@clawos-dev/clawd 0.2.700 → 0.2.702
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 +10 -0
- package/dist/cli.cjs +165 -54
- package/dist/cloud-persona-conversations.html +28 -28
- package/dist/cloud-persona-metrics.html +1 -1
- package/dist/dispatch/mcp-server.cjs +10 -0
- package/dist/owner-ui/assets/{owner-oewcizWF.js → owner-BQCYgfOm.js} +222 -222
- package/dist/owner-ui/assets/owner-C-ZD935y.css +32 -0
- package/dist/owner-ui/owner.html +2 -2
- package/dist/persona-defaults/persona-app-builder/mcp/clawd-app-builder/mcp-server.cjs +10 -0
- package/dist/persona-defaults/persona-dataclaw-builder/mcp/clawd-app-builder/mcp-server.cjs +10 -0
- package/dist/share-md-viewer-error.html +1 -1
- package/dist/share-md-viewer.html +1 -1
- package/dist/share-ui/assets/guest-CI_nvySJ.css +32 -0
- package/dist/share-ui/assets/{guest-Bqw_4Bav.js → guest-Cdie1sJf.js} +148 -148
- package/dist/share-ui/guest.html +2 -2
- package/package.json +1 -1
- package/dist/owner-ui/assets/owner-A3nMKgXm.css +0 -32
- package/dist/share-ui/assets/guest-DbVMi4R9.css +0 -32
|
@@ -31133,6 +31133,11 @@ var CloudWorkspaceResultSchema = external_exports.object({
|
|
|
31133
31133
|
notStored: external_exports.boolean().optional()
|
|
31134
31134
|
}).optional()
|
|
31135
31135
|
});
|
|
31136
|
+
var CloudForkResultSchema = external_exports.object({
|
|
31137
|
+
threadId: external_exports.string().min(1),
|
|
31138
|
+
conversationId: external_exports.string().min(1),
|
|
31139
|
+
workspace: WorkspaceBindingSchema.optional()
|
|
31140
|
+
});
|
|
31136
31141
|
|
|
31137
31142
|
// ../protocol/src/subscription-channel.ts
|
|
31138
31143
|
var SubscriptionChannelSchema = external_exports.object({
|
|
@@ -33349,6 +33354,11 @@ var SessionCreateArgs = external_exports.object({
|
|
|
33349
33354
|
serviceTier: CodexServiceTierSchema.optional(),
|
|
33350
33355
|
iconKey: external_exports.string().optional(),
|
|
33351
33356
|
forkedFromSessionId: external_exports.string().min(1).optional(),
|
|
33357
|
+
/** Cloud fork point (with forkedFromSessionId of a cloud session): Claude cuts at a message, Codex at a completed turn. */
|
|
33358
|
+
forkAt: external_exports.union([
|
|
33359
|
+
external_exports.object({ messageUuid: external_exports.string().min(1) }).strict(),
|
|
33360
|
+
external_exports.object({ turnId: external_exports.string().min(1) }).strict()
|
|
33361
|
+
]).optional(),
|
|
33352
33362
|
ephemeral: external_exports.boolean().optional(),
|
|
33353
33363
|
// Persona context derives cwd and spawn defaults; missing cwd is allowed when persona identity determines it.
|
|
33354
33364
|
ownerPersonaId: external_exports.string().min(1).optional(),
|
package/dist/cli.cjs
CHANGED
|
@@ -4150,7 +4150,7 @@ var init_zod = __esm({
|
|
|
4150
4150
|
});
|
|
4151
4151
|
|
|
4152
4152
|
// ../protocol/src/cloud-workspace-schemas.ts
|
|
4153
|
-
var WORKSPACE_COMPARISON_VALUES, Id, RepoId, Part, WorkspaceBranchSchema, FilePath, WorkspaceBindingSchema, WorkspaceRepoSchema, WorkspaceStatusSchema, Session, CloudWorkspaceArgsSchema, CloudWorkspaceResultSchema;
|
|
4153
|
+
var WORKSPACE_COMPARISON_VALUES, Id, RepoId, Part, WorkspaceBranchSchema, FilePath, WorkspaceBindingSchema, WorkspaceRepoSchema, WorkspaceStatusSchema, Session, CloudWorkspaceArgsSchema, CloudWorkspaceResultSchema, CloudForkResultSchema;
|
|
4154
4154
|
var init_cloud_workspace_schemas = __esm({
|
|
4155
4155
|
"../protocol/src/cloud-workspace-schemas.ts"() {
|
|
4156
4156
|
"use strict";
|
|
@@ -4251,6 +4251,11 @@ var init_cloud_workspace_schemas = __esm({
|
|
|
4251
4251
|
notStored: external_exports.boolean().optional()
|
|
4252
4252
|
}).optional()
|
|
4253
4253
|
});
|
|
4254
|
+
CloudForkResultSchema = external_exports.object({
|
|
4255
|
+
threadId: external_exports.string().min(1),
|
|
4256
|
+
conversationId: external_exports.string().min(1),
|
|
4257
|
+
workspace: WorkspaceBindingSchema.optional()
|
|
4258
|
+
});
|
|
4254
4259
|
}
|
|
4255
4260
|
});
|
|
4256
4261
|
|
|
@@ -8558,6 +8563,11 @@ var init_schemas = __esm({
|
|
|
8558
8563
|
serviceTier: CodexServiceTierSchema.optional(),
|
|
8559
8564
|
iconKey: external_exports.string().optional(),
|
|
8560
8565
|
forkedFromSessionId: external_exports.string().min(1).optional(),
|
|
8566
|
+
/** Cloud fork point (with forkedFromSessionId of a cloud session): Claude cuts at a message, Codex at a completed turn. */
|
|
8567
|
+
forkAt: external_exports.union([
|
|
8568
|
+
external_exports.object({ messageUuid: external_exports.string().min(1) }).strict(),
|
|
8569
|
+
external_exports.object({ turnId: external_exports.string().min(1) }).strict()
|
|
8570
|
+
]).optional(),
|
|
8561
8571
|
ephemeral: external_exports.boolean().optional(),
|
|
8562
8572
|
// Persona context derives cwd and spawn defaults; missing cwd is allowed when persona identity determines it.
|
|
8563
8573
|
ownerPersonaId: external_exports.string().min(1).optional(),
|
|
@@ -46811,7 +46821,7 @@ function requireEnvironmentIdentity(stores, environment) {
|
|
|
46811
46821
|
var import_node_path90 = __toESM(require("path"), 1);
|
|
46812
46822
|
var import_node_fs69 = __toESM(require("fs"), 1);
|
|
46813
46823
|
var import_node_os33 = __toESM(require("os"), 1);
|
|
46814
|
-
var
|
|
46824
|
+
var import_node_crypto33 = require("crypto");
|
|
46815
46825
|
var import_node_url6 = require("url");
|
|
46816
46826
|
|
|
46817
46827
|
// src/logger.ts
|
|
@@ -50287,10 +50297,14 @@ var SessionManager = class {
|
|
|
50287
50297
|
const iso = nowIso2(this.deps);
|
|
50288
50298
|
const toolSessionId = this.deps.mode === "tui" && tool === "claude" ? (0, import_node_crypto5.randomUUID)() : void 0;
|
|
50289
50299
|
const file = {
|
|
50290
|
-
sessionId: newSessionId(),
|
|
50300
|
+
sessionId: args.cloudFork?.sessionId ?? newSessionId(),
|
|
50291
50301
|
cwd,
|
|
50292
50302
|
tool,
|
|
50293
|
-
toolSessionId,
|
|
50303
|
+
toolSessionId: args.cloudFork?.toolSessionId ?? toolSessionId,
|
|
50304
|
+
...args.cloudFork ? {
|
|
50305
|
+
cloudConversationId: args.cloudFork.cloudConversationId,
|
|
50306
|
+
...args.cloudFork.cloudWorkspace ? { cloudWorkspace: args.cloudFork.cloudWorkspace } : {}
|
|
50307
|
+
} : {},
|
|
50294
50308
|
label: args.label,
|
|
50295
50309
|
aiLabel: args.aiLabel,
|
|
50296
50310
|
...personaDefaultFields(engineOverridden ? void 0 : personaDefaults, {
|
|
@@ -58091,6 +58105,7 @@ async function readReleaseArchive(bytes) {
|
|
|
58091
58105
|
init_protocol();
|
|
58092
58106
|
init_protocol();
|
|
58093
58107
|
var CLOUD_WORKSPACE_SLOT = "{{WORKSPACE}}";
|
|
58108
|
+
var CLOUD_ENGINE_HOME_SLOT = "{{ENGINE_HOME}}";
|
|
58094
58109
|
var GATEWAY_ROUTES = {
|
|
58095
58110
|
healthz: () => "/healthz",
|
|
58096
58111
|
turn: (personaId2) => `/p/${encodeURIComponent(personaId2)}/v1/chat/completions`,
|
|
@@ -58098,6 +58113,7 @@ var GATEWAY_ROUTES = {
|
|
|
58098
58113
|
conversationCancel: (personaId2, conversationId) => `/p/${encodeURIComponent(personaId2)}/conversations/${encodeURIComponent(conversationId)}:cancel`,
|
|
58099
58114
|
volume: () => "/me/volume",
|
|
58100
58115
|
workspace: (personaId2) => `/p/${encodeURIComponent(personaId2)}/workspace`,
|
|
58116
|
+
fork: (personaId2) => `/p/${encodeURIComponent(personaId2)}/fork`,
|
|
58101
58117
|
metrics: (personaId2) => `/metrics/${encodeURIComponent(personaId2)}`
|
|
58102
58118
|
};
|
|
58103
58119
|
var METRICS_TIMEOUT_MS = 3e4;
|
|
@@ -58236,6 +58252,21 @@ var CloudGatewayClient = class {
|
|
|
58236
58252
|
log("finished", { outcome, statusCode, durationMs: Math.round(performance.now() - started) });
|
|
58237
58253
|
}
|
|
58238
58254
|
}
|
|
58255
|
+
/** Copy a cloud conversation under the child's ids (design 2026-10-20-cloud-session-fork §4.2); nothing is written locally here. */
|
|
58256
|
+
async fork(personaId2, body) {
|
|
58257
|
+
const { apiKey, gatewayUrl } = await this.credentials();
|
|
58258
|
+
const res = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.fork(personaId2), {
|
|
58259
|
+
method: "POST",
|
|
58260
|
+
headers: { authorization: "Bearer " + apiKey, "content-type": "application/json" },
|
|
58261
|
+
body: JSON.stringify(body),
|
|
58262
|
+
signal: AbortSignal.timeout(3e5)
|
|
58263
|
+
});
|
|
58264
|
+
const result = await res.json().catch(() => ({}));
|
|
58265
|
+
if (res.status === 404 && !result.error?.code) throw new Error("\u4E91\u7AEF\u6682\u4E0D\u652F\u6301 fork");
|
|
58266
|
+
if (res.status === 409 && result.error?.code === "FORK_POINT_NOT_SYNCED") throw new Error("\u8FD9\u6761\u6D88\u606F\u8FD8\u6CA1\u540C\u6B65\u5230\u4E91\u7AEF\uFF0C\u7A0D\u540E\u518D\u8BD5");
|
|
58267
|
+
if (!res.ok) throw new Error("\u5206\u53C9\u5931\u8D25\uFF1A" + (result.error?.message ?? `gateway \u56DE ${res.status}`));
|
|
58268
|
+
return CloudForkResultSchema.parse(result);
|
|
58269
|
+
}
|
|
58239
58270
|
async openTurn(personaId2, opts) {
|
|
58240
58271
|
const { apiKey, gatewayUrl } = await this.credentials();
|
|
58241
58272
|
const health = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.healthz());
|
|
@@ -67065,6 +67096,24 @@ async function forwardPeerExecToPeer(args) {
|
|
|
67065
67096
|
// src/tools/codex-cloud.ts
|
|
67066
67097
|
init_protocol();
|
|
67067
67098
|
|
|
67099
|
+
// src/tools/cloud-instructions.ts
|
|
67100
|
+
function skillSection(engine) {
|
|
67101
|
+
const wrongHome = engine === "claude" ? "`~/.claude/skills` or `$HOME/.claude/skills`" : "`~/.codex/skills` or `<cwd>/.agents/skills`";
|
|
67102
|
+
return [
|
|
67103
|
+
"## Creating skills",
|
|
67104
|
+
"",
|
|
67105
|
+
`When the user asks you to create a skill, write it to \`${CLOUD_ENGINE_HOME_SLOT}/skills/<name>/SKILL.md\` (the user-level skills directory; it is kept across the user's later sessions with this persona). Do not write skills to ${wrongHome}: those paths are not read here and are lost.`,
|
|
67106
|
+
"Skills under `<cwd>/.claude/skills/` belong to the persona itself and are discarded when this session ends; only write there if the user explicitly asks for a skill that is part of the persona."
|
|
67107
|
+
].join("\n");
|
|
67108
|
+
}
|
|
67109
|
+
function cloudInstructions(ctx, engine) {
|
|
67110
|
+
return [
|
|
67111
|
+
ctx.extraSystemPrompt,
|
|
67112
|
+
workDirPrompt(CLOUD_WORKSPACE_SLOT, ctx.personaMode ?? "owner"),
|
|
67113
|
+
engine === "pi" ? void 0 : skillSection(engine)
|
|
67114
|
+
].filter((x2) => Boolean(x2)).join("\n\n");
|
|
67115
|
+
}
|
|
67116
|
+
|
|
67068
67117
|
// src/tools/codex-cloud-session.ts
|
|
67069
67118
|
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
67070
67119
|
|
|
@@ -67258,7 +67307,7 @@ function createCloudCodexSession(ctx, sink, deps) {
|
|
|
67258
67307
|
client: deps.client,
|
|
67259
67308
|
personaId: personaId2,
|
|
67260
67309
|
engine: "codex",
|
|
67261
|
-
instructions: ctx.titleOnly ? void 0 : ctx
|
|
67310
|
+
instructions: ctx.titleOnly ? void 0 : cloudInstructions(ctx, "codex"),
|
|
67262
67311
|
prepare: (text) => portableCloudInput(text, { resolveCodexImage: cloudImageInput(deps) })
|
|
67263
67312
|
});
|
|
67264
67313
|
}
|
|
@@ -67270,7 +67319,7 @@ var CLOUD_CODEX_CAPABILITIES = {
|
|
|
67270
67319
|
toolSessionIdLabel: "Codex Thread ID",
|
|
67271
67320
|
models: [],
|
|
67272
67321
|
permissionModes: [CLOUD_APPROVAL],
|
|
67273
|
-
features: { rewind: false, subagents: true, tui: false, observe: false, fileSharing: false, fork:
|
|
67322
|
+
features: { rewind: false, subagents: true, tui: false, observe: false, fileSharing: false, fork: true },
|
|
67274
67323
|
configSchema: [
|
|
67275
67324
|
{
|
|
67276
67325
|
name: "permissionMode",
|
|
@@ -67982,9 +68031,6 @@ var PiAdapter = class {
|
|
|
67982
68031
|
};
|
|
67983
68032
|
|
|
67984
68033
|
// src/tools/pi-cloud-session.ts
|
|
67985
|
-
function cloudPiInstructions(ctx) {
|
|
67986
|
-
return [ctx.extraSystemPrompt, workDirPrompt(CLOUD_WORKSPACE_SLOT, ctx.personaMode ?? "owner")].filter((x2) => Boolean(x2)).join("\n\n");
|
|
67987
|
-
}
|
|
67988
68034
|
function createCloudPiSession(ctx, sink, deps) {
|
|
67989
68035
|
const personaId2 = personaIdFromCloudCwd(ctx.cwd);
|
|
67990
68036
|
if (!personaId2 || ctx.cloudGatewaySessionId || ctx.cloudLegacyPendingCommand) {
|
|
@@ -68005,7 +68051,7 @@ function createCloudPiSession(ctx, sink, deps) {
|
|
|
68005
68051
|
personaId: personaId2,
|
|
68006
68052
|
engine: "pi",
|
|
68007
68053
|
engineSessionId: ctx.toolSessionId,
|
|
68008
|
-
instructions: ctx.titleOnly ? void 0 :
|
|
68054
|
+
instructions: ctx.titleOnly ? void 0 : cloudInstructions(ctx, "pi"),
|
|
68009
68055
|
prepare: (text) => portableCloudInput(text, { fetchPiImage: deps.fetchImage ?? makeImageFetcher() })
|
|
68010
68056
|
});
|
|
68011
68057
|
}
|
|
@@ -68099,7 +68145,7 @@ function createCloudClaudeSession(ctx, sink, deps) {
|
|
|
68099
68145
|
personaId: personaId2,
|
|
68100
68146
|
engine: "claude",
|
|
68101
68147
|
engineSessionId: ctx.toolSessionId,
|
|
68102
|
-
instructions: ctx.titleOnly ? void 0 :
|
|
68148
|
+
instructions: ctx.titleOnly ? void 0 : cloudInstructions(ctx, "claude"),
|
|
68103
68149
|
prepare: (text) => portableCloudInput(text, { fetchPiImage: deps.fetchImage ?? makeImageFetcher() })
|
|
68104
68150
|
});
|
|
68105
68151
|
}
|
|
@@ -68111,7 +68157,7 @@ var CLOUD_CLAUDE_CAPABILITIES = {
|
|
|
68111
68157
|
toolSessionIdLabel: "Claude Session ID",
|
|
68112
68158
|
models: [],
|
|
68113
68159
|
permissionModes: [CLOUD_APPROVAL3],
|
|
68114
|
-
features: { rewind: false, subagents: false, tui: false, observe: false, fileSharing: false, fork:
|
|
68160
|
+
features: { rewind: false, subagents: false, tui: false, observe: false, fileSharing: false, fork: true },
|
|
68115
68161
|
configSchema: [
|
|
68116
68162
|
{
|
|
68117
68163
|
name: "permissionMode",
|
|
@@ -72823,6 +72869,45 @@ var import_node_os26 = __toESM(require("os"), 1);
|
|
|
72823
72869
|
var import_node_path70 = __toESM(require("path"), 1);
|
|
72824
72870
|
var import_node_crypto26 = require("crypto");
|
|
72825
72871
|
init_claude_history();
|
|
72872
|
+
|
|
72873
|
+
// src/session/fork-transcript.ts
|
|
72874
|
+
var ForkPointNotFoundError = class extends Error {
|
|
72875
|
+
code = "FORK_POINT_NOT_FOUND";
|
|
72876
|
+
};
|
|
72877
|
+
function forkTranscriptEntries(entries, opts) {
|
|
72878
|
+
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
72879
|
+
const targetIdx = mainEntries.findIndex((e) => e.uuid === opts.messageUuid);
|
|
72880
|
+
if (targetIdx === -1) {
|
|
72881
|
+
throw new ForkPointNotFoundError(`fork: messageUuid not found in transcript: ${opts.messageUuid}`);
|
|
72882
|
+
}
|
|
72883
|
+
const moveCwd = (cwd) => {
|
|
72884
|
+
const from = opts.cwd.from;
|
|
72885
|
+
if (cwd === from) return opts.cwd.to;
|
|
72886
|
+
return cwd.startsWith(`${from}/`) ? opts.cwd.to + cwd.slice(from.length) : cwd;
|
|
72887
|
+
};
|
|
72888
|
+
let parentUuid = null;
|
|
72889
|
+
const out = [];
|
|
72890
|
+
for (const entry of mainEntries.slice(0, targetIdx + 1)) {
|
|
72891
|
+
const originalUuid = entry.uuid;
|
|
72892
|
+
const forked = {
|
|
72893
|
+
...entry,
|
|
72894
|
+
sessionId: opts.sessionId,
|
|
72895
|
+
parentUuid,
|
|
72896
|
+
isSidechain: false
|
|
72897
|
+
};
|
|
72898
|
+
if (opts.cwd && typeof entry.cwd === "string") forked.cwd = moveCwd(entry.cwd);
|
|
72899
|
+
if (originalUuid) {
|
|
72900
|
+
forked.forkedFrom = { sessionId: entry.sessionId ?? opts.sourceSessionId, messageUuid: originalUuid };
|
|
72901
|
+
}
|
|
72902
|
+
if (entry.type !== "progress" && originalUuid) {
|
|
72903
|
+
parentUuid = originalUuid;
|
|
72904
|
+
}
|
|
72905
|
+
out.push(forked);
|
|
72906
|
+
}
|
|
72907
|
+
return out;
|
|
72908
|
+
}
|
|
72909
|
+
|
|
72910
|
+
// src/session/fork.ts
|
|
72826
72911
|
function readJsonlEntries(file) {
|
|
72827
72912
|
const raw = import_node_fs62.default.readFileSync(file, "utf8");
|
|
72828
72913
|
const out = [];
|
|
@@ -72851,33 +72936,12 @@ function forkSession(input) {
|
|
|
72851
72936
|
sourceFile = found;
|
|
72852
72937
|
projectDir = import_node_path70.default.dirname(found);
|
|
72853
72938
|
}
|
|
72854
|
-
const entries = readJsonlEntries(sourceFile);
|
|
72855
|
-
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
72856
|
-
const targetIdx = mainEntries.findIndex((e) => e.uuid === input.messageUuid);
|
|
72857
|
-
if (targetIdx === -1) {
|
|
72858
|
-
throw new Error(`fork: messageUuid not found in transcript: ${input.messageUuid}`);
|
|
72859
|
-
}
|
|
72860
|
-
const sliced = mainEntries.slice(0, targetIdx + 1);
|
|
72861
72939
|
const forkedToolSessionId = (0, import_node_crypto26.randomUUID)();
|
|
72862
|
-
|
|
72863
|
-
|
|
72864
|
-
|
|
72865
|
-
|
|
72866
|
-
|
|
72867
|
-
const forked = {
|
|
72868
|
-
...entry,
|
|
72869
|
-
sessionId: forkedToolSessionId,
|
|
72870
|
-
parentUuid,
|
|
72871
|
-
isSidechain: false
|
|
72872
|
-
};
|
|
72873
|
-
if (originalUuid) {
|
|
72874
|
-
forked.forkedFrom = { sessionId: originalSessionId, messageUuid: originalUuid };
|
|
72875
|
-
}
|
|
72876
|
-
if (entry.type !== "progress" && originalUuid) {
|
|
72877
|
-
parentUuid = originalUuid;
|
|
72878
|
-
}
|
|
72879
|
-
forkedLines.push(JSON.stringify(forked));
|
|
72880
|
-
}
|
|
72940
|
+
const forkedLines = forkTranscriptEntries(readJsonlEntries(sourceFile), {
|
|
72941
|
+
messageUuid: input.messageUuid,
|
|
72942
|
+
sessionId: forkedToolSessionId,
|
|
72943
|
+
sourceSessionId: input.toolSessionId
|
|
72944
|
+
}).map((entry) => JSON.stringify(entry));
|
|
72881
72945
|
const outDir = input.targetCwd ? import_node_path70.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
72882
72946
|
const forkedFilePath = import_node_path70.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
72883
72947
|
import_node_fs62.default.mkdirSync(outDir, { recursive: true });
|
|
@@ -73227,6 +73291,7 @@ function appendImportLedger(dataDir, entry) {
|
|
|
73227
73291
|
|
|
73228
73292
|
// src/handlers/session.ts
|
|
73229
73293
|
init_protocol();
|
|
73294
|
+
var import_node_crypto27 = require("crypto");
|
|
73230
73295
|
var import_node_path74 = __toESM(require("path"), 1);
|
|
73231
73296
|
function canReadSearchHit(ctx, file) {
|
|
73232
73297
|
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
@@ -73277,6 +73342,45 @@ function buildSessionHandlers(deps) {
|
|
|
73277
73342
|
`${MASTER_PERSONA_ID} \u7684\u4F1A\u8BDD\u7531\u8BDD\u9898\u521B\u5EFA\uFF0C\u4E0D\u80FD\u76F4\u63A5\u5EFA\uFF1A\u8BF7\u5728\u9891\u9053\u91CC\u65B0\u5EFA\u8BDD\u9898`
|
|
73278
73343
|
);
|
|
73279
73344
|
};
|
|
73345
|
+
const forkCloudSession = async (args, forkAt, tool, ctx) => {
|
|
73346
|
+
if (!args.forkedFromSessionId) throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "fork: forkAt requires forkedFromSessionId");
|
|
73347
|
+
const source = manager.get({ sessionId: args.forkedFromSessionId }).response;
|
|
73348
|
+
if (!canReadSearchHit(ctx, source)) {
|
|
73349
|
+
throw new ClawdError(ERROR_CODES.UNAUTHORIZED, `principal ${ctx?.principal.kind}:${ctx?.principal.id} cannot fork session ${source.sessionId}`);
|
|
73350
|
+
}
|
|
73351
|
+
const engine = source.tool === CLAUDE_CLOUD_TOOL_ID ? "claude" : source.tool === CODEX_CLOUD_TOOL_ID ? "codex" : null;
|
|
73352
|
+
if (!engine || !deps.cloudFork) throw new ClawdError(ERROR_CODES.TOOL_NOT_SUPPORTED, `tool ${source.tool} does not support cloud fork`);
|
|
73353
|
+
if (tool !== source.tool || args.ownerPersonaId !== source.ownerPersonaId) {
|
|
73354
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "fork: cloud fork must stay on the source persona and engine");
|
|
73355
|
+
}
|
|
73356
|
+
if (engine === "claude" ? !("messageUuid" in forkAt) : !("turnId" in forkAt)) {
|
|
73357
|
+
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `fork: ${source.tool} needs ${engine === "claude" ? "messageUuid" : "turnId"}`);
|
|
73358
|
+
}
|
|
73359
|
+
const sourceConversationId = source.cloudConversationId ?? source.cloudExecutionId;
|
|
73360
|
+
if (!source.toolSessionId || !sourceConversationId) throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "fork: \u6E90\u4F1A\u8BDD\u8FD8\u6CA1\u6709\u4E91\u7AEF\u5386\u53F2");
|
|
73361
|
+
if (source.cloudPendingTurns?.length) throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "fork: \u8BF7\u7B49\u5F85\u6E90\u4F1A\u8BDD\u5F53\u524D\u4EFB\u52A1\u5B8C\u6210");
|
|
73362
|
+
const sessionId = newSessionId();
|
|
73363
|
+
const threadId = (0, import_node_crypto27.randomUUID)();
|
|
73364
|
+
const result = await deps.cloudFork(source, {
|
|
73365
|
+
engine,
|
|
73366
|
+
source: {
|
|
73367
|
+
conversationId: sourceConversationId,
|
|
73368
|
+
threadId: source.toolSessionId,
|
|
73369
|
+
...source.cloudWorkspace ? { workspaceId: source.cloudWorkspace.workspaceId } : {}
|
|
73370
|
+
},
|
|
73371
|
+
at: forkAt,
|
|
73372
|
+
child: { conversationId: sessionId, threadId, ...source.cloudWorkspace ? { workspaceId: sessionId } : {} }
|
|
73373
|
+
});
|
|
73374
|
+
if (result.threadId !== threadId || result.conversationId !== sessionId || Boolean(result.workspace) !== Boolean(source.cloudWorkspace)) {
|
|
73375
|
+
throw new Error("\u5206\u53C9\u5931\u8D25\uFF1Agateway \u8FD4\u56DE\u7684\u5B50\u4F1A\u8BDD\u4E0E\u8BF7\u6C42\u4E0D\u4E00\u81F4");
|
|
73376
|
+
}
|
|
73377
|
+
return {
|
|
73378
|
+
sessionId,
|
|
73379
|
+
toolSessionId: threadId,
|
|
73380
|
+
cloudConversationId: sessionId,
|
|
73381
|
+
...result.workspace ? { cloudWorkspace: result.workspace } : {}
|
|
73382
|
+
};
|
|
73383
|
+
};
|
|
73280
73384
|
const create = async (frame, _client, ctx) => {
|
|
73281
73385
|
const args = SessionCreateArgs.parse(frame);
|
|
73282
73386
|
assertNotMasterPersona(args.ownerPersonaId, args.ephemeral);
|
|
@@ -73303,8 +73407,10 @@ function buildSessionHandlers(deps) {
|
|
|
73303
73407
|
const creatorPrincipalId = ctx?.principal.id ?? ownerPrincipalId;
|
|
73304
73408
|
const creatorDisplayName = ctx?.principal.displayName ?? "Owner";
|
|
73305
73409
|
const creatorFeishuUnionId = ctx?.principal.feishuUnionId;
|
|
73410
|
+
const { forkAt, ...createArgs } = args;
|
|
73411
|
+
const cloudFork = forkAt ? await forkCloudSession(args, forkAt, tool, ctx) : void 0;
|
|
73306
73412
|
const { response, broadcast } = manager.create(
|
|
73307
|
-
{ ...
|
|
73413
|
+
{ ...createArgs, tool, model, effort, ...cloudFork ? { cloudFork } : {} },
|
|
73308
73414
|
creatorPrincipalId,
|
|
73309
73415
|
creatorDisplayName,
|
|
73310
73416
|
creatorFeishuUnionId
|
|
@@ -75391,7 +75497,7 @@ function buildCloudConnectorsHandlers(deps) {
|
|
|
75391
75497
|
|
|
75392
75498
|
// src/handlers/cloud-workspace.ts
|
|
75393
75499
|
init_protocol();
|
|
75394
|
-
var
|
|
75500
|
+
var import_node_crypto28 = require("crypto");
|
|
75395
75501
|
function buildCloudWorkspaceHandlers(deps) {
|
|
75396
75502
|
return {
|
|
75397
75503
|
"cloud:workspace": async (frame, _client, ctx) => {
|
|
@@ -75419,7 +75525,7 @@ function buildCloudWorkspaceHandlers(deps) {
|
|
|
75419
75525
|
) || file.cloudPendingTurns?.length))
|
|
75420
75526
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u5B8C\u6210");
|
|
75421
75527
|
const conversationId = file.cloudConversationId ?? file.cloudExecutionId ?? file.sessionId;
|
|
75422
|
-
const traceId = typeof frame.requestId === "string" && /^[A-Za-z0-9:_-]{1,128}$/.test(frame.requestId) ? frame.requestId : (0,
|
|
75528
|
+
const traceId = typeof frame.requestId === "string" && /^[A-Za-z0-9:_-]{1,128}$/.test(frame.requestId) ? frame.requestId : (0, import_node_crypto28.randomUUID)();
|
|
75423
75529
|
const started = performance.now();
|
|
75424
75530
|
const meta = { traceId, sessionId: args.sessionId, action: args.action };
|
|
75425
75531
|
const log = (event, detail) => {
|
|
@@ -75778,7 +75884,7 @@ function computeMethodAccess(args) {
|
|
|
75778
75884
|
}
|
|
75779
75885
|
|
|
75780
75886
|
// src/version.ts
|
|
75781
|
-
var version = "0.2.
|
|
75887
|
+
var version = "0.2.702".length > 0 ? "0.2.702" : "dev";
|
|
75782
75888
|
|
|
75783
75889
|
// src/cli-probe/probe.ts
|
|
75784
75890
|
var fs87 = __toESM(require("fs"), 1);
|
|
@@ -76176,7 +76282,7 @@ init_protocol();
|
|
|
76176
76282
|
// src/extension/bundle-zip.ts
|
|
76177
76283
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
76178
76284
|
var import_node_path79 = __toESM(require("path"), 1);
|
|
76179
|
-
var
|
|
76285
|
+
var import_node_crypto29 = __toESM(require("crypto"), 1);
|
|
76180
76286
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
76181
76287
|
async function bundleExtensionDir(dir) {
|
|
76182
76288
|
const entries = await listFilesSorted(dir);
|
|
@@ -76191,7 +76297,7 @@ async function bundleExtensionDir(dir) {
|
|
|
76191
76297
|
compression: "DEFLATE",
|
|
76192
76298
|
compressionOptions: { level: 6 }
|
|
76193
76299
|
});
|
|
76194
|
-
const sha256 =
|
|
76300
|
+
const sha256 = import_node_crypto29.default.createHash("sha256").update(buffer).digest("hex");
|
|
76195
76301
|
return { buffer, sha256 };
|
|
76196
76302
|
}
|
|
76197
76303
|
var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
@@ -76259,7 +76365,7 @@ function computePublishCheck(args) {
|
|
|
76259
76365
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
76260
76366
|
var import_node_path81 = __toESM(require("path"), 1);
|
|
76261
76367
|
var import_node_os30 = __toESM(require("os"), 1);
|
|
76262
|
-
var
|
|
76368
|
+
var import_node_crypto30 = __toESM(require("crypto"), 1);
|
|
76263
76369
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
76264
76370
|
|
|
76265
76371
|
// src/extension/paths.ts
|
|
@@ -76288,7 +76394,7 @@ var InstallError = class extends Error {
|
|
|
76288
76394
|
};
|
|
76289
76395
|
async function installFromChannel(args, deps) {
|
|
76290
76396
|
const { channelRef, snapshotHash, bundleZip } = args;
|
|
76291
|
-
const computed =
|
|
76397
|
+
const computed = import_node_crypto30.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
76292
76398
|
if (computed !== snapshotHash) {
|
|
76293
76399
|
throw new InstallError(
|
|
76294
76400
|
"HASH_MISMATCH",
|
|
@@ -76380,7 +76486,7 @@ async function installFromChannel(args, deps) {
|
|
|
76380
76486
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
76381
76487
|
var import_node_path82 = __toESM(require("path"), 1);
|
|
76382
76488
|
var import_node_os31 = __toESM(require("os"), 1);
|
|
76383
|
-
var
|
|
76489
|
+
var import_node_crypto31 = __toESM(require("crypto"), 1);
|
|
76384
76490
|
var import_jszip5 = __toESM(require_lib3(), 1);
|
|
76385
76491
|
var UpdateError = class extends Error {
|
|
76386
76492
|
constructor(code, message) {
|
|
@@ -76418,7 +76524,7 @@ async function updateFromChannel(args, deps) {
|
|
|
76418
76524
|
if (e instanceof UpdateError) throw e;
|
|
76419
76525
|
throw e;
|
|
76420
76526
|
}
|
|
76421
|
-
const computed =
|
|
76527
|
+
const computed = import_node_crypto31.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
76422
76528
|
if (computed !== snapshotHash) {
|
|
76423
76529
|
throw new UpdateError(
|
|
76424
76530
|
"HASH_MISMATCH",
|
|
@@ -77562,7 +77668,7 @@ async function uninstall(deps) {
|
|
|
77562
77668
|
}
|
|
77563
77669
|
|
|
77564
77670
|
// src/handlers/index.ts
|
|
77565
|
-
var
|
|
77671
|
+
var import_node_crypto32 = require("crypto");
|
|
77566
77672
|
|
|
77567
77673
|
// src/handlers/peer-exec.ts
|
|
77568
77674
|
init_protocol();
|
|
@@ -77719,7 +77825,7 @@ function buildMethodHandlers(deps) {
|
|
|
77719
77825
|
const c2 = deps.contactStore.get(deviceId);
|
|
77720
77826
|
return c2 ? { deviceId: c2.deviceId, remoteUrl: c2.remoteUrl, connectToken: c2.connectToken } : null;
|
|
77721
77827
|
},
|
|
77722
|
-
genId: () => (0,
|
|
77828
|
+
genId: () => (0, import_node_crypto32.randomUUID)(),
|
|
77723
77829
|
now: () => Date.now(),
|
|
77724
77830
|
forwardInboxPostToPeer,
|
|
77725
77831
|
logger: deps.logger
|
|
@@ -78453,7 +78559,7 @@ async function startDaemon(config) {
|
|
|
78453
78559
|
const channelStore = createChannelStore({
|
|
78454
78560
|
filePath: import_node_path90.default.join(config.dataDir, "channels.json"),
|
|
78455
78561
|
now: () => Date.now(),
|
|
78456
|
-
genId: () => `ch-${(0,
|
|
78562
|
+
genId: () => `ch-${(0, import_node_crypto33.randomUUID)().slice(0, 8)}`,
|
|
78457
78563
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
78458
78564
|
reason: err instanceof Error ? err.message : String(err)
|
|
78459
78565
|
})
|
|
@@ -78462,7 +78568,7 @@ async function startDaemon(config) {
|
|
|
78462
78568
|
const topicStore = createTopicStore({
|
|
78463
78569
|
filePath: import_node_path90.default.join(config.dataDir, "topics.json"),
|
|
78464
78570
|
now: () => Date.now(),
|
|
78465
|
-
genId: () => `tp-${(0,
|
|
78571
|
+
genId: () => `tp-${(0, import_node_crypto33.randomUUID)().slice(0, 8)}`,
|
|
78466
78572
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
78467
78573
|
reason: err instanceof Error ? err.message : String(err)
|
|
78468
78574
|
})
|
|
@@ -78470,7 +78576,7 @@ async function startDaemon(config) {
|
|
|
78470
78576
|
await topicStore.load();
|
|
78471
78577
|
let deliverPendingRef;
|
|
78472
78578
|
const personaDispatchManager = new PersonaDispatchManager({
|
|
78473
|
-
genId: () => (0,
|
|
78579
|
+
genId: () => (0, import_node_crypto33.randomUUID)(),
|
|
78474
78580
|
store: dispatchStore,
|
|
78475
78581
|
now: () => Date.now(),
|
|
78476
78582
|
onCompleted: (sid) => deliverPendingRef?.(sid),
|
|
@@ -78494,7 +78600,7 @@ async function startDaemon(config) {
|
|
|
78494
78600
|
const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
|
|
78495
78601
|
const githubTokenFile = import_node_path90.default.join(localSecretsDir, GITHUB_TOKEN_FILE);
|
|
78496
78602
|
const managedGithubVar = "CLAWD_GITHUB_MANAGED_TOKEN_SHA256";
|
|
78497
|
-
const githubFingerprint = (token) => (0,
|
|
78603
|
+
const githubFingerprint = (token) => (0, import_node_crypto33.createHash)("sha256").update(token).digest("hex");
|
|
78498
78604
|
const githubIdentity = createGithubIdentity({
|
|
78499
78605
|
isManaged: (token) => readEnvFileVar(githubTokenFile, managedGithubVar) === githubFingerprint(token),
|
|
78500
78606
|
markManaged: (token) => {
|
|
@@ -79333,6 +79439,11 @@ async function startDaemon(config) {
|
|
|
79333
79439
|
fill: (args) => centralConnectorFill({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
|
|
79334
79440
|
}
|
|
79335
79441
|
},
|
|
79442
|
+
cloudFork: (file, body) => {
|
|
79443
|
+
const personaId2 = personaIdFromCloudCwd(file.cwd);
|
|
79444
|
+
if (!personaId2) throw new Error(`\u4E91\u4F1A\u8BDD ${file.sessionId} \u7F3A\u5C11 gateway persona ID`);
|
|
79445
|
+
return gatewayForEnvironment(file.cloudEnvironment).fork(personaId2, body);
|
|
79446
|
+
},
|
|
79336
79447
|
cloudWorkspace: {
|
|
79337
79448
|
logger,
|
|
79338
79449
|
getFile: (id) => manager.get({ sessionId: id }).response,
|