@nocobase/app-cli-client 0.1.0-beta.2 → 0.1.0-beta.21
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/LICENSE.txt +129 -0
- package/README.md +12 -0
- package/dist/acp-service.d.ts +52 -0
- package/dist/acp-service.d.ts.map +1 -0
- package/dist/acp-service.js +329 -0
- package/dist/acp-service.js.map +1 -0
- package/dist/acp.d.ts +28 -0
- package/dist/acp.d.ts.map +1 -0
- package/dist/acp.js +414 -0
- package/dist/acp.js.map +1 -0
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +10 -0
- package/dist/commands.js.map +1 -1
- package/dist/dynamic/index.d.ts +3 -1
- package/dist/dynamic/index.d.ts.map +1 -1
- package/dist/dynamic/index.js +48 -12
- package/dist/dynamic/index.js.map +1 -1
- package/dist/dynamic/manifest.d.ts.map +1 -1
- package/dist/dynamic/manifest.js +10 -0
- package/dist/dynamic/manifest.js.map +1 -1
- package/dist/dynamic/output.d.ts +2 -2
- package/dist/dynamic/output.d.ts.map +1 -1
- package/dist/dynamic/output.js +23 -8
- package/dist/dynamic/output.js.map +1 -1
- package/dist/dynamic/rest.d.ts.map +1 -1
- package/dist/dynamic/rest.js +24 -0
- package/dist/dynamic/rest.js.map +1 -1
- package/dist/dynamic/session.d.ts +1 -0
- package/dist/dynamic/session.d.ts.map +1 -1
- package/dist/dynamic/session.js +29 -1
- package/dist/dynamic/session.js.map +1 -1
- package/dist/lib/command.d.ts.map +1 -1
- package/dist/lib/command.js +14 -4
- package/dist/lib/command.js.map +1 -1
- package/dist/lib/credentials.d.ts +2 -0
- package/dist/lib/credentials.d.ts.map +1 -1
- package/dist/lib/credentials.js +7 -3
- package/dist/lib/credentials.js.map +1 -1
- package/dist/lib/envelope.d.ts +2 -0
- package/dist/lib/envelope.d.ts.map +1 -1
- package/dist/lib/envelope.js +16 -2
- package/dist/lib/envelope.js.map +1 -1
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js +1 -0
- package/dist/lib/http.js.map +1 -1
- package/dist/parse/arguments.d.ts.map +1 -1
- package/dist/parse/arguments.js +9 -0
- package/dist/parse/arguments.js.map +1 -1
- package/dist/parse/distance.d.ts +22 -0
- package/dist/parse/distance.d.ts.map +1 -0
- package/dist/parse/distance.js +82 -0
- package/dist/parse/distance.js.map +1 -0
- package/dist/parse/manifest.d.ts +10 -0
- package/dist/parse/manifest.d.ts.map +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +36 -5
- package/dist/run.js.map +1 -1
- package/dist/skills-lock.d.ts +2 -0
- package/dist/skills-lock.d.ts.map +1 -0
- package/dist/skills-lock.js +151 -0
- package/dist/skills-lock.js.map +1 -0
- package/dist/skills.d.ts +73 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +728 -0
- package/dist/skills.js.map +1 -0
- package/dist/update.d.ts +4 -0
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +36 -1
- package/dist/update.js.map +1 -1
- package/dist/whoami.d.ts +2 -0
- package/dist/whoami.d.ts.map +1 -1
- package/dist/whoami.js +10 -3
- package/dist/whoami.js.map +1 -1
- package/package.json +6 -5
package/dist/acp.js
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
// `<bin> acp start`: connects this computer to the signed-in person's agent sessions and keeps it connected until it
|
|
2
|
+
// is stopped; `<bin> acp service install` does the same at every login, in the background (`acp-service.ts`). The
|
|
3
|
+
// bridge itself is `@nocobase/acp-bridge`; this command hands it the server, the person's credentials and the file that
|
|
4
|
+
// remembers this computer and its key for the profile, and keeps a second bridge for that profile from starting.
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
import { existsSync } from 'node:fs';
|
|
7
|
+
import { mkdir, open, readFile, rm } from 'node:fs/promises';
|
|
8
|
+
import os from 'node:os';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { Flags } from '@oclif/core';
|
|
11
|
+
import { BridgeStopped, BridgeUpgradeRequired, runBridge, } from '@nocobase/acp-bridge';
|
|
12
|
+
import { EXIT_CODES } from '@nocobase/agent-protocol';
|
|
13
|
+
import { acpServiceLoaded, acpServicePlan, capture, installAcpService, restartAcpServices, NETWORK_ENV, uninstallAcpService, } from "./acp-service.js";
|
|
14
|
+
import { currentSession } from "./dynamic/session.js";
|
|
15
|
+
import { detectInstallation } from "./install.js";
|
|
16
|
+
import { readUserConfig } from "./lib/credentials.js";
|
|
17
|
+
import { hasStudioSkill, prepareSessionSkill, sessionSkillInstructions, skillsEnvironment, } from "./skills.js";
|
|
18
|
+
import { AppCommand, UsageError } from "./lib/command.js";
|
|
19
|
+
import { successEnvelope } from "./lib/envelope.js";
|
|
20
|
+
import { globalFlags } from "./lib/globals.js";
|
|
21
|
+
import { updateCli, updateEnvironment, } from "./update.js";
|
|
22
|
+
export function acpCommands(app) {
|
|
23
|
+
const placeFlags = {
|
|
24
|
+
name: Flags.string({
|
|
25
|
+
description: "The computer's name in the application; its host name by default.",
|
|
26
|
+
}),
|
|
27
|
+
root: Flags.string({
|
|
28
|
+
description: 'A directory sessions may work in; repeat for several. Your home directory by default.',
|
|
29
|
+
multiple: true,
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
/** The signed-in person, or a usage error saying to sign in. */
|
|
33
|
+
async function signedIn() {
|
|
34
|
+
const session = await currentSession();
|
|
35
|
+
if (session?.kind !== 'user') {
|
|
36
|
+
throw new UsageError(session
|
|
37
|
+
? "An agent's run cannot connect a computer. Run this outside the run's working directory."
|
|
38
|
+
: `Not signed in. Run \`${app.bin} login\` first.`, EXIT_CODES.auth);
|
|
39
|
+
}
|
|
40
|
+
return session;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The service for the current profile, starting the CLI as it was started now (`root` is its package's); `hidden`
|
|
44
|
+
* leaves the values of the variables written into it out, for printing.
|
|
45
|
+
*/
|
|
46
|
+
function servicePlan(root, home, flags, hidden = false) {
|
|
47
|
+
const profile = globalFlags().profile;
|
|
48
|
+
const prefix = app.envPrefix;
|
|
49
|
+
const env = {
|
|
50
|
+
PATH: process.env.PATH ?? '/usr/local/bin:/usr/bin:/bin',
|
|
51
|
+
...capture(process.env, [
|
|
52
|
+
...(app.homeEnv ? [app.homeEnv] : []),
|
|
53
|
+
...(app.keychainEnv ? [app.keychainEnv] : []),
|
|
54
|
+
...(prefix
|
|
55
|
+
? [`${prefix}_SERVER`, `${prefix}_API_KEY`, `${prefix}_PROFILE`]
|
|
56
|
+
: []),
|
|
57
|
+
...NETWORK_ENV,
|
|
58
|
+
...(flags['pass-env'] ?? []),
|
|
59
|
+
]),
|
|
60
|
+
};
|
|
61
|
+
return acpServicePlan({
|
|
62
|
+
bin: app.bin,
|
|
63
|
+
command: selfCommand(root),
|
|
64
|
+
args: [
|
|
65
|
+
...(profile ? ['--profile', profile] : []),
|
|
66
|
+
...(flags.name ? ['--name', flags.name] : []),
|
|
67
|
+
...(flags.root ?? []).flatMap((root) => [
|
|
68
|
+
'--root',
|
|
69
|
+
path.resolve(expandHome(root)),
|
|
70
|
+
]),
|
|
71
|
+
],
|
|
72
|
+
log: path.join(home, 'acp', 'service.log'),
|
|
73
|
+
env: hidden
|
|
74
|
+
? Object.fromEntries(Object.keys(env).map((name) => [name, '<hidden>']))
|
|
75
|
+
: env,
|
|
76
|
+
profile,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
'acp:start': class AcpStart extends AppCommand {
|
|
81
|
+
static summary = 'Run your agent sessions on this computer.';
|
|
82
|
+
static description = `Connects this computer to ${app.displayName} as the signed-in person, so the sessions you start there run ` +
|
|
83
|
+
'here with the coding agents installed here, in the directories you allow. It stays connected until you stop it ' +
|
|
84
|
+
`with Ctrl+C; stopping it stops the agents it started. To keep it running in the background from every login, ` +
|
|
85
|
+
`run \`${app.bin} acp service install\` instead.`;
|
|
86
|
+
static examples = [
|
|
87
|
+
`${app.bin} acp start`,
|
|
88
|
+
`${app.bin} acp start --name "Work laptop" --root ~/code`,
|
|
89
|
+
];
|
|
90
|
+
static flags = {
|
|
91
|
+
...placeFlags,
|
|
92
|
+
service: Flags.boolean({
|
|
93
|
+
description: 'Run as the background service does: stop for good when the application no longer accepts this computer.',
|
|
94
|
+
hidden: true,
|
|
95
|
+
}),
|
|
96
|
+
};
|
|
97
|
+
async run() {
|
|
98
|
+
const { flags } = await this.parse(AcpStart);
|
|
99
|
+
const session = await signedIn();
|
|
100
|
+
const profile = session.profile;
|
|
101
|
+
if (!profile)
|
|
102
|
+
throw new UsageError(`Agent sessions require a signed-in profile. Run \`${app.bin} login\` first.`, EXIT_CODES.auth);
|
|
103
|
+
const stateFile = stateFileOf(this.paths.home, session);
|
|
104
|
+
const release = await holdLock(`${stateFile}.lock`, app.bin);
|
|
105
|
+
const stop = new AbortController();
|
|
106
|
+
const onSignal = () => stop.abort();
|
|
107
|
+
process.once('SIGINT', onSignal);
|
|
108
|
+
process.once('SIGTERM', onSignal);
|
|
109
|
+
const log = (message) => this.log(flags.service ? `${timestamp()} ${message}` : message);
|
|
110
|
+
try {
|
|
111
|
+
await runBridge({
|
|
112
|
+
sessionInstructions: (agentId) => sessionSkillInstructions(skillsEnvironment(app), agentId),
|
|
113
|
+
prepareSession: async (agentId, sessionId) => {
|
|
114
|
+
if (!hasStudioSkill(app) || !app.envPrefix)
|
|
115
|
+
throw new Error('This CLI does not ship the nb-studio-cli Skill required by agent sessions. Update the CLI.');
|
|
116
|
+
const user = await readUserConfig({
|
|
117
|
+
paths: this.paths,
|
|
118
|
+
config: app,
|
|
119
|
+
profile,
|
|
120
|
+
profileOnly: true,
|
|
121
|
+
});
|
|
122
|
+
if (!user || user.server !== session.server)
|
|
123
|
+
throw new Error('The bridge-selected profile is no longer available for this server. Sign in and restart the bridge.');
|
|
124
|
+
await prepareSessionSkill(skillsEnvironment(app), agentId);
|
|
125
|
+
return {
|
|
126
|
+
[`${app.envPrefix}_PROFILE`]: profile,
|
|
127
|
+
[`${app.envPrefix}_AGENT_SESSION`]: sessionId,
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
server: session.server,
|
|
131
|
+
headers: session.headers,
|
|
132
|
+
client: { name: app.bin, version: this.config.version },
|
|
133
|
+
stateFile,
|
|
134
|
+
...(flags.name ? { name: flags.name } : {}),
|
|
135
|
+
...(flags.root
|
|
136
|
+
? {
|
|
137
|
+
roots: flags.root.map((root) => path.resolve(expandHome(root))),
|
|
138
|
+
}
|
|
139
|
+
: {}),
|
|
140
|
+
reconnect: !flags.service,
|
|
141
|
+
signal: stop.signal,
|
|
142
|
+
log,
|
|
143
|
+
});
|
|
144
|
+
this.log('Disconnected.');
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
if (error instanceof BridgeUpgradeRequired) {
|
|
148
|
+
log(error.message);
|
|
149
|
+
const environment = updateEnvironment(app);
|
|
150
|
+
const outcome = await updateRefusedBridge({
|
|
151
|
+
bin: app.bin,
|
|
152
|
+
refusal: error,
|
|
153
|
+
update: environment && (() => updateCli(session, environment, { log })),
|
|
154
|
+
});
|
|
155
|
+
// Never 0: the service manager starts the bridge again, on the new version or to try again.
|
|
156
|
+
if (outcome.updated)
|
|
157
|
+
throw new UsageError(flags.service
|
|
158
|
+
? `Updated ${app.bin} to ${outcome.version}; the service starts the bridge again on it.`
|
|
159
|
+
: `Updated ${app.bin} to ${outcome.version}; run \`${app.bin} acp start\` again.`, EXIT_CODES.general);
|
|
160
|
+
if (flags.service)
|
|
161
|
+
await pause(UPGRADE_RETRY_MS, stop.signal);
|
|
162
|
+
throw new UsageError(outcome.reason, EXIT_CODES.general);
|
|
163
|
+
}
|
|
164
|
+
if (!(error instanceof BridgeStopped))
|
|
165
|
+
throw error;
|
|
166
|
+
// The service stops for good, exiting 0, rather than being started again to be refused again.
|
|
167
|
+
if (flags.service) {
|
|
168
|
+
this.log(`${timestamp()} ${error.message}`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
throw new UsageError(error.message, EXIT_CODES.auth);
|
|
172
|
+
}
|
|
173
|
+
finally {
|
|
174
|
+
process.off('SIGINT', onSignal);
|
|
175
|
+
process.off('SIGTERM', onSignal);
|
|
176
|
+
await release();
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
'acp:service:install': class AcpServiceInstall extends AppCommand {
|
|
181
|
+
static summary = 'Keep this computer connected in the background, from every login.';
|
|
182
|
+
static description = `Installs \`${app.bin} acp start\` as a service of your user: a launchd agent on macOS, a systemd user unit on ` +
|
|
183
|
+
'Linux, a script in the Startup folder on Windows. It starts now and at every login, and again when it fails. ' +
|
|
184
|
+
"A service does not read your shell configuration, so this shell's PATH (where the agents are found), proxy and " +
|
|
185
|
+
'CA variables and the --pass-env names are written into it with their values now; install again after ' +
|
|
186
|
+
'changing one, or after installing an agent somewhere new.';
|
|
187
|
+
static supportsDryRun = true;
|
|
188
|
+
static examples = [
|
|
189
|
+
`${app.bin} acp service install`,
|
|
190
|
+
`${app.bin} acp service install --root ~/code --pass-env ANTHROPIC_API_KEY`,
|
|
191
|
+
];
|
|
192
|
+
static flags = {
|
|
193
|
+
...placeFlags,
|
|
194
|
+
'pass-env': Flags.string({
|
|
195
|
+
description: 'An environment variable the agents need, such as an API key kept in your shell; repeat for several.',
|
|
196
|
+
multiple: true,
|
|
197
|
+
}),
|
|
198
|
+
};
|
|
199
|
+
async run() {
|
|
200
|
+
const { flags } = await this.parse(AcpServiceInstall);
|
|
201
|
+
const session = await signedIn();
|
|
202
|
+
const plan = servicePlan(this.config.root, this.paths.home, flags);
|
|
203
|
+
if (this.dryRun) {
|
|
204
|
+
this.log(`# ${plan.file}`);
|
|
205
|
+
this.log(servicePlan(this.config.root, this.paths.home, flags, true).content);
|
|
206
|
+
return { file: plan.file, installed: false };
|
|
207
|
+
}
|
|
208
|
+
const lock = `${stateFileOf(this.paths.home, session)}.lock`;
|
|
209
|
+
const running = await lockHolder(lock);
|
|
210
|
+
if (running !== undefined && !(await acpServiceLoaded(plan)))
|
|
211
|
+
throw new UsageError(`This computer is already connected by \`${app.bin} acp start\` (process ${running}). Stop it first, then install the service.`);
|
|
212
|
+
if (plan.platform === 'startup')
|
|
213
|
+
await stopHolder(lock);
|
|
214
|
+
await installAcpService(plan);
|
|
215
|
+
this.log(`Installed ${plan.file}: this computer stays connected from every login.`);
|
|
216
|
+
if (plan.platform === 'systemd')
|
|
217
|
+
this.log('A user service stops when you log out; to keep it running then, run `loginctl enable-linger`.');
|
|
218
|
+
this.log(`See how it runs with \`${app.bin} acp service status\`; stop it with \`${app.bin} acp service uninstall\`.`);
|
|
219
|
+
return { file: plan.file, installed: true };
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
'acp:service:restart': class AcpServiceRestart extends AppCommand {
|
|
223
|
+
warnings = [];
|
|
224
|
+
toSuccessJson(result) {
|
|
225
|
+
return successEnvelope(this.commandName, result, this.warnings);
|
|
226
|
+
}
|
|
227
|
+
static summary = 'Restart running background connections for all profiles.';
|
|
228
|
+
static description = 'Restarts installed, running ACP services on macOS and Linux using their saved environment. Stopped services are left stopped.';
|
|
229
|
+
async run() {
|
|
230
|
+
await this.parse(AcpServiceRestart);
|
|
231
|
+
const result = await restartAcpServices(app.bin);
|
|
232
|
+
this.warnings = result.warnings;
|
|
233
|
+
for (const label of result.restarted)
|
|
234
|
+
this.log(`Restarted ${label}.`);
|
|
235
|
+
for (const warning of result.warnings)
|
|
236
|
+
this.warn(warning);
|
|
237
|
+
return { restarted: result.restarted };
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
'acp:service:uninstall': class AcpServiceUninstall extends AppCommand {
|
|
241
|
+
static summary = 'Stop keeping this computer connected in the background.';
|
|
242
|
+
static description = 'Stops the service `acp service install` installed and removes it. The computer stays in the application, offline, until you remove it there or connect it again.';
|
|
243
|
+
async run() {
|
|
244
|
+
const plan = servicePlan(this.config.root, this.paths.home, {});
|
|
245
|
+
await uninstallAcpService(plan);
|
|
246
|
+
const session = await currentSession();
|
|
247
|
+
// On Windows the file only starts the bridge; the bridge running now is stopped here.
|
|
248
|
+
if (plan.platform === 'startup' && session?.kind === 'user')
|
|
249
|
+
await stopHolder(`${stateFileOf(this.paths.home, session)}.lock`);
|
|
250
|
+
this.log(`Removed ${plan.file}.`);
|
|
251
|
+
return { file: plan.file };
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
'acp:service:status': class AcpServiceStatus extends AppCommand {
|
|
255
|
+
static summary = 'Show whether this computer is connected in the background.';
|
|
256
|
+
async run() {
|
|
257
|
+
const plan = servicePlan(this.config.root, this.paths.home, {});
|
|
258
|
+
const session = await currentSession();
|
|
259
|
+
const installed = existsSync(plan.file);
|
|
260
|
+
const holder = session?.kind === 'user'
|
|
261
|
+
? await lockHolder(`${stateFileOf(this.paths.home, session)}.lock`)
|
|
262
|
+
: undefined;
|
|
263
|
+
const loaded = installed ? await acpServiceLoaded(plan) : false;
|
|
264
|
+
const log = path.join(this.paths.home, 'acp', 'service.log');
|
|
265
|
+
this.log(installed
|
|
266
|
+
? `Installed: ${plan.file}${loaded === false ? ' (not loaded)' : ''}`
|
|
267
|
+
: `Not installed. Install it with \`${app.bin} acp service install\`.`);
|
|
268
|
+
this.log(holder === undefined
|
|
269
|
+
? 'Not connected now.'
|
|
270
|
+
: `Connected now (process ${holder}).`);
|
|
271
|
+
if (plan.platform === 'systemd')
|
|
272
|
+
this.log(`Its output: journalctl --user -u ${plan.label}`);
|
|
273
|
+
else
|
|
274
|
+
this.log(`Its output: ${log}`);
|
|
275
|
+
return {
|
|
276
|
+
installed,
|
|
277
|
+
running: holder !== undefined,
|
|
278
|
+
file: plan.file,
|
|
279
|
+
log,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* How long the service waits, after the application refused its bridge and no update helped, before exiting for its
|
|
287
|
+
* service manager to start it again: it tries again then, without asking every few seconds.
|
|
288
|
+
*/
|
|
289
|
+
export const UPGRADE_RETRY_MS = 5 * 60_000;
|
|
290
|
+
/**
|
|
291
|
+
* After the application refused the bridge's protocol: updates the CLI as `<bin> update` does (`update`; undefined
|
|
292
|
+
* when this CLI does not update itself) when the bridge is the older side, and says why not otherwise.
|
|
293
|
+
*/
|
|
294
|
+
export async function updateRefusedBridge(options) {
|
|
295
|
+
const { bin, refusal, update } = options;
|
|
296
|
+
const needs = refusal.protocol === undefined
|
|
297
|
+
? ''
|
|
298
|
+
: `, the application ${refusal.protocol}`;
|
|
299
|
+
if (!refusal.bridgeIsOlder)
|
|
300
|
+
return {
|
|
301
|
+
updated: false,
|
|
302
|
+
reason: `This ${bin} speaks bridge protocol ${refusal.bridgeProtocol}, newer than the application (${refusal.protocol}): the application has to be updated.`,
|
|
303
|
+
};
|
|
304
|
+
if (update === undefined)
|
|
305
|
+
return {
|
|
306
|
+
updated: false,
|
|
307
|
+
reason: `This ${bin} does not update itself; update it the way it was installed (bridge protocol ${refusal.bridgeProtocol}${needs}).`,
|
|
308
|
+
};
|
|
309
|
+
try {
|
|
310
|
+
const result = await update();
|
|
311
|
+
if (result.updated)
|
|
312
|
+
return { updated: true, version: result.latest };
|
|
313
|
+
return {
|
|
314
|
+
updated: false,
|
|
315
|
+
reason: `${bin} ${result.current} is the newest the application serves, and it speaks bridge protocol ${refusal.bridgeProtocol}${needs}. Install the ${bin} the application expects.`,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
return {
|
|
320
|
+
updated: false,
|
|
321
|
+
reason: `Could not update ${bin}: ${error instanceof Error ? error.message : String(error)} Run \`${bin} update\`.`,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function pause(ms, signal) {
|
|
326
|
+
return new Promise((resolve) => {
|
|
327
|
+
const timer = setTimeout(done, ms);
|
|
328
|
+
function done() {
|
|
329
|
+
clearTimeout(timer);
|
|
330
|
+
signal.removeEventListener('abort', done);
|
|
331
|
+
resolve();
|
|
332
|
+
}
|
|
333
|
+
signal.addEventListener('abort', done, { once: true });
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
/** Where the bridge remembers this computer and its key, for the profile and server. */
|
|
337
|
+
function stateFileOf(home, session) {
|
|
338
|
+
return path.join(home, 'acp', `${createHash('sha256').update(session.cacheKey).update(session.server).digest('hex').slice(0, 16)}.json`);
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Makes this process the one running the bridge for the state file `lock` stands beside, or refuses when another
|
|
342
|
+
* running process is; answers what lets go of it.
|
|
343
|
+
*/
|
|
344
|
+
async function holdLock(lock, bin) {
|
|
345
|
+
await mkdir(path.dirname(lock), { recursive: true, mode: 0o700 });
|
|
346
|
+
for (;;) {
|
|
347
|
+
try {
|
|
348
|
+
const handle = await open(lock, 'wx', 0o600);
|
|
349
|
+
await handle.writeFile(String(process.pid));
|
|
350
|
+
await handle.close();
|
|
351
|
+
return () => rm(lock, { force: true });
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
if (error.code !== 'EEXIST')
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
const holder = await lockHolder(lock);
|
|
358
|
+
if (holder !== undefined)
|
|
359
|
+
throw new UsageError(`This computer is already connected (process ${holder}), in a terminal or by the background service (\`${bin} acp service status\`).`);
|
|
360
|
+
// Left behind by a bridge that did not stop cleanly.
|
|
361
|
+
await rm(lock, { force: true });
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/** The running process holding `lock`, if any. */
|
|
365
|
+
async function lockHolder(lock) {
|
|
366
|
+
const pid = Number(await readFile(lock, 'utf8').catch(() => ''));
|
|
367
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
368
|
+
return undefined;
|
|
369
|
+
try {
|
|
370
|
+
process.kill(pid, 0);
|
|
371
|
+
return pid;
|
|
372
|
+
}
|
|
373
|
+
catch (error) {
|
|
374
|
+
return error.code === 'EPERM' ? pid : undefined;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
/** Stops the bridge holding `lock`, with what it started. */
|
|
378
|
+
async function stopHolder(lock) {
|
|
379
|
+
const pid = await lockHolder(lock);
|
|
380
|
+
if (pid === undefined)
|
|
381
|
+
return;
|
|
382
|
+
if (process.platform === 'win32') {
|
|
383
|
+
const { execFile } = await import('node:child_process');
|
|
384
|
+
await new Promise((resolve) => {
|
|
385
|
+
execFile('taskkill', ['/pid', String(pid), '/T', '/F'], { windowsHide: true }, () => resolve());
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
else
|
|
389
|
+
process.kill(pid, 'SIGTERM');
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* How a service starts this CLI: this Node and this entry, through `<prefix>/current` when the CLI was installed by
|
|
393
|
+
* the application's install script, so that the service runs whichever version an update made current.
|
|
394
|
+
*/
|
|
395
|
+
function selfCommand(root) {
|
|
396
|
+
const installation = detectInstallation(root);
|
|
397
|
+
const throughCurrent = (file) => installation && file.startsWith(installation.versionDir)
|
|
398
|
+
? path.join(installation.current, file.slice(installation.versionDir.length))
|
|
399
|
+
: file;
|
|
400
|
+
return [
|
|
401
|
+
throughCurrent(process.execPath),
|
|
402
|
+
...process.execArgv,
|
|
403
|
+
throughCurrent(process.argv[1] ?? ''),
|
|
404
|
+
];
|
|
405
|
+
}
|
|
406
|
+
function timestamp() {
|
|
407
|
+
return new Date().toISOString();
|
|
408
|
+
}
|
|
409
|
+
function expandHome(dir) {
|
|
410
|
+
return dir === '~' || dir.startsWith('~/') || dir.startsWith('~\\')
|
|
411
|
+
? path.join(os.homedir(), dir.slice(1))
|
|
412
|
+
: dir;
|
|
413
|
+
}
|
|
414
|
+
//# sourceMappingURL=acp.js.map
|
package/dist/acp.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp.js","sourceRoot":"","sources":["../src/acp.ts"],"names":[],"mappings":"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"}
|
package/dist/commands.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAShD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAM,CAAC;AAE1D,mDAAmD;AACnD,eAAO,MAAM,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC,CAWzE,CAAC;AAEJ,wBAAgB,cAAc,CAC5B,MAAM,EAAE,YAAY,EACpB,KAAK,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAM,GAClD,IAAI,CAmBN"}
|
package/dist/commands.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { acpCommands } from "./acp.js";
|
|
1
2
|
import { completionCommands } from "./completion.js";
|
|
2
3
|
import { docsCommand } from "./docs.js";
|
|
3
4
|
import { loginCommand } from "./login.js";
|
|
4
5
|
import { logoutCommand } from "./logout.js";
|
|
5
6
|
import { profileCommands } from "./profile.js";
|
|
7
|
+
import { hasStudioSkill, skillsCommands } from "./skills.js";
|
|
6
8
|
import { updateCommand } from "./update.js";
|
|
7
9
|
import { whoamiCommand } from "./whoami.js";
|
|
8
10
|
export const COMMANDS = {};
|
|
@@ -11,6 +13,12 @@ export const STATIC_TOPICS = {
|
|
|
11
13
|
profile: {
|
|
12
14
|
description: 'The servers you are signed in to, one profile each.',
|
|
13
15
|
},
|
|
16
|
+
acp: {
|
|
17
|
+
description: 'Run your agent sessions on this computer.',
|
|
18
|
+
},
|
|
19
|
+
'acp:service': {
|
|
20
|
+
description: 'Keep this computer connected in the background.',
|
|
21
|
+
},
|
|
14
22
|
};
|
|
15
23
|
export function defineCommands(config, extra = {}) {
|
|
16
24
|
for (const key of Object.keys(COMMANDS))
|
|
@@ -22,6 +30,8 @@ export function defineCommands(config, extra = {}) {
|
|
|
22
30
|
docs: docsCommand(config),
|
|
23
31
|
...profileCommands(config),
|
|
24
32
|
...completionCommands(config),
|
|
33
|
+
...(hasStudioSkill(config) ? skillsCommands(config) : {}),
|
|
34
|
+
...acpCommands(config),
|
|
25
35
|
...(config.selfUpdate === undefined
|
|
26
36
|
? {}
|
|
27
37
|
: { update: updateCommand(config) }),
|
package/dist/commands.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,MAAM,QAAQ,GAAkC,EAAE,CAAC;AAE1D,mDAAmD;AACnD,MAAM,CAAC,MAAM,aAAa,GACxB;IACE,OAAO,EAAE;QACP,WAAW,EAAE,qDAAqD;KACnE;CACF,CAAC;AAEJ,MAAM,UAAU,cAAc,CAC5B,MAAoB,EACpB,QAAiD,EAAE;IAEnD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9D,MAAM,CAAC,MAAM,CACX,QAAQ,EACR;QACE,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;QAC3B,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;QAC7B,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;QAC7B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;QACzB,GAAG,eAAe,CAAC,MAAM,CAAC;QAC1B,GAAG,kBAAkB,CAAC,MAAM,CAAC;QAC7B,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS;YACjC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;KACvC,EACD,KAAK,CACN,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,CAAC,MAAM,QAAQ,GAAkC,EAAE,CAAC;AAE1D,mDAAmD;AACnD,MAAM,CAAC,MAAM,aAAa,GACxB;IACE,OAAO,EAAE;QACP,WAAW,EAAE,qDAAqD;KACnE;IACD,GAAG,EAAE;QACH,WAAW,EAAE,2CAA2C;KACzD;IACD,aAAa,EAAE;QACb,WAAW,EAAE,iDAAiD;KAC/D;CACF,CAAC;AAEJ,MAAM,UAAU,cAAc,CAC5B,MAAoB,EACpB,QAAiD,EAAE;IAEnD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9D,MAAM,CAAC,MAAM,CACX,QAAQ,EACR;QACE,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC;QAC3B,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;QAC7B,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;QAC7B,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC;QACzB,GAAG,eAAe,CAAC,MAAM,CAAC;QAC1B,GAAG,kBAAkB,CAAC,MAAM,CAAC;QAC7B,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,WAAW,CAAC,MAAM,CAAC;QACtB,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS;YACjC,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;KACvC,EACD,KAAK,CACN,CAAC;AACJ,CAAC"}
|
package/dist/dynamic/index.d.ts
CHANGED
|
@@ -2,8 +2,10 @@ import { CliCommandError } from '../lib/envelope.ts';
|
|
|
2
2
|
import { type CliCommand, type CliManifest } from './manifest.ts';
|
|
3
3
|
import { type Session } from './session.ts';
|
|
4
4
|
/** Records the argv the CLI was started with (`runAppCli`). */
|
|
5
|
-
export declare function setOriginalArgv(argv: readonly string[]): void;
|
|
5
|
+
export declare function setOriginalArgv(argv: readonly string[], commandIds?: readonly string[]): void;
|
|
6
6
|
export declare function getOriginalArgv(): readonly string[];
|
|
7
|
+
/** Uses the development CLI's matching strategy, over offered commands only. */
|
|
8
|
+
export declare function unknownCommandError(manifest: Pick<CliManifest, 'commands'>, argv: readonly string[], hint?: string): CliCommandError;
|
|
7
9
|
/**
|
|
8
10
|
* Why a command the line names is not offered, when the server describes it: another identity's, or needing an
|
|
9
11
|
* action the caller does not hold. Undefined when the server knows no such command.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dynamic/index.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,eAAe,EAGhB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAgB,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAIhF,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dynamic/index.ts"],"names":[],"mappings":"AAaA,OAAO,EACL,eAAe,EAGhB,MAAM,oBAAoB,CAAC;AAI5B,OAAO,EAAgB,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAIhF,OAAO,EAAkB,KAAK,OAAO,EAAE,MAAM,cAAc,CAAC;AAa5D,+DAA+D;AAC/D,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,UAAU,GAAE,SAAS,MAAM,EAAO,GACjC,IAAI,CAGN;AAED,wBAAgB,eAAe,IAAI,SAAS,MAAM,EAAE,CAEnD;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EACvC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,CAAC,EAAE,MAAM,GACZ,eAAe,CAgDjB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,eAAe,GAAG,SAAS,CA8C7B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;CAChC;AAED,iGAAiG;AACjG,wBAAsB,WAAW,CAC/B,OAAO,GAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3C,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAIrC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,QAAQ,GAAG,SAAS,CAUtB;AAED,mGAAmG;AACnG,wBAAgB,WAAW,CACzB,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,MAAM,GAAG,SAAS,CAIpB;AA2BD,iGAAiG;AACjG,wBAAsB,UAAU,CAC9B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,KAAK,GAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAkD,GAC1E,OAAO,CAAC,IAAI,CAAC,CAwCf"}
|
package/dist/dynamic/index.js
CHANGED
|
@@ -18,18 +18,59 @@ import { renderAnswer, renderCommandHelp, renderTopicHelp } from "./output.js";
|
|
|
18
18
|
import { leadingWords } from "./parse.js";
|
|
19
19
|
import { executeRest, parseRestCall } from "./rest.js";
|
|
20
20
|
import { currentSession } from "./session.js";
|
|
21
|
+
import { closestMatches, editDistance, matchDistance, nearest, typoAllowance, } from "../parse/distance.js";
|
|
21
22
|
let originalArgv;
|
|
23
|
+
let staticCommandIds = [];
|
|
22
24
|
/** Records the argv the CLI was started with (`runAppCli`). */
|
|
23
|
-
export function setOriginalArgv(argv) {
|
|
25
|
+
export function setOriginalArgv(argv, commandIds = []) {
|
|
24
26
|
originalArgv = [...argv];
|
|
27
|
+
staticCommandIds = [...commandIds];
|
|
25
28
|
}
|
|
26
29
|
export function getOriginalArgv() {
|
|
27
30
|
return originalArgv ?? process.argv.slice(2);
|
|
28
31
|
}
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
/** Uses the development CLI's matching strategy, over offered commands only. */
|
|
33
|
+
export function unknownCommandError(manifest, argv, hint) {
|
|
34
|
+
const typed = leadingWords(argv);
|
|
35
|
+
const scored = [];
|
|
36
|
+
const ids = [
|
|
37
|
+
...staticCommandIds,
|
|
38
|
+
...manifest.commands.map((command) => command.id),
|
|
39
|
+
];
|
|
40
|
+
for (const id of ids) {
|
|
41
|
+
const words = id.split(':');
|
|
42
|
+
const input = typed.slice(0, words.length).join(' ');
|
|
43
|
+
const candidate = words.join(' ');
|
|
44
|
+
const distance = input === typed.join(' ')
|
|
45
|
+
? matchDistance(input, candidate)
|
|
46
|
+
: editDistance(input, candidate);
|
|
47
|
+
if (distance !== undefined &&
|
|
48
|
+
(input === typed.join(' ') || distance <= typoAllowance(input)))
|
|
49
|
+
scored.push({ candidate, distance });
|
|
50
|
+
}
|
|
31
51
|
const { bin } = appCliConfig();
|
|
32
|
-
|
|
52
|
+
const matches = nearest(scored);
|
|
53
|
+
const topics = [...new Set(ids.map((id) => id.split(':')[0]))];
|
|
54
|
+
const suggestions = matches.map((candidate) => ({
|
|
55
|
+
message: `Did you mean ${candidate}?`,
|
|
56
|
+
run: { command: bin, args: [...candidate.split(' '), '--help'] },
|
|
57
|
+
}));
|
|
58
|
+
if (suggestions.length === 0 && typed[0])
|
|
59
|
+
for (const topic of closestMatches(typed[0], topics))
|
|
60
|
+
suggestions.push({
|
|
61
|
+
message: `See the ${topic} commands.`,
|
|
62
|
+
run: { command: bin, args: [topic, '--help'] },
|
|
63
|
+
});
|
|
64
|
+
return new CliCommandError('INVALID_USAGE', `Unknown command: ${bin} ${typed.join(' ')}.${hint ? ` ${hint}` : ''}`, {
|
|
65
|
+
exit: EXIT_CODES.notFound,
|
|
66
|
+
suggestions: [
|
|
67
|
+
...suggestions,
|
|
68
|
+
{
|
|
69
|
+
message: 'List available commands.',
|
|
70
|
+
run: { command: bin, args: ['--help'] },
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
});
|
|
33
74
|
}
|
|
34
75
|
/**
|
|
35
76
|
* Why a command the line names is not offered, when the server describes it: another identity's, or needing an
|
|
@@ -139,10 +180,8 @@ export async function runDynamic(argv, write = (text) => process.stdout.write(`$
|
|
|
139
180
|
throw fail(error);
|
|
140
181
|
}
|
|
141
182
|
if (!context) {
|
|
142
|
-
const error =
|
|
143
|
-
throw
|
|
144
|
-
? fail(new UsageError(error.message, EXIT_CODES.notFound))
|
|
145
|
-
: error;
|
|
183
|
+
const error = unknownCommandError({ commands: [] }, argv, `Business commands need a run, or \`${appCliConfig().bin} login\` first.`);
|
|
184
|
+
throw fail(error);
|
|
146
185
|
}
|
|
147
186
|
// A person's command asks whether a newer CLI is served, and says so after its own output.
|
|
148
187
|
const hint = context.session.kind === 'user'
|
|
@@ -168,10 +207,7 @@ async function runContext(context, argv, json, write, fail) {
|
|
|
168
207
|
const withheld = withheldCommand(context.manifest, argv);
|
|
169
208
|
if (withheld)
|
|
170
209
|
throw fail(withheld);
|
|
171
|
-
|
|
172
|
-
throw json
|
|
173
|
-
? fail(new UsageError(error.message, EXIT_CODES.notFound))
|
|
174
|
-
: error;
|
|
210
|
+
throw fail(unknownCommandError(context.manifest, argv));
|
|
175
211
|
}
|
|
176
212
|
const name = resolved.command.id.split(':').join(' ');
|
|
177
213
|
try {
|