@atomic-chat/core 0.20.6 → 0.21.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/dist/audio/jobs.js +4 -0
- package/dist/audio/jobs.js.map +1 -1
- package/dist/audio/service.d.ts +1 -1
- package/dist/audio/service.js +3 -1
- package/dist/audio/service.js.map +1 -1
- package/dist/audio/session.js +28 -16
- package/dist/audio/session.js.map +1 -1
- package/dist/audio/state.d.ts +3 -1
- package/dist/audio/state.js +3 -1
- package/dist/audio/state.js.map +1 -1
- package/dist/cli/launch.d.ts +23 -3
- package/dist/cli/launch.js +59 -8
- package/dist/cli/launch.js.map +1 -1
- package/dist/cli/main.d.ts +1 -1
- package/dist/contracts/events.d.ts +8 -0
- package/dist/contracts/settings.d.ts +5 -0
- package/dist/contracts/settings.js.map +1 -1
- package/dist/core/atomic-core.d.ts +3 -1
- package/dist/core/atomic-core.js +4 -1
- package/dist/core/atomic-core.js.map +1 -1
- package/dist/core/create.js +4 -1
- package/dist/core/create.js.map +1 -1
- package/dist/core/sessions.js +1 -0
- package/dist/core/sessions.js.map +1 -1
- package/dist/integrations/catalog.d.ts +25 -8
- package/dist/integrations/catalog.js +105 -38
- package/dist/integrations/catalog.js.map +1 -1
- package/dist/integrations/configure/atomic-agent.d.ts +9 -1
- package/dist/integrations/configure/atomic-agent.js +42 -3
- package/dist/integrations/configure/atomic-agent.js.map +1 -1
- package/dist/integrations/configure/backup.d.ts +21 -0
- package/dist/integrations/configure/backup.js +52 -0
- package/dist/integrations/configure/backup.js.map +1 -0
- package/dist/integrations/configure/claude-code.d.ts +11 -4
- package/dist/integrations/configure/claude-code.js +73 -24
- package/dist/integrations/configure/claude-code.js.map +1 -1
- package/dist/integrations/configure/cline.d.ts +14 -4
- package/dist/integrations/configure/cline.js +78 -6
- package/dist/integrations/configure/cline.js.map +1 -1
- package/dist/integrations/configure/codex.d.ts +5 -3
- package/dist/integrations/configure/codex.js +12 -5
- package/dist/integrations/configure/codex.js.map +1 -1
- package/dist/integrations/configure/copilot.d.ts +28 -5
- package/dist/integrations/configure/copilot.js +124 -8
- package/dist/integrations/configure/copilot.js.map +1 -1
- package/dist/integrations/configure/droid.d.ts +13 -7
- package/dist/integrations/configure/droid.js +48 -17
- package/dist/integrations/configure/droid.js.map +1 -1
- package/dist/integrations/configure/dsh.d.ts +36 -20
- package/dist/integrations/configure/dsh.js +250 -48
- package/dist/integrations/configure/dsh.js.map +1 -1
- package/dist/integrations/configure/goose.d.ts +21 -7
- package/dist/integrations/configure/goose.js +141 -10
- package/dist/integrations/configure/goose.js.map +1 -1
- package/dist/integrations/configure/hermes.d.ts +63 -10
- package/dist/integrations/configure/hermes.js +360 -75
- package/dist/integrations/configure/hermes.js.map +1 -1
- package/dist/integrations/configure/json-backup.d.ts +73 -0
- package/dist/integrations/configure/json-backup.js +292 -0
- package/dist/integrations/configure/json-backup.js.map +1 -0
- package/dist/integrations/configure/json-key-backup.d.ts +43 -0
- package/dist/integrations/configure/json-key-backup.js +113 -0
- package/dist/integrations/configure/json-key-backup.js.map +1 -0
- package/dist/integrations/configure/kilo.d.ts +4 -4
- package/dist/integrations/configure/kilo.js +6 -9
- package/dist/integrations/configure/kilo.js.map +1 -1
- package/dist/integrations/configure/legacy-env-block.d.ts +18 -0
- package/dist/integrations/configure/legacy-env-block.js +47 -0
- package/dist/integrations/configure/legacy-env-block.js.map +1 -0
- package/dist/integrations/configure/mimo.d.ts +3 -2
- package/dist/integrations/configure/mimo.js +8 -9
- package/dist/integrations/configure/mimo.js.map +1 -1
- package/dist/integrations/configure/muse.d.ts +3 -3
- package/dist/integrations/configure/muse.js +5 -6
- package/dist/integrations/configure/muse.js.map +1 -1
- package/dist/integrations/configure/openclaude.d.ts +22 -7
- package/dist/integrations/configure/openclaude.js +132 -39
- package/dist/integrations/configure/openclaude.js.map +1 -1
- package/dist/integrations/configure/openclaw.d.ts +19 -5
- package/dist/integrations/configure/openclaw.js +79 -23
- package/dist/integrations/configure/openclaw.js.map +1 -1
- package/dist/integrations/configure/opencode-style.d.ts +53 -11
- package/dist/integrations/configure/opencode-style.js +218 -23
- package/dist/integrations/configure/opencode-style.js.map +1 -1
- package/dist/integrations/configure/opencode.d.ts +5 -4
- package/dist/integrations/configure/opencode.js +8 -10
- package/dist/integrations/configure/opencode.js.map +1 -1
- package/dist/integrations/configure/openhands.d.ts +5 -4
- package/dist/integrations/configure/openhands.js +7 -7
- package/dist/integrations/configure/openhands.js.map +1 -1
- package/dist/integrations/configure/pi.d.ts +6 -5
- package/dist/integrations/configure/pi.js +79 -30
- package/dist/integrations/configure/pi.js.map +1 -1
- package/dist/integrations/configure/poolside.d.ts +5 -4
- package/dist/integrations/configure/poolside.js +7 -7
- package/dist/integrations/configure/poolside.js.map +1 -1
- package/dist/integrations/configure/registry.d.ts +6 -0
- package/dist/integrations/configure/registry.js +1 -0
- package/dist/integrations/configure/registry.js.map +1 -1
- package/dist/integrations/configure/zcode.d.ts +6 -7
- package/dist/integrations/configure/zcode.js +26 -11
- package/dist/integrations/configure/zcode.js.map +1 -1
- package/dist/integrations/configure/zed.d.ts +16 -4
- package/dist/integrations/configure/zed.js +61 -13
- package/dist/integrations/configure/zed.js.map +1 -1
- package/dist/models/gguf/kv-cache.d.ts +20 -1
- package/dist/models/gguf/kv-cache.js +97 -7
- package/dist/models/gguf/kv-cache.js.map +1 -1
- package/dist/models/gguf/reader.d.ts +5 -3
- package/dist/models/gguf/reader.js +10 -6
- package/dist/models/gguf/reader.js.map +1 -1
- package/dist/runtime/llamacpp/args.d.ts +14 -0
- package/dist/runtime/llamacpp/args.js +48 -4
- package/dist/runtime/llamacpp/args.js.map +1 -1
- package/dist/runtime/llamacpp/ctx-ladder.d.ts +6 -3
- package/dist/runtime/llamacpp/ctx-ladder.js +6 -3
- package/dist/runtime/llamacpp/ctx-ladder.js.map +1 -1
- package/dist/runtime/llamacpp/fit-margin.d.ts +24 -0
- package/dist/runtime/llamacpp/fit-margin.js +31 -0
- package/dist/runtime/llamacpp/fit-margin.js.map +1 -1
- package/dist/runtime/llamacpp/generation-limits.d.ts +45 -0
- package/dist/runtime/llamacpp/generation-limits.js +61 -0
- package/dist/runtime/llamacpp/generation-limits.js.map +1 -0
- package/dist/runtime/llamacpp/load-plan.d.ts +14 -2
- package/dist/runtime/llamacpp/load-plan.js +64 -13
- package/dist/runtime/llamacpp/load-plan.js.map +1 -1
- package/dist/runtime/llamacpp/runtime.d.ts +1 -0
- package/dist/runtime/llamacpp/runtime.js +2 -0
- package/dist/runtime/llamacpp/runtime.js.map +1 -1
- package/dist/runtime/managed-engines/runtime.js +13 -2
- package/dist/runtime/managed-engines/runtime.js.map +1 -1
- package/dist/runtime/managed-engines/spec.d.ts +6 -0
- package/dist/runtime/managed-engines/spec.js.map +1 -1
- package/dist/runtime/managed-models/auto-limits.d.ts +47 -0
- package/dist/runtime/managed-models/auto-limits.js +60 -0
- package/dist/runtime/managed-models/auto-limits.js.map +1 -0
- package/dist/runtime/managed-models/index.d.ts +1 -0
- package/dist/runtime/managed-models/index.js +1 -0
- package/dist/runtime/managed-models/index.js.map +1 -1
- package/dist/runtime/mlx/config.d.ts +9 -5
- package/dist/runtime/mlx/config.js +12 -6
- package/dist/runtime/mlx/config.js.map +1 -1
- package/dist/runtime/mlx/model-files.d.ts +9 -0
- package/dist/runtime/mlx/model-files.js +26 -0
- package/dist/runtime/mlx/model-files.js.map +1 -1
- package/dist/runtime/mlx/runtime.d.ts +7 -0
- package/dist/runtime/mlx/runtime.js +24 -2
- package/dist/runtime/mlx/runtime.js.map +1 -1
- package/dist/runtime/sglang/adapter.d.ts +4 -0
- package/dist/runtime/sglang/adapter.js +9 -6
- package/dist/runtime/sglang/adapter.js.map +1 -1
- package/dist/runtime/sglang/engine.js +2 -1
- package/dist/runtime/sglang/engine.js.map +1 -1
- package/dist/runtime/sglang/memory.d.ts +11 -1
- package/dist/runtime/sglang/memory.js +34 -3
- package/dist/runtime/sglang/memory.js.map +1 -1
- package/dist/runtime/sglang/settings.d.ts +2 -1
- package/dist/runtime/sglang/settings.js +11 -7
- package/dist/runtime/sglang/settings.js.map +1 -1
- package/dist/runtime/vllm/adapter.d.ts +4 -0
- package/dist/runtime/vllm/adapter.js +9 -6
- package/dist/runtime/vllm/adapter.js.map +1 -1
- package/dist/runtime/vllm/engine.js +1 -0
- package/dist/runtime/vllm/engine.js.map +1 -1
- package/dist/runtime/vllm/memory.d.ts +12 -1
- package/dist/runtime/vllm/memory.js +44 -2
- package/dist/runtime/vllm/memory.js.map +1 -1
- package/dist/runtime/vllm/settings.d.ts +2 -1
- package/dist/runtime/vllm/settings.js +12 -7
- package/dist/runtime/vllm/settings.js.map +1 -1
- package/dist/server/public/context-window.d.ts +29 -0
- package/dist/server/public/context-window.js +77 -0
- package/dist/server/public/context-window.js.map +1 -0
- package/dist/server/public/decision-preview.js +1 -0
- package/dist/server/public/decision-preview.js.map +1 -1
- package/dist/server/public/errors.d.ts +15 -4
- package/dist/server/public/errors.js +53 -7
- package/dist/server/public/errors.js.map +1 -1
- package/dist/server/public/forward.js +65 -5
- package/dist/server/public/forward.js.map +1 -1
- package/dist/server/public/index.d.ts +1 -0
- package/dist/server/public/index.js +1 -0
- package/dist/server/public/index.js.map +1 -1
- package/dist/server/public/listing.d.ts +9 -2
- package/dist/server/public/listing.js +30 -9
- package/dist/server/public/listing.js.map +1 -1
- package/dist/server/public/responses.js +9 -5
- package/dist/server/public/responses.js.map +1 -1
- package/dist/server/public/system-messages.d.ts +39 -0
- package/dist/server/public/system-messages.js +166 -0
- package/dist/server/public/system-messages.js.map +1 -0
- package/dist/server/public/telemetry.d.ts +9 -0
- package/dist/server/public/telemetry.js +42 -6
- package/dist/server/public/telemetry.js.map +1 -1
- package/dist/server/public/thinking.d.ts +26 -0
- package/dist/server/public/thinking.js +62 -0
- package/dist/server/public/thinking.js.map +1 -0
- package/dist/server/public/trace.d.ts +8 -0
- package/dist/server/public/trace.js +17 -0
- package/dist/server/public/trace.js.map +1 -1
- package/dist/server/public/types.d.ts +8 -0
- package/dist/server/shims/index.d.ts +1 -0
- package/dist/server/shims/index.js +1 -0
- package/dist/server/shims/index.js.map +1 -1
- package/dist/server/shims/reminders.d.ts +8 -0
- package/dist/server/shims/reminders.js +14 -0
- package/dist/server/shims/reminders.js.map +1 -0
- package/dist/server/shims/responses.d.ts +33 -9
- package/dist/server/shims/responses.js +160 -36
- package/dist/server/shims/responses.js.map +1 -1
- package/dist/settings/default-migrations.d.ts +34 -0
- package/dist/settings/default-migrations.js +47 -0
- package/dist/settings/default-migrations.js.map +1 -0
- package/dist/settings/schema/atomic-prism.json +23 -9
- package/dist/settings/schema/llamacpp-upstream.json +23 -9
- package/dist/settings/schema/llamacpp.json +23 -9
- package/dist/settings/schema/sglang.json +8 -8
- package/dist/settings/schema/vllm.json +8 -8
- package/dist/settings/schema.js +1 -0
- package/dist/settings/schema.js.map +1 -1
- package/dist/settings/store.d.ts +6 -0
- package/dist/settings/store.js +18 -1
- package/dist/settings/store.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenHands, Poolside and Muse Code read their endpoint from the environment only. Older releases
|
|
3
|
+
* persisted it — a marked block in the user's shell rc, `setx` on Windows — which captured every
|
|
4
|
+
* other use of the agent (a cloud key replaced by our placeholder, a dead localhost once the server
|
|
5
|
+
* stops). Now the variables are set only on the process we launch (`childEnv`, and inline in the
|
|
6
|
+
* app's terminal), and Connect removes the block an older release wrote: exactly the region between
|
|
7
|
+
* its paired marker lines, never a user's own export of the same variable. Mirrors
|
|
8
|
+
* `remove_legacy_env_agent_config` in the app's `core/system/commands.rs`; the Windows `setx`
|
|
9
|
+
* variables are removed by the app alone.
|
|
10
|
+
*/
|
|
11
|
+
/** The rc files an older release may have written to: which one depended on `$SHELL` back then. */
|
|
12
|
+
const LEGACY_RC_FILES = ['.zshenv', '.bash_profile', '.bashrc'];
|
|
13
|
+
/** `content` without the region between (and including) the paired `marker` lines. */
|
|
14
|
+
export function removeMarkedEnvBlock(content, marker) {
|
|
15
|
+
const lines = content.split('\n');
|
|
16
|
+
if (!lines.some((line) => line.startsWith(marker)))
|
|
17
|
+
return content;
|
|
18
|
+
let inBlock = false;
|
|
19
|
+
return lines
|
|
20
|
+
.filter((line) => {
|
|
21
|
+
if (line.startsWith(marker)) {
|
|
22
|
+
inBlock = !inBlock;
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
return !inBlock;
|
|
26
|
+
})
|
|
27
|
+
.join('\n');
|
|
28
|
+
}
|
|
29
|
+
/** Remove `marker`'s block from every rc file that has one; files without it are not touched. */
|
|
30
|
+
export async function removeLegacyEnvBlocks(fs, marker) {
|
|
31
|
+
for (const rc of LEGACY_RC_FILES) {
|
|
32
|
+
const content = await fs.read(rc);
|
|
33
|
+
if (content === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
const cleaned = removeMarkedEnvBlock(content, marker);
|
|
36
|
+
if (cleaned !== content)
|
|
37
|
+
await fs.write(rc, cleaned);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** The writer of an agent configured through its launch environment alone. */
|
|
41
|
+
export function legacyEnvAgentWriter(marker) {
|
|
42
|
+
return async ({ fs, platform }) => {
|
|
43
|
+
if (platform !== 'win32')
|
|
44
|
+
await removeLegacyEnvBlocks(fs, marker);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=legacy-env-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-env-block.js","sourceRoot":"","sources":["../../../src/integrations/configure/legacy-env-block.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,mGAAmG;AACnG,MAAM,eAAe,GAAG,CAAC,SAAS,EAAE,eAAe,EAAE,SAAS,CAAC,CAAA;AAE/D,sFAAsF;AACtF,MAAM,UAAU,oBAAoB,CAAC,OAAe,EAAE,MAAc;IAClE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAAE,OAAO,OAAO,CAAA;IAClE,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE;QACf,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,OAAO,GAAG,CAAC,OAAO,CAAA;YAClB,OAAO,KAAK,CAAA;QACd,CAAC;QACD,OAAO,CAAC,OAAO,CAAA;IACjB,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAA;AACf,CAAC;AAED,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,EAAY,EAAE,MAAc;IACtE,KAAK,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACjC,IAAI,OAAO,KAAK,SAAS;YAAE,SAAQ;QACnC,MAAM,OAAO,GAAG,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QACrD,IAAI,OAAO,KAAK,OAAO;YAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,OAAO,CAAC,CAAA;IACtD,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,oBAAoB,CAAC,MAAc;IACjD,OAAO,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QAChC,IAAI,QAAQ,KAAK,OAAO;YAAE,MAAM,qBAAqB,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IACnE,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MiMo Code —
|
|
2
|
+
* MiMo Code — `mimocode.jsonc` when there is one, else `mimocode.json`, in `$MIMOCODE_HOME/config`,
|
|
3
|
+
* else `~/.config/mimocode`.
|
|
3
4
|
*
|
|
4
5
|
* Port of `configure_mimo` in `src-tauri/src/core/system/commands.rs`. MiMo Code is a fork of
|
|
5
6
|
* OpenCode and its config is OpenCode's field for field; only the directory, the file name and the
|
|
6
|
-
* `$schema` URL differ.
|
|
7
|
+
* `$schema` URL differ. Earlier releases wrote a `$schema` MiMo does not serve; it is corrected.
|
|
7
8
|
*/
|
|
8
9
|
import type { ConfigureInput } from './registry.js';
|
|
9
10
|
export declare function configureMimo(input: ConfigureInput): Promise<void>;
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MiMo Code —
|
|
2
|
+
* MiMo Code — `mimocode.jsonc` when there is one, else `mimocode.json`, in `$MIMOCODE_HOME/config`,
|
|
3
|
+
* else `~/.config/mimocode`.
|
|
3
4
|
*
|
|
4
5
|
* Port of `configure_mimo` in `src-tauri/src/core/system/commands.rs`. MiMo Code is a fork of
|
|
5
6
|
* OpenCode and its config is OpenCode's field for field; only the directory, the file name and the
|
|
6
|
-
* `$schema` URL differ.
|
|
7
|
+
* `$schema` URL differ. Earlier releases wrote a `$schema` MiMo does not serve; it is corrected.
|
|
7
8
|
*/
|
|
8
9
|
import { registerWriter } from './registry.js';
|
|
9
|
-
import { writeOpencodeStyleConfig } from './opencode-style.js';
|
|
10
|
-
export function configureMimo(input) {
|
|
11
|
-
return writeOpencodeStyleConfig(input, {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
schema: 'https://mimo.xiaomi.com/config.json',
|
|
15
|
-
lenient: false,
|
|
10
|
+
import { mimoTarget, writeOpencodeStyleConfig } from './opencode-style.js';
|
|
11
|
+
export async function configureMimo(input) {
|
|
12
|
+
return writeOpencodeStyleConfig(input, await mimoTarget(input.fs, input.env), {
|
|
13
|
+
schema: 'https://mimo.xiaomi.com/mimocode/config.json',
|
|
14
|
+
staleSchema: 'https://mimo.xiaomi.com/config.json',
|
|
16
15
|
});
|
|
17
16
|
}
|
|
18
17
|
registerWriter('mimo', configureMimo);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mimo.js","sourceRoot":"","sources":["../../../src/integrations/configure/mimo.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mimo.js","sourceRoot":"","sources":["../../../src/integrations/configure/mimo.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAE1E,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAqB;IACvD,OAAO,wBAAwB,CAAC,KAAK,EAAE,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE;QAC5E,MAAM,EAAE,8CAA8C;QACtD,WAAW,EAAE,qCAAqC;KACnD,CAAC,CAAA;AACJ,CAAC;AAED,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Muse Code is the one agent with no writable endpoint configuration at all: the provider is chosen
|
|
3
3
|
* per invocation with `--provider meta --base-url <url> --model <id>` (see the catalog's run args),
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* and Muse only checks that `META_API_KEY` is present — the call goes wherever `--base-url` points —
|
|
5
|
+
* so the local server's own key (or the `atomic` placeholder) set on the child satisfies both ends.
|
|
6
|
+
* Nothing is persisted; Connect only removes what an older release did (`legacy-env-block.ts`).
|
|
7
7
|
*/
|
|
8
8
|
import type { ConfigureWriter } from './registry.js';
|
|
9
9
|
export declare const configureMuse: ConfigureWriter;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Muse Code is the one agent with no writable endpoint configuration at all: the provider is chosen
|
|
3
3
|
* per invocation with `--provider meta --base-url <url> --model <id>` (see the catalog's run args),
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* and Muse only checks that `META_API_KEY` is present — the call goes wherever `--base-url` points —
|
|
5
|
+
* so the local server's own key (or the `atomic` placeholder) set on the child satisfies both ends.
|
|
6
|
+
* Nothing is persisted; Connect only removes what an older release did (`legacy-env-block.ts`).
|
|
7
7
|
*/
|
|
8
|
+
import { legacyEnvAgentWriter } from './legacy-env-block.js';
|
|
8
9
|
import { registerWriter } from './registry.js';
|
|
9
|
-
|
|
10
|
-
const MARKER = '# Atomic Chat - Muse Code Config';
|
|
11
|
-
export const configureMuse = (input) => configureEnvAgent(input, { agentId: 'muse', marker: MARKER, prefix: 'META_' });
|
|
10
|
+
export const configureMuse = legacyEnvAgentWriter('# Atomic Chat - Muse Code Config');
|
|
12
11
|
registerWriter('muse', configureMuse);
|
|
13
12
|
//# sourceMappingURL=muse.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"muse.js","sourceRoot":"","sources":["../../../src/integrations/configure/muse.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"muse.js","sourceRoot":"","sources":["../../../src/integrations/configure/muse.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,MAAM,CAAC,MAAM,aAAa,GAAoB,oBAAoB,CAAC,kCAAkC,CAAC,CAAA;AAEtG,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA"}
|
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenClaude — `~/.openclaude.json` plus
|
|
2
|
+
* OpenClaude — its global config (`~/.openclaude.json`) plus the startup profile
|
|
3
|
+
* (`~/.openclaude/.openclaude-profile.json`).
|
|
3
4
|
*
|
|
4
|
-
* Port of `configure_openclaude` in `src-tauri/src/core/system/
|
|
5
|
-
* list of provider profiles in its global config and a
|
|
6
|
-
* the environment its launcher exports; both have to
|
|
5
|
+
* Port of `configure_openclaude` / `connect_openclaude` in the app (`src-tauri/src/core/system/
|
|
6
|
+
* claude_config.rs`). OpenClaude keeps a list of provider profiles in its global config and a
|
|
7
|
+
* separate startup-profile file that carries the environment its launcher exports; both have to
|
|
8
|
+
* agree, so both are written. Paths follow OpenClaude 0.34: the config home is
|
|
9
|
+
* `$OPENCLAUDE_CONFIG_DIR`, else `~/.openclaude`; a `.config.json` there is the global config, else
|
|
10
|
+
* `.openclaude.json` in `$OPENCLAUDE_CONFIG_DIR` or the home directory.
|
|
7
11
|
*
|
|
8
|
-
* OpenClaude routes us through its OpenAI-compatible shim and
|
|
9
|
-
*
|
|
10
|
-
*
|
|
12
|
+
* OpenClaude routes us through its OpenAI-compatible shim and sends the profile's `apiKey` as a
|
|
13
|
+
* bearer token, so the server's key goes into the profile (`atomic` for a keyless server) — without
|
|
14
|
+
* it a keyed server answers 401. Our profile is matched by its id only: one the user made from
|
|
15
|
+
* OpenClaude's own Atomic Chat preset is theirs. With a known window the profile carries
|
|
16
|
+
* `maxContextLength`, and the global `env` an output cap for the model (a profile has no output
|
|
17
|
+
* setting). The global `env` also gets empty values for the shell variables that would make
|
|
18
|
+
* OpenClaude skip its active profile: it applies that `env` before deciding. What every key held
|
|
19
|
+
* before is kept in the sidecars `json-backup.ts` describes, for the app's Disconnect.
|
|
11
20
|
*/
|
|
21
|
+
import type { ConfigFs } from '../config-io.js';
|
|
12
22
|
import type { ConfigureInput } from './registry.js';
|
|
23
|
+
export interface OpenclaudePaths {
|
|
24
|
+
config: string;
|
|
25
|
+
profile: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function openclaudePaths(fs: ConfigFs, env: NodeJS.ProcessEnv): Promise<OpenclaudePaths>;
|
|
13
28
|
export declare function configureOpenclaude(input: ConfigureInput): Promise<void>;
|
|
@@ -1,56 +1,149 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenClaude — `~/.openclaude.json` plus
|
|
2
|
+
* OpenClaude — its global config (`~/.openclaude.json`) plus the startup profile
|
|
3
|
+
* (`~/.openclaude/.openclaude-profile.json`).
|
|
3
4
|
*
|
|
4
|
-
* Port of `configure_openclaude` in `src-tauri/src/core/system/
|
|
5
|
-
* list of provider profiles in its global config and a
|
|
6
|
-
* the environment its launcher exports; both have to
|
|
5
|
+
* Port of `configure_openclaude` / `connect_openclaude` in the app (`src-tauri/src/core/system/
|
|
6
|
+
* claude_config.rs`). OpenClaude keeps a list of provider profiles in its global config and a
|
|
7
|
+
* separate startup-profile file that carries the environment its launcher exports; both have to
|
|
8
|
+
* agree, so both are written. Paths follow OpenClaude 0.34: the config home is
|
|
9
|
+
* `$OPENCLAUDE_CONFIG_DIR`, else `~/.openclaude`; a `.config.json` there is the global config, else
|
|
10
|
+
* `.openclaude.json` in `$OPENCLAUDE_CONFIG_DIR` or the home directory.
|
|
7
11
|
*
|
|
8
|
-
* OpenClaude routes us through its OpenAI-compatible shim and
|
|
9
|
-
*
|
|
10
|
-
*
|
|
12
|
+
* OpenClaude routes us through its OpenAI-compatible shim and sends the profile's `apiKey` as a
|
|
13
|
+
* bearer token, so the server's key goes into the profile (`atomic` for a keyless server) — without
|
|
14
|
+
* it a keyed server answers 401. Our profile is matched by its id only: one the user made from
|
|
15
|
+
* OpenClaude's own Atomic Chat preset is theirs. With a known window the profile carries
|
|
16
|
+
* `maxContextLength`, and the global `env` an output cap for the model (a profile has no output
|
|
17
|
+
* setting). The global `env` also gets empty values for the shell variables that would make
|
|
18
|
+
* OpenClaude skip its active profile: it applies that `env` before deciding. What every key held
|
|
19
|
+
* before is kept in the sidecars `json-backup.ts` describes, for the app's Disconnect.
|
|
11
20
|
*/
|
|
21
|
+
import { join } from 'node:path';
|
|
12
22
|
import { AtomicCoreError } from '../../contracts/index.js';
|
|
13
|
-
import { canonicalJson, parseJsonStrict } from '../config-io.js';
|
|
23
|
+
import { canonicalJson, keyOr, parseJsonStrict } from '../config-io.js';
|
|
24
|
+
import { configDirFrom, getAt, isOurServerUrl, jsonEqual, ourServerFromUrl, outputCap, readBackup, redo, wholeFileBackup, writeBackup, writeConfigFile, } from './json-backup.js';
|
|
14
25
|
import { asJsonArray, asJsonObject } from './json-tree.js';
|
|
15
26
|
import { registerWriter } from './registry.js';
|
|
16
|
-
const CONFIG_PATH = '.openclaude.json';
|
|
17
|
-
const CONFIG_HOME = '.openclaude';
|
|
18
|
-
const PROFILE_PATH = `${CONFIG_HOME}/.openclaude-profile.json`;
|
|
19
27
|
const ATOMIC_PROFILE_ID = 'provider_atomic_chat';
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
const PROVIDER = 'atomic-chat';
|
|
29
|
+
/**
|
|
30
|
+
* With `CLAUDE_CODE_USE_OPENAI` plus a base URL or model (or a complete `ANTHROPIC_*` trio) in the
|
|
31
|
+
* environment, OpenClaude treats the shell as the user's choice and skips its active profile
|
|
32
|
+
* (`hasCompleteProviderSelection`). Empty values in the global config's `env` take a shell's
|
|
33
|
+
* leftovers out of that decision; once our profile applies, OpenClaude clears and sets them itself.
|
|
34
|
+
*/
|
|
35
|
+
const SHELL_OVERRIDES = [
|
|
36
|
+
'CLAUDE_CODE_USE_OPENAI',
|
|
37
|
+
'OPENAI_BASE_URL',
|
|
38
|
+
'OPENAI_API_BASE',
|
|
39
|
+
'OPENAI_MODEL',
|
|
40
|
+
'ANTHROPIC_BASE_URL',
|
|
41
|
+
'CLAUDE_CODE_USE_GEMINI_VERTEX',
|
|
42
|
+
];
|
|
43
|
+
const PROFILE_PATH = ['providerProfiles', { id: ATOMIC_PROFILE_ID }];
|
|
44
|
+
export async function openclaudePaths(fs, env) {
|
|
45
|
+
const dir = configDirFrom(env['OPENCLAUDE_CONFIG_DIR'], fs.home);
|
|
46
|
+
const configHome = dir ?? '.openclaude';
|
|
47
|
+
const legacy = dir === undefined ? `${configHome}/.config.json` : join(configHome, '.config.json');
|
|
48
|
+
const config = (await fs.exists(legacy))
|
|
49
|
+
? legacy
|
|
50
|
+
: dir === undefined
|
|
51
|
+
? '.openclaude.json'
|
|
52
|
+
: join(dir, '.openclaude.json');
|
|
53
|
+
const profile = dir === undefined ? `${configHome}/.openclaude-profile.json` : join(dir, '.openclaude-profile.json');
|
|
54
|
+
return { config, profile };
|
|
55
|
+
}
|
|
56
|
+
function writesFor(input) {
|
|
57
|
+
const { apiUrl, model, apiKey, contextLength } = input;
|
|
58
|
+
const window = contextLength !== undefined && contextLength > 0 ? contextLength : undefined;
|
|
59
|
+
const profile = {
|
|
29
60
|
id: ATOMIC_PROFILE_ID,
|
|
30
61
|
name: 'Atomic Chat',
|
|
31
|
-
provider:
|
|
62
|
+
provider: PROVIDER,
|
|
63
|
+
apiKey: keyOr(apiKey, 'atomic'),
|
|
32
64
|
baseUrl: apiUrl,
|
|
33
65
|
model,
|
|
34
66
|
};
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
if (window !== undefined)
|
|
68
|
+
profile['maxContextLength'] = window;
|
|
69
|
+
const writes = [
|
|
70
|
+
[PROFILE_PATH, profile],
|
|
71
|
+
[['activeProviderProfileId'], ATOMIC_PROFILE_ID],
|
|
72
|
+
];
|
|
73
|
+
for (const name of SHELL_OVERRIDES)
|
|
74
|
+
writes.push([['env', name], '']);
|
|
75
|
+
if (window !== undefined) {
|
|
76
|
+
writes.push([
|
|
77
|
+
['env', 'CLAUDE_CODE_OPENAI_MAX_OUTPUT_TOKENS'],
|
|
78
|
+
JSON.stringify({ [model]: outputCap(window) }),
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
return writes;
|
|
82
|
+
}
|
|
83
|
+
/** What an earlier release wrote without a backup: our profile and the active pointer at it. */
|
|
84
|
+
function forgetLegacy(root) {
|
|
85
|
+
const profiles = asJsonArray(root['providerProfiles']);
|
|
86
|
+
if (profiles) {
|
|
87
|
+
for (let i = profiles.length - 1; i >= 0; i--) {
|
|
88
|
+
if (asJsonObject(profiles[i])?.['id'] === ATOMIC_PROFILE_ID)
|
|
89
|
+
profiles.splice(i, 1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (root['activeProviderProfileId'] === ATOMIC_PROFILE_ID)
|
|
93
|
+
delete root['activeProviderProfileId'];
|
|
94
|
+
}
|
|
95
|
+
function startupProfileIsOurs(doc, server) {
|
|
96
|
+
const base = getAt(doc, ['env', 'OPENAI_BASE_URL']);
|
|
97
|
+
return (asJsonObject(doc)?.['profile'] === PROVIDER && typeof base === 'string' && isOurServerUrl(server, base));
|
|
98
|
+
}
|
|
99
|
+
/** A startup profile that cannot be parsed counts as absent: OpenClaude ignores it too. */
|
|
100
|
+
async function readStartupProfile(fs, path) {
|
|
101
|
+
const text = await fs.read(path);
|
|
102
|
+
if (text === undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
try {
|
|
105
|
+
return parseJsonStrict(text, fs.absolute(path));
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function configureOpenclaude(input) {
|
|
112
|
+
const { fs, apiUrl, model, apiKey } = input;
|
|
113
|
+
const paths = await openclaudePaths(fs, input.env);
|
|
114
|
+
const text = await fs.read(paths.config);
|
|
115
|
+
const parsed = text === undefined ? {} : parseJsonStrict(text, fs.absolute(paths.config));
|
|
116
|
+
const root = asJsonObject(parsed);
|
|
117
|
+
if (!root)
|
|
118
|
+
throw new AtomicCoreError('IO_ERROR', `${fs.absolute(paths.config)} is not a JSON object`);
|
|
119
|
+
const backup = redo(root, await readBackup(fs, paths.config), text !== undefined, writesFor(input), [], forgetLegacy);
|
|
120
|
+
// Sidecar first: a crash between the two leaves a backup whose values simply do not match yet.
|
|
121
|
+
await writeBackup(fs, paths.config, backup);
|
|
122
|
+
await writeConfigFile(fs, paths.config, canonicalJson(root));
|
|
123
|
+
const doc = {
|
|
124
|
+
profile: PROVIDER,
|
|
125
|
+
env: { OPENAI_BASE_URL: apiUrl, OPENAI_MODEL: model, OPENAI_API_KEY: keyOr(apiKey, 'atomic') },
|
|
52
126
|
createdAt: new Date().toISOString(),
|
|
53
|
-
}
|
|
127
|
+
};
|
|
128
|
+
const current = await readStartupProfile(fs, paths.profile);
|
|
129
|
+
const previous = await readBackup(fs, paths.profile);
|
|
130
|
+
const entry = previous?.entries[0];
|
|
131
|
+
let existed;
|
|
132
|
+
let before;
|
|
133
|
+
if (entry && current !== undefined && jsonEqual(entry.written, current)) {
|
|
134
|
+
existed = entry.existed;
|
|
135
|
+
before = entry.previous;
|
|
136
|
+
}
|
|
137
|
+
else if (current !== undefined && !startupProfileIsOurs(current, ourServerFromUrl(apiUrl))) {
|
|
138
|
+
existed = true;
|
|
139
|
+
before = current;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
existed = false;
|
|
143
|
+
before = undefined;
|
|
144
|
+
}
|
|
145
|
+
await writeBackup(fs, paths.profile, wholeFileBackup(existed, before, doc));
|
|
146
|
+
await writeConfigFile(fs, paths.profile, canonicalJson(doc));
|
|
54
147
|
}
|
|
55
148
|
registerWriter('openclaude', configureOpenclaude);
|
|
56
149
|
//# sourceMappingURL=openclaude.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openclaude.js","sourceRoot":"","sources":["../../../src/integrations/configure/openclaude.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"openclaude.js","sourceRoot":"","sources":["../../../src/integrations/configure/openclaude.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,24 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenClaw keeps one config for the CLI and
|
|
2
|
+
* OpenClaw keeps one config for the CLI and the macOS app in `~/.openclaw/openclaw.json`
|
|
3
3
|
* (overridable with `OPENCLAW_CONFIG_PATH`); its Gateway watches the file and hot-reloads, so one
|
|
4
4
|
* write covers everything with no restart.
|
|
5
5
|
*
|
|
6
6
|
* The merge has two tiers. Keys that express a decision the user may have made deliberately are
|
|
7
|
-
* SEEDED only when absent — `models.mode`, `gateway.mode`, `gateway.auth.mode
|
|
8
|
-
*
|
|
9
|
-
* now" are always OVERWRITTEN — our provider block and
|
|
7
|
+
* SEEDED only when absent — `models.mode`, `gateway.mode`, `gateway.auth.mode` (and that one only
|
|
8
|
+
* when the Gateway has no token or password to expect), and the per-model settings entry. Keys that
|
|
9
|
+
* say "run this model now" are always OVERWRITTEN — our provider block and
|
|
10
|
+
* `agents.defaults.model.primary`. What the keys held before is recorded in
|
|
11
|
+
* `openclaw.json.atomic-chat-backup.json` for the app's Disconnect.
|
|
10
12
|
*
|
|
11
13
|
* The one non-obvious rule is `modelPolicy.allow`. When it is non-empty it gates model selection
|
|
12
14
|
* entirely, so a user restricted to a cloud provider would watch Run "succeed" and then be told our
|
|
13
15
|
* model is not allowed — hence the `atomic/*` widening. But an absent key or `[]` already means
|
|
14
16
|
* "allow anything", so writing into it would INTRODUCE a restriction nobody asked for. Those are
|
|
15
17
|
* left exactly as they are.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors `configure_openclaw_at` in the app's `core/system/commands.rs`, byte for byte.
|
|
16
20
|
*/
|
|
17
21
|
import type { JsonValue } from '../config-io.js';
|
|
18
22
|
import type { JsonObject } from './json-tree.js';
|
|
19
23
|
import type { ConfigureWriter } from './registry.js';
|
|
24
|
+
/** The output cap written next to a known window: a quarter of it, at most 8192 tokens. */
|
|
25
|
+
export declare function outputCapFor(contextLength: number): number;
|
|
20
26
|
/** Whether an allow-list already covers `modelRef`. A trailing `*` makes the entry a prefix match. */
|
|
21
27
|
export declare function modelPolicyAllows(list: JsonValue[], modelRef: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Bring a parsed `openclaw.json` into the shape the merge works on without changing what it means:
|
|
30
|
+
* a plain-string `agents.defaults.model` becomes `{ primary: <it> }`, and the
|
|
31
|
+
* `agents.defaults.timeoutSeconds: 240` older releases seeded goes.
|
|
32
|
+
*/
|
|
33
|
+
export declare function openclawNormalize(parsed: JsonValue): void;
|
|
34
|
+
/** The keys Connect may overwrite besides our own provider entry. */
|
|
35
|
+
export declare function openclawTrackedPaths(modelRef: string): string[][];
|
|
22
36
|
/** The whole merge, with no I/O, so every rule above is testable against a plain object. */
|
|
23
|
-
export declare function openclawPatchConfig(parsed: JsonValue, apiUrl: string, model: string, apiKey: string): JsonObject;
|
|
37
|
+
export declare function openclawPatchConfig(parsed: JsonValue, apiUrl: string, model: string, apiKey: string, contextLength?: number, gatewaySecretInEnv?: boolean): JsonObject;
|
|
24
38
|
export declare const configureOpenclaw: ConfigureWriter;
|
|
@@ -1,27 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* OpenClaw keeps one config for the CLI and
|
|
2
|
+
* OpenClaw keeps one config for the CLI and the macOS app in `~/.openclaw/openclaw.json`
|
|
3
3
|
* (overridable with `OPENCLAW_CONFIG_PATH`); its Gateway watches the file and hot-reloads, so one
|
|
4
4
|
* write covers everything with no restart.
|
|
5
5
|
*
|
|
6
6
|
* The merge has two tiers. Keys that express a decision the user may have made deliberately are
|
|
7
|
-
* SEEDED only when absent — `models.mode`, `gateway.mode`, `gateway.auth.mode
|
|
8
|
-
*
|
|
9
|
-
* now" are always OVERWRITTEN — our provider block and
|
|
7
|
+
* SEEDED only when absent — `models.mode`, `gateway.mode`, `gateway.auth.mode` (and that one only
|
|
8
|
+
* when the Gateway has no token or password to expect), and the per-model settings entry. Keys that
|
|
9
|
+
* say "run this model now" are always OVERWRITTEN — our provider block and
|
|
10
|
+
* `agents.defaults.model.primary`. What the keys held before is recorded in
|
|
11
|
+
* `openclaw.json.atomic-chat-backup.json` for the app's Disconnect.
|
|
10
12
|
*
|
|
11
13
|
* The one non-obvious rule is `modelPolicy.allow`. When it is non-empty it gates model selection
|
|
12
14
|
* entirely, so a user restricted to a cloud provider would watch Run "succeed" and then be told our
|
|
13
15
|
* model is not allowed — hence the `atomic/*` widening. But an absent key or `[]` already means
|
|
14
16
|
* "allow anything", so writing into it would INTRODUCE a restriction nobody asked for. Those are
|
|
15
17
|
* left exactly as they are.
|
|
18
|
+
*
|
|
19
|
+
* Mirrors `configure_openclaw_at` in the app's `core/system/commands.rs`, byte for byte.
|
|
16
20
|
*/
|
|
17
21
|
import { AtomicCoreError } from '../../contracts/index.js';
|
|
18
22
|
import { canonicalJson, keyOr, parseJsonLenient } from '../config-io.js';
|
|
23
|
+
import { readBackup, renderBackup, trackKeys, writeBackupText } from './json-key-backup.js';
|
|
19
24
|
import { asJsonArray, asJsonObject } from './json-tree.js';
|
|
20
25
|
import { registerWriter } from './registry.js';
|
|
21
26
|
const PROVIDER_ID = 'atomic';
|
|
22
27
|
const DEFAULT_PATH = '.openclaw/openclaw.json';
|
|
23
|
-
/**
|
|
24
|
-
|
|
28
|
+
/**
|
|
29
|
+
* Per-request budget on our provider: it covers connecting, the headers and streaming the body, and
|
|
30
|
+
* raises the ~120 s idle watchdog for this provider only — a long prompt on a slow machine needs
|
|
31
|
+
* more before the first token. Unlike `agents.defaults.timeoutSeconds`, it leaves every other model
|
|
32
|
+
* alone.
|
|
33
|
+
*/
|
|
34
|
+
const PROVIDER_TIMEOUT_SECONDS = 600;
|
|
35
|
+
/** `agents.defaults.timeoutSeconds` older releases seeded, capping every model's attempt. */
|
|
36
|
+
const LEGACY_AGENT_TIMEOUT_SECONDS = 240;
|
|
37
|
+
/** The output cap written next to a known window: a quarter of it, at most 8192 tokens. */
|
|
38
|
+
export function outputCapFor(contextLength) {
|
|
39
|
+
return Math.min(8192, Math.floor(contextLength / 4));
|
|
40
|
+
}
|
|
25
41
|
/** Read `<parent>[key]` as an object, creating it when absent; anything else is a hard error. */
|
|
26
42
|
function childObject(parent, key, label) {
|
|
27
43
|
if (parent[key] === undefined)
|
|
@@ -39,8 +55,34 @@ export function modelPolicyAllows(list, modelRef) {
|
|
|
39
55
|
return entry.endsWith('*') ? modelRef.startsWith(entry.slice(0, -1)) : entry === modelRef;
|
|
40
56
|
});
|
|
41
57
|
}
|
|
58
|
+
/**
|
|
59
|
+
* Bring a parsed `openclaw.json` into the shape the merge works on without changing what it means:
|
|
60
|
+
* a plain-string `agents.defaults.model` becomes `{ primary: <it> }`, and the
|
|
61
|
+
* `agents.defaults.timeoutSeconds: 240` older releases seeded goes.
|
|
62
|
+
*/
|
|
63
|
+
export function openclawNormalize(parsed) {
|
|
64
|
+
const defaults = asJsonObject(asJsonObject(asJsonObject(parsed)?.['agents'])?.['defaults']);
|
|
65
|
+
if (!defaults)
|
|
66
|
+
return;
|
|
67
|
+
if (defaults['timeoutSeconds'] === LEGACY_AGENT_TIMEOUT_SECONDS)
|
|
68
|
+
delete defaults['timeoutSeconds'];
|
|
69
|
+
const model = defaults['model'];
|
|
70
|
+
if (typeof model === 'string')
|
|
71
|
+
defaults['model'] = { primary: model };
|
|
72
|
+
}
|
|
73
|
+
/** The keys Connect may overwrite besides our own provider entry. */
|
|
74
|
+
export function openclawTrackedPaths(modelRef) {
|
|
75
|
+
return [
|
|
76
|
+
['models', 'mode'],
|
|
77
|
+
['gateway', 'mode'],
|
|
78
|
+
['gateway', 'auth', 'mode'],
|
|
79
|
+
['agents', 'defaults', 'model', 'primary'],
|
|
80
|
+
['agents', 'defaults', 'models', modelRef],
|
|
81
|
+
['agents', 'defaults', 'modelPolicy', 'allow'],
|
|
82
|
+
];
|
|
83
|
+
}
|
|
42
84
|
/** The whole merge, with no I/O, so every rule above is testable against a plain object. */
|
|
43
|
-
export function openclawPatchConfig(parsed, apiUrl, model, apiKey) {
|
|
85
|
+
export function openclawPatchConfig(parsed, apiUrl, model, apiKey, contextLength, gatewaySecretInEnv = false) {
|
|
44
86
|
const root = asJsonObject(parsed);
|
|
45
87
|
if (!root)
|
|
46
88
|
throw new AtomicCoreError('IO_ERROR', 'openclaw.json is not a JSON object');
|
|
@@ -50,31 +92,39 @@ export function openclawPatchConfig(parsed, apiUrl, model, apiKey) {
|
|
|
50
92
|
models['mode'] = 'merge';
|
|
51
93
|
const providers = childObject(models, 'providers', 'models.providers');
|
|
52
94
|
// The catalog entry's `id` is the bare model id our /v1 server reports; OpenClaw builds the ref as
|
|
53
|
-
// `<providerId>/<id>`, so prefixing here would double it to `atomic/atomic/…` and break lookup.
|
|
95
|
+
// `<providerId>/<id>`, so prefixing here would double it to `atomic/atomic/…` and break lookup. A
|
|
96
|
+
// known window lets OpenClaw compact before the server refuses; an unknown one is not invented.
|
|
97
|
+
const modelEntry = { id: model, name: model };
|
|
98
|
+
if (contextLength !== undefined) {
|
|
99
|
+
modelEntry['contextWindow'] = contextLength;
|
|
100
|
+
modelEntry['maxTokens'] = outputCapFor(contextLength);
|
|
101
|
+
}
|
|
54
102
|
providers[PROVIDER_ID] = {
|
|
55
103
|
baseUrl: apiUrl,
|
|
56
104
|
apiKey: keyOr(apiKey, 'atomic'),
|
|
57
105
|
api: 'openai-completions',
|
|
58
|
-
|
|
106
|
+
timeoutSeconds: PROVIDER_TIMEOUT_SECONDS,
|
|
107
|
+
models: [modelEntry],
|
|
59
108
|
};
|
|
60
|
-
// The local gateway refuses to open its websocket without connection auth; for a loopback-only
|
|
61
|
-
// setup "none" (private-ingress open auth) is what makes the agent reachable with no token.
|
|
62
109
|
const gateway = childObject(root, 'gateway', 'gateway');
|
|
63
110
|
if (gateway['mode'] === undefined)
|
|
64
111
|
gateway['mode'] = 'local';
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
112
|
+
// The local Gateway refuses its websocket without connection auth and, with no mode set, expects a
|
|
113
|
+
// token. With no token or password to expect, "none" (private-ingress open auth) makes it
|
|
114
|
+
// reachable; with one, "none" would switch token auth off.
|
|
115
|
+
const auth = asJsonObject(gateway['auth']);
|
|
116
|
+
const authIsSet = ['mode', 'token', 'password'].some((key) => {
|
|
117
|
+
const value = auth?.[key];
|
|
118
|
+
return value !== undefined && value !== null && value !== '';
|
|
119
|
+
});
|
|
120
|
+
if (!authIsSet && !gatewaySecretInEnv)
|
|
121
|
+
childObject(gateway, 'auth', 'gateway.auth')['mode'] = 'none';
|
|
68
122
|
const agents = childObject(root, 'agents', 'agents');
|
|
69
123
|
const defaults = childObject(agents, 'defaults', 'agents.defaults');
|
|
70
|
-
if (defaults['timeoutSeconds'] === undefined)
|
|
71
|
-
defaults['timeoutSeconds'] = DEFAULT_TIMEOUT_SECONDS;
|
|
72
|
-
// Both a plain string and an object are accepted here, but only the object form has room for the
|
|
73
|
-
// fallbacks OpenClaw writes itself, so a string is normalised rather than extended.
|
|
74
124
|
if (asJsonObject(defaults['model']) === undefined)
|
|
75
125
|
defaults['model'] = {};
|
|
76
|
-
const
|
|
77
|
-
|
|
126
|
+
const primary = asJsonObject(defaults['model']);
|
|
127
|
+
primary['primary'] = modelRef;
|
|
78
128
|
// `agents.defaults.models` holds aliases and per-model settings. Pre-migration builds also read it
|
|
79
129
|
// as an allowlist, so the entry is still seeded; on current builds it restricts nothing.
|
|
80
130
|
const settings = childObject(defaults, 'models', 'agents.defaults.models');
|
|
@@ -86,14 +136,20 @@ export function openclawPatchConfig(parsed, apiUrl, model, apiKey) {
|
|
|
86
136
|
}
|
|
87
137
|
return root;
|
|
88
138
|
}
|
|
89
|
-
export const configureOpenclaw = async ({ apiUrl, model, apiKey, fs, env, }) => {
|
|
139
|
+
export const configureOpenclaw = async ({ apiUrl, model, apiKey, fs, env, contextLength, }) => {
|
|
90
140
|
const override = env['OPENCLAW_CONFIG_PATH'];
|
|
91
141
|
const path = override && override.length > 0 ? override : DEFAULT_PATH;
|
|
142
|
+
const gatewaySecretInEnv = ['OPENCLAW_GATEWAY_TOKEN', 'OPENCLAW_GATEWAY_PASSWORD'].some((name) => (env[name] ?? '').trim() !== '');
|
|
92
143
|
// OpenClaw reads this file as JSON5, so we must parse with the same leniency or we reject configs
|
|
93
144
|
// it happily accepts. Comments are dropped on write; every setting is preserved.
|
|
94
145
|
const text = await fs.read(path);
|
|
95
|
-
const
|
|
96
|
-
|
|
146
|
+
const base = text === undefined ? {} : parseJsonLenient(text, fs.absolute(path));
|
|
147
|
+
openclawNormalize(base);
|
|
148
|
+
const patched = openclawPatchConfig(JSON.parse(JSON.stringify(base)), apiUrl, model, apiKey, contextLength, gatewaySecretInEnv);
|
|
149
|
+
const previous = await readBackup(fs, path);
|
|
150
|
+
const keys = trackKeys(base, patched, openclawTrackedPaths(`${PROVIDER_ID}/${model}`), previous?.keys ?? []);
|
|
151
|
+
await fs.write(path, canonicalJson(patched));
|
|
152
|
+
await writeBackupText(fs, path, renderBackup({ keys, seeded: [] }));
|
|
97
153
|
};
|
|
98
154
|
registerWriter('openclaw', configureOpenclaw);
|
|
99
155
|
//# sourceMappingURL=openclaw.js.map
|