pi-fabric 0.111.0 → 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/dist/agents/provider-bridge.d.ts +0 -16
- package/dist/agents/provider-bridge.d.ts.map +1 -1
- package/dist/agents/provider-bridge.js +5 -31
- 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/jev-decisions.md +6 -1
- package/docs/jev.md +9 -3
- package/package.json +1 -1
- 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
|
@@ -53,22 +53,6 @@ export declare function fabricExtensionEntries(moduleUrl?: string): string[];
|
|
|
53
53
|
* installed extension registers the provider.
|
|
54
54
|
*/
|
|
55
55
|
export declare function resolveExtensionProviders(options: ResolveExtensionProvidersOptions, sdk?: PiSdk): Promise<ExtensionProviderRegistrations | undefined>;
|
|
56
|
-
/**
|
|
57
|
-
* The SDK entry of the bundled Pi CLI running this process, if it is one. The
|
|
58
|
-
* published `pi` bin is `dist/bundle/cli.js`; its `dist/bundle/index.js` SDK
|
|
59
|
-
* entry is built from the same chunks the CLI has already evaluated.
|
|
60
|
-
*/
|
|
61
|
-
export declare function hostBundleSdkEntry(cliPath?: string | undefined): string | undefined;
|
|
62
|
-
/**
|
|
63
|
-
* The host's own SDK. Pi imports this bridge natively (it is ESM JavaScript),
|
|
64
|
-
* so jiti's virtual modules do not apply, and a bare package import from here
|
|
65
|
-
* evaluates the separate unbundled SDK: about 1,800 more modules in the
|
|
66
|
-
* bundled CLI. Besides the startup cost, that CLI enables Node's compile cache,
|
|
67
|
-
* which serializes every one of those modules on exit; with a cold cache that
|
|
68
|
-
* held a Windows child past the worker's exit grace after it had settled.
|
|
69
|
-
* The bundle's SDK entry shares the CLI's already loaded chunks instead.
|
|
70
|
-
*/
|
|
71
|
-
export declare function loadHostSdk(cliPath?: string | undefined): Promise<PiSdk>;
|
|
72
56
|
/**
|
|
73
57
|
* Loaded with `-e` into Pi children launched with `extensions: false`. It
|
|
74
58
|
* registers only the requested model's provider, as its extension registered
|
|
@@ -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,7 +1,11 @@
|
|
|
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";
|
|
4
|
-
import { fileURLToPath
|
|
8
|
+
import { fileURLToPath } from "node:url";
|
|
5
9
|
var PROVIDER_BRIDGE_MODEL_ENV = "PI_FABRIC_EXTENSION_MODEL";
|
|
6
10
|
function parseModelKey(key) {
|
|
7
11
|
const value = key.trim();
|
|
@@ -93,34 +97,6 @@ async function resolveExtensionProviders(options, sdk) {
|
|
|
93
97
|
`Model "${options.model}" needs provider "${key.provider}", which is not built into Pi or defined in models.json, and no installed Pi extension registers it for this extensions: false child. Install the extension that provides it, or run the child with extensions: true.` + (failures.length > 0 ? ` Extensions that failed to load while searching: ${[...new Set(failures)].join(", ")}.` : "")
|
|
94
98
|
);
|
|
95
99
|
}
|
|
96
|
-
function hostBundleSdkEntry(cliPath = process.argv[1]) {
|
|
97
|
-
if (!cliPath) return void 0;
|
|
98
|
-
let cli;
|
|
99
|
-
try {
|
|
100
|
-
cli = fs.realpathSync(cliPath);
|
|
101
|
-
} catch {
|
|
102
|
-
return void 0;
|
|
103
|
-
}
|
|
104
|
-
const bundle = path.dirname(cli);
|
|
105
|
-
if (path.basename(cli) !== "cli.js" || path.basename(bundle) !== "bundle") return void 0;
|
|
106
|
-
const entry = path.join(bundle, "index.js");
|
|
107
|
-
try {
|
|
108
|
-
const manifest = JSON.parse(fs.readFileSync(path.join(bundle, "..", "..", "package.json"), "utf8"));
|
|
109
|
-
return manifest.name === "@earendil-works/pi-coding-agent" && fs.existsSync(entry) ? entry : void 0;
|
|
110
|
-
} catch {
|
|
111
|
-
return void 0;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
async function loadHostSdk(cliPath = process.argv[1]) {
|
|
115
|
-
const entry = hostBundleSdkEntry(cliPath);
|
|
116
|
-
if (entry) {
|
|
117
|
-
try {
|
|
118
|
-
return await import(pathToFileURL(entry).href);
|
|
119
|
-
} catch {
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return import("@earendil-works/pi-coding-agent");
|
|
123
|
-
}
|
|
124
100
|
async function fabricProviderBridge(pi) {
|
|
125
101
|
const model = process.env[PROVIDER_BRIDGE_MODEL_ENV]?.trim();
|
|
126
102
|
if (!model) return;
|
|
@@ -134,8 +110,6 @@ export {
|
|
|
134
110
|
PROVIDER_BRIDGE_MODEL_ENV,
|
|
135
111
|
fabricProviderBridge as default,
|
|
136
112
|
fabricExtensionEntries,
|
|
137
|
-
hostBundleSdkEntry,
|
|
138
|
-
loadHostSdk,
|
|
139
113
|
orderProviderCandidates,
|
|
140
114
|
parseModelKey,
|
|
141
115
|
resolveExtensionProviders
|
|
@@ -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, pathToFileURL } 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/** 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 * The SDK entry of the bundled Pi CLI running this process, if it is one. The\n * published `pi` bin is `dist/bundle/cli.js`; its `dist/bundle/index.js` SDK\n * entry is built from the same chunks the CLI has already evaluated.\n */\nexport function hostBundleSdkEntry(cliPath: string | undefined = process.argv[1]): string | undefined {\n if (!cliPath) return undefined;\n let cli: string;\n try {\n cli = fs.realpathSync(cliPath);\n } catch {\n return undefined;\n }\n const bundle = path.dirname(cli);\n if (path.basename(cli) !== \"cli.js\" || path.basename(bundle) !== \"bundle\") return undefined;\n const entry = path.join(bundle, \"index.js\");\n try {\n const manifest = JSON.parse(fs.readFileSync(path.join(bundle, \"..\", \"..\", \"package.json\"), \"utf8\")) as { name?: unknown };\n return manifest.name === \"@earendil-works/pi-coding-agent\" && fs.existsSync(entry) ? entry : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * The host's own SDK. Pi imports this bridge natively (it is ESM JavaScript),\n * so jiti's virtual modules do not apply, and a bare package import from here\n * evaluates the separate unbundled SDK: about 1,800 more modules in the\n * bundled CLI. Besides the startup cost, that CLI enables Node's compile cache,\n * which serializes every one of those modules on exit; with a cold cache that\n * held a Windows child past the worker's exit grace after it had settled.\n * The bundle's SDK entry shares the CLI's already loaded chunks instead.\n */\nexport async function loadHostSdk(cliPath: string | undefined = process.argv[1]): Promise<PiSdk> {\n const entry = hostBundleSdkEntry(cliPath);\n if (entry) {\n try {\n return await import(pathToFileURL(entry).href) as PiSdk;\n } catch {\n // Unexpected bundle layout: fall back to the package entry.\n }\n }\n return import(\"@earendil-works/pi-coding-agent\");\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": "
|
|
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
|