Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion cmd/internal/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func CapabilityFlags() []cli.Flag {
&cli.BoolFlag{
Name: "with-all",
Category: "CAPABILITIES",
Usage: "grant all capabilities (console, IPFS, exec)",
Usage: "grant all capabilities (console, IPFS, exec, p2p)",
EnvVars: []string{"WW_WITH_ALL"},
},
&cli.BoolFlag{
Expand All @@ -33,6 +33,12 @@ func CapabilityFlags() []cli.Flag {
Usage: "grant process execution capability",
EnvVars: []string{"WW_WITH_EXEC"},
},
&cli.BoolFlag{
Name: "with-p2p",
Category: "CAPABILITIES",
Usage: "grant P2P networking capability",
EnvVars: []string{"WW_WITH_P2P"},
},
}
}

Expand Down
76 changes: 0 additions & 76 deletions cmd/ww/shell/executor.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
package shell

import (
"bytes"
"context"
"errors"
"fmt"
"io"
"strings"
"time"

"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
ma "github.com/multiformats/go-multiaddr"
"github.com/spy16/slurp/builtin"
"github.com/spy16/slurp/core"
"github.com/wetware/go/system"
Expand Down Expand Up @@ -106,74 +101,3 @@ func (e Exec) NewContext(opts map[builtin.Keyword]core.Any) (context.Context, co

return context.WithTimeout(context.Background(), time.Second*15)
}

// SendToPeer sends data to a specific peer and process
func SendToPeer(peerAddr, procIdStr string, data interface{}) error {
ctx := context.TODO()

// Create a new libp2p host for this connection
host, err := libp2p.New()
if err != nil {
return fmt.Errorf("failed to create libp2p host: %w", err)
}
defer host.Close()

var peerInfo *peer.AddrInfo

// Try to parse as peer ID first
peerId, err := peer.Decode(peerAddr)
if err == nil {
// Successfully parsed as peer ID
peerInfo = &peer.AddrInfo{
ID: peerId,
// Note: In a real implementation, you'd need peer discovery
// or provide addresses as additional parameters
}
} else {
// Fall back to treating as multiaddr
addr, err := ma.NewMultiaddr(peerAddr)
if err != nil {
return fmt.Errorf("invalid peer address or ID: %w", err)
}
peerInfo, err = peer.AddrInfoFromP2pAddr(addr)
if err != nil {
return fmt.Errorf("failed to parse peer info from multiaddr: %w", err)
}
}

// Connect to the peer
if err := host.Connect(ctx, *peerInfo); err != nil {
return fmt.Errorf("failed to connect to peer: %w", err)
}

// Create protocol ID from process ID
protocolID := protocol.ID("/ww/0.1.0/" + procIdStr)

// Open stream to the peer
stream, err := host.NewStream(ctx, peerInfo.ID, protocolID)
if err != nil {
return fmt.Errorf("failed to open stream: %w", err)
}
defer stream.Close()

// Convert data to io.Reader based on type
var reader io.Reader
switch v := data.(type) {
case io.Reader:
reader = v
case []byte:
reader = bytes.NewReader(v)
case string:
reader = strings.NewReader(v)
default:
return fmt.Errorf("unsupported data type: %T, expected io.Reader, []byte, or string", data)
}

// Send the data atomically
_, err = io.Copy(stream, reader)
if err != nil {
return fmt.Errorf("failed to send data: %w", err)
}

return nil
}
45 changes: 40 additions & 5 deletions cmd/ww/shell/globals.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package shell

import (
"errors"
"fmt"

"github.com/libp2p/go-libp2p"
"github.com/spy16/slurp"
"github.com/spy16/slurp/builtin"
"github.com/spy16/slurp/core"
"github.com/urfave/cli/v2"
)

const helpMessage = `Wetware Shell - Available commands:
Expand All @@ -18,12 +21,17 @@ version - Show wetware version
(< a b) - Less than
(println expr) - Print expression with newline
(print expr) - Print expression without newline
(send "peer-addr-or-id" "proc-id" data) - Send data to a peer process (data: string, []byte, or io.Reader)
(import "module") - Import a module (stubbed)

IPFS Path Syntax:
/ipfs/QmHash/... - Direct IPFS path
/ipns/domain/... - IPNS path`
/ipns/domain/... - IPNS path

P2P Commands (use --with-p2p):
(peer :send "peer-addr" "proc-id" data) - Send data to a peer process
(peer :connect "peer-addr") - Connect to a peer
(peer :is-self "peer-id") - Check if peer ID is our own
(peer :id) - Get our own peer ID`

var globals = map[string]core.Any{
// Basic values
Expand Down Expand Up @@ -72,7 +80,34 @@ var globals = map[string]core.Any{
fmt.Print(arg)
}
}),
"send": slurp.Func("send", func(peerAddr, procId string, data interface{}) error {
return SendToPeer(peerAddr, procId, data)
}),
}

func NewGlobals(c *cli.Context) (map[string]core.Any, error) {
gs := make(map[string]core.Any, len(globals))
for k, v := range globals {
gs[k] = v
}

// Add IPFS support if --with-ipfs flag is set
if c.Bool("with-ipfs") || c.Bool("with-all") {
if env.IPFS == nil {
return nil, errors.New("uninitialized IPFS environment")
}
gs["ipfs"] = &IPFS{CoreAPI: env.IPFS}
}

// Add P2P functionality if --with-p2p flag is set
if c.Bool("with-p2p") || c.Bool("with-all") {
// Create a new host for P2P functionality
host, err := libp2p.New()
if err != nil {
return nil, fmt.Errorf("failed to create libp2p host: %v", err)
}
gs["peer"] = &Peer{
Ctx: c.Context,
Host: host,
}
}

return gs, nil
}
9 changes: 6 additions & 3 deletions cmd/ww/shell/globals_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ func TestGetBaseGlobals(t *testing.T) {
flagSet.Bool("with-all", false, "Enable all capabilities")
c := cli.NewContext(app, flagSet, nil)
c.Context = context.Background()
baseGlobals := getBaseGlobals(c)
baseGlobals, err := NewGlobals(c)
require.NoError(t, err)

// Test that all expected base globals are present
expectedGlobals := []string{
Expand Down Expand Up @@ -140,8 +141,10 @@ func TestGlobalsConsistency(t *testing.T) {
flagSet.Bool("with-all", false, "Enable all capabilities")
c := cli.NewContext(app, flagSet, nil)
c.Context = context.Background()
baseGlobals1 := getBaseGlobals(c)
baseGlobals2 := getBaseGlobals(c)
baseGlobals1, err := NewGlobals(c)
require.NoError(t, err)
baseGlobals2, err := NewGlobals(c)
require.NoError(t, err)

// They should have the same content initially
assert.Equal(t, baseGlobals1, baseGlobals2)
Expand Down
Loading
Loading