@clawos-dev/clawd 0.2.682 → 0.2.684

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.
@@ -31064,12 +31064,6 @@ var WorkspaceRepoSchema = external_exports.object({
31064
31064
  private: external_exports.boolean(),
31065
31065
  description: external_exports.string().nullable()
31066
31066
  });
31067
- var WorkspacePrSchema = external_exports.object({
31068
- number: external_exports.number().int().positive(),
31069
- url: external_exports.string().url().refine((u) => new URL(u).origin === "https://github.com"),
31070
- base: external_exports.string(),
31071
- head: external_exports.string()
31072
- });
31073
31067
  var WorkspaceStatusSchema = WorkspaceBindingSchema.extend({
31074
31068
  initialCommit: external_exports.string(),
31075
31069
  head: external_exports.string(),
@@ -31094,10 +31088,7 @@ var WorkspaceStatusSchema = WorkspaceBindingSchema.extend({
31094
31088
  dirty: external_exports.boolean(),
31095
31089
  conflicted: external_exports.boolean(),
31096
31090
  version: external_exports.string(),
31097
- measuredAt: external_exports.number(),
31098
- pendingPublication: external_exports.object({ operationId: Id, expectedVersion: external_exports.string(), stage: external_exports.string() }).optional(),
31099
- pr: WorkspacePrSchema.nullable().optional(),
31100
- savedAt: external_exports.number().nullable().optional()
31091
+ measuredAt: external_exports.number()
31101
31092
  });
31102
31093
  var Session = external_exports.object({ sessionId: Id });
31103
31094
  var CloudWorkspaceArgsSchema = external_exports.discriminatedUnion("action", [
@@ -31117,17 +31108,12 @@ var CloudWorkspaceArgsSchema = external_exports.discriminatedUnion("action", [
31117
31108
  branch: WorkspaceBranchSchema
31118
31109
  }).strict(),
31119
31110
  Session.extend({ action: external_exports.literal("status") }).strict(),
31111
+ // 只记「待切换分支」意图,不碰网关;branch 缺省 = 清除意图
31120
31112
  Session.extend({
31121
- action: external_exports.literal("switch"),
31122
- branch: WorkspaceBranchSchema,
31123
- create: external_exports.boolean().optional()
31113
+ action: external_exports.literal("intend"),
31114
+ branch: WorkspaceBranchSchema.optional()
31124
31115
  }).strict(),
31125
- Session.extend({ action: external_exports.literal("diff"), filePath: FilePath }).strict(),
31126
- Session.extend({
31127
- action: external_exports.literal("publish"),
31128
- operationId: Id,
31129
- expectedVersion: external_exports.string().min(1).max(128)
31130
- }).strict()
31116
+ Session.extend({ action: external_exports.literal("diff"), filePath: FilePath }).strict()
31131
31117
  ]);
31132
31118
  var CloudWorkspaceResultSchema = external_exports.object({
31133
31119
  binding: WorkspaceBindingSchema.nullable().optional(),
@@ -31135,14 +31121,13 @@ var CloudWorkspaceResultSchema = external_exports.object({
31135
31121
  repositories: external_exports.array(WorkspaceRepoSchema).optional(),
31136
31122
  branches: external_exports.array(external_exports.string()).optional(),
31137
31123
  hasMore: external_exports.boolean().optional(),
31138
- cache: external_exports.enum(["warm", "cold"]).optional(),
31139
31124
  diff: external_exports.object({
31140
31125
  path: FilePath,
31141
31126
  patch: external_exports.string(),
31142
31127
  binary: external_exports.boolean(),
31143
- truncated: external_exports.boolean()
31144
- }).optional(),
31145
- pr: WorkspacePrSchema.optional()
31128
+ truncated: external_exports.boolean(),
31129
+ notStored: external_exports.boolean().optional()
31130
+ }).optional()
31146
31131
  });
31147
31132
 
31148
31133
  // ../protocol/src/subscription-channel.ts
@@ -33094,6 +33079,8 @@ var SessionFileSchema = external_exports.object({
33094
33079
  cloudWorkspace: WorkspaceBindingSchema.optional(),
33095
33080
  /** Accepted local turns whose terminal gateway status has not been observed. */
33096
33081
  cloudPendingTurns: external_exports.array(external_exports.object({ id: external_exports.string().min(1), text: external_exports.string(), prepared: external_exports.boolean().optional() })).optional(),
33082
+ /** 用户在前端选的、尚未由 agent 执行的分支;下一条 query 发出时作为上下文注入,被网关接受后清除。 */
33083
+ cloudBranchIntent: WorkspaceBranchSchema.optional(),
33097
33084
  /** Owner gateway session observed in ready; proves the remote Pod was opened. */
33098
33085
  cloudGatewaySessionId: external_exports.string().min(1).optional(),
33099
33086
  /** Persisted before sending so daemon restart can retry the same gateway command ID. */
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, WorkspacePrSchema, WorkspaceStatusSchema, Session, CloudWorkspaceArgsSchema, CloudWorkspaceResultSchema;
4153
+ var WORKSPACE_COMPARISON_VALUES, Id, RepoId, Part, WorkspaceBranchSchema, FilePath, WorkspaceBindingSchema, WorkspaceRepoSchema, WorkspaceStatusSchema, Session, CloudWorkspaceArgsSchema, CloudWorkspaceResultSchema;
4154
4154
  var init_cloud_workspace_schemas = __esm({
4155
4155
  "../protocol/src/cloud-workspace-schemas.ts"() {
4156
4156
  "use strict";
@@ -4182,12 +4182,6 @@ var init_cloud_workspace_schemas = __esm({
4182
4182
  private: external_exports.boolean(),
4183
4183
  description: external_exports.string().nullable()
4184
4184
  });
4185
- WorkspacePrSchema = external_exports.object({
4186
- number: external_exports.number().int().positive(),
4187
- url: external_exports.string().url().refine((u2) => new URL(u2).origin === "https://github.com"),
4188
- base: external_exports.string(),
4189
- head: external_exports.string()
4190
- });
4191
4185
  WorkspaceStatusSchema = WorkspaceBindingSchema.extend({
4192
4186
  initialCommit: external_exports.string(),
4193
4187
  head: external_exports.string(),
@@ -4212,10 +4206,7 @@ var init_cloud_workspace_schemas = __esm({
4212
4206
  dirty: external_exports.boolean(),
4213
4207
  conflicted: external_exports.boolean(),
4214
4208
  version: external_exports.string(),
4215
- measuredAt: external_exports.number(),
4216
- pendingPublication: external_exports.object({ operationId: Id, expectedVersion: external_exports.string(), stage: external_exports.string() }).optional(),
4217
- pr: WorkspacePrSchema.nullable().optional(),
4218
- savedAt: external_exports.number().nullable().optional()
4209
+ measuredAt: external_exports.number()
4219
4210
  });
4220
4211
  Session = external_exports.object({ sessionId: Id });
4221
4212
  CloudWorkspaceArgsSchema = external_exports.discriminatedUnion("action", [
@@ -4235,17 +4226,12 @@ var init_cloud_workspace_schemas = __esm({
4235
4226
  branch: WorkspaceBranchSchema
4236
4227
  }).strict(),
4237
4228
  Session.extend({ action: external_exports.literal("status") }).strict(),
4229
+ // 只记「待切换分支」意图,不碰网关;branch 缺省 = 清除意图
4238
4230
  Session.extend({
4239
- action: external_exports.literal("switch"),
4240
- branch: WorkspaceBranchSchema,
4241
- create: external_exports.boolean().optional()
4231
+ action: external_exports.literal("intend"),
4232
+ branch: WorkspaceBranchSchema.optional()
4242
4233
  }).strict(),
4243
- Session.extend({ action: external_exports.literal("diff"), filePath: FilePath }).strict(),
4244
- Session.extend({
4245
- action: external_exports.literal("publish"),
4246
- operationId: Id,
4247
- expectedVersion: external_exports.string().min(1).max(128)
4248
- }).strict()
4234
+ Session.extend({ action: external_exports.literal("diff"), filePath: FilePath }).strict()
4249
4235
  ]);
4250
4236
  CloudWorkspaceResultSchema = external_exports.object({
4251
4237
  binding: WorkspaceBindingSchema.nullable().optional(),
@@ -4253,14 +4239,13 @@ var init_cloud_workspace_schemas = __esm({
4253
4239
  repositories: external_exports.array(WorkspaceRepoSchema).optional(),
4254
4240
  branches: external_exports.array(external_exports.string()).optional(),
4255
4241
  hasMore: external_exports.boolean().optional(),
4256
- cache: external_exports.enum(["warm", "cold"]).optional(),
4257
4242
  diff: external_exports.object({
4258
4243
  path: FilePath,
4259
4244
  patch: external_exports.string(),
4260
4245
  binary: external_exports.boolean(),
4261
- truncated: external_exports.boolean()
4262
- }).optional(),
4263
- pr: WorkspacePrSchema.optional()
4246
+ truncated: external_exports.boolean(),
4247
+ notStored: external_exports.boolean().optional()
4248
+ }).optional()
4264
4249
  });
4265
4250
  }
4266
4251
  });
@@ -8303,6 +8288,8 @@ var init_schemas = __esm({
8303
8288
  cloudWorkspace: WorkspaceBindingSchema.optional(),
8304
8289
  /** Accepted local turns whose terminal gateway status has not been observed. */
8305
8290
  cloudPendingTurns: external_exports.array(external_exports.object({ id: external_exports.string().min(1), text: external_exports.string(), prepared: external_exports.boolean().optional() })).optional(),
8291
+ /** 用户在前端选的、尚未由 agent 执行的分支;下一条 query 发出时作为上下文注入,被网关接受后清除。 */
8292
+ cloudBranchIntent: WorkspaceBranchSchema.optional(),
8306
8293
  /** Owner gateway session observed in ready; proves the remote Pod was opened. */
8307
8294
  cloudGatewaySessionId: external_exports.string().min(1).optional(),
8308
8295
  /** Persisted before sending so daemon restart can retry the same gateway command ID. */
@@ -48439,7 +48426,7 @@ var RUNTIME_PATCH_KEYS = [
48439
48426
  "effort",
48440
48427
  "cwd"
48441
48428
  ];
48442
- var MARKER_PATCH_KEYS = ["pinnedAt", "pinSortOrder", "unreadAt", "archivedAt"];
48429
+ var MARKER_PATCH_KEYS = ["pinnedAt", "pinSortOrder", "unreadAt", "archivedAt", "cloudBranchIntent"];
48443
48430
  function isMarkerOnlyPatch(patch) {
48444
48431
  const keys = Object.keys(patch).filter(
48445
48432
  (k3) => patch[k3] !== void 0
@@ -49158,6 +49145,14 @@ function encodeAllowWithInputControlResponse(requestId, updatedInput) {
49158
49145
  }
49159
49146
  var DEFAULT_WAIT_STOP_TIMEOUT_MS = 3e3;
49160
49147
  var SUBAGENT_ACTIVE_WINDOW_MS = 3e5;
49148
+ function latestTurnId(state) {
49149
+ for (let index = state.buffer.length - 1; index >= 0; index--) {
49150
+ const event = state.buffer[index].event;
49151
+ if (event.turnId) return event.turnId;
49152
+ if (event.kind === "user_text") return void 0;
49153
+ }
49154
+ return void 0;
49155
+ }
49161
49156
  var SessionRunner = class {
49162
49157
  constructor(initial, hooks) {
49163
49158
  this.hooks = hooks;
@@ -49410,20 +49405,11 @@ var SessionRunner = class {
49410
49405
  }
49411
49406
  lifecycleMetadata() {
49412
49407
  const state = this.state;
49413
- let turnId;
49414
- for (let index = state.buffer.length - 1; index >= 0; index--) {
49415
- const event = state.buffer[index].event;
49416
- if (event.turnId) {
49417
- turnId = event.turnId;
49418
- break;
49419
- }
49420
- if (event.kind === "user_text") break;
49421
- }
49422
49408
  return {
49423
49409
  sessionId: state.file.sessionId,
49424
49410
  tool: state.file.tool,
49425
49411
  toolSessionId: state.file.toolSessionId,
49426
- turnId,
49412
+ turnId: latestTurnId(state),
49427
49413
  status: state.status,
49428
49414
  turnOpen: state.turnOpen,
49429
49415
  procAlive: state.procAlive
@@ -49621,6 +49607,11 @@ var SessionRunner = class {
49621
49607
  },
49622
49608
  onCloudTurnTerminal: (turnId) => {
49623
49609
  if (isCurrent()) this.input({ kind: "cloud-turn-terminal", turnId });
49610
+ },
49611
+ pendingBranchIntent: () => this.state.file.cloudBranchIntent,
49612
+ onBranchIntentDelivered: (branch) => {
49613
+ if (isCurrent() && this.state.file.cloudBranchIntent === branch)
49614
+ this.input({ kind: "command", command: { kind: "update", patch: { cloudBranchIntent: void 0 } } });
49624
49615
  }
49625
49616
  });
49626
49617
  if (isCurrent()) this.session = session;
@@ -50513,7 +50504,7 @@ var SessionManager = class {
50513
50504
  });
50514
50505
  return { response: value, broadcast };
50515
50506
  }
50516
- const updated = { ...existing, ...args.patch, updatedAt: nowIso2(this.deps) };
50507
+ const updated = isMarkerOnlyPatch(args.patch) ? { ...existing, ...args.patch } : { ...existing, ...args.patch, updatedAt: nowIso2(this.deps) };
50517
50508
  if (args.patch.model !== void 0) {
50518
50509
  delete updated.resolvedModel;
50519
50510
  delete updated.resolvedEffort;
@@ -50760,6 +50751,11 @@ var SessionManager = class {
50760
50751
  const runner = this.runners.get(sessionId);
50761
50752
  return runner?.getState() ?? null;
50762
50753
  }
50754
+ /** Native id of the turn this daemon is running right now; null when no foreground turn is open. */
50755
+ openTurnId(sessionId) {
50756
+ const state = this.runners.get(sessionId)?.getState();
50757
+ return state?.turnOpen ? latestTurnId(state) ?? null : null;
50758
+ }
50763
50759
  // 等真实 proc-exit 再 ack,避免调用方开始删除 worktree 时进程仍持文件锁;超时向上报错。
50764
50760
  async stop(args) {
50765
50761
  const file = this.findOwnedSession(args.sessionId);
@@ -66809,6 +66805,11 @@ async function portableCloudInput(text, resolvers) {
66809
66805
 
66810
66806
  // src/tools/cloud-turn-session.ts
66811
66807
  var import_node_crypto16 = require("crypto");
66808
+ function withBranchIntent(text, branch) {
66809
+ return `${text}
66810
+
66811
+ <system-reminder>\u7528\u6237\u5728\u754C\u9762\u4E0A\u9009\u62E9\u4E86\u5206\u652F ${branch}\uFF0C\u5E0C\u671B\u672C\u4F1A\u8BDD\u5DE5\u4F5C\u5728\u8BE5\u5206\u652F\u4E0A\u3002\u5F00\u59CB\u5904\u7406\u672C\u6761\u6D88\u606F\u524D\uFF0C\u8BF7\u5148\u5207\u6362\u5230 ${branch}\uFF08\u672C\u5730\u6CA1\u6709\u5C31\u4ECE origin \u53D6\uFF09\uFF1B\u5982\u679C\u5DE5\u4F5C\u533A\u6709\u672A\u63D0\u4EA4\u7684\u6539\u52A8\uFF0C\u5148\u544A\u8BC9\u7528\u6237\u518D\u5904\u7406\u3002</system-reminder>`;
66812
+ }
66812
66813
  function createCloudTurnSession(args) {
66813
66814
  const { ctx, sink, client, personaId: personaId2, engine, instructions, engineSessionId, prepare } = args;
66814
66815
  let conversationId = ctx.cloudConversationId ?? ctx.cloudExecutionId;
@@ -66836,7 +66837,9 @@ function createCloudTurnSession(args) {
66836
66837
  live.add(commandId);
66837
66838
  submission = submission.then(async () => {
66838
66839
  try {
66839
- const portable = prepared ? text : await prepare(text);
66840
+ const intent = prepared ? void 0 : sink.pendingBranchIntent?.();
66841
+ const prepared0 = prepared ? text : await prepare(text);
66842
+ const portable = intent ? withBranchIntent(prepared0, intent) : prepared0;
66840
66843
  if (closed || sink.onCommandPrepared?.(commandId, portable, prepared) === false) {
66841
66844
  live.delete(commandId);
66842
66845
  return;
@@ -66856,6 +66859,7 @@ function createCloudTurnSession(args) {
66856
66859
  ...ctx.personaMode ? { personaMode: ctx.personaMode } : {},
66857
66860
  ...ctx.titleOnly ? { purpose: "title" } : {}
66858
66861
  });
66862
+ if (intent) sink.onBranchIntentDelivered?.(intent);
66859
66863
  if (closed) {
66860
66864
  stream.close();
66861
66865
  return;
@@ -73495,6 +73499,13 @@ function slimHistoryMessages(messages) {
73495
73499
  return out;
73496
73500
  });
73497
73501
  }
73502
+ function markOpenTurnInProgress(page, openTurnId) {
73503
+ if (page.view !== "turns" || !openTurnId) return page;
73504
+ return {
73505
+ ...page,
73506
+ data: page.data.map((turn) => turn.id === openTurnId && turn.status === "interrupted" ? { ...turn, status: "inProgress" } : turn)
73507
+ };
73508
+ }
73498
73509
  function assertGuestPath(ctx, absPath, personaRoot, method, usersRoot) {
73499
73510
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
73500
73511
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
@@ -73563,6 +73574,7 @@ function buildHistoryHandlers(deps) {
73563
73574
  if (args.view) {
73564
73575
  const reader = getHistoryReader(f2.tool ?? "claude", f2.cloudEnvironment);
73565
73576
  if (!reader.readPage) throw new Error("This engine does not support turn history paging");
73577
+ const openTurnId = manager.openTurnId(args.sessionId);
73566
73578
  const page = await reader.readPage({
73567
73579
  cwd: f2.cwd,
73568
73580
  toolSessionId: f2.toolSessionId,
@@ -73572,7 +73584,7 @@ function buildHistoryHandlers(deps) {
73572
73584
  turnId: args.turnId,
73573
73585
  snapshotId: args.snapshotId
73574
73586
  });
73575
- return { response: { type: "history:read", ...page } };
73587
+ return { response: { type: "history:read", ...markOpenTurnInProgress(page, openTurnId) } };
73576
73588
  }
73577
73589
  let res;
73578
73590
  try {
@@ -74993,7 +75005,13 @@ function buildCloudWorkspaceHandlers(deps) {
74993
75005
  ERROR_CODES.VALIDATION_ERROR,
74994
75006
  "Workspace operations require a cloud session"
74995
75007
  );
74996
- if (["bind", "switch", "publish"].includes(args.action) && (!["idle", "running-idle", "stopped", "error"].includes(
75008
+ if (args.action === "intend") {
75009
+ if (!file.cloudWorkspace)
75010
+ throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "\u8BF7\u5148\u9009\u62E9\u4ED3\u5E93");
75011
+ const { broadcast } = deps.setBranchIntent(file.sessionId, args.branch);
75012
+ return { response: { type: "cloud:workspace:ok" }, broadcast };
75013
+ }
75014
+ if (args.action === "bind" && (!["idle", "running-idle", "stopped", "error"].includes(
74997
75015
  deps.status(file.sessionId)
74998
75016
  ) || file.cloudPendingTurns?.length))
74999
75017
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u5B8C\u6210");
@@ -75338,7 +75356,7 @@ function computeMethodAccess(args) {
75338
75356
  }
75339
75357
 
75340
75358
  // src/version.ts
75341
- var version = "0.2.682".length > 0 ? "0.2.682" : "dev";
75359
+ var version = "0.2.684".length > 0 ? "0.2.684" : "dev";
75342
75360
 
75343
75361
  // src/cli-probe/probe.ts
75344
75362
  var fs86 = __toESM(require("fs"), 1);
@@ -78859,6 +78877,7 @@ async function startDaemon(config) {
78859
78877
  getFile: (id) => manager.get({ sessionId: id }).response,
78860
78878
  status: (id) => manager.getCurrentStatus(id),
78861
78879
  bind: (id, binding, conversationId) => manager.bindCloudWorkspace(id, binding, conversationId),
78880
+ setBranchIntent: (id, branch) => manager.update({ sessionId: id, patch: { cloudBranchIntent: branch } }),
78862
78881
  command: (file, input) => {
78863
78882
  const personaId2 = personaIdFromCloudCwd(file.cwd);
78864
78883
  if (!personaId2)