@nocobase/app-cli-client 0.1.0-beta.1 → 0.1.0-beta.10
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 +13 -1
- package/dist/acp-service.d.ts +39 -0
- package/dist/acp-service.d.ts.map +1 -0
- package/dist/acp-service.js +257 -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 +395 -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/install.d.ts +75 -5
- package/dist/install.d.ts.map +1 -1
- package/dist/install.js +256 -13
- package/dist/install.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.d.ts +60 -0
- package/dist/skills.d.ts.map +1 -0
- package/dist/skills.js +558 -0
- package/dist/skills.js.map +1 -0
- package/dist/update.d.ts +6 -0
- package/dist/update.d.ts.map +1 -1
- package/dist/update.js +33 -14
- 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 +5 -4
package/README.md
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# @nocobase/app-cli-client
|
|
2
2
|
|
|
3
|
+
An application can provide next steps in an API error's `metadata.suggestions`: an array of `{ message, run?: { command, args } }`. The CLI validates that shape and exposes it as `error.suggestions` in JSON and in its human-readable error output. Without valid supplied suggestions, the existing hints for authentication and plans still apply. A `run` must be executable as given; put placeholders and steps needing user input in the message instead.
|
|
4
|
+
|
|
3
5
|
A command line for a NocoBase application, branded by the application: it signs in to a server and runs the business commands the server's command manifest (`GET /api/cli/manifest`) publishes for the caller, each a request to one API route. An application declares its brand under `nocobase.cli` in its `package.json` (`AppCliBrand`), and `nocobase cli build` and `nocobase cli link` of `@nocobase/app-cli` package it with an entry that calls `runAppCliPackage`, which reads the brand back from the packaged CLI's own `package.json` and runs it with `selfUpdate` on; an application's `acme` is made this way. A CLI may instead call `runAppCli` with an `AppCliConfig` of its own and add static commands.
|
|
4
6
|
|
|
7
|
+
Business commands render lists as tables and object responses as named fields. HTTP(S) URLs remain complete for copying. Ordinary text and structured fields retain their compact display. Use `--json` for complete nested results, including Projects invitation links, and for scripts instead of parsing the text layout.
|
|
8
|
+
|
|
9
|
+
A branded package with `skills/nb-studio-cli/SKILL.md` also exposes `skills install` and `skills status`. These local commands require neither a login nor a network connection. Install selects detected Claude Code and Codex tools by default, or takes repeated `--tool claude|codex|all`; `--dry-run` computes actions without writing. Claude's destination is `<CLAUDE_CONFIG_DIR or ~/.claude>/skills/nb-studio-cli`; Codex's destination is `~/.agents/skills/nb-studio-cli` regardless of `CODEX_HOME`, following the [official user Skill directory](https://learn.chatgpt.com/docs/build-skills#where-codex-loads-local-skills). Tool detection uses each tool's configuration variable or directory, or its executable on PATH; the shared `.agents/skills` directory alone does not detect Codex. No detected tool yields `SKILLS_NO_TOOL` with explicit installation suggestions.
|
|
10
|
+
|
|
11
|
+
Status compares sorted relative paths and file contents using SHA-256 and reports manual copies, legacy Codex copies in `<CODEX_HOME or ~/.codex>/skills/nb-studio-cli`, and previously registered paths. Only `nb-studio-cli` is managed; install does not create legacy copies. Successful installations are recorded in `<CLI state directory>/skills.json`. Self-update uses the newly installed package (tarball root or npm package root) to synchronize recorded destinations. Skill failures leave the CLI upgrade successful and appear in the update envelope's `warnings` and `result.skills`; manual copies prompt an installation reminder. External upgrades, including npm global installation, require running `skills install` again. Install refuses agent run contexts, while status remains available. See Studio's [static command reference](../../apps/studio/docs/cli/static-commands.md) for the result schema and filesystem constraints.
|
|
12
|
+
|
|
5
13
|
```ts
|
|
6
14
|
import { runAppCli } from '@nocobase/app-cli-client';
|
|
7
15
|
|
|
@@ -18,8 +26,12 @@ await runAppCli(
|
|
|
18
26
|
);
|
|
19
27
|
```
|
|
20
28
|
|
|
21
|
-
|
|
29
|
+
`<bin> acp start` connects the computer it runs on to the signed-in person's agent sessions (`@nocobase/app-plugin-agent-sessions`), so the sessions they start in the application's pages run there with the coding agents installed there; it runs the bridge of `@nocobase/acp-bridge` until stopped with Ctrl+C. `<bin> acp service install` runs the same in the background from every login, as a launchd agent on macOS, a systemd user unit on Linux or a script in the Startup folder on Windows, and starts it again when it fails; it writes in the shell's PATH, the CLI's own variables, proxy and CA variables and the `--pass-env` names, since a service reads no shell configuration. `acp service status` says whether it is installed and connected and where its output goes; `acp service uninstall` removes it. One bridge runs per profile: a second one refuses to start. `--root` limits where sessions may work on this computer, repeated for several directories (the home directory by default), and the person chooses the folders among them in the application. `--name` is the computer's name in the application (its host name by default). The computer's id and key are kept per profile and server under `<home>/acp/`, readable by their owner only: the key, issued when the person first connects the computer, keeps it connected however long the sign-in lasts, until the computer is removed in the application. Connecting needs a person's sign-in: an agent run's credential is refused.
|
|
30
|
+
|
|
31
|
+
An application whose install script (`/api/agents/dist/installScript` of `@nocobase/app-plugin-agents`) installs its CLI names `selfUpdate` in the configuration, with the root of the CLI's package as it runs (`packageRoot`). The CLI then has `<bin> update`, which asks the signed-in server for the newest version it serves for this platform (`selfUpdate.product`, the command name by default), downloads and checks its SHA-256, or, when the server serves no tarball and names the package on npm (`accept=npm`), installs that exact version with the machine's npm, and switches `<prefix>/current` to it, keeping the previous version; business commands and `login` say on stderr when a newer version is served, asking at most every 12 hours (`<state dir>/cache/update.json`). An installation the script made for the runner (`install.json` `mode: runner`) is the runner's, which updates itself, so `update` refuses it. `@nocobase/app-cli-client/install` is that installation layout (`<prefix>/versions/<version>`, `current`, `<prefix>/node`, `install.json`) and the update itself, without reading any CLI configuration, so a runner shares it. A version directory holds an unpacked tarball, or an npm install (`installNpmVersion`: `npm install --prefix <dir> --no-save --no-audit --no-fund --omit=optional <package>@<version>`, with npm from `NOCOBASE_NPM`, PATH or beside the Node) with the launcher `npmLauncherScript` at `bin/<bin>`, which starts `node_modules/.bin/<bin>` on `<prefix>/node` or the first Node.js 24 it finds; `detectInstallation` takes either root, the version directory or the package inside its `node_modules`, and `applyUpdate` installs an `UpdateTarget` of either kind.
|
|
22
32
|
|
|
23
33
|
`@nocobase/app-cli-client/request` exports `fillRequest`, which turns a manifest command and the values of its parameters into the request it makes. It imports nothing else, so a server that calls its own routes the way the CLI does, such as an online agent's tools in `@nocobase/app-plugin-agents`, builds the same request.
|
|
24
34
|
|
|
25
35
|
`@nocobase/app-cli-client/parse` is how the CLI reads a business command's line, with no file, environment or terminal of its own: `parseCommandLine(command, argv, { bin, io })` takes a manifest command and the words after its name, and answers the values of its parameters, the body read from `--file` and the files to send, or throws a `CliParseError` carrying the cli-envelope's `code`, message, suggestions and exit code. The `io` (`CliParseIo`) reads text files and environment variables, and optionally finds files to send (`file`, `changed`) and asks for a missing value (`ask`); a flag that sends a file is refused with `FILES_UNAVAILABLE` where `file` is absent. It also renders a command's help and an area's command list from the manifest (`renderCommandHelp`, `renderTopicHelp`) and maps a failed request to the CLI's exit code (`apiExitCode`). The CLI uses it over this machine, and the `acme` command of an online run's shell in `@nocobase/app-plugin-agents` over that shell, so both read a line the same way.
|
|
36
|
+
|
|
37
|
+
For My Agent sessions, the bridge invokes `prepareSession` before new or restored agent processes. It verifies the selected stored profile, prepares the shared Skill, and supplies `<PREFIX>_PROFILE` and `<PREFIX>_AGENT_SESSION`. In that mode identity selection ignores run-directory credentials, environment API keys and server overrides, and rejects profile changes or missing profiles. Ordinary CLI identity selection is unchanged. Claude Code and Codex retain their native Skill installation and synchronization, including explicit errors when installation fails. Every other compatible ACP agent receives the packaged Skill's full text through `sessionInstructions` at the beginning of each prompt, with its source directory for relative references. This includes new, restored and prewarmed sessions and preserves the application's instructions, page context and attachments in the original prompt. It writes no agent configuration or workspace files and requires no installation adapter. Missing or unreadable packaged instructions fail explicitly with steps to reinstall the CLI; they are never silently omitted.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface AcpServiceOptions {
|
|
2
|
+
/** The CLI's command name, such as `nb-studio`. */
|
|
3
|
+
readonly bin: string;
|
|
4
|
+
/** The program and arguments that start the CLI, such as [node, bin/run.js]. */
|
|
5
|
+
readonly command: readonly string[];
|
|
6
|
+
/** What follows `acp start --service`: the profile, the computer's name and its roots. */
|
|
7
|
+
readonly args: readonly string[];
|
|
8
|
+
/** Where the service's output goes, on macOS and Windows; systemd keeps it in the journal. */
|
|
9
|
+
readonly log: string;
|
|
10
|
+
/** The variables written into the service, with their values. */
|
|
11
|
+
readonly env: Readonly<Record<string, string>>;
|
|
12
|
+
/** Separates the services of several profiles. */
|
|
13
|
+
readonly profile?: string | undefined;
|
|
14
|
+
readonly platform?: NodeJS.Platform;
|
|
15
|
+
readonly home?: string;
|
|
16
|
+
readonly uid?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface AcpServicePlan {
|
|
19
|
+
readonly platform: 'launchd' | 'systemd' | 'startup';
|
|
20
|
+
readonly label: string;
|
|
21
|
+
readonly file: string;
|
|
22
|
+
readonly content: string;
|
|
23
|
+
readonly install: readonly (readonly string[])[];
|
|
24
|
+
readonly uninstall: readonly (readonly string[])[];
|
|
25
|
+
/** Answers with exit code 0 while the service is loaded; none on Windows, where the file is the service. */
|
|
26
|
+
readonly status?: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/** The proxy and CA variables a service needs to reach the application as the shell does. */
|
|
29
|
+
export declare const NETWORK_ENV: readonly string[];
|
|
30
|
+
/** `names` with their values in `env`, those set; a value with NUL cannot be written into a service. */
|
|
31
|
+
export declare function capture(env: NodeJS.ProcessEnv, names: readonly string[]): Record<string, string>;
|
|
32
|
+
export declare function acpServicePlan(options: AcpServiceOptions): AcpServicePlan;
|
|
33
|
+
/** Writes the service and starts it, replacing one installed before. */
|
|
34
|
+
export declare function installAcpService(plan: AcpServicePlan): Promise<void>;
|
|
35
|
+
/** Stops the service and removes it; on Windows the running bridge is stopped by the caller. */
|
|
36
|
+
export declare function uninstallAcpService(plan: AcpServicePlan): Promise<void>;
|
|
37
|
+
/** Whether the service is loaded (launchd, systemd); undefined where only its file says so. */
|
|
38
|
+
export declare function acpServiceLoaded(plan: AcpServicePlan): Promise<boolean | undefined>;
|
|
39
|
+
//# sourceMappingURL=acp-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-service.d.ts","sourceRoot":"","sources":["../src/acp-service.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,iBAAiB;IAChC,mDAAmD;IACnD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gFAAgF;IAChF,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,0FAA0F;IAC1F,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,8FAA8F;IAC9F,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/C,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IACnD,4GAA4G;IAC5G,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAED,6FAA6F;AAC7F,eAAO,MAAM,WAAW,EAAE,SAAS,MAAM,EAYxC,CAAC;AAEF,wGAAwG;AACxG,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUxB;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,cAAc,CAwEzE;AAED,wEAAwE;AACxE,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgC3E;AAED,gGAAgG;AAChG,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7E;AAED,+FAA+F;AAC/F,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAO9B"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// `<bin> acp start` as a per-user service that starts at login and starts again when it fails: a launchd agent on
|
|
2
|
+
// macOS, a systemd user unit on Linux, and on Windows a script in the Startup folder that runs it without a window. The
|
|
3
|
+
// service runs `acp start --service`, which stops for good, exiting 0, when the application no longer accepts the
|
|
4
|
+
// computer, rather than failing again and again. Refused for its protocol, it updates the CLI and exits non-zero, so
|
|
5
|
+
// the service starts it again on the new version (or, when no update helped, tries again a few minutes later). It gets
|
|
6
|
+
// the installing shell's PATH, the CLI's own variables, proxy and CA variables and the `--pass-env` names with their
|
|
7
|
+
// values now, since a service reads no shell configuration; its files are readable by their owner only. Each plan
|
|
8
|
+
// lists the file it writes and the commands it runs.
|
|
9
|
+
import { execFile, spawn } from 'node:child_process';
|
|
10
|
+
import { chmod, mkdir, rm, writeFile } from 'node:fs/promises';
|
|
11
|
+
import os from 'node:os';
|
|
12
|
+
import path from 'node:path';
|
|
13
|
+
import { promisify } from 'node:util';
|
|
14
|
+
const run = promisify(execFile);
|
|
15
|
+
/** The proxy and CA variables a service needs to reach the application as the shell does. */
|
|
16
|
+
export const NETWORK_ENV = [
|
|
17
|
+
'HTTP_PROXY',
|
|
18
|
+
'HTTPS_PROXY',
|
|
19
|
+
'ALL_PROXY',
|
|
20
|
+
'NO_PROXY',
|
|
21
|
+
'http_proxy',
|
|
22
|
+
'https_proxy',
|
|
23
|
+
'all_proxy',
|
|
24
|
+
'no_proxy',
|
|
25
|
+
'SSL_CERT_FILE',
|
|
26
|
+
'SSL_CERT_DIR',
|
|
27
|
+
'NODE_EXTRA_CA_CERTS',
|
|
28
|
+
];
|
|
29
|
+
/** `names` with their values in `env`, those set; a value with NUL cannot be written into a service. */
|
|
30
|
+
export function capture(env, names) {
|
|
31
|
+
const captured = {};
|
|
32
|
+
for (const name of names) {
|
|
33
|
+
const value = env[name];
|
|
34
|
+
if (value === undefined || value === '')
|
|
35
|
+
continue;
|
|
36
|
+
if (value.includes('\0'))
|
|
37
|
+
throw new Error(`Cannot write ${name} into a service: it holds NUL.`);
|
|
38
|
+
captured[name] = value;
|
|
39
|
+
}
|
|
40
|
+
return captured;
|
|
41
|
+
}
|
|
42
|
+
export function acpServicePlan(options) {
|
|
43
|
+
const platform = options.platform ?? process.platform;
|
|
44
|
+
const home = options.home ?? os.homedir();
|
|
45
|
+
const suffix = options.profile
|
|
46
|
+
? `-${options.profile.replace(/[^A-Za-z0-9._-]/gu, '_')}`
|
|
47
|
+
: '';
|
|
48
|
+
const name = `${options.bin}-acp${suffix}`;
|
|
49
|
+
const args = [
|
|
50
|
+
...options.command,
|
|
51
|
+
'acp',
|
|
52
|
+
'start',
|
|
53
|
+
'--service',
|
|
54
|
+
...options.args,
|
|
55
|
+
];
|
|
56
|
+
if (platform === 'darwin') {
|
|
57
|
+
const label = `com.nocobase.${name}`;
|
|
58
|
+
const file = path.join(home, 'Library', 'LaunchAgents', `${label}.plist`);
|
|
59
|
+
const domain = `gui/${options.uid ?? process.getuid?.() ?? 501}`;
|
|
60
|
+
return {
|
|
61
|
+
platform: 'launchd',
|
|
62
|
+
label,
|
|
63
|
+
file,
|
|
64
|
+
content: plist(label, args, options.env, options.log),
|
|
65
|
+
install: [
|
|
66
|
+
['launchctl', 'bootout', `${domain}/${label}`],
|
|
67
|
+
['launchctl', 'bootstrap', domain, file],
|
|
68
|
+
],
|
|
69
|
+
uninstall: [['launchctl', 'bootout', `${domain}/${label}`]],
|
|
70
|
+
status: ['launchctl', 'print', `${domain}/${label}`],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (platform === 'linux') {
|
|
74
|
+
const unit = `${name}.service`;
|
|
75
|
+
return {
|
|
76
|
+
platform: 'systemd',
|
|
77
|
+
label: unit,
|
|
78
|
+
file: path.join(home, '.config', 'systemd', 'user', unit),
|
|
79
|
+
content: systemdUnit(options.bin, args, options.env),
|
|
80
|
+
install: [
|
|
81
|
+
['systemctl', '--user', 'daemon-reload'],
|
|
82
|
+
['systemctl', '--user', 'enable', unit],
|
|
83
|
+
['systemctl', '--user', 'restart', unit],
|
|
84
|
+
],
|
|
85
|
+
uninstall: [
|
|
86
|
+
['systemctl', '--user', 'disable', '--now', unit],
|
|
87
|
+
['systemctl', '--user', 'daemon-reload'],
|
|
88
|
+
],
|
|
89
|
+
status: ['systemctl', '--user', 'is-active', '--quiet', unit],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (platform === 'win32') {
|
|
93
|
+
const appData = process.env.APPDATA ?? path.win32.join(home, 'AppData', 'Roaming');
|
|
94
|
+
const file = path.win32.join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', `${name}.vbs`);
|
|
95
|
+
return {
|
|
96
|
+
platform: 'startup',
|
|
97
|
+
label: name,
|
|
98
|
+
file,
|
|
99
|
+
content: startupScript(args, options.env, options.log),
|
|
100
|
+
install: [['wscript.exe', '//B', '//Nologo', file]],
|
|
101
|
+
uninstall: [],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
throw new Error(`Running as a service is not supported on ${platform}.`);
|
|
105
|
+
}
|
|
106
|
+
/** Writes the service and starts it, replacing one installed before. */
|
|
107
|
+
export async function installAcpService(plan) {
|
|
108
|
+
await mkdir(path.dirname(plan.file), { recursive: true });
|
|
109
|
+
// Only its owner reads it: the variables written into it may hold a proxy's password or a key.
|
|
110
|
+
await writeFile(plan.file, plan.content, { mode: 0o600 });
|
|
111
|
+
await chmod(plan.file, 0o600);
|
|
112
|
+
if (plan.platform === 'startup') {
|
|
113
|
+
// The script starts at the next login by itself; this starts it now, outliving this command.
|
|
114
|
+
const [command = '', ...args] = plan.install[0] ?? [];
|
|
115
|
+
spawn(command, args, {
|
|
116
|
+
detached: true,
|
|
117
|
+
stdio: 'ignore',
|
|
118
|
+
windowsHide: true,
|
|
119
|
+
}).unref();
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
for (const [index, [command = '', ...args]] of plan.install.entries()) {
|
|
123
|
+
// launchd's `bootout` of a service that is not loaded fails, which is fine; it may also still be removing the
|
|
124
|
+
// previous instance right after it, so `bootstrap` is tried again for a few seconds.
|
|
125
|
+
if (plan.platform === 'launchd' && index === 0) {
|
|
126
|
+
await run(command, args).catch(() => undefined);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
for (let attempt = 1;; attempt += 1) {
|
|
130
|
+
try {
|
|
131
|
+
await run(command, args);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (plan.platform !== 'launchd' || attempt >= 10)
|
|
136
|
+
throw error;
|
|
137
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** Stops the service and removes it; on Windows the running bridge is stopped by the caller. */
|
|
143
|
+
export async function uninstallAcpService(plan) {
|
|
144
|
+
for (const [command = '', ...args] of plan.uninstall)
|
|
145
|
+
// Not loaded is fine: the goal is that it is not.
|
|
146
|
+
await run(command, args).catch(() => undefined);
|
|
147
|
+
await rm(plan.file, { force: true });
|
|
148
|
+
}
|
|
149
|
+
/** Whether the service is loaded (launchd, systemd); undefined where only its file says so. */
|
|
150
|
+
export async function acpServiceLoaded(plan) {
|
|
151
|
+
if (!plan.status)
|
|
152
|
+
return undefined;
|
|
153
|
+
const [command = '', ...args] = plan.status;
|
|
154
|
+
return run(command, args).then(() => true, () => false);
|
|
155
|
+
}
|
|
156
|
+
function xml(value) {
|
|
157
|
+
return value
|
|
158
|
+
.replace(/&/gu, '&')
|
|
159
|
+
.replace(/</gu, '<')
|
|
160
|
+
.replace(/>/gu, '>');
|
|
161
|
+
}
|
|
162
|
+
function plist(label, args, env, log) {
|
|
163
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
164
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
165
|
+
<plist version="1.0">
|
|
166
|
+
<dict>
|
|
167
|
+
<key>Label</key>
|
|
168
|
+
<string>${xml(label)}</string>
|
|
169
|
+
<key>ProgramArguments</key>
|
|
170
|
+
<array>
|
|
171
|
+
${args.map((arg) => ` <string>${xml(arg)}</string>`).join('\n')}
|
|
172
|
+
</array>
|
|
173
|
+
<key>EnvironmentVariables</key>
|
|
174
|
+
<dict>
|
|
175
|
+
${Object.entries(env)
|
|
176
|
+
.map(([key, value]) => ` <key>${xml(key)}</key>\n <string>${xml(value)}</string>`)
|
|
177
|
+
.join('\n')}
|
|
178
|
+
</dict>
|
|
179
|
+
<key>RunAtLoad</key>
|
|
180
|
+
<true/>
|
|
181
|
+
<key>KeepAlive</key>
|
|
182
|
+
<dict>
|
|
183
|
+
<key>SuccessfulExit</key>
|
|
184
|
+
<false/>
|
|
185
|
+
</dict>
|
|
186
|
+
<key>ThrottleInterval</key>
|
|
187
|
+
<integer>10</integer>
|
|
188
|
+
<key>StandardOutPath</key>
|
|
189
|
+
<string>${xml(log)}</string>
|
|
190
|
+
<key>StandardErrorPath</key>
|
|
191
|
+
<string>${xml(log)}</string>
|
|
192
|
+
</dict>
|
|
193
|
+
</plist>
|
|
194
|
+
`;
|
|
195
|
+
}
|
|
196
|
+
function systemdQuote(value) {
|
|
197
|
+
return /[\s'"\\\p{Cc}]/u.test(value)
|
|
198
|
+
? `"${value.replace(/[\\"\p{Cc}]/gu, (character) => {
|
|
199
|
+
if (character === '\\' || character === '"')
|
|
200
|
+
return `\\${character}`;
|
|
201
|
+
const code = character.charCodeAt(0);
|
|
202
|
+
return code < 128
|
|
203
|
+
? `\\x${code.toString(16).padStart(2, '0')}`
|
|
204
|
+
: `\\u${code.toString(16).padStart(4, '0')}`;
|
|
205
|
+
})}"`
|
|
206
|
+
: value;
|
|
207
|
+
}
|
|
208
|
+
function systemdUnit(bin, args, env) {
|
|
209
|
+
return `[Unit]
|
|
210
|
+
Description=${bin} agent sessions on this computer
|
|
211
|
+
After=network-online.target
|
|
212
|
+
|
|
213
|
+
[Service]
|
|
214
|
+
ExecStart=${args.map(systemdQuote).join(' ')}
|
|
215
|
+
${Object.entries(env)
|
|
216
|
+
// Quoted, with `%` doubled so systemd expands no specifier in it.
|
|
217
|
+
.map(([key, value]) => `Environment=${systemdQuote(`${key}=${value}`.replace(/%/gu, '%%'))}`)
|
|
218
|
+
.join('\n')}
|
|
219
|
+
Restart=on-failure
|
|
220
|
+
RestartSec=10
|
|
221
|
+
KillMode=mixed
|
|
222
|
+
|
|
223
|
+
[Install]
|
|
224
|
+
WantedBy=default.target
|
|
225
|
+
`;
|
|
226
|
+
}
|
|
227
|
+
/** `value` as one argument of a cmd.exe command line. */
|
|
228
|
+
function cmdQuote(value) {
|
|
229
|
+
return /^[\w@+=:,./\\-]+$/u.test(value)
|
|
230
|
+
? value
|
|
231
|
+
: `"${value.replace(/"/gu, '""')}"`;
|
|
232
|
+
}
|
|
233
|
+
/** `value` as a VBScript string literal. */
|
|
234
|
+
function vbsString(value) {
|
|
235
|
+
return `"${value.replace(/"/gu, '""')}"`;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* A script Windows runs at login from the Startup folder: it runs the CLI without a window, its output appended to the
|
|
239
|
+
* log, and again 10 seconds after it fails, until the CLI exits 0 or the script is removed.
|
|
240
|
+
*/
|
|
241
|
+
function startupScript(args, env, log) {
|
|
242
|
+
const line = `cmd.exe /d /s /c "${args.map(cmdQuote).join(' ')} >> ${cmdQuote(log)} 2>&1"`;
|
|
243
|
+
return [
|
|
244
|
+
"' Runs the agent sessions bridge at login, without a window; remove this file to stop it starting.",
|
|
245
|
+
'Set shell = CreateObject("WScript.Shell")',
|
|
246
|
+
'Set files = CreateObject("Scripting.FileSystemObject")',
|
|
247
|
+
'Set env = shell.Environment("Process")',
|
|
248
|
+
...Object.entries(env).map(([key, value]) => `env(${vbsString(key)}) = ${vbsString(value)}`),
|
|
249
|
+
'Do',
|
|
250
|
+
` code = shell.Run(${vbsString(line)}, 0, True)`,
|
|
251
|
+
' If code = 0 Or Not files.FileExists(WScript.ScriptFullName) Then Exit Do',
|
|
252
|
+
' WScript.Sleep 10000',
|
|
253
|
+
'Loop',
|
|
254
|
+
'',
|
|
255
|
+
].join('\r\n');
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=acp-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-service.js","sourceRoot":"","sources":["../src/acp-service.ts"],"names":[],"mappings":"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"}
|
package/dist/acp.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Command } from '@oclif/core';
|
|
2
|
+
import { BridgeUpgradeRequired } from '@nocobase/acp-bridge';
|
|
3
|
+
import type { AppCliConfig } from './config.ts';
|
|
4
|
+
import { type CliUpdateResult } from './update.ts';
|
|
5
|
+
export declare function acpCommands(app: AppCliConfig): Record<string, Command.Class>;
|
|
6
|
+
/**
|
|
7
|
+
* How long the service waits, after the application refused its bridge and no update helped, before exiting for its
|
|
8
|
+
* service manager to start it again: it tries again then, without asking every few seconds.
|
|
9
|
+
*/
|
|
10
|
+
export declare const UPGRADE_RETRY_MS: number;
|
|
11
|
+
/** What updating a refused bridge came to: the version it now is, or why it is not updated. */
|
|
12
|
+
export type BridgeUpdateOutcome = {
|
|
13
|
+
readonly updated: true;
|
|
14
|
+
readonly version: string;
|
|
15
|
+
} | {
|
|
16
|
+
readonly updated: false;
|
|
17
|
+
readonly reason: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* After the application refused the bridge's protocol: updates the CLI as `<bin> update` does (`update`; undefined
|
|
21
|
+
* when this CLI does not update itself) when the bridge is the older side, and says why not otherwise.
|
|
22
|
+
*/
|
|
23
|
+
export declare function updateRefusedBridge(options: {
|
|
24
|
+
readonly bin: string;
|
|
25
|
+
readonly refusal: BridgeUpgradeRequired;
|
|
26
|
+
readonly update: (() => Promise<CliUpdateResult>) | undefined;
|
|
27
|
+
}): Promise<BridgeUpdateOutcome>;
|
|
28
|
+
//# sourceMappingURL=acp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../src/acp.ts"],"names":[],"mappings":"AAUA,OAAO,EAAS,KAAK,OAAO,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAEL,qBAAqB,EAEtB,MAAM,sBAAsB,CAAC;AAY9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAYhD,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CA6S5E;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAmB,CAAC;AAEnD,+FAA+F;AAC/F,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IACjD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,MAAM,EAAE,CAAC,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,SAAS,CAAC;CAC/D,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6B/B"}
|