agent-framework-js 0.3.0 → 0.4.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 (35) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +6 -0
  3. package/dist/{chunk-PYIZ4PT3.js → chunk-3KU76DCP.js} +3 -3
  4. package/dist/{chunk-PYIZ4PT3.js.map → chunk-3KU76DCP.js.map} +1 -1
  5. package/dist/{chunk-IHMPSELC.cjs → chunk-5KC6X2T5.cjs} +5 -5
  6. package/dist/{chunk-IHMPSELC.cjs.map → chunk-5KC6X2T5.cjs.map} +1 -1
  7. package/dist/{chunk-XMDGLQFL.cjs → chunk-JLPLGU7O.cjs} +15 -3
  8. package/dist/chunk-JLPLGU7O.cjs.map +1 -0
  9. package/dist/{chunk-FOTCUNP5.cjs → chunk-N64ZFATA.cjs} +5 -2
  10. package/dist/chunk-N64ZFATA.cjs.map +1 -0
  11. package/dist/{chunk-ACBIHS5H.js → chunk-QXAJ4DUJ.js} +5 -2
  12. package/dist/chunk-QXAJ4DUJ.js.map +1 -0
  13. package/dist/{chunk-YH5746OF.js → chunk-QYG4HLIC.js} +3 -3
  14. package/dist/{chunk-YH5746OF.js.map → chunk-QYG4HLIC.js.map} +1 -1
  15. package/dist/{chunk-GYDY3KX5.cjs → chunk-U3ULJMNH.cjs} +4 -4
  16. package/dist/{chunk-GYDY3KX5.cjs.map → chunk-U3ULJMNH.cjs.map} +1 -1
  17. package/dist/{chunk-QD2FFISV.js → chunk-YVJGF4HQ.js} +16 -4
  18. package/dist/chunk-YVJGF4HQ.js.map +1 -0
  19. package/dist/index.cjs +31 -31
  20. package/dist/index.d.cts +5 -0
  21. package/dist/index.d.ts +5 -0
  22. package/dist/index.js +4 -4
  23. package/dist/mcp/index.cjs +4 -4
  24. package/dist/mcp/index.js +2 -2
  25. package/dist/persistence/index.cjs +5 -5
  26. package/dist/persistence/index.js +2 -2
  27. package/dist/providers/index.cjs +7 -6
  28. package/dist/providers/index.d.cts +10 -0
  29. package/dist/providers/index.d.ts +10 -0
  30. package/dist/providers/index.js +2 -1
  31. package/package.json +7 -7
  32. package/dist/chunk-ACBIHS5H.js.map +0 -1
  33. package/dist/chunk-FOTCUNP5.cjs.map +0 -1
  34. package/dist/chunk-QD2FFISV.js.map +0 -1
  35. package/dist/chunk-XMDGLQFL.cjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.4.0] - 2026-06-16
11
+
12
+ ### Changed
13
+
14
+ - **GitHub Copilot now requires a backend/proxy in the browser.** `api.githubcopilot.com` sends no
15
+ CORS headers, so `createCopilotProvider` throws a typed `RuntimeUnsupportedError` when constructed
16
+ in a browser against the default host. Run it server-side (Node/edge) or set `baseUrl` to a
17
+ lightweight proxy (e.g. a Vite dev-server proxy); a custom `baseUrl` lifts the guard. Added
18
+ `isBrowser` to the runtime capability detection.
19
+ - **Tooling upgraded** (dev-only): ESLint 8 → 10 with a migration from `.eslintrc.yml` to flat
20
+ config (`eslint.config.js`) using the `typescript-eslint` meta package; TypeScript 5 → 6
21
+ (`ignoreDeprecations: "6.0"` for the soon-removed `baseUrl`); Vitest 2 → 4; `@types/node` 20 → 25.
22
+ No runtime/public-API impact.
23
+
10
24
  ## [0.3.0] - 2026-06-16
11
25
 
12
26
  ### Fixed
package/README.md CHANGED
@@ -121,6 +121,12 @@ Core features use only web-standard APIs and run in browser, edge, and Node. Nod
121
121
  (stdio MCP, filesystem storage) are gated by runtime detection and throw a typed
122
122
  `RuntimeUnsupportedError` when unavailable.
123
123
 
124
+ The **GitHub Copilot** provider cannot be used directly from a browser: `api.githubcopilot.com`
125
+ sends no CORS headers, so `createCopilotProvider` throws `RuntimeUnsupportedError` when constructed
126
+ in a browser against the default host. Run it server-side (Node/edge), or route through a
127
+ lightweight proxy (e.g. a Vite dev-server proxy) and set `baseUrl` to your proxy. See the
128
+ [agent-usage skill](.github/skills/agent-framework-usage/SKILL.md) for a proxy example.
129
+
124
130
  ## Scripts
125
131
 
