pi-fabric 0.110.3 → 0.112.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/README.md +2 -0
- package/THIRD_PARTY_NOTICES.md +7 -0
- package/dist/agents/provider-bridge.d.ts +6 -1
- package/dist/agents/provider-bridge.d.ts.map +1 -1
- package/dist/agents/provider-bridge.js +8 -3
- package/dist/agents/provider-bridge.js.map +2 -2
- package/dist/capture/interceptor.d.ts.map +1 -1
- package/dist/chunks/{chunk-WHBJDTCR.js → chunk-7PPIKFT5.js} +36 -9
- package/dist/chunks/chunk-7PPIKFT5.js.map +7 -0
- package/dist/chunks/{chunk-BEP6VFL2.js → chunk-GFBOLBU2.js} +51 -32
- package/dist/chunks/chunk-GFBOLBU2.js.map +7 -0
- package/dist/chunks/chunk-GQGXQCCO.js +38 -0
- package/dist/chunks/chunk-GQGXQCCO.js.map +7 -0
- package/dist/chunks/{chunk-KP2VU5SI.js → chunk-JAEDKSU4.js} +5 -5
- package/dist/chunks/{chunk-XMBRW6L2.js → chunk-ORRLYFKA.js} +2 -2
- package/dist/chunks/{chunk-PXAICAUT.js → chunk-PBDDXBHY.js} +2 -1
- package/dist/chunks/chunk-PBDDXBHY.js.map +7 -0
- package/dist/chunks/{chunk-GYPDGW27.js → chunk-QGP7AY2R.js} +4 -2
- package/dist/chunks/{chunk-GYPDGW27.js.map → chunk-QGP7AY2R.js.map} +2 -2
- package/dist/chunks/{chunk-CXTTLBUV.js → chunk-R2XQ6AHT.js} +2 -2
- package/dist/chunks/{chunk-QFR36ZSK.js → chunk-R4RROLJ4.js} +23 -14
- package/dist/chunks/chunk-R4RROLJ4.js.map +7 -0
- package/dist/chunks/{chunk-DV2JZSCI.js → chunk-SPCJXN4K.js} +14 -4
- package/dist/chunks/{chunk-DV2JZSCI.js.map → chunk-SPCJXN4K.js.map} +2 -2
- package/dist/chunks/{chunk-2TJHOQGO.js → chunk-TNPZBMYC.js} +1 -4
- package/dist/chunks/chunk-TNPZBMYC.js.map +7 -0
- package/dist/chunks/{chunk-5SU3YXBS.js → chunk-UGYCAG6O.js} +1 -1
- package/dist/chunks/{chunk-5SU3YXBS.js.map → chunk-UGYCAG6O.js.map} +1 -1
- package/dist/chunks/{chunk-DSNR5U7X.js → chunk-UQWBZKAN.js} +1 -1
- package/dist/chunks/{chunk-S6BFCVOG.js → chunk-VYWJVAK5.js} +2 -2
- package/dist/chunks/{chunk-XBGOJJQW.js → chunk-WQ6LC2KK.js} +2 -2
- package/dist/chunks/{chunk-W5CHVJBR.js → chunk-XDZMXORT.js} +53 -7
- package/dist/chunks/chunk-XDZMXORT.js.map +7 -0
- package/dist/chunks/{chunk-3DUKKQHN.js → chunk-ZQMBS5SH.js} +5 -5
- package/dist/commands/fabric.d.ts +1 -1
- package/dist/commands/fabric.d.ts.map +1 -1
- package/dist/compaction/hook.d.ts +1 -1
- package/dist/compaction/hook.d.ts.map +1 -1
- package/dist/compaction/hook.js +1 -1
- package/dist/compaction/owner.js +2 -2
- package/dist/core/agent-dir.d.ts +1 -0
- package/dist/core/agent-dir.d.ts.map +1 -1
- package/dist/core/fabric-state-paths.d.ts.map +1 -1
- package/dist/core/host-sdk.d.ts +21 -0
- package/dist/core/host-sdk.d.ts.map +1 -0
- package/dist/core/host-sdk.js +9 -0
- package/dist/core/host-sdk.js.map +7 -0
- package/dist/extension-bootstrap.d.ts +1 -1
- package/dist/extension-bootstrap.js +6 -6
- package/dist/fabric-runtime-state.js +8 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/jev/client.d.ts.map +1 -1
- package/dist/jev/client.js +2 -2
- package/dist/jev/manager.d.ts.map +1 -1
- package/dist/jev/observation.js +2 -2
- package/dist/jev/validation.d.ts +34 -0
- package/dist/jev/validation.d.ts.map +1 -1
- package/dist/jev.js +5 -5
- package/dist/providers/jev-provider.js +5 -5
- package/dist/residency/host.js +4 -4
- package/dist/residency/pi-entry.js +4 -4
- package/dist/runtime/node-process-runtime.js +3 -3
- package/dist/runtime/quickjs-runtime.d.ts.map +1 -1
- package/dist/runtime/quickjs-runtime.js +2 -2
- package/dist/runtime/typescript-kernel.js +3 -3
- package/dist/ui/controller.d.ts.map +1 -1
- package/dist/ui/conversation-chrome.js +2 -2
- package/dist/ui/conversation-host.js +1 -1
- package/dist/ui/conversation-native-reader.js +1 -1
- package/dist/ui/conversation.js +6 -6
- package/dist/ui/dashboard.js +3 -3
- package/dist/ui/settings.js +1 -1
- package/dist/worker/result.js +517 -517
- package/dist/worker/result.js.map +1 -1
- package/docs/configuration.md +27 -5
- package/docs/jev-decisions.md +6 -1
- package/docs/jev.md +9 -3
- package/node_modules/pi-coralbricks-provider/LICENSE +21 -0
- package/node_modules/pi-coralbricks-provider/README.md +306 -0
- package/node_modules/pi-coralbricks-provider/auth.ts +30 -0
- package/node_modules/pi-coralbricks-provider/custom-models.json +1 -0
- package/node_modules/pi-coralbricks-provider/deprecated-models.json +1 -0
- package/node_modules/pi-coralbricks-provider/guard.ts +155 -0
- package/node_modules/pi-coralbricks-provider/index.ts +662 -0
- package/node_modules/pi-coralbricks-provider/models.json +88 -0
- package/node_modules/pi-coralbricks-provider/package.json +74 -0
- package/node_modules/pi-coralbricks-provider/park.ts +122 -0
- package/node_modules/pi-coralbricks-provider/patch.json +34 -0
- package/node_modules/pi-coralbricks-provider/scripts/update-models.js +658 -0
- package/node_modules/pi-coralbricks-provider/settings.ts +143 -0
- package/node_modules/pi-coralbricks-provider/sync-policy.ts +309 -0
- package/package.json +8 -3
- package/dist/chunks/chunk-2TJHOQGO.js.map +0 -7
- package/dist/chunks/chunk-BEP6VFL2.js.map +0 -7
- package/dist/chunks/chunk-PXAICAUT.js.map +0 -7
- package/dist/chunks/chunk-QFR36ZSK.js.map +0 -7
- package/dist/chunks/chunk-W5CHVJBR.js.map +0 -7
- package/dist/chunks/chunk-WHBJDTCR.js.map +0 -7
- /package/dist/chunks/{chunk-KP2VU5SI.js.map → chunk-JAEDKSU4.js.map} +0 -0
- /package/dist/chunks/{chunk-XMBRW6L2.js.map → chunk-ORRLYFKA.js.map} +0 -0
- /package/dist/chunks/{chunk-CXTTLBUV.js.map → chunk-R2XQ6AHT.js.map} +0 -0
- /package/dist/chunks/{chunk-DSNR5U7X.js.map → chunk-UQWBZKAN.js.map} +0 -0
- /package/dist/chunks/{chunk-S6BFCVOG.js.map → chunk-VYWJVAK5.js.map} +0 -0
- /package/dist/chunks/{chunk-XBGOJJQW.js.map → chunk-WQ6LC2KK.js.map} +0 -0
- /package/dist/chunks/{chunk-3DUKKQHN.js.map → chunk-ZQMBS5SH.js.map} +0 -0
package/README.md
CHANGED
|
@@ -90,6 +90,8 @@ Requires Node.js 24+ and Pi 1.0.0+. Monty's optional native package installs on
|
|
|
90
90
|
pi install npm:pi-fabric
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
Fabric bundles the [Coral Bricks provider](docs/configuration.md#bundled-coral-bricks-provider): run `/login coralbricks` to use `coralbricks/*` models, or opt out with a package filter. Fabric's maintainers work at Coral Bricks.
|
|
94
|
+
|
|
93
95
|
<details>
|
|
94
96
|
<summary>Other install methods</summary>
|
|
95
97
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -8,6 +8,13 @@ Haydn Paterson, licensed under MIT. This private artifact is not loaded by the
|
|
|
8
8
|
Pi extension, which continues to use Pi's host-provided TypeBox. The complete
|
|
9
9
|
license is distributed at [docs/licenses/typebox-mit.txt](docs/licenses/typebox-mit.txt).
|
|
10
10
|
|
|
11
|
+
## pi-coralbricks-provider
|
|
12
|
+
|
|
13
|
+
The package bundles [`pi-coralbricks-provider`](https://github.com/monotykamary/pi-coralbricks-provider)
|
|
14
|
+
unmodified under `node_modules/pi-coralbricks-provider`, at the exact version
|
|
15
|
+
pinned in `package.json`. It is licensed under MIT, and its complete license is
|
|
16
|
+
distributed beside it at `node_modules/pi-coralbricks-provider/LICENSE`.
|
|
17
|
+
|
|
11
18
|
## Bend 2.0.36
|
|
12
19
|
|
|
13
20
|
The generated policy kernel includes Bend's emitted JavaScript trampoline and
|
|
@@ -38,7 +38,12 @@ export declare function orderProviderCandidates(paths: readonly string[], provid
|
|
|
38
38
|
named: string[];
|
|
39
39
|
rest: string[];
|
|
40
40
|
};
|
|
41
|
-
/**
|
|
41
|
+
/**
|
|
42
|
+
* Fabric's own manifest entries: they never register chat providers. Entries
|
|
43
|
+
* of bundled Pi packages (pi-coralbricks-provider) are not Fabric's own: they
|
|
44
|
+
* stay probe candidates, so the bundled provider resolves without loading
|
|
45
|
+
* Fabric's main extension.
|
|
46
|
+
*/
|
|
42
47
|
export declare function fabricExtensionEntries(moduleUrl?: string): string[];
|
|
43
48
|
/**
|
|
44
49
|
* Find the extension registrations that make `model` resolvable in a child
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-bridge.d.ts","sourceRoot":"","sources":["../../src/agents/provider-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAmB,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"provider-bridge.d.ts","sourceRoot":"","sources":["../../src/agents/provider-bridge.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAmB,MAAM,iCAAiC,CAAC;AAGrG;;;GAGG;AACH,eAAO,MAAM,yBAAyB,8BAA8B,CAAC;AAErE,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,cAAc,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,OAAO,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/D;AAED,MAAM,WAAW,gCAAgC;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7B;AAED,KAAK,KAAK,GAAG,cAAc,iCAAiC,CAAC,CAAC;AAE9D,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAKvF;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,QAAQ,EAAE,MAAM,GACf;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CASrC;AAcD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,SAAkB,GAAG,MAAM,EAAE,CAgB5E;AA0CD;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,gCAAgC,EACzC,GAAG,CAAC,EAAE,KAAK,GACV,OAAO,CAAC,8BAA8B,GAAG,SAAS,CAAC,CA4CrD;AAED;;;;;GAKG;AACH,wBAA8B,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlF"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loadHostSdk
|
|
3
|
+
} from "../chunks/chunk-GQGXQCCO.js";
|
|
4
|
+
|
|
1
5
|
// src/agents/provider-bridge.ts
|
|
2
6
|
import fs from "node:fs";
|
|
3
7
|
import path from "node:path";
|
|
@@ -26,13 +30,14 @@ var realPath = (file) => {
|
|
|
26
30
|
return path.resolve(file);
|
|
27
31
|
}
|
|
28
32
|
};
|
|
33
|
+
var isBundledPackageEntry = (entry) => entry.replace(/\\/g, "/").replace(/^(?:\.\/)+/, "").startsWith("node_modules/");
|
|
29
34
|
function fabricExtensionEntries(moduleUrl = import.meta.url) {
|
|
30
35
|
const root = path.resolve(path.dirname(fileURLToPath(moduleUrl)), "..", "..");
|
|
31
36
|
try {
|
|
32
37
|
const manifest = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
|
|
33
38
|
if (manifest.name !== "pi-fabric") return [];
|
|
34
39
|
const entries = [manifest.main, ...Array.isArray(manifest.pi?.extensions) ? manifest.pi.extensions : []];
|
|
35
|
-
return entries.filter((entry) => typeof entry === "string").map((entry) => path.resolve(root, entry));
|
|
40
|
+
return entries.filter((entry) => typeof entry === "string" && !isBundledPackageEntry(entry)).map((entry) => path.resolve(root, entry));
|
|
36
41
|
} catch {
|
|
37
42
|
return [];
|
|
38
43
|
}
|
|
@@ -95,8 +100,8 @@ async function resolveExtensionProviders(options, sdk) {
|
|
|
95
100
|
async function fabricProviderBridge(pi) {
|
|
96
101
|
const model = process.env[PROVIDER_BRIDGE_MODEL_ENV]?.trim();
|
|
97
102
|
if (!model) return;
|
|
98
|
-
const
|
|
99
|
-
const found = await resolveExtensionProviders({ model, cwd: process.cwd(), agentDir: getAgentDir() });
|
|
103
|
+
const sdk = await loadHostSdk();
|
|
104
|
+
const found = await resolveExtensionProviders({ model, cwd: process.cwd(), agentDir: sdk.getAgentDir() }, sdk);
|
|
100
105
|
if (!found) return;
|
|
101
106
|
for (const { name, config } of found.configs) pi.registerProvider(name, config);
|
|
102
107
|
for (const { provider } of found.natives) pi.registerProvider(provider);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/agents/provider-bridge.ts"],
|
|
4
|
-
"sourcesContent": ["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Provider } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI, ProviderConfig, SettingsManager } from \"@earendil-works/pi-coding-agent\";\n\n/**\n * The `provider/id` key a Pi child launched with `extensions: false` must\n * resolve. The worker sets it only when it also loads this bridge with `-e`.\n */\nexport const PROVIDER_BRIDGE_MODEL_ENV = \"PI_FABRIC_EXTENSION_MODEL\";\n\nexport interface ExtensionProviderRegistrations {\n configs: Array<{ name: string; config: ProviderConfig; extensionPath: string }>;\n natives: Array<{ provider: Provider; extensionPath: string }>;\n}\n\nexport interface ResolveExtensionProvidersOptions {\n model: string;\n cwd: string;\n agentDir: string;\n /** Extension entry files never probed (Fabric's own entries by default). */\n exclude?: readonly string[];\n}\n\ntype PiSdk = typeof import(\"@earendil-works/pi-coding-agent\");\n\n/** Split a canonical `provider/id` key at its first slash. */\nexport function parseModelKey(key: string): { provider: string; id: string } | undefined {\n const value = key.trim();\n const slash = value.indexOf(\"/\");\n if (slash <= 0 || slash === value.length - 1) return undefined;\n return { provider: value.slice(0, slash), id: value.slice(slash + 1) };\n}\n\n/**\n * Probe extensions whose own path names the provider first (the usual\n * `pi-<provider>-provider` package), so the common case runs one registration\n * function instead of every installed extension.\n */\nexport function orderProviderCandidates(\n paths: readonly string[],\n provider: string,\n): { named: string[]; rest: string[] } {\n const needle = provider.toLowerCase();\n const named: string[] = [];\n const rest: string[] = [];\n for (const candidate of paths) {\n const tail = candidate.split(/[\\\\/]+/).filter(Boolean).slice(-3);\n (tail.some((segment) => segment.toLowerCase().includes(needle)) ? named : rest).push(candidate);\n }\n return { named, rest };\n}\n\nconst realPath = (file: string): string => {\n try {\n return fs.realpathSync(file);\n } catch {\n return path.resolve(file);\n }\n};\n\n/** Fabric's own manifest entries: they never register chat providers. */\nexport function fabricExtensionEntries(moduleUrl = import.meta.url): string[] {\n const root = path.resolve(path.dirname(fileURLToPath(moduleUrl)), \"..\", \"..\");\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf8\")) as {\n name?: unknown;\n main?: unknown;\n pi?: { extensions?: unknown };\n };\n if (manifest.name !== \"pi-fabric\") return [];\n const entries = [manifest.main, ...(Array.isArray(manifest.pi?.extensions) ? manifest.pi.extensions : [])];\n return entries.filter((entry): entry is string => typeof entry === \"string\").map((entry) => path.resolve(root, entry));\n } catch {\n return [];\n }\n}\n\nconst emptyRegistrations = (): ExtensionProviderRegistrations => ({ configs: [], natives: [] });\n\n/**\n * Load extension paths with Pi's own loader into an isolated runtime and keep\n * only the requested provider's registrations. The loaded extensions are\n * discarded: their tools, commands, flags, shortcuts, renderers, and event\n * handlers never bind to the child session, and their event bus is private.\n */\nasync function loadProviderRegistrations(\n sdk: PiSdk,\n paths: readonly string[],\n provider: string,\n options: { cwd: string; agentDir: string; settingsManager: SettingsManager },\n failures: string[],\n): Promise<ExtensionProviderRegistrations> {\n if (paths.length === 0) return emptyRegistrations();\n const loader = new sdk.DefaultResourceLoader({\n cwd: options.cwd,\n agentDir: options.agentDir,\n settingsManager: options.settingsManager,\n noExtensions: true,\n additionalExtensionPaths: [...paths],\n noSkills: true,\n noPromptTemplates: true,\n noThemes: true,\n noContextFiles: true,\n });\n await loader.reload();\n const { runtime, errors } = loader.getExtensions();\n failures.push(...errors.map((error) => error.path));\n return {\n configs: runtime.pendingProviderRegistrations\n .filter((registration) => registration.name === provider)\n .map(({ name, config, extensionPath }) => ({ name, config, extensionPath })),\n natives: runtime.pendingNativeProviderRegistrations\n .filter((registration) => registration.provider.id === provider)\n .map(({ provider: registered, extensionPath }) => ({ provider: registered, extensionPath })),\n };\n}\n\n/**\n * Find the extension registrations that make `model` resolvable in a child\n * without its other extensions. Returns `undefined` when Pi already knows the\n * model (built in, models.json, or a cached catalog), so those children keep\n * their exact extension-free behaviour. Throws an actionable error when no\n * installed extension registers the provider.\n */\nexport async function resolveExtensionProviders(\n options: ResolveExtensionProvidersOptions,\n sdk?: PiSdk,\n): Promise<ExtensionProviderRegistrations | undefined> {\n const key = parseModelKey(options.model);\n if (!key) return undefined;\n const pi = sdk ?? await import(\"@earendil-works/pi-coding-agent\");\n const models = await pi.ModelRuntime.create({\n authPath: path.join(options.agentDir, \"auth.json\"),\n modelsPath: path.join(options.agentDir, \"models.json\"),\n refreshOnCreate: false,\n });\n if (models.getModel(key.provider, key.id)) return undefined;\n await models.refresh({ allowNetwork: false, signal: AbortSignal.timeout(15_000) });\n if (models.getModel(key.provider, key.id)) return undefined;\n\n // Same trust a headless child applies without consulting extension\n // project_trust handlers: those belong to the extensions left out here.\n const untrusted = pi.SettingsManager.create(options.cwd, options.agentDir, { projectTrusted: false });\n const trusted = !pi.hasTrustRequiringProjectResources(options.cwd) ||\n (new pi.ProjectTrustStore(options.agentDir).get(options.cwd) ?? untrusted.getDefaultProjectTrust() === \"always\");\n const settingsManager = trusted\n ? pi.SettingsManager.create(options.cwd, options.agentDir, { projectTrusted: true })\n : untrusted;\n const resolved = await new pi.DefaultPackageManager({\n cwd: options.cwd,\n agentDir: options.agentDir,\n settingsManager,\n }).resolve();\n const excluded = new Set((options.exclude ?? fabricExtensionEntries()).map(realPath));\n const candidates = resolved.extensions\n .filter((resource) => resource.enabled && !resource.path.startsWith(\"builtin:\"))\n .map((resource) => resource.path)\n .filter((candidate) => !excluded.has(realPath(candidate)));\n const { named, rest } = orderProviderCandidates(candidates, key.provider);\n const context = { cwd: options.cwd, agentDir: options.agentDir, settingsManager };\n const failures: string[] = [];\n for (const group of [named, rest]) {\n const found = await loadProviderRegistrations(pi, group, key.provider, context, failures);\n if (found.configs.length > 0 || found.natives.length > 0) return found;\n }\n throw new Error(\n `Model \"${options.model}\" needs provider \"${key.provider}\", which is not built into Pi or defined in models.json, ` +\n \"and no installed Pi extension registers it for this extensions: false child. \" +\n \"Install the extension that provides it, or run the child with extensions: true.\" +\n (failures.length > 0 ? ` Extensions that failed to load while searching: ${[...new Set(failures)].join(\", \")}.` : \"\"),\n );\n}\n\n/**\n * Loaded with `-e` into Pi children launched with `extensions: false`. It\n * registers only the requested model's provider, as its extension registered\n * it, so credentials still resolve in the child through auth.json, the\n * environment, or the credential store. Nothing else from that extension loads.\n */\nexport default async function fabricProviderBridge(pi: ExtensionAPI): Promise<void> {\n const model = process.env[PROVIDER_BRIDGE_MODEL_ENV]?.trim();\n if (!model) return;\n const
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { Provider } from \"@earendil-works/pi-ai\";\nimport type { ExtensionAPI, ProviderConfig, SettingsManager } from \"@earendil-works/pi-coding-agent\";\nimport { loadHostSdk } from \"../core/host-sdk.js\";\n\n/**\n * The `provider/id` key a Pi child launched with `extensions: false` must\n * resolve. The worker sets it only when it also loads this bridge with `-e`.\n */\nexport const PROVIDER_BRIDGE_MODEL_ENV = \"PI_FABRIC_EXTENSION_MODEL\";\n\nexport interface ExtensionProviderRegistrations {\n configs: Array<{ name: string; config: ProviderConfig; extensionPath: string }>;\n natives: Array<{ provider: Provider; extensionPath: string }>;\n}\n\nexport interface ResolveExtensionProvidersOptions {\n model: string;\n cwd: string;\n agentDir: string;\n /** Extension entry files never probed (Fabric's own entries by default). */\n exclude?: readonly string[];\n}\n\ntype PiSdk = typeof import(\"@earendil-works/pi-coding-agent\");\n\n/** Split a canonical `provider/id` key at its first slash. */\nexport function parseModelKey(key: string): { provider: string; id: string } | undefined {\n const value = key.trim();\n const slash = value.indexOf(\"/\");\n if (slash <= 0 || slash === value.length - 1) return undefined;\n return { provider: value.slice(0, slash), id: value.slice(slash + 1) };\n}\n\n/**\n * Probe extensions whose own path names the provider first (the usual\n * `pi-<provider>-provider` package), so the common case runs one registration\n * function instead of every installed extension.\n */\nexport function orderProviderCandidates(\n paths: readonly string[],\n provider: string,\n): { named: string[]; rest: string[] } {\n const needle = provider.toLowerCase();\n const named: string[] = [];\n const rest: string[] = [];\n for (const candidate of paths) {\n const tail = candidate.split(/[\\\\/]+/).filter(Boolean).slice(-3);\n (tail.some((segment) => segment.toLowerCase().includes(needle)) ? named : rest).push(candidate);\n }\n return { named, rest };\n}\n\nconst realPath = (file: string): string => {\n try {\n return fs.realpathSync(file);\n } catch {\n return path.resolve(file);\n }\n};\n\n/** A manifest entry that loads a Pi package Fabric bundles (`node_modules/<package>/...`). */\nconst isBundledPackageEntry = (entry: string): boolean =>\n entry.replace(/\\\\/g, \"/\").replace(/^(?:\\.\\/)+/, \"\").startsWith(\"node_modules/\");\n\n/**\n * Fabric's own manifest entries: they never register chat providers. Entries\n * of bundled Pi packages (pi-coralbricks-provider) are not Fabric's own: they\n * stay probe candidates, so the bundled provider resolves without loading\n * Fabric's main extension.\n */\nexport function fabricExtensionEntries(moduleUrl = import.meta.url): string[] {\n const root = path.resolve(path.dirname(fileURLToPath(moduleUrl)), \"..\", \"..\");\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(root, \"package.json\"), \"utf8\")) as {\n name?: unknown;\n main?: unknown;\n pi?: { extensions?: unknown };\n };\n if (manifest.name !== \"pi-fabric\") return [];\n const entries = [manifest.main, ...(Array.isArray(manifest.pi?.extensions) ? manifest.pi.extensions : [])];\n return entries\n .filter((entry): entry is string => typeof entry === \"string\" && !isBundledPackageEntry(entry))\n .map((entry) => path.resolve(root, entry));\n } catch {\n return [];\n }\n}\n\nconst emptyRegistrations = (): ExtensionProviderRegistrations => ({ configs: [], natives: [] });\n\n/**\n * Load extension paths with Pi's own loader into an isolated runtime and keep\n * only the requested provider's registrations. The loaded extensions are\n * discarded: their tools, commands, flags, shortcuts, renderers, and event\n * handlers never bind to the child session, and their event bus is private.\n */\nasync function loadProviderRegistrations(\n sdk: PiSdk,\n paths: readonly string[],\n provider: string,\n options: { cwd: string; agentDir: string; settingsManager: SettingsManager },\n failures: string[],\n): Promise<ExtensionProviderRegistrations> {\n if (paths.length === 0) return emptyRegistrations();\n const loader = new sdk.DefaultResourceLoader({\n cwd: options.cwd,\n agentDir: options.agentDir,\n settingsManager: options.settingsManager,\n noExtensions: true,\n additionalExtensionPaths: [...paths],\n noSkills: true,\n noPromptTemplates: true,\n noThemes: true,\n noContextFiles: true,\n });\n await loader.reload();\n const { runtime, errors } = loader.getExtensions();\n failures.push(...errors.map((error) => error.path));\n return {\n configs: runtime.pendingProviderRegistrations\n .filter((registration) => registration.name === provider)\n .map(({ name, config, extensionPath }) => ({ name, config, extensionPath })),\n natives: runtime.pendingNativeProviderRegistrations\n .filter((registration) => registration.provider.id === provider)\n .map(({ provider: registered, extensionPath }) => ({ provider: registered, extensionPath })),\n };\n}\n\n/**\n * Find the extension registrations that make `model` resolvable in a child\n * without its other extensions. Returns `undefined` when Pi already knows the\n * model (built in, models.json, or a cached catalog), so those children keep\n * their exact extension-free behaviour. Throws an actionable error when no\n * installed extension registers the provider.\n */\nexport async function resolveExtensionProviders(\n options: ResolveExtensionProvidersOptions,\n sdk?: PiSdk,\n): Promise<ExtensionProviderRegistrations | undefined> {\n const key = parseModelKey(options.model);\n if (!key) return undefined;\n const pi = sdk ?? await import(\"@earendil-works/pi-coding-agent\");\n const models = await pi.ModelRuntime.create({\n authPath: path.join(options.agentDir, \"auth.json\"),\n modelsPath: path.join(options.agentDir, \"models.json\"),\n refreshOnCreate: false,\n });\n if (models.getModel(key.provider, key.id)) return undefined;\n await models.refresh({ allowNetwork: false, signal: AbortSignal.timeout(15_000) });\n if (models.getModel(key.provider, key.id)) return undefined;\n\n // Same trust a headless child applies without consulting extension\n // project_trust handlers: those belong to the extensions left out here.\n const untrusted = pi.SettingsManager.create(options.cwd, options.agentDir, { projectTrusted: false });\n const trusted = !pi.hasTrustRequiringProjectResources(options.cwd) ||\n (new pi.ProjectTrustStore(options.agentDir).get(options.cwd) ?? untrusted.getDefaultProjectTrust() === \"always\");\n const settingsManager = trusted\n ? pi.SettingsManager.create(options.cwd, options.agentDir, { projectTrusted: true })\n : untrusted;\n const resolved = await new pi.DefaultPackageManager({\n cwd: options.cwd,\n agentDir: options.agentDir,\n settingsManager,\n }).resolve();\n const excluded = new Set((options.exclude ?? fabricExtensionEntries()).map(realPath));\n const candidates = resolved.extensions\n .filter((resource) => resource.enabled && !resource.path.startsWith(\"builtin:\"))\n .map((resource) => resource.path)\n .filter((candidate) => !excluded.has(realPath(candidate)));\n const { named, rest } = orderProviderCandidates(candidates, key.provider);\n const context = { cwd: options.cwd, agentDir: options.agentDir, settingsManager };\n const failures: string[] = [];\n for (const group of [named, rest]) {\n const found = await loadProviderRegistrations(pi, group, key.provider, context, failures);\n if (found.configs.length > 0 || found.natives.length > 0) return found;\n }\n throw new Error(\n `Model \"${options.model}\" needs provider \"${key.provider}\", which is not built into Pi or defined in models.json, ` +\n \"and no installed Pi extension registers it for this extensions: false child. \" +\n \"Install the extension that provides it, or run the child with extensions: true.\" +\n (failures.length > 0 ? ` Extensions that failed to load while searching: ${[...new Set(failures)].join(\", \")}.` : \"\"),\n );\n}\n\n/**\n * Loaded with `-e` into Pi children launched with `extensions: false`. It\n * registers only the requested model's provider, as its extension registered\n * it, so credentials still resolve in the child through auth.json, the\n * environment, or the credential store. Nothing else from that extension loads.\n */\nexport default async function fabricProviderBridge(pi: ExtensionAPI): Promise<void> {\n const model = process.env[PROVIDER_BRIDGE_MODEL_ENV]?.trim();\n if (!model) return;\n const sdk = await loadHostSdk();\n const found = await resolveExtensionProviders({ model, cwd: process.cwd(), agentDir: sdk.getAgentDir() }, sdk);\n if (!found) return;\n for (const { name, config } of found.configs) pi.registerProvider(name, config);\n for (const { provider } of found.natives) pi.registerProvider(provider);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../src/capture/interceptor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EACf,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAyB,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AASnD,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACjD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,EAAE,mBAAmB,CAAC;IAC7B,aAAa,CAAC,EAAE,uBAAuB,CAAC;IAUxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAiCD,KAAK,0BAA0B,GAAG;IAChC,SAAS,EAAE,eAAe,CAAC;CAC5B,CAAC;AAaF,eAAO,MAAM,iCAAiC,GAC5C,WAAW,MAAM,KAChB,OAAO,CAAC,0BAA0B,EAAE,CAuBtC,CAAC;
|
|
1
|
+
{"version":3,"file":"interceptor.d.ts","sourceRoot":"","sources":["../../src/capture/interceptor.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,eAAe,EAEf,cAAc,EACf,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAyB,KAAK,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AASnD,MAAM,WAAW,+BAA+B;IAC9C,SAAS,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAAC;IACjD,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,4BAA4B;IAC3C,gBAAgB,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAChD,OAAO,EAAE,mBAAmB,CAAC;IAC7B,aAAa,CAAC,EAAE,uBAAuB,CAAC;IAUxC,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAiCD,KAAK,0BAA0B,GAAG;IAChC,SAAS,EAAE,eAAe,CAAC;CAC5B,CAAC;AAaF,eAAO,MAAM,iCAAiC,GAC5C,WAAW,MAAM,KAChB,OAAO,CAAC,0BAA0B,EAAE,CAuBtC,CAAC;AAkLF,eAAO,MAAM,4BAA4B,GACvC,SAAS,4BAA4B,KACpC,OAAO,CAAC,+BAA+B,CA0CzC,CAAC"}
|
|
@@ -49,13 +49,38 @@ function checkRequest(value, maxBytes) {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
var probability = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 && v <= 1;
|
|
52
|
+
function reportedUsage(value) {
|
|
53
|
+
if (!object(value) || !object(value.usage)) return void 0;
|
|
54
|
+
const { input_tokens, output_tokens } = value.usage;
|
|
55
|
+
return [input_tokens, output_tokens].every((v) => Number.isSafeInteger(v) && v >= 0) ? { input_tokens, output_tokens } : void 0;
|
|
56
|
+
}
|
|
57
|
+
var JevBilledError = class extends Error {
|
|
58
|
+
constructor(message, usage) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.usage = usage;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var JevInvalidResponseError = class extends JevBilledError {
|
|
64
|
+
};
|
|
65
|
+
var JEV_TRANSIENT_HTTP_STATUSES = [408, 429, 500, 502, 503, 504, 529];
|
|
66
|
+
var JevTransientHttpError = class extends JevBilledError {
|
|
67
|
+
constructor(message, usage, status, retryAfterMs) {
|
|
68
|
+
super(message, usage);
|
|
69
|
+
this.status = status;
|
|
70
|
+
this.retryAfterMs = retryAfterMs;
|
|
71
|
+
}
|
|
72
|
+
get guestFields() {
|
|
73
|
+
return { status: this.status, ...this.retryAfterMs === void 0 ? {} : { retryAfterMs: this.retryAfterMs } };
|
|
74
|
+
}
|
|
75
|
+
};
|
|
52
76
|
function checkResponse(value, request) {
|
|
77
|
+
const message = "TypeSafe returned an invalid typed response";
|
|
78
|
+
const reported = reportedUsage(value);
|
|
79
|
+
if (!reported || !object(value)) throw new Error(message);
|
|
53
80
|
const invalid = () => {
|
|
54
|
-
throw new
|
|
81
|
+
throw new JevInvalidResponseError(message, reported);
|
|
55
82
|
};
|
|
56
|
-
if (
|
|
57
|
-
const usage = value.usage;
|
|
58
|
-
if (![usage.input_tokens, usage.output_tokens].every((v) => Number.isSafeInteger(v) && v >= 0)) return invalid();
|
|
83
|
+
if (typeof value.model !== "string" || value.model.length > 128 || !object(value.answers)) return invalid();
|
|
59
84
|
if (Object.keys(value.answers).length !== Object.keys(request.questions).length) return invalid();
|
|
60
85
|
const entries = [];
|
|
61
86
|
for (const [id, question] of Object.entries(request.questions)) {
|
|
@@ -79,10 +104,7 @@ function checkResponse(value, request) {
|
|
|
79
104
|
entries.push([id, { type: "score", score: a.score, confidence: a.confidence, probabilities, legend }]);
|
|
80
105
|
}
|
|
81
106
|
}
|
|
82
|
-
return { model: value.model, answers: Object.fromEntries(entries), usage:
|
|
83
|
-
input_tokens: usage.input_tokens,
|
|
84
|
-
output_tokens: usage.output_tokens
|
|
85
|
-
} };
|
|
107
|
+
return { model: value.model, answers: Object.fromEntries(entries), usage: reported };
|
|
86
108
|
}
|
|
87
109
|
var schemaKeys = /* @__PURE__ */ new Set(["type", "properties", "required", "additionalProperties", "items", "enum", "const", "anyOf", "oneOf", "allOf", "minimum", "maximum", "minLength", "maxLength", "minItems", "maxItems", "minProperties", "maxProperties", "description", "title"]);
|
|
88
110
|
function checkSchema(schema) {
|
|
@@ -118,8 +140,13 @@ export {
|
|
|
118
140
|
jsonText,
|
|
119
141
|
object,
|
|
120
142
|
checkRequest,
|
|
143
|
+
reportedUsage,
|
|
144
|
+
JevBilledError,
|
|
145
|
+
JevInvalidResponseError,
|
|
146
|
+
JEV_TRANSIENT_HTTP_STATUSES,
|
|
147
|
+
JevTransientHttpError,
|
|
121
148
|
checkResponse,
|
|
122
149
|
checkSchema,
|
|
123
150
|
checkValue
|
|
124
151
|
};
|
|
125
|
-
//# sourceMappingURL=chunk-
|
|
152
|
+
//# sourceMappingURL=chunk-7PPIKFT5.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/jev/validation.ts"],
|
|
4
|
+
"sourcesContent": ["import { Value } from \"typebox/value\";\nimport { isJevModelId } from \"./routes.js\";\nimport type { JevJson, JevRequest, JevResponse, JevAnswer } from \"./types.js\";\n\nexport function jsonText(value: unknown, maxBytes: number, label: string): string {\n let nodes = 0;\n const visit = (v: unknown, depth: number): void => {\n if (++nodes > 100_000 || depth > 32) throw new Error(`${label} exceeds JSON complexity limits`);\n if (v === null || typeof v === \"string\" || typeof v === \"boolean\") return;\n if (typeof v === \"number\" && Number.isFinite(v)) return;\n if (Array.isArray(v)) { for (const item of v) visit(item, depth + 1); return; }\n if (typeof v === \"object\" && v !== null && Object.getPrototypeOf(v) === Object.prototype) {\n for (const item of Object.values(v)) visit(item, depth + 1);\n return;\n }\n throw new Error(`${label} must contain only finite JSON values`);\n };\n visit(value, 0);\n const text = JSON.stringify(value);\n if (Buffer.byteLength(text) > maxBytes) throw new Error(`${label} exceeds ${maxBytes} bytes`);\n return text;\n}\nexport const object = (v: unknown): v is Record<string, unknown> =>\n typeof v === \"object\" && v !== null && !Array.isArray(v);\nconst description = (v: unknown): boolean => typeof v === \"string\" || object(v) || Array.isArray(v);\nconst keysOnly = (v: Record<string, unknown>, keys: string[]) => Object.keys(v).every(k => keys.includes(k));\n\nexport function checkRequest(value: unknown, maxBytes: number): asserts value is JevRequest {\n jsonText(value, maxBytes, \"Jev request\");\n if (!object(value) || !keysOnly(value, [\"state\", \"questions\", \"model\"]) || !description(value.state) ||\n !object(value.questions) || Object.keys(value.questions).length < 1 || Object.keys(value.questions).length > 128 ||\n (value.model !== undefined && (typeof value.model !== \"string\" || !isJevModelId(value.model)))) {\n throw new Error(\"Invalid Jev request: provide state, 1\u2013128 questions, and an optional model ID\");\n }\n for (const [id, q] of Object.entries(value.questions)) {\n if (!id || id.length > 128 || !object(q) || !keysOnly(q, [\"type\", \"instructions\", \"criteria\"]) || !description(q.instructions))\n throw new Error(\"Invalid Jev question: each question needs a type and complete instructions\");\n if (q.type === \"choice\") {\n if (!object(q.criteria) || Object.keys(q.criteria).length < 1 || Object.keys(q.criteria).length > 255 ||\n !Object.entries(q.criteria).every(([key, v]) => key.length > 0 && key.length <= 256 && (v === null || description(v))))\n throw new Error(\"Choice requires 1\u2013255 named options with descriptions or null\");\n } else if (q.type === \"score\") {\n if (!Array.isArray(q.criteria) || q.criteria.length < 2 || q.criteria.length > 10 || !q.criteria.every(description))\n throw new Error(\"Score requires 2\u201310 ordered descriptive levels\");\n } else if (q.type === \"noul\") {\n if (q.criteria !== undefined && (!object(q.criteria) || !keysOnly(q.criteria, [\"true\", \"false\"]) || !Object.values(q.criteria).every(description)))\n throw new Error(\"Noul criteria may describe true and false only\");\n } else throw new Error(\"Jev supports choice, score, and noul\u2014not free-text generation\");\n }\n}\nconst probability = (v: unknown): v is number => typeof v === \"number\" && Number.isFinite(v) && v >= 0 && v <= 1;\nexport interface JevUsage { input_tokens: number; output_tokens: number }\n/** Well-formed reported usage, or undefined. Never treats missing usage as zero. */\nexport function reportedUsage(value: unknown): JevUsage | undefined {\n if (!object(value) || !object(value.usage)) return undefined;\n const { input_tokens, output_tokens } = value.usage;\n return [input_tokens, output_tokens].every(v => Number.isSafeInteger(v) && (v as number) >= 0)\n ? { input_tokens: input_tokens as number, output_tokens: output_tokens as number } : undefined;\n}\n/**\n * A failed evaluation whose cost is known. A program bills `usage` and may\n * keep evaluating; every other failure is unknown usage and closes inference.\n */\nexport class JevBilledError extends Error {\n constructor(message: string, readonly usage: JevUsage) { super(message); }\n}\n/**\n * A typed response whose answers are unusable but whose usage is well formed.\n * The answers are never surfaced; the reported usage is still billed against\n * the caller's budget. Responses without valid usage throw a plain Error.\n */\nexport class JevInvalidResponseError extends JevBilledError {}\n/** HTTP statuses a received Jev response may carry that justify a later retry. */\nexport const JEV_TRANSIENT_HTTP_STATUSES: readonly number[] = [408, 429, 500, 502, 503, 504, 529];\n/**\n * A received transient HTTP error. `usage` is the error body's reported usage,\n * or the fixed cost: the request body's UTF-8 bytes as input tokens, 0 output.\n * `guestFields` crosses into the program's error object; the body never does.\n */\nexport class JevTransientHttpError extends JevBilledError {\n constructor(message: string, usage: JevUsage, readonly status: number, readonly retryAfterMs: number | undefined) { super(message, usage); }\n get guestFields(): Record<string, number> {\n return { status: this.status, ...(this.retryAfterMs === undefined ? {} : { retryAfterMs: this.retryAfterMs }) };\n }\n}\nexport function checkResponse(value: unknown, request: JevRequest): JevResponse {\n const message = \"TypeSafe returned an invalid typed response\";\n const reported = reportedUsage(value);\n if (!reported || !object(value)) throw new Error(message);\n const invalid = (): never => { throw new JevInvalidResponseError(message, reported); };\n if (typeof value.model !== \"string\" || value.model.length > 128 || !object(value.answers)) return invalid();\n if (Object.keys(value.answers).length !== Object.keys(request.questions).length) return invalid();\n const entries: Array<[string, JevAnswer]> = [];\n for (const [id, question] of Object.entries(request.questions)) {\n const a = Object.hasOwn(value.answers, id) ? value.answers[id] : undefined;\n if (!object(a) || a.type !== question.type) return invalid();\n if (question.type === \"noul\") {\n if (!probability(a.noul)) return invalid();\n entries.push([id, { type: \"noul\", noul: a.noul }]);\n continue;\n }\n const keys = question.type === \"choice\" ? Object.keys(question.criteria) : question.criteria.map((_, i) => String(i));\n const p = a.probabilities;\n if (!probability(a.confidence) || !object(p) || Object.keys(p).length !== keys.length ||\n !keys.every(k => Object.hasOwn(p, k) && probability(p[k])) ||\n Math.abs(Object.values(p).reduce<number>((sum, v) => sum + (v as number), 0) - 1) > 0.02) return invalid();\n const probabilities = Object.fromEntries(keys.map(k => [k, p[k] as number]));\n if (question.type === \"choice\") {\n if (typeof a.choice !== \"string\" || !Object.hasOwn(question.criteria, a.choice)) return invalid();\n entries.push([id, { type: \"choice\", choice: a.choice, confidence: a.confidence, probabilities }]);\n } else {\n if (typeof a.score !== \"number\" || !Number.isFinite(a.score) || a.score < 0 || a.score > keys.length - 1) return invalid();\n // Rubrics come from the request, not arbitrary server-produced content.\n const legend = Object.fromEntries(question.criteria.map((level, i) => [String(i), level]));\n entries.push([id, { type: \"score\", score: a.score, confidence: a.confidence, probabilities, legend }]);\n }\n }\n return { model: value.model, answers: Object.fromEntries(entries), usage: reported };\n}\n\nconst schemaKeys = new Set([\"type\", \"properties\", \"required\", \"additionalProperties\", \"items\", \"enum\", \"const\", \"anyOf\", \"oneOf\", \"allOf\", \"minimum\", \"maximum\", \"minLength\", \"maxLength\", \"minItems\", \"maxItems\", \"minProperties\", \"maxProperties\", \"description\", \"title\"]);\nexport function checkSchema(schema: unknown): asserts schema is Record<string, unknown> {\n jsonText(schema, 16_384, \"Program schema\");\n let nodes = 0;\n const visit = (s: unknown, depth: number): void => {\n if (!object(s) || ++nodes > 128 || depth > 12 || Object.keys(s).some(k => !schemaKeys.has(k)))\n throw new Error(\"Unsupported program schema; use the documented bounded JSON Schema subset (no references or regexes)\");\n if (s.type !== undefined && ![\"object\", \"array\", \"string\", \"number\", \"integer\", \"boolean\", \"null\"].includes(s.type as string)) throw new Error(\"Invalid schema type\");\n if (s.properties !== undefined) {\n if (!object(s.properties)) throw new Error(\"Schema properties must be an object\");\n Object.values(s.properties).forEach(v => visit(v, depth + 1));\n }\n if (s.required !== undefined && (!Array.isArray(s.required) || !s.required.every(v => typeof v === \"string\"))) throw new Error(\"Schema required must be a string array\");\n if (s.additionalProperties !== undefined && typeof s.additionalProperties !== \"boolean\") visit(s.additionalProperties, depth + 1);\n if (s.items !== undefined) visit(s.items, depth + 1);\n for (const k of [\"anyOf\", \"oneOf\", \"allOf\"]) if (s[k] !== undefined) {\n if (!Array.isArray(s[k]) || s[k].length < 1 || s[k].length > 16) throw new Error(\"Invalid schema alternatives\");\n s[k].forEach(v => visit(v, depth + 1));\n }\n for (const k of [\"minimum\", \"maximum\", \"minLength\", \"maxLength\", \"minItems\", \"maxItems\", \"minProperties\", \"maxProperties\"])\n if (s[k] !== undefined && (typeof s[k] !== \"number\" || !Number.isFinite(s[k]) || (!['minimum', 'maximum'].includes(k) && (!Number.isSafeInteger(s[k]) || s[k] < 0)))) throw new Error(\"Invalid schema bound\");\n if (s.enum !== undefined && (!Array.isArray(s.enum) || s.enum.length === 0 || s.enum.length > 256)) throw new Error(\"Invalid schema enum\");\n };\n visit(schema, 0);\n}\nexport function checkValue(schema: Record<string, unknown>, value: unknown, label: string): asserts value is JevJson {\n jsonText(value, 32_768, label);\n if (!Value.Check(schema, value)) throw new Error(`${label} does not match its declared schema`);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -28,6 +28,9 @@ import {
|
|
|
28
28
|
safeTerminalText,
|
|
29
29
|
singleCallProgressLine
|
|
30
30
|
} from "./chunk-U2UBUKNQ.js";
|
|
31
|
+
import {
|
|
32
|
+
FabricModelSelector
|
|
33
|
+
} from "./chunk-J7ZQERKA.js";
|
|
31
34
|
import {
|
|
32
35
|
configureHighlighting,
|
|
33
36
|
highlightCode,
|
|
@@ -38,9 +41,6 @@ import {
|
|
|
38
41
|
isActiveStatus,
|
|
39
42
|
orderAgentsByCreation
|
|
40
43
|
} from "./chunk-UTOBAZ5T.js";
|
|
41
|
-
import {
|
|
42
|
-
FabricModelSelector
|
|
43
|
-
} from "./chunk-J7ZQERKA.js";
|
|
44
44
|
import {
|
|
45
45
|
buildModelSource
|
|
46
46
|
} from "./chunk-CQFP2RCP.js";
|
|
@@ -83,7 +83,7 @@ import {
|
|
|
83
83
|
resolveFabricIdentity,
|
|
84
84
|
setModelSafely,
|
|
85
85
|
withTrajectoryRearmDirective
|
|
86
|
-
} from "./chunk-
|
|
86
|
+
} from "./chunk-QGP7AY2R.js";
|
|
87
87
|
import {
|
|
88
88
|
AgentTranscriptReader,
|
|
89
89
|
countNewlines,
|
|
@@ -113,13 +113,13 @@ import {
|
|
|
113
113
|
buildPeerCards,
|
|
114
114
|
readChildToolAllowlist
|
|
115
115
|
} from "./chunk-PYFJW3HC.js";
|
|
116
|
+
import {
|
|
117
|
+
resolveAgentDir
|
|
118
|
+
} from "./chunk-PBDDXBHY.js";
|
|
116
119
|
import {
|
|
117
120
|
closeScratch,
|
|
118
121
|
createScratch
|
|
119
122
|
} from "./chunk-5XBYFSI5.js";
|
|
120
|
-
import {
|
|
121
|
-
resolveAgentDir
|
|
122
|
-
} from "./chunk-PXAICAUT.js";
|
|
123
123
|
import {
|
|
124
124
|
DEFAULT_FABRIC_CONFIG,
|
|
125
125
|
NO_FOREGROUND,
|
|
@@ -138,7 +138,7 @@ import {
|
|
|
138
138
|
fabricExecTitleHintCached,
|
|
139
139
|
normalizeRunDisplay,
|
|
140
140
|
registerCompactionHook
|
|
141
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-TNPZBMYC.js";
|
|
142
142
|
import {
|
|
143
143
|
fabricWriteBindings
|
|
144
144
|
} from "./chunk-SZUXWOO7.js";
|
|
@@ -160,7 +160,7 @@ import {
|
|
|
160
160
|
ApprovalController,
|
|
161
161
|
FabricAutoApprovalClassifier,
|
|
162
162
|
FabricSessionApprovals
|
|
163
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-UQWBZKAN.js";
|
|
164
164
|
import {
|
|
165
165
|
getActiveRepairCompiler,
|
|
166
166
|
setActiveCompiledSurface
|
|
@@ -675,30 +675,52 @@ var entryRealmPackageRoot = () => {
|
|
|
675
675
|
}
|
|
676
676
|
return void 0;
|
|
677
677
|
};
|
|
678
|
+
var realPath = (file) => {
|
|
679
|
+
try {
|
|
680
|
+
return realpathSync(file);
|
|
681
|
+
} catch {
|
|
682
|
+
return file;
|
|
683
|
+
}
|
|
684
|
+
};
|
|
685
|
+
var isWithin = (directory, file) => {
|
|
686
|
+
const relative = path.relative(directory, file);
|
|
687
|
+
return relative !== "" && !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
688
|
+
};
|
|
689
|
+
var exportedExtensionRunner = async (entry) => {
|
|
690
|
+
try {
|
|
691
|
+
const module = await import(pathToFileURL(entry).href);
|
|
692
|
+
return isExtensionRunnerConstructor(module.ExtensionRunner) ? [module.ExtensionRunner] : [];
|
|
693
|
+
} catch {
|
|
694
|
+
return [];
|
|
695
|
+
}
|
|
696
|
+
};
|
|
697
|
+
var packageExtensionRunnerConstructors = async (packageRoot, entry) => {
|
|
698
|
+
const distDirectory = path.join(packageRoot, "dist");
|
|
699
|
+
const bundleDirectory = path.join(distDirectory, "bundle");
|
|
700
|
+
if (entry && isWithin(bundleDirectory, entry)) {
|
|
701
|
+
const bundled = await exportedExtensionRunner(path.join(bundleDirectory, "index.js"));
|
|
702
|
+
return bundled.length > 0 ? bundled : bundleExtensionRunnerConstructors(bundleDirectory);
|
|
703
|
+
}
|
|
704
|
+
const unbundled = await exportedExtensionRunner(path.join(distDirectory, "index.js"));
|
|
705
|
+
if (entry && isWithin(distDirectory, entry)) return unbundled;
|
|
706
|
+
return [...unbundled, ...await bundleExtensionRunnerConstructors(bundleDirectory)];
|
|
707
|
+
};
|
|
678
708
|
var extensionRunnerConstructors = async () => {
|
|
679
709
|
const constructors = /* @__PURE__ */ new Set();
|
|
710
|
+
const advertised = globalThis[HOST_RUNNERS_SYMBOL];
|
|
711
|
+
for (const Runner of advertised instanceof Set ? advertised : []) {
|
|
712
|
+
if (isExtensionRunnerConstructor(Runner)) constructors.add(Runner);
|
|
713
|
+
}
|
|
714
|
+
if (constructors.size > 0) return [...constructors];
|
|
680
715
|
const packageRoots = new Set(
|
|
681
|
-
[process.env.PI_PACKAGE_DIR, hostPackageRoot(), entryRealmPackageRoot()].filter(
|
|
682
|
-
(root) => typeof root === "string" && Boolean(root)
|
|
683
|
-
)
|
|
716
|
+
[process.env.PI_PACKAGE_DIR, hostPackageRoot(), entryRealmPackageRoot()].filter((root) => typeof root === "string" && Boolean(root)).map(realPath)
|
|
684
717
|
);
|
|
718
|
+
const entry = process.argv[1] ? realPath(process.argv[1]) : void 0;
|
|
685
719
|
for (const packageRoot of packageRoots) {
|
|
686
|
-
|
|
687
|
-
const hostEntry = path.join(packageRoot, "dist", "index.js");
|
|
688
|
-
const hostModule = await import(pathToFileURL(hostEntry).href);
|
|
689
|
-
if (hostModule.ExtensionRunner) constructors.add(hostModule.ExtensionRunner);
|
|
690
|
-
} catch {
|
|
691
|
-
}
|
|
692
|
-
for (const Runner of await bundleExtensionRunnerConstructors(
|
|
693
|
-
path.join(packageRoot, "dist", "bundle")
|
|
694
|
-
)) {
|
|
720
|
+
for (const Runner of await packageExtensionRunnerConstructors(packageRoot, entry)) {
|
|
695
721
|
constructors.add(Runner);
|
|
696
722
|
}
|
|
697
723
|
}
|
|
698
|
-
const advertised = globalThis[HOST_RUNNERS_SYMBOL];
|
|
699
|
-
for (const Runner of advertised instanceof Set ? advertised : []) {
|
|
700
|
-
if (isExtensionRunnerConstructor(Runner)) constructors.add(Runner);
|
|
701
|
-
}
|
|
702
724
|
if (constructors.size === 0) {
|
|
703
725
|
try {
|
|
704
726
|
const hostModule = await import("@earendil-works/pi-coding-agent");
|
|
@@ -747,9 +769,6 @@ var installRegisteredToolCapture = async (options) => {
|
|
|
747
769
|
};
|
|
748
770
|
};
|
|
749
771
|
|
|
750
|
-
// src/commands/fabric.ts
|
|
751
|
-
import "@earendil-works/pi-coding-agent";
|
|
752
|
-
|
|
753
772
|
// src/prewalk/arm.ts
|
|
754
773
|
var armFabricPrewalkSession = async (state, context, pi, input) => {
|
|
755
774
|
const { prewalk } = state.config;
|
|
@@ -4338,7 +4357,6 @@ var piHostCompatibilityWarning = (version = detectPiHostVersion()) => {
|
|
|
4338
4357
|
|
|
4339
4358
|
// src/ui/controller.ts
|
|
4340
4359
|
import path9 from "node:path";
|
|
4341
|
-
import * as piConversationHost from "@earendil-works/pi-coding-agent";
|
|
4342
4360
|
|
|
4343
4361
|
// src/ui/snapshot.ts
|
|
4344
4362
|
import { isDeepStrictEqual } from "node:util";
|
|
@@ -5061,9 +5079,10 @@ var FabricUiController = class {
|
|
|
5061
5079
|
this.#conversationOpen = true;
|
|
5062
5080
|
const epoch = this.#epoch;
|
|
5063
5081
|
try {
|
|
5064
|
-
const { initializeConversationHost } = await import("../ui/conversation-host.js");
|
|
5082
|
+
const [{ initializeConversationHost }, { loadHostSdk }] = await Promise.all([import("../ui/conversation-host.js"), import("../core/host-sdk.js")]);
|
|
5083
|
+
const conversationHost = await loadHostSdk();
|
|
5065
5084
|
if (epoch !== this.#epoch) return;
|
|
5066
|
-
initializeConversationHost(
|
|
5085
|
+
initializeConversationHost(conversationHost);
|
|
5067
5086
|
const [{ FabricConversationView, FabricConversationState }, { conversationTargets, resolveConversationTarget }, { readConversationAppearance }, { NativeConversationReader }, { imageSafeCustom }] = await Promise.all([import("../ui/conversation.js"), import("../ui/conversation-targets.js"), import("../ui/conversation-chrome.js"), import("../ui/conversation-native-reader.js"), import("../ui/image-overlays.js")]);
|
|
5068
5087
|
if (epoch !== this.#epoch) return;
|
|
5069
5088
|
this.#refresh();
|
|
@@ -6602,4 +6621,4 @@ export {
|
|
|
6602
6621
|
FABRIC_MANAGED_HOST_VERSION,
|
|
6603
6622
|
createFabricExtension
|
|
6604
6623
|
};
|
|
6605
|
-
//# sourceMappingURL=chunk-
|
|
6624
|
+
//# sourceMappingURL=chunk-GFBOLBU2.js.map
|