@chipschat/harness 0.0.0-stage → 1.0.0
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 +201 -0
- package/README.md +66 -2
- package/dist/asks.d.ts +75 -0
- package/dist/asks.d.ts.map +1 -0
- package/dist/asks.js +103 -0
- package/dist/asks.js.map +1 -0
- package/dist/connect.d.ts +406 -0
- package/dist/connect.d.ts.map +1 -0
- package/dist/connect.js +883 -0
- package/dist/connect.js.map +1 -0
- package/dist/events.d.ts +89 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +36 -0
- package/dist/events.js.map +1 -0
- package/dist/files.d.ts +34 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +78 -0
- package/dist/files.js.map +1 -0
- package/dist/heard.d.ts +22 -0
- package/dist/heard.d.ts.map +1 -0
- package/dist/heard.js +32 -0
- package/dist/heard.js.map +1 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/join.d.ts +101 -0
- package/dist/join.d.ts.map +1 -0
- package/dist/join.js +289 -0
- package/dist/join.js.map +1 -0
- package/dist/keep.d.ts +33 -0
- package/dist/keep.d.ts.map +1 -0
- package/dist/keep.js +160 -0
- package/dist/keep.js.map +1 -0
- package/dist/lane.d.ts +73 -0
- package/dist/lane.d.ts.map +1 -0
- package/dist/lane.js +105 -0
- package/dist/lane.js.map +1 -0
- package/dist/outbox.d.ts +50 -0
- package/dist/outbox.d.ts.map +1 -0
- package/dist/outbox.js +52 -0
- package/dist/outbox.js.map +1 -0
- package/dist/project.d.ts +224 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +619 -0
- package/dist/project.js.map +1 -0
- package/dist/prompt.d.ts +61 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +87 -0
- package/dist/prompt.js.map +1 -0
- package/dist/rules.d.ts +18 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +25 -0
- package/dist/rules.js.map +1 -0
- package/dist/run.d.ts +246 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +295 -0
- package/dist/run.js.map +1 -0
- package/dist/sending.d.ts +78 -0
- package/dist/sending.d.ts.map +1 -0
- package/dist/sending.js +149 -0
- package/dist/sending.js.map +1 -0
- package/dist/service.d.ts +124 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +349 -0
- package/dist/service.js.map +1 -0
- package/dist/settings.d.ts +137 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +228 -0
- package/dist/settings.js.map +1 -0
- package/dist/steps.d.ts +27 -0
- package/dist/steps.d.ts.map +1 -0
- package/dist/steps.js +26 -0
- package/dist/steps.js.map +1 -0
- package/dist/store.d.ts +35 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +52 -0
- package/dist/store.js.map +1 -0
- package/package.json +37 -3
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A harness kept running (setup audit HS-15): a launch agent on a Mac, a systemd user unit on
|
|
3
|
+
* Linux, that runs the bridge again at login and whenever it stops, so closing the terminal it
|
|
4
|
+
* joined from, or restarting the machine, doesn't take it offline in Chips. The CLI keeps
|
|
5
|
+
* `chips serve` running the same way (`cli/src/service.ts`); this is that, for a harness on the
|
|
6
|
+
* SDK, which cannot depend on the CLI.
|
|
7
|
+
*
|
|
8
|
+
* A bridge writes it once it has joined, so the service carries the server's address (`CHIPS_URL`)
|
|
9
|
+
* and finds the key `join()` kept, and needs no link. Each file says it was written here; one
|
|
10
|
+
* without those words is somebody's own, a launch agent written by hand, and is left exactly as
|
|
11
|
+
* it is and said, since its label is the same and a second copy would answer everything twice.
|
|
12
|
+
*
|
|
13
|
+
* A bridge kept on the Node that Chips for Mac carries names the app in its launch agent, so macOS's
|
|
14
|
+
* background-item notice and Login Items say Chips rather than Node (ADR 0218's addendum).
|
|
15
|
+
*
|
|
16
|
+
* What the files say is worked out purely; `keepRunning` and `stopKeeping` write them and run the
|
|
17
|
+
* service manager's commands.
|
|
18
|
+
*/
|
|
19
|
+
import type { Environment } from "./keep.js";
|
|
20
|
+
export type ServiceKind = "launchd" | "systemd";
|
|
21
|
+
/** What to keep running, and how. */
|
|
22
|
+
export interface KeepSpec {
|
|
23
|
+
/** Its label, `chat.chips.<name>`: `chat.chips.hermes`, `chat.chips.acp.codex`. */
|
|
24
|
+
readonly label: string;
|
|
25
|
+
/** The program and its words: `[process.execPath, "--import", "tsx", "src/main.ts"]`. */
|
|
26
|
+
readonly command: readonly [string, ...string[]];
|
|
27
|
+
/** Where it runs from: the bridge's own folder. */
|
|
28
|
+
readonly folder: string;
|
|
29
|
+
/** Its environment: the server it joined, a PATH that finds its agent (`keepEnvironment`). */
|
|
30
|
+
readonly environment: Readonly<Record<string, string>>;
|
|
31
|
+
/** What it says goes here; by default `~/Library/Logs/chips-<name>.log`, or under `~/.local/state/chips`. */
|
|
32
|
+
readonly logFile?: string | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Where the machine keeps things, and which machine it is. */
|
|
35
|
+
export interface Machine {
|
|
36
|
+
readonly platform: string;
|
|
37
|
+
readonly home: string;
|
|
38
|
+
readonly env: Environment;
|
|
39
|
+
}
|
|
40
|
+
/** The service's file, worked out: which manager, where it goes, and what it says. */
|
|
41
|
+
export interface ServiceFile {
|
|
42
|
+
readonly kind: ServiceKind;
|
|
43
|
+
readonly path: string;
|
|
44
|
+
readonly contents: string;
|
|
45
|
+
readonly logFile: string;
|
|
46
|
+
}
|
|
47
|
+
/** A command, as its words. */
|
|
48
|
+
export type Command = readonly [string, ...string[]];
|
|
49
|
+
/** What became of a keep, or a stop. */
|
|
50
|
+
export interface Kept {
|
|
51
|
+
/**
|
|
52
|
+
* `kept` running; `theirs`, a file of somebody's own was there and left; `unsupported`, no
|
|
53
|
+
* manager here; `off`, `CHIPS_KEEP=off` said not to (a test running a card's line as written).
|
|
54
|
+
*/
|
|
55
|
+
readonly state: "kept" | "theirs" | "unsupported" | "off";
|
|
56
|
+
readonly path?: string | undefined;
|
|
57
|
+
readonly logFile?: string | undefined;
|
|
58
|
+
}
|
|
59
|
+
export declare function serviceKind(platform: string): ServiceKind | undefined;
|
|
60
|
+
/** The service's file for `spec` on `machine`, or nothing where there is no service manager. */
|
|
61
|
+
export declare function serviceFile(spec: KeepSpec, given?: Partial<Machine>): ServiceFile | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* The Mac app whose bundle holds `program`, by its bundle identifier: the Node Chips for Mac
|
|
64
|
+
* carries, `Chips.app/Contents/Resources/chips/runtime/node`, is `chat.chips.desktop`'s. Nothing
|
|
65
|
+
* for a program outside an app, or an app whose `Info.plist` doesn't say. macOS names a launch
|
|
66
|
+
* agent after the app it names only when the program is signed by that app's team, which
|
|
67
|
+
* `pnpm desktop` does for the Node it carries.
|
|
68
|
+
*/
|
|
69
|
+
export declare function appHolding(program: string, read?: (path: string) => string): string | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* The launch agent: run from login, run again whenever it stops; credited to `app`, by its bundle
|
|
72
|
+
* identifier, where its program is inside one.
|
|
73
|
+
*/
|
|
74
|
+
export declare function launchdPlist(spec: KeepSpec, logFile: string, app?: string): string;
|
|
75
|
+
/** The systemd user unit: run from login, run again whenever it stops. */
|
|
76
|
+
export declare function systemdUnit(spec: KeepSpec, logFile: string): string;
|
|
77
|
+
/** Run it now: load the agent (afresh, when it is loaded), or enable the unit and start it again. */
|
|
78
|
+
export declare function startCommands(kind: ServiceKind, label: string, path: string, uid: number): readonly Command[];
|
|
79
|
+
/** Stop it, and keep it from starting at the next login. */
|
|
80
|
+
export declare function stopCommands(kind: ServiceKind, label: string, uid: number): readonly Command[];
|
|
81
|
+
/**
|
|
82
|
+
* What a kept bridge needs from the shell it was joined from: the server's address, so `join()`
|
|
83
|
+
* finds the key it kept; the PATH, so its agent's command is found; Chips's own settings (never
|
|
84
|
+
* what was handed over for the run alone, the spent link among them); and the names a bridge asks
|
|
85
|
+
* for, where they are set. Given the `node` it is kept on, that node's folder comes first on the
|
|
86
|
+
* PATH: an agent run as `#!/usr/bin/env node` (an ACP adapter) finds it on a machine with no Node
|
|
87
|
+
* of its own.
|
|
88
|
+
*/
|
|
89
|
+
export declare function keepEnvironment(url: string, env?: Environment, names?: readonly string[], node?: string): Record<string, string>;
|
|
90
|
+
/**
|
|
91
|
+
* The node a kept bridge runs on: the one `chips connect` hands over (`CHIPS_NODE`), named by a
|
|
92
|
+
* path an upgrade of Chips keeps (`~/.local/lib/chips/current/runtime/node`, or inside Chips.app);
|
|
93
|
+
* else the first on the PATH, as `npm start` runs it (`nodeOnPath`).
|
|
94
|
+
*/
|
|
95
|
+
export declare function keptNode(env?: Environment): string;
|
|
96
|
+
/**
|
|
97
|
+
* The node a kept bridge runs on: the first on the PATH, as `npm start` runs it, which is the link
|
|
98
|
+
* a package manager keeps (Homebrew's `/opt/homebrew/bin/node`); `process.execPath` is the
|
|
99
|
+
* version's own folder, which the next upgrade removes, and the service with it. This process's
|
|
100
|
+
* own where none is on the PATH.
|
|
101
|
+
*/
|
|
102
|
+
export declare function nodeOnPath(env?: Environment): string;
|
|
103
|
+
interface Running {
|
|
104
|
+
readonly machine?: Partial<Machine> | undefined;
|
|
105
|
+
/** Runs a command, throwing when it fails, and answers its output; the machine's own by default. */
|
|
106
|
+
readonly run?: ((command: Command) => unknown) | undefined;
|
|
107
|
+
readonly uid?: number | undefined;
|
|
108
|
+
/** How long to wait between tries to load it again while launchd lets the old copy go (250 ms). */
|
|
109
|
+
readonly retryMs?: number | undefined;
|
|
110
|
+
/** Where a word for the person who kept it goes: standard error by default. */
|
|
111
|
+
readonly say?: ((line: string) => void) | undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Write the service and run it, replacing one written here before. A file of somebody's own at
|
|
115
|
+
* that place is left as it is: `theirs`.
|
|
116
|
+
*/
|
|
117
|
+
export declare function keepRunning(spec: KeepSpec, options?: Running): Kept;
|
|
118
|
+
/** Stop a service written here, and remove its file. One of somebody's own is left: `theirs`. */
|
|
119
|
+
export declare function stopKeeping(label: string, options?: Running): {
|
|
120
|
+
readonly state: "stopped" | "none" | "theirs" | "unsupported";
|
|
121
|
+
readonly path?: string;
|
|
122
|
+
};
|
|
123
|
+
export {};
|
|
124
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A harness kept running (setup audit HS-15): a launch agent on a Mac, a systemd user unit on
|
|
3
|
+
* Linux, that runs the bridge again at login and whenever it stops, so closing the terminal it
|
|
4
|
+
* joined from, or restarting the machine, doesn't take it offline in Chips. The CLI keeps
|
|
5
|
+
* `chips serve` running the same way (`cli/src/service.ts`); this is that, for a harness on the
|
|
6
|
+
* SDK, which cannot depend on the CLI.
|
|
7
|
+
*
|
|
8
|
+
* A bridge writes it once it has joined, so the service carries the server's address (`CHIPS_URL`)
|
|
9
|
+
* and finds the key `join()` kept, and needs no link. Each file says it was written here; one
|
|
10
|
+
* without those words is somebody's own, a launch agent written by hand, and is left exactly as
|
|
11
|
+
* it is and said, since its label is the same and a second copy would answer everything twice.
|
|
12
|
+
*
|
|
13
|
+
* A bridge kept on the Node that Chips for Mac carries names the app in its launch agent, so macOS's
|
|
14
|
+
* background-item notice and Login Items say Chips rather than Node (ADR 0218's addendum).
|
|
15
|
+
*
|
|
16
|
+
* What the files say is worked out purely; `keepRunning` and `stopKeeping` write them and run the
|
|
17
|
+
* service manager's commands.
|
|
18
|
+
*/
|
|
19
|
+
import { execFileSync } from "node:child_process";
|
|
20
|
+
import { accessSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
21
|
+
import { homedir } from "node:os";
|
|
22
|
+
import { delimiter, dirname, join } from "node:path";
|
|
23
|
+
import { reportStep } from "./steps.js";
|
|
24
|
+
const MARK = "Written by a Chips harness's keep";
|
|
25
|
+
export function serviceKind(platform) {
|
|
26
|
+
if (platform === "darwin")
|
|
27
|
+
return "launchd";
|
|
28
|
+
if (platform === "linux")
|
|
29
|
+
return "systemd";
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const machineOf = (given = {}) => ({
|
|
33
|
+
platform: given.platform ?? process.platform,
|
|
34
|
+
home: given.home ?? homedir(),
|
|
35
|
+
// biome-ignore lint/style/noProcessEnv: the environment is where the machine says where things go.
|
|
36
|
+
env: given.env ?? process.env,
|
|
37
|
+
});
|
|
38
|
+
/** `chat.chips.acp.codex` → `chips-acp-codex`: the name its log is kept under. */
|
|
39
|
+
const logName = (label) => `${label.replace(/^chat\.chips\./, "chips-").replace(/\./g, "-")}.log`;
|
|
40
|
+
/** The service's file for `spec` on `machine`, or nothing where there is no service manager. */
|
|
41
|
+
export function serviceFile(spec, given = {}) {
|
|
42
|
+
const machine = machineOf(given);
|
|
43
|
+
const kind = serviceKind(machine.platform);
|
|
44
|
+
if (kind === undefined)
|
|
45
|
+
return undefined;
|
|
46
|
+
if (kind === "launchd") {
|
|
47
|
+
const logFile = spec.logFile ?? join(machine.home, "Library", "Logs", logName(spec.label));
|
|
48
|
+
const path = join(machine.home, "Library", "LaunchAgents", `${spec.label}.plist`);
|
|
49
|
+
return {
|
|
50
|
+
kind,
|
|
51
|
+
path,
|
|
52
|
+
logFile,
|
|
53
|
+
contents: launchdPlist(spec, logFile, appHolding(spec.command[0])),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const xdg = (name, fallback) => {
|
|
57
|
+
const set = machine.env[name];
|
|
58
|
+
return set !== undefined && set !== "" ? set : join(machine.home, fallback);
|
|
59
|
+
};
|
|
60
|
+
const logFile = spec.logFile ?? join(xdg("XDG_STATE_HOME", ".local/state"), "chips", logName(spec.label));
|
|
61
|
+
const path = join(xdg("XDG_CONFIG_HOME", ".config"), "systemd", "user", `${spec.label}.service`);
|
|
62
|
+
return { kind, path, logFile, contents: systemdUnit(spec, logFile) };
|
|
63
|
+
}
|
|
64
|
+
const xml = (text) => text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
65
|
+
/**
|
|
66
|
+
* The Mac app whose bundle holds `program`, by its bundle identifier: the Node Chips for Mac
|
|
67
|
+
* carries, `Chips.app/Contents/Resources/chips/runtime/node`, is `chat.chips.desktop`'s. Nothing
|
|
68
|
+
* for a program outside an app, or an app whose `Info.plist` doesn't say. macOS names a launch
|
|
69
|
+
* agent after the app it names only when the program is signed by that app's team, which
|
|
70
|
+
* `pnpm desktop` does for the Node it carries.
|
|
71
|
+
*/
|
|
72
|
+
export function appHolding(program, read = (path) => readFileSync(path, "utf8")) {
|
|
73
|
+
const app = /^(.+?\.app)\/Contents\//.exec(program)?.[1];
|
|
74
|
+
if (app === undefined)
|
|
75
|
+
return undefined;
|
|
76
|
+
try {
|
|
77
|
+
const info = read(join(app, "Contents", "Info.plist"));
|
|
78
|
+
return /<key>CFBundleIdentifier<\/key>\s*<string>([^<]+)<\/string>/.exec(info)?.[1];
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/** `AssociatedBundleIdentifiers`, naming the app the agent is credited to, when there is one. */
|
|
85
|
+
const associatedApp = (app) => app === undefined
|
|
86
|
+
? ""
|
|
87
|
+
: ` <key>AssociatedBundleIdentifiers</key>\n <array>\n <string>${xml(app)}</string>\n </array>\n`;
|
|
88
|
+
/**
|
|
89
|
+
* The launch agent: run from login, run again whenever it stops; credited to `app`, by its bundle
|
|
90
|
+
* identifier, where its program is inside one.
|
|
91
|
+
*/
|
|
92
|
+
export function launchdPlist(spec, logFile, app) {
|
|
93
|
+
const args = spec.command.map((word) => ` <string>${xml(word)}</string>`).join("\n");
|
|
94
|
+
const env = Object.entries(spec.environment)
|
|
95
|
+
.map(([key, value]) => ` <key>${xml(key)}</key>\n <string>${xml(value)}</string>`)
|
|
96
|
+
.join("\n");
|
|
97
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
98
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
99
|
+
<!-- ${MARK}. Its bridge's \`npm run keep -- --stop\` stops it and removes this file. -->
|
|
100
|
+
<plist version="1.0">
|
|
101
|
+
<dict>
|
|
102
|
+
<key>Label</key>
|
|
103
|
+
<string>${xml(spec.label)}</string>
|
|
104
|
+
${associatedApp(app)} <key>ProgramArguments</key>
|
|
105
|
+
<array>
|
|
106
|
+
${args}
|
|
107
|
+
</array>
|
|
108
|
+
<key>WorkingDirectory</key>
|
|
109
|
+
<string>${xml(spec.folder)}</string>
|
|
110
|
+
<key>EnvironmentVariables</key>
|
|
111
|
+
<dict>
|
|
112
|
+
${env}
|
|
113
|
+
</dict>
|
|
114
|
+
<key>RunAtLoad</key>
|
|
115
|
+
<true/>
|
|
116
|
+
<key>KeepAlive</key>
|
|
117
|
+
<true/>
|
|
118
|
+
<key>StandardOutPath</key>
|
|
119
|
+
<string>${xml(logFile)}</string>
|
|
120
|
+
<key>StandardErrorPath</key>
|
|
121
|
+
<string>${xml(logFile)}</string>
|
|
122
|
+
</dict>
|
|
123
|
+
</plist>
|
|
124
|
+
`;
|
|
125
|
+
}
|
|
126
|
+
/** The systemd user unit: run from login, run again whenever it stops. */
|
|
127
|
+
export function systemdUnit(spec, logFile) {
|
|
128
|
+
const quote = (value) => `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
129
|
+
const env = Object.entries(spec.environment)
|
|
130
|
+
.map(([key, value]) => `Environment=${quote(`${key}=${value}`)}`)
|
|
131
|
+
.join("\n");
|
|
132
|
+
return `# ${MARK}. Its bridge's \`npm run keep -- --stop\` stops it and removes this file.
|
|
133
|
+
[Unit]
|
|
134
|
+
Description=${spec.label}
|
|
135
|
+
After=network-online.target
|
|
136
|
+
|
|
137
|
+
[Service]
|
|
138
|
+
ExecStart=${spec.command.map(quote).join(" ")}
|
|
139
|
+
WorkingDirectory=${quote(spec.folder)}
|
|
140
|
+
${env}
|
|
141
|
+
Restart=always
|
|
142
|
+
RestartSec=5
|
|
143
|
+
StandardOutput=append:${logFile}
|
|
144
|
+
StandardError=append:${logFile}
|
|
145
|
+
|
|
146
|
+
[Install]
|
|
147
|
+
WantedBy=default.target
|
|
148
|
+
`;
|
|
149
|
+
}
|
|
150
|
+
/** Run it now: load the agent (afresh, when it is loaded), or enable the unit and start it again. */
|
|
151
|
+
export function startCommands(kind, label, path, uid) {
|
|
152
|
+
if (kind === "launchd") {
|
|
153
|
+
return [
|
|
154
|
+
["launchctl", "enable", `gui/${uid}/${label}`],
|
|
155
|
+
["launchctl", "bootout", `gui/${uid}/${label}`],
|
|
156
|
+
["launchctl", "bootstrap", `gui/${uid}`, path],
|
|
157
|
+
];
|
|
158
|
+
}
|
|
159
|
+
return [
|
|
160
|
+
["systemctl", "--user", "daemon-reload"],
|
|
161
|
+
["systemctl", "--user", "enable", `${label}.service`],
|
|
162
|
+
["systemctl", "--user", "restart", `${label}.service`],
|
|
163
|
+
];
|
|
164
|
+
}
|
|
165
|
+
/** Stop it, and keep it from starting at the next login. */
|
|
166
|
+
export function stopCommands(kind, label, uid) {
|
|
167
|
+
if (kind === "launchd")
|
|
168
|
+
return [["launchctl", "bootout", `gui/${uid}/${label}`]];
|
|
169
|
+
return [["systemctl", "--user", "disable", "--now", `${label}.service`]];
|
|
170
|
+
}
|
|
171
|
+
/** Unloading an agent that isn't loaded is how a first start begins, and how a second stop ends. */
|
|
172
|
+
const mayFail = (command) => command[0] === "launchctl" && command[1] === "bootout";
|
|
173
|
+
/**
|
|
174
|
+
* What `chips connect` hands a bridge for this run alone (ADR 0218): the link, which is spent once
|
|
175
|
+
* taken up; the Node to keep it on and the line that stops it, which keep has used by the time it
|
|
176
|
+
* writes the service; and the steps it reports, which only that `chips connect` reads.
|
|
177
|
+
*/
|
|
178
|
+
const HANDED_OVER = new Set([
|
|
179
|
+
"CHIPS_JOIN_LINK",
|
|
180
|
+
"CHIPS_NODE",
|
|
181
|
+
"CHIPS_STOP_COMMAND",
|
|
182
|
+
"CHIPS_STEPS",
|
|
183
|
+
]);
|
|
184
|
+
/**
|
|
185
|
+
* What a kept bridge needs from the shell it was joined from: the server's address, so `join()`
|
|
186
|
+
* finds the key it kept; the PATH, so its agent's command is found; Chips's own settings (never
|
|
187
|
+
* what was handed over for the run alone, the spent link among them); and the names a bridge asks
|
|
188
|
+
* for, where they are set. Given the `node` it is kept on, that node's folder comes first on the
|
|
189
|
+
* PATH: an agent run as `#!/usr/bin/env node` (an ACP adapter) finds it on a machine with no Node
|
|
190
|
+
* of its own.
|
|
191
|
+
*/
|
|
192
|
+
export function keepEnvironment(url,
|
|
193
|
+
// biome-ignore lint/style/noProcessEnv: the shell it joined from is what it takes with it.
|
|
194
|
+
env = process.env, names = [], node) {
|
|
195
|
+
const kept = { CHIPS_URL: url };
|
|
196
|
+
for (const [name, value] of Object.entries(env)) {
|
|
197
|
+
if (value === undefined || value === "")
|
|
198
|
+
continue;
|
|
199
|
+
if (name === "PATH" ||
|
|
200
|
+
names.includes(name) ||
|
|
201
|
+
(name.startsWith("CHIPS_") && !HANDED_OVER.has(name)))
|
|
202
|
+
kept[name] = value;
|
|
203
|
+
}
|
|
204
|
+
kept["CHIPS_URL"] = url;
|
|
205
|
+
if (node !== undefined)
|
|
206
|
+
kept["PATH"] = nodeFirst(dirname(node), kept["PATH"]);
|
|
207
|
+
return kept;
|
|
208
|
+
}
|
|
209
|
+
/** `folder` first on a PATH, and nowhere else on it. */
|
|
210
|
+
function nodeFirst(folder, path) {
|
|
211
|
+
const rest = (path ?? "").split(delimiter).filter((each) => each !== "" && each !== folder);
|
|
212
|
+
return [folder, ...rest].join(delimiter);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* The node a kept bridge runs on: the one `chips connect` hands over (`CHIPS_NODE`), named by a
|
|
216
|
+
* path an upgrade of Chips keeps (`~/.local/lib/chips/current/runtime/node`, or inside Chips.app);
|
|
217
|
+
* else the first on the PATH, as `npm start` runs it (`nodeOnPath`).
|
|
218
|
+
*/
|
|
219
|
+
export function keptNode(
|
|
220
|
+
// biome-ignore lint/style/noProcessEnv: `chips connect` hands its Node over in the environment.
|
|
221
|
+
env = process.env) {
|
|
222
|
+
const given = env["CHIPS_NODE"];
|
|
223
|
+
return given !== undefined && given !== "" ? given : nodeOnPath(env);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* The node a kept bridge runs on: the first on the PATH, as `npm start` runs it, which is the link
|
|
227
|
+
* a package manager keeps (Homebrew's `/opt/homebrew/bin/node`); `process.execPath` is the
|
|
228
|
+
* version's own folder, which the next upgrade removes, and the service with it. This process's
|
|
229
|
+
* own where none is on the PATH.
|
|
230
|
+
*/
|
|
231
|
+
export function nodeOnPath(
|
|
232
|
+
// biome-ignore lint/style/noProcessEnv: the shell it joined from is what it takes with it.
|
|
233
|
+
env = process.env) {
|
|
234
|
+
for (const folder of (env["PATH"] ?? "").split(delimiter)) {
|
|
235
|
+
if (folder === "")
|
|
236
|
+
continue;
|
|
237
|
+
try {
|
|
238
|
+
accessSync(join(folder, "node"), constants.X_OK);
|
|
239
|
+
return join(folder, "node");
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
// Not here.
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return process.execPath;
|
|
246
|
+
}
|
|
247
|
+
/** Wait here: the service's file and commands are all synchronous, and a bridge does nothing meanwhile. */
|
|
248
|
+
const pause = (ms) => Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
249
|
+
/** Tries at loading the launch agent: `bootout` returns before a running bridge has gone. */
|
|
250
|
+
const LOAD_TRIES = 40;
|
|
251
|
+
const runOf = (options) => options.run ??
|
|
252
|
+
((command) => execFileSync(command[0], command.slice(1), {
|
|
253
|
+
encoding: "utf8",
|
|
254
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
255
|
+
}));
|
|
256
|
+
const ours = (path) => !existsSync(path) || readFileSync(path, "utf8").includes(MARK);
|
|
257
|
+
/** One command run, tried again while launchd lets a stopped copy go, and let fail where that's fine. */
|
|
258
|
+
function runOne(command, run, retryMs) {
|
|
259
|
+
// `launchctl bootout` returns while the copy it stops is still going, and loading again before
|
|
260
|
+
// it has gone fails (status 5): try again, for about ten seconds.
|
|
261
|
+
const tries = command[0] === "launchctl" && command[1] === "bootstrap" ? LOAD_TRIES : 1;
|
|
262
|
+
for (let tried = 1;; tried += 1) {
|
|
263
|
+
try {
|
|
264
|
+
run(command);
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
if (mayFail(command))
|
|
269
|
+
return;
|
|
270
|
+
if (tried >= tries)
|
|
271
|
+
throw error;
|
|
272
|
+
pause(retryMs);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/** The commands, in order, on the machine's own manager unless `options.run` says otherwise. */
|
|
277
|
+
function runAll(commands, options) {
|
|
278
|
+
const run = runOf(options);
|
|
279
|
+
for (const command of commands)
|
|
280
|
+
runOne(command, run, options.retryMs ?? 250);
|
|
281
|
+
}
|
|
282
|
+
const uidOf = (options) => options.uid ?? process.getuid?.() ?? 0;
|
|
283
|
+
/**
|
|
284
|
+
* On Linux, a user's units run only while they are logged in, unless systemd keeps that user's
|
|
285
|
+
* manager running from boot ("lingering"), which `chips up` turns on for the server
|
|
286
|
+
* (`cli/src/service.ts`); this is that, for a harness on a machine that only runs one. Asked first,
|
|
287
|
+
* because turning it on over SSH is refused even when it is on; then turned on, which a local
|
|
288
|
+
* session may do without a password. False when it is off and stays off.
|
|
289
|
+
*/
|
|
290
|
+
function lingers(options) {
|
|
291
|
+
const run = runOf(options);
|
|
292
|
+
const uid = String(uidOf(options));
|
|
293
|
+
try {
|
|
294
|
+
const on = run(["loginctl", "show-user", uid, "--property=Linger", "--value"]);
|
|
295
|
+
if (typeof on === "string" && on.trim() === "yes")
|
|
296
|
+
return true;
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
// Not answered: turning it on may work all the same.
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
run(["loginctl", "enable-linger", uid]);
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
catch {
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** Where keep's word to the person goes: standard error, beside the bridge's own. */
|
|
310
|
+
const sayOf = (options) => options.say ?? ((line) => void process.stderr.write(`${line}\n`));
|
|
311
|
+
/**
|
|
312
|
+
* Write the service and run it, replacing one written here before. A file of somebody's own at
|
|
313
|
+
* that place is left as it is: `theirs`.
|
|
314
|
+
*/
|
|
315
|
+
export function keepRunning(spec, options = {}) {
|
|
316
|
+
// A test runs a card's line as a person does, and must never leave a real service behind.
|
|
317
|
+
if (machineOf(options.machine).env["CHIPS_KEEP"] === "off")
|
|
318
|
+
return { state: "off" };
|
|
319
|
+
const file = serviceFile(spec, options.machine);
|
|
320
|
+
if (file === undefined)
|
|
321
|
+
return { state: "unsupported" };
|
|
322
|
+
if (!ours(file.path))
|
|
323
|
+
return { state: "theirs", path: file.path, logFile: file.logFile };
|
|
324
|
+
reportStep("keeping", { label: spec.label }, machineOf(options.machine).env);
|
|
325
|
+
mkdirSync(dirname(file.path), { recursive: true });
|
|
326
|
+
mkdirSync(dirname(file.logFile), { recursive: true });
|
|
327
|
+
// Read by its user only: a bridge may carry a password its harness needs.
|
|
328
|
+
writeFileSync(file.path, file.contents, { mode: 0o600 });
|
|
329
|
+
chmodSync(file.path, 0o600);
|
|
330
|
+
runAll(startCommands(file.kind, spec.label, file.path, uidOf(options)), options);
|
|
331
|
+
if (file.kind === "systemd" && !lingers(options)) {
|
|
332
|
+
sayOf(options)("It stops when you log out. To keep it running on a machine nobody logs in to, run this once: sudo loginctl enable-linger $USER");
|
|
333
|
+
}
|
|
334
|
+
return { state: "kept", path: file.path, logFile: file.logFile };
|
|
335
|
+
}
|
|
336
|
+
/** Stop a service written here, and remove its file. One of somebody's own is left: `theirs`. */
|
|
337
|
+
export function stopKeeping(label, options = {}) {
|
|
338
|
+
const file = serviceFile({ label, command: ["-"], folder: "/", environment: {} }, options.machine);
|
|
339
|
+
if (file === undefined)
|
|
340
|
+
return { state: "unsupported" };
|
|
341
|
+
if (!existsSync(file.path))
|
|
342
|
+
return { state: "none", path: file.path };
|
|
343
|
+
if (!ours(file.path))
|
|
344
|
+
return { state: "theirs", path: file.path };
|
|
345
|
+
runAll(stopCommands(file.kind, label, uidOf(options)), options);
|
|
346
|
+
rmSync(file.path);
|
|
347
|
+
return { state: "stopped", path: file.path };
|
|
348
|
+
}
|
|
349
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a person changes about an agent from its page, kept by the harness (ADRs 0134, 0140, 0143,
|
|
3
|
+
* 0146): its context files, its model and effort, its heartbeat, its context window; and the jobs
|
|
4
|
+
* the harness runs on its own, from the harness's page (ADR 0252). One pattern five times. The harness sends its copy (`put…`) when it connects and whenever it changes on its
|
|
5
|
+
* own side; a person's change arrives as a frame, now or never; the harness makes it in its own way
|
|
6
|
+
* and answers with the copy as it is now. Here a handler does the making and returns the copy, and
|
|
7
|
+
* the answer — `answers`, or `refuses` when the handler throws — is sent for it.
|
|
8
|
+
*/
|
|
9
|
+
import { type AgentContextPut, type AgentContextWindowPut, type AgentHeartbeatPut, type AgentModelPut, type ContextEditFrame, type HarnessContextPut, type HarnessJobsPut, type HeartbeatChangeFrame, type JobChangeFrame, type JobRun, type ModelChangeFrame, type WindowChangeFrame, type WindowCompactFrame } from "@chipschat/protocol";
|
|
10
|
+
type Answered = "answers" | "refuses";
|
|
11
|
+
/** An agent's files, as `PUT /v1/agents/:id/context` takes them, without the answer. */
|
|
12
|
+
export type AgentContextCopy = Omit<AgentContextPut, Answered>;
|
|
13
|
+
/** The harness's own shared set, as `PUT /v1/harnesses/:id/context` takes it. */
|
|
14
|
+
export type HarnessContextCopy = Omit<HarnessContextPut, Answered>;
|
|
15
|
+
export type AgentModelCopy = Omit<AgentModelPut, Answered>;
|
|
16
|
+
export type AgentHeartbeatCopy = Omit<AgentHeartbeatPut, Answered>;
|
|
17
|
+
export type AgentContextWindowCopy = Omit<AgentContextWindowPut, Answered>;
|
|
18
|
+
/** The jobs the harness runs on its own, as `PUT /v1/harnesses/:id/jobs` takes them. */
|
|
19
|
+
export type HarnessJobsCopy = Omit<HarnessJobsPut, Answered>;
|
|
20
|
+
/**
|
|
21
|
+
* A change the harness won't or can't make. Throw it from a handler with the copy as it is now:
|
|
22
|
+
* the person is told `message`, and sees the copy. Anything else thrown refuses the same way, with
|
|
23
|
+
* the copy last sent for that agent, and its message.
|
|
24
|
+
*/
|
|
25
|
+
export declare class Refuse extends Error {
|
|
26
|
+
/** The copy as it is now. Absent: the one last sent for that agent. */
|
|
27
|
+
readonly copy?: unknown | undefined;
|
|
28
|
+
/** For a context file only: `changed` when the file moved on since the person's version. */
|
|
29
|
+
readonly reason?: "changed" | "failed" | undefined;
|
|
30
|
+
readonly name = "Refuse";
|
|
31
|
+
constructor(message: string,
|
|
32
|
+
/** The copy as it is now. Absent: the one last sent for that agent. */
|
|
33
|
+
copy?: unknown | undefined,
|
|
34
|
+
/** For a context file only: `changed` when the file moved on since the person's version. */
|
|
35
|
+
reason?: "changed" | "failed" | undefined);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The handlers a harness gives `connect({ settings })`, each for a capability it declares. Giving
|
|
39
|
+
* one says the matching word in the socket's `hello` (`context`, `models`, `heartbeats`,
|
|
40
|
+
* `context_windows`), so Chips sends that frame here; leaving it out, Chips never does.
|
|
41
|
+
*/
|
|
42
|
+
export interface SettingsHandlers {
|
|
43
|
+
/**
|
|
44
|
+
* A person changed a context file (ADR 0134): an agent's, or the harness's own set when
|
|
45
|
+
* `agent_id` is absent. Save it, then return the copy it is in now: the agent's files, or the
|
|
46
|
+
* shared set. `base_hash: null` asks to give the agent its own copy of a shared file. When the
|
|
47
|
+
* file changed since `base_hash`, throw `new Refuse(words, copy, "changed")`.
|
|
48
|
+
*/
|
|
49
|
+
readonly context?: ((edit: ContextEditFrame) => Promise<AgentContextCopy | HarnessContextCopy>) | undefined;
|
|
50
|
+
/** A person changed an agent's model or effort (ADR 0140); `model: null` is the default. */
|
|
51
|
+
readonly models?: ((change: ModelChangeFrame) => Promise<AgentModelCopy>) | undefined;
|
|
52
|
+
/** A person switched an agent's heartbeat or changed how often it beats (ADR 0143). */
|
|
53
|
+
readonly heartbeats?: ((change: HeartbeatChangeFrame) => Promise<AgentHeartbeatCopy>) | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* A person asked an agent to compact now, or changed the limit it compacts itself at (ADR
|
|
56
|
+
* 0146). For a compaction, return the copy at once with `compacting` set, and `put` it again
|
|
57
|
+
* when it is done.
|
|
58
|
+
*/
|
|
59
|
+
readonly contextWindows?: {
|
|
60
|
+
readonly compact: (ask: WindowCompactFrame) => Promise<AgentContextWindowCopy>;
|
|
61
|
+
readonly change: (ask: WindowChangeFrame) => Promise<AgentContextWindowCopy>;
|
|
62
|
+
} | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* A person switched one of the jobs the harness runs on its own, or changed how often it runs
|
|
65
|
+
* (ADR 0252). Make it, then return the copy of all its jobs as they are now.
|
|
66
|
+
*/
|
|
67
|
+
readonly jobs?: ((change: JobChangeFrame) => Promise<HarnessJobsCopy>) | undefined;
|
|
68
|
+
}
|
|
69
|
+
/** What `hello.accepts` says for these handlers, beside `restart` for a restart handler. */
|
|
70
|
+
export declare function acceptsFor(handlers: SettingsHandlers | undefined): string[];
|
|
71
|
+
/** A `PUT` to chipsd with the harness's token, as the connection makes it. */
|
|
72
|
+
export type Put = (path: string, body: Readonly<Record<string, unknown>>) => Promise<unknown>;
|
|
73
|
+
/**
|
|
74
|
+
* The harness's copies, sent and remembered: `chips.settings`. Each `put` sends the whole copy;
|
|
75
|
+
* the last one sent for each agent is what a refusal carries when a handler gives none. A copy
|
|
76
|
+
* the same as the last one Chips took for that agent is not sent again, unless it answers a
|
|
77
|
+
* person, so a harness may send its copies as often as it reads them; and one agent's copies of
|
|
78
|
+
* a kind go one after another, so a later one never lands before an earlier one.
|
|
79
|
+
*/
|
|
80
|
+
export declare class Settings {
|
|
81
|
+
private readonly put;
|
|
82
|
+
private readonly harnessId;
|
|
83
|
+
private readonly handlers;
|
|
84
|
+
/** A `POST` to chipsd with the harness's token, for its jobs' runs. */
|
|
85
|
+
private readonly post?;
|
|
86
|
+
/** The copy last given for each `kind:id`, for a refusal to carry. */
|
|
87
|
+
private readonly sent;
|
|
88
|
+
/** The copy Chips last took for each `kind:id`, as JSON. */
|
|
89
|
+
private readonly landed;
|
|
90
|
+
private readonly chains;
|
|
91
|
+
constructor(put: Put, harnessId: () => string, handlers: SettingsHandlers | undefined,
|
|
92
|
+
/** A `POST` to chipsd with the harness's token, for its jobs' runs. */
|
|
93
|
+
post?: Put | undefined);
|
|
94
|
+
/** An agent's context files (`context_files`). */
|
|
95
|
+
context(agentId: string, copy: AgentContextCopy): Promise<unknown>;
|
|
96
|
+
/** The harness's own shared set, which its agents read or start from (`context_files`). */
|
|
97
|
+
harnessContext(copy: HarnessContextCopy): Promise<unknown>;
|
|
98
|
+
/** An agent's model and effort, what it may run on instead, and the words for each (`models`). */
|
|
99
|
+
model(agentId: string, copy: AgentModelCopy): Promise<unknown>;
|
|
100
|
+
/** An agent's heartbeat (`heartbeats`). */
|
|
101
|
+
heartbeat(agentId: string, copy: AgentHeartbeatCopy): Promise<unknown>;
|
|
102
|
+
/** An agent's context window: how full, its limit, its last compaction (`context_windows`). */
|
|
103
|
+
contextWindow(agentId: string, copy: AgentContextWindowCopy): Promise<unknown>;
|
|
104
|
+
/** The jobs the harness runs on its own, all of them (`jobs`). */
|
|
105
|
+
jobs(copy: HarnessJobsCopy): Promise<unknown>;
|
|
106
|
+
/**
|
|
107
|
+
* Runs of its jobs the harness finished (`jobs`), two hundred to a post. A run sent again says
|
|
108
|
+
* what it says over the one before, and what it leaves out stays, so send it once more when its
|
|
109
|
+
* cost is known, and again without one does no harm. Send the copy first:
|
|
110
|
+
* Chips refuses runs of a job its copy doesn't list.
|
|
111
|
+
*/
|
|
112
|
+
jobRuns(runs: readonly JobRun[]): Promise<void>;
|
|
113
|
+
/** An agent deleted: nothing is remembered of it, so a copy for an agent made again is sent. */
|
|
114
|
+
forget(agentId: string): void;
|
|
115
|
+
/**
|
|
116
|
+
* A compaction taken (its handler returned) that then failed: the ask refused after all, with
|
|
117
|
+
* the harness's words, beside the copy as it is now, or the one last sent.
|
|
118
|
+
*/
|
|
119
|
+
contextWindowFailed(agentId: string, changeId: string, message: string, copy?: AgentContextWindowCopy): Promise<unknown>;
|
|
120
|
+
/**
|
|
121
|
+
* A frame from Chips, if it is one of these: read by its schema (SEC-14), handed to its handler
|
|
122
|
+
* and answered. The answer's promise, which never rejects; nothing for any other frame, and
|
|
123
|
+
* nothing for a frame that is not what it says it is.
|
|
124
|
+
*/
|
|
125
|
+
hear(frame: Readonly<Record<string, unknown>>): Promise<void> | undefined;
|
|
126
|
+
/** One of the frames read, handed to its handler and answered. */
|
|
127
|
+
private heard;
|
|
128
|
+
private send;
|
|
129
|
+
/**
|
|
130
|
+
* Make the change with its handler and answer with the copy: `answers` when it returns,
|
|
131
|
+
* `refuses` when it throws. With no handler and no copy ever sent there is nothing to answer
|
|
132
|
+
* with, and the person is told it was missed after a minute.
|
|
133
|
+
*/
|
|
134
|
+
private answer;
|
|
135
|
+
}
|
|
136
|
+
export {};
|
|
137
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|