@nocobase/app-cli-client 0.1.0-beta.2 → 0.1.0-beta.20

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.
Files changed (74) hide show
  1. package/LICENSE.txt +129 -0
  2. package/README.md +12 -0
  3. package/dist/acp-service.d.ts +52 -0
  4. package/dist/acp-service.d.ts.map +1 -0
  5. package/dist/acp-service.js +329 -0
  6. package/dist/acp-service.js.map +1 -0
  7. package/dist/acp.d.ts +28 -0
  8. package/dist/acp.d.ts.map +1 -0
  9. package/dist/acp.js +414 -0
  10. package/dist/acp.js.map +1 -0
  11. package/dist/commands.d.ts.map +1 -1
  12. package/dist/commands.js +10 -0
  13. package/dist/commands.js.map +1 -1
  14. package/dist/dynamic/index.d.ts +3 -1
  15. package/dist/dynamic/index.d.ts.map +1 -1
  16. package/dist/dynamic/index.js +48 -12
  17. package/dist/dynamic/index.js.map +1 -1
  18. package/dist/dynamic/manifest.d.ts.map +1 -1
  19. package/dist/dynamic/manifest.js +10 -0
  20. package/dist/dynamic/manifest.js.map +1 -1
  21. package/dist/dynamic/output.d.ts +2 -2
  22. package/dist/dynamic/output.d.ts.map +1 -1
  23. package/dist/dynamic/output.js +23 -8
  24. package/dist/dynamic/output.js.map +1 -1
  25. package/dist/dynamic/rest.d.ts.map +1 -1
  26. package/dist/dynamic/rest.js +24 -0
  27. package/dist/dynamic/rest.js.map +1 -1
  28. package/dist/dynamic/session.d.ts +1 -0
  29. package/dist/dynamic/session.d.ts.map +1 -1
  30. package/dist/dynamic/session.js +29 -1
  31. package/dist/dynamic/session.js.map +1 -1
  32. package/dist/lib/command.d.ts.map +1 -1
  33. package/dist/lib/command.js +14 -4
  34. package/dist/lib/command.js.map +1 -1
  35. package/dist/lib/credentials.d.ts +2 -0
  36. package/dist/lib/credentials.d.ts.map +1 -1
  37. package/dist/lib/credentials.js +7 -3
  38. package/dist/lib/credentials.js.map +1 -1
  39. package/dist/lib/envelope.d.ts +2 -0
  40. package/dist/lib/envelope.d.ts.map +1 -1
  41. package/dist/lib/envelope.js +16 -2
  42. package/dist/lib/envelope.js.map +1 -1
  43. package/dist/lib/http.d.ts.map +1 -1
  44. package/dist/lib/http.js +1 -0
  45. package/dist/lib/http.js.map +1 -1
  46. package/dist/parse/arguments.d.ts.map +1 -1
  47. package/dist/parse/arguments.js +9 -0
  48. package/dist/parse/arguments.js.map +1 -1
  49. package/dist/parse/distance.d.ts +22 -0
  50. package/dist/parse/distance.d.ts.map +1 -0
  51. package/dist/parse/distance.js +82 -0
  52. package/dist/parse/distance.js.map +1 -0
  53. package/dist/parse/manifest.d.ts +10 -0
  54. package/dist/parse/manifest.d.ts.map +1 -1
  55. package/dist/run.d.ts.map +1 -1
  56. package/dist/run.js +36 -5
  57. package/dist/run.js.map +1 -1
  58. package/dist/skills-lock.d.ts +2 -0
  59. package/dist/skills-lock.d.ts.map +1 -0
  60. package/dist/skills-lock.js +151 -0
  61. package/dist/skills-lock.js.map +1 -0
  62. package/dist/skills.d.ts +73 -0
  63. package/dist/skills.d.ts.map +1 -0
  64. package/dist/skills.js +728 -0
  65. package/dist/skills.js.map +1 -0
  66. package/dist/update.d.ts +4 -0
  67. package/dist/update.d.ts.map +1 -1
  68. package/dist/update.js +36 -1
  69. package/dist/update.js.map +1 -1
  70. package/dist/whoami.d.ts +2 -0
  71. package/dist/whoami.d.ts.map +1 -1
  72. package/dist/whoami.js +10 -3
  73. package/dist/whoami.js.map +1 -1
  74. package/package.json +5 -4
