@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
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
import { readdir, readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { agentsDirPath, defaultApiKeyEnvName, DEFAULT_STRATUS_AGENT, globalConfigPath, loadChannelCredentials, loadCredentials, loadRosterSouls, loadSoulFile, isSignedInRuntime, parseProviderName, readNonEmptyString, readProcessEnv, readWorkingDirectory, DEFAULT_CONFIG_FILENAME, loadConfigFile, resolveRuntimeConfig as resolveStateRuntimeConfig, CREDENTIAL_PROVIDER_NAMES, ignoredUntrustedConfigKeys, } from '@stratusagent/state';
|
|
4
|
+
import { readServiceCommand } from "../service.js";
|
|
5
|
+
import { serviceEnvFor } from "../daemon.js";
|
|
6
|
+
import { writeLine, pathExists } from "../io.js";
|
|
7
|
+
import { ignoredConfigRemedy } from "../runtime.js";
|
|
8
|
+
import { loadSlackAdapter } from "../loaders.js";
|
|
9
|
+
/**
|
|
10
|
+
* `stratus doctor` — what a run would resolve to right now, and which file
|
|
11
|
+
* or variable decided each part. Every "why is it using X" question needs
|
|
12
|
+
* the precedence chain, and reading it out of the source is not something
|
|
13
|
+
* anyone should have to do.
|
|
14
|
+
*/
|
|
15
|
+
export const collectDoctorReport = async (command, warn, env = {}) => {
|
|
16
|
+
const processEnv = readProcessEnv(env);
|
|
17
|
+
const cwd = readWorkingDirectory(env);
|
|
18
|
+
const problems = [];
|
|
19
|
+
// Config discovery, spelled out rather than delegated: doctor has to
|
|
20
|
+
// report the files that LOST as well as the one in use, which is the
|
|
21
|
+
// whole point when a stray project config is the answer.
|
|
22
|
+
// Which of the two named it, not just that one did: telling someone to
|
|
23
|
+
// fix STRATUS_CONFIG when --config is what is set leaves the real
|
|
24
|
+
// override in place — the same mistake as provider and key attribution,
|
|
25
|
+
// in the one place a typo is most likely.
|
|
26
|
+
const explicitSource = command.configPath !== undefined
|
|
27
|
+
? { name: '--config', value: command.configPath }
|
|
28
|
+
: readNonEmptyString(processEnv.STRATUS_CONFIG)
|
|
29
|
+
? { name: 'STRATUS_CONFIG', value: String(processEnv.STRATUS_CONFIG) }
|
|
30
|
+
: undefined;
|
|
31
|
+
const explicit = explicitSource?.value;
|
|
32
|
+
const candidates = explicitSource
|
|
33
|
+
? [{ path: path.resolve(cwd, explicitSource.value), label: explicitSource.name }]
|
|
34
|
+
: [
|
|
35
|
+
{ path: path.join(cwd, DEFAULT_CONFIG_FILENAME), label: 'project' },
|
|
36
|
+
{ path: globalConfigPath(env), label: 'global' },
|
|
37
|
+
];
|
|
38
|
+
const present = [];
|
|
39
|
+
let unreadable;
|
|
40
|
+
for (const candidate of candidates) {
|
|
41
|
+
try {
|
|
42
|
+
await readFile(candidate.path, 'utf8');
|
|
43
|
+
present.push(candidate);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const code = error.code;
|
|
47
|
+
if (code !== 'ENOENT') {
|
|
48
|
+
// resolveConfigLocation throws here rather than trying the next
|
|
49
|
+
// candidate, so discovery stops: a lower-priority file that a real
|
|
50
|
+
// run never reaches must not be reported as the config in use.
|
|
51
|
+
unreadable = candidate;
|
|
52
|
+
problems.push(`${candidate.path} exists but cannot be read (${error.message}). Every run fails here — discovery never reaches a lower-priority config.`);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
if (explicit) {
|
|
56
|
+
// Discovery treats a missing candidate as "try the next one", but
|
|
57
|
+
// an explicitly named config has no next one: a real run calls
|
|
58
|
+
// loadConfigFile on it and fails. Reporting built-in defaults here
|
|
59
|
+
// would describe a run that cannot happen, and hide the typo.
|
|
60
|
+
problems.push(`${candidate.path} does not exist, but ${candidate.label} names it — every run with this setting fails. `
|
|
61
|
+
+ 'Fix the path, or drop the setting to fall back to config discovery.');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const winner = unreadable ?? present[0];
|
|
66
|
+
const shadowed = unreadable ? [] : present.slice(1);
|
|
67
|
+
if (winner && shadowed.length > 0 && winner.label.startsWith('project')) {
|
|
68
|
+
problems.push(`${winner.path} outranks ${shadowed.map((entry) => entry.path).join(' and ')} for runs started in this directory. `
|
|
69
|
+
+ 'Run from elsewhere, or pass --config to pick one explicitly.');
|
|
70
|
+
}
|
|
71
|
+
let fileConfig = {};
|
|
72
|
+
let configFatal = unreadable !== undefined;
|
|
73
|
+
if (winner && !unreadable) {
|
|
74
|
+
try {
|
|
75
|
+
fileConfig = await loadConfigFile(winner.path);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
// resolveRuntimeConfig propagates this — no run reaches provider or
|
|
79
|
+
// credential resolution, so presenting defaults as resolved settings
|
|
80
|
+
// would describe a run that cannot happen.
|
|
81
|
+
configFatal = true;
|
|
82
|
+
problems.push(`${winner.path} could not be parsed (${error.message}). Every run fails until it is fixed or removed.`);
|
|
83
|
+
warn(`ignoring unreadable config ${winner.path}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Which variable supplied a value, not just the value: naming the wrong
|
|
87
|
+
// one sends the reader to unset something that was never the cause,
|
|
88
|
+
// leaving the real override in place.
|
|
89
|
+
const envPick = (name) => {
|
|
90
|
+
const value = readNonEmptyString(processEnv[name]);
|
|
91
|
+
return typeof value === 'string' ? { name, value } : undefined;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* The verdict comes from the resolver, not from a second copy of its
|
|
95
|
+
* rules. Everything below only *attributes* values to the file or
|
|
96
|
+
* variable that supplied them — which the resolver does not report —
|
|
97
|
+
* while whether a run works at all, and what it bills, is whatever
|
|
98
|
+
* resolveRuntimeConfig actually returns or throws.
|
|
99
|
+
*/
|
|
100
|
+
const envSoul = envPick('STRATUS_SOUL');
|
|
101
|
+
// The file's soul under the resolver's trust rule: a project-local file
|
|
102
|
+
// does not name one, so doctor must not attribute one to it.
|
|
103
|
+
const soulValue = envSoul?.value ?? (winner?.label === 'project' ? undefined : fileConfig.soul);
|
|
104
|
+
const soulSource = envSoul ? envSoul.name : (winner ? winner.path : '');
|
|
105
|
+
const soulPath = typeof soulValue === 'string' ? path.resolve(cwd, soulValue) : undefined;
|
|
106
|
+
// Loaded here for ATTRIBUTION only — the soul's frontmatter is what
|
|
107
|
+
// explains a provider nobody wrote in a config file. Whether a run works
|
|
108
|
+
// is still the resolver's verdict below.
|
|
109
|
+
const soul = soulPath ? await loadSoulFile(soulPath).catch(() => undefined) : undefined;
|
|
110
|
+
let resolved;
|
|
111
|
+
if (!configFatal) {
|
|
112
|
+
try {
|
|
113
|
+
resolved = await resolveStateRuntimeConfig(command.configPath ? { configPath: command.configPath } : {}, env);
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
117
|
+
problems.push(`No run can start: ${message}`);
|
|
118
|
+
if (soulPath && /soul/i.test(message)) {
|
|
119
|
+
// Worth saying explicitly: a soul that fails to load is fatal, not
|
|
120
|
+
// a quiet downgrade to the built-in agent.
|
|
121
|
+
problems.push(`Every run fails until ${soulPath} is fixed or the soul setting is removed — the built-in agent is not substituted.`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// A refused persona is a finding, not a silence: the file asks for a soul
|
|
126
|
+
// or a preamble, no run started here will use it, and a doctor that said
|
|
127
|
+
// "no soul configured" would be hiding the trust decision it exists to
|
|
128
|
+
// explain. The resolver's own record is the verdict — it already leaves
|
|
129
|
+
// out a key the environment outranked, which is not refused but beaten —
|
|
130
|
+
// and only when no run could resolve at all is the same rule applied
|
|
131
|
+
// here, so the finding still appears beside the failure that hid it.
|
|
132
|
+
const refusedByTrust = resolved?.ignoredFromUntrustedConfig
|
|
133
|
+
?? ignoredUntrustedConfigKeys({}, fileConfig, winner ? { path: winner.path, trusted: winner.label !== 'project' } : undefined, env);
|
|
134
|
+
if (refusedByTrust) {
|
|
135
|
+
problems.push(`${refusedByTrust.path} sets ${refusedByTrust.keys.join(' and ')}, which an auto-discovered config does not get to choose — `
|
|
136
|
+
+ `every run started here ignores ${refusedByTrust.keys.length === 1 ? 'it' : 'them'}. `
|
|
137
|
+
+ ignoredConfigRemedy(refusedByTrust, false));
|
|
138
|
+
}
|
|
139
|
+
const envProviderPick = envPick('STRATUS_PROVIDER');
|
|
140
|
+
const providerSource = envProviderPick
|
|
141
|
+
? envProviderPick.name
|
|
142
|
+
: soul?.provider
|
|
143
|
+
? `${soulPath} (soul frontmatter)`
|
|
144
|
+
: fileConfig.provider
|
|
145
|
+
? (winner?.path ?? 'config')
|
|
146
|
+
: 'built-in default — nothing set a provider';
|
|
147
|
+
// When resolution fails the intended provider is still worth reporting:
|
|
148
|
+
// "why is it anthropic" is exactly the question, and the problems below
|
|
149
|
+
// already say no run can start.
|
|
150
|
+
const intendedProvider = envProviderPick?.value ?? soul?.provider ?? fileConfig.provider ?? 'demo';
|
|
151
|
+
const provider = resolved
|
|
152
|
+
? { value: resolved.provider, source: providerSource }
|
|
153
|
+
: { value: `${intendedProvider} (unreachable)`, source: providerSource };
|
|
154
|
+
if (provider.value === 'demo') {
|
|
155
|
+
// Setup writes the config file, which is the LOWEST precedence of the
|
|
156
|
+
// three — so when an env var or a soul chose demo, "run setup" is
|
|
157
|
+
// advice that changes nothing and leaves every run on demo.
|
|
158
|
+
const fix = envProviderPick
|
|
159
|
+
? `Unset ${envProviderPick.name}; it outranks both your config and any soul.`
|
|
160
|
+
: soul?.provider === 'demo'
|
|
161
|
+
? `Change or remove the provider pin in ${soulPath}; a soul outranks the config file.`
|
|
162
|
+
: fileConfig.provider === 'demo'
|
|
163
|
+
? `Change "provider" in ${winner?.path}, or run \`stratus setup\` → Providers.`
|
|
164
|
+
: 'Run `stratus setup` → Providers and sign in, then Save & finish.';
|
|
165
|
+
problems.push(`Provider is the offline demo model, so replies are canned. ${fix}`);
|
|
166
|
+
}
|
|
167
|
+
let model;
|
|
168
|
+
if (resolved && resolved.provider !== 'demo') {
|
|
169
|
+
const envModel = envPick('STRATUS_MODEL');
|
|
170
|
+
// A soul's model belongs to the soul's provider, and the config's model
|
|
171
|
+
// to the config's provider — either can be stranded by an override.
|
|
172
|
+
// The soul's pin in resolved form, so a soul saying `ollama` matches
|
|
173
|
+
// the `plugin:ollama` the run resolved to.
|
|
174
|
+
const soulModelApplies = soul?.provider === undefined || parseProviderName(soul.provider, 'soul file') === resolved.provider;
|
|
175
|
+
const configModelApplies = (fileConfig.provider ?? 'openai') === resolved.provider;
|
|
176
|
+
model = {
|
|
177
|
+
value: resolved.model ?? 'the provider\'s own default',
|
|
178
|
+
source: envModel
|
|
179
|
+
? envModel.name
|
|
180
|
+
: soulModelApplies && soul?.model === resolved.model
|
|
181
|
+
? `${soulPath} (soul frontmatter)`
|
|
182
|
+
: configModelApplies && fileConfig.model === resolved.model
|
|
183
|
+
? (winner?.path ?? 'config')
|
|
184
|
+
: 'built-in default for this provider',
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const credentials = await loadCredentials(env);
|
|
188
|
+
const signIns = [];
|
|
189
|
+
const usedKeyEnvVar = resolved && isSignedInRuntime(resolved) ? resolved.apiKeyEnvVar : undefined;
|
|
190
|
+
const usesAuthToken = resolved?.provider === 'anthropic' && resolved.authToken !== undefined;
|
|
191
|
+
const fallback = resolved && resolved.provider !== 'demo' ? resolved.fallback : undefined;
|
|
192
|
+
for (const target of CREDENTIAL_PROVIDER_NAMES) {
|
|
193
|
+
const stored = credentials[target];
|
|
194
|
+
const label = stored?.type === 'oauth_token'
|
|
195
|
+
? (target === 'codex' ? 'ChatGPT sign-in (codex login)' : 'Claude subscription (Pro/Max)')
|
|
196
|
+
: 'API key';
|
|
197
|
+
const isDefault = resolved?.provider === target;
|
|
198
|
+
const isFallback = fallback?.provider === target;
|
|
199
|
+
// A provider no resolved run consults is reported, never diagnosed:
|
|
200
|
+
// flagging an override on a credential nothing reads is a false alarm.
|
|
201
|
+
if (!isDefault && !isFallback) {
|
|
202
|
+
signIns.push({
|
|
203
|
+
provider: target,
|
|
204
|
+
status: stored
|
|
205
|
+
? `${label} (unused — ${resolved ? resolved.provider : 'nothing'} serves your runs)`
|
|
206
|
+
: 'not signed in',
|
|
207
|
+
});
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const envVar = isDefault ? usedKeyEnvVar : defaultApiKeyEnvName(target);
|
|
211
|
+
const viaEnv = isDefault
|
|
212
|
+
? usedKeyEnvVar !== undefined
|
|
213
|
+
: fallback?.apiKey !== undefined && fallback.apiKey === readNonEmptyString(processEnv[String(envVar)]);
|
|
214
|
+
const where = isDefault ? 'runs are' : 'fallback runs are';
|
|
215
|
+
if (stored && viaEnv) {
|
|
216
|
+
signIns.push({ provider: target, status: `${label}, overridden by ${envVar} in your environment` });
|
|
217
|
+
// The costly case: an env key silently demotes a subscription to
|
|
218
|
+
// per-token billing, and nothing in a normal run says so.
|
|
219
|
+
problems.push(stored.type === 'oauth_token'
|
|
220
|
+
? `${envVar} in your environment outranks your saved ${target} subscription sign-in, so ${where} billed per token instead of through your plan. Unset it (check your shell profile) to use the subscription.`
|
|
221
|
+
: `${envVar} in your environment outranks your saved ${target} sign-in. Unset it to use the one \`stratus setup\` stored.`);
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
if (viaEnv) {
|
|
225
|
+
signIns.push({ provider: target, status: `using ${envVar} from your environment` });
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
if (stored) {
|
|
229
|
+
signIns.push({ provider: target, status: isDefault && usesAuthToken ? `${label} — runs go through the Claude Code runtime` : label });
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
signIns.push({ provider: target, status: 'not signed in' });
|
|
233
|
+
}
|
|
234
|
+
// A fallback the resolver dropped is the quiet failure: the config still
|
|
235
|
+
// names one, but a failing primary has nothing to retry on.
|
|
236
|
+
if (fileConfig.fallbackModel !== undefined && resolved && resolved.provider !== 'demo' && !fallback) {
|
|
237
|
+
problems.push(`A fallback model (${fileConfig.fallbackModel}) is configured but could not be resolved — usually no sign-in for its provider, or an endpoint its saved key is not sent to. `
|
|
238
|
+
+ 'A failing primary model has nothing to retry on.');
|
|
239
|
+
}
|
|
240
|
+
const channels = await loadChannelCredentials(env);
|
|
241
|
+
const slackAgents = Object.keys(channels.slack ?? {}).sort();
|
|
242
|
+
const slackPackageInstalled = (await loadSlackAdapter()) !== undefined;
|
|
243
|
+
if (slackAgents.length > 0 && !slackPackageInstalled) {
|
|
244
|
+
problems.push(`Slack tokens are stored for ${slackAgents.length} agent(s) but @stratusagent/channel-slack is not installed, so \`stratus serve\` skips them. `
|
|
245
|
+
+ 'Install it with: npm install -g @stratusagent/channel-slack');
|
|
246
|
+
}
|
|
247
|
+
let rosterCount = 0;
|
|
248
|
+
try {
|
|
249
|
+
rosterCount = (await readdir(agentsDirPath(env))).filter((file) => file.endsWith('.md')).length;
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
if (error.code !== 'ENOENT') {
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// Tokens keyed to an agent the roster no longer has are loaded and
|
|
257
|
+
// skipped on every start, silently.
|
|
258
|
+
let rosterEntries = [];
|
|
259
|
+
let rosterLoaded = true;
|
|
260
|
+
try {
|
|
261
|
+
rosterEntries = await loadRosterSouls(env, warn);
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
// Doctor exists to name problems, so a roster it cannot load is a
|
|
265
|
+
// finding to report — not an exception that replaces the report.
|
|
266
|
+
rosterLoaded = false;
|
|
267
|
+
problems.push(error instanceof Error ? error.message : String(error));
|
|
268
|
+
}
|
|
269
|
+
const rosterIds = new Set(rosterEntries.map((entry) => entry.soul.agent.id));
|
|
270
|
+
rosterIds.add(DEFAULT_STRATUS_AGENT.id);
|
|
271
|
+
if (soul) {
|
|
272
|
+
rosterIds.add(soul.agent.id);
|
|
273
|
+
}
|
|
274
|
+
// Only against a roster that actually loaded. "No agent has this id" is
|
|
275
|
+
// a claim about the roster, and a refused one cannot support it — every
|
|
276
|
+
// stored token would be reported as orphaned, and this advises clearing
|
|
277
|
+
// them. Advice is not deletion, but an operator who follows it loses the
|
|
278
|
+
// same credentials by hand.
|
|
279
|
+
const orphans = rosterLoaded ? slackAgents.filter((id) => !rosterIds.has(id)) : [];
|
|
280
|
+
if (orphans.length > 0) {
|
|
281
|
+
problems.push(`Slack tokens are stored for ${orphans.join(', ')}, which no agent matches — \`stratus serve\` skips them. `
|
|
282
|
+
+ 'Clear them from `stratus setup` → Channels.');
|
|
283
|
+
}
|
|
284
|
+
// The invisible failure doctor exists to surface: the service unit embeds
|
|
285
|
+
// absolute node and entrypoint paths, and upgrading node (an nvm version
|
|
286
|
+
// directory, say) leaves the unit pointing at an interpreter that no
|
|
287
|
+
// longer exists. The service stops working and nothing else says so.
|
|
288
|
+
const unitCommand = await readServiceCommand(serviceEnvFor(env));
|
|
289
|
+
if (unitCommand?.execPath !== undefined && !(await pathExists(unitCommand.execPath))) {
|
|
290
|
+
problems.push(`The service unit points at a node interpreter that no longer exists (${unitCommand.execPath}), so stratusd cannot start. `
|
|
291
|
+
+ 'Run `stratus update` (or `stratus service install`) to rewrite it with current paths.');
|
|
292
|
+
}
|
|
293
|
+
if (unitCommand?.scriptPath !== undefined && !(await pathExists(unitCommand.scriptPath))) {
|
|
294
|
+
problems.push(`The service unit points at a CLI entrypoint that no longer exists (${unitCommand.scriptPath}), so stratusd cannot start. `
|
|
295
|
+
+ 'Run `stratus update` (or `stratus service install`) to rewrite it with current paths.');
|
|
296
|
+
}
|
|
297
|
+
return {
|
|
298
|
+
...(winner ? { configInUse: winner.path } : {}),
|
|
299
|
+
configShadowed: shadowed.map((entry) => entry.path),
|
|
300
|
+
provider,
|
|
301
|
+
...(model ? { model } : {}),
|
|
302
|
+
...(soulPath ? { soul: { value: soulPath, source: soulSource } } : {}),
|
|
303
|
+
...(soul ? { agent: `${soul.agent.name} (${soul.agent.id})` } : {}),
|
|
304
|
+
...(fallback ? { fallback: { provider: fallback.provider, model: fallback.model } } : {}),
|
|
305
|
+
signIns,
|
|
306
|
+
slackAgents,
|
|
307
|
+
slackPackageInstalled,
|
|
308
|
+
rosterCount,
|
|
309
|
+
problems,
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
export const runDoctor = async (command, streams, env = {}) => {
|
|
313
|
+
const report = await collectDoctorReport(command, (message) => {
|
|
314
|
+
writeLine(streams.stderr, `Warning: ${message}.`);
|
|
315
|
+
}, env);
|
|
316
|
+
if (command.format === 'json') {
|
|
317
|
+
writeLine(streams.stdout, JSON.stringify(report, null, 2));
|
|
318
|
+
return report.problems.length > 0 ? 1 : 0;
|
|
319
|
+
}
|
|
320
|
+
const field = (label, setting) => {
|
|
321
|
+
if (!setting) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
writeLine(streams.stdout, ` ${label.padEnd(10)}${setting.value}`);
|
|
325
|
+
writeLine(streams.stdout, ` ${''.padEnd(10)}from ${setting.source}`);
|
|
326
|
+
};
|
|
327
|
+
writeLine(streams.stdout, 'Stratus Agent — what a run would use right now');
|
|
328
|
+
writeLine(streams.stdout);
|
|
329
|
+
field('provider', report.provider);
|
|
330
|
+
field('model', report.model);
|
|
331
|
+
field('soul', report.soul);
|
|
332
|
+
if (report.agent) {
|
|
333
|
+
writeLine(streams.stdout, ` ${'agent'.padEnd(10)}${report.agent}`);
|
|
334
|
+
}
|
|
335
|
+
else if (report.soul) {
|
|
336
|
+
// A soul is configured but did not load — saying "built-in" here would
|
|
337
|
+
// describe a run that cannot happen.
|
|
338
|
+
writeLine(streams.stdout, ` ${'agent'.padEnd(10)}unresolved — the configured soul could not be read`);
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
writeLine(streams.stdout, ` ${'agent'.padEnd(10)}${DEFAULT_STRATUS_AGENT.name} (built-in — no soul configured)`);
|
|
342
|
+
}
|
|
343
|
+
writeLine(streams.stdout);
|
|
344
|
+
writeLine(streams.stdout, 'Files');
|
|
345
|
+
writeLine(streams.stdout, ` config ${report.configInUse ?? 'none found — built-in defaults apply'}`);
|
|
346
|
+
for (const shadowedPath of report.configShadowed) {
|
|
347
|
+
writeLine(streams.stdout, ` (${shadowedPath} exists but is outranked)`);
|
|
348
|
+
}
|
|
349
|
+
writeLine(streams.stdout, ` agents ${report.rosterCount} soul file${report.rosterCount === 1 ? '' : 's'}`);
|
|
350
|
+
if (report.fallback) {
|
|
351
|
+
writeLine(streams.stdout, ` ${'fallback'.padEnd(10)}${report.fallback.provider} · ${report.fallback.model}`);
|
|
352
|
+
writeLine(streams.stdout, ` ${''.padEnd(10)}used when the default model errors mid-run`);
|
|
353
|
+
}
|
|
354
|
+
writeLine(streams.stdout);
|
|
355
|
+
writeLine(streams.stdout, 'Sign-ins');
|
|
356
|
+
for (const entry of report.signIns) {
|
|
357
|
+
writeLine(streams.stdout, ` ${entry.provider.padEnd(10)}${entry.status}`);
|
|
358
|
+
}
|
|
359
|
+
writeLine(streams.stdout);
|
|
360
|
+
writeLine(streams.stdout, 'Channels');
|
|
361
|
+
writeLine(streams.stdout, ` slack ${report.slackAgents.length === 0
|
|
362
|
+
? 'no agents connected'
|
|
363
|
+
: `${report.slackAgents.length} connected (${report.slackAgents.join(', ')})`}`);
|
|
364
|
+
writeLine(streams.stdout, ` @stratusagent/channel-slack ${report.slackPackageInstalled ? 'installed' : 'not installed'}`);
|
|
365
|
+
writeLine(streams.stdout);
|
|
366
|
+
if (report.problems.length === 0) {
|
|
367
|
+
writeLine(streams.stdout, 'No problems found.');
|
|
368
|
+
return 0;
|
|
369
|
+
}
|
|
370
|
+
writeLine(streams.stdout, `${report.problems.length} problem${report.problems.length === 1 ? '' : 's'} found:`);
|
|
371
|
+
for (const problem of report.problems) {
|
|
372
|
+
writeLine(streams.stdout, ` ! ${problem}`);
|
|
373
|
+
}
|
|
374
|
+
return 1;
|
|
375
|
+
};
|
|
376
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CliStreams, CliEnvironment } from '../environment.ts';
|
|
2
|
+
import type { ParsedGrantsCommand } from '../parse.ts';
|
|
3
|
+
/**
|
|
4
|
+
* `stratus grants <agent>` and `stratus grants revoke <agent> …` — the
|
|
5
|
+
* operator's view of what an agent may do unattended, and the way to take
|
|
6
|
+
* one back.
|
|
7
|
+
*
|
|
8
|
+
* Through the running daemon when one says it is serving, and only then
|
|
9
|
+
* from the files, because of the daemon's cache: the store reads each
|
|
10
|
+
* agent's file once per process, so a revoke that edited the file behind a
|
|
11
|
+
* live daemon would leave the policy honouring a grant the listing no
|
|
12
|
+
* longer shows until the next restart. Going through `POST
|
|
13
|
+
* /agents/:id/grants/revoke` is what makes a revoke the next call's answer.
|
|
14
|
+
* A daemon that `gateway.json` names but that does not answer falls back
|
|
15
|
+
* to the files with a warning saying exactly that, since the file is still
|
|
16
|
+
* the truth for the next daemon to start.
|
|
17
|
+
*/
|
|
18
|
+
export declare const runGrants: (command: ParsedGrantsCommand, streams: CliStreams, env?: CliEnvironment) => Promise<number>;
|
|
19
|
+
//# sourceMappingURL=grants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grants.d.ts","sourceRoot":"","sources":["../../src/commands/grants.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAQvD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS,GACpB,SAAS,mBAAmB,EAC5B,SAAS,UAAU,EACnB,MAAK,cAAmB,KACvB,OAAO,CAAC,MAAM,CAmHhB,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { createFileCommandWhitelist, describeAgentGrants, describeToolGrant, whitelistPathFor, } from '@stratusagent/permissions';
|
|
2
|
+
import { agentsDirPath, gatewayInfoPath } from '@stratusagent/state';
|
|
3
|
+
import { callRunningGateway, gatewayErrorMessage, readGatewayInfo } from "../daemon.js";
|
|
4
|
+
import { writeLine } from "../io.js";
|
|
5
|
+
/**
|
|
6
|
+
* `stratus grants <agent>` and `stratus grants revoke <agent> …` — the
|
|
7
|
+
* operator's view of what an agent may do unattended, and the way to take
|
|
8
|
+
* one back.
|
|
9
|
+
*
|
|
10
|
+
* Through the running daemon when one says it is serving, and only then
|
|
11
|
+
* from the files, because of the daemon's cache: the store reads each
|
|
12
|
+
* agent's file once per process, so a revoke that edited the file behind a
|
|
13
|
+
* live daemon would leave the policy honouring a grant the listing no
|
|
14
|
+
* longer shows until the next restart. Going through `POST
|
|
15
|
+
* /agents/:id/grants/revoke` is what makes a revoke the next call's answer.
|
|
16
|
+
* A daemon that `gateway.json` names but that does not answer falls back
|
|
17
|
+
* to the files with a warning saying exactly that, since the file is still
|
|
18
|
+
* the truth for the next daemon to start.
|
|
19
|
+
*/
|
|
20
|
+
export const runGrants = async (command, streams, env = {}) => {
|
|
21
|
+
const agentId = command.agentId;
|
|
22
|
+
const encoded = encodeURIComponent(agentId);
|
|
23
|
+
const base = command.gateway
|
|
24
|
+
? command.gateway.replace(/\/+$/, '')
|
|
25
|
+
: (await readGatewayInfo(env))?.url.replace(/\/+$/, '');
|
|
26
|
+
const revocation = command.action === 'revoke'
|
|
27
|
+
? command.tool !== undefined
|
|
28
|
+
? { tool: command.tool }
|
|
29
|
+
: command.scope !== undefined
|
|
30
|
+
? { scope: command.scope }
|
|
31
|
+
: { origin: command.origin ?? '' }
|
|
32
|
+
: undefined;
|
|
33
|
+
const named = revocation?.tool ?? revocation?.scope ?? revocation?.origin ?? '';
|
|
34
|
+
const fromFiles = async () => {
|
|
35
|
+
const store = createFileCommandWhitelist({
|
|
36
|
+
directory: agentsDirPath(env),
|
|
37
|
+
warn: (line) => writeLine(streams.stderr, `Warning: ${line}`),
|
|
38
|
+
});
|
|
39
|
+
if (revocation) {
|
|
40
|
+
const revoked = revocation.tool !== undefined
|
|
41
|
+
? await store.forgetTool(agentId, revocation.tool)
|
|
42
|
+
: revocation.scope !== undefined
|
|
43
|
+
? await store.forgetScope(agentId, revocation.scope)
|
|
44
|
+
: await store.forgetOrigin(agentId, revocation.origin ?? '');
|
|
45
|
+
return reportRevocation(revoked);
|
|
46
|
+
}
|
|
47
|
+
const listing = { agentId, ...describeAgentGrants(await store.grantsFor(agentId)) };
|
|
48
|
+
return render(listing, `${whitelistPathFor(agentsDirPath(env), agentId)}`);
|
|
49
|
+
};
|
|
50
|
+
const reportRevocation = (revoked) => {
|
|
51
|
+
if (!revoked) {
|
|
52
|
+
writeLine(streams.stderr, `${agentId} has no such grant. \`stratus grants ${agentId}\` lists what exists.`);
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
writeLine(streams.stdout, `Revoked ${named} for ${agentId}.`);
|
|
56
|
+
return 0;
|
|
57
|
+
};
|
|
58
|
+
const render = (listing, source) => {
|
|
59
|
+
if (command.format === 'json') {
|
|
60
|
+
writeLine(streams.stdout, JSON.stringify({ ...listing, source }, null, 2));
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
const total = listing.tools.length + listing.scopes.length + listing.origins.length;
|
|
64
|
+
if (total === 0) {
|
|
65
|
+
writeLine(streams.stdout, `${agentId} has no standing grants beyond the built-in safe list (${source}).`);
|
|
66
|
+
writeLine(streams.stdout, 'An "always allow" answered on one of its gated calls creates one.');
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
writeLine(streams.stdout, `${agentId} may do this unattended, beyond the built-in safe list (${source}):`);
|
|
70
|
+
if (listing.tools.length > 0) {
|
|
71
|
+
writeLine(streams.stdout, ' tools');
|
|
72
|
+
for (const grant of listing.tools) {
|
|
73
|
+
const by = grant.grantedBy ? ` by ${grant.grantedBy}` : '';
|
|
74
|
+
const stale = grant.stale ? ` — stale: ${grant.stale}` : '';
|
|
75
|
+
writeLine(streams.stdout, ` ${describeToolGrant(grant)} (granted ${grant.grantedAt}${by})${stale}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (listing.scopes.length > 0) {
|
|
79
|
+
writeLine(streams.stdout, ' commands');
|
|
80
|
+
for (const row of listing.scopes) {
|
|
81
|
+
writeLine(streams.stdout, ` ${row.description}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (listing.origins.length > 0) {
|
|
85
|
+
writeLine(streams.stdout, ' sites');
|
|
86
|
+
for (const row of listing.origins) {
|
|
87
|
+
writeLine(streams.stdout, ` ${row.origin}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
writeLine(streams.stdout, `Take one back: stratus grants revoke ${agentId} --tool <name> | --scope "<command>" | --origin <origin>`);
|
|
91
|
+
return 0;
|
|
92
|
+
};
|
|
93
|
+
if (!base) {
|
|
94
|
+
return fromFiles();
|
|
95
|
+
}
|
|
96
|
+
let response;
|
|
97
|
+
try {
|
|
98
|
+
response = revocation
|
|
99
|
+
? await callRunningGateway(env, command, base, `/api/v1/agents/${encoded}/grants/revoke`, revocation)
|
|
100
|
+
: await callRunningGateway(env, command, base, `/api/v1/agents/${encoded}/grants`, undefined, 'GET');
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
if (command.gateway) {
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
// Named by the file, not answering: a daemon that crashed leaves the
|
|
107
|
+
// file behind. The files are still the truth for the next one to
|
|
108
|
+
// start, so act on them — and say so, because if a daemon *is* alive
|
|
109
|
+
// behind a broken API it keeps its cached view until it restarts.
|
|
110
|
+
writeLine(streams.stderr, `Warning: ${gatewayInfoPath(env)} names a daemon at ${base}, but it did not answer `
|
|
111
|
+
+ `(${error instanceof Error ? error.message : String(error)}). `
|
|
112
|
+
+ `${revocation ? 'Revoking in' : 'Reading'} ${whitelistPathFor(agentsDirPath(env), agentId)} instead; `
|
|
113
|
+
+ 'a daemon that is running will not notice until it restarts.');
|
|
114
|
+
return fromFiles();
|
|
115
|
+
}
|
|
116
|
+
if (response.status === 404 && revocation) {
|
|
117
|
+
return reportRevocation(false);
|
|
118
|
+
}
|
|
119
|
+
if (!response.ok) {
|
|
120
|
+
writeLine(streams.stderr, `Error: ${await gatewayErrorMessage(response)}`);
|
|
121
|
+
return 1;
|
|
122
|
+
}
|
|
123
|
+
if (revocation) {
|
|
124
|
+
return reportRevocation(true);
|
|
125
|
+
}
|
|
126
|
+
return render(await response.json(), `from the daemon at ${base}`);
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=grants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grants.js","sourceRoot":"","sources":["../../src/commands/grants.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CliStreams, CliEnvironment } from '../environment.ts';
|
|
2
|
+
import type { ParsedLogsCommand } from '../parse.ts';
|
|
3
|
+
/**
|
|
4
|
+
* `stratus logs` — the daemon's structured log, filtered. `serve` streams
|
|
5
|
+
* to its own stdout, which is gone the moment it runs under a service
|
|
6
|
+
* manager; this reads the file it also writes, from any terminal.
|
|
7
|
+
*/
|
|
8
|
+
export declare const runLogs: (command: ParsedLogsCommand, streams: CliStreams, env?: CliEnvironment) => Promise<number>;
|
|
9
|
+
//# sourceMappingURL=logs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../../src/commands/logs.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,OAAO,GAClB,SAAS,iBAAiB,EAC1B,SAAS,UAAU,EACnB,MAAK,cAAmB,KACvB,OAAO,CAAC,MAAM,CAkDhB,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { logsDirPath } from '@stratusagent/state';
|
|
2
|
+
import { currentLogPosition, formatLogRecord, readRecentRecords, tailLog, } from "../logs.js";
|
|
3
|
+
import { writeLine } from "../io.js";
|
|
4
|
+
/**
|
|
5
|
+
* `stratus logs` — the daemon's structured log, filtered. `serve` streams
|
|
6
|
+
* to its own stdout, which is gone the moment it runs under a service
|
|
7
|
+
* manager; this reads the file it also writes, from any terminal.
|
|
8
|
+
*/
|
|
9
|
+
export const runLogs = async (command, streams, env = {}) => {
|
|
10
|
+
const dir = logsDirPath(env);
|
|
11
|
+
const filter = {
|
|
12
|
+
...(command.agentId ? { agentId: command.agentId } : {}),
|
|
13
|
+
...(command.sessionId ? { sessionId: command.sessionId } : {}),
|
|
14
|
+
};
|
|
15
|
+
const emit = (record) => {
|
|
16
|
+
writeLine(streams.stdout, command.format === 'json' ? JSON.stringify(record) : formatLogRecord(record));
|
|
17
|
+
};
|
|
18
|
+
// Captured BEFORE the backlog is read: the daemon keeps writing while a
|
|
19
|
+
// large backlog prints, and a follower that takes its offset afterwards
|
|
20
|
+
// skips everything written in between — permanently.
|
|
21
|
+
const followFrom = command.follow ? await currentLogPosition(dir) : undefined;
|
|
22
|
+
// Bounded by the same offset the follower resumes from: without it, a
|
|
23
|
+
// record written between the two reads is printed by the backlog and
|
|
24
|
+
// then again by the stream.
|
|
25
|
+
const recent = await readRecentRecords(dir, command.limit, filter, followFrom);
|
|
26
|
+
for (const record of recent) {
|
|
27
|
+
emit(record);
|
|
28
|
+
}
|
|
29
|
+
if (!command.follow) {
|
|
30
|
+
if (recent.length === 0 && command.format === 'text') {
|
|
31
|
+
writeLine(streams.stdout, `No log records yet in ${dir}. Start the daemon with \`stratus serve\`.`);
|
|
32
|
+
}
|
|
33
|
+
return 0;
|
|
34
|
+
}
|
|
35
|
+
const controller = new AbortController();
|
|
36
|
+
const stop = () => controller.abort();
|
|
37
|
+
process.once('SIGINT', stop);
|
|
38
|
+
process.once('SIGTERM', stop);
|
|
39
|
+
env.shutdownSignal?.addEventListener('abort', stop, { once: true });
|
|
40
|
+
if (env.shutdownSignal?.aborted) {
|
|
41
|
+
stop();
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
await tailLog({
|
|
45
|
+
dir,
|
|
46
|
+
filter,
|
|
47
|
+
...(followFrom !== undefined ? { startPosition: followFrom } : {}),
|
|
48
|
+
signal: controller.signal,
|
|
49
|
+
onRecord: emit,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
process.off('SIGINT', stop);
|
|
54
|
+
process.off('SIGTERM', stop);
|
|
55
|
+
}
|
|
56
|
+
return 0;
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=logs.js.map
|