@clawos-dev/clawd 0.2.675 → 0.2.677

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.
@@ -31036,6 +31036,114 @@ var import_node_path5 = require("path");
31036
31036
  var import_promises2 = __toESM(require("fs/promises"), 1);
31037
31037
  var import_node_path4 = __toESM(require("path"), 1);
31038
31038
 
31039
+ // ../protocol/src/cloud-workspace-schemas.ts
31040
+ var WORKSPACE_COMPARISON_VALUES = ["head", "index"];
31041
+ var Id = external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9-]{0,127}$/);
31042
+ var RepoId = external_exports.string().regex(/^[1-9][0-9]*$/);
31043
+ var Part = external_exports.string().regex(/^[A-Za-z0-9_.-]+$/);
31044
+ var WorkspaceBranchSchema = external_exports.string().min(1).max(255).refine(
31045
+ (b) => !b.startsWith("-") && b !== "HEAD" && !b.startsWith("/") && !b.endsWith("/") && !b.endsWith(".") && !/[\s~^:?*\[\\\x00-\x1f\x7f]/.test(b) && !b.includes("..") && !b.includes("@{") && !b.includes("//") && b.split("/").every((s) => !s.startsWith(".") && !s.endsWith(".lock")),
31046
+ "Invalid Git branch"
31047
+ );
31048
+ var FilePath = external_exports.string().min(1).max(4096).refine(
31049
+ (p) => !p.startsWith("/") && !p.includes("\0") && !p.split(/[\\/]/).includes("..")
31050
+ );
31051
+ var WorkspaceBindingSchema = external_exports.object({
31052
+ workspaceId: Id,
31053
+ repoId: RepoId,
31054
+ owner: Part,
31055
+ name: Part,
31056
+ sourceBranch: WorkspaceBranchSchema,
31057
+ defaultBranch: WorkspaceBranchSchema
31058
+ }).strict();
31059
+ var WorkspaceRepoSchema = external_exports.object({
31060
+ repoId: RepoId,
31061
+ owner: Part,
31062
+ name: Part,
31063
+ defaultBranch: external_exports.string(),
31064
+ private: external_exports.boolean(),
31065
+ description: external_exports.string().nullable()
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
+ var WorkspaceStatusSchema = WorkspaceBindingSchema.extend({
31074
+ initialCommit: external_exports.string(),
31075
+ head: external_exports.string(),
31076
+ actualBranch: external_exports.string().nullable(),
31077
+ branches: external_exports.array(external_exports.string()).optional(),
31078
+ files: external_exports.array(
31079
+ external_exports.object({
31080
+ path: FilePath,
31081
+ previousPath: external_exports.string().optional(),
31082
+ comparison: external_exports.enum(WORKSPACE_COMPARISON_VALUES).optional(),
31083
+ status: external_exports.string(),
31084
+ added: external_exports.number().nonnegative(),
31085
+ removed: external_exports.number().nonnegative(),
31086
+ binary: external_exports.boolean(),
31087
+ untracked: external_exports.boolean().optional()
31088
+ })
31089
+ ),
31090
+ totalFiles: external_exports.number().int().nonnegative().optional(),
31091
+ filesTruncated: external_exports.boolean().optional(),
31092
+ added: external_exports.number().nonnegative(),
31093
+ removed: external_exports.number().nonnegative(),
31094
+ dirty: external_exports.boolean(),
31095
+ conflicted: external_exports.boolean(),
31096
+ 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()
31101
+ });
31102
+ var Session = external_exports.object({ sessionId: Id });
31103
+ var CloudWorkspaceArgsSchema = external_exports.discriminatedUnion("action", [
31104
+ Session.extend({
31105
+ action: external_exports.literal("repositories"),
31106
+ page: external_exports.number().int().min(1).max(1e3).optional(),
31107
+ search: external_exports.string().max(100).optional()
31108
+ }).strict(),
31109
+ Session.extend({
31110
+ action: external_exports.literal("branches"),
31111
+ repoId: RepoId,
31112
+ page: external_exports.number().int().min(1).max(1e3).optional()
31113
+ }).strict(),
31114
+ Session.extend({
31115
+ action: external_exports.literal("bind"),
31116
+ repoId: RepoId,
31117
+ branch: WorkspaceBranchSchema
31118
+ }).strict(),
31119
+ Session.extend({ action: external_exports.literal("status") }).strict(),
31120
+ Session.extend({
31121
+ action: external_exports.literal("switch"),
31122
+ branch: WorkspaceBranchSchema,
31123
+ create: external_exports.boolean().optional()
31124
+ }).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()
31131
+ ]);
31132
+ var CloudWorkspaceResultSchema = external_exports.object({
31133
+ binding: WorkspaceBindingSchema.nullable().optional(),
31134
+ workspace: WorkspaceStatusSchema.nullable().optional(),
31135
+ repositories: external_exports.array(WorkspaceRepoSchema).optional(),
31136
+ branches: external_exports.array(external_exports.string()).optional(),
31137
+ hasMore: external_exports.boolean().optional(),
31138
+ diff: external_exports.object({
31139
+ path: FilePath,
31140
+ patch: external_exports.string(),
31141
+ binary: external_exports.boolean(),
31142
+ truncated: external_exports.boolean()
31143
+ }).optional(),
31144
+ pr: WorkspacePrSchema.optional()
31145
+ });
31146
+
31039
31147
  // ../protocol/src/subscription-channel.ts
31040
31148
  var SubscriptionChannelSchema = external_exports.object({
31041
31149
  id: external_exports.string().min(1),
@@ -32982,6 +33090,7 @@ var SessionFileSchema = external_exports.object({
32982
33090
  cloudExecutionId: external_exports.string().min(1).optional(),
32983
33091
  /** First turn ID of the per-query SSE conversation. */
32984
33092
  cloudConversationId: external_exports.string().min(1).optional(),
33093
+ cloudWorkspace: WorkspaceBindingSchema.optional(),
32985
33094
  /** Accepted local turns whose terminal gateway status has not been observed. */
32986
33095
  cloudPendingTurns: external_exports.array(external_exports.object({ id: external_exports.string().min(1), text: external_exports.string(), prepared: external_exports.boolean().optional() })).optional(),
32987
33096
  /** Owner gateway session observed in ready; proves the remote Pod was opened. */
@@ -33934,6 +34043,10 @@ var METHOD_DOCS = {
33934
34043
  summary: "\u586B\u5199\u578B\u8FDE\u63A5\u5668\uFF1A\u628A\u4F7F\u7528\u8005\u672C\u4EBA\u7684\u51ED\u636E\u503C\u4EA4\u7ED9\u4E2D\u5FC3\u52A0\u5BC6\u5165\u5E93\uFF08\u4E00\u6B21\u586B\u5199\u5168\u5C40\u5171\u7528\uFF09\u3002**\u8FD9\u662F\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u3001\u672C\u673A\u4E0D\u843D\u76D8\uFF1B\u683C\u540D\u5FC5\u987B\u662F\u8BE5\u8FDE\u63A5\u5668\u58F0\u660E\u8FC7\u7684\uFF1Bowner-only",
33935
34044
  args: CloudConnectorFillArgsSchema
33936
34045
  },
34046
+ "cloud:workspace": {
34047
+ summary: "Inspect or operate the calling owner cloud session Git workspace; paths and GitHub credentials stay server-side.",
34048
+ args: CloudWorkspaceArgsSchema
34049
+ },
33937
34050
  "cloud:volume:get": {
33938
34051
  summary: "\u8C03\u7528\u65B9\u81EA\u5DF1\u90A3\u5757\u4E91\u76D8\u4E0A\u4E00\u8F6E\u672B\u7684\u7528\u91CF\uFF08usedBytes / sizeBytes / measuredAt\uFF09\u3002\u4EC5 gateway \u7684 disk \u5907\u9009\u540E\u7AEF\u6709\u503C\uFF08\u90A3\u91CC\u6309\u4EBA\u4E0D\u6309 persona\uFF1A\u4E91\u4E0A\u6240\u6709 persona \u5171\u7528\u4E00\u5757\u76D8\uFF09\uFF0C\u7EBF\u4E0A snapshot \u540E\u7AEF\u6CA1\u6709\u4E91\u76D8\u3001\u6052\u56DE null\u3002daemon \u62FF\u672C\u673A api key \u95EE gateway /me/volume\uFF1B\u6CA1\u767B\u5F55 / \u6CA1 key / gateway \u4E0D\u901A / \u6CA1\u8DD1\u8FC7\u4EFB\u52A1 / \u5F53\u524D\u540E\u7AEF\u6CA1\u6709\u4E91\u76D8\u4E00\u5F8B\u56DE volume:null\uFF08\u89D2\u6807\u4E0D\u6E32\uFF09\uFF0C\u4E0D\u629B\uFF1Bowner-only\u3002\u65E0\u53C2\u6570\uFF08\u67E5\u7684\u662F\u8C03\u7528\u65B9\u81EA\u5DF1\u7684\u76D8\uFF09",
33939
34052
  args: NO_ARGS
@@ -34277,15 +34390,15 @@ var METHOD_DOCS = {
34277
34390
  summary: "\u5217\u51FA\u767B\u5F55\u8BBF\u95EE\u8FC7\u672C\u673A public persona \u7684 web \u8BBF\u5BA2\u3002owner-only",
34278
34391
  args: NO_ARGS
34279
34392
  },
34280
- "whoami": {
34393
+ whoami: {
34281
34394
  summary: "\u8FD4\u56DE\u672C\u8FDE\u63A5\u7684\u8EAB\u4EFD\uFF1Aowner \u663E\u793A\u540D + capability wire \u5F62\u6001 + \u88AB\u6388\u6743\u7684 persona \u5217\u8868\u3002\u4EFB\u4F55 authed \u8FDE\u63A5\u53EF\u8C03",
34282
34395
  args: NO_ARGS
34283
34396
  },
34284
- "info": {
34397
+ info: {
34285
34398
  summary: "daemon \u8FD0\u884C\u65F6\u4FE1\u606F\uFF1A\u7248\u672C / \u534F\u8BAE\u7248\u672C / \u4E3B\u673A / \u53EF\u7528 tool / \u5728\u8DD1\u7684\u4F1A\u8BDD / tunnel URL \u7B49",
34286
34399
  args: NO_ARGS
34287
34400
  },
34288
- "ping": {
34401
+ ping: {
34289
34402
  summary: "\u5B58\u6D3B\u63A2\u6D4B\uFF0C\u56DE pong",
34290
34403
  args: NO_ARGS
34291
34404
  },
package/dist/cli.cjs CHANGED
@@ -4149,6 +4149,121 @@ var init_zod = __esm({
4149
4149
  }
4150
4150
  });
4151
4151
 
4152
+ // ../protocol/src/cloud-workspace-schemas.ts
4153
+ var WORKSPACE_COMPARISON_VALUES, Id, RepoId, Part, WorkspaceBranchSchema, FilePath, WorkspaceBindingSchema, WorkspaceRepoSchema, WorkspacePrSchema, WorkspaceStatusSchema, Session, CloudWorkspaceArgsSchema, CloudWorkspaceResultSchema;
4154
+ var init_cloud_workspace_schemas = __esm({
4155
+ "../protocol/src/cloud-workspace-schemas.ts"() {
4156
+ "use strict";
4157
+ init_zod();
4158
+ WORKSPACE_COMPARISON_VALUES = ["head", "index"];
4159
+ Id = external_exports.string().regex(/^[A-Za-z0-9][A-Za-z0-9-]{0,127}$/);
4160
+ RepoId = external_exports.string().regex(/^[1-9][0-9]*$/);
4161
+ Part = external_exports.string().regex(/^[A-Za-z0-9_.-]+$/);
4162
+ WorkspaceBranchSchema = external_exports.string().min(1).max(255).refine(
4163
+ (b3) => !b3.startsWith("-") && b3 !== "HEAD" && !b3.startsWith("/") && !b3.endsWith("/") && !b3.endsWith(".") && !/[\s~^:?*\[\\\x00-\x1f\x7f]/.test(b3) && !b3.includes("..") && !b3.includes("@{") && !b3.includes("//") && b3.split("/").every((s2) => !s2.startsWith(".") && !s2.endsWith(".lock")),
4164
+ "Invalid Git branch"
4165
+ );
4166
+ FilePath = external_exports.string().min(1).max(4096).refine(
4167
+ (p3) => !p3.startsWith("/") && !p3.includes("\0") && !p3.split(/[\\/]/).includes("..")
4168
+ );
4169
+ WorkspaceBindingSchema = external_exports.object({
4170
+ workspaceId: Id,
4171
+ repoId: RepoId,
4172
+ owner: Part,
4173
+ name: Part,
4174
+ sourceBranch: WorkspaceBranchSchema,
4175
+ defaultBranch: WorkspaceBranchSchema
4176
+ }).strict();
4177
+ WorkspaceRepoSchema = external_exports.object({
4178
+ repoId: RepoId,
4179
+ owner: Part,
4180
+ name: Part,
4181
+ defaultBranch: external_exports.string(),
4182
+ private: external_exports.boolean(),
4183
+ description: external_exports.string().nullable()
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
+ WorkspaceStatusSchema = WorkspaceBindingSchema.extend({
4192
+ initialCommit: external_exports.string(),
4193
+ head: external_exports.string(),
4194
+ actualBranch: external_exports.string().nullable(),
4195
+ branches: external_exports.array(external_exports.string()).optional(),
4196
+ files: external_exports.array(
4197
+ external_exports.object({
4198
+ path: FilePath,
4199
+ previousPath: external_exports.string().optional(),
4200
+ comparison: external_exports.enum(WORKSPACE_COMPARISON_VALUES).optional(),
4201
+ status: external_exports.string(),
4202
+ added: external_exports.number().nonnegative(),
4203
+ removed: external_exports.number().nonnegative(),
4204
+ binary: external_exports.boolean(),
4205
+ untracked: external_exports.boolean().optional()
4206
+ })
4207
+ ),
4208
+ totalFiles: external_exports.number().int().nonnegative().optional(),
4209
+ filesTruncated: external_exports.boolean().optional(),
4210
+ added: external_exports.number().nonnegative(),
4211
+ removed: external_exports.number().nonnegative(),
4212
+ dirty: external_exports.boolean(),
4213
+ conflicted: external_exports.boolean(),
4214
+ 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()
4219
+ });
4220
+ Session = external_exports.object({ sessionId: Id });
4221
+ CloudWorkspaceArgsSchema = external_exports.discriminatedUnion("action", [
4222
+ Session.extend({
4223
+ action: external_exports.literal("repositories"),
4224
+ page: external_exports.number().int().min(1).max(1e3).optional(),
4225
+ search: external_exports.string().max(100).optional()
4226
+ }).strict(),
4227
+ Session.extend({
4228
+ action: external_exports.literal("branches"),
4229
+ repoId: RepoId,
4230
+ page: external_exports.number().int().min(1).max(1e3).optional()
4231
+ }).strict(),
4232
+ Session.extend({
4233
+ action: external_exports.literal("bind"),
4234
+ repoId: RepoId,
4235
+ branch: WorkspaceBranchSchema
4236
+ }).strict(),
4237
+ Session.extend({ action: external_exports.literal("status") }).strict(),
4238
+ Session.extend({
4239
+ action: external_exports.literal("switch"),
4240
+ branch: WorkspaceBranchSchema,
4241
+ create: external_exports.boolean().optional()
4242
+ }).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()
4249
+ ]);
4250
+ CloudWorkspaceResultSchema = external_exports.object({
4251
+ binding: WorkspaceBindingSchema.nullable().optional(),
4252
+ workspace: WorkspaceStatusSchema.nullable().optional(),
4253
+ repositories: external_exports.array(WorkspaceRepoSchema).optional(),
4254
+ branches: external_exports.array(external_exports.string()).optional(),
4255
+ hasMore: external_exports.boolean().optional(),
4256
+ diff: external_exports.object({
4257
+ path: FilePath,
4258
+ patch: external_exports.string(),
4259
+ binary: external_exports.boolean(),
4260
+ truncated: external_exports.boolean()
4261
+ }).optional(),
4262
+ pr: WorkspacePrSchema.optional()
4263
+ });
4264
+ }
4265
+ });
4266
+
4152
4267
  // ../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/Options.js
4153
4268
  var ignoreOverride, defaultOptions, getDefaultOptions;
4154
4269
  var init_Options = __esm({
@@ -8088,6 +8203,7 @@ var init_schemas = __esm({
8088
8203
  "../protocol/src/schemas.ts"() {
8089
8204
  "use strict";
8090
8205
  init_zod();
8206
+ init_cloud_workspace_schemas();
8091
8207
  init_release_schemas();
8092
8208
  init_events();
8093
8209
  init_attachment_schemas();
@@ -8183,6 +8299,7 @@ var init_schemas = __esm({
8183
8299
  cloudExecutionId: external_exports.string().min(1).optional(),
8184
8300
  /** First turn ID of the per-query SSE conversation. */
8185
8301
  cloudConversationId: external_exports.string().min(1).optional(),
8302
+ cloudWorkspace: WorkspaceBindingSchema.optional(),
8186
8303
  /** Accepted local turns whose terminal gateway status has not been observed. */
8187
8304
  cloudPendingTurns: external_exports.array(external_exports.object({ id: external_exports.string().min(1), text: external_exports.string(), prepared: external_exports.boolean().optional() })).optional(),
8188
8305
  /** Owner gateway session observed in ready; proves the remote Pod was opened. */
@@ -8870,6 +8987,7 @@ var init_methods = __esm({
8870
8987
  "../protocol/src/methods.ts"() {
8871
8988
  "use strict";
8872
8989
  init_zod();
8990
+ init_cloud_workspace_schemas();
8873
8991
  init_esm();
8874
8992
  init_subscription_channel();
8875
8993
  init_attachment_schemas();
@@ -9184,6 +9302,10 @@ var init_methods = __esm({
9184
9302
  summary: "\u586B\u5199\u578B\u8FDE\u63A5\u5668\uFF1A\u628A\u4F7F\u7528\u8005\u672C\u4EBA\u7684\u51ED\u636E\u503C\u4EA4\u7ED9\u4E2D\u5FC3\u52A0\u5BC6\u5165\u5E93\uFF08\u4E00\u6B21\u586B\u5199\u5168\u5C40\u5171\u7528\uFF09\u3002**\u8FD9\u662F\u503C\u552F\u4E00\u7684\u5165\u53E3**\uFF1A\u5165\u53C2\u4E0D\u8FDB\u65E5\u5FD7\u3001\u54CD\u5E94\u4E0D\u56DE\u663E\u3001\u672C\u673A\u4E0D\u843D\u76D8\uFF1B\u683C\u540D\u5FC5\u987B\u662F\u8BE5\u8FDE\u63A5\u5668\u58F0\u660E\u8FC7\u7684\uFF1Bowner-only",
9185
9303
  args: CloudConnectorFillArgsSchema
9186
9304
  },
9305
+ "cloud:workspace": {
9306
+ summary: "Inspect or operate the calling owner cloud session Git workspace; paths and GitHub credentials stay server-side.",
9307
+ args: CloudWorkspaceArgsSchema
9308
+ },
9187
9309
  "cloud:volume:get": {
9188
9310
  summary: "\u8C03\u7528\u65B9\u81EA\u5DF1\u90A3\u5757\u4E91\u76D8\u4E0A\u4E00\u8F6E\u672B\u7684\u7528\u91CF\uFF08usedBytes / sizeBytes / measuredAt\uFF09\u3002\u4EC5 gateway \u7684 disk \u5907\u9009\u540E\u7AEF\u6709\u503C\uFF08\u90A3\u91CC\u6309\u4EBA\u4E0D\u6309 persona\uFF1A\u4E91\u4E0A\u6240\u6709 persona \u5171\u7528\u4E00\u5757\u76D8\uFF09\uFF0C\u7EBF\u4E0A snapshot \u540E\u7AEF\u6CA1\u6709\u4E91\u76D8\u3001\u6052\u56DE null\u3002daemon \u62FF\u672C\u673A api key \u95EE gateway /me/volume\uFF1B\u6CA1\u767B\u5F55 / \u6CA1 key / gateway \u4E0D\u901A / \u6CA1\u8DD1\u8FC7\u4EFB\u52A1 / \u5F53\u524D\u540E\u7AEF\u6CA1\u6709\u4E91\u76D8\u4E00\u5F8B\u56DE volume:null\uFF08\u89D2\u6807\u4E0D\u6E32\uFF09\uFF0C\u4E0D\u629B\uFF1Bowner-only\u3002\u65E0\u53C2\u6570\uFF08\u67E5\u7684\u662F\u8C03\u7528\u65B9\u81EA\u5DF1\u7684\u76D8\uFF09",
9189
9311
  args: NO_ARGS
@@ -9527,15 +9649,15 @@ var init_methods = __esm({
9527
9649
  summary: "\u5217\u51FA\u767B\u5F55\u8BBF\u95EE\u8FC7\u672C\u673A public persona \u7684 web \u8BBF\u5BA2\u3002owner-only",
9528
9650
  args: NO_ARGS
9529
9651
  },
9530
- "whoami": {
9652
+ whoami: {
9531
9653
  summary: "\u8FD4\u56DE\u672C\u8FDE\u63A5\u7684\u8EAB\u4EFD\uFF1Aowner \u663E\u793A\u540D + capability wire \u5F62\u6001 + \u88AB\u6388\u6743\u7684 persona \u5217\u8868\u3002\u4EFB\u4F55 authed \u8FDE\u63A5\u53EF\u8C03",
9532
9654
  args: NO_ARGS
9533
9655
  },
9534
- "info": {
9656
+ info: {
9535
9657
  summary: "daemon \u8FD0\u884C\u65F6\u4FE1\u606F\uFF1A\u7248\u672C / \u534F\u8BAE\u7248\u672C / \u4E3B\u673A / \u53EF\u7528 tool / \u5728\u8DD1\u7684\u4F1A\u8BDD / tunnel URL \u7B49",
9536
9658
  args: NO_ARGS
9537
9659
  },
9538
- "ping": {
9660
+ ping: {
9539
9661
  summary: "\u5B58\u6D3B\u63A2\u6D4B\uFF0C\u56DE pong",
9540
9662
  args: NO_ARGS
9541
9663
  },
@@ -9970,6 +10092,7 @@ var init_runtime = __esm({
9970
10092
  init_engine_schemas();
9971
10093
  init_tool_family();
9972
10094
  init_subscription_channel();
10095
+ init_cloud_workspace_schemas();
9973
10096
  }
9974
10097
  });
9975
10098
 
@@ -48008,6 +48131,7 @@ function buildSpawnContext(state, deps) {
48008
48131
  const ctx = {
48009
48132
  cwd: file.cwd,
48010
48133
  cloudExecutionId: file.cloudExecutionId,
48134
+ ...file.cloudWorkspace ? { cloudWorkspace: file.cloudWorkspace } : {},
48011
48135
  ...file.cloudEnvironment ? { cloudEnvironment: file.cloudEnvironment } : {},
48012
48136
  ...file.cloudExpectedImage ? { cloudExpectedImage: file.cloudExpectedImage } : {},
48013
48137
  ...file.testReleaseId ? { testReleaseId: file.testReleaseId } : {},
@@ -49902,7 +50026,10 @@ var SessionManager = class {
49902
50026
  const expand = (p3) => p3 === "~" ? home : p3.startsWith("~/") ? import_node_path14.default.join(home, p3.slice(2)) : p3;
49903
50027
  const codexCfg = this.deps.personaStore?.readCodexSandboxSettings(scope.personaId) ?? null;
49904
50028
  subSessionMeta.codexSandbox = {
49905
- writableRoots: [subSessionMeta.userWorkDir, ...(codexCfg?.writableRoots ?? []).map(expand)],
50029
+ writableRoots: [
50030
+ subSessionMeta.userWorkDir,
50031
+ ...(codexCfg?.writableRoots ?? []).map(expand)
50032
+ ],
49906
50033
  denyRead: codexCfg?.denyRead ?? [],
49907
50034
  network: codexCfg?.network ?? false
49908
50035
  };
@@ -50345,6 +50472,24 @@ var SessionManager = class {
50345
50472
  this.writeOwned(updated);
50346
50473
  return { response: updated, broadcast: [] };
50347
50474
  }
50475
+ bindCloudWorkspace(sessionId, binding, conversationId) {
50476
+ const file = this.getFile(sessionId);
50477
+ if (!isCloudTool(file.tool) || file.cloudPendingTurns?.length)
50478
+ throw new ClawdError(
50479
+ ERROR_CODES.VALIDATION_ERROR,
50480
+ "Cloud workspace cannot bind while a turn is pending"
50481
+ );
50482
+ if (file.cloudWorkspace && JSON.stringify(file.cloudWorkspace) !== JSON.stringify(binding))
50483
+ throw new ClawdError(
50484
+ ERROR_CODES.VALIDATION_ERROR,
50485
+ "Workspace binding is immutable"
50486
+ );
50487
+ this.runners.get(sessionId)?.confirmCloudCancelled();
50488
+ this.update({
50489
+ sessionId,
50490
+ patch: { cloudWorkspace: binding, cloudConversationId: conversationId }
50491
+ });
50492
+ }
50348
50493
  /**
50349
50494
  * [T-17] observer 检测到 CC 挪走 transcript(cwd 中途变化)后的 cwd 校正入口。
50350
50495
  * 不进 withCollector:observer 回调没有 in-flight RPC,session:info 帧走
@@ -50711,6 +50856,11 @@ var SessionManager = class {
50711
50856
  }
50712
50857
  newSession(args) {
50713
50858
  const existingFile = this.getFile(args.sessionId);
50859
+ if (existingFile.cloudWorkspace)
50860
+ throw new ClawdError(
50861
+ ERROR_CODES.VALIDATION_ERROR,
50862
+ "\u6B64\u4F1A\u8BDD\u5DF2\u7ED1\u5B9A\u5DE5\u4F5C\u533A\uFF0C\u8BF7\u65B0\u5EFA\u4F1A\u8BDD\u4EE5\u5F00\u59CB\u72EC\u7ACB\u73B0\u573A"
50863
+ );
50714
50864
  this.titleGenPending.get(args.sessionId)?.abort();
50715
50865
  this.titleGenPending.delete(args.sessionId);
50716
50866
  const nextToolSessionId = this.deps.mode === "tui" && (existingFile.tool ?? "claude") === "claude" ? (0, import_node_crypto5.randomUUID)() : void 0;
@@ -50763,6 +50913,11 @@ var SessionManager = class {
50763
50913
  }
50764
50914
  async newSessionWithCloudCancel(args) {
50765
50915
  const file = this.getFile(args.sessionId);
50916
+ if (file.cloudWorkspace)
50917
+ throw new ClawdError(
50918
+ ERROR_CODES.VALIDATION_ERROR,
50919
+ "\u6B64\u4F1A\u8BDD\u5DF2\u7ED1\u5B9A\u5DE5\u4F5C\u533A\uFF0C\u8BF7\u65B0\u5EFA\u4F1A\u8BDD\u4EE5\u5F00\u59CB\u72EC\u7ACB\u73B0\u573A"
50920
+ );
50766
50921
  if (isCloudTool(file.tool)) {
50767
50922
  await this.cancelCloudTurns(file, this.runners.get(args.sessionId) ?? null);
50768
50923
  return this.newSession(args);
@@ -50770,7 +50925,12 @@ var SessionManager = class {
50770
50925
  return this.newSession(args);
50771
50926
  }
50772
50927
  resume(args) {
50773
- this.getFile(args.sessionId);
50928
+ const file = this.getFile(args.sessionId);
50929
+ if (file.cloudWorkspace && file.toolSessionId !== args.toolSessionId)
50930
+ throw new ClawdError(
50931
+ ERROR_CODES.VALIDATION_ERROR,
50932
+ "\u5DE5\u4F5C\u533A\u4E0D\u80FD\u5207\u6362\u5230\u53E6\u4E00\u6761\u539F\u751F\u4F1A\u8BDD\u5386\u53F2"
50933
+ );
50774
50934
  const runner = this.runners.get(args.sessionId);
50775
50935
  if (runner) {
50776
50936
  const { value, broadcast } = this.withCollector(() => {
@@ -57741,6 +57901,7 @@ var GATEWAY_ROUTES = {
57741
57901
  turnCommand: (personaId2, turnId) => `/p/${encodeURIComponent(personaId2)}/turns/${encodeURIComponent(turnId)}/commands`,
57742
57902
  conversationCancel: (personaId2, conversationId) => `/p/${encodeURIComponent(personaId2)}/conversations/${encodeURIComponent(conversationId)}:cancel`,
57743
57903
  volume: () => "/me/volume",
57904
+ workspace: (personaId2) => `/p/${encodeURIComponent(personaId2)}/workspace`,
57744
57905
  metrics: (personaId2) => `/metrics/${encodeURIComponent(personaId2)}`
57745
57906
  };
57746
57907
  var METRICS_TIMEOUT_MS = 3e4;
@@ -57824,6 +57985,27 @@ var CloudGatewayClient = class {
57824
57985
  const list = await this.fetchDeployments(trimSlash(gatewayUrl));
57825
57986
  return list.find((p3) => p3.personaId === gatewayPersonaId)?.connectors ?? [];
57826
57987
  }
57988
+ async workspaceCommand(personaId2, input) {
57989
+ const { apiKey, gatewayUrl } = await this.credentials();
57990
+ const res = await this.fetchImpl(
57991
+ gatewayUrl + GATEWAY_ROUTES.workspace(personaId2),
57992
+ {
57993
+ method: "POST",
57994
+ headers: {
57995
+ authorization: `Bearer ${apiKey}`,
57996
+ "content-type": "application/json"
57997
+ },
57998
+ body: JSON.stringify(input),
57999
+ signal: AbortSignal.timeout(3e5)
58000
+ }
58001
+ );
58002
+ const body = await res.json();
58003
+ if (!res.ok)
58004
+ throw new Error(
58005
+ body.error?.message ?? `Cloud workspace request failed (${res.status})`
58006
+ );
58007
+ return CloudWorkspaceResultSchema.parse(body);
58008
+ }
57827
58009
  async openTurn(personaId2, opts) {
57828
58010
  const { apiKey, gatewayUrl } = await this.credentials();
57829
58011
  const health = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.healthz());
@@ -57910,6 +58092,7 @@ function openHttpTurn(opts) {
57910
58092
  conversationId,
57911
58093
  turnId,
57912
58094
  expectedEngine,
58095
+ ...opts.workspaceId ? { workspaceId: opts.workspaceId } : {},
57913
58096
  ...opts.expectedImage ? { expectedImage: opts.expectedImage } : {},
57914
58097
  ...purpose ? { purpose } : {},
57915
58098
  ...engineSessionId ? { engineSessionId } : {},
@@ -57948,10 +58131,14 @@ function openHttpTurn(opts) {
57948
58131
  const retryWait = (ms) => new Promise((resolve9) => {
57949
58132
  const timer = setTimeout(resolve9, ms);
57950
58133
  timer.unref?.();
57951
- abort.signal.addEventListener("abort", () => {
57952
- clearTimeout(timer);
57953
- resolve9();
57954
- }, { once: true });
58134
+ abort.signal.addEventListener(
58135
+ "abort",
58136
+ () => {
58137
+ clearTimeout(timer);
58138
+ resolve9();
58139
+ },
58140
+ { once: true }
58141
+ );
57955
58142
  });
57956
58143
  void (async () => {
57957
58144
  while (!closed) {
@@ -64161,7 +64348,8 @@ function buildDeployHandlers(deps) {
64161
64348
  }
64162
64349
  }
64163
64350
  const already = [...file.releases].reverse().find((r2) => r2.environment === "integration" && r2.scanId === scanId && r2.pushed && r2.head === repo2.head);
64164
- if (already && !repo2.dirty) {
64351
+ const alreadyRun = already && !repo2.dirty ? await runByHead(api, repoSlug(repo2.url), already.head) : void 0;
64352
+ if (already && !repo2.dirty && alreadyRun?.status !== "completed") {
64165
64353
  await configureTestIdentity(api, repoSlug(repo2.url));
64166
64354
  return { response: { type: "deploy:release", sha: already.head, actionsUrl: "https://github.com/" + repoSlug(repo2.url) + "/actions" } };
64167
64355
  }
@@ -66603,6 +66791,7 @@ function createCloudTurnSession(args) {
66603
66791
  turnId: commandId,
66604
66792
  text: portable,
66605
66793
  expectedEngine: engine,
66794
+ ...ctx.cloudWorkspace ? { workspaceId: ctx.cloudWorkspace.workspaceId } : {},
66606
66795
  ...ctx.cloudExpectedImage ? { expectedImage: ctx.cloudExpectedImage } : {},
66607
66796
  // pi / claude 的会话 id 预分配(引擎按它新建或续那个会话文件);codex 的 thread id 在协议内
66608
66797
  ...(engine === "pi" || engine === "claude") && !ctx.titleOnly ? { engineSessionId: engineSessionId ?? conversationId } : {},
@@ -74714,6 +74903,44 @@ function buildCloudConnectorsHandlers(deps) {
74714
74903
  };
74715
74904
  }
74716
74905
 
74906
+ // src/handlers/cloud-workspace.ts
74907
+ init_protocol();
74908
+ function buildCloudWorkspaceHandlers(deps) {
74909
+ return {
74910
+ "cloud:workspace": async (frame, _client, ctx) => {
74911
+ if (ctx?.principal.kind !== "owner")
74912
+ throw new ClawdError(
74913
+ ERROR_CODES.UNAUTHORIZED,
74914
+ "cloud:workspace requires owner context"
74915
+ );
74916
+ const { type: _type, requestId: _requestId, ...body } = frame;
74917
+ const args = parseArgs2(CloudWorkspaceArgsSchema, body, "cloud:workspace");
74918
+ const file = deps.getFile(args.sessionId);
74919
+ if (!isCloudTool(file.tool))
74920
+ throw new ClawdError(
74921
+ ERROR_CODES.VALIDATION_ERROR,
74922
+ "Workspace operations require a cloud session"
74923
+ );
74924
+ if (["bind", "switch", "publish"].includes(args.action) && (!["idle", "running-idle", "stopped", "error"].includes(
74925
+ deps.status(file.sessionId)
74926
+ ) || file.cloudPendingTurns?.length))
74927
+ throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, "\u8BF7\u7B49\u5F85\u5F53\u524D\u4EFB\u52A1\u5B8C\u6210");
74928
+ const conversationId = file.cloudConversationId ?? file.cloudExecutionId ?? file.sessionId;
74929
+ const result = CloudWorkspaceResultSchema.parse(
74930
+ await deps.command(file, {
74931
+ ...args,
74932
+ workspaceId: file.cloudWorkspace?.workspaceId ?? file.sessionId,
74933
+ conversationId,
74934
+ ...file.toolSessionId ? { threadId: file.toolSessionId } : {}
74935
+ })
74936
+ );
74937
+ if (result.binding && !file.cloudWorkspace)
74938
+ deps.bind(file.sessionId, result.binding, conversationId);
74939
+ return { response: { type: "cloud:workspace:ok", ...result } };
74940
+ }
74941
+ };
74942
+ }
74943
+
74717
74944
  // src/handlers/cloud-volume.ts
74718
74945
  init_protocol();
74719
74946
  function ensureOwner7(ctx) {
@@ -74785,9 +75012,9 @@ var ADMIN_ANY = {
74785
75012
  };
74786
75013
  var CAPABILITY_SCOPED = { kind: "capability-scoped" };
74787
75014
  var METHOD_GRANT_MAP = {
74788
- "info": { kind: "public" },
74789
- "ping": { kind: "public" },
74790
- "whoami": { kind: "public" },
75015
+ info: { kind: "public" },
75016
+ ping: { kind: "public" },
75017
+ whoami: { kind: "public" },
74791
75018
  // Introspection includes denied methods so callers can discover their authorization boundaries.
74792
75019
  "meta:methods": { kind: "public" },
74793
75020
  // Public inbox handlers still bind guest access to the authenticated peer device, not arbitrary DM buckets.
@@ -74824,6 +75051,7 @@ var METHOD_GRANT_MAP = {
74824
75051
  "dashboard:openUrl": ADMIN_ANY,
74825
75052
  "cloud:connectors:fill": ADMIN_ANY,
74826
75053
  "cloud:volume:get": ADMIN_ANY,
75054
+ "cloud:workspace": ADMIN_ANY,
74827
75055
  // Session handlers resolve the target and enforce guest access; the dispatcher cannot authorize from method alone.
74828
75056
  "session:create": CAPABILITY_SCOPED,
74829
75057
  "session:importExternal": CAPABILITY_SCOPED,
@@ -75038,7 +75266,7 @@ function computeMethodAccess(args) {
75038
75266
  }
75039
75267
 
75040
75268
  // src/version.ts
75041
- var version = "0.2.675".length > 0 ? "0.2.675" : "dev";
75269
+ var version = "0.2.677".length > 0 ? "0.2.677" : "dev";
75042
75270
 
75043
75271
  // src/cli-probe/probe.ts
75044
75272
  var fs86 = __toESM(require("fs"), 1);
@@ -76990,6 +77218,7 @@ function buildMethodHandlers(deps) {
76990
77218
  ...buildDeviceHandlers(deps.feishuDevice),
76991
77219
  ...buildCloudConnectorsHandlers(deps.cloudConnectors),
76992
77220
  ...buildCloudVolumeHandlers(deps.cloudVolume),
77221
+ ...deps.cloudWorkspace ? buildCloudWorkspaceHandlers(deps.cloudWorkspace) : {},
76993
77222
  ...buildDashboardHandlers(deps.dashboard),
76994
77223
  ...deps.attachment ? buildAttachmentHandlers(deps.attachment) : {},
76995
77224
  ...buildExtensionHandlers({
@@ -78552,6 +78781,20 @@ async function startDaemon(config) {
78552
78781
  fill: (args) => centralConnectorFill({ api: config.clawosApi ?? DEFAULT_CLAWOS_API, ...args })
78553
78782
  }
78554
78783
  },
78784
+ cloudWorkspace: {
78785
+ getFile: (id) => manager.get({ sessionId: id }).response,
78786
+ status: (id) => manager.getCurrentStatus(id),
78787
+ bind: (id, binding, conversationId) => manager.bindCloudWorkspace(id, binding, conversationId),
78788
+ command: (file, input) => {
78789
+ const personaId2 = personaIdFromCloudCwd(file.cwd);
78790
+ if (!personaId2)
78791
+ throw new Error("Cloud workspace requires a registered persona URL");
78792
+ return gatewayForEnvironment(file.cloudEnvironment).workspaceCommand(
78793
+ personaId2,
78794
+ input
78795
+ );
78796
+ }
78797
+ },
78555
78798
  cloudVolume: {
78556
78799
  getLoginPass: () => ownerIdentityStore.read()?.loginPass ?? null,
78557
78800
  fetchVolume: () => cloudGateway.fetchVolume(),