omp-fabric 1.25.34 → 1.26.0
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/CHANGELOG.md +22 -0
- package/README.md +1 -0
- package/dist/chunks/{chunk-HOKJTRI4.js → chunk-3OQKG7H6.js} +3 -3
- package/dist/chunks/{chunk-JWC7B67Z.js → chunk-66H3QSMR.js} +62 -1
- package/dist/chunks/chunk-66H3QSMR.js.map +7 -0
- package/dist/chunks/{chunk-UKB5RJDP.js → chunk-BEFZRH76.js} +61 -1
- package/dist/chunks/{chunk-UKB5RJDP.js.map → chunk-BEFZRH76.js.map} +2 -2
- package/dist/chunks/{chunk-TRM76YFF.js → chunk-CEDP5WMR.js} +11 -3
- package/dist/chunks/chunk-CEDP5WMR.js.map +7 -0
- package/dist/chunks/{chunk-2C5YN36Y.js → chunk-GFUWAUL2.js} +15 -1
- package/dist/chunks/chunk-GFUWAUL2.js.map +7 -0
- package/dist/chunks/{chunk-5CW2S6EB.js → chunk-Q2LRXHPR.js} +2 -2
- package/dist/chunks/{chunk-3FCNSDDD.js → chunk-TGIT2F2G.js} +3 -3
- package/dist/chunks/{chunk-OLFP7R5J.js → chunk-Z3KAY6S7.js} +2 -2
- package/dist/compaction/hook.js +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/core/session-context.d.ts.map +1 -1
- package/dist/core/system-guidance.d.ts.map +1 -1
- package/dist/fabric-runtime-state.d.ts.map +1 -1
- package/dist/fabric-runtime-state.js +797 -139
- package/dist/fabric-runtime-state.js.map +4 -4
- package/dist/index.js +6 -6
- package/dist/index.js.map +2 -2
- package/dist/providers/image-provider.d.ts +37 -0
- package/dist/providers/image-provider.d.ts.map +1 -0
- package/dist/residency/host.js +5 -5
- package/dist/residency/omp-entry.js +5 -5
- package/dist/runtime/core-override-guest-types.js +1 -1
- package/dist/runtime/guest-types.d.ts +1 -1
- package/dist/runtime/guest-types.d.ts.map +1 -1
- package/dist/runtime/guest-types.js +1 -1
- package/dist/runtime/node-process-runtime.js +1 -1
- package/dist/runtime/quickjs-runtime.d.ts +1 -1
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
- package/dist/runtime/quickjs-runtime.js +1 -1
- package/dist/ui/settings.d.ts +1 -1
- package/dist/ui/settings.d.ts.map +1 -1
- package/dist/ui/settings.js +126 -11
- package/dist/ui/settings.js.map +3 -3
- package/docs/architecture.md +1 -1
- package/docs/certification.md +1 -1
- package/docs/configuration.md +13 -1
- package/docs/image.md +79 -0
- package/package.json +8 -8
- package/dist/chunks/chunk-2C5YN36Y.js.map +0 -7
- package/dist/chunks/chunk-JWC7B67Z.js.map +0 -7
- package/dist/chunks/chunk-TRM76YFF.js.map +0 -7
- /package/dist/chunks/{chunk-HOKJTRI4.js.map → chunk-3OQKG7H6.js.map} +0 -0
- /package/dist/chunks/{chunk-5CW2S6EB.js.map → chunk-Q2LRXHPR.js.map} +0 -0
- /package/dist/chunks/{chunk-3FCNSDDD.js.map → chunk-TGIT2F2G.js.map} +0 -0
- /package/dist/chunks/{chunk-OLFP7R5J.js.map → chunk-Z3KAY6S7.js.map} +0 -0
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
repairFabricGuestCode,
|
|
34
34
|
resolveFabricIdentity,
|
|
35
35
|
runFabricHandoffAtBoundary
|
|
36
|
-
} from "./chunks/chunk-
|
|
36
|
+
} from "./chunks/chunk-Z3KAY6S7.js";
|
|
37
37
|
import "./chunks/chunk-7VIQNUPS.js";
|
|
38
38
|
import {
|
|
39
39
|
AgentTranscriptReader,
|
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
resolveAgentCwd,
|
|
98
98
|
resolveOmpBinary,
|
|
99
99
|
validateAgentCwdRequest
|
|
100
|
-
} from "./chunks/chunk-
|
|
100
|
+
} from "./chunks/chunk-3OQKG7H6.js";
|
|
101
101
|
import "./chunks/chunk-VPPIJRNZ.js";
|
|
102
102
|
import {
|
|
103
103
|
executeFile,
|
|
@@ -107,7 +107,7 @@ import {
|
|
|
107
107
|
import "./chunks/chunk-CT2AJ2UI.js";
|
|
108
108
|
import {
|
|
109
109
|
checkedHandoffCompaction
|
|
110
|
-
} from "./chunks/chunk-
|
|
110
|
+
} from "./chunks/chunk-Q2LRXHPR.js";
|
|
111
111
|
import {
|
|
112
112
|
DEFAULT_FABRIC_CONFIG,
|
|
113
113
|
FUZZY_RESOLUTION_MARKERS,
|
|
@@ -117,7 +117,7 @@ import {
|
|
|
117
117
|
resolveAgentDir,
|
|
118
118
|
resolveAvailableOmpModel,
|
|
119
119
|
resolveFabricModel
|
|
120
|
-
} from "./chunks/chunk-
|
|
120
|
+
} from "./chunks/chunk-66H3QSMR.js";
|
|
121
121
|
import {
|
|
122
122
|
FABRIC_ACTOR_HOST_EVENTS,
|
|
123
123
|
isFabricActorHostEvent,
|
|
@@ -157,7 +157,7 @@ import {
|
|
|
157
157
|
import {
|
|
158
158
|
estimateTokens,
|
|
159
159
|
fabricExecTitleHintCached
|
|
160
|
-
} from "./chunks/chunk-
|
|
160
|
+
} from "./chunks/chunk-CEDP5WMR.js";
|
|
161
161
|
import "./chunks/chunk-3J7BKUNG.js";
|
|
162
162
|
import {
|
|
163
163
|
MAX_COMPACTION_INSTRUCTIONS_CHARS,
|
|
@@ -182,7 +182,7 @@ import {
|
|
|
182
182
|
} from "./chunks/chunk-ATTYOQSI.js";
|
|
183
183
|
|
|
184
184
|
// src/fabric-runtime-state.ts
|
|
185
|
-
import
|
|
185
|
+
import path20 from "node:path";
|
|
186
186
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
187
187
|
|
|
188
188
|
// src/actors/global-registry.ts
|
|
@@ -2235,10 +2235,10 @@ var FabricComponentSupervisor = class {
|
|
|
2235
2235
|
adjacent.set(edge.from, targets);
|
|
2236
2236
|
}
|
|
2237
2237
|
const cycles = /* @__PURE__ */ new Map();
|
|
2238
|
-
const visit = (node,
|
|
2238
|
+
const visit = (node, path21, positions) => {
|
|
2239
2239
|
const position = positions.get(node);
|
|
2240
2240
|
if (position !== void 0) {
|
|
2241
|
-
const cycle =
|
|
2241
|
+
const cycle = path21.slice(position);
|
|
2242
2242
|
const rotations = cycle.map((_, index) => [
|
|
2243
2243
|
...cycle.slice(index),
|
|
2244
2244
|
...cycle.slice(0, index)
|
|
@@ -2248,10 +2248,10 @@ var FabricComponentSupervisor = class {
|
|
|
2248
2248
|
cycles.set(canonical.join("\0"), canonical);
|
|
2249
2249
|
return;
|
|
2250
2250
|
}
|
|
2251
|
-
if (
|
|
2252
|
-
const nextPositions = new Map(positions).set(node,
|
|
2251
|
+
if (path21.length > this.#components.size) return;
|
|
2252
|
+
const nextPositions = new Map(positions).set(node, path21.length);
|
|
2253
2253
|
for (const target of adjacent.get(node) ?? []) {
|
|
2254
|
-
visit(target, [...
|
|
2254
|
+
visit(target, [...path21, node], nextPositions);
|
|
2255
2255
|
}
|
|
2256
2256
|
};
|
|
2257
2257
|
for (const id of this.#components.keys()) visit(id, [], /* @__PURE__ */ new Map());
|
|
@@ -7060,9 +7060,9 @@ var CapturedToolsProvider = class {
|
|
|
7060
7060
|
#allowedTools = readChildToolAllowlist();
|
|
7061
7061
|
async list(request, _context) {
|
|
7062
7062
|
const query = request.query?.trim().toLowerCase();
|
|
7063
|
-
const
|
|
7064
|
-
if (!query) return
|
|
7065
|
-
return
|
|
7063
|
+
const descriptors9 = this.catalog.list().filter((entry) => !this.#allowedTools || this.#allowedTools.has(entry.name)).map(descriptorFrom);
|
|
7064
|
+
if (!query) return descriptors9;
|
|
7065
|
+
return descriptors9.filter(
|
|
7066
7066
|
(descriptor) => `${descriptor.name} ${descriptor.description} ${descriptor.namespace ?? ""}`.toLowerCase().includes(query)
|
|
7067
7067
|
);
|
|
7068
7068
|
}
|
|
@@ -8498,6 +8498,650 @@ var CodemapProvider = class {
|
|
|
8498
8498
|
}
|
|
8499
8499
|
};
|
|
8500
8500
|
|
|
8501
|
+
// src/providers/image-provider.ts
|
|
8502
|
+
import { mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
|
|
8503
|
+
import os from "node:os";
|
|
8504
|
+
import path10 from "node:path";
|
|
8505
|
+
var IMAGE_MODEL_API = /image|imagen|dall-e|flux|stable-diffusion|sdxl|seedream|kolors|wanx|cogview|recraft|ideogram|midjourney|horde|banana/i;
|
|
8506
|
+
var generateSchema = {
|
|
8507
|
+
type: "object",
|
|
8508
|
+
additionalProperties: false,
|
|
8509
|
+
required: ["prompt"],
|
|
8510
|
+
properties: {
|
|
8511
|
+
prompt: { type: "string", description: "Full image description; the only required argument." },
|
|
8512
|
+
model: {
|
|
8513
|
+
type: "string",
|
|
8514
|
+
description: 'Optional provider/id to try first, e.g. "sub2api-agy/gemini-3.1-flash-image". Falls back to the configured chain.'
|
|
8515
|
+
},
|
|
8516
|
+
aspectRatio: {
|
|
8517
|
+
type: "string",
|
|
8518
|
+
description: "Aspect ratio forwarded as aspect_ratio or imageConfig.aspectRatio, e.g. 1:1, 16:9, 9:16."
|
|
8519
|
+
},
|
|
8520
|
+
size: {
|
|
8521
|
+
type: "string",
|
|
8522
|
+
enum: ["1024x1024", "1536x1024", "1024x1536"],
|
|
8523
|
+
description: "Pixel size for gateways that accept an images-API size field."
|
|
8524
|
+
},
|
|
8525
|
+
count: { type: "number", description: "Images to request from one model; only the images API honours more than one." },
|
|
8526
|
+
saveTo: { type: "string", description: "Absolute or cwd-relative file path for a single image." }
|
|
8527
|
+
}
|
|
8528
|
+
};
|
|
8529
|
+
var editSchema = {
|
|
8530
|
+
type: "object",
|
|
8531
|
+
additionalProperties: false,
|
|
8532
|
+
required: ["prompt", "images"],
|
|
8533
|
+
properties: {
|
|
8534
|
+
prompt: { type: "string", description: "What to change in the source images." },
|
|
8535
|
+
images: {
|
|
8536
|
+
type: "array",
|
|
8537
|
+
minItems: 1,
|
|
8538
|
+
description: "Source images as file paths or data URLs.",
|
|
8539
|
+
items: { type: "string" }
|
|
8540
|
+
},
|
|
8541
|
+
model: { type: "string", description: "Optional provider/id to try first." },
|
|
8542
|
+
aspectRatio: { type: "string", description: "Aspect ratio forwarded to the backend." },
|
|
8543
|
+
size: {
|
|
8544
|
+
type: "string",
|
|
8545
|
+
enum: ["1024x1024", "1536x1024", "1024x1536"],
|
|
8546
|
+
description: "Pixel size for gateways that accept an images-API size field."
|
|
8547
|
+
},
|
|
8548
|
+
saveTo: { type: "string", description: "Absolute or cwd-relative file path for a single image." }
|
|
8549
|
+
}
|
|
8550
|
+
};
|
|
8551
|
+
var modelsSchema = { type: "object", additionalProperties: false, properties: {} };
|
|
8552
|
+
var descriptors2 = [
|
|
8553
|
+
{
|
|
8554
|
+
name: "generate",
|
|
8555
|
+
description: "Generate an image from a prompt. Tries each configured model in priority order and returns the first success with its path, bytes, model, and dialect. Returns { ok: false, reason, failures } instead of throwing when every model fails.",
|
|
8556
|
+
inputSchema: generateSchema,
|
|
8557
|
+
risk: "network"
|
|
8558
|
+
},
|
|
8559
|
+
{
|
|
8560
|
+
name: "edit",
|
|
8561
|
+
description: "Edit existing images with a prompt. Tries each configured model in priority order and returns the first success or { ok: false, reason, failures }. Source images travel in the shape each dialect expects: input_references or image/images for the images API, image_url parts for chat, input_image for responses, inlineData for gemini.",
|
|
8562
|
+
inputSchema: editSchema,
|
|
8563
|
+
risk: "network"
|
|
8564
|
+
},
|
|
8565
|
+
{
|
|
8566
|
+
name: "models",
|
|
8567
|
+
description: "Show the resolved priority chain: each entry's provider, model id, api, inferred or overridden dialect, and whether credentials resolve. No network call.",
|
|
8568
|
+
inputSchema: modelsSchema,
|
|
8569
|
+
risk: "read"
|
|
8570
|
+
}
|
|
8571
|
+
];
|
|
8572
|
+
var splitModelSelector = (selector) => {
|
|
8573
|
+
const trimmed = selector.trim();
|
|
8574
|
+
const separator = trimmed.indexOf("/");
|
|
8575
|
+
if (separator <= 0 || separator === trimmed.length - 1) return void 0;
|
|
8576
|
+
return { provider: trimmed.slice(0, separator), id: trimmed.slice(separator + 1) };
|
|
8577
|
+
};
|
|
8578
|
+
var inferImageDialect = (api, modelId) => {
|
|
8579
|
+
if (api === "openai-images" || api === "openrouter-images") return "images";
|
|
8580
|
+
if (api === "google-generative-ai") return "gemini";
|
|
8581
|
+
if (api === "openai-responses" || api === "openai-codex-responses") {
|
|
8582
|
+
return IMAGE_MODEL_API.test(modelId) ? "images" : "responses";
|
|
8583
|
+
}
|
|
8584
|
+
return "chat";
|
|
8585
|
+
};
|
|
8586
|
+
var GPT_IMAGE_FAMILY = /gpt-image|chatgpt-image/i;
|
|
8587
|
+
var mimeFromMagic = (bytes) => {
|
|
8588
|
+
if (bytes.length > 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
8589
|
+
if (bytes.length > 8 && bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71) return "image/png";
|
|
8590
|
+
if (bytes.length > 6 && bytes.subarray(0, 3).toString("latin1") === "GIF") return "image/gif";
|
|
8591
|
+
if (bytes.length > 12 && bytes.subarray(0, 4).toString("latin1") === "RIFF" && bytes.subarray(8, 12).toString("latin1") === "WEBP") {
|
|
8592
|
+
return "image/webp";
|
|
8593
|
+
}
|
|
8594
|
+
return void 0;
|
|
8595
|
+
};
|
|
8596
|
+
var extensionForMime = (mimeType) => {
|
|
8597
|
+
if (mimeType === "image/jpeg") return "jpg";
|
|
8598
|
+
if (mimeType === "image/webp") return "webp";
|
|
8599
|
+
if (mimeType === "image/gif") return "gif";
|
|
8600
|
+
return "png";
|
|
8601
|
+
};
|
|
8602
|
+
var MAGIC_SNIFF_BASE64_CHARS = 64;
|
|
8603
|
+
var decodeImage = (value) => {
|
|
8604
|
+
if (typeof value !== "string" || value.length === 0) return void 0;
|
|
8605
|
+
let base64 = value;
|
|
8606
|
+
if (value.startsWith("data:")) {
|
|
8607
|
+
const comma = value.indexOf(",");
|
|
8608
|
+
if (comma < 0) return void 0;
|
|
8609
|
+
base64 = value.slice(comma + 1);
|
|
8610
|
+
}
|
|
8611
|
+
const head = Buffer.from(base64.slice(0, MAGIC_SNIFF_BASE64_CHARS), "base64");
|
|
8612
|
+
if (head.length < 16) return void 0;
|
|
8613
|
+
const mimeType = mimeFromMagic(head);
|
|
8614
|
+
if (mimeType === void 0) return void 0;
|
|
8615
|
+
return { data: base64, mimeType };
|
|
8616
|
+
};
|
|
8617
|
+
var collectFromUrlList = (value) => {
|
|
8618
|
+
if (!Array.isArray(value)) return [];
|
|
8619
|
+
const images = [];
|
|
8620
|
+
for (const entry of value) {
|
|
8621
|
+
if (typeof entry === "string") {
|
|
8622
|
+
const decoded2 = decodeImage(entry);
|
|
8623
|
+
if (decoded2) images.push(decoded2);
|
|
8624
|
+
continue;
|
|
8625
|
+
}
|
|
8626
|
+
if (typeof entry !== "object" || entry === null) continue;
|
|
8627
|
+
const record2 = entry;
|
|
8628
|
+
const nested = record2.image_url;
|
|
8629
|
+
const url = typeof nested === "string" ? nested : typeof nested === "object" && nested !== null ? nested.url : record2.url;
|
|
8630
|
+
const decoded = decodeImage(url);
|
|
8631
|
+
if (decoded) images.push(decoded);
|
|
8632
|
+
}
|
|
8633
|
+
return images;
|
|
8634
|
+
};
|
|
8635
|
+
var DATA_URL_PATTERN = /data:(image\/[a-z+]+);base64,([A-Za-z0-9+/=]+)/gi;
|
|
8636
|
+
var parseImagesApiPayload = (payload) => {
|
|
8637
|
+
const data = payload?.data;
|
|
8638
|
+
if (!Array.isArray(data)) return [];
|
|
8639
|
+
const images = [];
|
|
8640
|
+
for (const entry of data) {
|
|
8641
|
+
if (typeof entry !== "object" || entry === null) continue;
|
|
8642
|
+
const record2 = entry;
|
|
8643
|
+
const decoded = decodeImage(record2.b64_json) ?? decodeImage(record2.url);
|
|
8644
|
+
if (decoded) images.push(decoded);
|
|
8645
|
+
}
|
|
8646
|
+
return images;
|
|
8647
|
+
};
|
|
8648
|
+
var parseResponsesPayload = (payload) => {
|
|
8649
|
+
const output = payload?.output;
|
|
8650
|
+
if (!Array.isArray(output)) return [];
|
|
8651
|
+
const images = [];
|
|
8652
|
+
for (const entry of output) {
|
|
8653
|
+
if (typeof entry !== "object" || entry === null) continue;
|
|
8654
|
+
const record2 = entry;
|
|
8655
|
+
if (record2.type !== "image_generation_call") continue;
|
|
8656
|
+
const decoded = decodeImage(record2.result);
|
|
8657
|
+
if (decoded) images.push(decoded);
|
|
8658
|
+
}
|
|
8659
|
+
return images;
|
|
8660
|
+
};
|
|
8661
|
+
var parseChatPayload = (payload) => {
|
|
8662
|
+
const choices = payload?.choices;
|
|
8663
|
+
if (!Array.isArray(choices) || choices.length === 0) return [];
|
|
8664
|
+
const message2 = choices[0]?.message;
|
|
8665
|
+
if (!message2) return [];
|
|
8666
|
+
const direct = collectFromUrlList(message2.images);
|
|
8667
|
+
if (direct.length > 0) return direct;
|
|
8668
|
+
const content = message2.content;
|
|
8669
|
+
const text = typeof content === "string" ? content : Array.isArray(content) ? content.map(
|
|
8670
|
+
(part) => typeof part === "object" && part !== null && typeof part.text === "string" ? String(part.text) : ""
|
|
8671
|
+
).join("\n") : "";
|
|
8672
|
+
const images = [];
|
|
8673
|
+
for (const match of text.matchAll(DATA_URL_PATTERN)) {
|
|
8674
|
+
const decoded = decodeImage(match[0]);
|
|
8675
|
+
if (decoded) images.push(decoded);
|
|
8676
|
+
}
|
|
8677
|
+
if (images.length > 0) return images;
|
|
8678
|
+
return collectFromUrlList(
|
|
8679
|
+
Array.isArray(content) ? content.filter(
|
|
8680
|
+
(part) => typeof part === "object" && part !== null && part.type === "image_url"
|
|
8681
|
+
) : []
|
|
8682
|
+
);
|
|
8683
|
+
};
|
|
8684
|
+
var parseGeminiPayload = (payload) => {
|
|
8685
|
+
const candidates = payload?.candidates;
|
|
8686
|
+
if (!Array.isArray(candidates)) return [];
|
|
8687
|
+
const images = [];
|
|
8688
|
+
for (const candidate of candidates) {
|
|
8689
|
+
const parts = candidate?.content?.parts;
|
|
8690
|
+
if (!Array.isArray(parts)) continue;
|
|
8691
|
+
for (const part of parts) {
|
|
8692
|
+
if (typeof part !== "object" || part === null) continue;
|
|
8693
|
+
const inline = part.inlineData ?? part.inline_data;
|
|
8694
|
+
if (typeof inline !== "object" || inline === null) continue;
|
|
8695
|
+
const record2 = inline;
|
|
8696
|
+
const decoded = decodeImage(record2.data);
|
|
8697
|
+
if (decoded) images.push(decoded);
|
|
8698
|
+
}
|
|
8699
|
+
}
|
|
8700
|
+
return images;
|
|
8701
|
+
};
|
|
8702
|
+
var joinUrl = (baseUrl, suffix) => `${baseUrl.replace(/\/+$/, "")}${suffix.startsWith("/") ? suffix : "/" + suffix}`;
|
|
8703
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8704
|
+
var MAX_RESPONSE_BYTES = 96 * 1024 * 1024;
|
|
8705
|
+
var postJson = async (env, url, body, extraHeaders = {}) => {
|
|
8706
|
+
const response = await env.fetchImpl(url, {
|
|
8707
|
+
method: "POST",
|
|
8708
|
+
headers: { ...env.headers, "Content-Type": "application/json", ...extraHeaders },
|
|
8709
|
+
body: JSON.stringify(body),
|
|
8710
|
+
...env.signal ? { signal: env.signal } : {}
|
|
8711
|
+
});
|
|
8712
|
+
const declared = Number(response.headers.get("content-length") ?? "");
|
|
8713
|
+
if (Number.isFinite(declared) && declared > MAX_RESPONSE_BYTES) {
|
|
8714
|
+
throw Object.assign(new Error(`${url} declared ${declared} bytes, over the ${MAX_RESPONSE_BYTES} ceiling`), {
|
|
8715
|
+
status: 413
|
|
8716
|
+
});
|
|
8717
|
+
}
|
|
8718
|
+
const text = await response.text();
|
|
8719
|
+
if (!response.ok) {
|
|
8720
|
+
throw Object.assign(new Error(`${url} returned ${response.status}: ${text.slice(0, 400)}`), {
|
|
8721
|
+
status: response.status
|
|
8722
|
+
});
|
|
8723
|
+
}
|
|
8724
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
8725
|
+
if (contentType.includes("text/event-stream")) {
|
|
8726
|
+
return { payload: parseSsePayload(text), status: response.status, contentType };
|
|
8727
|
+
}
|
|
8728
|
+
try {
|
|
8729
|
+
return { payload: JSON.parse(text), status: response.status, contentType };
|
|
8730
|
+
} catch {
|
|
8731
|
+
throw new Error(`${url} returned non-JSON: ${text.slice(0, 200)}`);
|
|
8732
|
+
}
|
|
8733
|
+
};
|
|
8734
|
+
var parseSsePayload = (text) => {
|
|
8735
|
+
let last;
|
|
8736
|
+
for (const line of text.split("\n")) {
|
|
8737
|
+
if (!line.startsWith("data:")) continue;
|
|
8738
|
+
const data = line.slice(5).trim();
|
|
8739
|
+
if (data.length === 0 || data === "[DONE]") continue;
|
|
8740
|
+
let event;
|
|
8741
|
+
try {
|
|
8742
|
+
event = JSON.parse(data);
|
|
8743
|
+
} catch {
|
|
8744
|
+
continue;
|
|
8745
|
+
}
|
|
8746
|
+
if (!isRecord3(event)) continue;
|
|
8747
|
+
const nested = event.response;
|
|
8748
|
+
if (isRecord3(nested) && Array.isArray(nested.output)) {
|
|
8749
|
+
last = nested;
|
|
8750
|
+
continue;
|
|
8751
|
+
}
|
|
8752
|
+
if (Array.isArray(event.output)) last = event;
|
|
8753
|
+
}
|
|
8754
|
+
if (last === void 0) throw new Error("event stream carried no response payload");
|
|
8755
|
+
return last;
|
|
8756
|
+
};
|
|
8757
|
+
var dataUrl = (image) => `data:${image.mimeType};base64,${image.data}`;
|
|
8758
|
+
var requestImages = async (env, model, options) => {
|
|
8759
|
+
const openrouter = model.api === "openrouter-images";
|
|
8760
|
+
const body = { model: model.id, prompt: options.prompt, n: options.count };
|
|
8761
|
+
if (!model.gptImage) body.response_format = "b64_json";
|
|
8762
|
+
if (options.size !== void 0) {
|
|
8763
|
+
if (openrouter) body.image_size = options.size;
|
|
8764
|
+
else body.size = options.size;
|
|
8765
|
+
}
|
|
8766
|
+
if (options.aspectRatio !== void 0) body.aspect_ratio = options.aspectRatio;
|
|
8767
|
+
const references = options.inputImages.map((image) => ({ type: "image_url", url: dataUrl(image) }));
|
|
8768
|
+
if (options.inputImages.length === 0) {
|
|
8769
|
+
const url2 = joinUrl(env.baseUrl, openrouter ? "/images" : "/images/generations");
|
|
8770
|
+
const { payload } = await postJson(env, url2, body);
|
|
8771
|
+
return parseImagesApiPayload(payload);
|
|
8772
|
+
}
|
|
8773
|
+
if (model.provider === "openai") {
|
|
8774
|
+
const form = new FormData();
|
|
8775
|
+
form.set("model", model.id);
|
|
8776
|
+
form.set("prompt", options.prompt);
|
|
8777
|
+
form.set("n", String(options.count));
|
|
8778
|
+
if (!model.gptImage) form.set("response_format", "b64_json");
|
|
8779
|
+
if (options.size !== void 0) form.set("size", options.size);
|
|
8780
|
+
for (const image of options.inputImages) {
|
|
8781
|
+
form.append("image", new File([Buffer.from(image.data, "base64")], "image", { type: image.mimeType }));
|
|
8782
|
+
}
|
|
8783
|
+
const response = await env.fetchImpl(joinUrl(env.baseUrl, "/images/edits"), {
|
|
8784
|
+
method: "POST",
|
|
8785
|
+
headers: env.headers,
|
|
8786
|
+
body: form,
|
|
8787
|
+
...env.signal ? { signal: env.signal } : {}
|
|
8788
|
+
});
|
|
8789
|
+
const text = await response.text();
|
|
8790
|
+
if (!response.ok) {
|
|
8791
|
+
throw Object.assign(new Error(`images edit returned ${response.status}: ${text.slice(0, 400)}`), {
|
|
8792
|
+
status: response.status
|
|
8793
|
+
});
|
|
8794
|
+
}
|
|
8795
|
+
return parseImagesApiPayload(JSON.parse(text));
|
|
8796
|
+
}
|
|
8797
|
+
if (model.xai) {
|
|
8798
|
+
body.image = references[0];
|
|
8799
|
+
if (references.length > 1) body.images = references;
|
|
8800
|
+
} else {
|
|
8801
|
+
body.input_references = references;
|
|
8802
|
+
}
|
|
8803
|
+
const url = joinUrl(env.baseUrl, openrouter ? "/images" : "/images/edits");
|
|
8804
|
+
try {
|
|
8805
|
+
const { payload } = await postJson(env, url, body);
|
|
8806
|
+
return parseImagesApiPayload(payload);
|
|
8807
|
+
} catch (error) {
|
|
8808
|
+
if (error.status !== 404) throw error;
|
|
8809
|
+
const { payload } = await postJson(env, joinUrl(env.baseUrl, "/images/generations"), body);
|
|
8810
|
+
return parseImagesApiPayload(payload);
|
|
8811
|
+
}
|
|
8812
|
+
};
|
|
8813
|
+
var requestResponses = async (env, model, options) => {
|
|
8814
|
+
const content = [{ type: "input_text", text: options.prompt }];
|
|
8815
|
+
for (const image of options.inputImages) {
|
|
8816
|
+
content.push({ type: "input_image", image_url: dataUrl(image) });
|
|
8817
|
+
}
|
|
8818
|
+
const body = {
|
|
8819
|
+
model: model.id,
|
|
8820
|
+
input: [{ role: "user", content }],
|
|
8821
|
+
tools: [{ type: "image_generation" }],
|
|
8822
|
+
tool_choice: { type: "image_generation" },
|
|
8823
|
+
store: false
|
|
8824
|
+
};
|
|
8825
|
+
const url = model.codex ? joinUrl(env.baseUrl, "/codex/responses") : joinUrl(env.baseUrl, "/responses");
|
|
8826
|
+
if (model.codex) body.stream = true;
|
|
8827
|
+
const { payload } = await postJson(env, url, body, model.codex ? { Accept: "text/event-stream" } : {});
|
|
8828
|
+
const status = payload?.status;
|
|
8829
|
+
const images = parseResponsesPayload(payload);
|
|
8830
|
+
if (images.length === 0 && status === "failed") {
|
|
8831
|
+
const error = payload?.error;
|
|
8832
|
+
throw new Error(
|
|
8833
|
+
`responses backend reported status=failed${error ? `: ${JSON.stringify(error).slice(0, 200)}` : ""}`
|
|
8834
|
+
);
|
|
8835
|
+
}
|
|
8836
|
+
return images;
|
|
8837
|
+
};
|
|
8838
|
+
var requestChat = async (env, model, options) => {
|
|
8839
|
+
const content = [{ type: "text", text: options.prompt }];
|
|
8840
|
+
for (const image of options.inputImages) {
|
|
8841
|
+
content.push({ type: "image_url", image_url: { url: `data:${image.mimeType};base64,${image.data}` } });
|
|
8842
|
+
}
|
|
8843
|
+
const body = {
|
|
8844
|
+
model: model.id,
|
|
8845
|
+
messages: [{ role: "user", content }],
|
|
8846
|
+
modalities: ["image", "text"]
|
|
8847
|
+
};
|
|
8848
|
+
const { payload } = await postJson(env, joinUrl(env.baseUrl, "/chat/completions"), body);
|
|
8849
|
+
return parseChatPayload(payload);
|
|
8850
|
+
};
|
|
8851
|
+
var requestGemini = async (env, model, options) => {
|
|
8852
|
+
const parts = [{ text: options.prompt }];
|
|
8853
|
+
for (const image of options.inputImages) {
|
|
8854
|
+
parts.push({ inlineData: { mimeType: image.mimeType, data: image.data } });
|
|
8855
|
+
}
|
|
8856
|
+
const imageConfig = {};
|
|
8857
|
+
if (options.aspectRatio !== void 0) imageConfig.aspectRatio = options.aspectRatio;
|
|
8858
|
+
if (options.size !== void 0) imageConfig.imageSize = options.size;
|
|
8859
|
+
const body = {
|
|
8860
|
+
contents: [{ role: "user", parts }],
|
|
8861
|
+
generationConfig: {
|
|
8862
|
+
responseModalities: ["IMAGE"],
|
|
8863
|
+
candidateCount: 1,
|
|
8864
|
+
...Object.keys(imageConfig).length > 0 ? { imageConfig } : {}
|
|
8865
|
+
}
|
|
8866
|
+
};
|
|
8867
|
+
const base = env.baseUrl.replace(/\/+$/, "");
|
|
8868
|
+
const root = /\/v1beta\d*$/.test(base) ? base : `${base}/v1beta`;
|
|
8869
|
+
const { payload } = await postJson(env, `${root}/models/${model.id}:generateContent`, body);
|
|
8870
|
+
return parseGeminiPayload(payload);
|
|
8871
|
+
};
|
|
8872
|
+
var geminiHeaders = (apiKey) => ({ "x-goog-api-key": apiKey });
|
|
8873
|
+
var callDialect = (dialect, env, model, options) => {
|
|
8874
|
+
switch (dialect) {
|
|
8875
|
+
case "images":
|
|
8876
|
+
return requestImages(env, model, options);
|
|
8877
|
+
case "responses":
|
|
8878
|
+
return requestResponses(env, model, options);
|
|
8879
|
+
case "chat":
|
|
8880
|
+
return requestChat(env, model, options);
|
|
8881
|
+
case "gemini":
|
|
8882
|
+
return requestGemini(env, model, options);
|
|
8883
|
+
}
|
|
8884
|
+
};
|
|
8885
|
+
var readSourceImage = async (source, cwd) => {
|
|
8886
|
+
if (source.startsWith("data:")) {
|
|
8887
|
+
const decoded = decodeImage(source);
|
|
8888
|
+
if (!decoded) throw new Error(`image source is not a usable data URL: ${source.slice(0, 40)}`);
|
|
8889
|
+
return decoded;
|
|
8890
|
+
}
|
|
8891
|
+
const resolved = path10.isAbsolute(source) ? source : path10.resolve(cwd, source);
|
|
8892
|
+
const bytes = await readFile2(resolved);
|
|
8893
|
+
const mimeType = mimeFromMagic(bytes);
|
|
8894
|
+
if (!mimeType) throw new Error(`unsupported or missing image file: ${resolved}`);
|
|
8895
|
+
return { data: bytes.toString("base64"), mimeType };
|
|
8896
|
+
};
|
|
8897
|
+
var transient = (error) => {
|
|
8898
|
+
const status = error?.status;
|
|
8899
|
+
if (typeof status === "number") return status >= 500 || status === 408 || status === 409 || status === 429;
|
|
8900
|
+
return true;
|
|
8901
|
+
};
|
|
8902
|
+
var describeError = (error) => error instanceof Error ? error.message : String(error);
|
|
8903
|
+
var ImageProvider = class {
|
|
8904
|
+
constructor(config, options = {}) {
|
|
8905
|
+
this.config = config;
|
|
8906
|
+
this.options = options;
|
|
8907
|
+
}
|
|
8908
|
+
name = "image";
|
|
8909
|
+
description = "Image generation and editing across a configurable priority chain of image models";
|
|
8910
|
+
async list(request, _context) {
|
|
8911
|
+
const query = request.query?.toLowerCase();
|
|
8912
|
+
if (!query) return descriptors2;
|
|
8913
|
+
return descriptors2.filter(
|
|
8914
|
+
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
8915
|
+
);
|
|
8916
|
+
}
|
|
8917
|
+
async describe(actionName, _context) {
|
|
8918
|
+
return descriptors2.find((descriptor) => descriptor.name === actionName);
|
|
8919
|
+
}
|
|
8920
|
+
async invoke(actionName, args, context) {
|
|
8921
|
+
switch (actionName) {
|
|
8922
|
+
case "generate":
|
|
8923
|
+
return this.run("generate", args, context);
|
|
8924
|
+
case "edit":
|
|
8925
|
+
return this.run("edit", args, context);
|
|
8926
|
+
case "models":
|
|
8927
|
+
return this.chain(context);
|
|
8928
|
+
default:
|
|
8929
|
+
throw new Error(`Unknown image action: ${actionName}`);
|
|
8930
|
+
}
|
|
8931
|
+
}
|
|
8932
|
+
registry(context) {
|
|
8933
|
+
const registry = context.extensionContext.modelRegistry;
|
|
8934
|
+
if (!registry) throw new Error("image provider needs a model registry on the extension context");
|
|
8935
|
+
return registry;
|
|
8936
|
+
}
|
|
8937
|
+
resolveModel(registry, selector) {
|
|
8938
|
+
const parsed = splitModelSelector(selector);
|
|
8939
|
+
if (!parsed) return void 0;
|
|
8940
|
+
const found = registry.find(parsed.provider, parsed.id);
|
|
8941
|
+
if (!isRecord3(found)) return void 0;
|
|
8942
|
+
const api = typeof found.api === "string" ? found.api : "";
|
|
8943
|
+
const baseUrl = typeof found.baseUrl === "string" ? found.baseUrl : "";
|
|
8944
|
+
if (api.length === 0 || baseUrl.length === 0) return void 0;
|
|
8945
|
+
return {
|
|
8946
|
+
provider: parsed.provider,
|
|
8947
|
+
id: parsed.id,
|
|
8948
|
+
api,
|
|
8949
|
+
baseUrl,
|
|
8950
|
+
gptImage: GPT_IMAGE_FAMILY.test(parsed.id),
|
|
8951
|
+
codex: api === "openai-codex-responses",
|
|
8952
|
+
xai: parsed.provider === "xai" || parsed.provider === "xai-oauth" || parsed.provider.startsWith("xai-")
|
|
8953
|
+
};
|
|
8954
|
+
}
|
|
8955
|
+
dialectFor(model) {
|
|
8956
|
+
const override = this.config().dialects[`${model.provider}/${model.id}`];
|
|
8957
|
+
return override ?? inferImageDialect(model.api, model.id);
|
|
8958
|
+
}
|
|
8959
|
+
chainSelectors(args) {
|
|
8960
|
+
const preferred = typeof args.model === "string" ? args.model.trim() : "";
|
|
8961
|
+
const configured = this.config().models;
|
|
8962
|
+
const selectors = preferred.length > 0 ? [preferred, ...configured] : [...configured];
|
|
8963
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8964
|
+
return selectors.filter((selector) => {
|
|
8965
|
+
if (seen.has(selector)) return false;
|
|
8966
|
+
seen.add(selector);
|
|
8967
|
+
return true;
|
|
8968
|
+
});
|
|
8969
|
+
}
|
|
8970
|
+
async chain(context) {
|
|
8971
|
+
const registry = this.registry(context);
|
|
8972
|
+
const sessionId = context.extensionContext.sessionManager.getSessionId() ?? void 0;
|
|
8973
|
+
const entries = [];
|
|
8974
|
+
for (const selector of this.config().models) {
|
|
8975
|
+
const model = this.resolveModel(registry, selector);
|
|
8976
|
+
if (!model) {
|
|
8977
|
+
entries.push({ selector, resolved: false, reason: "no matching model in the registry" });
|
|
8978
|
+
continue;
|
|
8979
|
+
}
|
|
8980
|
+
let credentials = false;
|
|
8981
|
+
try {
|
|
8982
|
+
const apiKey = await registry.getApiKey(model, sessionId);
|
|
8983
|
+
credentials = typeof apiKey === "string" && apiKey.length > 0;
|
|
8984
|
+
} catch {
|
|
8985
|
+
credentials = false;
|
|
8986
|
+
}
|
|
8987
|
+
entries.push({
|
|
8988
|
+
selector,
|
|
8989
|
+
resolved: true,
|
|
8990
|
+
provider: model.provider,
|
|
8991
|
+
id: model.id,
|
|
8992
|
+
api: model.api,
|
|
8993
|
+
baseUrl: model.baseUrl,
|
|
8994
|
+
dialect: this.dialectFor(model),
|
|
8995
|
+
credentials
|
|
8996
|
+
});
|
|
8997
|
+
}
|
|
8998
|
+
return {
|
|
8999
|
+
enabled: this.config().enabled,
|
|
9000
|
+
timeoutMs: this.config().timeoutMs,
|
|
9001
|
+
retries: this.config().retries,
|
|
9002
|
+
outputDir: this.config().outputDir || os.tmpdir(),
|
|
9003
|
+
models: entries
|
|
9004
|
+
};
|
|
9005
|
+
}
|
|
9006
|
+
async run(action, args, context) {
|
|
9007
|
+
const config = this.config();
|
|
9008
|
+
if (!config.enabled) {
|
|
9009
|
+
return { ok: false, reason: "image provider is disabled (image.enabled=false)" };
|
|
9010
|
+
}
|
|
9011
|
+
const prompt = typeof args.prompt === "string" ? args.prompt.trim() : "";
|
|
9012
|
+
if (prompt.length === 0) return { ok: false, reason: "prompt must be a non-empty string" };
|
|
9013
|
+
const selectors = this.chainSelectors(args);
|
|
9014
|
+
if (selectors.length === 0) {
|
|
9015
|
+
return { ok: false, reason: "no image models configured (image.models is empty)" };
|
|
9016
|
+
}
|
|
9017
|
+
const count = typeof args.count === "number" && Number.isFinite(args.count) && args.count > 0 ? Math.min(Math.floor(args.count), 4) : 1;
|
|
9018
|
+
const aspectRatio = typeof args.aspectRatio === "string" ? args.aspectRatio : void 0;
|
|
9019
|
+
const size = typeof args.size === "string" ? args.size : void 0;
|
|
9020
|
+
const saveTo = typeof args.saveTo === "string" && args.saveTo.trim().length > 0 ? args.saveTo.trim() : void 0;
|
|
9021
|
+
const sources = action === "edit" ? Array.isArray(args.images) ? args.images.filter((entry) => typeof entry === "string") : [] : [];
|
|
9022
|
+
if (action === "edit" && sources.length === 0) {
|
|
9023
|
+
return { ok: false, reason: "edit needs at least one image path or data URL" };
|
|
9024
|
+
}
|
|
9025
|
+
let inputImages = [];
|
|
9026
|
+
try {
|
|
9027
|
+
inputImages = await Promise.all(sources.map((source) => readSourceImage(source, context.cwd)));
|
|
9028
|
+
} catch (error) {
|
|
9029
|
+
return { ok: false, reason: describeError(error) };
|
|
9030
|
+
}
|
|
9031
|
+
const registry = this.registry(context);
|
|
9032
|
+
const sessionId = context.extensionContext.sessionManager.getSessionId() ?? void 0;
|
|
9033
|
+
const fetchImpl = this.options.fetchImpl ?? fetch;
|
|
9034
|
+
const now = this.options.now ?? Date.now;
|
|
9035
|
+
const started = now();
|
|
9036
|
+
const failures = [];
|
|
9037
|
+
const attemptsPerModel = Math.max(1, Math.min(config.retries + 1, 5));
|
|
9038
|
+
for (const selector of selectors) {
|
|
9039
|
+
const model = this.resolveModel(registry, selector);
|
|
9040
|
+
if (!model) {
|
|
9041
|
+
failures.push({ model: selector, dialect: "images", error: "no matching model in the registry" });
|
|
9042
|
+
continue;
|
|
9043
|
+
}
|
|
9044
|
+
const dialect = this.dialectFor(model);
|
|
9045
|
+
let apiKey;
|
|
9046
|
+
let extraHeaders = {};
|
|
9047
|
+
try {
|
|
9048
|
+
apiKey = await registry.getApiKey(model, sessionId);
|
|
9049
|
+
extraHeaders = await registry.resolveModelHeaders?.(model, context.signal) ?? {};
|
|
9050
|
+
} catch (error) {
|
|
9051
|
+
failures.push({ model: selector, dialect, error: `credential lookup failed: ${describeError(error)}` });
|
|
9052
|
+
continue;
|
|
9053
|
+
}
|
|
9054
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
9055
|
+
failures.push({ model: selector, dialect, error: "no credential for this model" });
|
|
9056
|
+
continue;
|
|
9057
|
+
}
|
|
9058
|
+
const authHeaders = model.api === "google-generative-ai" ? geminiHeaders(apiKey) : { Authorization: `Bearer ${apiKey}` };
|
|
9059
|
+
for (let attempt = 1; attempt <= attemptsPerModel; attempt += 1) {
|
|
9060
|
+
context.signal?.throwIfAborted();
|
|
9061
|
+
const signals = [AbortSignal.timeout(config.timeoutMs)];
|
|
9062
|
+
if (context.signal) signals.push(context.signal);
|
|
9063
|
+
const env = {
|
|
9064
|
+
baseUrl: model.baseUrl,
|
|
9065
|
+
apiKey,
|
|
9066
|
+
headers: { ...authHeaders, ...extraHeaders },
|
|
9067
|
+
signal: AbortSignal.any(signals),
|
|
9068
|
+
fetchImpl
|
|
9069
|
+
};
|
|
9070
|
+
try {
|
|
9071
|
+
const images = await callDialect(dialect, env, model, {
|
|
9072
|
+
prompt,
|
|
9073
|
+
aspectRatio,
|
|
9074
|
+
size,
|
|
9075
|
+
count,
|
|
9076
|
+
inputImages,
|
|
9077
|
+
signal: env.signal
|
|
9078
|
+
});
|
|
9079
|
+
if (images.length === 0) throw new Error("backend returned no image data");
|
|
9080
|
+
let written;
|
|
9081
|
+
try {
|
|
9082
|
+
written = await this.write(images, saveTo, context.cwd);
|
|
9083
|
+
} catch (error) {
|
|
9084
|
+
return {
|
|
9085
|
+
ok: false,
|
|
9086
|
+
reason: `${model.provider}/${model.id} returned ${images.length} image(s) but the write failed: ${describeError(error)}`,
|
|
9087
|
+
model: `${model.provider}/${model.id}`,
|
|
9088
|
+
dialect,
|
|
9089
|
+
failures,
|
|
9090
|
+
elapsedMs: Math.max(0, now() - started)
|
|
9091
|
+
};
|
|
9092
|
+
}
|
|
9093
|
+
context.attachMedia?.(
|
|
9094
|
+
written.map((entry) => ({ type: "image", data: entry.data, mimeType: entry.mimeType })),
|
|
9095
|
+
`Generated ${written.length} image(s) with ${model.provider}/${model.id} (${dialect}):
|
|
9096
|
+
${written.map((entry) => ` ${entry.path} (${entry.bytes} bytes)`).join("\n")}`
|
|
9097
|
+
);
|
|
9098
|
+
return {
|
|
9099
|
+
ok: true,
|
|
9100
|
+
model: `${model.provider}/${model.id}`,
|
|
9101
|
+
dialect,
|
|
9102
|
+
images: written.map((entry) => ({ path: entry.path, bytes: entry.bytes, mimeType: entry.mimeType })),
|
|
9103
|
+
attempts: attempt,
|
|
9104
|
+
elapsedMs: Math.max(0, now() - started),
|
|
9105
|
+
failures
|
|
9106
|
+
};
|
|
9107
|
+
} catch (error) {
|
|
9108
|
+
const status = error?.status;
|
|
9109
|
+
failures.push({
|
|
9110
|
+
model: `${model.provider}/${model.id}`,
|
|
9111
|
+
dialect,
|
|
9112
|
+
error: describeError(error),
|
|
9113
|
+
...typeof status === "number" ? { status } : {}
|
|
9114
|
+
});
|
|
9115
|
+
if (context.signal?.aborted) throw error;
|
|
9116
|
+
if (attempt < attemptsPerModel && transient(error)) continue;
|
|
9117
|
+
break;
|
|
9118
|
+
}
|
|
9119
|
+
}
|
|
9120
|
+
}
|
|
9121
|
+
return {
|
|
9122
|
+
ok: false,
|
|
9123
|
+
reason: `every configured image model failed (${failures.length} attempt${failures.length === 1 ? "" : "s"})`,
|
|
9124
|
+
failures,
|
|
9125
|
+
elapsedMs: Math.max(0, now() - started)
|
|
9126
|
+
};
|
|
9127
|
+
}
|
|
9128
|
+
async write(images, saveTo, cwd) {
|
|
9129
|
+
const configured = this.config().outputDir;
|
|
9130
|
+
const directory = configured.length > 0 ? path10.isAbsolute(configured) ? configured : path10.resolve(cwd, configured) : os.tmpdir();
|
|
9131
|
+
await mkdir(directory, { recursive: true, mode: 448 });
|
|
9132
|
+
const written = [];
|
|
9133
|
+
for (const [index, image] of images.entries()) {
|
|
9134
|
+
const extension = extensionForMime(image.mimeType);
|
|
9135
|
+
const target = saveTo !== void 0 && images.length === 1 ? path10.isAbsolute(saveTo) ? saveTo : path10.resolve(cwd, saveTo) : path10.join(directory, `fabric-image-${Date.now()}-${index}.${extension}`);
|
|
9136
|
+
await mkdir(path10.dirname(target), { recursive: true, mode: 448 });
|
|
9137
|
+
const bytes = Buffer.from(image.data, "base64");
|
|
9138
|
+
await writeFile(target, bytes, { mode: 384 });
|
|
9139
|
+
written.push({ path: target, bytes: bytes.length, mimeType: image.mimeType, data: image.data });
|
|
9140
|
+
}
|
|
9141
|
+
return written;
|
|
9142
|
+
}
|
|
9143
|
+
};
|
|
9144
|
+
|
|
8501
9145
|
// src/providers/judgment-provider.ts
|
|
8502
9146
|
import { Type as Type2 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
|
|
8503
9147
|
import { validateJsonSchemaValue as validateJsonSchemaValue2 } from "@oh-my-pi/pi-ai/utils/schema";
|
|
@@ -8510,7 +9154,7 @@ var askSchema = Type2.Object({
|
|
|
8510
9154
|
})
|
|
8511
9155
|
}, { additionalProperties: false });
|
|
8512
9156
|
var statsSchema = Type2.Object({}, { additionalProperties: false });
|
|
8513
|
-
var
|
|
9157
|
+
var descriptors3 = [
|
|
8514
9158
|
{
|
|
8515
9159
|
name: "ask",
|
|
8516
9160
|
description: "Answer typed questions about one state with calibrated probabilities: choice (one label plus its distribution), bool (probability of yes), score (weighted position on ordered levels). Questions asked about the same state within the coalesce window travel as one backend request. Returns { ok: false, reason } instead of throwing when no backend is configured, the budget refuses, or the request fails.",
|
|
@@ -8524,8 +9168,8 @@ var descriptors2 = [
|
|
|
8524
9168
|
risk: "read"
|
|
8525
9169
|
}
|
|
8526
9170
|
];
|
|
8527
|
-
var normalizeJudgmentArgs = actionArgNormalizer(() =>
|
|
8528
|
-
var
|
|
9171
|
+
var normalizeJudgmentArgs = actionArgNormalizer(() => descriptors3);
|
|
9172
|
+
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8529
9173
|
var instructionsOf = (id, value) => {
|
|
8530
9174
|
if (typeof value !== "string" || value.length === 0) {
|
|
8531
9175
|
throw new Error(`judgment.ask question "${id}" needs non-empty string instructions`);
|
|
@@ -8534,7 +9178,7 @@ var instructionsOf = (id, value) => {
|
|
|
8534
9178
|
};
|
|
8535
9179
|
var parseChoice = (id, value) => {
|
|
8536
9180
|
const instructions = instructionsOf(id, value.instructions);
|
|
8537
|
-
if (!
|
|
9181
|
+
if (!isRecord4(value.criteria)) {
|
|
8538
9182
|
throw new Error(`judgment.ask choice question "${id}" needs criteria: { label: rubric | null }`);
|
|
8539
9183
|
}
|
|
8540
9184
|
const criteria = {};
|
|
@@ -8553,7 +9197,7 @@ var parseChoice = (id, value) => {
|
|
|
8553
9197
|
var parseBool = (id, value) => {
|
|
8554
9198
|
const instructions = instructionsOf(id, value.instructions);
|
|
8555
9199
|
if (value.criteria === void 0) return { type: "noul", instructions };
|
|
8556
|
-
if (!
|
|
9200
|
+
if (!isRecord4(value.criteria)) {
|
|
8557
9201
|
throw new Error(`judgment.ask bool question "${id}" criteria must be { true?: string, false?: string }`);
|
|
8558
9202
|
}
|
|
8559
9203
|
const criteria = {};
|
|
@@ -8580,7 +9224,7 @@ var parseScore = (id, value) => {
|
|
|
8580
9224
|
return { type: "score", instructions, criteria: [lowest, second, ...rest] };
|
|
8581
9225
|
};
|
|
8582
9226
|
var parseQuestion = (id, value) => {
|
|
8583
|
-
if (!
|
|
9227
|
+
if (!isRecord4(value)) throw new Error(`judgment.ask question "${id}" must be an object`);
|
|
8584
9228
|
switch (value.type) {
|
|
8585
9229
|
case "choice":
|
|
8586
9230
|
return parseChoice(id, value);
|
|
@@ -8597,7 +9241,7 @@ var parseState = (value) => {
|
|
|
8597
9241
|
if (value.length === 0) throw new Error("judgment.ask state must not be empty");
|
|
8598
9242
|
return value;
|
|
8599
9243
|
}
|
|
8600
|
-
if (Array.isArray(value) ||
|
|
9244
|
+
if (Array.isArray(value) || isRecord4(value)) return value;
|
|
8601
9245
|
throw new Error("judgment.ask state must be a string, a JSON object, or a JSON array");
|
|
8602
9246
|
};
|
|
8603
9247
|
var checked2 = (action, schema, args) => {
|
|
@@ -8616,12 +9260,12 @@ var JudgmentProvider = class {
|
|
|
8616
9260
|
description = "Typed judgments over one state: calibrated choice, bool, and score answers batched into one backend request";
|
|
8617
9261
|
async list(request, _context) {
|
|
8618
9262
|
const query = request.query?.toLowerCase();
|
|
8619
|
-
return query ?
|
|
9263
|
+
return query ? descriptors3.filter(
|
|
8620
9264
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
8621
|
-
) :
|
|
9265
|
+
) : descriptors3;
|
|
8622
9266
|
}
|
|
8623
9267
|
async describe(actionName, _context) {
|
|
8624
|
-
return
|
|
9268
|
+
return descriptors3.find((descriptor) => descriptor.name === actionName);
|
|
8625
9269
|
}
|
|
8626
9270
|
prepareArguments(actionName, args) {
|
|
8627
9271
|
return normalizeJudgmentArgs(actionName, args);
|
|
@@ -8933,7 +9577,7 @@ var emptySchema = {
|
|
|
8933
9577
|
properties: {},
|
|
8934
9578
|
additionalProperties: false
|
|
8935
9579
|
};
|
|
8936
|
-
var
|
|
9580
|
+
var descriptors4 = [
|
|
8937
9581
|
{
|
|
8938
9582
|
name: "request",
|
|
8939
9583
|
description: "Request an advisory compaction of the host session's context at the next safe boundary (agent_end). The host commits it only between turns, never mid-turn. A new request replaces any pending one.",
|
|
@@ -8956,7 +9600,7 @@ var descriptors3 = [
|
|
|
8956
9600
|
risk: "write"
|
|
8957
9601
|
}
|
|
8958
9602
|
];
|
|
8959
|
-
var normalizeCompactArgs = actionArgNormalizer(() =>
|
|
9603
|
+
var normalizeCompactArgs = actionArgNormalizer(() => descriptors4);
|
|
8960
9604
|
var CompactProvider = class {
|
|
8961
9605
|
constructor(controller) {
|
|
8962
9606
|
this.controller = controller;
|
|
@@ -8965,12 +9609,12 @@ var CompactProvider = class {
|
|
|
8965
9609
|
description = "Programmatic, advisory-then-committed context compaction for the host OMP session";
|
|
8966
9610
|
async list(request, _context) {
|
|
8967
9611
|
const query = request.query?.toLowerCase();
|
|
8968
|
-
return query ?
|
|
9612
|
+
return query ? descriptors4.filter(
|
|
8969
9613
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
8970
|
-
) :
|
|
9614
|
+
) : descriptors4;
|
|
8971
9615
|
}
|
|
8972
9616
|
async describe(actionName, _context) {
|
|
8973
|
-
return
|
|
9617
|
+
return descriptors4.find((descriptor) => descriptor.name === actionName);
|
|
8974
9618
|
}
|
|
8975
9619
|
prepareArguments(actionName, args) {
|
|
8976
9620
|
return normalizeCompactArgs(actionName, args);
|
|
@@ -9010,7 +9654,7 @@ var CompactProvider = class {
|
|
|
9010
9654
|
};
|
|
9011
9655
|
|
|
9012
9656
|
// src/providers/components-provider.ts
|
|
9013
|
-
var
|
|
9657
|
+
var descriptors5 = [
|
|
9014
9658
|
{
|
|
9015
9659
|
name: "list",
|
|
9016
9660
|
description: "List registered component definitions and configured component instances.",
|
|
@@ -9057,13 +9701,13 @@ var ComponentsProvider = class {
|
|
|
9057
9701
|
description = "Supervised component lifecycle, exact capability dependencies, effect cleanup, and reload diagnostics.";
|
|
9058
9702
|
async list(request, _context) {
|
|
9059
9703
|
const query = request.query?.normalize("NFKC").trim().toLowerCase();
|
|
9060
|
-
const filtered = query ?
|
|
9704
|
+
const filtered = query ? descriptors5.filter(
|
|
9061
9705
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
9062
|
-
) :
|
|
9706
|
+
) : descriptors5;
|
|
9063
9707
|
return filtered.slice(0, Math.max(1, Math.min(request.limit ?? 100, 100)));
|
|
9064
9708
|
}
|
|
9065
9709
|
async describe(actionName, _context) {
|
|
9066
|
-
return
|
|
9710
|
+
return descriptors5.find((descriptor) => descriptor.name === actionName);
|
|
9067
9711
|
}
|
|
9068
9712
|
async invoke(actionName, args, _context) {
|
|
9069
9713
|
switch (actionName) {
|
|
@@ -9097,37 +9741,37 @@ var ComponentsProvider = class {
|
|
|
9097
9741
|
// src/providers/mcp-descriptor-cache.ts
|
|
9098
9742
|
import fs5 from "node:fs/promises";
|
|
9099
9743
|
import fsSync from "node:fs";
|
|
9100
|
-
import
|
|
9101
|
-
import
|
|
9744
|
+
import os2 from "node:os";
|
|
9745
|
+
import path11 from "node:path";
|
|
9102
9746
|
var MCP_DESCRIPTOR_CACHE_VERSION = 1;
|
|
9103
9747
|
var homeDir = () => {
|
|
9104
9748
|
const home = process.env.HOME;
|
|
9105
|
-
return home && home.trim().length > 0 ? home :
|
|
9749
|
+
return home && home.trim().length > 0 ? home : os2.homedir();
|
|
9106
9750
|
};
|
|
9107
9751
|
var expandHome = (input) => {
|
|
9108
9752
|
if (!input.startsWith("~")) return input;
|
|
9109
9753
|
const home = homeDir();
|
|
9110
9754
|
if (input === "~") return home;
|
|
9111
9755
|
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
9112
|
-
return
|
|
9756
|
+
return path11.join(home, input.slice(2));
|
|
9113
9757
|
}
|
|
9114
9758
|
return input;
|
|
9115
9759
|
};
|
|
9116
|
-
var legacyMcporterDir = () =>
|
|
9760
|
+
var legacyMcporterDir = () => path11.join(homeDir(), ".mcporter");
|
|
9117
9761
|
var mcporterConfigDir = () => {
|
|
9118
9762
|
const raw = process.env.XDG_CONFIG_HOME;
|
|
9119
9763
|
if (raw && raw.trim().length > 0) {
|
|
9120
9764
|
const resolved = expandHome(raw.trim());
|
|
9121
|
-
if (
|
|
9765
|
+
if (path11.isAbsolute(resolved)) return path11.join(resolved, "mcporter");
|
|
9122
9766
|
}
|
|
9123
9767
|
return legacyMcporterDir();
|
|
9124
9768
|
};
|
|
9125
9769
|
var mcporterConfigCandidates = () => {
|
|
9126
9770
|
const base = mcporterConfigDir();
|
|
9127
|
-
const candidates = [
|
|
9771
|
+
const candidates = [path11.join(base, "mcporter.json"), path11.join(base, "mcporter.jsonc")];
|
|
9128
9772
|
const legacy = legacyMcporterDir();
|
|
9129
9773
|
if (base !== legacy) {
|
|
9130
|
-
candidates.push(
|
|
9774
|
+
candidates.push(path11.join(legacy, "mcporter.json"), path11.join(legacy, "mcporter.jsonc"));
|
|
9131
9775
|
}
|
|
9132
9776
|
return candidates;
|
|
9133
9777
|
};
|
|
@@ -9142,12 +9786,12 @@ var pathExists = (filePath) => {
|
|
|
9142
9786
|
var mcpConfigLayerPaths = (rootDir, configPath) => {
|
|
9143
9787
|
const explicitRaw = configPath ?? process.env.MCPORTER_CONFIG;
|
|
9144
9788
|
if (explicitRaw && explicitRaw.trim().length > 0) {
|
|
9145
|
-
return [
|
|
9789
|
+
return [path11.resolve(expandHome(explicitRaw.trim()))];
|
|
9146
9790
|
}
|
|
9147
9791
|
const paths = [];
|
|
9148
9792
|
const home = mcporterConfigCandidates().find(pathExists);
|
|
9149
9793
|
if (home) paths.push(home);
|
|
9150
|
-
const projectPath =
|
|
9794
|
+
const projectPath = path11.resolve(rootDir, "config", "mcporter.json");
|
|
9151
9795
|
if (pathExists(projectPath)) paths.push(projectPath);
|
|
9152
9796
|
return paths;
|
|
9153
9797
|
};
|
|
@@ -9169,11 +9813,11 @@ var sameConfigLayers = (left, right) => left.length === right.length && left.eve
|
|
|
9169
9813
|
return other !== void 0 && layer.path === other.path && layer.size === other.size && Math.abs(layer.mtimeMs - other.mtimeMs) <= 1;
|
|
9170
9814
|
});
|
|
9171
9815
|
var hashServerDefinition = (definition) => stableJsonHash(definition);
|
|
9172
|
-
var
|
|
9816
|
+
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9173
9817
|
var parseCachedServer = (value) => {
|
|
9174
|
-
if (!
|
|
9818
|
+
if (!isRecord5(value)) return void 0;
|
|
9175
9819
|
const tools = Array.isArray(value.tools) ? value.tools.filter(
|
|
9176
|
-
(tool) =>
|
|
9820
|
+
(tool) => isRecord5(tool) && typeof tool.name === "string"
|
|
9177
9821
|
) : void 0;
|
|
9178
9822
|
if (typeof value.definitionHash !== "string" || tools === void 0) return void 0;
|
|
9179
9823
|
return {
|
|
@@ -9186,10 +9830,10 @@ var parseCachedServer = (value) => {
|
|
|
9186
9830
|
};
|
|
9187
9831
|
};
|
|
9188
9832
|
var parseCacheFile = (value) => {
|
|
9189
|
-
if (!
|
|
9190
|
-
if (!Array.isArray(value.layers) || !
|
|
9833
|
+
if (!isRecord5(value) || value.version !== MCP_DESCRIPTOR_CACHE_VERSION) return void 0;
|
|
9834
|
+
if (!Array.isArray(value.layers) || !isRecord5(value.servers)) return void 0;
|
|
9191
9835
|
const layers = value.layers.filter(
|
|
9192
|
-
(layer) =>
|
|
9836
|
+
(layer) => isRecord5(layer) && typeof layer.path === "string" && typeof layer.mtimeMs === "number" && typeof layer.size === "number"
|
|
9193
9837
|
);
|
|
9194
9838
|
return {
|
|
9195
9839
|
version: MCP_DESCRIPTOR_CACHE_VERSION,
|
|
@@ -9198,8 +9842,8 @@ var parseCacheFile = (value) => {
|
|
|
9198
9842
|
servers: value.servers
|
|
9199
9843
|
};
|
|
9200
9844
|
};
|
|
9201
|
-
var projectMcpCachePath = (projectRoot) =>
|
|
9202
|
-
var globalMcpCachePath = (agentDir) =>
|
|
9845
|
+
var projectMcpCachePath = (projectRoot) => path11.join(projectRoot, ".omp", "fabric", "mcp-cache.json");
|
|
9846
|
+
var globalMcpCachePath = (agentDir) => path11.join(agentDir, "fabric", "mcp-descriptors.json");
|
|
9203
9847
|
var tempCounter = 0;
|
|
9204
9848
|
var McpDescriptorCacheStore = class {
|
|
9205
9849
|
constructor(filePath) {
|
|
@@ -9216,9 +9860,9 @@ var McpDescriptorCacheStore = class {
|
|
|
9216
9860
|
// Atomic-ish write: temp file then rename, so a concurrent reader either
|
|
9217
9861
|
// sees the previous cache or the next one, never a torn document.
|
|
9218
9862
|
async save(file) {
|
|
9219
|
-
const directory =
|
|
9863
|
+
const directory = path11.dirname(this.filePath);
|
|
9220
9864
|
await fs5.mkdir(directory, { recursive: true });
|
|
9221
|
-
const tempPath =
|
|
9865
|
+
const tempPath = path11.join(
|
|
9222
9866
|
directory,
|
|
9223
9867
|
`.mcp-cache-${process.pid}-${Date.now()}-${tempCounter++}.tmp`
|
|
9224
9868
|
);
|
|
@@ -9233,7 +9877,7 @@ var McpDescriptorCacheStore = class {
|
|
|
9233
9877
|
};
|
|
9234
9878
|
|
|
9235
9879
|
// src/providers/mcp-provider.ts
|
|
9236
|
-
import
|
|
9880
|
+
import path12 from "node:path";
|
|
9237
9881
|
var TOOL_METADATA_TTL_MS = 6e4;
|
|
9238
9882
|
var REVALIDATE_CONCURRENCY = 3;
|
|
9239
9883
|
var REVALIDATE_SERVER_TIMEOUT_MS = 2e4;
|
|
@@ -9394,9 +10038,9 @@ var McpProvider = class {
|
|
|
9394
10038
|
this.#kickRevalidation();
|
|
9395
10039
|
if (!request.namespace) await this.#awaitColdEnumeration(context.signal);
|
|
9396
10040
|
const query = request.query?.toLowerCase();
|
|
9397
|
-
const filterQuery = (
|
|
10041
|
+
const filterQuery = (descriptors9) => query ? descriptors9.filter(
|
|
9398
10042
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
9399
|
-
) :
|
|
10043
|
+
) : descriptors9;
|
|
9400
10044
|
if (request.namespace) {
|
|
9401
10045
|
const server = await this.#resolveKnownServer(request.namespace);
|
|
9402
10046
|
if (!server) return [];
|
|
@@ -9551,11 +10195,11 @@ var McpProvider = class {
|
|
|
9551
10195
|
// Provider-fidelity descriptors for everything currently known, cached or
|
|
9552
10196
|
// ephemeral.
|
|
9553
10197
|
sliceDescriptors() {
|
|
9554
|
-
const
|
|
10198
|
+
const descriptors9 = [];
|
|
9555
10199
|
for (const [server, entry] of this.#servers) {
|
|
9556
|
-
for (const tool of entry.tools)
|
|
10200
|
+
for (const tool of entry.tools) descriptors9.push(this.#toolDescriptor(server, tool));
|
|
9557
10201
|
}
|
|
9558
|
-
return
|
|
10202
|
+
return descriptors9;
|
|
9559
10203
|
}
|
|
9560
10204
|
// Test/ops hook: await hydration and any in-flight background revalidation,
|
|
9561
10205
|
// then flush pending persistence and notifications.
|
|
@@ -9957,7 +10601,7 @@ var McpProvider = class {
|
|
|
9957
10601
|
kind: "stdio",
|
|
9958
10602
|
command: args.command,
|
|
9959
10603
|
args: commandArgs,
|
|
9960
|
-
cwd:
|
|
10604
|
+
cwd: path12.resolve(this.cwd, typeof args.cwd === "string" ? args.cwd : ".")
|
|
9961
10605
|
},
|
|
9962
10606
|
...env ? { env } : {}
|
|
9963
10607
|
};
|
|
@@ -10022,13 +10666,13 @@ var McpProvider = class {
|
|
|
10022
10666
|
return tools.map((tool) => this.#toolDescriptor(server, tool));
|
|
10023
10667
|
})
|
|
10024
10668
|
);
|
|
10025
|
-
const
|
|
10669
|
+
const descriptors9 = settled.flatMap(
|
|
10026
10670
|
(entry) => entry.status === "fulfilled" ? entry.value : []
|
|
10027
10671
|
);
|
|
10028
10672
|
const query = request.query?.toLowerCase();
|
|
10029
|
-
const filtered = query ?
|
|
10673
|
+
const filtered = query ? descriptors9.filter(
|
|
10030
10674
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
10031
|
-
) :
|
|
10675
|
+
) : descriptors9;
|
|
10032
10676
|
return request.namespace ? filtered : [...managementDescriptors, ...filtered];
|
|
10033
10677
|
}
|
|
10034
10678
|
async #describeLegacy(actionName, _context) {
|
|
@@ -10100,7 +10744,7 @@ var assertReadableStateKey = (key) => {
|
|
|
10100
10744
|
throw new Error(`Fabric mesh key is private host state: ${key}`);
|
|
10101
10745
|
}
|
|
10102
10746
|
};
|
|
10103
|
-
var
|
|
10747
|
+
var descriptors6 = [
|
|
10104
10748
|
{
|
|
10105
10749
|
name: "self",
|
|
10106
10750
|
description: "Return this Fabric participant's mesh identity",
|
|
@@ -10227,7 +10871,7 @@ var descriptors5 = [
|
|
|
10227
10871
|
namespace: "coordination"
|
|
10228
10872
|
}
|
|
10229
10873
|
];
|
|
10230
|
-
var normalizeMeshArgs = actionArgNormalizer(() =>
|
|
10874
|
+
var normalizeMeshArgs = actionArgNormalizer(() => descriptors6);
|
|
10231
10875
|
var MeshProvider = class {
|
|
10232
10876
|
constructor(store, identity, participants) {
|
|
10233
10877
|
this.store = store;
|
|
@@ -10238,12 +10882,12 @@ var MeshProvider = class {
|
|
|
10238
10882
|
description = "Durable topics and compare-and-swap shared state for emergent agent coordination";
|
|
10239
10883
|
async list(request, _context) {
|
|
10240
10884
|
const query = request.query?.toLowerCase();
|
|
10241
|
-
return query ?
|
|
10885
|
+
return query ? descriptors6.filter(
|
|
10242
10886
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
10243
|
-
) :
|
|
10887
|
+
) : descriptors6;
|
|
10244
10888
|
}
|
|
10245
10889
|
async describe(actionName, _context) {
|
|
10246
|
-
return
|
|
10890
|
+
return descriptors6.find((descriptor) => descriptor.name === actionName);
|
|
10247
10891
|
}
|
|
10248
10892
|
prepareArguments(actionName, args) {
|
|
10249
10893
|
return normalizeMeshArgs(actionName, args);
|
|
@@ -10337,7 +10981,7 @@ var MeshProvider = class {
|
|
|
10337
10981
|
// src/providers/omp-tools-provider.ts
|
|
10338
10982
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, statSync as statSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
10339
10983
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10340
|
-
import
|
|
10984
|
+
import path15 from "node:path";
|
|
10341
10985
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
10342
10986
|
import { BashTool } from "@oh-my-pi/pi-coding-agent/tools/bash";
|
|
10343
10987
|
import { EditTool } from "@oh-my-pi/pi-coding-agent/edit";
|
|
@@ -10356,7 +11000,7 @@ import {
|
|
|
10356
11000
|
|
|
10357
11001
|
// src/agents/bash-worktree-add.ts
|
|
10358
11002
|
import fs6 from "node:fs";
|
|
10359
|
-
import
|
|
11003
|
+
import path13 from "node:path";
|
|
10360
11004
|
var BARE_SAFE = /^[A-Za-z0-9_./:@%+=,-]+$/;
|
|
10361
11005
|
var parseGitWorktreeAdd = (command) => {
|
|
10362
11006
|
const trimmed = command.trim();
|
|
@@ -10419,8 +11063,8 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
|
|
|
10419
11063
|
if (typeof command !== "string") return void 0;
|
|
10420
11064
|
const parsed = parseGitWorktreeAdd(command);
|
|
10421
11065
|
if (!parsed) return void 0;
|
|
10422
|
-
const gitCwd = parsed.gitCwd ?
|
|
10423
|
-
const dest =
|
|
11066
|
+
const gitCwd = parsed.gitCwd ? path13.resolve(sessionCwd, parsed.gitCwd) : typeof args.cwd === "string" ? args.cwd : sessionCwd;
|
|
11067
|
+
const dest = path13.resolve(gitCwd, parsed.dest);
|
|
10424
11068
|
let gitRoot;
|
|
10425
11069
|
try {
|
|
10426
11070
|
const root = await executeFile("git", ["rev-parse", "--show-toplevel"], {
|
|
@@ -10449,7 +11093,7 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
|
|
|
10449
11093
|
|
|
10450
11094
|
// src/providers/omp-bash-cwd.ts
|
|
10451
11095
|
import { accessSync, constants, statSync as statSync3 } from "node:fs";
|
|
10452
|
-
import
|
|
11096
|
+
import path14 from "node:path";
|
|
10453
11097
|
import { createBashToolDefinition } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-pi-coding-agent-shim";
|
|
10454
11098
|
import { Type as Type4 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
|
|
10455
11099
|
var OMP_BASH_CWD_KEY = "cwd";
|
|
@@ -10459,7 +11103,7 @@ var resolveOmpShellCwd = (toolName, sessionCwd, requested) => {
|
|
|
10459
11103
|
`Invalid omp.${toolName} cwd ${JSON.stringify(requested)}: path must be a non-empty string`
|
|
10460
11104
|
);
|
|
10461
11105
|
}
|
|
10462
|
-
const resolved =
|
|
11106
|
+
const resolved = path14.isAbsolute(requested) ? path14.resolve(requested) : path14.resolve(sessionCwd, requested);
|
|
10463
11107
|
try {
|
|
10464
11108
|
if (!statSync3(resolved).isDirectory()) throw new Error("path is not a directory");
|
|
10465
11109
|
accessSync(resolved, constants.R_OK | constants.X_OK);
|
|
@@ -10481,23 +11125,23 @@ var resolveShellCwdArgument = (toolName, sessionCwd, args) => Object.hasOwn(args
|
|
|
10481
11125
|
} : args;
|
|
10482
11126
|
var CWD_DESCRIPTION = "Execution directory for this command; relative paths resolve from the session cwd.";
|
|
10483
11127
|
var CWD_PROPERTY = Type4.Optional(Type4.String({ description: CWD_DESCRIPTION }));
|
|
10484
|
-
var
|
|
11128
|
+
var isRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10485
11129
|
var SHELL_FIELD_DESCRIPTIONS = {
|
|
10486
11130
|
command: "command to execute",
|
|
10487
11131
|
[OMP_BASH_CWD_KEY]: CWD_DESCRIPTION,
|
|
10488
11132
|
pty: "run in pty mode"
|
|
10489
11133
|
};
|
|
10490
11134
|
var schemaDocument2 = (schema) => {
|
|
10491
|
-
if (
|
|
11135
|
+
if (isRecord6(schema)) return schema;
|
|
10492
11136
|
if (typeof schema !== "function" || !("toJsonSchema" in schema)) return void 0;
|
|
10493
11137
|
const toJsonSchema = schema.toJsonSchema;
|
|
10494
11138
|
if (typeof toJsonSchema !== "function") return void 0;
|
|
10495
11139
|
const document = toJsonSchema.call(schema);
|
|
10496
|
-
return
|
|
11140
|
+
return isRecord6(document) ? document : void 0;
|
|
10497
11141
|
};
|
|
10498
11142
|
var withShellCwdSchema = (schema) => {
|
|
10499
11143
|
const document = schemaDocument2(schema);
|
|
10500
|
-
if (!document || !
|
|
11144
|
+
if (!document || !isRecord6(document.properties)) return schema;
|
|
10501
11145
|
const properties = { ...document.properties };
|
|
10502
11146
|
let changed = false;
|
|
10503
11147
|
const cwdSchema = Object.hasOwn(properties, OMP_BASH_CWD_KEY) ? void 0 : schemaDocument2(CWD_PROPERTY);
|
|
@@ -10507,7 +11151,7 @@ var withShellCwdSchema = (schema) => {
|
|
|
10507
11151
|
}
|
|
10508
11152
|
for (const [field, description] of Object.entries(SHELL_FIELD_DESCRIPTIONS)) {
|
|
10509
11153
|
const property = properties[field];
|
|
10510
|
-
if (!
|
|
11154
|
+
if (!isRecord6(property) || typeof property.description === "string") continue;
|
|
10511
11155
|
properties[field] = { ...property, description };
|
|
10512
11156
|
changed = true;
|
|
10513
11157
|
}
|
|
@@ -10544,23 +11188,23 @@ var BashCwdDefinitions = class extends ShellCwdDefinitions {
|
|
|
10544
11188
|
// src/providers/write-preview.ts
|
|
10545
11189
|
import { homedir } from "node:os";
|
|
10546
11190
|
import { dirname, isAbsolute, resolve, win32 } from "node:path";
|
|
10547
|
-
import { mkdir, readFile as
|
|
11191
|
+
import { mkdir as mkdir2, readFile as readFile3, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
10548
11192
|
import { Type as Type5 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
|
|
10549
11193
|
import { WriteTool } from "@oh-my-pi/pi-coding-agent/tools/write";
|
|
10550
11194
|
var mutationQueues = /* @__PURE__ */ new Map();
|
|
10551
|
-
var withFileMutationQueue = async (
|
|
10552
|
-
const previous = mutationQueues.get(
|
|
11195
|
+
var withFileMutationQueue = async (path21, operation) => {
|
|
11196
|
+
const previous = mutationQueues.get(path21) ?? Promise.resolve();
|
|
10553
11197
|
let release;
|
|
10554
11198
|
const current = new Promise((resolve2) => {
|
|
10555
11199
|
release = resolve2;
|
|
10556
11200
|
});
|
|
10557
|
-
mutationQueues.set(
|
|
11201
|
+
mutationQueues.set(path21, current);
|
|
10558
11202
|
await previous;
|
|
10559
11203
|
try {
|
|
10560
11204
|
return await operation();
|
|
10561
11205
|
} finally {
|
|
10562
11206
|
release();
|
|
10563
|
-
if (mutationQueues.get(
|
|
11207
|
+
if (mutationQueues.get(path21) === current) mutationQueues.delete(path21);
|
|
10564
11208
|
}
|
|
10565
11209
|
};
|
|
10566
11210
|
var URI_LIKE_WRITE_TARGET_RE = /^([a-z][a-z0-9+.-]*):\/{1,2}/i;
|
|
@@ -10605,7 +11249,7 @@ var readExistingFileForPreview = async (filePath, cwd, nextContent) => {
|
|
|
10605
11249
|
return skipped("previous file too large", fileStat.size, true);
|
|
10606
11250
|
}
|
|
10607
11251
|
try {
|
|
10608
|
-
const content = await
|
|
11252
|
+
const content = await readFile3(absolutePath, "utf8");
|
|
10609
11253
|
const bytes = Buffer.byteLength(content, "utf8");
|
|
10610
11254
|
return bytes > MAX_WRITE_DIFF_BYTES ? skipped("previous file too large", bytes, true) : { kind: "content", content };
|
|
10611
11255
|
} catch {
|
|
@@ -10623,11 +11267,11 @@ var createPreviewWriteToolDefinition = (cwd, session) => {
|
|
|
10623
11267
|
return {
|
|
10624
11268
|
...original,
|
|
10625
11269
|
async execute(_toolCallId, params, signal) {
|
|
10626
|
-
const { path:
|
|
10627
|
-
if (isUriLikeWriteTarget(
|
|
11270
|
+
const { path: path21, content } = params;
|
|
11271
|
+
if (isUriLikeWriteTarget(path21)) {
|
|
10628
11272
|
if (session === void 0) {
|
|
10629
11273
|
throw new Error(
|
|
10630
|
-
`Refusing to write '${
|
|
11274
|
+
`Refusing to write '${path21}': URI-like targets need a host session to resolve. Prefix the path with './' to create a literal file by that name.`
|
|
10631
11275
|
);
|
|
10632
11276
|
}
|
|
10633
11277
|
return await new WriteTool(session).execute(
|
|
@@ -10639,23 +11283,23 @@ var createPreviewWriteToolDefinition = (cwd, session) => {
|
|
|
10639
11283
|
{ signal }
|
|
10640
11284
|
);
|
|
10641
11285
|
}
|
|
10642
|
-
const absolutePath = resolvePreviewPath(
|
|
11286
|
+
const absolutePath = resolvePreviewPath(path21, cwd);
|
|
10643
11287
|
return withFileMutationQueue(absolutePath, async () => {
|
|
10644
11288
|
const throwIfAborted2 = () => {
|
|
10645
11289
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
10646
11290
|
};
|
|
10647
11291
|
throwIfAborted2();
|
|
10648
|
-
const before = await readExistingFileForPreview(
|
|
11292
|
+
const before = await readExistingFileForPreview(path21, cwd, content);
|
|
10649
11293
|
throwIfAborted2();
|
|
10650
|
-
await
|
|
11294
|
+
await mkdir2(dirname(absolutePath), { recursive: true });
|
|
10651
11295
|
throwIfAborted2();
|
|
10652
|
-
await
|
|
11296
|
+
await writeFile2(absolutePath, content, "utf8");
|
|
10653
11297
|
throwIfAborted2();
|
|
10654
11298
|
return {
|
|
10655
11299
|
content: [
|
|
10656
11300
|
{
|
|
10657
11301
|
type: "text",
|
|
10658
|
-
text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${
|
|
11302
|
+
text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path21}`
|
|
10659
11303
|
}
|
|
10660
11304
|
],
|
|
10661
11305
|
details: { codePreviewBeforeWrite: before }
|
|
@@ -10782,7 +11426,7 @@ var createNativeSession = (cwd, {
|
|
|
10782
11426
|
try {
|
|
10783
11427
|
mkdirSync2(artifacts.root, { recursive: true, mode: 448 });
|
|
10784
11428
|
const id = randomUUID3();
|
|
10785
|
-
const artifactPath =
|
|
11429
|
+
const artifactPath = path15.join(artifacts.root, `${toolType}-${id}.log`);
|
|
10786
11430
|
writeFileSync2(artifactPath, "", { mode: 384 });
|
|
10787
11431
|
artifacts.paths.set(id, artifactPath);
|
|
10788
11432
|
artifactAllocations.getStore()?.push(artifactPath);
|
|
@@ -10950,7 +11594,7 @@ var normalizeEditArguments = (args, replaceAll, cwd) => {
|
|
|
10950
11594
|
...replaceAll || record2.all === true || record2.replace_all === true ? { replace_all: true } : {}
|
|
10951
11595
|
};
|
|
10952
11596
|
});
|
|
10953
|
-
const resolvedPath =
|
|
11597
|
+
const resolvedPath = path15.resolve(cwd, filePath.startsWith("@") ? filePath.slice(1) : filePath);
|
|
10954
11598
|
const current = readFileSync2(resolvedPath, "utf8");
|
|
10955
11599
|
if (current.length > MAX_REPLACE_ALL_FILE_CHARS) {
|
|
10956
11600
|
throw new Error(`omp.edit refuses files over ${MAX_REPLACE_ALL_FILE_CHARS} characters`);
|
|
@@ -11425,10 +12069,10 @@ var OmpToolsProvider = class _OmpToolsProvider {
|
|
|
11425
12069
|
}
|
|
11426
12070
|
async list(request, _context) {
|
|
11427
12071
|
const query = request.query?.toLowerCase();
|
|
11428
|
-
const
|
|
12072
|
+
const descriptors9 = await Promise.all(
|
|
11429
12073
|
OMP_GUEST_TOOL_NAMES.map((name) => this.describe(name, _context))
|
|
11430
12074
|
);
|
|
11431
|
-
return
|
|
12075
|
+
return descriptors9.filter((descriptor) => descriptor !== void 0).filter(
|
|
11432
12076
|
(descriptor) => query ? `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query) : true
|
|
11433
12077
|
);
|
|
11434
12078
|
}
|
|
@@ -11834,7 +12478,7 @@ var OmpToolsProvider = class _OmpToolsProvider {
|
|
|
11834
12478
|
import { spawn } from "node:child_process";
|
|
11835
12479
|
import { createHash as createHash3, randomBytes, randomUUID as randomUUID4 } from "node:crypto";
|
|
11836
12480
|
import fs8 from "node:fs";
|
|
11837
|
-
import
|
|
12481
|
+
import path17 from "node:path";
|
|
11838
12482
|
|
|
11839
12483
|
// src/schema/types.ts
|
|
11840
12484
|
var stateBinding = (head) => head ? { transitionId: head.transitionId, version: head.version, to: head.to } : null;
|
|
@@ -11843,7 +12487,7 @@ var stateBinding = (head) => head ? { transitionId: head.transitionId, version:
|
|
|
11843
12487
|
import { execFileSync } from "node:child_process";
|
|
11844
12488
|
import { createHash as createHash2 } from "node:crypto";
|
|
11845
12489
|
import fs7 from "node:fs";
|
|
11846
|
-
import
|
|
12490
|
+
import path16 from "node:path";
|
|
11847
12491
|
var SNAPSHOT_MAX_FILES = 2e4;
|
|
11848
12492
|
var SNAPSHOT_MAX_BYTES = 512 * 1024 * 1024;
|
|
11849
12493
|
var FALLBACK_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
@@ -11861,10 +12505,10 @@ var git = (cwd, args) => execFileSync("git", ["-C", cwd, ...args], {
|
|
|
11861
12505
|
stdio: ["ignore", "pipe", "ignore"]
|
|
11862
12506
|
});
|
|
11863
12507
|
var nulPaths = (buffer) => buffer.toString("utf8").split("\0").filter((item) => item.length > 0);
|
|
11864
|
-
var normalizeRelative = (value) => value.split(
|
|
12508
|
+
var normalizeRelative = (value) => value.split(path16.sep).join("/");
|
|
11865
12509
|
var isInside = (root, candidate) => {
|
|
11866
|
-
const relative =
|
|
11867
|
-
return relative === "" || !
|
|
12510
|
+
const relative = path16.relative(root, candidate);
|
|
12511
|
+
return relative === "" || !path16.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path16.sep}`);
|
|
11868
12512
|
};
|
|
11869
12513
|
var excluded = (absolute, exclusions) => exclusions.some((root) => isInside(root, absolute));
|
|
11870
12514
|
var entryDigest = (absolute) => {
|
|
@@ -11890,12 +12534,12 @@ var buildSnapshot = (cwd, paths, metadata, exclusions) => {
|
|
|
11890
12534
|
let bytes = 0;
|
|
11891
12535
|
const unique = [...new Set(paths)].sort((left, right) => left.localeCompare(right));
|
|
11892
12536
|
for (const relativeInput of unique) {
|
|
11893
|
-
const absolute =
|
|
12537
|
+
const absolute = path16.resolve(cwd, relativeInput);
|
|
11894
12538
|
if (!isInside(cwd, absolute) || excluded(absolute, exclusions)) continue;
|
|
11895
12539
|
if (Object.keys(entries).length >= SNAPSHOT_MAX_FILES) {
|
|
11896
12540
|
throw new Error(`Schema workspace snapshot exceeds ${SNAPSHOT_MAX_FILES} files`);
|
|
11897
12541
|
}
|
|
11898
|
-
const relative = normalizeRelative(
|
|
12542
|
+
const relative = normalizeRelative(path16.relative(cwd, absolute));
|
|
11899
12543
|
const entry = entryDigest(absolute);
|
|
11900
12544
|
bytes += entry.bytes;
|
|
11901
12545
|
if (bytes > SNAPSHOT_MAX_BYTES) {
|
|
@@ -11924,9 +12568,9 @@ var fallbackPaths = (cwd, exclusions) => {
|
|
|
11924
12568
|
const entries = fs7.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
11925
12569
|
for (const entry of entries) {
|
|
11926
12570
|
if (FALLBACK_SKIPPED_DIRECTORIES.has(entry.name)) continue;
|
|
11927
|
-
const absolute =
|
|
12571
|
+
const absolute = path16.join(directory, entry.name);
|
|
11928
12572
|
if (excluded(absolute, exclusions)) continue;
|
|
11929
|
-
const relative = normalizeRelative(
|
|
12573
|
+
const relative = normalizeRelative(path16.relative(cwd, absolute));
|
|
11930
12574
|
if (entry.isDirectory()) visit(absolute);
|
|
11931
12575
|
else paths.push(relative);
|
|
11932
12576
|
if (paths.length > SNAPSHOT_MAX_FILES) {
|
|
@@ -11940,7 +12584,7 @@ var fallbackPaths = (cwd, exclusions) => {
|
|
|
11940
12584
|
var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
|
|
11941
12585
|
const cwd = fs7.realpathSync(cwdInput);
|
|
11942
12586
|
const exclusions = excludedRoots.map((root) => {
|
|
11943
|
-
const absolute =
|
|
12587
|
+
const absolute = path16.resolve(root);
|
|
11944
12588
|
try {
|
|
11945
12589
|
return fs7.realpathSync(absolute);
|
|
11946
12590
|
} catch {
|
|
@@ -11978,18 +12622,18 @@ var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
|
|
|
11978
12622
|
);
|
|
11979
12623
|
};
|
|
11980
12624
|
var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
|
|
11981
|
-
if (!requestedPath.trim() ||
|
|
12625
|
+
if (!requestedPath.trim() || path16.isAbsolute(requestedPath)) {
|
|
11982
12626
|
throw new Error(`Schema paths must be non-empty project-relative paths: ${requestedPath}`);
|
|
11983
12627
|
}
|
|
11984
12628
|
const cwd = fs7.realpathSync(cwdInput);
|
|
11985
|
-
const absolute =
|
|
12629
|
+
const absolute = path16.resolve(cwd, requestedPath);
|
|
11986
12630
|
if (!isInside(cwd, absolute) || absolute === cwd) {
|
|
11987
12631
|
throw new Error(`Schema path escapes the project workspace: ${requestedPath}`);
|
|
11988
12632
|
}
|
|
11989
|
-
const relativeParts =
|
|
12633
|
+
const relativeParts = path16.relative(cwd, absolute).split(path16.sep);
|
|
11990
12634
|
let cursor = cwd;
|
|
11991
12635
|
for (let index = 0; index < relativeParts.length; index++) {
|
|
11992
|
-
cursor =
|
|
12636
|
+
cursor = path16.join(cursor, relativeParts[index]);
|
|
11993
12637
|
let stat2;
|
|
11994
12638
|
try {
|
|
11995
12639
|
stat2 = fs7.lstatSync(cursor);
|
|
@@ -11998,9 +12642,9 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
|
|
|
11998
12642
|
if (index !== relativeParts.length - 1 || !options.allowAbsent) {
|
|
11999
12643
|
throw new Error(`Schema path does not exist: ${requestedPath}`);
|
|
12000
12644
|
}
|
|
12001
|
-
const parentReal = fs7.realpathSync(
|
|
12645
|
+
const parentReal = fs7.realpathSync(path16.dirname(cursor));
|
|
12002
12646
|
if (!isInside(cwd, parentReal)) throw new Error(`Schema path parent escapes the workspace: ${requestedPath}`);
|
|
12003
|
-
return { absolute, relative: normalizeRelative(
|
|
12647
|
+
return { absolute, relative: normalizeRelative(path16.relative(cwd, absolute)), exists: false };
|
|
12004
12648
|
}
|
|
12005
12649
|
throw error;
|
|
12006
12650
|
}
|
|
@@ -12012,7 +12656,7 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
|
|
|
12012
12656
|
throw new Error(`Schema transaction paths must name regular files: ${requestedPath}`);
|
|
12013
12657
|
}
|
|
12014
12658
|
}
|
|
12015
|
-
return { absolute, relative: normalizeRelative(
|
|
12659
|
+
return { absolute, relative: normalizeRelative(path16.relative(cwd, absolute)), exists: true };
|
|
12016
12660
|
};
|
|
12017
12661
|
var sha256File = (absolute) => `sha256:${digest(fs7.readFileSync(absolute))}`;
|
|
12018
12662
|
|
|
@@ -12063,8 +12707,8 @@ var SchemaController = class {
|
|
|
12063
12707
|
this.identity = identity;
|
|
12064
12708
|
this.state = state;
|
|
12065
12709
|
this.cwd = fs8.realpathSync(cwd);
|
|
12066
|
-
this.#journalRoot =
|
|
12067
|
-
this.#lockPath =
|
|
12710
|
+
this.#journalRoot = path17.join(mesh.root, "schema-transactions");
|
|
12711
|
+
this.#lockPath = path17.join(this.#journalRoot, ".commit.lock");
|
|
12068
12712
|
this.#recoverJournals();
|
|
12069
12713
|
}
|
|
12070
12714
|
#activeHypotheses = /* @__PURE__ */ new Map();
|
|
@@ -12263,7 +12907,7 @@ var SchemaController = class {
|
|
|
12263
12907
|
this.#assertPayloadBound(input);
|
|
12264
12908
|
const release = this.#acquireCommitLock();
|
|
12265
12909
|
const transactionId = randomUUID4();
|
|
12266
|
-
const journalPath =
|
|
12910
|
+
const journalPath = path17.join(this.#journalRoot, `${transactionId}.json`);
|
|
12267
12911
|
let journal;
|
|
12268
12912
|
let consumed = false;
|
|
12269
12913
|
let committed = false;
|
|
@@ -12744,7 +13388,7 @@ ${Date.now()}
|
|
|
12744
13388
|
}
|
|
12745
13389
|
for (const name of fs8.readdirSync(this.#journalRoot)) {
|
|
12746
13390
|
if (!name.endsWith(".json")) continue;
|
|
12747
|
-
const filePath =
|
|
13391
|
+
const filePath = path17.join(this.#journalRoot, name);
|
|
12748
13392
|
try {
|
|
12749
13393
|
const journal = JSON.parse(fs8.readFileSync(filePath, "utf8"));
|
|
12750
13394
|
if (journal.format !== 1 || journal.status !== "applying" || !Array.isArray(journal.before)) continue;
|
|
@@ -12864,7 +13508,7 @@ var operationSchema = {
|
|
|
12864
13508
|
}
|
|
12865
13509
|
]
|
|
12866
13510
|
};
|
|
12867
|
-
var
|
|
13511
|
+
var descriptors7 = [
|
|
12868
13512
|
{
|
|
12869
13513
|
name: "status",
|
|
12870
13514
|
description: "Read the fixed session Schema mode, transaction bounds, generation, and invocation hypotheses",
|
|
@@ -12934,7 +13578,7 @@ var descriptors6 = [
|
|
|
12934
13578
|
namespace: "schema"
|
|
12935
13579
|
}
|
|
12936
13580
|
];
|
|
12937
|
-
var normalizeSchemaArgs = actionArgNormalizer(() =>
|
|
13581
|
+
var normalizeSchemaArgs = actionArgNormalizer(() => descriptors7);
|
|
12938
13582
|
var SchemaProvider = class {
|
|
12939
13583
|
constructor(controller) {
|
|
12940
13584
|
this.controller = controller;
|
|
@@ -12943,12 +13587,12 @@ var SchemaProvider = class {
|
|
|
12943
13587
|
description = "Host-owned, opt-in Schema verification and bounded local-file transaction control plane";
|
|
12944
13588
|
async list(request, _context) {
|
|
12945
13589
|
const query = request.query?.toLowerCase();
|
|
12946
|
-
return query ?
|
|
13590
|
+
return query ? descriptors7.filter(
|
|
12947
13591
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
12948
|
-
) :
|
|
13592
|
+
) : descriptors7;
|
|
12949
13593
|
}
|
|
12950
13594
|
async describe(actionName, _context) {
|
|
12951
|
-
return
|
|
13595
|
+
return descriptors7.find((descriptor) => descriptor.name === actionName);
|
|
12952
13596
|
}
|
|
12953
13597
|
prepareArguments(actionName, args) {
|
|
12954
13598
|
return normalizeSchemaArgs(actionName, args);
|
|
@@ -12998,11 +13642,11 @@ var SchemaProvider = class {
|
|
|
12998
13642
|
|
|
12999
13643
|
// src/state/store.ts
|
|
13000
13644
|
import { createHash as createHash5 } from "node:crypto";
|
|
13001
|
-
import
|
|
13645
|
+
import path19 from "node:path";
|
|
13002
13646
|
|
|
13003
13647
|
// src/state/complexity.ts
|
|
13004
13648
|
import fs9 from "node:fs";
|
|
13005
|
-
import
|
|
13649
|
+
import path18 from "node:path";
|
|
13006
13650
|
var isWordStart = (character) => character !== void 0 && (character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character === "_" || character === "$");
|
|
13007
13651
|
var isWordPart = (character) => isWordStart(character) || character !== void 0 && character >= "0" && character <= "9";
|
|
13008
13652
|
var regularExpressionPrefixWords = /* @__PURE__ */ new Set([
|
|
@@ -13234,7 +13878,7 @@ var languageComplexities = [
|
|
|
13234
13878
|
typeScriptJavaScriptComplexity
|
|
13235
13879
|
];
|
|
13236
13880
|
var complexityForFile = (file, languages = languageComplexities) => {
|
|
13237
|
-
const extension =
|
|
13881
|
+
const extension = path18.extname(file).toLowerCase();
|
|
13238
13882
|
return languages.find((language) => language.extensions.includes(extension));
|
|
13239
13883
|
};
|
|
13240
13884
|
var countFileComplexity = (file) => {
|
|
@@ -14125,7 +14769,7 @@ var StateStore = class {
|
|
|
14125
14769
|
const files = [];
|
|
14126
14770
|
let netDelta = 0;
|
|
14127
14771
|
for (const file of this.normalizeComplexityFiles(requestedFiles, input.cwd)) {
|
|
14128
|
-
const measured = countFileComplexity(
|
|
14772
|
+
const measured = countFileComplexity(path19.resolve(input.cwd, file));
|
|
14129
14773
|
if (!measured) {
|
|
14130
14774
|
files.push({ file, supported: false });
|
|
14131
14775
|
continue;
|
|
@@ -14152,7 +14796,7 @@ var StateStore = class {
|
|
|
14152
14796
|
const updates = [];
|
|
14153
14797
|
let netDelta = 0;
|
|
14154
14798
|
for (const file of this.normalizeComplexityFiles(files, cwd)) {
|
|
14155
|
-
const measured = countFileComplexity(
|
|
14799
|
+
const measured = countFileComplexity(path19.resolve(cwd, file));
|
|
14156
14800
|
if (!measured) {
|
|
14157
14801
|
deltas.push({ file, supported: false });
|
|
14158
14802
|
continue;
|
|
@@ -14202,11 +14846,11 @@ var StateStore = class {
|
|
|
14202
14846
|
const normalized = /* @__PURE__ */ new Set();
|
|
14203
14847
|
for (const file of files) {
|
|
14204
14848
|
if (!file.trim()) continue;
|
|
14205
|
-
const relative =
|
|
14206
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
14849
|
+
const relative = path19.relative(cwd, path19.resolve(cwd, file));
|
|
14850
|
+
if (relative === ".." || relative.startsWith(`..${path19.sep}`) || path19.isAbsolute(relative)) {
|
|
14207
14851
|
throw new Error(`State complexity file must be inside the project cwd: ${file}`);
|
|
14208
14852
|
}
|
|
14209
|
-
normalized.add(relative.split(
|
|
14853
|
+
normalized.add(relative.split(path19.sep).join("/"));
|
|
14210
14854
|
}
|
|
14211
14855
|
return [...normalized];
|
|
14212
14856
|
}
|
|
@@ -14648,7 +15292,7 @@ var checkGoalSchema = {
|
|
|
14648
15292
|
additionalProperties: false
|
|
14649
15293
|
};
|
|
14650
15294
|
var emptySchema3 = { type: "object", properties: {}, additionalProperties: false };
|
|
14651
|
-
var
|
|
15295
|
+
var descriptors8 = [
|
|
14652
15296
|
{
|
|
14653
15297
|
name: "transition",
|
|
14654
15298
|
description: "Append a labeled, validated state transition and compare-and-swap advance the head",
|
|
@@ -14699,7 +15343,7 @@ var descriptors7 = [
|
|
|
14699
15343
|
namespace: "state"
|
|
14700
15344
|
}
|
|
14701
15345
|
];
|
|
14702
|
-
var normalizeStateArgs = actionArgNormalizer(() =>
|
|
15346
|
+
var normalizeStateArgs = actionArgNormalizer(() => descriptors8);
|
|
14703
15347
|
var StateProvider = class {
|
|
14704
15348
|
name = "state";
|
|
14705
15349
|
description = "Schema-style labeled transition layer: an append-only timeline of validated transitions with a compare-and-swap head and evidence-based certification over mesh storage";
|
|
@@ -14714,12 +15358,12 @@ var StateProvider = class {
|
|
|
14714
15358
|
}
|
|
14715
15359
|
async list(request, _context) {
|
|
14716
15360
|
const query = request.query?.toLowerCase();
|
|
14717
|
-
return query ?
|
|
15361
|
+
return query ? descriptors8.filter(
|
|
14718
15362
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
14719
|
-
) :
|
|
15363
|
+
) : descriptors8;
|
|
14720
15364
|
}
|
|
14721
15365
|
async describe(actionName, _context) {
|
|
14722
|
-
return
|
|
15366
|
+
return descriptors8.find((descriptor) => descriptor.name === actionName);
|
|
14723
15367
|
}
|
|
14724
15368
|
prepareArguments(actionName, args) {
|
|
14725
15369
|
return normalizeStateArgs(actionName, args);
|
|
@@ -15227,7 +15871,7 @@ var FabricRuntimeState = class {
|
|
|
15227
15871
|
const projectRoot = process.env.OMP_FABRIC_PROJECT_ROOT ?? context.cwd;
|
|
15228
15872
|
await ensureFabricStateExclude(projectRoot).catch(() => void 0);
|
|
15229
15873
|
const configuredMeshRoot = this.#config.mesh.root;
|
|
15230
|
-
const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ?
|
|
15874
|
+
const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path20.resolve(projectRoot, configuredMeshRoot) : path20.join(projectRoot, ".omp", "fabric", "mesh"));
|
|
15231
15875
|
this.#mesh = new MeshStore(
|
|
15232
15876
|
meshRoot,
|
|
15233
15877
|
this.#config.mesh.maxEventBytes,
|
|
@@ -15323,6 +15967,19 @@ var FabricRuntimeState = class {
|
|
|
15323
15967
|
'disabled by configuration (judgment.enabled=false); set "judgment": { "enabled": true } in .omp/fabric.json or the agent fabric.json to enable judgment.* actions'
|
|
15324
15968
|
);
|
|
15325
15969
|
}
|
|
15970
|
+
if (this.#config.image.enabled) {
|
|
15971
|
+
const imageConfig = () => this.#config?.image ?? DEFAULT_FABRIC_CONFIG.image;
|
|
15972
|
+
await installBuiltin(createProviderComponent({
|
|
15973
|
+
provider: "image",
|
|
15974
|
+
description: "Image generation and editing across a configured priority chain",
|
|
15975
|
+
create: () => new ImageProvider(imageConfig)
|
|
15976
|
+
}));
|
|
15977
|
+
} else {
|
|
15978
|
+
this.#registry.markUnavailable(
|
|
15979
|
+
"image",
|
|
15980
|
+
'disabled by configuration (image.enabled=false); set "image": { "enabled": true } in .omp/fabric.json or the agent fabric.json to enable image.* actions'
|
|
15981
|
+
);
|
|
15982
|
+
}
|
|
15326
15983
|
const agentConfig = enforceSchema ? { ...this.#config.agents, enabled: false } : this.#config.agents;
|
|
15327
15984
|
const modelsConfig = this.#config.models;
|
|
15328
15985
|
const visibleOmpModels = () => {
|
|
@@ -15421,8 +16078,8 @@ var FabricRuntimeState = class {
|
|
|
15421
16078
|
};
|
|
15422
16079
|
const lineageAlive = (rootId) => this.#participants?.get(rootId) !== void 0;
|
|
15423
16080
|
const actorRoots = {
|
|
15424
|
-
project:
|
|
15425
|
-
session:
|
|
16081
|
+
project: path20.join(meshRoot, "actors"),
|
|
16082
|
+
session: path20.join(meshRoot, "actors", fabricSessionId)
|
|
15426
16083
|
};
|
|
15427
16084
|
const acquireActorCapabilityView = (requirements, signal) => this.#registry.acquireCapabilityView(requirements, {
|
|
15428
16085
|
cwd: context.cwd,
|
|
@@ -15626,6 +16283,7 @@ ${escapeXmlText(text)}
|
|
|
15626
16283
|
"compact",
|
|
15627
16284
|
...this.#config.codemap.enabled ? ["codemap"] : [],
|
|
15628
16285
|
...this.#config.judgment.enabled ? ["judgment"] : [],
|
|
16286
|
+
...this.#config.image.enabled ? ["image"] : [],
|
|
15629
16287
|
"agents",
|
|
15630
16288
|
...this.#config.memory.enabled ? ["memory"] : []
|
|
15631
16289
|
]);
|