@clawos-dev/clawd 0.2.102 → 0.2.103
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/cli.cjs +69 -20
- 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
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
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
|
-
|
|
5485
|
+
target: ExtensionTargetSchema
|
|
5452
5486
|
}),
|
|
5453
5487
|
external_exports.object({
|
|
5454
5488
|
extId: external_exports.string(),
|
|
@@ -37791,12 +37825,6 @@ async function importZip(buf, root) {
|
|
|
37791
37825
|
} catch (e) {
|
|
37792
37826
|
throw new ImportError("INVALID_MANIFEST", `manifest.json: ${e.message}`);
|
|
37793
37827
|
}
|
|
37794
|
-
if (manifestJson && typeof manifestJson === "object" && "entry" in manifestJson && manifestJson.entry?.url !== void 0) {
|
|
37795
|
-
throw new ImportError(
|
|
37796
|
-
"REMOTE_NOT_SUPPORTED",
|
|
37797
|
-
"entry.url (remote mode) is not supported in v1"
|
|
37798
|
-
);
|
|
37799
|
-
}
|
|
37800
37828
|
const result = ExtensionManifestSchema.safeParse(manifestJson);
|
|
37801
37829
|
if (!result.success) {
|
|
37802
37830
|
throw new ImportError(
|
|
@@ -37805,6 +37833,16 @@ async function importZip(buf, root) {
|
|
|
37805
37833
|
);
|
|
37806
37834
|
}
|
|
37807
37835
|
const manifest = result.data;
|
|
37836
|
+
if (manifestMode(manifest) === "hosted") {
|
|
37837
|
+
const filenames = Object.keys(zip.files).filter((n) => !zip.files[n].dir);
|
|
37838
|
+
const extras = filenames.filter((n) => n !== "manifest.json");
|
|
37839
|
+
if (extras.length > 0) {
|
|
37840
|
+
throw new ImportError(
|
|
37841
|
+
"HOSTED_ZIP_EXTRA_FILES",
|
|
37842
|
+
`hosted extension may only contain manifest.json (extra: ${extras.join(", ")})`
|
|
37843
|
+
);
|
|
37844
|
+
}
|
|
37845
|
+
}
|
|
37808
37846
|
const destDir = import_node_path19.default.join(root, manifest.id);
|
|
37809
37847
|
let destExists = false;
|
|
37810
37848
|
try {
|
|
@@ -40963,10 +41001,17 @@ function pickExtId(frame) {
|
|
|
40963
41001
|
}
|
|
40964
41002
|
function composeState(rec, running, crashed, getPort) {
|
|
40965
41003
|
if (rec.state === "invalid") return rec;
|
|
41004
|
+
if (manifestMode(rec.manifest) === "hosted") {
|
|
41005
|
+
return {
|
|
41006
|
+
...rec,
|
|
41007
|
+
state: "running",
|
|
41008
|
+
target: { kind: "hosted", url: rec.manifest.entry.url }
|
|
41009
|
+
};
|
|
41010
|
+
}
|
|
40966
41011
|
if (running.has(rec.extId)) {
|
|
40967
41012
|
const port = getPort(rec.extId);
|
|
40968
41013
|
if (port == null) return rec;
|
|
40969
|
-
return { ...rec, state: "running", port };
|
|
41014
|
+
return { ...rec, state: "running", target: { kind: "local", port } };
|
|
40970
41015
|
}
|
|
40971
41016
|
if (crashed.has(rec.extId)) return { ...rec, state: "crashed" };
|
|
40972
41017
|
return rec;
|
|
@@ -40988,8 +41033,8 @@ function buildExtensionHandlers(deps) {
|
|
|
40988
41033
|
const open = async (frame, _client, ctx) => {
|
|
40989
41034
|
assertOwner(ctx);
|
|
40990
41035
|
const extId = pickExtId(frame);
|
|
40991
|
-
const
|
|
40992
|
-
return { response:
|
|
41036
|
+
const target = await deps.runtime.open(extId);
|
|
41037
|
+
return { response: target };
|
|
40993
41038
|
};
|
|
40994
41039
|
const close = async (frame, _client, ctx) => {
|
|
40995
41040
|
assertOwner(ctx);
|
|
@@ -41539,16 +41584,20 @@ var Runtime = class {
|
|
|
41539
41584
|
}
|
|
41540
41585
|
async open(extId) {
|
|
41541
41586
|
const existing = this.handles.get(extId);
|
|
41542
|
-
if (existing) return { port: existing.port };
|
|
41587
|
+
if (existing) return { kind: "local", port: existing.port };
|
|
41543
41588
|
const records = await loadAll(this.root);
|
|
41544
41589
|
const rec = records.find((r) => r.extId === extId);
|
|
41545
41590
|
if (!rec) throw new RuntimeError("NOT_FOUND", `extension ${extId} not installed`);
|
|
41546
41591
|
if (rec.state === "invalid")
|
|
41547
41592
|
throw new RuntimeError("INVALID_MANIFEST", rec.invalidReason);
|
|
41593
|
+
if (manifestMode(rec.manifest) === "hosted") {
|
|
41594
|
+
return { kind: "hosted", url: rec.manifest.entry.url };
|
|
41595
|
+
}
|
|
41548
41596
|
const port = await this.allocator.allocate().catch(() => {
|
|
41549
41597
|
throw new RuntimeError("PORT_EXHAUSTED", "no free port in configured range");
|
|
41550
41598
|
});
|
|
41551
|
-
const
|
|
41599
|
+
const startCommand = rec.manifest.runtime.startCommand;
|
|
41600
|
+
const cmd = startCommand.replace(
|
|
41552
41601
|
/\$CLAWOS_EXT_PORT/g,
|
|
41553
41602
|
String(port)
|
|
41554
41603
|
);
|
|
@@ -41586,7 +41635,7 @@ var Runtime = class {
|
|
|
41586
41635
|
try {
|
|
41587
41636
|
await this.waitForHealthz(port, () => earlyExit, handle);
|
|
41588
41637
|
this.crashed.delete(extId);
|
|
41589
|
-
return { port };
|
|
41638
|
+
return { kind: "local", port };
|
|
41590
41639
|
} catch (e) {
|
|
41591
41640
|
if (this.handles.get(extId) === handle) {
|
|
41592
41641
|
this.handles.delete(extId);
|