@circuitwall/jarela 0.7.2 → 0.7.3
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js +51 -35
- package/.next/standalone/.next/server/app/api/v1/agents/[id]/compact/route.js.map +1 -1
- package/.next/standalone/.next/server/app/api/v1/threads/[thread_id]/run/route.js +2 -2
- package/.next/standalone/.next/server/app/index.html +2 -2
- package/.next/standalone/.next/server/app/index.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page.js +515 -104
- package/.next/standalone/.next/server/app/page.js.map +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup.html +1 -1
- package/.next/standalone/.next/server/app/setup.rsc +2 -2
- package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/setup.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/setup.segments/_index.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/setup.segments/setup.segment.rsc +1 -1
- package/.next/standalone/.next/server/chunks/1683.js +26 -16
- package/.next/standalone/.next/server/chunks/1683.js.map +1 -1
- package/.next/standalone/.next/server/chunks/{317.js → 5432.js} +11100 -10858
- package/.next/standalone/.next/server/chunks/5432.js.map +1 -0
- package/.next/standalone/.next/server/chunks/7885.js +606 -353
- package/.next/standalone/.next/server/chunks/7885.js.map +1 -1
- package/.next/standalone/.next/server/chunks/8135.js +59 -16
- package/.next/standalone/.next/server/chunks/8135.js.map +1 -1
- package/.next/standalone/.next/server/chunks/9032.js +3 -3
- package/.next/standalone/.next/server/chunks/9032.js.map +1 -1
- package/.next/standalone/.next/server/instrumentation.js +3 -3
- package/.next/standalone/.next/server/instrumentation.js.map +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +2 -2
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/app/{page-a20902703c0a4f10.js → page-9fb006074fb13526.js} +582 -171
- package/.next/standalone/.next/static/chunks/app/page-9fb006074fb13526.js.map +1 -0
- package/.next/standalone/.next/static/css/5507dbe1cdc6c599.css +5 -0
- package/.next/standalone/.next/static/css/5507dbe1cdc6c599.css.map +1 -0
- package/.next/standalone/package.json +1 -1
- package/CHANGELOG.md +11 -0
- package/README.md +83 -1
- package/api/types.ts +7 -0
- package/app/api/v1/agents/[id]/compact/route.ts +2 -40
- package/components/bridges/BridgeEditor.tsx +8 -0
- package/components/chat/MessageBubble.tsx +3 -36
- package/components/models/ModelEditor.tsx +141 -0
- package/components/scheduled-tasks/ScheduledTasksPanel.tsx +5 -0
- package/components/scheduled-tasks/WatchersSection.tsx +5 -0
- package/lib/agents/context-budget.test.ts +128 -0
- package/lib/agents/context-budget.ts +128 -0
- package/lib/agents/conversation-summary.test.ts +68 -0
- package/lib/agents/conversation-summary.ts +51 -0
- package/lib/agents/run-thread.ts +112 -2
- package/lib/bridges/dispatcher.test.ts +134 -0
- package/lib/bridges/dispatcher.ts +34 -16
- package/lib/bridges/message-role.test.ts +83 -0
- package/lib/bridges/message-role.ts +46 -0
- package/lib/triggers/handlers/watcher.test.ts +23 -4
- package/lib/triggers/handlers/watcher.ts +56 -8
- package/package.json +1 -1
- package/.next/standalone/.next/server/chunks/317.js.map +0 -1
- package/.next/standalone/.next/static/chunks/app/page-a20902703c0a4f10.js.map +0 -1
- package/.next/standalone/.next/static/css/cc66c456aba91258.css +0 -5
- package/.next/standalone/.next/static/css/cc66c456aba91258.css.map +0 -1
- /package/.next/standalone/.next/static/{IauO0rNZkUVPX834k-SBa → AbCOWpaxP4v4lUSeFWWYz}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{IauO0rNZkUVPX834k-SBa → AbCOWpaxP4v4lUSeFWWYz}/_ssgManifest.js +0 -0
|
@@ -43,8 +43,8 @@ function __resetTriggerRegistry() {
|
|
|
43
43
|
var threads = __webpack_require__(83042);
|
|
44
44
|
// EXTERNAL MODULE: ./lib/stores/agent-configs.ts
|
|
45
45
|
var agent_configs = __webpack_require__(41720);
|
|
46
|
-
// EXTERNAL MODULE: ./lib/agents/run-thread.ts +
|
|
47
|
-
var run_thread = __webpack_require__(
|
|
46
|
+
// EXTERNAL MODULE: ./lib/agents/run-thread.ts + 12 modules
|
|
47
|
+
var run_thread = __webpack_require__(76644);
|
|
48
48
|
// EXTERNAL MODULE: ./lib/agents/stream-collector.ts
|
|
49
49
|
var stream_collector = __webpack_require__(30685);
|
|
50
50
|
// EXTERNAL MODULE: ./lib/triggers/scripts.ts
|
|
@@ -276,6 +276,8 @@ var external_node_crypto_ = __webpack_require__(77598);
|
|
|
276
276
|
var watchers = __webpack_require__(96638);
|
|
277
277
|
// EXTERNAL MODULE: ./lib/tools/registry.ts
|
|
278
278
|
var registry = __webpack_require__(83085);
|
|
279
|
+
// EXTERNAL MODULE: ./lib/utils/text.ts
|
|
280
|
+
var utils_text = __webpack_require__(46723);
|
|
279
281
|
;// ./lib/triggers/handlers/watcher.ts
|
|
280
282
|
// Watcher trigger handler (ADR-0027). Sibling of scheduled-task.ts.
|
|
281
283
|
//
|
|
@@ -285,7 +287,7 @@ var registry = __webpack_require__(83085);
|
|
|
285
287
|
// tools must be context-free).
|
|
286
288
|
// 3. Hash the stringified result and compare to last_fingerprint.
|
|
287
289
|
// 4. If the hash differs from the previous run, return a TriggerFiring
|
|
288
|
-
// whose prompt embeds
|
|
290
|
+
// whose prompt embeds a compact previous->current diff for the agent.
|
|
289
291
|
// If it matches (or this is the first run with no previous), record
|
|
290
292
|
// the fingerprint and skip — no LLM call, no firing.
|
|
291
293
|
// 5. Either way the watcher's next_run_at is advanced by
|
|
@@ -298,6 +300,7 @@ var registry = __webpack_require__(83085);
|
|
|
298
300
|
|
|
299
301
|
|
|
300
302
|
|
|
303
|
+
|
|
301
304
|
const WATCHER_KIND = "watcher";
|
|
302
305
|
function fingerprint(s) {
|
|
303
306
|
return (0,external_node_crypto_.createHash)("sha256").update(s).digest("hex");
|
|
@@ -311,6 +314,47 @@ function stringifyResult(value) {
|
|
|
311
314
|
}
|
|
312
315
|
}
|
|
313
316
|
const DEFAULT_REACTION_DIRECTIVE = `Summarise what changed and decide whether the user needs to know. ` + `If nothing material changed, you may stay silent.`;
|
|
317
|
+
// Watcher tool outputs can be very large (full JSON payloads, long lists).
|
|
318
|
+
// Keep the diff context bounded so one firing cannot consume most of an
|
|
319
|
+
// agent's prompt budget.
|
|
320
|
+
const MAX_DIFF_CONTEXT_BYTES = 3500;
|
|
321
|
+
function normalizeForDiff(raw) {
|
|
322
|
+
try {
|
|
323
|
+
return JSON.stringify(JSON.parse(raw), null, 2);
|
|
324
|
+
} catch {
|
|
325
|
+
return raw;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
function buildDiffForPrompt(previous, current) {
|
|
329
|
+
if (previous === null) return "+ (first observation baseline established; no diff available)";
|
|
330
|
+
const prev = normalizeForDiff(previous).split(/\r?\n/);
|
|
331
|
+
const curr = normalizeForDiff(current).split(/\r?\n/);
|
|
332
|
+
let start = 0;
|
|
333
|
+
while(start < prev.length && start < curr.length && prev[start] === curr[start]){
|
|
334
|
+
start += 1;
|
|
335
|
+
}
|
|
336
|
+
let prevEnd = prev.length - 1;
|
|
337
|
+
let currEnd = curr.length - 1;
|
|
338
|
+
while(prevEnd >= start && currEnd >= start && prev[prevEnd] === curr[currEnd]){
|
|
339
|
+
prevEnd -= 1;
|
|
340
|
+
currEnd -= 1;
|
|
341
|
+
}
|
|
342
|
+
const removed = prev.slice(start, prevEnd + 1);
|
|
343
|
+
const added = curr.slice(start, currEnd + 1);
|
|
344
|
+
if (removed.length === 0 && added.length === 0) {
|
|
345
|
+
return "(no textual diff after normalization)";
|
|
346
|
+
}
|
|
347
|
+
const hunkHeader = `@@ old:${start + 1}-${Math.max(start, prevEnd + 1)} new:${start + 1}-${Math.max(start, currEnd + 1)} @@`;
|
|
348
|
+
const raw = [
|
|
349
|
+
hunkHeader,
|
|
350
|
+
...removed.map((l)=>`- ${l}`),
|
|
351
|
+
...added.map((l)=>`+ ${l}`)
|
|
352
|
+
].join("\n");
|
|
353
|
+
const bytes = Buffer.byteLength(raw, "utf8");
|
|
354
|
+
const clipped = (0,utils_text/* truncateBytes */.Q)(raw, MAX_DIFF_CONTEXT_BYTES);
|
|
355
|
+
if (!clipped.truncated) return raw;
|
|
356
|
+
return `${clipped.text}\n… [diff truncated: showing ${MAX_DIFF_CONTEXT_BYTES} of ${bytes} bytes; full values retained in watcher state]`;
|
|
357
|
+
}
|
|
314
358
|
function buildFiringPrompt(watcher, previous, current) {
|
|
315
359
|
const argsPretty = (()=>{
|
|
316
360
|
try {
|
|
@@ -320,8 +364,8 @@ function buildFiringPrompt(watcher, previous, current) {
|
|
|
320
364
|
}
|
|
321
365
|
})();
|
|
322
366
|
// ADR-0030: a non-null reaction_prompt swaps in for the default directive.
|
|
323
|
-
// The diff envelope (label/tool/args/
|
|
324
|
-
//
|
|
367
|
+
// The diff envelope (label/tool/args/diff) is unchanged so the agent
|
|
368
|
+
// always has the change context regardless of the user's instruction.
|
|
325
369
|
const directive = watcher.reaction_prompt?.trim() || DEFAULT_REACTION_DIRECTIVE;
|
|
326
370
|
return [
|
|
327
371
|
`Watcher "${watcher.label}" detected a change.`,
|
|
@@ -329,11 +373,8 @@ function buildFiringPrompt(watcher, previous, current) {
|
|
|
329
373
|
`Tool: ${watcher.tool_name}`,
|
|
330
374
|
`Args: ${argsPretty}`,
|
|
331
375
|
``,
|
|
332
|
-
`---
|
|
333
|
-
previous
|
|
334
|
-
``,
|
|
335
|
-
`--- Current result ---`,
|
|
336
|
-
current,
|
|
376
|
+
`--- Diff (previous -> current) ---`,
|
|
377
|
+
buildDiffForPrompt(previous, current),
|
|
337
378
|
``,
|
|
338
379
|
directive
|
|
339
380
|
].join("\n");
|
|
@@ -1649,6 +1690,52 @@ async function tick() {
|
|
|
1649
1690
|
}
|
|
1650
1691
|
|
|
1651
1692
|
|
|
1693
|
+
/***/ }),
|
|
1694
|
+
|
|
1695
|
+
/***/ 15393:
|
|
1696
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1697
|
+
|
|
1698
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
1699
|
+
/* harmony export */ K: () => (/* binding */ transcriptText),
|
|
1700
|
+
/* harmony export */ S: () => (/* binding */ summarizeTranscript)
|
|
1701
|
+
/* harmony export */ });
|
|
1702
|
+
function transcriptText(raw) {
|
|
1703
|
+
if (!raw.startsWith("[")) return raw;
|
|
1704
|
+
try {
|
|
1705
|
+
const parsed = JSON.parse(raw);
|
|
1706
|
+
if (!Array.isArray(parsed)) return raw;
|
|
1707
|
+
return parsed.map((p)=>{
|
|
1708
|
+
if (p.type === "text") return p.text;
|
|
1709
|
+
if (p.type === "image") return `[image attachment: ${p.media_type}]`;
|
|
1710
|
+
if (p.type === "file") return `[file attachment: ${p.name} (${p.media_type})]`;
|
|
1711
|
+
return "";
|
|
1712
|
+
}).filter(Boolean).join(" ").trim();
|
|
1713
|
+
} catch {
|
|
1714
|
+
return raw;
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
function summaryMessages(transcript) {
|
|
1718
|
+
return [
|
|
1719
|
+
{
|
|
1720
|
+
role: "system",
|
|
1721
|
+
content: "You are a concise summarizer. Summarize the conversation below in 3-7 bullet points, capturing key facts, decisions, and context that would be useful to remember later."
|
|
1722
|
+
},
|
|
1723
|
+
{
|
|
1724
|
+
role: "user",
|
|
1725
|
+
content: `Conversation to summarize:\n\n${transcript}`
|
|
1726
|
+
}
|
|
1727
|
+
];
|
|
1728
|
+
}
|
|
1729
|
+
async function summarizeTranscript(provider, modelId, providerParams, transcript) {
|
|
1730
|
+
const trimmed = transcript.trim();
|
|
1731
|
+
if (!trimmed) return "";
|
|
1732
|
+
const { stream } = await provider.chat(modelId, summaryMessages(trimmed), providerParams);
|
|
1733
|
+
let summary = "";
|
|
1734
|
+
for await (const chunk of stream)summary += chunk;
|
|
1735
|
+
return summary.trim();
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
|
|
1652
1739
|
/***/ }),
|
|
1653
1740
|
|
|
1654
1741
|
/***/ 18689:
|
|
@@ -5728,356 +5815,54 @@ function markTaskRan(id, kind, schedule, error) {
|
|
|
5728
5815
|
|
|
5729
5816
|
/***/ }),
|
|
5730
5817
|
|
|
5731
|
-
/***/
|
|
5818
|
+
/***/ 76644:
|
|
5732
5819
|
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5733
5820
|
|
|
5734
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
5735
|
-
/* harmony export */ IT: () => (/* binding */ getScript),
|
|
5736
|
-
/* harmony export */ Pl: () => (/* binding */ REACTION_SCRIPT_PREFIX),
|
|
5737
|
-
/* harmony export */ S$: () => (/* binding */ listReactionScripts),
|
|
5738
|
-
/* harmony export */ tX: () => (/* binding */ registerScript),
|
|
5739
|
-
/* harmony export */ z3: () => (/* binding */ isReactionScript)
|
|
5740
|
-
/* harmony export */ });
|
|
5741
|
-
/* unused harmony exports listScripts, __resetScriptRegistry */
|
|
5742
|
-
/* harmony import */ var _lib_utils_global_state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15559);
|
|
5743
|
-
// ADR-0028. In-process script registry for ScriptFiring.
|
|
5744
|
-
//
|
|
5745
|
-
// Trust model: only built-ins are registered, in code, at module load
|
|
5746
|
-
// time. There is NO mechanism to register a script from DB, user input,
|
|
5747
|
-
// or shell-out — `script` on a ScriptFiring is just a key into this
|
|
5748
|
-
// map. This keeps scripted triggers safe even though they bypass the
|
|
5749
|
-
// LLM/thread machinery that gates prompt firings.
|
|
5750
5821
|
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
state.scripts.set(name, fn);
|
|
5759
|
-
}
|
|
5760
|
-
function getScript(name) {
|
|
5761
|
-
return state.scripts.get(name);
|
|
5762
|
-
}
|
|
5763
|
-
function listScripts() {
|
|
5764
|
-
return Array.from(state.scripts.keys()).sort();
|
|
5765
|
-
}
|
|
5766
|
-
// ADR-0031 — names beginning with this prefix are user-attachable
|
|
5767
|
-
// reaction scripts. Internal plumbing scripts (e.g.
|
|
5768
|
-
// `documents.reindex_local_file`) live under other namespaces and are
|
|
5769
|
-
// excluded so the watcher schedule surface can't accidentally invoke
|
|
5770
|
-
// them.
|
|
5771
|
-
const REACTION_SCRIPT_PREFIX = "reaction.";
|
|
5772
|
-
function listReactionScripts() {
|
|
5773
|
-
return listScripts().filter((n)=>n.startsWith(REACTION_SCRIPT_PREFIX));
|
|
5774
|
-
}
|
|
5775
|
-
function isReactionScript(name) {
|
|
5776
|
-
return name.startsWith(REACTION_SCRIPT_PREFIX) && state.scripts.has(name);
|
|
5777
|
-
}
|
|
5778
|
-
/** Test-only helper. */ function __resetScriptRegistry() {
|
|
5779
|
-
state.scripts.clear();
|
|
5780
|
-
}
|
|
5822
|
+
// EXPORTS
|
|
5823
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
5824
|
+
op: () => (/* binding */ RunThreadError),
|
|
5825
|
+
_w: () => (/* binding */ persistAssistantMessage),
|
|
5826
|
+
fn: () => (/* binding */ prepareThreadRun),
|
|
5827
|
+
ib: () => (/* binding */ shouldEmitChunk)
|
|
5828
|
+
});
|
|
5781
5829
|
|
|
5830
|
+
// UNUSED EXPORTS: contentText, looksLikeStall
|
|
5782
5831
|
|
|
5783
|
-
|
|
5832
|
+
// EXTERNAL MODULE: ./node_modules/@langchain/langgraph/dist/prebuilt/index.js + 6 modules
|
|
5833
|
+
var prebuilt = __webpack_require__(67462);
|
|
5834
|
+
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/messages/index.js + 4 modules
|
|
5835
|
+
var dist_messages = __webpack_require__(12016);
|
|
5836
|
+
// EXTERNAL MODULE: ./lib/providers/index.ts + 8 modules
|
|
5837
|
+
var providers = __webpack_require__(68866);
|
|
5838
|
+
// EXTERNAL MODULE: ./lib/stores/model-config.ts
|
|
5839
|
+
var model_config = __webpack_require__(80937);
|
|
5840
|
+
// EXTERNAL MODULE: ./lib/tools/index.ts + 17 modules
|
|
5841
|
+
var lib_tools = __webpack_require__(36185);
|
|
5842
|
+
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/language_models/chat_models.js + 1 modules
|
|
5843
|
+
var chat_models = __webpack_require__(87233);
|
|
5844
|
+
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/outputs.js
|
|
5845
|
+
var outputs = __webpack_require__(40964);
|
|
5846
|
+
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/utils/function_calling.js
|
|
5847
|
+
var function_calling = __webpack_require__(46329);
|
|
5848
|
+
;// ./lib/providers/jarela-chat-model.ts
|
|
5784
5849
|
|
|
5785
|
-
/***/ 81753:
|
|
5786
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5787
5850
|
|
|
5788
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
5789
|
-
/* harmony export */ Fp: () => (/* binding */ describeToolSecrets),
|
|
5790
|
-
/* harmony export */ eg: () => (/* binding */ deleteToolSecret),
|
|
5791
|
-
/* harmony export */ pq: () => (/* binding */ getToolSecret),
|
|
5792
|
-
/* harmony export */ zR: () => (/* binding */ setToolSecret)
|
|
5793
|
-
/* harmony export */ });
|
|
5794
|
-
/* unused harmony export purgeToolSecrets */
|
|
5795
|
-
/* harmony import */ var _lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80956);
|
|
5796
|
-
// Encrypted-at-rest secrets for external tools (ADR-0023).
|
|
5797
|
-
//
|
|
5798
|
-
// External tools declare secret "slots" in their module.exports:
|
|
5799
|
-
// secrets: [{ key: "api_key", label: "OpenWeather API key", required: true }]
|
|
5800
|
-
//
|
|
5801
|
-
// Values are persisted in the `tool-secrets` namespace of the memory store
|
|
5802
|
-
// (which is flagged sensitive in lib/crypto/sensitive.ts, so envelope
|
|
5803
|
-
// encryption applies — same primitive as the integrations store).
|
|
5804
|
-
//
|
|
5805
|
-
// Keys are stored as `<toolName>:<slotKey>`. Tool names and slot keys are
|
|
5806
|
-
// validated to a conservative character set so they can't collide with the
|
|
5807
|
-
// namespace delimiter or smuggle SQL/JSON metacharacters.
|
|
5808
|
-
//
|
|
5809
|
-
// Note on isolation: external tools run in-process with full Node privileges
|
|
5810
|
-
// (ADR-0013), so a malicious tool could read another tool's secrets by going
|
|
5811
|
-
// around this API (e.g. directly opening the SQLite file). The per-tool
|
|
5812
|
-
// scoping here is a *convention* surfaced through `ctx.getSecret`, not a
|
|
5813
|
-
// sandbox boundary.
|
|
5814
5851
|
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5818
|
-
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
return typeof v === "string" ? v : null;
|
|
5827
|
-
} catch {
|
|
5828
|
-
return null;
|
|
5852
|
+
|
|
5853
|
+
class JarelaChatModel extends chat_models/* BaseChatModel */.xV {
|
|
5854
|
+
constructor(fields){
|
|
5855
|
+
super({}), this.lc_namespace = [
|
|
5856
|
+
"jarela",
|
|
5857
|
+
"chat_models"
|
|
5858
|
+
], this.lc_serializable = false;
|
|
5859
|
+
this._provider = fields.provider;
|
|
5860
|
+
this._modelId = fields.modelId;
|
|
5861
|
+
this._params = fields.params;
|
|
5862
|
+
this._boundTools = fields.boundTools ?? [];
|
|
5829
5863
|
}
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
if (!validName(toolName) || !validName(key)) return null;
|
|
5833
|
-
const row = (0,_lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__/* .getMemory */ .So)(NAMESPACE, compoundKey(toolName, key));
|
|
5834
|
-
if (!row) return null;
|
|
5835
|
-
return parseStored(row.value);
|
|
5836
|
-
}
|
|
5837
|
-
function setToolSecret(toolName, key, value) {
|
|
5838
|
-
if (!validName(toolName)) throw new Error(`invalid tool name: ${toolName}`);
|
|
5839
|
-
if (!validName(key)) throw new Error(`invalid secret key: ${key}`);
|
|
5840
|
-
if (typeof value !== "string") throw new Error("secret value must be a string");
|
|
5841
|
-
(0,_lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__/* .putMemory */ .Ri)(NAMESPACE, compoundKey(toolName, key), value);
|
|
5842
|
-
}
|
|
5843
|
-
function deleteToolSecret(toolName, key) {
|
|
5844
|
-
if (!validName(toolName) || !validName(key)) return false;
|
|
5845
|
-
return (0,_lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__/* .deleteMemory */ .h0)(NAMESPACE, compoundKey(toolName, key));
|
|
5846
|
-
}
|
|
5847
|
-
// Returns which declared slots have a value persisted. Never returns the
|
|
5848
|
-
// plaintext — that only escapes via `ctx.getSecret` inside the tool's own
|
|
5849
|
-
// run loop.
|
|
5850
|
-
function describeToolSecrets(toolName, slots) {
|
|
5851
|
-
if (!validName(toolName)) return slots.map((s)=>({
|
|
5852
|
-
...s,
|
|
5853
|
-
is_set: false
|
|
5854
|
-
}));
|
|
5855
|
-
return slots.map((s)=>({
|
|
5856
|
-
...s,
|
|
5857
|
-
is_set: getToolSecret(toolName, s.key) !== null
|
|
5858
|
-
}));
|
|
5859
|
-
}
|
|
5860
|
-
// Delete every persisted secret for a tool — used when an external tool
|
|
5861
|
-
// file is removed and the operator wants to clear stale credentials.
|
|
5862
|
-
function purgeToolSecrets(toolName) {
|
|
5863
|
-
if (!validName(toolName)) return 0;
|
|
5864
|
-
const prefix = `${toolName}:`;
|
|
5865
|
-
const rows = listMemory(NAMESPACE, undefined, 1000).filter((r)=>r.key.startsWith(prefix));
|
|
5866
|
-
let n = 0;
|
|
5867
|
-
for (const r of rows){
|
|
5868
|
-
if (deleteMemory(NAMESPACE, r.key)) n++;
|
|
5869
|
-
}
|
|
5870
|
-
return n;
|
|
5871
|
-
}
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
/***/ }),
|
|
5875
|
-
|
|
5876
|
-
/***/ 83042:
|
|
5877
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
5878
|
-
|
|
5879
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
5880
|
-
/* harmony export */ Iz: () => (/* binding */ listThreadsByAgent),
|
|
5881
|
-
/* harmony export */ KX: () => (/* binding */ deleteThread),
|
|
5882
|
-
/* harmony export */ Mi: () => (/* binding */ listThreads),
|
|
5883
|
-
/* harmony export */ Nn: () => (/* binding */ getMessagesAfter),
|
|
5884
|
-
/* harmony export */ Nw: () => (/* binding */ createThread),
|
|
5885
|
-
/* harmony export */ S0: () => (/* binding */ getRecentMessagesWindow),
|
|
5886
|
-
/* harmony export */ VL: () => (/* binding */ getMessages),
|
|
5887
|
-
/* harmony export */ az: () => (/* binding */ clearThreadMessages),
|
|
5888
|
-
/* harmony export */ fG: () => (/* binding */ getThread),
|
|
5889
|
-
/* harmony export */ mI: () => (/* binding */ touchThread),
|
|
5890
|
-
/* harmony export */ qI: () => (/* binding */ getMessagesPage),
|
|
5891
|
-
/* harmony export */ tj: () => (/* binding */ addMessage),
|
|
5892
|
-
/* harmony export */ xH: () => (/* binding */ getOrCreateAgentThread)
|
|
5893
|
-
/* harmony export */ });
|
|
5894
|
-
/* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(77598);
|
|
5895
|
-
/* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_crypto__WEBPACK_IMPORTED_MODULE_0__);
|
|
5896
|
-
/* harmony import */ var _lib_db__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46);
|
|
5897
|
-
/* harmony import */ var _lib_embeddings__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21839);
|
|
5898
|
-
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
const now = ()=>new Date().toISOString();
|
|
5902
|
-
// Explicit column list for message reads — omits `embedding` (~20KB of
|
|
5903
|
-
// JSON-encoded float[] per row) which only the embeddings module reads.
|
|
5904
|
-
// Avoids dragging it through the chat-history result set on every call.
|
|
5905
|
-
const MSG_COLS_SQL = "SELECT msg_id, thread_id, role, content, created_at, tool_events, category FROM messages";
|
|
5906
|
-
function listThreads(limit = 50, offset = 0) {
|
|
5907
|
-
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads ORDER BY updated_at DESC LIMIT ? OFFSET ?").all(limit, offset);
|
|
5908
|
-
}
|
|
5909
|
-
function listThreadsByAgent(agent_id, limit = 50) {
|
|
5910
|
-
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads WHERE agent_id=? ORDER BY updated_at DESC LIMIT ?").all(agent_id, limit);
|
|
5911
|
-
}
|
|
5912
|
-
function getThread(thread_id) {
|
|
5913
|
-
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads WHERE thread_id=?").get(thread_id) ?? null;
|
|
5914
|
-
}
|
|
5915
|
-
function createThread(agent_id, title) {
|
|
5916
|
-
const t = now();
|
|
5917
|
-
const thread_id = (0,node_crypto__WEBPACK_IMPORTED_MODULE_0__.randomUUID)();
|
|
5918
|
-
(0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("INSERT INTO threads (thread_id,agent_id,title,created_at,updated_at,message_count) VALUES (?,?,?,?,?,0)").run(thread_id, agent_id, title ?? null, t, t);
|
|
5919
|
-
return {
|
|
5920
|
-
thread_id,
|
|
5921
|
-
agent_id,
|
|
5922
|
-
title: title ?? null,
|
|
5923
|
-
created_at: t,
|
|
5924
|
-
updated_at: t,
|
|
5925
|
-
message_count: 0
|
|
5926
|
-
};
|
|
5927
|
-
}
|
|
5928
|
-
function deleteThread(thread_id) {
|
|
5929
|
-
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
5930
|
-
db.prepare("DELETE FROM messages WHERE thread_id=?").run(thread_id);
|
|
5931
|
-
const r = db.prepare("DELETE FROM threads WHERE thread_id=?").run(thread_id);
|
|
5932
|
-
return r.changes > 0;
|
|
5933
|
-
}
|
|
5934
|
-
function getMessages(thread_id) {
|
|
5935
|
-
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare(MSG_COLS_SQL + " WHERE thread_id=? ORDER BY created_at ASC").all(thread_id);
|
|
5936
|
-
}
|
|
5937
|
-
// Pull the latest N messages within a time window. Used to build the LLM
|
|
5938
|
-
// context — keeps prompt size bounded as threads grow indefinitely.
|
|
5939
|
-
// limit: 0 or negative = unlimited
|
|
5940
|
-
// sinceISO: undefined = no time bound
|
|
5941
|
-
// Returns chronological order (oldest first) so it can be appended to the prompt directly.
|
|
5942
|
-
function getRecentMessagesWindow(thread_id, limit, sinceISO) {
|
|
5943
|
-
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
5944
|
-
const params = [
|
|
5945
|
-
thread_id
|
|
5946
|
-
];
|
|
5947
|
-
let sql = MSG_COLS_SQL + " WHERE thread_id=?";
|
|
5948
|
-
if (sinceISO) {
|
|
5949
|
-
sql += " AND created_at >= ?";
|
|
5950
|
-
params.push(sinceISO);
|
|
5951
|
-
}
|
|
5952
|
-
sql += " ORDER BY created_at DESC";
|
|
5953
|
-
if (limit > 0) {
|
|
5954
|
-
sql += " LIMIT ?";
|
|
5955
|
-
params.push(limit);
|
|
5956
|
-
}
|
|
5957
|
-
const rows = db.prepare(sql).all(...params);
|
|
5958
|
-
return rows.reverse();
|
|
5959
|
-
}
|
|
5960
|
-
// Forward-fetch — return messages strictly newer than `afterISO`, oldest
|
|
5961
|
-
// first, capped at `limit`. Used by the chat view to pull only the
|
|
5962
|
-
// freshly-persisted user+assistant pair after a run completes, instead of
|
|
5963
|
-
// re-fetching the whole most-recent page.
|
|
5964
|
-
function getMessagesAfter(thread_id, afterISO, limit = 50) {
|
|
5965
|
-
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare(MSG_COLS_SQL + " WHERE thread_id=? AND created_at > ? ORDER BY created_at ASC LIMIT ?").all(thread_id, afterISO, limit);
|
|
5966
|
-
}
|
|
5967
|
-
// Pagination for the chat UI. Returns the latest N messages strictly older
|
|
5968
|
-
// than `beforeISO` (cursor). Caller passes the oldest already-loaded message's
|
|
5969
|
-
// created_at as the cursor; first page omits beforeISO.
|
|
5970
|
-
function getMessagesPage(thread_id, limit, beforeISO) {
|
|
5971
|
-
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
5972
|
-
const params = [
|
|
5973
|
-
thread_id
|
|
5974
|
-
];
|
|
5975
|
-
let sql = MSG_COLS_SQL + " WHERE thread_id=?";
|
|
5976
|
-
if (beforeISO) {
|
|
5977
|
-
sql += " AND created_at < ?";
|
|
5978
|
-
params.push(beforeISO);
|
|
5979
|
-
}
|
|
5980
|
-
sql += " ORDER BY created_at DESC LIMIT ?";
|
|
5981
|
-
params.push(limit + 1); // fetch one extra to detect if there's more
|
|
5982
|
-
const rows = db.prepare(sql).all(...params);
|
|
5983
|
-
const has_more = rows.length > limit;
|
|
5984
|
-
return {
|
|
5985
|
-
messages: rows.slice(0, limit).reverse(),
|
|
5986
|
-
has_more
|
|
5987
|
-
};
|
|
5988
|
-
}
|
|
5989
|
-
function addMessage(thread_id, role, content, toolEvents, category = null) {
|
|
5990
|
-
const msg_id = (0,node_crypto__WEBPACK_IMPORTED_MODULE_0__.randomUUID)();
|
|
5991
|
-
const t = now();
|
|
5992
|
-
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
5993
|
-
const toolEventsJson = toolEvents && toolEvents.length > 0 ? JSON.stringify(toolEvents) : null;
|
|
5994
|
-
db.prepare("INSERT INTO messages (msg_id,thread_id,role,content,created_at,tool_events,category) VALUES (?,?,?,?,?,?,?)").run(msg_id, thread_id, role, content, t, toolEventsJson, category);
|
|
5995
|
-
db.prepare("UPDATE threads SET message_count=message_count+1 WHERE thread_id=?").run(thread_id);
|
|
5996
|
-
// Best-effort: embed the message so semantic recall can pull it back later.
|
|
5997
|
-
// Skip empty / very short content (greetings have no useful signal).
|
|
5998
|
-
if (content.trim().length >= 12) {
|
|
5999
|
-
(0,_lib_embeddings__WEBPACK_IMPORTED_MODULE_2__/* .embedOne */ ._L)(content).then((vec)=>{
|
|
6000
|
-
if (vec) {
|
|
6001
|
-
(0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("UPDATE messages SET embedding=? WHERE msg_id=?").run(JSON.stringify(vec), msg_id);
|
|
6002
|
-
}
|
|
6003
|
-
}).catch(()=>{});
|
|
6004
|
-
}
|
|
6005
|
-
return {
|
|
6006
|
-
msg_id,
|
|
6007
|
-
thread_id,
|
|
6008
|
-
role,
|
|
6009
|
-
content,
|
|
6010
|
-
created_at: t,
|
|
6011
|
-
tool_events: toolEventsJson,
|
|
6012
|
-
category
|
|
6013
|
-
};
|
|
6014
|
-
}
|
|
6015
|
-
function getOrCreateAgentThread(agentId) {
|
|
6016
|
-
const existing = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads WHERE agent_id=? LIMIT 1").get(agentId);
|
|
6017
|
-
if (existing) return existing;
|
|
6018
|
-
return createThread(agentId);
|
|
6019
|
-
}
|
|
6020
|
-
function clearThreadMessages(threadId) {
|
|
6021
|
-
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
6022
|
-
db.prepare("DELETE FROM messages WHERE thread_id=?").run(threadId);
|
|
6023
|
-
db.prepare("UPDATE threads SET message_count=0, updated_at=? WHERE thread_id=?").run(new Date().toISOString(), threadId);
|
|
6024
|
-
}
|
|
6025
|
-
function touchThread(thread_id, firstMsg) {
|
|
6026
|
-
const t = now();
|
|
6027
|
-
(0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("UPDATE threads SET updated_at=?, title=COALESCE(title,?) WHERE thread_id=?").run(t, firstMsg ? firstMsg.slice(0, 80) : null, thread_id);
|
|
6028
|
-
}
|
|
6029
|
-
|
|
6030
|
-
|
|
6031
|
-
/***/ }),
|
|
6032
|
-
|
|
6033
|
-
/***/ 91396:
|
|
6034
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
// EXPORTS
|
|
6038
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
6039
|
-
op: () => (/* binding */ RunThreadError),
|
|
6040
|
-
_w: () => (/* binding */ persistAssistantMessage),
|
|
6041
|
-
fn: () => (/* binding */ prepareThreadRun),
|
|
6042
|
-
ib: () => (/* binding */ shouldEmitChunk)
|
|
6043
|
-
});
|
|
6044
|
-
|
|
6045
|
-
// UNUSED EXPORTS: contentText, looksLikeStall
|
|
6046
|
-
|
|
6047
|
-
// EXTERNAL MODULE: ./node_modules/@langchain/langgraph/dist/prebuilt/index.js + 6 modules
|
|
6048
|
-
var prebuilt = __webpack_require__(67462);
|
|
6049
|
-
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/messages/index.js + 4 modules
|
|
6050
|
-
var dist_messages = __webpack_require__(12016);
|
|
6051
|
-
// EXTERNAL MODULE: ./lib/providers/index.ts + 8 modules
|
|
6052
|
-
var providers = __webpack_require__(68866);
|
|
6053
|
-
// EXTERNAL MODULE: ./lib/stores/model-config.ts
|
|
6054
|
-
var model_config = __webpack_require__(80937);
|
|
6055
|
-
// EXTERNAL MODULE: ./lib/tools/index.ts + 17 modules
|
|
6056
|
-
var lib_tools = __webpack_require__(36185);
|
|
6057
|
-
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/language_models/chat_models.js + 1 modules
|
|
6058
|
-
var chat_models = __webpack_require__(87233);
|
|
6059
|
-
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/outputs.js
|
|
6060
|
-
var outputs = __webpack_require__(40964);
|
|
6061
|
-
// EXTERNAL MODULE: ./node_modules/@langchain/core/dist/utils/function_calling.js
|
|
6062
|
-
var function_calling = __webpack_require__(46329);
|
|
6063
|
-
;// ./lib/providers/jarela-chat-model.ts
|
|
6064
|
-
|
|
6065
|
-
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
class JarelaChatModel extends chat_models/* BaseChatModel */.xV {
|
|
6069
|
-
constructor(fields){
|
|
6070
|
-
super({}), this.lc_namespace = [
|
|
6071
|
-
"jarela",
|
|
6072
|
-
"chat_models"
|
|
6073
|
-
], this.lc_serializable = false;
|
|
6074
|
-
this._provider = fields.provider;
|
|
6075
|
-
this._modelId = fields.modelId;
|
|
6076
|
-
this._params = fields.params;
|
|
6077
|
-
this._boundTools = fields.boundTools ?? [];
|
|
6078
|
-
}
|
|
6079
|
-
_llmType() {
|
|
6080
|
-
return `jarela_${this._provider?.name ?? "chat"}`;
|
|
5864
|
+
_llmType() {
|
|
5865
|
+
return `jarela_${this._provider?.name ?? "chat"}`;
|
|
6081
5866
|
}
|
|
6082
5867
|
// createReactAgent calls bindTools() to attach the tool list before streaming.
|
|
6083
5868
|
bindTools(tools, _kwargs) {
|
|
@@ -7553,6 +7338,101 @@ var app_config = __webpack_require__(48954);
|
|
|
7553
7338
|
// EXTERNAL MODULE: external "node:os"
|
|
7554
7339
|
var external_node_os_ = __webpack_require__(48161);
|
|
7555
7340
|
var external_node_os_default = /*#__PURE__*/__webpack_require__.n(external_node_os_);
|
|
7341
|
+
// EXTERNAL MODULE: ./lib/agents/conversation-summary.ts
|
|
7342
|
+
var conversation_summary = __webpack_require__(15393);
|
|
7343
|
+
;// ./lib/agents/context-budget.ts
|
|
7344
|
+
|
|
7345
|
+
const DEFAULT_CONTEXT_WINDOW_TOKENS = 8192;
|
|
7346
|
+
const DEFAULT_OVERHEAD_TOKENS = 1200;
|
|
7347
|
+
const DEFAULT_OUTPUT_RESERVE_RATIO = 0.2;
|
|
7348
|
+
const DEFAULT_TIER_PRIORITY = [
|
|
7349
|
+
"hot",
|
|
7350
|
+
"warm",
|
|
7351
|
+
"facts"
|
|
7352
|
+
];
|
|
7353
|
+
const DEFAULT_TIER_PROPORTIONS = {
|
|
7354
|
+
hot: 0.6,
|
|
7355
|
+
warm: 0.25,
|
|
7356
|
+
facts: 0.15
|
|
7357
|
+
};
|
|
7358
|
+
function estimateTokens(text) {
|
|
7359
|
+
const trimmed = text.trim();
|
|
7360
|
+
if (!trimmed) return 0;
|
|
7361
|
+
return Math.max(1, Math.ceil(trimmed.length / 4));
|
|
7362
|
+
}
|
|
7363
|
+
function normalizeTierPriority(value) {
|
|
7364
|
+
if (!Array.isArray(value)) return DEFAULT_TIER_PRIORITY;
|
|
7365
|
+
const tiers = value.filter((v)=>v === "hot" || v === "warm" || v === "facts");
|
|
7366
|
+
if (tiers.length !== 3) return DEFAULT_TIER_PRIORITY;
|
|
7367
|
+
if (new Set(tiers).size !== 3) return DEFAULT_TIER_PRIORITY;
|
|
7368
|
+
return [
|
|
7369
|
+
tiers[0],
|
|
7370
|
+
tiers[1],
|
|
7371
|
+
tiers[2]
|
|
7372
|
+
];
|
|
7373
|
+
}
|
|
7374
|
+
function normalizeTierProportions(value) {
|
|
7375
|
+
const hot = toPositiveNumber(value?.hot, DEFAULT_TIER_PROPORTIONS.hot);
|
|
7376
|
+
const warm = toPositiveNumber(value?.warm, DEFAULT_TIER_PROPORTIONS.warm);
|
|
7377
|
+
const facts = toPositiveNumber(value?.facts, DEFAULT_TIER_PROPORTIONS.facts);
|
|
7378
|
+
const sum = hot + warm + facts;
|
|
7379
|
+
if (sum <= 0) return DEFAULT_TIER_PROPORTIONS;
|
|
7380
|
+
return {
|
|
7381
|
+
hot: hot / sum,
|
|
7382
|
+
warm: warm / sum,
|
|
7383
|
+
facts: facts / sum
|
|
7384
|
+
};
|
|
7385
|
+
}
|
|
7386
|
+
function computeContextBudget(config) {
|
|
7387
|
+
const contextWindowTokens = Math.max(1, Math.floor(config.context_window_tokens ?? DEFAULT_CONTEXT_WINDOW_TOKENS));
|
|
7388
|
+
const outputReserveTokens = Math.max(256, Math.min(contextWindowTokens - 1, Math.floor(config.max_tokens ?? contextWindowTokens * DEFAULT_OUTPUT_RESERVE_RATIO)));
|
|
7389
|
+
const overheadTokens = Math.max(0, Math.min(DEFAULT_OVERHEAD_TOKENS, contextWindowTokens - outputReserveTokens));
|
|
7390
|
+
const inputBudgetTokens = Math.max(0, contextWindowTokens - outputReserveTokens - overheadTokens);
|
|
7391
|
+
const proportions = normalizeTierProportions(config.context_tier_proportions);
|
|
7392
|
+
const tierPriority = normalizeTierPriority(config.context_tier_priority);
|
|
7393
|
+
const tierBudgets = {
|
|
7394
|
+
hot: Math.floor(inputBudgetTokens * proportions.hot),
|
|
7395
|
+
warm: Math.floor(inputBudgetTokens * proportions.warm),
|
|
7396
|
+
facts: Math.max(0, inputBudgetTokens - Math.floor(inputBudgetTokens * proportions.hot) - Math.floor(inputBudgetTokens * proportions.warm))
|
|
7397
|
+
};
|
|
7398
|
+
return {
|
|
7399
|
+
contextWindowTokens,
|
|
7400
|
+
outputReserveTokens,
|
|
7401
|
+
inputBudgetTokens,
|
|
7402
|
+
overheadTokens,
|
|
7403
|
+
tierBudgets,
|
|
7404
|
+
tierPriority
|
|
7405
|
+
};
|
|
7406
|
+
}
|
|
7407
|
+
function takeRecentMessagesWithinBudget(messages, tokenBudget) {
|
|
7408
|
+
if (tokenBudget <= 0 || messages.length === 0) return [];
|
|
7409
|
+
const chosen = [];
|
|
7410
|
+
let used = 0;
|
|
7411
|
+
for(let i = messages.length - 1; i >= 0; i -= 1){
|
|
7412
|
+
const msg = messages[i];
|
|
7413
|
+
const tokens = estimateTokens((0,conversation_summary/* transcriptText */.K)(msg.content));
|
|
7414
|
+
if (chosen.length > 0 && used + tokens > tokenBudget) break;
|
|
7415
|
+
chosen.push(msg);
|
|
7416
|
+
used += tokens;
|
|
7417
|
+
if (used >= tokenBudget) break;
|
|
7418
|
+
}
|
|
7419
|
+
return chosen.reverse();
|
|
7420
|
+
}
|
|
7421
|
+
function formatContextBudgetSummary(budget) {
|
|
7422
|
+
const parts = [
|
|
7423
|
+
`window ${budget.contextWindowTokens} tokens`,
|
|
7424
|
+
`output reserve ${budget.outputReserveTokens}`,
|
|
7425
|
+
`input budget ${budget.inputBudgetTokens}`,
|
|
7426
|
+
`hot ${budget.tierBudgets.hot}`,
|
|
7427
|
+
`warm ${budget.tierBudgets.warm}`,
|
|
7428
|
+
`facts ${budget.tierBudgets.facts}`
|
|
7429
|
+
];
|
|
7430
|
+
return parts.join(" · ");
|
|
7431
|
+
}
|
|
7432
|
+
function toPositiveNumber(value, fallback) {
|
|
7433
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
|
|
7434
|
+
}
|
|
7435
|
+
|
|
7556
7436
|
;// ./lib/agents/run-thread.ts
|
|
7557
7437
|
|
|
7558
7438
|
|
|
@@ -7567,6 +7447,11 @@ var external_node_os_default = /*#__PURE__*/__webpack_require__.n(external_node_
|
|
|
7567
7447
|
|
|
7568
7448
|
|
|
7569
7449
|
|
|
7450
|
+
|
|
7451
|
+
|
|
7452
|
+
|
|
7453
|
+
|
|
7454
|
+
|
|
7570
7455
|
// Resolve the app name once at module load. Forks set NEXT_PUBLIC_APP_NAME to
|
|
7571
7456
|
// rebrand the user-visible name the LLM echoes in chat replies; default
|
|
7572
7457
|
// "Jarela" for upstream. Per-turn pieces of the system prompt (user profile,
|
|
@@ -7666,7 +7551,24 @@ userCategory = null) {
|
|
|
7666
7551
|
const limit = agentCfg.history_limit ?? 50;
|
|
7667
7552
|
const windowHours = agentCfg.history_window_hours ?? 8;
|
|
7668
7553
|
const sinceISO = windowHours > 0 ? new Date(Date.now() - windowHours * 3600000).toISOString() : undefined;
|
|
7669
|
-
const
|
|
7554
|
+
const allWindowMessages = (0,threads/* getRecentMessagesWindow */.S0)(thread_id, limit, sinceISO);
|
|
7555
|
+
const modelCfg = agentCfg.model_config_name ? (0,model_config/* getModelConfig */.Ac)(agentCfg.model_config_name) : (0,model_config/* getDefaultModelConfig */.lB)();
|
|
7556
|
+
let providerParams = {};
|
|
7557
|
+
if (modelCfg) {
|
|
7558
|
+
try {
|
|
7559
|
+
providerParams = JSON.parse(modelCfg.params);
|
|
7560
|
+
} catch {
|
|
7561
|
+
providerParams = {};
|
|
7562
|
+
}
|
|
7563
|
+
}
|
|
7564
|
+
const budget = computeContextBudget({
|
|
7565
|
+
context_window_tokens: typeof providerParams.context_window_tokens === "number" ? providerParams.context_window_tokens : undefined,
|
|
7566
|
+
max_tokens: typeof providerParams.max_tokens === "number" ? providerParams.max_tokens : undefined,
|
|
7567
|
+
context_tier_proportions: typeof providerParams.context_tier_proportions === "object" && providerParams.context_tier_proportions ? providerParams.context_tier_proportions : undefined,
|
|
7568
|
+
context_tier_priority: providerParams.context_tier_priority
|
|
7569
|
+
});
|
|
7570
|
+
const hotMessages = takeRecentMessagesWithinBudget(allWindowMessages, budget.tierBudgets.hot);
|
|
7571
|
+
const history = hotMessages.map((m)=>({
|
|
7670
7572
|
role: m.role,
|
|
7671
7573
|
content: parseContent(m.content)
|
|
7672
7574
|
}));
|
|
@@ -7752,11 +7654,19 @@ userCategory = null) {
|
|
|
7752
7654
|
const memoryCtx = [
|
|
7753
7655
|
"--- Memory & recall ---",
|
|
7754
7656
|
"You have long-term memory across sessions and a fresh recall pass on every turn.",
|
|
7755
|
-
`-
|
|
7657
|
+
`- Hot conversation history is budgeted by model context size: ${formatContextBudgetSummary(budget)}.`,
|
|
7756
7658
|
"- A semantic search over all stored memory entries + past chat messages was run against the user's turn; matching items appear under \"Relevant context\" below.",
|
|
7757
7659
|
"- Use memory_write proactively when the user shares a fact, preference, or decision worth remembering. Use memory_read / memory_list to recall stored facts on demand.",
|
|
7758
7660
|
"- If you want detail from outside the recent window, the user can scroll up — but for facts you've stored explicitly, prefer recall over guessing."
|
|
7759
7661
|
].join("\n");
|
|
7662
|
+
const warmSummaryCtx = await buildWarmSummaryContext(allWindowMessages, hotMessages.length, modelCfg?.provider, modelCfg?.model_id, providerParams, budget.tierBudgets.warm);
|
|
7663
|
+
const factsCtx = buildFactsContext(trimmed, budget.tierBudgets.facts);
|
|
7664
|
+
const tierCtxByName = {
|
|
7665
|
+
hot: "",
|
|
7666
|
+
warm: warmSummaryCtx,
|
|
7667
|
+
facts: factsCtx
|
|
7668
|
+
};
|
|
7669
|
+
const tierOrderCtx = budget.tierPriority.map((tier)=>tierCtxByName[tier]).filter(Boolean);
|
|
7760
7670
|
// Semantic recall: pull in long-term memory + past messages relevant to this turn.
|
|
7761
7671
|
// Skip messages from the current thread that are already in the windowed history.
|
|
7762
7672
|
// Capped at RECALL_BUDGET_MS — if the embedding round-trip is slower than
|
|
@@ -7780,6 +7690,7 @@ userCategory = null) {
|
|
|
7780
7690
|
envCtx,
|
|
7781
7691
|
harnessParts.self_config,
|
|
7782
7692
|
memoryCtx,
|
|
7693
|
+
...tierOrderCtx,
|
|
7783
7694
|
recallCtx
|
|
7784
7695
|
].filter(Boolean);
|
|
7785
7696
|
let allowedTools = [];
|
|
@@ -7800,6 +7711,46 @@ userCategory = null) {
|
|
|
7800
7711
|
thread_id
|
|
7801
7712
|
};
|
|
7802
7713
|
}
|
|
7714
|
+
async function buildWarmSummaryContext(allWindowMessages, hotCount, providerName, modelId, providerParams, warmBudgetTokens) {
|
|
7715
|
+
if (warmBudgetTokens <= 32) return "";
|
|
7716
|
+
if (!providerName || !modelId) return "";
|
|
7717
|
+
const warmMessages = allWindowMessages.slice(0, Math.max(0, allWindowMessages.length - hotCount));
|
|
7718
|
+
if (warmMessages.length < 2) return "";
|
|
7719
|
+
// Keep summary input bounded by the warm budget to avoid recursive prompt bloat.
|
|
7720
|
+
const summaryInputChars = Math.max(0, warmBudgetTokens * 4);
|
|
7721
|
+
const transcript = warmMessages.map((m)=>`${m.role === "user" ? "User" : "Assistant"}: ${(0,conversation_summary/* transcriptText */.K)(m.content)}`).join("\n\n").slice(-summaryInputChars);
|
|
7722
|
+
if (!transcript.trim()) return "";
|
|
7723
|
+
try {
|
|
7724
|
+
const provider = (0,providers/* getProvider */.sO)(providerName);
|
|
7725
|
+
const summary = await (0,conversation_summary/* summarizeTranscript */.S)(provider, modelId, providerParams, transcript);
|
|
7726
|
+
if (!summary) return "";
|
|
7727
|
+
return [
|
|
7728
|
+
"--- Warm context summary ---",
|
|
7729
|
+
"Compressed recap of earlier messages outside the hot window:",
|
|
7730
|
+
summary
|
|
7731
|
+
].join("\n");
|
|
7732
|
+
} catch {
|
|
7733
|
+
return "";
|
|
7734
|
+
}
|
|
7735
|
+
}
|
|
7736
|
+
function buildFactsContext(query, factsBudgetTokens) {
|
|
7737
|
+
if (factsBudgetTokens <= 16) return "";
|
|
7738
|
+
const charBudget = factsBudgetTokens * 4;
|
|
7739
|
+
const rows = (0,memory/* listMemory */.Q_)("facts", query.slice(0, 120), 12);
|
|
7740
|
+
if (rows.length === 0) return "";
|
|
7741
|
+
const lines = [
|
|
7742
|
+
"--- Facts memory ---",
|
|
7743
|
+
"Durable fact entries from memory_store namespace=facts:"
|
|
7744
|
+
];
|
|
7745
|
+
let used = 0;
|
|
7746
|
+
for (const row of rows){
|
|
7747
|
+
const line = `- ${row.key}: ${String(row.value).slice(0, 220)}`;
|
|
7748
|
+
if (used > 0 && used + line.length > charBudget) break;
|
|
7749
|
+
lines.push(line);
|
|
7750
|
+
used += line.length;
|
|
7751
|
+
}
|
|
7752
|
+
return lines.length > 2 ? lines.join("\n") : "";
|
|
7753
|
+
}
|
|
7803
7754
|
// Wraps the raw agent stream with stall-retry logic. Chunks pass through
|
|
7804
7755
|
// LIVE to the consumer (so the chat UI sees deltas as they arrive); we only
|
|
7805
7756
|
// hold the terminal `done` chunk so we can decide whether to retry. If the
|
|
@@ -8029,6 +7980,308 @@ function shouldEmitChunk(chunkType, options) {
|
|
|
8029
7980
|
|
|
8030
7981
|
|
|
8031
7982
|
|
|
7983
|
+
/***/ }),
|
|
7984
|
+
|
|
7985
|
+
/***/ 79876:
|
|
7986
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
7987
|
+
|
|
7988
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
7989
|
+
/* harmony export */ IT: () => (/* binding */ getScript),
|
|
7990
|
+
/* harmony export */ Pl: () => (/* binding */ REACTION_SCRIPT_PREFIX),
|
|
7991
|
+
/* harmony export */ S$: () => (/* binding */ listReactionScripts),
|
|
7992
|
+
/* harmony export */ tX: () => (/* binding */ registerScript),
|
|
7993
|
+
/* harmony export */ z3: () => (/* binding */ isReactionScript)
|
|
7994
|
+
/* harmony export */ });
|
|
7995
|
+
/* unused harmony exports listScripts, __resetScriptRegistry */
|
|
7996
|
+
/* harmony import */ var _lib_utils_global_state__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(15559);
|
|
7997
|
+
// ADR-0028. In-process script registry for ScriptFiring.
|
|
7998
|
+
//
|
|
7999
|
+
// Trust model: only built-ins are registered, in code, at module load
|
|
8000
|
+
// time. There is NO mechanism to register a script from DB, user input,
|
|
8001
|
+
// or shell-out — `script` on a ScriptFiring is just a key into this
|
|
8002
|
+
// map. This keeps scripted triggers safe even though they bypass the
|
|
8003
|
+
// LLM/thread machinery that gates prompt firings.
|
|
8004
|
+
|
|
8005
|
+
const state = (0,_lib_utils_global_state__WEBPACK_IMPORTED_MODULE_0__/* .getOrCreateGlobal */ .X)("__jarela_trigger_scripts", ()=>({
|
|
8006
|
+
scripts: new Map()
|
|
8007
|
+
}));
|
|
8008
|
+
function registerScript(name, fn) {
|
|
8009
|
+
// Idempotent re-registration is fine — HMR and repeated module imports
|
|
8010
|
+
// in dev re-execute the registration calls. We just overwrite with the
|
|
8011
|
+
// latest function, matching the trigger handler registry's behaviour.
|
|
8012
|
+
state.scripts.set(name, fn);
|
|
8013
|
+
}
|
|
8014
|
+
function getScript(name) {
|
|
8015
|
+
return state.scripts.get(name);
|
|
8016
|
+
}
|
|
8017
|
+
function listScripts() {
|
|
8018
|
+
return Array.from(state.scripts.keys()).sort();
|
|
8019
|
+
}
|
|
8020
|
+
// ADR-0031 — names beginning with this prefix are user-attachable
|
|
8021
|
+
// reaction scripts. Internal plumbing scripts (e.g.
|
|
8022
|
+
// `documents.reindex_local_file`) live under other namespaces and are
|
|
8023
|
+
// excluded so the watcher schedule surface can't accidentally invoke
|
|
8024
|
+
// them.
|
|
8025
|
+
const REACTION_SCRIPT_PREFIX = "reaction.";
|
|
8026
|
+
function listReactionScripts() {
|
|
8027
|
+
return listScripts().filter((n)=>n.startsWith(REACTION_SCRIPT_PREFIX));
|
|
8028
|
+
}
|
|
8029
|
+
function isReactionScript(name) {
|
|
8030
|
+
return name.startsWith(REACTION_SCRIPT_PREFIX) && state.scripts.has(name);
|
|
8031
|
+
}
|
|
8032
|
+
/** Test-only helper. */ function __resetScriptRegistry() {
|
|
8033
|
+
state.scripts.clear();
|
|
8034
|
+
}
|
|
8035
|
+
|
|
8036
|
+
|
|
8037
|
+
/***/ }),
|
|
8038
|
+
|
|
8039
|
+
/***/ 81753:
|
|
8040
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
8041
|
+
|
|
8042
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
8043
|
+
/* harmony export */ Fp: () => (/* binding */ describeToolSecrets),
|
|
8044
|
+
/* harmony export */ eg: () => (/* binding */ deleteToolSecret),
|
|
8045
|
+
/* harmony export */ pq: () => (/* binding */ getToolSecret),
|
|
8046
|
+
/* harmony export */ zR: () => (/* binding */ setToolSecret)
|
|
8047
|
+
/* harmony export */ });
|
|
8048
|
+
/* unused harmony export purgeToolSecrets */
|
|
8049
|
+
/* harmony import */ var _lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(80956);
|
|
8050
|
+
// Encrypted-at-rest secrets for external tools (ADR-0023).
|
|
8051
|
+
//
|
|
8052
|
+
// External tools declare secret "slots" in their module.exports:
|
|
8053
|
+
// secrets: [{ key: "api_key", label: "OpenWeather API key", required: true }]
|
|
8054
|
+
//
|
|
8055
|
+
// Values are persisted in the `tool-secrets` namespace of the memory store
|
|
8056
|
+
// (which is flagged sensitive in lib/crypto/sensitive.ts, so envelope
|
|
8057
|
+
// encryption applies — same primitive as the integrations store).
|
|
8058
|
+
//
|
|
8059
|
+
// Keys are stored as `<toolName>:<slotKey>`. Tool names and slot keys are
|
|
8060
|
+
// validated to a conservative character set so they can't collide with the
|
|
8061
|
+
// namespace delimiter or smuggle SQL/JSON metacharacters.
|
|
8062
|
+
//
|
|
8063
|
+
// Note on isolation: external tools run in-process with full Node privileges
|
|
8064
|
+
// (ADR-0013), so a malicious tool could read another tool's secrets by going
|
|
8065
|
+
// around this API (e.g. directly opening the SQLite file). The per-tool
|
|
8066
|
+
// scoping here is a *convention* surfaced through `ctx.getSecret`, not a
|
|
8067
|
+
// sandbox boundary.
|
|
8068
|
+
|
|
8069
|
+
const NAMESPACE = "tool-secrets";
|
|
8070
|
+
const NAME_RE = /^[a-z0-9_-]+$/i;
|
|
8071
|
+
function validName(s) {
|
|
8072
|
+
return typeof s === "string" && s.length > 0 && s.length <= 64 && NAME_RE.test(s);
|
|
8073
|
+
}
|
|
8074
|
+
function compoundKey(toolName, key) {
|
|
8075
|
+
return `${toolName}:${key}`;
|
|
8076
|
+
}
|
|
8077
|
+
function parseStored(raw) {
|
|
8078
|
+
try {
|
|
8079
|
+
const v = JSON.parse(raw);
|
|
8080
|
+
return typeof v === "string" ? v : null;
|
|
8081
|
+
} catch {
|
|
8082
|
+
return null;
|
|
8083
|
+
}
|
|
8084
|
+
}
|
|
8085
|
+
function getToolSecret(toolName, key) {
|
|
8086
|
+
if (!validName(toolName) || !validName(key)) return null;
|
|
8087
|
+
const row = (0,_lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__/* .getMemory */ .So)(NAMESPACE, compoundKey(toolName, key));
|
|
8088
|
+
if (!row) return null;
|
|
8089
|
+
return parseStored(row.value);
|
|
8090
|
+
}
|
|
8091
|
+
function setToolSecret(toolName, key, value) {
|
|
8092
|
+
if (!validName(toolName)) throw new Error(`invalid tool name: ${toolName}`);
|
|
8093
|
+
if (!validName(key)) throw new Error(`invalid secret key: ${key}`);
|
|
8094
|
+
if (typeof value !== "string") throw new Error("secret value must be a string");
|
|
8095
|
+
(0,_lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__/* .putMemory */ .Ri)(NAMESPACE, compoundKey(toolName, key), value);
|
|
8096
|
+
}
|
|
8097
|
+
function deleteToolSecret(toolName, key) {
|
|
8098
|
+
if (!validName(toolName) || !validName(key)) return false;
|
|
8099
|
+
return (0,_lib_stores_memory__WEBPACK_IMPORTED_MODULE_0__/* .deleteMemory */ .h0)(NAMESPACE, compoundKey(toolName, key));
|
|
8100
|
+
}
|
|
8101
|
+
// Returns which declared slots have a value persisted. Never returns the
|
|
8102
|
+
// plaintext — that only escapes via `ctx.getSecret` inside the tool's own
|
|
8103
|
+
// run loop.
|
|
8104
|
+
function describeToolSecrets(toolName, slots) {
|
|
8105
|
+
if (!validName(toolName)) return slots.map((s)=>({
|
|
8106
|
+
...s,
|
|
8107
|
+
is_set: false
|
|
8108
|
+
}));
|
|
8109
|
+
return slots.map((s)=>({
|
|
8110
|
+
...s,
|
|
8111
|
+
is_set: getToolSecret(toolName, s.key) !== null
|
|
8112
|
+
}));
|
|
8113
|
+
}
|
|
8114
|
+
// Delete every persisted secret for a tool — used when an external tool
|
|
8115
|
+
// file is removed and the operator wants to clear stale credentials.
|
|
8116
|
+
function purgeToolSecrets(toolName) {
|
|
8117
|
+
if (!validName(toolName)) return 0;
|
|
8118
|
+
const prefix = `${toolName}:`;
|
|
8119
|
+
const rows = listMemory(NAMESPACE, undefined, 1000).filter((r)=>r.key.startsWith(prefix));
|
|
8120
|
+
let n = 0;
|
|
8121
|
+
for (const r of rows){
|
|
8122
|
+
if (deleteMemory(NAMESPACE, r.key)) n++;
|
|
8123
|
+
}
|
|
8124
|
+
return n;
|
|
8125
|
+
}
|
|
8126
|
+
|
|
8127
|
+
|
|
8128
|
+
/***/ }),
|
|
8129
|
+
|
|
8130
|
+
/***/ 83042:
|
|
8131
|
+
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
8132
|
+
|
|
8133
|
+
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
8134
|
+
/* harmony export */ Iz: () => (/* binding */ listThreadsByAgent),
|
|
8135
|
+
/* harmony export */ KX: () => (/* binding */ deleteThread),
|
|
8136
|
+
/* harmony export */ Mi: () => (/* binding */ listThreads),
|
|
8137
|
+
/* harmony export */ Nn: () => (/* binding */ getMessagesAfter),
|
|
8138
|
+
/* harmony export */ Nw: () => (/* binding */ createThread),
|
|
8139
|
+
/* harmony export */ S0: () => (/* binding */ getRecentMessagesWindow),
|
|
8140
|
+
/* harmony export */ VL: () => (/* binding */ getMessages),
|
|
8141
|
+
/* harmony export */ az: () => (/* binding */ clearThreadMessages),
|
|
8142
|
+
/* harmony export */ fG: () => (/* binding */ getThread),
|
|
8143
|
+
/* harmony export */ mI: () => (/* binding */ touchThread),
|
|
8144
|
+
/* harmony export */ qI: () => (/* binding */ getMessagesPage),
|
|
8145
|
+
/* harmony export */ tj: () => (/* binding */ addMessage),
|
|
8146
|
+
/* harmony export */ xH: () => (/* binding */ getOrCreateAgentThread)
|
|
8147
|
+
/* harmony export */ });
|
|
8148
|
+
/* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(77598);
|
|
8149
|
+
/* harmony import */ var node_crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(node_crypto__WEBPACK_IMPORTED_MODULE_0__);
|
|
8150
|
+
/* harmony import */ var _lib_db__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(46);
|
|
8151
|
+
/* harmony import */ var _lib_embeddings__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21839);
|
|
8152
|
+
|
|
8153
|
+
|
|
8154
|
+
|
|
8155
|
+
const now = ()=>new Date().toISOString();
|
|
8156
|
+
// Explicit column list for message reads — omits `embedding` (~20KB of
|
|
8157
|
+
// JSON-encoded float[] per row) which only the embeddings module reads.
|
|
8158
|
+
// Avoids dragging it through the chat-history result set on every call.
|
|
8159
|
+
const MSG_COLS_SQL = "SELECT msg_id, thread_id, role, content, created_at, tool_events, category FROM messages";
|
|
8160
|
+
function listThreads(limit = 50, offset = 0) {
|
|
8161
|
+
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads ORDER BY updated_at DESC LIMIT ? OFFSET ?").all(limit, offset);
|
|
8162
|
+
}
|
|
8163
|
+
function listThreadsByAgent(agent_id, limit = 50) {
|
|
8164
|
+
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads WHERE agent_id=? ORDER BY updated_at DESC LIMIT ?").all(agent_id, limit);
|
|
8165
|
+
}
|
|
8166
|
+
function getThread(thread_id) {
|
|
8167
|
+
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads WHERE thread_id=?").get(thread_id) ?? null;
|
|
8168
|
+
}
|
|
8169
|
+
function createThread(agent_id, title) {
|
|
8170
|
+
const t = now();
|
|
8171
|
+
const thread_id = (0,node_crypto__WEBPACK_IMPORTED_MODULE_0__.randomUUID)();
|
|
8172
|
+
(0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("INSERT INTO threads (thread_id,agent_id,title,created_at,updated_at,message_count) VALUES (?,?,?,?,?,0)").run(thread_id, agent_id, title ?? null, t, t);
|
|
8173
|
+
return {
|
|
8174
|
+
thread_id,
|
|
8175
|
+
agent_id,
|
|
8176
|
+
title: title ?? null,
|
|
8177
|
+
created_at: t,
|
|
8178
|
+
updated_at: t,
|
|
8179
|
+
message_count: 0
|
|
8180
|
+
};
|
|
8181
|
+
}
|
|
8182
|
+
function deleteThread(thread_id) {
|
|
8183
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
8184
|
+
db.prepare("DELETE FROM messages WHERE thread_id=?").run(thread_id);
|
|
8185
|
+
const r = db.prepare("DELETE FROM threads WHERE thread_id=?").run(thread_id);
|
|
8186
|
+
return r.changes > 0;
|
|
8187
|
+
}
|
|
8188
|
+
function getMessages(thread_id) {
|
|
8189
|
+
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare(MSG_COLS_SQL + " WHERE thread_id=? ORDER BY created_at ASC").all(thread_id);
|
|
8190
|
+
}
|
|
8191
|
+
// Pull the latest N messages within a time window. Used to build the LLM
|
|
8192
|
+
// context — keeps prompt size bounded as threads grow indefinitely.
|
|
8193
|
+
// limit: 0 or negative = unlimited
|
|
8194
|
+
// sinceISO: undefined = no time bound
|
|
8195
|
+
// Returns chronological order (oldest first) so it can be appended to the prompt directly.
|
|
8196
|
+
function getRecentMessagesWindow(thread_id, limit, sinceISO) {
|
|
8197
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
8198
|
+
const params = [
|
|
8199
|
+
thread_id
|
|
8200
|
+
];
|
|
8201
|
+
let sql = MSG_COLS_SQL + " WHERE thread_id=?";
|
|
8202
|
+
if (sinceISO) {
|
|
8203
|
+
sql += " AND created_at >= ?";
|
|
8204
|
+
params.push(sinceISO);
|
|
8205
|
+
}
|
|
8206
|
+
sql += " ORDER BY created_at DESC";
|
|
8207
|
+
if (limit > 0) {
|
|
8208
|
+
sql += " LIMIT ?";
|
|
8209
|
+
params.push(limit);
|
|
8210
|
+
}
|
|
8211
|
+
const rows = db.prepare(sql).all(...params);
|
|
8212
|
+
return rows.reverse();
|
|
8213
|
+
}
|
|
8214
|
+
// Forward-fetch — return messages strictly newer than `afterISO`, oldest
|
|
8215
|
+
// first, capped at `limit`. Used by the chat view to pull only the
|
|
8216
|
+
// freshly-persisted user+assistant pair after a run completes, instead of
|
|
8217
|
+
// re-fetching the whole most-recent page.
|
|
8218
|
+
function getMessagesAfter(thread_id, afterISO, limit = 50) {
|
|
8219
|
+
return (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare(MSG_COLS_SQL + " WHERE thread_id=? AND created_at > ? ORDER BY created_at ASC LIMIT ?").all(thread_id, afterISO, limit);
|
|
8220
|
+
}
|
|
8221
|
+
// Pagination for the chat UI. Returns the latest N messages strictly older
|
|
8222
|
+
// than `beforeISO` (cursor). Caller passes the oldest already-loaded message's
|
|
8223
|
+
// created_at as the cursor; first page omits beforeISO.
|
|
8224
|
+
function getMessagesPage(thread_id, limit, beforeISO) {
|
|
8225
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
8226
|
+
const params = [
|
|
8227
|
+
thread_id
|
|
8228
|
+
];
|
|
8229
|
+
let sql = MSG_COLS_SQL + " WHERE thread_id=?";
|
|
8230
|
+
if (beforeISO) {
|
|
8231
|
+
sql += " AND created_at < ?";
|
|
8232
|
+
params.push(beforeISO);
|
|
8233
|
+
}
|
|
8234
|
+
sql += " ORDER BY created_at DESC LIMIT ?";
|
|
8235
|
+
params.push(limit + 1); // fetch one extra to detect if there's more
|
|
8236
|
+
const rows = db.prepare(sql).all(...params);
|
|
8237
|
+
const has_more = rows.length > limit;
|
|
8238
|
+
return {
|
|
8239
|
+
messages: rows.slice(0, limit).reverse(),
|
|
8240
|
+
has_more
|
|
8241
|
+
};
|
|
8242
|
+
}
|
|
8243
|
+
function addMessage(thread_id, role, content, toolEvents, category = null) {
|
|
8244
|
+
const msg_id = (0,node_crypto__WEBPACK_IMPORTED_MODULE_0__.randomUUID)();
|
|
8245
|
+
const t = now();
|
|
8246
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
8247
|
+
const toolEventsJson = toolEvents && toolEvents.length > 0 ? JSON.stringify(toolEvents) : null;
|
|
8248
|
+
db.prepare("INSERT INTO messages (msg_id,thread_id,role,content,created_at,tool_events,category) VALUES (?,?,?,?,?,?,?)").run(msg_id, thread_id, role, content, t, toolEventsJson, category);
|
|
8249
|
+
db.prepare("UPDATE threads SET message_count=message_count+1 WHERE thread_id=?").run(thread_id);
|
|
8250
|
+
// Best-effort: embed the message so semantic recall can pull it back later.
|
|
8251
|
+
// Skip empty / very short content (greetings have no useful signal).
|
|
8252
|
+
if (content.trim().length >= 12) {
|
|
8253
|
+
(0,_lib_embeddings__WEBPACK_IMPORTED_MODULE_2__/* .embedOne */ ._L)(content).then((vec)=>{
|
|
8254
|
+
if (vec) {
|
|
8255
|
+
(0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("UPDATE messages SET embedding=? WHERE msg_id=?").run(JSON.stringify(vec), msg_id);
|
|
8256
|
+
}
|
|
8257
|
+
}).catch(()=>{});
|
|
8258
|
+
}
|
|
8259
|
+
return {
|
|
8260
|
+
msg_id,
|
|
8261
|
+
thread_id,
|
|
8262
|
+
role,
|
|
8263
|
+
content,
|
|
8264
|
+
created_at: t,
|
|
8265
|
+
tool_events: toolEventsJson,
|
|
8266
|
+
category
|
|
8267
|
+
};
|
|
8268
|
+
}
|
|
8269
|
+
function getOrCreateAgentThread(agentId) {
|
|
8270
|
+
const existing = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("SELECT * FROM threads WHERE agent_id=? LIMIT 1").get(agentId);
|
|
8271
|
+
if (existing) return existing;
|
|
8272
|
+
return createThread(agentId);
|
|
8273
|
+
}
|
|
8274
|
+
function clearThreadMessages(threadId) {
|
|
8275
|
+
const db = (0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)();
|
|
8276
|
+
db.prepare("DELETE FROM messages WHERE thread_id=?").run(threadId);
|
|
8277
|
+
db.prepare("UPDATE threads SET message_count=0, updated_at=? WHERE thread_id=?").run(new Date().toISOString(), threadId);
|
|
8278
|
+
}
|
|
8279
|
+
function touchThread(thread_id, firstMsg) {
|
|
8280
|
+
const t = now();
|
|
8281
|
+
(0,_lib_db__WEBPACK_IMPORTED_MODULE_1__/* .getDb */ .Lf)().prepare("UPDATE threads SET updated_at=?, title=COALESCE(title,?) WHERE thread_id=?").run(t, firstMsg ? firstMsg.slice(0, 80) : null, thread_id);
|
|
8282
|
+
}
|
|
8283
|
+
|
|
8284
|
+
|
|
8032
8285
|
/***/ }),
|
|
8033
8286
|
|
|
8034
8287
|
/***/ 93348:
|