@sigrun/ext-codemode 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/LICENSE +21 -0
- package/README.md +115 -2
- package/dist/config.d.ts +68 -0
- package/dist/config.js +166 -0
- package/dist/extension.d.ts +62 -0
- package/dist/extension.js +80 -0
- package/dist/index.d.ts +72 -0
- package/dist/index.js +68 -0
- package/package.json +58 -5
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.1] - 2026-10-27
|
|
9
|
+
### Changed
|
|
10
|
+
- Re-released through CI trusted publishing; this version carries SLSA
|
|
11
|
+
provenance. No functional change from 0.1.0.
|
|
12
|
+
|
|
13
|
+
## [Unreleased]
|
|
14
|
+
|
|
15
|
+
## [0.1.0] - 2026-10-13
|
|
16
|
+
### Added
|
|
17
|
+
- Renamed to `@sigrun/ext-codemode` for the 0.1.0 release (repo stays
|
|
18
|
+
`sigrun-ai/sigrun-ext-codemode`): published package metadata
|
|
19
|
+
(`publishConfig` access/provenance), host modules moved to
|
|
20
|
+
`peerDependencies` mirrored in `devDependencies` at exact `1.3.0`
|
|
21
|
+
(`quickjs-wasi` remains the one runtime dependency), and a manifest
|
|
22
|
+
hygiene check wired into `npm test`.
|
|
23
|
+
- sigrun loader-contract wrapper over pi-durable's `createCodemodeExtension`:
|
|
24
|
+
a `CodemodeSandbox` pinned `timeoutMs: 300_000` / `memoryLimitBytes: 256 MiB`
|
|
25
|
+
at construction, MCP-config-driven namespaces (`SIGRUN_MCP_CONFIG` →
|
|
26
|
+
`~/.config/sigrun/mcp.json; snapshot semantics), and the installed-not-offered
|
|
27
|
+
notice section.
|
|
28
|
+
- Boot canary (`scripts/canary.mjs`): wasm resolution + a real harness
|
|
29
|
+
`return 1+1`, fail-loud exit 1 — the image entry pre-step.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Michael MacLeod
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,116 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @sigrun/ext-codemode
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The codemode extension for sigrun (pi-durable): the `codemode` tool —
|
|
4
|
+
model-written JavaScript run in a QuickJS sandbox, whose script survives
|
|
5
|
+
a restart — installed via upstream's
|
|
6
|
+
`createCodemodeExtension` (`@earendil-works/pi-durable/codemode`) with
|
|
7
|
+
sigrun's config and prompt additions.
|
|
8
|
+
|
|
9
|
+
The sigrun extension-package contract: the default export is a factory
|
|
10
|
+
taking no arguments, returning `{ extension }`.
|
|
11
|
+
|
|
12
|
+
## What the factory does
|
|
13
|
+
|
|
14
|
+
1. Reads the MCP namespace snapshot ONCE from the same config
|
|
15
|
+
sigrun-ext-mcp reads: `SIGRUN_MCP_CONFIG` env override →
|
|
16
|
+
`~/.config/sigrun/mcp.json`. One `CodemodeNamespace` per enabled
|
|
17
|
+
server, `prefix: "<server>/"`. Absent file → empty namespaces (the
|
|
18
|
+
codemode tool + section still ship). A bad file warns at factory time
|
|
19
|
+
(best-effort) and installs un-namespaced rather than throwing — a bad
|
|
20
|
+
config must not cost the model its codemode tool.
|
|
21
|
+
2. Builds the QuickJS sandbox (`CodemodeSandbox` from
|
|
22
|
+
`@earendil-works/pi-codemode`) with pinned constructor options:
|
|
23
|
+
`timeoutMs: 300_000`, `memoryLimitBytes: 256 MiB`.
|
|
24
|
+
3. Wraps upstream's `createCodemodeExtension({ sandbox, namespaces })`
|
|
25
|
+
with a companion `codemode_notice` section (below).
|
|
26
|
+
|
|
27
|
+
Config fields read per server entry (the sigrun-ext-mcp shapes,
|
|
28
|
+
duplicated here because that package is not npm-published): `enabled` /
|
|
29
|
+
`disabled` (either false means off), `exposure`
|
|
30
|
+
(`"codemode"` default | `"deferred"` | `"direct"` | `"hidden"`, plus the
|
|
31
|
+
pi alias `"codemode-deferred"`), and `toolExposure` overrides. A server
|
|
32
|
+
resolving fully `hidden` (server default `hidden` and every override
|
|
33
|
+
`hidden`) is excluded from the snapshot — hidden tools never register,
|
|
34
|
+
so nothing scripts can call remains. Per-tool `hidden` resolution is
|
|
35
|
+
sigrun-ext-mcp's job at registration time; this snapshot only groups by
|
|
36
|
+
prefix, and hidden tools never reach `agent.callable` to be grouped.
|
|
37
|
+
|
|
38
|
+
### The deadline (verified against pi-codemode 1.2.0)
|
|
39
|
+
|
|
40
|
+
The sandbox constructor's `timeoutMs` governs the plain
|
|
41
|
+
`sandbox.execute()` surface. The durable codemode tool path
|
|
42
|
+
(`sandbox.start()`) takes its deadline from the script's own first line:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
// @options: {"timeout_ms": 60000}
|
|
46
|
+
while (true) {}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
A script without an options line has NO deadline (the constructor cap
|
|
50
|
+
does not apply there) — models should be prompted to set one; sigrun's
|
|
51
|
+
system prompt carries that guidance. The pinned constructor options
|
|
52
|
+
still bound the plain sandbox surface and document the ceiling.
|
|
53
|
+
|
|
54
|
+
## The warn-if-not-offered section
|
|
55
|
+
|
|
56
|
+
Upstream's `codemode` section lists script-callable tools (grouped by
|
|
57
|
+
namespace) but does not know whether the `codemode` tool itself is
|
|
58
|
+
model-offered. When the extension is installed yet the tool is excluded
|
|
59
|
+
from a request's offered set (Settings → default tools), the companion
|
|
60
|
+
`codemode_notice` section renders:
|
|
61
|
+
|
|
62
|
+
> codemode scripts are available but the tool is not offered; enable it
|
|
63
|
+
> via Settings → default tools
|
|
64
|
+
|
|
65
|
+
When the tool is offered the section renders NOTHING (returns
|
|
66
|
+
`undefined`; no tag is written) — de-duplication with upstream's listing
|
|
67
|
+
by construction. Mechanism choice: a companion section rather than a
|
|
68
|
+
`wrapSection` on upstream's key — the wrap could only prepend text
|
|
69
|
+
around upstream's render, while the companion keys the notice to the
|
|
70
|
+
not-offered condition exactly and leaves the upstream render untouched.
|
|
71
|
+
Both sections are registered by the one extension this package installs,
|
|
72
|
+
so the pair always travels together.
|
|
73
|
+
|
|
74
|
+
## Tool naming: `<server>/<tool>` (decision, agreeing with sigrun-ext-mcp)
|
|
75
|
+
|
|
76
|
+
Tools keep the `<server>/<tool>` shape rather than upstream pi's
|
|
77
|
+
`mcp__<server>__<tool>`; the codemode namespaces use
|
|
78
|
+
`prefix: "<server>/"`, so upstream's longest-prefix grouping renders per
|
|
79
|
+
server with no renames. The same decision is recorded in
|
|
80
|
+
sigrun-ext-mcp's README; the two must stay consistent.
|
|
81
|
+
|
|
82
|
+
## Package replacement semantics (slice 4)
|
|
83
|
+
|
|
84
|
+
Replace this package by not installing it and installing yours: the
|
|
85
|
+
surface is one tool named exactly `codemode` (plus the companion
|
|
86
|
+
`codemode_notice` section and the factory-time namespace snapshot), so a
|
|
87
|
+
per-name replacement is trivial — uninstall ours, install the replacement
|
|
88
|
+
under the same tool name. Do NOT co-install: pi-durable resolves
|
|
89
|
+
cross-extension duplicate tool names last-selected-wins, so a co-installed
|
|
90
|
+
replacement silently shadows the original. Sigrun's extension loader now
|
|
91
|
+
makes the shadowing visible at boot (it `console.warn`s once per duplicate
|
|
92
|
+
tool name, naming the extensions and the last-wins resolution), but the
|
|
93
|
+
warning changes nothing: last-wins stands. Replace, don't co-install.
|
|
94
|
+
|
|
95
|
+
## Dependencies
|
|
96
|
+
|
|
97
|
+
`quickjs-wasi` is a REAL dependency of this package, not a transitive
|
|
98
|
+
courtesy: pi-codemode's worker resolves `quickjs-wasi/quickjs.wasm`
|
|
99
|
+
from disk at the first script. A re-pinned or deduped-away transitive
|
|
100
|
+
copy strands the wasm file, and the first codemode call fails at runtime
|
|
101
|
+
(in prod: a 500 on the first script). The canary test
|
|
102
|
+
(`test/canary.spec.ts`) asserts the wasm resolves and runs
|
|
103
|
+
`return 1 + 1` against the BUILT package — the same assertions Task 8
|
|
104
|
+
wires into the container image build.
|
|
105
|
+
|
|
106
|
+
## Development
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
npm install && npm test # vitest run (includes the canary + the runaway test, last)
|
|
110
|
+
npm run typecheck
|
|
111
|
+
npm run build
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
The runaway-script test (`while (true) {}` with a 1s `timeout_ms`) is
|
|
115
|
+
the LAST test in `test/codemode.test.ts`, so a wall-clock death on it
|
|
116
|
+
still ships the rest of the suite.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The codemode config snapshot: the mcp.json-derived namespace list.
|
|
3
|
+
*
|
|
4
|
+
* Reuses the MCP config RESOLUTION and the namespace-relevant parse SHAPES
|
|
5
|
+
* from sigrun-ext-mcp (rev-3 ruling accepts the duplicated parse of the
|
|
6
|
+
* config file across repos; sigrun-ext-mcp is not npm-published, so its
|
|
7
|
+
* `parseMcpConfig` cannot be imported here — the shapes are duplicated
|
|
8
|
+
* with the derivations quoted below for review parity).
|
|
9
|
+
*
|
|
10
|
+
* Resolution order (identical to sigrun-ext-mcp src/config.ts):
|
|
11
|
+
* 1. `SIGRUN_MCP_CONFIG` env override — an explicit path to an mcp.json
|
|
12
|
+
* 2. `~/.config/sigrun/mcp.json` (the sigrun config dir)
|
|
13
|
+
*
|
|
14
|
+
* What we read from each server entry:
|
|
15
|
+
* - `serverEnabled` (mcp repo's derivation): `enabled: false` OR
|
|
16
|
+
* `disabled: true` skips the server entirely.
|
|
17
|
+
* - Exposure (mcp repo's shape): a server-default `exposure` word, plus
|
|
18
|
+
* `toolExposure` overrides mapping exact tool names or `*`-patterns to
|
|
19
|
+
* exposure words; the pi alias `codemode-deferred` normalizes to
|
|
20
|
+
* `codemode`. A server whose tools all resolve `hidden` contributes
|
|
21
|
+
* nothing scripts can call (hidden tools never register), so it is
|
|
22
|
+
* excluded from the snapshot: that happens when the server default is
|
|
23
|
+
* `hidden` and every override is `hidden` too (an exact name wins over
|
|
24
|
+
* patterns; among patterns the first match in config order wins — so
|
|
25
|
+
* only a fully-hidden override table leaves every tool hidden).
|
|
26
|
+
*
|
|
27
|
+
* Snapshot semantics (the spec ruling): the config is read ONCE at factory
|
|
28
|
+
* time; late or flapping servers render un-namespaced in the section until
|
|
29
|
+
* the next boot. The section BODY re-renders live from
|
|
30
|
+
* `PromptInput.agent.callable` each turn (upstream's render), so tool
|
|
31
|
+
* lists are never stale — only the namespace GROUPING is a snapshot.
|
|
32
|
+
*/
|
|
33
|
+
import type { CodemodeNamespace } from "@earendil-works/pi-durable/codemode";
|
|
34
|
+
/** The env override the config store reads (sigrun-ext-mcp's name). */
|
|
35
|
+
export declare const MCP_CONFIG_ENV = "SIGRUN_MCP_CONFIG";
|
|
36
|
+
/** The exposure words, after normalization (mcp repo's McpExposure). */
|
|
37
|
+
declare const EXPOSURE_WORDS: readonly ["codemode", "deferred", "direct", "hidden"];
|
|
38
|
+
type ExposureWord = (typeof EXPOSURE_WORDS)[number];
|
|
39
|
+
/** One server entry as this package needs it (a subset of the mcp repo's
|
|
40
|
+
* McpServerConfig: only the namespace-relevant fields). */
|
|
41
|
+
export interface McpServerEntry {
|
|
42
|
+
/** Skip this server entirely (either false means off). */
|
|
43
|
+
readonly enabled?: boolean;
|
|
44
|
+
readonly disabled?: boolean;
|
|
45
|
+
/** Server-default exposure (default "codemode"). */
|
|
46
|
+
readonly exposure?: ExposureWord;
|
|
47
|
+
/** Per-tool overrides: exact names beat `*`-patterns; first pattern wins. */
|
|
48
|
+
readonly toolExposure?: Readonly<Record<string, ExposureWord>>;
|
|
49
|
+
}
|
|
50
|
+
/** Resolve the config path without reading it (for diagnostics). */
|
|
51
|
+
export declare function resolveMcpConfigPath(env?: NodeJS.ProcessEnv): string;
|
|
52
|
+
/** Whether a configured server participates at all (mcp repo's
|
|
53
|
+
* `serverEnabled`): `enabled: false` and `disabled: true` both skip it. */
|
|
54
|
+
export declare function serverEnabled(server: McpServerEntry): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Read the mcp.json from the resolved path and build the namespace
|
|
57
|
+
* snapshot: one `CodemodeNamespace` per participating server with prefix
|
|
58
|
+
* `"<server>/"` (the namespace ruler: our tool-name shape is already
|
|
59
|
+
* `<server>/<tool>`, so upstream's longest-prefix grouping needs no renames).
|
|
60
|
+
*
|
|
61
|
+
* A missing file is an EMPTY namespace list (the extension still ships its
|
|
62
|
+
* codemode tool + section). An existing-but-bad file or entry warns at
|
|
63
|
+
* factory time (the spec's best-effort boot log; NOT the contract — a bad
|
|
64
|
+
* config must not cost the model its codemode tool) and the extension
|
|
65
|
+
* installs un-namespaced rather than throwing.
|
|
66
|
+
*/
|
|
67
|
+
export declare function loadNamespaces(env?: NodeJS.ProcessEnv): readonly CodemodeNamespace[];
|
|
68
|
+
export {};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The codemode config snapshot: the mcp.json-derived namespace list.
|
|
3
|
+
*
|
|
4
|
+
* Reuses the MCP config RESOLUTION and the namespace-relevant parse SHAPES
|
|
5
|
+
* from sigrun-ext-mcp (rev-3 ruling accepts the duplicated parse of the
|
|
6
|
+
* config file across repos; sigrun-ext-mcp is not npm-published, so its
|
|
7
|
+
* `parseMcpConfig` cannot be imported here — the shapes are duplicated
|
|
8
|
+
* with the derivations quoted below for review parity).
|
|
9
|
+
*
|
|
10
|
+
* Resolution order (identical to sigrun-ext-mcp src/config.ts):
|
|
11
|
+
* 1. `SIGRUN_MCP_CONFIG` env override — an explicit path to an mcp.json
|
|
12
|
+
* 2. `~/.config/sigrun/mcp.json` (the sigrun config dir)
|
|
13
|
+
*
|
|
14
|
+
* What we read from each server entry:
|
|
15
|
+
* - `serverEnabled` (mcp repo's derivation): `enabled: false` OR
|
|
16
|
+
* `disabled: true` skips the server entirely.
|
|
17
|
+
* - Exposure (mcp repo's shape): a server-default `exposure` word, plus
|
|
18
|
+
* `toolExposure` overrides mapping exact tool names or `*`-patterns to
|
|
19
|
+
* exposure words; the pi alias `codemode-deferred` normalizes to
|
|
20
|
+
* `codemode`. A server whose tools all resolve `hidden` contributes
|
|
21
|
+
* nothing scripts can call (hidden tools never register), so it is
|
|
22
|
+
* excluded from the snapshot: that happens when the server default is
|
|
23
|
+
* `hidden` and every override is `hidden` too (an exact name wins over
|
|
24
|
+
* patterns; among patterns the first match in config order wins — so
|
|
25
|
+
* only a fully-hidden override table leaves every tool hidden).
|
|
26
|
+
*
|
|
27
|
+
* Snapshot semantics (the spec ruling): the config is read ONCE at factory
|
|
28
|
+
* time; late or flapping servers render un-namespaced in the section until
|
|
29
|
+
* the next boot. The section BODY re-renders live from
|
|
30
|
+
* `PromptInput.agent.callable` each turn (upstream's render), so tool
|
|
31
|
+
* lists are never stale — only the namespace GROUPING is a snapshot.
|
|
32
|
+
*/
|
|
33
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
34
|
+
import { homedir } from "node:os";
|
|
35
|
+
import { isAbsolute, resolve } from "node:path";
|
|
36
|
+
/** The env override the config store reads (sigrun-ext-mcp's name). */
|
|
37
|
+
export const MCP_CONFIG_ENV = "SIGRUN_MCP_CONFIG";
|
|
38
|
+
/** The exposure words, after normalization (mcp repo's McpExposure). */
|
|
39
|
+
const EXPOSURE_WORDS = ["codemode", "deferred", "direct", "hidden"];
|
|
40
|
+
/** Parse one exposure word; the pi alias normalizes to "codemode". */
|
|
41
|
+
const EXPOSURE_WORD_SET = new Set(EXPOSURE_WORDS);
|
|
42
|
+
function parseExposure(value, where) {
|
|
43
|
+
if (value === "codemode-deferred")
|
|
44
|
+
return "codemode";
|
|
45
|
+
if (typeof value !== "string" || !EXPOSURE_WORD_SET.has(value)) {
|
|
46
|
+
throw new Error(`${where} exposure must be one of ${EXPOSURE_WORDS.map((word) => JSON.stringify(word)).join(", ")} (or "codemode-deferred", the pi alias for "codemode")`);
|
|
47
|
+
}
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
/** Resolve the config path without reading it (for diagnostics). */
|
|
51
|
+
export function resolveMcpConfigPath(env = process.env) {
|
|
52
|
+
const override = env[MCP_CONFIG_ENV];
|
|
53
|
+
if (override !== undefined && override !== "") {
|
|
54
|
+
// A relative override resolves against cwd, like sigrun's other paths.
|
|
55
|
+
return isAbsolute(override) ? override : resolve(override);
|
|
56
|
+
}
|
|
57
|
+
return resolve(homedir(), ".config", "sigrun", "mcp.json");
|
|
58
|
+
}
|
|
59
|
+
function isRecord(value) {
|
|
60
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
61
|
+
}
|
|
62
|
+
/** Whether a configured server participates at all (mcp repo's
|
|
63
|
+
* `serverEnabled`): `enabled: false` and `disabled: true` both skip it. */
|
|
64
|
+
export function serverEnabled(server) {
|
|
65
|
+
return server.enabled !== false && server.disabled !== true;
|
|
66
|
+
}
|
|
67
|
+
/** Whether every tool of this server resolves `hidden`: the server default
|
|
68
|
+
* is `hidden` and no override can un-hide a tool (every override value is
|
|
69
|
+
* `hidden`; an exact name or pattern pointing elsewhere un-hides whatever
|
|
70
|
+
* it matches). Hidden tools never register, so such a server contributes
|
|
71
|
+
* nothing scripts can call and gets no namespace. */
|
|
72
|
+
function serverFullyHidden(server) {
|
|
73
|
+
if ((server.exposure ?? "codemode") !== "hidden")
|
|
74
|
+
return false;
|
|
75
|
+
return Object.values(server.toolExposure ?? {}).every((word) => word === "hidden");
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Read the mcp.json from the resolved path and build the namespace
|
|
79
|
+
* snapshot: one `CodemodeNamespace` per participating server with prefix
|
|
80
|
+
* `"<server>/"` (the namespace ruler: our tool-name shape is already
|
|
81
|
+
* `<server>/<tool>`, so upstream's longest-prefix grouping needs no renames).
|
|
82
|
+
*
|
|
83
|
+
* A missing file is an EMPTY namespace list (the extension still ships its
|
|
84
|
+
* codemode tool + section). An existing-but-bad file or entry warns at
|
|
85
|
+
* factory time (the spec's best-effort boot log; NOT the contract — a bad
|
|
86
|
+
* config must not cost the model its codemode tool) and the extension
|
|
87
|
+
* installs un-namespaced rather than throwing.
|
|
88
|
+
*/
|
|
89
|
+
export function loadNamespaces(env = process.env) {
|
|
90
|
+
const path = resolveMcpConfigPath(env);
|
|
91
|
+
if (!existsSync(path))
|
|
92
|
+
return [];
|
|
93
|
+
try {
|
|
94
|
+
return parseNamespaces(readFileSync(path, "utf8"), path);
|
|
95
|
+
}
|
|
96
|
+
catch (cause) {
|
|
97
|
+
console.warn(`sigrun-ext-codemode: mcp config ${path} is invalid (codemode ` +
|
|
98
|
+
`tools install un-namespaced): ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/** Parse and validate the config body into the namespace snapshot. */
|
|
103
|
+
function parseNamespaces(text, path) {
|
|
104
|
+
const parsed = JSON.parse(text);
|
|
105
|
+
if (!isRecord(parsed) || !isRecord(parsed.servers)) {
|
|
106
|
+
throw new Error(`must be a JSON object with a "servers" object mapping names to server entries`);
|
|
107
|
+
}
|
|
108
|
+
const namespaces = [];
|
|
109
|
+
for (const [name, entry] of Object.entries(parsed.servers)) {
|
|
110
|
+
if (!isRecord(entry)) {
|
|
111
|
+
throw new Error(`server "${name}" must be an object`);
|
|
112
|
+
}
|
|
113
|
+
const server = parseServerEntry(entry, path, name);
|
|
114
|
+
if (!serverEnabled(server))
|
|
115
|
+
continue;
|
|
116
|
+
if (serverFullyHidden(server)) {
|
|
117
|
+
// The spec's best-effort boot log: hidden-only rows.
|
|
118
|
+
console.warn(`sigrun-ext-codemode: mcp server "${name}" resolves fully ` +
|
|
119
|
+
`hidden (excluded from the codemode namespaces)`);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
namespaces.push({
|
|
123
|
+
name,
|
|
124
|
+
description: `MCP server ${name} (tools ${name}/<tool>, registered by sigrun-ext-mcp)`,
|
|
125
|
+
prefix: `${name}/`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
return namespaces;
|
|
129
|
+
}
|
|
130
|
+
/** Validate one server entry's namespace-relevant fields. */
|
|
131
|
+
function parseServerEntry(entry, path, name) {
|
|
132
|
+
for (const field of ["enabled", "disabled"]) {
|
|
133
|
+
const value = entry[field];
|
|
134
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
135
|
+
throw new Error(`mcp config ${path}: server "${name}" ${field} must be a boolean`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
...(entry.enabled === undefined
|
|
140
|
+
? {}
|
|
141
|
+
: { enabled: entry.enabled }),
|
|
142
|
+
...(entry.disabled === undefined
|
|
143
|
+
? {}
|
|
144
|
+
: { disabled: entry.disabled }),
|
|
145
|
+
...(entry.exposure === undefined
|
|
146
|
+
? {}
|
|
147
|
+
: {
|
|
148
|
+
exposure: parseExposure(entry.exposure, `mcp config ${path}: server "${name}"`),
|
|
149
|
+
}),
|
|
150
|
+
...(entry.toolExposure === undefined
|
|
151
|
+
? {}
|
|
152
|
+
: {
|
|
153
|
+
toolExposure: parseToolExposure(entry.toolExposure, path, name),
|
|
154
|
+
}),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function parseToolExposure(value, path, name) {
|
|
158
|
+
if (!isRecord(value)) {
|
|
159
|
+
throw new Error(`mcp config ${path}: server "${name}" toolExposure must be an object`);
|
|
160
|
+
}
|
|
161
|
+
const overrides = {};
|
|
162
|
+
for (const [key, exposure] of Object.entries(value)) {
|
|
163
|
+
overrides[key] = parseExposure(exposure, `mcp config ${path}: server "${name}" toolExposure "${key}"`);
|
|
164
|
+
}
|
|
165
|
+
return overrides;
|
|
166
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The codemode extension wrapper (sigrun-ext-codemode): installs upstream's
|
|
3
|
+
* `codemode` extension (the `codemode` tool, named exactly, with
|
|
4
|
+
* `callers: ["model"]`, plus the upstream `codemode` prompt section) with
|
|
5
|
+
* our two sigrun additions:
|
|
6
|
+
*
|
|
7
|
+
* 1. The MCP namespace snapshot (src/config.ts): one `CodemodeNamespace`
|
|
8
|
+
* per configured MCP server, prefix `"<server>/"`, read once at factory
|
|
9
|
+
* time. The upstream section groups `agent.callable` tools by the
|
|
10
|
+
* longest matching prefix, so sigrun's `<server>/<tool>` MCP tools
|
|
11
|
+
* render grouped per server with no renames (the namespace ruler).
|
|
12
|
+
*
|
|
13
|
+
* 2. The warn-if-not-offered channel (the spec's corrected mechanism):
|
|
14
|
+
* when the extension is installed but the `codemode` TOOL is not
|
|
15
|
+
* model-offered in this request, a short companion section renders the
|
|
16
|
+
* enable notice instead of silence. Upstream's `codemode` section
|
|
17
|
+
* renders `undefined` when nothing is callable, and it does NOT know
|
|
18
|
+
* whether the codemode tool itself is offered — a model whose
|
|
19
|
+
* Settings → default tools excluded `codemode` would see MCP tools
|
|
20
|
+
* listed as script-callable with no way to learn the tool is off. The
|
|
21
|
+
* companion section renders NOTHING (returns undefined, so no tag is
|
|
22
|
+
* written) whenever the tool IS offered, which de-duplicates with
|
|
23
|
+
* upstream's listing by construction.
|
|
24
|
+
*
|
|
25
|
+
* Mechanism choice (documented for review): a `wrapSection("codemode", …)`
|
|
26
|
+
* would also work — pi-durable's `resolveAgent` applies wraps across
|
|
27
|
+
* selected extensions, and our factory owns both the wrapped section and
|
|
28
|
+
* the wrapper — but the wrap could only prepend text around upstream's
|
|
29
|
+
* render, and upstream's render already covers the offered case; the
|
|
30
|
+
* companion section keys the notice to the not-offered condition exactly,
|
|
31
|
+
* leaves the upstream render untouched, and renders undefined (absent from
|
|
32
|
+
* the prompt, no `<key>` tag written) when offered. Companion section it
|
|
33
|
+
* is. Both extensions are installed by the same factory, so the pair
|
|
34
|
+
* (upstream section + notice section) travels together.
|
|
35
|
+
*/
|
|
36
|
+
import { type CodemodeNamespace } from "@earendil-works/pi-durable/codemode";
|
|
37
|
+
import type { CodemodeSandboxBase } from "@earendil-works/pi-codemode/portable";
|
|
38
|
+
import { type Extension, type PromptInput } from "@earendil-works/pi-durable";
|
|
39
|
+
/** Our companion section's key (distinct from upstream's `"codemode"`). */
|
|
40
|
+
export declare const CODEMODE_NOTICE_SECTION_KEY = "codemode_notice";
|
|
41
|
+
/** The enable notice, the spec's wording. */
|
|
42
|
+
export declare const CODEMODE_NOT_OFFERED_NOTICE: string;
|
|
43
|
+
/**
|
|
44
|
+
* The companion section render: the notice ONLY when the codemode tool
|
|
45
|
+
* is installed (one of the selected extensions registers it) yet not
|
|
46
|
+
* model-offered in this request (`agent.tools` is the offered set);
|
|
47
|
+
* `undefined` otherwise (offered, or not installed — nothing to warn
|
|
48
|
+
* about). Installation cannot be read from `agent.callable`: that set
|
|
49
|
+
* holds only tools-callable tools, and `codemode` registers with
|
|
50
|
+
* `callers: ["model"]`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function renderCodemodeNotice(input: PromptInput): string | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* The sigrun codemode extension: upstream's `codemode` extension (tool +
|
|
55
|
+
* section, with our namespace snapshot) plus the companion notice section.
|
|
56
|
+
*/
|
|
57
|
+
export declare function createSigrunCodemodeExtension(options: {
|
|
58
|
+
/** Runs the scripts: `CodemodeSandbox` on Node. */
|
|
59
|
+
readonly sandbox: CodemodeSandboxBase;
|
|
60
|
+
/** The factory-time MCP namespace snapshot (src/config.ts). */
|
|
61
|
+
readonly namespaces?: readonly CodemodeNamespace[];
|
|
62
|
+
}): Extension;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The codemode extension wrapper (sigrun-ext-codemode): installs upstream's
|
|
3
|
+
* `codemode` extension (the `codemode` tool, named exactly, with
|
|
4
|
+
* `callers: ["model"]`, plus the upstream `codemode` prompt section) with
|
|
5
|
+
* our two sigrun additions:
|
|
6
|
+
*
|
|
7
|
+
* 1. The MCP namespace snapshot (src/config.ts): one `CodemodeNamespace`
|
|
8
|
+
* per configured MCP server, prefix `"<server>/"`, read once at factory
|
|
9
|
+
* time. The upstream section groups `agent.callable` tools by the
|
|
10
|
+
* longest matching prefix, so sigrun's `<server>/<tool>` MCP tools
|
|
11
|
+
* render grouped per server with no renames (the namespace ruler).
|
|
12
|
+
*
|
|
13
|
+
* 2. The warn-if-not-offered channel (the spec's corrected mechanism):
|
|
14
|
+
* when the extension is installed but the `codemode` TOOL is not
|
|
15
|
+
* model-offered in this request, a short companion section renders the
|
|
16
|
+
* enable notice instead of silence. Upstream's `codemode` section
|
|
17
|
+
* renders `undefined` when nothing is callable, and it does NOT know
|
|
18
|
+
* whether the codemode tool itself is offered — a model whose
|
|
19
|
+
* Settings → default tools excluded `codemode` would see MCP tools
|
|
20
|
+
* listed as script-callable with no way to learn the tool is off. The
|
|
21
|
+
* companion section renders NOTHING (returns undefined, so no tag is
|
|
22
|
+
* written) whenever the tool IS offered, which de-duplicates with
|
|
23
|
+
* upstream's listing by construction.
|
|
24
|
+
*
|
|
25
|
+
* Mechanism choice (documented for review): a `wrapSection("codemode", …)`
|
|
26
|
+
* would also work — pi-durable's `resolveAgent` applies wraps across
|
|
27
|
+
* selected extensions, and our factory owns both the wrapped section and
|
|
28
|
+
* the wrapper — but the wrap could only prepend text around upstream's
|
|
29
|
+
* render, and upstream's render already covers the offered case; the
|
|
30
|
+
* companion section keys the notice to the not-offered condition exactly,
|
|
31
|
+
* leaves the upstream render untouched, and renders undefined (absent from
|
|
32
|
+
* the prompt, no `<key>` tag written) when offered. Companion section it
|
|
33
|
+
* is. Both extensions are installed by the same factory, so the pair
|
|
34
|
+
* (upstream section + notice section) travels together.
|
|
35
|
+
*/
|
|
36
|
+
import { CODEMODE_TOOL_NAME, createCodemodeExtension, } from "@earendil-works/pi-durable/codemode";
|
|
37
|
+
import { defineExtension, } from "@earendil-works/pi-durable";
|
|
38
|
+
/** Our companion section's key (distinct from upstream's `"codemode"`). */
|
|
39
|
+
export const CODEMODE_NOTICE_SECTION_KEY = "codemode_notice";
|
|
40
|
+
/** The enable notice, the spec's wording. */
|
|
41
|
+
export const CODEMODE_NOT_OFFERED_NOTICE = "codemode scripts are available but the tool is not offered; enable it " +
|
|
42
|
+
"via Settings → default tools";
|
|
43
|
+
/**
|
|
44
|
+
* The companion section render: the notice ONLY when the codemode tool
|
|
45
|
+
* is installed (one of the selected extensions registers it) yet not
|
|
46
|
+
* model-offered in this request (`agent.tools` is the offered set);
|
|
47
|
+
* `undefined` otherwise (offered, or not installed — nothing to warn
|
|
48
|
+
* about). Installation cannot be read from `agent.callable`: that set
|
|
49
|
+
* holds only tools-callable tools, and `codemode` registers with
|
|
50
|
+
* `callers: ["model"]`.
|
|
51
|
+
*/
|
|
52
|
+
export function renderCodemodeNotice(input) {
|
|
53
|
+
const installed = input.agent.extensions.some((extension) => (extension.tools ?? []).some((tool) => tool.name === CODEMODE_TOOL_NAME));
|
|
54
|
+
if (!installed)
|
|
55
|
+
return undefined; // not installed: no lie to correct
|
|
56
|
+
const offered = input.agent.tools.some((tool) => tool.name === CODEMODE_TOOL_NAME);
|
|
57
|
+
return offered ? undefined : CODEMODE_NOT_OFFERED_NOTICE;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The sigrun codemode extension: upstream's `codemode` extension (tool +
|
|
61
|
+
* section, with our namespace snapshot) plus the companion notice section.
|
|
62
|
+
*/
|
|
63
|
+
export function createSigrunCodemodeExtension(options) {
|
|
64
|
+
const upstream = createCodemodeExtension({
|
|
65
|
+
sandbox: options.sandbox,
|
|
66
|
+
...(options.namespaces === undefined
|
|
67
|
+
? {}
|
|
68
|
+
: { namespaces: options.namespaces }),
|
|
69
|
+
});
|
|
70
|
+
return defineExtension({
|
|
71
|
+
...upstream,
|
|
72
|
+
sections: [
|
|
73
|
+
...(upstream.sections ?? []),
|
|
74
|
+
{
|
|
75
|
+
key: CODEMODE_NOTICE_SECTION_KEY,
|
|
76
|
+
render: renderCodemodeNotice,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sigrun-ext-codemode: the codemode factory (the loader contract).
|
|
3
|
+
*
|
|
4
|
+
* The sigrun extension-package contract (sigrun's src/harness/loader.ts):
|
|
5
|
+
* the default export is a FACTORY TAKING NO ARGUMENTS, returning
|
|
6
|
+
* `{ extension }`. The loader calls it synchronously at boot, before
|
|
7
|
+
* `Harness.open` reads the registry.
|
|
8
|
+
*
|
|
9
|
+
* What the factory does, in order:
|
|
10
|
+
* 1. Reads the MCP namespace snapshot ONCE (src/config.ts):
|
|
11
|
+
* `SIGRUN_MCP_CONFIG` → `~/.config/sigrun/mcp.json`; absent file →
|
|
12
|
+
* empty namespaces (the extension still ships its codemode tool +
|
|
13
|
+
* section); a bad file warns and installs un-namespaced.
|
|
14
|
+
* 2. Builds the QuickJS sandbox with the pinned constructor options
|
|
15
|
+
* (timeoutMs 300_000 — pi-codemode's own default, restated so the
|
|
16
|
+
* contract does not drift; memoryLimitBytes 256 MiB — a real cap
|
|
17
|
+
* where the upstream default is unbounded wasm32).
|
|
18
|
+
* 3. Wraps upstream's `createCodemodeExtension({ sandbox, namespaces })`
|
|
19
|
+
* with the companion notice section (src/extension.ts).
|
|
20
|
+
*
|
|
21
|
+
* Note on `timeoutMs` (verified against pi-codemode 1.2.0): the
|
|
22
|
+
* CONSTRUCTOR timeout governs `sandbox.execute()`; the durable codemode
|
|
23
|
+
* tool path (`sandbox.start()`) takes its deadline from the script's own
|
|
24
|
+
* `// @options: {"timeout_ms": N}` line (no options line → no deadline:
|
|
25
|
+
* the sandbox default does not apply there). The constructor cap is
|
|
26
|
+
* still the right pin: it bounds every execution of the plain sandbox
|
|
27
|
+
* surface and documents the intended ceiling.
|
|
28
|
+
*
|
|
29
|
+
* `quickjs-wasi` is a REAL dependency of this package, not a transitive
|
|
30
|
+
* courtesy: pi-codemode's worker resolves `quickjs-wasi/quickjs.wasm`
|
|
31
|
+
* from disk at the first script. A re-pinned or deduped-away transitive
|
|
32
|
+
* copy strands the wasm file and the first codemode call fails at runtime
|
|
33
|
+
* (500s in prod) — declaring it here pins the resolution to this
|
|
34
|
+
* package's own tree.
|
|
35
|
+
*/
|
|
36
|
+
import type { CodemodeSandboxBase } from "@earendil-works/pi-codemode/portable";
|
|
37
|
+
import type { CodemodeNamespace } from "@earendil-works/pi-durable/codemode";
|
|
38
|
+
import type { Extension } from "@earendil-works/pi-durable";
|
|
39
|
+
/** Pinned per-execution wall-clock deadline (pi-codemode's default). */
|
|
40
|
+
export declare const CODEMODE_TIMEOUT_MS = 300000;
|
|
41
|
+
/** Pinned QuickJS heap cap (256 MiB; upstream default is unbounded). */
|
|
42
|
+
export declare const CODEMODE_MEMORY_LIMIT_BYTES: number;
|
|
43
|
+
/** What {@link createCodemodeWiring} returns (the loader contract). */
|
|
44
|
+
export interface CodemodeWiring {
|
|
45
|
+
/** The extension to install into the harness registry. */
|
|
46
|
+
readonly extension: Extension;
|
|
47
|
+
/** The sandbox the extension runs scripts in (call `close()` on shutdown). */
|
|
48
|
+
readonly sandbox: CodemodeSandboxBase;
|
|
49
|
+
/** The factory-time namespace snapshot (empty without an mcp.json). */
|
|
50
|
+
readonly namespaces: readonly CodemodeNamespace[];
|
|
51
|
+
/**
|
|
52
|
+
* Close the sandbox: aborts in-flight executions and stops the worker
|
|
53
|
+
* machinery. Called by hosts on harness shutdown; a fresh factory builds
|
|
54
|
+
* a fresh sandbox, so a closed wiring is never reused.
|
|
55
|
+
*/
|
|
56
|
+
close(): Promise<void>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The codemode factory (the loader contract: no arguments; config resolves
|
|
60
|
+
* from the package context). Each call builds a FRESH sandbox — one
|
|
61
|
+
* wiring, one sandbox, no shared worker state across installs.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createCodemodeWiring(): CodemodeWiring;
|
|
64
|
+
/**
|
|
65
|
+
* The sigrun extension-package contract: the default export is a factory
|
|
66
|
+
* taking no arguments, returning `{ extension }`.
|
|
67
|
+
*/
|
|
68
|
+
declare const _default: typeof createCodemodeWiring;
|
|
69
|
+
export default _default;
|
|
70
|
+
export { CODEMODE_NOT_OFFERED_NOTICE, CODEMODE_NOTICE_SECTION_KEY, renderCodemodeNotice, } from "./extension.js";
|
|
71
|
+
export { loadNamespaces, MCP_CONFIG_ENV, resolveMcpConfigPath, serverEnabled, } from "./config.js";
|
|
72
|
+
export type { McpServerEntry } from "./config.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sigrun-ext-codemode: the codemode factory (the loader contract).
|
|
3
|
+
*
|
|
4
|
+
* The sigrun extension-package contract (sigrun's src/harness/loader.ts):
|
|
5
|
+
* the default export is a FACTORY TAKING NO ARGUMENTS, returning
|
|
6
|
+
* `{ extension }`. The loader calls it synchronously at boot, before
|
|
7
|
+
* `Harness.open` reads the registry.
|
|
8
|
+
*
|
|
9
|
+
* What the factory does, in order:
|
|
10
|
+
* 1. Reads the MCP namespace snapshot ONCE (src/config.ts):
|
|
11
|
+
* `SIGRUN_MCP_CONFIG` → `~/.config/sigrun/mcp.json`; absent file →
|
|
12
|
+
* empty namespaces (the extension still ships its codemode tool +
|
|
13
|
+
* section); a bad file warns and installs un-namespaced.
|
|
14
|
+
* 2. Builds the QuickJS sandbox with the pinned constructor options
|
|
15
|
+
* (timeoutMs 300_000 — pi-codemode's own default, restated so the
|
|
16
|
+
* contract does not drift; memoryLimitBytes 256 MiB — a real cap
|
|
17
|
+
* where the upstream default is unbounded wasm32).
|
|
18
|
+
* 3. Wraps upstream's `createCodemodeExtension({ sandbox, namespaces })`
|
|
19
|
+
* with the companion notice section (src/extension.ts).
|
|
20
|
+
*
|
|
21
|
+
* Note on `timeoutMs` (verified against pi-codemode 1.2.0): the
|
|
22
|
+
* CONSTRUCTOR timeout governs `sandbox.execute()`; the durable codemode
|
|
23
|
+
* tool path (`sandbox.start()`) takes its deadline from the script's own
|
|
24
|
+
* `// @options: {"timeout_ms": N}` line (no options line → no deadline:
|
|
25
|
+
* the sandbox default does not apply there). The constructor cap is
|
|
26
|
+
* still the right pin: it bounds every execution of the plain sandbox
|
|
27
|
+
* surface and documents the intended ceiling.
|
|
28
|
+
*
|
|
29
|
+
* `quickjs-wasi` is a REAL dependency of this package, not a transitive
|
|
30
|
+
* courtesy: pi-codemode's worker resolves `quickjs-wasi/quickjs.wasm`
|
|
31
|
+
* from disk at the first script. A re-pinned or deduped-away transitive
|
|
32
|
+
* copy strands the wasm file and the first codemode call fails at runtime
|
|
33
|
+
* (500s in prod) — declaring it here pins the resolution to this
|
|
34
|
+
* package's own tree.
|
|
35
|
+
*/
|
|
36
|
+
import { CodemodeSandbox } from "@earendil-works/pi-codemode";
|
|
37
|
+
import { loadNamespaces } from "./config.js";
|
|
38
|
+
import { createSigrunCodemodeExtension } from "./extension.js";
|
|
39
|
+
/** Pinned per-execution wall-clock deadline (pi-codemode's default). */
|
|
40
|
+
export const CODEMODE_TIMEOUT_MS = 300_000;
|
|
41
|
+
/** Pinned QuickJS heap cap (256 MiB; upstream default is unbounded). */
|
|
42
|
+
export const CODEMODE_MEMORY_LIMIT_BYTES = 256 * 1024 * 1024;
|
|
43
|
+
/**
|
|
44
|
+
* The codemode factory (the loader contract: no arguments; config resolves
|
|
45
|
+
* from the package context). Each call builds a FRESH sandbox — one
|
|
46
|
+
* wiring, one sandbox, no shared worker state across installs.
|
|
47
|
+
*/
|
|
48
|
+
export function createCodemodeWiring() {
|
|
49
|
+
const namespaces = loadNamespaces();
|
|
50
|
+
const sandbox = new CodemodeSandbox({
|
|
51
|
+
timeoutMs: CODEMODE_TIMEOUT_MS,
|
|
52
|
+
memoryLimitBytes: CODEMODE_MEMORY_LIMIT_BYTES,
|
|
53
|
+
});
|
|
54
|
+
const extension = createSigrunCodemodeExtension({ sandbox, namespaces });
|
|
55
|
+
return {
|
|
56
|
+
extension,
|
|
57
|
+
sandbox,
|
|
58
|
+
namespaces,
|
|
59
|
+
close: () => sandbox.close(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* The sigrun extension-package contract: the default export is a factory
|
|
64
|
+
* taking no arguments, returning `{ extension }`.
|
|
65
|
+
*/
|
|
66
|
+
export default createCodemodeWiring;
|
|
67
|
+
export { CODEMODE_NOT_OFFERED_NOTICE, CODEMODE_NOTICE_SECTION_KEY, renderCodemodeNotice, } from "./extension.js";
|
|
68
|
+
export { loadNamespaces, MCP_CONFIG_ENV, resolveMcpConfigPath, serverEnabled, } from "./config.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,59 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@sigrun/ext-codemode",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Codemode extension for sigrun (pi-durable): the `codemode` tool \u2014 model-written JavaScript in a QuickJS sandbox, with MCP-server tools namespaced as script-callable tools",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=22.19.0"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"CHANGELOG.md"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"test": "node scripts/check-manifest.mjs --expect-name @sigrun/ext-codemode && vitest run",
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"build": "tsc -p tsconfig.build.json",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"quickjs-wasi": "3.6.2"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@earendil-works/chord": "1.3.0",
|
|
32
|
+
"@earendil-works/pi-ai": "1.3.0",
|
|
33
|
+
"@earendil-works/pi-codemode": "1.3.0",
|
|
34
|
+
"@earendil-works/pi-durable": "1.3.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@earendil-works/chord": "1.3.0",
|
|
38
|
+
"@earendil-works/pi-ai": "1.3.0",
|
|
39
|
+
"@earendil-works/pi-codemode": "1.3.0",
|
|
40
|
+
"@earendil-works/pi-durable": "1.3.0",
|
|
41
|
+
"@types/node": "^26.6.4",
|
|
42
|
+
"tsx": "^4.23.15",
|
|
43
|
+
"typescript": "^7.0.2",
|
|
44
|
+
"vitest": "^5.0.3"
|
|
45
|
+
},
|
|
46
|
+
"license": "MIT",
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "github",
|
|
49
|
+
"url": "git+https://github.com/sigrun-ai/sigrun-ext-codemode.git"
|
|
50
|
+
},
|
|
51
|
+
"bugs": {
|
|
52
|
+
"url": "https://github.com/sigrun-ai/sigrun-ext-codemode/issues"
|
|
53
|
+
},
|
|
54
|
+
"homepage": "https://github.com/sigrun-ai/sigrun-ext-codemode#readme",
|
|
55
|
+
"publishConfig": {
|
|
56
|
+
"access": "public",
|
|
57
|
+
"provenance": true
|
|
58
|
+
}
|
|
59
|
+
}
|