package/LICENSE.txt ADDED
@@ -0,0 +1,129 @@
1
+ Updated Date: November 7, 2026
2
+
3
+ NocoBase License Agreement
4
+
5
+ NOCOBASE PTE. LTD., a Singaporean Exempt Private Company Limited by Shares with its principal place of business located at 112 ROBINSON ROAD, #03-01, SINGAPORE ("The Company") https://www.nocobase.com/ issues this License Agreement ("Agreement") to you. You, as an individual or a company ("The User"), will be deemed to voluntarily accept all terms of this Agreement by using NocoBase (including but not limited to obtaining NocoBase source code, installation package, or image in any form, installing and using NocoBase, developing Applications with NocoBase, purchasing NocoBase commercial license and services). If the User does not agree to any term of this Agreement, or cannot accurately understand our interpretation of the relevant terms, please stop using it immediately.
6
+
7
+ This Agreement applies to any use, quotation, contract, invoice, and all software delivered by the Company. The User and the Company or NocoBase's agents need not sign a separate license agreement for the sale and delivery of the software.
8
+
9
+ This Agreement applies to NocoBase 3 and later versions. NocoBase 2 and earlier versions are independent products and remain subject to their original license agreement. Where a NocoBase 2 Commercial Edition user uses NocoBase 3 or later versions under a policy announced by the Company, that use is subject to this Agreement.
10
+
11
+ The Company reserves the right to formulate and modify this Agreement from time to time as needed. If there are changes, the Company will announce them in the form of website announcements, without further individual notification. The changed Agreement will automatically take effect once it is announced, becoming part of this Agreement.
12
+
13
+ ==============
14
+ 1. Definitions
15
+ ==============
16
+
17
+ 1.1 "Software" refers to NocoBase, consisting of Core, Studio, and Commercial Plugins, including their source code, installation packages, images, and all their modifications, updates, and upgrades.
18
+
19
+ 1.2 "Core" refers to NocoBase Core, the open source application foundation released by the Company, including the runtime, plugins, application templates, development standards, and development skills placed in the same code repository.
20
+
21
+ 1.3 "Studio" refers to NocoBase Studio, the governance platform for people and agents building software together, provided in the Commercial Edition.
22
+
23
+ 1.4 "Commercial Plugins" refers to the plugins provided in the Commercial Edition that extend the capabilities of Core, such as advanced approvals and enterprise SSO.
24
+
25
+ 1.5 "Community Edition" refers to the free version of the Software provided to the User through public channels, namely Core.
26
+
27
+ 1.6 "Commercial Edition" refers to the paid version of the Software purchased by the User from the Company or its agents, downloaded through exclusive channels, and includes additional benefits. In addition to Core, it includes Studio and Commercial Plugins, and consists of two versions: Professional Edition and Enterprise Edition.
28
+
29
+ 1.7 "Application" refers to a specific business use case application serving internal or external customers of the User, developed based on the Software, such as ERP/CRM. Studio is a development tool and is not part of any Application.
30
+
31
+ 1.8 "Customer" refers to the clients who commission the User to develop Applications or purchase the User's Applications.
32
+
33
+ 1.9 "Agent" refers to an AI agent that works with the Software, including the coding agents the User uses to develop Applications and the business agents in Applications.
34
+
35
+ 1.10 "Third-Party Services" refers to the large models, coding agents, cloud services, and other third-party products and services that the User chooses to use with the Software.
36
+
37
+ 1.11 "Third-Party Open Source Software" refers to open source software provided with the Software. They are licensed through various published open source software licenses or copyright notices accompanying such software.
38
+
39
+ ===================================
40
+ 2. Intellectual Property Protection
41
+ ===================================
42
+
43
+ Except for Third-Party Open Source Software, the Company owns all copyrights, trademark rights, patent rights, trade secrets, and other intellectual property rights of the Software, and has registered and protected them in relevant countries and regions according to the "Paris Convention" or "TRIPS Agreement", ensuring that the intellectual property rights of the Software are internationally recognized and protected.
44
+
45
+ The Company claims no intellectual property rights in the business code written by the User or by Agents when developing Applications, or in the User's business data, skills, and knowledge bases. The parts of the Software contained in an Application remain the intellectual property of the Company and are subject to this Agreement.
46
+
47
+ =============
48
+ 3. Disclaimer
49
+ =============
50
+
51
+ 3.1 The User shall not use the Software to engage in activities that contravene applicable laws and regulations or offend against public order or religious prohibitions. All legal liabilities and consequences arising from the User's use shall be borne by the User.
52
+
53
+ 3.2 The Company shall not be liable for any direct, indirect, special, incidental, or consequential damages (including but not limited to loss of profits, business interruption, data loss, or business information disclosure) caused by the User's use of the Software, even if it has been previously informed of the possibility of such damages.
54
+
55
+ 3.3 Code written, content generated, and actions taken by Agents shall be reviewed and accepted by the User before being used in production. All consequences arising from the use of the work of Agents shall be borne by the User.
56
+
57
+ 3.4 Third-Party Services are chosen and paid for by the User and are subject to their own terms. The Company shall not be liable for the availability, output, or data handling of Third-Party Services.
58
+
59
+ ===============
60
+ 4. License Type
61
+ ===============
62
+
63
+ 4.1 This Agreement serves as the unified license agreement for NocoBase Software, applying to both the Community Edition and the Commercial Editions.
64
+
65
+ 4.2 Core is open source software. This Agreement incorporates and references the full text of the Apache License, Version 2.0 ("Apache-2.0", available at: https://www.apache.org/licenses/LICENSE-2.0 ). Users of Core must comply with the Apache-2.0 License as well as the supplementary terms set forth in this Agreement. In case of any inconsistency between Apache-2.0 and this Agreement, the supplementary terms of this Agreement shall prevail.
66
+
67
+ 4.3 Studio and Commercial Plugins are commercial software of the Company and are not licensed under Apache-2.0. They can only be used under the Commercial License and in accordance with this Agreement.
68
+
69
+ ================================================
70
+ 5. Rights and Obligations of Open Source License
71
+ ================================================
72
+
73
+ 5.1 The Community Edition can be used for commercial purposes, including developing Applications for Customers.
74
+
75
+ 5.2 It is not allowed to remove or change the NocoBase statement "AI + NocoBase" and "Build reliable business systems", or its link to https://www.nocobase.com/, at the bottom left of the interface of any Application, including Applications delivered to Customers, even though the code that displays the statement is part of the Application. If the default layout is replaced, the statement shall be kept at an equally visible position on the main interface of the Application. Pages that can be accessed without signing in and pages embedded in other systems are not subject to this requirement. When the sidebar is collapsed, showing the statement as an icon with a tooltip, as provided by default, meets this requirement. The main LOGO in the upper left corner of the page, the version number, and other information on the interface can be changed.
76
+
77
+ 5.3 It is not allowed to remove or change all intellectual property statements about NocoBase in the code.
78
+
79
+ 5.4 It is not allowed to provide to the public any form of AI application development platform or agent development platform SaaS/PaaS products using the original or modified Software.
80
+
81
+ ===============================
82
+ 6. Rights of Commercial License
83
+ ===============================
84
+
85
+ 6.1 Obtain a permanent commercial license of the Software.
86
+
87
+ 6.2 Can develop Applications for Customers, deploy the completed Applications, including the Commercial Plugins they use, on Customers' servers, or host them and provide them to Customers as a service. This does not include Studio.
88
+
89
+ 6.3 Customers can use the Commercial Plugins in the Applications delivered to them, within those Applications only, and can continue to develop those Applications on their own or through others.
90
+
91
+ 6.4 Get software upgrades and exclusive technical support during the upgrade validity period. Upgrades and technical support are provided to the User only, and the User can upgrade the Commercial Plugins in Applications delivered to Customers during this period.
92
+
93
+ 6.5 The licensed Software can be used for commercial purposes with no restrictions on the number of Applications, Customers, users, and Agents.
94
+
95
+ 6.6 Can remove or change the NocoBase statement described in 5.2, and the brand, name, link, and other information about NocoBase on the interface of Applications.
96
+
97
+ 6.7 If there are other agreements in the contract for the above rights, the contract agreement shall prevail.
98
+
99
+ ====================================
100
+ 7. Obligations of Commercial License
101
+ ====================================
102
+
103
+ 7.1 It is not allowed to remove or change all intellectual property statements about NocoBase in the code.
104
+
105
+ 7.2 It is not allowed to sell, transfer, lease, share, gift, or distribute the Commercial License. Deploying Applications for Customers under 6.2 is not considered sharing the Commercial License, but the license key, access token, or other credentials of the Commercial License shall not be provided to Customers for any purpose other than deploying and running the Applications delivered to them.
106
+
107
+ 7.3 It is not allowed to sell, transfer, lease, share, or distribute any form of AI application development platform, agent development platform, or developer tools developed based on Software.
108
+
109
+ 7.4 It is not allowed to provide any form of AI application development platform or agent development platform SaaS/PaaS products to the public using the original or modified Software.
110
+
111
+ 7.5 Studio can only be used by the User holding the Commercial License, on servers owned or rented by the User. It is not allowed to deploy Studio for Customers, or to provide Studio to Customers or any third party in any form, including as a hosted service. Customers that need Studio shall purchase their own Commercial License.
112
+
113
+ 7.6 Customer personnel can take part in requirement confirmation, acceptance, and release approval in the User's Studio for the Applications the User develops for them. This is not considered providing Studio to Customers, but it is not allowed to let Customers use Studio to develop their own projects.
114
+
115
+ 7.7 If there is a violation of the above obligations or the terms of this Agreement, the rights owned by the User will be immediately terminated, the paid fees will not be refunded, and the Company reserves the right to pursue the User's legal responsibility.
116
+
117
+ 7.8 If there are other agreements in the contract for the above obligations, the contract agreement shall prevail.
118
+
119
+ =============================================================
120
+ 8. Legal Jurisdiction, Interpretation, and Dispute Resolution
121
+ =============================================================
122
+
123
+ 8.1 Except for Mainland China, the interpretation, application, and all matters related to this agreement are subject to the jurisdiction of Singapore law.
124
+
125
+ 8.2 Any dispute related to this Agreement should first be resolved through friendly negotiation. If the negotiation fails to resolve the dispute, the dispute should be submitted to the International Chamber of Commerce (ICC) for arbitration. The arbitration venue should be Singapore, conducted in English.
126
+
127
+ 8.3 All terms and conditions of this Agreement shall be deemed enforceable to the maximum extent permitted by applicable law. If any term of this Agreement is deemed invalid by any applicable law, the invalidity of that term does not affect the validity of any other term of this Agreement, and it should be deemed that the invalid term has been modified as much as possible to make it valid and enforceable, or if the term cannot be modified, it should be deemed to have been deleted from this Agreement.
128
+
129
+ 8.4 The arbitration award is final, binding on both parties, and can be enforced in any court with jurisdiction.
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 whose `skills/<slug>/` directories hold a `SKILL.md` (the build copies each directory named by `nocobase.cli.skills` there) 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. Every shipped Skill is installed, discovered from the package at run time and sorted by slug (names with a path separator or a leading dot are ignored). Claude's destination is `<CLAUDE_CONFIG_DIR or ~/.claude>/skills/<slug>`; Codex's destination is `~/.agents/skills/<slug>` 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 the shipped Skills are managed and neighbouring Skills are never touched; install does not create legacy copies, and only `nb-studio-cli` has a legacy Codex location. Successful installations are recorded per Skill in `<CLI state directory>/skills.json` (`{ version: 2, targets: [{ skill, tool, path, cliVersion, hash }] }`); the original single-Skill file is still read and rewritten in this shape. The result lists `skills` (slug and hash) and each target carries its `skill`. 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. A Skill the new package no longer ships is retired: a registered copy whose content still matches what was installed is removed, an edited copy is kept with a warning, and its record is dropped either way; unregistered copies are never deleted. 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
 
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
+
21
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,52 @@
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
+ export interface AcpRestartResult {
40
+ readonly restarted: string[];
41
+ readonly warnings: string[];
42
+ }
43
+ /** Restart installed, running services for every profile without changing their saved environment. */
44
+ export declare function restartAcpServices(bin: string, options?: {
45
+ readonly platform?: NodeJS.Platform;
46
+ readonly home?: string;
47
+ readonly uid?: number;
48
+ readonly run?: (command: string, args: string[]) => Promise<{
49
+ stdout: string;
50
+ }>;
51
+ }): Promise<AcpRestartResult>;
52
+ //# 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;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED,sGAAsG;AACtG,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE;IACP,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;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,CACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,KACX,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC7B,GACL,OAAO,CAAC,gBAAgB,CAAC,CAoE3B"}
@@ -0,0 +1,329 @@
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, readdir, 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
+ /** Restart installed, running services for every profile without changing their saved environment. */
157
+ export async function restartAcpServices(bin, options = {}) {
158
+ const result = { restarted: [], warnings: [] };
159
+ const platform = options.platform ?? process.platform;
160
+ if (platform !== 'darwin' && platform !== 'linux')
161
+ return result;
162
+ const home = options.home ?? os.homedir();
163
+ const directory = platform === 'darwin'
164
+ ? path.join(home, 'Library', 'LaunchAgents')
165
+ : path.join(home, '.config', 'systemd', 'user');
166
+ const prefix = platform === 'darwin' ? `com.nocobase.${bin}-acp` : `${bin}-acp`;
167
+ const extension = platform === 'darwin' ? '.plist' : '.service';
168
+ const execute = options.run ?? run;
169
+ const warn = (label) => {
170
+ result.warnings.push(`Could not restart ${label}. Run \`${bin} acp service restart\` to retry.`);
171
+ };
172
+ let files;
173
+ try {
174
+ files = await readdir(directory);
175
+ }
176
+ catch (error) {
177
+ if (error.code !== 'ENOENT')
178
+ warn(directory);
179
+ return result;
180
+ }
181
+ for (const file of files.sort()) {
182
+ if (!file.endsWith(extension))
183
+ continue;
184
+ const name = file.slice(0, -extension.length);
185
+ if (name !== prefix &&
186
+ !(name.startsWith(`${prefix}-`) &&
187
+ /^[A-Za-z0-9._-]+$/u.test(name.slice(prefix.length + 1))))
188
+ continue;
189
+ const label = platform === 'darwin' ? name : file;
190
+ const target = `gui/${options.uid ?? process.getuid?.() ?? 501}/${label}`;
191
+ try {
192
+ if (platform === 'darwin') {
193
+ let stdout;
194
+ try {
195
+ ({ stdout } = await execute('launchctl', ['print', target]));
196
+ }
197
+ catch (error) {
198
+ // launchctl exits 113 when the service is not loaded.
199
+ if (error.code === 113)
200
+ continue;
201
+ throw error;
202
+ }
203
+ if (!/^\s*state = running\s*$/mu.test(stdout))
204
+ continue;
205
+ await execute('launchctl', ['kickstart', '-k', target]);
206
+ }
207
+ else {
208
+ const { stdout } = await execute('systemctl', [
209
+ '--user',
210
+ 'show',
211
+ '--property=ActiveState',
212
+ '--value',
213
+ label,
214
+ ]);
215
+ if (stdout.trim() !== 'active')
216
+ continue;
217
+ // try-restart also preserves a stopped service if it stopped after the check.
218
+ await execute('systemctl', ['--user', 'try-restart', label]);
219
+ }
220
+ result.restarted.push(label);
221
+ }
222
+ catch {
223
+ warn(label);
224
+ }
225
+ }
226
+ return result;
227
+ }
228
+ function xml(value) {
229
+ return value
230
+ .replace(/&/gu, '&amp;')
231
+ .replace(/</gu, '&lt;')
232
+ .replace(/>/gu, '&gt;');
233
+ }
234
+ function plist(label, args, env, log) {
235
+ return `<?xml version="1.0" encoding="UTF-8"?>
236
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
237
+ <plist version="1.0">
238
+ <dict>
239
+ <key>Label</key>
240
+ <string>${xml(label)}</string>
241
+ <key>ProgramArguments</key>
242
+ <array>
243
+ ${args.map((arg) => ` <string>${xml(arg)}</string>`).join('\n')}
244
+ </array>
245
+ <key>EnvironmentVariables</key>
246
+ <dict>
247
+ ${Object.entries(env)
248
+ .map(([key, value]) => ` <key>${xml(key)}</key>\n <string>${xml(value)}</string>`)
249
+ .join('\n')}
250
+ </dict>
251
+ <key>RunAtLoad</key>
252
+ <true/>
253
+ <key>KeepAlive</key>
254
+ <dict>
255
+ <key>SuccessfulExit</key>
256
+ <false/>
257
+ </dict>
258
+ <key>ThrottleInterval</key>
259
+ <integer>10</integer>
260
+ <key>StandardOutPath</key>
261
+ <string>${xml(log)}</string>
262
+ <key>StandardErrorPath</key>
263
+ <string>${xml(log)}</string>
264
+ </dict>
265
+ </plist>
266
+ `;
267
+ }
268
+ function systemdQuote(value) {
269
+ return /[\s'"\\\p{Cc}]/u.test(value)
270
+ ? `"${value.replace(/[\\"\p{Cc}]/gu, (character) => {
271
+ if (character === '\\' || character === '"')
272
+ return `\\${character}`;
273
+ const code = character.charCodeAt(0);
274
+ return code < 128
275
+ ? `\\x${code.toString(16).padStart(2, '0')}`
276
+ : `\\u${code.toString(16).padStart(4, '0')}`;
277
+ })}"`
278
+ : value;
279
+ }
280
+ function systemdUnit(bin, args, env) {
281
+ return `[Unit]
282
+ Description=${bin} agent sessions on this computer
283
+ After=network-online.target
284
+
285
+ [Service]
286
+ ExecStart=${args.map(systemdQuote).join(' ')}
287
+ ${Object.entries(env)
288
+ // Quoted, with `%` doubled so systemd expands no specifier in it.
289
+ .map(([key, value]) => `Environment=${systemdQuote(`${key}=${value}`.replace(/%/gu, '%%'))}`)
290
+ .join('\n')}
291
+ Restart=on-failure
292
+ RestartSec=10
293
+ KillMode=mixed
294
+
295
+ [Install]
296
+ WantedBy=default.target
297
+ `;
298
+ }
299
+ /** `value` as one argument of a cmd.exe command line. */
300
+ function cmdQuote(value) {
301
+ return /^[\w@+=:,./\\-]+$/u.test(value)
302
+ ? value
303
+ : `"${value.replace(/"/gu, '""')}"`;
304
+ }
305
+ /** `value` as a VBScript string literal. */
306
+ function vbsString(value) {
307
+ return `"${value.replace(/"/gu, '""')}"`;
308
+ }
309
+ /**
310
+ * A script Windows runs at login from the Startup folder: it runs the CLI without a window, its output appended to the
311
+ * log, and again 10 seconds after it fails, until the CLI exits 0 or the script is removed.
312
+ */
313
+ function startupScript(args, env, log) {
314
+ const line = `cmd.exe /d /s /c "${args.map(cmdQuote).join(' ')} >> ${cmdQuote(log)} 2>&1"`;
315
+ return [
316
+ "' Runs the agent sessions bridge at login, without a window; remove this file to stop it starting.",
317
+ 'Set shell = CreateObject("WScript.Shell")',
318
+ 'Set files = CreateObject("Scripting.FileSystemObject")',
319
+ 'Set env = shell.Environment("Process")',
320
+ ...Object.entries(env).map(([key, value]) => `env(${vbsString(key)}) = ${vbsString(value)}`),
321
+ 'Do',
322
+ ` code = shell.Run(${vbsString(line)}, 0, True)`,
323
+ ' If code = 0 Or Not files.FileExists(WScript.ScriptFullName) Then Exit Do',
324
+ ' WScript.Sleep 10000',
325
+ 'Loop',
326
+ '',
327
+ ].join('\r\n');
328
+ }
329
+ //# 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;AAa9B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAahD,OAAO,EAGL,KAAK,eAAe,EACrB,MAAM,aAAa,CAAC;AAErB,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAkU5E;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"}