@clawos-dev/clawd 0.2.102-beta.197.08025e2 → 0.2.103-beta.198.c756b33

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.
Files changed (2) hide show
  1. package/dist/cli.cjs +69 -22
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -5367,6 +5367,20 @@ var init_received_capability = __esm({
5367
5367
  });
5368
5368
 
5369
5369
  // ../protocol/src/extension.ts
5370
+ function isAllowedHostedUrl(raw) {
5371
+ let u;
5372
+ try {
5373
+ u = new URL(raw);
5374
+ } catch {
5375
+ return false;
5376
+ }
5377
+ if (u.protocol === "https:") return true;
5378
+ if (u.protocol === "http:" && LOCALHOST_HOSTS.has(u.hostname)) return true;
5379
+ return false;
5380
+ }
5381
+ function manifestMode(m2) {
5382
+ return m2.entry?.url ? "hosted" : "local";
5383
+ }
5370
5384
  function ownerNamespace(ownerPrincipalId) {
5371
5385
  let h = 2166136261;
5372
5386
  for (let i = 0; i < ownerPrincipalId.length; i++) {
@@ -5408,7 +5422,7 @@ function parseOrThrow(v2) {
5408
5422
  const [a, b2, c] = v2.split(".").map((p2) => parseInt(p2, 10));
5409
5423
  return [a, b2, c];
5410
5424
  }
5411
- var EXT_ID_REGEX, ExtensionStateSchema, ExtensionManifestSchema, ExtensionRecordSchema, PublishedSnapshotSchema, ChannelRefSchema, SourceRefSchema, PublishedExtensionRecordSchema, PublishCheckSchema, PublishStatusResultSchema;
5425
+ var EXT_ID_REGEX, ExtensionStateSchema, LOCALHOST_HOSTS, ExtensionManifestSchema, ExtensionTargetSchema, ExtensionRecordSchema, PublishedSnapshotSchema, ChannelRefSchema, SourceRefSchema, PublishedExtensionRecordSchema, PublishCheckSchema, PublishStatusResultSchema;
5412
5426
  var init_extension = __esm({
5413
5427
  "../protocol/src/extension.ts"() {
5414
5428
  "use strict";
@@ -5421,18 +5435,38 @@ var init_extension = __esm({
5421
5435
  "crashed",
5422
5436
  "invalid"
5423
5437
  ]);
5438
+ LOCALHOST_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1"]);
5424
5439
  ExtensionManifestSchema = external_exports.object({
5425
5440
  id: external_exports.string().regex(EXT_ID_REGEX),
5426
5441
  name: external_exports.string().min(1),
5427
5442
  version: external_exports.string().min(1),
5428
5443
  apiVersion: external_exports.literal("1"),
5444
+ runtime: external_exports.object({ startCommand: external_exports.string().min(1) }).passthrough().optional(),
5429
5445
  entry: external_exports.object({
5430
- ui: external_exports.string().min(1).optional()
5431
- }).strict().optional(),
5432
- runtime: external_exports.object({
5433
- startCommand: external_exports.string().min(1)
5434
- }).passthrough()
5435
- }).passthrough();
5446
+ url: external_exports.string().url().refine(isAllowedHostedUrl, {
5447
+ message: "INVALID_URL_SCHEME: only https or http://localhost is allowed"
5448
+ })
5449
+ }).strict().optional()
5450
+ }).passthrough().superRefine((m2, ctx) => {
5451
+ const hasRuntime = !!m2.runtime;
5452
+ const hasUrl = !!m2.entry?.url;
5453
+ if (hasRuntime && hasUrl) {
5454
+ ctx.addIssue({
5455
+ code: external_exports.ZodIssueCode.custom,
5456
+ message: "INVALID_MANIFEST: entry.url and runtime cannot coexist"
5457
+ });
5458
+ }
5459
+ if (!hasRuntime && !hasUrl) {
5460
+ ctx.addIssue({
5461
+ code: external_exports.ZodIssueCode.custom,
5462
+ message: "INVALID_MANIFEST: must have either entry.url or runtime"
5463
+ });
5464
+ }
5465
+ });
5466
+ ExtensionTargetSchema = external_exports.discriminatedUnion("kind", [
5467
+ external_exports.object({ kind: external_exports.literal("local"), port: external_exports.number().int().min(1).max(65535) }),
5468
+ external_exports.object({ kind: external_exports.literal("hosted"), url: external_exports.string().url() })
5469
+ ]);
5436
5470
  ExtensionRecordSchema = external_exports.discriminatedUnion("state", [
5437
5471
  external_exports.object({
5438
5472
  extId: external_exports.string(),
@@ -5448,7 +5482,7 @@ var init_extension = __esm({
5448
5482
  extId: external_exports.string(),
5449
5483
  manifest: ExtensionManifestSchema,
5450
5484
  state: external_exports.literal("running"),
5451
- port: external_exports.number().int().min(1).max(65535)
5485
+ target: ExtensionTargetSchema
5452
5486
  }),
5453
5487
  external_exports.object({
5454
5488
  extId: external_exports.string(),
@@ -37766,12 +37800,6 @@ async function importZip(buf, root) {
37766
37800
  } catch (e) {
37767
37801
  throw new ImportError("INVALID_MANIFEST", `manifest.json: ${e.message}`);
37768
37802
  }
37769
- if (manifestJson && typeof manifestJson === "object" && "entry" in manifestJson && manifestJson.entry?.url !== void 0) {
37770
- throw new ImportError(
37771
- "REMOTE_NOT_SUPPORTED",
37772
- "entry.url (remote mode) is not supported in v1"
37773
- );
37774
- }
37775
37803
  const result = ExtensionManifestSchema.safeParse(manifestJson);
37776
37804
  if (!result.success) {
37777
37805
  throw new ImportError(
@@ -37780,6 +37808,16 @@ async function importZip(buf, root) {
37780
37808
  );
37781
37809
  }
37782
37810
  const manifest = result.data;
37811
+ if (manifestMode(manifest) === "hosted") {
37812
+ const filenames = Object.keys(zip.files).filter((n) => !zip.files[n].dir);
37813
+ const extras = filenames.filter((n) => n !== "manifest.json");
37814
+ if (extras.length > 0) {
37815
+ throw new ImportError(
37816
+ "HOSTED_ZIP_EXTRA_FILES",
37817
+ `hosted extension may only contain manifest.json (extra: ${extras.join(", ")})`
37818
+ );
37819
+ }
37820
+ }
37783
37821
  const destDir = import_node_path19.default.join(root, manifest.id);
37784
37822
  let destExists = false;
37785
37823
  try {
@@ -40240,7 +40278,6 @@ function buildReadyFrame(deps, client) {
40240
40278
  fileSharing.httpBaseUrl = httpBaseUrl;
40241
40279
  if (deps.httpToken) fileSharing.httpToken = deps.httpToken;
40242
40280
  }
40243
- const daemonSource = process.env.CLAWD_DAEMON_SOURCE === "ota" ? "ota" : "packaged";
40244
40281
  return {
40245
40282
  version,
40246
40283
  protocolVersion: PROTOCOL_VERSION,
@@ -40250,7 +40287,6 @@ function buildReadyFrame(deps, client) {
40250
40287
  runningSessions: info.runningSessions,
40251
40288
  tunnelUrl,
40252
40289
  mode: deps.mode,
40253
- daemonSource,
40254
40290
  ...fileSharing
40255
40291
  };
40256
40292
  }
@@ -40940,10 +40976,17 @@ function pickExtId(frame) {
40940
40976
  }
40941
40977
  function composeState(rec, running, crashed, getPort) {
40942
40978
  if (rec.state === "invalid") return rec;
40979
+ if (manifestMode(rec.manifest) === "hosted") {
40980
+ return {
40981
+ ...rec,
40982
+ state: "running",
40983
+ target: { kind: "hosted", url: rec.manifest.entry.url }
40984
+ };
40985
+ }
40943
40986
  if (running.has(rec.extId)) {
40944
40987
  const port = getPort(rec.extId);
40945
40988
  if (port == null) return rec;
40946
- return { ...rec, state: "running", port };
40989
+ return { ...rec, state: "running", target: { kind: "local", port } };
40947
40990
  }
40948
40991
  if (crashed.has(rec.extId)) return { ...rec, state: "crashed" };
40949
40992
  return rec;
@@ -40965,8 +41008,8 @@ function buildExtensionHandlers(deps) {
40965
41008
  const open = async (frame, _client, ctx) => {
40966
41009
  assertOwner(ctx);
40967
41010
  const extId = pickExtId(frame);
40968
- const { port } = await deps.runtime.open(extId);
40969
- return { response: { port } };
41011
+ const target = await deps.runtime.open(extId);
41012
+ return { response: target };
40970
41013
  };
40971
41014
  const close = async (frame, _client, ctx) => {
40972
41015
  assertOwner(ctx);
@@ -41516,16 +41559,20 @@ var Runtime = class {
41516
41559
  }
41517
41560
  async open(extId) {
41518
41561
  const existing = this.handles.get(extId);
41519
- if (existing) return { port: existing.port };
41562
+ if (existing) return { kind: "local", port: existing.port };
41520
41563
  const records = await loadAll(this.root);
41521
41564
  const rec = records.find((r) => r.extId === extId);
41522
41565
  if (!rec) throw new RuntimeError("NOT_FOUND", `extension ${extId} not installed`);
41523
41566
  if (rec.state === "invalid")
41524
41567
  throw new RuntimeError("INVALID_MANIFEST", rec.invalidReason);
41568
+ if (manifestMode(rec.manifest) === "hosted") {
41569
+ return { kind: "hosted", url: rec.manifest.entry.url };
41570
+ }
41525
41571
  const port = await this.allocator.allocate().catch(() => {
41526
41572
  throw new RuntimeError("PORT_EXHAUSTED", "no free port in configured range");
41527
41573
  });
41528
- const cmd = rec.manifest.runtime.startCommand.replace(
41574
+ const startCommand = rec.manifest.runtime.startCommand;
41575
+ const cmd = startCommand.replace(
41529
41576
  /\$CLAWOS_EXT_PORT/g,
41530
41577
  String(port)
41531
41578
  );
@@ -41563,7 +41610,7 @@ var Runtime = class {
41563
41610
  try {
41564
41611
  await this.waitForHealthz(port, () => earlyExit, handle);
41565
41612
  this.crashed.delete(extId);
41566
- return { port };
41613
+ return { kind: "local", port };
41567
41614
  } catch (e) {
41568
41615
  if (this.handles.get(extId) === handle) {
41569
41616
  this.handles.delete(extId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.102-beta.197.08025e2",
3
+ "version": "0.2.103-beta.198.c756b33",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",