aicodeman 1.28.1 → 1.29.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 +2 -1
- package/README.zh-CN.md +1 -0
- package/dist/attachment-registry.d.ts +20 -0
- package/dist/attachment-registry.d.ts.map +1 -1
- package/dist/attachment-registry.js +75 -10
- package/dist/attachment-registry.js.map +1 -1
- package/dist/config/cli-registry/schema.d.ts +29 -0
- package/dist/config/cli-registry/schema.d.ts.map +1 -1
- package/dist/config/cli-registry/schema.js +50 -0
- package/dist/config/cli-registry/schema.js.map +1 -1
- package/dist/config/cli-registry/stock.d.ts.map +1 -1
- package/dist/config/cli-registry/stock.js +165 -2
- package/dist/config/cli-registry/stock.js.map +1 -1
- package/dist/config/cli-registry/types.d.ts +79 -0
- package/dist/config/cli-registry/types.d.ts.map +1 -1
- package/dist/custom-model-hosts.d.ts +39 -0
- package/dist/custom-model-hosts.d.ts.map +1 -0
- package/dist/custom-model-hosts.js +35 -0
- package/dist/custom-model-hosts.js.map +1 -0
- package/dist/custom-model-injection-apply.d.ts +49 -0
- package/dist/custom-model-injection-apply.d.ts.map +1 -0
- package/dist/custom-model-injection-apply.js +77 -0
- package/dist/custom-model-injection-apply.js.map +1 -0
- package/dist/custom-model-injection.d.ts +79 -0
- package/dist/custom-model-injection.d.ts.map +1 -0
- package/dist/custom-model-injection.js +169 -0
- package/dist/custom-model-injection.js.map +1 -0
- package/dist/docker-hosts.d.ts +64 -1
- package/dist/docker-hosts.d.ts.map +1 -1
- package/dist/docker-hosts.js +75 -3
- package/dist/docker-hosts.js.map +1 -1
- package/dist/generated-artifact-attachments.d.ts +3 -0
- package/dist/generated-artifact-attachments.d.ts.map +1 -1
- package/dist/generated-artifact-attachments.js +18 -8
- package/dist/generated-artifact-attachments.js.map +1 -1
- package/dist/hooks-config.d.ts +93 -0
- package/dist/hooks-config.d.ts.map +1 -1
- package/dist/hooks-config.js +211 -6
- package/dist/hooks-config.js.map +1 -1
- package/dist/mux-interface.d.ts +7 -0
- package/dist/mux-interface.d.ts.map +1 -1
- package/dist/remote-files.d.ts +145 -0
- package/dist/remote-files.d.ts.map +1 -0
- package/dist/remote-files.js +347 -0
- package/dist/remote-files.js.map +1 -0
- package/dist/remote-hosts.d.ts +12 -0
- package/dist/remote-hosts.d.ts.map +1 -1
- package/dist/remote-hosts.js +7 -1
- package/dist/remote-hosts.js.map +1 -1
- package/dist/remote-ssh-limiter.d.ts +42 -0
- package/dist/remote-ssh-limiter.d.ts.map +1 -0
- package/dist/remote-ssh-limiter.js +84 -0
- package/dist/remote-ssh-limiter.js.map +1 -0
- package/dist/session-cli-registry-bridge.d.ts +8 -0
- package/dist/session-cli-registry-bridge.d.ts.map +1 -1
- package/dist/session-cli-registry-bridge.js +14 -3
- package/dist/session-cli-registry-bridge.js.map +1 -1
- package/dist/session-manager.d.ts.map +1 -1
- package/dist/session-manager.js +8 -1
- package/dist/session-manager.js.map +1 -1
- package/dist/session.d.ts +79 -2
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +169 -3
- package/dist/session.js.map +1 -1
- package/dist/tmux-manager.d.ts +21 -0
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +80 -13
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/api.d.ts +6 -0
- package/dist/types/api.d.ts.map +1 -1
- package/dist/types/api.js.map +1 -1
- package/dist/types/session.d.ts +30 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/usage-telemetry.d.ts +4 -1
- package/dist/usage-telemetry.d.ts.map +1 -1
- package/dist/usage-telemetry.js +6 -3
- package/dist/usage-telemetry.js.map +1 -1
- package/dist/web/middleware/auth.d.ts +11 -1
- package/dist/web/middleware/auth.d.ts.map +1 -1
- package/dist/web/middleware/auth.js +69 -1
- package/dist/web/middleware/auth.js.map +1 -1
- package/dist/web/public/admin-ui.js.gz +0 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/{app.78bf0bf8.js → app.556be563.js} +7 -7
- package/dist/web/public/app.556be563.js.br +0 -0
- package/dist/web/public/app.556be563.js.gz +0 -0
- package/dist/web/public/approvals-ui.js.gz +0 -0
- package/dist/web/public/{constants.9cd8ed69.js → constants.258b140f.js} +50 -0
- package/dist/web/public/constants.258b140f.js.br +0 -0
- package/dist/web/public/constants.258b140f.js.gz +0 -0
- package/dist/web/public/cron-ui.js.gz +0 -0
- package/dist/web/public/entrance-animations.js.gz +0 -0
- package/dist/web/public/home-sessions.js.gz +0 -0
- package/dist/web/public/i18n.561ca09c.js +1 -0
- package/dist/web/public/i18n.561ca09c.js.br +0 -0
- package/dist/web/public/i18n.561ca09c.js.gz +0 -0
- package/dist/web/public/image-input.cd4b97c4.js.gz +0 -0
- package/dist/web/public/index.html +59 -16
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.8bc46081.js +1 -0
- package/dist/web/public/input-cjk.8bc46081.js.br +0 -0
- package/dist/web/public/input-cjk.8bc46081.js.gz +0 -0
- package/dist/web/public/{keyboard-accessory.1d0dda9b.js → keyboard-accessory.2cf04f17.js} +38 -3
- package/dist/web/public/keyboard-accessory.2cf04f17.js.br +0 -0
- package/dist/web/public/keyboard-accessory.2cf04f17.js.gz +0 -0
- package/dist/web/public/{mobile-handlers.2e9c214a.js → mobile-handlers.6f354a87.js} +61 -13
- package/dist/web/public/mobile-handlers.6f354a87.js.br +0 -0
- package/dist/web/public/mobile-handlers.6f354a87.js.gz +0 -0
- package/dist/web/public/mobile-overview.js +2 -2
- package/dist/web/public/mobile-overview.js.br +0 -0
- package/dist/web/public/mobile-overview.js.gz +0 -0
- package/dist/web/public/{mobile.65176832.css → mobile.e9d0b53e.css} +1 -1
- package/dist/web/public/mobile.e9d0b53e.css.br +0 -0
- package/dist/web/public/mobile.e9d0b53e.css.gz +0 -0
- package/dist/web/public/notification-manager.36ea4624.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.4e9ea307.js → panels-ui.5b07ad14.js} +77 -77
- package/dist/web/public/panels-ui.5b07ad14.js.br +0 -0
- package/dist/web/public/panels-ui.5b07ad14.js.gz +0 -0
- package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
- package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
- package/dist/web/public/readmymind-ui.js.gz +0 -0
- package/dist/web/public/respawn-ui.ff0dae4c.js.gz +0 -0
- package/dist/web/public/sanitize-html.bc7078d6.js.gz +0 -0
- package/dist/web/public/session-lineage.js.gz +0 -0
- package/dist/web/public/session-ui.42b81477.js +77 -0
- package/dist/web/public/session-ui.42b81477.js.br +0 -0
- package/dist/web/public/session-ui.42b81477.js.gz +0 -0
- package/dist/web/public/settings-ui.e0c7f6b4.js +67 -0
- package/dist/web/public/settings-ui.e0c7f6b4.js.br +0 -0
- package/dist/web/public/settings-ui.e0c7f6b4.js.gz +0 -0
- package/dist/web/public/{styles.8ecf20cf.css → styles.6add175d.css} +1 -1
- package/dist/web/public/styles.6add175d.css.br +0 -0
- package/dist/web/public/styles.6add175d.css.gz +0 -0
- package/dist/web/public/subagent-windows.e6ca799f.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/tab-rail-resize.42c24949.js.gz +0 -0
- package/dist/web/public/terminal-keycode229-recovery.6ea8fe37.js.gz +0 -0
- package/dist/web/public/terminal-ui.38c49244.js +2 -0
- package/dist/web/public/terminal-ui.38c49244.js.br +0 -0
- package/dist/web/public/terminal-ui.38c49244.js.gz +0 -0
- package/dist/web/public/ultracode-panel.js.gz +0 -0
- package/dist/web/public/ultracode-windows.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/dompurify.min.js.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-predictive-echo.bd6882b8.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.6fee72f2.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.c4b51eb6.js.gz +0 -0
- package/dist/web/public/voice-pcm-worklet.js.gz +0 -0
- package/dist/web/public/webview-tabs.js +56 -4
- package/dist/web/public/webview-tabs.js.br +0 -0
- package/dist/web/public/webview-tabs.js.gz +0 -0
- package/dist/web/route-helpers.d.ts +20 -0
- package/dist/web/route-helpers.d.ts.map +1 -1
- package/dist/web/route-helpers.js +29 -2
- package/dist/web/route-helpers.js.map +1 -1
- package/dist/web/routes/case-routes.d.ts.map +1 -1
- package/dist/web/routes/case-routes.js +23 -6
- package/dist/web/routes/case-routes.js.map +1 -1
- package/dist/web/routes/custom-model-routes.d.ts +18 -0
- package/dist/web/routes/custom-model-routes.d.ts.map +1 -0
- package/dist/web/routes/custom-model-routes.js +136 -0
- package/dist/web/routes/custom-model-routes.js.map +1 -0
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +484 -100
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/index.d.ts +1 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +1 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +95 -23
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/status-telemetry-routes.d.ts +3 -2
- package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -1
- package/dist/web/routes/status-telemetry-routes.js +6 -4
- package/dist/web/routes/status-telemetry-routes.js.map +1 -1
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +32 -22
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/routes/ws-routes.d.ts.map +1 -1
- package/dist/web/routes/ws-routes.js +26 -2
- package/dist/web/routes/ws-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +20 -2
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +37 -8
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/server.d.ts +8 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +69 -4
- package/dist/web/server.js.map +1 -1
- package/dist/web/webview-proxy.d.ts +41 -0
- package/dist/web/webview-proxy.d.ts.map +1 -1
- package/dist/web/webview-proxy.js +102 -1
- package/dist/web/webview-proxy.js.map +1 -1
- package/package.json +10 -9
- package/dist/web/public/app.78bf0bf8.js.br +0 -0
- package/dist/web/public/app.78bf0bf8.js.gz +0 -0
- package/dist/web/public/constants.9cd8ed69.js.br +0 -0
- package/dist/web/public/constants.9cd8ed69.js.gz +0 -0
- package/dist/web/public/i18n.9db8c4e0.js +0 -1
- package/dist/web/public/i18n.9db8c4e0.js.br +0 -0
- package/dist/web/public/i18n.9db8c4e0.js.gz +0 -0
- package/dist/web/public/input-cjk.87f14251.js +0 -1
- package/dist/web/public/input-cjk.87f14251.js.br +0 -0
- package/dist/web/public/input-cjk.87f14251.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.1d0dda9b.js.br +0 -0
- package/dist/web/public/keyboard-accessory.1d0dda9b.js.gz +0 -0
- package/dist/web/public/mobile-handlers.2e9c214a.js.br +0 -0
- package/dist/web/public/mobile-handlers.2e9c214a.js.gz +0 -0
- package/dist/web/public/mobile.65176832.css.br +0 -0
- package/dist/web/public/mobile.65176832.css.gz +0 -0
- package/dist/web/public/panels-ui.4e9ea307.js.br +0 -0
- package/dist/web/public/panels-ui.4e9ea307.js.gz +0 -0
- package/dist/web/public/session-ui.cd222710.js +0 -77
- package/dist/web/public/session-ui.cd222710.js.br +0 -0
- package/dist/web/public/session-ui.cd222710.js.gz +0 -0
- package/dist/web/public/settings-ui.c175db9a.js +0 -67
- package/dist/web/public/settings-ui.c175db9a.js.br +0 -0
- package/dist/web/public/settings-ui.c175db9a.js.gz +0 -0
- package/dist/web/public/styles.8ecf20cf.css.br +0 -0
- package/dist/web/public/styles.8ecf20cf.css.gz +0 -0
- package/dist/web/public/terminal-ui.89e4eb1a.js +0 -2
- package/dist/web/public/terminal-ui.89e4eb1a.js.br +0 -0
- package/dist/web/public/terminal-ui.89e4eb1a.js.gz +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The one IO wrapper around `custom-model-injection.ts`'s pure
|
|
3
|
+
* `ConfigDirInjection` output — deliberately split out so that file, the
|
|
4
|
+
* discovery routes, and `scripts/test-local-llm-harnesses.ts` (via tsx) can
|
|
5
|
+
* all share EXACTLY one "write these files, merge this env" implementation.
|
|
6
|
+
* Before this existed, the route and the standalone script each carried
|
|
7
|
+
* their own copy of this logic, which is exactly the kind of drift the CLI
|
|
8
|
+
* registry's "declare once, consume everywhere" design exists to prevent —
|
|
9
|
+
* see docs/custom-model-endpoints-plan.md and the "dynamic to support
|
|
10
|
+
* cli-registry changes" requirement it was written against.
|
|
11
|
+
*/
|
|
12
|
+
import type { CliEntry } from './config/cli-registry/types.js';
|
|
13
|
+
import { type ConfigDirInjection, type CustomModelEndpoint } from './custom-model-injection.js';
|
|
14
|
+
/** Where a session's isolated `configDir`-kind files live: never the user's real CLI config path. */
|
|
15
|
+
export declare function customModelConfigDir(sessionId: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Writes a `ConfigDirInjection`'s files under `baseDir` and returns the full
|
|
18
|
+
* envOverrides object a caller should merge into the session/process env
|
|
19
|
+
* (the dir-redirect var plus any `extraEnv` the config file references by
|
|
20
|
+
* name). Never touches anything outside `baseDir` — the caller is
|
|
21
|
+
* responsible for choosing an isolated directory (never the user's real
|
|
22
|
+
* `~/.codex`, `~/.pi`, etc.).
|
|
23
|
+
*
|
|
24
|
+
* pi and omp embed the API key literally in the file, so the tree is written
|
|
25
|
+
* 0700/0600 like every other secret-bearing file under `~/.codeman`; the chmod
|
|
26
|
+
* covers a re-apply onto a file that already exists (`mode` only applies at
|
|
27
|
+
* creation).
|
|
28
|
+
*/
|
|
29
|
+
export declare function applyConfigDirInjection(baseDir: string, injection: ConfigDirInjection): Record<string, string>;
|
|
30
|
+
/** Best-effort recursive removal of a previously-written configDir. Never throws. */
|
|
31
|
+
export declare function removeConfigDir(dir: string | undefined): void;
|
|
32
|
+
/** What applying an endpoint to a session yields, ready for `Session.setCustomModel()`. */
|
|
33
|
+
export interface AppliedCustomModel {
|
|
34
|
+
envOverrides: Record<string, string>;
|
|
35
|
+
envKeys: string[];
|
|
36
|
+
configDir?: string;
|
|
37
|
+
launchModel?: string;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Compute (and for the `configDir` kind, write) everything a session needs to run
|
|
41
|
+
* against `endpoint`/`modelId`. Returns undefined for a CLI with no mechanism.
|
|
42
|
+
*
|
|
43
|
+
* Idempotent on purpose: the boot-recovery path calls it again for a session that
|
|
44
|
+
* was already pointed at an endpoint, so the config files are rewritten in place
|
|
45
|
+
* (same content) and the env values, which are never persisted because they carry
|
|
46
|
+
* the API key, are re-derived from the endpoint store instead.
|
|
47
|
+
*/
|
|
48
|
+
export declare function applyCustomModelInjection(entry: Pick<CliEntry, 'capabilities'>, endpoint: CustomModelEndpoint, modelId: string, sessionId: string): AppliedCustomModel | undefined;
|
|
49
|
+
//# sourceMappingURL=custom-model-injection-apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-model-injection-apply.d.ts","sourceRoot":"","sources":["../src/custom-model-injection-apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAErC,qGAAqG;AACrG,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ9G;AAED,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAO7D;AAED,2FAA2F;AAC3F,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EACrC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,kBAAkB,GAAG,SAAS,CAahC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The one IO wrapper around `custom-model-injection.ts`'s pure
|
|
3
|
+
* `ConfigDirInjection` output — deliberately split out so that file, the
|
|
4
|
+
* discovery routes, and `scripts/test-local-llm-harnesses.ts` (via tsx) can
|
|
5
|
+
* all share EXACTLY one "write these files, merge this env" implementation.
|
|
6
|
+
* Before this existed, the route and the standalone script each carried
|
|
7
|
+
* their own copy of this logic, which is exactly the kind of drift the CLI
|
|
8
|
+
* registry's "declare once, consume everywhere" design exists to prevent —
|
|
9
|
+
* see docs/custom-model-endpoints-plan.md and the "dynamic to support
|
|
10
|
+
* cli-registry changes" requirement it was written against.
|
|
11
|
+
*/
|
|
12
|
+
import { chmodSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
13
|
+
import { join, dirname } from 'node:path';
|
|
14
|
+
import { dataPath } from './config/instance.js';
|
|
15
|
+
import { buildCustomModelInjection, } from './custom-model-injection.js';
|
|
16
|
+
/** Where a session's isolated `configDir`-kind files live: never the user's real CLI config path. */
|
|
17
|
+
export function customModelConfigDir(sessionId) {
|
|
18
|
+
return join(dataPath('custom-model-configs'), sessionId);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Writes a `ConfigDirInjection`'s files under `baseDir` and returns the full
|
|
22
|
+
* envOverrides object a caller should merge into the session/process env
|
|
23
|
+
* (the dir-redirect var plus any `extraEnv` the config file references by
|
|
24
|
+
* name). Never touches anything outside `baseDir` — the caller is
|
|
25
|
+
* responsible for choosing an isolated directory (never the user's real
|
|
26
|
+
* `~/.codex`, `~/.pi`, etc.).
|
|
27
|
+
*
|
|
28
|
+
* pi and omp embed the API key literally in the file, so the tree is written
|
|
29
|
+
* 0700/0600 like every other secret-bearing file under `~/.codeman`; the chmod
|
|
30
|
+
* covers a re-apply onto a file that already exists (`mode` only applies at
|
|
31
|
+
* creation).
|
|
32
|
+
*/
|
|
33
|
+
export function applyConfigDirInjection(baseDir, injection) {
|
|
34
|
+
for (const file of injection.files) {
|
|
35
|
+
const filePath = join(baseDir, file.relPath);
|
|
36
|
+
mkdirSync(dirname(filePath), { recursive: true, mode: 0o700 });
|
|
37
|
+
writeFileSync(filePath, file.content, { encoding: 'utf8', mode: 0o600 });
|
|
38
|
+
chmodSync(filePath, 0o600);
|
|
39
|
+
}
|
|
40
|
+
return { [injection.dirEnvVar]: baseDir, ...injection.extraEnv };
|
|
41
|
+
}
|
|
42
|
+
/** Best-effort recursive removal of a previously-written configDir. Never throws. */
|
|
43
|
+
export function removeConfigDir(dir) {
|
|
44
|
+
if (!dir)
|
|
45
|
+
return;
|
|
46
|
+
try {
|
|
47
|
+
rmSync(dir, { recursive: true, force: true });
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// best-effort cleanup only
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Compute (and for the `configDir` kind, write) everything a session needs to run
|
|
55
|
+
* against `endpoint`/`modelId`. Returns undefined for a CLI with no mechanism.
|
|
56
|
+
*
|
|
57
|
+
* Idempotent on purpose: the boot-recovery path calls it again for a session that
|
|
58
|
+
* was already pointed at an endpoint, so the config files are rewritten in place
|
|
59
|
+
* (same content) and the env values, which are never persisted because they carry
|
|
60
|
+
* the API key, are re-derived from the endpoint store instead.
|
|
61
|
+
*/
|
|
62
|
+
export function applyCustomModelInjection(entry, endpoint, modelId, sessionId) {
|
|
63
|
+
const injection = buildCustomModelInjection(entry, endpoint, modelId);
|
|
64
|
+
if (injection.kind === 'unsupported')
|
|
65
|
+
return undefined;
|
|
66
|
+
if (injection.kind === 'env') {
|
|
67
|
+
return {
|
|
68
|
+
envOverrides: injection.envOverrides,
|
|
69
|
+
envKeys: Object.keys(injection.envOverrides),
|
|
70
|
+
launchModel: injection.launchModel,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const configDir = customModelConfigDir(sessionId);
|
|
74
|
+
const envOverrides = applyConfigDirInjection(configDir, injection);
|
|
75
|
+
return { envOverrides, envKeys: Object.keys(envOverrides), configDir, launchModel: injection.launchModel };
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=custom-model-injection-apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-model-injection-apply.js","sourceRoot":"","sources":["../src/custom-model-injection-apply.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EACL,yBAAyB,GAG1B,MAAM,6BAA6B,CAAC;AAErC,qGAAqG;AACrG,MAAM,UAAU,oBAAoB,CAAC,SAAiB;IACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,SAAS,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,SAA6B;IACpF,KAAK,MAAM,IAAI,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7C,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzE,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;AACnE,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,eAAe,CAAC,GAAuB;IACrD,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,2BAA2B;IAC7B,CAAC;AACH,CAAC;AAUD;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAqC,EACrC,QAA6B,EAC7B,OAAe,EACf,SAAiB;IAEjB,MAAM,SAAS,GAAG,yBAAyB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IACtE,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC;IACvD,IAAI,SAAS,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC7B,OAAO;YACL,YAAY,EAAE,SAAS,CAAC,YAAY;YACpC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;YAC5C,WAAW,EAAE,SAAS,CAAC,WAAW;SACnC,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,uBAAuB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACnE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC;AAC7G,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure builder for the Custom Model Endpoint Profiles feature
|
|
3
|
+
* (docs/custom-model-endpoints-plan.md): turns a CLI registry entry's
|
|
4
|
+
* `capabilities.customModelInjection` declaration, a configured endpoint,
|
|
5
|
+
* and a chosen model id into the concrete env vars / config-file content
|
|
6
|
+
* that would redirect that CLI's session at the endpoint.
|
|
7
|
+
*
|
|
8
|
+
* No IO here on purpose (mirrors `session-cli-builder.ts`) — a caller
|
|
9
|
+
* writes `ConfigDirInjection.files` to disk under an isolated per-session
|
|
10
|
+
* directory and points `dirEnvVar` at it; this module only computes what
|
|
11
|
+
* those files/env vars should contain.
|
|
12
|
+
*
|
|
13
|
+
* Confidence: `claude` and `opencode` are verified end-to-end against a real
|
|
14
|
+
* llama-swap server (a real "hello world" reply came back). `codex`'s
|
|
15
|
+
* config.toml STRUCTURE is now verified (an earlier `[model].default` table
|
|
16
|
+
* shape was rejected by a real codex binary with "invalid type: map,
|
|
17
|
+
* expected a string" — caught by `scripts/test-local-llm-harnesses.ts`),
|
|
18
|
+
* but `wire_api = "responses"` is the only value codex still accepts
|
|
19
|
+
* (support for `"chat"` was dropped in Feb 2026), and a plain OpenAI
|
|
20
|
+
* Chat-Completions server (llama.cpp, llama-swap, most local setups) does
|
|
21
|
+
* NOT implement the Responses API — so codex may still fail at the
|
|
22
|
+
* PROTOCOL level even with a correctly-shaped config file. That gap is
|
|
23
|
+
* real and current, not a stale warning; see docs/custom-model-endpoints-plan.md. The rest
|
|
24
|
+
* (gemini/pi/grok/deepseek/omp) have their ONE-SHOT INVOCATION flags
|
|
25
|
+
* confirmed against real installed binaries' own `--help` output, but
|
|
26
|
+
* their custom-endpoint env/config conventions remain web-researched,
|
|
27
|
+
* unverified.
|
|
28
|
+
*/
|
|
29
|
+
import type { CliEntry } from './config/cli-registry/types.js';
|
|
30
|
+
export interface CustomModelEndpoint {
|
|
31
|
+
id: string;
|
|
32
|
+
label: string;
|
|
33
|
+
/** Root URL, no trailing slash required — e.g. "http://192.168.1.50:8080" or an Azure AI Foundry URL. */
|
|
34
|
+
baseUrl: string;
|
|
35
|
+
/** Falls back to a harmless placeholder for endpoints (llama.cpp) that don't check it. */
|
|
36
|
+
apiKey?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface EnvInjection {
|
|
39
|
+
kind: 'env';
|
|
40
|
+
/** Ready to merge into a session's envOverrides. */
|
|
41
|
+
envOverrides: Record<string, string>;
|
|
42
|
+
/** See {@link ConfigDirInjection.launchModel}. */
|
|
43
|
+
launchModel?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ConfigDirInjection {
|
|
46
|
+
kind: 'configDir';
|
|
47
|
+
/** Env var that must be set to the directory the caller writes `files` under. */
|
|
48
|
+
dirEnvVar: string;
|
|
49
|
+
files: Array<{
|
|
50
|
+
relPath: string;
|
|
51
|
+
content: string;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* Env vars the written config file REFERENCES by name rather than embedding a
|
|
55
|
+
* literal value (codex's `env_key = "..."` convention: config.toml never carries
|
|
56
|
+
* the API key itself, only the name of an env var codex reads it from). Merge
|
|
57
|
+
* these into the session's envOverrides alongside `dirEnvVar` — never skip them,
|
|
58
|
+
* or the config points at a credential that was never actually set.
|
|
59
|
+
*/
|
|
60
|
+
extraEnv?: Record<string, string>;
|
|
61
|
+
/**
|
|
62
|
+
* The value the CLI's `model` launch param must carry for it to SELECT the injected
|
|
63
|
+
* provider (pi/omp: `custom/<modelId>`; grok: the `[model.<name>]` block name). Absent
|
|
64
|
+
* when the config alone selects the model. Rendered from the registry entry's
|
|
65
|
+
* `customModelInjection.launchModel` template, never hand-built per CLI.
|
|
66
|
+
*/
|
|
67
|
+
launchModel?: string;
|
|
68
|
+
}
|
|
69
|
+
export interface UnsupportedInjection {
|
|
70
|
+
kind: 'unsupported';
|
|
71
|
+
}
|
|
72
|
+
export type CustomModelInjectionResult = EnvInjection | ConfigDirInjection | UnsupportedInjection;
|
|
73
|
+
/** Normalizes a base URL to end in exactly one trailing `/v1`, for CLIs whose config expects the OpenAI-style suffix. */
|
|
74
|
+
export declare function withV1Suffix(baseUrl: string): string;
|
|
75
|
+
export declare function buildCustomModelInjection(entry: Pick<CliEntry, 'capabilities'>, endpoint: CustomModelEndpoint, modelId: string): CustomModelInjectionResult;
|
|
76
|
+
/** The `[model.<name>]` block name grok's config.toml uses for the injected model — also
|
|
77
|
+
* what `-m <name>` in the standalone script's ONE_SHOT argv must reference to select it. */
|
|
78
|
+
export declare const GROK_CUSTOM_MODEL_NAME = "codeman-custom";
|
|
79
|
+
//# sourceMappingURL=custom-model-injection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-model-injection.d.ts","sourceRoot":"","sources":["../src/custom-model-injection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAE/D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,yGAAyG;IACzG,OAAO,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,KAAK,CAAC;IACZ,oDAAoD;IACpD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,kDAAkD;IAClD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,WAAW,CAAC;IAClB,iFAAiF;IACjF,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,MAAM,MAAM,0BAA0B,GAAG,YAAY,GAAG,kBAAkB,GAAG,oBAAoB,CAAC;AAIlG,yHAAyH;AACzH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpD;AAOD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EACrC,QAAQ,EAAE,mBAAmB,EAC7B,OAAO,EAAE,MAAM,GACd,0BAA0B,CA+B5B;AAmCD;6FAC6F;AAC7F,eAAO,MAAM,sBAAsB,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure builder for the Custom Model Endpoint Profiles feature
|
|
3
|
+
* (docs/custom-model-endpoints-plan.md): turns a CLI registry entry's
|
|
4
|
+
* `capabilities.customModelInjection` declaration, a configured endpoint,
|
|
5
|
+
* and a chosen model id into the concrete env vars / config-file content
|
|
6
|
+
* that would redirect that CLI's session at the endpoint.
|
|
7
|
+
*
|
|
8
|
+
* No IO here on purpose (mirrors `session-cli-builder.ts`) — a caller
|
|
9
|
+
* writes `ConfigDirInjection.files` to disk under an isolated per-session
|
|
10
|
+
* directory and points `dirEnvVar` at it; this module only computes what
|
|
11
|
+
* those files/env vars should contain.
|
|
12
|
+
*
|
|
13
|
+
* Confidence: `claude` and `opencode` are verified end-to-end against a real
|
|
14
|
+
* llama-swap server (a real "hello world" reply came back). `codex`'s
|
|
15
|
+
* config.toml STRUCTURE is now verified (an earlier `[model].default` table
|
|
16
|
+
* shape was rejected by a real codex binary with "invalid type: map,
|
|
17
|
+
* expected a string" — caught by `scripts/test-local-llm-harnesses.ts`),
|
|
18
|
+
* but `wire_api = "responses"` is the only value codex still accepts
|
|
19
|
+
* (support for `"chat"` was dropped in Feb 2026), and a plain OpenAI
|
|
20
|
+
* Chat-Completions server (llama.cpp, llama-swap, most local setups) does
|
|
21
|
+
* NOT implement the Responses API — so codex may still fail at the
|
|
22
|
+
* PROTOCOL level even with a correctly-shaped config file. That gap is
|
|
23
|
+
* real and current, not a stale warning; see docs/custom-model-endpoints-plan.md. The rest
|
|
24
|
+
* (gemini/pi/grok/deepseek/omp) have their ONE-SHOT INVOCATION flags
|
|
25
|
+
* confirmed against real installed binaries' own `--help` output, but
|
|
26
|
+
* their custom-endpoint env/config conventions remain web-researched,
|
|
27
|
+
* unverified.
|
|
28
|
+
*/
|
|
29
|
+
const DEFAULT_API_KEY = 'local-dummy-key';
|
|
30
|
+
/** Normalizes a base URL to end in exactly one trailing `/v1`, for CLIs whose config expects the OpenAI-style suffix. */
|
|
31
|
+
export function withV1Suffix(baseUrl) {
|
|
32
|
+
const trimmed = baseUrl.replace(/\/+$/, '');
|
|
33
|
+
return /\/v1$/.test(trimmed) ? trimmed : `${trimmed}/v1`;
|
|
34
|
+
}
|
|
35
|
+
/** JSON-escapes a string for embedding in a TOML/YAML double-quoted scalar — a safe superset of both grammars' basic escapes. */
|
|
36
|
+
function quoted(value) {
|
|
37
|
+
return JSON.stringify(value);
|
|
38
|
+
}
|
|
39
|
+
export function buildCustomModelInjection(entry, endpoint, modelId) {
|
|
40
|
+
const cap = entry.capabilities.customModelInjection;
|
|
41
|
+
const apiKey = endpoint.apiKey?.trim() || DEFAULT_API_KEY;
|
|
42
|
+
switch (cap.kind) {
|
|
43
|
+
case 'env': {
|
|
44
|
+
const envOverrides = {
|
|
45
|
+
[cap.baseUrlVar]: endpoint.baseUrl,
|
|
46
|
+
[cap.apiKeyVar]: apiKey,
|
|
47
|
+
};
|
|
48
|
+
for (const modelVar of cap.modelVars)
|
|
49
|
+
envOverrides[modelVar] = modelId;
|
|
50
|
+
return withLaunchModel({ kind: 'env', envOverrides }, cap.launchModel, modelId);
|
|
51
|
+
}
|
|
52
|
+
case 'configContentEnv': {
|
|
53
|
+
const content = renderConfigContent(cap.template, endpoint, modelId, apiKey);
|
|
54
|
+
return withLaunchModel({ kind: 'env', envOverrides: { [cap.envVar]: content } }, cap.launchModel, modelId);
|
|
55
|
+
}
|
|
56
|
+
case 'configDir': {
|
|
57
|
+
const { content, extraEnv } = renderConfigFile(cap.template, endpoint, modelId, apiKey);
|
|
58
|
+
return withLaunchModel({ kind: 'configDir', dirEnvVar: cap.dirEnvVar, files: [{ relPath: cap.fileName, content }], extraEnv }, cap.launchModel, modelId);
|
|
59
|
+
}
|
|
60
|
+
case 'unsupported':
|
|
61
|
+
return { kind: 'unsupported' };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/** Render a `launchModel` template (`{modelId}` = the chosen id) onto an injection result. */
|
|
65
|
+
function withLaunchModel(result, template, modelId) {
|
|
66
|
+
if (!template)
|
|
67
|
+
return result;
|
|
68
|
+
return { ...result, launchModel: template.split('{modelId}').join(modelId) };
|
|
69
|
+
}
|
|
70
|
+
function renderConfigContent(template, endpoint, modelId, apiKey) {
|
|
71
|
+
switch (template) {
|
|
72
|
+
case 'opencode-json':
|
|
73
|
+
return JSON.stringify({
|
|
74
|
+
$schema: 'https://opencode.ai/config.json',
|
|
75
|
+
provider: {
|
|
76
|
+
custom: {
|
|
77
|
+
options: { baseURL: withV1Suffix(endpoint.baseUrl), apiKey },
|
|
78
|
+
models: { [modelId]: {} },
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
model: `custom/${modelId}`,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const CODEX_API_KEY_ENV_VAR = 'CODEMAN_CUSTOM_MODEL_API_KEY';
|
|
86
|
+
/** The `[model.<name>]` block name grok's config.toml uses for the injected model — also
|
|
87
|
+
* what `-m <name>` in the standalone script's ONE_SHOT argv must reference to select it. */
|
|
88
|
+
export const GROK_CUSTOM_MODEL_NAME = 'codeman-custom';
|
|
89
|
+
function renderConfigFile(template, endpoint, modelId, apiKey) {
|
|
90
|
+
const baseUrl = withV1Suffix(endpoint.baseUrl);
|
|
91
|
+
switch (template) {
|
|
92
|
+
case 'codex-toml': {
|
|
93
|
+
// Verified against real codex (>= Feb 2026): `model` is a top-level STRING, never
|
|
94
|
+
// a `[model].default` table — codex rejects that with "invalid type: map, expected
|
|
95
|
+
// a string" (caught by scripts/test-local-llm-harnesses.ts against a real llama-swap
|
|
96
|
+
// server). The API key is NEVER a literal TOML field: codex's schema only supports
|
|
97
|
+
// `env_key`, the NAME of an env var it reads the credential from at runtime, so the
|
|
98
|
+
// actual value must ride along as an extra env var, never embedded in the file.
|
|
99
|
+
// ⚠️ `wire_api = "responses"` is the only value codex still accepts (it dropped
|
|
100
|
+
// `"chat"` support in Feb 2026) — a plain OpenAI Chat-Completions server (llama.cpp,
|
|
101
|
+
// llama-swap, most local setups) does NOT implement the Responses API, so this
|
|
102
|
+
// recipe may still fail at the PROTOCOL level even though the file now parses
|
|
103
|
+
// correctly. That is a real, currently-unresolved compatibility gap, not a syntax
|
|
104
|
+
// bug — track it before calling codex support done.
|
|
105
|
+
const content = [
|
|
106
|
+
`model = ${quoted(modelId)}`,
|
|
107
|
+
`model_provider = "custom"`,
|
|
108
|
+
'',
|
|
109
|
+
'[model_providers.custom]',
|
|
110
|
+
`name = "Custom Endpoint"`,
|
|
111
|
+
`base_url = ${quoted(baseUrl)}`,
|
|
112
|
+
`env_key = ${quoted(CODEX_API_KEY_ENV_VAR)}`,
|
|
113
|
+
`wire_api = "responses"`,
|
|
114
|
+
'',
|
|
115
|
+
].join('\n');
|
|
116
|
+
return { content, extraEnv: { [CODEX_API_KEY_ENV_VAR]: apiKey } };
|
|
117
|
+
}
|
|
118
|
+
case 'pi-models-json':
|
|
119
|
+
// Verified against pi's OWN bundled docs (models.md): `models` is an ARRAY of
|
|
120
|
+
// `{id: "..."}` objects, NOT an object keyed by model id — the earlier shape here
|
|
121
|
+
// silently loaded zero models ("No models available"), confirmed live. `authHeader:
|
|
122
|
+
// true` is required too: pi does not automatically send `Authorization: Bearer
|
|
123
|
+
// <apiKey>` just because `apiKey` is set (per the same doc) — without it, a real
|
|
124
|
+
// (non-llama.cpp) endpoint that actually checks the key would reject every request.
|
|
125
|
+
return {
|
|
126
|
+
content: JSON.stringify({
|
|
127
|
+
providers: {
|
|
128
|
+
custom: {
|
|
129
|
+
baseUrl,
|
|
130
|
+
apiKey,
|
|
131
|
+
api: 'openai-completions',
|
|
132
|
+
authHeader: true,
|
|
133
|
+
models: [{ id: modelId }],
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
}, null, 2),
|
|
137
|
+
};
|
|
138
|
+
case 'omp-models-yml':
|
|
139
|
+
// Mirrors the pi-models-json fix above (omp shares pi's config lineage per
|
|
140
|
+
// CLAUDE.md — it reads several of pi's own env vars): a flat list of bare model
|
|
141
|
+
// name strings under `models` is UNCONFIRMED against real omp docs (none are
|
|
142
|
+
// bundled with the binary) — this now matches pi's `{id: "..."}` object-list
|
|
143
|
+
// shape and adds `authHeader: true` on the same reasoning, but has not itself
|
|
144
|
+
// been live-tested the way pi's fix was. Verify before raising its confidence.
|
|
145
|
+
return {
|
|
146
|
+
content: `providers:\n custom:\n baseUrl: ${quoted(baseUrl)}\n apiKey: ${quoted(apiKey)}\n api: openai-completions\n authHeader: true\n models:\n - id: ${quoted(modelId)}\n`,
|
|
147
|
+
};
|
|
148
|
+
case 'grok-toml': {
|
|
149
|
+
// Verified against xAI's own docs (docs.x.ai/build/settings/reference): a
|
|
150
|
+
// `[model.<name>]` block, NOT plain env vars — an earlier `env`-kind recipe for
|
|
151
|
+
// grok was wrong, not just unverified (see the customModelInjection doc comment
|
|
152
|
+
// in cli-registry/types.ts). `api_backend = "chat_completions"` is explicitly
|
|
153
|
+
// supported (unlike codex, which dropped it after Feb 2026), so this one CAN
|
|
154
|
+
// talk to a plain OpenAI-compatible server directly. `env_key` reuses grok's own
|
|
155
|
+
// documented fallback var name (XAI_API_KEY) rather than inventing a new one.
|
|
156
|
+
const content = [
|
|
157
|
+
`[model.${GROK_CUSTOM_MODEL_NAME}]`,
|
|
158
|
+
`model = ${quoted(modelId)}`,
|
|
159
|
+
`base_url = ${quoted(baseUrl)}`,
|
|
160
|
+
`name = "Custom Endpoint"`,
|
|
161
|
+
`env_key = "XAI_API_KEY"`,
|
|
162
|
+
`api_backend = "chat_completions"`,
|
|
163
|
+
'',
|
|
164
|
+
].join('\n');
|
|
165
|
+
return { content, extraEnv: { XAI_API_KEY: apiKey } };
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=custom-model-injection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"custom-model-injection.js","sourceRoot":"","sources":["../src/custom-model-injection.ts"],"names":[],"mappings":"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"}
|
package/dist/docker-hosts.d.ts
CHANGED
|
@@ -100,6 +100,48 @@ export declare function dockerConfigHash(docker: Pick<SessionDocker, 'engine' |
|
|
|
100
100
|
* computed last over the resolved values.
|
|
101
101
|
*/
|
|
102
102
|
export declare function toSessionDocker(host: DockerHost, dockerCase: DockerCase): SessionDocker;
|
|
103
|
+
/**
|
|
104
|
+
* Which existing case, if any, blocks adopting `container` at `containerWorkdir`.
|
|
105
|
+
*
|
|
106
|
+
* One container may back SEVERAL adopted cases, each pointing at a different
|
|
107
|
+
* directory inside it — that is the whole reason to adopt the same container
|
|
108
|
+
* twice, and it is safe because the in-container tmux session is named per
|
|
109
|
+
* SESSION (`dockerTmuxSessionName`, `codeman-dkr-<id8>`) and not per case, so a
|
|
110
|
+
* session teardown kills exactly one session and its siblings on the shared
|
|
111
|
+
* in-container tmux server are untouched. Nothing else reaches an adopted
|
|
112
|
+
* container's lifecycle either: stop/remove throw at the builder, recreate
|
|
113
|
+
* refuses `owned === false`, and the orphan reaper filters on the
|
|
114
|
+
* `codeman.managed=1` label that only Codeman-created containers carry.
|
|
115
|
+
*
|
|
116
|
+
* So the conflicts that remain are NOT about the tmux server:
|
|
117
|
+
* - `owned-case` the container backs a case Codeman CREATED, whose lifecycle
|
|
118
|
+
* it owns; a recreate or delete there would destroy the
|
|
119
|
+
* adopted case's container out from under it.
|
|
120
|
+
* - `other-owner` already adopted by a different user. Adoption hands out a
|
|
121
|
+
* shell inside someone else's container, so it stays scoped.
|
|
122
|
+
* - `duplicate` same container AND same directory: the second case would
|
|
123
|
+
* behave identically to the first, so name the first instead
|
|
124
|
+
* of silently creating a twin. A DIFFERENT directory is the
|
|
125
|
+
* supported case and returns null.
|
|
126
|
+
*/
|
|
127
|
+
export type AdoptContainerConflict = {
|
|
128
|
+
kind: 'owned-case';
|
|
129
|
+
caseName: string;
|
|
130
|
+
} | {
|
|
131
|
+
kind: 'other-owner';
|
|
132
|
+
caseName: string;
|
|
133
|
+
} | {
|
|
134
|
+
kind: 'duplicate';
|
|
135
|
+
caseName: string;
|
|
136
|
+
} | null;
|
|
137
|
+
export declare function classifyAdoptContainerConflict(params: {
|
|
138
|
+
container: string;
|
|
139
|
+
/** Directory inside the container this adoption targets (already defaulted). */
|
|
140
|
+
containerWorkdir: string;
|
|
141
|
+
existing: ReadonlyArray<Pick<DockerCase, 'name' | 'container' | 'containerWorkdir' | 'hostWorkspacePath' | 'owned' | 'owner'>>;
|
|
142
|
+
/** Owner visibility test (canAccessOwned bound to the caller). */
|
|
143
|
+
canAccess: (owner?: string) => boolean;
|
|
144
|
+
}): AdoptContainerConflict;
|
|
103
145
|
/**
|
|
104
146
|
* An ADOPTED container is one the user built and runs themselves. Codeman may
|
|
105
147
|
* only exec into it; it must never create, start, stop, restart or remove it.
|
|
@@ -176,7 +218,28 @@ export declare function buildDockerCreateArgs(ctx: DockerCreateContext): string[
|
|
|
176
218
|
* scripts/build-agent-image.mjs): `build -f <dockerfile> -t <image> [--no-cache]
|
|
177
219
|
* <contextDir>`. Kept pure + unit-testable; the caller prepends the engine binary.
|
|
178
220
|
*/
|
|
179
|
-
export declare function agentImageBuildArgs(dockerfile: string, image: string, contextDir: string, noCache?: boolean): string[];
|
|
221
|
+
export declare function agentImageBuildArgs(dockerfile: string, image: string, contextDir: string, noCache?: boolean, buildArgs?: Array<[string, string]>): string[];
|
|
222
|
+
/**
|
|
223
|
+
* npm packages the agent image installs in its shared layer, from the STOCK catalogue.
|
|
224
|
+
*
|
|
225
|
+
* ⚠️ Stock, deliberately, NOT the merged registry. A user's `~/.codeman/clis.json` must not
|
|
226
|
+
* change what lands inside an image tagged `codeman/agent:base`, or two machines holding that
|
|
227
|
+
* same tag hold different images and every cache-hit decision downstream is a lie.
|
|
228
|
+
*
|
|
229
|
+
* ⚠️ An entry carrying `discovery.install.agentImageLayer` is excluded here — see that field's
|
|
230
|
+
* doc comment in `types.ts` for why some CLIs need their own hand-written Dockerfile layer
|
|
231
|
+
* instead of the shared one, and `test/docker-agent-image-coverage.test.ts` for the guard that
|
|
232
|
+
* an exclusion here still lands in the Dockerfile somewhere.
|
|
233
|
+
*
|
|
234
|
+
* ⚠️ This mirrors `agentImageNpmPackages()` in `scripts/lib/cli-catalog.mjs`, which the CLI
|
|
235
|
+
* build path uses because a `.mjs` cannot import TypeScript. Two producers of one command
|
|
236
|
+
* line drift; `test/agent-image-build-args-parity.test.ts` is what stops them — including the
|
|
237
|
+
* SAFE_PACKAGE regex below, which is duplicated (not imported) in that file for the same
|
|
238
|
+
* reason and must stay byte-identical to it.
|
|
239
|
+
*/
|
|
240
|
+
export declare function agentImageNpmPackages(): string[];
|
|
241
|
+
/** The `--build-arg` pairs the agent image takes. */
|
|
242
|
+
export declare function agentImageBuildArgPairs(): Array<[string, string]>;
|
|
180
243
|
/** Container Claude config dir (created gid-0 writable in the image). */
|
|
181
244
|
export declare const CONTAINER_CLAUDE_DIR = "/home/agent/.claude";
|
|
182
245
|
/** In-container path of the seeded (writable) `~/.claude.json`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker-hosts.d.ts","sourceRoot":"","sources":["../src/docker-hosts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;
|
|
1
|
+
{"version":3,"file":"docker-hosts.d.ts","sourceRoot":"","sources":["../src/docker-hosts.ts"],"names":[],"mappings":"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"}
|
package/dist/docker-hosts.js
CHANGED
|
@@ -24,6 +24,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
24
24
|
import fs from 'node:fs/promises';
|
|
25
25
|
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
26
26
|
import { enabledCliIds, getCli } from './config/cli-registry/registry.js';
|
|
27
|
+
import { STOCK_CLIS } from './config/cli-registry/stock.js';
|
|
27
28
|
import { fileURLToPath } from 'node:url';
|
|
28
29
|
import { homedir } from 'node:os';
|
|
29
30
|
import { createHash } from 'node:crypto';
|
|
@@ -243,6 +244,24 @@ export function toSessionDocker(host, dockerCase) {
|
|
|
243
244
|
session.owned = false;
|
|
244
245
|
return session;
|
|
245
246
|
}
|
|
247
|
+
export function classifyAdoptContainerConflict(params) {
|
|
248
|
+
const { container, containerWorkdir, existing, canAccess } = params;
|
|
249
|
+
const sharing = existing.filter((item) => (item.container ?? dockerContainerName(item.name)) === container);
|
|
250
|
+
if (sharing.length === 0)
|
|
251
|
+
return null;
|
|
252
|
+
// `owned` is optional and an ABSENT flag means owned (legacy cases predate the
|
|
253
|
+
// field), so this must test `!== false` rather than truthiness.
|
|
254
|
+
const owned = sharing.find((item) => item.owned !== false);
|
|
255
|
+
if (owned)
|
|
256
|
+
return { kind: 'owned-case', caseName: owned.name };
|
|
257
|
+
const foreign = sharing.find((item) => !canAccess(item.owner));
|
|
258
|
+
if (foreign)
|
|
259
|
+
return { kind: 'other-owner', caseName: foreign.name };
|
|
260
|
+
const twin = sharing.find((item) => (item.containerWorkdir ?? item.hostWorkspacePath) === containerWorkdir);
|
|
261
|
+
if (twin)
|
|
262
|
+
return { kind: 'duplicate', caseName: twin.name };
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
246
265
|
/**
|
|
247
266
|
* An ADOPTED container is one the user built and runs themselves. Codeman may
|
|
248
267
|
* only exec into it; it must never create, start, stop, restart or remove it.
|
|
@@ -381,8 +400,61 @@ export function buildDockerCreateArgs(ctx) {
|
|
|
381
400
|
* scripts/build-agent-image.mjs): `build -f <dockerfile> -t <image> [--no-cache]
|
|
382
401
|
* <contextDir>`. Kept pure + unit-testable; the caller prepends the engine binary.
|
|
383
402
|
*/
|
|
384
|
-
export function agentImageBuildArgs(dockerfile, image, contextDir, noCache = false) {
|
|
385
|
-
return [
|
|
403
|
+
export function agentImageBuildArgs(dockerfile, image, contextDir, noCache = false, buildArgs = []) {
|
|
404
|
+
return [
|
|
405
|
+
'build',
|
|
406
|
+
'-f',
|
|
407
|
+
dockerfile,
|
|
408
|
+
'-t',
|
|
409
|
+
image,
|
|
410
|
+
...(noCache ? ['--no-cache'] : []),
|
|
411
|
+
...buildArgs.flatMap(([name, value]) => ['--build-arg', `${name}=${value}`]),
|
|
412
|
+
contextDir,
|
|
413
|
+
];
|
|
414
|
+
}
|
|
415
|
+
/** Tokens allowed in an npm package name reaching a Dockerfile build arg unquoted. */
|
|
416
|
+
const SAFE_PACKAGE = /^[@A-Za-z0-9][@A-Za-z0-9/._-]*$/;
|
|
417
|
+
/**
|
|
418
|
+
* npm packages the agent image installs in its shared layer, from the STOCK catalogue.
|
|
419
|
+
*
|
|
420
|
+
* ⚠️ Stock, deliberately, NOT the merged registry. A user's `~/.codeman/clis.json` must not
|
|
421
|
+
* change what lands inside an image tagged `codeman/agent:base`, or two machines holding that
|
|
422
|
+
* same tag hold different images and every cache-hit decision downstream is a lie.
|
|
423
|
+
*
|
|
424
|
+
* ⚠️ An entry carrying `discovery.install.agentImageLayer` is excluded here — see that field's
|
|
425
|
+
* doc comment in `types.ts` for why some CLIs need their own hand-written Dockerfile layer
|
|
426
|
+
* instead of the shared one, and `test/docker-agent-image-coverage.test.ts` for the guard that
|
|
427
|
+
* an exclusion here still lands in the Dockerfile somewhere.
|
|
428
|
+
*
|
|
429
|
+
* ⚠️ This mirrors `agentImageNpmPackages()` in `scripts/lib/cli-catalog.mjs`, which the CLI
|
|
430
|
+
* build path uses because a `.mjs` cannot import TypeScript. Two producers of one command
|
|
431
|
+
* line drift; `test/agent-image-build-args-parity.test.ts` is what stops them — including the
|
|
432
|
+
* SAFE_PACKAGE regex below, which is duplicated (not imported) in that file for the same
|
|
433
|
+
* reason and must stay byte-identical to it.
|
|
434
|
+
*/
|
|
435
|
+
export function agentImageNpmPackages() {
|
|
436
|
+
const packages = [];
|
|
437
|
+
for (const entry of STOCK_CLIS) {
|
|
438
|
+
if (!entry.enabled || entry.discovery.install.agentImageLayer)
|
|
439
|
+
continue;
|
|
440
|
+
const pkg = entry.discovery.install.npmPackage;
|
|
441
|
+
if (!pkg)
|
|
442
|
+
continue;
|
|
443
|
+
// The value is interpolated into a Dockerfile ARG expanded UNQUOTED (word splitting is
|
|
444
|
+
// how the list becomes several arguments), so a token with whitespace or shell
|
|
445
|
+
// metacharacters would change what the RUN line means. The source is `stock.ts`, so the
|
|
446
|
+
// practical risk is nil, but this is the in-app auto-build path and the only one of the
|
|
447
|
+
// two producers where that had gone unchecked.
|
|
448
|
+
if (!SAFE_PACKAGE.test(pkg)) {
|
|
449
|
+
throw new Error(`Refusing unsafe npm package name for "${String(entry.id)}": ${JSON.stringify(pkg)}`);
|
|
450
|
+
}
|
|
451
|
+
packages.push(pkg);
|
|
452
|
+
}
|
|
453
|
+
return packages;
|
|
454
|
+
}
|
|
455
|
+
/** The `--build-arg` pairs the agent image takes. */
|
|
456
|
+
export function agentImageBuildArgPairs() {
|
|
457
|
+
return [['CLI_NPM_PACKAGES', agentImageNpmPackages().join(' ')]];
|
|
386
458
|
}
|
|
387
459
|
// ========== Credential mount resolution (IO) ==========
|
|
388
460
|
/** Container Claude config dir (created gid-0 writable in the image). */
|
|
@@ -802,7 +874,7 @@ function buildAgentImage(docker, image, opts) {
|
|
|
802
874
|
const argv = dockerEngineArgv(docker);
|
|
803
875
|
const args = [
|
|
804
876
|
...argv.slice(1),
|
|
805
|
-
...agentImageBuildArgs(resolved.dockerfile, image, resolved.contextDir, opts.noCache),
|
|
877
|
+
...agentImageBuildArgs(resolved.dockerfile, image, resolved.contextDir, opts.noCache, agentImageBuildArgPairs()),
|
|
806
878
|
];
|
|
807
879
|
return new Promise((resolve) => {
|
|
808
880
|
// async spawn (NEVER spawnSync) so a multi-minute build never wedges the event loop.
|