omp-fabric 1.25.35 → 1.26.1
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 +23 -1
- package/README.md +1 -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-2C5YN36Y.js → chunk-GFUWAUL2.js} +15 -1
- package/dist/chunks/chunk-GFUWAUL2.js.map +7 -0
- package/dist/chunks/{chunk-JWC7B67Z.js → chunk-GGQ5MHXB.js} +62 -1
- package/dist/chunks/chunk-GGQ5MHXB.js.map +7 -0
- package/dist/chunks/{chunk-I2GBVR67.js → chunk-YHFQDI36.js} +3 -3
- package/dist/chunks/{chunk-53ZZTYHQ.js → chunk-YI4HU67V.js} +2 -2
- package/dist/config.d.ts +11 -0
- package/dist/config.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 +804 -136
- package/dist/fabric-runtime-state.js.map +4 -4
- package/dist/index.js +3 -3
- package/dist/index.js.map +2 -2
- package/dist/providers/image-provider.d.ts +46 -0
- package/dist/providers/image-provider.d.ts.map +1 -0
- package/dist/residency/host.js +3 -3
- package/dist/residency/omp-entry.js +3 -3
- 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 +1 -1
- package/dist/chunks/chunk-2C5YN36Y.js.map +0 -7
- package/dist/chunks/chunk-JWC7B67Z.js.map +0 -7
- /package/dist/chunks/{chunk-I2GBVR67.js.map → chunk-YHFQDI36.js.map} +0 -0
- /package/dist/chunks/{chunk-53ZZTYHQ.js.map → chunk-YI4HU67V.js.map} +0 -0
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
resolveAgentCwd,
|
|
98
98
|
resolveOmpBinary,
|
|
99
99
|
validateAgentCwdRequest
|
|
100
|
-
} from "./chunks/chunk-
|
|
100
|
+
} from "./chunks/chunk-YI4HU67V.js";
|
|
101
101
|
import "./chunks/chunk-VPPIJRNZ.js";
|
|
102
102
|
import {
|
|
103
103
|
executeFile,
|
|
@@ -117,7 +117,7 @@ import {
|
|
|
117
117
|
resolveAgentDir,
|
|
118
118
|
resolveAvailableOmpModel,
|
|
119
119
|
resolveFabricModel
|
|
120
|
-
} from "./chunks/chunk-
|
|
120
|
+
} from "./chunks/chunk-GGQ5MHXB.js";
|
|
121
121
|
import {
|
|
122
122
|
FABRIC_ACTOR_HOST_EVENTS,
|
|
123
123
|
isFabricActorHostEvent,
|
|
@@ -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,657 @@ 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: "write"
|
|
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: "write"
|
|
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 injected = this.options.registry;
|
|
8934
|
+
if (injected) return injected;
|
|
8935
|
+
const registry = context.extensionContext.modelRegistry;
|
|
8936
|
+
if (!registry) throw new Error("image provider needs a model registry on the extension context");
|
|
8937
|
+
return registry;
|
|
8938
|
+
}
|
|
8939
|
+
sessionId(context) {
|
|
8940
|
+
const injected = this.options.getSessionId;
|
|
8941
|
+
if (injected) return injected();
|
|
8942
|
+
return context.extensionContext?.sessionManager?.getSessionId?.() ?? void 0;
|
|
8943
|
+
}
|
|
8944
|
+
resolveModel(registry, selector) {
|
|
8945
|
+
const parsed = splitModelSelector(selector);
|
|
8946
|
+
if (!parsed) return void 0;
|
|
8947
|
+
const found = registry.find(parsed.provider, parsed.id);
|
|
8948
|
+
if (!isRecord3(found)) return void 0;
|
|
8949
|
+
const api = typeof found.api === "string" ? found.api : "";
|
|
8950
|
+
const baseUrl = typeof found.baseUrl === "string" ? found.baseUrl : "";
|
|
8951
|
+
if (api.length === 0 || baseUrl.length === 0) return void 0;
|
|
8952
|
+
return {
|
|
8953
|
+
provider: parsed.provider,
|
|
8954
|
+
id: parsed.id,
|
|
8955
|
+
api,
|
|
8956
|
+
baseUrl,
|
|
8957
|
+
gptImage: GPT_IMAGE_FAMILY.test(parsed.id),
|
|
8958
|
+
codex: api === "openai-codex-responses",
|
|
8959
|
+
xai: parsed.provider === "xai" || parsed.provider === "xai-oauth" || parsed.provider.startsWith("xai-")
|
|
8960
|
+
};
|
|
8961
|
+
}
|
|
8962
|
+
dialectFor(model) {
|
|
8963
|
+
const override = this.config().dialects[`${model.provider}/${model.id}`];
|
|
8964
|
+
return override ?? inferImageDialect(model.api, model.id);
|
|
8965
|
+
}
|
|
8966
|
+
chainSelectors(args) {
|
|
8967
|
+
const preferred = typeof args.model === "string" ? args.model.trim() : "";
|
|
8968
|
+
const configured = this.config().models;
|
|
8969
|
+
const selectors = preferred.length > 0 ? [preferred, ...configured] : [...configured];
|
|
8970
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8971
|
+
return selectors.filter((selector) => {
|
|
8972
|
+
if (seen.has(selector)) return false;
|
|
8973
|
+
seen.add(selector);
|
|
8974
|
+
return true;
|
|
8975
|
+
});
|
|
8976
|
+
}
|
|
8977
|
+
async chain(context) {
|
|
8978
|
+
const registry = this.registry(context);
|
|
8979
|
+
const sessionId = this.sessionId(context);
|
|
8980
|
+
const entries = [];
|
|
8981
|
+
for (const selector of this.config().models) {
|
|
8982
|
+
const model = this.resolveModel(registry, selector);
|
|
8983
|
+
if (!model) {
|
|
8984
|
+
entries.push({ selector, resolved: false, reason: "no matching model in the registry" });
|
|
8985
|
+
continue;
|
|
8986
|
+
}
|
|
8987
|
+
let credentials = false;
|
|
8988
|
+
try {
|
|
8989
|
+
const apiKey = await registry.getApiKey(model, sessionId);
|
|
8990
|
+
credentials = typeof apiKey === "string" && apiKey.length > 0;
|
|
8991
|
+
} catch {
|
|
8992
|
+
credentials = false;
|
|
8993
|
+
}
|
|
8994
|
+
entries.push({
|
|
8995
|
+
selector,
|
|
8996
|
+
resolved: true,
|
|
8997
|
+
provider: model.provider,
|
|
8998
|
+
id: model.id,
|
|
8999
|
+
api: model.api,
|
|
9000
|
+
baseUrl: model.baseUrl,
|
|
9001
|
+
dialect: this.dialectFor(model),
|
|
9002
|
+
credentials
|
|
9003
|
+
});
|
|
9004
|
+
}
|
|
9005
|
+
return {
|
|
9006
|
+
enabled: this.config().enabled,
|
|
9007
|
+
timeoutMs: this.config().timeoutMs,
|
|
9008
|
+
retries: this.config().retries,
|
|
9009
|
+
outputDir: this.config().outputDir || os.tmpdir(),
|
|
9010
|
+
models: entries
|
|
9011
|
+
};
|
|
9012
|
+
}
|
|
9013
|
+
async run(action, args, context) {
|
|
9014
|
+
const config = this.config();
|
|
9015
|
+
if (!config.enabled) {
|
|
9016
|
+
return { ok: false, reason: "image provider is disabled (image.enabled=false)" };
|
|
9017
|
+
}
|
|
9018
|
+
const prompt = typeof args.prompt === "string" ? args.prompt.trim() : "";
|
|
9019
|
+
if (prompt.length === 0) return { ok: false, reason: "prompt must be a non-empty string" };
|
|
9020
|
+
const selectors = this.chainSelectors(args);
|
|
9021
|
+
if (selectors.length === 0) {
|
|
9022
|
+
return { ok: false, reason: "no image models configured (image.models is empty)" };
|
|
9023
|
+
}
|
|
9024
|
+
const count = typeof args.count === "number" && Number.isFinite(args.count) && args.count > 0 ? Math.min(Math.floor(args.count), 4) : 1;
|
|
9025
|
+
const aspectRatio = typeof args.aspectRatio === "string" ? args.aspectRatio : void 0;
|
|
9026
|
+
const size = typeof args.size === "string" ? args.size : void 0;
|
|
9027
|
+
const saveTo = typeof args.saveTo === "string" && args.saveTo.trim().length > 0 ? args.saveTo.trim() : void 0;
|
|
9028
|
+
const sources = action === "edit" ? Array.isArray(args.images) ? args.images.filter((entry) => typeof entry === "string") : [] : [];
|
|
9029
|
+
if (action === "edit" && sources.length === 0) {
|
|
9030
|
+
return { ok: false, reason: "edit needs at least one image path or data URL" };
|
|
9031
|
+
}
|
|
9032
|
+
let inputImages = [];
|
|
9033
|
+
try {
|
|
9034
|
+
inputImages = await Promise.all(sources.map((source) => readSourceImage(source, context.cwd)));
|
|
9035
|
+
} catch (error) {
|
|
9036
|
+
return { ok: false, reason: describeError(error) };
|
|
9037
|
+
}
|
|
9038
|
+
const registry = this.registry(context);
|
|
9039
|
+
const sessionId = this.sessionId(context);
|
|
9040
|
+
const fetchImpl = this.options.fetchImpl ?? fetch;
|
|
9041
|
+
const now = this.options.now ?? Date.now;
|
|
9042
|
+
const started = now();
|
|
9043
|
+
const failures = [];
|
|
9044
|
+
const attemptsPerModel = Math.max(1, Math.min(config.retries + 1, 5));
|
|
9045
|
+
for (const selector of selectors) {
|
|
9046
|
+
const model = this.resolveModel(registry, selector);
|
|
9047
|
+
if (!model) {
|
|
9048
|
+
failures.push({ model: selector, dialect: "images", error: "no matching model in the registry" });
|
|
9049
|
+
continue;
|
|
9050
|
+
}
|
|
9051
|
+
const dialect = this.dialectFor(model);
|
|
9052
|
+
let apiKey;
|
|
9053
|
+
let extraHeaders = {};
|
|
9054
|
+
try {
|
|
9055
|
+
apiKey = await registry.getApiKey(model, sessionId);
|
|
9056
|
+
extraHeaders = await registry.resolveModelHeaders?.(model, context.signal) ?? {};
|
|
9057
|
+
} catch (error) {
|
|
9058
|
+
failures.push({ model: selector, dialect, error: `credential lookup failed: ${describeError(error)}` });
|
|
9059
|
+
continue;
|
|
9060
|
+
}
|
|
9061
|
+
if (typeof apiKey !== "string" || apiKey.length === 0) {
|
|
9062
|
+
failures.push({ model: selector, dialect, error: "no credential for this model" });
|
|
9063
|
+
continue;
|
|
9064
|
+
}
|
|
9065
|
+
const authHeaders = model.api === "google-generative-ai" ? geminiHeaders(apiKey) : { Authorization: `Bearer ${apiKey}` };
|
|
9066
|
+
for (let attempt = 1; attempt <= attemptsPerModel; attempt += 1) {
|
|
9067
|
+
context.signal?.throwIfAborted();
|
|
9068
|
+
const signals = [AbortSignal.timeout(config.timeoutMs)];
|
|
9069
|
+
if (context.signal) signals.push(context.signal);
|
|
9070
|
+
const env = {
|
|
9071
|
+
baseUrl: model.baseUrl,
|
|
9072
|
+
apiKey,
|
|
9073
|
+
headers: { ...authHeaders, ...extraHeaders },
|
|
9074
|
+
signal: AbortSignal.any(signals),
|
|
9075
|
+
fetchImpl
|
|
9076
|
+
};
|
|
9077
|
+
try {
|
|
9078
|
+
const images = await callDialect(dialect, env, model, {
|
|
9079
|
+
prompt,
|
|
9080
|
+
aspectRatio,
|
|
9081
|
+
size,
|
|
9082
|
+
count,
|
|
9083
|
+
inputImages,
|
|
9084
|
+
signal: env.signal
|
|
9085
|
+
});
|
|
9086
|
+
if (images.length === 0) throw new Error("backend returned no image data");
|
|
9087
|
+
let written;
|
|
9088
|
+
try {
|
|
9089
|
+
written = await this.write(images, saveTo, context.cwd);
|
|
9090
|
+
} catch (error) {
|
|
9091
|
+
return {
|
|
9092
|
+
ok: false,
|
|
9093
|
+
reason: `${model.provider}/${model.id} returned ${images.length} image(s) but the write failed: ${describeError(error)}`,
|
|
9094
|
+
model: `${model.provider}/${model.id}`,
|
|
9095
|
+
dialect,
|
|
9096
|
+
failures,
|
|
9097
|
+
elapsedMs: Math.max(0, now() - started)
|
|
9098
|
+
};
|
|
9099
|
+
}
|
|
9100
|
+
context.attachMedia?.(
|
|
9101
|
+
written.map((entry) => ({ type: "image", data: entry.data, mimeType: entry.mimeType })),
|
|
9102
|
+
`Generated ${written.length} image(s) with ${model.provider}/${model.id} (${dialect}):
|
|
9103
|
+
${written.map((entry) => ` ${entry.path} (${entry.bytes} bytes)`).join("\n")}`
|
|
9104
|
+
);
|
|
9105
|
+
return {
|
|
9106
|
+
ok: true,
|
|
9107
|
+
model: `${model.provider}/${model.id}`,
|
|
9108
|
+
dialect,
|
|
9109
|
+
images: written.map((entry) => ({ path: entry.path, bytes: entry.bytes, mimeType: entry.mimeType })),
|
|
9110
|
+
attempts: attempt,
|
|
9111
|
+
elapsedMs: Math.max(0, now() - started),
|
|
9112
|
+
failures
|
|
9113
|
+
};
|
|
9114
|
+
} catch (error) {
|
|
9115
|
+
const status = error?.status;
|
|
9116
|
+
failures.push({
|
|
9117
|
+
model: `${model.provider}/${model.id}`,
|
|
9118
|
+
dialect,
|
|
9119
|
+
error: describeError(error),
|
|
9120
|
+
...typeof status === "number" ? { status } : {}
|
|
9121
|
+
});
|
|
9122
|
+
if (context.signal?.aborted) throw error;
|
|
9123
|
+
if (attempt < attemptsPerModel && transient(error)) continue;
|
|
9124
|
+
break;
|
|
9125
|
+
}
|
|
9126
|
+
}
|
|
9127
|
+
}
|
|
9128
|
+
return {
|
|
9129
|
+
ok: false,
|
|
9130
|
+
reason: `every configured image model failed (${failures.length} attempt${failures.length === 1 ? "" : "s"})`,
|
|
9131
|
+
failures,
|
|
9132
|
+
elapsedMs: Math.max(0, now() - started)
|
|
9133
|
+
};
|
|
9134
|
+
}
|
|
9135
|
+
async write(images, saveTo, cwd) {
|
|
9136
|
+
const configured = this.config().outputDir;
|
|
9137
|
+
const directory = configured.length > 0 ? path10.isAbsolute(configured) ? configured : path10.resolve(cwd, configured) : os.tmpdir();
|
|
9138
|
+
await mkdir(directory, { recursive: true, mode: 448 });
|
|
9139
|
+
const written = [];
|
|
9140
|
+
for (const [index, image] of images.entries()) {
|
|
9141
|
+
const extension = extensionForMime(image.mimeType);
|
|
9142
|
+
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}`);
|
|
9143
|
+
await mkdir(path10.dirname(target), { recursive: true, mode: 448 });
|
|
9144
|
+
const bytes = Buffer.from(image.data, "base64");
|
|
9145
|
+
await writeFile(target, bytes, { mode: 384 });
|
|
9146
|
+
written.push({ path: target, bytes: bytes.length, mimeType: image.mimeType, data: image.data });
|
|
9147
|
+
}
|
|
9148
|
+
return written;
|
|
9149
|
+
}
|
|
9150
|
+
};
|
|
9151
|
+
|
|
8501
9152
|
// src/providers/judgment-provider.ts
|
|
8502
9153
|
import { Type as Type2 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
|
|
8503
9154
|
import { validateJsonSchemaValue as validateJsonSchemaValue2 } from "@oh-my-pi/pi-ai/utils/schema";
|
|
@@ -8510,7 +9161,7 @@ var askSchema = Type2.Object({
|
|
|
8510
9161
|
})
|
|
8511
9162
|
}, { additionalProperties: false });
|
|
8512
9163
|
var statsSchema = Type2.Object({}, { additionalProperties: false });
|
|
8513
|
-
var
|
|
9164
|
+
var descriptors3 = [
|
|
8514
9165
|
{
|
|
8515
9166
|
name: "ask",
|
|
8516
9167
|
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 +9175,8 @@ var descriptors2 = [
|
|
|
8524
9175
|
risk: "read"
|
|
8525
9176
|
}
|
|
8526
9177
|
];
|
|
8527
|
-
var normalizeJudgmentArgs = actionArgNormalizer(() =>
|
|
8528
|
-
var
|
|
9178
|
+
var normalizeJudgmentArgs = actionArgNormalizer(() => descriptors3);
|
|
9179
|
+
var isRecord4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
8529
9180
|
var instructionsOf = (id, value) => {
|
|
8530
9181
|
if (typeof value !== "string" || value.length === 0) {
|
|
8531
9182
|
throw new Error(`judgment.ask question "${id}" needs non-empty string instructions`);
|
|
@@ -8534,7 +9185,7 @@ var instructionsOf = (id, value) => {
|
|
|
8534
9185
|
};
|
|
8535
9186
|
var parseChoice = (id, value) => {
|
|
8536
9187
|
const instructions = instructionsOf(id, value.instructions);
|
|
8537
|
-
if (!
|
|
9188
|
+
if (!isRecord4(value.criteria)) {
|
|
8538
9189
|
throw new Error(`judgment.ask choice question "${id}" needs criteria: { label: rubric | null }`);
|
|
8539
9190
|
}
|
|
8540
9191
|
const criteria = {};
|
|
@@ -8553,7 +9204,7 @@ var parseChoice = (id, value) => {
|
|
|
8553
9204
|
var parseBool = (id, value) => {
|
|
8554
9205
|
const instructions = instructionsOf(id, value.instructions);
|
|
8555
9206
|
if (value.criteria === void 0) return { type: "noul", instructions };
|
|
8556
|
-
if (!
|
|
9207
|
+
if (!isRecord4(value.criteria)) {
|
|
8557
9208
|
throw new Error(`judgment.ask bool question "${id}" criteria must be { true?: string, false?: string }`);
|
|
8558
9209
|
}
|
|
8559
9210
|
const criteria = {};
|
|
@@ -8580,7 +9231,7 @@ var parseScore = (id, value) => {
|
|
|
8580
9231
|
return { type: "score", instructions, criteria: [lowest, second, ...rest] };
|
|
8581
9232
|
};
|
|
8582
9233
|
var parseQuestion = (id, value) => {
|
|
8583
|
-
if (!
|
|
9234
|
+
if (!isRecord4(value)) throw new Error(`judgment.ask question "${id}" must be an object`);
|
|
8584
9235
|
switch (value.type) {
|
|
8585
9236
|
case "choice":
|
|
8586
9237
|
return parseChoice(id, value);
|
|
@@ -8597,7 +9248,7 @@ var parseState = (value) => {
|
|
|
8597
9248
|
if (value.length === 0) throw new Error("judgment.ask state must not be empty");
|
|
8598
9249
|
return value;
|
|
8599
9250
|
}
|
|
8600
|
-
if (Array.isArray(value) ||
|
|
9251
|
+
if (Array.isArray(value) || isRecord4(value)) return value;
|
|
8601
9252
|
throw new Error("judgment.ask state must be a string, a JSON object, or a JSON array");
|
|
8602
9253
|
};
|
|
8603
9254
|
var checked2 = (action, schema, args) => {
|
|
@@ -8616,12 +9267,12 @@ var JudgmentProvider = class {
|
|
|
8616
9267
|
description = "Typed judgments over one state: calibrated choice, bool, and score answers batched into one backend request";
|
|
8617
9268
|
async list(request, _context) {
|
|
8618
9269
|
const query = request.query?.toLowerCase();
|
|
8619
|
-
return query ?
|
|
9270
|
+
return query ? descriptors3.filter(
|
|
8620
9271
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
8621
|
-
) :
|
|
9272
|
+
) : descriptors3;
|
|
8622
9273
|
}
|
|
8623
9274
|
async describe(actionName, _context) {
|
|
8624
|
-
return
|
|
9275
|
+
return descriptors3.find((descriptor) => descriptor.name === actionName);
|
|
8625
9276
|
}
|
|
8626
9277
|
prepareArguments(actionName, args) {
|
|
8627
9278
|
return normalizeJudgmentArgs(actionName, args);
|
|
@@ -8933,7 +9584,7 @@ var emptySchema = {
|
|
|
8933
9584
|
properties: {},
|
|
8934
9585
|
additionalProperties: false
|
|
8935
9586
|
};
|
|
8936
|
-
var
|
|
9587
|
+
var descriptors4 = [
|
|
8937
9588
|
{
|
|
8938
9589
|
name: "request",
|
|
8939
9590
|
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 +9607,7 @@ var descriptors3 = [
|
|
|
8956
9607
|
risk: "write"
|
|
8957
9608
|
}
|
|
8958
9609
|
];
|
|
8959
|
-
var normalizeCompactArgs = actionArgNormalizer(() =>
|
|
9610
|
+
var normalizeCompactArgs = actionArgNormalizer(() => descriptors4);
|
|
8960
9611
|
var CompactProvider = class {
|
|
8961
9612
|
constructor(controller) {
|
|
8962
9613
|
this.controller = controller;
|
|
@@ -8965,12 +9616,12 @@ var CompactProvider = class {
|
|
|
8965
9616
|
description = "Programmatic, advisory-then-committed context compaction for the host OMP session";
|
|
8966
9617
|
async list(request, _context) {
|
|
8967
9618
|
const query = request.query?.toLowerCase();
|
|
8968
|
-
return query ?
|
|
9619
|
+
return query ? descriptors4.filter(
|
|
8969
9620
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
8970
|
-
) :
|
|
9621
|
+
) : descriptors4;
|
|
8971
9622
|
}
|
|
8972
9623
|
async describe(actionName, _context) {
|
|
8973
|
-
return
|
|
9624
|
+
return descriptors4.find((descriptor) => descriptor.name === actionName);
|
|
8974
9625
|
}
|
|
8975
9626
|
prepareArguments(actionName, args) {
|
|
8976
9627
|
return normalizeCompactArgs(actionName, args);
|
|
@@ -9010,7 +9661,7 @@ var CompactProvider = class {
|
|
|
9010
9661
|
};
|
|
9011
9662
|
|
|
9012
9663
|
// src/providers/components-provider.ts
|
|
9013
|
-
var
|
|
9664
|
+
var descriptors5 = [
|
|
9014
9665
|
{
|
|
9015
9666
|
name: "list",
|
|
9016
9667
|
description: "List registered component definitions and configured component instances.",
|
|
@@ -9057,13 +9708,13 @@ var ComponentsProvider = class {
|
|
|
9057
9708
|
description = "Supervised component lifecycle, exact capability dependencies, effect cleanup, and reload diagnostics.";
|
|
9058
9709
|
async list(request, _context) {
|
|
9059
9710
|
const query = request.query?.normalize("NFKC").trim().toLowerCase();
|
|
9060
|
-
const filtered = query ?
|
|
9711
|
+
const filtered = query ? descriptors5.filter(
|
|
9061
9712
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
9062
|
-
) :
|
|
9713
|
+
) : descriptors5;
|
|
9063
9714
|
return filtered.slice(0, Math.max(1, Math.min(request.limit ?? 100, 100)));
|
|
9064
9715
|
}
|
|
9065
9716
|
async describe(actionName, _context) {
|
|
9066
|
-
return
|
|
9717
|
+
return descriptors5.find((descriptor) => descriptor.name === actionName);
|
|
9067
9718
|
}
|
|
9068
9719
|
async invoke(actionName, args, _context) {
|
|
9069
9720
|
switch (actionName) {
|
|
@@ -9097,37 +9748,37 @@ var ComponentsProvider = class {
|
|
|
9097
9748
|
// src/providers/mcp-descriptor-cache.ts
|
|
9098
9749
|
import fs5 from "node:fs/promises";
|
|
9099
9750
|
import fsSync from "node:fs";
|
|
9100
|
-
import
|
|
9101
|
-
import
|
|
9751
|
+
import os2 from "node:os";
|
|
9752
|
+
import path11 from "node:path";
|
|
9102
9753
|
var MCP_DESCRIPTOR_CACHE_VERSION = 1;
|
|
9103
9754
|
var homeDir = () => {
|
|
9104
9755
|
const home = process.env.HOME;
|
|
9105
|
-
return home && home.trim().length > 0 ? home :
|
|
9756
|
+
return home && home.trim().length > 0 ? home : os2.homedir();
|
|
9106
9757
|
};
|
|
9107
9758
|
var expandHome = (input) => {
|
|
9108
9759
|
if (!input.startsWith("~")) return input;
|
|
9109
9760
|
const home = homeDir();
|
|
9110
9761
|
if (input === "~") return home;
|
|
9111
9762
|
if (input.startsWith("~/") || input.startsWith("~\\")) {
|
|
9112
|
-
return
|
|
9763
|
+
return path11.join(home, input.slice(2));
|
|
9113
9764
|
}
|
|
9114
9765
|
return input;
|
|
9115
9766
|
};
|
|
9116
|
-
var legacyMcporterDir = () =>
|
|
9767
|
+
var legacyMcporterDir = () => path11.join(homeDir(), ".mcporter");
|
|
9117
9768
|
var mcporterConfigDir = () => {
|
|
9118
9769
|
const raw = process.env.XDG_CONFIG_HOME;
|
|
9119
9770
|
if (raw && raw.trim().length > 0) {
|
|
9120
9771
|
const resolved = expandHome(raw.trim());
|
|
9121
|
-
if (
|
|
9772
|
+
if (path11.isAbsolute(resolved)) return path11.join(resolved, "mcporter");
|
|
9122
9773
|
}
|
|
9123
9774
|
return legacyMcporterDir();
|
|
9124
9775
|
};
|
|
9125
9776
|
var mcporterConfigCandidates = () => {
|
|
9126
9777
|
const base = mcporterConfigDir();
|
|
9127
|
-
const candidates = [
|
|
9778
|
+
const candidates = [path11.join(base, "mcporter.json"), path11.join(base, "mcporter.jsonc")];
|
|
9128
9779
|
const legacy = legacyMcporterDir();
|
|
9129
9780
|
if (base !== legacy) {
|
|
9130
|
-
candidates.push(
|
|
9781
|
+
candidates.push(path11.join(legacy, "mcporter.json"), path11.join(legacy, "mcporter.jsonc"));
|
|
9131
9782
|
}
|
|
9132
9783
|
return candidates;
|
|
9133
9784
|
};
|
|
@@ -9142,12 +9793,12 @@ var pathExists = (filePath) => {
|
|
|
9142
9793
|
var mcpConfigLayerPaths = (rootDir, configPath) => {
|
|
9143
9794
|
const explicitRaw = configPath ?? process.env.MCPORTER_CONFIG;
|
|
9144
9795
|
if (explicitRaw && explicitRaw.trim().length > 0) {
|
|
9145
|
-
return [
|
|
9796
|
+
return [path11.resolve(expandHome(explicitRaw.trim()))];
|
|
9146
9797
|
}
|
|
9147
9798
|
const paths = [];
|
|
9148
9799
|
const home = mcporterConfigCandidates().find(pathExists);
|
|
9149
9800
|
if (home) paths.push(home);
|
|
9150
|
-
const projectPath =
|
|
9801
|
+
const projectPath = path11.resolve(rootDir, "config", "mcporter.json");
|
|
9151
9802
|
if (pathExists(projectPath)) paths.push(projectPath);
|
|
9152
9803
|
return paths;
|
|
9153
9804
|
};
|
|
@@ -9169,11 +9820,11 @@ var sameConfigLayers = (left, right) => left.length === right.length && left.eve
|
|
|
9169
9820
|
return other !== void 0 && layer.path === other.path && layer.size === other.size && Math.abs(layer.mtimeMs - other.mtimeMs) <= 1;
|
|
9170
9821
|
});
|
|
9171
9822
|
var hashServerDefinition = (definition) => stableJsonHash(definition);
|
|
9172
|
-
var
|
|
9823
|
+
var isRecord5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9173
9824
|
var parseCachedServer = (value) => {
|
|
9174
|
-
if (!
|
|
9825
|
+
if (!isRecord5(value)) return void 0;
|
|
9175
9826
|
const tools = Array.isArray(value.tools) ? value.tools.filter(
|
|
9176
|
-
(tool) =>
|
|
9827
|
+
(tool) => isRecord5(tool) && typeof tool.name === "string"
|
|
9177
9828
|
) : void 0;
|
|
9178
9829
|
if (typeof value.definitionHash !== "string" || tools === void 0) return void 0;
|
|
9179
9830
|
return {
|
|
@@ -9186,10 +9837,10 @@ var parseCachedServer = (value) => {
|
|
|
9186
9837
|
};
|
|
9187
9838
|
};
|
|
9188
9839
|
var parseCacheFile = (value) => {
|
|
9189
|
-
if (!
|
|
9190
|
-
if (!Array.isArray(value.layers) || !
|
|
9840
|
+
if (!isRecord5(value) || value.version !== MCP_DESCRIPTOR_CACHE_VERSION) return void 0;
|
|
9841
|
+
if (!Array.isArray(value.layers) || !isRecord5(value.servers)) return void 0;
|
|
9191
9842
|
const layers = value.layers.filter(
|
|
9192
|
-
(layer) =>
|
|
9843
|
+
(layer) => isRecord5(layer) && typeof layer.path === "string" && typeof layer.mtimeMs === "number" && typeof layer.size === "number"
|
|
9193
9844
|
);
|
|
9194
9845
|
return {
|
|
9195
9846
|
version: MCP_DESCRIPTOR_CACHE_VERSION,
|
|
@@ -9198,8 +9849,8 @@ var parseCacheFile = (value) => {
|
|
|
9198
9849
|
servers: value.servers
|
|
9199
9850
|
};
|
|
9200
9851
|
};
|
|
9201
|
-
var projectMcpCachePath = (projectRoot) =>
|
|
9202
|
-
var globalMcpCachePath = (agentDir) =>
|
|
9852
|
+
var projectMcpCachePath = (projectRoot) => path11.join(projectRoot, ".omp", "fabric", "mcp-cache.json");
|
|
9853
|
+
var globalMcpCachePath = (agentDir) => path11.join(agentDir, "fabric", "mcp-descriptors.json");
|
|
9203
9854
|
var tempCounter = 0;
|
|
9204
9855
|
var McpDescriptorCacheStore = class {
|
|
9205
9856
|
constructor(filePath) {
|
|
@@ -9216,9 +9867,9 @@ var McpDescriptorCacheStore = class {
|
|
|
9216
9867
|
// Atomic-ish write: temp file then rename, so a concurrent reader either
|
|
9217
9868
|
// sees the previous cache or the next one, never a torn document.
|
|
9218
9869
|
async save(file) {
|
|
9219
|
-
const directory =
|
|
9870
|
+
const directory = path11.dirname(this.filePath);
|
|
9220
9871
|
await fs5.mkdir(directory, { recursive: true });
|
|
9221
|
-
const tempPath =
|
|
9872
|
+
const tempPath = path11.join(
|
|
9222
9873
|
directory,
|
|
9223
9874
|
`.mcp-cache-${process.pid}-${Date.now()}-${tempCounter++}.tmp`
|
|
9224
9875
|
);
|
|
@@ -9233,7 +9884,7 @@ var McpDescriptorCacheStore = class {
|
|
|
9233
9884
|
};
|
|
9234
9885
|
|
|
9235
9886
|
// src/providers/mcp-provider.ts
|
|
9236
|
-
import
|
|
9887
|
+
import path12 from "node:path";
|
|
9237
9888
|
var TOOL_METADATA_TTL_MS = 6e4;
|
|
9238
9889
|
var REVALIDATE_CONCURRENCY = 3;
|
|
9239
9890
|
var REVALIDATE_SERVER_TIMEOUT_MS = 2e4;
|
|
@@ -9394,9 +10045,9 @@ var McpProvider = class {
|
|
|
9394
10045
|
this.#kickRevalidation();
|
|
9395
10046
|
if (!request.namespace) await this.#awaitColdEnumeration(context.signal);
|
|
9396
10047
|
const query = request.query?.toLowerCase();
|
|
9397
|
-
const filterQuery = (
|
|
10048
|
+
const filterQuery = (descriptors9) => query ? descriptors9.filter(
|
|
9398
10049
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
9399
|
-
) :
|
|
10050
|
+
) : descriptors9;
|
|
9400
10051
|
if (request.namespace) {
|
|
9401
10052
|
const server = await this.#resolveKnownServer(request.namespace);
|
|
9402
10053
|
if (!server) return [];
|
|
@@ -9551,11 +10202,11 @@ var McpProvider = class {
|
|
|
9551
10202
|
// Provider-fidelity descriptors for everything currently known, cached or
|
|
9552
10203
|
// ephemeral.
|
|
9553
10204
|
sliceDescriptors() {
|
|
9554
|
-
const
|
|
10205
|
+
const descriptors9 = [];
|
|
9555
10206
|
for (const [server, entry] of this.#servers) {
|
|
9556
|
-
for (const tool of entry.tools)
|
|
10207
|
+
for (const tool of entry.tools) descriptors9.push(this.#toolDescriptor(server, tool));
|
|
9557
10208
|
}
|
|
9558
|
-
return
|
|
10209
|
+
return descriptors9;
|
|
9559
10210
|
}
|
|
9560
10211
|
// Test/ops hook: await hydration and any in-flight background revalidation,
|
|
9561
10212
|
// then flush pending persistence and notifications.
|
|
@@ -9957,7 +10608,7 @@ var McpProvider = class {
|
|
|
9957
10608
|
kind: "stdio",
|
|
9958
10609
|
command: args.command,
|
|
9959
10610
|
args: commandArgs,
|
|
9960
|
-
cwd:
|
|
10611
|
+
cwd: path12.resolve(this.cwd, typeof args.cwd === "string" ? args.cwd : ".")
|
|
9961
10612
|
},
|
|
9962
10613
|
...env ? { env } : {}
|
|
9963
10614
|
};
|
|
@@ -10022,13 +10673,13 @@ var McpProvider = class {
|
|
|
10022
10673
|
return tools.map((tool) => this.#toolDescriptor(server, tool));
|
|
10023
10674
|
})
|
|
10024
10675
|
);
|
|
10025
|
-
const
|
|
10676
|
+
const descriptors9 = settled.flatMap(
|
|
10026
10677
|
(entry) => entry.status === "fulfilled" ? entry.value : []
|
|
10027
10678
|
);
|
|
10028
10679
|
const query = request.query?.toLowerCase();
|
|
10029
|
-
const filtered = query ?
|
|
10680
|
+
const filtered = query ? descriptors9.filter(
|
|
10030
10681
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
10031
|
-
) :
|
|
10682
|
+
) : descriptors9;
|
|
10032
10683
|
return request.namespace ? filtered : [...managementDescriptors, ...filtered];
|
|
10033
10684
|
}
|
|
10034
10685
|
async #describeLegacy(actionName, _context) {
|
|
@@ -10100,7 +10751,7 @@ var assertReadableStateKey = (key) => {
|
|
|
10100
10751
|
throw new Error(`Fabric mesh key is private host state: ${key}`);
|
|
10101
10752
|
}
|
|
10102
10753
|
};
|
|
10103
|
-
var
|
|
10754
|
+
var descriptors6 = [
|
|
10104
10755
|
{
|
|
10105
10756
|
name: "self",
|
|
10106
10757
|
description: "Return this Fabric participant's mesh identity",
|
|
@@ -10227,7 +10878,7 @@ var descriptors5 = [
|
|
|
10227
10878
|
namespace: "coordination"
|
|
10228
10879
|
}
|
|
10229
10880
|
];
|
|
10230
|
-
var normalizeMeshArgs = actionArgNormalizer(() =>
|
|
10881
|
+
var normalizeMeshArgs = actionArgNormalizer(() => descriptors6);
|
|
10231
10882
|
var MeshProvider = class {
|
|
10232
10883
|
constructor(store, identity, participants) {
|
|
10233
10884
|
this.store = store;
|
|
@@ -10238,12 +10889,12 @@ var MeshProvider = class {
|
|
|
10238
10889
|
description = "Durable topics and compare-and-swap shared state for emergent agent coordination";
|
|
10239
10890
|
async list(request, _context) {
|
|
10240
10891
|
const query = request.query?.toLowerCase();
|
|
10241
|
-
return query ?
|
|
10892
|
+
return query ? descriptors6.filter(
|
|
10242
10893
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
10243
|
-
) :
|
|
10894
|
+
) : descriptors6;
|
|
10244
10895
|
}
|
|
10245
10896
|
async describe(actionName, _context) {
|
|
10246
|
-
return
|
|
10897
|
+
return descriptors6.find((descriptor) => descriptor.name === actionName);
|
|
10247
10898
|
}
|
|
10248
10899
|
prepareArguments(actionName, args) {
|
|
10249
10900
|
return normalizeMeshArgs(actionName, args);
|
|
@@ -10337,7 +10988,7 @@ var MeshProvider = class {
|
|
|
10337
10988
|
// src/providers/omp-tools-provider.ts
|
|
10338
10989
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, statSync as statSync4, writeFileSync as writeFileSync2 } from "node:fs";
|
|
10339
10990
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10340
|
-
import
|
|
10991
|
+
import path15 from "node:path";
|
|
10341
10992
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
10342
10993
|
import { BashTool } from "@oh-my-pi/pi-coding-agent/tools/bash";
|
|
10343
10994
|
import { EditTool } from "@oh-my-pi/pi-coding-agent/edit";
|
|
@@ -10356,7 +11007,7 @@ import {
|
|
|
10356
11007
|
|
|
10357
11008
|
// src/agents/bash-worktree-add.ts
|
|
10358
11009
|
import fs6 from "node:fs";
|
|
10359
|
-
import
|
|
11010
|
+
import path13 from "node:path";
|
|
10360
11011
|
var BARE_SAFE = /^[A-Za-z0-9_./:@%+=,-]+$/;
|
|
10361
11012
|
var parseGitWorktreeAdd = (command) => {
|
|
10362
11013
|
const trimmed = command.trim();
|
|
@@ -10419,8 +11070,8 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
|
|
|
10419
11070
|
if (typeof command !== "string") return void 0;
|
|
10420
11071
|
const parsed = parseGitWorktreeAdd(command);
|
|
10421
11072
|
if (!parsed) return void 0;
|
|
10422
|
-
const gitCwd = parsed.gitCwd ?
|
|
10423
|
-
const dest =
|
|
11073
|
+
const gitCwd = parsed.gitCwd ? path13.resolve(sessionCwd, parsed.gitCwd) : typeof args.cwd === "string" ? args.cwd : sessionCwd;
|
|
11074
|
+
const dest = path13.resolve(gitCwd, parsed.dest);
|
|
10424
11075
|
let gitRoot;
|
|
10425
11076
|
try {
|
|
10426
11077
|
const root = await executeFile("git", ["rev-parse", "--show-toplevel"], {
|
|
@@ -10449,7 +11100,7 @@ var tryExecuteGitWorktreeAdd = async (args, sessionCwd) => {
|
|
|
10449
11100
|
|
|
10450
11101
|
// src/providers/omp-bash-cwd.ts
|
|
10451
11102
|
import { accessSync, constants, statSync as statSync3 } from "node:fs";
|
|
10452
|
-
import
|
|
11103
|
+
import path14 from "node:path";
|
|
10453
11104
|
import { createBashToolDefinition } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-pi-coding-agent-shim";
|
|
10454
11105
|
import { Type as Type4 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
|
|
10455
11106
|
var OMP_BASH_CWD_KEY = "cwd";
|
|
@@ -10459,7 +11110,7 @@ var resolveOmpShellCwd = (toolName, sessionCwd, requested) => {
|
|
|
10459
11110
|
`Invalid omp.${toolName} cwd ${JSON.stringify(requested)}: path must be a non-empty string`
|
|
10460
11111
|
);
|
|
10461
11112
|
}
|
|
10462
|
-
const resolved =
|
|
11113
|
+
const resolved = path14.isAbsolute(requested) ? path14.resolve(requested) : path14.resolve(sessionCwd, requested);
|
|
10463
11114
|
try {
|
|
10464
11115
|
if (!statSync3(resolved).isDirectory()) throw new Error("path is not a directory");
|
|
10465
11116
|
accessSync(resolved, constants.R_OK | constants.X_OK);
|
|
@@ -10481,23 +11132,23 @@ var resolveShellCwdArgument = (toolName, sessionCwd, args) => Object.hasOwn(args
|
|
|
10481
11132
|
} : args;
|
|
10482
11133
|
var CWD_DESCRIPTION = "Execution directory for this command; relative paths resolve from the session cwd.";
|
|
10483
11134
|
var CWD_PROPERTY = Type4.Optional(Type4.String({ description: CWD_DESCRIPTION }));
|
|
10484
|
-
var
|
|
11135
|
+
var isRecord6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10485
11136
|
var SHELL_FIELD_DESCRIPTIONS = {
|
|
10486
11137
|
command: "command to execute",
|
|
10487
11138
|
[OMP_BASH_CWD_KEY]: CWD_DESCRIPTION,
|
|
10488
11139
|
pty: "run in pty mode"
|
|
10489
11140
|
};
|
|
10490
11141
|
var schemaDocument2 = (schema) => {
|
|
10491
|
-
if (
|
|
11142
|
+
if (isRecord6(schema)) return schema;
|
|
10492
11143
|
if (typeof schema !== "function" || !("toJsonSchema" in schema)) return void 0;
|
|
10493
11144
|
const toJsonSchema = schema.toJsonSchema;
|
|
10494
11145
|
if (typeof toJsonSchema !== "function") return void 0;
|
|
10495
11146
|
const document = toJsonSchema.call(schema);
|
|
10496
|
-
return
|
|
11147
|
+
return isRecord6(document) ? document : void 0;
|
|
10497
11148
|
};
|
|
10498
11149
|
var withShellCwdSchema = (schema) => {
|
|
10499
11150
|
const document = schemaDocument2(schema);
|
|
10500
|
-
if (!document || !
|
|
11151
|
+
if (!document || !isRecord6(document.properties)) return schema;
|
|
10501
11152
|
const properties = { ...document.properties };
|
|
10502
11153
|
let changed = false;
|
|
10503
11154
|
const cwdSchema = Object.hasOwn(properties, OMP_BASH_CWD_KEY) ? void 0 : schemaDocument2(CWD_PROPERTY);
|
|
@@ -10507,7 +11158,7 @@ var withShellCwdSchema = (schema) => {
|
|
|
10507
11158
|
}
|
|
10508
11159
|
for (const [field, description] of Object.entries(SHELL_FIELD_DESCRIPTIONS)) {
|
|
10509
11160
|
const property = properties[field];
|
|
10510
|
-
if (!
|
|
11161
|
+
if (!isRecord6(property) || typeof property.description === "string") continue;
|
|
10511
11162
|
properties[field] = { ...property, description };
|
|
10512
11163
|
changed = true;
|
|
10513
11164
|
}
|
|
@@ -10544,23 +11195,23 @@ var BashCwdDefinitions = class extends ShellCwdDefinitions {
|
|
|
10544
11195
|
// src/providers/write-preview.ts
|
|
10545
11196
|
import { homedir } from "node:os";
|
|
10546
11197
|
import { dirname, isAbsolute, resolve, win32 } from "node:path";
|
|
10547
|
-
import { mkdir, readFile as
|
|
11198
|
+
import { mkdir as mkdir2, readFile as readFile3, stat, writeFile as writeFile2 } from "node:fs/promises";
|
|
10548
11199
|
import { Type as Type5 } from "@oh-my-pi/pi-coding-agent/extensibility/legacy-typebox";
|
|
10549
11200
|
import { WriteTool } from "@oh-my-pi/pi-coding-agent/tools/write";
|
|
10550
11201
|
var mutationQueues = /* @__PURE__ */ new Map();
|
|
10551
|
-
var withFileMutationQueue = async (
|
|
10552
|
-
const previous = mutationQueues.get(
|
|
11202
|
+
var withFileMutationQueue = async (path21, operation) => {
|
|
11203
|
+
const previous = mutationQueues.get(path21) ?? Promise.resolve();
|
|
10553
11204
|
let release;
|
|
10554
11205
|
const current = new Promise((resolve2) => {
|
|
10555
11206
|
release = resolve2;
|
|
10556
11207
|
});
|
|
10557
|
-
mutationQueues.set(
|
|
11208
|
+
mutationQueues.set(path21, current);
|
|
10558
11209
|
await previous;
|
|
10559
11210
|
try {
|
|
10560
11211
|
return await operation();
|
|
10561
11212
|
} finally {
|
|
10562
11213
|
release();
|
|
10563
|
-
if (mutationQueues.get(
|
|
11214
|
+
if (mutationQueues.get(path21) === current) mutationQueues.delete(path21);
|
|
10564
11215
|
}
|
|
10565
11216
|
};
|
|
10566
11217
|
var URI_LIKE_WRITE_TARGET_RE = /^([a-z][a-z0-9+.-]*):\/{1,2}/i;
|
|
@@ -10605,7 +11256,7 @@ var readExistingFileForPreview = async (filePath, cwd, nextContent) => {
|
|
|
10605
11256
|
return skipped("previous file too large", fileStat.size, true);
|
|
10606
11257
|
}
|
|
10607
11258
|
try {
|
|
10608
|
-
const content = await
|
|
11259
|
+
const content = await readFile3(absolutePath, "utf8");
|
|
10609
11260
|
const bytes = Buffer.byteLength(content, "utf8");
|
|
10610
11261
|
return bytes > MAX_WRITE_DIFF_BYTES ? skipped("previous file too large", bytes, true) : { kind: "content", content };
|
|
10611
11262
|
} catch {
|
|
@@ -10623,11 +11274,11 @@ var createPreviewWriteToolDefinition = (cwd, session) => {
|
|
|
10623
11274
|
return {
|
|
10624
11275
|
...original,
|
|
10625
11276
|
async execute(_toolCallId, params, signal) {
|
|
10626
|
-
const { path:
|
|
10627
|
-
if (isUriLikeWriteTarget(
|
|
11277
|
+
const { path: path21, content } = params;
|
|
11278
|
+
if (isUriLikeWriteTarget(path21)) {
|
|
10628
11279
|
if (session === void 0) {
|
|
10629
11280
|
throw new Error(
|
|
10630
|
-
`Refusing to write '${
|
|
11281
|
+
`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
11282
|
);
|
|
10632
11283
|
}
|
|
10633
11284
|
return await new WriteTool(session).execute(
|
|
@@ -10639,23 +11290,23 @@ var createPreviewWriteToolDefinition = (cwd, session) => {
|
|
|
10639
11290
|
{ signal }
|
|
10640
11291
|
);
|
|
10641
11292
|
}
|
|
10642
|
-
const absolutePath = resolvePreviewPath(
|
|
11293
|
+
const absolutePath = resolvePreviewPath(path21, cwd);
|
|
10643
11294
|
return withFileMutationQueue(absolutePath, async () => {
|
|
10644
11295
|
const throwIfAborted2 = () => {
|
|
10645
11296
|
if (signal?.aborted) throw new Error("Operation aborted");
|
|
10646
11297
|
};
|
|
10647
11298
|
throwIfAborted2();
|
|
10648
|
-
const before = await readExistingFileForPreview(
|
|
11299
|
+
const before = await readExistingFileForPreview(path21, cwd, content);
|
|
10649
11300
|
throwIfAborted2();
|
|
10650
|
-
await
|
|
11301
|
+
await mkdir2(dirname(absolutePath), { recursive: true });
|
|
10651
11302
|
throwIfAborted2();
|
|
10652
|
-
await
|
|
11303
|
+
await writeFile2(absolutePath, content, "utf8");
|
|
10653
11304
|
throwIfAborted2();
|
|
10654
11305
|
return {
|
|
10655
11306
|
content: [
|
|
10656
11307
|
{
|
|
10657
11308
|
type: "text",
|
|
10658
|
-
text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${
|
|
11309
|
+
text: `Successfully wrote ${Buffer.byteLength(content, "utf8")} bytes to ${path21}`
|
|
10659
11310
|
}
|
|
10660
11311
|
],
|
|
10661
11312
|
details: { codePreviewBeforeWrite: before }
|
|
@@ -10782,7 +11433,7 @@ var createNativeSession = (cwd, {
|
|
|
10782
11433
|
try {
|
|
10783
11434
|
mkdirSync2(artifacts.root, { recursive: true, mode: 448 });
|
|
10784
11435
|
const id = randomUUID3();
|
|
10785
|
-
const artifactPath =
|
|
11436
|
+
const artifactPath = path15.join(artifacts.root, `${toolType}-${id}.log`);
|
|
10786
11437
|
writeFileSync2(artifactPath, "", { mode: 384 });
|
|
10787
11438
|
artifacts.paths.set(id, artifactPath);
|
|
10788
11439
|
artifactAllocations.getStore()?.push(artifactPath);
|
|
@@ -10950,7 +11601,7 @@ var normalizeEditArguments = (args, replaceAll, cwd) => {
|
|
|
10950
11601
|
...replaceAll || record2.all === true || record2.replace_all === true ? { replace_all: true } : {}
|
|
10951
11602
|
};
|
|
10952
11603
|
});
|
|
10953
|
-
const resolvedPath =
|
|
11604
|
+
const resolvedPath = path15.resolve(cwd, filePath.startsWith("@") ? filePath.slice(1) : filePath);
|
|
10954
11605
|
const current = readFileSync2(resolvedPath, "utf8");
|
|
10955
11606
|
if (current.length > MAX_REPLACE_ALL_FILE_CHARS) {
|
|
10956
11607
|
throw new Error(`omp.edit refuses files over ${MAX_REPLACE_ALL_FILE_CHARS} characters`);
|
|
@@ -11425,10 +12076,10 @@ var OmpToolsProvider = class _OmpToolsProvider {
|
|
|
11425
12076
|
}
|
|
11426
12077
|
async list(request, _context) {
|
|
11427
12078
|
const query = request.query?.toLowerCase();
|
|
11428
|
-
const
|
|
12079
|
+
const descriptors9 = await Promise.all(
|
|
11429
12080
|
OMP_GUEST_TOOL_NAMES.map((name) => this.describe(name, _context))
|
|
11430
12081
|
);
|
|
11431
|
-
return
|
|
12082
|
+
return descriptors9.filter((descriptor) => descriptor !== void 0).filter(
|
|
11432
12083
|
(descriptor) => query ? `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query) : true
|
|
11433
12084
|
);
|
|
11434
12085
|
}
|
|
@@ -11834,7 +12485,7 @@ var OmpToolsProvider = class _OmpToolsProvider {
|
|
|
11834
12485
|
import { spawn } from "node:child_process";
|
|
11835
12486
|
import { createHash as createHash3, randomBytes, randomUUID as randomUUID4 } from "node:crypto";
|
|
11836
12487
|
import fs8 from "node:fs";
|
|
11837
|
-
import
|
|
12488
|
+
import path17 from "node:path";
|
|
11838
12489
|
|
|
11839
12490
|
// src/schema/types.ts
|
|
11840
12491
|
var stateBinding = (head) => head ? { transitionId: head.transitionId, version: head.version, to: head.to } : null;
|
|
@@ -11843,7 +12494,7 @@ var stateBinding = (head) => head ? { transitionId: head.transitionId, version:
|
|
|
11843
12494
|
import { execFileSync } from "node:child_process";
|
|
11844
12495
|
import { createHash as createHash2 } from "node:crypto";
|
|
11845
12496
|
import fs7 from "node:fs";
|
|
11846
|
-
import
|
|
12497
|
+
import path16 from "node:path";
|
|
11847
12498
|
var SNAPSHOT_MAX_FILES = 2e4;
|
|
11848
12499
|
var SNAPSHOT_MAX_BYTES = 512 * 1024 * 1024;
|
|
11849
12500
|
var FALLBACK_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
@@ -11861,10 +12512,10 @@ var git = (cwd, args) => execFileSync("git", ["-C", cwd, ...args], {
|
|
|
11861
12512
|
stdio: ["ignore", "pipe", "ignore"]
|
|
11862
12513
|
});
|
|
11863
12514
|
var nulPaths = (buffer) => buffer.toString("utf8").split("\0").filter((item) => item.length > 0);
|
|
11864
|
-
var normalizeRelative = (value) => value.split(
|
|
12515
|
+
var normalizeRelative = (value) => value.split(path16.sep).join("/");
|
|
11865
12516
|
var isInside = (root, candidate) => {
|
|
11866
|
-
const relative =
|
|
11867
|
-
return relative === "" || !
|
|
12517
|
+
const relative = path16.relative(root, candidate);
|
|
12518
|
+
return relative === "" || !path16.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path16.sep}`);
|
|
11868
12519
|
};
|
|
11869
12520
|
var excluded = (absolute, exclusions) => exclusions.some((root) => isInside(root, absolute));
|
|
11870
12521
|
var entryDigest = (absolute) => {
|
|
@@ -11890,12 +12541,12 @@ var buildSnapshot = (cwd, paths, metadata, exclusions) => {
|
|
|
11890
12541
|
let bytes = 0;
|
|
11891
12542
|
const unique = [...new Set(paths)].sort((left, right) => left.localeCompare(right));
|
|
11892
12543
|
for (const relativeInput of unique) {
|
|
11893
|
-
const absolute =
|
|
12544
|
+
const absolute = path16.resolve(cwd, relativeInput);
|
|
11894
12545
|
if (!isInside(cwd, absolute) || excluded(absolute, exclusions)) continue;
|
|
11895
12546
|
if (Object.keys(entries).length >= SNAPSHOT_MAX_FILES) {
|
|
11896
12547
|
throw new Error(`Schema workspace snapshot exceeds ${SNAPSHOT_MAX_FILES} files`);
|
|
11897
12548
|
}
|
|
11898
|
-
const relative = normalizeRelative(
|
|
12549
|
+
const relative = normalizeRelative(path16.relative(cwd, absolute));
|
|
11899
12550
|
const entry = entryDigest(absolute);
|
|
11900
12551
|
bytes += entry.bytes;
|
|
11901
12552
|
if (bytes > SNAPSHOT_MAX_BYTES) {
|
|
@@ -11924,9 +12575,9 @@ var fallbackPaths = (cwd, exclusions) => {
|
|
|
11924
12575
|
const entries = fs7.readdirSync(directory, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
11925
12576
|
for (const entry of entries) {
|
|
11926
12577
|
if (FALLBACK_SKIPPED_DIRECTORIES.has(entry.name)) continue;
|
|
11927
|
-
const absolute =
|
|
12578
|
+
const absolute = path16.join(directory, entry.name);
|
|
11928
12579
|
if (excluded(absolute, exclusions)) continue;
|
|
11929
|
-
const relative = normalizeRelative(
|
|
12580
|
+
const relative = normalizeRelative(path16.relative(cwd, absolute));
|
|
11930
12581
|
if (entry.isDirectory()) visit(absolute);
|
|
11931
12582
|
else paths.push(relative);
|
|
11932
12583
|
if (paths.length > SNAPSHOT_MAX_FILES) {
|
|
@@ -11940,7 +12591,7 @@ var fallbackPaths = (cwd, exclusions) => {
|
|
|
11940
12591
|
var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
|
|
11941
12592
|
const cwd = fs7.realpathSync(cwdInput);
|
|
11942
12593
|
const exclusions = excludedRoots.map((root) => {
|
|
11943
|
-
const absolute =
|
|
12594
|
+
const absolute = path16.resolve(root);
|
|
11944
12595
|
try {
|
|
11945
12596
|
return fs7.realpathSync(absolute);
|
|
11946
12597
|
} catch {
|
|
@@ -11978,18 +12629,18 @@ var snapshotWorkspace = (cwdInput, excludedRoots = []) => {
|
|
|
11978
12629
|
);
|
|
11979
12630
|
};
|
|
11980
12631
|
var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
|
|
11981
|
-
if (!requestedPath.trim() ||
|
|
12632
|
+
if (!requestedPath.trim() || path16.isAbsolute(requestedPath)) {
|
|
11982
12633
|
throw new Error(`Schema paths must be non-empty project-relative paths: ${requestedPath}`);
|
|
11983
12634
|
}
|
|
11984
12635
|
const cwd = fs7.realpathSync(cwdInput);
|
|
11985
|
-
const absolute =
|
|
12636
|
+
const absolute = path16.resolve(cwd, requestedPath);
|
|
11986
12637
|
if (!isInside(cwd, absolute) || absolute === cwd) {
|
|
11987
12638
|
throw new Error(`Schema path escapes the project workspace: ${requestedPath}`);
|
|
11988
12639
|
}
|
|
11989
|
-
const relativeParts =
|
|
12640
|
+
const relativeParts = path16.relative(cwd, absolute).split(path16.sep);
|
|
11990
12641
|
let cursor = cwd;
|
|
11991
12642
|
for (let index = 0; index < relativeParts.length; index++) {
|
|
11992
|
-
cursor =
|
|
12643
|
+
cursor = path16.join(cursor, relativeParts[index]);
|
|
11993
12644
|
let stat2;
|
|
11994
12645
|
try {
|
|
11995
12646
|
stat2 = fs7.lstatSync(cursor);
|
|
@@ -11998,9 +12649,9 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
|
|
|
11998
12649
|
if (index !== relativeParts.length - 1 || !options.allowAbsent) {
|
|
11999
12650
|
throw new Error(`Schema path does not exist: ${requestedPath}`);
|
|
12000
12651
|
}
|
|
12001
|
-
const parentReal = fs7.realpathSync(
|
|
12652
|
+
const parentReal = fs7.realpathSync(path16.dirname(cursor));
|
|
12002
12653
|
if (!isInside(cwd, parentReal)) throw new Error(`Schema path parent escapes the workspace: ${requestedPath}`);
|
|
12003
|
-
return { absolute, relative: normalizeRelative(
|
|
12654
|
+
return { absolute, relative: normalizeRelative(path16.relative(cwd, absolute)), exists: false };
|
|
12004
12655
|
}
|
|
12005
12656
|
throw error;
|
|
12006
12657
|
}
|
|
@@ -12012,7 +12663,7 @@ var resolveWorkspaceFile = (cwdInput, requestedPath, options) => {
|
|
|
12012
12663
|
throw new Error(`Schema transaction paths must name regular files: ${requestedPath}`);
|
|
12013
12664
|
}
|
|
12014
12665
|
}
|
|
12015
|
-
return { absolute, relative: normalizeRelative(
|
|
12666
|
+
return { absolute, relative: normalizeRelative(path16.relative(cwd, absolute)), exists: true };
|
|
12016
12667
|
};
|
|
12017
12668
|
var sha256File = (absolute) => `sha256:${digest(fs7.readFileSync(absolute))}`;
|
|
12018
12669
|
|
|
@@ -12063,8 +12714,8 @@ var SchemaController = class {
|
|
|
12063
12714
|
this.identity = identity;
|
|
12064
12715
|
this.state = state;
|
|
12065
12716
|
this.cwd = fs8.realpathSync(cwd);
|
|
12066
|
-
this.#journalRoot =
|
|
12067
|
-
this.#lockPath =
|
|
12717
|
+
this.#journalRoot = path17.join(mesh.root, "schema-transactions");
|
|
12718
|
+
this.#lockPath = path17.join(this.#journalRoot, ".commit.lock");
|
|
12068
12719
|
this.#recoverJournals();
|
|
12069
12720
|
}
|
|
12070
12721
|
#activeHypotheses = /* @__PURE__ */ new Map();
|
|
@@ -12263,7 +12914,7 @@ var SchemaController = class {
|
|
|
12263
12914
|
this.#assertPayloadBound(input);
|
|
12264
12915
|
const release = this.#acquireCommitLock();
|
|
12265
12916
|
const transactionId = randomUUID4();
|
|
12266
|
-
const journalPath =
|
|
12917
|
+
const journalPath = path17.join(this.#journalRoot, `${transactionId}.json`);
|
|
12267
12918
|
let journal;
|
|
12268
12919
|
let consumed = false;
|
|
12269
12920
|
let committed = false;
|
|
@@ -12744,7 +13395,7 @@ ${Date.now()}
|
|
|
12744
13395
|
}
|
|
12745
13396
|
for (const name of fs8.readdirSync(this.#journalRoot)) {
|
|
12746
13397
|
if (!name.endsWith(".json")) continue;
|
|
12747
|
-
const filePath =
|
|
13398
|
+
const filePath = path17.join(this.#journalRoot, name);
|
|
12748
13399
|
try {
|
|
12749
13400
|
const journal = JSON.parse(fs8.readFileSync(filePath, "utf8"));
|
|
12750
13401
|
if (journal.format !== 1 || journal.status !== "applying" || !Array.isArray(journal.before)) continue;
|
|
@@ -12864,7 +13515,7 @@ var operationSchema = {
|
|
|
12864
13515
|
}
|
|
12865
13516
|
]
|
|
12866
13517
|
};
|
|
12867
|
-
var
|
|
13518
|
+
var descriptors7 = [
|
|
12868
13519
|
{
|
|
12869
13520
|
name: "status",
|
|
12870
13521
|
description: "Read the fixed session Schema mode, transaction bounds, generation, and invocation hypotheses",
|
|
@@ -12934,7 +13585,7 @@ var descriptors6 = [
|
|
|
12934
13585
|
namespace: "schema"
|
|
12935
13586
|
}
|
|
12936
13587
|
];
|
|
12937
|
-
var normalizeSchemaArgs = actionArgNormalizer(() =>
|
|
13588
|
+
var normalizeSchemaArgs = actionArgNormalizer(() => descriptors7);
|
|
12938
13589
|
var SchemaProvider = class {
|
|
12939
13590
|
constructor(controller) {
|
|
12940
13591
|
this.controller = controller;
|
|
@@ -12943,12 +13594,12 @@ var SchemaProvider = class {
|
|
|
12943
13594
|
description = "Host-owned, opt-in Schema verification and bounded local-file transaction control plane";
|
|
12944
13595
|
async list(request, _context) {
|
|
12945
13596
|
const query = request.query?.toLowerCase();
|
|
12946
|
-
return query ?
|
|
13597
|
+
return query ? descriptors7.filter(
|
|
12947
13598
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
12948
|
-
) :
|
|
13599
|
+
) : descriptors7;
|
|
12949
13600
|
}
|
|
12950
13601
|
async describe(actionName, _context) {
|
|
12951
|
-
return
|
|
13602
|
+
return descriptors7.find((descriptor) => descriptor.name === actionName);
|
|
12952
13603
|
}
|
|
12953
13604
|
prepareArguments(actionName, args) {
|
|
12954
13605
|
return normalizeSchemaArgs(actionName, args);
|
|
@@ -12998,11 +13649,11 @@ var SchemaProvider = class {
|
|
|
12998
13649
|
|
|
12999
13650
|
// src/state/store.ts
|
|
13000
13651
|
import { createHash as createHash5 } from "node:crypto";
|
|
13001
|
-
import
|
|
13652
|
+
import path19 from "node:path";
|
|
13002
13653
|
|
|
13003
13654
|
// src/state/complexity.ts
|
|
13004
13655
|
import fs9 from "node:fs";
|
|
13005
|
-
import
|
|
13656
|
+
import path18 from "node:path";
|
|
13006
13657
|
var isWordStart = (character) => character !== void 0 && (character >= "a" && character <= "z" || character >= "A" && character <= "Z" || character === "_" || character === "$");
|
|
13007
13658
|
var isWordPart = (character) => isWordStart(character) || character !== void 0 && character >= "0" && character <= "9";
|
|
13008
13659
|
var regularExpressionPrefixWords = /* @__PURE__ */ new Set([
|
|
@@ -13234,7 +13885,7 @@ var languageComplexities = [
|
|
|
13234
13885
|
typeScriptJavaScriptComplexity
|
|
13235
13886
|
];
|
|
13236
13887
|
var complexityForFile = (file, languages = languageComplexities) => {
|
|
13237
|
-
const extension =
|
|
13888
|
+
const extension = path18.extname(file).toLowerCase();
|
|
13238
13889
|
return languages.find((language) => language.extensions.includes(extension));
|
|
13239
13890
|
};
|
|
13240
13891
|
var countFileComplexity = (file) => {
|
|
@@ -14125,7 +14776,7 @@ var StateStore = class {
|
|
|
14125
14776
|
const files = [];
|
|
14126
14777
|
let netDelta = 0;
|
|
14127
14778
|
for (const file of this.normalizeComplexityFiles(requestedFiles, input.cwd)) {
|
|
14128
|
-
const measured = countFileComplexity(
|
|
14779
|
+
const measured = countFileComplexity(path19.resolve(input.cwd, file));
|
|
14129
14780
|
if (!measured) {
|
|
14130
14781
|
files.push({ file, supported: false });
|
|
14131
14782
|
continue;
|
|
@@ -14152,7 +14803,7 @@ var StateStore = class {
|
|
|
14152
14803
|
const updates = [];
|
|
14153
14804
|
let netDelta = 0;
|
|
14154
14805
|
for (const file of this.normalizeComplexityFiles(files, cwd)) {
|
|
14155
|
-
const measured = countFileComplexity(
|
|
14806
|
+
const measured = countFileComplexity(path19.resolve(cwd, file));
|
|
14156
14807
|
if (!measured) {
|
|
14157
14808
|
deltas.push({ file, supported: false });
|
|
14158
14809
|
continue;
|
|
@@ -14202,11 +14853,11 @@ var StateStore = class {
|
|
|
14202
14853
|
const normalized = /* @__PURE__ */ new Set();
|
|
14203
14854
|
for (const file of files) {
|
|
14204
14855
|
if (!file.trim()) continue;
|
|
14205
|
-
const relative =
|
|
14206
|
-
if (relative === ".." || relative.startsWith(`..${
|
|
14856
|
+
const relative = path19.relative(cwd, path19.resolve(cwd, file));
|
|
14857
|
+
if (relative === ".." || relative.startsWith(`..${path19.sep}`) || path19.isAbsolute(relative)) {
|
|
14207
14858
|
throw new Error(`State complexity file must be inside the project cwd: ${file}`);
|
|
14208
14859
|
}
|
|
14209
|
-
normalized.add(relative.split(
|
|
14860
|
+
normalized.add(relative.split(path19.sep).join("/"));
|
|
14210
14861
|
}
|
|
14211
14862
|
return [...normalized];
|
|
14212
14863
|
}
|
|
@@ -14648,7 +15299,7 @@ var checkGoalSchema = {
|
|
|
14648
15299
|
additionalProperties: false
|
|
14649
15300
|
};
|
|
14650
15301
|
var emptySchema3 = { type: "object", properties: {}, additionalProperties: false };
|
|
14651
|
-
var
|
|
15302
|
+
var descriptors8 = [
|
|
14652
15303
|
{
|
|
14653
15304
|
name: "transition",
|
|
14654
15305
|
description: "Append a labeled, validated state transition and compare-and-swap advance the head",
|
|
@@ -14699,7 +15350,7 @@ var descriptors7 = [
|
|
|
14699
15350
|
namespace: "state"
|
|
14700
15351
|
}
|
|
14701
15352
|
];
|
|
14702
|
-
var normalizeStateArgs = actionArgNormalizer(() =>
|
|
15353
|
+
var normalizeStateArgs = actionArgNormalizer(() => descriptors8);
|
|
14703
15354
|
var StateProvider = class {
|
|
14704
15355
|
name = "state";
|
|
14705
15356
|
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 +15365,12 @@ var StateProvider = class {
|
|
|
14714
15365
|
}
|
|
14715
15366
|
async list(request, _context) {
|
|
14716
15367
|
const query = request.query?.toLowerCase();
|
|
14717
|
-
return query ?
|
|
15368
|
+
return query ? descriptors8.filter(
|
|
14718
15369
|
(descriptor) => `${descriptor.name} ${descriptor.description}`.toLowerCase().includes(query)
|
|
14719
|
-
) :
|
|
15370
|
+
) : descriptors8;
|
|
14720
15371
|
}
|
|
14721
15372
|
async describe(actionName, _context) {
|
|
14722
|
-
return
|
|
15373
|
+
return descriptors8.find((descriptor) => descriptor.name === actionName);
|
|
14723
15374
|
}
|
|
14724
15375
|
prepareArguments(actionName, args) {
|
|
14725
15376
|
return normalizeStateArgs(actionName, args);
|
|
@@ -15227,7 +15878,7 @@ var FabricRuntimeState = class {
|
|
|
15227
15878
|
const projectRoot = process.env.OMP_FABRIC_PROJECT_ROOT ?? context.cwd;
|
|
15228
15879
|
await ensureFabricStateExclude(projectRoot).catch(() => void 0);
|
|
15229
15880
|
const configuredMeshRoot = this.#config.mesh.root;
|
|
15230
|
-
const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ?
|
|
15881
|
+
const meshRoot = process.env.OMP_FABRIC_MESH_ROOT ?? (configuredMeshRoot ? path20.resolve(projectRoot, configuredMeshRoot) : path20.join(projectRoot, ".omp", "fabric", "mesh"));
|
|
15231
15882
|
this.#mesh = new MeshStore(
|
|
15232
15883
|
meshRoot,
|
|
15233
15884
|
this.#config.mesh.maxEventBytes,
|
|
@@ -15323,6 +15974,22 @@ var FabricRuntimeState = class {
|
|
|
15323
15974
|
'disabled by configuration (judgment.enabled=false); set "judgment": { "enabled": true } in .omp/fabric.json or the agent fabric.json to enable judgment.* actions'
|
|
15324
15975
|
);
|
|
15325
15976
|
}
|
|
15977
|
+
if (this.#config.image.enabled) {
|
|
15978
|
+
const imageConfig = () => this.#config?.image ?? DEFAULT_FABRIC_CONFIG.image;
|
|
15979
|
+
await installBuiltin(createProviderComponent({
|
|
15980
|
+
provider: "image",
|
|
15981
|
+
description: "Image generation and editing across a configured priority chain",
|
|
15982
|
+
create: () => new ImageProvider(imageConfig, {
|
|
15983
|
+
registry: context.modelRegistry,
|
|
15984
|
+
getSessionId: () => context.sessionManager.getSessionId() ?? void 0
|
|
15985
|
+
})
|
|
15986
|
+
}));
|
|
15987
|
+
} else {
|
|
15988
|
+
this.#registry.markUnavailable(
|
|
15989
|
+
"image",
|
|
15990
|
+
'disabled by configuration (image.enabled=false); set "image": { "enabled": true } in .omp/fabric.json or the agent fabric.json to enable image.* actions'
|
|
15991
|
+
);
|
|
15992
|
+
}
|
|
15326
15993
|
const agentConfig = enforceSchema ? { ...this.#config.agents, enabled: false } : this.#config.agents;
|
|
15327
15994
|
const modelsConfig = this.#config.models;
|
|
15328
15995
|
const visibleOmpModels = () => {
|
|
@@ -15421,8 +16088,8 @@ var FabricRuntimeState = class {
|
|
|
15421
16088
|
};
|
|
15422
16089
|
const lineageAlive = (rootId) => this.#participants?.get(rootId) !== void 0;
|
|
15423
16090
|
const actorRoots = {
|
|
15424
|
-
project:
|
|
15425
|
-
session:
|
|
16091
|
+
project: path20.join(meshRoot, "actors"),
|
|
16092
|
+
session: path20.join(meshRoot, "actors", fabricSessionId)
|
|
15426
16093
|
};
|
|
15427
16094
|
const acquireActorCapabilityView = (requirements, signal) => this.#registry.acquireCapabilityView(requirements, {
|
|
15428
16095
|
cwd: context.cwd,
|
|
@@ -15626,6 +16293,7 @@ ${escapeXmlText(text)}
|
|
|
15626
16293
|
"compact",
|
|
15627
16294
|
...this.#config.codemap.enabled ? ["codemap"] : [],
|
|
15628
16295
|
...this.#config.judgment.enabled ? ["judgment"] : [],
|
|
16296
|
+
...this.#config.image.enabled ? ["image"] : [],
|
|
15629
16297
|
"agents",
|
|
15630
16298
|
...this.#config.memory.enabled ? ["memory"] : []
|
|
15631
16299
|
]);
|