oasis_test_v2 2.2.7 → 2.2.9
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/index.js +668 -147
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -665,7 +665,7 @@ function isAgentAvatarPresetRef(ref2) {
|
|
|
665
665
|
const id = ref2.slice(AGENT_AVATAR_PRESET_PREFIX.length);
|
|
666
666
|
return AGENT_AVATAR_PRESET_IDS.includes(id);
|
|
667
667
|
}
|
|
668
|
-
var AGENT_AVATAR_PRESET_PREFIX, AGENT_AVATAR_LEGACY_PRESET_IDS, AGENT_AVATAR_V2_PRESET_IDS, AGENT_AVATAR_PRESET_IDS;
|
|
668
|
+
var AGENT_AVATAR_PRESET_PREFIX, AGENT_AVATAR_LEGACY_PRESET_IDS, AGENT_AVATAR_V2_PRESET_IDS, AGENT_AVATAR_PRESET_IDS, SYSTEM_AVATAR_REF;
|
|
669
669
|
var init_avatar = __esm({
|
|
670
670
|
"../contract/src/avatar.ts"() {
|
|
671
671
|
"use strict";
|
|
@@ -695,6 +695,7 @@ var init_avatar = __esm({
|
|
|
695
695
|
...AGENT_AVATAR_LEGACY_PRESET_IDS,
|
|
696
696
|
...AGENT_AVATAR_V2_PRESET_IDS
|
|
697
697
|
];
|
|
698
|
+
SYSTEM_AVATAR_REF = "preset:system";
|
|
698
699
|
}
|
|
699
700
|
});
|
|
700
701
|
|
|
@@ -910,10 +911,15 @@ var init_link_windows = __esm({
|
|
|
910
911
|
});
|
|
911
912
|
|
|
912
913
|
// ../contract/src/registry.ts
|
|
913
|
-
|
|
914
|
+
function isSystemActorId(id) {
|
|
915
|
+
return typeof id === "string" && id.startsWith(SYSTEM_ACTOR_ID_PREFIX);
|
|
916
|
+
}
|
|
917
|
+
var SYSTEM_ACTOR_ID_PREFIX, SYSTEM_ACTOR_DISPLAY_NAME, AGENT_PREFS_DEFAULTS, SkillOwnedByAnotherCompanyError;
|
|
914
918
|
var init_registry = __esm({
|
|
915
919
|
"../contract/src/registry.ts"() {
|
|
916
920
|
"use strict";
|
|
921
|
+
SYSTEM_ACTOR_ID_PREFIX = "actor:system";
|
|
922
|
+
SYSTEM_ACTOR_DISPLAY_NAME = "\u7CFB\u7EDF";
|
|
917
923
|
AGENT_PREFS_DEFAULTS = { memoryEnabled: true };
|
|
918
924
|
SkillOwnedByAnotherCompanyError = class extends Error {
|
|
919
925
|
constructor(skillId, companyId) {
|
|
@@ -17406,6 +17412,7 @@ ${supplemental.taskAppend.trim()}
|
|
|
17406
17412
|
...Object.keys(jobEnv).length > 0 ? { env: jobEnv } : {},
|
|
17407
17413
|
...provisioned?.wrapperPaths && provisioned.wrapperPaths.length > 0 ? { wrapperPaths: provisioned.wrapperPaths } : {},
|
|
17408
17414
|
...provisioned?.requiredTools && provisioned.requiredTools.length > 0 ? { requiredTools: provisioned.requiredTools } : {},
|
|
17415
|
+
...provisioned?.requiredToolVersions && Object.keys(provisioned.requiredToolVersions).length > 0 ? { requiredToolVersions: provisioned.requiredToolVersions } : {},
|
|
17409
17416
|
// 凭据本体随 job 下发,供**节点侧本机注入**(见上方 provision 注释)。
|
|
17410
17417
|
...provisioned?.connectorCreds && provisioned.connectorCreds.length > 0 ? { connectorCreds: provisioned.connectorCreds } : {},
|
|
17411
17418
|
...executionEnv !== void 0 ? { executionEnv } : {},
|
|
@@ -29522,7 +29529,7 @@ async function sweepStaleChatTurns(deps) {
|
|
|
29522
29529
|
`[chat-turn-sweep] \u8F6E\u6B21 ${turn.id}\uFF08\u4F1A\u8BDD ${turn.chatSessionId}\uFF09\u6536\u53E3\u4E3A ${outcome.status}\uFF08${outcome.reason}\uFF09\uFF0C\u4F1A\u8BDD\u69FD\u5DF2\u91CA\u653E`
|
|
29523
29530
|
);
|
|
29524
29531
|
const settledStatus = outcome.settled ? outcome.status : void 0;
|
|
29525
|
-
if (deps.onTurnSettled && settledStatus
|
|
29532
|
+
if (deps.onTurnSettled && settledStatus) {
|
|
29526
29533
|
await deps.onTurnSettled({
|
|
29527
29534
|
chatSessionId: turn.chatSessionId,
|
|
29528
29535
|
turnId: turn.id,
|
|
@@ -162346,6 +162353,17 @@ var init_planner = __esm({
|
|
|
162346
162353
|
});
|
|
162347
162354
|
|
|
162348
162355
|
// ../server/src/domains/collab/workorders.ts
|
|
162356
|
+
function systemActorFallback(id) {
|
|
162357
|
+
return isSystemActorId(id) ? { name: SYSTEM_ACTOR_DISPLAY_NAME, avatar: SYSTEM_AVATAR_REF } : void 0;
|
|
162358
|
+
}
|
|
162359
|
+
function actorRefFieldsOf(a) {
|
|
162360
|
+
const avatar = a.avatar ?? (a.kind === "system" ? SYSTEM_AVATAR_REF : void 0);
|
|
162361
|
+
return {
|
|
162362
|
+
name: a.name,
|
|
162363
|
+
...a.roles[0] ? { role: a.roles[0] } : {},
|
|
162364
|
+
...avatar ? { avatar } : {}
|
|
162365
|
+
};
|
|
162366
|
+
}
|
|
162349
162367
|
function overviewRootIdOf(arts) {
|
|
162350
162368
|
const roots = arts.filter((a) => a.inputs.length === 0);
|
|
162351
162369
|
if (roots.length <= 1) return roots[0]?.id;
|
|
@@ -162606,6 +162624,7 @@ var init_workorders = __esm({
|
|
|
162606
162624
|
"../server/src/domains/collab/workorders.ts"() {
|
|
162607
162625
|
"use strict";
|
|
162608
162626
|
init_src5();
|
|
162627
|
+
init_src();
|
|
162609
162628
|
init_node_state();
|
|
162610
162629
|
init_planner();
|
|
162611
162630
|
init_workorder_detail();
|
|
@@ -195837,7 +195856,15 @@ var init_service3 = __esm({
|
|
|
195837
195856
|
...companyId ? { companyId } : {},
|
|
195838
195857
|
...snapshot ? { parentConversationSnapshot: snapshot } : {},
|
|
195839
195858
|
extraSystemPrompt: EXPERT_DELEGATION_SYSTEM_PROMPT,
|
|
195840
|
-
..._DelegationService.inboundBundle(inbound) ? { workspaceBundle: _DelegationService.inboundBundle(inbound) } : {}
|
|
195859
|
+
..._DelegationService.inboundBundle(inbound) ? { workspaceBundle: _DelegationService.inboundBundle(inbound) } : {},
|
|
195860
|
+
/* 派发这一侧要拿它们建 `chat_items` 账本(见本文件 `DelegationDispatchRequest` 的注释)。
|
|
195861
|
+
轮次口径与 `bindChildRunToPlaceholder` / `seedChildRoundRows` **逐字一致**:
|
|
195862
|
+
`record.roundSummaries.length + 1`。三处一旦不同源,item 就会挂到上一轮那条回答行上。 */
|
|
195863
|
+
assistantMessageId: childRoundMessageIds(
|
|
195864
|
+
record8.childSessionId,
|
|
195865
|
+
record8.roundSummaries.length + 1
|
|
195866
|
+
).placeholderId,
|
|
195867
|
+
chatTurnId: turnId
|
|
195841
195868
|
});
|
|
195842
195869
|
outcomeSettled = true;
|
|
195843
195870
|
await opts?.onDispatched?.().catch((err) => console.warn(`[delegation] \u5F85\u8F6C\u8FBE\u6807\u8BB0\u5DF2\u6D88\u8D39\u5931\u8D25\uFF08${record8.id}\uFF09: ${String(err)}`));
|
|
@@ -195996,11 +196023,12 @@ var init_service3 = __esm({
|
|
|
195996
196023
|
);
|
|
195997
196024
|
}
|
|
195998
196025
|
}
|
|
195999
|
-
async settleFromSweep(childSessionId, reason, companyId) {
|
|
196026
|
+
async settleFromSweep(childSessionId, reason, companyId, opts) {
|
|
196000
196027
|
const store = await this.options.resolveStore(companyId).catch(() => null);
|
|
196001
196028
|
if (!store) return null;
|
|
196002
196029
|
const record8 = await store.getByChildSession(childSessionId).catch(() => null);
|
|
196003
196030
|
if (!record8 || record8.state !== "running") return record8;
|
|
196031
|
+
if (opts?.outcome === "succeeded") return this.settleSucceededFromSweep(record8, companyId);
|
|
196004
196032
|
const at = this.now();
|
|
196005
196033
|
const settledSeqAtRound = record8.settledSeq + 1;
|
|
196006
196034
|
const newSummary = {
|
|
@@ -196020,6 +196048,58 @@ var init_service3 = __esm({
|
|
|
196020
196048
|
if (settled) await this.notifySettled(settled, companyId);
|
|
196021
196049
|
return settled;
|
|
196022
196050
|
}
|
|
196051
|
+
/**
|
|
196052
|
+
* 清扫拍把这一轮收成 **succeeded** 时的收口(2026-09-10 生产实测的那个洞)。
|
|
196053
|
+
*
|
|
196054
|
+
* 什么时候会走到这里:`settleRound` 是**派发那一刻建的闭包**,serve 一重启它就随老进程消失,
|
|
196055
|
+
* 这一轮改由 `chat-recovery` 重挂、跑完、把 assistant 行写成 done;随后清扫拍按「行已终态」
|
|
196056
|
+
* 把轮次收成 succeeded。此前这一支不外报,于是**没有任何人**去记这一轮、判终态、通知父会话、
|
|
196057
|
+
* 把产物搬回主会话工作区——专家干完了,页面上却永远转圈。
|
|
196058
|
+
* 现场:委派 e6196ab7 第 6 轮 04:02 写完 `outputs/org-collaboration-relationship.md` 并收尾,
|
|
196059
|
+
* 轮次 04:03:30 succeeded,台账仍是 `running`/5 轮、`settled_at` 空。
|
|
196060
|
+
*
|
|
196061
|
+
* 与失败那一支的差别只有三处,其余(追加式记账、`settledSeq`、唯一出口 `notifySettled`)逐字相同:
|
|
196062
|
+
* ① 摘要正文取**子会话这一轮真正的回答**,不是「被时钟闭合」那句;
|
|
196063
|
+
* ② 收成 `done`,不带 `failureKind`,`consecutiveFails` 归零;
|
|
196064
|
+
* ③ 多一道幂等闸,见下。
|
|
196065
|
+
*
|
|
196066
|
+
* **幂等闸**:`roundSummaries.length > dispatchSeq` 就说明这一轮 `settleRound` 已经记过了
|
|
196067
|
+
* (第 N 轮用的是 `dispatchSeq = N-1`),直接收手。没有它,「本进程没重启、`settleRound`
|
|
196068
|
+
* 正在后台跑收尾」与这一拍撞车时会把同一轮记两遍——这正是这一支原先被整个关掉的理由,
|
|
196069
|
+
* 现在用一道显式的闸换掉那个一刀切。
|
|
196070
|
+
*/
|
|
196071
|
+
async settleSucceededFromSweep(record8, companyId) {
|
|
196072
|
+
const store = await this.options.resolveStore(companyId).catch(() => null);
|
|
196073
|
+
if (!store) return record8;
|
|
196074
|
+
const roundsRecorded = record8.roundSummaries.length;
|
|
196075
|
+
const thisRound = (record8.dispatchSeq ?? 0) + 1;
|
|
196076
|
+
if (roundsRecorded >= thisRound) return record8;
|
|
196077
|
+
const at = this.now();
|
|
196078
|
+
const text5 = await this.readChildRoundAnswer(record8, thisRound, companyId);
|
|
196079
|
+
const settledSeqAtRound = record8.settledSeq + 1;
|
|
196080
|
+
const newSummary = {
|
|
196081
|
+
round: (record8.roundSummaries[record8.roundSummaries.length - 1]?.round ?? 0) + 1,
|
|
196082
|
+
text: text5 || "\u8FD9\u4E00\u8F6E\u5DF2\u5B8C\u6210\uFF08\u6536\u5C3E\u65F6\u6B63\u6587\u6CA1\u8BFB\u5230\uFF0C\u4EA7\u7269\u4EE5\u5DE5\u4F5C\u533A\u91CC\u7684\u6587\u4EF6\u4E3A\u51C6\uFF09\u3002",
|
|
196083
|
+
at,
|
|
196084
|
+
settledSeq: settledSeqAtRound
|
|
196085
|
+
};
|
|
196086
|
+
const settled = await store.appendRoundSummary(record8.id, newSummary, {
|
|
196087
|
+
state: "done",
|
|
196088
|
+
consecutiveFails: 0,
|
|
196089
|
+
settledSeq: settledSeqAtRound,
|
|
196090
|
+
settledAt: at
|
|
196091
|
+
}).catch(() => null);
|
|
196092
|
+
if (settled) await this.notifySettled(settled, companyId);
|
|
196093
|
+
return settled;
|
|
196094
|
+
}
|
|
196095
|
+
/** 子会话第 `round` 轮那条回答行的正文(`childRoundMessageIds` 是唯一的 id 口径)。 */
|
|
196096
|
+
async readChildRoundAnswer(record8, round, companyId) {
|
|
196097
|
+
const chatStore = await this.options.resolveChatSessions(companyId).catch(() => null);
|
|
196098
|
+
if (!chatStore?.listMessages) return "";
|
|
196099
|
+
const { placeholderId } = childRoundMessageIds(record8.childSessionId, round);
|
|
196100
|
+
const messages = await chatStore.listMessages(record8.childSessionId).catch(() => []);
|
|
196101
|
+
return (messages.find((m2) => m2.id === placeholderId)?.content ?? "").trim();
|
|
196102
|
+
}
|
|
196023
196103
|
/**
|
|
196024
196104
|
* 队列里还有话没送到专家眼前 → 起下一轮,**把队列内容拼进 message**(§6.2.1 第二条路径)。
|
|
196025
196105
|
*
|
|
@@ -197101,7 +197181,11 @@ function toChatDispatchRequest(request2) {
|
|
|
197101
197181
|
delegatedChildTurn: true,
|
|
197102
197182
|
// §6.1.3 去程:`--file` 带来的字节就在这一格。**丢了它命令照样回 202**,
|
|
197103
197183
|
// 而专家的工作区里什么都没有——这正是上一版真实发生过的形态。
|
|
197104
|
-
...request2.workspaceBundle ? { workspaceBundle: request2.workspaceBundle } : {}
|
|
197184
|
+
...request2.workspaceBundle ? { workspaceBundle: request2.workspaceBundle } : {},
|
|
197185
|
+
// 这两格漏了同样**不报错**:子会话照跑、正文照回,只是 `chat_items` 的行没有 message_id、
|
|
197186
|
+
// turnId 回落成 `chat-run-turn:<runId>`,右栏面板的增量流对不上轮——正是本文件存在的理由。
|
|
197187
|
+
...request2.assistantMessageId ? { assistantMessageId: request2.assistantMessageId } : {},
|
|
197188
|
+
...request2.chatTurnId ? { chatTurnId: request2.chatTurnId } : {}
|
|
197105
197189
|
};
|
|
197106
197190
|
}
|
|
197107
197191
|
function applyWorkspaceBundle(target, bundle) {
|
|
@@ -197321,27 +197405,77 @@ var init_assembly = __esm({
|
|
|
197321
197405
|
});
|
|
197322
197406
|
|
|
197323
197407
|
// ../server/src/domains/delegations/child-live-turn.ts
|
|
197324
|
-
function registerDelegatedChildTurn(liveChat, childSessionId, session) {
|
|
197408
|
+
function registerDelegatedChildTurn(liveChat, childSessionId, session, deps = {}) {
|
|
197409
|
+
const log3 = deps.log ?? ((m2) => console.warn(m2));
|
|
197325
197410
|
const appendInput = session.appendInput;
|
|
197326
|
-
|
|
197411
|
+
const canAppend = typeof appendInput === "function" && session.canAppendInput !== false;
|
|
197412
|
+
const ledger = new ChatItemLedger({
|
|
197413
|
+
...deps.items ? { items: deps.items } : {},
|
|
197414
|
+
sessionId: childSessionId,
|
|
197415
|
+
turnId: deps.turnId ?? fallbackTurnId(session.runId),
|
|
197416
|
+
...session.runId ? { runId: session.runId } : {},
|
|
197417
|
+
...deps.assistantMessageId ? { messageId: deps.assistantMessageId } : {},
|
|
197418
|
+
...deps.versionSeed !== void 0 ? { versionSeed: deps.versionSeed } : {},
|
|
197419
|
+
log: log3
|
|
197420
|
+
});
|
|
197327
197421
|
const ctrl = liveChat.start(childSessionId, {
|
|
197328
197422
|
runtimeSessionId: session.id,
|
|
197329
197423
|
...session.runId ? { runId: session.runId } : {},
|
|
197330
197424
|
kill: () => {
|
|
197331
197425
|
void session.kill?.();
|
|
197332
197426
|
},
|
|
197333
|
-
|
|
197427
|
+
// 纪律 ①:插不进去的 runtime 也登记,只是这两格照实报。
|
|
197428
|
+
...canAppend && appendInput ? { appendInput: (input) => appendInput.call(session, input) } : {},
|
|
197334
197429
|
// **每次现读**,不快照:一轮跑到收尾时 stdin 会先关,那之后 runtime 自己会回
|
|
197335
197430
|
// `session-closing`,判断权本就该留在它那儿(同 `/api/chat` 那条路的写法)。
|
|
197336
197431
|
get canAppendInput() {
|
|
197337
|
-
return session.canAppendInput !== false;
|
|
197432
|
+
return typeof session.appendInput === "function" && session.canAppendInput !== false;
|
|
197433
|
+
}
|
|
197434
|
+
}, { items: ledger });
|
|
197435
|
+
if (deps.assistantMessageId) ctrl.setAssistantMessageId(deps.assistantMessageId);
|
|
197436
|
+
const hasChannels = typeof session.onOutput === "function" || typeof session.onTelemetry === "function" || typeof session.onLiveEvent === "function";
|
|
197437
|
+
const normalized4 = typeof session.onNormalizedProviderEvent === "function" ? {
|
|
197438
|
+
onNormalizedProviderEvent: session.onNormalizedProviderEvent.bind(session),
|
|
197439
|
+
finishTurn: (signal) => session.finishNormalizedTurn?.(signal)
|
|
197440
|
+
} : hasChannels ? attachStreamNormalizer(
|
|
197441
|
+
{
|
|
197442
|
+
id: session.id,
|
|
197443
|
+
onOutput: (cb) => session.onOutput?.(cb),
|
|
197444
|
+
onTelemetry: (cb) => session.onTelemetry?.(cb),
|
|
197445
|
+
onLiveEvent: (cb) => session.onLiveEvent?.(cb),
|
|
197446
|
+
...session.supportsLiveProtocol !== void 0 ? { supportsLiveProtocol: session.supportsLiveProtocol } : {}
|
|
197447
|
+
},
|
|
197448
|
+
{
|
|
197449
|
+
providerName: deps.runtimeKind ?? "runtime",
|
|
197450
|
+
fallbackTurnId: `oasis-turn:${session.runId ?? session.id}`
|
|
197451
|
+
}
|
|
197452
|
+
) : null;
|
|
197453
|
+
normalized4?.onNormalizedProviderEvent((event) => {
|
|
197454
|
+
try {
|
|
197455
|
+
ctrl.applyNormalizedEvent(event);
|
|
197456
|
+
} catch {
|
|
197338
197457
|
}
|
|
197339
197458
|
});
|
|
197340
|
-
|
|
197459
|
+
const settle = async (signal) => {
|
|
197460
|
+
try {
|
|
197461
|
+
normalized4?.finishTurn(signal);
|
|
197462
|
+
} catch {
|
|
197463
|
+
}
|
|
197464
|
+
try {
|
|
197465
|
+
ledger.finish(signal);
|
|
197466
|
+
await ledger.drain();
|
|
197467
|
+
} catch (err) {
|
|
197468
|
+
log3(`[delegation] \u5B50\u4F1A\u8BDD ${childSessionId} \u8D26\u672C\u6536\u5C3E\u5931\u8D25: ${String(err)}`);
|
|
197469
|
+
}
|
|
197470
|
+
ctrl.finish(signal === "completed" ? "done" : "error");
|
|
197471
|
+
};
|
|
197472
|
+
void session.done.then(() => settle("completed"), () => settle("failed"));
|
|
197341
197473
|
}
|
|
197342
197474
|
var init_child_live_turn = __esm({
|
|
197343
197475
|
"../server/src/domains/delegations/child-live-turn.ts"() {
|
|
197344
197476
|
"use strict";
|
|
197477
|
+
init_src6();
|
|
197478
|
+
init_chat_item_ledger();
|
|
197345
197479
|
}
|
|
197346
197480
|
});
|
|
197347
197481
|
|
|
@@ -197455,10 +197589,12 @@ var init_tool_home = __esm({
|
|
|
197455
197589
|
});
|
|
197456
197590
|
|
|
197457
197591
|
// ../connectors/src/_base/install.ts
|
|
197458
|
-
function installPlan(cmd, platform2, toolsPrefix) {
|
|
197459
|
-
|
|
197592
|
+
function installPlan(cmd, platform2, toolsPrefix, version2) {
|
|
197593
|
+
const npmPkg = NPM_TOOL_PACKAGES[cmd];
|
|
197594
|
+
if (npmPkg) {
|
|
197460
197595
|
const npm = platform2 === "win32" ? "npm.cmd" : "npm";
|
|
197461
|
-
|
|
197596
|
+
const spec = version2 ? `${npmPkg}@${version2}` : npmPkg;
|
|
197597
|
+
return [{ file: npm, args: ["install", "-g", "--prefix", toolsPrefix, spec], ensureDir: toolsPrefix }];
|
|
197462
197598
|
}
|
|
197463
197599
|
const pkg = cmd === "gh" ? { brew: "gh", apt: "gh", dnf: "gh", pacman: "github-cli", apk: "github-cli", winget: "GitHub.cli", choco: "gh", scoop: "gh" } : { brew: "git", apt: "git", dnf: "git", pacman: "git", apk: "git", winget: "Git.Git", choco: "git", scoop: "git" };
|
|
197464
197600
|
if (platform2 === "darwin") {
|
|
@@ -197503,17 +197639,54 @@ function defaultDeps() {
|
|
|
197503
197639
|
mkdirp: (dir) => {
|
|
197504
197640
|
(0, import_node_fs9.mkdirSync)(dir, { recursive: true });
|
|
197505
197641
|
},
|
|
197506
|
-
log: (msg) => console.warn(msg)
|
|
197642
|
+
log: (msg) => console.warn(msg),
|
|
197643
|
+
installedVersion: async (pkg, prefix) => readInstalledVersion(pkg, prefix)
|
|
197507
197644
|
};
|
|
197508
197645
|
}
|
|
197509
|
-
|
|
197646
|
+
function readInstalledVersion(pkg, prefix) {
|
|
197647
|
+
const parts = pkg.split("/");
|
|
197648
|
+
for (const mid of [["lib", "node_modules"], ["node_modules"]]) {
|
|
197649
|
+
const file = (0, import_node_path11.join)(prefix, ...mid, ...parts, "package.json");
|
|
197650
|
+
if (!(0, import_node_fs9.existsSync)(file)) continue;
|
|
197651
|
+
try {
|
|
197652
|
+
const v2 = JSON.parse((0, import_node_fs9.readFileSync)(file, "utf8")).version;
|
|
197653
|
+
if (typeof v2 === "string" && v2) return v2;
|
|
197654
|
+
} catch {
|
|
197655
|
+
}
|
|
197656
|
+
}
|
|
197657
|
+
return null;
|
|
197658
|
+
}
|
|
197659
|
+
async function alignToWantedVersion(cmd, wanted, d) {
|
|
197660
|
+
if (alignedVersion.get(cmd) === wanted) return;
|
|
197661
|
+
const pkg = NPM_TOOL_PACKAGES[cmd];
|
|
197662
|
+
if (!pkg) return;
|
|
197663
|
+
const installed = await d.installedVersion(pkg, d.toolsPrefix);
|
|
197664
|
+
if (!installed) return;
|
|
197665
|
+
if (installed === wanted) {
|
|
197666
|
+
alignedVersion.set(cmd, wanted);
|
|
197667
|
+
return;
|
|
197668
|
+
}
|
|
197669
|
+
const npm = d.platform === "win32" ? "npm.cmd" : "npm";
|
|
197670
|
+
d.log(`[connector-install] ${cmd} ${installed} \u2192 ${wanted}\uFF08\u670D\u52A1\u7AEF\u767B\u8BB0\u7248\u672C\uFF09\uFF0C\u5B89\u88C5\u4E2D\u2026`);
|
|
197671
|
+
try {
|
|
197672
|
+
d.mkdirp(d.toolsPrefix);
|
|
197673
|
+
await d.run(npm, ["install", "-g", "--prefix", d.toolsPrefix, `${pkg}@${wanted}`]);
|
|
197674
|
+
alignedVersion.set(cmd, wanted);
|
|
197675
|
+
d.log(`[connector-install] ${cmd} \u5DF2\u5BF9\u9F50\u5230 ${wanted}`);
|
|
197676
|
+
} catch (err) {
|
|
197677
|
+
d.log(`[connector-install] ${cmd} \u5BF9\u9F50\u5230 ${wanted} \u5931\u8D25\uFF0C\u7EE7\u7EED\u7528 ${installed}\uFF1A${String(err)}`);
|
|
197678
|
+
}
|
|
197679
|
+
}
|
|
197680
|
+
async function ensureToolInstalled(cmd, opts = {}) {
|
|
197681
|
+
const { versions, ...deps } = opts;
|
|
197510
197682
|
const d = { ...defaultDeps(), ...deps };
|
|
197511
|
-
|
|
197512
|
-
if (await d.isPresent(cmd)) {
|
|
197683
|
+
const wanted = versions?.[cmd];
|
|
197684
|
+
if (confirmed.has(cmd) || await d.isPresent(cmd)) {
|
|
197513
197685
|
confirmed.add(cmd);
|
|
197686
|
+
if (wanted) await alignToWantedVersion(cmd, wanted, d);
|
|
197514
197687
|
return true;
|
|
197515
197688
|
}
|
|
197516
|
-
const steps = installPlan(cmd, d.platform, d.toolsPrefix);
|
|
197689
|
+
const steps = installPlan(cmd, d.platform, d.toolsPrefix, wanted);
|
|
197517
197690
|
if (steps.length === 0) {
|
|
197518
197691
|
d.log(`[connector-install] ${cmd} \u7F3A\u5931\uFF0C\u4E14 ${d.platform} \u4E0B\u65E0\u5DF2\u77E5\u81EA\u52A8\u5B89\u88C5\u6CD5\u2014\u2014\u8BF7\u624B\u52A8\u5B89\u88C5`);
|
|
197519
197692
|
return false;
|
|
@@ -197526,6 +197699,7 @@ async function ensureToolInstalled(cmd, deps = {}) {
|
|
|
197526
197699
|
await d.run(step.file, step.args);
|
|
197527
197700
|
if (await d.isPresent(cmd)) {
|
|
197528
197701
|
confirmed.add(cmd);
|
|
197702
|
+
if (wanted) alignedVersion.set(cmd, wanted);
|
|
197529
197703
|
d.log(`[connector-install] ${cmd} \u5B89\u88C5\u6210\u529F\uFF08${step.file} ${step.args.join(" ")}\uFF09`);
|
|
197530
197704
|
return true;
|
|
197531
197705
|
}
|
|
@@ -197536,15 +197710,15 @@ async function ensureToolInstalled(cmd, deps = {}) {
|
|
|
197536
197710
|
d.log(`[connector-install] ${cmd} \u81EA\u52A8\u5B89\u88C5\u672A\u6210\u529F\u2014\u2014\u5C06\u56DE\u9000\u5230 wrapper/\u547D\u4EE4\u81EA\u8EAB\u62A5\u9519`);
|
|
197537
197711
|
return false;
|
|
197538
197712
|
}
|
|
197539
|
-
async function ensureConnectorTools(tools,
|
|
197713
|
+
async function ensureConnectorTools(tools, opts = {}) {
|
|
197540
197714
|
if (!tools || tools.length === 0) return [];
|
|
197541
197715
|
const missing = [];
|
|
197542
197716
|
for (const cmd of tools) {
|
|
197543
|
-
if (!await ensureToolInstalled(cmd,
|
|
197717
|
+
if (!await ensureToolInstalled(cmd, opts)) missing.push(cmd);
|
|
197544
197718
|
}
|
|
197545
197719
|
return missing;
|
|
197546
197720
|
}
|
|
197547
|
-
var import_node_child_process12, import_node_util2, import_node_fs9, import_node_path11, execFileAsync, confirmed;
|
|
197721
|
+
var import_node_child_process12, import_node_util2, import_node_fs9, import_node_path11, execFileAsync, NPM_TOOL_PACKAGES, confirmed, alignedVersion;
|
|
197548
197722
|
var init_install = __esm({
|
|
197549
197723
|
"../connectors/src/_base/install.ts"() {
|
|
197550
197724
|
"use strict";
|
|
@@ -197554,7 +197728,9 @@ var init_install = __esm({
|
|
|
197554
197728
|
import_node_path11 = require("node:path");
|
|
197555
197729
|
init_tool_home();
|
|
197556
197730
|
execFileAsync = (0, import_node_util2.promisify)(import_node_child_process12.execFile);
|
|
197731
|
+
NPM_TOOL_PACKAGES = { "lark-cli": "@larksuite/cli" };
|
|
197557
197732
|
confirmed = /* @__PURE__ */ new Set();
|
|
197733
|
+
alignedVersion = /* @__PURE__ */ new Map();
|
|
197558
197734
|
}
|
|
197559
197735
|
});
|
|
197560
197736
|
|
|
@@ -201625,7 +201801,7 @@ var init_connector_adapter = __esm({
|
|
|
201625
201801
|
async spawn(job) {
|
|
201626
201802
|
const t0 = Date.now();
|
|
201627
201803
|
if (job.requiredTools?.length) {
|
|
201628
|
-
const missing = await ensureConnectorTools(job.requiredTools);
|
|
201804
|
+
const missing = await ensureConnectorTools(job.requiredTools, { versions: job.requiredToolVersions });
|
|
201629
201805
|
if (missing.length) log("[adapter]", ` connector tools still missing (agent may fail): ${missing.join(", ")}`);
|
|
201630
201806
|
}
|
|
201631
201807
|
const prepared = await prepareConnectorsForJob(job);
|
|
@@ -201746,7 +201922,7 @@ async function draftActorResolver(registry2) {
|
|
|
201746
201922
|
const byId = new Map(actors.map((a) => [a.id, a]));
|
|
201747
201923
|
return (id) => {
|
|
201748
201924
|
const a = byId.get(id);
|
|
201749
|
-
return a ?
|
|
201925
|
+
return a ? actorRefFieldsOf(a) : systemActorFallback(id);
|
|
201750
201926
|
};
|
|
201751
201927
|
}
|
|
201752
201928
|
async function draftRoleStaffingResolver(registry2) {
|
|
@@ -203289,13 +203465,22 @@ async function startOasisServer(opts) {
|
|
|
203289
203465
|
resolveStore: opts.delegationStoreFor,
|
|
203290
203466
|
resolveChatSessions: resolveChatSessionsForDelegation,
|
|
203291
203467
|
resolveActors: async (companyId) => (await actorsDomain2.resolveCtx(companyId)).service,
|
|
203292
|
-
|
|
203293
|
-
|
|
203294
|
-
|
|
203295
|
-
|
|
203468
|
+
/* **派发完顺手把子会话这一轮登记进 live 注册表,并给它接上 `chat_items` 账本。**
|
|
203469
|
+
两件事的成因不同,都在 `child-live-turn.ts` 的文件头:
|
|
203470
|
+
· 不登记 → 下面那行 `appendToChild` 恒回 `no-live-turn`,每一条 `--follow-up` 转达
|
|
203471
|
+
都落队列,专家要等本轮跑完才看见「手上这段作废」(v2 bug 0088);
|
|
203472
|
+
· 不接账本 → 子会话在 `chat_items` 里只有 storage 层镜像来的一问一答两行纯文字,
|
|
203473
|
+
右栏面板只能靠详情接口拿 run_id 去轨迹表**现折**,跑的过程中一片空白。 */
|
|
203296
203474
|
dispatchChat: async (request2) => {
|
|
203297
203475
|
const session = await dispatchChat(request2);
|
|
203298
|
-
|
|
203476
|
+
const itemStore = opts.resolveChatItems ? await opts.resolveChatItems(request2.companyId).catch(() => void 0) : opts.chatItems;
|
|
203477
|
+
const versionSeed = itemStore ? await itemStore.sessionVersionCursor(request2.chatSessionId).catch(() => 0) : 0;
|
|
203478
|
+
registerDelegatedChildTurn(liveChat, request2.chatSessionId, session, {
|
|
203479
|
+
...itemStore ? { items: itemStore } : {},
|
|
203480
|
+
...request2.chatTurnId ? { turnId: request2.chatTurnId } : {},
|
|
203481
|
+
...request2.assistantMessageId ? { assistantMessageId: request2.assistantMessageId } : {},
|
|
203482
|
+
versionSeed
|
|
203483
|
+
});
|
|
203299
203484
|
return session;
|
|
203300
203485
|
},
|
|
203301
203486
|
appendToChild: (childSessionId, text5, extra) => liveChat.append(childSessionId, text5, extra),
|
|
@@ -204070,6 +204255,7 @@ async function startOasisServer(opts) {
|
|
|
204070
204255
|
const rawBody = Buffer.concat(chunks).toString("utf8");
|
|
204071
204256
|
const companyCtx = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname) : void 0;
|
|
204072
204257
|
const currentCompanyId = companyCtx?.kind === "ok" ? companyCtx.companyId : void 0;
|
|
204258
|
+
const connectorActorsService = async (companyId) => opts.actors ? (await opts.actors.resolveCtx(companyId ?? currentCompanyId)).service : void 0;
|
|
204073
204259
|
const wodrafts = opts.resolveWorkorderDrafts ? await opts.resolveWorkorderDrafts(currentCompanyId) : opts.workorderDrafts;
|
|
204074
204260
|
const wodraftPlannerIssues = (opts.resolveWorkorderDraftPlannerIssues && await opts.resolveWorkorderDraftPlannerIssues(currentCompanyId)) ?? opts.workorderDraftPlannerIssues ?? defaultDraftPlannerIssuesStore;
|
|
204075
204261
|
const engine = await resolveEngine(currentCompanyId);
|
|
@@ -206133,12 +206319,12 @@ ${composed}`;
|
|
|
206133
206319
|
const actorCtx = await opts.resolveActorContext(body2.actorId).catch(() => null);
|
|
206134
206320
|
if (actorCtx) {
|
|
206135
206321
|
const { mkdtempSync: mkdtempSync6, mkdirSync: mkdirSync25, writeFileSync: writeFileSync18 } = await import("node:fs");
|
|
206136
|
-
const { join:
|
|
206322
|
+
const { join: join40, dirname: dirname36 } = await import("node:path");
|
|
206137
206323
|
const { tmpdir: tmpdir12 } = await import("node:os");
|
|
206138
|
-
const dir = mkdtempSync6(
|
|
206324
|
+
const dir = mkdtempSync6(join40(tmpdir12(), "oasis-chat-"));
|
|
206139
206325
|
if (actorCtx.config?.prompt) {
|
|
206140
206326
|
for (const [rel, content3] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
|
|
206141
|
-
const file =
|
|
206327
|
+
const file = join40(dir, rel);
|
|
206142
206328
|
mkdirSync25(dirname36(file), { recursive: true });
|
|
206143
206329
|
writeFileSync18(file, content3);
|
|
206144
206330
|
}
|
|
@@ -206150,12 +206336,12 @@ ${composed}`;
|
|
|
206150
206336
|
const s2 = byId.get(id);
|
|
206151
206337
|
return s2 ? `- **${s2.name}** (\`${s2.id}\`): ${s2.description}` : `- \`${id}\`\uFF08\u672A\u5728\u6280\u80FD\u5E93\u4E2D\uFF0C\u53EF\u80FD\u5DF2\u5378\u8F7D\uFF09`;
|
|
206152
206338
|
});
|
|
206153
|
-
writeFileSync18(
|
|
206339
|
+
writeFileSync18(join40(dir, "SKILLS.md"), ["# \u53EF\u7528\u6280\u80FD", "", "\u4EE5\u4E0B\u6280\u80FD\u5DF2\u4E3A\u4F60\u542F\u7528\uFF0C\u53EF\u5728\u672C\u6B21\u4F1A\u8BDD\u4E2D\u76F4\u63A5\u4F7F\u7528\uFF1A", "", ...lines].join("\n"));
|
|
206154
206340
|
}
|
|
206155
206341
|
if (opts.materializeSkills) {
|
|
206156
206342
|
const skillFiles = await opts.materializeSkills(body2.actorId, "claude").catch(() => ({}));
|
|
206157
206343
|
for (const [rel, content3] of Object.entries(skillFiles)) {
|
|
206158
|
-
const file =
|
|
206344
|
+
const file = join40(dir, rel);
|
|
206159
206345
|
mkdirSync25(dirname36(file), { recursive: true });
|
|
206160
206346
|
writeFileSync18(file, content3);
|
|
206161
206347
|
}
|
|
@@ -206169,7 +206355,7 @@ ${composed}`;
|
|
|
206169
206355
|
const modeNote = c.mode === "oauth" ? "OAuth \xB7 \u51ED\u8BC1\u7531\u5E73\u53F0\u7BA1\u7406\uFF0C\u901A\u8FC7\u5BF9\u5E94 CLI wrapper \u8C03\u7528" : "\u76F4\u63A5\u5199\u5165 \xB7 \u51ED\u8BC1\u5DF2\u6CE8\u5165\u73AF\u5883\u53D8\u91CF";
|
|
206170
206356
|
return `- **${c.name}** (\`${c.id}\`): ${statusNote} \xB7 ${modeNote}`;
|
|
206171
206357
|
});
|
|
206172
|
-
writeFileSync18(
|
|
206358
|
+
writeFileSync18(join40(dir, "CONNECTORS.md"), ["# \u53EF\u7528\u8FDE\u63A5\u5668", "", "\u4EE5\u4E0B\u8FDE\u63A5\u5668\u5DF2\u4E3A\u672C\u6B21\u4F1A\u8BDD\u914D\u7F6E\uFF0C\u51ED\u8BC1\u5DF2\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 CLI wrapper \u6CE8\u5165\uFF0C\u65E0\u9700\u624B\u52A8\u914D\u7F6E\uFF1A", "", ...lines].join("\n"));
|
|
206173
206359
|
}
|
|
206174
206360
|
spawnCwd = dir;
|
|
206175
206361
|
}
|
|
@@ -206254,7 +206440,7 @@ ${composed}`;
|
|
|
206254
206440
|
}
|
|
206255
206441
|
if (req.method === "POST" && /^\/api\/connectors\/[^/]+\/disconnect$/.test(url.pathname)) {
|
|
206256
206442
|
const connId = decodeURIComponent(url.pathname.split("/")[3] ?? "");
|
|
206257
|
-
const svc =
|
|
206443
|
+
const svc = await connectorActorsService();
|
|
206258
206444
|
if (!svc) {
|
|
206259
206445
|
res.writeHead(501).end(JSON.stringify({ error: "actors service disabled" }));
|
|
206260
206446
|
return;
|
|
@@ -206280,7 +206466,7 @@ ${composed}`;
|
|
|
206280
206466
|
}
|
|
206281
206467
|
if (req.method === "DELETE" && /^\/api\/connectors\/[^/]+$/.test(url.pathname)) {
|
|
206282
206468
|
const connId = decodeURIComponent(url.pathname.slice("/api/connectors/".length));
|
|
206283
|
-
const svc =
|
|
206469
|
+
const svc = await connectorActorsService();
|
|
206284
206470
|
if (!svc) {
|
|
206285
206471
|
res.writeHead(501).end(JSON.stringify({ error: "actors service disabled" }));
|
|
206286
206472
|
return;
|
|
@@ -206299,6 +206485,31 @@ ${composed}`;
|
|
|
206299
206485
|
}
|
|
206300
206486
|
return;
|
|
206301
206487
|
}
|
|
206488
|
+
if (req.method === "DELETE" && /^\/api\/actors\/[^/]+\/connectors\/[^/]+$/.test(url.pathname)) {
|
|
206489
|
+
const parts = url.pathname.split("/");
|
|
206490
|
+
const actorId = decodeURIComponent(parts[3] ?? "");
|
|
206491
|
+
const connId = decodeURIComponent(parts[5] ?? "");
|
|
206492
|
+
const svc = await connectorActorsService();
|
|
206493
|
+
if (!svc) {
|
|
206494
|
+
res.writeHead(501).end(JSON.stringify({ error: "actors service disabled" }));
|
|
206495
|
+
return;
|
|
206496
|
+
}
|
|
206497
|
+
try {
|
|
206498
|
+
const { variablesDeleted } = await svc.deleteActorConnector(actorId, connId);
|
|
206499
|
+
let channelDisabled = false;
|
|
206500
|
+
if (connId === "feishu" && channelService) {
|
|
206501
|
+
const b2 = await channelService.getBindingForActor(actorId);
|
|
206502
|
+
if (b2 && b2.status !== "revoked") {
|
|
206503
|
+
await channelService.disable(actorId);
|
|
206504
|
+
channelDisabled = true;
|
|
206505
|
+
}
|
|
206506
|
+
}
|
|
206507
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true, variablesDeleted, channelDisabled }));
|
|
206508
|
+
} catch (e) {
|
|
206509
|
+
res.writeHead(500).end(JSON.stringify({ error: String(e) }));
|
|
206510
|
+
}
|
|
206511
|
+
return;
|
|
206512
|
+
}
|
|
206302
206513
|
if (url.pathname === "/api/connectors/feishu/setup" && req.method === "GET") {
|
|
206303
206514
|
res.writeHead(200, { "content-type": "text/event-stream", "cache-control": "no-cache", connection: "keep-alive" });
|
|
206304
206515
|
const send = (obj2) => res.write(`data: ${JSON.stringify(obj2)}
|
|
@@ -206348,8 +206559,8 @@ ${composed}`;
|
|
|
206348
206559
|
if (!errStr && pollData["client_id"]) {
|
|
206349
206560
|
const clientId = String(pollData["client_id"]);
|
|
206350
206561
|
const clientSecret = pollData["client_secret"] ? String(pollData["client_secret"]) : void 0;
|
|
206351
|
-
|
|
206352
|
-
|
|
206562
|
+
const svc = clientSecret ? await connectorActorsService() : void 0;
|
|
206563
|
+
if (svc && clientSecret) {
|
|
206353
206564
|
const credScope = actorIdParam ? { scope: "personal", actorId: actorIdParam } : { scope: "global" };
|
|
206354
206565
|
await svc.putVariable({ key: "FEISHU_APP_ID", value: clientId, ...credScope, connectorId: "feishu", encrypted: true });
|
|
206355
206566
|
await svc.putVariable({ key: "FEISHU_APP_SECRET", value: clientSecret, ...credScope, connectorId: "feishu", encrypted: true });
|
|
@@ -206412,6 +206623,8 @@ ${composed}`;
|
|
|
206412
206623
|
});
|
|
206413
206624
|
githubAppPending.put(state, {
|
|
206414
206625
|
...actorId ? { actorId } : {},
|
|
206626
|
+
// 回调那一步没有鉴权头,解析不出公司——只能在这里记下来带过去。
|
|
206627
|
+
...currentCompanyId ? { companyId: currentCompanyId } : {},
|
|
206415
206628
|
employeeSlug: nameSlug,
|
|
206416
206629
|
createdAtMs: Date.now(),
|
|
206417
206630
|
// 存下这次选的归属——回调时要拿它跟 GitHub 返回的 owner 比对。
|
|
@@ -206432,7 +206645,7 @@ ${composed}`;
|
|
|
206432
206645
|
if (url.pathname === "/api/connectors/github/app/orgs" && req.method === "POST") {
|
|
206433
206646
|
try {
|
|
206434
206647
|
const { actorId } = JSON.parse(rawBody || "{}");
|
|
206435
|
-
const svc =
|
|
206648
|
+
const svc = await connectorActorsService();
|
|
206436
206649
|
if (!svc) throw new Error("actors service unavailable");
|
|
206437
206650
|
const token = await svc.revealResolvedVariable("GITHUB_TOKEN", actorId);
|
|
206438
206651
|
if (!token) {
|
|
@@ -206465,7 +206678,7 @@ ${composed}`;
|
|
|
206465
206678
|
}
|
|
206466
206679
|
if (url.pathname === "/api/connectors/github/app/available" && req.method === "POST") {
|
|
206467
206680
|
try {
|
|
206468
|
-
const svc =
|
|
206681
|
+
const svc = await connectorActorsService();
|
|
206469
206682
|
if (!svc) throw new Error("actors service unavailable");
|
|
206470
206683
|
const rows = await svc.listVariables();
|
|
206471
206684
|
const plain = (key, actorId) => rows.find((r) => r.key === key && r.actorId === actorId && !r.encrypted)?.maskedValue ?? "";
|
|
@@ -206528,7 +206741,7 @@ ${composed}`;
|
|
|
206528
206741
|
res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: "\u7F3A\u5C11 appId" }));
|
|
206529
206742
|
return;
|
|
206530
206743
|
}
|
|
206531
|
-
const svc =
|
|
206744
|
+
const svc = await connectorActorsService();
|
|
206532
206745
|
if (!svc) throw new Error("actors service unavailable");
|
|
206533
206746
|
const rows = await svc.listVariables();
|
|
206534
206747
|
const owners = rows.filter((r) => r.key === "GITHUB_APP_ID" && !r.encrypted && r.maskedValue === appId);
|
|
@@ -206575,7 +206788,7 @@ ${composed}`;
|
|
|
206575
206788
|
bad(400, "\u8FD9\u4E0D\u50CF\u4E00\u4E2A\u79C1\u94A5\u6587\u4EF6\u2014\u2014\u8BF7\u4E0A\u4F20 GitHub \u4E0B\u8F7D\u7684 .pem\uFF08\u5185\u5BB9\u4EE5 -----BEGIN ... PRIVATE KEY----- \u5F00\u5934\uFF09");
|
|
206576
206789
|
return;
|
|
206577
206790
|
}
|
|
206578
|
-
const svc =
|
|
206791
|
+
const svc = await connectorActorsService();
|
|
206579
206792
|
if (!svc) throw new Error("actors service unavailable");
|
|
206580
206793
|
let meta;
|
|
206581
206794
|
try {
|
|
@@ -206633,7 +206846,7 @@ ${composed}`;
|
|
|
206633
206846
|
if (url.pathname === "/api/connectors/github/app/permissions" && req.method === "POST") {
|
|
206634
206847
|
try {
|
|
206635
206848
|
const { actorId } = JSON.parse(rawBody || "{}");
|
|
206636
|
-
const svc =
|
|
206849
|
+
const svc = await connectorActorsService();
|
|
206637
206850
|
if (!svc) throw new Error("actors service unavailable");
|
|
206638
206851
|
const appId = await svc.revealResolvedVariable("GITHUB_APP_ID", actorId);
|
|
206639
206852
|
const privateKeyPem = await svc.revealResolvedVariable("GITHUB_APP_PRIVATE_KEY", actorId);
|
|
@@ -206687,7 +206900,7 @@ ${composed}`;
|
|
|
206687
206900
|
fail(problem.message);
|
|
206688
206901
|
return;
|
|
206689
206902
|
}
|
|
206690
|
-
const svc =
|
|
206903
|
+
const svc = await connectorActorsService(pending.companyId);
|
|
206691
206904
|
if (!svc) throw new Error("actors service unavailable");
|
|
206692
206905
|
const scope = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
|
|
206693
206906
|
const put3 = (key, value2, encrypted) => svc.putVariable({ key, value: value2, ...scope, connectorId: "github", encrypted });
|
|
@@ -206756,7 +206969,7 @@ ${composed}`;
|
|
|
206756
206969
|
reply({ ok: false, error: "pending" });
|
|
206757
206970
|
return;
|
|
206758
206971
|
}
|
|
206759
|
-
const svc =
|
|
206972
|
+
const svc = await connectorActorsService();
|
|
206760
206973
|
if (!svc) throw new Error("actors service unavailable");
|
|
206761
206974
|
const scope = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
|
|
206762
206975
|
const put3 = (key, value2, encrypted) => svc.putVariable({ key, value: value2, ...scope, connectorId: "github", encrypted });
|
|
@@ -206845,8 +207058,8 @@ ${composed}`;
|
|
|
206845
207058
|
throw new Error(String(data["error_description"] ?? errStr ?? "login failed"));
|
|
206846
207059
|
}
|
|
206847
207060
|
if (!data["access_token"]) throw new Error("no access_token in response");
|
|
206848
|
-
|
|
206849
|
-
|
|
207061
|
+
const svc = await connectorActorsService();
|
|
207062
|
+
if (svc) {
|
|
206850
207063
|
if (actorId) {
|
|
206851
207064
|
await svc.putVariable({ key: "FEISHU_APP_ID", value: appId, scope: "personal", actorId, connectorId: "feishu", encrypted: true });
|
|
206852
207065
|
} else {
|
|
@@ -206936,7 +207149,16 @@ ${composed}`;
|
|
|
206936
207149
|
body: JSON.stringify({ client_id: GH_CLIENT_ID, scope: "repo,read:user,read:org" })
|
|
206937
207150
|
});
|
|
206938
207151
|
const d = await dr.json();
|
|
206939
|
-
|
|
207152
|
+
const verifyUrl = (() => {
|
|
207153
|
+
try {
|
|
207154
|
+
const u = new URL(d.verification_uri);
|
|
207155
|
+
u.searchParams.set("user_code", d.user_code);
|
|
207156
|
+
return u.toString();
|
|
207157
|
+
} catch {
|
|
207158
|
+
return d.verification_uri;
|
|
207159
|
+
}
|
|
207160
|
+
})();
|
|
207161
|
+
send({ type: "code", code: d.user_code, url: verifyUrl });
|
|
206940
207162
|
const deadline = Date.now() + d.expires_in * 1e3;
|
|
206941
207163
|
while (!closed && Date.now() < deadline) {
|
|
206942
207164
|
await new Promise((r) => setTimeout(r, d.interval * 1e3));
|
|
@@ -206947,8 +207169,8 @@ ${composed}`;
|
|
|
206947
207169
|
});
|
|
206948
207170
|
const p2 = await pr.json();
|
|
206949
207171
|
if (p2.access_token) {
|
|
206950
|
-
|
|
206951
|
-
|
|
207172
|
+
const svc = await connectorActorsService();
|
|
207173
|
+
if (svc) {
|
|
206952
207174
|
const connId = "github";
|
|
206953
207175
|
await svc.upsertConnector({ id: connId, name: "GitHub", mode: "oauth", status: "connected", account: "github" });
|
|
206954
207176
|
for (const [k2, v2] of [["GIT_AUTHOR_NAME", actorNameParam], ["GIT_AUTHOR_EMAIL", ""], ["GIT_COMMITTER_NAME", actorNameParam], ["GIT_COMMITTER_EMAIL", ""], ["EMAIL", ""]])
|
|
@@ -207051,7 +207273,7 @@ ${composed}`;
|
|
|
207051
207273
|
* **接进既有那一拍,不新写一套扫描**——新写的那套迟早和既有判据漂移。
|
|
207052
207274
|
* 委派域没装配时返回 null,调用方照常。
|
|
207053
207275
|
*/
|
|
207054
|
-
settleDelegationFromSweep: (childSessionId, reason, companyId) => delegationService?.settleFromSweep(childSessionId, reason, companyId) ?? Promise.resolve(null),
|
|
207276
|
+
settleDelegationFromSweep: (childSessionId, reason, companyId, opts2) => delegationService?.settleFromSweep(childSessionId, reason, companyId, opts2) ?? Promise.resolve(null),
|
|
207055
207277
|
close: async () => {
|
|
207056
207278
|
if (broadcastTimer) clearInterval(broadcastTimer);
|
|
207057
207279
|
if (pendingSystemNoticesRecoveryTimer) clearInterval(pendingSystemNoticesRecoveryTimer);
|
|
@@ -218233,9 +218455,32 @@ var init_service5 = __esm({
|
|
|
218233
218455
|
const a = await this.opts.store.getActor(id);
|
|
218234
218456
|
if (!a) throw new Error(`actor not found: ${id}`);
|
|
218235
218457
|
await this.upsertActor({ ...a, status: "disabled" }, by);
|
|
218458
|
+
await this.dropRuntimeBindingOfDeletedAgent(a.id, a.kind, by);
|
|
218236
218459
|
if (a.status === "active") await this.opts.onActorDisabled?.(id, by);
|
|
218237
218460
|
return a;
|
|
218238
218461
|
}
|
|
218462
|
+
/**
|
|
218463
|
+
* 删掉 Agent 时把它跟 runtime 的绑定一起撤掉。
|
|
218464
|
+
*
|
|
218465
|
+
* 为什么必须做(2026-09-09 线上实测):删除只写 `status='disabled'`,`actor_bindings` 那行
|
|
218466
|
+
* 原样留着且仍是 `active`。而 `GET /api/actors` 会把已删 Agent 过滤掉、`GET /api/bindings` 不会——
|
|
218467
|
+
* 运行时管理页拿两份数据对着算「运行 Agent」,于是已删的 Agent 继续占着一格,
|
|
218468
|
+
* 名字还查不回来,页面上直接露出 `asst-xxx-cbf34f` 这种裸 id。didi 组织实测:yx_claude 上
|
|
218469
|
+
* 12 条 active 绑定里 7 条的 Agent 早被删了(其中 5 条是助理)。
|
|
218470
|
+
*
|
|
218471
|
+
* 顺带修好另一处:`pickAssistantRuntime` 用「(nodeId,kind) 上的 active 绑定数」当负载做均衡,
|
|
218472
|
+
* 已删 Agent 的残留绑定会把负载算高,把新助理往别的机器上赶。
|
|
218473
|
+
*
|
|
218474
|
+
* 只对 agent 生效:真人被移出组织是「离岗」不是删除,PRD 明确其助理照常在岗、账号回来还能接上。
|
|
218475
|
+
* 幂等:removeBinding 对没有绑定的 actor 是 no-op,所以重复删也安全(存量脏数据也能靠再删一次修好)。
|
|
218476
|
+
*/
|
|
218477
|
+
async dropRuntimeBindingOfDeletedAgent(id, kind, by) {
|
|
218478
|
+
if (kind !== "agent") return;
|
|
218479
|
+
const existing = await this.opts.store.getBinding(id);
|
|
218480
|
+
if (!existing) return;
|
|
218481
|
+
await this.opts.store.removeBinding(id);
|
|
218482
|
+
await this.audit({ kind: "binding_change", actorId: id, by, at: this.now(), detail: { removed: true, reason: "agent_deleted" } });
|
|
218483
|
+
}
|
|
218239
218484
|
/**
|
|
218240
218485
|
* 原子「若当前 active 则停用」(QA R10):与 disableActor 的区别在于——
|
|
218241
218486
|
* 只在 actor 当前**确为 active** 时才写,返回 `ok:true + before + seq`;已被并发者/别的路径先 disable
|
|
@@ -218259,6 +218504,7 @@ var init_service5 = __esm({
|
|
|
218259
218504
|
if (!res.ok) return res;
|
|
218260
218505
|
this.opts.onRolesChanged?.(id, []);
|
|
218261
218506
|
await this.audit({ kind: "actor_upsert", actorId: id, by, at: this.now(), detail: { status: "disabled", roles: res.before.roles } });
|
|
218507
|
+
await this.dropRuntimeBindingOfDeletedAgent(id, res.before.kind, by);
|
|
218262
218508
|
await this.opts.onActorDisabled?.(id, by);
|
|
218263
218509
|
return { ok: true, before: res.before, seq };
|
|
218264
218510
|
}
|
|
@@ -218859,39 +219105,42 @@ ${input.description}
|
|
|
218859
219105
|
const c = cfg ?? await this.opts.store.latestConfig(actorId);
|
|
218860
219106
|
return new Set(c?.connectorIds ?? []);
|
|
218861
219107
|
}
|
|
218862
|
-
/**
|
|
218863
|
-
|
|
218864
|
-
|
|
219108
|
+
/**
|
|
219109
|
+
* 设置某员工×连接器的连接记录(启用/停用)。无则创建,有则翻转 enabled。
|
|
219110
|
+
*
|
|
219111
|
+
* `configuredBy` 只在**授权流程走完**时传(「谁为这名员工把它接上的」)。普通开关不传,
|
|
219112
|
+
* 此时把已有值原样带回——**只增不抹**:翻一次开关不该把授权时记下的人擦掉。
|
|
219113
|
+
* pg 侧另有 `COALESCE` 兜同一条,两层都做是因为内存 store 是整行替换。
|
|
219114
|
+
*/
|
|
219115
|
+
async setActorConnectorEnabled(actorId, connectorId, enabled, configuredBy) {
|
|
219116
|
+
const keep = configuredBy ?? (await this.opts.store.listActorConnectorConnections(actorId)).find((c) => c.connectorId === connectorId)?.configuredBy;
|
|
219117
|
+
const conn = {
|
|
219118
|
+
actorId,
|
|
219119
|
+
connectorId,
|
|
219120
|
+
enabled,
|
|
219121
|
+
updatedAt: this.now(),
|
|
219122
|
+
...keep ? { configuredBy: keep } : {}
|
|
219123
|
+
};
|
|
218865
219124
|
await this.opts.store.upsertActorConnectorConnection(conn);
|
|
218866
219125
|
return conn;
|
|
218867
219126
|
}
|
|
218868
|
-
listActorConnectorConnections(actorId) {
|
|
218869
|
-
return this.opts.store.listActorConnectorConnections(actorId);
|
|
218870
|
-
}
|
|
218871
219127
|
/**
|
|
218872
|
-
*
|
|
218873
|
-
*
|
|
218874
|
-
* 删两样东西,缺一不可:
|
|
218875
|
-
* ① 这名员工**自己**那份连接器凭据(`scope=personal` 且 `connectorId` 命中的变量行)——
|
|
218876
|
-
* 不删的话,「移除」之后 `actorConnected` 里还有它,卡片照样在,读作「删不掉」;
|
|
218877
|
-
* ② 「员工×连接器」的连接记录——不删的话 `effective` 里还有它(enabled=false),
|
|
218878
|
-
* 卡片变成一张「已停用」的僵尸卡,而人要的是它消失。
|
|
219128
|
+
* 删除**一条**「员工 × 连接器」连接:连接记录 + 该员工这个连接器的**个人凭据变量**。
|
|
218879
219129
|
*
|
|
218880
|
-
*
|
|
218881
|
-
*
|
|
218882
|
-
* 于是:组织已连接时,移除个人连接后这名员工会**回落到组织默认**——卡片仍在,但身份那一行
|
|
218883
|
-
* 变回组织账号。这是对的,不是没删干净。
|
|
219130
|
+
* 与开关的区别(发起人 2026-09-09 定的,两颗按钮并存):开关是「暂时不用」,凭据留着、
|
|
219131
|
+
* 打开就能接着用;删除是「不要了」,凭据清掉、再要用得重走一遍授权。
|
|
218884
219132
|
*
|
|
218885
|
-
*
|
|
219133
|
+
* **只动这名员工自己的东西**:组织级变量(scope=global)一个不碰——那是别人也在用的。
|
|
219134
|
+
* 飞书对话通道的下线不在这里做(本服务够不到 channelService),由路由层在删完凭据后补一刀。
|
|
218886
219135
|
*/
|
|
218887
|
-
async
|
|
218888
|
-
const
|
|
218889
|
-
const
|
|
218890
|
-
(v2) => v2.scope === "personal" && v2.actorId === actorId && v2.connectorId === connectorId
|
|
218891
|
-
);
|
|
218892
|
-
for (const v2 of mine) await this.opts.store.deleteVariable(v2.key, actorId);
|
|
219136
|
+
async deleteActorConnector(actorId, connectorId) {
|
|
219137
|
+
const personal = (await this.opts.store.listVariables(actorId)).filter((v2) => v2.scope === "personal" && v2.actorId === actorId && v2.connectorId === connectorId);
|
|
219138
|
+
for (const v2 of personal) await this.deleteVariable(v2.key, actorId);
|
|
218893
219139
|
await this.opts.store.deleteActorConnectorConnection(actorId, connectorId);
|
|
218894
|
-
return {
|
|
219140
|
+
return { variablesDeleted: personal.length };
|
|
219141
|
+
}
|
|
219142
|
+
listActorConnectorConnections(actorId) {
|
|
219143
|
+
return this.opts.store.listActorConnectorConnections(actorId);
|
|
218895
219144
|
}
|
|
218896
219145
|
/**
|
|
218897
219146
|
* 员工连接器面板所需状态:连接记录 + 组织级已连接集合 + 该员工已授权(有个人 connector 变量)集合。
|
|
@@ -220860,14 +221109,9 @@ function actorsDomain(opts) {
|
|
|
220860
221109
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
220861
221110
|
const b2 = req.body;
|
|
220862
221111
|
if (typeof b2?.enabled !== "boolean") throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 enabled (boolean)");
|
|
220863
|
-
const conn = await service.setActorConnectorEnabled(req.params.id, req.params.connectorId,
|
|
221112
|
+
const conn = b2.enabled ? await service.setActorConnectorEnabled(req.params.id, req.params.connectorId, true, req.auth.actor) : await service.setActorConnectorEnabled(req.params.id, req.params.connectorId, false);
|
|
220864
221113
|
return { status: 200, body: conn };
|
|
220865
221114
|
});
|
|
220866
|
-
router.delete("/api/actors/:id/connectors/:connectorId", async (req) => {
|
|
220867
|
-
const { service } = await resolveCtx(req.auth.companyId);
|
|
220868
|
-
const r = await service.removeActorConnector(req.params.id, req.params.connectorId);
|
|
220869
|
-
return { status: 200, body: r };
|
|
220870
|
-
});
|
|
220871
221115
|
const requireVariableManager = (req) => {
|
|
220872
221116
|
if (!isHumanActor(req.auth.actor)) {
|
|
220873
221117
|
throw new ApiError(
|
|
@@ -226090,7 +226334,13 @@ function reviewSummary(snap, reviews, events) {
|
|
|
226090
226334
|
const name = node2?.title ?? first.nodeId;
|
|
226091
226335
|
const latest = latestActivityReviews(reviews, events);
|
|
226092
226336
|
const requirements = snap.requirements.filter((r) => r.nodeId === first.nodeId && r.reviewerActorId === first.reviewerActorId);
|
|
226093
|
-
|
|
226337
|
+
for (const requirement of requirements) {
|
|
226338
|
+
const current = reviews.find((r) => r.id === requirement.latestReviewId);
|
|
226339
|
+
if (!current) continue;
|
|
226340
|
+
const index2 = latest.findIndex((r) => r.reviewGroup === requirement.reviewGroup);
|
|
226341
|
+
if (index2 >= 0) latest[index2] = current;
|
|
226342
|
+
}
|
|
226343
|
+
const judgement = judgeWork({ requirements: requirements.length ? requirements : latest, reviews: latest });
|
|
226094
226344
|
const pending = latest.filter((r) => !r.cancelledAt && !r.verdict && reviewState(r) === "running");
|
|
226095
226345
|
if (work?.acceptanceState === "accepted" || work?.acceptedAt || work?.acceptanceState !== "rejected" && judgement === "passed") {
|
|
226096
226346
|
return { phase: "done", status: `\u300A${name}\u300B\u5BA1\u6838\u901A\u8FC7\u3002`, latest, pending: [] };
|
|
@@ -226126,6 +226376,66 @@ var init_review_activity = __esm({
|
|
|
226126
226376
|
}
|
|
226127
226377
|
});
|
|
226128
226378
|
|
|
226379
|
+
// ../server/src/domains/collab/review-requirement-activity.ts
|
|
226380
|
+
function reviewRequirementActivity(snap, events, ref2) {
|
|
226381
|
+
const previous3 = /* @__PURE__ */ new Map();
|
|
226382
|
+
const titles = new Map(snap.nodes.map((n) => [n.id, n.title]));
|
|
226383
|
+
const cards = [];
|
|
226384
|
+
const label = (r) => `${ref2(r.reviewerActorId).name || "\u672A\u547D\u540D\u5BA1\u6838\u4EBA"}${r.source === "closure" ? "\uFF08\u7ED3\u6848\u5BA1\u6838\uFF09" : ""}`;
|
|
226385
|
+
const names = (rows) => [...new Set(rows.map(label))].join("\u3001") || "\u65E0";
|
|
226386
|
+
for (const rec of [...events].sort((a, b2) => a.seq - b2.seq)) {
|
|
226387
|
+
if (rec.status === "pending" || rec.status === "failed") continue;
|
|
226388
|
+
const e = rec.event;
|
|
226389
|
+
if (e.kind === "plan.changed") {
|
|
226390
|
+
for (const node2 of e.addNodes ?? []) previous3.set(node2.id, node2.reviewers ?? []);
|
|
226391
|
+
for (const id of e.removeNodes ?? []) previous3.delete(id);
|
|
226392
|
+
continue;
|
|
226393
|
+
}
|
|
226394
|
+
if (e.kind === "plan.add_node") {
|
|
226395
|
+
previous3.set(e.nodeId, e.reviewers ?? []);
|
|
226396
|
+
continue;
|
|
226397
|
+
}
|
|
226398
|
+
if (e.kind !== "plan.update_review_requirements") continue;
|
|
226399
|
+
const before = previous3.get(e.nodeId);
|
|
226400
|
+
const after = e.reviewers;
|
|
226401
|
+
const beforeKeys = new Set(before?.map(requirementKey));
|
|
226402
|
+
const afterKeys = new Set(after.map(requirementKey));
|
|
226403
|
+
const added = before ? after.filter((r) => !beforeKeys.has(requirementKey(r))) : [];
|
|
226404
|
+
const removed = before?.filter((r) => !afterKeys.has(requirementKey(r))) ?? [];
|
|
226405
|
+
const nodeTitle = titles.get(e.nodeId) || "\u5DF2\u79FB\u9664\u7684\u8282\u70B9";
|
|
226406
|
+
const system = rec.actorId.startsWith("actor:system:");
|
|
226407
|
+
const closureAdded = system && added.length > 0 && !removed.length && added.every((r) => r.source === "closure");
|
|
226408
|
+
cards.push({
|
|
226409
|
+
id: `wo:${rec.seq}`,
|
|
226410
|
+
seq: rec.seq,
|
|
226411
|
+
at: rec.createdAt,
|
|
226412
|
+
updatedAt: rec.createdAt,
|
|
226413
|
+
nodeId: e.nodeId,
|
|
226414
|
+
nodeTitle,
|
|
226415
|
+
executor: system ? { ...ref2(rec.actorId), name: "\u7CFB\u7EDF" } : ref2(rec.actorId),
|
|
226416
|
+
...rec.handActorId ? { handActor: ref2(rec.handActorId) } : {},
|
|
226417
|
+
phase: "done",
|
|
226418
|
+
status: closureAdded ? `\u4E3A\u300A${nodeTitle}\u300B\u8865\u5145\u4E86\u7ED3\u6848\u5BA1\u6838\u8981\u6C42\u3002` : `\u66F4\u65B0\u4E86\u300A${nodeTitle}\u300B\u7684\u5BA1\u6838\u5217\u8868\u3002`,
|
|
226419
|
+
detail: [
|
|
226420
|
+
...added.length ? [`\u65B0\u589E\uFF1A${names(added)}`] : [],
|
|
226421
|
+
...removed.length ? [`\u79FB\u9664\uFF1A${names(removed)}`] : [],
|
|
226422
|
+
`\u66F4\u65B0\u540E\uFF1A${names(after)}`
|
|
226423
|
+
].join("\n"),
|
|
226424
|
+
artifacts: [],
|
|
226425
|
+
actions: []
|
|
226426
|
+
});
|
|
226427
|
+
previous3.set(e.nodeId, after);
|
|
226428
|
+
}
|
|
226429
|
+
return cards;
|
|
226430
|
+
}
|
|
226431
|
+
var requirementKey;
|
|
226432
|
+
var init_review_requirement_activity = __esm({
|
|
226433
|
+
"../server/src/domains/collab/review-requirement-activity.ts"() {
|
|
226434
|
+
"use strict";
|
|
226435
|
+
requirementKey = (r) => JSON.stringify([r.reviewerActorId, r.reviewGroup, r.source]);
|
|
226436
|
+
}
|
|
226437
|
+
});
|
|
226438
|
+
|
|
226129
226439
|
// ../server/src/domains/collab/workorder-manager.ts
|
|
226130
226440
|
function resolveWorkorderManager(snap) {
|
|
226131
226441
|
const nodes = snap.nodes;
|
|
@@ -226299,12 +226609,16 @@ function buildWorkorderActivity(input) {
|
|
|
226299
226609
|
const reasonKinds = new Set(reasons.map((r) => String(r.kind)));
|
|
226300
226610
|
const executorId = w2?.assigneeActorId ?? rec.actorId;
|
|
226301
226611
|
if (isPendingActor(executorId)) break;
|
|
226302
|
-
const
|
|
226303
|
-
const
|
|
226304
|
-
|
|
226305
|
-
|
|
226306
|
-
|
|
226307
|
-
const
|
|
226612
|
+
const forcedBy = str4(reasons.find((r) => r.kind === "forced")?.actorId);
|
|
226613
|
+
const gapDriven = reasons.some((r) => r.kind === "issue" && r.issueKind === "gap");
|
|
226614
|
+
const status = reasonKinds.has("rework") ? ACTIVITY_COPY.reworking(nodeName(nodeId)) : reasonKinds.has("resumed") ? ACTIVITY_COPY.resumed(nameOf(executorId), nodeName(nodeId)) : reasonKinds.has("spec_changed") ? ACTIVITY_COPY.specChanged(nodeName(nodeId)) : gapDriven ? ACTIVITY_COPY.gapReworked(nameOf(executorId), nodeName(nodeId)) : reasonKinds.has("issue") ? ACTIVITY_COPY.issueDriven(nodeName(nodeId)) : forcedBy ? ACTIVITY_COPY.forcedRerun(nameOf(forcedBy), nodeName(nodeId)) : ACTIVITY_COPY.working(nodeName(nodeId));
|
|
226615
|
+
for (const r of reasons) {
|
|
226616
|
+
if (r.kind !== "issue") continue;
|
|
226617
|
+
const issueId = str4(r.issueId);
|
|
226618
|
+
if (!issueId) continue;
|
|
226619
|
+
workOfIssue.set(issueId, workId);
|
|
226620
|
+
const ic = plainCommentIssueIds.has(issueId) ? issueCards.get(issueId) : void 0;
|
|
226621
|
+
const commentAuthor = issueById.get(issueId)?.authorActorId;
|
|
226308
226622
|
if (ic && commentAuthor) {
|
|
226309
226623
|
touch(ic, rec);
|
|
226310
226624
|
ic.executorId = executorId;
|
|
@@ -226806,6 +227120,8 @@ function buildWorkorderActivity(input) {
|
|
|
226806
227120
|
.../* @__PURE__ */ ((r) => r ? { runId: r, traceAvailable: true } : {})(traced ? runIdOfCard(d) : void 0)
|
|
226807
227121
|
};
|
|
226808
227122
|
});
|
|
227123
|
+
cards.push(...reviewRequirementActivity(snap, events, ref2));
|
|
227124
|
+
cards.sort((a, b2) => a.updatedAt.localeCompare(b2.updatedAt) || a.seq - b2.seq || a.id.localeCompare(b2.id));
|
|
226809
227125
|
return { workorderId, cards, truncated };
|
|
226810
227126
|
}
|
|
226811
227127
|
var ACTIVITY_EVENT_KINDS, ACTIVITY_EVENT_LIMIT, ACTIVITY_COPY, REWORK_ANNOTATION_PREFIX, ENGINE_RETRY_EXHAUSTED, BUTTON;
|
|
@@ -226815,9 +227131,12 @@ var init_activity2 = __esm({
|
|
|
226815
227131
|
init_src();
|
|
226816
227132
|
init_src4();
|
|
226817
227133
|
init_review_activity();
|
|
227134
|
+
init_review_requirement_activity();
|
|
226818
227135
|
init_workorder_manager();
|
|
226819
227136
|
ACTIVITY_EVENT_KINDS = [
|
|
226820
227137
|
"plan.changed",
|
|
227138
|
+
"plan.add_node",
|
|
227139
|
+
"plan.update_review_requirements",
|
|
226821
227140
|
"plan.update_spec",
|
|
226822
227141
|
"plan.node_retry",
|
|
226823
227142
|
"work.create",
|
|
@@ -226856,6 +227175,22 @@ var init_activity2 = __esm({
|
|
|
226856
227175
|
reworking: (node2) => `\u6B63\u5728\u6839\u636E\u5BA1\u6838\u4E0D\u901A\u8FC7\u539F\u56E0\u4FEE\u6539\u300A${node2}\u300B\u3002`,
|
|
226857
227176
|
specChanged: (node2) => `\u6B63\u5728\u6839\u636E\u4EFB\u52A1\u8BF4\u660E\u7684\u66F4\u65B0\u8C03\u6574\u300A${node2}\u300B\u3002`,
|
|
226858
227177
|
issueDriven: (node2) => `\u6B63\u5728\u6839\u636E\u53CD\u9988\u8C03\u6574\u300A${node2}\u300B\u3002`,
|
|
227178
|
+
/**
|
|
227179
|
+
* 缺口解开后**带着答复重开工**的那一轮(`reasons` 里有 `{kind:"issue", issueKind:"gap"}`)。
|
|
227180
|
+
*
|
|
227181
|
+
* 与 {@link issueDriven} 分开:那句说的是「按反馈调整」,而这一轮的事实是**卡点解除、重新开始**
|
|
227182
|
+
* ——中断链上最该看清的一拍。此前两者共用一句,恢复后的那一轮被说回泛泛的「正在根据反馈调整」。
|
|
227183
|
+
* 实测 next 213 次 / 23 单、v2 4 次,最近一次 2026-09-09(`issue` 里第二多的一档)。
|
|
227184
|
+
*/
|
|
227185
|
+
gapReworked: (executor, node2) => `\u7F3A\u53E3\u5DF2\u89E3\u51B3\uFF0C${executor} \u5E26\u7740\u7B54\u590D\u91CD\u65B0\u5F00\u5DE5\u300A${node2}\u300B\u3002`,
|
|
227186
|
+
/**
|
|
227187
|
+
* 人点了 UI 的「重新运行」(`kernel-bridge.rerunNode`,ADR 0137)——`reasons` 里那条
|
|
227188
|
+
* `{kind:"forced", actorId}` 就是点的人。
|
|
227189
|
+
*
|
|
227190
|
+
* 此前没有自己的文案、落到 `working` 说成「正在处理《X》。」,**页面上完全看不出这一轮是
|
|
227191
|
+
* 有人手动强推的**。实测两条生产线合计 80 次(next 73 / v2 7,最近一次 2026-09-09)。
|
|
227192
|
+
*/
|
|
227193
|
+
forcedRerun: (by, node2) => `${by} \u91CD\u65B0\u8FD0\u884C\u4E86\u300A${node2}\u300B\u3002`,
|
|
226859
227194
|
/* 自动判定的那一刻**只说事实,不断言谁介入了**。
|
|
226860
227195
|
`work.timeout` 由引擎发(`engine/activate.ts` 与 `server/run-settlement.ts`),失败后的重试
|
|
226861
227196
|
也是引擎做的(`activate.ts` 的 `tryToRun`)——管理者根本不知道这两件事,此前却写成
|
|
@@ -228045,9 +228380,33 @@ function toAuditEntry(op) {
|
|
|
228045
228380
|
summary: `${KIND_LABEL2[op.kind] ?? op.kind} \xB7 ${op.artifactId}`
|
|
228046
228381
|
};
|
|
228047
228382
|
}
|
|
228383
|
+
function nodeIdOfWorkId(workId) {
|
|
228384
|
+
if (!workId || !workId.startsWith("wk:")) return null;
|
|
228385
|
+
const body2 = workId.slice(3);
|
|
228386
|
+
const cut = body2.lastIndexOf(":");
|
|
228387
|
+
if (cut <= 0) return null;
|
|
228388
|
+
if (!/^\d+$/.test(body2.slice(cut + 1))) return null;
|
|
228389
|
+
const nodeId = body2.slice(0, cut);
|
|
228390
|
+
return nodeId.startsWith("artifact:") ? nodeId : null;
|
|
228391
|
+
}
|
|
228392
|
+
function nodeIdOfIssueId(issueId, model) {
|
|
228393
|
+
if (!issueId) return null;
|
|
228394
|
+
const anchored = model.annotations.get(issueId)?.anchor.target;
|
|
228395
|
+
if (anchored) {
|
|
228396
|
+
if (anchored.startsWith("artifact:")) return anchored;
|
|
228397
|
+
const fromWork = nodeIdOfWorkId(anchored);
|
|
228398
|
+
if (fromWork) return fromWork;
|
|
228399
|
+
}
|
|
228400
|
+
const body2 = issueId.replace(/^(?:ann:rework:)?(?:gap:|esc:|ann:)/, "");
|
|
228401
|
+
if (!body2.startsWith("artifact:")) return null;
|
|
228402
|
+
const cut = body2.lastIndexOf(":");
|
|
228403
|
+
if (cut <= 0) return null;
|
|
228404
|
+
const nodeId = body2.slice(0, cut);
|
|
228405
|
+
return nodeId.startsWith("artifact:") ? nodeId : null;
|
|
228406
|
+
}
|
|
228048
228407
|
function eventToAuditEntry(rec) {
|
|
228049
228408
|
const ev = rec.event;
|
|
228050
|
-
const artifactId = rec.nodeId ?? rec.workId ?? "";
|
|
228409
|
+
const artifactId = rec.nodeId ?? nodeIdOfWorkId(rec.workId) ?? "";
|
|
228051
228410
|
return {
|
|
228052
228411
|
seq: rec.seq,
|
|
228053
228412
|
at: rec.createdAt,
|
|
@@ -228057,16 +228416,25 @@ function eventToAuditEntry(rec) {
|
|
|
228057
228416
|
summary: `${KIND_LABEL2[ev.kind] ?? ev.kind}${artifactId ? ` \xB7 ${artifactId}` : ""}`
|
|
228058
228417
|
};
|
|
228059
228418
|
}
|
|
228060
|
-
function
|
|
228061
|
-
const
|
|
228062
|
-
|
|
228063
|
-
|
|
228064
|
-
|
|
228065
|
-
|
|
228066
|
-
|
|
228067
|
-
...
|
|
228068
|
-
visibility: "ok"
|
|
228419
|
+
function auditAnchorsOf(rec) {
|
|
228420
|
+
const issueId = rec.event.issueId;
|
|
228421
|
+
return { workorderId: rec.workorderId, ...typeof issueId === "string" && issueId ? { issueId } : {} };
|
|
228422
|
+
}
|
|
228423
|
+
function enrichAudit(entry, model, titleOf, anchors = {}) {
|
|
228424
|
+
const withNode = (id, a) => {
|
|
228425
|
+
const workspaceTitle2 = titleOf.get(a.workspace);
|
|
228426
|
+
return { ...entry, artifactId: id, nodeName: nodeLabel(a), ...workspaceTitle2 ? { workspaceTitle: workspaceTitle2 } : {}, visibility: "ok" };
|
|
228069
228427
|
};
|
|
228428
|
+
if (entry.artifactId) {
|
|
228429
|
+
const a = model.artifacts.get(entry.artifactId);
|
|
228430
|
+
if (!a) return { ...entry, visibility: "deleted" };
|
|
228431
|
+
return withNode(entry.artifactId, a);
|
|
228432
|
+
}
|
|
228433
|
+
const viaIssue = nodeIdOfIssueId(anchors.issueId, model);
|
|
228434
|
+
const viaIssueArtifact = viaIssue ? model.artifacts.get(viaIssue) : void 0;
|
|
228435
|
+
if (viaIssue && viaIssueArtifact) return withNode(viaIssue, viaIssueArtifact);
|
|
228436
|
+
const workspaceTitle = anchors.workorderId ? titleOf.get(anchors.workorderId) : void 0;
|
|
228437
|
+
return { ...entry, ...workspaceTitle ? { workspaceTitle } : {}, visibility: "ok" };
|
|
228070
228438
|
}
|
|
228071
228439
|
async function buildAudit(source, q2 = {}, model) {
|
|
228072
228440
|
const limit = Math.min(Math.max(q2.limit ?? 100, 1), 500);
|
|
@@ -228075,8 +228443,8 @@ async function buildAudit(source, q2 = {}, model) {
|
|
|
228075
228443
|
const items = [];
|
|
228076
228444
|
let lastCursor = null;
|
|
228077
228445
|
let truncated = false;
|
|
228078
|
-
const push2 = (entry, cursor) => {
|
|
228079
|
-
items.push(model && titleOf ? enrichAudit(entry, model, titleOf) : entry);
|
|
228446
|
+
const push2 = (entry, cursor, anchors) => {
|
|
228447
|
+
items.push(model && titleOf ? enrichAudit(entry, model, titleOf, anchors) : entry);
|
|
228080
228448
|
lastCursor = cursor;
|
|
228081
228449
|
};
|
|
228082
228450
|
const match = (actor, kind, at) => {
|
|
@@ -228087,30 +228455,33 @@ async function buildAudit(source, q2 = {}, model) {
|
|
|
228087
228455
|
return true;
|
|
228088
228456
|
};
|
|
228089
228457
|
if (q2.latest) {
|
|
228090
|
-
|
|
228458
|
+
const collected = [];
|
|
228091
228459
|
if (source.engineStore) {
|
|
228092
228460
|
const records = await source.engineStore.transaction((tx) => tx.listEvents(void 0, 0));
|
|
228093
228461
|
for (const rec of records) {
|
|
228094
228462
|
const ev = rec.event;
|
|
228095
228463
|
if (!match(rec.actorId, ev.kind, rec.createdAt)) continue;
|
|
228096
|
-
collected.push(eventToAuditEntry(rec));
|
|
228464
|
+
collected.push({ entry: eventToAuditEntry(rec), anchors: auditAnchorsOf(rec) });
|
|
228097
228465
|
}
|
|
228098
228466
|
} else if (source.oplog) {
|
|
228099
228467
|
const src = source.oplog.readFilteredOps ? source.oplog.readFilteredOps({ ...q2.actor ? { actor: q2.actor } : {}, ...q2.kind ? { kind: q2.kind } : {} }, void 0, { latest: true }) : source.oplog.readAll();
|
|
228100
228468
|
for await (const { op } of src) {
|
|
228101
228469
|
if (!match(op.actor, op.kind, op.timestamp)) continue;
|
|
228102
|
-
collected.push(toAuditEntry(op));
|
|
228470
|
+
collected.push({ entry: toAuditEntry(op) });
|
|
228103
228471
|
}
|
|
228104
228472
|
}
|
|
228105
228473
|
const tail = collected.slice(-limit).reverse();
|
|
228106
|
-
return {
|
|
228474
|
+
return {
|
|
228475
|
+
items: model && titleOf ? tail.map(({ entry, anchors }) => enrichAudit(entry, model, titleOf, anchors)) : tail.map(({ entry }) => entry),
|
|
228476
|
+
cursor: null
|
|
228477
|
+
};
|
|
228107
228478
|
}
|
|
228108
228479
|
if (source.engineStore) {
|
|
228109
228480
|
const records = await source.engineStore.transaction((tx) => tx.listEvents(void 0, fromSeq));
|
|
228110
228481
|
for (const rec of records) {
|
|
228111
228482
|
const ev = rec.event;
|
|
228112
228483
|
if (!match(rec.actorId, ev.kind, rec.createdAt)) continue;
|
|
228113
|
-
push2(eventToAuditEntry(rec), String(rec.seq));
|
|
228484
|
+
push2(eventToAuditEntry(rec), String(rec.seq), auditAnchorsOf(rec));
|
|
228114
228485
|
if (items.length >= limit) {
|
|
228115
228486
|
truncated = true;
|
|
228116
228487
|
break;
|
|
@@ -228156,6 +228527,30 @@ var init_audit = __esm({
|
|
|
228156
228527
|
"workorder.paused": "\u6682\u505C\u6D3E\u53D1",
|
|
228157
228528
|
"workorder.resumed": "\u6062\u590D\u6D3E\u53D1",
|
|
228158
228529
|
"workorder.sealed": "\u5C01\u5B58",
|
|
228530
|
+
// 其余新引擎事件 kind——缺标签时 summary 直接露英文 kind(生产实测:`plan.changed` 是量最大的
|
|
228531
|
+
// 一类审计条目,界面上就写着「plan.changed」)。这张表按 EngineEvent 的 kind 全集补齐。
|
|
228532
|
+
"plan.changed": "\u6539\u4EFB\u52A1\u56FE",
|
|
228533
|
+
"plan.add_edge": "\u63A5\u4F9D\u8D56",
|
|
228534
|
+
"plan.delete_edge": "\u65AD\u4F9D\u8D56",
|
|
228535
|
+
"plan.update_review_requirements": "\u6539\u8BC4\u5BA1\u8981\u6C42",
|
|
228536
|
+
"plan.update_fields": "\u6539\u5B57\u6BB5",
|
|
228537
|
+
"work.started": "\u5F00\u5DE5",
|
|
228538
|
+
"work.redispatch": "\u91CD\u6D3E",
|
|
228539
|
+
"work.snapshot_recorded": "\u5B58\u5FEB\u7167",
|
|
228540
|
+
"work.handoff_recorded": "\u8BB0\u4EA4\u63A5",
|
|
228541
|
+
"work.reject": "\u6253\u56DE",
|
|
228542
|
+
"work.content_edited": "\u6539\u5185\u5BB9",
|
|
228543
|
+
"work.conclude": "\u5B9A\u7A3F",
|
|
228544
|
+
"node.latest_proposed.rebased": "\u6362\u57FA\u7EBF",
|
|
228545
|
+
"review.started": "\u5F00\u59CB\u8BC4\u5BA1",
|
|
228546
|
+
"review.kill": "\u64A4\u8BC4\u5BA1",
|
|
228547
|
+
"review.timeout": "\u8BC4\u5BA1\u8D85\u65F6",
|
|
228548
|
+
"issue.resolution_proposed": "\u63D0\u89E3\u51B3\u65B9\u6848",
|
|
228549
|
+
"issue.resolution_rejected": "\u9A73\u56DE\u89E3\u51B3\u65B9\u6848",
|
|
228550
|
+
"workorder.created": "\u5EFA\u5DE5\u5355",
|
|
228551
|
+
"workorder.root_set": "\u5B9A\u6839\u8282\u70B9",
|
|
228552
|
+
"workorder.meta_changed": "\u6539\u5DE5\u5355\u4FE1\u606F",
|
|
228553
|
+
"workorder.ping": "\u5524\u9192",
|
|
228159
228554
|
// 旧 op kind(oplog 回退路径)
|
|
228160
228555
|
spawn_artifact: "\u5EFA\u4EA7\u7269",
|
|
228161
228556
|
propose_revision: "\u63D0\u4FEE\u8BA2",
|
|
@@ -228974,11 +229369,7 @@ async function buildResolver(registry2) {
|
|
|
228974
229369
|
const byId = new Map(actors.map((a) => [a.id, a]));
|
|
228975
229370
|
return (id) => {
|
|
228976
229371
|
const a = byId.get(id);
|
|
228977
|
-
return a ?
|
|
228978
|
-
name: a.name,
|
|
228979
|
-
...a.roles[0] ? { role: a.roles[0] } : {},
|
|
228980
|
-
...a.avatar ? { avatar: a.avatar } : {}
|
|
228981
|
-
} : void 0;
|
|
229372
|
+
return a ? actorRefFieldsOf(a) : systemActorFallback(id);
|
|
228982
229373
|
};
|
|
228983
229374
|
}
|
|
228984
229375
|
async function buildProjectResolver(artifacts) {
|
|
@@ -233555,7 +233946,7 @@ function createChatSessionsDomain(opts) {
|
|
|
233555
233946
|
const byId = new Map(actors.map((a) => [a.id, a]));
|
|
233556
233947
|
const resolver2 = (id) => {
|
|
233557
233948
|
const a = byId.get(id);
|
|
233558
|
-
return a ? { name: a.name } :
|
|
233949
|
+
return a ? { name: a.name } : systemActorFallback(id);
|
|
233559
233950
|
};
|
|
233560
233951
|
const allSummaries = buildWorkorderSummaries(wkKernel.model, resolver2, (wo) => byWo.get(wo) ?? null, (wo) => held.has(wo), void 0, void 0, (role) => wkKernel.actorForRole(role));
|
|
233561
233952
|
const summaryById = new Map(allSummaries.map((s2) => [s2.id, s2]));
|
|
@@ -237750,6 +238141,11 @@ var init_daemon_adapter = __esm({
|
|
|
237750
238141
|
clearTimeout(entry.ackTimer);
|
|
237751
238142
|
entry.ackTimer = void 0;
|
|
237752
238143
|
}
|
|
238144
|
+
const reapTimer = this.sessionReapTimers.get(dispatchId);
|
|
238145
|
+
if (reapTimer) {
|
|
238146
|
+
clearTimeout(reapTimer);
|
|
238147
|
+
this.sessionReapTimers.delete(dispatchId);
|
|
238148
|
+
}
|
|
237753
238149
|
entry.exited = info;
|
|
237754
238150
|
for (const w2 of entry.appendWaiters.splice(0)) {
|
|
237755
238151
|
clearTimeout(w2.timer);
|
|
@@ -237845,6 +238241,10 @@ var init_daemon_adapter = __esm({
|
|
|
237845
238241
|
for (const [dispatchId, entry] of this.pending) {
|
|
237846
238242
|
if (entry.nodeId !== daemonId || entry.exited || present.has(dispatchId)) continue;
|
|
237847
238243
|
if (this.hub.hasSession?.(dispatchId)) continue;
|
|
238244
|
+
if (this.sessionReapTimers.has(dispatchId)) {
|
|
238245
|
+
this.log(`[dispatch-delivery] ${dispatchId}\uFF1A\u8282\u70B9 ${daemonId} \u7A7A\u5E93\u5B58\u4E0D\u8986\u76D6\u72EC\u7ACB\u4F1A\u8BDD\u65AD\u7EBF\u5BBD\u9650\uFF0C\u7ED3\u8BBA=unknown\uFF08\u4F9D\u636E\uFF1A\u6570\u636E\u9762\u66FE\u8FDE\u63A5\uFF0C\u7B49\u5F85\u91CD\u8FDE\u6216\u539F ${this.sessionReapGraceMs}ms \u671F\u9650\uFF09`);
|
|
238246
|
+
continue;
|
|
238247
|
+
}
|
|
237848
238248
|
absent.push(dispatchId);
|
|
237849
238249
|
}
|
|
237850
238250
|
for (const dispatchId of absent) {
|
|
@@ -237877,8 +238277,7 @@ var init_daemon_adapter = __esm({
|
|
|
237877
238277
|
*/
|
|
237878
238278
|
onSessionDown(dispatchId) {
|
|
237879
238279
|
if (this.sessionReapTimers.has(dispatchId)) return;
|
|
237880
|
-
|
|
237881
|
-
if (!entry || entry.exited) return;
|
|
238280
|
+
if (this.settledDispatchIds.has(dispatchId)) return;
|
|
237882
238281
|
const timer = setTimeout(() => {
|
|
237883
238282
|
this.sessionReapTimers.delete(dispatchId);
|
|
237884
238283
|
const e = this.pending.get(dispatchId);
|
|
@@ -239214,6 +239613,7 @@ ${ctx.nodeFault}
|
|
|
239214
239613
|
env: { ...prov?.env ?? {}, OASIS_STAGE: "1", ...workspace ? { OASIS_WORKSPACE: workspace } : {} },
|
|
239215
239614
|
...prov?.wrapperPaths && prov.wrapperPaths.length > 0 ? { wrapperPaths: prov.wrapperPaths } : {},
|
|
239216
239615
|
...prov?.requiredTools && prov.requiredTools.length > 0 ? { requiredTools: prov.requiredTools } : {},
|
|
239616
|
+
...prov?.requiredToolVersions && Object.keys(prov.requiredToolVersions).length > 0 ? { requiredToolVersions: prov.requiredToolVersions } : {},
|
|
239217
239617
|
...prov?.connectorCreds && prov.connectorCreds.length > 0 ? { connectorCreds: prov.connectorCreds } : {}
|
|
239218
239618
|
};
|
|
239219
239619
|
this.deps.log?.(`[coordinator] ${logMsg}`);
|
|
@@ -239774,6 +240174,7 @@ var init_postgres_registry = __esm({
|
|
|
239774
240174
|
updated_at timestamptz NOT NULL,
|
|
239775
240175
|
PRIMARY KEY (actor_id, connector_id)
|
|
239776
240176
|
)`);
|
|
240177
|
+
await pool.query(`ALTER TABLE "${s2}".actor_connector_connections ADD COLUMN IF NOT EXISTS configured_by text`);
|
|
239777
240178
|
await pool.query(`
|
|
239778
240179
|
CREATE TABLE IF NOT EXISTS "${s2}".skill_catalog (
|
|
239779
240180
|
id text PRIMARY KEY, -- slug
|
|
@@ -240161,10 +240562,11 @@ var init_postgres_registry = __esm({
|
|
|
240161
240562
|
}
|
|
240162
240563
|
async upsertActorConnectorConnection(c) {
|
|
240163
240564
|
await this.pool.query(
|
|
240164
|
-
`INSERT INTO ${this.s}.actor_connector_connections (actor_id, connector_id, enabled, updated_at)
|
|
240165
|
-
VALUES ($1, $2, $3, $4)
|
|
240166
|
-
ON CONFLICT (actor_id, connector_id) DO UPDATE SET enabled = $3, updated_at = $4
|
|
240167
|
-
|
|
240565
|
+
`INSERT INTO ${this.s}.actor_connector_connections (actor_id, connector_id, enabled, updated_at, configured_by)
|
|
240566
|
+
VALUES ($1, $2, $3, $4, $5)
|
|
240567
|
+
ON CONFLICT (actor_id, connector_id) DO UPDATE SET enabled = $3, updated_at = $4,
|
|
240568
|
+
configured_by = COALESCE($5, ${this.s}.actor_connector_connections.configured_by)`,
|
|
240569
|
+
[c.actorId, c.connectorId, c.enabled, c.updatedAt, c.configuredBy ?? null]
|
|
240168
240570
|
);
|
|
240169
240571
|
}
|
|
240170
240572
|
async listActorConnectorConnections(actorId) {
|
|
@@ -240176,7 +240578,8 @@ var init_postgres_registry = __esm({
|
|
|
240176
240578
|
actorId: row.actor_id,
|
|
240177
240579
|
connectorId: row.connector_id,
|
|
240178
240580
|
enabled: row.enabled,
|
|
240179
|
-
updatedAt: new Date(row.updated_at).toISOString()
|
|
240581
|
+
updatedAt: new Date(row.updated_at).toISOString(),
|
|
240582
|
+
...row.configured_by ? { configuredBy: row.configured_by } : {}
|
|
240180
240583
|
}));
|
|
240181
240584
|
}
|
|
240182
240585
|
async listAllActorConnectorConnections() {
|
|
@@ -240187,7 +240590,8 @@ var init_postgres_registry = __esm({
|
|
|
240187
240590
|
actorId: row.actor_id,
|
|
240188
240591
|
connectorId: row.connector_id,
|
|
240189
240592
|
enabled: row.enabled,
|
|
240190
|
-
updatedAt: new Date(row.updated_at).toISOString()
|
|
240593
|
+
updatedAt: new Date(row.updated_at).toISOString(),
|
|
240594
|
+
...row.configured_by ? { configuredBy: row.configured_by } : {}
|
|
240191
240595
|
}));
|
|
240192
240596
|
}
|
|
240193
240597
|
async deleteActorConnectorConnection(actorId, connectorId) {
|
|
@@ -255201,6 +255605,98 @@ var init_chat_builtin_skills = __esm({
|
|
|
255201
255605
|
}
|
|
255202
255606
|
});
|
|
255203
255607
|
|
|
255608
|
+
// ../server/src/governance/connector-tool-versions.ts
|
|
255609
|
+
function connectorToolVersionsFile(dataDir) {
|
|
255610
|
+
return (0, import_node_path25.join)(dataDir, "connector-tools", "versions.json");
|
|
255611
|
+
}
|
|
255612
|
+
function registryBase() {
|
|
255613
|
+
const raw = process.env["npm_config_registry"] || process.env["NPM_CONFIG_REGISTRY"] || "https://registry.npmjs.org";
|
|
255614
|
+
return raw.replace(/\/+$/, "");
|
|
255615
|
+
}
|
|
255616
|
+
async function fetchLatestNpmVersion(pkg) {
|
|
255617
|
+
try {
|
|
255618
|
+
const url = `${registryBase()}/${pkg.split("/").map(encodeURIComponent).join("%2F")}/latest`;
|
|
255619
|
+
const res = await fetch(url, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(NPM_PROBE_TIMEOUT_MS) });
|
|
255620
|
+
if (!res.ok) return null;
|
|
255621
|
+
const v2 = (await res.json()).version;
|
|
255622
|
+
return typeof v2 === "string" && v2 ? v2 : null;
|
|
255623
|
+
} catch {
|
|
255624
|
+
return null;
|
|
255625
|
+
}
|
|
255626
|
+
}
|
|
255627
|
+
async function readRegisteredToolVersions(dataDir) {
|
|
255628
|
+
try {
|
|
255629
|
+
const raw = JSON.parse(await (0, import_promises14.readFile)(connectorToolVersionsFile(dataDir), "utf8"));
|
|
255630
|
+
if (!raw || typeof raw !== "object") return {};
|
|
255631
|
+
const out = {};
|
|
255632
|
+
for (const [k2, v2] of Object.entries(raw)) {
|
|
255633
|
+
if (typeof v2 === "string" && v2) out[k2] = v2;
|
|
255634
|
+
}
|
|
255635
|
+
return out;
|
|
255636
|
+
} catch {
|
|
255637
|
+
return {};
|
|
255638
|
+
}
|
|
255639
|
+
}
|
|
255640
|
+
async function writeRegisteredToolVersions(dataDir, versions) {
|
|
255641
|
+
const file = connectorToolVersionsFile(dataDir);
|
|
255642
|
+
await (0, import_promises14.mkdir)((0, import_node_path25.join)(dataDir, "connector-tools"), { recursive: true });
|
|
255643
|
+
const tmp = `${file}.${process.pid}.tmp`;
|
|
255644
|
+
await (0, import_promises14.writeFile)(tmp, `${JSON.stringify(versions, null, 2)}
|
|
255645
|
+
`, "utf8");
|
|
255646
|
+
await (0, import_promises14.rename)(tmp, file);
|
|
255647
|
+
}
|
|
255648
|
+
async function refreshConnectorToolVersions(opts) {
|
|
255649
|
+
const fetchLatest = opts.fetchLatest ?? fetchLatestNpmVersion;
|
|
255650
|
+
const log3 = opts.log ?? (() => {
|
|
255651
|
+
});
|
|
255652
|
+
const versions = await readRegisteredToolVersions(opts.dataDir);
|
|
255653
|
+
const results = [];
|
|
255654
|
+
let changed = false;
|
|
255655
|
+
for (const [tool, pkg] of Object.entries(NPM_TOOL_PACKAGES)) {
|
|
255656
|
+
const before = versions[tool];
|
|
255657
|
+
const latest = await fetchLatest(pkg);
|
|
255658
|
+
if (!latest) {
|
|
255659
|
+
results.push({ tool, pkg, ...before ? { from: before, to: before } : {}, outcome: "unreachable" });
|
|
255660
|
+
log3(`[connector-tools] ${pkg} \u95EE\u4E0D\u5230\u6700\u65B0\u7248\uFF0C\u6CBF\u7528\u767B\u8BB0\u7248\u672C ${before ?? "\uFF08\u65E0\uFF09"}`);
|
|
255661
|
+
continue;
|
|
255662
|
+
}
|
|
255663
|
+
if (before === latest) {
|
|
255664
|
+
results.push({ tool, pkg, from: before, to: latest, outcome: "unchanged" });
|
|
255665
|
+
continue;
|
|
255666
|
+
}
|
|
255667
|
+
versions[tool] = latest;
|
|
255668
|
+
changed = true;
|
|
255669
|
+
results.push({ tool, pkg, ...before ? { from: before } : {}, to: latest, outcome: "updated" });
|
|
255670
|
+
log3(`[connector-tools] ${pkg} \u767B\u8BB0\u7248\u672C ${before ?? "\uFF08\u65E0\uFF09"} \u2192 ${latest}`);
|
|
255671
|
+
}
|
|
255672
|
+
if (changed) {
|
|
255673
|
+
try {
|
|
255674
|
+
await writeRegisteredToolVersions(opts.dataDir, versions);
|
|
255675
|
+
} catch (err) {
|
|
255676
|
+
log3(`[connector-tools] \u767B\u8BB0\u7248\u672C\u843D\u76D8\u5931\u8D25\uFF08\u672C\u8FDB\u7A0B\u5185\u4ECD\u751F\u6548\uFF09\uFF1A${String(err)}`);
|
|
255677
|
+
}
|
|
255678
|
+
}
|
|
255679
|
+
return { versions, results };
|
|
255680
|
+
}
|
|
255681
|
+
function pickToolVersions(registered, tools) {
|
|
255682
|
+
const out = {};
|
|
255683
|
+
for (const t of tools) {
|
|
255684
|
+
const v2 = registered[t];
|
|
255685
|
+
if (v2) out[t] = v2;
|
|
255686
|
+
}
|
|
255687
|
+
return out;
|
|
255688
|
+
}
|
|
255689
|
+
var import_promises14, import_node_path25, NPM_PROBE_TIMEOUT_MS;
|
|
255690
|
+
var init_connector_tool_versions = __esm({
|
|
255691
|
+
"../server/src/governance/connector-tool-versions.ts"() {
|
|
255692
|
+
"use strict";
|
|
255693
|
+
import_promises14 = require("node:fs/promises");
|
|
255694
|
+
import_node_path25 = require("node:path");
|
|
255695
|
+
init_src8();
|
|
255696
|
+
NPM_PROBE_TIMEOUT_MS = 3e3;
|
|
255697
|
+
}
|
|
255698
|
+
});
|
|
255699
|
+
|
|
255204
255700
|
// ../server/src/design/board-watch.ts
|
|
255205
255701
|
function decideBoardLetter(c, nowMs, quietMs) {
|
|
255206
255702
|
if (c.hasOpenWatchLetter) return false;
|
|
@@ -255953,6 +256449,7 @@ var init_src11 = __esm({
|
|
|
255953
256449
|
init_node_store();
|
|
255954
256450
|
init_tokens();
|
|
255955
256451
|
init_collab();
|
|
256452
|
+
init_workorders();
|
|
255956
256453
|
init_collab();
|
|
255957
256454
|
init_closure_report();
|
|
255958
256455
|
init_workorders();
|
|
@@ -255996,6 +256493,7 @@ var init_src11 = __esm({
|
|
|
255996
256493
|
init_builtin_skills();
|
|
255997
256494
|
init_chat_builtin_skills();
|
|
255998
256495
|
init_connector_skills();
|
|
256496
|
+
init_connector_tool_versions();
|
|
255999
256497
|
init_board_watch();
|
|
256000
256498
|
init_ephemeral_project();
|
|
256001
256499
|
init_run_settlement();
|
|
@@ -256858,6 +257356,7 @@ function materializeBuiltins(builtins, runtimeKind, opts) {
|
|
|
256858
257356
|
var CONNECTOR_SKILL_SOURCES = [
|
|
256859
257357
|
{ connectorId: "feishu", baseUrl: FEISHU_WELL_KNOWN_SKILLS_BASE }
|
|
256860
257358
|
];
|
|
257359
|
+
var registeredToolVersions = {};
|
|
256861
257360
|
async function readAllConnectorSkills(dataDir) {
|
|
256862
257361
|
const out = [];
|
|
256863
257362
|
for (const src of CONNECTOR_SKILL_SOURCES) {
|
|
@@ -256889,11 +257388,18 @@ async function refreshConnectorSkillsNow(dataDir, apply) {
|
|
|
256889
257388
|
}
|
|
256890
257389
|
}
|
|
256891
257390
|
if (out.length > 0) apply(out);
|
|
257391
|
+
try {
|
|
257392
|
+
const { versions } = await refreshConnectorToolVersions({ dataDir, log: (m2) => console.log(m2) });
|
|
257393
|
+
registeredToolVersions = versions;
|
|
257394
|
+
} catch (err) {
|
|
257395
|
+
console.warn(`[serve] connector CLI \u767B\u8BB0\u7248\u672C\u5237\u65B0\u5931\u8D25\uFF0C\u6CBF\u7528\u4E0A\u4E00\u4EFD\uFF1A${String(err)}`);
|
|
257396
|
+
}
|
|
256892
257397
|
return results;
|
|
256893
257398
|
}
|
|
256894
257399
|
function refreshConnectorSkillsInBackground(dataDir, apply) {
|
|
256895
257400
|
void refreshConnectorSkillsNow(dataDir, apply);
|
|
256896
257401
|
}
|
|
257402
|
+
var CONNECTOR_SKILL_REFRESH_MS = 24 * 60 * 6e4;
|
|
256897
257403
|
var SESSION_TOKEN_GRACE_MS = 15 * 6e4;
|
|
256898
257404
|
function makeResumeRetryProxy(first, spawnFallback) {
|
|
256899
257405
|
const relay = () => {
|
|
@@ -257087,6 +257593,8 @@ async function buildActorProvision(service, actorId, scope, onBrokerRefused) {
|
|
|
257087
257593
|
env,
|
|
257088
257594
|
wrapperPaths: [oasisWrapperScript(), ...provision.wrapperPaths],
|
|
257089
257595
|
requiredTools: provision.requiredTools,
|
|
257596
|
+
// 只挑本次真要用的那几个:job 里不塞无关工具的版本号。
|
|
257597
|
+
requiredToolVersions: pickToolVersions(registeredToolVersions, provision.requiredTools),
|
|
257090
257598
|
connectorCreds: provision.connectorCreds,
|
|
257091
257599
|
cleanup: provision.cleanup
|
|
257092
257600
|
};
|
|
@@ -257658,7 +258166,8 @@ async function startServe(opts) {
|
|
|
257658
258166
|
kernel: defaultCompanyKernel,
|
|
257659
258167
|
// B2:读路径走 oplog 派生投影——同一 oplog 写后重放重建
|
|
257660
258168
|
oplog,
|
|
257661
|
-
|
|
258169
|
+
// 系统身份(`actor:system*`)不在名册里,缓存必然打空——补同一份展示名,别让它退成裸 id。
|
|
258170
|
+
actorNames: { resolve: (actorId) => registryActorNames.get(actorId) ?? systemActorFallback(actorId)?.name },
|
|
257662
258171
|
blobs,
|
|
257663
258172
|
// 项目普通文件上传入 blob 库
|
|
257664
258173
|
actorDirectory: registryStore,
|
|
@@ -257694,7 +258203,7 @@ async function startServe(opts) {
|
|
|
257694
258203
|
...engine2.blobs ? { blobs: engine2.blobs } : {},
|
|
257695
258204
|
actorDirectory: companyRegistry,
|
|
257696
258205
|
actorNames: {
|
|
257697
|
-
resolve: (actorId) => perCompanyActorNames.get(companyId)?.get(actorId)
|
|
258206
|
+
resolve: (actorId) => perCompanyActorNames.get(companyId)?.get(actorId) ?? systemActorFallback(actorId)?.name
|
|
257698
258207
|
},
|
|
257699
258208
|
resolveActorContext: async (actorId) => {
|
|
257700
258209
|
const config2 = await companyRegistry.latestConfig(actorId).catch(() => null);
|
|
@@ -257755,7 +258264,8 @@ async function startServe(opts) {
|
|
|
257755
258264
|
ops: [],
|
|
257756
258265
|
nodeOutputs: persisted.nodeOutputs,
|
|
257757
258266
|
workspaceBindings: persisted.workspaceBindings,
|
|
257758
|
-
|
|
258267
|
+
// 系统身份(`actor:system*`)不在名册里,缓存必然打空——补同一份展示名,别让它退成裸 id。
|
|
258268
|
+
actorNames: { resolve: (actorId) => registryActorNames.get(actorId) ?? systemActorFallback(actorId)?.name }
|
|
257759
258269
|
});
|
|
257760
258270
|
};
|
|
257761
258271
|
const traceDsn = process.env["OASIS_TRACE_PG_DSN"] ?? pgDsn;
|
|
@@ -258275,10 +258785,17 @@ async function startServe(opts) {
|
|
|
258275
258785
|
});
|
|
258276
258786
|
console.log(`[serve] loaded ${builtinSkills.length} builtin skill(s): ${builtinSkills.map((s2) => s2.id).join(", ") || "(none)"}`);
|
|
258277
258787
|
connectorSkills = await readAllConnectorSkills(opts.dir);
|
|
258788
|
+
registeredToolVersions = await readRegisteredToolVersions(opts.dir);
|
|
258278
258789
|
console.log(`[serve] connector skills\uFF08\u843D\u76D8\u526F\u672C\uFF09\uFF1A${connectorSkills.length} \u4E2A`);
|
|
258279
258790
|
refreshConnectorSkillsInBackground(opts.dir, (s2) => {
|
|
258280
258791
|
connectorSkills = s2;
|
|
258281
258792
|
});
|
|
258793
|
+
const connectorSkillTimer = setInterval(() => {
|
|
258794
|
+
refreshConnectorSkillsInBackground(opts.dir, (s2) => {
|
|
258795
|
+
connectorSkills = s2;
|
|
258796
|
+
});
|
|
258797
|
+
}, CONNECTOR_SKILL_REFRESH_MS);
|
|
258798
|
+
connectorSkillTimer.unref?.();
|
|
258282
258799
|
if (defaultCompanyMigration.createdCompany) {
|
|
258283
258800
|
const seededAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
258284
258801
|
for (const devActor of ["actor:human:yx"]) {
|
|
@@ -259148,6 +259665,7 @@ async function startServe(opts) {
|
|
|
259148
259665
|
env: provision.env,
|
|
259149
259666
|
wrapperPaths: provision.wrapperPaths,
|
|
259150
259667
|
...provision.requiredTools.length > 0 ? { requiredTools: provision.requiredTools } : {},
|
|
259668
|
+
...Object.keys(provision.requiredToolVersions).length > 0 ? { requiredToolVersions: provision.requiredToolVersions } : {},
|
|
259151
259669
|
...provision.connectorCreds.length > 0 ? { connectorCreds: provision.connectorCreds } : {}
|
|
259152
259670
|
});
|
|
259153
259671
|
const chunks = [];
|
|
@@ -260133,7 +260651,7 @@ async function startServe(opts) {
|
|
|
260133
260651
|
console.warn(`[trace] chat run ${traceRunId} \u7EED\u8D26\u5F02\u5E38: ${String(err)}`);
|
|
260134
260652
|
});
|
|
260135
260653
|
};
|
|
260136
|
-
const provision = isolatedKnowledgeTurn ? { env: {}, wrapperPaths: [], requiredTools: [], connectorCreds: [], cleanup: async () => void 0 } : await buildActorProvision(actorService, actorId);
|
|
260654
|
+
const provision = isolatedKnowledgeTurn ? { env: {}, wrapperPaths: [], requiredTools: [], requiredToolVersions: {}, connectorCreds: [], cleanup: async () => void 0 } : await buildActorProvision(actorService, actorId);
|
|
260137
260655
|
const actorCtx = await buildActorContext(actorService, actorId).catch(() => null);
|
|
260138
260656
|
const chatResolvedModel = sessionModelOverride ?? actorCtx?.config?.model ?? void 0;
|
|
260139
260657
|
const chatModel = chatResolvedModel ?? await registryStore.getRuntimeConfig(`runtime:${binding.nodeId}:${binding.runtimeKind}`).then((c) => c?.model).catch(() => void 0) ?? void 0;
|
|
@@ -260273,6 +260791,7 @@ async function startServe(opts) {
|
|
|
260273
260791
|
},
|
|
260274
260792
|
wrapperPaths: provision.wrapperPaths,
|
|
260275
260793
|
...provision.requiredTools.length > 0 ? { requiredTools: provision.requiredTools } : {},
|
|
260794
|
+
...Object.keys(provision.requiredToolVersions).length > 0 ? { requiredToolVersions: provision.requiredToolVersions } : {},
|
|
260276
260795
|
...provision.connectorCreds.length > 0 ? { connectorCreds: provision.connectorCreds } : {},
|
|
260277
260796
|
...requiredConnectors.length > 0 ? { requiredConnectorSlugs: requiredConnectors } : {}
|
|
260278
260797
|
});
|
|
@@ -260809,7 +261328,8 @@ async function startServe(opts) {
|
|
|
260809
261328
|
await server.settleDelegationFromSweep(
|
|
260810
261329
|
chatSessionId,
|
|
260811
261330
|
`\u5B50\u4F1A\u8BDD\u8FD9\u4E00\u8F6E\u88AB\u6062\u590D\u5668\u6536\u53E3\u4E3A ${status}\uFF08${reason}\uFF09`,
|
|
260812
|
-
companyId
|
|
261331
|
+
companyId,
|
|
261332
|
+
{ outcome: status === "succeeded" ? "succeeded" : "failed" }
|
|
260813
261333
|
);
|
|
260814
261334
|
},
|
|
260815
261335
|
log: (m2) => console.log(m2),
|
|
@@ -262894,6 +263414,7 @@ ${nodeFault}` : "");
|
|
|
262894
263414
|
if (gitTimer) clearInterval(gitTimer);
|
|
262895
263415
|
if (coordTimer) clearInterval(coordTimer);
|
|
262896
263416
|
if (livenessTimer) clearInterval(livenessTimer);
|
|
263417
|
+
clearInterval(connectorSkillTimer);
|
|
262897
263418
|
if (orphanSweepTimer) clearInterval(orphanSweepTimer);
|
|
262898
263419
|
for (const t of dropSweepTimers) clearInterval(t);
|
|
262899
263420
|
if (deadlineClockTimer) clearInterval(deadlineClockTimer);
|
|
@@ -263092,7 +263613,7 @@ async function runSession(dispatchId, job, deps) {
|
|
|
263092
263613
|
}
|
|
263093
263614
|
}
|
|
263094
263615
|
if (job.requiredTools?.length) {
|
|
263095
|
-
const missing = await ensureConnectorTools(job.requiredTools);
|
|
263616
|
+
const missing = await ensureConnectorTools(job.requiredTools, { versions: job.requiredToolVersions });
|
|
263096
263617
|
if (missing.length) log2("[node-cli]", ` connector tools still missing (agent may fail): ${missing.join(", ")}`);
|
|
263097
263618
|
}
|
|
263098
263619
|
const prepared = await prepareConnectorsForJob(job);
|
|
@@ -263495,7 +264016,7 @@ function detectRuntimes() {
|
|
|
263495
264016
|
|
|
263496
264017
|
// ../cli/src/daemon/workdir-handler.ts
|
|
263497
264018
|
var import_node_fs19 = __toESM(require("node:fs"), 1);
|
|
263498
|
-
var
|
|
264019
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
263499
264020
|
init_src6();
|
|
263500
264021
|
init_src();
|
|
263501
264022
|
var WORKDIR_READ_MAX_BYTES2 = 2 * 1024 * 1024;
|
|
@@ -263514,10 +264035,10 @@ function isSensitiveSegment(segment) {
|
|
|
263514
264035
|
}
|
|
263515
264036
|
function relPathIsSensitive(rel) {
|
|
263516
264037
|
if (!rel) return false;
|
|
263517
|
-
return rel.split(
|
|
264038
|
+
return rel.split(import_node_path26.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
|
|
263518
264039
|
}
|
|
263519
264040
|
function withinBase(p2, base) {
|
|
263520
|
-
return p2 === base || p2.startsWith(base +
|
|
264041
|
+
return p2 === base || p2.startsWith(base + import_node_path26.default.sep);
|
|
263521
264042
|
}
|
|
263522
264043
|
function normalizeRel(raw) {
|
|
263523
264044
|
const trimmed = (raw ?? "").trim();
|
|
@@ -263534,7 +264055,7 @@ async function trustedCanonicalContainer(req, logicalBase, dirKind) {
|
|
|
263534
264055
|
} catch {
|
|
263535
264056
|
return null;
|
|
263536
264057
|
}
|
|
263537
|
-
return isLegacy ?
|
|
264058
|
+
return isLegacy ? import_node_path26.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path26.default.join(trustedRootReal, "sessions", dirKind);
|
|
263538
264059
|
}
|
|
263539
264060
|
async function resolveWithinWorkdir(req) {
|
|
263540
264061
|
const dirKind = sessionDirKind(req.runtimeKind);
|
|
@@ -263552,11 +264073,11 @@ async function resolveWithinWorkdir(req) {
|
|
|
263552
264073
|
} catch {
|
|
263553
264074
|
return { ok: false, code: "NOT_FOUND" };
|
|
263554
264075
|
}
|
|
263555
|
-
if (
|
|
264076
|
+
if (import_node_path26.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
|
|
263556
264077
|
const rel = normalizeRel(req.path);
|
|
263557
|
-
const requested =
|
|
264078
|
+
const requested = import_node_path26.default.resolve(base, rel);
|
|
263558
264079
|
if (!withinBase(requested, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
263559
|
-
const cleanRel = base === requested ? "" :
|
|
264080
|
+
const cleanRel = base === requested ? "" : import_node_path26.default.relative(base, requested);
|
|
263560
264081
|
if (relPathIsSensitive(cleanRel)) return { ok: false, code: "SENSITIVE" };
|
|
263561
264082
|
let real;
|
|
263562
264083
|
try {
|
|
@@ -263566,7 +264087,7 @@ async function resolveWithinWorkdir(req) {
|
|
|
263566
264087
|
return { ok: false, code: "PATH_ESCAPE" };
|
|
263567
264088
|
}
|
|
263568
264089
|
if (!withinBase(real, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
263569
|
-
const realRel = base === real ? "" :
|
|
264090
|
+
const realRel = base === real ? "" : import_node_path26.default.relative(base, real);
|
|
263570
264091
|
if (relPathIsSensitive(realRel)) return { ok: false, code: "SENSITIVE" };
|
|
263571
264092
|
return { ok: true, base, real };
|
|
263572
264093
|
}
|
|
@@ -263602,7 +264123,7 @@ async function handleWorkdirList(req) {
|
|
|
263602
264123
|
const slice = truncated ? visible.slice(0, WORKDIR_LIST_MAX_ENTRIES) : visible;
|
|
263603
264124
|
const entries = [];
|
|
263604
264125
|
for (const d of slice) {
|
|
263605
|
-
const abs =
|
|
264126
|
+
const abs = import_node_path26.default.join(anchor, d.name);
|
|
263606
264127
|
try {
|
|
263607
264128
|
const st = await import_node_fs19.default.promises.lstat(abs);
|
|
263608
264129
|
if (st.isSymbolicLink()) continue;
|
|
@@ -263634,7 +264155,7 @@ async function verifyOpenedFd(fh, base, fallback) {
|
|
|
263634
264155
|
const fdReal = await fdCanonicalPath(fh);
|
|
263635
264156
|
if (fdReal === null) return { anchor: fallback };
|
|
263636
264157
|
if (!withinBase(fdReal, base)) return { error: { ok: false, code: "PATH_ESCAPE" } };
|
|
263637
|
-
const fdRel = base === fdReal ? "" :
|
|
264158
|
+
const fdRel = base === fdReal ? "" : import_node_path26.default.relative(base, fdReal);
|
|
263638
264159
|
if (relPathIsSensitive(fdRel)) return { error: { ok: false, code: "SENSITIVE" } };
|
|
263639
264160
|
return { anchor: `/proc/self/fd/${fh.fd}` };
|
|
263640
264161
|
}
|
|
@@ -263723,7 +264244,7 @@ function looksBinary(bytes2) {
|
|
|
263723
264244
|
function contentTypeFor(absPath, bytes2) {
|
|
263724
264245
|
const sniffed = sniffContentType(bytes2);
|
|
263725
264246
|
if (sniffed) return sniffed;
|
|
263726
|
-
const ext =
|
|
264247
|
+
const ext = import_node_path26.default.extname(absPath).toLowerCase();
|
|
263727
264248
|
if (EXT_CONTENT_TYPE[ext]) return EXT_CONTENT_TYPE[ext];
|
|
263728
264249
|
return looksBinary(bytes2) ? "application/octet-stream" : "text/plain; charset=utf-8";
|
|
263729
264250
|
}
|
|
@@ -264319,17 +264840,17 @@ var RuntimeRouterAdapter = class {
|
|
|
264319
264840
|
// ../cli/src/daemon/reap-claude-projects.ts
|
|
264320
264841
|
var import_node_fs20 = __toESM(require("node:fs"), 1);
|
|
264321
264842
|
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
264322
|
-
var
|
|
264843
|
+
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
264323
264844
|
function claudeProjectSlug(cwd) {
|
|
264324
264845
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
264325
264846
|
}
|
|
264326
264847
|
function claudeProjectsRoot() {
|
|
264327
|
-
const configDir = process.env["CLAUDE_CONFIG_DIR"] ||
|
|
264328
|
-
return
|
|
264848
|
+
const configDir = process.env["CLAUDE_CONFIG_DIR"] || import_node_path27.default.join(import_node_os10.default.homedir(), ".claude");
|
|
264849
|
+
return import_node_path27.default.join(configDir, "projects");
|
|
264329
264850
|
}
|
|
264330
264851
|
function reapClaudeProjects(workdir, runtimeKind) {
|
|
264331
264852
|
if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return;
|
|
264332
|
-
const dir =
|
|
264853
|
+
const dir = import_node_path27.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
|
|
264333
264854
|
if (!import_node_fs20.default.existsSync(dir)) return;
|
|
264334
264855
|
try {
|
|
264335
264856
|
import_node_fs20.default.rmSync(dir, { recursive: true, force: true });
|
|
@@ -264338,7 +264859,7 @@ function reapClaudeProjects(workdir, runtimeKind) {
|
|
|
264338
264859
|
}
|
|
264339
264860
|
function measureClaudeProjects(workdir, runtimeKind) {
|
|
264340
264861
|
if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return 0;
|
|
264341
|
-
const dir =
|
|
264862
|
+
const dir = import_node_path27.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
|
|
264342
264863
|
return dirSizeBytes2(dir);
|
|
264343
264864
|
}
|
|
264344
264865
|
function dirSizeBytes2(dir) {
|
|
@@ -264350,7 +264871,7 @@ function dirSizeBytes2(dir) {
|
|
|
264350
264871
|
return 0;
|
|
264351
264872
|
}
|
|
264352
264873
|
for (const e of entries) {
|
|
264353
|
-
const p2 =
|
|
264874
|
+
const p2 = import_node_path27.default.join(dir, e.name);
|
|
264354
264875
|
if (e.isSymbolicLink()) continue;
|
|
264355
264876
|
if (e.isDirectory()) {
|
|
264356
264877
|
total += dirSizeBytes2(p2);
|
|
@@ -266761,7 +267282,7 @@ function fieldsFromFlags(flags, ownFlags) {
|
|
|
266761
267282
|
}
|
|
266762
267283
|
return Object.keys(fields).length > 0 ? fields : void 0;
|
|
266763
267284
|
}
|
|
266764
|
-
function buildStageOp(cmd, flags, positional,
|
|
267285
|
+
function buildStageOp(cmd, flags, positional, readFile9 = (file) => fs39.readFileSync(file, "utf8")) {
|
|
266765
267286
|
switch (cmd) {
|
|
266766
267287
|
case "link":
|
|
266767
267288
|
return {
|
|
@@ -266783,7 +267304,7 @@ function buildStageOp(cmd, flags, positional, readFile8 = (file) => fs39.readFil
|
|
|
266783
267304
|
...flags.get("title") !== void 0 ? { title: flags.get("title") } : {},
|
|
266784
267305
|
...(flags.get("brief") ?? flags.get("description")) !== void 0 ? { description: flags.get("brief") ?? flags.get("description") } : {},
|
|
266785
267306
|
...flags.get("input") !== void 0 ? { inputs: flags.get("input").split(",").map((to) => ({ to: to.trim() })) } : {},
|
|
266786
|
-
...partsFile !== void 0 ? { parts: JSON.parse(
|
|
267307
|
+
...partsFile !== void 0 ? { parts: JSON.parse(readFile9(partsFile)) } : {},
|
|
266787
267308
|
...fields !== void 0 ? { fields } : {}
|
|
266788
267309
|
};
|
|
266789
267310
|
}
|
|
@@ -270150,7 +270671,7 @@ function shimScript() {
|
|
|
270150
270671
|
}
|
|
270151
270672
|
|
|
270152
270673
|
// src/index.ts
|
|
270153
|
-
var PKG_VERSION = true ? "2.2.
|
|
270674
|
+
var PKG_VERSION = true ? "2.2.9" : "dev";
|
|
270154
270675
|
var LOCAL_BIN = localBin();
|
|
270155
270676
|
var NPM_PREFIX = npmPrefix();
|
|
270156
270677
|
var INSTANCE = DEFAULT_INSTANCE;
|