pi-fabric 0.110.2 → 0.111.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.
Files changed (44) hide show
  1. package/README.md +3 -1
  2. package/THIRD_PARTY_NOTICES.md +7 -0
  3. package/dist/agents/provider-bridge.d.ts +80 -0
  4. package/dist/agents/provider-bridge.d.ts.map +1 -0
  5. package/dist/agents/provider-bridge.js +143 -0
  6. package/dist/agents/provider-bridge.js.map +7 -0
  7. package/dist/agents.js +3 -3
  8. package/dist/capture/interceptor.d.ts.map +1 -1
  9. package/dist/chunks/{chunk-6C7FX3WA.js → chunk-BEP6VFL2.js} +6 -1
  10. package/dist/chunks/chunk-BEP6VFL2.js.map +7 -0
  11. package/dist/chunks/{chunk-3R6NIF2N.js → chunk-QFR36ZSK.js} +2 -2
  12. package/dist/chunks/{chunk-5DKVWEE4.js → chunk-S6BFCVOG.js} +4 -4
  13. package/dist/durable/worker-host.d.ts.map +1 -1
  14. package/dist/durable/worker-host.js +7 -0
  15. package/dist/durable/worker-host.js.map +2 -2
  16. package/dist/extension-bootstrap.js +1 -1
  17. package/dist/index.js +1 -1
  18. package/dist/jev/observation.js +2 -2
  19. package/dist/jev.js +3 -3
  20. package/dist/providers/jev-provider.js +3 -3
  21. package/dist/worker/result.js +517 -517
  22. package/dist/worker/result.js.map +1 -1
  23. package/dist/worker.js +8 -1
  24. package/dist/worker.js.map +2 -2
  25. package/docs/architecture.md +1 -1
  26. package/docs/configuration.md +64 -1
  27. package/node_modules/pi-coralbricks-provider/LICENSE +21 -0
  28. package/node_modules/pi-coralbricks-provider/README.md +306 -0
  29. package/node_modules/pi-coralbricks-provider/auth.ts +30 -0
  30. package/node_modules/pi-coralbricks-provider/custom-models.json +1 -0
  31. package/node_modules/pi-coralbricks-provider/deprecated-models.json +1 -0
  32. package/node_modules/pi-coralbricks-provider/guard.ts +155 -0
  33. package/node_modules/pi-coralbricks-provider/index.ts +662 -0
  34. package/node_modules/pi-coralbricks-provider/models.json +88 -0
  35. package/node_modules/pi-coralbricks-provider/package.json +74 -0
  36. package/node_modules/pi-coralbricks-provider/park.ts +122 -0
  37. package/node_modules/pi-coralbricks-provider/patch.json +34 -0
  38. package/node_modules/pi-coralbricks-provider/scripts/update-models.js +658 -0
  39. package/node_modules/pi-coralbricks-provider/settings.ts +143 -0
  40. package/node_modules/pi-coralbricks-provider/sync-policy.ts +309 -0
  41. package/package.json +8 -3
  42. package/dist/chunks/chunk-6C7FX3WA.js.map +0 -7
  43. /package/dist/chunks/{chunk-3R6NIF2N.js.map → chunk-QFR36ZSK.js.map} +0 -0
  44. /package/dist/chunks/{chunk-5DKVWEE4.js.map → chunk-S6BFCVOG.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
 
@@ -156,7 +158,7 @@ See the [interface & commands reference](docs/interface.md) for every view, keyb
156
158
 
157
159
  ## Reference
158
160
 
159
- - [Configuration](docs/configuration.md): `fabric.json`, code modes, tool capture, approvals, and budgets.
161
+ - [Configuration](docs/configuration.md): `fabric.json`, code modes, tool capture, approvals, budgets, and [third-party model providers](docs/configuration.md#third-party-model-providers).
160
162
  - [Execution kernels](docs/kernels.md): exclusive TypeScript/Python selection, Monty sandboxing, CPython escape hatch, agent inheritance, and examples.
161
163
  - [Native codemode APIs](docs/codemode-parity.md): additive native tool aliases or opt-in Pi-compatible scripts, collision-safe Fabric discovery, native models/images, branch-local state, and sPTC.
162
164
  - [Prompt cache](docs/prompt-cache.md): honest cache observations and optional, time-bounded native warming leases.
@@ -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
@@ -0,0 +1,80 @@
1
+ import type { Provider } from "@earendil-works/pi-ai";
2
+ import type { ExtensionAPI, ProviderConfig } from "@earendil-works/pi-coding-agent";
3
+ /**
4
+ * The `provider/id` key a Pi child launched with `extensions: false` must
5
+ * resolve. The worker sets it only when it also loads this bridge with `-e`.
6
+ */
7
+ export declare const PROVIDER_BRIDGE_MODEL_ENV = "PI_FABRIC_EXTENSION_MODEL";
8
+ export interface ExtensionProviderRegistrations {
9
+ configs: Array<{
10
+ name: string;
11
+ config: ProviderConfig;
12
+ extensionPath: string;
13
+ }>;
14
+ natives: Array<{
15
+ provider: Provider;
16
+ extensionPath: string;
17
+ }>;
18
+ }
19
+ export interface ResolveExtensionProvidersOptions {
20
+ model: string;
21
+ cwd: string;
22
+ agentDir: string;
23
+ /** Extension entry files never probed (Fabric's own entries by default). */
24
+ exclude?: readonly string[];
25
+ }
26
+ type PiSdk = typeof import("@earendil-works/pi-coding-agent");
27
+ /** Split a canonical `provider/id` key at its first slash. */
28
+ export declare function parseModelKey(key: string): {
29
+ provider: string;
30
+ id: string;
31
+ } | undefined;
32
+ /**
33
+ * Probe extensions whose own path names the provider first (the usual
34
+ * `pi-<provider>-provider` package), so the common case runs one registration
35
+ * function instead of every installed extension.
36
+ */
37
+ export declare function orderProviderCandidates(paths: readonly string[], provider: string): {
38
+ named: string[];
39
+ rest: string[];
40
+ };
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
+ */
47
+ export declare function fabricExtensionEntries(moduleUrl?: string): string[];
48
+ /**
49
+ * Find the extension registrations that make `model` resolvable in a child
50
+ * without its other extensions. Returns `undefined` when Pi already knows the
51
+ * model (built in, models.json, or a cached catalog), so those children keep
52
+ * their exact extension-free behaviour. Throws an actionable error when no
53
+ * installed extension registers the provider.
54
+ */
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
+ /**
73
+ * Loaded with `-e` into Pi children launched with `extensions: false`. It
74
+ * registers only the requested model's provider, as its extension registered
75
+ * it, so credentials still resolve in the child through auth.json, the
76
+ * environment, or the credential store. Nothing else from that extension loads.
77
+ */
78
+ export default function fabricProviderBridge(pi: ExtensionAPI): Promise<void>;
79
+ export {};
80
+ //# sourceMappingURL=provider-bridge.d.ts.map
@@ -0,0 +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;AAErG;;;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;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,MAAM,GAAG,SAA2B,GAAG,MAAM,GAAG,SAAS,CAiBpG;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,OAAO,GAAE,MAAM,GAAG,SAA2B,GAAG,OAAO,CAAC,KAAK,CAAC,CAU/F;AAED;;;;;GAKG;AACH,wBAA8B,oBAAoB,CAAC,EAAE,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAQlF"}
@@ -0,0 +1,143 @@
1
+ // src/agents/provider-bridge.ts
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+ var PROVIDER_BRIDGE_MODEL_ENV = "PI_FABRIC_EXTENSION_MODEL";
6
+ function parseModelKey(key) {
7
+ const value = key.trim();
8
+ const slash = value.indexOf("/");
9
+ if (slash <= 0 || slash === value.length - 1) return void 0;
10
+ return { provider: value.slice(0, slash), id: value.slice(slash + 1) };
11
+ }
12
+ function orderProviderCandidates(paths, provider) {
13
+ const needle = provider.toLowerCase();
14
+ const named = [];
15
+ const rest = [];
16
+ for (const candidate of paths) {
17
+ const tail = candidate.split(/[\\/]+/).filter(Boolean).slice(-3);
18
+ (tail.some((segment) => segment.toLowerCase().includes(needle)) ? named : rest).push(candidate);
19
+ }
20
+ return { named, rest };
21
+ }
22
+ var realPath = (file) => {
23
+ try {
24
+ return fs.realpathSync(file);
25
+ } catch {
26
+ return path.resolve(file);
27
+ }
28
+ };
29
+ var isBundledPackageEntry = (entry) => entry.replace(/\\/g, "/").replace(/^(?:\.\/)+/, "").startsWith("node_modules/");
30
+ function fabricExtensionEntries(moduleUrl = import.meta.url) {
31
+ const root = path.resolve(path.dirname(fileURLToPath(moduleUrl)), "..", "..");
32
+ try {
33
+ const manifest = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
34
+ if (manifest.name !== "pi-fabric") return [];
35
+ const entries = [manifest.main, ...Array.isArray(manifest.pi?.extensions) ? manifest.pi.extensions : []];
36
+ return entries.filter((entry) => typeof entry === "string" && !isBundledPackageEntry(entry)).map((entry) => path.resolve(root, entry));
37
+ } catch {
38
+ return [];
39
+ }
40
+ }
41
+ var emptyRegistrations = () => ({ configs: [], natives: [] });
42
+ async function loadProviderRegistrations(sdk, paths, provider, options, failures) {
43
+ if (paths.length === 0) return emptyRegistrations();
44
+ const loader = new sdk.DefaultResourceLoader({
45
+ cwd: options.cwd,
46
+ agentDir: options.agentDir,
47
+ settingsManager: options.settingsManager,
48
+ noExtensions: true,
49
+ additionalExtensionPaths: [...paths],
50
+ noSkills: true,
51
+ noPromptTemplates: true,
52
+ noThemes: true,
53
+ noContextFiles: true
54
+ });
55
+ await loader.reload();
56
+ const { runtime, errors } = loader.getExtensions();
57
+ failures.push(...errors.map((error) => error.path));
58
+ return {
59
+ configs: runtime.pendingProviderRegistrations.filter((registration) => registration.name === provider).map(({ name, config, extensionPath }) => ({ name, config, extensionPath })),
60
+ natives: runtime.pendingNativeProviderRegistrations.filter((registration) => registration.provider.id === provider).map(({ provider: registered, extensionPath }) => ({ provider: registered, extensionPath }))
61
+ };
62
+ }
63
+ async function resolveExtensionProviders(options, sdk) {
64
+ const key = parseModelKey(options.model);
65
+ if (!key) return void 0;
66
+ const pi = sdk ?? await import("@earendil-works/pi-coding-agent");
67
+ const models = await pi.ModelRuntime.create({
68
+ authPath: path.join(options.agentDir, "auth.json"),
69
+ modelsPath: path.join(options.agentDir, "models.json"),
70
+ refreshOnCreate: false
71
+ });
72
+ if (models.getModel(key.provider, key.id)) return void 0;
73
+ await models.refresh({ allowNetwork: false, signal: AbortSignal.timeout(15e3) });
74
+ if (models.getModel(key.provider, key.id)) return void 0;
75
+ const untrusted = pi.SettingsManager.create(options.cwd, options.agentDir, { projectTrusted: false });
76
+ const trusted = !pi.hasTrustRequiringProjectResources(options.cwd) || (new pi.ProjectTrustStore(options.agentDir).get(options.cwd) ?? untrusted.getDefaultProjectTrust() === "always");
77
+ const settingsManager = trusted ? pi.SettingsManager.create(options.cwd, options.agentDir, { projectTrusted: true }) : untrusted;
78
+ const resolved = await new pi.DefaultPackageManager({
79
+ cwd: options.cwd,
80
+ agentDir: options.agentDir,
81
+ settingsManager
82
+ }).resolve();
83
+ const excluded = new Set((options.exclude ?? fabricExtensionEntries()).map(realPath));
84
+ const candidates = resolved.extensions.filter((resource) => resource.enabled && !resource.path.startsWith("builtin:")).map((resource) => resource.path).filter((candidate) => !excluded.has(realPath(candidate)));
85
+ const { named, rest } = orderProviderCandidates(candidates, key.provider);
86
+ const context = { cwd: options.cwd, agentDir: options.agentDir, settingsManager };
87
+ const failures = [];
88
+ for (const group of [named, rest]) {
89
+ const found = await loadProviderRegistrations(pi, group, key.provider, context, failures);
90
+ if (found.configs.length > 0 || found.natives.length > 0) return found;
91
+ }
92
+ throw new Error(
93
+ `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
+ );
95
+ }
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
+ async function fabricProviderBridge(pi) {
125
+ const model = process.env[PROVIDER_BRIDGE_MODEL_ENV]?.trim();
126
+ if (!model) return;
127
+ const sdk = await loadHostSdk();
128
+ const found = await resolveExtensionProviders({ model, cwd: process.cwd(), agentDir: sdk.getAgentDir() }, sdk);
129
+ if (!found) return;
130
+ for (const { name, config } of found.configs) pi.registerProvider(name, config);
131
+ for (const { provider } of found.natives) pi.registerProvider(provider);
132
+ }
133
+ export {
134
+ PROVIDER_BRIDGE_MODEL_ENV,
135
+ fabricProviderBridge as default,
136
+ fabricExtensionEntries,
137
+ hostBundleSdkEntry,
138
+ loadHostSdk,
139
+ orderProviderCandidates,
140
+ parseModelKey,
141
+ resolveExtensionProviders
142
+ };
143
+ //# sourceMappingURL=provider-bridge.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 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": "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",
6
+ "names": []
7
+ }
package/dist/agents.js CHANGED
@@ -1,10 +1,10 @@
1
- import {
2
- validateAgentResult
3
- } from "./chunks/chunk-VYQV5JRT.js";
4
1
  import {
5
2
  AGENTS_ACTION_DESCRIPTORS,
6
3
  normalizeAgentRunRequest
7
4
  } from "./chunks/chunk-JJQECUUA.js";
5
+ import {
6
+ validateAgentResult
7
+ } from "./chunks/chunk-VYQV5JRT.js";
8
8
  import {
9
9
  AgentAdmission,
10
10
  assertAgentTask,
@@ -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;AAyBD,KAAK,0BAA0B,GAAG;IAChC,SAAS,EAAE,eAAe,CAAC;CAC5B,CAAC;AAaF,eAAO,MAAM,iCAAiC,GAC5C,WAAW,MAAM,KAChB,OAAO,CAAC,0BAA0B,EAAE,CAuBtC,CAAC;AAiIF,eAAO,MAAM,4BAA4B,GACvC,SAAS,4BAA4B,KACpC,OAAO,CAAC,+BAA+B,CA0CzC,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;AAqIF,eAAO,MAAM,4BAA4B,GACvC,SAAS,4BAA4B,KACpC,OAAO,CAAC,+BAA+B,CA0CzC,CAAC"}
@@ -561,6 +561,7 @@ import { createRequire } from "node:module";
561
561
  import path from "node:path";
562
562
  import { pathToFileURL } from "node:url";
563
563
  var HUB_SYMBOL = Symbol.for("pi-fabric.registered-tool-capture.v1");
564
+ var HOST_RUNNERS_SYMBOL = Symbol.for("pi-fabric.host-extension-runners.v1");
564
565
  var ANCHOR_SYMBOL = Symbol.for("pi-fabric.registered-tool-anchor.v1");
565
566
  var definitionDelegatesTo = (definition, target) => {
566
567
  let current = definition;
@@ -694,6 +695,10 @@ var extensionRunnerConstructors = async () => {
694
695
  constructors.add(Runner);
695
696
  }
696
697
  }
698
+ const advertised = globalThis[HOST_RUNNERS_SYMBOL];
699
+ for (const Runner of advertised instanceof Set ? advertised : []) {
700
+ if (isExtensionRunnerConstructor(Runner)) constructors.add(Runner);
701
+ }
697
702
  if (constructors.size === 0) {
698
703
  try {
699
704
  const hostModule = await import("@earendil-works/pi-coding-agent");
@@ -6597,4 +6602,4 @@ export {
6597
6602
  FABRIC_MANAGED_HOST_VERSION,
6598
6603
  createFabricExtension
6599
6604
  };
6600
- //# sourceMappingURL=chunk-6C7FX3WA.js.map
6605
+ //# sourceMappingURL=chunk-BEP6VFL2.js.map