@stratusagent/cli 0.11.2 → 0.11.4
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/README.md +14 -8
- package/dist/approvals.d.ts +93 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +368 -0
- package/dist/approvals.js.map +1 -0
- package/dist/commands/agent-new.d.ts +22 -0
- package/dist/commands/agent-new.d.ts.map +1 -0
- package/dist/commands/agent-new.js +159 -0
- package/dist/commands/agent-new.js.map +1 -0
- package/dist/commands/agents.d.ts +4 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +90 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/chat.d.ts +4 -0
- package/dist/commands/chat.d.ts.map +1 -0
- package/dist/commands/chat.js +227 -0
- package/dist/commands/chat.js.map +1 -0
- package/dist/commands/credential.d.ts +22 -0
- package/dist/commands/credential.d.ts.map +1 -0
- package/dist/commands/credential.js +93 -0
- package/dist/commands/credential.js.map +1 -0
- package/dist/commands/dashboard.d.ts +14 -0
- package/dist/commands/dashboard.d.ts.map +1 -0
- package/dist/commands/dashboard.js +195 -0
- package/dist/commands/dashboard.js.map +1 -0
- package/dist/commands/doctor.d.ts +40 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +376 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/grants.d.ts +19 -0
- package/dist/commands/grants.d.ts.map +1 -0
- package/dist/commands/grants.js +128 -0
- package/dist/commands/grants.js.map +1 -0
- package/dist/commands/logs.d.ts +9 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +58 -0
- package/dist/commands/logs.js.map +1 -0
- package/dist/commands/memory.d.ts +20 -0
- package/dist/commands/memory.d.ts.map +1 -0
- package/dist/commands/memory.js +110 -0
- package/dist/commands/memory.js.map +1 -0
- package/dist/commands/plugins.d.ts +103 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +386 -0
- package/dist/commands/plugins.js.map +1 -0
- package/dist/commands/restart.d.ts +4 -0
- package/dist/commands/restart.d.ts.map +1 -0
- package/dist/commands/restart.js +25 -0
- package/dist/commands/restart.js.map +1 -0
- package/dist/commands/schedules.d.ts +11 -0
- package/dist/commands/schedules.d.ts.map +1 -0
- package/dist/commands/schedules.js +50 -0
- package/dist/commands/schedules.js.map +1 -0
- package/dist/commands/serve.d.ts +4 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +633 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/service.d.ts +9 -0
- package/dist/commands/service.d.ts.map +1 -0
- package/dist/commands/service.js +97 -0
- package/dist/commands/service.js.map +1 -0
- package/dist/commands/session.d.ts +9 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +25 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/setup.d.ts +5 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +2467 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/skills.d.ts +15 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +272 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/template.d.ts +4 -0
- package/dist/commands/template.d.ts.map +1 -0
- package/dist/commands/template.js +593 -0
- package/dist/commands/template.js.map +1 -0
- package/dist/commands/update.d.ts +21 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +291 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/daemon.d.ts +74 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +192 -0
- package/dist/daemon.js.map +1 -0
- package/dist/environment.d.ts +114 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +2 -0
- package/dist/environment.js.map +1 -0
- package/dist/events.d.ts +17 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +87 -0
- package/dist/events.js.map +1 -0
- package/dist/help.d.ts +2 -0
- package/dist/help.d.ts.map +1 -0
- package/dist/help.js +272 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +32 -624
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +39 -6981
- package/dist/index.js.map +1 -1
- package/dist/io.d.ts +16 -0
- package/dist/io.d.ts.map +1 -0
- package/dist/io.js +45 -0
- package/dist/io.js.map +1 -0
- package/dist/loaders.d.ts +31 -0
- package/dist/loaders.d.ts.map +1 -0
- package/dist/loaders.js +56 -0
- package/dist/loaders.js.map +1 -0
- package/dist/main.d.ts +8 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +218 -0
- package/dist/main.js.map +1 -0
- package/dist/npm.d.ts +66 -0
- package/dist/npm.d.ts.map +1 -0
- package/dist/npm.js +201 -0
- package/dist/npm.js.map +1 -0
- package/dist/parse.d.ts +245 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +1098 -0
- package/dist/parse.js.map +1 -0
- package/dist/plugin-catalog.d.ts +44 -0
- package/dist/plugin-catalog.d.ts.map +1 -0
- package/dist/plugin-catalog.js +70 -0
- package/dist/plugin-catalog.js.map +1 -0
- package/dist/preflight.d.ts +60 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +102 -0
- package/dist/preflight.js.map +1 -0
- package/dist/prompter.d.ts +84 -0
- package/dist/prompter.d.ts.map +1 -0
- package/dist/prompter.js +347 -0
- package/dist/prompter.js.map +1 -0
- package/dist/roster.d.ts +57 -0
- package/dist/roster.d.ts.map +1 -0
- package/dist/roster.js +78 -0
- package/dist/roster.js.map +1 -0
- package/dist/runtime.d.ts +76 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +372 -0
- package/dist/runtime.js.map +1 -0
- package/dist/slack.d.ts +26 -0
- package/dist/slack.d.ts.map +1 -0
- package/dist/slack.js +113 -0
- package/dist/slack.js.map +1 -0
- package/dist/source.d.ts +24 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +80 -0
- package/dist/source.js.map +1 -0
- package/dist/supervisor.d.ts +69 -0
- package/dist/supervisor.d.ts.map +1 -0
- package/dist/supervisor.js +218 -0
- package/dist/supervisor.js.map +1 -0
- package/dist/trusted-config.d.ts +84 -0
- package/dist/trusted-config.d.ts.map +1 -0
- package/dist/trusted-config.js +159 -0
- package/dist/trusted-config.js.map +1 -0
- package/package.json +27 -23
package/dist/source.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { realpath, stat } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { readWorkingDirectory } from '@stratusagent/state';
|
|
5
|
+
/**
|
|
6
|
+
* What a `skill add` source string means, in order: a directory on this
|
|
7
|
+
* machine, a GitHub `owner/repo` shorthand, or a URL git can clone. The
|
|
8
|
+
* shorthand is the form skills.sh and its CLI print, so a skill published
|
|
9
|
+
* there installs by the name its listing shows.
|
|
10
|
+
*/
|
|
11
|
+
export const resolveSource = async (source, env, what) => {
|
|
12
|
+
const localPath = path.resolve(readWorkingDirectory(env), source);
|
|
13
|
+
try {
|
|
14
|
+
if ((await stat(localPath)).isDirectory()) {
|
|
15
|
+
// The real directory, not the path as typed: a source that is
|
|
16
|
+
// itself a symlink would otherwise be copied as that link — an
|
|
17
|
+
// installed entry pointing back at the source tree, which the
|
|
18
|
+
// loader ignores as not-a-directory.
|
|
19
|
+
return { kind: 'local', directory: await realpath(localPath) };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Not a local directory; read it as a remote source.
|
|
24
|
+
}
|
|
25
|
+
if (/^[\w.-]+\/[\w.-]+$/.test(source)) {
|
|
26
|
+
return { kind: 'git', url: `https://github.com/${source}` };
|
|
27
|
+
}
|
|
28
|
+
if (/^(https?|git|ssh|file):\/\//.test(source) || /^git@[\w.-]+:/.test(source)) {
|
|
29
|
+
return { kind: 'git', url: source };
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`Cannot read ${JSON.stringify(source)} as a ${what} source. Pass a GitHub owner/repo, a git URL, or a local path.`);
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A source URL safe to print: userinfo stripped. A token travels in exactly
|
|
35
|
+
* this position (`https://user:token@host/repo.git`), stdout is commonly
|
|
36
|
+
* retained in CI logs, and git's own stderr already redacts — only the
|
|
37
|
+
* unredacted URL is handed to git itself.
|
|
38
|
+
*/
|
|
39
|
+
export const redactedSourceUrl = (url) => {
|
|
40
|
+
try {
|
|
41
|
+
const parsed = new URL(url);
|
|
42
|
+
if (parsed.username || parsed.password) {
|
|
43
|
+
parsed.username = '***';
|
|
44
|
+
parsed.password = '';
|
|
45
|
+
}
|
|
46
|
+
return parsed.toString();
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// scp-style (git@host:path) or anything else URL() refuses: keep the
|
|
50
|
+
// shape, hide whatever sits before the @.
|
|
51
|
+
return url.replace(/^[^@/]+@/, '***@');
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
/** Shallow-clone a source repository. Git owns every transport we would otherwise re-implement. */
|
|
55
|
+
export const cloneSource = async (url, destination) => {
|
|
56
|
+
const display = redactedSourceUrl(url);
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
const child = spawn('git', ['clone', '--depth', '1', '--quiet', url, destination], {
|
|
59
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
60
|
+
});
|
|
61
|
+
let stderr = '';
|
|
62
|
+
child.stderr?.on('data', (chunk) => {
|
|
63
|
+
stderr += String(chunk);
|
|
64
|
+
});
|
|
65
|
+
child.on('error', (error) => {
|
|
66
|
+
reject(new Error(`Could not run git to fetch ${display}: ${error.message}`));
|
|
67
|
+
});
|
|
68
|
+
child.on('close', (code) => {
|
|
69
|
+
if (code === 0) {
|
|
70
|
+
resolve();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// git redacts credentials in its own messages; the URL we echo is
|
|
74
|
+
// ours to redact.
|
|
75
|
+
reject(new Error(`git clone failed for ${display}: ${stderr.trim() || `exit code ${code}`}`));
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=source.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAG3D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAChC,MAAc,EACd,GAAmB,EACnB,IAA0B,EACoD,EAAE;IAChF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,oBAAoB,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;IAClE,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;YAC1C,8DAA8D;YAC9D,+DAA+D;YAC/D,8DAA8D;YAC9D,qCAAqC;YACrC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACjE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;IACvD,CAAC;IACD,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,sBAAsB,MAAM,EAAE,EAAE,CAAC;IAC9D,CAAC;IACD,IAAI,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/E,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;IACD,MAAM,IAAI,KAAK,CACb,eAAe,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,IAAI,gEAAgE,CACnH,CAAC;AACJ,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAU,EAAE;IACvD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvC,MAAM,CAAC,QAAQ,GAAG,KAAK,CAAC;YACxB,MAAM,CAAC,QAAQ,GAAG,EAAE,CAAC;QACvB,CAAC;QACD,OAAO,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,0CAA0C;QAC1C,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACzC,CAAC;AACH,CAAC,CAAC;AAEF,mGAAmG;AACnG,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,GAAW,EAAE,WAAmB,EAAiB,EAAE;IACnF,MAAM,OAAO,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,CAAC,EAAE;YACjF,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;SACpC,CAAC,CAAC;QACH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE;YACzC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAC/E,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,kEAAkE;gBAClE,kBAAkB;gBAClB,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,OAAO,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,aAAa,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;YAChG,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { CliStreams, CliEnvironment, SupervisorLink, RestartHandoff } from './environment.ts';
|
|
2
|
+
import type { ParsedServeCommand } from './parse.ts';
|
|
3
|
+
/**
|
|
4
|
+
* `stratus serve` — run the gateway (stratusd) in the foreground: load the
|
|
5
|
+
* roster, accept dispatches, print events, and drain cleanly on SIGTERM,
|
|
6
|
+
* SIGINT, or the injected shutdown signal.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* What a daemon exits with to ask for a fresh process. Only ever seen by the
|
|
10
|
+
* supervisor below, which is the only thing that starts a daemon with the
|
|
11
|
+
* environment marker that makes it exit this way instead of supervising.
|
|
12
|
+
*/
|
|
13
|
+
export declare const RESTART_EXIT_CODE = 75;
|
|
14
|
+
/**
|
|
15
|
+
* What a daemon exits with when a restart could not drain — a turn that
|
|
16
|
+
* ignored its abort, a plugin or channel that did not let go. Distinct from
|
|
17
|
+
* the restart status on purpose: the supervisor answers this one by
|
|
18
|
+
* exiting with it too, so the process the service manager started ends
|
|
19
|
+
* and the manager restarts the whole unit — under systemd, cleaning the
|
|
20
|
+
* cgroup of whatever the plugin left running. A supervisor that started
|
|
21
|
+
* another daemon instead would keep that cgroup, and its leaks, alive.
|
|
22
|
+
*/
|
|
23
|
+
export declare const UNDRAINED_RESTART_EXIT_CODE = 76;
|
|
24
|
+
/** Set in a daemon the supervisor started, so its own restart is an exit, not a second supervisor. */
|
|
25
|
+
export declare const SUPERVISED_ENV = "STRATUS_SERVE_SUPERVISED";
|
|
26
|
+
/**
|
|
27
|
+
* The control API port the last daemon bound, handed to its replacement by
|
|
28
|
+
* the supervisor. Honoured only where the replacement's own request — the
|
|
29
|
+
* flag, else the config it reads afresh — is still for any free port: a
|
|
30
|
+
* daemon that asked for port 0 comes back on the port it had, so a
|
|
31
|
+
* dashboard page reconnects to it, while a config since edited to a fixed
|
|
32
|
+
* port takes effect on that restart, as an `api` block change is meant to.
|
|
33
|
+
* A hint, never a pin: passing the port back as `--api-port` would outrank
|
|
34
|
+
* the config for every restart after.
|
|
35
|
+
*/
|
|
36
|
+
export declare const BOUND_API_PORT_ENV = "STRATUS_SERVE_BOUND_API_PORT";
|
|
37
|
+
/**
|
|
38
|
+
* The IPC channel a supervisor opens when it spawns a daemon: what a
|
|
39
|
+
* supervised daemon says up it (the port it bound, so the supervisor
|
|
40
|
+
* carries *that* port to the next daemon rather than the first one's; the
|
|
41
|
+
* dashboard sessions it hands on) and what comes down it. Where there is
|
|
42
|
+
* no channel — the first daemon, or one a service manager started — there
|
|
43
|
+
* is no one to say it to, and nothing is said.
|
|
44
|
+
*/
|
|
45
|
+
export declare const defaultSupervisorLink: SupervisorLink;
|
|
46
|
+
/**
|
|
47
|
+
* The parsed serve command as arguments again — what the fresh daemon is
|
|
48
|
+
* started with. From the command, not from `process.argv`: `stratus
|
|
49
|
+
* dashboard` runs the daemon through `runServe` with a command it built,
|
|
50
|
+
* and the process's own arguments would start a second dashboard.
|
|
51
|
+
*/
|
|
52
|
+
export declare const serveArgv: (command: ParsedServeCommand) => string[];
|
|
53
|
+
/**
|
|
54
|
+
* The `bin` beside the module at `moduleUrl`, with that module's own
|
|
55
|
+
* extension: `dist/supervisor.js` respawns `dist/bin.js`, and a source checkout
|
|
56
|
+
* running `src/supervisor.ts` under type stripping respawns `src/bin.ts` — the
|
|
57
|
+
* flags that made that possible travel in `process.execArgv`. Assuming
|
|
58
|
+
* compiled output would hand a source checkout a file that does not exist,
|
|
59
|
+
* and a daemon that never comes back.
|
|
60
|
+
*/
|
|
61
|
+
export declare const restartEntrypoint: (moduleUrl: string) => string;
|
|
62
|
+
/**
|
|
63
|
+
* Keep starting daemons for as long as they exit asking for another; the
|
|
64
|
+
* first exit that does not is this process's own — an undrained restart's
|
|
65
|
+
* status included, which ends the supervisor rather than starting a daemon
|
|
66
|
+
* beside what the last one could not release.
|
|
67
|
+
*/
|
|
68
|
+
export declare const superviseRestarts: (command: ParsedServeCommand, first: RestartHandoff, streams: CliStreams, env: CliEnvironment) => Promise<number>;
|
|
69
|
+
//# sourceMappingURL=supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EAGd,cAAc,EACd,cAAc,EAEf,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;GAIG;AACH;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,KAAK,CAAC;AAE9C,sGAAsG;AACtG,eAAO,MAAM,cAAc,6BAA6B,CAAC;AAEzD;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,iCAAiC,CAAC;AAuBjE;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAoBnC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,SAAS,kBAAkB,KAAG,MAAM,EAU7D,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAAI,WAAW,MAAM,KAAG,MAGrD,CAAC;AA+EF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,SAAS,kBAAkB,EAC3B,OAAO,cAAc,EACrB,SAAS,UAAU,EACnB,KAAK,cAAc,KAClB,OAAO,CAAC,MAAM,CAoBhB,CAAC"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { writeLine } from "./io.js";
|
|
5
|
+
/**
|
|
6
|
+
* `stratus serve` — run the gateway (stratusd) in the foreground: load the
|
|
7
|
+
* roster, accept dispatches, print events, and drain cleanly on SIGTERM,
|
|
8
|
+
* SIGINT, or the injected shutdown signal.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* What a daemon exits with to ask for a fresh process. Only ever seen by the
|
|
12
|
+
* supervisor below, which is the only thing that starts a daemon with the
|
|
13
|
+
* environment marker that makes it exit this way instead of supervising.
|
|
14
|
+
*/
|
|
15
|
+
export const RESTART_EXIT_CODE = 75;
|
|
16
|
+
/**
|
|
17
|
+
* What a daemon exits with when a restart could not drain — a turn that
|
|
18
|
+
* ignored its abort, a plugin or channel that did not let go. Distinct from
|
|
19
|
+
* the restart status on purpose: the supervisor answers this one by
|
|
20
|
+
* exiting with it too, so the process the service manager started ends
|
|
21
|
+
* and the manager restarts the whole unit — under systemd, cleaning the
|
|
22
|
+
* cgroup of whatever the plugin left running. A supervisor that started
|
|
23
|
+
* another daemon instead would keep that cgroup, and its leaks, alive.
|
|
24
|
+
*/
|
|
25
|
+
export const UNDRAINED_RESTART_EXIT_CODE = 76;
|
|
26
|
+
/** Set in a daemon the supervisor started, so its own restart is an exit, not a second supervisor. */
|
|
27
|
+
export const SUPERVISED_ENV = 'STRATUS_SERVE_SUPERVISED';
|
|
28
|
+
/**
|
|
29
|
+
* The control API port the last daemon bound, handed to its replacement by
|
|
30
|
+
* the supervisor. Honoured only where the replacement's own request — the
|
|
31
|
+
* flag, else the config it reads afresh — is still for any free port: a
|
|
32
|
+
* daemon that asked for port 0 comes back on the port it had, so a
|
|
33
|
+
* dashboard page reconnects to it, while a config since edited to a fixed
|
|
34
|
+
* port takes effect on that restart, as an `api` block change is meant to.
|
|
35
|
+
* A hint, never a pin: passing the port back as `--api-port` would outrank
|
|
36
|
+
* the config for every restart after.
|
|
37
|
+
*/
|
|
38
|
+
export const BOUND_API_PORT_ENV = 'STRATUS_SERVE_BOUND_API_PORT';
|
|
39
|
+
const isDashboardSession = (value) => typeof value === 'object' && value !== null
|
|
40
|
+
&& typeof value.id === 'string'
|
|
41
|
+
&& typeof value.expiresAt === 'number'
|
|
42
|
+
&& typeof value.vouchedBy === 'string';
|
|
43
|
+
/** Shape-checked, because the other end of an IPC channel is still another process. */
|
|
44
|
+
const isSupervisorMessage = (value) => {
|
|
45
|
+
if (typeof value !== 'object' || value === null) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const message = value;
|
|
49
|
+
if (message.type === 'stratusd.bound-api-port') {
|
|
50
|
+
return typeof message.port === 'number' && Number.isInteger(message.port) && message.port > 0;
|
|
51
|
+
}
|
|
52
|
+
if (message.type === 'stratusd.sessions') {
|
|
53
|
+
return Array.isArray(message.sessions) && message.sessions.every(isDashboardSession);
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* The IPC channel a supervisor opens when it spawns a daemon: what a
|
|
59
|
+
* supervised daemon says up it (the port it bound, so the supervisor
|
|
60
|
+
* carries *that* port to the next daemon rather than the first one's; the
|
|
61
|
+
* dashboard sessions it hands on) and what comes down it. Where there is
|
|
62
|
+
* no channel — the first daemon, or one a service manager started — there
|
|
63
|
+
* is no one to say it to, and nothing is said.
|
|
64
|
+
*/
|
|
65
|
+
export const defaultSupervisorLink = {
|
|
66
|
+
send(message) {
|
|
67
|
+
if (typeof process.send === 'function' && process.channel) {
|
|
68
|
+
process.send(message);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
receive(handler) {
|
|
72
|
+
const channel = process.channel;
|
|
73
|
+
if (!channel) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
process.on('message', (message) => {
|
|
77
|
+
if (isSupervisorMessage(message)) {
|
|
78
|
+
handler(message);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// A 'message' listener refs the channel, which would keep this process
|
|
82
|
+
// alive after its drain; the daemon's own work is what holds it open.
|
|
83
|
+
channel.unref?.();
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* The parsed serve command as arguments again — what the fresh daemon is
|
|
88
|
+
* started with. From the command, not from `process.argv`: `stratus
|
|
89
|
+
* dashboard` runs the daemon through `runServe` with a command it built,
|
|
90
|
+
* and the process's own arguments would start a second dashboard.
|
|
91
|
+
*/
|
|
92
|
+
export const serveArgv = (command) => [
|
|
93
|
+
'serve',
|
|
94
|
+
...(command.configPath !== undefined ? ['--config', command.configPath] : []),
|
|
95
|
+
...(command.idleTimeoutMs !== undefined ? ['--idle-timeout', String(command.idleTimeoutMs / 1000)] : []),
|
|
96
|
+
...(command.approvals !== undefined ? ['--approvals', command.approvals] : []),
|
|
97
|
+
...(command.events ? [] : ['--no-events']),
|
|
98
|
+
...(command.logToFile === false ? ['--no-log-file'] : []),
|
|
99
|
+
...(command.api === false ? ['--no-api'] : command.api === true ? ['--api'] : []),
|
|
100
|
+
...(command.apiPort !== undefined ? ['--api-port', String(command.apiPort)] : []),
|
|
101
|
+
...(command.apiHost !== undefined ? ['--api-host', command.apiHost] : []),
|
|
102
|
+
];
|
|
103
|
+
/**
|
|
104
|
+
* The `bin` beside the module at `moduleUrl`, with that module's own
|
|
105
|
+
* extension: `dist/supervisor.js` respawns `dist/bin.js`, and a source checkout
|
|
106
|
+
* running `src/supervisor.ts` under type stripping respawns `src/bin.ts` — the
|
|
107
|
+
* flags that made that possible travel in `process.execArgv`. Assuming
|
|
108
|
+
* compiled output would hand a source checkout a file that does not exist,
|
|
109
|
+
* and a daemon that never comes back.
|
|
110
|
+
*/
|
|
111
|
+
export const restartEntrypoint = (moduleUrl) => {
|
|
112
|
+
const modulePath = fileURLToPath(moduleUrl);
|
|
113
|
+
return path.join(path.dirname(modulePath), `bin${path.extname(modulePath)}`);
|
|
114
|
+
};
|
|
115
|
+
/**
|
|
116
|
+
* Run this CLI's own entrypoint as a child with the daemon's streams and
|
|
117
|
+
* exit code, forwarding the signals a supervisor would otherwise swallow.
|
|
118
|
+
*
|
|
119
|
+
* A child, and the parent waits, rather than a detached process and an
|
|
120
|
+
* exit: under systemd and launchd the process the manager started is the
|
|
121
|
+
* service, and its exit ends the job — cgroup and all, on Linux — so the
|
|
122
|
+
* daemon that received the restart has to stay the manager's process and
|
|
123
|
+
* become the supervisor of the next one. That is what makes the same path
|
|
124
|
+
* hold in the foreground and under `--no-login`, where nothing else would
|
|
125
|
+
* bring a clean exit back.
|
|
126
|
+
*/
|
|
127
|
+
const defaultServeRespawn = (env) => (argv, handoff) => new Promise((resolve, reject) => {
|
|
128
|
+
const entrypoint = restartEntrypoint(import.meta.url);
|
|
129
|
+
// The daemon's own streams, plus an IPC channel for what it and its
|
|
130
|
+
// supervisor have to tell each other. See SupervisorLink.
|
|
131
|
+
const child = spawn(process.execPath, [...process.execArgv, entrypoint, ...argv], {
|
|
132
|
+
stdio: ['inherit', 'inherit', 'inherit', 'ipc'],
|
|
133
|
+
env: {
|
|
134
|
+
...process.env,
|
|
135
|
+
[SUPERVISED_ENV]: '1',
|
|
136
|
+
...(handoff.boundApiPort !== undefined ? { [BOUND_API_PORT_ENV]: String(handoff.boundApiPort) } : {}),
|
|
137
|
+
},
|
|
138
|
+
});
|
|
139
|
+
if (handoff.sessions.length > 0 && child.connected) {
|
|
140
|
+
// Queued in the channel until the daemon listens, which it does
|
|
141
|
+
// before its API is up; the API holds them until it can adopt them.
|
|
142
|
+
// A send that fails (the daemon died before reading) is not this
|
|
143
|
+
// supervisor's failure: the exit below reports what happened, and a
|
|
144
|
+
// daemon that never took them simply comes up signed out.
|
|
145
|
+
const sessions = { type: 'stratusd.sessions', sessions: handoff.sessions };
|
|
146
|
+
child.send(sessions, () => undefined);
|
|
147
|
+
}
|
|
148
|
+
const forward = (signal) => () => {
|
|
149
|
+
child.kill(signal);
|
|
150
|
+
};
|
|
151
|
+
const onTerm = forward('SIGTERM');
|
|
152
|
+
const onInt = forward('SIGINT');
|
|
153
|
+
const onAbort = () => {
|
|
154
|
+
child.kill('SIGTERM');
|
|
155
|
+
};
|
|
156
|
+
process.on('SIGTERM', onTerm);
|
|
157
|
+
process.on('SIGINT', onInt);
|
|
158
|
+
env.shutdownSignal?.addEventListener('abort', onAbort, { once: true });
|
|
159
|
+
const done = () => {
|
|
160
|
+
process.off('SIGTERM', onTerm);
|
|
161
|
+
process.off('SIGINT', onInt);
|
|
162
|
+
env.shutdownSignal?.removeEventListener('abort', onAbort);
|
|
163
|
+
};
|
|
164
|
+
let reportedPort;
|
|
165
|
+
let handedBack;
|
|
166
|
+
child.on('message', (message) => {
|
|
167
|
+
if (!isSupervisorMessage(message)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (message.type === 'stratusd.bound-api-port') {
|
|
171
|
+
reportedPort = message.port;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
handedBack = message.sessions;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
child.once('error', (error) => {
|
|
178
|
+
done();
|
|
179
|
+
reject(error);
|
|
180
|
+
});
|
|
181
|
+
child.once('exit', (code, signal) => {
|
|
182
|
+
done();
|
|
183
|
+
// Killed by a signal is a stop, not a request to come back.
|
|
184
|
+
resolve({
|
|
185
|
+
code: code ?? (signal ? 1 : 0),
|
|
186
|
+
...(reportedPort !== undefined ? { boundApiPort: reportedPort } : {}),
|
|
187
|
+
...(handedBack !== undefined ? { sessions: handedBack } : {}),
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
/**
|
|
192
|
+
* Keep starting daemons for as long as they exit asking for another; the
|
|
193
|
+
* first exit that does not is this process's own — an undrained restart's
|
|
194
|
+
* status included, which ends the supervisor rather than starting a daemon
|
|
195
|
+
* beside what the last one could not release.
|
|
196
|
+
*/
|
|
197
|
+
export const superviseRestarts = async (command, first, streams, env) => {
|
|
198
|
+
const respawn = env.serveRespawn ?? defaultServeRespawn(env);
|
|
199
|
+
// The hand-off follows the daemons: the port each one said it bound is
|
|
200
|
+
// what the next one is told (so a config edited to a fixed port and
|
|
201
|
+
// back hands on the last address, not the first), and the sessions are
|
|
202
|
+
// whatever the last one handed back — a daemon that handed nothing
|
|
203
|
+
// hands nothing on.
|
|
204
|
+
let handoff = first;
|
|
205
|
+
let result;
|
|
206
|
+
do {
|
|
207
|
+
writeLine(streams.stdout, 'Restarting stratusd.');
|
|
208
|
+
result = await respawn(serveArgv(command), handoff);
|
|
209
|
+
handoff = {
|
|
210
|
+
...(result.boundApiPort !== undefined || handoff.boundApiPort !== undefined
|
|
211
|
+
? { boundApiPort: result.boundApiPort ?? handoff.boundApiPort }
|
|
212
|
+
: {}),
|
|
213
|
+
sessions: result.sessions ?? [],
|
|
214
|
+
};
|
|
215
|
+
} while (result.code === RESTART_EXIT_CODE);
|
|
216
|
+
return result.code;
|
|
217
|
+
};
|
|
218
|
+
//# sourceMappingURL=supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../src/supervisor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { type ApiConfig, type ApprovalsConfig, type PrincipalsConfig, type PluginsConfig } from '@stratusagent/state';
|
|
2
|
+
import type { CliEnvironment } from './environment.ts';
|
|
3
|
+
/**
|
|
4
|
+
* A credential that exists only in this shell cannot reach the daemon: a
|
|
5
|
+
* service manager starts with its own environment and never sources a
|
|
6
|
+
* profile, so the unit would come up unauthenticated while setup had just
|
|
7
|
+
* reported everything ready. Returns the variable to name, if so.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* The daemon's `approvals` block, from the config file the daemon itself
|
|
11
|
+
* would load. Discovery goes through the shared resolver rather than
|
|
12
|
+
* reading ~/.stratus/config.json directly: `--config` and STRATUS_CONFIG
|
|
13
|
+
* both move it, and a second copy of that precedence would resolve the
|
|
14
|
+
* approver set from a file the gateway is not running on.
|
|
15
|
+
*
|
|
16
|
+
* **Only from a trusted location.** An auto-discovered project-local
|
|
17
|
+
* `stratus.config.json` outranks the global one and can be checked into any
|
|
18
|
+
* repository — which is why stored credentials are already never combined
|
|
19
|
+
* with an endpoint it selects. This block is the same kind of boundary and
|
|
20
|
+
* a sharper one: it names the people who may authorize an agent's gated
|
|
21
|
+
* tool calls, and it would do so through Slack tokens the user configured
|
|
22
|
+
* globally. A cloned repo must not be able to appoint its own approver, so
|
|
23
|
+
* an untrusted config's approvals are ignored — loudly, since silently
|
|
24
|
+
* dropping the block someone is looking at is its own kind of wrong.
|
|
25
|
+
*
|
|
26
|
+
* An unreadable config degrades to headless with a warning, matching how
|
|
27
|
+
* every other consumer treats one: refusing to start would take the whole
|
|
28
|
+
* fleet down over a policy block that may not even be present.
|
|
29
|
+
*/
|
|
30
|
+
export declare const loadServeApprovals: (env: CliEnvironment, configPath: string | undefined, warn: (line: string) => void) => Promise<ApprovalsConfig>;
|
|
31
|
+
/**
|
|
32
|
+
* One line naming who can actually answer, so a remote daemon does not look
|
|
33
|
+
* configured when it is not. Two ways it can be hollow, and they fail
|
|
34
|
+
* differently, so they read differently:
|
|
35
|
+
*
|
|
36
|
+
* - No channel running at all (no Slack tokens, or the optional package is
|
|
37
|
+
* not installed) — nothing renders the request, so the turn waits out the
|
|
38
|
+
* whole timeout before being denied. That is the bad one, and the only
|
|
39
|
+
* place it is visible is here, at startup.
|
|
40
|
+
* - A channel is running but an agent has no approvers — the adapter denies
|
|
41
|
+
* that agent's requests on arrival, which is at least prompt.
|
|
42
|
+
*
|
|
43
|
+
* `agentIds` is therefore the agents that can actually be *asked*, not
|
|
44
|
+
* every agent with tokens on disk.
|
|
45
|
+
*/
|
|
46
|
+
/**
|
|
47
|
+
* The `principals` block, read under the same trust rule as `approvals` and
|
|
48
|
+
* for a sharper reason: it names the people whose messages an agent takes
|
|
49
|
+
* as its operator's, which is the trust root everything downstream lowers
|
|
50
|
+
* from. A cloned repo appointing itself the principal would arrive as
|
|
51
|
+
* `user` in every Slack thread the daemon serves.
|
|
52
|
+
*/
|
|
53
|
+
export declare const loadServePrincipals: (env: CliEnvironment, configPath: string | undefined, warn: (line: string) => void) => Promise<PrincipalsConfig>;
|
|
54
|
+
/**
|
|
55
|
+
* The daemon's `api` block, from the config file the daemon itself would
|
|
56
|
+
* load — and only from a trusted location.
|
|
57
|
+
*
|
|
58
|
+
* An auto-discovered project-local `stratus.config.json` outranks the global
|
|
59
|
+
* one and can be checked into any repository. Which interface a daemon binds
|
|
60
|
+
* is exactly the kind of decision a cloned repo must not get to make, so an
|
|
61
|
+
* untrusted config's block is ignored loudly rather than obeyed.
|
|
62
|
+
*/
|
|
63
|
+
export declare const loadServeApi: (env: CliEnvironment, configPath: string | undefined, warn: (line: string) => void) => Promise<ApiConfig>;
|
|
64
|
+
/**
|
|
65
|
+
* The daemon's `plugins` block — the same trust boundary as the three above,
|
|
66
|
+
* and the one it was written for. A plugin runs in-process with the daemon,
|
|
67
|
+
* so a list of them is a list of code; a `stratus.config.json` that ships
|
|
68
|
+
* in a cloned repository must not be able to write it.
|
|
69
|
+
*/
|
|
70
|
+
export declare const loadServePlugins: (env: CliEnvironment, configPath: string | undefined, warn: (line: string) => void) => Promise<PluginsConfig>;
|
|
71
|
+
/**
|
|
72
|
+
* The daemon's `executor` or `memoryStore` selection — a name a plugin
|
|
73
|
+
* registered — under the trust rule `plugins` has, and for the same
|
|
74
|
+
* reason one step on: the plugins block decides which code runs, and
|
|
75
|
+
* these decide which of that code an agent's commands run in and where its
|
|
76
|
+
* memories are written. A cloned repository swapping a sandbox executor
|
|
77
|
+
* for the host's is the downgrade this refuses.
|
|
78
|
+
*
|
|
79
|
+
* Absent, or ignored, means the built-in — the caller substitutes it. A
|
|
80
|
+
* project config that says nothing leaves the global file's choice in
|
|
81
|
+
* force, as every trusted block does.
|
|
82
|
+
*/
|
|
83
|
+
export declare const loadServeRuntimeSelection: (key: "executor" | "memoryStore", env: CliEnvironment, configPath: string | undefined, warn: (line: string) => void) => Promise<string | undefined>;
|
|
84
|
+
//# sourceMappingURL=trusted-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trusted-config.d.ts","sourceRoot":"","sources":["../src/trusted-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;GAKG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,kBAAkB,GAC7B,KAAK,cAAc,EACnB,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC3B,OAAO,CAAC,eAAe,CAczB,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,GAC9B,KAAK,cAAc,EACnB,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC3B,OAAO,CAAC,gBAAgB,CA0B1B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,cAAc,EACnB,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC3B,OAAO,CAAC,SAAS,CAcnB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,KAAK,cAAc,EACnB,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC3B,OAAO,CAAC,aAAa,CAcvB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,yBAAyB,GACpC,KAAK,UAAU,GAAG,aAAa,EAC/B,KAAK,cAAc,EACnB,YAAY,MAAM,GAAG,SAAS,EAC9B,MAAM,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC3B,OAAO,CAAC,MAAM,GAAG,SAAS,CAoB5B,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { readGlobalConfigBlock, readTrustedConfigBlock, } from '@stratusagent/state';
|
|
2
|
+
/**
|
|
3
|
+
* A credential that exists only in this shell cannot reach the daemon: a
|
|
4
|
+
* service manager starts with its own environment and never sources a
|
|
5
|
+
* profile, so the unit would come up unauthenticated while setup had just
|
|
6
|
+
* reported everything ready. Returns the variable to name, if so.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* The daemon's `approvals` block, from the config file the daemon itself
|
|
10
|
+
* would load. Discovery goes through the shared resolver rather than
|
|
11
|
+
* reading ~/.stratus/config.json directly: `--config` and STRATUS_CONFIG
|
|
12
|
+
* both move it, and a second copy of that precedence would resolve the
|
|
13
|
+
* approver set from a file the gateway is not running on.
|
|
14
|
+
*
|
|
15
|
+
* **Only from a trusted location.** An auto-discovered project-local
|
|
16
|
+
* `stratus.config.json` outranks the global one and can be checked into any
|
|
17
|
+
* repository — which is why stored credentials are already never combined
|
|
18
|
+
* with an endpoint it selects. This block is the same kind of boundary and
|
|
19
|
+
* a sharper one: it names the people who may authorize an agent's gated
|
|
20
|
+
* tool calls, and it would do so through Slack tokens the user configured
|
|
21
|
+
* globally. A cloned repo must not be able to appoint its own approver, so
|
|
22
|
+
* an untrusted config's approvals are ignored — loudly, since silently
|
|
23
|
+
* dropping the block someone is looking at is its own kind of wrong.
|
|
24
|
+
*
|
|
25
|
+
* An unreadable config degrades to headless with a warning, matching how
|
|
26
|
+
* every other consumer treats one: refusing to start would take the whole
|
|
27
|
+
* fleet down over a policy block that may not even be present.
|
|
28
|
+
*/
|
|
29
|
+
export const loadServeApprovals = async (env, configPath, warn) => {
|
|
30
|
+
const block = await readTrustedConfigBlock('approvals', env, configPath);
|
|
31
|
+
if (block.status === 'untrusted') {
|
|
32
|
+
warn(`ignoring the approvals config in ${block.path}: a project-local config cannot decide who may approve `
|
|
33
|
+
+ 'this daemon\'s tool calls. Move it to ~/.stratus/config.json, or pass it with --config.');
|
|
34
|
+
return {};
|
|
35
|
+
}
|
|
36
|
+
if (block.status === 'unreadable') {
|
|
37
|
+
warn(`ignoring the approvals config (${block.error instanceof Error ? block.error.message : String(block.error)}); refusing gated calls`);
|
|
38
|
+
return {};
|
|
39
|
+
}
|
|
40
|
+
return block.status === 'present' ? block.value : {};
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* One line naming who can actually answer, so a remote daemon does not look
|
|
44
|
+
* configured when it is not. Two ways it can be hollow, and they fail
|
|
45
|
+
* differently, so they read differently:
|
|
46
|
+
*
|
|
47
|
+
* - No channel running at all (no Slack tokens, or the optional package is
|
|
48
|
+
* not installed) — nothing renders the request, so the turn waits out the
|
|
49
|
+
* whole timeout before being denied. That is the bad one, and the only
|
|
50
|
+
* place it is visible is here, at startup.
|
|
51
|
+
* - A channel is running but an agent has no approvers — the adapter denies
|
|
52
|
+
* that agent's requests on arrival, which is at least prompt.
|
|
53
|
+
*
|
|
54
|
+
* `agentIds` is therefore the agents that can actually be *asked*, not
|
|
55
|
+
* every agent with tokens on disk.
|
|
56
|
+
*/
|
|
57
|
+
/**
|
|
58
|
+
* The `principals` block, read under the same trust rule as `approvals` and
|
|
59
|
+
* for a sharper reason: it names the people whose messages an agent takes
|
|
60
|
+
* as its operator's, which is the trust root everything downstream lowers
|
|
61
|
+
* from. A cloned repo appointing itself the principal would arrive as
|
|
62
|
+
* `user` in every Slack thread the daemon serves.
|
|
63
|
+
*/
|
|
64
|
+
export const loadServePrincipals = async (env, configPath, warn) => {
|
|
65
|
+
let block = await readTrustedConfigBlock('principals', env, configPath);
|
|
66
|
+
if (block.status === 'untrusted') {
|
|
67
|
+
// An auto-discovered project config shadows the global one in
|
|
68
|
+
// discovery, and a daemon started inside a cloned repository would
|
|
69
|
+
// otherwise run with no principals policy at all — a cloned repo that
|
|
70
|
+
// cannot define the policy must not be able to suppress it either. The
|
|
71
|
+
// global file is the trusted answer; it is read instead.
|
|
72
|
+
warn(`ignoring the principals config in ${block.path}: a project-local config cannot decide whose messages `
|
|
73
|
+
+ 'this daemon\'s agents treat as their operator\'s. Using ~/.stratus/config.json instead.');
|
|
74
|
+
block = await readGlobalConfigBlock('principals', env);
|
|
75
|
+
}
|
|
76
|
+
if (block.status === 'unreadable') {
|
|
77
|
+
// Closed, not open: the one thing in this block that can fail to
|
|
78
|
+
// parse is `admit`, whose misspelling would otherwise mean `anyone` —
|
|
79
|
+
// the setting exists so that a typo does not open the door, and a
|
|
80
|
+
// warning that opens it anyway is the door with a note on it.
|
|
81
|
+
warn(`the principals config could not be read (${block.error instanceof Error ? block.error.message : String(block.error)}); `
|
|
82
|
+
+ 'refusing every Slack sender until it is fixed');
|
|
83
|
+
return { admit: 'principals' };
|
|
84
|
+
}
|
|
85
|
+
return block.status === 'present' ? block.value : {};
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* The daemon's `api` block, from the config file the daemon itself would
|
|
89
|
+
* load — and only from a trusted location.
|
|
90
|
+
*
|
|
91
|
+
* An auto-discovered project-local `stratus.config.json` outranks the global
|
|
92
|
+
* one and can be checked into any repository. Which interface a daemon binds
|
|
93
|
+
* is exactly the kind of decision a cloned repo must not get to make, so an
|
|
94
|
+
* untrusted config's block is ignored loudly rather than obeyed.
|
|
95
|
+
*/
|
|
96
|
+
export const loadServeApi = async (env, configPath, warn) => {
|
|
97
|
+
const block = await readTrustedConfigBlock('api', env, configPath);
|
|
98
|
+
if (block.status === 'untrusted') {
|
|
99
|
+
warn(`ignoring the api config in ${block.path}: a project-local config cannot decide which interface this `
|
|
100
|
+
+ 'daemon binds. Move it to ~/.stratus/config.json, or pass it with --config.');
|
|
101
|
+
return {};
|
|
102
|
+
}
|
|
103
|
+
if (block.status === 'unreadable') {
|
|
104
|
+
warn(`ignoring the api config (${block.error instanceof Error ? block.error.message : String(block.error)}); using the defaults`);
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
return block.status === 'present' ? block.value : {};
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* The daemon's `plugins` block — the same trust boundary as the three above,
|
|
111
|
+
* and the one it was written for. A plugin runs in-process with the daemon,
|
|
112
|
+
* so a list of them is a list of code; a `stratus.config.json` that ships
|
|
113
|
+
* in a cloned repository must not be able to write it.
|
|
114
|
+
*/
|
|
115
|
+
export const loadServePlugins = async (env, configPath, warn) => {
|
|
116
|
+
const block = await readTrustedConfigBlock('plugins', env, configPath);
|
|
117
|
+
if (block.status === 'untrusted') {
|
|
118
|
+
warn(`ignoring the plugins config in ${block.path}: a project-local config cannot decide which code runs inside `
|
|
119
|
+
+ 'this daemon. Move it to ~/.stratus/config.json, or pass it with --config.');
|
|
120
|
+
return {};
|
|
121
|
+
}
|
|
122
|
+
if (block.status === 'unreadable') {
|
|
123
|
+
warn(`ignoring the plugins config (${block.error instanceof Error ? block.error.message : String(block.error)}); loading no plugins`);
|
|
124
|
+
return {};
|
|
125
|
+
}
|
|
126
|
+
return block.status === 'present' ? block.value : {};
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* The daemon's `executor` or `memoryStore` selection — a name a plugin
|
|
130
|
+
* registered — under the trust rule `plugins` has, and for the same
|
|
131
|
+
* reason one step on: the plugins block decides which code runs, and
|
|
132
|
+
* these decide which of that code an agent's commands run in and where its
|
|
133
|
+
* memories are written. A cloned repository swapping a sandbox executor
|
|
134
|
+
* for the host's is the downgrade this refuses.
|
|
135
|
+
*
|
|
136
|
+
* Absent, or ignored, means the built-in — the caller substitutes it. A
|
|
137
|
+
* project config that says nothing leaves the global file's choice in
|
|
138
|
+
* force, as every trusted block does.
|
|
139
|
+
*/
|
|
140
|
+
export const loadServeRuntimeSelection = async (key, env, configPath, warn) => {
|
|
141
|
+
let block = await readTrustedConfigBlock(key, env, configPath);
|
|
142
|
+
if (block.status === 'untrusted') {
|
|
143
|
+
// The global file's choice, not the built-in: a clone that cannot
|
|
144
|
+
// select an executor must not be able to deselect one either — a
|
|
145
|
+
// repository shipping `"executor": "local"` would otherwise swap the
|
|
146
|
+
// operator's sandbox for the host, which is the exact downgrade this
|
|
147
|
+
// block refuses. The same fall-through `principals` uses.
|
|
148
|
+
warn(`ignoring ${key} in ${block.path}: a project-local config cannot decide `
|
|
149
|
+
+ (key === 'executor' ? 'where this daemon\'s agents run their commands' : 'where this daemon\'s agents keep their memories')
|
|
150
|
+
+ '. Using ~/.stratus/config.json instead.');
|
|
151
|
+
block = await readGlobalConfigBlock(key, env);
|
|
152
|
+
}
|
|
153
|
+
if (block.status === 'unreadable') {
|
|
154
|
+
warn(`ignoring ${key} (${block.error instanceof Error ? block.error.message : String(block.error)}); using the built-in`);
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
return block.status === 'present' ? block.value : undefined;
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=trusted-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trusted-config.js","sourceRoot":"","sources":["../src/trusted-config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GAKvB,MAAM,qBAAqB,CAAC;AAG7B;;;;;GAKG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACrC,GAAmB,EACnB,UAA8B,EAC9B,IAA4B,EACF,EAAE;IAC5B,MAAM,KAAK,GAAG,MAAM,sBAAsB,CAAC,WAAW,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IACzE,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,IAAI,CACF,oCAAoC,KAAK,CAAC,IAAI,yDAAyD;cACrG,yFAAyF,CAC5F,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC,kCAAkC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC1I,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EACtC,GAAmB,EACnB,UAA8B,EAC9B,IAA4B,EACD,EAAE;IAC7B,IAAI,KAAK,GAAG,MAAM,sBAAsB,CAAC,YAAY,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IACxE,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,8DAA8D;QAC9D,mEAAmE;QACnE,sEAAsE;QACtE,uEAAuE;QACvE,yDAAyD;QACzD,IAAI,CACF,qCAAqC,KAAK,CAAC,IAAI,wDAAwD;cACrG,yFAAyF,CAC5F,CAAC;QACF,KAAK,GAAG,MAAM,qBAAqB,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAClC,iEAAiE;QACjE,sEAAsE;QACtE,kEAAkE;QAClE,8DAA8D;QAC9D,IAAI,CACF,4CAA4C,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;cACvH,+CAA+C,CAClD,CAAC;QACF,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAC/B,GAAmB,EACnB,UAA8B,EAC9B,IAA4B,EACR,EAAE;IACtB,MAAM,KAAK,GAAG,MAAM,sBAAsB,CAAC,KAAK,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IACnE,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,IAAI,CACF,8BAA8B,KAAK,CAAC,IAAI,8DAA8D;cACpG,4EAA4E,CAC/E,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC,4BAA4B,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAClI,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EACnC,GAAmB,EACnB,UAA8B,EAC9B,IAA4B,EACJ,EAAE;IAC1B,MAAM,KAAK,GAAG,MAAM,sBAAsB,CAAC,SAAS,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,IAAI,CACF,kCAAkC,KAAK,CAAC,IAAI,gEAAgE;cAC1G,2EAA2E,CAC9E,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC,gCAAgC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACtI,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACvD,CAAC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,KAAK,EAC5C,GAA+B,EAC/B,GAAmB,EACnB,UAA8B,EAC9B,IAA4B,EACC,EAAE;IAC/B,IAAI,KAAK,GAAG,MAAM,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;IAC/D,IAAI,KAAK,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QACjC,kEAAkE;QAClE,iEAAiE;QACjE,qEAAqE;QACrE,qEAAqE;QACrE,0DAA0D;QAC1D,IAAI,CACF,YAAY,GAAG,OAAO,KAAK,CAAC,IAAI,yCAAyC;cACvE,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,CAAC,gDAAgD,CAAC,CAAC,CAAC,iDAAiD,CAAC;cAC3H,yCAAyC,CAC5C,CAAC;QACF,KAAK,GAAG,MAAM,qBAAqB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC,YAAY,GAAG,KAAK,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC1H,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9D,CAAC,CAAC"}
|