agent-framework-js 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/AGENT_USAGE.md +207 -0
  2. package/LICENSE +21 -0
  3. package/README.md +99 -0
  4. package/dist/agents/index.cjs +35 -0
  5. package/dist/agents/index.cjs.map +1 -0
  6. package/dist/agents/index.d.cts +8 -0
  7. package/dist/agents/index.d.ts +8 -0
  8. package/dist/agents/index.js +10 -0
  9. package/dist/agents/index.js.map +1 -0
  10. package/dist/chunk-5M6ER4ZX.cjs +4 -0
  11. package/dist/chunk-5M6ER4ZX.cjs.map +1 -0
  12. package/dist/chunk-5PDJOBTD.js +38 -0
  13. package/dist/chunk-5PDJOBTD.js.map +1 -0
  14. package/dist/chunk-7ZXUIHLH.js +18 -0
  15. package/dist/chunk-7ZXUIHLH.js.map +1 -0
  16. package/dist/chunk-ACBIHS5H.js +30 -0
  17. package/dist/chunk-ACBIHS5H.js.map +1 -0
  18. package/dist/chunk-DEABART4.js +54 -0
  19. package/dist/chunk-DEABART4.js.map +1 -0
  20. package/dist/chunk-FOTCUNP5.cjs +34 -0
  21. package/dist/chunk-FOTCUNP5.cjs.map +1 -0
  22. package/dist/chunk-FSDMBWQV.cjs +20 -0
  23. package/dist/chunk-FSDMBWQV.cjs.map +1 -0
  24. package/dist/chunk-GYDY3KX5.cjs +72 -0
  25. package/dist/chunk-GYDY3KX5.cjs.map +1 -0
  26. package/dist/chunk-HGEPXJDG.js +129 -0
  27. package/dist/chunk-HGEPXJDG.js.map +1 -0
  28. package/dist/chunk-IJASUMIQ.cjs +57 -0
  29. package/dist/chunk-IJASUMIQ.cjs.map +1 -0
  30. package/dist/chunk-IU3LS5FC.cjs +10 -0
  31. package/dist/chunk-IU3LS5FC.cjs.map +1 -0
  32. package/dist/chunk-IUKD54F7.js +8 -0
  33. package/dist/chunk-IUKD54F7.js.map +1 -0
  34. package/dist/chunk-IXV4UIF5.js +79 -0
  35. package/dist/chunk-IXV4UIF5.js.map +1 -0
  36. package/dist/chunk-KEI3EALJ.cjs +10 -0
  37. package/dist/chunk-KEI3EALJ.cjs.map +1 -0
  38. package/dist/chunk-LMN75W3W.cjs +87 -0
  39. package/dist/chunk-LMN75W3W.cjs.map +1 -0
  40. package/dist/chunk-MCLVWCOB.js +3 -0
  41. package/dist/chunk-MCLVWCOB.js.map +1 -0
  42. package/dist/chunk-MQ2XTH3S.cjs +87 -0
  43. package/dist/chunk-MQ2XTH3S.cjs.map +1 -0
  44. package/dist/chunk-QJ5XHA6S.cjs +95 -0
  45. package/dist/chunk-QJ5XHA6S.cjs.map +1 -0
  46. package/dist/chunk-RD5YUB2E.js +190 -0
  47. package/dist/chunk-RD5YUB2E.js.map +1 -0
  48. package/dist/chunk-RZ43WNHR.js +8 -0
  49. package/dist/chunk-RZ43WNHR.js.map +1 -0
  50. package/dist/chunk-RZP2ZUUX.cjs +252 -0
  51. package/dist/chunk-RZP2ZUUX.cjs.map +1 -0
  52. package/dist/chunk-T2GHJ5R4.js +241 -0
  53. package/dist/chunk-T2GHJ5R4.js.map +1 -0
  54. package/dist/chunk-TAMJ5HSR.cjs +137 -0
  55. package/dist/chunk-TAMJ5HSR.cjs.map +1 -0
  56. package/dist/chunk-TLACSVEZ.cjs +201 -0
  57. package/dist/chunk-TLACSVEZ.cjs.map +1 -0
  58. package/dist/chunk-UVWQWOLO.js +196 -0
  59. package/dist/chunk-UVWQWOLO.js.map +1 -0
  60. package/dist/chunk-V472N2PK.js +91 -0
  61. package/dist/chunk-V472N2PK.js.map +1 -0
  62. package/dist/chunk-V6O6SYAN.cjs +43 -0
  63. package/dist/chunk-V6O6SYAN.cjs.map +1 -0
  64. package/dist/chunk-VLSVL5N2.js +48 -0
  65. package/dist/chunk-VLSVL5N2.js.map +1 -0
  66. package/dist/chunk-WSMYH2IN.cjs +86 -0
  67. package/dist/chunk-WSMYH2IN.cjs.map +1 -0
  68. package/dist/chunk-XPXTXOYQ.js +81 -0
  69. package/dist/chunk-XPXTXOYQ.js.map +1 -0
  70. package/dist/chunk-YBFLWRO5.cjs +194 -0
  71. package/dist/chunk-YBFLWRO5.cjs.map +1 -0
  72. package/dist/chunk-YCBDEEAV.js +82 -0
  73. package/dist/chunk-YCBDEEAV.js.map +1 -0
  74. package/dist/chunk-YH5746OF.js +69 -0
  75. package/dist/chunk-YH5746OF.js.map +1 -0
  76. package/dist/chunk-YKZJRE32.cjs +50 -0
  77. package/dist/chunk-YKZJRE32.cjs.map +1 -0
  78. package/dist/declarative/index.cjs +19 -0
  79. package/dist/declarative/index.cjs.map +1 -0
  80. package/dist/declarative/index.d.cts +60 -0
  81. package/dist/declarative/index.d.ts +60 -0
  82. package/dist/declarative/index.js +10 -0
  83. package/dist/declarative/index.js.map +1 -0
  84. package/dist/errors-CjVz4W_5.d.cts +68 -0
  85. package/dist/errors-CjVz4W_5.d.ts +68 -0
  86. package/dist/index-C2vzfbBz.d.cts +57 -0
  87. package/dist/index-C2vzfbBz.d.ts +57 -0
  88. package/dist/index-D7-znzrc.d.ts +153 -0
  89. package/dist/index-DdYZeNIu.d.cts +153 -0
  90. package/dist/index.cjs +236 -0
  91. package/dist/index.cjs.map +1 -0
  92. package/dist/index.d.cts +51 -0
  93. package/dist/index.d.ts +51 -0
  94. package/dist/index.js +19 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/mcp/index.cjs +19 -0
  97. package/dist/mcp/index.cjs.map +1 -0
  98. package/dist/mcp/index.d.cts +72 -0
  99. package/dist/mcp/index.d.ts +72 -0
  100. package/dist/mcp/index.js +6 -0
  101. package/dist/mcp/index.js.map +1 -0
  102. package/dist/middleware/index.cjs +17 -0
  103. package/dist/middleware/index.cjs.map +1 -0
  104. package/dist/middleware/index.d.cts +29 -0
  105. package/dist/middleware/index.d.ts +29 -0
  106. package/dist/middleware/index.js +4 -0
  107. package/dist/middleware/index.js.map +1 -0
  108. package/dist/observability/index.cjs +29 -0
  109. package/dist/observability/index.cjs.map +1 -0
  110. package/dist/observability/index.d.cts +1 -0
  111. package/dist/observability/index.d.ts +1 -0
  112. package/dist/observability/index.js +4 -0
  113. package/dist/observability/index.js.map +1 -0
  114. package/dist/persistence/index.cjs +24 -0
  115. package/dist/persistence/index.cjs.map +1 -0
  116. package/dist/persistence/index.d.cts +51 -0
  117. package/dist/persistence/index.d.ts +51 -0
  118. package/dist/persistence/index.js +7 -0
  119. package/dist/persistence/index.js.map +1 -0
  120. package/dist/provider-CMAymr1b.d.cts +82 -0
  121. package/dist/provider-osAtfZ7x.d.ts +82 -0
  122. package/dist/providers/index.cjs +26 -0
  123. package/dist/providers/index.cjs.map +1 -0
  124. package/dist/providers/index.d.cts +107 -0
  125. package/dist/providers/index.d.ts +107 -0
  126. package/dist/providers/index.js +5 -0
  127. package/dist/providers/index.js.map +1 -0
  128. package/dist/registry-CpO0yH5v.d.ts +57 -0
  129. package/dist/registry-D4fThGiN.d.cts +57 -0
  130. package/dist/skill-DfNChtJN.d.cts +45 -0
  131. package/dist/skill-DfNChtJN.d.ts +45 -0
  132. package/dist/skills/index.cjs +20 -0
  133. package/dist/skills/index.cjs.map +1 -0
  134. package/dist/skills/index.d.cts +30 -0
  135. package/dist/skills/index.d.ts +30 -0
  136. package/dist/skills/index.js +3 -0
  137. package/dist/skills/index.js.map +1 -0
  138. package/dist/thread-CWVzTyti.d.ts +51 -0
  139. package/dist/thread-Dfo9LLf7.d.cts +51 -0
  140. package/dist/tool-BZg_znMZ.d.cts +50 -0
  141. package/dist/tool-CSCC87OD.d.ts +50 -0
  142. package/dist/tools/index.cjs +27 -0
  143. package/dist/tools/index.cjs.map +1 -0
  144. package/dist/tools/index.d.cts +21 -0
  145. package/dist/tools/index.d.ts +21 -0
  146. package/dist/tools/index.js +6 -0
  147. package/dist/tools/index.js.map +1 -0
  148. package/dist/types-Cn1g9Tg4.d.cts +63 -0
  149. package/dist/types-Cn1g9Tg4.d.ts +63 -0
  150. package/dist/workflows/index.cjs +50 -0
  151. package/dist/workflows/index.cjs.map +1 -0
  152. package/dist/workflows/index.d.cts +182 -0
  153. package/dist/workflows/index.d.ts +182 -0
  154. package/dist/workflows/index.js +5 -0
  155. package/dist/workflows/index.js.map +1 -0
  156. package/package.json +145 -0
