@stratusagent/cli 0.11.1 → 0.11.3
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 +18 -7
- package/dist/approvals.d.ts +87 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +315 -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 +154 -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 +224 -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 +357 -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 +91 -0
- package/dist/commands/plugins.d.ts.map +1 -0
- package/dist/commands/plugins.js +359 -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 +612 -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 +2412 -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 +575 -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 +108 -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 +266 -0
- package/dist/help.js.map +1 -0
- package/dist/index.d.ts +31 -582
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +38 -6646
- 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 +214 -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 +231 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +1082 -0
- package/dist/parse.js.map +1 -0
- package/dist/plugin-catalog.d.ts +35 -0
- package/dist/plugin-catalog.d.ts.map +1 -0
- package/dist/plugin-catalog.js +58 -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 +59 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +266 -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 +71 -0
- package/dist/trusted-config.d.ts.map +1 -0
- package/dist/trusted-config.js +118 -0
- package/dist/trusted-config.js.map +1 -0
- package/package.json +25 -23
|
@@ -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,71 @@
|
|
|
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
|
+
//# 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,EAEL,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,CAc1B,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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { 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
|
+
const block = await readTrustedConfigBlock('principals', env, configPath);
|
|
66
|
+
if (block.status === 'untrusted') {
|
|
67
|
+
warn(`ignoring the principals config in ${block.path}: a project-local config cannot decide whose messages `
|
|
68
|
+
+ 'this daemon\'s agents treat as their operator\'s. Move it to ~/.stratus/config.json, or pass it with --config.');
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
if (block.status === 'unreadable') {
|
|
72
|
+
warn(`ignoring the principals config (${block.error instanceof Error ? block.error.message : String(block.error)}); every Slack sender is unknown`);
|
|
73
|
+
return {};
|
|
74
|
+
}
|
|
75
|
+
return block.status === 'present' ? block.value : {};
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* The daemon's `api` block, from the config file the daemon itself would
|
|
79
|
+
* load — and only from a trusted location.
|
|
80
|
+
*
|
|
81
|
+
* An auto-discovered project-local `stratus.config.json` outranks the global
|
|
82
|
+
* one and can be checked into any repository. Which interface a daemon binds
|
|
83
|
+
* is exactly the kind of decision a cloned repo must not get to make, so an
|
|
84
|
+
* untrusted config's block is ignored loudly rather than obeyed.
|
|
85
|
+
*/
|
|
86
|
+
export const loadServeApi = async (env, configPath, warn) => {
|
|
87
|
+
const block = await readTrustedConfigBlock('api', env, configPath);
|
|
88
|
+
if (block.status === 'untrusted') {
|
|
89
|
+
warn(`ignoring the api config in ${block.path}: a project-local config cannot decide which interface this `
|
|
90
|
+
+ 'daemon binds. Move it to ~/.stratus/config.json, or pass it with --config.');
|
|
91
|
+
return {};
|
|
92
|
+
}
|
|
93
|
+
if (block.status === 'unreadable') {
|
|
94
|
+
warn(`ignoring the api config (${block.error instanceof Error ? block.error.message : String(block.error)}); using the defaults`);
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
return block.status === 'present' ? block.value : {};
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* The daemon's `plugins` block — the same trust boundary as the three above,
|
|
101
|
+
* and the one it was written for. A plugin runs in-process with the daemon,
|
|
102
|
+
* so a list of them is a list of code; a `stratus.config.json` that ships
|
|
103
|
+
* in a cloned repository must not be able to write it.
|
|
104
|
+
*/
|
|
105
|
+
export const loadServePlugins = async (env, configPath, warn) => {
|
|
106
|
+
const block = await readTrustedConfigBlock('plugins', env, configPath);
|
|
107
|
+
if (block.status === 'untrusted') {
|
|
108
|
+
warn(`ignoring the plugins config in ${block.path}: a project-local config cannot decide which code runs inside `
|
|
109
|
+
+ 'this daemon. Move it to ~/.stratus/config.json, or pass it with --config.');
|
|
110
|
+
return {};
|
|
111
|
+
}
|
|
112
|
+
if (block.status === 'unreadable') {
|
|
113
|
+
warn(`ignoring the plugins config (${block.error instanceof Error ? block.error.message : String(block.error)}); loading no plugins`);
|
|
114
|
+
return {};
|
|
115
|
+
}
|
|
116
|
+
return block.status === 'present' ? block.value : {};
|
|
117
|
+
};
|
|
118
|
+
//# sourceMappingURL=trusted-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trusted-config.js","sourceRoot":"","sources":["../src/trusted-config.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stratusagent/cli",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -20,28 +20,29 @@
|
|
|
20
20
|
"node": ">=22.13 <23 || >=23.4"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@stratusagent/
|
|
24
|
-
"@stratusagent/
|
|
25
|
-
"@stratusagent/
|
|
26
|
-
"@stratusagent/gateway": "0.11.
|
|
27
|
-
"@stratusagent/permissions": "0.11.
|
|
28
|
-
"@stratusagent/
|
|
29
|
-
"@stratusagent/provider-claude-code": "0.11.
|
|
30
|
-
"@stratusagent/provider-
|
|
31
|
-
"@stratusagent/providers": "0.11.
|
|
32
|
-
"@stratusagent/
|
|
33
|
-
"@stratusagent/
|
|
23
|
+
"@stratusagent/agents": "0.11.3",
|
|
24
|
+
"@stratusagent/core": "0.11.3",
|
|
25
|
+
"@stratusagent/executor-local": "0.11.3",
|
|
26
|
+
"@stratusagent/gateway": "0.11.3",
|
|
27
|
+
"@stratusagent/permissions": "0.11.3",
|
|
28
|
+
"@stratusagent/plugins": "0.11.3",
|
|
29
|
+
"@stratusagent/provider-claude-code": "0.11.3",
|
|
30
|
+
"@stratusagent/provider-anthropic": "0.11.3",
|
|
31
|
+
"@stratusagent/providers": "0.11.3",
|
|
32
|
+
"@stratusagent/state": "0.11.3",
|
|
33
|
+
"@stratusagent/provider-codex": "0.11.3"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^24.6.0",
|
|
37
37
|
"typescript": "^5.9.3",
|
|
38
|
-
"@stratusagent/channel-slack": "0.11.
|
|
39
|
-
"@stratusagent/
|
|
40
|
-
"@stratusagent/tool-
|
|
41
|
-
"@stratusagent/
|
|
42
|
-
"@stratusagent/tool-
|
|
43
|
-
"@stratusagent/tool-
|
|
44
|
-
"@stratusagent/
|
|
38
|
+
"@stratusagent/channel-slack": "0.11.3",
|
|
39
|
+
"@stratusagent/dashboard": "0.11.3",
|
|
40
|
+
"@stratusagent/tool-browser": "0.11.3",
|
|
41
|
+
"@stratusagent/plugin-mcp": "0.11.3",
|
|
42
|
+
"@stratusagent/tool-fs": "0.11.3",
|
|
43
|
+
"@stratusagent/tool-web": "0.11.3",
|
|
44
|
+
"@stratusagent/control-api": "0.11.3",
|
|
45
|
+
"@stratusagent/tool-shell": "0.11.3"
|
|
45
46
|
},
|
|
46
47
|
"license": "MIT",
|
|
47
48
|
"repository": {
|
|
@@ -60,9 +61,9 @@
|
|
|
60
61
|
"access": "public"
|
|
61
62
|
},
|
|
62
63
|
"peerDependencies": {
|
|
63
|
-
"@stratusagent/
|
|
64
|
-
"@stratusagent/
|
|
65
|
-
"@stratusagent/
|
|
64
|
+
"@stratusagent/control-api": "0.11.3",
|
|
65
|
+
"@stratusagent/channel-slack": "0.11.3",
|
|
66
|
+
"@stratusagent/dashboard": "0.11.3"
|
|
66
67
|
},
|
|
67
68
|
"peerDependenciesMeta": {
|
|
68
69
|
"@stratusagent/channel-slack": {
|
|
@@ -79,6 +80,7 @@
|
|
|
79
80
|
"build": "tsc -b",
|
|
80
81
|
"cli": "node --experimental-strip-types ./src/bin.ts",
|
|
81
82
|
"typecheck": "tsc --noEmit --project tsconfig.test.json",
|
|
82
|
-
"test": "node --test --experimental-strip-types ./test/**/*.test.ts"
|
|
83
|
+
"test": "node --test --experimental-strip-types ./test/**/*.test.ts",
|
|
84
|
+
"eval:room": "node --experimental-strip-types ./eval/reading-the-room/run.ts"
|
|
83
85
|
}
|
|
84
86
|
}
|