Skip to content
This repository was archived by the owner on Sep 11, 2025. It is now read-only.

Commit e4f2973

Browse files
feat: enforce WASI reactor mode (#859)
1 parent 279689d commit e4f2973

File tree

6 files changed

+25
-18
lines changed

6 files changed

+25
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
- chore: update json-as and remove hack [#857](https://github.com/hypermodeinc/modus/pull/857)
88
- chore: rename agent lifecycle methods and APIs [#858](https://github.com/hypermodeinc/modus/pull/858)
9+
- feat: enforce WASI reactor mode [#859](https://github.com/hypermodeinc/modus/pull/859)
910

1011
## 2025-05-22 - Go SDK 0.18.0-alpha.3
1112

cli/src/custom/globals.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const ModusHomeDir = process.env.MODUS_HOME || path.join(os.homedir(), ".
1515

1616
export const MinNodeVersion = "22.0.0";
1717
export const MinGoVersion = "1.23.1";
18-
export const MinTinyGoVersion = "0.33.0";
18+
export const MinTinyGoVersion = "0.35.0";
1919

2020
export const GitHubOwner = "hypermodeinc";
2121
export const GitHubRepo = "modus";

runtime/plugins/plugins.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type Plugin struct {
3030
FileName string
3131
Language langsupport.Language
3232
ExecutionPlans map[string]langsupport.ExecutionPlan
33+
StartFunction string
3334
}
3435

3536
func NewPlugin(ctx context.Context, cm wazero.CompiledModule, filename string, md *metadata.Metadata) (*Plugin, error) {
@@ -83,13 +84,28 @@ func NewPlugin(ctx context.Context, cm wazero.CompiledModule, filename string, m
8384
plans[importName] = plan
8485
}
8586

87+
var startFunction string
88+
if _, found := exports["_initialize"]; found {
89+
// all modules should be reactors, but prior to v0.18, some modules were not.
90+
startFunction = "_initialize"
91+
} else if _, found := exports["_start"]; found {
92+
// this will happen if the module was compiled using TinyGo < 0.35, or Modus AssemblyScript SDK < v0.18.0-alpha.3
93+
startFunction = "_start"
94+
logger.Warn(ctx).Bool("user_visible", true).
95+
Msgf("%s is not correctly configured as a WASI reactor module. Please rebuild the Modus app using the latest version of the Modus SDK.", filename)
96+
} else {
97+
// this path would only occur if the module was not compiled using a Modus SDK
98+
return nil, fmt.Errorf("no WASI startup function found in %s", filename)
99+
}
100+
86101
plugin := &Plugin{
87102
Id: utils.GenerateUUIDv7(),
88103
Module: cm,
89104
Metadata: md,
90105
FileName: filename,
91106
Language: language,
92107
ExecutionPlans: plans,
108+
StartFunction: startFunction,
93109
}
94110

95111
return plugin, nil

runtime/wasmhost/wasmhost.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (host *wasmHost) GetModuleInstance(ctx context.Context, plugin *plugins.Plu
106106
span, ctx := utils.NewSentrySpanForCurrentFunc(ctx)
107107
defer span.Finish()
108108

109-
cfg := getModuleConfig(ctx, buffers)
109+
cfg := getModuleConfig(ctx, buffers, plugin)
110110
mod, err := host.runtime.InstantiateModule(ctx, plugin.Module, cfg)
111111
if err != nil {
112112
return nil, fmt.Errorf("failed to instantiate the plugin module: %w", err)
@@ -127,7 +127,7 @@ func (host *wasmHost) CompileModule(ctx context.Context, bytes []byte) (wazero.C
127127
return cm, nil
128128
}
129129

130-
func getModuleConfig(ctx context.Context, buffers utils.OutputBuffers) wazero.ModuleConfig {
130+
func getModuleConfig(ctx context.Context, buffers utils.OutputBuffers, plugin *plugins.Plugin) wazero.ModuleConfig {
131131

132132
// Get the logger and writers for the plugin's stdout and stderr.
133133
log := logger.Get(ctx).With().Bool("user_visible", true).Logger()
@@ -155,7 +155,7 @@ func getModuleConfig(ctx context.Context, buffers utils.OutputBuffers) wazero.Mo
155155
// And https://gophers.slack.com/archives/C040AKTNTE0/p1719587772724619?thread_ts=1719522663.531579&cid=C040AKTNTE0
156156
cfg := wazero.NewModuleConfig().
157157
WithName("").
158-
WithStartFunctions("_initialize", "_start").
158+
WithStartFunctions(plugin.StartFunction).
159159
WithSysWalltime().WithSysNanotime().
160160
WithRandSource(rand.Reader).
161161
WithStdout(wOut).WithStderr(wErr).

sdk/assemblyscript/src/plugin.asconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"process=wasi_process",
1616
"Date=wasi_Date"
1717
],
18-
"exportStart": "_start",
18+
"exportStart": "_initialize",
1919
"exportRuntime": true
2020
},
2121
"targets": {

sdk/go/tools/modus-go-build/compiler/compiler.go

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,26 +21,16 @@ import (
2121
"github.com/hashicorp/go-version"
2222
)
2323

24-
const minTinyGoVersion = "0.33.0"
24+
const minTinyGoVersion = "0.35.0"
2525

2626
func Compile(config *config.Config) error {
2727

28-
tinygoVersion, err := getCompilerVersion(config)
29-
if err != nil {
30-
return err
31-
}
32-
3328
args := []string{"build"}
3429
args = append(args, "-target", "wasip1")
3530
args = append(args, "-o", filepath.Join(config.OutputDir, config.WasmFileName))
3631

37-
// WASI "reactor mode" (-buildmode=c-shared) is required for TinyGo 0.35.0 and later.
38-
// Otherwise, the _start function runs and immediately exits before any function can execute.
39-
// This also switches the startup function to _initialize instead of _start, so the Modus runtime
40-
// needs to match.
41-
if tinygoVersion.GreaterThanOrEqual(version.Must(version.NewVersion("0.35.0"))) {
42-
args = append(args, "-buildmode", "c-shared")
43-
}
32+
// build a WASI reactor module - not a command module
33+
args = append(args, "-buildmode", "c-shared")
4434

4535
// disable the asyncify scheduler until we better understand how to use it
4636
args = append(args, "-scheduler", "none")

0 commit comments

Comments
 (0)