@@ -0,0 +1,91 @@
1
+ import { Thread } from './chunk-XPXTXOYQ.js';
2
+ import { requireCapability } from './chunk-ACBIHS5H.js';
3
+
4
+ // src/persistence/store.ts
5
+ var ThreadPersistence = {
6
+ /** Persist a thread under the key `thread:<id>`. */
7
+ async save(store, thread) {
8
+ await store.set(`thread:${thread.id}`, thread.toJSON());
9
+ },
10
+ /** Load and rehydrate a thread, or undefined if absent. */
11
+ async load(store, id) {
12
+ const data = await store.get(`thread:${id}`);
13
+ return data ? Thread.fromJSON(data) : void 0;
14
+ }
15
+ };
16
+
17
+ // src/persistence/memory.ts
18
+ function createMemoryStore() {
19
+ const map = /* @__PURE__ */ new Map();
20
+ return {
21
+ async get(key) {
22
+ return map.get(key);
23
+ },
24
+ async set(key, value) {
25
+ map.set(key, value);
26
+ },
27
+ async delete(key) {
28
+ map.delete(key);
29
+ }
30
+ };
31
+ }
32
+
33
+ // src/persistence/browser.ts
34
+ function createBrowserStore(options = {}) {
35
+ const backend = options.backend ?? "local";
36
+ const ns = options.namespace ?? "afjs";
37
+ return backend === "indexeddb" ? indexedDbStore(ns) : localStorageStore(ns);
38
+ }
39
+ function localStorageStore(ns) {
40
+ requireCapability("hasLocalStorage", "localStorage store");
41
+ const ls = globalThis.localStorage;
42
+ const k = (key) => `${ns}:${key}`;
43
+ return {
44
+ async get(key) {
45
+ const raw = ls.getItem(k(key));
46
+ return raw == null ? void 0 : JSON.parse(raw);
47
+ },
48
+ async set(key, value) {
49
+ ls.setItem(k(key), JSON.stringify(value));
50
+ },
51
+ async delete(key) {
52
+ ls.removeItem(k(key));
53
+ }
54
+ };
55
+ }
56
+ function indexedDbStore(ns) {
57
+ requireCapability("hasIndexedDB", "IndexedDB store");
58
+ const idb = globalThis.indexedDB;
59
+ function open() {
60
+ return new Promise((resolve, reject) => {
61
+ const req = idb.open(ns, 1);
62
+ req.onupgradeneeded = () => req.result.createObjectStore("kv");
63
+ req.onsuccess = () => resolve(req.result);
64
+ req.onerror = () => reject(req.error);
65
+ });
66
+ }
67
+ async function tx(mode, fn) {
68
+ const db = await open();
69
+ return new Promise((resolve, reject) => {
70
+ const store = db.transaction("kv", mode).objectStore("kv");
71
+ const req = fn(store);
72
+ req.onsuccess = () => resolve(req.result);
73
+ req.onerror = () => reject(req.error);
74
+ });
75
+ }
76
+ return {
77
+ async get(key) {
78
+ return tx("readonly", (s) => s.get(key));
79
+ },
80
+ async set(key, value) {
81
+ await tx("readwrite", (s) => s.put(value, key));
82
+ },
83
+ async delete(key) {
84
+ await tx("readwrite", (s) => s.delete(key));
85
+ }
86
+ };
87
+ }
88
+
89
+ export { ThreadPersistence, createBrowserStore, createMemoryStore };
90
+ //# sourceMappingURL=chunk-V472N2PK.js.map
91
+ //# sourceMappingURL=chunk-V472N2PK.js.map
@@ -0,0 +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-V472N2PK.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"]}
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ var chunkIJASUMIQ_cjs = require('./chunk-IJASUMIQ.cjs');
4
+
5
+ // src/observability/tracing.ts
6
+ var state = { enabled: false };
7
+ function configureObservability(config) {
8
+ state.tracer = config.tracer;
9
+ state.enabled = config.enabled ?? !!config.tracer;
10
+ }
11
+ async function withSpan(name, attributes, fn) {
12
+ if (!state.enabled || !state.tracer) return fn();
13
+ const span = state.tracer.startSpan(name);
14
+ const safe = chunkIJASUMIQ_cjs.redact(attributes);
15
+ for (const [k, v] of Object.entries(safe)) {
16
+ span.setAttribute(k, typeof v === "object" ? JSON.stringify(v) : v);
17
+ }
18
+ try {
19
+ const result = await fn();
20
+ span.setStatus?.({ code: 1 });
21
+ return result;
22
+ } catch (e) {
23
+ span.setStatus?.({ code: 2, message: e.message });
24
+ span.recordException?.(chunkIJASUMIQ_cjs.redact({ message: e.message }));
25
+ throw e;
26
+ } finally {
27
+ span.end();
28
+ }
29
+ }
30
+ function isObservabilityEnabled() {
31
+ return state.enabled && !!state.tracer;
32
+ }
33
+ function resetObservability() {
34
+ state.tracer = void 0;
35
+ state.enabled = false;
36
+ }
37
+
38
+ exports.configureObservability = configureObservability;
39
+ exports.isObservabilityEnabled = isObservabilityEnabled;
40
+ exports.resetObservability = resetObservability;
41
+ exports.withSpan = withSpan;
42
+ //# sourceMappingURL=chunk-V6O6SYAN.cjs.map
43
+ //# sourceMappingURL=chunk-V6O6SYAN.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/observability/tracing.ts"],"names":["redact"],"mappings":";;;;;AAqBA,IAAM,KAAA,GAA4B,EAAE,OAAA,EAAS,KAAA,EAAM;AAW5C,SAAS,uBAAuB,MAAA,EAAmC;AACzE,EAAA,KAAA,CAAM,SAAS,MAAA,CAAO,MAAA;AACtB,EAAA,KAAA,CAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,CAAC,CAAC,MAAA,CAAO,MAAA;AAC5C;AAaA,eAAsB,QAAA,CACrB,IAAA,EACA,UAAA,EACA,EAAA,EACa;AACb,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,IAAW,CAAC,KAAA,CAAM,MAAA,SAAe,EAAA,EAAG;AAE/C,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,MAAA,CAAO,SAAA,CAAU,IAAI,CAAA;AACxC,EAAA,MAAM,IAAA,GAAOA,yBAAO,UAAU,CAAA;AAC9B,EAAA,KAAA,MAAW,CAAC,CAAA,EAAG,CAAC,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAC1C,IAAA,IAAA,CAAK,YAAA,CAAa,GAAG,OAAO,CAAA,KAAM,WAAW,IAAA,CAAK,SAAA,CAAU,CAAC,CAAA,GAAK,CAAW,CAAA;AAAA,EAC9E;AACA,EAAA,IAAI;AACH,IAAA,MAAM,MAAA,GAAS,MAAM,EAAA,EAAG;AACxB,IAAA,IAAA,CAAK,SAAA,GAAY,EAAE,IAAA,EAAM,CAAA,EAAG,CAAA;AAC5B,IAAA,OAAO,MAAA;AAAA,EACR,SAAS,CAAA,EAAG;AACX,IAAA,IAAA,CAAK,YAAY,EAAE,IAAA,EAAM,GAAG,OAAA,EAAU,CAAA,CAAY,SAAS,CAAA;AAC3D,IAAA,IAAA,CAAK,kBAAkBA,wBAAA,CAAO,EAAE,SAAU,CAAA,CAAY,OAAA,EAAS,CAAC,CAAA;AAChE,IAAA,MAAM,CAAA;AAAA,EACP,CAAA,SAAE;AACD,IAAA,IAAA,CAAK,GAAA,EAAI;AAAA,EACV;AACD;AAGO,SAAS,sBAAA,GAAkC;AACjD,EAAA,OAAO,KAAA,CAAM,OAAA,IAAW,CAAC,CAAC,KAAA,CAAM,MAAA;AACjC;AAGO,SAAS,kBAAA,GAA2B;AAC1C,EAAA,KAAA,CAAM,MAAA,GAAS,MAAA;AACf,EAAA,KAAA,CAAM,OAAA,GAAU,KAAA;AACjB","file":"chunk-V6O6SYAN.cjs","sourcesContent":["/**\n * Observability via OpenTelemetry. Consumers supply their own tracer/exporters;\n * the framework emits spans for agent/tool/provider/workflow operations and routes\n * all attributes and errors through redaction so no secret ever leaks. (FR-025,\n * FR-026, FR-026a)\n *\n * The `@opentelemetry/api` package is an optional peer dependency.\n *\n * @packageDocumentation\n */\n\nimport { redact } from \"../core/redaction.js\";\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ntype Tracer = any;\n\ninterface ObservabilityState {\n\ttracer?: Tracer;\n\tenabled: boolean;\n}\n\nconst state: ObservabilityState = { enabled: false };\n\n/** Configuration for {@link configureObservability}. */\nexport interface ObservabilityConfig {\n\t/** A consumer-supplied OpenTelemetry tracer. */\n\ttracer?: Tracer;\n\t/** Whether tracing is active. Default false. */\n\tenabled?: boolean;\n}\n\n/** Enable/disable tracing and set the tracer. */\nexport function configureObservability(config: ObservabilityConfig): void {\n\tstate.tracer = config.tracer;\n\tstate.enabled = config.enabled ?? !!config.tracer;\n}\n\n/** Re-export of the redaction helper for convenience. (FR-026a) */\nexport { redact };\n\n/**\n * Run `fn` inside a span named `name`. Attributes are redacted before being set.\n * If tracing is disabled or no tracer is configured, `fn` runs without a span.\n *\n * @param name - Span name, e.g. `agent.run`, `tool.invoke`.\n * @param attributes - Span attributes (redacted automatically).\n * @param fn - The operation to trace.\n */\nexport async function withSpan<T>(\n\tname: string,\n\tattributes: Record<string, unknown>,\n\tfn: () => Promise<T>,\n): Promise<T> {\n\tif (!state.enabled || !state.tracer) return fn();\n\n\tconst span = state.tracer.startSpan(name);\n\tconst safe = redact(attributes);\n\tfor (const [k, v] of Object.entries(safe)) {\n\t\tspan.setAttribute(k, typeof v === \"object\" ? JSON.stringify(v) : (v as never));\n\t}\n\ttry {\n\t\tconst result = await fn();\n\t\tspan.setStatus?.({ code: 1 }); // OK\n\t\treturn result;\n\t} catch (e) {\n\t\tspan.setStatus?.({ code: 2, message: (e as Error).message }); // ERROR\n\t\tspan.recordException?.(redact({ message: (e as Error).message }));\n\t\tthrow e;\n\t} finally {\n\t\tspan.end();\n\t}\n}\n\n/** Whether tracing is currently active. */\nexport function isObservabilityEnabled(): boolean {\n\treturn state.enabled && !!state.tracer;\n}\n\n/** Reset observability state — intended for tests. */\nexport function resetObservability(): void {\n\tstate.tracer = undefined;\n\tstate.enabled = false;\n}\n"]}
@@ -0,0 +1,48 @@
1
+ import { createAgent } from './chunk-RD5YUB2E.js';
2
+ import { ValidationError } from './chunk-IXV4UIF5.js';
3
+
4
+ // src/declarative/loader.ts
5
+ function looksLikeJson(source) {
6
+ const t = source.trimStart();
7
+ return t.startsWith("{") || t.startsWith("[");
8
+ }
9
+ async function parse(source) {
10
+ if (looksLikeJson(source)) {
11
+ try {
12
+ return JSON.parse(source);
13
+ } catch (e) {
14
+ throw new ValidationError(`Invalid JSON definition: ${e.message}`);
15
+ }
16
+ }
17
+ const YAML = await import('yaml');
18
+ try {
19
+ return YAML.parse(source);
20
+ } catch (e) {
21
+ throw new ValidationError(`Invalid YAML definition: ${e.message}`);
22
+ }
23
+ }
24
+ function assertDefinition(value) {
25
+ const d = value;
26
+ if (!d || typeof d.name !== "string" || typeof d.instructions !== "string" || !d.provider) {
27
+ throw new ValidationError("Definition must include name, instructions, and provider");
28
+ }
29
+ }
30
+ async function loadAgentDefinition(source, deps) {
31
+ const parsed = await parse(source);
32
+ assertDefinition(parsed);
33
+ const provider = deps.providerFactory(parsed.provider, deps.getCredential);
34
+ const tools = (parsed.tools ?? []).map((name) => deps.tools?.[name]).filter((t) => !!t);
35
+ const skills = (parsed.skills ?? []).map((name) => deps.skills?.[name]).filter((s) => !!s);
36
+ return createAgent({
37
+ name: parsed.name,
38
+ instructions: parsed.instructions,
39
+ provider,
40
+ tools,
41
+ skills,
42
+ maxIterations: parsed.maxIterations
43
+ });
44
+ }
45
+
46
+ export { loadAgentDefinition };
47
+ //# sourceMappingURL=chunk-VLSVL5N2.js.map
48
+ //# sourceMappingURL=chunk-VLSVL5N2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/declarative/loader.ts"],"names":[],"mappings":";;;;AA+CA,SAAS,cAAc,MAAA,EAAyB;AAC/C,EAAA,MAAM,CAAA,GAAI,OAAO,SAAA,EAAU;AAC3B,EAAA,OAAO,EAAE,UAAA,CAAW,GAAG,CAAA,IAAK,CAAA,CAAE,WAAW,GAAG,CAAA;AAC7C;AAEA,eAAe,MAAM,MAAA,EAAkC;AACtD,EAAA,IAAI,aAAA,CAAc,MAAM,CAAA,EAAG;AAC1B,IAAA,IAAI;AACH,MAAA,OAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,IACzB,SAAS,CAAA,EAAG;AACX,MAAA,MAAM,IAAI,eAAA,CAAgB,CAAA,yBAAA,EAA6B,CAAA,CAAY,OAAO,CAAA,CAAE,CAAA;AAAA,IAC7E;AAAA,EACD;AAEA,EAAA,MAAM,IAAA,GAAO,MAAM,OAAO,MAAM,CAAA;AAChC,EAAA,IAAI;AACH,IAAA,OAAO,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,EACzB,SAAS,CAAA,EAAG;AACX,IAAA,MAAM,IAAI,eAAA,CAAgB,CAAA,yBAAA,EAA6B,CAAA,CAAY,OAAO,CAAA,CAAE,CAAA;AAAA,EAC7E;AACD;AAEA,SAAS,iBAAiB,KAAA,EAAkD;AAC3E,EAAA,MAAM,CAAA,GAAI,KAAA;AACV,EAAA,IAAI,CAAC,CAAA,IAAK,OAAO,CAAA,CAAE,IAAA,KAAS,QAAA,IAAY,OAAO,CAAA,CAAE,YAAA,KAAiB,QAAA,IAAY,CAAC,CAAA,CAAE,QAAA,EAAU;AAC1F,IAAA,MAAM,IAAI,gBAAgB,0DAA0D,CAAA;AAAA,EACrF;AACD;AAaA,eAAsB,mBAAA,CAAoB,QAAgB,IAAA,EAAkC;AAC3F,EAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,MAAM,CAAA;AACjC,EAAA,gBAAA,CAAiB,MAAM,CAAA;AAEvB,EAAA,MAAM,WAAW,IAAA,CAAK,eAAA,CAAgB,MAAA,CAAO,QAAA,EAAU,KAAK,aAAa,CAAA;AACzE,EAAA,MAAM,SAAS,MAAA,CAAO,KAAA,IAAS,EAAC,EAC9B,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,KAAA,GAAQ,IAAI,CAAC,CAAA,CAChC,MAAA,CAAO,CAAC,CAAA,KAAiB,CAAC,CAAC,CAAC,CAAA;AAC9B,EAAA,MAAM,UAAU,MAAA,CAAO,MAAA,IAAU,EAAC,EAChC,GAAA,CAAI,CAAC,IAAA,KAAS,IAAA,CAAK,MAAA,GAAS,IAAI,CAAC,CAAA,CACjC,MAAA,CAAO,CAAC,CAAA,KAAkB,CAAC,CAAC,CAAC,CAAA;AAE/B,EAAA,OAAO,WAAA,CAAY;AAAA,IAClB,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,cAAc,MAAA,CAAO,YAAA;AAAA,IACrB,QAAA;AAAA,IACA,KAAA;AAAA,IACA,MAAA;AAAA,IACA,eAAe,MAAA,CAAO;AAAA,GACtB,CAAA;AACF","file":"chunk-VLSVL5N2.js","sourcesContent":["/**\n * Declarative agent definitions. Agents can be defined in YAML or JSON against a\n * single shared schema; the loader auto-detects the format (the YAML parser is\n * lazy-loaded so JSON-only/browser use pays no cost) and builds an equivalent\n * runnable agent. Credentials are still injected via callback, never embedded.\n * (FR-027, FR-005a)\n *\n * @packageDocumentation\n */\n\nimport type { ModelCapabilities } from \"../core/types.js\";\nimport type { Provider } from \"../providers/provider.js\";\nimport type { Tool } from \"../tools/tool.js\";\nimport type { Skill } from \"../skills/skill.js\";\nimport { createAgent, type Agent } from \"../agents/agent.js\";\nimport { ValidationError } from \"../core/errors.js\";\n\n/** Provider section of a declarative definition. */\nexport interface ProviderDefinition extends ModelCapabilities {\n\ttype: \"copilot\" | \"openai-compatible\";\n\tbaseUrl?: string;\n}\n\n/** A declarative agent definition (shared by YAML and JSON). */\nexport interface AgentDefinition {\n\tname: string;\n\tinstructions: string;\n\tprovider: ProviderDefinition;\n\t/** Names referencing tools provided in `deps.tools`. */\n\ttools?: string[];\n\t/** Names referencing skills provided in `deps.skills`. */\n\tskills?: string[];\n\tmaxIterations?: number;\n}\n\n/** Dependencies the loader needs to construct a live agent. */\nexport interface LoaderDeps {\n\t/** Build a provider from the definition + injected credential. */\n\tproviderFactory: (def: ProviderDefinition, getCredential: () => string | Promise<string>) => Provider;\n\t/** Credential callback — never embedded in the definition. (FR-005a) */\n\tgetCredential: () => string | Promise<string>;\n\t/** Registered tools available for reference by name. */\n\ttools?: Record<string, Tool>;\n\t/** Registered skills available for reference by name. */\n\tskills?: Record<string, Skill>;\n}\n\nfunction looksLikeJson(source: string): boolean {\n\tconst t = source.trimStart();\n\treturn t.startsWith(\"{\") || t.startsWith(\"[\");\n}\n\nasync function parse(source: string): Promise<unknown> {\n\tif (looksLikeJson(source)) {\n\t\ttry {\n\t\t\treturn JSON.parse(source);\n\t\t} catch (e) {\n\t\t\tthrow new ValidationError(`Invalid JSON definition: ${(e as Error).message}`);\n\t\t}\n\t}\n\t// Lazy-load the YAML parser only when needed. (FR-027)\n\tconst YAML = await import(\"yaml\");\n\ttry {\n\t\treturn YAML.parse(source);\n\t} catch (e) {\n\t\tthrow new ValidationError(`Invalid YAML definition: ${(e as Error).message}`);\n\t}\n}\n\nfunction assertDefinition(value: unknown): asserts value is AgentDefinition {\n\tconst d = value as Partial<AgentDefinition>;\n\tif (!d || typeof d.name !== \"string\" || typeof d.instructions !== \"string\" || !d.provider) {\n\t\tthrow new ValidationError(\"Definition must include name, instructions, and provider\");\n\t}\n}\n\n/**\n * Load an agent from a YAML or JSON definition string.\n *\n * @example\n * ```ts\n * const agent = await loadAgentDefinition(yamlOrJson, {\n * providerFactory,\n * getCredential: () => process.env.LMSTUDIO_KEY ?? \"\",\n * });\n * ```\n */\nexport async function loadAgentDefinition(source: string, deps: LoaderDeps): Promise<Agent> {\n\tconst parsed = await parse(source);\n\tassertDefinition(parsed);\n\n\tconst provider = deps.providerFactory(parsed.provider, deps.getCredential);\n\tconst tools = (parsed.tools ?? [])\n\t\t.map((name) => deps.tools?.[name])\n\t\t.filter((t): t is Tool => !!t);\n\tconst skills = (parsed.skills ?? [])\n\t\t.map((name) => deps.skills?.[name])\n\t\t.filter((s): s is Skill => !!s);\n\n\treturn createAgent({\n\t\tname: parsed.name,\n\t\tinstructions: parsed.instructions,\n\t\tprovider,\n\t\ttools,\n\t\tskills,\n\t\tmaxIterations: parsed.maxIterations,\n\t});\n}\n"]}
@@ -0,0 +1,86 @@
1
+ 'use strict';
2
+
3
+ // src/skills/skill.ts
4
+ function defineSkill(skill) {
5
+ return skill;
6
+ }
7
+ async function loadSource(source) {
8
+ switch (source.kind) {
9
+ case "inline":
10
+ return source.content;
11
+ case "code":
12
+ return source.load();
13
+ case "file": {
14
+ const { readFile } = await import('fs/promises');
15
+ return readFile(source.path, "utf8");
16
+ }
17
+ }
18
+ }
19
+
20
+ // src/skills/index.ts
21
+ var STOPWORDS = /* @__PURE__ */ new Set([
22
+ "the",
23
+ "a",
24
+ "an",
25
+ "and",
26
+ "or",
27
+ "of",
28
+ "to",
29
+ "in",
30
+ "for",
31
+ "on",
32
+ "is",
33
+ "are",
34
+ "with",
35
+ "how",
36
+ "what",
37
+ "do",
38
+ "does",
39
+ "i",
40
+ "you",
41
+ "it",
42
+ "this",
43
+ "that"
44
+ ]);
45
+ function tokenize(text) {
46
+ return new Set(
47
+ text.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length > 2 && !STOPWORDS.has(w))
48
+ );
49
+ }
50
+ var SkillIndex = class {
51
+ entries = [];
52
+ constructor(skills = []) {
53
+ for (const s of skills) this.add(s);
54
+ }
55
+ /** Add a skill to the index (description-only). */
56
+ add(skill) {
57
+ this.entries.push({ skill, tokens: tokenize(`${skill.name} ${skill.description}`) });
58
+ }
59
+ /**
60
+ * Select skills relevant to `prompt` by keyword overlap with their descriptions.
61
+ *
62
+ * @param prompt - The user prompt.
63
+ * @param minOverlap - Minimum overlapping tokens to count as relevant. Default 1.
64
+ */
65
+ select(prompt, minOverlap = 1) {
66
+ const promptTokens = tokenize(prompt);
67
+ const scored = [];
68
+ for (const { skill, tokens } of this.entries) {
69
+ let score = 0;
70
+ for (const t of tokens) if (promptTokens.has(t)) score++;
71
+ if (score >= minOverlap) scored.push({ skill, score });
72
+ }
73
+ return scored.sort((a, b) => b.score - a.score).map((s) => s.skill);
74
+ }
75
+ /** Load the full content of a selected skill (concatenated sources). (FR-017) */
76
+ async load(skill) {
77
+ const parts = await Promise.all(skill.sources.map(loadSource));
78
+ return parts.join("\n\n");
79
+ }
80
+ };
81
+
82
+ exports.SkillIndex = SkillIndex;
83
+ exports.defineSkill = defineSkill;
84
+ exports.loadSource = loadSource;
85
+ //# sourceMappingURL=chunk-WSMYH2IN.cjs.map
86
+ //# sourceMappingURL=chunk-WSMYH2IN.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/skills/skill.ts","../src/skills/index.ts"],"names":[],"mappings":"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","file":"chunk-WSMYH2IN.cjs","sourcesContent":["/**\n * Skills: domain-specific knowledge bundles attached to agents. Skills use\n * progressive disclosure — only a skill's short description is used to decide\n * relevance, and its full content is loaded only when the skill is deemed needed.\n * (FR-016, FR-017)\n *\n * @packageDocumentation\n */\n\n/** A source of skill content, loaded on demand. */\nexport type SkillSource =\n\t| { kind: \"inline\"; content: string }\n\t| { kind: \"file\"; path: string }\n\t| { kind: \"code\"; load: () => Promise<string> };\n\n/** A domain knowledge bundle. */\nexport interface Skill {\n\t/** Unique skill name. */\n\tname: string;\n\t/** Short description — the ONLY text used to decide relevance. (FR-017) */\n\tdescription: string;\n\t/** Content sources, read only when the skill is selected. */\n\tsources: SkillSource[];\n}\n\n/**\n * Define a skill.\n *\n * @example\n * ```ts\n * const refund = defineSkill({\n * name: \"refund-policy\",\n * description: \"Company refund and return rules.\",\n * sources: [{ kind: \"inline\", content: \"Refunds allowed within 30 days...\" }],\n * });\n * ```\n */\nexport function defineSkill(skill: Skill): Skill {\n\treturn skill;\n}\n\n/** Read a single source's content. File sources require a Node runtime. */\nexport async function loadSource(source: SkillSource): Promise<string> {\n\tswitch (source.kind) {\n\t\tcase \"inline\":\n\t\t\treturn source.content;\n\t\tcase \"code\":\n\t\t\treturn source.load();\n\t\tcase \"file\": {\n\t\t\tconst { readFile } = await import(\"node:fs/promises\");\n\t\t\treturn readFile(source.path, \"utf8\");\n\t\t}\n\t}\n}\n","/**\n * Client-side keyword/text index over skill descriptions. No embeddings and no\n * extra provider — relevance is decided by simple token overlap so it runs fully\n * in the browser/edge. Full content is loaded only after a skill is selected.\n * (FR-017, FR-017a)\n *\n * @packageDocumentation\n */\n\nimport type { Skill } from \"./skill.js\";\nimport { loadSource } from \"./skill.js\";\n\nexport * from \"./skill.js\";\n\nconst STOPWORDS = new Set([\n\t\"the\", \"a\", \"an\", \"and\", \"or\", \"of\", \"to\", \"in\", \"for\", \"on\", \"is\", \"are\",\n\t\"with\", \"how\", \"what\", \"do\", \"does\", \"i\", \"you\", \"it\", \"this\", \"that\",\n]);\n\nfunction tokenize(text: string): Set<string> {\n\treturn new Set(\n\t\ttext\n\t\t\t.toLowerCase()\n\t\t\t.split(/[^a-z0-9]+/)\n\t\t\t.filter((w) => w.length > 2 && !STOPWORDS.has(w)),\n\t);\n}\n\n/** Indexes skills by description and selects relevant ones for a prompt. */\nexport class SkillIndex {\n\tprivate readonly entries: Array<{ skill: Skill; tokens: Set<string> }> = [];\n\n\tconstructor(skills: Skill[] = []) {\n\t\tfor (const s of skills) this.add(s);\n\t}\n\n\t/** Add a skill to the index (description-only). */\n\tadd(skill: Skill): void {\n\t\tthis.entries.push({ skill, tokens: tokenize(`${skill.name} ${skill.description}`) });\n\t}\n\n\t/**\n\t * Select skills relevant to `prompt` by keyword overlap with their descriptions.\n\t *\n\t * @param prompt - The user prompt.\n\t * @param minOverlap - Minimum overlapping tokens to count as relevant. Default 1.\n\t */\n\tselect(prompt: string, minOverlap = 1): Skill[] {\n\t\tconst promptTokens = tokenize(prompt);\n\t\tconst scored: Array<{ skill: Skill; score: number }> = [];\n\t\tfor (const { skill, tokens } of this.entries) {\n\t\t\tlet score = 0;\n\t\t\tfor (const t of tokens) if (promptTokens.has(t)) score++;\n\t\t\tif (score >= minOverlap) scored.push({ skill, score });\n\t\t}\n\t\treturn scored.sort((a, b) => b.score - a.score).map((s) => s.skill);\n\t}\n\n\t/** Load the full content of a selected skill (concatenated sources). (FR-017) */\n\tasync load(skill: Skill): Promise<string> {\n\t\tconst parts = await Promise.all(skill.sources.map(loadSource));\n\t\treturn parts.join(\"\\n\\n\");\n\t}\n}\n"]}
@@ -0,0 +1,81 @@
1
+ // src/core/types.ts
2
+ function textMessage(role, text) {
3
+ return { role, parts: [{ type: "text", text }] };
4
+ }
5
+ function hasImage(message) {
6
+ return message.parts.some((p) => p.type === "image");
7
+ }
8
+ function messageText(message) {
9
+ return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
10
+ }
11
+
12
+ // src/agents/thread.ts
13
+ function estimateTokens(messages) {
14
+ const chars = messages.reduce((sum, m) => sum + messageText(m).length, 0);
15
+ return Math.ceil(chars / 4);
16
+ }
17
+ var Thread = class _Thread {
18
+ id;
19
+ messages;
20
+ /** Whether the thread has been compacted at least once. */
21
+ compacted = false;
22
+ constructor(id, messages = []) {
23
+ this.id = id ?? cryptoRandomId();
24
+ this.messages = messages;
25
+ }
26
+ /** Append a message. */
27
+ add(message) {
28
+ this.messages.push(message);
29
+ }
30
+ /** Serializable snapshot for persistence. */
31
+ toJSON() {
32
+ return { id: this.id, messages: this.messages, compacted: this.compacted };
33
+ }
34
+ /** Restore a thread from a snapshot. */
35
+ static fromJSON(data) {
36
+ const t = new _Thread(data.id, data.messages);
37
+ t.compacted = data.compacted ?? false;
38
+ return t;
39
+ }
40
+ /**
41
+ * Compact the thread if it exceeds the threshold. System messages and the most
42
+ * recent turn are preserved; older turns are summarized via the model.
43
+ *
44
+ * @returns true if compaction occurred.
45
+ */
46
+ async maybeCompact(provider, options) {
47
+ const threshold = options?.compactionThreshold ?? 0.9;
48
+ const limit = provider.capabilities.maxInputTokens * threshold;
49
+ if (estimateTokens(this.messages) < limit) return false;
50
+ const summarizer = options?.compactionModel ?? provider;
51
+ const system = this.messages.filter((m) => m.role === "system");
52
+ const recent = this.messages.slice(-2);
53
+ const toSummarize = this.messages.filter((m) => m.role !== "system").slice(0, -2);
54
+ if (toSummarize.length === 0) return false;
55
+ const summary = await summarizer.generate({
56
+ messages: [
57
+ textMessage(
58
+ "system",
59
+ "Summarize the following conversation compactly, preserving facts, decisions, and open questions."
60
+ ),
61
+ textMessage("user", toSummarize.map((m) => `${m.role}: ${messageText(m)}`).join("\n"))
62
+ ]
63
+ });
64
+ this.messages = [
65
+ ...system,
66
+ textMessage("system", `Summary of earlier conversation: ${summary.text}`),
67
+ ...recent
68
+ ];
69
+ this.compacted = true;
70
+ return true;
71
+ }
72
+ };
73
+ function cryptoRandomId() {
74
+ const c = globalThis.crypto;
75
+ if (c?.randomUUID) return c.randomUUID();
76
+ return `thread-${Math.random().toString(36).slice(2)}-${Date.now()}`;
77
+ }
78
+
79
+ export { Thread, estimateTokens, hasImage, messageText, textMessage };
80
+ //# sourceMappingURL=chunk-XPXTXOYQ.js.map
81
+ //# sourceMappingURL=chunk-XPXTXOYQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/types.ts","../src/agents/thread.ts"],"names":[],"mappings":"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","file":"chunk-XPXTXOYQ.js","sourcesContent":["/**\n * Shared content, message, and model-capability types used across the framework.\n *\n * These are the lowest-level building blocks: every higher-level module (agents,\n * providers, tools, workflows) speaks in terms of {@link Message} and\n * {@link ContentPart}. Keeping them dependency-free keeps the core tree-shakeable.\n *\n * @packageDocumentation\n */\n\n/** A JSON Schema object (draft 2020-12 compatible), as popularized by MCP. */\nexport type JSONSchema = Record<string, unknown>;\n\n/** Role of a message in a conversation. */\nexport type Role = \"system\" | \"user\" | \"assistant\" | \"tool\";\n\n/** A single piece of message content. Images are only valid for vision-capable models. */\nexport type ContentPart =\n\t| { type: \"text\"; text: string }\n\t| { type: \"image\"; data: string; mimeType: string };\n\n/**\n * A conversation message.\n *\n * @example\n * ```ts\n * const msg: Message = { role: \"user\", parts: [{ type: \"text\", text: \"Hi\" }] };\n * ```\n */\nexport interface Message {\n\trole: Role;\n\tparts: ContentPart[];\n\t/** Optional tool-call linkage for assistant/tool messages. */\n\ttoolCallId?: string;\n\t/** Optional display name (e.g., the tool name for a tool message). */\n\tname?: string;\n}\n\n/**\n * Per-model capabilities supplied by the caller. The framework cannot reliably\n * discover these for arbitrary OpenAI-compatible/LM Studio models, so they are\n * provided explicitly. (FR-007a)\n */\nexport interface ModelCapabilities {\n\t/** Model id/name. */\n\tmodel: string;\n\t/** Maximum input/context tokens; drives compaction threshold. */\n\tmaxInputTokens: number;\n\t/** Maximum output tokens. */\n\tmaxOutputTokens: number;\n\t/** Whether the model accepts image input. Defaults to false. */\n\tsupportsVision?: boolean;\n\t/** Whether the model emits separate reasoning/thinking content. Defaults to false. */\n\tsupportsReasoning?: boolean;\n}\n\n/** Convenience: build a user message from a plain string. */\nexport function textMessage(role: Role, text: string): Message {\n\treturn { role, parts: [{ type: \"text\", text }] };\n}\n\n/** Returns true if a message contains any image content part. */\nexport function hasImage(message: Message): boolean {\n\treturn message.parts.some((p) => p.type === \"image\");\n}\n\n/** Extract the concatenated text from a message. */\nexport function messageText(message: Message): string {\n\treturn message.parts\n\t\t.filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n\t\t.map((p) => p.text)\n\t\t.join(\"\");\n}\n","/**\n * Conversation thread with automatic compaction. When a thread approaches the\n * model's input-token budget it is summarized into a compact form so the\n * conversation can continue. (FR-004, FR-004a, FR-004b)\n *\n * @packageDocumentation\n */\n\nimport type { Message } from \"../core/types.js\";\nimport { messageText, textMessage } from \"../core/types.js\";\nimport type { Provider } from \"../providers/provider.js\";\n\n/** Options controlling a thread's compaction behavior. */\nexport interface ThreadOptions {\n\t/** Fraction of `maxInputTokens` at which compaction triggers. Default 0.9. */\n\tcompactionThreshold?: number;\n\t/** Provider used to summarize; defaults to the agent's own provider. (FR-004b) */\n\tcompactionModel?: Provider;\n}\n\n/** Rough token estimate (~4 chars/token) — avoids a tokenizer dependency. */\nexport function estimateTokens(messages: Message[]): number {\n\tconst chars = messages.reduce((sum, m) => sum + messageText(m).length, 0);\n\treturn Math.ceil(chars / 4);\n}\n\n/** A multi-turn conversation that preserves context and compacts when large. */\nexport class Thread {\n\treadonly id: string;\n\tmessages: Message[];\n\t/** Whether the thread has been compacted at least once. */\n\tcompacted = false;\n\n\tconstructor(id?: string, messages: Message[] = []) {\n\t\tthis.id = id ?? cryptoRandomId();\n\t\tthis.messages = messages;\n\t}\n\n\t/** Append a message. */\n\tadd(message: Message): void {\n\t\tthis.messages.push(message);\n\t}\n\n\t/** Serializable snapshot for persistence. */\n\ttoJSON(): { id: string; messages: Message[]; compacted: boolean } {\n\t\treturn { id: this.id, messages: this.messages, compacted: this.compacted };\n\t}\n\n\t/** Restore a thread from a snapshot. */\n\tstatic fromJSON(data: { id: string; messages: Message[]; compacted?: boolean }): Thread {\n\t\tconst t = new Thread(data.id, data.messages);\n\t\tt.compacted = data.compacted ?? false;\n\t\treturn t;\n\t}\n\n\t/**\n\t * Compact the thread if it exceeds the threshold. System messages and the most\n\t * recent turn are preserved; older turns are summarized via the model.\n\t *\n\t * @returns true if compaction occurred.\n\t */\n\tasync maybeCompact(provider: Provider, options?: ThreadOptions): Promise<boolean> {\n\t\tconst threshold = options?.compactionThreshold ?? 0.9;\n\t\tconst limit = provider.capabilities.maxInputTokens * threshold;\n\t\tif (estimateTokens(this.messages) < limit) return false;\n\n\t\tconst summarizer = options?.compactionModel ?? provider;\n\t\tconst system = this.messages.filter((m) => m.role === \"system\");\n\t\tconst recent = this.messages.slice(-2);\n\t\tconst toSummarize = this.messages.filter((m) => m.role !== \"system\").slice(0, -2);\n\t\tif (toSummarize.length === 0) return false;\n\n\t\tconst summary = await summarizer.generate({\n\t\t\tmessages: [\n\t\t\t\ttextMessage(\n\t\t\t\t\t\"system\",\n\t\t\t\t\t\"Summarize the following conversation compactly, preserving facts, decisions, and open questions.\",\n\t\t\t\t),\n\t\t\t\ttextMessage(\"user\", toSummarize.map((m) => `${m.role}: ${messageText(m)}`).join(\"\\n\")),\n\t\t\t],\n\t\t});\n\n\t\tthis.messages = [\n\t\t\t...system,\n\t\t\ttextMessage(\"system\", `Summary of earlier conversation: ${summary.text}`),\n\t\t\t...recent,\n\t\t];\n\t\tthis.compacted = true;\n\t\treturn true;\n\t}\n}\n\nfunction cryptoRandomId(): string {\n\tconst c = (globalThis as { crypto?: Crypto }).crypto;\n\tif (c?.randomUUID) return c.randomUUID();\n\treturn `thread-${Math.random().toString(36).slice(2)}-${Date.now()}`;\n}\n"]}
@@ -0,0 +1,194 @@
1
+ 'use strict';
2
+
3
+ var chunkWSMYH2IN_cjs = require('./chunk-WSMYH2IN.cjs');
4
+ var chunkTAMJ5HSR_cjs = require('./chunk-TAMJ5HSR.cjs');
5
+ var chunkFSDMBWQV_cjs = require('./chunk-FSDMBWQV.cjs');
6
+ var chunkLMN75W3W_cjs = require('./chunk-LMN75W3W.cjs');
7
+ var chunkMQ2XTH3S_cjs = require('./chunk-MQ2XTH3S.cjs');
8
+
9
+ // src/agents/loop.ts
10
+ async function runLoop(generate, registry, messages, options) {
11
+ const maxIterations = options?.maxIterations ?? 10;
12
+ const working = [...messages];
13
+ let iteration = 0;
14
+ for (; ; ) {
15
+ if (maxIterations !== -1 && iteration >= maxIterations) {
16
+ return {
17
+ messages: working,
18
+ final: { text: "" },
19
+ status: "limit-exceeded"
20
+ };
21
+ }
22
+ iteration++;
23
+ const specs = registry.specs();
24
+ const response = await generate({
25
+ messages: working,
26
+ tools: specs.length > 0 ? specs : void 0,
27
+ signal: options?.signal
28
+ });
29
+ if (!response.toolCalls || response.toolCalls.length === 0) {
30
+ return { messages: working, final: response, status: "completed" };
31
+ }
32
+ working.push({
33
+ role: "assistant",
34
+ parts: response.text ? [{ type: "text", text: response.text }] : []
35
+ });
36
+ for (const call of response.toolCalls) {
37
+ const result = await registry.invoke(call.name, call.arguments, options?.toolTimeoutMs);
38
+ const payload = result.error ? `ERROR (${result.error.reason}): ${result.error.message}` : JSON.stringify(result.value ?? null);
39
+ working.push({
40
+ role: "tool",
41
+ name: call.name,
42
+ toolCallId: call.id,
43
+ parts: [{ type: "text", text: payload }]
44
+ });
45
+ }
46
+ }
47
+ }
48
+ function buildMessages(instructions, input) {
49
+ return [chunkLMN75W3W_cjs.textMessage("system", instructions), ...input];
50
+ }
51
+
52
+ // src/agents/agent.ts
53
+ function normalizeInput(input) {
54
+ if (typeof input === "string") return [chunkLMN75W3W_cjs.textMessage("user", input)];
55
+ return Array.isArray(input) ? input : [input];
56
+ }
57
+ function promptText(messages) {
58
+ return messages.flatMap((m) => m.parts).filter((p) => p.type === "text").map((p) => p.text).join(" ");
59
+ }
60
+ function createAgent(config) {
61
+ const registry = new chunkTAMJ5HSR_cjs.ToolRegistry(config.tools ?? []);
62
+ const skillIndex = new chunkWSMYH2IN_cjs.SkillIndex(config.skills ?? []);
63
+ const middleware = config.middleware ?? [];
64
+ function gateVision(messages) {
65
+ if (!config.provider.capabilities.supportsVision && messages.some(chunkLMN75W3W_cjs.hasImage)) {
66
+ throw new chunkMQ2XTH3S_cjs.ProviderError(
67
+ "Image input was provided but the configured model does not support vision",
68
+ "client"
69
+ );
70
+ }
71
+ }
72
+ async function injectSkills(userMessages) {
73
+ if ((config.skills ?? []).length === 0) return userMessages;
74
+ const selected = skillIndex.select(promptText(userMessages));
75
+ if (selected.length === 0) return userMessages;
76
+ const contents = await Promise.all(selected.map((s) => skillIndex.load(s)));
77
+ const skillBlock = chunkLMN75W3W_cjs.textMessage(
78
+ "system",
79
+ `Relevant skill knowledge:
80
+ ${contents.join("\n\n")}`
81
+ );
82
+ return [skillBlock, ...userMessages];
83
+ }
84
+ async function callProvider(req) {
85
+ const ctx = {
86
+ agentName: config.name,
87
+ request: req
88
+ };
89
+ const pipeline = chunkFSDMBWQV_cjs.composeMiddleware(middleware, (c) => config.provider.generate(c.request));
90
+ return pipeline(ctx);
91
+ }
92
+ async function prepare(input, opts) {
93
+ const userMessages = normalizeInput(input);
94
+ gateVision(userMessages);
95
+ const thread = opts?.thread ?? new chunkLMN75W3W_cjs.Thread(void 0, [chunkLMN75W3W_cjs.textMessage("system", config.instructions)]);
96
+ const withSkills = await injectSkills(userMessages);
97
+ for (const m of withSkills) thread.add(m);
98
+ await thread.maybeCompact(config.provider, {
99
+ compactionThreshold: config.compactionThreshold,
100
+ compactionModel: config.compactionModel
101
+ });
102
+ return thread;
103
+ }
104
+ async function run(input, opts) {
105
+ let thread;
106
+ try {
107
+ thread = await prepare(input, opts);
108
+ } catch (e) {
109
+ if (e instanceof chunkMQ2XTH3S_cjs.ProviderError) {
110
+ return { output: "", status: "failed", partial: false, error: e, thread: opts?.thread ?? new chunkLMN75W3W_cjs.Thread() };
111
+ }
112
+ throw e;
113
+ }
114
+ try {
115
+ const loop = await runLoop(callProvider, registry, thread.messages, {
116
+ maxIterations: config.maxIterations,
117
+ toolTimeoutMs: config.toolTimeoutMs,
118
+ signal: opts?.signal
119
+ });
120
+ if (loop.final.text) {
121
+ thread.add({ role: "assistant", parts: [{ type: "text", text: loop.final.text }] });
122
+ }
123
+ return {
124
+ output: loop.final.text,
125
+ reasoning: config.provider.capabilities.supportsReasoning ? loop.final.reasoning : void 0,
126
+ status: loop.status,
127
+ partial: loop.status === "incomplete",
128
+ thread
129
+ };
130
+ } catch (e) {
131
+ if (e instanceof chunkMQ2XTH3S_cjs.ProviderError) {
132
+ return { output: "", status: "failed", partial: false, error: e, thread };
133
+ }
134
+ throw e;
135
+ }
136
+ }
137
+ async function* runStream(input, opts) {
138
+ let thread;
139
+ try {
140
+ thread = await prepare(input, opts);
141
+ } catch (e) {
142
+ if (e instanceof chunkMQ2XTH3S_cjs.ProviderError) {
143
+ yield { type: "done", result: { output: "", status: "failed", partial: false, error: e, thread: opts?.thread ?? new chunkLMN75W3W_cjs.Thread() } };
144
+ return;
145
+ }
146
+ throw e;
147
+ }
148
+ let text = "";
149
+ let reasoning = "";
150
+ try {
151
+ for await (const chunk of config.provider.generateStream({
152
+ messages: thread.messages,
153
+ tools: registry.specs(),
154
+ signal: opts?.signal
155
+ })) {
156
+ if (chunk.type === "text") {
157
+ text += chunk.text;
158
+ yield { type: "text", text: chunk.text };
159
+ } else if (chunk.type === "reasoning" && config.provider.capabilities.supportsReasoning) {
160
+ reasoning += chunk.text;
161
+ yield { type: "reasoning", text: chunk.text };
162
+ } else if (chunk.type === "done") {
163
+ text = chunk.response.text || text;
164
+ reasoning = chunk.response.reasoning || reasoning;
165
+ }
166
+ }
167
+ } catch (e) {
168
+ const error = e instanceof chunkMQ2XTH3S_cjs.ProviderError ? e : new chunkMQ2XTH3S_cjs.ProviderError(e.message, "transient");
169
+ yield {
170
+ type: "done",
171
+ result: { output: text, status: "incomplete", partial: true, error, thread }
172
+ };
173
+ return;
174
+ }
175
+ if (text) thread.add({ role: "assistant", parts: [{ type: "text", text }] });
176
+ yield {
177
+ type: "done",
178
+ result: {
179
+ output: text,
180
+ reasoning: config.provider.capabilities.supportsReasoning ? reasoning || void 0 : void 0,
181
+ status: "completed",
182
+ partial: false,
183
+ thread
184
+ }
185
+ };
186
+ }
187
+ return { name: config.name, run, runStream };
188
+ }
189
+
190
+ exports.buildMessages = buildMessages;
191
+ exports.createAgent = createAgent;
192
+ exports.runLoop = runLoop;
193
+ //# sourceMappingURL=chunk-YBFLWRO5.cjs.map
194
+ //# sourceMappingURL=chunk-YBFLWRO5.cjs.map