@superjackfruitlabs/salaam 0.0.3 → 0.0.5
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 +86 -0
- package/README.md +12 -11
- package/dist/src/acp-desk.js +140 -0
- package/dist/src/acp-outcome.js +182 -18
- package/dist/src/acp.js +296 -15
- package/dist/src/agent-profiles.js +45 -0
- package/dist/src/agentpod-authority.js +169 -11
- package/dist/src/agentpod-default-config.js +12 -0
- package/dist/src/agentpod-work-decision-protocol.js +40 -6
- package/dist/src/agentpod-work-decisions.js +108 -4
- package/dist/src/agentpod-work.js +1214 -127
- package/dist/src/approval-rules.js +287 -0
- package/dist/src/attach.js +3 -1
- package/dist/src/autonomy.js +80 -9
- package/dist/src/board-reads.js +106 -0
- package/dist/src/children.js +83 -0
- package/dist/src/cli-help.js +61 -6
- package/dist/src/cli.js +140 -4
- package/dist/src/command-danger.js +797 -0
- package/dist/src/command-network.js +200 -0
- package/dist/src/command-sandbox.js +327 -0
- package/dist/src/custom-commands.js +159 -0
- package/dist/src/danger-classifier.js +286 -0
- package/dist/src/execution-evidence.js +33 -1
- package/dist/src/git-helpers.js +160 -0
- package/dist/src/hooks.js +351 -0
- package/dist/src/host-bind.js +111 -0
- package/dist/src/host-breaker.js +88 -0
- package/dist/src/host-start.js +41 -1
- package/dist/src/host.js +284 -6
- package/dist/src/house-extension.js +292 -61
- package/dist/src/local-coding.js +726 -35
- package/dist/src/local-edit-helper.js +25 -0
- package/dist/src/local-edits.js +168 -6
- package/dist/src/local-undo.js +25 -16
- package/dist/src/managed.js +1 -1
- package/dist/src/mentions.js +277 -0
- package/dist/src/operator-mcp-cli.js +107 -0
- package/dist/src/operator-mcp.js +342 -0
- package/dist/src/persona.js +31 -0
- package/dist/src/pi-sessions.js +5 -1
- package/dist/src/pi.js +22 -1
- package/dist/src/project-instructions.js +195 -0
- package/dist/src/protocol.js +9 -3
- package/dist/src/rate-limit-retries.js +62 -0
- package/dist/src/recurring-work.js +1 -0
- package/dist/src/repository-snapshots.js +5 -2
- package/dist/src/run-grants.js +62 -0
- package/dist/src/service.js +482 -10
- package/dist/src/session-pick.js +77 -0
- package/dist/src/shell-passthrough.js +39 -0
- package/dist/src/station-checkpoints.js +139 -0
- package/dist/src/station-config.js +8 -1
- package/dist/src/station-files.js +20 -1
- package/dist/src/station-task-verification.js +6 -3
- package/dist/src/station-work.js +315 -22
- package/dist/src/store.js +70 -4
- package/dist/src/supervisor.js +408 -25
- package/dist/src/task-budget.js +39 -3
- package/dist/src/task-context.js +8 -2
- package/dist/src/task-critic.js +115 -0
- package/dist/src/task-driver.js +46 -2
- package/dist/src/task-policy.js +44 -12
- package/dist/src/task-verification.js +42 -9
- package/dist/src/task-work.js +47 -0
- package/dist/src/terminal-status.js +88 -0
- package/dist/src/tool-identity.js +69 -0
- package/dist/src/tui-activity.js +99 -0
- package/dist/src/tui-classifier.js +25 -0
- package/dist/src/tui-client.js +186 -5
- package/dist/src/tui-commands.js +23 -5
- package/dist/src/tui-composer.js +113 -0
- package/dist/src/tui-keymap.js +116 -0
- package/dist/src/tui-mentions.js +38 -0
- package/dist/src/tui-modals.js +157 -34
- package/dist/src/tui-notify.js +62 -0
- package/dist/src/tui-review.js +55 -0
- package/dist/src/tui-turn-keys.js +52 -0
- package/dist/src/tui-view.js +243 -69
- package/dist/src/tui.js +875 -118
- package/dist/src/turn-checkpoints.js +221 -0
- package/dist/src/turn-rewind.js +168 -0
- package/dist/src/usage.js +1 -1
- package/dist/src/web-fetch.js +114 -0
- package/dist/src/web-guard.js +163 -0
- package/dist/src/web-search.js +302 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/src/acp-desk.ts +155 -0
- package/src/acp-outcome.ts +174 -20
- package/src/acp.ts +386 -30
- package/src/agent-profiles.ts +48 -0
- package/src/agentpod-authority.ts +234 -15
- package/src/agentpod-default-config.ts +16 -0
- package/src/agentpod-work-decision-protocol.ts +69 -8
- package/src/agentpod-work-decisions.ts +123 -5
- package/src/agentpod-work.ts +1455 -152
- package/src/approval-rules.ts +360 -0
- package/src/attach.ts +4 -1
- package/src/autonomy.ts +111 -10
- package/src/board-reads.ts +148 -0
- package/src/children.ts +112 -0
- package/src/cli-help.ts +60 -6
- package/src/cli.ts +174 -4
- package/src/command-danger.ts +886 -0
- package/src/command-network.ts +215 -0
- package/src/command-sandbox.ts +393 -0
- package/src/custom-commands.ts +175 -0
- package/src/danger-classifier.ts +321 -0
- package/src/execution-evidence.ts +31 -1
- package/src/git-helpers.ts +177 -0
- package/src/hooks.ts +425 -0
- package/src/host-bind.ts +156 -0
- package/src/host-breaker.ts +89 -0
- package/src/host-start.ts +51 -1
- package/src/host.ts +365 -6
- package/src/house-extension.ts +313 -60
- package/src/local-coding.ts +894 -43
- package/src/local-edit-helper.ts +26 -0
- package/src/local-edits.ts +191 -8
- package/src/local-undo.ts +29 -14
- package/src/managed.ts +2 -2
- package/src/mentions.ts +304 -0
- package/src/operator-mcp-cli.ts +108 -0
- package/src/operator-mcp.ts +420 -0
- package/src/persona.ts +37 -0
- package/src/pi-sessions.ts +9 -1
- package/src/pi.ts +23 -1
- package/src/project-instructions.ts +229 -0
- package/src/protocol.ts +25 -3
- package/src/rate-limit-retries.ts +69 -0
- package/src/recurring-work.ts +1 -0
- package/src/repository-snapshots.ts +5 -2
- package/src/run-grants.ts +107 -0
- package/src/service.ts +709 -10
- package/src/session-pick.ts +102 -0
- package/src/shell-passthrough.ts +38 -0
- package/src/station-checkpoints.ts +183 -0
- package/src/station-config.ts +10 -1
- package/src/station-files.ts +20 -1
- package/src/station-task-verification.ts +6 -3
- package/src/station-work.ts +369 -20
- package/src/store.ts +70 -3
- package/src/supervisor.ts +463 -26
- package/src/task-budget.ts +48 -3
- package/src/task-context.ts +9 -2
- package/src/task-critic.ts +171 -0
- package/src/task-driver.ts +49 -2
- package/src/task-policy.ts +65 -13
- package/src/task-verification.ts +53 -9
- package/src/task-work.ts +75 -0
- package/src/terminal-status.ts +103 -0
- package/src/tool-identity.ts +110 -0
- package/src/tui-activity.ts +133 -0
- package/src/tui-classifier.ts +38 -0
- package/src/tui-client.ts +239 -8
- package/src/tui-commands.ts +49 -10
- package/src/tui-composer.ts +124 -0
- package/src/tui-keymap.ts +152 -0
- package/src/tui-mentions.ts +43 -0
- package/src/tui-modals.ts +173 -43
- package/src/tui-notify.ts +77 -0
- package/src/tui-review.ts +76 -0
- package/src/tui-turn-keys.ts +77 -0
- package/src/tui-view.ts +341 -88
- package/src/tui.ts +1047 -137
- package/src/turn-checkpoints.ts +253 -0
- package/src/turn-rewind.ts +258 -0
- package/src/usage.ts +1 -1
- package/src/web-fetch.ts +140 -0
- package/src/web-guard.ts +195 -0
- package/src/web-search.ts +402 -0
package/dist/src/cli-help.js
CHANGED
|
@@ -53,12 +53,22 @@ salaam agents revoke GRANT_ID --session SESSION_ID
|
|
|
53
53
|
Profiles are data in .salaam/agents/*.md with JSON front matter and a prompt body.
|
|
54
54
|
Inspect the effective tools and digest before admission. Project definitions cannot
|
|
55
55
|
grant themselves authority. Mutations accept --request-id and --takeover.`,
|
|
56
|
+
code: `salaam code [--continue | --new | --resume] [--cwd DIR] [--takeover]
|
|
57
|
+
salaam here (the same)
|
|
58
|
+
salaam -c (short for salaam code --continue)
|
|
59
|
+
|
|
60
|
+
Work in this folder with one command: start the service if it is not running, then continue
|
|
61
|
+
the folder's latest session (the default), start a new local coding session (--new), or pick
|
|
62
|
+
any session from a list (--resume), this folder's sessions first. No session id needed.
|
|
63
|
+
SALAAM_TERMINAL_STATUS=off stops the window-title and Herdr status reports.`,
|
|
56
64
|
tui: `salaam tui [--session SESSION_ID] [--observe|--takeover] [--theme night|paper]
|
|
57
65
|
[--cwd DIR] [--coding-root PRIVATE_DIR] [--coding-socket DOCKER_SOCKET]
|
|
58
66
|
|
|
59
67
|
Bare sal opens the same Salaam terminal interface in a TTY.
|
|
60
|
-
Ctrl+K actions · Ctrl+P sessions · Ctrl+N new · Ctrl+O approvals
|
|
61
|
-
|
|
68
|
+
Ctrl+K (empty composer) or F2 actions · Ctrl+P sessions · Ctrl+N new · Ctrl+O approvals
|
|
69
|
+
Alt+G changes · Ctrl+T commands · Ctrl+G external editor · Ctrl+R history search
|
|
70
|
+
F5 refresh · !command shell · Ctrl+C stops/clears, twice to detach.
|
|
71
|
+
? on an empty composer (or F1) shows the keys for where you are.
|
|
62
72
|
Work continues in the service when the terminal closes.`,
|
|
63
73
|
remote: `salaam remote SSH_HOST [--remote-bin ABSOLUTE_PATH] [--state REMOTE_DIR]
|
|
64
74
|
[--session SESSION_ID] [--observe|--takeover] [--theme night|paper]
|
|
@@ -88,9 +98,11 @@ Run the M9.1 boundary proof on a pre-provisioned local Linux Docker engine.
|
|
|
88
98
|
Only disposable fixtures are mounted. The pinned image must already be present.
|
|
89
99
|
No coding tools are enabled. A failed/unavailable backend exits nonzero.
|
|
90
100
|
Cleanup reconciles the saved proof run without replaying commands.`,
|
|
91
|
-
acp: `salaam acp [--state DIR] [--coding]
|
|
101
|
+
acp: `salaam acp [--state DIR] [--local | --coding]
|
|
92
102
|
|
|
93
103
|
Run the ACP v1 stdio client adapter against an already running Salaam service.
|
|
104
|
+
--local creates your desk session in the editor's project folder, the same as
|
|
105
|
+
salaam in a terminal there: modes, approvals with diffs, rules and /rewind.
|
|
94
106
|
--coding creates owned coding sessions; the service must have --coding-root.
|
|
95
107
|
Loading an existing session preserves its original tool authority.`,
|
|
96
108
|
artifacts: `salaam artifacts put SESSION_ID --text TEXT [--request-id ID] [--takeover]
|
|
@@ -103,6 +115,10 @@ salaam host inspect --manifest host-manifest.json
|
|
|
103
115
|
salaam host unit --manifest host-manifest.json --platform systemd|launchd
|
|
104
116
|
salaam host run --manifest host-manifest.json
|
|
105
117
|
salaam host start --manifest host-manifest.json
|
|
118
|
+
salaam host unit-start --unit salaam-host@STATION.service --state DIR
|
|
119
|
+
salaam host bind --organization ORG --node NODE --station-key KEY --workspace DIR \
|
|
120
|
+
--tools-user USER --files HELPER --runtime-root DIR --runtime-image-digest sha256:… \
|
|
121
|
+
[--operator-group GROUP] [--provider P --model M] [--mcp-config FILE] [--persona FILE] [--managed-mcp-config FILE] [--dir DIR] [--state DIR]
|
|
106
122
|
|
|
107
123
|
Config requires absolute state, coding_root and coding_socket paths; optional
|
|
108
124
|
provider, model, max_output_tokens and workspace_id. Planning probes the existing
|
|
@@ -116,7 +132,18 @@ For a bound AgentPod host, use mode="agentpod", state and agentpod_config instea
|
|
|
116
132
|
of coding_root/coding_socket. This profile enables no station tools. The private
|
|
117
133
|
manifest pins Node, CLI, source/build, Pi, provider and authority pins. Invoke the
|
|
118
134
|
canonical Node executable explicitly. host start waits for matching live health
|
|
119
|
-
and safely coalesces concurrent callers; it never installs or upgrades packages
|
|
135
|
+
and safely coalesces concurrent callers; it never installs or upgrades packages.
|
|
136
|
+
|
|
137
|
+
Launcher profile (Linux): root plans a strict work host with operator_group set.
|
|
138
|
+
A root-owned unit runs host run from that root-held manifest. The daemon lets that
|
|
139
|
+
one group traverse its state and use operator.sock. An unprivileged member then
|
|
140
|
+
runs host unit-start, which asks systemd to start the named salaam-host@ unit and
|
|
141
|
+
prints the receipt the running daemon reports. It cannot choose what root runs.
|
|
142
|
+
|
|
143
|
+
host bind (root, Linux) writes everything a launcher-profile station needs into
|
|
144
|
+
--dir (default /etc/salaam/stations/<key>): agentpod-pins.json, station-config.json
|
|
145
|
+
(with tools_user), host-config.json, and host.json from host plan. It is
|
|
146
|
+
idempotent: the same inputs leave the files and the manifest digest unchanged.`,
|
|
120
147
|
schedules: `salaam schedules create TASK_ID --name NAME --revision N --max-steps N [--schedule FILE] [--compact]
|
|
121
148
|
salaam schedules list [--offset N]
|
|
122
149
|
salaam schedules inspect JOB_ID
|
|
@@ -208,10 +235,32 @@ Status prints metadata only. Existing Anthropic keys remain compatible.`,
|
|
|
208
235
|
[--coding-root PRIVATE_DIR] [--coding-socket DOCKER_SOCKET]
|
|
209
236
|
[--harness-config OWNER_ONLY_FILE] [--a2a-config OWNER_ONLY_FILE]
|
|
210
237
|
[--a2a-listen-config OWNER_ONLY_FILE]
|
|
211
|
-
[--agentpod-config OWNER_ONLY_FILE]
|
|
238
|
+
[--agentpod-config OWNER_ONLY_FILE] [--mcp-config FILE]
|
|
239
|
+
[--tools-user USER]
|
|
240
|
+
[--local-sandbox read-only|workspace-write|full-access]
|
|
241
|
+
[--local-sandbox-read PATH,…|toolchain] [--unsandboxed-commands allow]
|
|
212
242
|
salaam service status
|
|
213
243
|
salaam service stop
|
|
214
244
|
|
|
245
|
+
--tools-user USER (or SALAAM_TOOLS_USER) runs local agent commands and edits as
|
|
246
|
+
USER through sudo -n -u USER on Linux. Without it, tools share the provider
|
|
247
|
+
credential's OS user and start prints a warning.
|
|
248
|
+
|
|
249
|
+
Local commands (session create --local-coding) run under the host OS sandbox:
|
|
250
|
+
bubblewrap on Linux, Seatbelt on macOS. --local-sandbox (or SALAAM_LOCAL_SANDBOX)
|
|
251
|
+
picks the level: workspace-write (default) writes only inside the workspace,
|
|
252
|
+
read-only writes nothing, full-access runs commands unsandboxed with network. A
|
|
253
|
+
sandboxed command has no network and cannot read outside the workspace and the
|
|
254
|
+
system; --local-sandbox-read (or SALAAM_LOCAL_SANDBOX_READ) lists read-only paths
|
|
255
|
+
it may also read, comma-separated, and "toolchain" adds this host's node prefix,
|
|
256
|
+
~/.npm, ~/.nvm, ~/.cargo, ~/.rustup, ~/go and ~/.gitconfig where present. Home
|
|
257
|
+
itself and credential directories (~/.ssh, ~/.aws, keychains …) are refused. On
|
|
258
|
+
macOS commands get the real git from the active developer dir. A host with no
|
|
259
|
+
usable sandbox refuses commands unless --unsandboxed-commands allow.
|
|
260
|
+
|
|
261
|
+
Without --agentpod-config, start binds to ~/.config/salaam/agentpod-pins.json
|
|
262
|
+
($XDG_CONFIG_HOME/salaam) when that file exists.
|
|
263
|
+
|
|
215
264
|
The default provider is offline. Anthropic defaults to claude-sonnet-5-5.
|
|
216
265
|
Other providers require --model; use salaam providers list and salaam models list PROVIDER.
|
|
217
266
|
Start with --foreground for process-supervisor use; otherwise the service detaches.
|
|
@@ -219,7 +268,8 @@ An AgentPod daemon requires node-bound admissions and a fresh authority lease.
|
|
|
219
268
|
Keep its private state outside the pinned workspace. Coding, external runtimes,
|
|
220
269
|
effect connectors and managed MCP are unavailable in this profile.`,
|
|
221
270
|
session: `salaam session create [--cwd DIR] [--request-id ID] [--coding | --local | --local-coding]
|
|
222
|
-
--local-coding allows reviewed edits and native commands
|
|
271
|
+
--local-coding allows reviewed edits and native commands, each under the host OS sandbox
|
|
272
|
+
(see salaam help service for levels and read paths)
|
|
223
273
|
--local allows bounded local file inspection; optionally select --provider ID --model ID
|
|
224
274
|
salaam session list
|
|
225
275
|
salaam session inspect SESSION_ID
|
|
@@ -272,6 +322,8 @@ const globalOptions = `Global options:
|
|
|
272
322
|
-h, --help Show help without starting a service or model request.
|
|
273
323
|
-V, --version Show the installed version.`;
|
|
274
324
|
export function cliHelp(group) {
|
|
325
|
+
if (group === 'here')
|
|
326
|
+
group = 'code';
|
|
275
327
|
if (group)
|
|
276
328
|
return commands[group] ? `${commands[group]}\n\n${globalOptions}` : undefined;
|
|
277
329
|
return `Salaam — persistent coding sessions
|
|
@@ -280,6 +332,7 @@ Usage: salaam <command> [options]
|
|
|
280
332
|
sal <command> [options]
|
|
281
333
|
|
|
282
334
|
Commands:
|
|
335
|
+
code Work in this folder: continue its session or start one (also: here, -c)
|
|
283
336
|
tui Open the Salaam terminal interface (also bare sal)
|
|
284
337
|
remote Open the same session over SSH
|
|
285
338
|
providers List pinned Pi providers and capabilities
|
|
@@ -287,6 +340,7 @@ Commands:
|
|
|
287
340
|
auth Configure provider credentials or OAuth
|
|
288
341
|
service Start, inspect or stop the session service
|
|
289
342
|
session Create, inspect, submit, resume or cancel work
|
|
343
|
+
mcp Declare operator MCP servers (add, list, rm)
|
|
290
344
|
attach Open an interactive terminal on a session
|
|
291
345
|
acp Connect an editor over ACP v1 stdio
|
|
292
346
|
approvals Inspect, approve or deny managed operations
|
|
@@ -357,6 +411,7 @@ const valueOptions = new Set([
|
|
|
357
411
|
'--a2a-config',
|
|
358
412
|
'--agentpod-config',
|
|
359
413
|
'--a2a-listen-config',
|
|
414
|
+
'--tools-user',
|
|
360
415
|
'--assignment',
|
|
361
416
|
'--peer',
|
|
362
417
|
'--peer-client',
|
package/dist/src/cli.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { loadDangerClassifierOptions } from './danger-classifier.js';
|
|
3
|
+
import { loadWebSearchConfig } from './web-search.js';
|
|
4
|
+
import { SANDBOX_LEVELS } from './command-sandbox.js';
|
|
2
5
|
import { acp } from './acp.js';
|
|
3
6
|
import { homedir } from 'node:os';
|
|
4
7
|
import { join, resolve, dirname } from 'node:path';
|
|
@@ -6,9 +9,12 @@ import { spawn } from 'node:child_process';
|
|
|
6
9
|
import { randomUUID, randomBytes } from 'node:crypto';
|
|
7
10
|
import { digest, object } from './protocol.js';
|
|
8
11
|
import { fileURLToPath } from 'node:url';
|
|
9
|
-
import { mkdirSync, openSync, closeSync, readFileSync, realpathSync, writeFileSync, fsyncSync, } from 'node:fs';
|
|
12
|
+
import { mkdirSync, openSync, closeSync, readFileSync, realpathSync, writeFileSync, fsyncSync, existsSync, } from 'node:fs';
|
|
10
13
|
import { VERSION } from './config.js';
|
|
11
14
|
import { cliHelp, hasHelpFlag } from './cli-help.js';
|
|
15
|
+
import { mcpCli, MCP_HELP } from './operator-mcp-cli.js';
|
|
16
|
+
import { operatorMcpPath, readOperatorMcpFile } from './operator-mcp.js';
|
|
17
|
+
import { defaultAgentPodConfig } from './agentpod-default-config.js';
|
|
12
18
|
import { SalaamService } from './service.js';
|
|
13
19
|
import { call } from './transport.js';
|
|
14
20
|
import { attach, acquireControl, Outbox } from './attach.js';
|
|
@@ -29,6 +35,21 @@ async function main() {
|
|
|
29
35
|
console.log('salaam ' + VERSION);
|
|
30
36
|
return;
|
|
31
37
|
}
|
|
38
|
+
if (args[0] === '-c' || args[0] === '--continue') {
|
|
39
|
+
const { continueArgs } = await import('./session-pick.js');
|
|
40
|
+
args.splice(0, args.length, ...continueArgs(args));
|
|
41
|
+
}
|
|
42
|
+
if (args[0] === 'mcp') {
|
|
43
|
+
// Parsed before global help: a declared command's own flags follow "--".
|
|
44
|
+
const rest = args.slice(1);
|
|
45
|
+
const dash = rest.indexOf('--');
|
|
46
|
+
const flags = dash < 0 ? rest : rest.slice(0, dash);
|
|
47
|
+
if (!rest.length || flags.includes('--help') || flags.includes('-h'))
|
|
48
|
+
console.log(MCP_HELP);
|
|
49
|
+
else
|
|
50
|
+
console.log(mcpCli(rest));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
32
53
|
if ((!args.length && !(process.stdin.isTTY && process.stdout.isTTY)) ||
|
|
33
54
|
args[0] === 'help' ||
|
|
34
55
|
hasHelpFlag(args)) {
|
|
@@ -388,7 +409,7 @@ async function main() {
|
|
|
388
409
|
return;
|
|
389
410
|
}
|
|
390
411
|
if (group === 'host') {
|
|
391
|
-
const { planHost, readHost, hostUnit, runHost } = await import('./host.js');
|
|
412
|
+
const { planHost, readHost, hostUnit, runHost, hostReceipt, hostToolsUser, hostApprovalTtlMs, hostAllowsUnsandboxed, hostAllowsFullAccessSessions, hostAllowsYoloSessions, hostDangerClassifier, hostCommandNetwork, hostReadPaths, } = await import('./host.js');
|
|
392
413
|
if (verb?.startsWith('config-')) {
|
|
393
414
|
const file = option('--manifest');
|
|
394
415
|
if (!file)
|
|
@@ -413,6 +434,42 @@ async function main() {
|
|
|
413
434
|
console.log(JSON.stringify(await planHost(JSON.parse(readFileSync(resolve(file), 'utf8'))), null, 2));
|
|
414
435
|
return;
|
|
415
436
|
}
|
|
437
|
+
if (verb === 'bind') {
|
|
438
|
+
const { bindHost } = await import('./host-bind.js');
|
|
439
|
+
const required = (name) => {
|
|
440
|
+
const v = option(name);
|
|
441
|
+
if (!v)
|
|
442
|
+
throw new Error('Supply ' + name);
|
|
443
|
+
return v;
|
|
444
|
+
};
|
|
445
|
+
console.log(JSON.stringify(await bindHost({
|
|
446
|
+
organization_id: required('--organization'),
|
|
447
|
+
node_id: required('--node'),
|
|
448
|
+
station_key: required('--station-key'),
|
|
449
|
+
workspace: required('--workspace'),
|
|
450
|
+
tools_user: required('--tools-user'),
|
|
451
|
+
files: required('--files'),
|
|
452
|
+
runtime_root: required('--runtime-root'),
|
|
453
|
+
runtime_image_digest: required('--runtime-image-digest'),
|
|
454
|
+
operator_group: option('--operator-group'),
|
|
455
|
+
dir: option('--dir'),
|
|
456
|
+
state: explicitState ? state : undefined,
|
|
457
|
+
provider: option('--provider'),
|
|
458
|
+
model: option('--model'),
|
|
459
|
+
mcp_config: option('--mcp-config'),
|
|
460
|
+
persona: option('--persona'),
|
|
461
|
+
managed_mcp_config: option('--managed-mcp-config'),
|
|
462
|
+
})));
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
if (verb === 'unit-start') {
|
|
466
|
+
const { startHostUnit } = await import('./host-start.js');
|
|
467
|
+
const unit = option('--unit');
|
|
468
|
+
if (!unit || !explicitState)
|
|
469
|
+
throw new Error('Supply --unit UNIT and --state DIR');
|
|
470
|
+
console.log(JSON.stringify(await startHostUnit(unit, state)));
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
416
473
|
const file = option('--manifest');
|
|
417
474
|
if (!file)
|
|
418
475
|
throw new Error('Supply --manifest FILE');
|
|
@@ -462,9 +519,32 @@ async function main() {
|
|
|
462
519
|
: {}),
|
|
463
520
|
...(m.schema === 5 || m.schema === 6 ? { stationConfig: m.station_execution } : {}),
|
|
464
521
|
...(m.schema === 6 ? { agentpodWorkProgression: true } : {}),
|
|
522
|
+
...(m.schema === 6 && m.operator_access
|
|
523
|
+
? { operatorAccess: m.operator_access }
|
|
524
|
+
: {}),
|
|
525
|
+
...(m.schema === 6 && m.operator_mcp
|
|
526
|
+
? { operatorMcpConfig: m.operator_mcp.config }
|
|
527
|
+
: {}),
|
|
528
|
+
...(m.schema === 6 && m.persona ? { personaConfig: m.persona } : {}),
|
|
465
529
|
}),
|
|
466
530
|
hostManifestDigest: digest(m),
|
|
531
|
+
hostReceipt: hostReceipt(m),
|
|
532
|
+
toolsUser: hostToolsUser(m),
|
|
467
533
|
providerRoute: m.provider,
|
|
534
|
+
approvalTtlMs: hostApprovalTtlMs(m),
|
|
535
|
+
...(hostAllowsUnsandboxed(m) ? { unsandboxedCommands: 'allow' } : {}),
|
|
536
|
+
// A host session may choose full access only when the reviewed manifest says so.
|
|
537
|
+
allowFullAccessSessions: hostAllowsFullAccessSessions(m),
|
|
538
|
+
allowYoloSessions: hostAllowsYoloSessions(m),
|
|
539
|
+
// The command reviewer only as the reviewed manifest names it (forbidden when absent).
|
|
540
|
+
...(hostDangerClassifier(m).config
|
|
541
|
+
? { dangerClassifierConfig: hostDangerClassifier(m).config }
|
|
542
|
+
: {}),
|
|
543
|
+
...(hostDangerClassifier(m).pin
|
|
544
|
+
? { dangerClassifierPin: hostDangerClassifier(m).pin }
|
|
545
|
+
: {}),
|
|
546
|
+
...(hostCommandNetwork(m) ? { commandNetwork: hostCommandNetwork(m) } : {}),
|
|
547
|
+
...(hostReadPaths(m).length ? { localSandboxReadPaths: hostReadPaths(m) } : {}),
|
|
468
548
|
});
|
|
469
549
|
if (process.connected)
|
|
470
550
|
process.once('disconnect', () => void service.close());
|
|
@@ -493,6 +573,20 @@ async function main() {
|
|
|
493
573
|
});
|
|
494
574
|
return;
|
|
495
575
|
}
|
|
576
|
+
if (group === 'code' || group === 'here') {
|
|
577
|
+
const { parseCodeStart } = await import('./session-pick.js');
|
|
578
|
+
const start = parseCodeStart(args.slice(1));
|
|
579
|
+
const { tui } = await import('./tui.js');
|
|
580
|
+
await tui({
|
|
581
|
+
state,
|
|
582
|
+
start,
|
|
583
|
+
cwd: option('--cwd'),
|
|
584
|
+
takeover: args.includes('--takeover'),
|
|
585
|
+
codingRoot: option('--coding-root'),
|
|
586
|
+
codingSocket: option('--coding-socket'),
|
|
587
|
+
});
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
496
590
|
if (!group ||
|
|
497
591
|
group === 'tui' ||
|
|
498
592
|
[
|
|
@@ -626,7 +720,7 @@ async function main() {
|
|
|
626
720
|
return;
|
|
627
721
|
}
|
|
628
722
|
if (group === 'acp') {
|
|
629
|
-
await acp(state, { coding: args.includes('--coding') });
|
|
723
|
+
await acp(state, { coding: args.includes('--coding'), local: args.includes('--local') });
|
|
630
724
|
return;
|
|
631
725
|
}
|
|
632
726
|
if (group === 'providers' && verb === 'list') {
|
|
@@ -1245,17 +1339,41 @@ async function main() {
|
|
|
1245
1339
|
}
|
|
1246
1340
|
const effectSocket = option('--effect-socket');
|
|
1247
1341
|
const opaque = args.includes('--effect-opaque');
|
|
1248
|
-
const codingRoot = option('--coding-root'), codingSocket = option('--coding-socket'), harnessConfig = option('--harness-config'), a2aConfig = option('--a2a-config'), agentpodConfig = option('--agentpod-config'), a2aListenConfig = option('--a2a-listen-config')
|
|
1342
|
+
const codingRoot = option('--coding-root'), codingSocket = option('--coding-socket'), harnessConfig = option('--harness-config'), a2aConfig = option('--a2a-config'), agentpodConfig = option('--agentpod-config') ?? defaultAgentPodConfig(process.env, existsSync), a2aListenConfig = option('--a2a-listen-config'), mcpConfig = resolve(option('--mcp-config') ?? operatorMcpPath(process.env)), toolsUser = option('--tools-user') ?? (process.env.SALAAM_TOOLS_USER || undefined), localSandbox = option('--local-sandbox') ?? (process.env.SALAAM_LOCAL_SANDBOX || undefined), unsandboxedCommands = option('--unsandboxed-commands') ?? (process.env.SALAAM_UNSANDBOXED_COMMANDS || undefined), localSandboxRead = (option('--local-sandbox-read') ??
|
|
1343
|
+
(process.env.SALAAM_LOCAL_SANDBOX_READ || ''))
|
|
1344
|
+
.split(',')
|
|
1345
|
+
.map((p) => p.trim())
|
|
1346
|
+
.filter(Boolean), webSearchConfig = option('--web-search-config') ?? (process.env.SALAAM_WEB_SEARCH_CONFIG || undefined), dangerClassifierConfig = option('--danger-classifier-config') ??
|
|
1347
|
+
(process.env.SALAAM_DANGER_CLASSIFIER_CONFIG || undefined);
|
|
1348
|
+
// Fail early on a bad command-reviewer config; its key is read from the named variable, never printed.
|
|
1349
|
+
if (dangerClassifierConfig)
|
|
1350
|
+
loadDangerClassifierOptions(JSON.parse(readFileSync(resolve(dangerClassifierConfig), 'utf8')));
|
|
1351
|
+
// Fail early on a bad web search config; its keys are read, never printed.
|
|
1352
|
+
if (webSearchConfig)
|
|
1353
|
+
loadWebSearchConfig(resolve(webSearchConfig));
|
|
1354
|
+
if (localSandbox !== undefined && !SANDBOX_LEVELS.includes(localSandbox))
|
|
1355
|
+
throw Error('--local-sandbox is read-only, workspace-write or full-access');
|
|
1356
|
+
if (unsandboxedCommands !== undefined && unsandboxedCommands !== 'allow')
|
|
1357
|
+
throw Error('--unsandboxed-commands is allow or absent');
|
|
1249
1358
|
if (foreground) {
|
|
1250
1359
|
const service = await SalaamService.open({
|
|
1251
1360
|
stateDir: state,
|
|
1252
1361
|
providerRoute: route,
|
|
1253
1362
|
agentpodConfig: agentpodConfig ? resolve(agentpodConfig) : undefined,
|
|
1363
|
+
operatorMcpConfig: mcpConfig,
|
|
1254
1364
|
codingRoot: codingRoot ? resolve(codingRoot) : undefined,
|
|
1255
1365
|
codingSocket: codingSocket ? resolve(codingSocket) : undefined,
|
|
1256
1366
|
harnessConfig: harnessConfig ? resolve(harnessConfig) : undefined,
|
|
1257
1367
|
a2aConfig: a2aConfig ? resolve(a2aConfig) : undefined,
|
|
1258
1368
|
a2aListenConfig: a2aListenConfig ? resolve(a2aListenConfig) : undefined,
|
|
1369
|
+
toolsUser,
|
|
1370
|
+
...(localSandbox ? { localSandbox: localSandbox } : {}),
|
|
1371
|
+
...(unsandboxedCommands ? { unsandboxedCommands: 'allow' } : {}),
|
|
1372
|
+
...(localSandboxRead.length ? { localSandboxReadPaths: localSandboxRead } : {}),
|
|
1373
|
+
...(webSearchConfig ? { webSearchConfig: resolve(webSearchConfig) } : {}),
|
|
1374
|
+
...(dangerClassifierConfig
|
|
1375
|
+
? { dangerClassifierConfig: resolve(dangerClassifierConfig) }
|
|
1376
|
+
: {}),
|
|
1259
1377
|
effectConnector: effectSocket
|
|
1260
1378
|
? new SocketEffectConnector(resolve(effectSocket), { opaque })
|
|
1261
1379
|
: undefined,
|
|
@@ -1263,6 +1381,9 @@ async function main() {
|
|
|
1263
1381
|
const warning = service.supervisor.providerCapabilities().warning;
|
|
1264
1382
|
if (warning)
|
|
1265
1383
|
console.error(warning);
|
|
1384
|
+
// Only a live provider has a credential to share; the offline proof route stays quiet.
|
|
1385
|
+
if (service.toolIdentity.warning && route.provider !== 'salaam-proof')
|
|
1386
|
+
console.error('warning: ' + service.toolIdentity.warning);
|
|
1266
1387
|
process.stdout.write(JSON.stringify({ socket, service: 'started' }) + '\n');
|
|
1267
1388
|
for (const signal of ['SIGINT', 'SIGTERM'])
|
|
1268
1389
|
process.once(signal, () => {
|
|
@@ -1290,6 +1411,11 @@ async function main() {
|
|
|
1290
1411
|
if ((health.coding_root ?? null) !== (codingRoot ? resolve(codingRoot) : null) ||
|
|
1291
1412
|
(health.coding_socket ?? null) !== (codingSocket ? resolve(codingSocket) : null))
|
|
1292
1413
|
throw new Error('Service is already running with another coding configuration; stop it first');
|
|
1414
|
+
if ((health.operator_mcp?.config ?? null) !== mcpConfig)
|
|
1415
|
+
throw new Error('Service is already running with another MCP config; stop it first');
|
|
1416
|
+
if (health.operator_mcp &&
|
|
1417
|
+
health.operator_mcp.digest !== digest(readOperatorMcpFile(mcpConfig)))
|
|
1418
|
+
console.error('Declared MCP servers changed since the service started; run salaam service stop, then start, to apply them');
|
|
1293
1419
|
console.log('Salaam service already running');
|
|
1294
1420
|
return;
|
|
1295
1421
|
}
|
|
@@ -1315,6 +1441,16 @@ async function main() {
|
|
|
1315
1441
|
...(a2aConfig ? ['--a2a-config', resolve(a2aConfig)] : []),
|
|
1316
1442
|
...(agentpodConfig ? ['--agentpod-config', resolve(agentpodConfig)] : []),
|
|
1317
1443
|
...(a2aListenConfig ? ['--a2a-listen-config', resolve(a2aListenConfig)] : []),
|
|
1444
|
+
'--mcp-config',
|
|
1445
|
+
mcpConfig,
|
|
1446
|
+
...(toolsUser ? ['--tools-user', toolsUser] : []),
|
|
1447
|
+
...(localSandbox ? ['--local-sandbox', localSandbox] : []),
|
|
1448
|
+
...(unsandboxedCommands ? ['--unsandboxed-commands', 'allow'] : []),
|
|
1449
|
+
...(localSandboxRead.length ? ['--local-sandbox-read', localSandboxRead.join(',')] : []),
|
|
1450
|
+
...(webSearchConfig ? ['--web-search-config', resolve(webSearchConfig)] : []),
|
|
1451
|
+
...(dangerClassifierConfig
|
|
1452
|
+
? ['--danger-classifier-config', resolve(dangerClassifierConfig)]
|
|
1453
|
+
: []),
|
|
1318
1454
|
], { detached: true, stdio: ['ignore', fd, fd] });
|
|
1319
1455
|
closeSync(fd);
|
|
1320
1456
|
child.unref();
|