@duckcodeailabs/dql-agent 1.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 (50) hide show
  1. package/LICENSE +123 -0
  2. package/dist/answer-loop.d.ts +74 -0
  3. package/dist/answer-loop.d.ts.map +1 -0
  4. package/dist/answer-loop.js +170 -0
  5. package/dist/answer-loop.js.map +1 -0
  6. package/dist/index.d.ts +51 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +87 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/kg/build.d.ts +17 -0
  11. package/dist/kg/build.d.ts.map +1 -0
  12. package/dist/kg/build.js +126 -0
  13. package/dist/kg/build.js.map +1 -0
  14. package/dist/kg/sqlite-fts.d.ts +39 -0
  15. package/dist/kg/sqlite-fts.d.ts.map +1 -0
  16. package/dist/kg/sqlite-fts.js +257 -0
  17. package/dist/kg/sqlite-fts.js.map +1 -0
  18. package/dist/kg/types.d.ts +64 -0
  19. package/dist/kg/types.d.ts.map +1 -0
  20. package/dist/kg/types.js +10 -0
  21. package/dist/kg/types.js.map +1 -0
  22. package/dist/providers/claude.d.ts +21 -0
  23. package/dist/providers/claude.d.ts.map +1 -0
  24. package/dist/providers/claude.js +56 -0
  25. package/dist/providers/claude.js.map +1 -0
  26. package/dist/providers/gemini.d.ts +18 -0
  27. package/dist/providers/gemini.d.ts.map +1 -0
  28. package/dist/providers/gemini.js +60 -0
  29. package/dist/providers/gemini.js.map +1 -0
  30. package/dist/providers/index.d.ts +24 -0
  31. package/dist/providers/index.d.ts.map +1 -0
  32. package/dist/providers/index.js +43 -0
  33. package/dist/providers/index.js.map +1 -0
  34. package/dist/providers/ollama.d.ts +21 -0
  35. package/dist/providers/ollama.d.ts.map +1 -0
  36. package/dist/providers/ollama.js +49 -0
  37. package/dist/providers/ollama.js.map +1 -0
  38. package/dist/providers/openai.d.ts +19 -0
  39. package/dist/providers/openai.d.ts.map +1 -0
  40. package/dist/providers/openai.js +44 -0
  41. package/dist/providers/openai.js.map +1 -0
  42. package/dist/providers/types.d.ts +39 -0
  43. package/dist/providers/types.d.ts.map +1 -0
  44. package/dist/providers/types.js +15 -0
  45. package/dist/providers/types.js.map +1 -0
  46. package/dist/skills/loader.d.ts +49 -0
  47. package/dist/skills/loader.d.ts.map +1 -0
  48. package/dist/skills/loader.js +177 -0
  49. package/dist/skills/loader.js.map +1 -0
  50. package/package.json +46 -0
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Google Gemini provider via the v1beta REST surface. Reads GEMINI_API_KEY.
3
+ * Maps system messages by prepending them to the first user turn since
4
+ * Gemini's API doesn't have a first-class system role.
5
+ */
6
+ export class GeminiProvider {
7
+ name = 'gemini';
8
+ apiKey;
9
+ defaultModel;
10
+ constructor(opts = {}) {
11
+ this.apiKey = opts.apiKey ?? process.env.GEMINI_API_KEY ?? process.env.GOOGLE_API_KEY;
12
+ this.defaultModel = opts.model ?? 'gemini-2.5-pro';
13
+ }
14
+ async available() {
15
+ return Boolean(this.apiKey);
16
+ }
17
+ async generate(messages, options = {}) {
18
+ if (!this.apiKey) {
19
+ throw new Error('gemini: GEMINI_API_KEY is not set');
20
+ }
21
+ const systemText = messages.filter((m) => m.role === 'system').map((m) => m.content).join('\n\n');
22
+ const turns = messages.filter((m) => m.role !== 'system');
23
+ if (systemText) {
24
+ const firstUser = turns.findIndex((m) => m.role === 'user');
25
+ if (firstUser >= 0) {
26
+ turns[firstUser] = {
27
+ ...turns[firstUser],
28
+ content: `${systemText}\n\n${turns[firstUser].content}`,
29
+ };
30
+ }
31
+ else {
32
+ turns.unshift({ role: 'user', content: systemText });
33
+ }
34
+ }
35
+ const model = options.model ?? this.defaultModel;
36
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(model)}:generateContent?key=${encodeURIComponent(this.apiKey)}`;
37
+ const res = await fetch(url, {
38
+ method: 'POST',
39
+ headers: { 'content-type': 'application/json' },
40
+ body: JSON.stringify({
41
+ contents: turns.map((m) => ({
42
+ role: m.role === 'assistant' ? 'model' : 'user',
43
+ parts: [{ text: m.content }],
44
+ })),
45
+ generationConfig: {
46
+ temperature: options.temperature ?? 0.2,
47
+ maxOutputTokens: options.maxTokens ?? 1024,
48
+ },
49
+ }),
50
+ signal: options.signal,
51
+ });
52
+ if (!res.ok) {
53
+ const body = await res.text().catch(() => res.statusText);
54
+ throw new Error(`gemini: ${res.status} ${body}`);
55
+ }
56
+ const json = (await res.json());
57
+ return json.candidates?.[0]?.content?.parts?.map((p) => p.text ?? '').join('') ?? '';
58
+ }
59
+ }
60
+ //# sourceMappingURL=gemini.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../src/providers/gemini.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,QAAiB,CAAC;IACjB,MAAM,CAAU;IAChB,YAAY,CAAS;IAEtC,YAAY,OAA4C,EAAE;QACxD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACtF,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,IAAI,gBAAgB,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAwB,EAAE,UAA8B,EAAE;QACvE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClG,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAC1D,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;YAC5D,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;gBACnB,KAAK,CAAC,SAAS,CAAC,GAAG;oBACjB,GAAG,KAAK,CAAC,SAAS,CAAC;oBACnB,OAAO,EAAE,GAAG,UAAU,OAAO,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;iBACxD,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY,CAAC;QACjD,MAAM,GAAG,GAAG,2DAA2D,kBAAkB,CAAC,KAAK,CAAC,wBAAwB,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1J,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC1B,IAAI,EAAE,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;oBAC/C,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;iBAC7B,CAAC,CAAC;gBACH,gBAAgB,EAAE;oBAChB,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG;oBACvC,eAAe,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;iBAC3C;aACF,CAAC;YACF,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAE7B,CAAC;QACF,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;IACvF,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Provider registry. The `pickProvider()` helper falls back through the
3
+ * configured list and returns the first one that has its credentials.
4
+ *
5
+ * Order is intentional: closed-source first (Claude → OpenAI → Gemini),
6
+ * Ollama last as the local-only fallback.
7
+ */
8
+ import type { AgentProvider, ProviderName } from './types.js';
9
+ import { ClaudeProvider } from './claude.js';
10
+ import { OpenAIProvider } from './openai.js';
11
+ import { GeminiProvider } from './gemini.js';
12
+ import { OllamaProvider } from './ollama.js';
13
+ export type { AgentProvider, AgentMessage, ProviderName, ProviderRunOptions } from './types.js';
14
+ export { ClaudeProvider, OpenAIProvider, GeminiProvider, OllamaProvider };
15
+ export declare function buildProvider(name: ProviderName): AgentProvider;
16
+ /**
17
+ * Pick a provider:
18
+ * - If `preferred` is set, return it (no availability check, fail-fast at use time).
19
+ * - Otherwise probe FALLBACK_ORDER and return the first available.
20
+ * - If nothing is available, return the Ollama provider (so callers get
21
+ * a usable error message at generate time).
22
+ */
23
+ export declare function pickProvider(preferred?: ProviderName): Promise<AgentProvider>;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChG,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAI1E,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAW/D;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,SAAS,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAOnF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Provider registry. The `pickProvider()` helper falls back through the
3
+ * configured list and returns the first one that has its credentials.
4
+ *
5
+ * Order is intentional: closed-source first (Claude → OpenAI → Gemini),
6
+ * Ollama last as the local-only fallback.
7
+ */
8
+ import { ClaudeProvider } from './claude.js';
9
+ import { OpenAIProvider } from './openai.js';
10
+ import { GeminiProvider } from './gemini.js';
11
+ import { OllamaProvider } from './ollama.js';
12
+ export { ClaudeProvider, OpenAIProvider, GeminiProvider, OllamaProvider };
13
+ const FALLBACK_ORDER = ['claude', 'openai', 'gemini', 'ollama'];
14
+ export function buildProvider(name) {
15
+ switch (name) {
16
+ case 'claude':
17
+ return new ClaudeProvider();
18
+ case 'openai':
19
+ return new OpenAIProvider();
20
+ case 'gemini':
21
+ return new GeminiProvider();
22
+ case 'ollama':
23
+ return new OllamaProvider();
24
+ }
25
+ }
26
+ /**
27
+ * Pick a provider:
28
+ * - If `preferred` is set, return it (no availability check, fail-fast at use time).
29
+ * - Otherwise probe FALLBACK_ORDER and return the first available.
30
+ * - If nothing is available, return the Ollama provider (so callers get
31
+ * a usable error message at generate time).
32
+ */
33
+ export async function pickProvider(preferred) {
34
+ if (preferred)
35
+ return buildProvider(preferred);
36
+ for (const name of FALLBACK_ORDER) {
37
+ const p = buildProvider(name);
38
+ if (await p.available())
39
+ return p;
40
+ }
41
+ return buildProvider('ollama');
42
+ }
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/providers/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAE1E,MAAM,cAAc,GAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAEhF,MAAM,UAAU,aAAa,CAAC,IAAkB;IAC9C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,EAAE,CAAC;QAC9B,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,EAAE,CAAC;QAC9B,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,EAAE,CAAC;QAC9B,KAAK,QAAQ;YACX,OAAO,IAAI,cAAc,EAAE,CAAC;IAChC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAwB;IACzD,IAAI,SAAS;QAAE,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,MAAM,CAAC,CAAC,SAAS,EAAE;YAAE,OAAO,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { AgentProvider, AgentMessage, ProviderRunOptions } from './types.js';
2
+ /**
3
+ * Local Ollama provider — talks to a local Ollama daemon on
4
+ * http://127.0.0.1:11434 (overridable via OLLAMA_BASE_URL).
5
+ *
6
+ * `available()` does a HEAD request and returns true on any 2xx/4xx — a
7
+ * 4xx still means a daemon is listening. Use OLLAMA_MODEL or pass `model`
8
+ * to pin the served model.
9
+ */
10
+ export declare class OllamaProvider implements AgentProvider {
11
+ readonly name: "ollama";
12
+ private readonly baseUrl;
13
+ private readonly defaultModel;
14
+ constructor(opts?: {
15
+ baseUrl?: string;
16
+ model?: string;
17
+ });
18
+ available(): Promise<boolean>;
19
+ generate(messages: AgentMessage[], options?: ProviderRunOptions): Promise<string>;
20
+ }
21
+ //# sourceMappingURL=ollama.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.d.ts","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,aAAa;IAClD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,IAAI,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO;IAKrD,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAS7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC;CAsB5F"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Local Ollama provider — talks to a local Ollama daemon on
3
+ * http://127.0.0.1:11434 (overridable via OLLAMA_BASE_URL).
4
+ *
5
+ * `available()` does a HEAD request and returns true on any 2xx/4xx — a
6
+ * 4xx still means a daemon is listening. Use OLLAMA_MODEL or pass `model`
7
+ * to pin the served model.
8
+ */
9
+ export class OllamaProvider {
10
+ name = 'ollama';
11
+ baseUrl;
12
+ defaultModel;
13
+ constructor(opts = {}) {
14
+ this.baseUrl = (opts.baseUrl ?? process.env.OLLAMA_BASE_URL ?? 'http://127.0.0.1:11434').replace(/\/+$/, '');
15
+ this.defaultModel = opts.model ?? process.env.OLLAMA_MODEL ?? 'llama3.1';
16
+ }
17
+ async available() {
18
+ try {
19
+ const res = await fetch(`${this.baseUrl}/api/tags`, { method: 'GET' });
20
+ return res.status < 500;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ async generate(messages, options = {}) {
27
+ const res = await fetch(`${this.baseUrl}/api/chat`, {
28
+ method: 'POST',
29
+ headers: { 'content-type': 'application/json' },
30
+ body: JSON.stringify({
31
+ model: options.model ?? this.defaultModel,
32
+ messages: messages.map((m) => ({ role: m.role, content: m.content })),
33
+ stream: false,
34
+ options: {
35
+ temperature: options.temperature ?? 0.2,
36
+ num_predict: options.maxTokens ?? 1024,
37
+ },
38
+ }),
39
+ signal: options.signal,
40
+ });
41
+ if (!res.ok) {
42
+ const body = await res.text().catch(() => res.statusText);
43
+ throw new Error(`ollama: ${res.status} ${body}`);
44
+ }
45
+ const json = (await res.json());
46
+ return json.message?.content ?? '';
47
+ }
48
+ }
49
+ //# sourceMappingURL=ollama.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,QAAiB,CAAC;IACjB,OAAO,CAAS;IAChB,YAAY,CAAS;IAEtC,YAAY,OAA6C,EAAE;QACzD,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7G,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,UAAU,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;YACvE,OAAO,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAwB,EAAE,UAA8B,EAAE;QACvE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,WAAW,EAAE;YAClD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;gBACzC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBACrE,MAAM,EAAE,KAAK;gBACb,OAAO,EAAE;oBACP,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG;oBACvC,WAAW,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;iBACvC;aACF,CAAC;YACF,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAuC,CAAC;QACtE,OAAO,IAAI,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IACrC,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import type { AgentProvider, AgentMessage, ProviderRunOptions } from './types.js';
2
+ /**
3
+ * OpenAI / Chat Completions-compatible provider. Reads OPENAI_API_KEY plus
4
+ * an optional OPENAI_BASE_URL (e.g. point at Azure OpenAI or vLLM).
5
+ */
6
+ export declare class OpenAIProvider implements AgentProvider {
7
+ readonly name: "openai";
8
+ private readonly apiKey?;
9
+ private readonly baseUrl;
10
+ private readonly defaultModel;
11
+ constructor(opts?: {
12
+ apiKey?: string;
13
+ baseUrl?: string;
14
+ model?: string;
15
+ });
16
+ available(): Promise<boolean>;
17
+ generate(messages: AgentMessage[], options?: ProviderRunOptions): Promise<string>;
18
+ }
19
+ //# sourceMappingURL=openai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,qBAAa,cAAe,YAAW,aAAa;IAClD,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;gBAE1B,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO;IAMtE,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;IAI7B,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC;CA2B5F"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * OpenAI / Chat Completions-compatible provider. Reads OPENAI_API_KEY plus
3
+ * an optional OPENAI_BASE_URL (e.g. point at Azure OpenAI or vLLM).
4
+ */
5
+ export class OpenAIProvider {
6
+ name = 'openai';
7
+ apiKey;
8
+ baseUrl;
9
+ defaultModel;
10
+ constructor(opts = {}) {
11
+ this.apiKey = opts.apiKey ?? process.env.OPENAI_API_KEY;
12
+ this.baseUrl = (opts.baseUrl ?? process.env.OPENAI_BASE_URL ?? 'https://api.openai.com/v1').replace(/\/+$/, '');
13
+ this.defaultModel = opts.model ?? 'gpt-4.1-mini';
14
+ }
15
+ async available() {
16
+ return Boolean(this.apiKey);
17
+ }
18
+ async generate(messages, options = {}) {
19
+ if (!this.apiKey) {
20
+ throw new Error('openai: OPENAI_API_KEY is not set');
21
+ }
22
+ const res = await fetch(`${this.baseUrl}/chat/completions`, {
23
+ method: 'POST',
24
+ headers: {
25
+ Authorization: `Bearer ${this.apiKey}`,
26
+ 'content-type': 'application/json',
27
+ },
28
+ body: JSON.stringify({
29
+ model: options.model ?? this.defaultModel,
30
+ messages: messages.map((m) => ({ role: m.role, content: m.content })),
31
+ max_tokens: options.maxTokens ?? 1024,
32
+ temperature: options.temperature ?? 0.2,
33
+ }),
34
+ signal: options.signal,
35
+ });
36
+ if (!res.ok) {
37
+ const body = await res.text().catch(() => res.statusText);
38
+ throw new Error(`openai: ${res.status} ${body}`);
39
+ }
40
+ const json = (await res.json());
41
+ return json.choices?.[0]?.message?.content ?? '';
42
+ }
43
+ }
44
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,QAAiB,CAAC;IACjB,MAAM,CAAU;IAChB,OAAO,CAAS;IAChB,YAAY,CAAS;IAEtC,YAAY,OAA8D,EAAE;QAC1E,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QACxD,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,2BAA2B,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAChH,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,KAAK,IAAI,cAAc,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,SAAS;QACb,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,QAAwB,EAAE,UAA8B,EAAE;QACvE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,OAAO,mBAAmB,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,EAAE;gBACtC,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,IAAI,CAAC,YAAY;gBACzC,QAAQ,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;gBACrE,UAAU,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI;gBACrC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,GAAG;aACxC,CAAC;YACF,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,WAAW,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAE7B,CAAC;QACF,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC;IACnD,CAAC;CACF"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Pluggable LLM provider interface for the agent.
3
+ *
4
+ * Providers are intentionally tiny — they take a system+user message pair
5
+ * and return a string response. Streaming and tool-use orchestration are
6
+ * intentionally out of scope at this layer; the answer-loop owns that
7
+ * orchestration on top of the provider.
8
+ *
9
+ * Each provider is implementation-detail-free: it reads its config from
10
+ * env vars and an optional user-supplied object, and uses `fetch` so we
11
+ * stay zero-dep at the package level. Network-bound failures bubble out as
12
+ * thrown Errors with provider-prefixed messages.
13
+ */
14
+ export type ProviderName = 'claude' | 'openai' | 'gemini' | 'ollama';
15
+ export interface AgentMessage {
16
+ role: 'system' | 'user' | 'assistant';
17
+ content: string;
18
+ }
19
+ export interface ProviderRunOptions {
20
+ /** Optional model override; otherwise the provider picks a sane default. */
21
+ model?: string;
22
+ /** Hard token cap. */
23
+ maxTokens?: number;
24
+ /** Sampling temperature (0..1). */
25
+ temperature?: number;
26
+ /** Caller-supplied AbortSignal — providers honor it. */
27
+ signal?: AbortSignal;
28
+ }
29
+ export interface AgentProvider {
30
+ readonly name: ProviderName;
31
+ /**
32
+ * Send the conversation, return a single response string.
33
+ * Throws on transport / API errors.
34
+ */
35
+ generate(messages: AgentMessage[], options?: ProviderRunOptions): Promise<string>;
36
+ /** True if this provider has all the credentials/binaries it needs. */
37
+ available(): Promise<boolean>;
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAErE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAClF,uEAAuE;IACvE,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC/B"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Pluggable LLM provider interface for the agent.
3
+ *
4
+ * Providers are intentionally tiny — they take a system+user message pair
5
+ * and return a string response. Streaming and tool-use orchestration are
6
+ * intentionally out of scope at this layer; the answer-loop owns that
7
+ * orchestration on top of the provider.
8
+ *
9
+ * Each provider is implementation-detail-free: it reads its config from
10
+ * env vars and an optional user-supplied object, and uses `fetch` so we
11
+ * stay zero-dep at the package level. Network-bound failures bubble out as
12
+ * thrown Errors with provider-prefixed messages.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/providers/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Skills loader — discover and parse `.dql/skills/*.skill.md` files.
3
+ *
4
+ * Each skill is a markdown file with YAML frontmatter:
5
+ *
6
+ * ---
7
+ * id: cxo-monthly-review
8
+ * user: alice@acme.com
9
+ * description: Alice's monthly board review
10
+ * preferred_metrics: [arr, nrr]
11
+ * vocabulary: { "ARR": "metric:arr" }
12
+ * ---
13
+ * Free-form prompt body...
14
+ *
15
+ * No external YAML dep — we ship a tiny parser that handles only flat
16
+ * key/value, list-of-strings, and one-level objects (good enough for skills).
17
+ */
18
+ export interface Skill {
19
+ id: string;
20
+ /** Optional user this skill is bound to. Empty = project-level skill. */
21
+ user?: string;
22
+ description?: string;
23
+ preferredMetrics: string[];
24
+ preferredBlocks: string[];
25
+ vocabulary: Record<string, string>;
26
+ /** Markdown body (everything after the closing `---`). */
27
+ body: string;
28
+ sourcePath: string;
29
+ }
30
+ export interface SkillLoadResult {
31
+ skills: Skill[];
32
+ errors: Array<{
33
+ path: string;
34
+ message: string;
35
+ }>;
36
+ }
37
+ /**
38
+ * Walk `<projectRoot>/.dql/skills/**` and return every parsed Skill.
39
+ * Misformed files are reported in `errors`; valid Skills still come back.
40
+ */
41
+ export declare function loadSkills(projectRoot: string): SkillLoadResult;
42
+ /** Public for tests. */
43
+ export declare function parseSkill(raw: string, path: string): Skill | null;
44
+ /**
45
+ * Compose Skills into a single system-prompt fragment for the agent.
46
+ * Filtered by user when a persona is active.
47
+ */
48
+ export declare function buildSkillsPrompt(skills: Skill[], userId: string | null): string;
49
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/skills/loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,MAAM,WAAW,KAAK;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CAiB/D;AAiBD,wBAAwB;AACxB,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAkBlE;AAiFD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAYhF"}
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Skills loader — discover and parse `.dql/skills/*.skill.md` files.
3
+ *
4
+ * Each skill is a markdown file with YAML frontmatter:
5
+ *
6
+ * ---
7
+ * id: cxo-monthly-review
8
+ * user: alice@acme.com
9
+ * description: Alice's monthly board review
10
+ * preferred_metrics: [arr, nrr]
11
+ * vocabulary: { "ARR": "metric:arr" }
12
+ * ---
13
+ * Free-form prompt body...
14
+ *
15
+ * No external YAML dep — we ship a tiny parser that handles only flat
16
+ * key/value, list-of-strings, and one-level objects (good enough for skills).
17
+ */
18
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
19
+ import { join, basename } from 'node:path';
20
+ /**
21
+ * Walk `<projectRoot>/.dql/skills/**` and return every parsed Skill.
22
+ * Misformed files are reported in `errors`; valid Skills still come back.
23
+ */
24
+ export function loadSkills(projectRoot) {
25
+ const skillsDir = join(projectRoot, '.dql', 'skills');
26
+ if (!existsSync(skillsDir))
27
+ return { skills: [], errors: [] };
28
+ const skills = [];
29
+ const errors = [];
30
+ const files = walkMd(skillsDir);
31
+ for (const f of files) {
32
+ try {
33
+ const raw = readFileSync(f, 'utf-8');
34
+ const skill = parseSkill(raw, f);
35
+ if (skill)
36
+ skills.push(skill);
37
+ }
38
+ catch (err) {
39
+ errors.push({ path: f, message: err.message });
40
+ }
41
+ }
42
+ return { skills, errors };
43
+ }
44
+ function walkMd(dir) {
45
+ const out = [];
46
+ if (!existsSync(dir))
47
+ return out;
48
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
49
+ const p = join(dir, entry.name);
50
+ if (entry.isDirectory()) {
51
+ if (entry.name.startsWith('.'))
52
+ continue;
53
+ out.push(...walkMd(p));
54
+ }
55
+ else if (entry.isFile() && (entry.name.endsWith('.skill.md') || entry.name.endsWith('.md'))) {
56
+ if (statSync(p).size <= 1024 * 256)
57
+ out.push(p);
58
+ }
59
+ }
60
+ return out;
61
+ }
62
+ /** Public for tests. */
63
+ export function parseSkill(raw, path) {
64
+ const m = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/);
65
+ if (!m)
66
+ return null;
67
+ const front = m[1];
68
+ const body = m[2].trim();
69
+ const meta = parseMiniYaml(front);
70
+ const id = pickString(meta.id) ?? basename(path).replace(/\.skill\.md$|\.md$/, '');
71
+ return {
72
+ id,
73
+ user: pickString(meta.user),
74
+ description: pickString(meta.description),
75
+ preferredMetrics: pickStringArray(meta.preferred_metrics),
76
+ preferredBlocks: pickStringArray(meta.preferred_blocks),
77
+ vocabulary: pickStringMap(meta.vocabulary),
78
+ body,
79
+ sourcePath: path,
80
+ };
81
+ }
82
+ function pickString(v) {
83
+ return typeof v === 'string' ? v : undefined;
84
+ }
85
+ function pickStringArray(v) {
86
+ return Array.isArray(v) && v.every((x) => typeof x === 'string') ? v : [];
87
+ }
88
+ function pickStringMap(v) {
89
+ if (!v || typeof v !== 'object' || Array.isArray(v))
90
+ return {};
91
+ const out = {};
92
+ for (const [k, val] of Object.entries(v)) {
93
+ if (typeof val === 'string')
94
+ out[k] = val;
95
+ }
96
+ return out;
97
+ }
98
+ /**
99
+ * Tiny YAML parser tailored to skill frontmatter.
100
+ *
101
+ * Supports:
102
+ * key: scalar
103
+ * key: [item1, item2]
104
+ * key:
105
+ * subkey: value
106
+ *
107
+ * Not a real YAML implementation. If a skill needs richer YAML, point users
108
+ * at js-yaml manually and we'll widen the surface.
109
+ */
110
+ function parseMiniYaml(text) {
111
+ const lines = text.split(/\r?\n/);
112
+ const out = {};
113
+ let inObject = null;
114
+ for (const line of lines) {
115
+ if (!line.trim() || line.trim().startsWith('#'))
116
+ continue;
117
+ if (inObject) {
118
+ // Match either a quoted key ("key with spaces": value) or a bare key.
119
+ const subMatch = line.match(/^\s+("([^"]+)"|'([^']+)'|([a-zA-Z0-9_.-]+))\s*:\s*(.+)$/);
120
+ if (subMatch && line.startsWith(' ')) {
121
+ const k = subMatch[2] ?? subMatch[3] ?? subMatch[4];
122
+ const v = stripQuotes(subMatch[5].trim());
123
+ if (k)
124
+ inObject.obj[k] = v;
125
+ continue;
126
+ }
127
+ out[inObject.key] = inObject.obj;
128
+ inObject = null;
129
+ }
130
+ const top = line.match(/^([a-zA-Z0-9_-]+)\s*:\s*(.*)$/);
131
+ if (!top)
132
+ continue;
133
+ const key = top[1];
134
+ const value = top[2].trim();
135
+ if (!value) {
136
+ inObject = { key, obj: {} };
137
+ continue;
138
+ }
139
+ if (value.startsWith('[') && value.endsWith(']')) {
140
+ out[key] = value
141
+ .slice(1, -1)
142
+ .split(',')
143
+ .map((s) => stripQuotes(s.trim()))
144
+ .filter(Boolean);
145
+ continue;
146
+ }
147
+ out[key] = stripQuotes(value);
148
+ }
149
+ if (inObject)
150
+ out[inObject.key] = inObject.obj;
151
+ return out;
152
+ }
153
+ function stripQuotes(s) {
154
+ if ((s.startsWith('"') && s.endsWith('"')) || (s.startsWith("'") && s.endsWith("'"))) {
155
+ return s.slice(1, -1);
156
+ }
157
+ return s;
158
+ }
159
+ /**
160
+ * Compose Skills into a single system-prompt fragment for the agent.
161
+ * Filtered by user when a persona is active.
162
+ */
163
+ export function buildSkillsPrompt(skills, userId) {
164
+ const relevant = skills.filter((s) => !s.user || s.user === userId);
165
+ if (relevant.length === 0)
166
+ return '';
167
+ const sections = relevant.map((s) => {
168
+ const header = s.description ? `${s.id} — ${s.description}` : s.id;
169
+ const metrics = s.preferredMetrics.length > 0 ? `\nPreferred metrics: ${s.preferredMetrics.join(', ')}` : '';
170
+ const vocab = Object.keys(s.vocabulary).length > 0
171
+ ? `\nVocabulary: ${Object.entries(s.vocabulary).map(([k, v]) => `"${k}" → ${v}`).join(', ')}`
172
+ : '';
173
+ return `### Skill: ${header}${metrics}${vocab}\n\n${s.body}`;
174
+ });
175
+ return `## Active Skills\n\n${sections.join('\n\n')}\n`;
176
+ }
177
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/skills/loader.ts"],"names":[],"mappings":"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"}