@aeolus-fleet/trierarch 0.33.1 → 0.34.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/README.md +7 -4
- package/dist/adapters/claude-code-setup.d.ts +11 -0
- package/dist/adapters/claude-code-setup.js +60 -0
- package/dist/adapters/claude-code-setup.js.map +1 -1
- package/dist/adapters/claude-code.d.ts +21 -18
- package/dist/adapters/claude-code.js +46 -36
- package/dist/adapters/claude-code.js.map +1 -1
- package/dist/adapters/codex-setup.d.ts +2 -0
- package/dist/adapters/codex-setup.js +6 -0
- package/dist/adapters/codex-setup.js.map +1 -1
- package/dist/adapters/codex.d.ts +2 -0
- package/dist/adapters/codex.js +31 -3
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/container.d.ts +36 -15
- package/dist/adapters/container.js +72 -93
- package/dist/adapters/container.js.map +1 -1
- package/dist/adapters/copilot-detector.d.ts +13 -0
- package/dist/adapters/copilot-detector.js +62 -0
- package/dist/adapters/copilot-detector.js.map +1 -0
- package/dist/adapters/copilot.d.ts +79 -0
- package/dist/adapters/copilot.js +187 -0
- package/dist/adapters/copilot.js.map +1 -0
- package/dist/adapters/detectors.js +6 -0
- package/dist/adapters/detectors.js.map +1 -1
- package/dist/adapters/files.d.ts +16 -0
- package/dist/adapters/files.js +5 -0
- package/dist/adapters/files.js.map +1 -1
- package/dist/adapters/harnesses.d.ts +3 -2
- package/dist/adapters/harnesses.js +21 -9
- package/dist/adapters/harnesses.js.map +1 -1
- package/dist/adapters/hold-runtime.d.ts +19 -5
- package/dist/adapters/hold-runtime.js +23 -10
- package/dist/adapters/hold-runtime.js.map +1 -1
- package/dist/adapters/hold.d.ts +12 -0
- package/dist/adapters/hold.js +66 -31
- package/dist/adapters/hold.js.map +1 -1
- package/dist/adapters/json-state.js +4 -0
- package/dist/adapters/json-state.js.map +1 -1
- package/dist/adapters/key-files.d.ts +16 -0
- package/dist/adapters/key-files.js +28 -0
- package/dist/adapters/key-files.js.map +1 -0
- package/dist/adapters/key-states.d.ts +21 -0
- package/dist/adapters/key-states.js +43 -0
- package/dist/adapters/key-states.js.map +1 -0
- package/dist/adapters/model-logins.d.ts +21 -0
- package/dist/adapters/model-logins.js +48 -0
- package/dist/adapters/model-logins.js.map +1 -0
- package/dist/adapters/model-proxy.d.ts +32 -0
- package/dist/adapters/model-proxy.js +171 -0
- package/dist/adapters/model-proxy.js.map +1 -0
- package/dist/adapters/paths.d.ts +4 -0
- package/dist/adapters/paths.js +2 -0
- package/dist/adapters/paths.js.map +1 -1
- package/dist/adapters/plugin.d.ts +11 -8
- package/dist/adapters/plugin.js +47 -13
- package/dist/adapters/plugin.js.map +1 -1
- package/dist/adapters/proxy-runtime.d.ts +31 -0
- package/dist/adapters/proxy-runtime.js +100 -0
- package/dist/adapters/proxy-runtime.js.map +1 -0
- package/dist/adapters/proxy-tokens.d.ts +25 -0
- package/dist/adapters/proxy-tokens.js +67 -0
- package/dist/adapters/proxy-tokens.js.map +1 -0
- package/dist/adapters/runtime-adapters.d.ts +11 -6
- package/dist/adapters/runtime-adapters.js +25 -11
- package/dist/adapters/runtime-adapters.js.map +1 -1
- package/dist/adapters/service.d.ts +1 -1
- package/dist/adapters/service.js +2 -2
- package/dist/adapters/service.js.map +1 -1
- package/dist/adapters/trust.d.ts +2 -1
- package/dist/adapters/trust.js +4 -1
- package/dist/adapters/trust.js.map +1 -1
- package/dist/adapters/vendor-answers.d.ts +6 -0
- package/dist/adapters/vendor-answers.js +38 -0
- package/dist/adapters/vendor-answers.js.map +1 -0
- package/dist/adapters/vendor-key-check.d.ts +23 -0
- package/dist/adapters/vendor-key-check.js +36 -0
- package/dist/adapters/vendor-key-check.js.map +1 -0
- package/dist/bin/aeolus-trierarch.js +7 -2
- package/dist/bin/aeolus-trierarch.js.map +1 -1
- package/dist/cli/add.d.ts +2 -2
- package/dist/cli/config-check.js +1 -1
- package/dist/cli/config-check.js.map +1 -1
- package/dist/cli/hold.js +13 -4
- package/dist/cli/hold.js.map +1 -1
- package/dist/cli/login.d.ts +72 -0
- package/dist/cli/login.js +114 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/main.js +85 -5
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/proxy.d.ts +2 -0
- package/dist/cli/proxy.js +58 -0
- package/dist/cli/proxy.js.map +1 -0
- package/dist/cli/run.js +30 -4
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/upgrade.d.ts +2 -2
- package/dist/cli/upgrade.js +2 -2
- package/dist/core/argo-reports.d.ts +10 -0
- package/dist/core/argo-reports.js +17 -0
- package/dist/core/argo-reports.js.map +1 -1
- package/dist/core/check-session-runtime.js +3 -1
- package/dist/core/check-session-runtime.js.map +1 -1
- package/dist/core/check-settings.d.ts +2 -0
- package/dist/core/check-settings.js +6 -1
- package/dist/core/check-settings.js.map +1 -1
- package/dist/core/entry.d.ts +12 -0
- package/dist/core/entry.js.map +1 -1
- package/dist/core/login.d.ts +28 -0
- package/dist/core/login.js +14 -0
- package/dist/core/login.js.map +1 -0
- package/dist/core/ports.d.ts +33 -1
- package/dist/core/reconciler.d.ts +5 -0
- package/dist/core/reconciler.js +12 -7
- package/dist/core/reconciler.js.map +1 -1
- package/dist/core/report-self.js +9 -3
- package/dist/core/report-self.js.map +1 -1
- package/dist/core/run-pass.d.ts +6 -1
- package/dist/core/run-pass.js +81 -13
- package/dist/core/run-pass.js.map +1 -1
- package/package.json +1 -2
- package/dist/adapters/claude-code-screen.d.ts +0 -1
- package/dist/adapters/claude-code-screen.js +0 -22
- package/dist/adapters/claude-code-screen.js.map +0 -1
- package/dist/adapters/held-command.d.ts +0 -13
- package/dist/adapters/held-command.js +0 -16
- package/dist/adapters/held-command.js.map +0 -1
- package/dist/adapters/launch-screen.d.ts +0 -14
- package/dist/adapters/launch-screen.js +0 -5
- package/dist/adapters/launch-screen.js.map +0 -1
- package/dist/adapters/stop-turn.d.ts +0 -13
- package/dist/adapters/stop-turn.js +0 -26
- package/dist/adapters/stop-turn.js.map +0 -1
- package/dist/adapters/tmux.d.ts +0 -13
- package/dist/adapters/tmux.js +0 -33
- package/dist/adapters/tmux.js.map +0 -1
package/dist/adapters/codex.js
CHANGED
|
@@ -6,6 +6,7 @@ import { firstPromptOf, wakePromptOf } from '../core/no-terminal-questions.js';
|
|
|
6
6
|
import { parsedLine } from './hold-protocol.js';
|
|
7
7
|
import { createLaunchMarks } from './launch-marker.js';
|
|
8
8
|
import { createPluginIdentity } from './plugin-identity.js';
|
|
9
|
+
import { newProxyToken } from './proxy-tokens.js';
|
|
9
10
|
/**
|
|
10
11
|
* Codex as a harness (docs/architecture.md, "First adapters"), headless
|
|
11
12
|
* (headless H11): one `codex exec --json` per turn in the folder, the first
|
|
@@ -36,6 +37,10 @@ const NO_DAEMON = '--no-daemon';
|
|
|
36
37
|
*/
|
|
37
38
|
const NO_QUESTION_TOOL = '--config=tools.experimental_request_user_input.enabled=false';
|
|
38
39
|
const END_OF_FLAGS = '--';
|
|
40
|
+
/** The model provider a session on an API key uses: the model proxy (api keys K6). */
|
|
41
|
+
const PROVIDER = 'aeolus';
|
|
42
|
+
/** The variable the provider reads its token from, which the hold sets from the session's own file. */
|
|
43
|
+
const PROXY_TOKEN_VARIABLE = 'AEOLUS_MODEL_TOKEN';
|
|
39
44
|
const EXEC = 'exec';
|
|
40
45
|
const RESUME = 'resume';
|
|
41
46
|
const LAST = '--last';
|
|
@@ -106,21 +111,42 @@ export function codexErrorIn(at) {
|
|
|
106
111
|
}
|
|
107
112
|
export function createCodexHarness(options) {
|
|
108
113
|
const { configuration, plugin, sessions } = options;
|
|
114
|
+
/**
|
|
115
|
+
* The session's way to its model (api keys K6): on an API key, the model
|
|
116
|
+
* proxy as a provider of its own, set on the command line (a project's
|
|
117
|
+
* config cannot set one), its token in the variable the provider names and
|
|
118
|
+
* fresh for each start; on the subscription, nothing, so it signs in as
|
|
119
|
+
* Codex does. Every later turn's exec keeps the flags and the hold keeps the
|
|
120
|
+
* variable.
|
|
121
|
+
*/
|
|
122
|
+
const routeOf = async (login) => {
|
|
123
|
+
if (login === 'subscription') {
|
|
124
|
+
return { flags: [] };
|
|
125
|
+
}
|
|
126
|
+
const url = await options.proxyUrl?.();
|
|
127
|
+
if (url === undefined) {
|
|
128
|
+
throw new Error('the model proxy is not running yet');
|
|
129
|
+
}
|
|
130
|
+
const provider = { name: '"Aeolus model proxy"', base_url: `"${url}/openai/v1"`, env_key: `"${PROXY_TOKEN_VARIABLE}"`, wire_api: '"responses"' };
|
|
131
|
+
const flags = [...Object.entries(provider).flatMap(([key, value]) => ['-c', `model_providers.${PROVIDER}.${key}=${value}`]), '-c', `model_provider="${PROVIDER}"`];
|
|
132
|
+
return { flags, proxyToken: { harness: 'codex', variable: PROXY_TOKEN_VARIABLE, token: newProxyToken() } };
|
|
133
|
+
};
|
|
109
134
|
const marks = createLaunchMarks(plugin);
|
|
110
135
|
const { handOverLine, forceOverLine, ...identity } = createPluginIdentity(plugin);
|
|
111
136
|
return {
|
|
112
137
|
...identity,
|
|
113
|
-
launch: async ({ shipId, folder, checkouts, harness, options: picked, isFirstStart, launchId, firstPrompt }) => {
|
|
138
|
+
launch: async ({ shipId, folder, checkouts, harness, options: picked, isFirstStart, launchId, login, firstPrompt }) => {
|
|
114
139
|
const settings = configuration.harnesses[harness];
|
|
115
140
|
if (settings === undefined) {
|
|
116
141
|
throw new Error(`The configuration has no harness ${harness}`);
|
|
117
142
|
}
|
|
143
|
+
const route = await routeOf(login);
|
|
118
144
|
const prompt = isFirstStart && firstPrompt !== undefined ? firstPromptOf(firstPrompt) : wakePromptOf(WAKE_PROMPT);
|
|
119
|
-
const command = codexCommandLine({ flags: effectiveFlags(settings, picked), prompt, isFirstStart, ...(options.command !== undefined && { program: options.command }) });
|
|
145
|
+
const command = codexCommandLine({ flags: [...effectiveFlags(settings, picked), ...route.flags], prompt, isFirstStart, ...(options.command !== undefined && { program: options.command }) });
|
|
120
146
|
await options.setup.trustAeolusHooks(folder);
|
|
121
147
|
await marks.clear(folder);
|
|
122
148
|
// Codex reads outside its folder as it is: its read-only checkouts need no flag (#1182).
|
|
123
|
-
await sessions.start({ shipId, folder, command: wordsOf(command), harness, env: { [LAUNCH_VARIABLE]: launchId }, ...(checkouts.length > 0 && { readOnly: checkouts.map((checkout) => checkout.path) }) });
|
|
149
|
+
await sessions.start({ shipId, folder, command: wordsOf(command), harness, env: { [LAUNCH_VARIABLE]: launchId }, ...(route.proxyToken !== undefined && { proxyToken: route.proxyToken }), ...(checkouts.length > 0 && { readOnly: checkouts.map((checkout) => checkout.path) }) });
|
|
124
150
|
},
|
|
125
151
|
handOver: async (session) => {
|
|
126
152
|
const line = await handOverLine(session);
|
|
@@ -142,6 +168,8 @@ export function createCodexHarness(options) {
|
|
|
142
168
|
return 'handed';
|
|
143
169
|
},
|
|
144
170
|
marksLaunches: () => marks.isMarking(),
|
|
171
|
+
// Codex is offered wherever its plugin is: no build or runtime of it is held back.
|
|
172
|
+
notOfferedReason: () => Promise.resolve(undefined),
|
|
145
173
|
// The marker says what the session did (#490); Codex has no hook for a failed turn, so a refusal, or why a start shows none, is read from its last error event (headless H13).
|
|
146
174
|
launchSeen: async ({ shipId, folder, launchId, model }) => {
|
|
147
175
|
const error = codexErrorIn({ events: await sessions.events(shipId), ...(model !== undefined && { model }) });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/adapters/codex.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,6 +5,14 @@ import { type CommandResult } from './run-command.js';
|
|
|
5
5
|
export declare const MODEL_TOKEN_VARIABLE = "CLAUDE_CODE_OAUTH_TOKEN";
|
|
6
6
|
/** The session user's home in the image, where each container gets its ship's own home. */
|
|
7
7
|
export declare const SESSION_HOME = "/home/ubuntu";
|
|
8
|
+
/**
|
|
9
|
+
* Where a container reaches the host's loopback, and so the model proxy
|
|
10
|
+
* (headless H16): the host's address in Podman's slirp4netns network, which
|
|
11
|
+
* maps it to the host's loopback when the network allows that.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MODEL_PROXY_HOST = "10.0.2.2";
|
|
14
|
+
/** Where a session in a container reaches the model proxy the trierarch reaches at the url, on the host's loopback. */
|
|
15
|
+
export declare function containerProxyUrl(url: string): string;
|
|
8
16
|
type Run = (command: string, options: {
|
|
9
17
|
args: readonly string[];
|
|
10
18
|
}) => Promise<CommandResult>;
|
|
@@ -21,29 +29,42 @@ export interface ContainerRuntimeOptions {
|
|
|
21
29
|
/** The memory cap of each container, as the runtime takes it (`4g`). */
|
|
22
30
|
readonly memory: string;
|
|
23
31
|
readonly cpus: number;
|
|
32
|
+
/** The sessions folder: a folder per ship, with its hold's files and its env file. */
|
|
33
|
+
readonly sessions: string;
|
|
34
|
+
/** The trierarch program, which `hold` and its words follow. */
|
|
35
|
+
readonly program: readonly string[];
|
|
36
|
+
readonly version: string;
|
|
37
|
+
readonly platform: string;
|
|
24
38
|
/** Tells this trierarch's containers apart from any other on the machine. */
|
|
25
39
|
readonly owner?: string;
|
|
26
|
-
/** What
|
|
40
|
+
/** What a hold's start goes through: a systemd scope of its own under a systemd unit (see sessionsLaunch). */
|
|
27
41
|
readonly launch?: readonly string[];
|
|
28
42
|
readonly run?: Run;
|
|
29
43
|
}
|
|
30
44
|
/**
|
|
31
|
-
* The container session runtime (decision 0039): one container
|
|
32
|
-
* named after its ship id,
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
45
|
+
* The container session runtime (decision 0039, headless H18): one container
|
|
46
|
+
* per ship, named after its ship id, run by the ship's hold on the host as
|
|
47
|
+
* `run --rm -i`, attached: the hold holds the harness's input and output
|
|
48
|
+
* through the runtime, so a line sent, an interrupt and the events are the
|
|
49
|
+
* hold's, as on the host, and the container lives as long as the hold, a
|
|
50
|
+
* signal to it reaching the harness through the image's tini. A container an
|
|
51
|
+
* older trierarch started detached is listed as of another version until its
|
|
52
|
+
* ship starts again (H19). Rootless only, with hard memory and cpu caps and no
|
|
53
|
+
* restart policy: the trierarch starts a dead session again itself. The
|
|
54
|
+
* container sees its folder, its ship's own home, as its home, and its ship's
|
|
55
|
+
* socket folder, at its own path, and nothing else of the host, never the
|
|
56
|
+
* runtime's socket. The home is made, for its owner alone, when the ship has
|
|
57
|
+
* none yet.
|
|
41
58
|
*
|
|
42
59
|
* The model token and the session's environment reach the container through
|
|
43
|
-
* an env file
|
|
44
|
-
* command line (#445).
|
|
45
|
-
*
|
|
46
|
-
*
|
|
60
|
+
* an env file in the session's own folder, for its owner alone, never a
|
|
61
|
+
* command line (#445). A session on an API key gets no model token, the
|
|
62
|
+
* subscription's login: its proxy token, which its hold holds in the
|
|
63
|
+
* environment it runs the container with, is passed on by its variable's name
|
|
64
|
+
* alone, and the container reaches the host's loopback, where the model proxy
|
|
65
|
+
* listens (headless H16, api keys K7). It is kept while the session runs, since the hold runs
|
|
66
|
+
* the container again when it starts Claude Code again (H12), and goes with
|
|
67
|
+
* the session's folder when it stops.
|
|
47
68
|
*/
|
|
48
69
|
export declare function createContainerRuntime(options: ContainerRuntimeOptions): SessionRuntime & SessionRoots;
|
|
49
70
|
export {};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import { mkdir,
|
|
2
|
-
import { tmpdir } from 'node:os';
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
3
2
|
import { join } from 'node:path';
|
|
4
3
|
import { idSchema } from '@aeolus-fleet/common';
|
|
5
|
-
import {
|
|
4
|
+
import { createHoldRuntime } from './hold-runtime.js';
|
|
6
5
|
import { shipHome } from './paths.js';
|
|
7
6
|
import { runCommand } from './run-command.js';
|
|
8
|
-
import { stopTurn } from './stop-turn.js';
|
|
9
7
|
const PREFIX = 'trierarch-';
|
|
10
8
|
const OWNER_LABEL = 'aeolus.trierarch';
|
|
11
9
|
const CONTAINER_OWNER = 'aeolus-trierarch';
|
|
@@ -15,30 +13,28 @@ export const MODEL_TOKEN_VARIABLE = 'CLAUDE_CODE_OAUTH_TOKEN';
|
|
|
15
13
|
export const SESSION_HOME = '/home/ubuntu';
|
|
16
14
|
/** The image's session user (ubuntu), whose subordinate ids the nested Podman maps. */
|
|
17
15
|
const SESSION_USER = 'uid=1000,gid=1000';
|
|
18
|
-
/** The tmux session inside each container: one per container, so one name serves. */
|
|
19
|
-
const TMUX_TARGET = '=session:';
|
|
20
16
|
/**
|
|
21
17
|
* The most processes and threads a container may hold, a hard cap beside
|
|
22
18
|
* memory and cpus (decision 0039): room for Claude Code, a test run with its
|
|
23
19
|
* workers, a browser and a nested Postgres, and none for a runaway fork.
|
|
24
20
|
*/
|
|
25
21
|
const PIDS_LIMIT = 4096;
|
|
26
|
-
/** How many lines back a screen is read, as on the host. */
|
|
27
|
-
const SCREEN_LINES = 200;
|
|
28
22
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* starts with the shell and is respawned with the command once remain-on-exit
|
|
33
|
-
* is set, so even a command that ends at once leaves its exit to see.
|
|
23
|
+
* Where a container reaches the host's loopback, and so the model proxy
|
|
24
|
+
* (headless H16): the host's address in Podman's slirp4netns network, which
|
|
25
|
+
* maps it to the host's loopback when the network allows that.
|
|
34
26
|
*/
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
export const MODEL_PROXY_HOST = '10.0.2.2';
|
|
28
|
+
/** The network that lets a session on an API key reach the host's loopback, and nothing more of the host than the network gives any container. */
|
|
29
|
+
const HOST_LOOPBACK_NETWORK = 'slirp4netns:allow_host_loopback=true';
|
|
30
|
+
/** Where a session in a container reaches the model proxy the trierarch reaches at the url, on the host's loopback. */
|
|
31
|
+
export function containerProxyUrl(url) {
|
|
32
|
+
const at = new URL(url);
|
|
33
|
+
at.hostname = MODEL_PROXY_HOST;
|
|
34
|
+
return at.origin;
|
|
35
|
+
}
|
|
36
|
+
/** The env file in the session's own folder, beside its hold's files. */
|
|
37
|
+
const ENV_FILE = 'session.env';
|
|
42
38
|
function containerName(shipId) {
|
|
43
39
|
return `${PREFIX}${shipId}`;
|
|
44
40
|
}
|
|
@@ -54,26 +50,32 @@ function envFileOf(env) {
|
|
|
54
50
|
.join('');
|
|
55
51
|
}
|
|
56
52
|
/**
|
|
57
|
-
* The container session runtime (decision 0039): one container
|
|
58
|
-
* named after its ship id,
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
53
|
+
* The container session runtime (decision 0039, headless H18): one container
|
|
54
|
+
* per ship, named after its ship id, run by the ship's hold on the host as
|
|
55
|
+
* `run --rm -i`, attached: the hold holds the harness's input and output
|
|
56
|
+
* through the runtime, so a line sent, an interrupt and the events are the
|
|
57
|
+
* hold's, as on the host, and the container lives as long as the hold, a
|
|
58
|
+
* signal to it reaching the harness through the image's tini. A container an
|
|
59
|
+
* older trierarch started detached is listed as of another version until its
|
|
60
|
+
* ship starts again (H19). Rootless only, with hard memory and cpu caps and no
|
|
61
|
+
* restart policy: the trierarch starts a dead session again itself. The
|
|
62
|
+
* container sees its folder, its ship's own home, as its home, and its ship's
|
|
63
|
+
* socket folder, at its own path, and nothing else of the host, never the
|
|
64
|
+
* runtime's socket. The home is made, for its owner alone, when the ship has
|
|
65
|
+
* none yet.
|
|
67
66
|
*
|
|
68
67
|
* The model token and the session's environment reach the container through
|
|
69
|
-
* an env file
|
|
70
|
-
* command line (#445).
|
|
71
|
-
*
|
|
72
|
-
*
|
|
68
|
+
* an env file in the session's own folder, for its owner alone, never a
|
|
69
|
+
* command line (#445). A session on an API key gets no model token, the
|
|
70
|
+
* subscription's login: its proxy token, which its hold holds in the
|
|
71
|
+
* environment it runs the container with, is passed on by its variable's name
|
|
72
|
+
* alone, and the container reaches the host's loopback, where the model proxy
|
|
73
|
+
* listens (headless H16, api keys K7). It is kept while the session runs, since the hold runs
|
|
74
|
+
* the container again when it starts Claude Code again (H12), and goes with
|
|
75
|
+
* the session's folder when it stops.
|
|
73
76
|
*/
|
|
74
77
|
export function createContainerRuntime(options) {
|
|
75
78
|
const owner = options.owner ?? CONTAINER_OWNER;
|
|
76
|
-
const launch = options.launch ?? [];
|
|
77
79
|
const run = options.run ?? runCommand;
|
|
78
80
|
const runtime = async (args) => run(options.binary, { args });
|
|
79
81
|
const must = async (args) => {
|
|
@@ -83,22 +85,8 @@ export function createContainerRuntime(options) {
|
|
|
83
85
|
}
|
|
84
86
|
return result.stdout;
|
|
85
87
|
};
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
await runtime(['kill', containerName(shipId)]);
|
|
89
|
-
await runtime(['rm', '--force', containerName(shipId)]);
|
|
90
|
-
};
|
|
91
|
-
const tmux = (shipId, args) => ['exec', containerName(shipId), 'tmux', ...args];
|
|
92
|
-
const screen = async (shipId) => {
|
|
93
|
-
const shown = await runtime(tmux(shipId, ['capture-pane', '-p', '-J', '-S', `-${String(SCREEN_LINES)}`, '-t', TMUX_TARGET]));
|
|
94
|
-
if (shown.status === 0) {
|
|
95
|
-
return shown.stdout;
|
|
96
|
-
}
|
|
97
|
-
// An exited container printed its last screen as it ended.
|
|
98
|
-
const logged = await runtime(['logs', containerName(shipId)]);
|
|
99
|
-
return logged.status === 0 ? logged.stdout : '';
|
|
100
|
-
};
|
|
101
|
-
return {
|
|
88
|
+
/** The ship's container: stopped before its hold, so the hold ends with it, and listed where no hold holds the ship. */
|
|
89
|
+
const containers = {
|
|
102
90
|
list: async () => {
|
|
103
91
|
const listed = await must(['ps', '--all', '--filter', `label=${OWNER_LABEL}=${owner}`, '--format', '{{.Names}} {{.State}}']);
|
|
104
92
|
return listed.split('\n').flatMap((line) => {
|
|
@@ -107,25 +95,36 @@ export function createContainerRuntime(options) {
|
|
|
107
95
|
return name.startsWith(PREFIX) && shipId.success ? [{ shipId: shipId.data, status: state === 'running' ? 'running' : 'exited' }] : [];
|
|
108
96
|
});
|
|
109
97
|
},
|
|
110
|
-
stop
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
98
|
+
stop: async (shipId) => {
|
|
99
|
+
// Kill, then remove: a remove alone waits out the stop timeout on podman.
|
|
100
|
+
await runtime(['kill', containerName(shipId)]);
|
|
101
|
+
await runtime(['rm', '--force', containerName(shipId)]);
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
const holds = createHoldRuntime({
|
|
105
|
+
sessions: options.sessions,
|
|
106
|
+
program: options.program,
|
|
107
|
+
version: options.version,
|
|
108
|
+
platform: options.platform,
|
|
109
|
+
launch: options.launch ?? [],
|
|
110
|
+
beside: containers,
|
|
111
|
+
heldAs: async ({ shipId, folder, command, env = {}, readOnly = [], proxyToken }, files) => {
|
|
112
|
+
const login = proxyToken === undefined ? { [MODEL_TOKEN_VARIABLE]: (await readFile(options.tokenFile, 'utf8')).trim() } : {};
|
|
113
|
+
const content = envFileOf({ ...env, ...login });
|
|
115
114
|
const home = shipHome(options.homes, shipId);
|
|
116
115
|
const shipSockets = join(options.sockets, shipId);
|
|
117
116
|
// The runtime mounts only a folder that exists, and the ship's socket may not have made it yet.
|
|
118
117
|
await mkdir(shipSockets, { recursive: true, mode: 0o700 });
|
|
119
118
|
await mkdir(home, { recursive: true, mode: 0o700 });
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
...launch,
|
|
119
|
+
await mkdir(files.folder, { recursive: true, mode: 0o700 });
|
|
120
|
+
const envFile = join(files.folder, ENV_FILE);
|
|
121
|
+
await writeFile(envFile, content, { mode: 0o600 });
|
|
122
|
+
return {
|
|
123
|
+
command: [
|
|
126
124
|
options.binary,
|
|
127
125
|
'run',
|
|
128
|
-
'--
|
|
126
|
+
'--rm',
|
|
127
|
+
'-i',
|
|
129
128
|
'--name',
|
|
130
129
|
containerName(shipId),
|
|
131
130
|
'--label',
|
|
@@ -159,42 +158,22 @@ export function createContainerRuntime(options) {
|
|
|
159
158
|
...readOnly.flatMap((path) => ['--volume', `${path}:${path}:ro`]),
|
|
160
159
|
'--env',
|
|
161
160
|
`HOME=${SESSION_HOME}`,
|
|
161
|
+
...(proxyToken === undefined ? [] : ['--env', proxyToken.variable, '--network', HOST_LOOPBACK_NETWORK]),
|
|
162
162
|
'--workdir',
|
|
163
163
|
folder,
|
|
164
164
|
'--env-file',
|
|
165
165
|
envFile,
|
|
166
166
|
options.image,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
];
|
|
173
|
-
const started = await run(program, { args });
|
|
174
|
-
if (started.status !== 0) {
|
|
175
|
-
throw new Error(`${options.binary} run failed: ${started.stderr.trim()}`);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
finally {
|
|
179
|
-
await rm(secrets, { recursive: true, force: true });
|
|
180
|
-
}
|
|
181
|
-
},
|
|
182
|
-
// The line typed, then Enter, as a person types it in the session's terminal.
|
|
183
|
-
send: async ({ shipId, line }) => {
|
|
184
|
-
await must(tmux(shipId, ['send-keys', '-t', TMUX_TARGET, '-l', line]));
|
|
185
|
-
await must(tmux(shipId, ['send-keys', '-t', TMUX_TARGET, 'Enter']));
|
|
186
|
-
},
|
|
187
|
-
interrupt: async (shipId) => {
|
|
188
|
-
await stopTurn({ escape: async () => {
|
|
189
|
-
await must(tmux(shipId, ['send-keys', '-t', TMUX_TARGET, 'Escape']));
|
|
190
|
-
}, screen: () => screen(shipId) });
|
|
167
|
+
...command,
|
|
168
|
+
],
|
|
169
|
+
// The session's environment reaches the container through the env file alone.
|
|
170
|
+
env: {},
|
|
171
|
+
};
|
|
191
172
|
},
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
},
|
|
197
|
-
// The container's first process as the host sees it: every process of the session runs under it; 0 once it runs no more.
|
|
173
|
+
});
|
|
174
|
+
return {
|
|
175
|
+
...holds,
|
|
176
|
+
// The container's first process as the host sees it: every process of the session runs under it; none once it runs no more.
|
|
198
177
|
sessionRootOf: async (shipId) => {
|
|
199
178
|
const inspected = await runtime(['inspect', '--format', '{{.State.Pid}}', containerName(shipId)]);
|
|
200
179
|
const pid = Number(inspected.stdout.trim());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/adapters/container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"container.js","sourceRoot":"","sources":["../../src/adapters/container.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { HarnessDetector } from '../core/ports.js';
|
|
2
|
+
import type { CommandResult } from './run-command.js';
|
|
3
|
+
export declare const AUTO_MODEL = "auto";
|
|
4
|
+
export declare function createCopilotDetector(deps: {
|
|
5
|
+
run: (command: string, options: {
|
|
6
|
+
args: readonly string[];
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
}) => Promise<CommandResult>;
|
|
9
|
+
/** Copilot's own settings, `settings.json` in COPILOT_HOME or `~/.copilot`; undefined when there are none. */
|
|
10
|
+
readSettings: () => Promise<string | undefined>;
|
|
11
|
+
/** The program to run; `copilot` unless a test runs another. */
|
|
12
|
+
program?: string;
|
|
13
|
+
}): HarnessDetector;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { trierarchNameSchema } from '@aeolus-fleet/common';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* Detecting Copilot (docs/trierarch.md, "Detected options"): its version from
|
|
5
|
+
* `copilot --version`, and its models from the model setting `copilot help
|
|
6
|
+
* config` documents, offline, with `auto`, on which Copilot picks the model
|
|
7
|
+
* per request (CC9). No model is probed: every Copilot prompt costs a
|
|
8
|
+
* premium request, so none is confirmed, and a model this login may not use
|
|
9
|
+
* is refused in its session's launch window, as Copilot says it then. The
|
|
10
|
+
* default is the model Copilot's own settings name when it is declared, else
|
|
11
|
+
* `auto`, on which Copilot starts. Copilot has an effort flag, but its levels
|
|
12
|
+
* differ per model, so no effort is declared.
|
|
13
|
+
*/
|
|
14
|
+
/** The longest --version and the help may take: both are read offline. */
|
|
15
|
+
const QUICK_TIMEOUT_MS = 10_000;
|
|
16
|
+
const MODEL_FLAG = '--model';
|
|
17
|
+
export const AUTO_MODEL = 'auto';
|
|
18
|
+
/** The model setting's entry in `copilot help config`, up to the blank line that ends it. */
|
|
19
|
+
const MODEL_SETTING = /^ {2}`model`:[^\n]*\n((?: {4}- "[^"]+"\n?)+)/m;
|
|
20
|
+
const LISTED_MODEL = /- "([^"]+)"/g;
|
|
21
|
+
const settingsSchema = z.object({ model: z.string() });
|
|
22
|
+
/** The models the help lists for the model setting, in its order. */
|
|
23
|
+
function listedModelsOf(result) {
|
|
24
|
+
const listed = result.status === 0 ? MODEL_SETTING.exec(result.stdout)?.[1] : undefined;
|
|
25
|
+
return [...(listed ?? '').matchAll(LISTED_MODEL)].flatMap((match) => (match[1] === undefined ? [] : [match[1]]));
|
|
26
|
+
}
|
|
27
|
+
/** The model Copilot's settings name, when they are JSON naming one. */
|
|
28
|
+
function configuredModelOf(settings) {
|
|
29
|
+
try {
|
|
30
|
+
return settingsSchema.safeParse(JSON.parse(settings ?? '')).data?.model;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Settings that are no JSON name no model.
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function createCopilotDetector(deps) {
|
|
38
|
+
const program = deps.program ?? 'copilot';
|
|
39
|
+
return {
|
|
40
|
+
version: async () => {
|
|
41
|
+
const result = await deps.run(program, { args: ['--version'], timeoutMs: QUICK_TIMEOUT_MS }).catch(() => undefined);
|
|
42
|
+
// "GitHub Copilot CLI 1.0.105." on its first line.
|
|
43
|
+
return result?.status === 0 ? /(\d+\.\d+\.\d+)/.exec(result.stdout.split('\n')[0] ?? '')?.[1] : undefined;
|
|
44
|
+
},
|
|
45
|
+
detect: async ({ version, now }) => {
|
|
46
|
+
const help = await deps.run(program, { args: ['help', 'config'], timeoutMs: QUICK_TIMEOUT_MS }).catch(() => ({ status: 1, stdout: '', stderr: '' }));
|
|
47
|
+
const listed = listedModelsOf(help).filter((model) => trierarchNameSchema.safeParse(model).success && model !== AUTO_MODEL);
|
|
48
|
+
const models = [...listed, AUTO_MODEL];
|
|
49
|
+
const configured = configuredModelOf(await deps.readSettings());
|
|
50
|
+
const defaultModel = configured !== undefined && models.includes(configured) ? configured : AUTO_MODEL;
|
|
51
|
+
const values = Object.fromEntries(models.map((model) => [model, [MODEL_FLAG, model]]));
|
|
52
|
+
return {
|
|
53
|
+
version,
|
|
54
|
+
detectedAt: now,
|
|
55
|
+
confirmedAt: null,
|
|
56
|
+
options: { model: { values, default: defaultModel } },
|
|
57
|
+
...(listed.length === 0 && { problem: `Copilot ${version} names no model in copilot help config, so this machine declares auto only` }),
|
|
58
|
+
};
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=copilot-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-detector.js","sourceRoot":"","sources":["../../src/adapters/copilot-detector.ts"],"names":[],"mappings":"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"}
|