@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
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
import { randomUUID } from 'node:crypto';
|
|
10
|
+
import { AgentRunner, EventBus, SkillRegistry, ToolRegistry, missingSkillRequirements, describeToolAllowlistFinding, unmatchedToolAllowlist, } from '@stratusagent/core';
|
|
11
|
+
import { createLocalCommandExecutor } from '@stratusagent/executor-local';
|
|
12
|
+
import { loadPlugins } from '@stratusagent/plugins';
|
|
13
|
+
import { createForgetTool, createRecallTool, createRememberTool, GATEWAY_ONLY_TOOL_NAMES, } from '@stratusagent/agents';
|
|
14
|
+
import { createDemoTool, createFileCredentialResolver, createFileMemoryStore, createRuntimeProvider, defaultApiKeyEnvName, DEFAULT_STRATUS_AGENT, loadCredentials, loadOperatorSkills, memoryFilePath, migrateLegacyMemory, readNonEmptyString, readProcessEnv, resolveRuntimeConfig as resolveStateRuntimeConfig, withLegacyDefaultMemories, workspacesDirPath, } from '@stratusagent/state';
|
|
15
|
+
import { createApprovalPolicy } from "./approvals.js";
|
|
16
|
+
import { formatEvent } from "./events.js";
|
|
17
|
+
import { writeLine, stringifyValue } from "./io.js";
|
|
18
|
+
import { loadServePlugins } from "./trusted-config.js";
|
|
19
|
+
/**
|
|
20
|
+
* Kept with its historical CLI signature: a parsed run command is a
|
|
21
|
+
* RuntimeSelection plus CLI-only fields the resolver ignores.
|
|
22
|
+
*
|
|
23
|
+
* Those fields are *permitted*, not required. Demanding a whole
|
|
24
|
+
* `ParsedRunCommand` made the type claim the resolver cared about
|
|
25
|
+
* `approvals`, `format`, and `events` — it reads none of them — so every
|
|
26
|
+
* caller with a selection in hand had to invent values to get past it.
|
|
27
|
+
*/
|
|
28
|
+
export const resolveRuntimeConfig = (command, env = {}) => resolveStateRuntimeConfig(command, env);
|
|
29
|
+
/**
|
|
30
|
+
* A saved subscription sign-in silently demoted to per-token billing is the
|
|
31
|
+
* one config surprise that costs money — an API key in the environment
|
|
32
|
+
* outranks the stored credential, and the run otherwise looks identical.
|
|
33
|
+
* Detected from the resolved config: an apiKey where the stored credential
|
|
34
|
+
* is a subscription token means the environment won.
|
|
35
|
+
*/
|
|
36
|
+
export const warnOnCredentialOverride = async (runtime, streams, env = {}) => {
|
|
37
|
+
if (runtime.provider === 'demo') {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const credentials = await loadCredentials(env);
|
|
41
|
+
const processEnv = readProcessEnv(env);
|
|
42
|
+
// The resolver records the variable that actually won — guessing it here
|
|
43
|
+
// would name the wrong one whenever a custom apiKeyEnv supplied the key,
|
|
44
|
+
// sending the reader to unset something that was never the cause.
|
|
45
|
+
const primaryOverride = runtime.apiKey !== undefined
|
|
46
|
+
? { provider: runtime.provider, envVar: runtime.apiKeyEnvVar }
|
|
47
|
+
: undefined;
|
|
48
|
+
// Both subscription sign-ins demote the same way: a Claude setup token
|
|
49
|
+
// and the codex ChatGPT marker each lose to an environment API key, and
|
|
50
|
+
// the run otherwise looks identical while billing per token.
|
|
51
|
+
for (const target of ['anthropic', 'codex']) {
|
|
52
|
+
if (credentials[target]?.type !== 'oauth_token') {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const planName = target === 'anthropic'
|
|
56
|
+
? 'Claude subscription sign-in'
|
|
57
|
+
: 'ChatGPT (codex login) sign-in';
|
|
58
|
+
const primary = primaryOverride?.provider === target ? primaryOverride.envVar : undefined;
|
|
59
|
+
// A fallback demoted the same way costs exactly as much, and only bites
|
|
60
|
+
// once the primary is already failing — the worst moment to discover it.
|
|
61
|
+
// The fallback path consults the provider's own conventional variable.
|
|
62
|
+
const conventionalVar = defaultApiKeyEnvName(target);
|
|
63
|
+
const fallbackVar = runtime.fallback?.provider === target
|
|
64
|
+
&& runtime.fallback.apiKey !== undefined
|
|
65
|
+
&& readNonEmptyString(processEnv[conventionalVar]) === runtime.fallback.apiKey
|
|
66
|
+
? conventionalVar
|
|
67
|
+
: undefined;
|
|
68
|
+
const culprit = primary ?? fallbackVar;
|
|
69
|
+
if (!culprit) {
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
writeLine(streams.stderr, `Warning: ${culprit} in your environment outranks the ${planName} saved by \`stratus setup\`, `
|
|
73
|
+
+ `so ${primary ? 'this run is' : 'a fallback retry would be'} billed per token instead of through your plan. `
|
|
74
|
+
+ 'Unset it to use the subscription, or run `stratus doctor` to see everything that is being overridden.');
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
// The shared wiring behind every conversational command: memory (with
|
|
78
|
+
// legacy migration), tools, events, provider (with fallback), and the
|
|
79
|
+
// agent the runtime resolved. run uses it for one shot; chat keeps the
|
|
80
|
+
// runner alive and resumes the same session turn after turn.
|
|
81
|
+
export const createAgentRuntime = async (streams, options) => {
|
|
82
|
+
const runEnv = options.env ?? {};
|
|
83
|
+
await migrateLegacyMemory(runEnv);
|
|
84
|
+
const memory = withLegacyDefaultMemories(createFileMemoryStore(memoryFilePath(runEnv)));
|
|
85
|
+
const tools = new ToolRegistry();
|
|
86
|
+
tools.register(createDemoTool());
|
|
87
|
+
tools.register(createRememberTool(memory));
|
|
88
|
+
tools.register(createRecallTool(memory));
|
|
89
|
+
tools.register(createForgetTool(memory));
|
|
90
|
+
// The same skills the daemon would serve, from the same directory, for
|
|
91
|
+
// the same reason the plugins below match: a skill that routes in
|
|
92
|
+
// `stratus run` routes in `stratus serve`, and one that is broken is
|
|
93
|
+
// broken (and warned about) in both. The runner registers `skill.read`
|
|
94
|
+
// itself, gated on the soul enabling any skill.
|
|
95
|
+
const skills = new SkillRegistry();
|
|
96
|
+
await loadOperatorSkills(runEnv, skills, (line) => {
|
|
97
|
+
writeLine(streams.stderr, `Warning: ${line}`);
|
|
98
|
+
});
|
|
99
|
+
const bus = new EventBus({
|
|
100
|
+
onError: (error) => {
|
|
101
|
+
writeLine(streams.stderr, `Warning: event handler failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
if (options.onEvent) {
|
|
105
|
+
const onEvent = options.onEvent;
|
|
106
|
+
bus.subscribe(async (event) => {
|
|
107
|
+
onEvent(event);
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else if (options.events ?? true) {
|
|
111
|
+
bus.subscribe(async (event) => {
|
|
112
|
+
const line = formatEvent(event);
|
|
113
|
+
if (line) {
|
|
114
|
+
writeLine(streams.stdout, line);
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
// The same plugins the daemon would load, from the same trusted config,
|
|
119
|
+
// so a tool that works in `stratus run` works in `stratus serve` and a
|
|
120
|
+
// tool that is missing is missing in both. A local test that silently ran
|
|
121
|
+
// a different toolset than the daemon would be worse than no local test.
|
|
122
|
+
const pluginsConfig = await loadServePlugins(runEnv, options.configPath, (line) => {
|
|
123
|
+
writeLine(streams.stderr, `Warning: ${line}`);
|
|
124
|
+
});
|
|
125
|
+
const loadedPlugins = [];
|
|
126
|
+
if (Object.keys(pluginsConfig).length > 0) {
|
|
127
|
+
const result = await loadPlugins({
|
|
128
|
+
config: pluginsConfig,
|
|
129
|
+
host: {
|
|
130
|
+
resolve: (specifier) => import.meta.resolve(specifier),
|
|
131
|
+
import: (specifier) => import(__rewriteRelativeImportExtension(specifier)),
|
|
132
|
+
},
|
|
133
|
+
tools,
|
|
134
|
+
skills,
|
|
135
|
+
bus,
|
|
136
|
+
credentials: createFileCredentialResolver(runEnv),
|
|
137
|
+
workspaceRoot: workspacesDirPath(runEnv),
|
|
138
|
+
});
|
|
139
|
+
loadedPlugins.push(...result.loaded);
|
|
140
|
+
for (const failure of result.failures) {
|
|
141
|
+
writeLine(streams.stderr, `Warning: plugin ${failure.package} did not load: ${failure.reason}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// The Claude Code runtime executes kernel tools by calling back into the
|
|
145
|
+
// runner built just below — late-bound because the runner needs the
|
|
146
|
+
// provider first.
|
|
147
|
+
let hostedRunner;
|
|
148
|
+
const runtimeProvider = createRuntimeProvider(options.runtime, (error) => {
|
|
149
|
+
const fallback = options.runtime.provider === 'demo' ? undefined : options.runtime.fallback;
|
|
150
|
+
writeLine(streams.stderr, `Warning: the default model failed (${error instanceof Error ? error.message : String(error)}); falling back to ${fallback?.model ?? 'the fallback model'}.`);
|
|
151
|
+
}, async (session, call, context) => {
|
|
152
|
+
if (!hostedRunner) {
|
|
153
|
+
throw new Error('The Stratus runtime is not ready to execute tools yet.');
|
|
154
|
+
}
|
|
155
|
+
return hostedRunner.executeHostedToolCall(session, call, context);
|
|
156
|
+
}, options.maxTurns);
|
|
157
|
+
const runner = new AgentRunner({
|
|
158
|
+
provider: runtimeProvider,
|
|
159
|
+
tools,
|
|
160
|
+
executor: createLocalCommandExecutor(),
|
|
161
|
+
approvals: createApprovalPolicy(options.approvals ?? 'always', streams, options.env ?? {}, options.askApproval),
|
|
162
|
+
bus,
|
|
163
|
+
skills,
|
|
164
|
+
memory,
|
|
165
|
+
...(options.maxTurns !== undefined ? { maxTurns: options.maxTurns } : {}),
|
|
166
|
+
});
|
|
167
|
+
hostedRunner = runner;
|
|
168
|
+
await runner.initialize();
|
|
169
|
+
// A soul is a full identity — without one, every provider serves the
|
|
170
|
+
// same built-in Stratus persona.
|
|
171
|
+
const agent = options.runtime.soul?.agent ?? DEFAULT_STRATUS_AGENT;
|
|
172
|
+
// The same advisory the daemon gives at roster load, from the same
|
|
173
|
+
// kernel check: a soul enabling a skill whose `requires:` its `tools:`
|
|
174
|
+
// does not cover must warn here too, or the local test stays silent
|
|
175
|
+
// about a configuration `stratus serve` flags.
|
|
176
|
+
for (const { skill, missing } of missingSkillRequirements(agent, skills)) {
|
|
177
|
+
writeLine(streams.stderr, `Warning: agent ${agent.id} enables skill ${skill.id}, which expects tools the agent is not allowed: ${missing.join(', ')}`);
|
|
178
|
+
}
|
|
179
|
+
// And the same for the tools themselves, after `initialize()` so the
|
|
180
|
+
// plugins have registered theirs: an allowlist entry naming a tool
|
|
181
|
+
// nothing provides grants nothing and says nothing, and a soul made only
|
|
182
|
+
// of those runs with no tools while its persona still talks about them.
|
|
183
|
+
const finding = unmatchedToolAllowlist(agent, tools.describe().map((tool) => tool.name), {
|
|
184
|
+
mayRegister: loadedPlugins.flatMap((plugin) => plugin.manifest.contributes.toolsDiscovered.map((declared) => declared.namespace)),
|
|
185
|
+
// A local run has no dispatcher, store, or channels, so it registers
|
|
186
|
+
// none of the daemon's tools. A soul written for `stratus serve` is
|
|
187
|
+
// not wrong for naming them here — it is in the wrong process.
|
|
188
|
+
elsewhere: GATEWAY_ONLY_TOOL_NAMES,
|
|
189
|
+
});
|
|
190
|
+
for (const line of finding ? describeToolAllowlistFinding(agent.id, finding) : []) {
|
|
191
|
+
writeLine(streams.stderr, `Warning: ${line}`);
|
|
192
|
+
}
|
|
193
|
+
// The kernel leaves this one to the host, because only the host knows
|
|
194
|
+
// which process it is not.
|
|
195
|
+
if (finding && finding.elsewhere.length > 0) {
|
|
196
|
+
writeLine(streams.stderr, `Warning: agent ${agent.id} lists ${finding.elsewhere.join(', ')}, which only the daemon provides`
|
|
197
|
+
+ ' — the names are right, but stratus run cannot call them; stratus serve can');
|
|
198
|
+
}
|
|
199
|
+
const metadata = options.runtime.provider === 'demo'
|
|
200
|
+
? { provider: 'demo', executor: 'local-command' }
|
|
201
|
+
: {
|
|
202
|
+
provider: options.runtime.provider,
|
|
203
|
+
model: options.runtime.model,
|
|
204
|
+
...(options.runtime.provider === 'openai' ? { baseUrl: options.runtime.baseUrl } : {}),
|
|
205
|
+
};
|
|
206
|
+
// Handed back so a command can release what a plugin acquired — a browser
|
|
207
|
+
// above all. A one-shot `stratus run` that left a Chromium behind would
|
|
208
|
+
// be a leak per invocation.
|
|
209
|
+
const disposePlugins = async () => {
|
|
210
|
+
for (const plugin of loadedPlugins) {
|
|
211
|
+
try {
|
|
212
|
+
await plugin.instance.dispose?.();
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
writeLine(streams.stderr, `Warning: plugin ${plugin.package} failed to shut down: ${error instanceof Error ? error.message : String(error)}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
return { runner, agent, metadata, disposePlugins };
|
|
220
|
+
};
|
|
221
|
+
export const runSingleLoop = async (prompt, streams, options) => {
|
|
222
|
+
const { runner, agent, metadata, disposePlugins } = await createAgentRuntime(streams, options);
|
|
223
|
+
try {
|
|
224
|
+
return await runner.run({
|
|
225
|
+
sessionId: randomUUID(),
|
|
226
|
+
agent,
|
|
227
|
+
userMessage: prompt,
|
|
228
|
+
metadata,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
finally {
|
|
232
|
+
// Even when the run failed: a plugin that started a browser started it
|
|
233
|
+
// before the turn could fail.
|
|
234
|
+
await disposePlugins();
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
export const printSessionSummary = (session, streams) => {
|
|
238
|
+
writeLine(streams.stdout);
|
|
239
|
+
writeLine(streams.stdout, 'Messages');
|
|
240
|
+
for (const message of session.messages) {
|
|
241
|
+
if (message.role === 'assistant' && message.toolCalls && message.toolCalls.length > 0) {
|
|
242
|
+
const calls = message.toolCalls
|
|
243
|
+
.map((call) => `${call.toolName}(${JSON.stringify(call.input)})`)
|
|
244
|
+
.join(', ');
|
|
245
|
+
const prefix = message.content ? `${message.content} ` : '';
|
|
246
|
+
writeLine(streams.stdout, `[assistant] ${prefix}→ tool call ${calls}`);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (message.role === 'assistant' && message.content.length === 0) {
|
|
250
|
+
// A turn nobody asked for that said nothing — see `RunInput.addressed`.
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const nameSuffix = message.name ? `:${message.name}` : '';
|
|
254
|
+
const content = message.role === 'tool' ? stringifyValue(JSON.parse(message.content)) : message.content;
|
|
255
|
+
writeLine(streams.stdout, `[${message.role}${nameSuffix}] ${content}`);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
export const formatRuntimeBanner = (runtime) => {
|
|
259
|
+
const soulSuffix = runtime.soul ? ` as ${runtime.soul.agent.name}` : '';
|
|
260
|
+
if (runtime.provider === 'demo') {
|
|
261
|
+
return `Starting Stratus Agent local loop with provider=demo${soulSuffix}`;
|
|
262
|
+
}
|
|
263
|
+
const fallbackSuffix = runtime.fallback ? ` fallback=${runtime.fallback.model}` : '';
|
|
264
|
+
return `Starting Stratus Agent local loop with provider=${runtime.provider} model=${runtime.model}${fallbackSuffix}${soulSuffix}`;
|
|
265
|
+
};
|
|
266
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/slack.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface SlackIdentity {
|
|
2
|
+
botUserId?: string;
|
|
3
|
+
teamName?: string;
|
|
4
|
+
teamId?: string;
|
|
5
|
+
}
|
|
6
|
+
type SlackVerdict = {
|
|
7
|
+
status: 'ok';
|
|
8
|
+
identity: SlackIdentity;
|
|
9
|
+
} | {
|
|
10
|
+
status: 'rejected';
|
|
11
|
+
detail: string;
|
|
12
|
+
} | {
|
|
13
|
+
status: 'unreachable';
|
|
14
|
+
detail: string;
|
|
15
|
+
};
|
|
16
|
+
/** Verifies a bot token and reports the identity it belongs to. */
|
|
17
|
+
export declare const verifySlackBotToken: (token: string, fetchImpl: typeof fetch | undefined) => Promise<SlackVerdict>;
|
|
18
|
+
/**
|
|
19
|
+
* Verifies an app-level token by opening a Socket Mode URL. The URL is
|
|
20
|
+
* discarded — this only proves the token carries connections:write, which
|
|
21
|
+
* is the failure the daemon would otherwise hit at start time.
|
|
22
|
+
*/
|
|
23
|
+
export declare const verifySlackAppToken: (token: string, fetchImpl: typeof fetch | undefined) => Promise<SlackVerdict>;
|
|
24
|
+
export declare const slackAppManifest: (agentName: string) => string;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=slack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"AAMA,UAAU,aAAa;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,YAAY,GACb;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,GACzC;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAiC9C,mEAAmE;AACnE,eAAO,MAAM,mBAAmB,GAAU,OAAO,MAAM,EAAE,WAAW,OAAO,KAAK,GAAG,SAAS,KAAG,OAAO,CAAC,YAAY,CAalH,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAU,OAAO,MAAM,EAAE,WAAW,OAAO,KAAK,GAAG,SAAS,KAAG,OAAO,CAAC,YAAY,CAGlH,CAAC;AAqCF,eAAO,MAAM,gBAAgB,GAAI,WAAW,MAAM,KAAG,MAsB1C,CAAC"}
|
package/dist/slack.js
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// Slack verification talks to the Web API over plain fetch rather than
|
|
2
|
+
// through @stratusagent/channel-slack. Setup must stay usable before that
|
|
3
|
+
// optional package is installed, and the CLI deliberately does not depend
|
|
4
|
+
// on it (or on the ~9 MB of Slack SDKs underneath).
|
|
5
|
+
const SLACK_API_ROOT = 'https://slack.com/api';
|
|
6
|
+
const callSlack = async (method, token, fetchImpl) => {
|
|
7
|
+
if (typeof fetchImpl !== 'function') {
|
|
8
|
+
return { ok: false, verdict: { status: 'unreachable', detail: 'fetch is unavailable' } };
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const response = await fetchImpl(`${SLACK_API_ROOT}/${method}`, {
|
|
12
|
+
method: 'POST',
|
|
13
|
+
headers: {
|
|
14
|
+
authorization: `Bearer ${token}`,
|
|
15
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
return { ok: false, verdict: { status: 'unreachable', detail: `HTTP ${response.status}` } };
|
|
20
|
+
}
|
|
21
|
+
const body = await response.json();
|
|
22
|
+
if (body.ok === true) {
|
|
23
|
+
return { ok: true, body };
|
|
24
|
+
}
|
|
25
|
+
// Slack answers 200 with { ok: false, error } for bad credentials, so
|
|
26
|
+
// the error string — not the status — is what condemns a token.
|
|
27
|
+
return { ok: false, verdict: { status: 'rejected', detail: String(body.error ?? 'unknown error') } };
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
return { ok: false, verdict: { status: 'unreachable', detail: error instanceof Error ? error.message : String(error) } };
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
/** Verifies a bot token and reports the identity it belongs to. */
|
|
34
|
+
export const verifySlackBotToken = async (token, fetchImpl) => {
|
|
35
|
+
const result = await callSlack('auth.test', token, fetchImpl);
|
|
36
|
+
if (!result.ok) {
|
|
37
|
+
return result.verdict;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
status: 'ok',
|
|
41
|
+
identity: {
|
|
42
|
+
...(typeof result.body.user_id === 'string' ? { botUserId: result.body.user_id } : {}),
|
|
43
|
+
...(typeof result.body.team === 'string' ? { teamName: result.body.team } : {}),
|
|
44
|
+
...(typeof result.body.team_id === 'string' ? { teamId: result.body.team_id } : {}),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Verifies an app-level token by opening a Socket Mode URL. The URL is
|
|
50
|
+
* discarded — this only proves the token carries connections:write, which
|
|
51
|
+
* is the failure the daemon would otherwise hit at start time.
|
|
52
|
+
*/
|
|
53
|
+
export const verifySlackAppToken = async (token, fetchImpl) => {
|
|
54
|
+
const result = await callSlack('apps.connections.open', token, fetchImpl);
|
|
55
|
+
return result.ok ? { status: 'ok', identity: {} } : result.verdict;
|
|
56
|
+
};
|
|
57
|
+
// Scopes and events the adapter needs. Kept in step with the manifest
|
|
58
|
+
// shipped by @stratusagent/channel-slack (a test pins them together) so
|
|
59
|
+
// setup can hand over a ready-to-paste manifest without depending on that
|
|
60
|
+
// package being installed.
|
|
61
|
+
const SLACK_BOT_SCOPES = [
|
|
62
|
+
'app_mentions:read',
|
|
63
|
+
// The history family is what lets an agent stay in a conversation it was
|
|
64
|
+
// brought into: without it Slack delivers only mentions, and a reply in
|
|
65
|
+
// the agent's own thread never reaches it. It is the workspace's switch
|
|
66
|
+
// for that — an app installed without these scopes answers mentions and
|
|
67
|
+
// nothing else, exactly as it always did.
|
|
68
|
+
'channels:history',
|
|
69
|
+
// The conversations read family backs outbound destination validation
|
|
70
|
+
// (conversations.info): whether a channel a schedule wants to report to
|
|
71
|
+
// exists, and whether this app is a member of it.
|
|
72
|
+
'channels:read',
|
|
73
|
+
'chat:write',
|
|
74
|
+
// What lets an agent be shown a screenshot: file bytes sit behind an
|
|
75
|
+
// authenticated URL that answers a token without this scope with a
|
|
76
|
+
// sign-in page. An app installed without it still hears about the
|
|
77
|
+
// attachment, by name, and is told it cannot open it.
|
|
78
|
+
'files:read',
|
|
79
|
+
'files:write',
|
|
80
|
+
'groups:history',
|
|
81
|
+
'groups:read',
|
|
82
|
+
'im:history',
|
|
83
|
+
'im:read',
|
|
84
|
+
'im:write',
|
|
85
|
+
'mpim:history',
|
|
86
|
+
'mpim:read',
|
|
87
|
+
'users:read',
|
|
88
|
+
];
|
|
89
|
+
const SLACK_BOT_EVENTS = ['app_mention', 'message.channels', 'message.groups', 'message.im', 'message.mpim'];
|
|
90
|
+
export const slackAppManifest = (agentName) => JSON.stringify({
|
|
91
|
+
display_information: {
|
|
92
|
+
name: agentName,
|
|
93
|
+
description: 'A Stratus agent',
|
|
94
|
+
background_color: '#1a1d21',
|
|
95
|
+
},
|
|
96
|
+
features: {
|
|
97
|
+
bot_user: { display_name: agentName, always_online: true },
|
|
98
|
+
},
|
|
99
|
+
oauth_config: { scopes: { bot: SLACK_BOT_SCOPES } },
|
|
100
|
+
settings: {
|
|
101
|
+
event_subscriptions: { bot_events: SLACK_BOT_EVENTS },
|
|
102
|
+
// Required for remote approval: Allow / Always allow / Deny arrive as
|
|
103
|
+
// block_actions, and Slack delivers none of them to an app that has
|
|
104
|
+
// interactivity switched off. Enabled unconditionally rather than per
|
|
105
|
+
// mode — an app is created once, and discovering months later that the
|
|
106
|
+
// buttons do nothing means editing the manifest and reinstalling.
|
|
107
|
+
interactivity: { is_enabled: true },
|
|
108
|
+
org_deploy_enabled: false,
|
|
109
|
+
socket_mode_enabled: true,
|
|
110
|
+
token_rotation_enabled: false,
|
|
111
|
+
},
|
|
112
|
+
}, null, 2);
|
|
113
|
+
//# sourceMappingURL=slack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slack.js","sourceRoot":"","sources":["../src/slack.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,0EAA0E;AAC1E,0EAA0E;AAC1E,oDAAoD;AACpD,MAAM,cAAc,GAAG,uBAAuB,CAAC;AAa/C,MAAM,SAAS,GAAG,KAAK,EACrB,MAAc,EACd,KAAa,EACb,SAAmC,EAC0D,EAAE;IAC/F,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;QACpC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,sBAAsB,EAAE,EAAE,CAAC;IAC3F,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,GAAG,cAAc,IAAI,MAAM,EAAE,EAAE;YAC9D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,KAAK,EAAE;gBAChC,cAAc,EAAE,mCAAmC;aACpD;SACF,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;QAC9F,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAA6B,CAAC;QAC9D,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC5B,CAAC;QACD,sEAAsE;QACtE,gEAAgE;QAChE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,eAAe,CAAC,EAAE,EAAE,CAAC;IACvG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IAC3H,CAAC;AACH,CAAC,CAAC;AAEF,mEAAmE;AACnE,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,KAAa,EAAE,SAAmC,EAAyB,EAAE;IACrH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAC9D,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,OAAO,MAAM,CAAC,OAAO,CAAC;IACxB,CAAC;IACD,OAAO;QACL,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE;YACR,GAAG,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACtF,GAAG,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/E,GAAG,CAAC,OAAO,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,KAAa,EAAE,SAAmC,EAAyB,EAAE;IACrH,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,uBAAuB,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC;IAC1E,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;AACrE,CAAC,CAAC;AAEF,sEAAsE;AACtE,wEAAwE;AACxE,0EAA0E;AAC1E,2BAA2B;AAC3B,MAAM,gBAAgB,GAAG;IACvB,mBAAmB;IACnB,yEAAyE;IACzE,wEAAwE;IACxE,wEAAwE;IACxE,wEAAwE;IACxE,0CAA0C;IAC1C,kBAAkB;IAClB,sEAAsE;IACtE,wEAAwE;IACxE,kDAAkD;IAClD,eAAe;IACf,YAAY;IACZ,qEAAqE;IACrE,mEAAmE;IACnE,kEAAkE;IAClE,sDAAsD;IACtD,YAAY;IACZ,aAAa;IACb,gBAAgB;IAChB,aAAa;IACb,YAAY;IACZ,SAAS;IACT,UAAU;IACV,cAAc;IACd,WAAW;IACX,YAAY;CACb,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,aAAa,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;AAE7G,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,SAAiB,EAAU,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC;IAC5E,mBAAmB,EAAE;QACnB,IAAI,EAAE,SAAS;QACf,WAAW,EAAE,iBAAiB;QAC9B,gBAAgB,EAAE,SAAS;KAC5B;IACD,QAAQ,EAAE;QACR,QAAQ,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,IAAI,EAAE;KAC3D;IACD,YAAY,EAAE,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE;IACnD,QAAQ,EAAE;QACR,mBAAmB,EAAE,EAAE,UAAU,EAAE,gBAAgB,EAAE;QACrD,sEAAsE;QACtE,oEAAoE;QACpE,sEAAsE;QACtE,uEAAuE;QACvE,kEAAkE;QAClE,aAAa,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;QACnC,kBAAkB,EAAE,KAAK;QACzB,mBAAmB,EAAE,IAAI;QACzB,sBAAsB,EAAE,KAAK;KAC9B;CACF,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC"}
|
package/dist/source.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CliEnvironment } from './environment.ts';
|
|
2
|
+
/**
|
|
3
|
+
* What a `skill add` source string means, in order: a directory on this
|
|
4
|
+
* machine, a GitHub `owner/repo` shorthand, or a URL git can clone. The
|
|
5
|
+
* shorthand is the form skills.sh and its CLI print, so a skill published
|
|
6
|
+
* there installs by the name its listing shows.
|
|
7
|
+
*/
|
|
8
|
+
export declare const resolveSource: (source: string, env: CliEnvironment, what: "skill" | "template") => Promise<{
|
|
9
|
+
kind: "local";
|
|
10
|
+
directory: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "git";
|
|
13
|
+
url: string;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* A source URL safe to print: userinfo stripped. A token travels in exactly
|
|
17
|
+
* this position (`https://user:token@host/repo.git`), stdout is commonly
|
|
18
|
+
* retained in CI logs, and git's own stderr already redacts — only the
|
|
19
|
+
* unredacted URL is handed to git itself.
|
|
20
|
+
*/
|
|
21
|
+
export declare const redactedSourceUrl: (url: string) => string;
|
|
22
|
+
/** Shallow-clone a source repository. Git owns every transport we would otherwise re-implement. */
|
|
23
|
+
export declare const cloneSource: (url: string, destination: string) => Promise<void>;
|
|
24
|
+
//# sourceMappingURL=source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,MAAM,EACd,KAAK,cAAc,EACnB,MAAM,OAAO,GAAG,UAAU,KACzB,OAAO,CAAC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAsB7E,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,KAAG,MAa/C,CAAC;AAEF,mGAAmG;AACnG,eAAO,MAAM,WAAW,GAAU,KAAK,MAAM,EAAE,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CAuBhF,CAAC"}
|
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":"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"}
|
|
@@ -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"}
|