126
132
  ```bash
@@ -1,5 +1,5 @@
1
1
  import { Thread } from './chunk-LC54DGGR.js';
2
- import { requireCapability } from './chunk-ACBIHS5H.js';
2
+ import { requireCapability } from './chunk-QXAJ4DUJ.js';
3
3
 
4
4
  // src/persistence/store.ts
5
5
  var ThreadPersistence = {
@@ -87,5 +87,5 @@ function indexedDbStore(ns) {
87
87
  }
88
88
 
89
89
  export { ThreadPersistence, createBrowserStore, createMemoryStore };
90
- //# sourceMappingURL=chunk-PYIZ4PT3.js.map
91
- //# sourceMappingURL=chunk-PYIZ4PT3.js.map
90
+ //# sourceMappingURL=chunk-3KU76DCP.js.map
91
+ //# sourceMappingURL=chunk-3KU76DCP.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/persistence/store.ts","../src/persistence/memory.ts","../src/persistence/browser.ts"],"names":[],"mappings":"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","file":"chunk-PYIZ4PT3.js","sourcesContent":["/**\n * Pluggable storage abstraction for persisting conversation/thread state in a\n * no-backend environment. No database server is assumed. (FR-024)\n *\n * @packageDocumentation\n */\n\nimport type { Thread } from \"../agents/thread.js\";\nimport { Thread as ThreadClass } from \"../agents/thread.js\";\n\n/** A minimal key/value store. */\nexport interface Store {\n\tget(key: string): Promise<unknown | undefined>;\n\tset(key: string, value: unknown): Promise<void>;\n\tdelete(key: string): Promise<void>;\n}\n\n/** Save and load threads via a {@link Store}. */\nexport const ThreadPersistence = {\n\t/** Persist a thread under the key `thread:<id>`. */\n\tasync save(store: Store, thread: Thread): Promise<void> {\n\t\tawait store.set(`thread:${thread.id}`, thread.toJSON());\n\t},\n\t/** Load and rehydrate a thread, or undefined if absent. */\n\tasync load(store: Store, id: string): Promise<Thread | undefined> {\n\t\tconst data = (await store.get(`thread:${id}`)) as\n\t\t\t| { id: string; messages: never[]; compacted?: boolean }\n\t\t\t| undefined;\n\t\treturn data ? ThreadClass.fromJSON(data) : undefined;\n\t},\n};\n","/**\n * In-memory store adapter. Works in every runtime; ideal as a default and for tests.\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\n\n/** Create an in-memory {@link Store}. */\nexport function createMemoryStore(): Store {\n\tconst map = new Map<string, unknown>();\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn map.get(key);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tmap.set(key, value);\n\t\t},\n\t\tasync delete(key) {\n\t\t\tmap.delete(key);\n\t\t},\n\t};\n}\n","/**\n * Browser store adapters backed by `localStorage` or `IndexedDB`. Capability-gated\n * so a clear typed error is thrown if used where unavailable. (FR-024, FR-030a)\n *\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\nimport { requireCapability } from \"../core/runtime.js\";\n\n/** Options for {@link createBrowserStore}. */\nexport interface BrowserStoreOptions {\n\t/** Storage backend. Default \"local\". */\n\tbackend?: \"local\" | \"indexeddb\";\n\t/** Key namespace/prefix. Default \"afjs\". */\n\tnamespace?: string;\n}\n\n/** Create a browser-backed {@link Store}. */\nexport function createBrowserStore(options: BrowserStoreOptions = {}): Store {\n\tconst backend = options.backend ?? \"local\";\n\tconst ns = options.namespace ?? \"afjs\";\n\treturn backend === \"indexeddb\" ? indexedDbStore(ns) : localStorageStore(ns);\n}\n\nfunction localStorageStore(ns: string): Store {\n\trequireCapability(\"hasLocalStorage\", \"localStorage store\");\n\tconst ls = (globalThis as unknown as { localStorage: Storage }).localStorage;\n\tconst k = (key: string) => `${ns}:${key}`;\n\treturn {\n\t\tasync get(key) {\n\t\t\tconst raw = ls.getItem(k(key));\n\t\t\treturn raw == null ? undefined : JSON.parse(raw);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tls.setItem(k(key), JSON.stringify(value));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tls.removeItem(k(key));\n\t\t},\n\t};\n}\n\nfunction indexedDbStore(ns: string): Store {\n\trequireCapability(\"hasIndexedDB\", \"IndexedDB store\");\n\tconst idb = (globalThis as unknown as { indexedDB: IDBFactory }).indexedDB;\n\n\tfunction open(): Promise<IDBDatabase> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst req = idb.open(ns, 1);\n\t\t\treq.onupgradeneeded = () => req.result.createObjectStore(\"kv\");\n\t\t\treq.onsuccess = () => resolve(req.result);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\tasync function tx<T>(mode: IDBTransactionMode, fn: (s: IDBObjectStore) => IDBRequest): Promise<T> {\n\t\tconst db = await open();\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst store = db.transaction(\"kv\", mode).objectStore(\"kv\");\n\t\t\tconst req = fn(store);\n\t\t\treq.onsuccess = () => resolve(req.result as T);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn tx<unknown>(\"readonly\", (s) => s.get(key));\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tawait tx(\"readwrite\", (s) => s.put(value, key));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tawait tx(\"readwrite\", (s) => s.delete(key));\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"sources":["../src/persistence/store.ts","../src/persistence/memory.ts","../src/persistence/browser.ts"],"names":[],"mappings":"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","file":"chunk-3KU76DCP.js","sourcesContent":["/**\n * Pluggable storage abstraction for persisting conversation/thread state in a\n * no-backend environment. No database server is assumed. (FR-024)\n *\n * @packageDocumentation\n */\n\nimport type { Thread } from \"../agents/thread.js\";\nimport { Thread as ThreadClass } from \"../agents/thread.js\";\n\n/** A minimal key/value store. */\nexport interface Store {\n\tget(key: string): Promise<unknown | undefined>;\n\tset(key: string, value: unknown): Promise<void>;\n\tdelete(key: string): Promise<void>;\n}\n\n/** Save and load threads via a {@link Store}. */\nexport const ThreadPersistence = {\n\t/** Persist a thread under the key `thread:<id>`. */\n\tasync save(store: Store, thread: Thread): Promise<void> {\n\t\tawait store.set(`thread:${thread.id}`, thread.toJSON());\n\t},\n\t/** Load and rehydrate a thread, or undefined if absent. */\n\tasync load(store: Store, id: string): Promise<Thread | undefined> {\n\t\tconst data = (await store.get(`thread:${id}`)) as\n\t\t\t| { id: string; messages: never[]; compacted?: boolean }\n\t\t\t| undefined;\n\t\treturn data ? ThreadClass.fromJSON(data) : undefined;\n\t},\n};\n","/**\n * In-memory store adapter. Works in every runtime; ideal as a default and for tests.\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\n\n/** Create an in-memory {@link Store}. */\nexport function createMemoryStore(): Store {\n\tconst map = new Map<string, unknown>();\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn map.get(key);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tmap.set(key, value);\n\t\t},\n\t\tasync delete(key) {\n\t\t\tmap.delete(key);\n\t\t},\n\t};\n}\n","/**\n * Browser store adapters backed by `localStorage` or `IndexedDB`. Capability-gated\n * so a clear typed error is thrown if used where unavailable. (FR-024, FR-030a)\n *\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\nimport { requireCapability } from \"../core/runtime.js\";\n\n/** Options for {@link createBrowserStore}. */\nexport interface BrowserStoreOptions {\n\t/** Storage backend. Default \"local\". */\n\tbackend?: \"local\" | \"indexeddb\";\n\t/** Key namespace/prefix. Default \"afjs\". */\n\tnamespace?: string;\n}\n\n/** Create a browser-backed {@link Store}. */\nexport function createBrowserStore(options: BrowserStoreOptions = {}): Store {\n\tconst backend = options.backend ?? \"local\";\n\tconst ns = options.namespace ?? \"afjs\";\n\treturn backend === \"indexeddb\" ? indexedDbStore(ns) : localStorageStore(ns);\n}\n\nfunction localStorageStore(ns: string): Store {\n\trequireCapability(\"hasLocalStorage\", \"localStorage store\");\n\tconst ls = (globalThis as unknown as { localStorage: Storage }).localStorage;\n\tconst k = (key: string) => `${ns}:${key}`;\n\treturn {\n\t\tasync get(key) {\n\t\t\tconst raw = ls.getItem(k(key));\n\t\t\treturn raw == null ? undefined : JSON.parse(raw);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tls.setItem(k(key), JSON.stringify(value));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tls.removeItem(k(key));\n\t\t},\n\t};\n}\n\nfunction indexedDbStore(ns: string): Store {\n\trequireCapability(\"hasIndexedDB\", \"IndexedDB store\");\n\tconst idb = (globalThis as unknown as { indexedDB: IDBFactory }).indexedDB;\n\n\tfunction open(): Promise<IDBDatabase> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst req = idb.open(ns, 1);\n\t\t\treq.onupgradeneeded = () => req.result.createObjectStore(\"kv\");\n\t\t\treq.onsuccess = () => resolve(req.result);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\tasync function tx<T>(mode: IDBTransactionMode, fn: (s: IDBObjectStore) => IDBRequest): Promise<T> {\n\t\tconst db = await open();\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst store = db.transaction(\"kv\", mode).objectStore(\"kv\");\n\t\t\tconst req = fn(store);\n\t\t\treq.onsuccess = () => resolve(req.result as T);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn tx<unknown>(\"readonly\", (s) => s.get(key));\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tawait tx(\"readwrite\", (s) => s.put(value, key));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tawait tx(\"readwrite\", (s) => s.delete(key));\n\t\t},\n\t};\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkI55OVD23_cjs = require('./chunk-I55OVD23.cjs');
4
- var chunkFOTCUNP5_cjs = require('./chunk-FOTCUNP5.cjs');
4
+ var chunkN64ZFATA_cjs = require('./chunk-N64ZFATA.cjs');
5
5
 
6
6
  // src/persistence/store.ts
7
7
  var ThreadPersistence = {
@@ -39,7 +39,7 @@ function createBrowserStore(options = {}) {
39
39
  return backend === "indexeddb" ? indexedDbStore(ns) : localStorageStore(ns);
40
40
  }
41
41
  function localStorageStore(ns) {
42
- chunkFOTCUNP5_cjs.requireCapability("hasLocalStorage", "localStorage store");
42
+ chunkN64ZFATA_cjs.requireCapability("hasLocalStorage", "localStorage store");
43
43
  const ls = globalThis.localStorage;
44
44
  const k = (key) => `${ns}:${key}`;
45
45
  return {
@@ -56,7 +56,7 @@ function localStorageStore(ns) {
56
56
  };
57
57
  }
58
58
  function indexedDbStore(ns) {
59
- chunkFOTCUNP5_cjs.requireCapability("hasIndexedDB", "IndexedDB store");
59
+ chunkN64ZFATA_cjs.requireCapability("hasIndexedDB", "IndexedDB store");
60
60
  const idb = globalThis.indexedDB;
61
61
  function open() {
62
62
  return new Promise((resolve, reject) => {
@@ -91,5 +91,5 @@ function indexedDbStore(ns) {
91
91
  exports.ThreadPersistence = ThreadPersistence;
92
92
  exports.createBrowserStore = createBrowserStore;
93
93
  exports.createMemoryStore = createMemoryStore;
94
- //# sourceMappingURL=chunk-IHMPSELC.cjs.map
95
- //# sourceMappingURL=chunk-IHMPSELC.cjs.map
94
+ //# sourceMappingURL=chunk-5KC6X2T5.cjs.map
95
+ //# sourceMappingURL=chunk-5KC6X2T5.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/persistence/store.ts","../src/persistence/memory.ts","../src/persistence/browser.ts"],"names":["Thread","requireCapability"],"mappings":"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","file":"chunk-IHMPSELC.cjs","sourcesContent":["/**\n * Pluggable storage abstraction for persisting conversation/thread state in a\n * no-backend environment. No database server is assumed. (FR-024)\n *\n * @packageDocumentation\n */\n\nimport type { Thread } from \"../agents/thread.js\";\nimport { Thread as ThreadClass } from \"../agents/thread.js\";\n\n/** A minimal key/value store. */\nexport interface Store {\n\tget(key: string): Promise<unknown | undefined>;\n\tset(key: string, value: unknown): Promise<void>;\n\tdelete(key: string): Promise<void>;\n}\n\n/** Save and load threads via a {@link Store}. */\nexport const ThreadPersistence = {\n\t/** Persist a thread under the key `thread:<id>`. */\n\tasync save(store: Store, thread: Thread): Promise<void> {\n\t\tawait store.set(`thread:${thread.id}`, thread.toJSON());\n\t},\n\t/** Load and rehydrate a thread, or undefined if absent. */\n\tasync load(store: Store, id: string): Promise<Thread | undefined> {\n\t\tconst data = (await store.get(`thread:${id}`)) as\n\t\t\t| { id: string; messages: never[]; compacted?: boolean }\n\t\t\t| undefined;\n\t\treturn data ? ThreadClass.fromJSON(data) : undefined;\n\t},\n};\n","/**\n * In-memory store adapter. Works in every runtime; ideal as a default and for tests.\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\n\n/** Create an in-memory {@link Store}. */\nexport function createMemoryStore(): Store {\n\tconst map = new Map<string, unknown>();\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn map.get(key);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tmap.set(key, value);\n\t\t},\n\t\tasync delete(key) {\n\t\t\tmap.delete(key);\n\t\t},\n\t};\n}\n","/**\n * Browser store adapters backed by `localStorage` or `IndexedDB`. Capability-gated\n * so a clear typed error is thrown if used where unavailable. (FR-024, FR-030a)\n *\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\nimport { requireCapability } from \"../core/runtime.js\";\n\n/** Options for {@link createBrowserStore}. */\nexport interface BrowserStoreOptions {\n\t/** Storage backend. Default \"local\". */\n\tbackend?: \"local\" | \"indexeddb\";\n\t/** Key namespace/prefix. Default \"afjs\". */\n\tnamespace?: string;\n}\n\n/** Create a browser-backed {@link Store}. */\nexport function createBrowserStore(options: BrowserStoreOptions = {}): Store {\n\tconst backend = options.backend ?? \"local\";\n\tconst ns = options.namespace ?? \"afjs\";\n\treturn backend === \"indexeddb\" ? indexedDbStore(ns) : localStorageStore(ns);\n}\n\nfunction localStorageStore(ns: string): Store {\n\trequireCapability(\"hasLocalStorage\", \"localStorage store\");\n\tconst ls = (globalThis as unknown as { localStorage: Storage }).localStorage;\n\tconst k = (key: string) => `${ns}:${key}`;\n\treturn {\n\t\tasync get(key) {\n\t\t\tconst raw = ls.getItem(k(key));\n\t\t\treturn raw == null ? undefined : JSON.parse(raw);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tls.setItem(k(key), JSON.stringify(value));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tls.removeItem(k(key));\n\t\t},\n\t};\n}\n\nfunction indexedDbStore(ns: string): Store {\n\trequireCapability(\"hasIndexedDB\", \"IndexedDB store\");\n\tconst idb = (globalThis as unknown as { indexedDB: IDBFactory }).indexedDB;\n\n\tfunction open(): Promise<IDBDatabase> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst req = idb.open(ns, 1);\n\t\t\treq.onupgradeneeded = () => req.result.createObjectStore(\"kv\");\n\t\t\treq.onsuccess = () => resolve(req.result);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\tasync function tx<T>(mode: IDBTransactionMode, fn: (s: IDBObjectStore) => IDBRequest): Promise<T> {\n\t\tconst db = await open();\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst store = db.transaction(\"kv\", mode).objectStore(\"kv\");\n\t\t\tconst req = fn(store);\n\t\t\treq.onsuccess = () => resolve(req.result as T);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn tx<unknown>(\"readonly\", (s) => s.get(key));\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tawait tx(\"readwrite\", (s) => s.put(value, key));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tawait tx(\"readwrite\", (s) => s.delete(key));\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"sources":["../src/persistence/store.ts","../src/persistence/memory.ts","../src/persistence/browser.ts"],"names":["Thread","requireCapability"],"mappings":"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","file":"chunk-5KC6X2T5.cjs","sourcesContent":["/**\n * Pluggable storage abstraction for persisting conversation/thread state in a\n * no-backend environment. No database server is assumed. (FR-024)\n *\n * @packageDocumentation\n */\n\nimport type { Thread } from \"../agents/thread.js\";\nimport { Thread as ThreadClass } from \"../agents/thread.js\";\n\n/** A minimal key/value store. */\nexport interface Store {\n\tget(key: string): Promise<unknown | undefined>;\n\tset(key: string, value: unknown): Promise<void>;\n\tdelete(key: string): Promise<void>;\n}\n\n/** Save and load threads via a {@link Store}. */\nexport const ThreadPersistence = {\n\t/** Persist a thread under the key `thread:<id>`. */\n\tasync save(store: Store, thread: Thread): Promise<void> {\n\t\tawait store.set(`thread:${thread.id}`, thread.toJSON());\n\t},\n\t/** Load and rehydrate a thread, or undefined if absent. */\n\tasync load(store: Store, id: string): Promise<Thread | undefined> {\n\t\tconst data = (await store.get(`thread:${id}`)) as\n\t\t\t| { id: string; messages: never[]; compacted?: boolean }\n\t\t\t| undefined;\n\t\treturn data ? ThreadClass.fromJSON(data) : undefined;\n\t},\n};\n","/**\n * In-memory store adapter. Works in every runtime; ideal as a default and for tests.\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\n\n/** Create an in-memory {@link Store}. */\nexport function createMemoryStore(): Store {\n\tconst map = new Map<string, unknown>();\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn map.get(key);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tmap.set(key, value);\n\t\t},\n\t\tasync delete(key) {\n\t\t\tmap.delete(key);\n\t\t},\n\t};\n}\n","/**\n * Browser store adapters backed by `localStorage` or `IndexedDB`. Capability-gated\n * so a clear typed error is thrown if used where unavailable. (FR-024, FR-030a)\n *\n * @packageDocumentation\n */\n\nimport type { Store } from \"./store.js\";\nimport { requireCapability } from \"../core/runtime.js\";\n\n/** Options for {@link createBrowserStore}. */\nexport interface BrowserStoreOptions {\n\t/** Storage backend. Default \"local\". */\n\tbackend?: \"local\" | \"indexeddb\";\n\t/** Key namespace/prefix. Default \"afjs\". */\n\tnamespace?: string;\n}\n\n/** Create a browser-backed {@link Store}. */\nexport function createBrowserStore(options: BrowserStoreOptions = {}): Store {\n\tconst backend = options.backend ?? \"local\";\n\tconst ns = options.namespace ?? \"afjs\";\n\treturn backend === \"indexeddb\" ? indexedDbStore(ns) : localStorageStore(ns);\n}\n\nfunction localStorageStore(ns: string): Store {\n\trequireCapability(\"hasLocalStorage\", \"localStorage store\");\n\tconst ls = (globalThis as unknown as { localStorage: Storage }).localStorage;\n\tconst k = (key: string) => `${ns}:${key}`;\n\treturn {\n\t\tasync get(key) {\n\t\t\tconst raw = ls.getItem(k(key));\n\t\t\treturn raw == null ? undefined : JSON.parse(raw);\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tls.setItem(k(key), JSON.stringify(value));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tls.removeItem(k(key));\n\t\t},\n\t};\n}\n\nfunction indexedDbStore(ns: string): Store {\n\trequireCapability(\"hasIndexedDB\", \"IndexedDB store\");\n\tconst idb = (globalThis as unknown as { indexedDB: IDBFactory }).indexedDB;\n\n\tfunction open(): Promise<IDBDatabase> {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst req = idb.open(ns, 1);\n\t\t\treq.onupgradeneeded = () => req.result.createObjectStore(\"kv\");\n\t\t\treq.onsuccess = () => resolve(req.result);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\tasync function tx<T>(mode: IDBTransactionMode, fn: (s: IDBObjectStore) => IDBRequest): Promise<T> {\n\t\tconst db = await open();\n\t\treturn new Promise<T>((resolve, reject) => {\n\t\t\tconst store = db.transaction(\"kv\", mode).objectStore(\"kv\");\n\t\t\tconst req = fn(store);\n\t\t\treq.onsuccess = () => resolve(req.result as T);\n\t\t\treq.onerror = () => reject(req.error);\n\t\t});\n\t}\n\n\treturn {\n\t\tasync get(key) {\n\t\t\treturn tx<unknown>(\"readonly\", (s) => s.get(key));\n\t\t},\n\t\tasync set(key, value) {\n\t\t\tawait tx(\"readwrite\", (s) => s.put(value, key));\n\t\t},\n\t\tasync delete(key) {\n\t\t\tawait tx(\"readwrite\", (s) => s.delete(key));\n\t\t},\n\t};\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var chunkN64ZFATA_cjs = require('./chunk-N64ZFATA.cjs');
3
4
  var chunkMQ2XTH3S_cjs = require('./chunk-MQ2XTH3S.cjs');
4
5
 
5
6
  // src/providers/provider.ts
@@ -302,8 +303,19 @@ var COPILOT_DEFAULT_HEADERS = {
302
303
  "Openai-Intent": "conversation-panel"
303
304
  };
304
305
  function createCopilotProvider(options) {
306
+ const baseUrl = options.baseUrl ?? DEFAULT_COPILOT_BASE_URL;
307
+ const usingDefaultHost = baseUrl === DEFAULT_COPILOT_BASE_URL;
308
+ if (usingDefaultHost && chunkN64ZFATA_cjs.detectRuntime().isBrowser) {
309
+ throw new chunkMQ2XTH3S_cjs.RuntimeUnsupportedError(
310
+ "GitHub Copilot directly from a browser (the Copilot API sends no CORS headers)",
311
+ {
312
+ reason: "cors",
313
+ remedy: "Run a lightweight backend/proxy (e.g. a Vite dev-server proxy or a small server route) that forwards to https://api.githubcopilot.com, then set `baseUrl` to your proxy URL. Alternatively, run the Copilot provider server-side (Node or an edge function)."
314
+ }
315
+ );
316
+ }
305
317
  const inner = createOpenAICompatibleProvider({
306
- baseUrl: options.baseUrl ?? DEFAULT_COPILOT_BASE_URL,
318
+ baseUrl,
307
319
  getCredential: options.getCredential,
308
320
  capabilities: options.capabilities,
309
321
  models: options.models,
@@ -329,5 +341,5 @@ exports.createOpenAICompatibleProvider = createOpenAICompatibleProvider;
329
341
  exports.providerErrorFromStatus = providerErrorFromStatus;
330
342
  exports.resolveModels = resolveModels;
331
343
  exports.withRetry = withRetry;
332
- //# sourceMappingURL=chunk-XMDGLQFL.cjs.map
333
- //# sourceMappingURL=chunk-XMDGLQFL.cjs.map
344
+ //# sourceMappingURL=chunk-JLPLGU7O.cjs.map
345
+ //# sourceMappingURL=chunk-JLPLGU7O.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/provider.ts","../src/providers/retry.ts","../src/providers/openai-compatible.ts","../src/providers/copilot.ts"],"names":["ValidationError","ProviderError","detectRuntime","RuntimeUnsupportedError"],"mappings":";;;;;;AA4DO,SAAS,cAAc,OAAA,EAAgD;AAC7E,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,KAAW,OAAA,CAAQ,eAAe,CAAC,OAAA,CAAQ,YAAY,CAAA,GAAI,EAAC,CAAA;AACnF,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACxB,IAAA,MAAM,IAAIA,kCAAgB,uEAAuE,CAAA;AAAA,EAClG;AACA,EAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,YAAA,GAC1B,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,KAAA,KAAU,OAAA,CAAQ,YAAY,CAAA,GACnD,OAAO,CAAC,CAAA;AACX,EAAA,IAAI,CAAC,YAAA,EAAc;AAClB,IAAA,MAAM,IAAIA,iCAAA,CAAgB,CAAA,cAAA,EAAiB,OAAA,CAAQ,YAAY,CAAA,0BAAA,CAA4B,CAAA;AAAA,EAC5F;AACA,EAAA,MAAM,OAAA,GAAU,CAAC,IAAA,KAAqC;AACrD,IAAA,IAAI,CAAC,MAAM,OAAO,YAAA;AAClB,IAAA,MAAM,QAAQ,MAAA,CAAO,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,UAAU,IAAI,CAAA;AACjD,IAAA,IAAI,CAAC,KAAA,EAAO;AACX,MAAA,MAAM,IAAIA,iCAAA,CAAgB,CAAA,OAAA,EAAU,IAAI,CAAA,qCAAA,CAAuC,CAAA;AAAA,IAChF;AACA,IAAA,OAAO,KAAA;AAAA,EACR,CAAA;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,YAAA,EAAc,OAAA,EAAQ;AACxC;;;AC5DA,IAAM,QAAA,GAAmC;AAAA,EACxC,UAAA,EAAY,CAAA;AAAA,EACZ,WAAA,EAAa,GAAA;AAAA,EACb,UAAA,EAAY;AACb,CAAA;AAEA,SAAS,MAAM,EAAA,EAA2B;AACzC,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,MAAM,UAAA,CAAW,CAAA,EAAG,EAAE,CAAC,CAAA;AAC5C;AAUA,eAAsB,SAAA,CACrB,EAAA,EACA,IAAA,EACA,YAAA,EACa;AACb,EAAA,MAAM,GAAA,GAAM,EAAE,GAAG,QAAA,EAAU,GAAG,IAAA,EAAK;AACnC,EAAA,IAAI,OAAA,GAAU,CAAA;AAEd,EAAA,WAAU;AACT,IAAA,IAAI;AACH,MAAA,OAAO,MAAM,EAAA,EAAG;AAAA,IACjB,SAAS,GAAA,EAAK;AACb,MAAA,MAAM,WAAA,GAAc,GAAA,YAAeC,+BAAA,IAAiB,GAAA,CAAI,SAAA;AACxD,MAAA,IAAI,CAAC,WAAA,IAAe,OAAA,IAAW,GAAA,CAAI,UAAA,EAAY;AAC9C,QAAA,MAAM,GAAA;AAAA,MACP;AACA,MAAA,MAAM,WAAA,GAAc,eAAe,GAAoB,CAAA;AACvD,MAAA,MAAM,OAAA,GAAU,KAAK,GAAA,CAAI,GAAA,CAAI,cAAc,CAAA,IAAK,OAAA,EAAS,IAAI,UAAU,CAAA;AACvE,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,EAAO,GAAI,GAAA,CAAI,WAAA;AACnC,MAAA,MAAM,KAAA,CAAM,WAAA,IAAe,OAAA,GAAU,MAAM,CAAA;AAC3C,MAAA,OAAA,EAAA;AAAA,IACD;AAAA,EACD;AACD;AAGO,SAAS,uBAAA,CAAwB,QAAgB,OAAA,EAAgC;AACvF,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,IAAU,GAAA,EAAK;AACpC,IAAA,OAAO,IAAIA,+BAAA,CAAc,OAAA,EAAS,WAAA,EAAa,EAAE,QAAQ,CAAA;AAAA,EAC1D;AACA,EAAA,IAAI,MAAA,KAAW,GAAA,IAAO,MAAA,KAAW,GAAA,EAAK;AACrC,IAAA,OAAO,IAAIA,+BAAA,CAAc,OAAA,EAAS,MAAA,EAAQ,EAAE,QAAQ,CAAA;AAAA,EACrD;AACA,EAAA,OAAO,IAAIA,+BAAA,CAAc,OAAA,EAAS,QAAA,EAAU,EAAE,QAAQ,CAAA;AACvD;;;ACNA,IAAM,sBAAA,GAAyB,iBAAA;AAO/B,SAAS,iBAAiB,IAAA,EAAsB;AAC/C,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,sBAAA,EAAwB,GAAG,CAAA;AAChD;AAEA,SAAS,gBAAgB,KAAA,EAA+B;AACvD,EAAA,IAAI,MAAM,KAAA,CAAM,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,MAAM,CAAA,EAAG;AAC1C,IAAA,OAAO,KAAA,CAAM,IAAI,CAAC,CAAA,KAAO,EAAuB,IAAI,CAAA,CAAE,KAAK,EAAE,CAAA;AAAA,EAC9D;AACA,EAAA,OAAO,KAAA,CAAM,GAAA;AAAA,IAAI,CAAC,MACjB,CAAA,CAAE,IAAA,KAAS,SACR,EAAE,IAAA,EAAM,QAAQ,IAAA,EAAM,CAAA,CAAE,MAAK,GAC7B,EAAE,MAAM,WAAA,EAAa,SAAA,EAAW,EAAE,GAAA,EAAK,CAAA,CAAE,MAAK;AAAE,GACpD;AACD;AAEA,SAAS,gBACR,SAAA,EACyF;AACzF,EAAA,OAAO,SAAA,CAAU,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,IAC7B,IAAI,EAAA,CAAG,EAAA;AAAA,IACP,IAAA,EAAM,UAAA;AAAA,IACN,QAAA,EAAU;AAAA,MACT,IAAA,EAAM,gBAAA,CAAiB,EAAA,CAAG,IAAI,CAAA;AAAA,MAC9B,SAAA,EACC,OAAO,EAAA,CAAG,SAAA,KAAc,QAAA,GAAW,EAAA,CAAG,SAAA,GAAY,IAAA,CAAK,SAAA,CAAU,EAAA,CAAG,SAAA,IAAa,EAAE;AAAA;AACrF,GACD,CAAE,CAAA;AACH;AAEA,SAAS,iBAAiB,QAAA,EAAsC;AAC/D,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,KAAM;AAC1B,IAAA,MAAM,GAAA,GAAqB,EAAE,IAAA,EAAM,CAAA,CAAE,MAAM,OAAA,EAAS,eAAA,CAAgB,CAAA,CAAE,KAAK,CAAA,EAAE;AAC7E,IAAA,IAAI,CAAA,CAAE,SAAA,IAAa,CAAA,CAAE,SAAA,CAAU,SAAS,CAAA,EAAG;AAC1C,MAAA,GAAA,CAAI,UAAA,GAAa,eAAA,CAAgB,CAAA,CAAE,SAAS,CAAA;AAG5C,MAAA,MAAM,OAAA,GAAU,CAAA,CAAE,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,KAAS,MAAA,IAAU,CAAA,CAAE,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAC1E,MAAA,IAAI,CAAC,OAAA,EAAS,GAAA,CAAI,OAAA,GAAU,IAAA;AAAA,IAC7B;AACA,IAAA,IAAI,CAAA,CAAE,UAAA,EAAY,GAAA,CAAI,YAAA,GAAe,CAAA,CAAE,UAAA;AACvC,IAAA,IAAI,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA,GAAO,gBAAA,CAAiB,EAAE,IAAI,CAAA;AAC9C,IAAA,IAAI,CAAA,CAAE,eAAA,EAAiB,GAAA,CAAI,gBAAA,GAAmB,CAAA,CAAE,eAAA;AAChD,IAAA,OAAO,GAAA;AAAA,EACR,CAAC,CAAA;AACF;AAQA,SAAS,eAAe,KAAA,EAA+B;AACtD,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,EAAA,IAAI,CAAC,SAAS,KAAA,CAAM,MAAA,KAAW,GAAG,OAAO,EAAE,KAAA,EAAO,MAAA,EAAW,OAAA,EAAQ;AACrE,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM;AAC9B,IAAA,MAAM,QAAA,GAAW,gBAAA,CAAiB,CAAA,CAAE,IAAI,CAAA;AACxC,IAAA,OAAA,CAAQ,GAAA,CAAI,QAAA,EAAU,CAAA,CAAE,IAAI,CAAA;AAC5B,IAAA,OAAO;AAAA,MACN,IAAA,EAAM,UAAA;AAAA,MACN,QAAA,EAAU,EAAE,IAAA,EAAM,QAAA,EAAU,aAAa,CAAA,CAAE,WAAA,EAAa,UAAA,EAAY,CAAA,CAAE,WAAA;AAAY,KACnF;AAAA,EACD,CAAC,CAAA;AACD,EAAA,OAAO,EAAE,OAAO,OAAA,EAAQ;AACzB;AAcO,SAAS,+BACf,OAAA,EACW;AACX,EAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,SAAA,IAAa,UAAA,CAAW,KAAA;AAChD,EAAA,MAAM,MAAM,CAAA,EAAG,OAAA,CAAQ,QAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAC,CAAA,iBAAA,CAAA;AACjD,EAAA,MAAM,EAAE,MAAA,EAAQ,YAAA,EAAc,OAAA,EAAQ,GAAI,cAAc,OAAO,CAAA;AAE/D,EAAA,eAAe,WAAA,GAA+C;AAC7D,IAAA,MAAM,IAAA,GAAO,MAAM,OAAA,CAAQ,aAAA,EAAc;AAGzC,IAAA,MAAM,OAAA,GAAkC;AAAA,MACvC,cAAA,EAAgB,kBAAA;AAAA,MAChB,GAAI,OAAA,CAAQ,OAAA,IAAW;AAAC,KACzB;AACA,IAAA,IAAI,IAAA,EAAM,OAAA,CAAQ,eAAe,CAAA,GAAI,UAAU,IAAI,CAAA,CAAA;AACnD,IAAA,OAAO,OAAA;AAAA,EACR;AAEA,EAAA,SAAS,IAAA,CAAK,GAAA,EAAsB,MAAA,EAAiB,IAAA,EAAyB;AAC7E,IAAA,OAAO,KAAK,SAAA,CAAU;AAAA,MACrB,KAAA,EAAO,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,CAAE,KAAA;AAAA,MAC1B,QAAA,EAAU,gBAAA,CAAiB,GAAA,CAAI,QAAQ,CAAA;AAAA,MACvC,MAAA;AAAA,MACA,GAAI,KAAK,KAAA,GAAQ,EAAE,OAAO,IAAA,CAAK,KAAA,KAAU;AAAC,KAC1C,CAAA;AAAA,EACF;AAEA,EAAA,SAAS,cAAA,CAAe,KAAc,OAAA,EAAsD;AAC3F,IAAA,MAAM,QAAS,GAAA,EAEX,UAAA;AACJ,IAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,MAAA,KAAW,GAAG,OAAO,MAAA;AACzC,IAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,MACxB,IAAI,CAAA,CAAE,EAAA;AAAA,MACN,IAAA,EAAM,QAAQ,GAAA,CAAI,CAAA,CAAE,SAAS,IAAI,CAAA,IAAK,EAAE,QAAA,CAAS,IAAA;AAAA,MACjD,SAAA,EAAW,QAAA,CAAS,CAAA,CAAE,QAAA,CAAS,SAAS;AAAA,KACzC,CAAE,CAAA;AAAA,EACH;AAEA,EAAA,eAAe,SAAS,GAAA,EAAiD;AACxE,IAAA,OAAO,UAAU,YAAY;AAC5B,MAAA,MAAM,IAAA,GAAO,cAAA,CAAe,GAAA,CAAI,KAAK,CAAA;AACrC,MAAA,IAAI,GAAA;AACJ,MAAA,IAAI;AACH,QAAA,GAAA,GAAM,MAAM,QAAQ,GAAA,EAAK;AAAA,UACxB,MAAA,EAAQ,MAAA;AAAA,UACR,OAAA,EAAS,MAAM,WAAA,EAAY;AAAA,UAC3B,IAAA,EAAM,IAAA,CAAK,GAAA,EAAK,KAAA,EAAO,IAAI,CAAA;AAAA,UAC3B,QAAQ,GAAA,CAAI;AAAA,SACZ,CAAA;AAAA,MACF,SAAS,CAAA,EAAG;AACX,QAAA,MAAM,IAAIA,+BAAA,CAAc,CAAA,eAAA,EAAmB,CAAA,CAAY,OAAO,IAAI,WAAW,CAAA;AAAA,MAC9E;AACA,MAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,uBAAA,CAAwB,IAAI,MAAA,EAAQ,CAAA,kBAAA,EAAqB,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAExF,MAAA,IAAI,IAAA;AACJ,MAAA,IAAI;AACH,QAAA,IAAA,GAAQ,MAAM,IAAI,IAAA,EAAK;AAAA,MACxB,CAAA,CAAA,MAAQ;AACP,QAAA,MAAM,IAAIA,+BAAA,CAAc,6BAAA,EAA+B,WAAW,CAAA;AAAA,MACnE;AACA,MAAA,MAAM,MAAA,GACL,IAAA,CAAK,SAAS,CAAA,GACX,CAAC,CAAA;AACL,MAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAIA,+BAAA,CAAc,gCAAgC,WAAW,CAAA;AAChF,MAAA,MAAM,UAAU,MAAA,CAAO,OAAA;AACvB,MAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,CAAE,iBAAA;AAC1C,MAAA,IAAI,SAAA,GAAY,cAAA,CAAe,OAAA,EAAS,IAAA,CAAK,OAAO,CAAA;AAKpD,MAAA,IAAA,CAAK,CAAC,SAAA,IAAa,SAAA,CAAU,WAAW,CAAA,KAAM,MAAA,CAAO,kBAAkB,YAAA,EAAc;AACpF,QAAA,MAAM,SAAA,GAAY,MAAM,iBAAA,CAAkB,GAAG,CAAA;AAC7C,QAAA,SAAA,GAAY,SAAA,CAAU,SAAA;AACtB,QAAA,IAAI,CAAC,SAAA,IAAa,SAAA,CAAU,MAAA,KAAW,CAAA,EAAG;AACzC,UAAA,MAAM,IAAIA,+BAAA;AAAA,YACT,qEAAA;AAAA,YACA;AAAA,WACD;AAAA,QACD;AACA,QAAA,OAAO;AAAA,UACN,IAAA,EAAO,OAAA,CAAQ,SAAS,CAAA,IAAgB,UAAU,IAAA,IAAQ,EAAA;AAAA,UAC1D,WAAW,cAAA,GACN,OAAA,CAAQ,WAAW,CAAA,IAAgB,SAAA,CAAU,aAAa,KAAA,CAAA,GAC5D,KAAA,CAAA;AAAA,UACH,iBAAiB,cAAA,GACZ,OAAA,CAAQ,kBAAkB,CAAA,IAAgB,SAAA,CAAU,mBAAmB,KAAA,CAAA,GACzE,KAAA,CAAA;AAAA,UACH;AAAA,SACD;AAAA,MACD;AAEA,MAAA,OAAO;AAAA,QACN,IAAA,EAAO,OAAA,CAAQ,SAAS,CAAA,IAAgB,EAAA;AAAA,QACxC,SAAA,EAAW,cAAA,GAAmB,OAAA,CAAQ,WAAW,KAAgB,KAAA,CAAA,GAAa,KAAA,CAAA;AAAA,QAC9E,eAAA,EAAiB,cAAA,GACZ,OAAA,CAAQ,kBAAkB,KAAgB,KAAA,CAAA,GAC5C,KAAA,CAAA;AAAA,QACH;AAAA,OACD;AAAA,IACD,CAAA,EAAG,QAAQ,KAAK,CAAA;AAAA,EACjB;AAGA,EAAA,eAAe,kBAAkB,GAAA,EAAiD;AACjF,IAAA,IAAI,KAAA,GAA0B,EAAE,IAAA,EAAM,EAAA,EAAG;AACzC,IAAA,WAAA,MAAiB,KAAA,IAAS,cAAA,CAAe,GAAG,CAAA,EAAG;AAC9C,MAAA,IAAI,KAAA,CAAM,IAAA,KAAS,MAAA,EAAQ,KAAA,GAAQ,KAAA,CAAM,QAAA;AAAA,IAC1C;AACA,IAAA,OAAO,KAAA;AAAA,EACR;AAEA,EAAA,gBAAgB,eAAe,GAAA,EAAoD;AAClF,IAAA,MAAM,IAAA,GAAO,cAAA,CAAe,GAAA,CAAI,KAAK,CAAA;AACrC,IAAA,IAAI,GAAA;AACJ,IAAA,IAAI;AACH,MAAA,GAAA,GAAM,MAAM,QAAQ,GAAA,EAAK;AAAA,QACxB,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,MAAM,WAAA,EAAY;AAAA,QAC3B,IAAA,EAAM,IAAA,CAAK,GAAA,EAAK,IAAA,EAAM,IAAI,CAAA;AAAA,QAC1B,QAAQ,GAAA,CAAI;AAAA,OACZ,CAAA;AAAA,IACF,SAAS,CAAA,EAAG;AACX,MAAA,MAAM,IAAIA,+BAAA,CAAc,CAAA,eAAA,EAAmB,CAAA,CAAY,OAAO,IAAI,WAAW,CAAA;AAAA,IAC9E;AACA,IAAA,IAAI,CAAC,GAAA,CAAI,EAAA,EAAI,MAAM,uBAAA,CAAwB,IAAI,MAAA,EAAQ,CAAA,kBAAA,EAAqB,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AACxF,IAAA,IAAI,CAAC,GAAA,CAAI,IAAA,QAAY,IAAIA,+BAAA,CAAc,oCAAoC,WAAW,CAAA;AAEtF,IAAA,MAAM,cAAA,GAAiB,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,CAAE,iBAAA;AAC1C,IAAA,MAAM,MAAA,GAAS,GAAA,CAAI,IAAA,CAAK,SAAA,EAAU;AAClC,IAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI,IAAA,GAAO,EAAA;AACX,IAAA,IAAI,SAAA,GAAY,EAAA;AAChB,IAAA,IAAI,eAAA,GAAkB,EAAA;AAGtB,IAAA,MAAM,SAAA,uBAAgB,GAAA,EAA0D;AAEhF,IAAA,WAAU;AACT,MAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,MAAA,IAAI,IAAA,EAAM;AACV,MAAA,MAAA,IAAU,QAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAM,CAAA;AAChD,MAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAC/B,MAAA,MAAA,GAAS,KAAA,CAAM,KAAI,IAAK,EAAA;AACxB,MAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACzB,QAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,QAAA,IAAI,CAAC,OAAA,CAAQ,UAAA,CAAW,OAAO,CAAA,EAAG;AAClC,QAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,CAAC,EAAE,IAAA,EAAK;AACnC,QAAA,IAAI,SAAS,QAAA,EAAU;AACvB,QAAA,MAAM,MAAA,GAAS,SAAS,IAAI,CAAA;AAgB5B,QAAA,MAAM,KAAA,GAAQ,MAAA,EAAQ,OAAA,GAAU,CAAC,CAAA,EAAG,KAAA;AACpC,QAAA,IAAI,CAAC,KAAA,EAAO;AACZ,QAAA,IAAI,MAAM,OAAA,EAAS;AAClB,UAAA,IAAA,IAAQ,KAAA,CAAM,OAAA;AACd,UAAA,MAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAM,OAAA,EAAQ;AAAA,QAC3C;AACA,QAAA,IAAI,KAAA,CAAM,aAAa,cAAA,EAAgB;AACtC,UAAA,SAAA,IAAa,KAAA,CAAM,SAAA;AACnB,UAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,MAAM,SAAA,EAAU;AAAA,QAClD;AACA,QAAA,IAAI,KAAA,CAAM,oBAAoB,cAAA,EAAgB;AAC7C,UAAA,eAAA,IAAmB,KAAA,CAAM,gBAAA;AAAA,QAC1B;AACA,QAAA,IAAI,MAAM,UAAA,EAAY;AACrB,UAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,UAAA,EAAY;AACpC,YAAA,MAAM,GAAA,GAAM,KAAK,KAAA,IAAS,CAAA;AAC1B,YAAA,MAAM,OAAO,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA,IAAK,EAAE,MAAM,EAAA,EAAG;AAC9C,YAAA,IAAI,IAAA,CAAK,EAAA,EAAI,IAAA,CAAK,EAAA,GAAK,IAAA,CAAK,EAAA;AAC5B,YAAA,IAAI,KAAK,QAAA,EAAU,IAAA,EAAM,IAAA,CAAK,IAAA,GAAO,KAAK,QAAA,CAAS,IAAA;AACnD,YAAA,IAAI,KAAK,QAAA,EAAU,SAAA,EAAW,IAAA,CAAK,IAAA,IAAQ,KAAK,QAAA,CAAS,SAAA;AACzD,YAAA,SAAA,CAAU,GAAA,CAAI,KAAK,IAAI,CAAA;AAAA,UACxB;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAIA,IAAA,MAAM,SAAA,GAAwB,CAAC,GAAG,SAAA,CAAU,SAAS,CAAA,CACnD,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,CAAC,IAAI,CAAA,CAAE,CAAC,CAAC,CAAA,CAC1B,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAA,CACxB,GAAA,CAAI,CAAC,CAAC,GAAA,EAAK,CAAC,CAAA,MAAO;AAAA,MACnB,EAAA,EAAI,CAAA,CAAE,EAAA,IAAM,CAAA,KAAA,EAAQ,GAAG,CAAA,CAAA;AAAA,MACvB,MAAM,IAAA,CAAK,OAAA,CAAQ,IAAI,CAAA,CAAE,IAAc,KAAM,CAAA,CAAE,IAAA;AAAA,MAC/C,SAAA,EAAW,QAAA,CAAS,CAAA,CAAE,IAAI,KAAK;AAAC,KACjC,CAAE,CAAA;AACH,IAAA,KAAA,MAAW,YAAY,SAAA,EAAW;AACjC,MAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,QAAA,EAAS;AAAA,IACrC;AACA,IAAA,MAAM;AAAA,MACL,IAAA,EAAM,MAAA;AAAA,MACN,QAAA,EAAU;AAAA,QACT,IAAA;AAAA,QACA,WAAW,SAAA,IAAa,MAAA;AAAA,QACxB,iBAAiB,eAAA,IAAmB,MAAA;AAAA,QACpC,SAAA,EAAW,SAAA,CAAU,MAAA,GAAS,CAAA,GAAI,SAAA,GAAY;AAAA;AAC/C,KACD;AAAA,EACD;AAEA,EAAA,OAAO;AAAA,IACN,IAAA,EAAM,mBAAA;AAAA,IACN,YAAA,EAAc,YAAA;AAAA,IACd,MAAA;AAAA,IACA,KAAA,EAAO,OAAA;AAAA,IACP,QAAA;AAAA,IACA;AAAA,GACD;AACD;AAEA,SAAS,SAAS,CAAA,EAAoB;AACrC,EAAA,IAAI;AACH,IAAA,OAAO,IAAA,CAAK,MAAM,CAAC,CAAA;AAAA,EACpB,CAAA,CAAA,MAAQ;AACP,IAAA,OAAO,MAAA;AAAA,EACR;AACD;;;ACtWA,IAAM,wBAAA,GAA2B,+BAAA;AAOjC,IAAM,uBAAA,GAAkD;AAAA,EACvD,gBAAA,EAAkB,eAAA;AAAA,EAClB,uBAAA,EAAyB,qBAAA;AAAA,EACzB,wBAAA,EAA0B,aAAA;AAAA,EAC1B,eAAA,EAAiB;AAClB,CAAA;AAoDO,SAAS,sBAAsB,OAAA,EAA2C;AAChF,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAA,IAAW,wBAAA;AAKnC,EAAA,MAAM,mBAAmB,OAAA,KAAY,wBAAA;AACrC,EAAA,IAAI,gBAAA,IAAoBC,+BAAA,EAAc,CAAE,SAAA,EAAW;AAClD,IAAA,MAAM,IAAIC,yCAAA;AAAA,MACT,gFAAA;AAAA,MACA;AAAA,QACC,MAAA,EAAQ,MAAA;AAAA,QACR,MAAA,EACC;AAAA;AAGF,KACD;AAAA,EACD;AAEA,EAAA,MAAM,QAAQ,8BAAA,CAA+B;AAAA,IAC5C,OAAA;AAAA,IACA,eAAe,OAAA,CAAQ,aAAA;AAAA,IACvB,cAAc,OAAA,CAAQ,YAAA;AAAA,IACtB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,cAAc,OAAA,CAAQ,YAAA;AAAA;AAAA;AAAA,IAGtB,OAAA,EAAS,EAAE,GAAG,uBAAA,EAAyB,GAAI,OAAA,CAAQ,OAAA,IAAW,EAAC,EAAG;AAAA,IAClE,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,WAAW,OAAA,CAAQ;AAAA,GACnB,CAAA;AAED,EAAA,OAAO;AAAA,IACN,IAAA,EAAM,SAAA;AAAA,IACN,cAAc,KAAA,CAAM,YAAA;AAAA,IACpB,QAAQ,KAAA,CAAM,MAAA;AAAA,IACd,KAAA,EAAO,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,KAAK,CAAA;AAAA,IAC7B,QAAA,EAAU,KAAA,CAAM,QAAA,CAAS,IAAA,CAAK,KAAK,CAAA;AAAA,IACnC,cAAA,EAAgB,KAAA,CAAM,cAAA,CAAe,IAAA,CAAK,KAAK;AAAA,GAChD;AACD","file":"chunk-JLPLGU7O.cjs","sourcesContent":["/**\n * LLM provider abstraction. Agents and workflows depend only on this interface,\n * never on a concrete provider, so new providers can be added without changing\n * agent/workflow code. (FR-007)\n *\n * Credentials are always obtained via a caller-supplied callback and are never\n * bundled, persisted, or logged by the framework. (FR-005a, FR-008)\n *\n * @packageDocumentation\n */\n\nimport type { Message, ModelCapabilities } from \"../core/types.js\";\nimport { ValidationError } from \"../core/errors.js\";\n\n/** A caller-supplied source of credentials. The framework never stores the value. */\nexport interface CredentialSource {\n\t/** Return the current credential (token/api key). May be async. */\n\tgetCredential(): string | Promise<string>;\n}\n\n/**\n * Model configuration for a provider. A provider may expose **one or more** models\n * (e.g. GitHub Copilot offers several; an OpenAI-compatible endpoint is usually one).\n * Supply either a single `capabilities` object or an array via `models`.\n */\nexport interface ModelSelectionOptions {\n\t/** Single-model shorthand. */\n\tcapabilities?: ModelCapabilities;\n\t/** One or more models this provider can use. */\n\tmodels?: ModelCapabilities[];\n\t/** Name of the default model (defaults to the first entry). */\n\tdefaultModel?: string;\n}\n\n/** Resolved model set with a default and a lookup helper. */\nexport interface ResolvedModels {\n\t/** All configured models (at least one). */\n\tmodels: ModelCapabilities[];\n\t/** The default model used when a request does not specify one. */\n\tdefaultModel: ModelCapabilities;\n\t/** Look up a model by name, or return the default when omitted. */\n\tmodelOf(name?: string): ModelCapabilities;\n}\n\n/**\n * Normalize {@link ModelSelectionOptions} into a model list, a default, and a\n * lookup helper. Throws {@link ValidationError} if no model is configured or a\n * named model is missing.\n *\n * @example\n * ```ts\n * const { defaultModel, modelOf } = resolveModels({\n * models: [\n * { model: \"gpt-4o\", maxInputTokens: 128000, maxOutputTokens: 16000 },\n * { model: \"o3-mini\", maxInputTokens: 200000, maxOutputTokens: 100000, supportsReasoning: true },\n * ],\n * defaultModel: \"gpt-4o\",\n * });\n * ```\n */\nexport function resolveModels(options: ModelSelectionOptions): ResolvedModels {\n\tconst models = options.models ?? (options.capabilities ? [options.capabilities] : []);\n\tif (models.length === 0) {\n\t\tthrow new ValidationError(\"Provider requires at least one model (set `capabilities` or `models`)\");\n\t}\n\tconst defaultModel = options.defaultModel\n\t\t? models.find((m) => m.model === options.defaultModel)\n\t\t: models[0];\n\tif (!defaultModel) {\n\t\tthrow new ValidationError(`defaultModel \"${options.defaultModel}\" is not present in models`);\n\t}\n\tconst modelOf = (name?: string): ModelCapabilities => {\n\t\tif (!name) return defaultModel;\n\t\tconst found = models.find((m) => m.model === name);\n\t\tif (!found) {\n\t\t\tthrow new ValidationError(`Model \"${name}\" is not configured for this provider`);\n\t\t}\n\t\treturn found;\n\t};\n\treturn { models, defaultModel, modelOf };\n}\n\n/** A tool description passed to the provider so the model can decide to call it. */\nexport interface ToolSpec {\n\tname: string;\n\tdescription: string;\n\tinputSchema: Record<string, unknown>;\n}\n\n/** A request to generate a model response. */\nexport interface GenerateRequest {\n\tmessages: Message[];\n\ttools?: ToolSpec[];\n\t/** Which configured model to use; defaults to the provider's default model. */\n\tmodel?: string;\n\t/** Abort signal to cancel an in-flight request. */\n\tsignal?: AbortSignal;\n}\n\n/** A tool call requested by the model. */\nexport interface ToolCall {\n\tid: string;\n\tname: string;\n\t/** Raw JSON arguments (validated by the tools module before invocation). */\n\targuments: unknown;\n}\n\n/** A complete (non-streaming) model response. */\nexport interface GenerateResponse {\n\t/** Final answer text. */\n\ttext: string;\n\t/** Reasoning/thinking content — only present for reasoning-capable models. (FR-003a) */\n\treasoning?: string;\n\t/**\n\t * Opaque reasoning blob (e.g. Claude thinking signature) to round-trip on the\n\t * next assistant turn for thinking continuity. Never logged or inspected.\n\t */\n\treasoningOpaque?: string;\n\t/** Tool calls the model wants to make, if any. */\n\ttoolCalls?: ToolCall[];\n\t/** Approximate token usage if reported by the provider. */\n\tusage?: { inputTokens?: number; outputTokens?: number };\n}\n\n/** An incremental streaming chunk. */\nexport type GenerateChunk =\n\t| { type: \"text\"; text: string }\n\t| { type: \"reasoning\"; text: string }\n\t| { type: \"tool-call\"; toolCall: ToolCall }\n\t| { type: \"done\"; response: GenerateResponse };\n\n/**\n * An LLM backend. Implementations adapt a concrete API (Copilot, OpenAI-compatible)\n * onto this uniform surface.\n */\nexport interface Provider {\n\t/** Stable provider identifier, e.g. `\"openai-compatible\"`. */\n\treadonly name: string;\n\t/** The default model's capability configuration. (FR-007a) */\n\treadonly capabilities: ModelCapabilities;\n\t/** All models this provider is configured with (one or more). */\n\treadonly models: ModelCapabilities[];\n\t/** Look up a configured model by name, or the default when omitted. */\n\tmodel(name?: string): ModelCapabilities;\n\t/** Generate a complete response. */\n\tgenerate(req: GenerateRequest): Promise<GenerateResponse>;\n\t/** Generate a streamed response. */\n\tgenerateStream(req: GenerateRequest): AsyncIterable<GenerateChunk>;\n}\n","/**\n * Exponential-backoff retry for transient provider failures. Transient errors\n * (429 with Retry-After, 5xx, network/timeout) are retried; auth/4xx fail fast.\n * (FR-008a)\n *\n * @packageDocumentation\n */\n\nimport { ProviderError } from \"../core/errors.js\";\n\n/** Retry tuning. All fields have safe defaults. */\nexport interface RetryOptions {\n\t/** Maximum retry attempts after the first try. Default 3. */\n\tmaxRetries?: number;\n\t/** Base delay in ms for backoff. Default 250. */\n\tbaseDelayMs?: number;\n\t/** Maximum delay cap in ms. Default 8000. */\n\tmaxDelayMs?: number;\n}\n\nconst DEFAULTS: Required<RetryOptions> = {\n\tmaxRetries: 3,\n\tbaseDelayMs: 250,\n\tmaxDelayMs: 8000,\n};\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((r) => setTimeout(r, ms));\n}\n\n/**\n * Run `fn`, retrying transient {@link ProviderError}s with exponential backoff\n * and jitter. Non-transient errors are rethrown immediately (fail fast).\n *\n * @param fn - The operation to attempt. It should throw a {@link ProviderError}.\n * @param opts - Retry tuning.\n * @param retryAfterMs - Optional hook returning a server-specified delay (Retry-After).\n */\nexport async function withRetry<T>(\n\tfn: () => Promise<T>,\n\topts?: RetryOptions,\n\tretryAfterMs?: (err: ProviderError) => number | undefined,\n): Promise<T> {\n\tconst cfg = { ...DEFAULTS, ...opts };\n\tlet attempt = 0;\n\n\tfor (; ;) {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (err) {\n\t\t\tconst isRetryable = err instanceof ProviderError && err.retryable;\n\t\t\tif (!isRetryable || attempt >= cfg.maxRetries) {\n\t\t\t\tthrow err;\n\t\t\t}\n\t\t\tconst serverDelay = retryAfterMs?.(err as ProviderError);\n\t\t\tconst backoff = Math.min(cfg.baseDelayMs * 2 ** attempt, cfg.maxDelayMs);\n\t\t\tconst jitter = Math.random() * cfg.baseDelayMs;\n\t\t\tawait sleep(serverDelay ?? backoff + jitter);\n\t\t\tattempt++;\n\t\t}\n\t}\n}\n\n/** Map an HTTP status to a {@link ProviderError} with the right retry semantics. */\nexport function providerErrorFromStatus(status: number, message: string): ProviderError {\n\tif (status === 429 || status >= 500) {\n\t\treturn new ProviderError(message, \"transient\", { status });\n\t}\n\tif (status === 401 || status === 403) {\n\t\treturn new ProviderError(message, \"auth\", { status });\n\t}\n\treturn new ProviderError(message, \"client\", { status });\n}\n","/**\n * OpenAI-compatible provider. Targets any endpoint speaking the OpenAI\n * `/chat/completions` API, including local servers such as LM Studio via a custom\n * `baseUrl`, and GitHub Copilot (see {@link createCopilotProvider}). (FR-006)\n *\n * Provider compatibility notes (handled here so callers don't have to):\n * - Tool names are sanitized to `^[a-zA-Z0-9_-]+$` on the wire (OpenAI/Copilot\n * reject dotted names like `webiq.browse`) and translated back to the registry\n * key when the model calls them.\n * - Assistant turns that requested tools emit `tool_calls` with `content: null`\n * so strict providers (e.g. Anthropic) can pair each tool result with its call.\n * - Streaming responses accumulate `delta.tool_calls[]` keyed by `index`\n * (fragments may start at a non-zero index when reasoning occupies 0/1).\n * - Some reasoning models report `finish_reason: \"tool_calls\"` from the\n * non-streaming endpoint without a `tool_calls` array; `generate` transparently\n * re-requests in streaming mode and assembles them, failing loud (typed\n * {@link ProviderError}) rather than silently stopping if none materialize.\n *\n * @packageDocumentation\n */\n\nimport type { Message, ContentPart, MessageToolCall } from \"../core/types.js\";\nimport { ProviderError } from \"../core/errors.js\";\nimport type {\n\tProvider,\n\tCredentialSource,\n\tGenerateRequest,\n\tGenerateResponse,\n\tGenerateChunk,\n\tToolCall,\n\tToolSpec,\n} from \"./provider.js\";\nimport { resolveModels, type ModelSelectionOptions } from \"./provider.js\";\nimport { withRetry, providerErrorFromStatus, type RetryOptions } from \"./retry.js\";\n\n/**\n * Options for {@link createOpenAICompatibleProvider}.\n *\n * Supply a single model via `capabilities`, or multiple via `models` (most\n * OpenAI-compatible endpoints expose one model, but multiple are supported).\n */\nexport interface OpenAICompatibleProviderOptions extends CredentialSource, ModelSelectionOptions {\n\t/** Base URL of the OpenAI-compatible API, e.g. `http://localhost:1234/v1`. */\n\tbaseUrl: string;\n\t/**\n\t * Extra request headers merged into every call (e.g. provider-required\n\t * identification headers). The `authorization` header is always set from\n\t * `getCredential()` and cannot be overridden here.\n\t */\n\theaders?: Record<string, string>;\n\t/** Retry tuning for transient failures. */\n\tretry?: RetryOptions;\n\t/** Optional custom fetch (for testing or non-standard runtimes). */\n\tfetchImpl?: typeof fetch;\n}\n\ninterface OpenAIMessage {\n\trole: string;\n\tcontent: unknown;\n\ttool_calls?: Array<{ id: string; type: \"function\"; function: { name: string; arguments: string } }>;\n\ttool_call_id?: string;\n\tname?: string;\n\treasoning_opaque?: string;\n}\n\n/** OpenAI/Copilot require tool names to match `^[a-zA-Z0-9_-]{1,128}$`. */\nconst UNSAFE_TOOL_NAME_CHARS = /[^a-zA-Z0-9_-]/g;\n\n/**\n * Sanitize a (possibly namespaced) tool name for the wire. Dotted MCP names like\n * `webiq.browse` become `webiq_browse`; the original is recovered via the\n * per-request name map when the model calls the tool.\n */\nfunction sanitizeToolName(name: string): string {\n\treturn name.replace(UNSAFE_TOOL_NAME_CHARS, \"_\");\n}\n\nfunction toOpenAIContent(parts: ContentPart[]): unknown {\n\tif (parts.every((p) => p.type === \"text\")) {\n\t\treturn parts.map((p) => (p as { text: string }).text).join(\"\");\n\t}\n\treturn parts.map((p) =>\n\t\tp.type === \"text\"\n\t\t\t? { type: \"text\", text: p.text }\n\t\t\t: { type: \"image_url\", image_url: { url: p.data } },\n\t);\n}\n\nfunction toWireToolCalls(\n\ttoolCalls: MessageToolCall[],\n): Array<{ id: string; type: \"function\"; function: { name: string; arguments: string } }> {\n\treturn toolCalls.map((tc) => ({\n\t\tid: tc.id,\n\t\ttype: \"function\",\n\t\tfunction: {\n\t\t\tname: sanitizeToolName(tc.name),\n\t\t\targuments:\n\t\t\t\ttypeof tc.arguments === \"string\" ? tc.arguments : JSON.stringify(tc.arguments ?? {}),\n\t\t},\n\t}));\n}\n\nfunction toOpenAIMessages(messages: Message[]): OpenAIMessage[] {\n\treturn messages.map((m) => {\n\t\tconst msg: OpenAIMessage = { role: m.role, content: toOpenAIContent(m.parts) };\n\t\tif (m.toolCalls && m.toolCalls.length > 0) {\n\t\t\tmsg.tool_calls = toWireToolCalls(m.toolCalls);\n\t\t\t// Strict providers require `content: null` (not \"\") on an assistant turn\n\t\t\t// that only carries tool calls.\n\t\t\tconst hasText = m.parts.some((p) => p.type === \"text\" && p.text.length > 0);\n\t\t\tif (!hasText) msg.content = null;\n\t\t}\n\t\tif (m.toolCallId) msg.tool_call_id = m.toolCallId;\n\t\tif (m.name) msg.name = sanitizeToolName(m.name);\n\t\tif (m.reasoningOpaque) msg.reasoning_opaque = m.reasoningOpaque;\n\t\treturn msg;\n\t});\n}\n\n/** Wire tool specs plus a map from sanitized name back to the registry key. */\ninterface WireTools {\n\ttools?: Array<{ type: \"function\"; function: { name: string; description: string; parameters: unknown } }>;\n\tnameMap: Map<string, string>;\n}\n\nfunction buildWireTools(specs?: ToolSpec[]): WireTools {\n\tconst nameMap = new Map<string, string>();\n\tif (!specs || specs.length === 0) return { tools: undefined, nameMap };\n\tconst tools = specs.map((t) => {\n\t\tconst wireName = sanitizeToolName(t.name);\n\t\tnameMap.set(wireName, t.name);\n\t\treturn {\n\t\t\ttype: \"function\" as const,\n\t\t\tfunction: { name: wireName, description: t.description, parameters: t.inputSchema },\n\t\t};\n\t});\n\treturn { tools, nameMap };\n}\n\n/**\n * Create an OpenAI-compatible provider (works with LM Studio, vLLM, etc.).\n *\n * @example\n * ```ts\n * const provider = createOpenAICompatibleProvider({\n * baseUrl: \"http://localhost:1234/v1\",\n * getCredential: () => process.env.LMSTUDIO_KEY ?? \"\",\n * capabilities: { model: \"local\", maxInputTokens: 262144, maxOutputTokens: 32000 },\n * });\n * ```\n */\nexport function createOpenAICompatibleProvider(\n\toptions: OpenAICompatibleProviderOptions,\n): Provider {\n\tconst doFetch = options.fetchImpl ?? globalThis.fetch;\n\tconst url = `${options.baseUrl.replace(/\\/$/, \"\")}/chat/completions`;\n\tconst { models, defaultModel, modelOf } = resolveModels(options);\n\n\tasync function authHeaders(): Promise<Record<string, string>> {\n\t\tconst cred = await options.getCredential();\n\t\t// content-type first, then caller headers (may override it), then the\n\t\t// credential-derived authorization which always wins.\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"content-type\": \"application/json\",\n\t\t\t...(options.headers ?? {}),\n\t\t};\n\t\tif (cred) headers[\"authorization\"] = `Bearer ${cred}`;\n\t\treturn headers;\n\t}\n\n\tfunction body(req: GenerateRequest, stream: boolean, wire: WireTools): string {\n\t\treturn JSON.stringify({\n\t\t\tmodel: modelOf(req.model).model,\n\t\t\tmessages: toOpenAIMessages(req.messages),\n\t\t\tstream,\n\t\t\t...(wire.tools ? { tools: wire.tools } : {}),\n\t\t});\n\t}\n\n\tfunction parseToolCalls(raw: unknown, nameMap: Map<string, string>): ToolCall[] | undefined {\n\t\tconst calls = (raw as {\n\t\t\ttool_calls?: Array<{ id: string; function: { name: string; arguments: string } }>;\n\t\t})?.tool_calls;\n\t\tif (!calls || calls.length === 0) return undefined;\n\t\treturn calls.map((c) => ({\n\t\t\tid: c.id,\n\t\t\tname: nameMap.get(c.function.name) ?? c.function.name,\n\t\t\targuments: safeJson(c.function.arguments),\n\t\t}));\n\t}\n\n\tasync function generate(req: GenerateRequest): Promise<GenerateResponse> {\n\t\treturn withRetry(async () => {\n\t\t\tconst wire = buildWireTools(req.tools);\n\t\t\tlet res: Response;\n\t\t\ttry {\n\t\t\t\tres = await doFetch(url, {\n\t\t\t\t\tmethod: \"POST\",\n\t\t\t\t\theaders: await authHeaders(),\n\t\t\t\t\tbody: body(req, false, wire),\n\t\t\t\t\tsignal: req.signal,\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tthrow new ProviderError(`Network error: ${(e as Error).message}`, \"transient\");\n\t\t\t}\n\t\t\tif (!res.ok) throw providerErrorFromStatus(res.status, `Provider returned ${res.status}`);\n\n\t\t\tlet json: Record<string, unknown>;\n\t\t\ttry {\n\t\t\t\tjson = (await res.json()) as Record<string, unknown>;\n\t\t\t} catch {\n\t\t\t\tthrow new ProviderError(\"Malformed provider response\", \"malformed\");\n\t\t\t}\n\t\t\tconst choice = (\n\t\t\t\tjson[\"choices\"] as Array<{ message: Record<string, unknown>; finish_reason?: string }>\n\t\t\t)?.[0];\n\t\t\tif (!choice) throw new ProviderError(\"Provider returned no choices\", \"malformed\");\n\t\t\tconst message = choice.message;\n\t\t\tconst reasoningModel = modelOf(req.model).supportsReasoning;\n\t\t\tlet toolCalls = parseToolCalls(message, wire.nameMap);\n\n\t\t\t// Bug 4(b): some reasoning models report `finish_reason: \"tool_calls\"` from\n\t\t\t// the non-streaming endpoint without a `tool_calls` array. Re-request in\n\t\t\t// streaming mode and assemble them so the agent loop can proceed.\n\t\t\tif ((!toolCalls || toolCalls.length === 0) && choice.finish_reason === \"tool_calls\") {\n\t\t\t\tconst assembled = await assembleViaStream(req);\n\t\t\t\ttoolCalls = assembled.toolCalls;\n\t\t\t\tif (!toolCalls || toolCalls.length === 0) {\n\t\t\t\t\tthrow new ProviderError(\n\t\t\t\t\t\t\"Provider signaled tool_calls but returned none (even when streamed)\",\n\t\t\t\t\t\t\"malformed\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\ttext: (message[\"content\"] as string) ?? assembled.text ?? \"\",\n\t\t\t\t\treasoning: reasoningModel\n\t\t\t\t\t\t? ((message[\"reasoning\"] as string) ?? assembled.reasoning ?? undefined)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\treasoningOpaque: reasoningModel\n\t\t\t\t\t\t? ((message[\"reasoning_opaque\"] as string) ?? assembled.reasoningOpaque ?? undefined)\n\t\t\t\t\t\t: undefined,\n\t\t\t\t\ttoolCalls,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttext: (message[\"content\"] as string) ?? \"\",\n\t\t\t\treasoning: reasoningModel ? ((message[\"reasoning\"] as string) ?? undefined) : undefined,\n\t\t\t\treasoningOpaque: reasoningModel\n\t\t\t\t\t? ((message[\"reasoning_opaque\"] as string) ?? undefined)\n\t\t\t\t\t: undefined,\n\t\t\t\ttoolCalls,\n\t\t\t};\n\t\t}, options.retry);\n\t}\n\n\t/** Drive a streaming request to completion and return its assembled final response. */\n\tasync function assembleViaStream(req: GenerateRequest): Promise<GenerateResponse> {\n\t\tlet final: GenerateResponse = { text: \"\" };\n\t\tfor await (const chunk of generateStream(req)) {\n\t\t\tif (chunk.type === \"done\") final = chunk.response;\n\t\t}\n\t\treturn final;\n\t}\n\n\tasync function* generateStream(req: GenerateRequest): AsyncIterable<GenerateChunk> {\n\t\tconst wire = buildWireTools(req.tools);\n\t\tlet res: Response;\n\t\ttry {\n\t\t\tres = await doFetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: await authHeaders(),\n\t\t\t\tbody: body(req, true, wire),\n\t\t\t\tsignal: req.signal,\n\t\t\t});\n\t\t} catch (e) {\n\t\t\tthrow new ProviderError(`Network error: ${(e as Error).message}`, \"transient\");\n\t\t}\n\t\tif (!res.ok) throw providerErrorFromStatus(res.status, `Provider returned ${res.status}`);\n\t\tif (!res.body) throw new ProviderError(\"Provider returned no stream body\", \"malformed\");\n\n\t\tconst reasoningModel = modelOf(req.model).supportsReasoning;\n\t\tconst reader = res.body.getReader();\n\t\tconst decoder = new TextDecoder();\n\t\tlet buffer = \"\";\n\t\tlet text = \"\";\n\t\tlet reasoning = \"\";\n\t\tlet reasoningOpaque = \"\";\n\t\t// Accumulate streamed tool-call fragments keyed by their `index` (which may\n\t\t// start at a non-zero value when reasoning deltas occupy the first indices).\n\t\tconst toolAccum = new Map<number, { id?: string; name?: string; args: string }>();\n\n\t\tfor (; ;) {\n\t\t\tconst { value, done } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\tbuffer = lines.pop() ?? \"\";\n\t\t\tfor (const line of lines) {\n\t\t\t\tconst trimmed = line.trim();\n\t\t\t\tif (!trimmed.startsWith(\"data:\")) continue;\n\t\t\t\tconst data = trimmed.slice(5).trim();\n\t\t\t\tif (data === \"[DONE]\") continue;\n\t\t\t\tconst parsed = safeJson(data) as\n\t\t\t\t\t| {\n\t\t\t\t\t\tchoices?: Array<{\n\t\t\t\t\t\t\tdelta?: {\n\t\t\t\t\t\t\t\tcontent?: string;\n\t\t\t\t\t\t\t\treasoning?: string;\n\t\t\t\t\t\t\t\treasoning_opaque?: string;\n\t\t\t\t\t\t\t\ttool_calls?: Array<{\n\t\t\t\t\t\t\t\t\tindex?: number;\n\t\t\t\t\t\t\t\t\tid?: string;\n\t\t\t\t\t\t\t\t\tfunction?: { name?: string; arguments?: string };\n\t\t\t\t\t\t\t\t}>;\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}>;\n\t\t\t\t\t}\n\t\t\t\t\t| undefined;\n\t\t\t\tconst delta = parsed?.choices?.[0]?.delta;\n\t\t\t\tif (!delta) continue;\n\t\t\t\tif (delta.content) {\n\t\t\t\t\ttext += delta.content;\n\t\t\t\t\tyield { type: \"text\", text: delta.content };\n\t\t\t\t}\n\t\t\t\tif (delta.reasoning && reasoningModel) {\n\t\t\t\t\treasoning += delta.reasoning;\n\t\t\t\t\tyield { type: \"reasoning\", text: delta.reasoning };\n\t\t\t\t}\n\t\t\t\tif (delta.reasoning_opaque && reasoningModel) {\n\t\t\t\t\treasoningOpaque += delta.reasoning_opaque;\n\t\t\t\t}\n\t\t\t\tif (delta.tool_calls) {\n\t\t\t\t\tfor (const frag of delta.tool_calls) {\n\t\t\t\t\t\tconst idx = frag.index ?? 0;\n\t\t\t\t\t\tconst slot = toolAccum.get(idx) ?? { args: \"\" };\n\t\t\t\t\t\tif (frag.id) slot.id = frag.id;\n\t\t\t\t\t\tif (frag.function?.name) slot.name = frag.function.name;\n\t\t\t\t\t\tif (frag.function?.arguments) slot.args += frag.function.arguments;\n\t\t\t\t\t\ttoolAccum.set(idx, slot);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Materialize accumulated tool calls (sorted by stream index) and surface\n\t\t// them both as chunks and in the final `done` response.\n\t\tconst toolCalls: ToolCall[] = [...toolAccum.entries()]\n\t\t\t.sort((a, b) => a[0] - b[0])\n\t\t\t.filter(([, s]) => s.name)\n\t\t\t.map(([idx, s]) => ({\n\t\t\t\tid: s.id ?? `call_${idx}`,\n\t\t\t\tname: wire.nameMap.get(s.name as string) ?? (s.name as string),\n\t\t\t\targuments: safeJson(s.args) ?? {},\n\t\t\t}));\n\t\tfor (const toolCall of toolCalls) {\n\t\t\tyield { type: \"tool-call\", toolCall };\n\t\t}\n\t\tyield {\n\t\t\ttype: \"done\",\n\t\t\tresponse: {\n\t\t\t\ttext,\n\t\t\t\treasoning: reasoning || undefined,\n\t\t\t\treasoningOpaque: reasoningOpaque || undefined,\n\t\t\t\ttoolCalls: toolCalls.length > 0 ? toolCalls : undefined,\n\t\t\t},\n\t\t};\n\t}\n\n\treturn {\n\t\tname: \"openai-compatible\",\n\t\tcapabilities: defaultModel,\n\t\tmodels,\n\t\tmodel: modelOf,\n\t\tgenerate,\n\t\tgenerateStream,\n\t};\n}\n\nfunction safeJson(s: string): unknown {\n\ttry {\n\t\treturn JSON.parse(s);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n","/**\n * GitHub Copilot provider. (FR-005)\n *\n * Copilot's chat API is OpenAI-compatible, so this provider configures the shared\n * OpenAI-compatible transport with Copilot's endpoint and the caller-supplied\n * credential (a Copilot/GitHub token). The token is obtained via callback and is\n * never bundled, persisted, or logged. (FR-005a)\n *\n * In a frontend-only deployment the end user supplies their own token (it stays\n * client-side); in a backend deployment the developer may supply it, or the user\n * sends it per request over SSL/TLS and the backend must not log or persist it.\n *\n * Note: the Copilot API (`api.githubcopilot.com`) sends no CORS headers, so it\n * cannot be called directly from a browser. A browser deployment must route through\n * a backend/proxy (set `baseUrl` to it); constructing this provider in a browser\n * against the default host throws {@link RuntimeUnsupportedError}.\n *\n * @packageDocumentation\n */\n\nimport type { Provider, CredentialSource, ModelSelectionOptions } from \"./provider.js\";\nimport type { RetryOptions } from \"./retry.js\";\nimport { createOpenAICompatibleProvider } from \"./openai-compatible.js\";\nimport { detectRuntime } from \"../core/runtime.js\";\nimport { RuntimeUnsupportedError } from \"../core/errors.js\";\n\n/** Default Copilot-compatible chat completions base URL. */\nconst DEFAULT_COPILOT_BASE_URL = \"https://api.githubcopilot.com\";\n\n/**\n * Headers `api.githubcopilot.com` requires on every request. Omitting any of\n * these causes the API to reject the call with HTTP 400. They are sent by default\n * and can be overridden per option via `headers`.\n */\nconst COPILOT_DEFAULT_HEADERS: Record<string, string> = {\n\t\"Editor-Version\": \"vscode/1.95.0\",\n\t\"Editor-Plugin-Version\": \"copilot-chat/0.20.0\",\n\t\"Copilot-Integration-Id\": \"vscode-chat\",\n\t\"Openai-Intent\": \"conversation-panel\",\n};\n\n/**\n * Options for {@link createCopilotProvider}.\n *\n * GitHub Copilot exposes several models, so configure them via `models` (with an\n * optional `defaultModel`). A single `capabilities` object is also accepted.\n */\nexport interface CopilotProviderOptions extends CredentialSource, ModelSelectionOptions {\n\t/** Override the Copilot base URL if needed. */\n\tbaseUrl?: string;\n\t/**\n\t * Extra/override request headers. Merged over the required Copilot defaults\n\t * (`Editor-Version`, `Editor-Plugin-Version`, `Copilot-Integration-Id`,\n\t * `Openai-Intent`), so you can adjust them without losing the others.\n\t */\n\theaders?: Record<string, string>;\n\t/** Retry tuning for transient failures. */\n\tretry?: RetryOptions;\n\t/** Optional custom fetch (for testing or non-standard runtimes). */\n\tfetchImpl?: typeof fetch;\n}\n\n/**\n * Create a GitHub Copilot provider.\n *\n * @example Single model\n * ```ts\n * const provider = createCopilotProvider({\n * getCredential: () => myCopilotToken, // never logged or persisted\n * capabilities: { model: \"gpt-4o\", maxInputTokens: 128000, maxOutputTokens: 16000 },\n * });\n * ```\n *\n * @example Multiple models\n * ```ts\n * const provider = createCopilotProvider({\n * getCredential: () => myCopilotToken,\n * models: [\n * { model: \"gpt-4o\", maxInputTokens: 128000, maxOutputTokens: 16000, supportsVision: true },\n * { model: \"o3-mini\", maxInputTokens: 200000, maxOutputTokens: 100000, supportsReasoning: true },\n * ],\n * defaultModel: \"gpt-4o\",\n * });\n * // Pick a model per request: provider.generate({ messages, model: \"o3-mini\" })\n * ```\n *\n * @throws {RuntimeUnsupportedError} when constructed in a browser against the\n * default Copilot host. `api.githubcopilot.com` does not send CORS headers, so a\n * browser cannot call it directly — host a small backend/proxy and point `baseUrl`\n * at it (which lifts this guard), or run the provider server-side (Node/edge).\n */\nexport function createCopilotProvider(options: CopilotProviderOptions): Provider {\n\tconst baseUrl = options.baseUrl ?? DEFAULT_COPILOT_BASE_URL;\n\n\t// Frontend-only guard: the Copilot API has no CORS support, so a browser must\n\t// route through a backend/proxy. Setting a custom `baseUrl` (your proxy) is the\n\t// supported opt-in and lifts this guard. Edge/Node (server-side) are unaffected.\n\tconst usingDefaultHost = baseUrl === DEFAULT_COPILOT_BASE_URL;\n\tif (usingDefaultHost && detectRuntime().isBrowser) {\n\t\tthrow new RuntimeUnsupportedError(\n\t\t\t\"GitHub Copilot directly from a browser (the Copilot API sends no CORS headers)\",\n\t\t\t{\n\t\t\t\treason: \"cors\",\n\t\t\t\tremedy:\n\t\t\t\t\t\"Run a lightweight backend/proxy (e.g. a Vite dev-server proxy or a small server route) \" +\n\t\t\t\t\t\"that forwards to https://api.githubcopilot.com, then set `baseUrl` to your proxy URL. \" +\n\t\t\t\t\t\"Alternatively, run the Copilot provider server-side (Node or an edge function).\",\n\t\t\t},\n\t\t);\n\t}\n\n\tconst inner = createOpenAICompatibleProvider({\n\t\tbaseUrl,\n\t\tgetCredential: options.getCredential,\n\t\tcapabilities: options.capabilities,\n\t\tmodels: options.models,\n\t\tdefaultModel: options.defaultModel,\n\t\t// Copilot rejects calls missing its identification headers; defaults are\n\t\t// applied here and remain overridable via `options.headers`.\n\t\theaders: { ...COPILOT_DEFAULT_HEADERS, ...(options.headers ?? {}) },\n\t\tretry: options.retry,\n\t\tfetchImpl: options.fetchImpl,\n\t});\n\t// Preserve the provider contract but report the Copilot name.\n\treturn {\n\t\tname: \"copilot\",\n\t\tcapabilities: inner.capabilities,\n\t\tmodels: inner.models,\n\t\tmodel: inner.model.bind(inner),\n\t\tgenerate: inner.generate.bind(inner),\n\t\tgenerateStream: inner.generateStream.bind(inner),\n\t};\n}\n"]}
@@ -9,8 +9,11 @@ function detectRuntime() {
9
9
  const g = globalThis;
10
10
  const proc = g["process"];
11
11
  const isNode = typeof proc !== "undefined" && !!proc.versions?.node;
12
+ const win = g["window"];
13
+ const isBrowser = typeof win !== "undefined" && typeof win.document !== "undefined";
12
14
  cached = {
13
15
  isNode,
16
+ isBrowser,
14
17
  // Process spawning requires Node's child_process; treat Node as capable.
15
18
  canSpawnProcess: isNode,
16
19
  hasLocalStorage: typeof g["localStorage"] !== "undefined",
@@ -30,5 +33,5 @@ function resetRuntimeCache() {
30
33
  exports.detectRuntime = detectRuntime;
31
34
  exports.requireCapability = requireCapability;
32
35
  exports.resetRuntimeCache = resetRuntimeCache;
33
- //# sourceMappingURL=chunk-FOTCUNP5.cjs.map
34
- //# sourceMappingURL=chunk-FOTCUNP5.cjs.map
36
+ //# sourceMappingURL=chunk-N64ZFATA.cjs.map
37
+ //# sourceMappingURL=chunk-N64ZFATA.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/runtime.ts"],"names":["RuntimeUnsupportedError"],"mappings":";;;;;AA4BA,IAAI,MAAA;AAGG,SAAS,aAAA,GAAqC;AACpD,EAAA,IAAI,QAAQ,OAAO,MAAA;AAEnB,EAAA,MAAM,CAAA,GAAI,UAAA;AACV,EAAA,MAAM,IAAA,GAAO,EAAE,SAAS,CAAA;AACxB,EAAA,MAAM,SAAS,OAAO,IAAA,KAAS,eAAe,CAAC,CAAC,KAAK,QAAA,EAAU,IAAA;AAC/D,EAAA,MAAM,GAAA,GAAM,EAAE,QAAQ,CAAA;AACtB,EAAA,MAAM,YAAY,OAAO,GAAA,KAAQ,WAAA,IAAe,OAAO,IAAI,QAAA,KAAa,WAAA;AAExE,EAAA,MAAA,GAAS;AAAA,IACR,MAAA;AAAA,IACA,SAAA;AAAA;AAAA,IAEA,eAAA,EAAiB,MAAA;AAAA,IACjB,eAAA,EAAiB,OAAO,CAAA,CAAE,cAAc,CAAA,KAAM,WAAA;AAAA,IAC9C,YAAA,EAAc,OAAO,CAAA,CAAE,WAAW,CAAA,KAAM;AAAA,GACzC;AACA,EAAA,OAAO,MAAA;AACR;AASO,SAAS,iBAAA,CACf,YACA,OAAA,EACO;AACP,EAAA,IAAI,CAAC,aAAA,EAAc,CAAE,UAAU,CAAA,EAAG;AACjC,IAAA,MAAM,IAAIA,yCAAA,CAAwB,OAAA,EAAS,EAAE,YAAY,CAAA;AAAA,EAC1D;AACD;AAGO,SAAS,iBAAA,GAA0B;AACzC,EAAA,MAAA,GAAS,MAAA;AACV","file":"chunk-N64ZFATA.cjs","sourcesContent":["/**\n * Runtime capability detection. The framework runs in browsers, edge runtimes,\n * and Node. Features that need Node-only APIs (process spawning, filesystem) are\n * gated behind these checks and throw {@link RuntimeUnsupportedError} when used\n * in a runtime that cannot support them. (FR-030, FR-030a)\n *\n * @packageDocumentation\n */\n\nimport { RuntimeUnsupportedError } from \"./errors.js\";\n\n/** Describes which optional capabilities the current runtime supports. */\nexport interface RuntimeCapabilities {\n\t/** Can spawn child processes (Node only) — required for stdio MCP transport. */\n\tcanSpawnProcess: boolean;\n\t/** Has `localStorage` available (browsers). */\n\thasLocalStorage: boolean;\n\t/** Has `indexedDB` available (browsers). */\n\thasIndexedDB: boolean;\n\t/** Running under Node.js. */\n\tisNode: boolean;\n\t/**\n\t * Running inside a web browser (has `window`/`document`). Distinguished from\n\t * edge runtimes, which also lack Node but make server-side (CORS-free) requests.\n\t */\n\tisBrowser: boolean;\n}\n\nlet cached: RuntimeCapabilities | undefined;\n\n/** Detect the current runtime's capabilities (memoized). */\nexport function detectRuntime(): RuntimeCapabilities {\n\tif (cached) return cached;\n\n\tconst g = globalThis as Record<string, unknown>;\n\tconst proc = g[\"process\"] as { versions?: { node?: string } } | undefined;\n\tconst isNode = typeof proc !== \"undefined\" && !!proc.versions?.node;\n\tconst win = g[\"window\"] as { document?: unknown } | undefined;\n\tconst isBrowser = typeof win !== \"undefined\" && typeof win.document !== \"undefined\";\n\n\tcached = {\n\t\tisNode,\n\t\tisBrowser,\n\t\t// Process spawning requires Node's child_process; treat Node as capable.\n\t\tcanSpawnProcess: isNode,\n\t\thasLocalStorage: typeof g[\"localStorage\"] !== \"undefined\",\n\t\thasIndexedDB: typeof g[\"indexedDB\"] !== \"undefined\",\n\t};\n\treturn cached;\n}\n\n/**\n * Assert that a runtime capability is present, throwing a typed error otherwise.\n *\n * @param capability - The capability key to require.\n * @param feature - Human-readable feature name used in the error message.\n * @throws {RuntimeUnsupportedError} when the capability is unavailable.\n */\nexport function requireCapability(\n\tcapability: keyof RuntimeCapabilities,\n\tfeature: string,\n): void {\n\tif (!detectRuntime()[capability]) {\n\t\tthrow new RuntimeUnsupportedError(feature, { capability });\n\t}\n}\n\n/** Reset the memoized detection — intended for tests only. */\nexport function resetRuntimeCache(): void {\n\tcached = undefined;\n}\n"]}
@@ -7,8 +7,11 @@ function detectRuntime() {
7
7
  const g = globalThis;
8
8
  const proc = g["process"];
9
9
  const isNode = typeof proc !== "undefined" && !!proc.versions?.node;
10
+ const win = g["window"];
11
+ const isBrowser = typeof win !== "undefined" && typeof win.document !== "undefined";
10
12
  cached = {
11
13
  isNode,
14
+ isBrowser,
12
15
  // Process spawning requires Node's child_process; treat Node as capable.
13
16
  canSpawnProcess: isNode,
14
17
  hasLocalStorage: typeof g["localStorage"] !== "undefined",
@@ -26,5 +29,5 @@ function resetRuntimeCache() {
26
29
  }
27
30
 
28
31
  export { detectRuntime, requireCapability, resetRuntimeCache };
29
- //# sourceMappingURL=chunk-ACBIHS5H.js.map
30
- //# sourceMappingURL=chunk-ACBIHS5H.js.map
32
+ //# sourceMappingURL=chunk-QXAJ4DUJ.js.map
33
+ //# sourceMappingURL=chunk-QXAJ4DUJ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/runtime.ts"],"names":[],"mappings":";;;AA4BA,IAAI,MAAA;AAGG,SAAS,aAAA,GAAqC;AACpD,EAAA,IAAI,QAAQ,OAAO,MAAA;AAEnB,EAAA,MAAM,CAAA,GAAI,UAAA;AACV,EAAA,MAAM,IAAA,GAAO,EAAE,SAAS,CAAA;AACxB,EAAA,MAAM,SAAS,OAAO,IAAA,KAAS,eAAe,CAAC,CAAC,KAAK,QAAA,EAAU,IAAA;AAC/D,EAAA,MAAM,GAAA,GAAM,EAAE,QAAQ,CAAA;AACtB,EAAA,MAAM,YAAY,OAAO,GAAA,KAAQ,WAAA,IAAe,OAAO,IAAI,QAAA,KAAa,WAAA;AAExE,EAAA,MAAA,GAAS;AAAA,IACR,MAAA;AAAA,IACA,SAAA;AAAA;AAAA,IAEA,eAAA,EAAiB,MAAA;AAAA,IACjB,eAAA,EAAiB,OAAO,CAAA,CAAE,cAAc,CAAA,KAAM,WAAA;AAAA,IAC9C,YAAA,EAAc,OAAO,CAAA,CAAE,WAAW,CAAA,KAAM;AAAA,GACzC;AACA,EAAA,OAAO,MAAA;AACR;AASO,SAAS,iBAAA,CACf,YACA,OAAA,EACO;AACP,EAAA,IAAI,CAAC,aAAA,EAAc,CAAE,UAAU,CAAA,EAAG;AACjC,IAAA,MAAM,IAAI,uBAAA,CAAwB,OAAA,EAAS,EAAE,YAAY,CAAA;AAAA,EAC1D;AACD;AAGO,SAAS,iBAAA,GAA0B;AACzC,EAAA,MAAA,GAAS,MAAA;AACV","file":"chunk-QXAJ4DUJ.js","sourcesContent":["/**\n * Runtime capability detection. The framework runs in browsers, edge runtimes,\n * and Node. Features that need Node-only APIs (process spawning, filesystem) are\n * gated behind these checks and throw {@link RuntimeUnsupportedError} when used\n * in a runtime that cannot support them. (FR-030, FR-030a)\n *\n * @packageDocumentation\n */\n\nimport { RuntimeUnsupportedError } from \"./errors.js\";\n\n/** Describes which optional capabilities the current runtime supports. */\nexport interface RuntimeCapabilities {\n\t/** Can spawn child processes (Node only) — required for stdio MCP transport. */\n\tcanSpawnProcess: boolean;\n\t/** Has `localStorage` available (browsers). */\n\thasLocalStorage: boolean;\n\t/** Has `indexedDB` available (browsers). */\n\thasIndexedDB: boolean;\n\t/** Running under Node.js. */\n\tisNode: boolean;\n\t/**\n\t * Running inside a web browser (has `window`/`document`). Distinguished from\n\t * edge runtimes, which also lack Node but make server-side (CORS-free) requests.\n\t */\n\tisBrowser: boolean;\n}\n\nlet cached: RuntimeCapabilities | undefined;\n\n/** Detect the current runtime's capabilities (memoized). */\nexport function detectRuntime(): RuntimeCapabilities {\n\tif (cached) return cached;\n\n\tconst g = globalThis as Record<string, unknown>;\n\tconst proc = g[\"process\"] as { versions?: { node?: string } } | undefined;\n\tconst isNode = typeof proc !== \"undefined\" && !!proc.versions?.node;\n\tconst win = g[\"window\"] as { document?: unknown } | undefined;\n\tconst isBrowser = typeof win !== \"undefined\" && typeof win.document !== \"undefined\";\n\n\tcached = {\n\t\tisNode,\n\t\tisBrowser,\n\t\t// Process spawning requires Node's child_process; treat Node as capable.\n\t\tcanSpawnProcess: isNode,\n\t\thasLocalStorage: typeof g[\"localStorage\"] !== \"undefined\",\n\t\thasIndexedDB: typeof g[\"indexedDB\"] !== \"undefined\",\n\t};\n\treturn cached;\n}\n\n/**\n * Assert that a runtime capability is present, throwing a typed error otherwise.\n *\n * @param capability - The capability key to require.\n * @param feature - Human-readable feature name used in the error message.\n * @throws {RuntimeUnsupportedError} when the capability is unavailable.\n */\nexport function requireCapability(\n\tcapability: keyof RuntimeCapabilities,\n\tfeature: string,\n): void {\n\tif (!detectRuntime()[capability]) {\n\t\tthrow new RuntimeUnsupportedError(feature, { capability });\n\t}\n}\n\n/** Reset the memoized detection — intended for tests only. */\nexport function resetRuntimeCache(): void {\n\tcached = undefined;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { requireCapability } from './chunk-ACBIHS5H.js';
1
+ import { requireCapability } from './chunk-QXAJ4DUJ.js';
2
2
  import { MCPError } from './chunk-IXV4UIF5.js';
3
3
 
4
4
  // src/mcp/adapter.ts
@@ -65,5 +65,5 @@ async function connectMCP(config) {
65
65
  }
66
66
 
67
67
  export { connectMCP, mcpToolToTool };
68
- //# sourceMappingURL=chunk-YH5746OF.js.map
69
- //# sourceMappingURL=chunk-YH5746OF.js.map
68
+ //# sourceMappingURL=chunk-QYG4HLIC.js.map
69
+ //# sourceMappingURL=chunk-QYG4HLIC.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mcp/adapter.ts","../src/mcp/connection.ts"],"names":[],"mappings":";;;;AAqBO,SAAS,aAAA,CAAc,QAAA,EAAkB,GAAA,EAAiB,MAAA,EAAmB;AACnF,EAAA,OAAO;AAAA,IACN,MAAM,GAAA,CAAI,IAAA;AAAA,IACV,WAAA,EAAa,IAAI,WAAA,IAAe,EAAA;AAAA,IAChC,aAAa,GAAA,CAAI,WAAA;AAAA,IACjB,MAAA,EAAQ,QAAA;AAAA,IACR,OAAA,EAAS,IAAA;AAAA,IACT,MAAM,IAAI,IAAA,EAAiC;AAC1C,MAAA,IAAI;AACH,QAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,QAAA,CAAS,EAAE,MAAM,GAAA,CAAI,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,CAAA;AACxE,QAAA,OAAO,OAAO,OAAA,IAAW,MAAA;AAAA,MAC1B,SAAS,CAAA,EAAG;AACX,QAAA,MAAM,IAAI,SAAS,CAAA,UAAA,EAAa,GAAA,CAAI,IAAI,CAAA,UAAA,EAAc,CAAA,CAAY,OAAO,CAAA,CAAA,EAAI,QAAQ,CAAA;AAAA,MACtF;AAAA,IACD;AAAA,GACD;AACD;;;ACQA,eAAe,gBAAgB,MAAA,EAAiD;AAC/E,EAAA,IAAI,MAAA,CAAO,SAAA,CAAU,IAAA,KAAS,OAAA,EAAS;AAEtC,IAAA,iBAAA,CAAkB,mBAAmB,qBAAqB,CAAA;AAC1D,IAAA,MAAM,EAAE,oBAAA,EAAqB,GAAI,MAAM,OACtC,2CACD,CAAA;AACA,IAAA,OAAO,IAAI,oBAAA,CAAqB;AAAA,MAC/B,OAAA,EAAS,OAAO,SAAA,CAAU,OAAA;AAAA,MAC1B,IAAA,EAAM,MAAA,CAAO,SAAA,CAAU,IAAA,IAAQ;AAAC,KAChC,CAAA;AAAA,EACF;AACA,EAAA,MAAM,EAAE,6BAAA,EAA8B,GAAI,MAAM,OAC/C,oDACD,CAAA;AACA,EAAA,OAAO,IAAI,6BAAA,CAA8B,IAAI,IAAI,MAAA,CAAO,SAAA,CAAU,GAAG,CAAC,CAAA;AACvE;AAWA,eAAsB,WAAW,MAAA,EAAqD;AACrF,EAAA,IAAI,MAAA;AAEJ,EAAA,eAAe,OAAA,GAAyB;AACvC,IAAA,IAAI;AACH,MAAA,MAAM,EAAE,MAAA,EAAO,GAAI,MAAM,OAAO,2CAA2C,CAAA;AAC3E,MAAA,MAAM,SAAA,GAAY,MAAM,eAAA,CAAgB,MAAM,CAAA;AAC9C,MAAA,MAAA,GAAS,IAAI,MAAA,CAAO,EAAE,IAAA,EAAM,oBAAA,EAAsB,OAAA,EAAS,OAAA,EAAQ,EAAG,EAAE,YAAA,EAAc,EAAC,EAAG,CAAA;AAC1F,MAAA,MAAM,MAAA,CAAO,QAAQ,SAAS,CAAA;AAAA,IAC/B,SAAS,CAAA,EAAG;AAEX,MAAA,IAAK,CAAA,CAAY,IAAA,KAAS,yBAAA,EAA2B,MAAM,CAAA;AAC3D,MAAA,MAAM,IAAI,QAAA,CAAS,CAAA,iCAAA,EAAqC,EAAY,OAAO,CAAA,CAAA,EAAI,OAAO,EAAE,CAAA;AAAA,IACzF;AAAA,EACD;AAEA,EAAA,eAAe,SAAA,GAA6B;AAC3C,IAAA,IAAI,CAAC,MAAA,EAAQ,MAAM,IAAI,QAAA,CAAS,eAAA,EAAiB,OAAO,EAAE,CAAA;AAC1D,IAAA,IAAI;AACH,MAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,SAAA,EAAU;AACtC,MAAA,OAAA,CAAQ,MAAA,CAAO,KAAA,IAAS,EAAC,EAAG,GAAA;AAAA,QAAI,CAAC,CAAA,KAChC,aAAA,CAAc,MAAA,CAAO,EAAA,EAAI,GAAG,MAAM;AAAA,OACnC;AAAA,IACD,SAAS,CAAA,EAAG;AACX,MAAA,MAAM,IAAI,QAAA,CAAS,CAAA,sBAAA,EAA0B,EAAY,OAAO,CAAA,CAAA,EAAI,OAAO,EAAE,CAAA;AAAA,IAC9E;AAAA,EACD;AAEA,EAAA,eAAe,KAAA,GAAuB;AACrC,IAAA,MAAM,QAAQ,KAAA,IAAQ;AACtB,IAAA,MAAA,GAAS,MAAA;AAAA,EACV;AAEA,EAAA,OAAO,EAAE,EAAA,EAAI,MAAA,CAAO,EAAA,EAAI,OAAA,EAAS,WAAW,KAAA,EAAM;AACnD","file":"chunk-YH5746OF.js","sourcesContent":["/**\n * Adapts MCP-provided tools onto the framework's uniform {@link Tool} contract,\n * namespaced by the connection id so collisions are impossible. (FR-014, FR-014a)\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from \"../tools/tool.js\";\nimport { MCPError } from \"../core/errors.js\";\n\ninterface MCPToolDef {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: Record<string, unknown>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * Wrap an MCP tool definition as a framework tool. Invocation calls back through\n * the MCP client; failures surface as typed {@link MCPError}/tool errors.\n */\nexport function mcpToolToTool(serverId: string, def: MCPToolDef, client: any): Tool {\n\treturn {\n\t\tname: def.name,\n\t\tdescription: def.description ?? \"\",\n\t\tinputSchema: def.inputSchema,\n\t\tsource: serverId,\n\t\tenabled: true,\n\t\tasync run(args: unknown): Promise<unknown> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool({ name: def.name, arguments: args });\n\t\t\t\treturn result.content ?? result;\n\t\t\t} catch (e) {\n\t\t\t\tthrow new MCPError(`MCP tool \"${def.name}\" failed: ${(e as Error).message}`, serverId);\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * MCP (Model Context Protocol) integration. Connects to MCP servers and exposes\n * their tools through the framework's uniform tool interface.\n *\n * Remote transport (HTTP/SSE) works in all runtimes; stdio (spawning a server\n * process) works only where process spawning is permitted (Node). Requesting\n * stdio elsewhere throws a typed {@link RuntimeUnsupportedError}. (FR-013, FR-013a,\n * FR-013b, FR-030a)\n *\n * The `@modelcontextprotocol/sdk` package is an optional peer dependency and is\n * loaded lazily so browser bundles that do not use MCP pay no cost.\n *\n * @packageDocumentation\n */\n\nimport { MCPError } from \"../core/errors.js\";\nimport { requireCapability } from \"../core/runtime.js\";\nimport type { Tool } from \"../tools/tool.js\";\nimport { mcpToolToTool } from \"./adapter.js\";\n\n/** Transport options for an MCP connection. */\nexport type MCPTransport =\n\t| { kind: \"remote\"; url: string }\n\t| { kind: \"stdio\"; command: string; args?: string[] };\n\n/** Configuration for connecting to an MCP server. */\nexport interface MCPConnectionConfig {\n\t/** Connection id; becomes the namespace prefix for discovered tools. (FR-014a) */\n\tid: string;\n\ttransport: MCPTransport;\n\t/** Whether the connection's tools are enabled. Defaults to true. */\n\tenabled?: boolean;\n}\n\n/** A live connection to an MCP server. */\nexport interface MCPConnection {\n\treadonly id: string;\n\tconnect(): Promise<void>;\n\tlistTools(): Promise<Tool[]>;\n\tclose(): Promise<void>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype AnyClient = any;\n\nasync function createTransport(config: MCPConnectionConfig): Promise<AnyClient> {\n\tif (config.transport.kind === \"stdio\") {\n\t\t// Gate on runtime capability before attempting to spawn. (FR-013b, FR-030a)\n\t\trequireCapability(\"canSpawnProcess\", \"MCP stdio transport\");\n\t\tconst { StdioClientTransport } = await import(\n\t\t\t\"@modelcontextprotocol/sdk/client/stdio.js\"\n\t\t);\n\t\treturn new StdioClientTransport({\n\t\t\tcommand: config.transport.command,\n\t\t\targs: config.transport.args ?? [],\n\t\t});\n\t}\n\tconst { StreamableHTTPClientTransport } = await import(\n\t\t\"@modelcontextprotocol/sdk/client/streamableHttp.js\"\n\t);\n\treturn new StreamableHTTPClientTransport(new URL(config.transport.url));\n}\n\n/**\n * Connect to an MCP server.\n *\n * @example\n * ```ts\n * const mcp = await connectMCP({ id: \"docs\", transport: { kind: \"remote\", url: \"https://mcp.example.com\" } });\n * const tools = await mcp.listTools(); // namespaced as docs.<tool>\n * ```\n */\nexport async function connectMCP(config: MCPConnectionConfig): Promise<MCPConnection> {\n\tlet client: AnyClient | undefined;\n\n\tasync function connect(): Promise<void> {\n\t\ttry {\n\t\t\tconst { Client } = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n\t\t\tconst transport = await createTransport(config);\n\t\t\tclient = new Client({ name: \"agent-framework-js\", version: \"0.1.0\" }, { capabilities: {} });\n\t\t\tawait client.connect(transport);\n\t\t} catch (e) {\n\t\t\t// Preserve typed runtime errors; wrap everything else as an MCP error.\n\t\t\tif ((e as Error).name === \"RuntimeUnsupportedError\") throw e;\n\t\t\tthrow new MCPError(`Failed to connect to MCP server: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function listTools(): Promise<Tool[]> {\n\t\tif (!client) throw new MCPError(\"Not connected\", config.id);\n\t\ttry {\n\t\t\tconst result = await client.listTools();\n\t\t\treturn (result.tools ?? []).map((t: { name: string; description?: string; inputSchema: Record<string, unknown> }) =>\n\t\t\t\tmcpToolToTool(config.id, t, client),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow new MCPError(`Failed to list tools: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function close(): Promise<void> {\n\t\tawait client?.close?.();\n\t\tclient = undefined;\n\t}\n\n\treturn { id: config.id, connect, listTools, close };\n}\n"]}
1
+ {"version":3,"sources":["../src/mcp/adapter.ts","../src/mcp/connection.ts"],"names":[],"mappings":"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","file":"chunk-QYG4HLIC.js","sourcesContent":["/**\n * Adapts MCP-provided tools onto the framework's uniform {@link Tool} contract,\n * namespaced by the connection id so collisions are impossible. (FR-014, FR-014a)\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from \"../tools/tool.js\";\nimport { MCPError } from \"../core/errors.js\";\n\ninterface MCPToolDef {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: Record<string, unknown>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * Wrap an MCP tool definition as a framework tool. Invocation calls back through\n * the MCP client; failures surface as typed {@link MCPError}/tool errors.\n */\nexport function mcpToolToTool(serverId: string, def: MCPToolDef, client: any): Tool {\n\treturn {\n\t\tname: def.name,\n\t\tdescription: def.description ?? \"\",\n\t\tinputSchema: def.inputSchema,\n\t\tsource: serverId,\n\t\tenabled: true,\n\t\tasync run(args: unknown): Promise<unknown> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool({ name: def.name, arguments: args });\n\t\t\t\treturn result.content ?? result;\n\t\t\t} catch (e) {\n\t\t\t\tthrow new MCPError(`MCP tool \"${def.name}\" failed: ${(e as Error).message}`, serverId);\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * MCP (Model Context Protocol) integration. Connects to MCP servers and exposes\n * their tools through the framework's uniform tool interface.\n *\n * Remote transport (HTTP/SSE) works in all runtimes; stdio (spawning a server\n * process) works only where process spawning is permitted (Node). Requesting\n * stdio elsewhere throws a typed {@link RuntimeUnsupportedError}. (FR-013, FR-013a,\n * FR-013b, FR-030a)\n *\n * The `@modelcontextprotocol/sdk` package is an optional peer dependency and is\n * loaded lazily so browser bundles that do not use MCP pay no cost.\n *\n * @packageDocumentation\n */\n\nimport { MCPError } from \"../core/errors.js\";\nimport { requireCapability } from \"../core/runtime.js\";\nimport type { Tool } from \"../tools/tool.js\";\nimport { mcpToolToTool } from \"./adapter.js\";\n\n/** Transport options for an MCP connection. */\nexport type MCPTransport =\n\t| { kind: \"remote\"; url: string }\n\t| { kind: \"stdio\"; command: string; args?: string[] };\n\n/** Configuration for connecting to an MCP server. */\nexport interface MCPConnectionConfig {\n\t/** Connection id; becomes the namespace prefix for discovered tools. (FR-014a) */\n\tid: string;\n\ttransport: MCPTransport;\n\t/** Whether the connection's tools are enabled. Defaults to true. */\n\tenabled?: boolean;\n}\n\n/** A live connection to an MCP server. */\nexport interface MCPConnection {\n\treadonly id: string;\n\tconnect(): Promise<void>;\n\tlistTools(): Promise<Tool[]>;\n\tclose(): Promise<void>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype AnyClient = any;\n\nasync function createTransport(config: MCPConnectionConfig): Promise<AnyClient> {\n\tif (config.transport.kind === \"stdio\") {\n\t\t// Gate on runtime capability before attempting to spawn. (FR-013b, FR-030a)\n\t\trequireCapability(\"canSpawnProcess\", \"MCP stdio transport\");\n\t\tconst { StdioClientTransport } = await import(\n\t\t\t\"@modelcontextprotocol/sdk/client/stdio.js\"\n\t\t);\n\t\treturn new StdioClientTransport({\n\t\t\tcommand: config.transport.command,\n\t\t\targs: config.transport.args ?? [],\n\t\t});\n\t}\n\tconst { StreamableHTTPClientTransport } = await import(\n\t\t\"@modelcontextprotocol/sdk/client/streamableHttp.js\"\n\t);\n\treturn new StreamableHTTPClientTransport(new URL(config.transport.url));\n}\n\n/**\n * Connect to an MCP server.\n *\n * @example\n * ```ts\n * const mcp = await connectMCP({ id: \"docs\", transport: { kind: \"remote\", url: \"https://mcp.example.com\" } });\n * const tools = await mcp.listTools(); // namespaced as docs.<tool>\n * ```\n */\nexport async function connectMCP(config: MCPConnectionConfig): Promise<MCPConnection> {\n\tlet client: AnyClient | undefined;\n\n\tasync function connect(): Promise<void> {\n\t\ttry {\n\t\t\tconst { Client } = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n\t\t\tconst transport = await createTransport(config);\n\t\t\tclient = new Client({ name: \"agent-framework-js\", version: \"0.1.0\" }, { capabilities: {} });\n\t\t\tawait client.connect(transport);\n\t\t} catch (e) {\n\t\t\t// Preserve typed runtime errors; wrap everything else as an MCP error.\n\t\t\tif ((e as Error).name === \"RuntimeUnsupportedError\") throw e;\n\t\t\tthrow new MCPError(`Failed to connect to MCP server: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function listTools(): Promise<Tool[]> {\n\t\tif (!client) throw new MCPError(\"Not connected\", config.id);\n\t\ttry {\n\t\t\tconst result = await client.listTools();\n\t\t\treturn (result.tools ?? []).map((t: { name: string; description?: string; inputSchema: Record<string, unknown> }) =>\n\t\t\t\tmcpToolToTool(config.id, t, client),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow new MCPError(`Failed to list tools: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function close(): Promise<void> {\n\t\tawait client?.close?.();\n\t\tclient = undefined;\n\t}\n\n\treturn { id: config.id, connect, listTools, close };\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkFOTCUNP5_cjs = require('./chunk-FOTCUNP5.cjs');
3
+ var chunkN64ZFATA_cjs = require('./chunk-N64ZFATA.cjs');
4
4
  var chunkMQ2XTH3S_cjs = require('./chunk-MQ2XTH3S.cjs');
5
5
 
6
6
  // src/mcp/adapter.ts
@@ -25,7 +25,7 @@ function mcpToolToTool(serverId, def, client) {
25
25
  // src/mcp/connection.ts
26
26
  async function createTransport(config) {
27
27
  if (config.transport.kind === "stdio") {
28
- chunkFOTCUNP5_cjs.requireCapability("canSpawnProcess", "MCP stdio transport");
28
+ chunkN64ZFATA_cjs.requireCapability("canSpawnProcess", "MCP stdio transport");
29
29
  const { StdioClientTransport } = await import('@modelcontextprotocol/sdk/client/stdio.js');
30
30
  return new StdioClientTransport({
31
31
  command: config.transport.command,
@@ -68,5 +68,5 @@ async function connectMCP(config) {
68
68
 
69
69
  exports.connectMCP = connectMCP;
70
70
  exports.mcpToolToTool = mcpToolToTool;
71
- //# sourceMappingURL=chunk-GYDY3KX5.cjs.map
72
- //# sourceMappingURL=chunk-GYDY3KX5.cjs.map
71
+ //# sourceMappingURL=chunk-U3ULJMNH.cjs.map
72
+ //# sourceMappingURL=chunk-U3ULJMNH.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mcp/adapter.ts","../src/mcp/connection.ts"],"names":["MCPError","requireCapability"],"mappings":"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","file":"chunk-GYDY3KX5.cjs","sourcesContent":["/**\n * Adapts MCP-provided tools onto the framework's uniform {@link Tool} contract,\n * namespaced by the connection id so collisions are impossible. (FR-014, FR-014a)\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from \"../tools/tool.js\";\nimport { MCPError } from \"../core/errors.js\";\n\ninterface MCPToolDef {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: Record<string, unknown>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * Wrap an MCP tool definition as a framework tool. Invocation calls back through\n * the MCP client; failures surface as typed {@link MCPError}/tool errors.\n */\nexport function mcpToolToTool(serverId: string, def: MCPToolDef, client: any): Tool {\n\treturn {\n\t\tname: def.name,\n\t\tdescription: def.description ?? \"\",\n\t\tinputSchema: def.inputSchema,\n\t\tsource: serverId,\n\t\tenabled: true,\n\t\tasync run(args: unknown): Promise<unknown> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool({ name: def.name, arguments: args });\n\t\t\t\treturn result.content ?? result;\n\t\t\t} catch (e) {\n\t\t\t\tthrow new MCPError(`MCP tool \"${def.name}\" failed: ${(e as Error).message}`, serverId);\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * MCP (Model Context Protocol) integration. Connects to MCP servers and exposes\n * their tools through the framework's uniform tool interface.\n *\n * Remote transport (HTTP/SSE) works in all runtimes; stdio (spawning a server\n * process) works only where process spawning is permitted (Node). Requesting\n * stdio elsewhere throws a typed {@link RuntimeUnsupportedError}. (FR-013, FR-013a,\n * FR-013b, FR-030a)\n *\n * The `@modelcontextprotocol/sdk` package is an optional peer dependency and is\n * loaded lazily so browser bundles that do not use MCP pay no cost.\n *\n * @packageDocumentation\n */\n\nimport { MCPError } from \"../core/errors.js\";\nimport { requireCapability } from \"../core/runtime.js\";\nimport type { Tool } from \"../tools/tool.js\";\nimport { mcpToolToTool } from \"./adapter.js\";\n\n/** Transport options for an MCP connection. */\nexport type MCPTransport =\n\t| { kind: \"remote\"; url: string }\n\t| { kind: \"stdio\"; command: string; args?: string[] };\n\n/** Configuration for connecting to an MCP server. */\nexport interface MCPConnectionConfig {\n\t/** Connection id; becomes the namespace prefix for discovered tools. (FR-014a) */\n\tid: string;\n\ttransport: MCPTransport;\n\t/** Whether the connection's tools are enabled. Defaults to true. */\n\tenabled?: boolean;\n}\n\n/** A live connection to an MCP server. */\nexport interface MCPConnection {\n\treadonly id: string;\n\tconnect(): Promise<void>;\n\tlistTools(): Promise<Tool[]>;\n\tclose(): Promise<void>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype AnyClient = any;\n\nasync function createTransport(config: MCPConnectionConfig): Promise<AnyClient> {\n\tif (config.transport.kind === \"stdio\") {\n\t\t// Gate on runtime capability before attempting to spawn. (FR-013b, FR-030a)\n\t\trequireCapability(\"canSpawnProcess\", \"MCP stdio transport\");\n\t\tconst { StdioClientTransport } = await import(\n\t\t\t\"@modelcontextprotocol/sdk/client/stdio.js\"\n\t\t);\n\t\treturn new StdioClientTransport({\n\t\t\tcommand: config.transport.command,\n\t\t\targs: config.transport.args ?? [],\n\t\t});\n\t}\n\tconst { StreamableHTTPClientTransport } = await import(\n\t\t\"@modelcontextprotocol/sdk/client/streamableHttp.js\"\n\t);\n\treturn new StreamableHTTPClientTransport(new URL(config.transport.url));\n}\n\n/**\n * Connect to an MCP server.\n *\n * @example\n * ```ts\n * const mcp = await connectMCP({ id: \"docs\", transport: { kind: \"remote\", url: \"https://mcp.example.com\" } });\n * const tools = await mcp.listTools(); // namespaced as docs.<tool>\n * ```\n */\nexport async function connectMCP(config: MCPConnectionConfig): Promise<MCPConnection> {\n\tlet client: AnyClient | undefined;\n\n\tasync function connect(): Promise<void> {\n\t\ttry {\n\t\t\tconst { Client } = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n\t\t\tconst transport = await createTransport(config);\n\t\t\tclient = new Client({ name: \"agent-framework-js\", version: \"0.1.0\" }, { capabilities: {} });\n\t\t\tawait client.connect(transport);\n\t\t} catch (e) {\n\t\t\t// Preserve typed runtime errors; wrap everything else as an MCP error.\n\t\t\tif ((e as Error).name === \"RuntimeUnsupportedError\") throw e;\n\t\t\tthrow new MCPError(`Failed to connect to MCP server: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function listTools(): Promise<Tool[]> {\n\t\tif (!client) throw new MCPError(\"Not connected\", config.id);\n\t\ttry {\n\t\t\tconst result = await client.listTools();\n\t\t\treturn (result.tools ?? []).map((t: { name: string; description?: string; inputSchema: Record<string, unknown> }) =>\n\t\t\t\tmcpToolToTool(config.id, t, client),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow new MCPError(`Failed to list tools: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function close(): Promise<void> {\n\t\tawait client?.close?.();\n\t\tclient = undefined;\n\t}\n\n\treturn { id: config.id, connect, listTools, close };\n}\n"]}
1
+ {"version":3,"sources":["../src/mcp/adapter.ts","../src/mcp/connection.ts"],"names":["MCPError","requireCapability"],"mappings":"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","file":"chunk-U3ULJMNH.cjs","sourcesContent":["/**\n * Adapts MCP-provided tools onto the framework's uniform {@link Tool} contract,\n * namespaced by the connection id so collisions are impossible. (FR-014, FR-014a)\n *\n * @packageDocumentation\n */\n\nimport type { Tool } from \"../tools/tool.js\";\nimport { MCPError } from \"../core/errors.js\";\n\ninterface MCPToolDef {\n\tname: string;\n\tdescription?: string;\n\tinputSchema: Record<string, unknown>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * Wrap an MCP tool definition as a framework tool. Invocation calls back through\n * the MCP client; failures surface as typed {@link MCPError}/tool errors.\n */\nexport function mcpToolToTool(serverId: string, def: MCPToolDef, client: any): Tool {\n\treturn {\n\t\tname: def.name,\n\t\tdescription: def.description ?? \"\",\n\t\tinputSchema: def.inputSchema,\n\t\tsource: serverId,\n\t\tenabled: true,\n\t\tasync run(args: unknown): Promise<unknown> {\n\t\t\ttry {\n\t\t\t\tconst result = await client.callTool({ name: def.name, arguments: args });\n\t\t\t\treturn result.content ?? result;\n\t\t\t} catch (e) {\n\t\t\t\tthrow new MCPError(`MCP tool \"${def.name}\" failed: ${(e as Error).message}`, serverId);\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * MCP (Model Context Protocol) integration. Connects to MCP servers and exposes\n * their tools through the framework's uniform tool interface.\n *\n * Remote transport (HTTP/SSE) works in all runtimes; stdio (spawning a server\n * process) works only where process spawning is permitted (Node). Requesting\n * stdio elsewhere throws a typed {@link RuntimeUnsupportedError}. (FR-013, FR-013a,\n * FR-013b, FR-030a)\n *\n * The `@modelcontextprotocol/sdk` package is an optional peer dependency and is\n * loaded lazily so browser bundles that do not use MCP pay no cost.\n *\n * @packageDocumentation\n */\n\nimport { MCPError } from \"../core/errors.js\";\nimport { requireCapability } from \"../core/runtime.js\";\nimport type { Tool } from \"../tools/tool.js\";\nimport { mcpToolToTool } from \"./adapter.js\";\n\n/** Transport options for an MCP connection. */\nexport type MCPTransport =\n\t| { kind: \"remote\"; url: string }\n\t| { kind: \"stdio\"; command: string; args?: string[] };\n\n/** Configuration for connecting to an MCP server. */\nexport interface MCPConnectionConfig {\n\t/** Connection id; becomes the namespace prefix for discovered tools. (FR-014a) */\n\tid: string;\n\ttransport: MCPTransport;\n\t/** Whether the connection's tools are enabled. Defaults to true. */\n\tenabled?: boolean;\n}\n\n/** A live connection to an MCP server. */\nexport interface MCPConnection {\n\treadonly id: string;\n\tconnect(): Promise<void>;\n\tlistTools(): Promise<Tool[]>;\n\tclose(): Promise<void>;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype AnyClient = any;\n\nasync function createTransport(config: MCPConnectionConfig): Promise<AnyClient> {\n\tif (config.transport.kind === \"stdio\") {\n\t\t// Gate on runtime capability before attempting to spawn. (FR-013b, FR-030a)\n\t\trequireCapability(\"canSpawnProcess\", \"MCP stdio transport\");\n\t\tconst { StdioClientTransport } = await import(\n\t\t\t\"@modelcontextprotocol/sdk/client/stdio.js\"\n\t\t);\n\t\treturn new StdioClientTransport({\n\t\t\tcommand: config.transport.command,\n\t\t\targs: config.transport.args ?? [],\n\t\t});\n\t}\n\tconst { StreamableHTTPClientTransport } = await import(\n\t\t\"@modelcontextprotocol/sdk/client/streamableHttp.js\"\n\t);\n\treturn new StreamableHTTPClientTransport(new URL(config.transport.url));\n}\n\n/**\n * Connect to an MCP server.\n *\n * @example\n * ```ts\n * const mcp = await connectMCP({ id: \"docs\", transport: { kind: \"remote\", url: \"https://mcp.example.com\" } });\n * const tools = await mcp.listTools(); // namespaced as docs.<tool>\n * ```\n */\nexport async function connectMCP(config: MCPConnectionConfig): Promise<MCPConnection> {\n\tlet client: AnyClient | undefined;\n\n\tasync function connect(): Promise<void> {\n\t\ttry {\n\t\t\tconst { Client } = await import(\"@modelcontextprotocol/sdk/client/index.js\");\n\t\t\tconst transport = await createTransport(config);\n\t\t\tclient = new Client({ name: \"agent-framework-js\", version: \"0.1.0\" }, { capabilities: {} });\n\t\t\tawait client.connect(transport);\n\t\t} catch (e) {\n\t\t\t// Preserve typed runtime errors; wrap everything else as an MCP error.\n\t\t\tif ((e as Error).name === \"RuntimeUnsupportedError\") throw e;\n\t\t\tthrow new MCPError(`Failed to connect to MCP server: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function listTools(): Promise<Tool[]> {\n\t\tif (!client) throw new MCPError(\"Not connected\", config.id);\n\t\ttry {\n\t\t\tconst result = await client.listTools();\n\t\t\treturn (result.tools ?? []).map((t: { name: string; description?: string; inputSchema: Record<string, unknown> }) =>\n\t\t\t\tmcpToolToTool(config.id, t, client),\n\t\t\t);\n\t\t} catch (e) {\n\t\t\tthrow new MCPError(`Failed to list tools: ${(e as Error).message}`, config.id);\n\t\t}\n\t}\n\n\tasync function close(): Promise<void> {\n\t\tawait client?.close?.();\n\t\tclient = undefined;\n\t}\n\n\treturn { id: config.id, connect, listTools, close };\n}\n"]}
@@ -1,4 +1,5 @@
1
- import { ValidationError, ProviderError } from './chunk-IXV4UIF5.js';
1
+ import { detectRuntime } from './chunk-QXAJ4DUJ.js';
2
+ import { ValidationError, ProviderError, RuntimeUnsupportedError } from './chunk-IXV4UIF5.js';
2
3
 
3
4
  // src/providers/provider.ts
4
5
  function resolveModels(options) {
@@ -300,8 +301,19 @@ var COPILOT_DEFAULT_HEADERS = {
300
301
  "Openai-Intent": "conversation-panel"
301
302
  };
302
303
  function createCopilotProvider(options) {
304
+ const baseUrl = options.baseUrl ?? DEFAULT_COPILOT_BASE_URL;
305
+ const usingDefaultHost = baseUrl === DEFAULT_COPILOT_BASE_URL;
306
+ if (usingDefaultHost && detectRuntime().isBrowser) {
307
+ throw new RuntimeUnsupportedError(
308
+ "GitHub Copilot directly from a browser (the Copilot API sends no CORS headers)",
309
+ {
310
+ reason: "cors",
311
+ remedy: "Run a lightweight backend/proxy (e.g. a Vite dev-server proxy or a small server route) that forwards to https://api.githubcopilot.com, then set `baseUrl` to your proxy URL. Alternatively, run the Copilot provider server-side (Node or an edge function)."
312
+ }
313
+ );
314
+ }
303
315
  const inner = createOpenAICompatibleProvider({
304
- baseUrl: options.baseUrl ?? DEFAULT_COPILOT_BASE_URL,
316
+ baseUrl,
305
317
  getCredential: options.getCredential,
306
318
  capabilities: options.capabilities,
307
319
  models: options.models,
@@ -323,5 +335,5 @@ function createCopilotProvider(options) {
323
335
  }
324
336
 
325
337
  export { createCopilotProvider, createOpenAICompatibleProvider, providerErrorFromStatus, resolveModels, withRetry };
326
- //# sourceMappingURL=chunk-QD2FFISV.js.map
327
- //# sourceMappingURL=chunk-QD2FFISV.js.map
338
+ //# sourceMappingURL=chunk-YVJGF4HQ.js.map
339
+ //# sourceMappingURL=chunk-YVJGF4HQ.js.map