@ycodium-ai/agent-claude 0.2.2106 → 0.2.2130
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 +16 -2
- package/dist/index.js +651 -97
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
# @ycodium-ai/agent-claude
|
|
2
2
|
|
|
3
3
|
Claude executor plugin. Talks to Claude Code through
|
|
4
|
-
`@anthropic-ai/claude-agent-sdk` (`query()`), not ACP.
|
|
5
|
-
|
|
4
|
+
`@anthropic-ai/claude-agent-sdk` (`query()`), not ACP.
|
|
5
|
+
|
|
6
|
+
Since 2026-09-19 this package **is** the Claude hand: the catalog row carries
|
|
7
|
+
`executorPlugin: "@ycodium-ai/agent-claude"`, the host `ClaudeDriver` /
|
|
8
|
+
`ClaudeAdapter` / `ClaudeProvider` / `ClaudeTextGeneration` are deleted, and the
|
|
9
|
+
built-in `claudeAgent` card no longer joins the catalog. The host keeps one copy
|
|
10
|
+
of the connectivity literal (`executorRegistry.ts` → `officialCardForDriver`)
|
|
11
|
+
because `compileBinding` is synchronous and cannot read the plugin registry;
|
|
12
|
+
`executorRegistry.test.ts` pins the two copies to be byte-identical.
|
|
6
13
|
|
|
7
14
|
Facts:
|
|
8
15
|
|
|
@@ -13,6 +20,13 @@ Facts:
|
|
|
13
20
|
- Manifest permission is `{ kind: "executor" }`.
|
|
14
21
|
- Card capabilities: `sessionModelSwitch: "in-session"`, `runtimeModeSwitch: "in-session"`,
|
|
15
22
|
`contextCompaction: "native"`, `turnSteering: true`.
|
|
23
|
+
- `modelConnectivity` carries `baseUrlEnvKey: ANTHROPIC_BASE_URL`,
|
|
24
|
+
`credentialEnvKey: ANTHROPIC_AUTH_TOKEN` and seven `extraEnv` rows pinning every
|
|
25
|
+
model-role variable to `$model`. It deliberately does **not** claim
|
|
26
|
+
`supportsNativeSubscription`: Ycodium has no Claude native-subscription login.
|
|
27
|
+
- Recordings: `test/fixtures/*.sdk.ndjson`, ten scenes captured from Claude Code
|
|
28
|
+
2.1.277 by `scripts/record-claude-sdk-session.ts`; `src/replay.test.ts` replays
|
|
29
|
+
them through the same `createQuery` seam the recorder tapped.
|
|
16
30
|
- Quota-probe dissolution: `credentialSources` lists the json-file and
|
|
17
31
|
macOS-keychain locations. `sessions.scan` / `sessions.read` take the Claude
|
|
18
32
|
half of session-import.
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,9 @@ import { definePlugin } from "@ycodium-ai/plugin-api";
|
|
|
5
5
|
var CLAUDE_DRIVER_KIND = "claudeAgent";
|
|
6
6
|
var CLAUDE_CARD = {
|
|
7
7
|
driverKind: CLAUDE_DRIVER_KIND,
|
|
8
|
-
|
|
8
|
+
// 手叫 Claude Code,不叫 Claude——「Claude」会和脑(Anthropic · Claude Opus 5)混。
|
|
9
|
+
// 已有实例存的显示名不动,这里只影响新建实例与手脑拆分后的回填名。
|
|
10
|
+
displayName: "Claude Code",
|
|
9
11
|
iconUrl: "./assets/icon.svg",
|
|
10
12
|
commandName: "claude",
|
|
11
13
|
launchArgs: "",
|
|
@@ -60,9 +62,16 @@ var CLAUDE_CARD = {
|
|
|
60
62
|
verifiedSkills: true,
|
|
61
63
|
everydayHarness: true,
|
|
62
64
|
capabilities: {
|
|
65
|
+
// 会话中途换模型走 SDK 的 `setModel` 控制请求,不重开会话:`claudeInstance.ts` 的
|
|
66
|
+
// sendTurn 在 `currentApiModelId` 与本轮选择不一致时调它,`reconfigureSession` 复用
|
|
67
|
+
// 会话时也是同一条路。录像证据是 `test/fixtures/claudeModelSwitchTurn.sdk.ndjson`
|
|
68
|
+
// (同一会话两轮不同模型,中间一条 `setModel`)。宿主内置名片此前写 unsupported,
|
|
69
|
+
// 与 adapter 自己声明给编排的 `"in-session"` 相反——那边是真的,名片是错的。
|
|
63
70
|
sessionModelSwitch: "in-session",
|
|
64
71
|
sessionOptionSwitch: "unsupported",
|
|
65
72
|
runtimeModeSwitch: "in-session",
|
|
73
|
+
// SDK 的 `setPermissionMode` 会话中途就能改,所以这一位也是真的。
|
|
74
|
+
nativeModeSwitch: true,
|
|
66
75
|
contextCompaction: "native",
|
|
67
76
|
turnSteering: true
|
|
68
77
|
},
|
|
@@ -98,15 +107,34 @@ var CLAUDE_CARD = {
|
|
|
98
107
|
modelConnectivity: {
|
|
99
108
|
dialects: ["anthropic-messages"],
|
|
100
109
|
acceptsExternalEndpoints: true,
|
|
110
|
+
// claude 认 origin:CLI 自己在注入的 base 后追加 `/v1/messages`,所以后缀整条
|
|
111
|
+
// 就是路由,注进去的 base 是纯 origin(compileBinding 按这一栏算出该注什么)。
|
|
101
112
|
nativePathSuffix: "/v1/messages",
|
|
102
|
-
credentialEnvKey
|
|
103
|
-
|
|
113
|
+
// 与宿主内置名片逐字相同。credentialEnvKey 是宿主给绑定注入的那个变量;
|
|
114
|
+
// alternateCredentialEnvKeys 是 CLI 也认的备选凭据变量(手脑拆分线加的,用来识别捆绑)。
|
|
115
|
+
baseUrlEnvKey: "ANTHROPIC_BASE_URL",
|
|
116
|
+
credentialEnvKey: "ANTHROPIC_AUTH_TOKEN",
|
|
117
|
+
alternateCredentialEnvKeys: ["ANTHROPIC_API_KEY"],
|
|
118
|
+
supportsNativeSubscription: true,
|
|
119
|
+
// 七个档位变量一起钉成这次的模型:claude 的 opus / sonnet / haiku / fable 档与
|
|
120
|
+
// 子代理、小快模型各读一个变量,只钉 `ANTHROPIC_MODEL` 的话子代理会跑回默认档。
|
|
121
|
+
// 名单与旧 `CLAUDE_SETTINGS_MODEL_ENV_KEYS` 逐字相同(含 2026-09-09 从 2.1.265
|
|
122
|
+
// 二进制核实出来的 fable 那一条)。`$model` 由 compileBinding 替换。
|
|
123
|
+
extraEnv: [
|
|
124
|
+
{ name: "ANTHROPIC_MODEL", value: "$model" },
|
|
125
|
+
{ name: "ANTHROPIC_DEFAULT_OPUS_MODEL", value: "$model" },
|
|
126
|
+
{ name: "ANTHROPIC_DEFAULT_SONNET_MODEL", value: "$model" },
|
|
127
|
+
{ name: "ANTHROPIC_DEFAULT_HAIKU_MODEL", value: "$model" },
|
|
128
|
+
{ name: "ANTHROPIC_DEFAULT_FABLE_MODEL", value: "$model" },
|
|
129
|
+
{ name: "ANTHROPIC_SMALL_FAST_MODEL", value: "$model" },
|
|
130
|
+
{ name: "CLAUDE_CODE_SUBAGENT_MODEL", value: "$model" }
|
|
131
|
+
]
|
|
104
132
|
}
|
|
105
133
|
};
|
|
106
134
|
|
|
107
135
|
// src/claudeInstance.ts
|
|
108
136
|
import * as NodeOS6 from "node:os";
|
|
109
|
-
import * as
|
|
137
|
+
import * as NodePath7 from "node:path";
|
|
110
138
|
|
|
111
139
|
// ../../node_modules/.pnpm/@anthropic-ai+claude-agent-sdk@0.3.170_@anthropic-ai+sdk@0.93.0_zod@4.6.5__@modelcontex_64204813d4dba2ebc464c3aa751485a4/node_modules/@anthropic-ai/claude-agent-sdk/sdk.mjs
|
|
112
140
|
import { createRequire as xz } from "node:module";
|
|
@@ -19538,6 +19566,13 @@ function HU(e, t) {
|
|
|
19538
19566
|
return null;
|
|
19539
19567
|
}
|
|
19540
19568
|
|
|
19569
|
+
// src/claudeInstance.ts
|
|
19570
|
+
import {
|
|
19571
|
+
mergeLaunchEnv as mergeLaunchEnv2,
|
|
19572
|
+
withoutBrainSlots,
|
|
19573
|
+
brainSlotEnvKeys as brainSlotEnvKeys3
|
|
19574
|
+
} from "@ycodium-ai/plugin-api/executor";
|
|
19575
|
+
|
|
19541
19576
|
// src/claudeAccount.ts
|
|
19542
19577
|
import * as NodeFS from "node:fs";
|
|
19543
19578
|
import * as NodeOS from "node:os";
|
|
@@ -19694,10 +19729,17 @@ function expandHomePath(value) {
|
|
|
19694
19729
|
|
|
19695
19730
|
// src/claudeHome.ts
|
|
19696
19731
|
var CLAUDE_CREDENTIALS_DIR_ENVIRONMENT_VARIABLE = "CLAUDE_SECURESTORAGE_CONFIG_DIR";
|
|
19732
|
+
var CLAUDE_ROUTED_HOME_DIR_NAME = "claude-home";
|
|
19733
|
+
function claudeRoutedHomePath(pluginDataDirPath) {
|
|
19734
|
+
return NodePath4.join(pluginDataDirPath, CLAUDE_ROUTED_HOME_DIR_NAME);
|
|
19735
|
+
}
|
|
19697
19736
|
function resolveClaudeHomePath(homePath) {
|
|
19698
19737
|
const trimmed = homePath.trim();
|
|
19699
19738
|
return NodePath4.resolve(trimmed.length > 0 ? expandHomePath(trimmed) : NodeOS4.homedir());
|
|
19700
19739
|
}
|
|
19740
|
+
function claudeContinuationKey(homePath) {
|
|
19741
|
+
return `claude:home:${resolveClaudeHomePath(homePath)}`;
|
|
19742
|
+
}
|
|
19701
19743
|
function resolveClaudeConfigDirPath(homePath, environment, cwd) {
|
|
19702
19744
|
const trimmed = homePath.trim();
|
|
19703
19745
|
if (trimmed.length > 0) {
|
|
@@ -19714,18 +19756,47 @@ function resolveClaudeCredentialsDirPath(credentialsPath) {
|
|
|
19714
19756
|
if (trimmed.length === 0) return null;
|
|
19715
19757
|
return NodePath4.resolve(expandHomePath(trimmed));
|
|
19716
19758
|
}
|
|
19717
|
-
function
|
|
19718
|
-
const
|
|
19719
|
-
const
|
|
19720
|
-
const
|
|
19721
|
-
|
|
19722
|
-
|
|
19759
|
+
function resolveClaudeHomeLayout(input) {
|
|
19760
|
+
const userConfigDirPath = resolveClaudeConfigDirPath(input.homePath, input.environment ?? {});
|
|
19761
|
+
const instanceConfigDirPath = input.homePath.trim().length > 0 ? resolveClaudeHomePath(input.homePath) : void 0;
|
|
19762
|
+
const instanceCredentialsDirPath = resolveClaudeCredentialsDirPath(input.credentialsPath);
|
|
19763
|
+
const routedHomePath = input.routedHomePath?.trim() ?? "";
|
|
19764
|
+
if (routedHomePath.length === 0 || instanceConfigDirPath !== void 0 || instanceCredentialsDirPath !== null) {
|
|
19765
|
+
return {
|
|
19766
|
+
mode: "instance",
|
|
19767
|
+
userConfigDirPath,
|
|
19768
|
+
configDirPath: instanceConfigDirPath,
|
|
19769
|
+
credentialsDirPath: instanceCredentialsDirPath ?? void 0
|
|
19770
|
+
};
|
|
19771
|
+
}
|
|
19772
|
+
const resolvedRoutedHomePath = NodePath4.resolve(expandHomePath(routedHomePath));
|
|
19773
|
+
return {
|
|
19774
|
+
mode: "routed",
|
|
19775
|
+
userConfigDirPath,
|
|
19776
|
+
configDirPath: resolvedRoutedHomePath,
|
|
19777
|
+
// 登录目录显式钉成影子目录本身。不设这个变量时 CLI 本来就把凭据放配置目录,但
|
|
19778
|
+
// 「登录去哪」正是这次要修的东西,不靠默认值。
|
|
19779
|
+
credentialsDirPath: resolvedRoutedHomePath
|
|
19780
|
+
};
|
|
19781
|
+
}
|
|
19782
|
+
function claudeHomeVariables(layout) {
|
|
19723
19783
|
return {
|
|
19724
|
-
...
|
|
19725
|
-
...
|
|
19726
|
-
...credentialsDirPath === null ? {} : { [CLAUDE_CREDENTIALS_DIR_ENVIRONMENT_VARIABLE]: credentialsDirPath }
|
|
19784
|
+
...layout.configDirPath === void 0 ? {} : { CLAUDE_CONFIG_DIR: layout.configDirPath },
|
|
19785
|
+
...layout.credentialsDirPath === void 0 ? {} : { [CLAUDE_CREDENTIALS_DIR_ENVIRONMENT_VARIABLE]: layout.credentialsDirPath }
|
|
19727
19786
|
};
|
|
19728
19787
|
}
|
|
19788
|
+
function makeClaudeEnvironment(config, baseEnv) {
|
|
19789
|
+
const resolvedBaseEnv = { ...baseEnv ?? process.env };
|
|
19790
|
+
const variables = claudeHomeVariables(
|
|
19791
|
+
resolveClaudeHomeLayout({
|
|
19792
|
+
homePath: config.homePath,
|
|
19793
|
+
credentialsPath: config.credentialsPath,
|
|
19794
|
+
environment: resolvedBaseEnv
|
|
19795
|
+
})
|
|
19796
|
+
);
|
|
19797
|
+
if (Object.keys(variables).length === 0) return resolvedBaseEnv;
|
|
19798
|
+
return { ...resolvedBaseEnv, ...variables };
|
|
19799
|
+
}
|
|
19729
19800
|
|
|
19730
19801
|
// src/claudeSignIn.ts
|
|
19731
19802
|
var POSIX_BARE_VALUE = /^[A-Za-z0-9_@%+=:,./-]+$/;
|
|
@@ -19953,8 +20024,8 @@ var EventBus = class {
|
|
|
19953
20024
|
const queued = this.#queued.shift();
|
|
19954
20025
|
if (queued !== void 0) return Promise.resolve({ done: false, value: queued });
|
|
19955
20026
|
if (this.#closed) return Promise.resolve({ done: true, value: void 0 });
|
|
19956
|
-
return new Promise((
|
|
19957
|
-
this.#waiters.push(
|
|
20027
|
+
return new Promise((resolve3) => {
|
|
20028
|
+
this.#waiters.push(resolve3);
|
|
19958
20029
|
});
|
|
19959
20030
|
}
|
|
19960
20031
|
};
|
|
@@ -19962,6 +20033,7 @@ var EventBus = class {
|
|
|
19962
20033
|
};
|
|
19963
20034
|
|
|
19964
20035
|
// src/model.ts
|
|
20036
|
+
import { matchCatalogModel } from "@ycodium-ai/plugin-api/executor";
|
|
19965
20037
|
var DEFAULT_CLAUDE_MODEL_CAPABILITIES = {
|
|
19966
20038
|
optionDescriptors: []
|
|
19967
20039
|
};
|
|
@@ -19969,6 +20041,10 @@ var CLAUDE_CUSTOM_MODEL_THINKING_SELECT = {
|
|
|
19969
20041
|
id: "effort",
|
|
19970
20042
|
label: "Reasoning"
|
|
19971
20043
|
};
|
|
20044
|
+
var MINIMUM_CLAUDE_OPUS_5_VERSION = "2.1.219";
|
|
20045
|
+
var MINIMUM_CLAUDE_FABLE_5_VERSION = "2.1.169";
|
|
20046
|
+
var MINIMUM_CLAUDE_OPUS_4_8_VERSION = "2.1.154";
|
|
20047
|
+
var MINIMUM_CLAUDE_OPUS_4_7_VERSION = "2.1.111";
|
|
19972
20048
|
var CURRENT_CLAUDE_MODELS = /* @__PURE__ */ new Set(["claude-fable-5", "claude-opus-5", "claude-sonnet-5"]);
|
|
19973
20049
|
function isLegacyClaudeModel(model) {
|
|
19974
20050
|
return !CURRENT_CLAUDE_MODELS.has(model);
|
|
@@ -20209,6 +20285,35 @@ var CLAUDE_XHIGH_SLUGS = /* @__PURE__ */ new Set([
|
|
|
20209
20285
|
"claude-opus-4-8",
|
|
20210
20286
|
"claude-sonnet-5"
|
|
20211
20287
|
]);
|
|
20288
|
+
function compareSemverVersions(left, right) {
|
|
20289
|
+
const parse = (value) => {
|
|
20290
|
+
const match = value.trim().replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
20291
|
+
if (!match) return null;
|
|
20292
|
+
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
20293
|
+
};
|
|
20294
|
+
const a = parse(left);
|
|
20295
|
+
const b3 = parse(right);
|
|
20296
|
+
if (!a || !b3) return left.localeCompare(right);
|
|
20297
|
+
if (a[0] !== b3[0]) return a[0] - b3[0];
|
|
20298
|
+
if (a[1] !== b3[1]) return a[1] - b3[1];
|
|
20299
|
+
return a[2] - b3[2];
|
|
20300
|
+
}
|
|
20301
|
+
function supportsVersion(version, minimum) {
|
|
20302
|
+
return version ? compareSemverVersions(version, minimum) >= 0 : false;
|
|
20303
|
+
}
|
|
20304
|
+
function getBuiltInClaudeModelsForVersion(version) {
|
|
20305
|
+
return BUILT_IN_MODELS.filter((model) => {
|
|
20306
|
+
if (model.slug === "claude-opus-5")
|
|
20307
|
+
return supportsVersion(version, MINIMUM_CLAUDE_OPUS_5_VERSION);
|
|
20308
|
+
if (model.slug === "claude-fable-5")
|
|
20309
|
+
return supportsVersion(version, MINIMUM_CLAUDE_FABLE_5_VERSION);
|
|
20310
|
+
if (model.slug === "claude-opus-4-8")
|
|
20311
|
+
return supportsVersion(version, MINIMUM_CLAUDE_OPUS_4_8_VERSION);
|
|
20312
|
+
if (model.slug === "claude-opus-4-7")
|
|
20313
|
+
return supportsVersion(version, MINIMUM_CLAUDE_OPUS_4_7_VERSION);
|
|
20314
|
+
return true;
|
|
20315
|
+
});
|
|
20316
|
+
}
|
|
20212
20317
|
function parseGenericCliVersion(output) {
|
|
20213
20318
|
const match = output.match(/\b(\d+\.\d+\.\d+)\b/);
|
|
20214
20319
|
return match?.[1] ?? null;
|
|
@@ -20316,6 +20421,13 @@ function resolveClaudeContextWindow(caps, modelSelection) {
|
|
|
20316
20421
|
if (!descriptor || descriptor.type !== "select") return void 0;
|
|
20317
20422
|
return currentSelectValue(descriptor, raw);
|
|
20318
20423
|
}
|
|
20424
|
+
function claudeCliModelId(input) {
|
|
20425
|
+
const catalog = [
|
|
20426
|
+
...BUILT_IN_MODELS.map((model) => model.slug),
|
|
20427
|
+
...(input.customModels ?? []).map((model) => normalizeCustomModelSlug(model.slug))
|
|
20428
|
+
];
|
|
20429
|
+
return matchCatalogModel(input.boundModelId, catalog) ?? input.placeholder;
|
|
20430
|
+
}
|
|
20319
20431
|
function resolveClaudeApiModelId(caps, modelSelection) {
|
|
20320
20432
|
switch (resolveClaudeContextWindow(caps, modelSelection)) {
|
|
20321
20433
|
case "1m":
|
|
@@ -20386,6 +20498,15 @@ function toMessage(cause, fallback) {
|
|
|
20386
20498
|
}
|
|
20387
20499
|
return fallback;
|
|
20388
20500
|
}
|
|
20501
|
+
function createOutputTail(maxChars) {
|
|
20502
|
+
let buffered = "";
|
|
20503
|
+
return {
|
|
20504
|
+
append: (chunk) => {
|
|
20505
|
+
buffered = (buffered + chunk).slice(-maxChars);
|
|
20506
|
+
},
|
|
20507
|
+
read: () => buffered.trim()
|
|
20508
|
+
};
|
|
20509
|
+
}
|
|
20389
20510
|
function asRuntimeItemId(value) {
|
|
20390
20511
|
return value;
|
|
20391
20512
|
}
|
|
@@ -20533,10 +20654,10 @@ function inputDiffStat(input) {
|
|
|
20533
20654
|
let deletions = 0;
|
|
20534
20655
|
for (const edit of input.edits) {
|
|
20535
20656
|
if (edit === null || typeof edit !== "object" || Array.isArray(edit)) return void 0;
|
|
20536
|
-
const
|
|
20537
|
-
if (!
|
|
20538
|
-
additions +=
|
|
20539
|
-
deletions +=
|
|
20657
|
+
const stat2 = replacementDiffStat(edit, budget);
|
|
20658
|
+
if (!stat2) return void 0;
|
|
20659
|
+
additions += stat2.additions;
|
|
20660
|
+
deletions += stat2.deletions;
|
|
20540
20661
|
}
|
|
20541
20662
|
return { additions, deletions };
|
|
20542
20663
|
}
|
|
@@ -21071,11 +21192,40 @@ function diffClaudeSessionSettings(previous, next) {
|
|
|
21071
21192
|
}
|
|
21072
21193
|
return changed ? patch : void 0;
|
|
21073
21194
|
}
|
|
21074
|
-
var
|
|
21195
|
+
var CLAUDE_NATIVE_MODES = [
|
|
21196
|
+
{ id: "default", name: "Manual", description: "Always ask before making changes" },
|
|
21197
|
+
{ id: "acceptEdits", name: "Accept edits", description: "Automatically accept all file edits" },
|
|
21198
|
+
{ id: "plan", name: "Plan", description: "Create a plan before making changes" },
|
|
21199
|
+
{ id: "auto", name: "Auto", description: "Claude handles permission decisions" },
|
|
21200
|
+
{
|
|
21201
|
+
id: "bypassPermissions",
|
|
21202
|
+
name: "Bypass permissions",
|
|
21203
|
+
description: "Accepts all permissions"
|
|
21204
|
+
}
|
|
21205
|
+
];
|
|
21206
|
+
var CLAUDE_DEFAULT_NATIVE_MODE_ID = "default";
|
|
21207
|
+
var CLAUDE_NATIVE_MODE_BY_RUNTIME_MODE = {
|
|
21208
|
+
"approval-required": "default",
|
|
21075
21209
|
"auto-accept-edits": "acceptEdits",
|
|
21076
21210
|
auto: "auto",
|
|
21077
21211
|
"full-access": "bypassPermissions"
|
|
21078
21212
|
};
|
|
21213
|
+
var CLAUDE_NATIVE_MODE_REPORT = {
|
|
21214
|
+
nativeModes: CLAUDE_NATIVE_MODES.map((mode) => ({
|
|
21215
|
+
id: mode.id,
|
|
21216
|
+
name: mode.name,
|
|
21217
|
+
description: mode.description
|
|
21218
|
+
})),
|
|
21219
|
+
currentNativeModeId: CLAUDE_DEFAULT_NATIVE_MODE_ID,
|
|
21220
|
+
nativeModeByRuntimeMode: CLAUDE_NATIVE_MODE_BY_RUNTIME_MODE
|
|
21221
|
+
};
|
|
21222
|
+
function isClaudeNativeModeId(value) {
|
|
21223
|
+
return CLAUDE_NATIVE_MODES.some((mode) => mode.id === value);
|
|
21224
|
+
}
|
|
21225
|
+
function claudePermissionModeFor(runtimeMode, nativeModeId) {
|
|
21226
|
+
if (nativeModeId !== void 0 && isClaudeNativeModeId(nativeModeId)) return nativeModeId;
|
|
21227
|
+
return CLAUDE_NATIVE_MODE_BY_RUNTIME_MODE[runtimeMode];
|
|
21228
|
+
}
|
|
21079
21229
|
var CLAUDE_SETTING_SOURCES = [
|
|
21080
21230
|
"user",
|
|
21081
21231
|
"project",
|
|
@@ -21213,17 +21363,17 @@ function listTranscriptFiles(transcriptDir, directory) {
|
|
|
21213
21363
|
continue;
|
|
21214
21364
|
}
|
|
21215
21365
|
for (const name of names) {
|
|
21216
|
-
let
|
|
21366
|
+
let stat2;
|
|
21217
21367
|
try {
|
|
21218
|
-
|
|
21368
|
+
stat2 = NodeFS3.statSync(NodePath5.join(projectDir, name));
|
|
21219
21369
|
} catch {
|
|
21220
21370
|
continue;
|
|
21221
21371
|
}
|
|
21222
21372
|
found.push({
|
|
21223
21373
|
path: NodePath5.join(projectDir, name),
|
|
21224
21374
|
sessionId: name.slice(0, -TRANSCRIPT_SUFFIX.length),
|
|
21225
|
-
size:
|
|
21226
|
-
mtimeMs: Number.isFinite(
|
|
21375
|
+
size: stat2.size,
|
|
21376
|
+
mtimeMs: Number.isFinite(stat2.mtimeMs) ? stat2.mtimeMs : 0
|
|
21227
21377
|
});
|
|
21228
21378
|
}
|
|
21229
21379
|
}
|
|
@@ -21787,6 +21937,305 @@ function normalizeClaudeTaskProgressTokenUsage(value, memory) {
|
|
|
21787
21937
|
};
|
|
21788
21938
|
}
|
|
21789
21939
|
|
|
21940
|
+
// src/probeModels.ts
|
|
21941
|
+
var CONTEXT_WINDOW_TOKENS = {
|
|
21942
|
+
"200k": 2e5,
|
|
21943
|
+
"1m": 1e6
|
|
21944
|
+
};
|
|
21945
|
+
var defaultContextWindowOf = (caps) => {
|
|
21946
|
+
const descriptor = caps.optionDescriptors.find(
|
|
21947
|
+
(entry) => entry.type === "select" && entry.id === "contextWindow"
|
|
21948
|
+
);
|
|
21949
|
+
if (descriptor === void 0) return void 0;
|
|
21950
|
+
const chosen = descriptor.options.find((option) => option.isDefault === true);
|
|
21951
|
+
return chosen === void 0 ? void 0 : CONTEXT_WINDOW_TOKENS[chosen.id];
|
|
21952
|
+
};
|
|
21953
|
+
var toProbeCapabilities = (caps) => ({
|
|
21954
|
+
optionDescriptors: caps.optionDescriptors.map(
|
|
21955
|
+
(descriptor) => descriptor.type === "select" ? {
|
|
21956
|
+
id: descriptor.id,
|
|
21957
|
+
label: descriptor.label,
|
|
21958
|
+
type: "select",
|
|
21959
|
+
options: descriptor.options.map((option) => ({
|
|
21960
|
+
id: option.id,
|
|
21961
|
+
label: option.label,
|
|
21962
|
+
...option.description === void 0 ? {} : { description: option.description },
|
|
21963
|
+
...option.isDefault === void 0 ? {} : { isDefault: option.isDefault }
|
|
21964
|
+
}))
|
|
21965
|
+
} : {
|
|
21966
|
+
id: descriptor.id,
|
|
21967
|
+
label: descriptor.label,
|
|
21968
|
+
type: "boolean"
|
|
21969
|
+
}
|
|
21970
|
+
)
|
|
21971
|
+
});
|
|
21972
|
+
var claudeProbeModels = (input) => {
|
|
21973
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21974
|
+
const out = [];
|
|
21975
|
+
for (const model of input.builtIn) {
|
|
21976
|
+
if (seen.has(model.slug)) continue;
|
|
21977
|
+
seen.add(model.slug);
|
|
21978
|
+
const userLabel = input.customModels.find((entry) => entry.slug === model.slug)?.label;
|
|
21979
|
+
const contextWindow = defaultContextWindowOf(model.capabilities);
|
|
21980
|
+
out.push({
|
|
21981
|
+
slug: model.slug,
|
|
21982
|
+
name: userLabel?.trim() || model.name,
|
|
21983
|
+
...model.isLegacy === void 0 ? {} : { isLegacy: model.isLegacy },
|
|
21984
|
+
capabilities: toProbeCapabilities(model.capabilities),
|
|
21985
|
+
...contextWindow === void 0 ? {} : { contextWindow }
|
|
21986
|
+
});
|
|
21987
|
+
}
|
|
21988
|
+
for (const model of input.customModels) {
|
|
21989
|
+
if (model.slug.trim().length === 0 || seen.has(model.slug)) continue;
|
|
21990
|
+
seen.add(model.slug);
|
|
21991
|
+
out.push({ slug: model.slug, name: model.label?.trim() || model.slug });
|
|
21992
|
+
}
|
|
21993
|
+
for (const model of input.discovered ?? []) {
|
|
21994
|
+
if (seen.has(model.slug)) continue;
|
|
21995
|
+
seen.add(model.slug);
|
|
21996
|
+
out.push(model);
|
|
21997
|
+
}
|
|
21998
|
+
return out;
|
|
21999
|
+
};
|
|
22000
|
+
|
|
22001
|
+
// src/routedHome.ts
|
|
22002
|
+
import * as NodeFSP from "node:fs/promises";
|
|
22003
|
+
import * as NodePath6 from "node:path";
|
|
22004
|
+
|
|
22005
|
+
// src/routedSettings.ts
|
|
22006
|
+
import { brainSlotEnvKeys } from "@ycodium-ai/plugin-api";
|
|
22007
|
+
var PROXY_ENV_KEYS = [
|
|
22008
|
+
"HTTP_PROXY",
|
|
22009
|
+
"HTTPS_PROXY",
|
|
22010
|
+
"NO_PROXY",
|
|
22011
|
+
"ALL_PROXY",
|
|
22012
|
+
"http_proxy",
|
|
22013
|
+
"https_proxy",
|
|
22014
|
+
"no_proxy",
|
|
22015
|
+
"all_proxy"
|
|
22016
|
+
];
|
|
22017
|
+
function isRoutedLaunch(launchProcessEnv) {
|
|
22018
|
+
const baseUrlKey = CLAUDE_CARD.modelConnectivity.baseUrlEnvKey;
|
|
22019
|
+
if (baseUrlKey === void 0) return false;
|
|
22020
|
+
return (launchProcessEnv?.[baseUrlKey] ?? "").trim().length > 0;
|
|
22021
|
+
}
|
|
22022
|
+
function routedEnvOverride(input) {
|
|
22023
|
+
if (!isRoutedLaunch(input.launchProcessEnv)) return void 0;
|
|
22024
|
+
const valueOf = (key) => input.mergedEnv[key] ?? "";
|
|
22025
|
+
const override = {};
|
|
22026
|
+
for (const key of brainSlotEnvKeys(CLAUDE_CARD)) override[key] = valueOf(key);
|
|
22027
|
+
for (const { name } of CLAUDE_CARD.modelConnectivity.extraEnv ?? []) {
|
|
22028
|
+
const bound = valueOf(name);
|
|
22029
|
+
override[name] = bound.length === 0 ? "" : claudeCliModelId({
|
|
22030
|
+
boundModelId: bound,
|
|
22031
|
+
placeholder: CLAUDE_CARD.defaultModel,
|
|
22032
|
+
...input.customModels === void 0 ? {} : { customModels: input.customModels }
|
|
22033
|
+
});
|
|
22034
|
+
}
|
|
22035
|
+
for (const key of PROXY_ENV_KEYS) override[key] = valueOf(key);
|
|
22036
|
+
return override;
|
|
22037
|
+
}
|
|
22038
|
+
|
|
22039
|
+
// src/routedHome.ts
|
|
22040
|
+
var BORROWED_ENTRY_NAMES = [
|
|
22041
|
+
"projects",
|
|
22042
|
+
"plugins",
|
|
22043
|
+
"skills",
|
|
22044
|
+
"agents",
|
|
22045
|
+
"commands",
|
|
22046
|
+
"CLAUDE.md"
|
|
22047
|
+
];
|
|
22048
|
+
var GLOBAL_CONFIG_FILE_NAME = ".claude.json";
|
|
22049
|
+
var USER_SETTINGS_FILE_NAME = "settings.json";
|
|
22050
|
+
var ROUTING_AND_IDENTITY_SETTING_KEYS = [
|
|
22051
|
+
"env",
|
|
22052
|
+
"apiKeyHelper",
|
|
22053
|
+
"awsAuthRefresh",
|
|
22054
|
+
"awsCredentialExport"
|
|
22055
|
+
];
|
|
22056
|
+
var FIRST_RUN_FLAG_KEYS = ["hasCompletedOnboarding", "bypassPermissionsModeAccepted"];
|
|
22057
|
+
function isRecord5(value) {
|
|
22058
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22059
|
+
}
|
|
22060
|
+
async function readTextFile(filePath) {
|
|
22061
|
+
try {
|
|
22062
|
+
return await NodeFSP.readFile(filePath, "utf8");
|
|
22063
|
+
} catch {
|
|
22064
|
+
return null;
|
|
22065
|
+
}
|
|
22066
|
+
}
|
|
22067
|
+
function parseJsonObject(raw) {
|
|
22068
|
+
try {
|
|
22069
|
+
const parsed = JSON.parse(raw);
|
|
22070
|
+
return isRecord5(parsed) ? parsed : null;
|
|
22071
|
+
} catch {
|
|
22072
|
+
return null;
|
|
22073
|
+
}
|
|
22074
|
+
}
|
|
22075
|
+
async function writeFileAtomic(filePath, contents) {
|
|
22076
|
+
const tempPath = `${filePath}.${crypto.randomUUID()}.tmp`;
|
|
22077
|
+
await NodeFSP.writeFile(tempPath, contents, { encoding: "utf8", mode: 384 });
|
|
22078
|
+
await NodeFSP.rename(tempPath, filePath);
|
|
22079
|
+
}
|
|
22080
|
+
async function readLinkState(linkPath) {
|
|
22081
|
+
try {
|
|
22082
|
+
return { _tag: "Symlink", target: await NodeFSP.readlink(linkPath) };
|
|
22083
|
+
} catch (error) {
|
|
22084
|
+
const code = typeof error === "object" && error !== null && "code" in error ? String(error.code) : "";
|
|
22085
|
+
if (code === "ENOENT") return { _tag: "Missing" };
|
|
22086
|
+
return { _tag: "NotSymlink" };
|
|
22087
|
+
}
|
|
22088
|
+
}
|
|
22089
|
+
async function isEmptyDirectory(path) {
|
|
22090
|
+
try {
|
|
22091
|
+
return (await NodeFSP.readdir(path)).length === 0;
|
|
22092
|
+
} catch {
|
|
22093
|
+
return false;
|
|
22094
|
+
}
|
|
22095
|
+
}
|
|
22096
|
+
async function borrowEntry(input) {
|
|
22097
|
+
const target = NodePath6.join(input.userConfigDirPath, input.entryName);
|
|
22098
|
+
const targetInfo = await NodeFSP.stat(target).then(
|
|
22099
|
+
(info) => info,
|
|
22100
|
+
() => null
|
|
22101
|
+
);
|
|
22102
|
+
if (targetInfo === null) return;
|
|
22103
|
+
const link = NodePath6.join(input.configDirPath, input.entryName);
|
|
22104
|
+
const state = await readLinkState(link);
|
|
22105
|
+
if (state._tag === "NotSymlink") {
|
|
22106
|
+
if (!await isEmptyDirectory(link)) {
|
|
22107
|
+
input.log?.warn("Claude routed home entry left unlinked: a real entry is already there.", {
|
|
22108
|
+
entryName: input.entryName,
|
|
22109
|
+
link
|
|
22110
|
+
});
|
|
22111
|
+
return;
|
|
22112
|
+
}
|
|
22113
|
+
await NodeFSP.rm(link, { recursive: true, force: true });
|
|
22114
|
+
await NodeFSP.symlink(target, link, targetInfo.isDirectory() ? "junction" : "file");
|
|
22115
|
+
return;
|
|
22116
|
+
}
|
|
22117
|
+
if (state._tag === "Symlink") {
|
|
22118
|
+
if (NodePath6.resolve(NodePath6.dirname(link), state.target) === target) return;
|
|
22119
|
+
await NodeFSP.rm(link, { force: true });
|
|
22120
|
+
}
|
|
22121
|
+
await NodeFSP.symlink(target, link, targetInfo.isDirectory() ? "junction" : "file");
|
|
22122
|
+
}
|
|
22123
|
+
async function mirrorUserSettings(input) {
|
|
22124
|
+
const sourcePath = NodePath6.join(input.userConfigDirPath, USER_SETTINGS_FILE_NAME);
|
|
22125
|
+
const raw = await readTextFile(sourcePath);
|
|
22126
|
+
if (raw === null) return;
|
|
22127
|
+
const parsed = parseJsonObject(raw);
|
|
22128
|
+
if (parsed === null) {
|
|
22129
|
+
input.log?.warn(
|
|
22130
|
+
"Claude routed home settings mirror skipped: the source is not a JSON object.",
|
|
22131
|
+
{
|
|
22132
|
+
sourcePath
|
|
22133
|
+
}
|
|
22134
|
+
);
|
|
22135
|
+
return;
|
|
22136
|
+
}
|
|
22137
|
+
const mirrored = { ...parsed };
|
|
22138
|
+
for (const key of ROUTING_AND_IDENTITY_SETTING_KEYS) delete mirrored[key];
|
|
22139
|
+
const targetPath = NodePath6.join(input.configDirPath, USER_SETTINGS_FILE_NAME);
|
|
22140
|
+
const desired = `${JSON.stringify(mirrored, null, 2)}
|
|
22141
|
+
`;
|
|
22142
|
+
if (await readTextFile(targetPath) === desired) return;
|
|
22143
|
+
await writeFileAtomic(targetPath, desired);
|
|
22144
|
+
}
|
|
22145
|
+
async function seedFirstRun(input) {
|
|
22146
|
+
const filePath = NodePath6.join(input.configDirPath, GLOBAL_CONFIG_FILE_NAME);
|
|
22147
|
+
const raw = await readTextFile(filePath);
|
|
22148
|
+
const parsed = raw === null ? {} : parseJsonObject(raw);
|
|
22149
|
+
if (parsed === null) {
|
|
22150
|
+
input.log?.warn("Claude routed home first-run seed skipped: the config file is not readable.", {
|
|
22151
|
+
filePath
|
|
22152
|
+
});
|
|
22153
|
+
return;
|
|
22154
|
+
}
|
|
22155
|
+
const next = { ...parsed };
|
|
22156
|
+
let changed = false;
|
|
22157
|
+
if (raw === null) {
|
|
22158
|
+
for (const key of FIRST_RUN_FLAG_KEYS) next[key] = true;
|
|
22159
|
+
changed = true;
|
|
22160
|
+
}
|
|
22161
|
+
const existingProjects = next["projects"];
|
|
22162
|
+
const projects = isRecord5(existingProjects) ? { ...existingProjects } : {};
|
|
22163
|
+
for (const trustedPath of input.trustedPaths) {
|
|
22164
|
+
const resolved = NodePath6.resolve(trustedPath);
|
|
22165
|
+
const entry = projects[resolved];
|
|
22166
|
+
const project = isRecord5(entry) ? { ...entry } : {};
|
|
22167
|
+
if (project["hasTrustDialogAccepted"] === true) continue;
|
|
22168
|
+
project["hasTrustDialogAccepted"] = true;
|
|
22169
|
+
projects[resolved] = project;
|
|
22170
|
+
changed = true;
|
|
22171
|
+
}
|
|
22172
|
+
if (Object.keys(projects).length > 0) next["projects"] = projects;
|
|
22173
|
+
if (!changed) return;
|
|
22174
|
+
await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
|
|
22175
|
+
`);
|
|
22176
|
+
}
|
|
22177
|
+
function resolveClaudeLaunchHome(input) {
|
|
22178
|
+
const routed = isRoutedLaunch(input.launchProcessEnv);
|
|
22179
|
+
const dataDirPath = input.pluginDataDirPath?.trim() ?? "";
|
|
22180
|
+
if (routed && dataDirPath.length === 0) {
|
|
22181
|
+
input.log?.warn(
|
|
22182
|
+
"Ycodium is routing this turn but has no directory of its own to hand the CLI; it will read the user's."
|
|
22183
|
+
);
|
|
22184
|
+
}
|
|
22185
|
+
return resolveClaudeHomeLayout({
|
|
22186
|
+
homePath: input.homePath,
|
|
22187
|
+
credentialsPath: input.credentialsPath,
|
|
22188
|
+
...routed && dataDirPath.length > 0 ? { routedHomePath: claudeRoutedHomePath(dataDirPath) } : {},
|
|
22189
|
+
...input.environment === void 0 ? {} : { environment: input.environment }
|
|
22190
|
+
});
|
|
22191
|
+
}
|
|
22192
|
+
async function materializeClaudeRoutedHome(layout, options) {
|
|
22193
|
+
if (layout.mode !== "routed") return;
|
|
22194
|
+
const configDirPath = layout.configDirPath;
|
|
22195
|
+
if (configDirPath === void 0) return;
|
|
22196
|
+
if (configDirPath === layout.userConfigDirPath) {
|
|
22197
|
+
throw new Error(
|
|
22198
|
+
`Ycodium's Claude configuration directory '${configDirPath}' must differ from the user's.`
|
|
22199
|
+
);
|
|
22200
|
+
}
|
|
22201
|
+
await NodeFSP.mkdir(configDirPath, { recursive: true });
|
|
22202
|
+
await NodeFSP.chmod(configDirPath, 448);
|
|
22203
|
+
const credentialsDirPath = layout.credentialsDirPath;
|
|
22204
|
+
if (credentialsDirPath !== void 0 && credentialsDirPath !== configDirPath) {
|
|
22205
|
+
await NodeFSP.mkdir(credentialsDirPath, { recursive: true });
|
|
22206
|
+
await NodeFSP.chmod(credentialsDirPath, 448);
|
|
22207
|
+
}
|
|
22208
|
+
const log = options?.log;
|
|
22209
|
+
for (const entryName of BORROWED_ENTRY_NAMES) {
|
|
22210
|
+
try {
|
|
22211
|
+
await borrowEntry({
|
|
22212
|
+
userConfigDirPath: layout.userConfigDirPath,
|
|
22213
|
+
configDirPath,
|
|
22214
|
+
entryName,
|
|
22215
|
+
log
|
|
22216
|
+
});
|
|
22217
|
+
} catch (error) {
|
|
22218
|
+
log?.warn("Claude routed home entry left unlinked.", {
|
|
22219
|
+
entryName,
|
|
22220
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
22221
|
+
});
|
|
22222
|
+
}
|
|
22223
|
+
}
|
|
22224
|
+
await mirrorUserSettings({
|
|
22225
|
+
userConfigDirPath: layout.userConfigDirPath,
|
|
22226
|
+
configDirPath,
|
|
22227
|
+
log
|
|
22228
|
+
});
|
|
22229
|
+
await seedFirstRun({
|
|
22230
|
+
configDirPath,
|
|
22231
|
+
trustedPaths: options?.trustedPaths ?? [],
|
|
22232
|
+
log
|
|
22233
|
+
});
|
|
22234
|
+
}
|
|
22235
|
+
|
|
22236
|
+
// src/textGeneration.ts
|
|
22237
|
+
import { mergeLaunchEnv, brainSlotEnvKeys as brainSlotEnvKeys2 } from "@ycodium-ai/plugin-api/executor";
|
|
22238
|
+
|
|
21790
22239
|
// src/textGenerationUtils.ts
|
|
21791
22240
|
function limitSection(value, maxChars) {
|
|
21792
22241
|
if (value.length <= maxChars) return value;
|
|
@@ -22134,7 +22583,7 @@ function buildHandoverSummaryPrompt(input) {
|
|
|
22134
22583
|
|
|
22135
22584
|
// src/textGeneration.ts
|
|
22136
22585
|
var CLAUDE_TIMEOUT_MS = 18e4;
|
|
22137
|
-
function
|
|
22586
|
+
function isRecord6(value) {
|
|
22138
22587
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22139
22588
|
}
|
|
22140
22589
|
function readString3(value) {
|
|
@@ -22156,18 +22605,31 @@ function decodeStructuredOutput(stdout, operation) {
|
|
|
22156
22605
|
cause: error
|
|
22157
22606
|
});
|
|
22158
22607
|
}
|
|
22159
|
-
if (!
|
|
22608
|
+
if (!isRecord6(parsed) || !("structured_output" in parsed)) {
|
|
22160
22609
|
throw new Error(`${operation}: Claude CLI returned unexpected output format.`);
|
|
22161
22610
|
}
|
|
22162
22611
|
return parsed.structured_output;
|
|
22163
22612
|
}
|
|
22164
|
-
function createClaudeTextGeneration(recipe, host) {
|
|
22613
|
+
function createClaudeTextGeneration(recipe, host, pluginDataDirPath) {
|
|
22165
22614
|
const runClaudeJson = async (input) => {
|
|
22166
|
-
const
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22615
|
+
const homeLayout = resolveClaudeLaunchHome({
|
|
22616
|
+
homePath: recipe.homePath,
|
|
22617
|
+
credentialsPath: recipe.credentialsPath,
|
|
22618
|
+
launchProcessEnv: input.launch?.processEnv,
|
|
22619
|
+
pluginDataDirPath,
|
|
22620
|
+
log: host.log
|
|
22621
|
+
});
|
|
22622
|
+
await materializeClaudeRoutedHome(homeLayout, {
|
|
22623
|
+
trustedPaths: [input.cwd],
|
|
22624
|
+
log: host.log
|
|
22625
|
+
});
|
|
22626
|
+
const processEnv = mergeLaunchEnv({
|
|
22627
|
+
brainSlots: brainSlotEnvKeys2(CLAUDE_CARD),
|
|
22628
|
+
instanceTable: recipe.environment,
|
|
22629
|
+
handOverrides: claudeHomeVariables(homeLayout),
|
|
22630
|
+
launch: input.launch?.processEnv
|
|
22631
|
+
});
|
|
22632
|
+
const modelSelection = isRecord6(input.modelSelection) ? input.modelSelection : {};
|
|
22171
22633
|
const requestedModel = input.launch?.requestedModelId ?? modelIdFromSelection(modelSelection) ?? "claude-haiku-4-5";
|
|
22172
22634
|
const caps = claudeModelCapabilities(requestedModel, recipe.customModels);
|
|
22173
22635
|
const rawEffort = getModelSelectionStringOptionValue(modelSelection, "effort");
|
|
@@ -22200,7 +22662,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22200
22662
|
program,
|
|
22201
22663
|
args,
|
|
22202
22664
|
cwd: input.cwd,
|
|
22203
|
-
env:
|
|
22665
|
+
env: processEnv,
|
|
22204
22666
|
owner: { bindingId: host.bindingId }
|
|
22205
22667
|
});
|
|
22206
22668
|
const timeout = AbortSignal.timeout(CLAUDE_TIMEOUT_MS);
|
|
@@ -22229,7 +22691,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22229
22691
|
return decodeStructuredOutput(stdout, input.operation);
|
|
22230
22692
|
};
|
|
22231
22693
|
const asRecord = (value, operation) => {
|
|
22232
|
-
if (!
|
|
22694
|
+
if (!isRecord6(value))
|
|
22233
22695
|
throw new Error(`${operation}: Claude returned invalid structured output.`);
|
|
22234
22696
|
return value;
|
|
22235
22697
|
};
|
|
@@ -22243,7 +22705,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22243
22705
|
stagedSummary: readString3(input["stagedSummary"]),
|
|
22244
22706
|
stagedPatch: readString3(input["stagedPatch"]),
|
|
22245
22707
|
includeBranch,
|
|
22246
|
-
...
|
|
22708
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
22247
22709
|
});
|
|
22248
22710
|
const generated = asRecord(
|
|
22249
22711
|
await runClaudeJson({
|
|
@@ -22252,7 +22714,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22252
22714
|
prompt,
|
|
22253
22715
|
outputSchema,
|
|
22254
22716
|
modelSelection: input["modelSelection"],
|
|
22255
|
-
...
|
|
22717
|
+
...isRecord6(input["launch"]) ? { launch: input["launch"] } : {},
|
|
22256
22718
|
...signal === void 0 ? {} : { signal }
|
|
22257
22719
|
}),
|
|
22258
22720
|
"generateCommitMessage"
|
|
@@ -22276,7 +22738,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22276
22738
|
diffSummary: readString3(input["diffSummary"]),
|
|
22277
22739
|
diffPatch: readString3(input["diffPatch"]),
|
|
22278
22740
|
...typeof input["changeRequestTemplate"] === "string" ? { changeRequestTemplate: input["changeRequestTemplate"] } : {},
|
|
22279
|
-
...
|
|
22741
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
22280
22742
|
});
|
|
22281
22743
|
const generated = asRecord(
|
|
22282
22744
|
await runClaudeJson({
|
|
@@ -22285,7 +22747,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22285
22747
|
prompt,
|
|
22286
22748
|
outputSchema,
|
|
22287
22749
|
modelSelection: input["modelSelection"],
|
|
22288
|
-
...
|
|
22750
|
+
...isRecord6(input["launch"]) ? { launch: input["launch"] } : {},
|
|
22289
22751
|
...signal === void 0 ? {} : { signal }
|
|
22290
22752
|
}),
|
|
22291
22753
|
"generatePrContent"
|
|
@@ -22304,7 +22766,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22304
22766
|
const { prompt, outputSchema } = buildBranchNamePrompt({
|
|
22305
22767
|
message: readString3(input["message"]),
|
|
22306
22768
|
...Array.isArray(input["attachments"]) ? { attachments: input["attachments"] } : {},
|
|
22307
|
-
...
|
|
22769
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
22308
22770
|
});
|
|
22309
22771
|
const generated = asRecord(
|
|
22310
22772
|
await runClaudeJson({
|
|
@@ -22313,7 +22775,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22313
22775
|
prompt,
|
|
22314
22776
|
outputSchema,
|
|
22315
22777
|
modelSelection: input["modelSelection"],
|
|
22316
|
-
...
|
|
22778
|
+
...isRecord6(input["launch"]) ? { launch: input["launch"] } : {},
|
|
22317
22779
|
...signal === void 0 ? {} : { signal }
|
|
22318
22780
|
}),
|
|
22319
22781
|
"generateBranchName"
|
|
@@ -22330,7 +22792,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22330
22792
|
message: readString3(input["message"]),
|
|
22331
22793
|
...typeof input["previousTitle"] === "string" ? { previousTitle: input["previousTitle"] } : {},
|
|
22332
22794
|
...Array.isArray(input["attachments"]) ? { attachments: input["attachments"] } : {},
|
|
22333
|
-
...
|
|
22795
|
+
...isRecord6(input["policy"]) ? { policy: input["policy"] } : {}
|
|
22334
22796
|
});
|
|
22335
22797
|
const generated = asRecord(
|
|
22336
22798
|
await runClaudeJson({
|
|
@@ -22339,7 +22801,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22339
22801
|
prompt,
|
|
22340
22802
|
outputSchema,
|
|
22341
22803
|
modelSelection: input["modelSelection"],
|
|
22342
|
-
...
|
|
22804
|
+
...isRecord6(input["launch"]) ? { launch: input["launch"] } : {},
|
|
22343
22805
|
...signal === void 0 ? {} : { signal }
|
|
22344
22806
|
}),
|
|
22345
22807
|
"generateThreadTitle"
|
|
@@ -22362,7 +22824,7 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22362
22824
|
prompt,
|
|
22363
22825
|
outputSchema,
|
|
22364
22826
|
modelSelection: input["modelSelection"],
|
|
22365
|
-
...
|
|
22827
|
+
...isRecord6(input["launch"]) ? { launch: input["launch"] } : {},
|
|
22366
22828
|
...signal === void 0 ? {} : { signal }
|
|
22367
22829
|
}),
|
|
22368
22830
|
"summarizeHandover"
|
|
@@ -22374,14 +22836,6 @@ function createClaudeTextGeneration(recipe, host) {
|
|
|
22374
22836
|
}
|
|
22375
22837
|
};
|
|
22376
22838
|
}
|
|
22377
|
-
function compactEnv(env) {
|
|
22378
|
-
const out = {};
|
|
22379
|
-
if (!env) return out;
|
|
22380
|
-
for (const [key, value] of Object.entries(env)) {
|
|
22381
|
-
if (value !== void 0) out[key] = value;
|
|
22382
|
-
}
|
|
22383
|
-
return out;
|
|
22384
|
-
}
|
|
22385
22839
|
|
|
22386
22840
|
// src/imageMime.ts
|
|
22387
22841
|
var IMAGE_EXTENSION_BY_MIME_TYPE = {
|
|
@@ -22463,9 +22917,9 @@ var PromptQueue = class {
|
|
|
22463
22917
|
const queued = this.#queued.shift();
|
|
22464
22918
|
if (queued !== void 0) return Promise.resolve(queued);
|
|
22465
22919
|
if (this.#closed) return Promise.resolve(void 0);
|
|
22466
|
-
return new Promise((
|
|
22920
|
+
return new Promise((resolve3) => {
|
|
22467
22921
|
this.#waiters.push((result) => {
|
|
22468
|
-
|
|
22922
|
+
resolve3(result.done ? void 0 : result.value);
|
|
22469
22923
|
});
|
|
22470
22924
|
});
|
|
22471
22925
|
}
|
|
@@ -22496,6 +22950,7 @@ var SUPPORTED_CLAUDE_IMAGE_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
|
22496
22950
|
]);
|
|
22497
22951
|
var CLAUDE_INTERRUPT_GRACE_MS = 5e3;
|
|
22498
22952
|
var CLAUDE_SESSION_CONTEXT_WAIT_MS = 1e4;
|
|
22953
|
+
var CLAUDE_STDERR_TAIL_CHARS = 4e3;
|
|
22499
22954
|
function asClaudeModelSelection(value) {
|
|
22500
22955
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
22501
22956
|
return value;
|
|
@@ -22583,7 +23038,7 @@ async function persistProducedImage(input) {
|
|
|
22583
23038
|
}
|
|
22584
23039
|
|
|
22585
23040
|
// src/claudeInstance.ts
|
|
22586
|
-
function
|
|
23041
|
+
function compactEnv(env) {
|
|
22587
23042
|
const out = {};
|
|
22588
23043
|
if (!env) return out;
|
|
22589
23044
|
for (const [key, value] of Object.entries(env)) {
|
|
@@ -22591,10 +23046,26 @@ function compactEnv2(env) {
|
|
|
22591
23046
|
}
|
|
22592
23047
|
return out;
|
|
22593
23048
|
}
|
|
23049
|
+
function toClaudeMcpServers(entries) {
|
|
23050
|
+
if (entries === void 0 || entries.length === 0) return void 0;
|
|
23051
|
+
const servers = {};
|
|
23052
|
+
for (const entry of entries) {
|
|
23053
|
+
servers[entry.name] = entry.transport.type === "stdio" ? {
|
|
23054
|
+
type: "stdio",
|
|
23055
|
+
command: entry.transport.command,
|
|
23056
|
+
...entry.transport.args === void 0 ? {} : { args: [...entry.transport.args] },
|
|
23057
|
+
...entry.transport.env === void 0 ? {} : { env: { ...entry.transport.env } }
|
|
23058
|
+
} : {
|
|
23059
|
+
type: entry.transport.type,
|
|
23060
|
+
url: entry.transport.url,
|
|
23061
|
+
...entry.transport.headers === void 0 ? {} : { headers: { ...entry.transport.headers } }
|
|
23062
|
+
};
|
|
23063
|
+
}
|
|
23064
|
+
return servers;
|
|
23065
|
+
}
|
|
22594
23066
|
function createClaudeAdapter(recipe, host, options) {
|
|
22595
23067
|
const boundInstanceId = options?.instanceId ?? host.instanceId ?? "claudeAgent";
|
|
22596
23068
|
const claudeHomeEnvironment = makeClaudeEnvironment(recipe, options?.environment);
|
|
22597
|
-
const sessionLaunchEnv = /* @__PURE__ */ new Map();
|
|
22598
23069
|
const claudeSdkExecutablePath = resolveClaudeSdkExecutablePath(
|
|
22599
23070
|
recipe.binaryPath,
|
|
22600
23071
|
claudeHomeEnvironment
|
|
@@ -22886,8 +23357,8 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
22886
23357
|
try {
|
|
22887
23358
|
usage = await Promise.race([
|
|
22888
23359
|
context.query.getContextUsage(),
|
|
22889
|
-
new Promise((
|
|
22890
|
-
setTimeout(() =>
|
|
23360
|
+
new Promise((resolve3) => {
|
|
23361
|
+
setTimeout(() => resolve3(void 0), 1e3);
|
|
22891
23362
|
})
|
|
22892
23363
|
]);
|
|
22893
23364
|
} catch {
|
|
@@ -24180,7 +24651,9 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24180
24651
|
await completeTurn(context, "interrupted", "Claude runtime interrupted.");
|
|
24181
24652
|
}
|
|
24182
24653
|
} else {
|
|
24183
|
-
const
|
|
24654
|
+
const cliSaid = context.stderrTail.read();
|
|
24655
|
+
const reason = cause instanceof Error ? cause.message : "Claude runtime stream failed.";
|
|
24656
|
+
const message = cliSaid.length > 0 ? `${reason}: ${cliSaid}` : reason;
|
|
24184
24657
|
await emitRuntimeError(context, message, { cause: String(cause) });
|
|
24185
24658
|
await completeTurn(context, "failed", message);
|
|
24186
24659
|
}
|
|
@@ -24256,7 +24729,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24256
24729
|
if (streamFiber) {
|
|
24257
24730
|
await Promise.race([
|
|
24258
24731
|
streamFiber.catch(() => void 0),
|
|
24259
|
-
new Promise((
|
|
24732
|
+
new Promise((resolve3) => setTimeout(resolve3, 1e3))
|
|
24260
24733
|
]);
|
|
24261
24734
|
}
|
|
24262
24735
|
const updatedAt = nowIso();
|
|
@@ -24283,9 +24756,6 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24283
24756
|
}
|
|
24284
24757
|
if (sessions.get(context.session.threadId) === context) {
|
|
24285
24758
|
sessions.delete(context.session.threadId);
|
|
24286
|
-
if (stopOptions?.keepLaunch !== true) {
|
|
24287
|
-
sessionLaunchEnv.delete(context.session.threadId);
|
|
24288
|
-
}
|
|
24289
24759
|
}
|
|
24290
24760
|
})();
|
|
24291
24761
|
context.stopWork = work;
|
|
@@ -24365,7 +24835,13 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24365
24835
|
const modelSelection = boundModelSelection(input.modelSelection, boundInstanceId);
|
|
24366
24836
|
const caps = claudeModelCapabilities(modelSelection?.model, recipe.customModels);
|
|
24367
24837
|
const descriptors = caps.optionDescriptors;
|
|
24368
|
-
const apiModelId = modelSelection?.model ? resolveClaudeApiModelId(caps, {
|
|
24838
|
+
const apiModelId = modelSelection?.model ? resolveClaudeApiModelId(caps, {
|
|
24839
|
+
model: claudeCliModelId({
|
|
24840
|
+
boundModelId: modelSelection.model,
|
|
24841
|
+
placeholder: CLAUDE_CARD.defaultModel,
|
|
24842
|
+
customModels: recipe.customModels
|
|
24843
|
+
})
|
|
24844
|
+
}) : void 0;
|
|
24369
24845
|
const initialContextWindow = selectedClaudeContextWindow(caps, modelSelection);
|
|
24370
24846
|
const rawEffort = getModelSelectionStringOptionValue(modelSelection, "effort");
|
|
24371
24847
|
const effort = resolveClaudeEffort(caps, rawEffort) ?? null;
|
|
@@ -24379,16 +24855,13 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24379
24855
|
const thinking = thinkingSupported ? getModelSelectionBooleanOptionValue(modelSelection, "thinking") : void 0;
|
|
24380
24856
|
const ultracode = isClaudeUltracodeEffort(effort);
|
|
24381
24857
|
const effectiveEffort = getEffectiveClaudeAgentEffort(effort, modelSelection?.model, caps);
|
|
24382
|
-
const permissionMode =
|
|
24858
|
+
const permissionMode = claudePermissionModeFor(input.runtimeMode, input.nativeModeId);
|
|
24383
24859
|
const settings = buildClaudeSessionSettings({
|
|
24384
24860
|
thinking,
|
|
24385
24861
|
fastMode,
|
|
24386
24862
|
ultracode,
|
|
24387
24863
|
autoCompactWindow: recipe.autoCompactWindow
|
|
24388
24864
|
});
|
|
24389
|
-
if (input.launch.processEnv) {
|
|
24390
|
-
sessionLaunchEnv.set(input.threadId, input.launch.processEnv);
|
|
24391
|
-
}
|
|
24392
24865
|
const existingContext = sessions.get(input.threadId);
|
|
24393
24866
|
if (existingContext) {
|
|
24394
24867
|
const reconfigured = await reconfigureSession(existingContext, input, {
|
|
@@ -24407,10 +24880,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24407
24880
|
existingSessionStatus: existingContext.session.status,
|
|
24408
24881
|
reason: "startSession called with existing active session"
|
|
24409
24882
|
});
|
|
24410
|
-
await stopSessionInternal(existingContext, {
|
|
24411
|
-
emitExitEvent: false,
|
|
24412
|
-
keepLaunch: true
|
|
24413
|
-
});
|
|
24883
|
+
await stopSessionInternal(existingContext, { emitExitEvent: false });
|
|
24414
24884
|
}
|
|
24415
24885
|
const startedAt = nowIso();
|
|
24416
24886
|
const resumeState = input.discardResumeCursor === true ? void 0 : readClaudeResumeState(input.resumeCursor);
|
|
@@ -24433,7 +24903,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24433
24903
|
return await Promise.race([
|
|
24434
24904
|
contextDeferred.promise,
|
|
24435
24905
|
new Promise(
|
|
24436
|
-
(
|
|
24906
|
+
(resolve3) => setTimeout(() => resolve3(void 0), CLAUDE_SESSION_CONTEXT_WAIT_MS)
|
|
24437
24907
|
)
|
|
24438
24908
|
]);
|
|
24439
24909
|
} catch {
|
|
@@ -24575,7 +25045,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24575
25045
|
message: "The client captured your proposed plan. Stop here and wait for the user's feedback or implementation request in a later turn."
|
|
24576
25046
|
};
|
|
24577
25047
|
}
|
|
24578
|
-
if (context2.
|
|
25048
|
+
if (context2.currentPermissionMode === "bypassPermissions") {
|
|
24579
25049
|
return {
|
|
24580
25050
|
behavior: "allow",
|
|
24581
25051
|
updatedInput: toolInput
|
|
@@ -24716,16 +25186,33 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24716
25186
|
};
|
|
24717
25187
|
const onUserDialog = (request, callbackOptions) => handleResumeDialog(request, callbackOptions);
|
|
24718
25188
|
const additionalDirectories = input.cwd ? [input.cwd] : [];
|
|
24719
|
-
const
|
|
24720
|
-
|
|
24721
|
-
|
|
24722
|
-
|
|
24723
|
-
|
|
24724
|
-
|
|
24725
|
-
|
|
24726
|
-
...
|
|
24727
|
-
};
|
|
24728
|
-
|
|
25189
|
+
const mcpServers = toClaudeMcpServers(input.mcpServers);
|
|
25190
|
+
const homeLayout = resolveClaudeLaunchHome({
|
|
25191
|
+
homePath: recipe.homePath,
|
|
25192
|
+
credentialsPath: recipe.credentialsPath,
|
|
25193
|
+
launchProcessEnv: input.launch.processEnv,
|
|
25194
|
+
pluginDataDirPath: options?.pluginDataDirPath,
|
|
25195
|
+
environment: claudeHomeEnvironment,
|
|
25196
|
+
...options?.log === void 0 ? {} : { log: options.log }
|
|
25197
|
+
});
|
|
25198
|
+
await materializeClaudeRoutedHome(homeLayout, {
|
|
25199
|
+
...input.cwd ? { trustedPaths: [input.cwd] } : {},
|
|
25200
|
+
...options?.log === void 0 ? {} : { log: options.log }
|
|
25201
|
+
});
|
|
25202
|
+
const launchEnvironment = mergeLaunchEnv2({
|
|
25203
|
+
brainSlots: brainSlotEnvKeys3(CLAUDE_CARD),
|
|
25204
|
+
inherited: { ...process.env, ...options?.environment },
|
|
25205
|
+
instanceTable: recipe.environment,
|
|
25206
|
+
handOverrides: claudeHomeVariables(homeLayout),
|
|
25207
|
+
launch: input.launch.processEnv
|
|
25208
|
+
});
|
|
25209
|
+
const envOverride = routedEnvOverride({
|
|
25210
|
+
launchProcessEnv: input.launch.processEnv,
|
|
25211
|
+
mergedEnv: launchEnvironment,
|
|
25212
|
+
...recipe.customModels === void 0 ? {} : { customModels: recipe.customModels }
|
|
25213
|
+
});
|
|
25214
|
+
const querySettings = envOverride === void 0 ? { ...settings } : { ...settings, env: envOverride };
|
|
25215
|
+
const stderrTail = createOutputTail(CLAUDE_STDERR_TAIL_CHARS);
|
|
24729
25216
|
const queryOptions = {
|
|
24730
25217
|
...input.cwd ? { cwd: input.cwd } : {},
|
|
24731
25218
|
...apiModelId ? { model: apiModelId } : {},
|
|
@@ -24741,6 +25228,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24741
25228
|
...existingResumeSessionId ? { resume: existingResumeSessionId } : {},
|
|
24742
25229
|
...newSessionId ? { sessionId: newSessionId } : {},
|
|
24743
25230
|
includePartialMessages: true,
|
|
25231
|
+
stderr: stderrTail.append,
|
|
24744
25232
|
canUseTool,
|
|
24745
25233
|
onUserDialog,
|
|
24746
25234
|
hooks: {
|
|
@@ -24758,9 +25246,10 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24758
25246
|
]
|
|
24759
25247
|
},
|
|
24760
25248
|
supportedDialogKinds: ["resume_return"],
|
|
24761
|
-
env:
|
|
25249
|
+
env: compactEnv(launchEnvironment),
|
|
24762
25250
|
additionalDirectories,
|
|
24763
|
-
...Object.keys(extraArgs).length > 0 ? { extraArgs } : {}
|
|
25251
|
+
...Object.keys(extraArgs).length > 0 ? { extraArgs } : {},
|
|
25252
|
+
...mcpServers === void 0 ? {} : { mcpServers }
|
|
24764
25253
|
};
|
|
24765
25254
|
let queryRuntime;
|
|
24766
25255
|
try {
|
|
@@ -24777,6 +25266,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24777
25266
|
providerInstanceId: boundInstanceId,
|
|
24778
25267
|
status: "ready",
|
|
24779
25268
|
runtimeMode: input.runtimeMode,
|
|
25269
|
+
nativeModeId: permissionMode,
|
|
24780
25270
|
...input.cwd ? { cwd: input.cwd } : {},
|
|
24781
25271
|
...modelSelection?.model ? { model: modelSelection.model } : {},
|
|
24782
25272
|
resumeCursor: {
|
|
@@ -24796,6 +25286,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24796
25286
|
},
|
|
24797
25287
|
promptQueue,
|
|
24798
25288
|
query: queryRuntime,
|
|
25289
|
+
stderrTail,
|
|
24799
25290
|
streamFiber: void 0,
|
|
24800
25291
|
startedAt,
|
|
24801
25292
|
basePermissionMode: permissionMode,
|
|
@@ -24904,7 +25395,13 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
24904
25395
|
}
|
|
24905
25396
|
if (modelSelection?.model) {
|
|
24906
25397
|
const turnCaps = claudeModelCapabilities(modelSelection.model, recipe.customModels);
|
|
24907
|
-
const apiModelId = resolveClaudeApiModelId(turnCaps, {
|
|
25398
|
+
const apiModelId = resolveClaudeApiModelId(turnCaps, {
|
|
25399
|
+
model: claudeCliModelId({
|
|
25400
|
+
boundModelId: modelSelection.model,
|
|
25401
|
+
placeholder: CLAUDE_CARD.defaultModel,
|
|
25402
|
+
customModels: recipe.customModels
|
|
25403
|
+
})
|
|
25404
|
+
});
|
|
24908
25405
|
if (context.currentApiModelId !== apiModelId) {
|
|
24909
25406
|
try {
|
|
24910
25407
|
await context.query.setModel(apiModelId);
|
|
@@ -25002,7 +25499,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
25002
25499
|
context.query.interrupt().then(() => settled.promise).then(() => {
|
|
25003
25500
|
acknowledged = true;
|
|
25004
25501
|
}),
|
|
25005
|
-
new Promise((
|
|
25502
|
+
new Promise((resolve3) => setTimeout(resolve3, CLAUDE_INTERRUPT_GRACE_MS))
|
|
25006
25503
|
]);
|
|
25007
25504
|
} catch (cause) {
|
|
25008
25505
|
throw toRequestError(threadId, "turn/interrupt", cause);
|
|
@@ -25037,22 +25534,49 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
25037
25534
|
if (context.session.runtimeMode === runtimeMode) {
|
|
25038
25535
|
return;
|
|
25039
25536
|
}
|
|
25040
|
-
const permissionMode =
|
|
25537
|
+
const permissionMode = claudePermissionModeFor(runtimeMode);
|
|
25041
25538
|
context.basePermissionMode = permissionMode;
|
|
25042
25539
|
context.session = {
|
|
25043
25540
|
...context.session,
|
|
25044
25541
|
runtimeMode,
|
|
25542
|
+
nativeModeId: permissionMode,
|
|
25045
25543
|
updatedAt: nowIso()
|
|
25046
25544
|
};
|
|
25047
25545
|
if (context.currentPermissionMode !== "plan") {
|
|
25048
25546
|
try {
|
|
25049
|
-
await context.query.setPermissionMode(permissionMode
|
|
25547
|
+
await context.query.setPermissionMode(permissionMode);
|
|
25050
25548
|
} catch (cause) {
|
|
25051
25549
|
throw toRequestError(threadId, "session/setPermissionMode", cause);
|
|
25052
25550
|
}
|
|
25053
25551
|
context.currentPermissionMode = permissionMode;
|
|
25054
25552
|
}
|
|
25055
|
-
if (
|
|
25553
|
+
if (permissionMode !== "bypassPermissions") {
|
|
25554
|
+
return;
|
|
25555
|
+
}
|
|
25556
|
+
for (const [requestId, pending] of context.pendingApprovals) {
|
|
25557
|
+
context.pendingApprovals.delete(requestId);
|
|
25558
|
+
pending.decision.resolve({ decision: "accept" });
|
|
25559
|
+
}
|
|
25560
|
+
};
|
|
25561
|
+
const setNativeMode = async (threadId, nativeModeId) => {
|
|
25562
|
+
const context = requireSession(threadId);
|
|
25563
|
+
if (!isClaudeNativeModeId(nativeModeId)) return;
|
|
25564
|
+
if (context.currentPermissionMode === nativeModeId) return;
|
|
25565
|
+
context.basePermissionMode = nativeModeId;
|
|
25566
|
+
context.session = {
|
|
25567
|
+
...context.session,
|
|
25568
|
+
nativeModeId,
|
|
25569
|
+
updatedAt: nowIso()
|
|
25570
|
+
};
|
|
25571
|
+
if (context.currentPermissionMode !== "plan" || nativeModeId === "plan") {
|
|
25572
|
+
try {
|
|
25573
|
+
await context.query.setPermissionMode(nativeModeId);
|
|
25574
|
+
} catch (cause) {
|
|
25575
|
+
throw toRequestError(threadId, "session/setPermissionMode", cause);
|
|
25576
|
+
}
|
|
25577
|
+
context.currentPermissionMode = nativeModeId;
|
|
25578
|
+
}
|
|
25579
|
+
if (nativeModeId !== "bypassPermissions") {
|
|
25056
25580
|
return;
|
|
25057
25581
|
}
|
|
25058
25582
|
for (const [requestId, pending] of context.pendingApprovals) {
|
|
@@ -25085,6 +25609,7 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
25085
25609
|
respondToRequest,
|
|
25086
25610
|
respondToUserInput,
|
|
25087
25611
|
setRuntimeMode,
|
|
25612
|
+
setNativeMode,
|
|
25088
25613
|
stopSession,
|
|
25089
25614
|
events: runtimeEventQueue,
|
|
25090
25615
|
dispose: async () => {
|
|
@@ -25095,12 +25620,19 @@ function createClaudeAdapter(recipe, host, options) {
|
|
|
25095
25620
|
}
|
|
25096
25621
|
};
|
|
25097
25622
|
}
|
|
25098
|
-
function
|
|
25623
|
+
function claudeAdapterBaseEnvironment(recipe) {
|
|
25624
|
+
return {
|
|
25625
|
+
...process.env,
|
|
25626
|
+
...withoutBrainSlots(recipe.environment, brainSlotEnvKeys3(CLAUDE_CARD))
|
|
25627
|
+
};
|
|
25628
|
+
}
|
|
25629
|
+
function createClaudeInstance(config, host, attachments, pluginDataDirPath) {
|
|
25099
25630
|
const recipe = parseClaudeInstanceConfig(config);
|
|
25100
25631
|
const adapter = createClaudeAdapter(recipe, host, {
|
|
25101
25632
|
instanceId: host.instanceId,
|
|
25102
25633
|
...attachments === void 0 ? {} : { attachments },
|
|
25103
|
-
|
|
25634
|
+
...pluginDataDirPath === void 0 ? {} : { pluginDataDirPath },
|
|
25635
|
+
environment: claudeAdapterBaseEnvironment(recipe),
|
|
25104
25636
|
log: host.log
|
|
25105
25637
|
});
|
|
25106
25638
|
const collectProcessText = async (stream) => {
|
|
@@ -25111,6 +25643,15 @@ function createClaudeInstance(config, host, attachments) {
|
|
|
25111
25643
|
return Buffer.concat(chunks).toString("utf8");
|
|
25112
25644
|
};
|
|
25113
25645
|
const probeAuth = () => {
|
|
25646
|
+
const hasEnvToken = (recipe.environment.ANTHROPIC_AUTH_TOKEN ?? "").trim().length > 0;
|
|
25647
|
+
const hasEnvApiKey = (recipe.environment.ANTHROPIC_API_KEY ?? "").trim().length > 0;
|
|
25648
|
+
if (hasEnvToken || hasEnvApiKey) {
|
|
25649
|
+
return {
|
|
25650
|
+
status: "authenticated",
|
|
25651
|
+
type: hasEnvToken ? "env-token" : "api-key",
|
|
25652
|
+
label: hasEnvToken ? "ANTHROPIC_AUTH_TOKEN" : "ANTHROPIC_API_KEY"
|
|
25653
|
+
};
|
|
25654
|
+
}
|
|
25114
25655
|
const account = readClaudeAccount(resolveClaudeCredentialsDirPath(recipe.credentialsPath));
|
|
25115
25656
|
switch (account.state) {
|
|
25116
25657
|
case "signed-in":
|
|
@@ -25147,6 +25688,10 @@ function createClaudeInstance(config, host, attachments) {
|
|
|
25147
25688
|
]);
|
|
25148
25689
|
const version = parseGenericCliVersion(`${stdout}
|
|
25149
25690
|
${stderr}`);
|
|
25691
|
+
const models = claudeProbeModels({
|
|
25692
|
+
builtIn: getBuiltInClaudeModelsForVersion(version),
|
|
25693
|
+
customModels: recipe.customModels
|
|
25694
|
+
});
|
|
25150
25695
|
const auth = probeAuth();
|
|
25151
25696
|
if (exitCode !== 0 && version === null) {
|
|
25152
25697
|
const detail = (stderr || stdout || "claude --version failed").trim();
|
|
@@ -25164,14 +25709,19 @@ ${stderr}`);
|
|
|
25164
25709
|
version,
|
|
25165
25710
|
readiness: "error",
|
|
25166
25711
|
auth,
|
|
25167
|
-
|
|
25712
|
+
models,
|
|
25713
|
+
detail: "Claude is signed out",
|
|
25714
|
+
// 退出登录了档位照样是那五档。不报就退回宿主四档,而那份映射少了 `plan`。
|
|
25715
|
+
...CLAUDE_NATIVE_MODE_REPORT
|
|
25168
25716
|
};
|
|
25169
25717
|
}
|
|
25170
25718
|
return {
|
|
25171
25719
|
installed: true,
|
|
25172
25720
|
version,
|
|
25173
25721
|
readiness: "ready",
|
|
25174
|
-
auth
|
|
25722
|
+
auth,
|
|
25723
|
+
models,
|
|
25724
|
+
...CLAUDE_NATIVE_MODE_REPORT
|
|
25175
25725
|
};
|
|
25176
25726
|
};
|
|
25177
25727
|
const resolveTranscriptRoots = (directory) => {
|
|
@@ -25182,7 +25732,7 @@ ${stderr}`);
|
|
|
25182
25732
|
);
|
|
25183
25733
|
return {
|
|
25184
25734
|
configDir,
|
|
25185
|
-
transcriptDir:
|
|
25735
|
+
transcriptDir: NodePath7.join(configDir, "projects")
|
|
25186
25736
|
};
|
|
25187
25737
|
};
|
|
25188
25738
|
return {
|
|
@@ -25193,12 +25743,14 @@ ${stderr}`);
|
|
|
25193
25743
|
respondToRequest: adapter.respondToRequest,
|
|
25194
25744
|
respondToUserInput: adapter.respondToUserInput,
|
|
25195
25745
|
setRuntimeMode: adapter.setRuntimeMode,
|
|
25746
|
+
setNativeMode: adapter.setNativeMode,
|
|
25196
25747
|
compactContext: adapter.compactContext,
|
|
25197
25748
|
stopSession: adapter.stopSession,
|
|
25198
25749
|
readThread: adapter.readThread,
|
|
25199
25750
|
events: adapter.events,
|
|
25200
25751
|
dispose: adapter.dispose,
|
|
25201
|
-
textGeneration: createClaudeTextGeneration(recipe, host),
|
|
25752
|
+
textGeneration: createClaudeTextGeneration(recipe, host, pluginDataDirPath),
|
|
25753
|
+
continuationKey: claudeContinuationKey(recipe.homePath),
|
|
25202
25754
|
sessions: {
|
|
25203
25755
|
scan: async (input) => {
|
|
25204
25756
|
const roots = resolveTranscriptRoots(input.directory);
|
|
@@ -25239,12 +25791,13 @@ ${stderr}`);
|
|
|
25239
25791
|
|
|
25240
25792
|
// src/index.ts
|
|
25241
25793
|
var capturedAttachments;
|
|
25794
|
+
var capturedDataDirPath;
|
|
25242
25795
|
var executors = [
|
|
25243
25796
|
{
|
|
25244
25797
|
card: CLAUDE_CARD,
|
|
25245
25798
|
createInstance: async (config, host) => {
|
|
25246
25799
|
host.log.info("createInstance");
|
|
25247
|
-
return createClaudeInstance(config, host, capturedAttachments);
|
|
25800
|
+
return createClaudeInstance(config, host, capturedAttachments, capturedDataDirPath);
|
|
25248
25801
|
}
|
|
25249
25802
|
}
|
|
25250
25803
|
];
|
|
@@ -25254,6 +25807,7 @@ var index_default = definePlugin({
|
|
|
25254
25807
|
executors,
|
|
25255
25808
|
activate(ctx) {
|
|
25256
25809
|
capturedAttachments = ctx.attachments;
|
|
25810
|
+
capturedDataDirPath = ctx.paths.dataDir;
|
|
25257
25811
|
ctx.log.info("claude executor ready");
|
|
25258
25812
|
}
|
|
25259
25813
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/agent-claude",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2130",
|
|
4
4
|
"description": "Claude executor: Claude Code CLI via @anthropic-ai/claude-agent-sdk.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"@types/node": "24.12.4",
|
|
24
24
|
"esbuild": "0.28.1",
|
|
25
25
|
"vite-plus": "0.2.2",
|
|
26
|
-
"@ycodium-ai/plugin-api": "0.2.
|
|
26
|
+
"@ycodium-ai/plugin-api": "0.2.2130"
|
|
27
27
|
},
|
|
28
28
|
"ycodium": {
|
|
29
29
|
"plugin": "./dist/index.js",
|
|
30
|
-
"displayName": "Claude",
|
|
30
|
+
"displayName": "Claude Code",
|
|
31
31
|
"description": "Run Claude Code with in-session model and runtime-mode switching, native compaction, and session import.",
|
|
32
32
|
"icon": "./assets/icon.svg",
|
|
33
33
|
"permissions": [
|