@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/runtime.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
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, ContributionRegistry, createRoutedMemoryStore, 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 { BUILTIN_EXECUTOR_NAME, BUILTIN_MEMORY_STORE_NAME, createDemoTool, createFileCredentialResolver, createFileMemoryStore, createRuntimeProvider, defaultApiKeyEnvName, DEFAULT_STRATUS_AGENT, isSignedInRuntime, 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 { quoteShellArg } from "./prompter.js";
|
|
19
|
+
import { loadServePlugins, loadServeRuntimeSelection } from "./trusted-config.js";
|
|
20
|
+
/**
|
|
21
|
+
* Kept with its historical CLI signature: a parsed run command is a
|
|
22
|
+
* RuntimeSelection plus CLI-only fields the resolver ignores.
|
|
23
|
+
*
|
|
24
|
+
* Those fields are *permitted*, not required. Demanding a whole
|
|
25
|
+
* `ParsedRunCommand` made the type claim the resolver cared about
|
|
26
|
+
* `approvals`, `format`, and `events` — it reads none of them — so every
|
|
27
|
+
* caller with a selection in hand had to invent values to get past it.
|
|
28
|
+
*/
|
|
29
|
+
export const resolveRuntimeConfig = (command, env = {}) => resolveStateRuntimeConfig(command, env);
|
|
30
|
+
/**
|
|
31
|
+
* Says, once the run is up, what an auto-discovered project config asked
|
|
32
|
+
* for and did not get. The resolver only records it — nothing is logging
|
|
33
|
+
* while a run resolves — and a persona that silently failed to apply would
|
|
34
|
+
* read as the agent ignoring its instructions rather than as the trust
|
|
35
|
+
* decision it is.
|
|
36
|
+
*/
|
|
37
|
+
export const warnOnUntrustedConfig = (runtime, streams, soulFlag = true) => {
|
|
38
|
+
warnOnIgnoredConfig(runtime.ignoredFromUntrustedConfig, streams, soulFlag);
|
|
39
|
+
};
|
|
40
|
+
/** The environment variable that names each refused key, as the resolver reads it. */
|
|
41
|
+
const ENV_FOR_PROMPT_KEY = {
|
|
42
|
+
soul: 'STRATUS_SOUL',
|
|
43
|
+
systemPrompt: 'STRATUS_SYSTEM_PROMPT',
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* The way out of a refused persona, as one sentence. `--config` trusts the
|
|
47
|
+
* file; the other way is the operator's own channel for the key — the
|
|
48
|
+
* `--soul` flag where the command takes one (`run` and `chat`; `serve` and
|
|
49
|
+
* `doctor` do not, and a notice sending the operator to a flag the daemon
|
|
50
|
+
* refuses is a notice that cost a restart), the environment otherwise.
|
|
51
|
+
* Never "move the key to ~/.stratus/config.json": the project file that
|
|
52
|
+
* caused this shadows the global one in discovery, so a key moved there
|
|
53
|
+
* would go on being unset for every run started here.
|
|
54
|
+
*/
|
|
55
|
+
export const ignoredConfigRemedy = (ignored, soulFlag) => {
|
|
56
|
+
const environment = (keys) => `set ${keys.map((key) => ENV_FOR_PROMPT_KEY[key]).join(' / ')}`;
|
|
57
|
+
const rest = ignored.keys.filter((key) => key !== 'soul');
|
|
58
|
+
// The flag restores only the soul: when the preamble was refused too,
|
|
59
|
+
// a remedy that stopped at --soul would leave it silently unset.
|
|
60
|
+
const otherWay = soulFlag && ignored.keys.includes('soul')
|
|
61
|
+
? (rest.length === 0 ? 'pass --soul <path>' : `pass --soul <path> and ${environment(rest)}`)
|
|
62
|
+
: environment(ignored.keys);
|
|
63
|
+
return `Run with --config ${quoteShellArg(ignored.path)} to trust that file, or ${otherWay}.`;
|
|
64
|
+
};
|
|
65
|
+
/** `soulFlag`: whether the command printing this takes `--soul` — see {@link ignoredConfigRemedy}. */
|
|
66
|
+
export const warnOnIgnoredConfig = (ignored, streams, soulFlag = true) => {
|
|
67
|
+
if (!ignored) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const keys = ignored.keys.join(' and ');
|
|
71
|
+
writeLine(streams.stderr, `ignoring ${keys} in ${ignored.path}: what an agent is told is not a decision an auto-discovered config gets to make. `
|
|
72
|
+
+ ignoredConfigRemedy(ignored, soulFlag));
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* A saved subscription sign-in silently demoted to per-token billing is the
|
|
76
|
+
* one config surprise that costs money — an API key in the environment
|
|
77
|
+
* outranks the stored credential, and the run otherwise looks identical.
|
|
78
|
+
* Detected from the resolved config: an apiKey where the stored credential
|
|
79
|
+
* is a subscription token means the environment won.
|
|
80
|
+
*/
|
|
81
|
+
export const warnOnCredentialOverride = async (runtime, streams, env = {}) => {
|
|
82
|
+
if (runtime.provider === 'demo') {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const credentials = await loadCredentials(env);
|
|
86
|
+
const processEnv = readProcessEnv(env);
|
|
87
|
+
// The resolver records the variable that actually won — guessing it here
|
|
88
|
+
// would name the wrong one whenever a custom apiKeyEnv supplied the key,
|
|
89
|
+
// sending the reader to unset something that was never the cause.
|
|
90
|
+
const primaryOverride = isSignedInRuntime(runtime) && runtime.apiKey !== undefined
|
|
91
|
+
? { provider: runtime.provider, envVar: runtime.apiKeyEnvVar }
|
|
92
|
+
: undefined;
|
|
93
|
+
// Both subscription sign-ins demote the same way: a Claude setup token
|
|
94
|
+
// and the codex ChatGPT marker each lose to an environment API key, and
|
|
95
|
+
// the run otherwise looks identical while billing per token.
|
|
96
|
+
for (const target of ['anthropic', 'codex']) {
|
|
97
|
+
if (credentials[target]?.type !== 'oauth_token') {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const planName = target === 'anthropic'
|
|
101
|
+
? 'Claude subscription sign-in'
|
|
102
|
+
: 'ChatGPT (codex login) sign-in';
|
|
103
|
+
const primary = primaryOverride?.provider === target ? primaryOverride.envVar : undefined;
|
|
104
|
+
// A fallback demoted the same way costs exactly as much, and only bites
|
|
105
|
+
// once the primary is already failing — the worst moment to discover it.
|
|
106
|
+
// The fallback path consults the provider's own conventional variable.
|
|
107
|
+
const conventionalVar = defaultApiKeyEnvName(target);
|
|
108
|
+
const fallbackVar = runtime.fallback?.provider === target
|
|
109
|
+
&& runtime.fallback.apiKey !== undefined
|
|
110
|
+
&& readNonEmptyString(processEnv[conventionalVar]) === runtime.fallback.apiKey
|
|
111
|
+
? conventionalVar
|
|
112
|
+
: undefined;
|
|
113
|
+
const culprit = primary ?? fallbackVar;
|
|
114
|
+
if (!culprit) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
writeLine(streams.stderr, `Warning: ${culprit} in your environment outranks the ${planName} saved by \`stratus setup\`, `
|
|
118
|
+
+ `so ${primary ? 'this run is' : 'a fallback retry would be'} billed per token instead of through your plan. `
|
|
119
|
+
+ 'Unset it to use the subscription, or run `stratus doctor` to see everything that is being overridden.');
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
// The shared wiring behind every conversational command: memory (with
|
|
123
|
+
// legacy migration), tools, events, provider (with fallback), and the
|
|
124
|
+
// agent the runtime resolved. run uses it for one shot; chat keeps the
|
|
125
|
+
// runner alive and resumes the same session turn after turn.
|
|
126
|
+
export const createAgentRuntime = async (streams, options) => {
|
|
127
|
+
const runEnv = options.env ?? {};
|
|
128
|
+
await migrateLegacyMemory(runEnv);
|
|
129
|
+
// Routed, as the daemon's is: the memory tools register before the
|
|
130
|
+
// plugins load (so a plugin cannot claim their names), and the store
|
|
131
|
+
// they hold answers per call with whichever the trusted config selected
|
|
132
|
+
// once the plugins are up.
|
|
133
|
+
const fileMemory = withLegacyDefaultMemories(createFileMemoryStore(memoryFilePath(runEnv)));
|
|
134
|
+
let selectedMemory = fileMemory;
|
|
135
|
+
const memory = createRoutedMemoryStore(() => selectedMemory);
|
|
136
|
+
const tools = new ToolRegistry();
|
|
137
|
+
tools.register(createDemoTool());
|
|
138
|
+
tools.register(createRememberTool(memory));
|
|
139
|
+
tools.register(createRecallTool(memory));
|
|
140
|
+
tools.register(createForgetTool(memory));
|
|
141
|
+
// The same skills the daemon would serve, from the same directory, for
|
|
142
|
+
// the same reason the plugins below match: a skill that routes in
|
|
143
|
+
// `stratus run` routes in `stratus serve`, and one that is broken is
|
|
144
|
+
// broken (and warned about) in both. The runner registers `skill.read`
|
|
145
|
+
// itself, gated on the soul enabling any skill.
|
|
146
|
+
const skills = new SkillRegistry();
|
|
147
|
+
await loadOperatorSkills(runEnv, skills, (line) => {
|
|
148
|
+
writeLine(streams.stderr, `Warning: ${line}`);
|
|
149
|
+
});
|
|
150
|
+
const bus = new EventBus({
|
|
151
|
+
onError: (error) => {
|
|
152
|
+
writeLine(streams.stderr, `Warning: event handler failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
if (options.onEvent) {
|
|
156
|
+
const onEvent = options.onEvent;
|
|
157
|
+
bus.subscribe(async (event) => {
|
|
158
|
+
onEvent(event);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
else if (options.events ?? true) {
|
|
162
|
+
bus.subscribe(async (event) => {
|
|
163
|
+
const line = formatEvent(event);
|
|
164
|
+
if (line) {
|
|
165
|
+
writeLine(streams.stdout, line);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
// The same plugins the daemon would load, from the same trusted config,
|
|
170
|
+
// so a tool that works in `stratus run` works in `stratus serve` and a
|
|
171
|
+
// tool that is missing is missing in both. A local test that silently ran
|
|
172
|
+
// a different toolset than the daemon would be worse than no local test.
|
|
173
|
+
const pluginsConfig = await loadServePlugins(runEnv, options.configPath, (line) => {
|
|
174
|
+
writeLine(streams.stderr, `Warning: ${line}`);
|
|
175
|
+
});
|
|
176
|
+
const loadedPlugins = [];
|
|
177
|
+
const providers = new ContributionRegistry();
|
|
178
|
+
const memoryStores = new ContributionRegistry();
|
|
179
|
+
const executors = new ContributionRegistry();
|
|
180
|
+
if (Object.keys(pluginsConfig).length > 0) {
|
|
181
|
+
const result = await loadPlugins({
|
|
182
|
+
config: pluginsConfig,
|
|
183
|
+
host: {
|
|
184
|
+
resolve: (specifier) => import.meta.resolve(specifier),
|
|
185
|
+
import: (specifier) => import(__rewriteRelativeImportExtension(specifier)),
|
|
186
|
+
},
|
|
187
|
+
tools,
|
|
188
|
+
skills,
|
|
189
|
+
bus,
|
|
190
|
+
providers,
|
|
191
|
+
memory: memoryStores,
|
|
192
|
+
executors,
|
|
193
|
+
// No channel registry and no transport secrets: a local run has no
|
|
194
|
+
// channels, so a channel plugin's registration is recorded and goes
|
|
195
|
+
// nowhere, and its request for its secrets is refused with a message
|
|
196
|
+
// that says so rather than answered with an empty roster.
|
|
197
|
+
credentials: createFileCredentialResolver(runEnv),
|
|
198
|
+
workspaceRoot: workspacesDirPath(runEnv),
|
|
199
|
+
});
|
|
200
|
+
loadedPlugins.push(...result.loaded);
|
|
201
|
+
for (const failure of result.failures) {
|
|
202
|
+
writeLine(streams.stderr, `Warning: plugin ${failure.package} did not load: ${failure.reason}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
// Handed back so a command can release what a plugin acquired — a browser
|
|
206
|
+
// above all. A one-shot `stratus run` that left a Chromium behind would
|
|
207
|
+
// be a leak per invocation. Defined before anything after the load can
|
|
208
|
+
// fail, because a refusal below — a selection nothing registers, a
|
|
209
|
+
// provider factory that throws — has the same plugins to release and no
|
|
210
|
+
// caller yet to release them: the callers' `finally` only begins once
|
|
211
|
+
// this returns.
|
|
212
|
+
const disposePlugins = async () => {
|
|
213
|
+
for (const plugin of loadedPlugins) {
|
|
214
|
+
try {
|
|
215
|
+
await plugin.instance.dispose?.();
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
writeLine(streams.stderr, `Warning: plugin ${plugin.package} failed to shut down: ${error instanceof Error ? error.message : String(error)}`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
try {
|
|
223
|
+
// The same selections the daemon makes, from the same trusted keys, and
|
|
224
|
+
// the same refusal: a run that quietly fell back to the host's executor
|
|
225
|
+
// when the operator selected a sandbox would be the local test lying
|
|
226
|
+
// about what the daemon does.
|
|
227
|
+
const warnTrusted = (line) => {
|
|
228
|
+
writeLine(streams.stderr, `Warning: ${line}`);
|
|
229
|
+
};
|
|
230
|
+
const executorName = (await loadServeRuntimeSelection('executor', runEnv, options.configPath, warnTrusted)) ?? BUILTIN_EXECUTOR_NAME;
|
|
231
|
+
let executor;
|
|
232
|
+
if (executorName !== BUILTIN_EXECUTOR_NAME) {
|
|
233
|
+
const contribution = executors.get(executorName);
|
|
234
|
+
if (!contribution) {
|
|
235
|
+
throw new Error(`The config selects executor ${executorName}, which no loaded plugin registers`
|
|
236
|
+
+ (executors.names().length > 0 ? ` (registered: ${executors.names().join(', ')})` : '')
|
|
237
|
+
+ `. Enable the plugin that contributes it, or set executor to ${BUILTIN_EXECUTOR_NAME}.`);
|
|
238
|
+
}
|
|
239
|
+
executor = contribution.executor;
|
|
240
|
+
}
|
|
241
|
+
const memoryName = (await loadServeRuntimeSelection('memoryStore', runEnv, options.configPath, warnTrusted)) ?? BUILTIN_MEMORY_STORE_NAME;
|
|
242
|
+
if (memoryName !== BUILTIN_MEMORY_STORE_NAME) {
|
|
243
|
+
const contribution = memoryStores.get(memoryName);
|
|
244
|
+
if (!contribution) {
|
|
245
|
+
throw new Error(`The config selects memoryStore ${memoryName}, which no loaded plugin registers`
|
|
246
|
+
+ (memoryStores.names().length > 0 ? ` (registered: ${memoryStores.names().join(', ')})` : '')
|
|
247
|
+
+ `. Enable the plugin that contributes it, or set memoryStore to ${BUILTIN_MEMORY_STORE_NAME}.`);
|
|
248
|
+
}
|
|
249
|
+
selectedMemory = contribution.store;
|
|
250
|
+
}
|
|
251
|
+
// The Claude Code runtime executes kernel tools by calling back into the
|
|
252
|
+
// runner built just below — late-bound because the runner needs the
|
|
253
|
+
// provider first.
|
|
254
|
+
let hostedRunner;
|
|
255
|
+
const runtimeProvider = createRuntimeProvider(options.runtime, (error) => {
|
|
256
|
+
const fallback = options.runtime.provider === 'demo' ? undefined : options.runtime.fallback;
|
|
257
|
+
writeLine(streams.stderr, `Warning: the default model failed (${error instanceof Error ? error.message : String(error)}); falling back to ${fallback?.model ?? 'the fallback model'}.`);
|
|
258
|
+
}, async (session, call, context) => {
|
|
259
|
+
if (!hostedRunner) {
|
|
260
|
+
throw new Error('The Stratus runtime is not ready to execute tools yet.');
|
|
261
|
+
}
|
|
262
|
+
return hostedRunner.executeHostedToolCall(session, call, context);
|
|
263
|
+
}, options.maxTurns, undefined, providers);
|
|
264
|
+
const runner = new AgentRunner({
|
|
265
|
+
provider: runtimeProvider,
|
|
266
|
+
tools,
|
|
267
|
+
executor: executor ?? createLocalCommandExecutor(),
|
|
268
|
+
approvals: createApprovalPolicy(options.approvals ?? 'always', streams, options.env ?? {}, options.askApproval, options.approvalsDefaulted ?? false),
|
|
269
|
+
bus,
|
|
270
|
+
skills,
|
|
271
|
+
memory,
|
|
272
|
+
...(options.maxTurns !== undefined ? { maxTurns: options.maxTurns } : {}),
|
|
273
|
+
});
|
|
274
|
+
hostedRunner = runner;
|
|
275
|
+
await runner.initialize();
|
|
276
|
+
// A soul is a full identity — without one, every provider serves the
|
|
277
|
+
// same built-in Stratus persona.
|
|
278
|
+
const agent = options.runtime.soul?.agent ?? DEFAULT_STRATUS_AGENT;
|
|
279
|
+
// The same advisory the daemon gives at roster load, from the same
|
|
280
|
+
// kernel check: a soul enabling a skill whose `requires:` its `tools:`
|
|
281
|
+
// does not cover must warn here too, or the local test stays silent
|
|
282
|
+
// about a configuration `stratus serve` flags.
|
|
283
|
+
for (const { skill, missing } of missingSkillRequirements(agent, skills)) {
|
|
284
|
+
writeLine(streams.stderr, `Warning: agent ${agent.id} enables skill ${skill.id}, which expects tools the agent is not allowed: ${missing.join(', ')}`);
|
|
285
|
+
}
|
|
286
|
+
// And the same for the tools themselves, after `initialize()` so the
|
|
287
|
+
// plugins have registered theirs: an allowlist entry naming a tool
|
|
288
|
+
// nothing provides grants nothing and says nothing, and a soul made only
|
|
289
|
+
// of those runs with no tools while its persona still talks about them.
|
|
290
|
+
const finding = unmatchedToolAllowlist(agent, tools.describe().map((tool) => tool.name), {
|
|
291
|
+
mayRegister: loadedPlugins.flatMap((plugin) => plugin.manifest.contributes.toolsDiscovered.map((declared) => declared.namespace)),
|
|
292
|
+
// A local run has no dispatcher, store, or channels, so it registers
|
|
293
|
+
// none of the daemon's tools. A soul written for `stratus serve` is
|
|
294
|
+
// not wrong for naming them here — it is in the wrong process.
|
|
295
|
+
elsewhere: GATEWAY_ONLY_TOOL_NAMES,
|
|
296
|
+
});
|
|
297
|
+
for (const line of finding ? describeToolAllowlistFinding(agent.id, finding) : []) {
|
|
298
|
+
writeLine(streams.stderr, `Warning: ${line}`);
|
|
299
|
+
}
|
|
300
|
+
// The kernel leaves this one to the host, because only the host knows
|
|
301
|
+
// which process it is not.
|
|
302
|
+
if (finding && finding.elsewhere.length > 0) {
|
|
303
|
+
writeLine(streams.stderr, `Warning: agent ${agent.id} lists ${finding.elsewhere.join(', ')}, which only the daemon provides`
|
|
304
|
+
+ ' — the names are right, but stratus run cannot call them; stratus serve can');
|
|
305
|
+
}
|
|
306
|
+
// The built-in executor keeps the name it has always recorded; a
|
|
307
|
+
// contributed one records the name it registered under — on every
|
|
308
|
+
// provider's session, since where a command ran is not a question only
|
|
309
|
+
// demo runs get to answer.
|
|
310
|
+
const executorRecord = executor ? executorName : 'local-command';
|
|
311
|
+
const metadata = options.runtime.provider === 'demo'
|
|
312
|
+
? { provider: 'demo', executor: executorRecord }
|
|
313
|
+
: {
|
|
314
|
+
provider: options.runtime.provider,
|
|
315
|
+
// A contributed provider may leave the model to its own default.
|
|
316
|
+
...(options.runtime.model !== undefined ? { model: options.runtime.model } : {}),
|
|
317
|
+
...(options.runtime.provider === 'openai' ? { baseUrl: options.runtime.baseUrl } : {}),
|
|
318
|
+
executor: executorRecord,
|
|
319
|
+
};
|
|
320
|
+
return { runner, agent, metadata, disposePlugins };
|
|
321
|
+
}
|
|
322
|
+
catch (error) {
|
|
323
|
+
await disposePlugins();
|
|
324
|
+
throw error;
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
export const runSingleLoop = async (prompt, streams, options) => {
|
|
328
|
+
const { runner, agent, metadata, disposePlugins } = await createAgentRuntime(streams, options);
|
|
329
|
+
try {
|
|
330
|
+
return await runner.run({
|
|
331
|
+
sessionId: randomUUID(),
|
|
332
|
+
agent,
|
|
333
|
+
userMessage: prompt,
|
|
334
|
+
metadata,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
finally {
|
|
338
|
+
// Even when the run failed: a plugin that started a browser started it
|
|
339
|
+
// before the turn could fail.
|
|
340
|
+
await disposePlugins();
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
export const printSessionSummary = (session, streams) => {
|
|
344
|
+
writeLine(streams.stdout);
|
|
345
|
+
writeLine(streams.stdout, 'Messages');
|
|
346
|
+
for (const message of session.messages) {
|
|
347
|
+
if (message.role === 'assistant' && message.toolCalls && message.toolCalls.length > 0) {
|
|
348
|
+
const calls = message.toolCalls
|
|
349
|
+
.map((call) => `${call.toolName}(${JSON.stringify(call.input)})`)
|
|
350
|
+
.join(', ');
|
|
351
|
+
const prefix = message.content ? `${message.content} ` : '';
|
|
352
|
+
writeLine(streams.stdout, `[assistant] ${prefix}→ tool call ${calls}`);
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (message.role === 'assistant' && message.content.length === 0) {
|
|
356
|
+
// A turn nobody asked for that said nothing — see `RunInput.addressed`.
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
const nameSuffix = message.name ? `:${message.name}` : '';
|
|
360
|
+
const content = message.role === 'tool' ? stringifyValue(JSON.parse(message.content)) : message.content;
|
|
361
|
+
writeLine(streams.stdout, `[${message.role}${nameSuffix}] ${content}`);
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
export const formatRuntimeBanner = (runtime) => {
|
|
365
|
+
const soulSuffix = runtime.soul ? ` as ${runtime.soul.agent.name}` : '';
|
|
366
|
+
if (runtime.provider === 'demo') {
|
|
367
|
+
return `Starting Stratus Agent local loop with provider=demo${soulSuffix}`;
|
|
368
|
+
}
|
|
369
|
+
const fallbackSuffix = runtime.fallback ? ` fallback=${runtime.fallback.model}` : '';
|
|
370
|
+
return `Starting Stratus Agent local loop with provider=${runtime.provider} model=${runtime.model}${fallbackSuffix}${soulSuffix}`;
|
|
371
|
+
};
|
|
372
|
+
//# 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":"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"}
|
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"}
|