funolio-agent 0.5.14 → 0.10.2
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/auto-organizer.d.ts +16 -0
- package/dist/auto-organizer.d.ts.map +1 -0
- package/dist/auto-organizer.js +235 -0
- package/dist/auto-organizer.js.map +1 -0
- package/dist/clerk-model.d.ts +101 -0
- package/dist/clerk-model.d.ts.map +1 -0
- package/dist/clerk-model.js +396 -0
- package/dist/clerk-model.js.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +38 -0
- package/dist/commands/start.js.map +1 -1
- package/dist/local-data.d.ts +528 -0
- package/dist/local-data.d.ts.map +1 -0
- package/dist/local-data.js +918 -0
- package/dist/local-data.js.map +1 -0
- package/dist/local-db.d.ts +26 -0
- package/dist/local-db.d.ts.map +1 -0
- package/dist/local-db.js +517 -0
- package/dist/local-db.js.map +1 -0
- package/dist/local-funnel.d.ts +20 -0
- package/dist/local-funnel.d.ts.map +1 -0
- package/dist/local-funnel.js +297 -0
- package/dist/local-funnel.js.map +1 -0
- package/dist/local-import-worker.d.ts +6 -0
- package/dist/local-import-worker.d.ts.map +1 -0
- package/dist/local-import-worker.js +370 -0
- package/dist/local-import-worker.js.map +1 -0
- package/dist/local-server.d.ts +7 -0
- package/dist/local-server.d.ts.map +1 -0
- package/dist/local-server.js +1340 -0
- package/dist/local-server.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +3 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/local-memory-server.d.ts +22 -0
- package/dist/mcp/local-memory-server.d.ts.map +1 -0
- package/dist/mcp/local-memory-server.js +284 -0
- package/dist/mcp/local-memory-server.js.map +1 -0
- package/dist/mcp/registry.d.ts.map +1 -1
- package/dist/mcp/registry.js +9 -0
- package/dist/mcp/registry.js.map +1 -1
- package/dist/message-loop.d.ts +10 -0
- package/dist/message-loop.d.ts.map +1 -1
- package/dist/message-loop.js +181 -30
- package/dist/message-loop.js.map +1 -1
- package/dist/mqtt-client.d.ts.map +1 -1
- package/dist/mqtt-client.js +40 -13
- package/dist/mqtt-client.js.map +1 -1
- package/dist/orchestration/guided-actions.d.ts +34 -0
- package/dist/orchestration/guided-actions.d.ts.map +1 -0
- package/dist/orchestration/guided-actions.js +115 -0
- package/dist/orchestration/guided-actions.js.map +1 -0
- package/dist/orchestration/status-parser.d.ts +27 -0
- package/dist/orchestration/status-parser.d.ts.map +1 -0
- package/dist/orchestration/status-parser.js +50 -0
- package/dist/orchestration/status-parser.js.map +1 -0
- package/dist/providers/claude-cli.d.ts.map +1 -1
- package/dist/providers/claude-cli.js +49 -23
- package/dist/providers/claude-cli.js.map +1 -1
- package/dist/providers/codex-cli.d.ts +13 -0
- package/dist/providers/codex-cli.d.ts.map +1 -0
- package/dist/providers/codex-cli.js +130 -0
- package/dist/providers/codex-cli.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +6 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +24 -3
- package/dist/providers/openai.js.map +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/search-local-memory.d.ts +9 -0
- package/dist/tools/search-local-memory.d.ts.map +1 -0
- package/dist/tools/search-local-memory.js +103 -0
- package/dist/tools/search-local-memory.js.map +1 -0
- package/dist/workflow-engine.d.ts +91 -0
- package/dist/workflow-engine.d.ts.map +1 -0
- package/dist/workflow-engine.js +429 -0
- package/dist/workflow-engine.js.map +1 -0
- package/package.json +9 -5
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface AutoOrganizeResult {
|
|
2
|
+
conversationId: string;
|
|
3
|
+
topicId: string | null;
|
|
4
|
+
topicTitle: string | null;
|
|
5
|
+
isNewTopic: boolean;
|
|
6
|
+
error?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Check if auto-organize is enabled.
|
|
10
|
+
*/
|
|
11
|
+
export declare function isAutoOrganizeEnabled(): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Organize a conversation into a broad topic.
|
|
14
|
+
*/
|
|
15
|
+
export declare function organizeConversation(conversationId: string): Promise<AutoOrganizeResult>;
|
|
16
|
+
//# sourceMappingURL=auto-organizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-organizer.d.ts","sourceRoot":"","sources":["../src/auto-organizer.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,OAAO,CAE/C;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2H9F"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.isAutoOrganizeEnabled = isAutoOrganizeEnabled;
|
|
40
|
+
exports.organizeConversation = organizeConversation;
|
|
41
|
+
/**
|
|
42
|
+
* Post-session auto-organization engine.
|
|
43
|
+
*
|
|
44
|
+
* After a session goes idle (no messages for N minutes), this module:
|
|
45
|
+
* 1. Classifies the session into an existing broad topic (or creates a new one)
|
|
46
|
+
* 2. Links the conversation to the topic via topic_segment
|
|
47
|
+
* 3. Updates the topic summary
|
|
48
|
+
*
|
|
49
|
+
* Design principle: topics are BROAD and GENERIC (~5-15 per project).
|
|
50
|
+
* Good: "Desktop App Creation", "Web Chat UI", "Database & Migrations"
|
|
51
|
+
* Bad: "Fix CLI Provider Bug", "Add Bot Colors"
|
|
52
|
+
*
|
|
53
|
+
* Uses the cheapest available LLM (clerk model or agent's own provider).
|
|
54
|
+
* Opt-in via `auto_organize` setting.
|
|
55
|
+
*/
|
|
56
|
+
const data = __importStar(require("./local-data"));
|
|
57
|
+
const index_1 = require("./providers/index");
|
|
58
|
+
const config_1 = require("./config");
|
|
59
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
60
|
+
/**
|
|
61
|
+
* Check if auto-organize is enabled.
|
|
62
|
+
*/
|
|
63
|
+
function isAutoOrganizeEnabled() {
|
|
64
|
+
return data.getSetting('auto_organize') === 'true';
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Organize a conversation into a broad topic.
|
|
68
|
+
*/
|
|
69
|
+
async function organizeConversation(conversationId) {
|
|
70
|
+
const result = {
|
|
71
|
+
conversationId,
|
|
72
|
+
topicId: null,
|
|
73
|
+
topicTitle: null,
|
|
74
|
+
isNewTopic: false,
|
|
75
|
+
};
|
|
76
|
+
try {
|
|
77
|
+
if (!isAutoOrganizeEnabled())
|
|
78
|
+
return result;
|
|
79
|
+
const conv = data.getConversation(conversationId);
|
|
80
|
+
if (!conv)
|
|
81
|
+
return result;
|
|
82
|
+
// Get first few messages for classification
|
|
83
|
+
const messages = data.getMessages(conversationId, { limit: 10 });
|
|
84
|
+
if (messages.length < 2)
|
|
85
|
+
return result;
|
|
86
|
+
const llm = getOrganizerLlm(conv.agent_id);
|
|
87
|
+
if (!llm) {
|
|
88
|
+
result.error = 'No LLM available for auto-organize';
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
91
|
+
// Get existing topics for matching
|
|
92
|
+
const existingTopics = data.listTopics({ projectId: conv.project_id ?? undefined, limit: 50 });
|
|
93
|
+
// Build transcript preview (first ~500 tokens worth)
|
|
94
|
+
const preview = messages.slice(0, 6)
|
|
95
|
+
.map(m => `${m.role}: ${m.content.slice(0, 200)}`)
|
|
96
|
+
.join('\n');
|
|
97
|
+
// Step 1: Classify the session
|
|
98
|
+
const topicList = existingTopics.length > 0
|
|
99
|
+
? existingTopics.map((t, i) => `${i + 1}. "${t.title}"`).join('\n')
|
|
100
|
+
: '(no existing topics)';
|
|
101
|
+
const classifyPrompt = `You are organizing a developer's conversations into broad topic folders.
|
|
102
|
+
|
|
103
|
+
Existing topics:
|
|
104
|
+
${topicList}
|
|
105
|
+
|
|
106
|
+
This session starts with:
|
|
107
|
+
"${preview.slice(0, 1500)}"
|
|
108
|
+
|
|
109
|
+
Which existing topic does this session belong to?
|
|
110
|
+
If none fit, suggest a new broad topic (2-5 words, like a folder name — e.g. "Desktop App Creation", not "Fix CLI Bug").
|
|
111
|
+
|
|
112
|
+
Return JSON only: {"topic_index": 1} or {"topic_index": null, "new_topic": "Topic Name"}`;
|
|
113
|
+
const resp = await llm.chat({
|
|
114
|
+
messages: [{ role: 'user', content: classifyPrompt }],
|
|
115
|
+
system: 'You classify conversations into broad topic folders. Return ONLY valid JSON, no explanation.',
|
|
116
|
+
});
|
|
117
|
+
if (!resp.content)
|
|
118
|
+
return result;
|
|
119
|
+
const parsed = parseJson(resp.content);
|
|
120
|
+
if (!parsed) {
|
|
121
|
+
result.error = 'Failed to parse LLM classification response';
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
let topic;
|
|
125
|
+
if (parsed.topic_index != null && parsed.topic_index >= 1 && parsed.topic_index <= existingTopics.length) {
|
|
126
|
+
// Match existing topic
|
|
127
|
+
topic = existingTopics[parsed.topic_index - 1];
|
|
128
|
+
result.isNewTopic = false;
|
|
129
|
+
}
|
|
130
|
+
else if (parsed.new_topic) {
|
|
131
|
+
// Create new topic
|
|
132
|
+
topic = data.createTopic({
|
|
133
|
+
title: parsed.new_topic.slice(0, 100),
|
|
134
|
+
projectId: conv.project_id ?? undefined,
|
|
135
|
+
isAuto: true,
|
|
136
|
+
});
|
|
137
|
+
result.isNewTopic = true;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
result.error = 'LLM returned invalid classification';
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
result.topicId = topic.id;
|
|
144
|
+
result.topicTitle = topic.title;
|
|
145
|
+
// Step 2: Link the whole conversation as a segment
|
|
146
|
+
const maxSeq = messages.length > 0 ? messages[messages.length - 1].seq : 1;
|
|
147
|
+
data.createTopicSegment({
|
|
148
|
+
topicId: topic.id,
|
|
149
|
+
conversationId,
|
|
150
|
+
startSeq: 1,
|
|
151
|
+
endSeq: maxSeq,
|
|
152
|
+
});
|
|
153
|
+
// Update topic activity + message count
|
|
154
|
+
data.updateTopic(topic.id, {
|
|
155
|
+
messageCount: (topic.message_count || 0) + conv.message_count,
|
|
156
|
+
lastActivityAt: new Date().toISOString().replace('T', ' ').replace('Z', ''),
|
|
157
|
+
});
|
|
158
|
+
// Step 3: Update topic summary (only if we have enough messages)
|
|
159
|
+
if (conv.message_count >= 4) {
|
|
160
|
+
try {
|
|
161
|
+
const summaryResp = await llm.chat({
|
|
162
|
+
messages: [{ role: 'user', content: `Write a 1-2 sentence summary of this developer topic: "${topic.title}". Latest session preview:\n${preview.slice(0, 800)}${topic.summary ? `\nPrevious summary: ${topic.summary}` : ''}` }],
|
|
163
|
+
system: 'You write concise topic summaries. Return ONLY the summary text.',
|
|
164
|
+
});
|
|
165
|
+
if (summaryResp.content) {
|
|
166
|
+
data.updateTopic(topic.id, { summary: summaryResp.content.trim().slice(0, 500) });
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch { /* best-effort */ }
|
|
170
|
+
}
|
|
171
|
+
console.log(chalk_1.default.gray(` [auto-organize] Conv ${conversationId.slice(0, 8)} → topic "${topic.title}" (${result.isNewTopic ? 'new' : 'existing'})`));
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
result.error = err.message;
|
|
175
|
+
console.error(chalk_1.default.red(` [auto-organize] Error: ${err.message}`));
|
|
176
|
+
}
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
function getOrganizerLlm(agentId) {
|
|
180
|
+
try {
|
|
181
|
+
// Try clerk model first (cheapest)
|
|
182
|
+
const clerkProvider = data.getSetting('clerk_provider');
|
|
183
|
+
const clerkModel = data.getSetting('clerk_model');
|
|
184
|
+
const clerkKey = data.getSetting('clerk_api_key');
|
|
185
|
+
if (clerkProvider && clerkModel && clerkKey) {
|
|
186
|
+
return (0, index_1.createProvider)(clerkProvider, { apiKey: clerkKey, model: clerkModel });
|
|
187
|
+
}
|
|
188
|
+
// Fall back to agent's provider
|
|
189
|
+
if (agentId) {
|
|
190
|
+
const profile = data.getAgentProfile(agentId);
|
|
191
|
+
if (profile?.api_key_enc) {
|
|
192
|
+
const model = cheapModel(profile.provider, profile.model);
|
|
193
|
+
return (0, index_1.createProvider)(profile.provider, { apiKey: profile.api_key_enc, model });
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Fall back to config
|
|
197
|
+
const config = (0, config_1.loadConfig)();
|
|
198
|
+
const prov = (0, config_1.getProvider)(config);
|
|
199
|
+
if (prov) {
|
|
200
|
+
const apiKey = prov.apiKey || prov.oauthToken;
|
|
201
|
+
if (apiKey) {
|
|
202
|
+
const model = cheapModel(prov.id, prov.defaultModel);
|
|
203
|
+
return (0, index_1.createProvider)(prov.id, { apiKey, model });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return null;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function cheapModel(provider, fallback) {
|
|
213
|
+
switch (provider) {
|
|
214
|
+
case 'anthropic': return 'claude-haiku-4-5-20251001';
|
|
215
|
+
case 'openai': return 'gpt-4o-mini';
|
|
216
|
+
case 'google': return 'gemini-2.0-flash';
|
|
217
|
+
default: return fallback;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function parseJson(content) {
|
|
221
|
+
try {
|
|
222
|
+
return JSON.parse(content);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
const match = content.match(/\{[\s\S]*\}/);
|
|
226
|
+
if (match) {
|
|
227
|
+
try {
|
|
228
|
+
return JSON.parse(match[0]);
|
|
229
|
+
}
|
|
230
|
+
catch { /* fall through */ }
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=auto-organizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-organizer.js","sourceRoot":"","sources":["../src/auto-organizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clerk Model — Local-First Orchestration Layer
|
|
3
|
+
*
|
|
4
|
+
* The clerk is a user-configured LLM (cheapest from their provider) that handles:
|
|
5
|
+
* 1. Task routing — decides which agent/model handles a prompt
|
|
6
|
+
* 2. Prompt building — retrieves relevant context within token budget
|
|
7
|
+
* 3. Token budgeting — calculates available tokens, selects relevant memory
|
|
8
|
+
* 4. Memory extraction — after conversation turns, extracts facts locally
|
|
9
|
+
*
|
|
10
|
+
* The user configures the clerk during setup: provider + model.
|
|
11
|
+
* It runs locally inside the agent, never on the server.
|
|
12
|
+
*/
|
|
13
|
+
import * as data from './local-data';
|
|
14
|
+
export interface ClerkModelConfig {
|
|
15
|
+
provider: string;
|
|
16
|
+
model: string;
|
|
17
|
+
apiKey: string;
|
|
18
|
+
/** Max tokens the clerk can use for context injection (default: 8000) */
|
|
19
|
+
maxContextTokens?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface BuiltPrompt {
|
|
22
|
+
systemPrompt: string;
|
|
23
|
+
contextTokensUsed: number;
|
|
24
|
+
injectedFacts: number;
|
|
25
|
+
injectedDecisions: number;
|
|
26
|
+
injectedSummaries: number;
|
|
27
|
+
/** Budget remaining for conversation history */
|
|
28
|
+
historyBudget: number;
|
|
29
|
+
}
|
|
30
|
+
export interface TaskRoute {
|
|
31
|
+
agentId: string;
|
|
32
|
+
agentName: string;
|
|
33
|
+
provider: string;
|
|
34
|
+
model: string;
|
|
35
|
+
reasoning: string;
|
|
36
|
+
}
|
|
37
|
+
export interface ExtractionResult {
|
|
38
|
+
facts: Array<{
|
|
39
|
+
factType: string;
|
|
40
|
+
content: string;
|
|
41
|
+
entityName?: string;
|
|
42
|
+
entityType?: string;
|
|
43
|
+
}>;
|
|
44
|
+
decisions: Array<{
|
|
45
|
+
title: string;
|
|
46
|
+
reasoning?: string;
|
|
47
|
+
category?: string;
|
|
48
|
+
}>;
|
|
49
|
+
actionItems: Array<{
|
|
50
|
+
title: string;
|
|
51
|
+
priority?: string;
|
|
52
|
+
type?: string;
|
|
53
|
+
}>;
|
|
54
|
+
entities: Array<{
|
|
55
|
+
name: string;
|
|
56
|
+
type: string;
|
|
57
|
+
}>;
|
|
58
|
+
}
|
|
59
|
+
export declare class ClerkModel {
|
|
60
|
+
private config;
|
|
61
|
+
private llm;
|
|
62
|
+
constructor(config: ClerkModelConfig);
|
|
63
|
+
/**
|
|
64
|
+
* Route a task to the best agent/model.
|
|
65
|
+
* Given a user prompt and available agents, the clerk decides which agent handles it.
|
|
66
|
+
* Falls back to the default agent if clerk call fails.
|
|
67
|
+
*/
|
|
68
|
+
routeTask(prompt: string, agents: data.AgentProfileRow[]): Promise<TaskRoute>;
|
|
69
|
+
/**
|
|
70
|
+
* Build an optimized system prompt with relevant context, respecting token budget.
|
|
71
|
+
*
|
|
72
|
+
* Budget allocation:
|
|
73
|
+
* - System prompt base: ~500 tokens
|
|
74
|
+
* - Memory facts: up to 30% of budget
|
|
75
|
+
* - Decisions: up to 15% of budget
|
|
76
|
+
* - Summaries: up to 15% of budget
|
|
77
|
+
* - Remaining: reserved for conversation history
|
|
78
|
+
*/
|
|
79
|
+
buildPrompt(userPrompt: string, agentId: string, profile: data.AgentProfileRow, opts?: {
|
|
80
|
+
targetModel?: string;
|
|
81
|
+
maxContextTokens?: number;
|
|
82
|
+
}): BuiltPrompt;
|
|
83
|
+
/**
|
|
84
|
+
* Extract memory facts, decisions, action items, and entities from conversation messages.
|
|
85
|
+
* Uses the user's own LLM (clerk model) — runs entirely locally.
|
|
86
|
+
*/
|
|
87
|
+
extractMemory(conversationId: string, messages: data.MessageRow[]): Promise<ExtractionResult>;
|
|
88
|
+
/**
|
|
89
|
+
* Trim conversation history to fit within token budget.
|
|
90
|
+
* Keeps the most recent messages, with a summary of older ones.
|
|
91
|
+
*/
|
|
92
|
+
trimHistory(messages: data.MessageRow[], maxTokens: number): data.MessageRow[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get or create the global clerk model instance.
|
|
96
|
+
* Resolves clerk config from: settings table → config.json providers → env vars.
|
|
97
|
+
*/
|
|
98
|
+
export declare function getClerk(): ClerkModel | null;
|
|
99
|
+
/** Reset the clerk instance (e.g., after config change) */
|
|
100
|
+
export declare function resetClerk(): void;
|
|
101
|
+
//# sourceMappingURL=clerk-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clerk-model.d.ts","sourceRoot":"","sources":["../src/clerk-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,IAAI,MAAM,cAAc,CAAC;AAKrC,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gDAAgD;IAChD,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9F,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3E,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,QAAQ,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AA8BD,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,GAAG,CAAc;gBAEb,MAAM,EAAE,gBAAgB;IAQpC;;;;OAIG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAyDnF;;;;;;;;;OASG;IACH,WAAW,CACT,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,IAAI,CAAC,eAAe,EAC7B,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;KAAE,GACzD,WAAW;IA2Gd;;;OAGG;IACG,aAAa,CACjB,cAAc,EAAE,MAAM,EACtB,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,GAC1B,OAAO,CAAC,gBAAgB,CAAC;IAwC5B;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE;CAe/E;AAMD;;;GAGG;AACH,wBAAgB,QAAQ,IAAI,UAAU,GAAG,IAAI,CAsC5C;AAED,2DAA2D;AAC3D,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}
|