@clawos-dev/clawd 0.2.613 → 0.2.614
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/app-builder-plugin/mcp-server.cjs +4 -0
- package/dist/cli.cjs +405 -62
- package/dist/cloud-persona-conversations.html +2 -2
- package/dist/dispatch/mcp-server.cjs +4 -0
- package/dist/persona-defaults/persona-app-builder/mcp/clawd-app-builder/mcp-server.cjs +4 -0
- package/dist/persona-defaults/persona-dataclaw-builder/mcp/clawd-app-builder/mcp-server.cjs +4 -0
- package/dist/share-ui/assets/{guest-BXOhTM3E.js → guest-Bx73wM5k.js} +84 -84
- package/dist/share-ui/guest.html +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -8168,6 +8168,10 @@ var init_schemas = __esm({
|
|
|
8168
8168
|
sessionId: external_exports.string().min(1),
|
|
8169
8169
|
/** New gateway execution identity after session:new; defaults to sessionId for the first execution. */
|
|
8170
8170
|
cloudExecutionId: external_exports.string().min(1).optional(),
|
|
8171
|
+
/** First turn ID of the per-query SSE conversation. */
|
|
8172
|
+
cloudConversationId: external_exports.string().min(1).optional(),
|
|
8173
|
+
/** Accepted local turns whose terminal gateway status has not been observed. */
|
|
8174
|
+
cloudPendingTurns: external_exports.array(external_exports.object({ id: external_exports.string().min(1), text: external_exports.string(), prepared: external_exports.boolean().optional() })).optional(),
|
|
8171
8175
|
/** Owner gateway session observed in ready; proves the remote Pod was opened. */
|
|
8172
8176
|
cloudGatewaySessionId: external_exports.string().min(1).optional(),
|
|
8173
8177
|
/** Persisted before sending so daemon restart can retry the same gateway command ID. */
|
|
@@ -44805,7 +44809,7 @@ Env (advanced):
|
|
|
44805
44809
|
var import_node_path85 = __toESM(require("path"), 1);
|
|
44806
44810
|
var import_node_fs66 = __toESM(require("fs"), 1);
|
|
44807
44811
|
var import_node_os31 = __toESM(require("os"), 1);
|
|
44808
|
-
var
|
|
44812
|
+
var import_node_crypto29 = require("crypto");
|
|
44809
44813
|
var import_node_url6 = require("url");
|
|
44810
44814
|
|
|
44811
44815
|
// src/logger.ts
|
|
@@ -46120,6 +46124,8 @@ function buildSpawnContext(state, deps) {
|
|
|
46120
46124
|
const ctx = {
|
|
46121
46125
|
cwd: file.cwd,
|
|
46122
46126
|
cloudExecutionId: file.cloudExecutionId,
|
|
46127
|
+
...file.cloudConversationId ? { cloudConversationId: file.cloudConversationId } : {},
|
|
46128
|
+
...file.cloudPendingCommand && !file.cloudPendingTurns ? { cloudLegacyPendingCommand: true } : {},
|
|
46123
46129
|
cloudGatewaySessionId: file.cloudGatewaySessionId,
|
|
46124
46130
|
toolSessionId: file.toolSessionId,
|
|
46125
46131
|
model: file.model,
|
|
@@ -46375,10 +46381,16 @@ function pushEventToBufferInPlace(next, event, deps) {
|
|
|
46375
46381
|
}
|
|
46376
46382
|
}
|
|
46377
46383
|
if (isUserText || isTurnEnd) {
|
|
46384
|
+
const cloudTurnId = isUserText ? withSeq.uuid ?? `${next.file.sessionId}-${seq}` : void 0;
|
|
46385
|
+
const cloudPerTurn = isCloudTool(next.file.tool) && !next.file.cloudGatewaySessionId && (!next.file.cloudPendingCommand || !!next.file.cloudPendingTurns);
|
|
46378
46386
|
next.file = {
|
|
46379
46387
|
...next.file,
|
|
46380
46388
|
updatedAt: nowIso(deps),
|
|
46381
|
-
...
|
|
46389
|
+
...cloudPerTurn && isUserText && next.status !== "error" ? {
|
|
46390
|
+
cloudConversationId: next.file.cloudConversationId ?? next.file.cloudExecutionId ?? cloudTurnId,
|
|
46391
|
+
cloudPendingTurns: [...next.file.cloudPendingTurns ?? [], { id: cloudTurnId, text: withSeq.text }]
|
|
46392
|
+
} : {},
|
|
46393
|
+
...!cloudPerTurn && isCloudTool(next.file.tool) && next.status !== "error" && !(withSeq.kind === "turn_end" && withSeq.reason === "interrupted") ? { cloudPendingCommand: withSeq.kind === "user_text" ? { id: withSeq.uuid ?? `${next.file.sessionId}-${seq}`, text: withSeq.text } : void 0 } : {}
|
|
46382
46394
|
};
|
|
46383
46395
|
effects.push({ kind: "persist-file", file: next.file });
|
|
46384
46396
|
effects.push(sessionInfoFrame(next.file));
|
|
@@ -46443,7 +46455,7 @@ function applyCommand(state, command, deps) {
|
|
|
46443
46455
|
const sessionId = next.file.sessionId;
|
|
46444
46456
|
switch (command.kind) {
|
|
46445
46457
|
case "send": {
|
|
46446
|
-
if (command.queueWhileRunning && (next.status === "running" || next.status === "spawning")) {
|
|
46458
|
+
if (command.queueWhileRunning && !(isCloudTool(next.file.tool) && !next.file.cloudGatewaySessionId) && (next.status === "running" || next.status === "spawning")) {
|
|
46447
46459
|
next.queuedSends = [
|
|
46448
46460
|
...next.queuedSends,
|
|
46449
46461
|
{
|
|
@@ -46495,8 +46507,8 @@ function applyCommand(state, command, deps) {
|
|
|
46495
46507
|
return { state: next, effects };
|
|
46496
46508
|
}
|
|
46497
46509
|
case "stop": {
|
|
46498
|
-
if (isCloudTool(next.file.tool) && next.file.cloudPendingCommand) {
|
|
46499
|
-
next.file = { ...next.file, cloudPendingCommand: void 0 };
|
|
46510
|
+
if (isCloudTool(next.file.tool) && (next.file.cloudPendingCommand || next.file.cloudPendingTurns?.length)) {
|
|
46511
|
+
next.file = { ...next.file, cloudPendingCommand: void 0, cloudPendingTurns: void 0 };
|
|
46500
46512
|
effects.push({ kind: "persist-file", file: next.file }, sessionInfoFrame(next.file));
|
|
46501
46513
|
}
|
|
46502
46514
|
for (const toolUseId of Object.keys(state.pendingQuestions ?? {})) {
|
|
@@ -46634,6 +46646,9 @@ function applyCommand(state, command, deps) {
|
|
|
46634
46646
|
toolSessionId: _drop,
|
|
46635
46647
|
cloudPendingCommand: _cloudPendingCommand,
|
|
46636
46648
|
cloudGatewaySessionId: _cloudGatewaySessionId,
|
|
46649
|
+
cloudConversationId: _cloudConversationId,
|
|
46650
|
+
cloudPendingTurns: _cloudPendingTurns,
|
|
46651
|
+
cloudExecutionId: _cloudExecutionId,
|
|
46637
46652
|
contextUsage: _ctx,
|
|
46638
46653
|
contextWindowSize: _win,
|
|
46639
46654
|
gitBranch: _branch,
|
|
@@ -46646,6 +46661,9 @@ function applyCommand(state, command, deps) {
|
|
|
46646
46661
|
void _drop;
|
|
46647
46662
|
void _cloudPendingCommand;
|
|
46648
46663
|
void _cloudGatewaySessionId;
|
|
46664
|
+
void _cloudConversationId;
|
|
46665
|
+
void _cloudPendingTurns;
|
|
46666
|
+
void _cloudExecutionId;
|
|
46649
46667
|
void _ctx;
|
|
46650
46668
|
void _win;
|
|
46651
46669
|
void _branch;
|
|
@@ -46731,9 +46749,16 @@ function reduceSessionInner(state, input, deps) {
|
|
|
46731
46749
|
}
|
|
46732
46750
|
case "cloud-command-prepared": {
|
|
46733
46751
|
const pending = state.file.cloudPendingCommand;
|
|
46734
|
-
|
|
46752
|
+
const turn = state.file.cloudPendingTurns?.find((item) => item.id === input.commandId);
|
|
46753
|
+
if ((!pending || pending.id !== input.commandId) && !turn) return { state, effects: [] };
|
|
46754
|
+
const next = cloneState(state);
|
|
46755
|
+
next.file = turn ? { ...next.file, cloudPendingTurns: next.file.cloudPendingTurns?.map((item) => item.id === input.commandId ? { ...item, text: input.text, prepared: true } : item) } : { ...next.file, cloudPendingCommand: { id: pending.id, text: input.text, prepared: true } };
|
|
46756
|
+
return { state: next, effects: [{ kind: "persist-file", file: next.file }] };
|
|
46757
|
+
}
|
|
46758
|
+
case "cloud-turn-terminal": {
|
|
46759
|
+
if (!state.file.cloudPendingTurns?.some((item) => item.id === input.turnId)) return { state, effects: [] };
|
|
46735
46760
|
const next = cloneState(state);
|
|
46736
|
-
next.file = { ...next.file,
|
|
46761
|
+
next.file = { ...next.file, cloudPendingTurns: next.file.cloudPendingTurns?.filter((item) => item.id !== input.turnId) };
|
|
46737
46762
|
return { state: next, effects: [{ kind: "persist-file", file: next.file }] };
|
|
46738
46763
|
}
|
|
46739
46764
|
case "proc-exit": {
|
|
@@ -47243,6 +47268,7 @@ var SessionRunner = class {
|
|
|
47243
47268
|
this.input({ kind: "command", command: { kind: "spawn-if-needed" } });
|
|
47244
47269
|
const pending = this.state.file.cloudPendingCommand;
|
|
47245
47270
|
if (pending) this.session?.startTurn(pending.text, pending.id, pending.prepared === true);
|
|
47271
|
+
for (const turn of this.state.file.cloudPendingTurns ?? []) this.session?.startTurn(turn.text, turn.id, turn.prepared === true);
|
|
47246
47272
|
} finally {
|
|
47247
47273
|
this.recoveringCloud = false;
|
|
47248
47274
|
}
|
|
@@ -47440,7 +47466,7 @@ var SessionRunner = class {
|
|
|
47440
47466
|
break;
|
|
47441
47467
|
case "write-stdin":
|
|
47442
47468
|
if (this.session) {
|
|
47443
|
-
this.session.startTurn(effect.payload, this.state.file.cloudPendingCommand?.id);
|
|
47469
|
+
this.session.startTurn(effect.payload, this.state.file.cloudPendingTurns?.at(-1)?.id ?? this.state.file.cloudPendingCommand?.id);
|
|
47444
47470
|
break;
|
|
47445
47471
|
}
|
|
47446
47472
|
this.hooks.logger?.debug("[RG] write-stdin", {
|
|
@@ -47585,14 +47611,15 @@ var SessionRunner = class {
|
|
|
47585
47611
|
this.input({ kind: "cloud-gateway-ready", gatewaySessionId });
|
|
47586
47612
|
},
|
|
47587
47613
|
onCommandPrepared: (commandId, text, prepared) => {
|
|
47588
|
-
const pending = this.state.file.cloudPendingCommand;
|
|
47614
|
+
const pending = this.state.file.cloudPendingTurns?.find((turn) => turn.id === commandId) ?? this.state.file.cloudPendingCommand;
|
|
47589
47615
|
if (!pending || pending.id !== commandId || prepared && pending.text !== text) return false;
|
|
47590
47616
|
if (!prepared) {
|
|
47591
|
-
this.hooks.store.write({ ...this.state.file, cloudPendingCommand: { id: commandId, text, prepared: true } });
|
|
47617
|
+
this.hooks.store.write(this.state.file.cloudPendingTurns?.some((turn) => turn.id === commandId) ? { ...this.state.file, cloudPendingTurns: this.state.file.cloudPendingTurns.map((turn) => turn.id === commandId ? { ...turn, text, prepared: true } : turn) } : { ...this.state.file, cloudPendingCommand: { id: commandId, text, prepared: true } });
|
|
47592
47618
|
this.input({ kind: "cloud-command-prepared", commandId, text });
|
|
47593
47619
|
}
|
|
47594
47620
|
return true;
|
|
47595
|
-
}
|
|
47621
|
+
},
|
|
47622
|
+
onCloudTurnTerminal: (turnId) => this.input({ kind: "cloud-turn-terminal", turnId })
|
|
47596
47623
|
});
|
|
47597
47624
|
return;
|
|
47598
47625
|
}
|
|
@@ -48662,11 +48689,10 @@ var SessionManager = class {
|
|
|
48662
48689
|
if (!file) throw new ClawdError(ERROR_CODES.SESSION_NOT_FOUND, args.sessionId);
|
|
48663
48690
|
const runner = this.runners.get(args.sessionId) ?? null;
|
|
48664
48691
|
if (isCloudTool(file.tool)) {
|
|
48665
|
-
if (
|
|
48666
|
-
else if (file.cloudPendingCommand || runner?.getState().procAlive) {
|
|
48692
|
+
if (file.cloudConversationId || file.cloudGatewaySessionId) {
|
|
48667
48693
|
if (!this.cloudCancel) throw new Error("cloud canceller is not configured");
|
|
48668
48694
|
await this.cloudCancel(file, runner);
|
|
48669
|
-
}
|
|
48695
|
+
} else runner?.confirmCloudCancelled();
|
|
48670
48696
|
}
|
|
48671
48697
|
return this.delete(args);
|
|
48672
48698
|
}
|
|
@@ -48836,14 +48862,13 @@ var SessionManager = class {
|
|
|
48836
48862
|
const file = this.findOwnedSession(args.sessionId);
|
|
48837
48863
|
const runner = this.runners.get(args.sessionId);
|
|
48838
48864
|
if (file && isCloudTool(file.tool)) {
|
|
48839
|
-
if (
|
|
48840
|
-
else if (file.cloudPendingCommand || runner?.getState().procAlive) {
|
|
48865
|
+
if (file.cloudConversationId || file.cloudGatewaySessionId) {
|
|
48841
48866
|
if (!this.cloudCancel) throw new Error("cloud canceller is not configured");
|
|
48842
48867
|
await this.cloudCancel(file, runner ?? null);
|
|
48843
|
-
}
|
|
48868
|
+
} else runner?.confirmCloudCancelled();
|
|
48844
48869
|
}
|
|
48845
48870
|
if (!runner) {
|
|
48846
|
-
if (file && isCloudTool(file.tool) && file.cloudPendingCommand) this.writeOwned({ ...file, cloudPendingCommand: void 0 });
|
|
48871
|
+
if (file && isCloudTool(file.tool) && (file.cloudPendingCommand || file.cloudPendingTurns?.length)) this.writeOwned({ ...file, cloudPendingCommand: void 0, cloudPendingTurns: void 0 });
|
|
48847
48872
|
return { response: { ok: true }, broadcast: [] };
|
|
48848
48873
|
}
|
|
48849
48874
|
this.clearPendingTurnEnd(args.sessionId);
|
|
@@ -49009,6 +49034,9 @@ var SessionManager = class {
|
|
|
49009
49034
|
toolSessionId: _drop,
|
|
49010
49035
|
cloudPendingCommand: _cloudPendingCommand,
|
|
49011
49036
|
cloudGatewaySessionId: _cloudGatewaySessionId,
|
|
49037
|
+
cloudConversationId: _cloudConversationId,
|
|
49038
|
+
cloudPendingTurns: _cloudPendingTurns,
|
|
49039
|
+
cloudExecutionId: _cloudExecutionId,
|
|
49012
49040
|
contextUsage: _ctx,
|
|
49013
49041
|
contextWindowSize: _win,
|
|
49014
49042
|
gitBranch: _branch,
|
|
@@ -49020,6 +49048,9 @@ var SessionManager = class {
|
|
|
49020
49048
|
void _drop;
|
|
49021
49049
|
void _cloudPendingCommand;
|
|
49022
49050
|
void _cloudGatewaySessionId;
|
|
49051
|
+
void _cloudConversationId;
|
|
49052
|
+
void _cloudPendingTurns;
|
|
49053
|
+
void _cloudExecutionId;
|
|
49023
49054
|
void _ctx;
|
|
49024
49055
|
void _win;
|
|
49025
49056
|
void _branch;
|
|
@@ -49038,12 +49069,11 @@ var SessionManager = class {
|
|
|
49038
49069
|
const file = this.getFile(args.sessionId);
|
|
49039
49070
|
if (isCloudTool(file.tool)) {
|
|
49040
49071
|
const runner = this.runners.get(args.sessionId) ?? null;
|
|
49041
|
-
if (
|
|
49042
|
-
else if (file.cloudPendingCommand || runner?.getState().procAlive) {
|
|
49072
|
+
if (file.cloudConversationId || file.cloudGatewaySessionId) {
|
|
49043
49073
|
if (!this.cloudCancel) throw new Error("cloud canceller is not configured");
|
|
49044
49074
|
await this.cloudCancel(file, runner);
|
|
49045
|
-
}
|
|
49046
|
-
return this.newSession(args, (0, import_node_crypto3.randomUUID)());
|
|
49075
|
+
} else runner?.confirmCloudCancelled();
|
|
49076
|
+
return this.newSession(args, file.cloudGatewaySessionId ? (0, import_node_crypto3.randomUUID)() : void 0);
|
|
49047
49077
|
}
|
|
49048
49078
|
return this.newSession(args);
|
|
49049
49079
|
}
|
|
@@ -49114,7 +49144,7 @@ var SessionManager = class {
|
|
|
49114
49144
|
/** Reattach only to executions whose last turn lacks a durable end marker. */
|
|
49115
49145
|
recoverCloudSessions() {
|
|
49116
49146
|
for (const file of this.listAllOwned()) {
|
|
49117
|
-
if (!isCloudTool(file.tool) || !file.cloudPendingCommand) continue;
|
|
49147
|
+
if (!isCloudTool(file.tool) || !file.cloudPendingCommand && !file.cloudPendingTurns?.length) continue;
|
|
49118
49148
|
const runner = this.ensureSession(file);
|
|
49119
49149
|
runner.recoverCloud();
|
|
49120
49150
|
}
|
|
@@ -64751,6 +64781,9 @@ var GATEWAY_ROUTES = {
|
|
|
64751
64781
|
eventSession: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session/events`,
|
|
64752
64782
|
eventCancel: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session/events:cancel`,
|
|
64753
64783
|
eventSend: (personaId2, sessionId) => `/p/${encodeURIComponent(personaId2)}/session/events/${encodeURIComponent(sessionId)}`,
|
|
64784
|
+
turn: (personaId2) => `/p/${encodeURIComponent(personaId2)}/v1/chat/completions`,
|
|
64785
|
+
turnCommand: (personaId2, turnId) => `/p/${encodeURIComponent(personaId2)}/turns/${encodeURIComponent(turnId)}/commands`,
|
|
64786
|
+
conversationCancel: (personaId2, conversationId) => `/p/${encodeURIComponent(personaId2)}/conversations/${encodeURIComponent(conversationId)}:cancel`,
|
|
64754
64787
|
// 调用方自己那块盘的用量(design 2026-09-19-cloud-volume-usage §3.3):同样按人、不挂 persona
|
|
64755
64788
|
volume: () => "/me/volume",
|
|
64756
64789
|
// 云 persona 运行看板的数据(design 2026-09-23-cloud-persona-metrics §3.6):只给发布者与管理员(gateway 问中心,design 2026-09-24-cloud-persona-conversations §3.2)
|
|
@@ -64892,6 +64925,32 @@ var CloudGatewayClient = class {
|
|
|
64892
64925
|
logger: this.deps.logger
|
|
64893
64926
|
});
|
|
64894
64927
|
}
|
|
64928
|
+
async openTurn(personaId2, opts) {
|
|
64929
|
+
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64930
|
+
const health = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.healthz());
|
|
64931
|
+
if (!health.ok || (await health.json()).turnProtocolVersion !== 1) {
|
|
64932
|
+
throw new Error("\u4E91 gateway \u4E0D\u652F\u6301\u6309\u8F6E SSE\uFF0C\u8BF7\u5148\u5347\u7EA7 gateway");
|
|
64933
|
+
}
|
|
64934
|
+
return openHttpTurn({ ...opts, fetchImpl: this.fetchImpl, gatewayUrl, apiKey, personaId: personaId2, logger: this.deps.logger });
|
|
64935
|
+
}
|
|
64936
|
+
async commandTurn(personaId2, conversationId, turnId, command) {
|
|
64937
|
+
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64938
|
+
const res = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.turnCommand(personaId2, turnId), {
|
|
64939
|
+
method: "POST",
|
|
64940
|
+
headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json", "x-clawd-turn-protocol": "1" },
|
|
64941
|
+
body: JSON.stringify({ conversationId, ...command })
|
|
64942
|
+
});
|
|
64943
|
+
if (!res.ok) throw new Error(`gateway turn command returned ${res.status}`);
|
|
64944
|
+
}
|
|
64945
|
+
async cancelConversation(personaId2, conversationId) {
|
|
64946
|
+
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64947
|
+
const res = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.conversationCancel(personaId2, conversationId), {
|
|
64948
|
+
method: "POST",
|
|
64949
|
+
headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json", "x-clawd-turn-protocol": "1" },
|
|
64950
|
+
body: "{}"
|
|
64951
|
+
});
|
|
64952
|
+
if (!res.ok) throw new Error(`gateway conversation cancel returned ${res.status}`);
|
|
64953
|
+
}
|
|
64895
64954
|
async cancelEventSession(personaId2, clientSessionId, gatewaySessionId) {
|
|
64896
64955
|
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64897
64956
|
const res = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.eventCancel(personaId2), {
|
|
@@ -64964,6 +65023,152 @@ var CloudGatewayClient = class {
|
|
|
64964
65023
|
return CloudVolumeUsageSchema.parse(body.volume);
|
|
64965
65024
|
}
|
|
64966
65025
|
};
|
|
65026
|
+
function openHttpTurn(opts) {
|
|
65027
|
+
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, conversationId, turnId, text, expectedEngine, engineSessionId, instructions, effort, personaMode, logger } = opts;
|
|
65028
|
+
const body = JSON.stringify({
|
|
65029
|
+
messages: [{ role: "user", content: text }],
|
|
65030
|
+
stream: true,
|
|
65031
|
+
clawd: {
|
|
65032
|
+
eventMode: "parsed",
|
|
65033
|
+
conversationId,
|
|
65034
|
+
turnId,
|
|
65035
|
+
expectedEngine,
|
|
65036
|
+
...engineSessionId ? { engineSessionId } : {},
|
|
65037
|
+
...instructions ? { instructions } : {},
|
|
65038
|
+
...effort ? { effort } : {},
|
|
65039
|
+
...personaMode ? { personaMode } : {}
|
|
65040
|
+
}
|
|
65041
|
+
});
|
|
65042
|
+
const eventsCbs = [];
|
|
65043
|
+
const stateCbs = [];
|
|
65044
|
+
const gapCbs = [];
|
|
65045
|
+
const closeCbs = [];
|
|
65046
|
+
const earlyEvents = [];
|
|
65047
|
+
const earlyStates = [];
|
|
65048
|
+
let earlyGap = false;
|
|
65049
|
+
let closed = false;
|
|
65050
|
+
let lastSeq = 0;
|
|
65051
|
+
let abort = new AbortController();
|
|
65052
|
+
const finish = () => {
|
|
65053
|
+
if (closed) return;
|
|
65054
|
+
closed = true;
|
|
65055
|
+
abort.abort();
|
|
65056
|
+
for (const cb of closeCbs) cb();
|
|
65057
|
+
};
|
|
65058
|
+
const state = (value) => {
|
|
65059
|
+
if (!stateCbs.length) earlyStates.push(value);
|
|
65060
|
+
for (const cb of stateCbs) cb(value);
|
|
65061
|
+
if (value.status === "completed" || value.status === "failed" || value.status === "cancelled") finish();
|
|
65062
|
+
};
|
|
65063
|
+
const gap = () => {
|
|
65064
|
+
if (!gapCbs.length) earlyGap = true;
|
|
65065
|
+
for (const cb of gapCbs) cb();
|
|
65066
|
+
};
|
|
65067
|
+
const retryWait = () => new Promise((resolve9) => {
|
|
65068
|
+
const timer = setTimeout(resolve9, 250);
|
|
65069
|
+
timer.unref?.();
|
|
65070
|
+
abort.signal.addEventListener("abort", () => {
|
|
65071
|
+
clearTimeout(timer);
|
|
65072
|
+
resolve9();
|
|
65073
|
+
}, { once: true });
|
|
65074
|
+
});
|
|
65075
|
+
void (async () => {
|
|
65076
|
+
while (!closed) {
|
|
65077
|
+
abort = new AbortController();
|
|
65078
|
+
try {
|
|
65079
|
+
const res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.turn(personaId2), {
|
|
65080
|
+
method: "POST",
|
|
65081
|
+
headers: {
|
|
65082
|
+
authorization: `Bearer ${apiKey}`,
|
|
65083
|
+
"content-type": "application/json",
|
|
65084
|
+
"x-clawd-turn-protocol": "1",
|
|
65085
|
+
...lastSeq ? { "last-event-id": String(lastSeq) } : {}
|
|
65086
|
+
},
|
|
65087
|
+
body,
|
|
65088
|
+
signal: abort.signal
|
|
65089
|
+
});
|
|
65090
|
+
if (!res.ok || !res.body) {
|
|
65091
|
+
const raw = await res.text().catch(() => "");
|
|
65092
|
+
let code = `HTTP_${res.status}`;
|
|
65093
|
+
try {
|
|
65094
|
+
const parsed = JSON.parse(raw);
|
|
65095
|
+
code = parsed.error?.code ?? code;
|
|
65096
|
+
} catch {
|
|
65097
|
+
}
|
|
65098
|
+
if ([400, 401, 403, 404, 409, 410, 426].includes(res.status)) {
|
|
65099
|
+
state({ conversationId, turnId, status: "failed", errorCode: code });
|
|
65100
|
+
return;
|
|
65101
|
+
}
|
|
65102
|
+
throw new Error(`gateway returned ${res.status}`);
|
|
65103
|
+
}
|
|
65104
|
+
const reader = res.body.getReader();
|
|
65105
|
+
const decoder = new TextDecoder();
|
|
65106
|
+
let pending = "";
|
|
65107
|
+
for (; ; ) {
|
|
65108
|
+
const { value, done } = await reader.read();
|
|
65109
|
+
if (done || closed) break;
|
|
65110
|
+
pending += decoder.decode(value, { stream: true });
|
|
65111
|
+
let delimiter2;
|
|
65112
|
+
while ((delimiter2 = /\r?\n\r?\n/.exec(pending)) !== null) {
|
|
65113
|
+
const frame = pending.slice(0, delimiter2.index);
|
|
65114
|
+
pending = pending.slice(delimiter2.index + delimiter2[0].length);
|
|
65115
|
+
if (!frame || frame.startsWith(":")) continue;
|
|
65116
|
+
const lines = frame.split(/\r?\n/);
|
|
65117
|
+
const name = lines.find((line) => line.startsWith("event: "))?.slice(7);
|
|
65118
|
+
const dataLine = lines.find((line) => line.startsWith("data: "));
|
|
65119
|
+
if (!name || !dataLine) throw new Error("invalid Clawd SSE frame");
|
|
65120
|
+
const id = lines.find((line) => line.startsWith("id: "))?.slice(4);
|
|
65121
|
+
const seq = id === void 0 ? null : Number(id);
|
|
65122
|
+
if (seq !== null && (!Number.isSafeInteger(seq) || seq < 0)) throw new Error("invalid Clawd SSE cursor");
|
|
65123
|
+
if (seq !== null && seq <= lastSeq) continue;
|
|
65124
|
+
if (seq !== null) lastSeq = seq;
|
|
65125
|
+
const data = JSON.parse(dataLine.slice(6));
|
|
65126
|
+
if (data.turnId !== void 0 && data.turnId !== turnId) throw new Error("Clawd SSE turn ID mismatch");
|
|
65127
|
+
if (name === "events") {
|
|
65128
|
+
const events = ParsedEventSchema.array().parse(data.events);
|
|
65129
|
+
if (!eventsCbs.length) earlyEvents.push(events);
|
|
65130
|
+
for (const cb of eventsCbs) cb(events);
|
|
65131
|
+
} else if (name === "history-gap") gap();
|
|
65132
|
+
else if (["inqueue", "running", "completed", "failed", "cancelled"].includes(name)) {
|
|
65133
|
+
state({ ...data, conversationId, turnId, status: name });
|
|
65134
|
+
} else throw new Error(`unknown Clawd SSE event ${name}`);
|
|
65135
|
+
if (closed) return;
|
|
65136
|
+
}
|
|
65137
|
+
}
|
|
65138
|
+
} catch (error) {
|
|
65139
|
+
if (closed) return;
|
|
65140
|
+
if (error instanceof SyntaxError || error.name === "ZodError" || error.message.startsWith("invalid Clawd SSE")) {
|
|
65141
|
+
state({ conversationId, turnId, status: "failed", errorCode: "INVALID_TURN_STREAM" });
|
|
65142
|
+
return;
|
|
65143
|
+
}
|
|
65144
|
+
logger?.warn("cloud turn SSE disconnected; reconnecting", { message: error.message, turnId });
|
|
65145
|
+
}
|
|
65146
|
+
if (!closed) await retryWait();
|
|
65147
|
+
}
|
|
65148
|
+
})();
|
|
65149
|
+
return {
|
|
65150
|
+
onEvents(cb) {
|
|
65151
|
+
eventsCbs.push(cb);
|
|
65152
|
+
for (const events of earlyEvents.splice(0)) cb(events);
|
|
65153
|
+
},
|
|
65154
|
+
onState(cb) {
|
|
65155
|
+
stateCbs.push(cb);
|
|
65156
|
+
for (const item of earlyStates.splice(0)) cb(item);
|
|
65157
|
+
},
|
|
65158
|
+
onHistoryGap(cb) {
|
|
65159
|
+
gapCbs.push(cb);
|
|
65160
|
+
if (earlyGap) {
|
|
65161
|
+
earlyGap = false;
|
|
65162
|
+
cb();
|
|
65163
|
+
}
|
|
65164
|
+
},
|
|
65165
|
+
onClose(cb) {
|
|
65166
|
+
closeCbs.push(cb);
|
|
65167
|
+
if (closed) cb();
|
|
65168
|
+
},
|
|
65169
|
+
close: finish
|
|
65170
|
+
};
|
|
65171
|
+
}
|
|
64967
65172
|
function openHttpEventSession(opts) {
|
|
64968
65173
|
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, clientSessionId, gatewaySessionId, engineSessionId, instructions, purpose, effort, personaMode, attachOnly, expectedEngine, logger } = opts;
|
|
64969
65174
|
const headers = { authorization: `Bearer ${apiKey}`, "content-type": "application/json" };
|
|
@@ -65482,7 +65687,7 @@ init_protocol();
|
|
|
65482
65687
|
|
|
65483
65688
|
// src/tools/codex-cloud-session.ts
|
|
65484
65689
|
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
65485
|
-
var
|
|
65690
|
+
var import_node_crypto14 = require("crypto");
|
|
65486
65691
|
|
|
65487
65692
|
// src/tools/cloud-portable-input.ts
|
|
65488
65693
|
async function portableCloudInput(text, resolvers) {
|
|
@@ -65502,6 +65707,116 @@ async function portableCloudInput(text, resolvers) {
|
|
|
65502
65707
|
return result;
|
|
65503
65708
|
}
|
|
65504
65709
|
|
|
65710
|
+
// src/tools/cloud-turn-session.ts
|
|
65711
|
+
var import_node_crypto13 = require("crypto");
|
|
65712
|
+
function createCloudTurnSession(args) {
|
|
65713
|
+
const { ctx, sink, client, personaId: personaId2, engine, instructions, engineSessionId, prepare } = args;
|
|
65714
|
+
let conversationId = ctx.cloudConversationId ?? ctx.cloudExecutionId;
|
|
65715
|
+
let closed = false;
|
|
65716
|
+
let detached = false;
|
|
65717
|
+
let exited = false;
|
|
65718
|
+
let stopping = null;
|
|
65719
|
+
const streams = /* @__PURE__ */ new Map();
|
|
65720
|
+
const live = /* @__PURE__ */ new Set();
|
|
65721
|
+
let submission = Promise.resolve();
|
|
65722
|
+
const exit = () => {
|
|
65723
|
+
if (!exited) {
|
|
65724
|
+
exited = true;
|
|
65725
|
+
sink.onExit(null);
|
|
65726
|
+
}
|
|
65727
|
+
};
|
|
65728
|
+
const sendCommand = (turnId, command) => {
|
|
65729
|
+
if (!conversationId || closed) return;
|
|
65730
|
+
void client.commandTurn(personaId2, conversationId, turnId, command).catch((e) => sink.onError(`\u4E91\u4E0A\u547D\u4EE4\u5931\u8D25\uFF1A${e.message}`));
|
|
65731
|
+
};
|
|
65732
|
+
return {
|
|
65733
|
+
startTurn(text, commandId = (0, import_node_crypto13.randomUUID)(), prepared = false) {
|
|
65734
|
+
if (closed || live.has(commandId)) return;
|
|
65735
|
+
conversationId ??= commandId;
|
|
65736
|
+
live.add(commandId);
|
|
65737
|
+
submission = submission.then(async () => {
|
|
65738
|
+
try {
|
|
65739
|
+
const portable = prepared ? text : await prepare(text);
|
|
65740
|
+
if (closed || sink.onCommandPrepared?.(commandId, portable, prepared) === false) {
|
|
65741
|
+
live.delete(commandId);
|
|
65742
|
+
return;
|
|
65743
|
+
}
|
|
65744
|
+
const stream = await client.openTurn(personaId2, {
|
|
65745
|
+
conversationId,
|
|
65746
|
+
turnId: commandId,
|
|
65747
|
+
text: portable,
|
|
65748
|
+
expectedEngine: engine,
|
|
65749
|
+
...engine === "pi" ? { engineSessionId: engineSessionId ?? conversationId } : {},
|
|
65750
|
+
...instructions ? { instructions } : {},
|
|
65751
|
+
...ctx.effort ? { effort: ctx.effort } : {},
|
|
65752
|
+
...ctx.personaMode ? { personaMode: ctx.personaMode } : {}
|
|
65753
|
+
});
|
|
65754
|
+
if (closed) {
|
|
65755
|
+
stream.close();
|
|
65756
|
+
return;
|
|
65757
|
+
}
|
|
65758
|
+
streams.set(commandId, stream);
|
|
65759
|
+
let resolveAccepted;
|
|
65760
|
+
const accepted = new Promise((resolve9) => {
|
|
65761
|
+
resolveAccepted = resolve9;
|
|
65762
|
+
});
|
|
65763
|
+
stream.onEvents((events) => sink.pushEvents(events));
|
|
65764
|
+
stream.onHistoryGap(() => sink.onHistoryGap?.(false));
|
|
65765
|
+
stream.onState((state) => {
|
|
65766
|
+
resolveAccepted();
|
|
65767
|
+
if (state.status === "inqueue") sink.pushEvents([{ kind: "meta-text", text: "\u5DF2\u6392\u961F\uFF0C\u4E0A\u4E00\u8F6E\u7ED3\u675F\u540E\u6267\u884C" }]);
|
|
65768
|
+
if (state.status === "completed" || state.status === "failed" || state.status === "cancelled") {
|
|
65769
|
+
live.delete(commandId);
|
|
65770
|
+
streams.delete(commandId);
|
|
65771
|
+
if (state.status === "completed" && state.threadId) sink.pushEvents([{ kind: "session_init", toolSessionId: state.threadId }]);
|
|
65772
|
+
if (state.status === "failed") sink.pushEvents([{ kind: "error", message: `\u4E91\u4E0A\u6267\u884C\u5931\u8D25\uFF1A${state.errorCode ?? "TURN_FAILED"}` }]);
|
|
65773
|
+
if (state.status === "failed" || state.status === "cancelled") sink.pushEvents([{ kind: "turn_end", reason: "interrupted" }]);
|
|
65774
|
+
sink.onCloudTurnTerminal?.(commandId);
|
|
65775
|
+
}
|
|
65776
|
+
});
|
|
65777
|
+
stream.onClose(() => {
|
|
65778
|
+
resolveAccepted();
|
|
65779
|
+
if (streams.get(commandId) === stream) streams.delete(commandId);
|
|
65780
|
+
});
|
|
65781
|
+
await accepted;
|
|
65782
|
+
} catch (e) {
|
|
65783
|
+
live.delete(commandId);
|
|
65784
|
+
sink.onCloudTurnTerminal?.(commandId);
|
|
65785
|
+
sink.onError(`\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
|
|
65786
|
+
}
|
|
65787
|
+
});
|
|
65788
|
+
},
|
|
65789
|
+
respondPermission(requestId, allow) {
|
|
65790
|
+
const turnId = [...live][0];
|
|
65791
|
+
if (turnId) sendCommand(turnId, { command: "permission", requestId, allow });
|
|
65792
|
+
},
|
|
65793
|
+
interrupt() {
|
|
65794
|
+
const turnId = [...live][0];
|
|
65795
|
+
if (turnId) sendCommand(turnId, { command: "interrupt" });
|
|
65796
|
+
},
|
|
65797
|
+
detach() {
|
|
65798
|
+
detached = true;
|
|
65799
|
+
closed = true;
|
|
65800
|
+
for (const stream of streams.values()) stream.close();
|
|
65801
|
+
streams.clear();
|
|
65802
|
+
},
|
|
65803
|
+
stop() {
|
|
65804
|
+
if (stopping) return stopping;
|
|
65805
|
+
closed = true;
|
|
65806
|
+
for (const stream of streams.values()) stream.close();
|
|
65807
|
+
streams.clear();
|
|
65808
|
+
stopping = (async () => {
|
|
65809
|
+
try {
|
|
65810
|
+
if (!detached && conversationId) await client.cancelConversation(personaId2, conversationId);
|
|
65811
|
+
} finally {
|
|
65812
|
+
exit();
|
|
65813
|
+
}
|
|
65814
|
+
})();
|
|
65815
|
+
return stopping;
|
|
65816
|
+
}
|
|
65817
|
+
};
|
|
65818
|
+
}
|
|
65819
|
+
|
|
65505
65820
|
// src/tools/codex-cloud-session.ts
|
|
65506
65821
|
function cloudImageInput(deps) {
|
|
65507
65822
|
return (url) => {
|
|
@@ -65521,7 +65836,18 @@ function cloudImageInput(deps) {
|
|
|
65521
65836
|
}
|
|
65522
65837
|
function createCloudCodexSession(ctx, sink, deps) {
|
|
65523
65838
|
const personaId2 = personaIdFromCloudCwd(ctx.cwd);
|
|
65524
|
-
|
|
65839
|
+
if (personaId2 && !ctx.titleOnly && !ctx.cloudGatewaySessionId && !ctx.cloudLegacyPendingCommand && deps.client.openTurn && deps.client.commandTurn && deps.client.cancelConversation) {
|
|
65840
|
+
return createCloudTurnSession({
|
|
65841
|
+
ctx,
|
|
65842
|
+
sink,
|
|
65843
|
+
client: deps.client,
|
|
65844
|
+
personaId: personaId2,
|
|
65845
|
+
engine: "codex",
|
|
65846
|
+
instructions: ctx.extraSystemPrompt,
|
|
65847
|
+
prepare: (text) => portableCloudInput(text, { resolveCodexImage: cloudImageInput(deps) })
|
|
65848
|
+
});
|
|
65849
|
+
}
|
|
65850
|
+
const clientSessionId = ctx.titleOnly ? (0, import_node_crypto14.randomUUID)() : ctx.cloudExecutionId ?? ctx.env?.CLAWD_SESSION_ID;
|
|
65525
65851
|
let channel = null;
|
|
65526
65852
|
let closed = false;
|
|
65527
65853
|
let detached = false;
|
|
@@ -65595,7 +65921,7 @@ function createCloudCodexSession(ctx, sink, deps) {
|
|
|
65595
65921
|
});
|
|
65596
65922
|
};
|
|
65597
65923
|
return {
|
|
65598
|
-
startTurn(text, commandId = (0,
|
|
65924
|
+
startTurn(text, commandId = (0, import_node_crypto14.randomUUID)(), prepared = false) {
|
|
65599
65925
|
send2(async () => {
|
|
65600
65926
|
const ch = await opened;
|
|
65601
65927
|
if (closed) return;
|
|
@@ -65799,7 +66125,7 @@ var PiRpcClient = class {
|
|
|
65799
66125
|
|
|
65800
66126
|
// src/tools/pi-session.ts
|
|
65801
66127
|
var import_node_child_process11 = require("child_process");
|
|
65802
|
-
var
|
|
66128
|
+
var import_node_crypto15 = require("crypto");
|
|
65803
66129
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
65804
66130
|
var import_node_path45 = __toESM(require("path"), 1);
|
|
65805
66131
|
|
|
@@ -66072,7 +66398,7 @@ ${dirs.map((d2) => `- ${d2}`).join("\n")}`;
|
|
|
66072
66398
|
}
|
|
66073
66399
|
function createPiSession(ctx, sink, deps = {}) {
|
|
66074
66400
|
const cmd = process.env.PI_BIN ?? "pi";
|
|
66075
|
-
const sessionId = ctx.toolSessionId ?? (0,
|
|
66401
|
+
const sessionId = ctx.toolSessionId ?? (0, import_node_crypto15.randomUUID)();
|
|
66076
66402
|
const skillsDir = import_node_path45.default.join(ctx.cwd, ".claude", "skills");
|
|
66077
66403
|
const exists = deps.skillsDirExists ?? ((d2) => import_node_fs41.default.existsSync(d2));
|
|
66078
66404
|
const args = buildPiArgs(ctx, {
|
|
@@ -66309,14 +66635,26 @@ var PiAdapter = class {
|
|
|
66309
66635
|
};
|
|
66310
66636
|
|
|
66311
66637
|
// src/tools/pi-cloud-session.ts
|
|
66312
|
-
var
|
|
66638
|
+
var import_node_crypto16 = require("crypto");
|
|
66313
66639
|
function cloudPiInstructions(ctx) {
|
|
66314
66640
|
return [ctx.extraSystemPrompt, workDirPrompt(CLOUD_WORKSPACE_SLOT, ctx.personaMode ?? "owner")].filter((x2) => Boolean(x2)).join("\n\n");
|
|
66315
66641
|
}
|
|
66316
66642
|
function createCloudPiSession(ctx, sink, deps) {
|
|
66317
66643
|
const personaId2 = personaIdFromCloudCwd(ctx.cwd);
|
|
66318
|
-
|
|
66319
|
-
|
|
66644
|
+
if (personaId2 && !ctx.titleOnly && !ctx.cloudGatewaySessionId && !ctx.cloudLegacyPendingCommand && deps.client.openTurn && deps.client.commandTurn && deps.client.cancelConversation) {
|
|
66645
|
+
return createCloudTurnSession({
|
|
66646
|
+
ctx,
|
|
66647
|
+
sink,
|
|
66648
|
+
client: deps.client,
|
|
66649
|
+
personaId: personaId2,
|
|
66650
|
+
engine: "pi",
|
|
66651
|
+
engineSessionId: ctx.toolSessionId,
|
|
66652
|
+
instructions: cloudPiInstructions(ctx),
|
|
66653
|
+
prepare: (text) => portableCloudInput(text, { fetchPiImage: deps.fetchImage ?? makeImageFetcher() })
|
|
66654
|
+
});
|
|
66655
|
+
}
|
|
66656
|
+
const clientSessionId = ctx.titleOnly ? (0, import_node_crypto16.randomUUID)() : ctx.cloudExecutionId ?? ctx.env?.CLAWD_SESSION_ID;
|
|
66657
|
+
const sessionId = ctx.toolSessionId ?? (0, import_node_crypto16.randomUUID)();
|
|
66320
66658
|
let channel = null;
|
|
66321
66659
|
let closed = false;
|
|
66322
66660
|
let detached = false;
|
|
@@ -66380,7 +66718,7 @@ function createCloudPiSession(ctx, sink, deps) {
|
|
|
66380
66718
|
});
|
|
66381
66719
|
};
|
|
66382
66720
|
return {
|
|
66383
|
-
startTurn(text, commandId = (0,
|
|
66721
|
+
startTurn(text, commandId = (0, import_node_crypto16.randomUUID)(), prepared = false) {
|
|
66384
66722
|
send2(async () => {
|
|
66385
66723
|
const ch = await opened;
|
|
66386
66724
|
if (closed) return;
|
|
@@ -67499,7 +67837,7 @@ var wrapper_default = import_websocket.default;
|
|
|
67499
67837
|
|
|
67500
67838
|
// src/transport/local-ws-server.ts
|
|
67501
67839
|
var import_node_http = __toESM(require("http"), 1);
|
|
67502
|
-
var
|
|
67840
|
+
var import_node_crypto17 = require("crypto");
|
|
67503
67841
|
var LocalWsServer = class {
|
|
67504
67842
|
constructor(opts) {
|
|
67505
67843
|
this.opts = opts;
|
|
@@ -67716,7 +68054,7 @@ var LocalWsServer = class {
|
|
|
67716
68054
|
}
|
|
67717
68055
|
}
|
|
67718
68056
|
onConnection(socket, remoteAddress) {
|
|
67719
|
-
const id = (0,
|
|
68057
|
+
const id = (0, import_node_crypto17.randomUUID)();
|
|
67720
68058
|
const subscribedSessions = /* @__PURE__ */ new Map();
|
|
67721
68059
|
const handle = {
|
|
67722
68060
|
id,
|
|
@@ -68681,7 +69019,7 @@ var import_node_path54 = __toESM(require("path"), 1);
|
|
|
68681
69019
|
// src/attachment/upload.ts
|
|
68682
69020
|
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
68683
69021
|
var import_node_path52 = __toESM(require("path"), 1);
|
|
68684
|
-
var
|
|
69022
|
+
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
68685
69023
|
var import_promises8 = require("stream/promises");
|
|
68686
69024
|
var UploadError = class extends Error {
|
|
68687
69025
|
constructor(code, message) {
|
|
@@ -68705,11 +69043,11 @@ async function writeUploadedAttachment(args) {
|
|
|
68705
69043
|
} catch (err) {
|
|
68706
69044
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
68707
69045
|
}
|
|
68708
|
-
const hasher =
|
|
69046
|
+
const hasher = import_node_crypto18.default.createHash("sha256");
|
|
68709
69047
|
let actualSize = 0;
|
|
68710
69048
|
const tmpPath = import_node_path52.default.join(
|
|
68711
69049
|
attachmentsRoot,
|
|
68712
|
-
`.upload-${process.pid}-${Date.now()}-${
|
|
69050
|
+
`.upload-${process.pid}-${Date.now()}-${import_node_crypto18.default.randomBytes(4).toString("hex")}`
|
|
68713
69051
|
);
|
|
68714
69052
|
try {
|
|
68715
69053
|
await (0, import_promises8.pipeline)(
|
|
@@ -69560,7 +69898,7 @@ function runAttachmentGc(args) {
|
|
|
69560
69898
|
// src/attachment/group.ts
|
|
69561
69899
|
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
69562
69900
|
var import_node_path56 = __toESM(require("path"), 1);
|
|
69563
|
-
var
|
|
69901
|
+
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
69564
69902
|
init_protocol();
|
|
69565
69903
|
var GroupFileStore = class {
|
|
69566
69904
|
dataDir;
|
|
@@ -69649,7 +69987,7 @@ var GroupFileStore = class {
|
|
|
69649
69987
|
entries[idx] = next;
|
|
69650
69988
|
} else {
|
|
69651
69989
|
next = {
|
|
69652
|
-
id: `gf-${
|
|
69990
|
+
id: `gf-${import_node_crypto19.default.randomBytes(6).toString("base64url")}`,
|
|
69653
69991
|
relPath: input.relPath,
|
|
69654
69992
|
from: input.from,
|
|
69655
69993
|
label: input.label,
|
|
@@ -69795,7 +70133,7 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
69795
70133
|
// src/tunnel/tunnel-manager.ts
|
|
69796
70134
|
var import_node_fs56 = __toESM(require("fs"), 1);
|
|
69797
70135
|
var import_node_path61 = __toESM(require("path"), 1);
|
|
69798
|
-
var
|
|
70136
|
+
var import_node_crypto20 = __toESM(require("crypto"), 1);
|
|
69799
70137
|
var import_node_child_process16 = require("child_process");
|
|
69800
70138
|
|
|
69801
70139
|
// src/tunnel/tunnel-store.ts
|
|
@@ -70294,7 +70632,7 @@ var TunnelManager = class {
|
|
|
70294
70632
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
70295
70633
|
});
|
|
70296
70634
|
const tomlPath = import_node_path61.default.join(this.deps.dataDir, "frpc.toml");
|
|
70297
|
-
const proxyName = `clawd-${t2.subdomain}-${localPort}-${
|
|
70635
|
+
const proxyName = `clawd-${t2.subdomain}-${localPort}-${import_node_crypto20.default.randomBytes(3).toString("hex")}`;
|
|
70298
70636
|
const toml = buildFrpcToml({
|
|
70299
70637
|
serverAddr: t2.frpsHost,
|
|
70300
70638
|
serverPort: t2.frpsPort,
|
|
@@ -70395,7 +70733,7 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
70395
70733
|
// src/tunnel/device-key.ts
|
|
70396
70734
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
70397
70735
|
var import_node_path62 = __toESM(require("path"), 1);
|
|
70398
|
-
var
|
|
70736
|
+
var import_node_crypto21 = __toESM(require("crypto"), 1);
|
|
70399
70737
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
70400
70738
|
function deriveStableDeviceKey(opts = {}) {
|
|
70401
70739
|
const hostname = opts.hostname ?? import_node_os22.default.hostname();
|
|
@@ -70405,13 +70743,13 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
70405
70743
|
const normalizedDataDir = opts.dataDir ? import_node_path62.default.resolve(opts.dataDir) : null;
|
|
70406
70744
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
70407
70745
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
70408
|
-
return
|
|
70746
|
+
return import_node_crypto21.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
70409
70747
|
}
|
|
70410
70748
|
|
|
70411
70749
|
// src/auth-store.ts
|
|
70412
70750
|
var import_node_fs57 = __toESM(require("fs"), 1);
|
|
70413
70751
|
var import_node_path63 = __toESM(require("path"), 1);
|
|
70414
|
-
var
|
|
70752
|
+
var import_node_crypto22 = __toESM(require("crypto"), 1);
|
|
70415
70753
|
var AUTH_FILE_NAME = "auth.json";
|
|
70416
70754
|
function authFilePath(dataDir) {
|
|
70417
70755
|
return import_node_path63.default.join(dataDir, AUTH_FILE_NAME);
|
|
@@ -70448,10 +70786,10 @@ function loadOrCreateTunnelDeviceKey(opts) {
|
|
|
70448
70786
|
return tunnelDeviceKey;
|
|
70449
70787
|
}
|
|
70450
70788
|
function defaultGenerateToken() {
|
|
70451
|
-
return
|
|
70789
|
+
return import_node_crypto22.default.randomBytes(32).toString("base64url");
|
|
70452
70790
|
}
|
|
70453
70791
|
function defaultGenerateOwnerPrincipalId() {
|
|
70454
|
-
return `owner-${
|
|
70792
|
+
return `owner-${import_node_crypto22.default.randomUUID()}`;
|
|
70455
70793
|
}
|
|
70456
70794
|
function readAuthFile(file) {
|
|
70457
70795
|
try {
|
|
@@ -70583,7 +70921,7 @@ var OwnerIdentityStore = class {
|
|
|
70583
70921
|
};
|
|
70584
70922
|
|
|
70585
70923
|
// src/feishu-auth/login-flow.ts
|
|
70586
|
-
var
|
|
70924
|
+
var import_node_crypto23 = __toESM(require("crypto"), 1);
|
|
70587
70925
|
var STATE_TTL_MS = 5 * 60 * 1e3;
|
|
70588
70926
|
var LoginFlow = class {
|
|
70589
70927
|
constructor(deps) {
|
|
@@ -70592,7 +70930,7 @@ var LoginFlow = class {
|
|
|
70592
70930
|
deps;
|
|
70593
70931
|
pendingStates = /* @__PURE__ */ new Map();
|
|
70594
70932
|
start() {
|
|
70595
|
-
const state =
|
|
70933
|
+
const state = import_node_crypto23.default.randomBytes(16).toString("base64url");
|
|
70596
70934
|
const now = (this.deps.now ?? Date.now)();
|
|
70597
70935
|
this.pendingStates.set(state, now);
|
|
70598
70936
|
this.gcExpired(now);
|
|
@@ -71123,7 +71461,7 @@ init_protocol();
|
|
|
71123
71461
|
var import_node_fs60 = __toESM(require("fs"), 1);
|
|
71124
71462
|
var import_node_os24 = __toESM(require("os"), 1);
|
|
71125
71463
|
var import_node_path66 = __toESM(require("path"), 1);
|
|
71126
|
-
var
|
|
71464
|
+
var import_node_crypto24 = require("crypto");
|
|
71127
71465
|
init_claude_history();
|
|
71128
71466
|
function readJsonlEntries(file) {
|
|
71129
71467
|
const raw = import_node_fs60.default.readFileSync(file, "utf8");
|
|
@@ -71160,7 +71498,7 @@ function forkSession(input) {
|
|
|
71160
71498
|
throw new Error(`fork: messageUuid not found in transcript: ${input.messageUuid}`);
|
|
71161
71499
|
}
|
|
71162
71500
|
const sliced = mainEntries.slice(0, targetIdx + 1);
|
|
71163
|
-
const forkedToolSessionId = (0,
|
|
71501
|
+
const forkedToolSessionId = (0, import_node_crypto24.randomUUID)();
|
|
71164
71502
|
let parentUuid = null;
|
|
71165
71503
|
const forkedLines = [];
|
|
71166
71504
|
for (const entry of sliced) {
|
|
@@ -73948,7 +74286,7 @@ function computeMethodAccess(args) {
|
|
|
73948
74286
|
}
|
|
73949
74287
|
|
|
73950
74288
|
// src/version.ts
|
|
73951
|
-
var version = "0.2.
|
|
74289
|
+
var version = "0.2.614".length > 0 ? "0.2.614" : "dev";
|
|
73952
74290
|
|
|
73953
74291
|
// src/cli-probe/probe.ts
|
|
73954
74292
|
var fs84 = __toESM(require("fs"), 1);
|
|
@@ -74345,7 +74683,7 @@ init_protocol();
|
|
|
74345
74683
|
// src/extension/bundle-zip.ts
|
|
74346
74684
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
74347
74685
|
var import_node_path74 = __toESM(require("path"), 1);
|
|
74348
|
-
var
|
|
74686
|
+
var import_node_crypto25 = __toESM(require("crypto"), 1);
|
|
74349
74687
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
74350
74688
|
async function bundleExtensionDir(dir) {
|
|
74351
74689
|
const entries = await listFilesSorted(dir);
|
|
@@ -74360,7 +74698,7 @@ async function bundleExtensionDir(dir) {
|
|
|
74360
74698
|
compression: "DEFLATE",
|
|
74361
74699
|
compressionOptions: { level: 6 }
|
|
74362
74700
|
});
|
|
74363
|
-
const sha256 =
|
|
74701
|
+
const sha256 = import_node_crypto25.default.createHash("sha256").update(buffer).digest("hex");
|
|
74364
74702
|
return { buffer, sha256 };
|
|
74365
74703
|
}
|
|
74366
74704
|
var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
@@ -74428,7 +74766,7 @@ function computePublishCheck(args) {
|
|
|
74428
74766
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
74429
74767
|
var import_node_path76 = __toESM(require("path"), 1);
|
|
74430
74768
|
var import_node_os28 = __toESM(require("os"), 1);
|
|
74431
|
-
var
|
|
74769
|
+
var import_node_crypto26 = __toESM(require("crypto"), 1);
|
|
74432
74770
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
74433
74771
|
|
|
74434
74772
|
// src/extension/paths.ts
|
|
@@ -74457,7 +74795,7 @@ var InstallError = class extends Error {
|
|
|
74457
74795
|
};
|
|
74458
74796
|
async function installFromChannel(args, deps) {
|
|
74459
74797
|
const { channelRef, snapshotHash, bundleZip } = args;
|
|
74460
|
-
const computed =
|
|
74798
|
+
const computed = import_node_crypto26.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
74461
74799
|
if (computed !== snapshotHash) {
|
|
74462
74800
|
throw new InstallError(
|
|
74463
74801
|
"HASH_MISMATCH",
|
|
@@ -74549,7 +74887,7 @@ async function installFromChannel(args, deps) {
|
|
|
74549
74887
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
74550
74888
|
var import_node_path77 = __toESM(require("path"), 1);
|
|
74551
74889
|
var import_node_os29 = __toESM(require("os"), 1);
|
|
74552
|
-
var
|
|
74890
|
+
var import_node_crypto27 = __toESM(require("crypto"), 1);
|
|
74553
74891
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
74554
74892
|
var UpdateError = class extends Error {
|
|
74555
74893
|
constructor(code, message) {
|
|
@@ -74587,7 +74925,7 @@ async function updateFromChannel(args, deps) {
|
|
|
74587
74925
|
if (e instanceof UpdateError) throw e;
|
|
74588
74926
|
throw e;
|
|
74589
74927
|
}
|
|
74590
|
-
const computed =
|
|
74928
|
+
const computed = import_node_crypto27.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
74591
74929
|
if (computed !== snapshotHash) {
|
|
74592
74930
|
throw new UpdateError(
|
|
74593
74931
|
"HASH_MISMATCH",
|
|
@@ -75716,7 +76054,7 @@ async function uninstall(deps) {
|
|
|
75716
76054
|
}
|
|
75717
76055
|
|
|
75718
76056
|
// src/handlers/index.ts
|
|
75719
|
-
var
|
|
76057
|
+
var import_node_crypto28 = require("crypto");
|
|
75720
76058
|
|
|
75721
76059
|
// src/handlers/peer-exec.ts
|
|
75722
76060
|
init_protocol();
|
|
@@ -75873,7 +76211,7 @@ function buildMethodHandlers(deps) {
|
|
|
75873
76211
|
const c2 = deps.contactStore.get(deviceId);
|
|
75874
76212
|
return c2 ? { deviceId: c2.deviceId, remoteUrl: c2.remoteUrl, connectToken: c2.connectToken } : null;
|
|
75875
76213
|
},
|
|
75876
|
-
genId: () => (0,
|
|
76214
|
+
genId: () => (0, import_node_crypto28.randomUUID)(),
|
|
75877
76215
|
now: () => Date.now(),
|
|
75878
76216
|
forwardInboxPostToPeer,
|
|
75879
76217
|
logger: deps.logger
|
|
@@ -76606,7 +76944,7 @@ async function startDaemon(config) {
|
|
|
76606
76944
|
const channelStore = createChannelStore({
|
|
76607
76945
|
filePath: import_node_path85.default.join(config.dataDir, "channels.json"),
|
|
76608
76946
|
now: () => Date.now(),
|
|
76609
|
-
genId: () => `ch-${(0,
|
|
76947
|
+
genId: () => `ch-${(0, import_node_crypto29.randomUUID)().slice(0, 8)}`,
|
|
76610
76948
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
76611
76949
|
reason: err instanceof Error ? err.message : String(err)
|
|
76612
76950
|
})
|
|
@@ -76615,7 +76953,7 @@ async function startDaemon(config) {
|
|
|
76615
76953
|
const topicStore = createTopicStore({
|
|
76616
76954
|
filePath: import_node_path85.default.join(config.dataDir, "topics.json"),
|
|
76617
76955
|
now: () => Date.now(),
|
|
76618
|
-
genId: () => `tp-${(0,
|
|
76956
|
+
genId: () => `tp-${(0, import_node_crypto29.randomUUID)().slice(0, 8)}`,
|
|
76619
76957
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
76620
76958
|
reason: err instanceof Error ? err.message : String(err)
|
|
76621
76959
|
})
|
|
@@ -76623,7 +76961,7 @@ async function startDaemon(config) {
|
|
|
76623
76961
|
await topicStore.load();
|
|
76624
76962
|
let deliverPendingRef;
|
|
76625
76963
|
const personaDispatchManager = new PersonaDispatchManager({
|
|
76626
|
-
genId: () => (0,
|
|
76964
|
+
genId: () => (0, import_node_crypto29.randomUUID)(),
|
|
76627
76965
|
store: dispatchStore,
|
|
76628
76966
|
now: () => Date.now(),
|
|
76629
76967
|
onCompleted: (sid) => deliverPendingRef?.(sid),
|
|
@@ -77047,6 +77385,11 @@ async function startDaemon(config) {
|
|
|
77047
77385
|
manager.setCloudCanceller(async (file, runner) => {
|
|
77048
77386
|
const personaId2 = personaIdFromCloudCwd(file.cwd);
|
|
77049
77387
|
if (!personaId2) throw new Error(`\u4E91\u4F1A\u8BDD ${file.sessionId} \u7F3A\u5C11 gateway persona ID`);
|
|
77388
|
+
if (file.cloudConversationId) {
|
|
77389
|
+
await cloudGateway.cancelConversation(personaId2, file.cloudConversationId);
|
|
77390
|
+
runner?.confirmCloudCancelled();
|
|
77391
|
+
return;
|
|
77392
|
+
}
|
|
77050
77393
|
const executionId = file.cloudExecutionId ?? file.sessionId;
|
|
77051
77394
|
if (!file.cloudGatewaySessionId) throw new Error(`\u4E91\u4F1A\u8BDD ${file.sessionId} \u5C1A\u672A\u6536\u5230 gateway ready`);
|
|
77052
77395
|
cloudCancelOutbox.record(executionId, personaId2, file.cloudGatewaySessionId);
|