@kaleidorg/mind 0.0.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.
- package/dist/engine.d.ts +61 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +99 -0
- package/dist/engine.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +74 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +63 -0
- package/dist/logger.js.map +1 -0
- package/dist/providers/qvac.d.ts +89 -0
- package/dist/providers/qvac.d.ts.map +1 -0
- package/dist/providers/qvac.js +150 -0
- package/dist/providers/qvac.js.map +1 -0
- package/dist/providers/types.d.ts +44 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +13 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/tools/in-process.d.ts +27 -0
- package/dist/tools/in-process.d.ts.map +1 -0
- package/dist/tools/in-process.js +34 -0
- package/dist/tools/in-process.js.map +1 -0
- package/dist/tools/mcp.d.ts +52 -0
- package/dist/tools/mcp.d.ts.map +1 -0
- package/dist/tools/mcp.js +81 -0
- package/dist/tools/mcp.js.map +1 -0
- package/dist/tools/registry.d.ts +23 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +49 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/source.d.ts +25 -0
- package/dist/tools/source.d.ts.map +1 -0
- package/dist/tools/source.js +15 -0
- package/dist/tools/source.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +46 -0
- package/src/engine.ts +141 -0
- package/src/index.ts +31 -0
- package/src/logger.ts +127 -0
- package/src/providers/types.ts +47 -0
- package/src/tools/in-process.ts +49 -0
- package/src/tools/mcp.ts +112 -0
- package/src/tools/registry.ts +56 -0
- package/src/tools/source.ts +26 -0
- package/src/types.ts +46 -0
package/dist/engine.d.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine — the agentic loop, provider- and tool-source-agnostic.
|
|
3
|
+
*
|
|
4
|
+
* This is the shared "brain" logic, lifted out of rate's QVACService so the
|
|
5
|
+
* mobile app, the desktop app and the agent all run the SAME loop:
|
|
6
|
+
*
|
|
7
|
+
* reason → (tool calls?) → execute / confirm → feed results back → repeat
|
|
8
|
+
* → natural-language answer.
|
|
9
|
+
*
|
|
10
|
+
* Follows the QVAC multi-turn pattern: push the raw assistant frame plus
|
|
11
|
+
* `{role:'tool'}` results into history each round, loop until the model stops
|
|
12
|
+
* calling tools. Money tools pause for an `onConfirm` gate; their handlers run
|
|
13
|
+
* wherever the ToolSource lives (on the phone for the wallet), even when
|
|
14
|
+
* inference is delegated to a remote provider.
|
|
15
|
+
*/
|
|
16
|
+
import type { ConfirmDecision, Message, ToolResult } from './types.js';
|
|
17
|
+
import type { LLMProvider } from './providers/types.js';
|
|
18
|
+
import type { ToolRegistry } from './tools/registry.js';
|
|
19
|
+
export interface EngineOptions {
|
|
20
|
+
provider: LLMProvider;
|
|
21
|
+
tools: ToolRegistry;
|
|
22
|
+
/** Prepended as a system message when the caller didn't supply one. */
|
|
23
|
+
defaultSystem?: string;
|
|
24
|
+
/** Max reasoning↔tool rounds before forcing a stop. Default 5. */
|
|
25
|
+
defaultMaxTurns?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface AgenticOptions {
|
|
28
|
+
maxTurns?: number;
|
|
29
|
+
/** Visible content tokens as they stream, tagged with the current turn. */
|
|
30
|
+
onToken?: (token: string, turn: number) => void;
|
|
31
|
+
/** The live requestId for the current turn (so a stop button can cancel it). */
|
|
32
|
+
onStart?: (requestId: string, turn: number) => void;
|
|
33
|
+
/** Fired when the model requests a tool, before it executes. */
|
|
34
|
+
onToolCall?: (call: {
|
|
35
|
+
name: string;
|
|
36
|
+
arguments: Record<string, unknown>;
|
|
37
|
+
}, turn: number) => void;
|
|
38
|
+
/** Human-in-the-loop gate for tools flagged requiresConfirmation. */
|
|
39
|
+
onConfirm?: (call: {
|
|
40
|
+
name: string;
|
|
41
|
+
arguments: Record<string, unknown>;
|
|
42
|
+
}) => Promise<ConfirmDecision>;
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
}
|
|
45
|
+
export interface AgenticResult {
|
|
46
|
+
text: string;
|
|
47
|
+
turns: number;
|
|
48
|
+
toolCalls: ToolResult[];
|
|
49
|
+
requestId?: string;
|
|
50
|
+
}
|
|
51
|
+
export declare class Engine {
|
|
52
|
+
private readonly provider;
|
|
53
|
+
private readonly registry;
|
|
54
|
+
private readonly defaultSystem?;
|
|
55
|
+
private readonly defaultMaxTurns;
|
|
56
|
+
constructor(opts: EngineOptions);
|
|
57
|
+
runAgentic(messages: Message[], opts?: AgenticOptions): Promise<AgenticResult>;
|
|
58
|
+
cancel(requestId: string): Promise<void>;
|
|
59
|
+
private safeExecute;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,YAAY,CAAC;IACpB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,gFAAgF;IAChF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,gEAAgE;IAChE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChG,qEAAqE;IACrE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACrG,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAc;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,IAAI,EAAE,aAAa;IAOzB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,aAAa,CAAC;IAmElF,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAIhC,WAAW;CAO1B"}
|
package/dist/engine.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine — the agentic loop, provider- and tool-source-agnostic.
|
|
3
|
+
*
|
|
4
|
+
* This is the shared "brain" logic, lifted out of rate's QVACService so the
|
|
5
|
+
* mobile app, the desktop app and the agent all run the SAME loop:
|
|
6
|
+
*
|
|
7
|
+
* reason → (tool calls?) → execute / confirm → feed results back → repeat
|
|
8
|
+
* → natural-language answer.
|
|
9
|
+
*
|
|
10
|
+
* Follows the QVAC multi-turn pattern: push the raw assistant frame plus
|
|
11
|
+
* `{role:'tool'}` results into history each round, loop until the model stops
|
|
12
|
+
* calling tools. Money tools pause for an `onConfirm` gate; their handlers run
|
|
13
|
+
* wherever the ToolSource lives (on the phone for the wallet), even when
|
|
14
|
+
* inference is delegated to a remote provider.
|
|
15
|
+
*/
|
|
16
|
+
export class Engine {
|
|
17
|
+
provider;
|
|
18
|
+
registry;
|
|
19
|
+
defaultSystem;
|
|
20
|
+
defaultMaxTurns;
|
|
21
|
+
constructor(opts) {
|
|
22
|
+
this.provider = opts.provider;
|
|
23
|
+
this.registry = opts.tools;
|
|
24
|
+
this.defaultSystem = opts.defaultSystem;
|
|
25
|
+
this.defaultMaxTurns = opts.defaultMaxTurns ?? 5;
|
|
26
|
+
}
|
|
27
|
+
async runAgentic(messages, opts = {}) {
|
|
28
|
+
const maxTurns = opts.maxTurns ?? this.defaultMaxTurns;
|
|
29
|
+
const hasSystem = messages.some((m) => m.role === 'system');
|
|
30
|
+
const system = hasSystem ? undefined : this.defaultSystem;
|
|
31
|
+
const history = [...messages];
|
|
32
|
+
const allTools = await this.registry.listTools();
|
|
33
|
+
const executed = [];
|
|
34
|
+
let lastRequestId;
|
|
35
|
+
let finalText = '';
|
|
36
|
+
let turns = 0;
|
|
37
|
+
for (let turn = 1; turn <= maxTurns; turn++) {
|
|
38
|
+
turns = turn;
|
|
39
|
+
if (opts.signal?.aborted)
|
|
40
|
+
break;
|
|
41
|
+
const out = await this.provider.runTurn({
|
|
42
|
+
messages: history,
|
|
43
|
+
tools: allTools,
|
|
44
|
+
system,
|
|
45
|
+
onToken: opts.onToken ? (t) => opts.onToken(t, turn) : undefined,
|
|
46
|
+
signal: opts.signal,
|
|
47
|
+
});
|
|
48
|
+
lastRequestId = out.requestId;
|
|
49
|
+
if (out.requestId)
|
|
50
|
+
opts.onStart?.(out.requestId, turn);
|
|
51
|
+
finalText = (out.text || '').trim();
|
|
52
|
+
// No tool calls ⇒ the model produced its final answer.
|
|
53
|
+
if (!out.toolCalls || out.toolCalls.length === 0)
|
|
54
|
+
break;
|
|
55
|
+
// Anchor the next turn with the raw assistant frame.
|
|
56
|
+
history.push({ role: 'assistant', content: out.rawContent || finalText });
|
|
57
|
+
for (const call of out.toolCalls) {
|
|
58
|
+
opts.onToolCall?.({ name: call.name, arguments: call.arguments }, turn);
|
|
59
|
+
const def = await this.registry.getDef(call.name);
|
|
60
|
+
let result;
|
|
61
|
+
if (def?.requiresConfirmation) {
|
|
62
|
+
const decision = opts.onConfirm
|
|
63
|
+
? await opts.onConfirm({ name: call.name, arguments: call.arguments })
|
|
64
|
+
: { approved: false, reason: 'no confirmation handler available' };
|
|
65
|
+
if (decision.approved) {
|
|
66
|
+
result = await this.safeExecute(call.name, call.arguments);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
result = { declined: true, reason: decision.reason ?? 'user declined' };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
result = await this.safeExecute(call.name, call.arguments);
|
|
74
|
+
}
|
|
75
|
+
executed.push({ name: call.name, arguments: call.arguments, result });
|
|
76
|
+
history.push({
|
|
77
|
+
role: 'tool',
|
|
78
|
+
content: typeof result === 'string' ? result : JSON.stringify(result),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (turn === maxTurns && !finalText) {
|
|
82
|
+
finalText = 'I had to stop after several steps — please try a more specific request.';
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { text: finalText, turns, toolCalls: executed, requestId: lastRequestId };
|
|
86
|
+
}
|
|
87
|
+
async cancel(requestId) {
|
|
88
|
+
await this.provider.cancel?.(requestId);
|
|
89
|
+
}
|
|
90
|
+
async safeExecute(name, args) {
|
|
91
|
+
try {
|
|
92
|
+
return await this.registry.execute(name, args);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kaleido/mind — shared local-AI reasoning engine for KaleidoSwap.
|
|
3
|
+
*
|
|
4
|
+
* Pure TypeScript, zero runtime dependencies. Hosts inject:
|
|
5
|
+
* - an LLMProvider (wrapping @qvac/sdk, Anthropic, …)
|
|
6
|
+
* - one or more ToolSources (in-process wallet tools, MCP servers, …)
|
|
7
|
+
*
|
|
8
|
+
* and get the shared agentic loop, identical on mobile / desktop / agent.
|
|
9
|
+
*/
|
|
10
|
+
export type { Role, Message, ToolDef, ToolCall, ToolResult, ConfirmDecision, } from './types.js';
|
|
11
|
+
export type { LLMProvider, TurnInput, TurnOutput } from './providers/types.js';
|
|
12
|
+
export type { ToolSource } from './tools/source.js';
|
|
13
|
+
export { InProcessToolSource } from './tools/in-process.js';
|
|
14
|
+
export type { InProcessTool } from './tools/in-process.js';
|
|
15
|
+
export { ToolRegistry } from './tools/registry.js';
|
|
16
|
+
export { Engine } from './engine.js';
|
|
17
|
+
export type { EngineOptions, AgenticOptions, AgenticResult } from './engine.js';
|
|
18
|
+
export { TurnLogger, defaultMask } from './logger.js';
|
|
19
|
+
export type { TurnLog, Device, LoggerIO, LoggerOptions } from './logger.js';
|
|
20
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EACV,IAAI,EACJ,OAAO,EACP,OAAO,EACP,QAAQ,EACR,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE/E,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEhF,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kaleido/mind — shared local-AI reasoning engine for KaleidoSwap.
|
|
3
|
+
*
|
|
4
|
+
* Pure TypeScript, zero runtime dependencies. Hosts inject:
|
|
5
|
+
* - an LLMProvider (wrapping @qvac/sdk, Anthropic, …)
|
|
6
|
+
* - one or more ToolSources (in-process wallet tools, MCP servers, …)
|
|
7
|
+
*
|
|
8
|
+
* and get the shared agentic loop, identical on mobile / desktop / agent.
|
|
9
|
+
*/
|
|
10
|
+
export { InProcessToolSource } from './tools/in-process.js';
|
|
11
|
+
export { ToolRegistry } from './tools/registry.js';
|
|
12
|
+
export { Engine } from './engine.js';
|
|
13
|
+
export { TurnLogger, defaultMask } from './logger.js';
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAcH,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured turn logger — JSONL output, designed for future fine-tuning
|
|
3
|
+
* datasets. Format is compatible with Salesforce/APIGen-MT-5k so KaleidoMind
|
|
4
|
+
* records can be concatenated with public data and fed to SFT pipelines.
|
|
5
|
+
*
|
|
6
|
+
* Privacy posture: amounts/addresses/contacts are HASHED at log time.
|
|
7
|
+
* Raw values are kept in a separate local store and only re-attached at
|
|
8
|
+
* export with explicit --include-pii.
|
|
9
|
+
*/
|
|
10
|
+
import type { Message, ToolCall, ToolResult } from './types.js';
|
|
11
|
+
export type Device = 'rate-ios' | 'rate-android' | 'kaleido-agent' | 'rate-extension' | 'kaleido-cli' | 'playground';
|
|
12
|
+
export interface TurnLog {
|
|
13
|
+
id: string;
|
|
14
|
+
ts: string;
|
|
15
|
+
session_id: string;
|
|
16
|
+
device: Device;
|
|
17
|
+
model: {
|
|
18
|
+
provider: string;
|
|
19
|
+
name: string;
|
|
20
|
+
version?: string;
|
|
21
|
+
};
|
|
22
|
+
/** Hash-based identifier for the system prompt — same hash = same prompt. */
|
|
23
|
+
system_hash: string;
|
|
24
|
+
/** Names + schema hashes only, never raw schemas with semantic data. */
|
|
25
|
+
tools: {
|
|
26
|
+
name: string;
|
|
27
|
+
schema_hash: string;
|
|
28
|
+
}[];
|
|
29
|
+
messages: Message[];
|
|
30
|
+
decision: {
|
|
31
|
+
tool_calls: ToolCall[];
|
|
32
|
+
final_text: string | null;
|
|
33
|
+
reasoning_tokens?: number;
|
|
34
|
+
};
|
|
35
|
+
results: ToolResult[];
|
|
36
|
+
feedback?: {
|
|
37
|
+
thumbs?: 'up' | 'down';
|
|
38
|
+
edited_args?: Record<string, unknown>;
|
|
39
|
+
retry_count?: number;
|
|
40
|
+
};
|
|
41
|
+
latency_ms: {
|
|
42
|
+
transcribe?: number;
|
|
43
|
+
reason: number;
|
|
44
|
+
tools?: number;
|
|
45
|
+
total: number;
|
|
46
|
+
};
|
|
47
|
+
meta?: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
export interface LoggerOptions {
|
|
50
|
+
/** Absolute path where YYYY-MM-DD/session-<id>.jsonl files are written. */
|
|
51
|
+
dir: string;
|
|
52
|
+
device: Device;
|
|
53
|
+
/** Pluggable IO so the same logger works in Node + RN + tests. */
|
|
54
|
+
io: LoggerIO;
|
|
55
|
+
/** PII masker — defaults to hashing common fields. */
|
|
56
|
+
mask?: (log: TurnLog) => TurnLog;
|
|
57
|
+
}
|
|
58
|
+
export interface LoggerIO {
|
|
59
|
+
ensureDir(path: string): Promise<void>;
|
|
60
|
+
appendLine(filePath: string, line: string): Promise<void>;
|
|
61
|
+
hash(value: unknown): string;
|
|
62
|
+
now(): Date;
|
|
63
|
+
}
|
|
64
|
+
export declare class TurnLogger {
|
|
65
|
+
private readonly opts;
|
|
66
|
+
constructor(opts: LoggerOptions);
|
|
67
|
+
log(input: Omit<TurnLog, 'id' | 'ts' | 'device'>): Promise<void>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Default masking — hashes amounts, addresses, invoices, contact names.
|
|
71
|
+
* Tools without these fields pass through unchanged.
|
|
72
|
+
*/
|
|
73
|
+
export declare function defaultMask(io: LoggerIO): (log: TurnLog) => TurnLog;
|
|
74
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,MAAM,MAAM,GACd,UAAU,GACV,cAAc,GACd,eAAe,GACf,gBAAgB,GAChB,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC/C,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,QAAQ,EAAE;QACR,UAAU,EAAE,QAAQ,EAAE,CAAC;QACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtC,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,UAAU,EAAE;QACV,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IACF,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,EAAE,EAAE,QAAQ,CAAC;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,GAAG,IAAI,IAAI,CAAC;CACb;AAED,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,IAAI;gBAAJ,IAAI,EAAE,aAAa;IAE1C,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,IAAI,GAAG,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAcvE;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CA+BnE"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured turn logger — JSONL output, designed for future fine-tuning
|
|
3
|
+
* datasets. Format is compatible with Salesforce/APIGen-MT-5k so KaleidoMind
|
|
4
|
+
* records can be concatenated with public data and fed to SFT pipelines.
|
|
5
|
+
*
|
|
6
|
+
* Privacy posture: amounts/addresses/contacts are HASHED at log time.
|
|
7
|
+
* Raw values are kept in a separate local store and only re-attached at
|
|
8
|
+
* export with explicit --include-pii.
|
|
9
|
+
*/
|
|
10
|
+
export class TurnLogger {
|
|
11
|
+
opts;
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
this.opts = opts;
|
|
14
|
+
}
|
|
15
|
+
async log(input) {
|
|
16
|
+
const ts = this.opts.io.now().toISOString();
|
|
17
|
+
const id = `${input.session_id}-${this.opts.io.hash({ ts, n: Math.random() }).slice(0, 8)}`;
|
|
18
|
+
let entry = { ...input, id, ts, device: this.opts.device };
|
|
19
|
+
if (this.opts.mask)
|
|
20
|
+
entry = this.opts.mask(entry);
|
|
21
|
+
const day = ts.slice(0, 10);
|
|
22
|
+
const dir = `${this.opts.dir}/${day}`;
|
|
23
|
+
await this.opts.io.ensureDir(dir);
|
|
24
|
+
await this.opts.io.appendLine(`${dir}/session-${input.session_id}.jsonl`, JSON.stringify(entry));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Default masking — hashes amounts, addresses, invoices, contact names.
|
|
29
|
+
* Tools without these fields pass through unchanged.
|
|
30
|
+
*/
|
|
31
|
+
export function defaultMask(io) {
|
|
32
|
+
const FIELDS_TO_HASH = new Set([
|
|
33
|
+
'amount', 'amount_msat', 'amount_sat',
|
|
34
|
+
'address', 'invoice', 'bolt11', 'pubkey', 'node_id',
|
|
35
|
+
'contact', 'contact_name', 'recipient',
|
|
36
|
+
]);
|
|
37
|
+
const walk = (v) => {
|
|
38
|
+
if (v === null || v === undefined)
|
|
39
|
+
return v;
|
|
40
|
+
if (Array.isArray(v))
|
|
41
|
+
return v.map(walk);
|
|
42
|
+
if (typeof v === 'object') {
|
|
43
|
+
const out = {};
|
|
44
|
+
for (const [k, val] of Object.entries(v)) {
|
|
45
|
+
out[k] = FIELDS_TO_HASH.has(k) ? `h:${io.hash(val).slice(0, 8)}` : walk(val);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
return v;
|
|
50
|
+
};
|
|
51
|
+
return (log) => ({
|
|
52
|
+
...log,
|
|
53
|
+
decision: {
|
|
54
|
+
...log.decision,
|
|
55
|
+
tool_calls: log.decision.tool_calls.map((c) => ({
|
|
56
|
+
...c,
|
|
57
|
+
arguments: walk(c.arguments),
|
|
58
|
+
})),
|
|
59
|
+
},
|
|
60
|
+
results: log.results.map((r) => ({ ...r, result: walk(r.result) })),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QVAC provider — primary, on-device.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the QVAC SDK's llamacpp-completion plugin. The actual binding
|
|
5
|
+
* differs slightly per host (RN vs Node vs browser worker), so the heavy
|
|
6
|
+
* lifting is delegated to a `QvacBinding` injected by the adapter packages.
|
|
7
|
+
*
|
|
8
|
+
* Node (kaleido-agent): binding = await import('@qvac/sdk/node')
|
|
9
|
+
* React Native (rate): binding from @kaleido/mind-rn → wraps QVACService
|
|
10
|
+
* Browser (rate-extension): binding from @kaleido/mind-browser → talks to worker
|
|
11
|
+
*/
|
|
12
|
+
import type { LLMProvider, ProviderConfig, ProviderRunOptions, ProviderRunResult } from './types.js';
|
|
13
|
+
import type { Message, ToolDef, TurnEvent } from '../types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Host-injected binding. Each adapter package supplies its own.
|
|
16
|
+
* We keep this duck-typed (not an abstract class) so adapters
|
|
17
|
+
* don't have to extend anything heavy.
|
|
18
|
+
*/
|
|
19
|
+
export interface QvacBinding {
|
|
20
|
+
load(modelPath: string, opts: {
|
|
21
|
+
contextSize: number;
|
|
22
|
+
backend?: 'metal' | 'cpu' | 'auto';
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
unload(): Promise<void>;
|
|
25
|
+
isReady(): boolean;
|
|
26
|
+
/** Synchronous completion. The adapter handles the QVAC SDK plumbing. */
|
|
27
|
+
complete(prompt: string, opts: {
|
|
28
|
+
maxTokens?: number;
|
|
29
|
+
temperature?: number;
|
|
30
|
+
topP?: number;
|
|
31
|
+
stop?: string[];
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
text: string;
|
|
35
|
+
usage?: {
|
|
36
|
+
prompt: number;
|
|
37
|
+
completion: number;
|
|
38
|
+
};
|
|
39
|
+
}>;
|
|
40
|
+
/** Streaming completion — yields token strings. */
|
|
41
|
+
stream(prompt: string, opts: {
|
|
42
|
+
maxTokens?: number;
|
|
43
|
+
temperature?: number;
|
|
44
|
+
topP?: number;
|
|
45
|
+
stop?: string[];
|
|
46
|
+
signal?: AbortSignal;
|
|
47
|
+
}): AsyncIterable<string>;
|
|
48
|
+
}
|
|
49
|
+
export interface QvacProviderOpts extends ProviderConfig {
|
|
50
|
+
binding: QvacBinding;
|
|
51
|
+
/**
|
|
52
|
+
* Chat template family. Auto-detect from model name when omitted.
|
|
53
|
+
* 'qwen3' — Qwen 3 family (thinking-mode aware)
|
|
54
|
+
* 'hermes' — Hermes 3/4 family
|
|
55
|
+
* 'llama3' — Llama 3.x Instruct
|
|
56
|
+
* 'chatml' — generic ChatML
|
|
57
|
+
*/
|
|
58
|
+
template?: 'qwen3' | 'hermes' | 'llama3' | 'chatml';
|
|
59
|
+
backend?: 'metal' | 'cpu' | 'auto';
|
|
60
|
+
}
|
|
61
|
+
export declare class QvacProvider implements LLMProvider {
|
|
62
|
+
readonly name = "qvac";
|
|
63
|
+
readonly modelId: string;
|
|
64
|
+
private readonly binding;
|
|
65
|
+
private readonly contextSize;
|
|
66
|
+
private readonly temperature;
|
|
67
|
+
private readonly topP;
|
|
68
|
+
private readonly template;
|
|
69
|
+
private readonly backend;
|
|
70
|
+
constructor(opts: QvacProviderOpts);
|
|
71
|
+
load(): Promise<void>;
|
|
72
|
+
unload(): Promise<void>;
|
|
73
|
+
isReady(): boolean;
|
|
74
|
+
run(messages: Message[], tools: ToolDef[], opts?: ProviderRunOptions): Promise<ProviderRunResult>;
|
|
75
|
+
stream(messages: Message[], tools: ToolDef[], opts?: ProviderRunOptions): AsyncIterable<TurnEvent>;
|
|
76
|
+
private detectTemplate;
|
|
77
|
+
/**
|
|
78
|
+
* Render messages + tools into the model's chat template.
|
|
79
|
+
* TODO: full implementations per family. This stub uses a minimal
|
|
80
|
+
* tool-aware ChatML rendering that works for Qwen3 / Hermes / Llama 3.
|
|
81
|
+
*/
|
|
82
|
+
private formatPrompt;
|
|
83
|
+
/**
|
|
84
|
+
* Parse the model's text output into (text, tool_calls).
|
|
85
|
+
* Recognises <tool_call>{...}</tool_call> blocks.
|
|
86
|
+
*/
|
|
87
|
+
private parseCompletion;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=qvac.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qvac.d.ts","sourceRoot":"","sources":["../../src/providers/qvac.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,OAAO,EAAY,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEzE;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1G,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,OAAO,IAAI,OAAO,CAAC;IACnB,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;QAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC,CAAC;IAC9E,mDAAmD;IACnD,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;QAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,OAAO,EAAE,WAAW,CAAC;IACrB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACpD,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;CACpC;AAED,qBAAa,YAAa,YAAW,WAAW;IAC9C,SAAgB,IAAI,UAAU;IAC9B,SAAgB,OAAO,EAAE,MAAM,CAAC;IAEhC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA4C;IACrE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2C;gBAEvD,IAAI,EAAE,gBAAgB;IAU5B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQrB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7B,OAAO,IAAI,OAAO;IAIZ,GAAG,CACP,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,OAAO,EAAE,EAChB,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,iBAAiB,CAAC;IAYtB,MAAM,CACX,QAAQ,EAAE,OAAO,EAAE,EACnB,KAAK,EAAE,OAAO,EAAE,EAChB,IAAI,GAAE,kBAAuB,GAC5B,aAAa,CAAC,SAAS,CAAC;IAoB3B,OAAO,CAAC,cAAc;IAQtB;;;;OAIG;IACH,OAAO,CAAC,YAAY;IA+BpB;;;OAGG;IACH,OAAO,CAAC,eAAe;CAwBxB"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QVAC provider — primary, on-device.
|
|
3
|
+
*
|
|
4
|
+
* Wraps the QVAC SDK's llamacpp-completion plugin. The actual binding
|
|
5
|
+
* differs slightly per host (RN vs Node vs browser worker), so the heavy
|
|
6
|
+
* lifting is delegated to a `QvacBinding` injected by the adapter packages.
|
|
7
|
+
*
|
|
8
|
+
* Node (kaleido-agent): binding = await import('@qvac/sdk/node')
|
|
9
|
+
* React Native (rate): binding from @kaleido/mind-rn → wraps QVACService
|
|
10
|
+
* Browser (rate-extension): binding from @kaleido/mind-browser → talks to worker
|
|
11
|
+
*/
|
|
12
|
+
export class QvacProvider {
|
|
13
|
+
name = 'qvac';
|
|
14
|
+
modelId;
|
|
15
|
+
binding;
|
|
16
|
+
contextSize;
|
|
17
|
+
temperature;
|
|
18
|
+
topP;
|
|
19
|
+
template;
|
|
20
|
+
backend;
|
|
21
|
+
constructor(opts) {
|
|
22
|
+
this.modelId = opts.model;
|
|
23
|
+
this.binding = opts.binding;
|
|
24
|
+
this.contextSize = opts.contextSize ?? 32768;
|
|
25
|
+
this.temperature = opts.temperature ?? 0.2;
|
|
26
|
+
this.topP = opts.topP ?? 0.9;
|
|
27
|
+
this.template = opts.template ?? this.detectTemplate(opts.model);
|
|
28
|
+
this.backend = opts.backend ?? 'auto';
|
|
29
|
+
}
|
|
30
|
+
async load() {
|
|
31
|
+
if (this.binding.isReady())
|
|
32
|
+
return;
|
|
33
|
+
await this.binding.load(this.modelId, {
|
|
34
|
+
contextSize: this.contextSize,
|
|
35
|
+
backend: this.backend,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async unload() {
|
|
39
|
+
await this.binding.unload();
|
|
40
|
+
}
|
|
41
|
+
isReady() {
|
|
42
|
+
return this.binding.isReady();
|
|
43
|
+
}
|
|
44
|
+
async run(messages, tools, opts = {}) {
|
|
45
|
+
await this.load();
|
|
46
|
+
const prompt = this.formatPrompt(messages, tools, opts);
|
|
47
|
+
const { text, usage } = await this.binding.complete(prompt, {
|
|
48
|
+
temperature: this.temperature,
|
|
49
|
+
topP: this.topP,
|
|
50
|
+
stop: opts.stop,
|
|
51
|
+
signal: opts.signal,
|
|
52
|
+
});
|
|
53
|
+
return this.parseCompletion(text, usage);
|
|
54
|
+
}
|
|
55
|
+
async *stream(messages, tools, opts = {}) {
|
|
56
|
+
await this.load();
|
|
57
|
+
const prompt = this.formatPrompt(messages, tools, opts);
|
|
58
|
+
let buffer = '';
|
|
59
|
+
for await (const chunk of this.binding.stream(prompt, {
|
|
60
|
+
temperature: this.temperature,
|
|
61
|
+
topP: this.topP,
|
|
62
|
+
stop: opts.stop,
|
|
63
|
+
signal: opts.signal,
|
|
64
|
+
})) {
|
|
65
|
+
buffer += chunk;
|
|
66
|
+
yield { type: 'token', text: chunk };
|
|
67
|
+
}
|
|
68
|
+
const parsed = this.parseCompletion(buffer);
|
|
69
|
+
for (const call of parsed.tool_calls) {
|
|
70
|
+
yield { type: 'tool_call', call };
|
|
71
|
+
}
|
|
72
|
+
yield { type: 'done', final: parsed.text };
|
|
73
|
+
}
|
|
74
|
+
detectTemplate(model) {
|
|
75
|
+
const m = model.toLowerCase();
|
|
76
|
+
if (m.includes('qwen3') || m.includes('qwen-3'))
|
|
77
|
+
return 'qwen3';
|
|
78
|
+
if (m.includes('hermes'))
|
|
79
|
+
return 'hermes';
|
|
80
|
+
if (m.includes('llama-3') || m.includes('llama3'))
|
|
81
|
+
return 'llama3';
|
|
82
|
+
return 'chatml';
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Render messages + tools into the model's chat template.
|
|
86
|
+
* TODO: full implementations per family. This stub uses a minimal
|
|
87
|
+
* tool-aware ChatML rendering that works for Qwen3 / Hermes / Llama 3.
|
|
88
|
+
*/
|
|
89
|
+
formatPrompt(messages, tools, opts) {
|
|
90
|
+
const toolDescriptions = tools.length
|
|
91
|
+
? `\n\n<tools>\n${tools.map(t => JSON.stringify({
|
|
92
|
+
name: t.name,
|
|
93
|
+
description: t.description,
|
|
94
|
+
parameters: '<schema:' + t.name + '>',
|
|
95
|
+
})).join('\n')}\n</tools>\n\n` +
|
|
96
|
+
`When you need to call a tool, emit a single line of JSON wrapped in <tool_call></tool_call> tags. ` +
|
|
97
|
+
`Wait for the tool result before continuing.`
|
|
98
|
+
: '';
|
|
99
|
+
const sys = (opts.system ?? '') + toolDescriptions;
|
|
100
|
+
let prompt = sys ? `<|im_start|>system\n${sys}<|im_end|>\n` : '';
|
|
101
|
+
for (const m of messages) {
|
|
102
|
+
if (m.role === 'system')
|
|
103
|
+
continue;
|
|
104
|
+
prompt += `<|im_start|>${m.role}\n${m.content ?? ''}`;
|
|
105
|
+
if (m.tool_calls?.length) {
|
|
106
|
+
for (const c of m.tool_calls) {
|
|
107
|
+
prompt += `\n<tool_call>${JSON.stringify({ name: c.name, arguments: c.args })}</tool_call>`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
prompt += `<|im_end|>\n`;
|
|
111
|
+
}
|
|
112
|
+
prompt += `<|im_start|>assistant\n`;
|
|
113
|
+
if (this.template === 'qwen3' && !opts.thinking) {
|
|
114
|
+
prompt += `<think>\n</think>\n`;
|
|
115
|
+
}
|
|
116
|
+
return prompt;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Parse the model's text output into (text, tool_calls).
|
|
120
|
+
* Recognises <tool_call>{...}</tool_call> blocks.
|
|
121
|
+
*/
|
|
122
|
+
parseCompletion(text, usage) {
|
|
123
|
+
const tool_calls = [];
|
|
124
|
+
const callRegex = /<tool_call>\s*([\s\S]*?)\s*<\/tool_call>/g;
|
|
125
|
+
let match;
|
|
126
|
+
let i = 0;
|
|
127
|
+
while ((match = callRegex.exec(text)) !== null) {
|
|
128
|
+
const raw = match[1];
|
|
129
|
+
if (!raw)
|
|
130
|
+
continue;
|
|
131
|
+
try {
|
|
132
|
+
const parsed = JSON.parse(raw);
|
|
133
|
+
tool_calls.push({
|
|
134
|
+
id: `c-${i++}`,
|
|
135
|
+
name: parsed.name,
|
|
136
|
+
args: parsed.arguments ?? {},
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Ignore malformed — the engine's retry loop will reprompt.
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const cleaned = text.replace(callRegex, '').trim();
|
|
144
|
+
const result = { text: cleaned, tool_calls };
|
|
145
|
+
if (usage)
|
|
146
|
+
result.usage = usage;
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=qvac.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qvac.js","sourceRoot":"","sources":["../../src/providers/qvac.ts"],"names":[],"mappings":"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"}
|