mixdog 1.0.3 → 1.0.5
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/README.md +10 -5
- package/package.json +18 -17
- package/scripts/gate-local.mjs +93 -0
- package/scripts/lib/gate-scheduler.mjs +24 -0
- package/scripts/lib/run-node-tests.mjs +5 -1
- package/scripts/release-paths.mjs +22 -1
- package/scripts/test-direct.mjs +2 -1
- package/scripts/test.mjs +3 -1
- package/src/defaults/agents.json +0 -12
- package/src/defaults/mixdog-config.template.json +1 -2
- package/src/defaults/skills/docx/SKILL.md +7 -4
- package/src/defaults/skills/docx/references/html.md +46 -0
- package/src/defaults/skills/docx/references/native-authoring.md +18 -4
- package/src/defaults/skills/goal-management/SKILL.md +2 -2
- package/src/defaults/skills/pdf/SKILL.md +10 -2
- package/src/defaults/skills/pdf/references/html.md +64 -0
- package/src/defaults/skills/pptx/references/html.md +1 -1
- package/src/defaults/skills/xlsx/SKILL.md +7 -3
- package/src/defaults/skills/xlsx/references/html.md +40 -0
- package/src/defaults/skills/xlsx/references/report-design.md +21 -4
- package/src/runtime/agent/orchestrator/agent-runtime/agent-dispatch/preset.mjs +1 -1
- package/src/runtime/agent/orchestrator/agent-runtime/cache-strategy.mjs +2 -3
- package/src/runtime/agent/orchestrator/internal-agents.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +6 -5
- package/src/runtime/agent/orchestrator/runtime-core/goal-tool-defs.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +50 -9
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +28 -1
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +34 -8
- package/src/runtime/agent/orchestrator/session/tool-result-offload.mjs +10 -2
- package/src/runtime/agent/orchestrator/session/transcript-restore/agent-envelope.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +1 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs +3 -1
- package/src/runtime/attachments/pdf-extract.mjs +7 -3
- package/src/runtime/computer-bridge/client.mjs +1 -1
- package/src/runtime/memory/index.mjs +4 -15
- package/src/runtime/memory/lib/core-memory-store.mjs +1 -1
- package/src/runtime/memory/lib/cycle-llm-adapters.mjs +0 -2
- package/src/runtime/memory/lib/cycle-scheduler/backlog-probe.mjs +3 -11
- package/src/runtime/memory/lib/cycle-scheduler/health-ledger.mjs +1 -3
- package/src/runtime/memory/lib/cycle-scheduler/scheduled-enqueue.mjs +1 -11
- package/src/runtime/memory/lib/cycle-scheduler/tick-loop.mjs +0 -2
- package/src/runtime/memory/lib/cycle-scheduler.mjs +4 -13
- package/src/runtime/memory/lib/cycle-signatures.mjs +0 -6
- package/src/runtime/memory/lib/cycle1/cycle1-rows.mjs +1 -1
- package/src/runtime/memory/lib/cycle1/cycle1-window.mjs +2 -2
- package/src/runtime/memory/lib/embedding-reindex.mjs +1 -1
- package/src/runtime/memory/lib/http-router/lifecycle-routes.mjs +0 -1
- package/src/runtime/memory/lib/memory-action-handlers/cycle-actions.mjs +7 -52
- package/src/runtime/memory/lib/memory-action-handlers/cycle-backfill-action.mjs +6 -22
- package/src/runtime/memory/lib/memory-action-handlers/cycle-rebuild-action.mjs +10 -17
- package/src/runtime/memory/lib/memory-action-handlers/maintenance-actions.mjs +1 -3
- package/src/runtime/memory/lib/memory-action-handlers/manage-actions.mjs +2 -4
- package/src/runtime/memory/lib/memory-action-handlers.mjs +2 -4
- package/src/runtime/memory/lib/memory-cycle-requests.mjs +1 -1
- package/src/runtime/memory/lib/{memory-cycle2-shared.mjs → memory-cycle-shared.mjs} +14 -16
- package/src/runtime/memory/lib/memory-cycle.mjs +3 -2
- package/src/runtime/memory/lib/memory-cycle1.mjs +1 -1
- package/src/runtime/memory/lib/memory-embed.mjs +14 -1
- package/src/runtime/memory/lib/memory-ops-policy.mjs +8 -11
- package/src/runtime/memory/lib/memory-schema/entries.mjs +0 -1
- package/src/runtime/memory/lib/memory.mjs +2 -6
- package/src/runtime/memory/lib/pg/adapter.mjs +1 -1
- package/src/runtime/memory/lib/query-handlers.mjs +1 -1
- package/src/runtime/memory/lib/query-hybrid-search.mjs +1 -1
- package/src/runtime/memory/lib/query-maintenance-handlers.mjs +0 -6
- package/src/runtime/memory/lib/recall-format.mjs +1 -1
- package/src/runtime/office/authoring/docx-html-build.mjs +375 -0
- package/src/runtime/office/authoring/docx-html-measure.mjs +561 -0
- package/src/runtime/office/authoring/docx-html-runner.mjs +102 -0
- package/src/runtime/office/authoring/html-browser.mjs +61 -0
- package/src/runtime/office/authoring/html-document-author.mjs +181 -0
- package/src/runtime/office/authoring/html-source-drift.mjs +36 -0
- package/src/runtime/office/authoring/pdf-author-action.mjs +266 -0
- package/src/runtime/office/authoring/pdf-html-charts.mjs +379 -0
- package/src/runtime/office/authoring/pdf-html-runner.mjs +317 -0
- package/src/runtime/office/authoring/pptx-author-action.mjs +44 -22
- package/src/runtime/office/authoring/pptx-author-session.mjs +12 -6
- package/src/runtime/office/authoring/pptx-html-build.mjs +23 -4
- package/src/runtime/office/authoring/pptx-html-measure.mjs +38 -44
- package/src/runtime/office/authoring/pptx-html-runner.mjs +18 -3
- package/src/runtime/office/authoring/pptx-receipt.mjs +39 -31
- package/src/runtime/office/authoring/pptx-review-artifacts.mjs +9 -1
- package/src/runtime/office/authoring/pptx-script-runner.mjs +6 -2
- package/src/runtime/office/authoring/xlsx-html-build.mjs +365 -0
- package/src/runtime/office/authoring/xlsx-html-measure.mjs +257 -0
- package/src/runtime/office/authoring/xlsx-html-runner.mjs +139 -0
- package/src/runtime/office/capabilities-catalog.mjs +8 -0
- package/src/runtime/office/capabilities-signatures.mjs +18 -6
- package/src/runtime/office/capabilities.mjs +26 -1
- package/src/runtime/office/com/office-com-host.ps1 +133 -17
- package/src/runtime/office/core/office-actions-batch.mjs +16 -1
- package/src/runtime/office/core/office-actions-inspect.mjs +3 -2
- package/src/runtime/office/core/office-actions-lifecycle.mjs +6 -2
- package/src/runtime/office/core/office-actions-render.mjs +4 -1
- package/src/runtime/office/core/office-finalize/review-stage.mjs +15 -2
- package/src/runtime/office/core/office-qa/design-review-stage.mjs +9 -0
- package/src/runtime/office/core/office-session-dispatch.mjs +3 -0
- package/src/runtime/office/core/office-sessionless-actions.mjs +7 -2
- package/src/runtime/office/core/office-sessions.mjs +19 -2
- package/src/runtime/office/pdf/pdf-writer.mjs +1 -1
- package/src/runtime/office/portable/docx-formatting.mjs +21 -0
- package/src/runtime/office/portable/ooxml-validator.mjs +22 -1
- package/src/runtime/office/portable/portable-chart.mjs +10 -2
- package/src/runtime/office/portable/portable-docx-edits.mjs +12 -6
- package/src/runtime/office/portable/portable-docx-operations.mjs +75 -1
- package/src/runtime/office/portable/portable-docx-xml.mjs +49 -6
- package/src/runtime/office/portable/portable-docx.mjs +2 -0
- package/src/runtime/office/portable/portable-snapshot-docx.mjs +2 -0
- package/src/runtime/office/portable/portable-validation.mjs +6 -3
- package/src/runtime/office/portable/portable-xlsx-cell-values.mjs +87 -0
- package/src/runtime/office/portable/portable-xlsx-charts.mjs +55 -13
- package/src/runtime/office/portable/portable-xlsx-sheet-edits.mjs +1 -1
- package/src/runtime/office/portable/xlsx-contract.mjs +82 -3
- package/src/runtime/office/quality/assurance-checklist.mjs +2 -2
- package/src/runtime/office/quality/assurance-rendered.mjs +27 -1
- package/src/runtime/office/quality/assurance-structure-docx.mjs +44 -0
- package/src/runtime/office/quality/assurance-structure-pptx.mjs +24 -6
- package/src/runtime/office/quality/assurance-structure-xlsx.mjs +50 -1
- package/src/runtime/office/quality/design-review-critique.mjs +3 -2
- package/src/runtime/office/quality/document-brief.mjs +44 -0
- package/src/runtime/office/quality/inline-audit.mjs +7 -2
- package/src/runtime/office/quality/quality-pipeline.mjs +9 -1
- package/src/runtime/office/tool-defs.mjs +2 -2
- package/src/runtime/shared/llm/quota-value-estimate.mjs +317 -0
- package/src/runtime/shared/llm/usage-ledger-quota.mjs +266 -63
- package/src/runtime/shared/llm/usage-ledger-rollup.mjs +35 -0
- package/src/runtime/shared/llm/usage-ledger-worker.mjs +2 -1
- package/src/runtime/shared/llm/usage-ledger.mjs +10 -1
- package/src/runtime/shared/provider-accounts.mjs +11 -1
- package/src/runtime/shared/statusline/statusline-segments.mjs +4 -4
- package/src/runtime/shared/tool-execution-contract.mjs +1 -1
- package/src/runtime/shared/wait-until.test-support.mjs +33 -0
- package/src/session-runtime/boot/apis.mjs +1 -1
- package/src/session-runtime/services/channel-admin.mjs +4 -3
- package/src/session-runtime/services/usage-stats-model.mjs +22 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +6 -1
- package/src/session-runtime/turn/session-ops.mjs +15 -9
- package/src/session-runtime/usage-stats-api.mjs +34 -2
- package/src/standalone/agent-dispatch-broker.mjs +1 -1
- package/src/standalone/local-session-runtime.mjs +488 -0
- package/src/standalone/session-protocol.mjs +1 -0
- package/src/standalone/session-runtime-inline-host.mjs +1 -1
- package/src/tui/hooks/useSession.mjs +1 -1
- package/src/tui/session/session-api/commands.mjs +1 -1
- package/src/tui/session/session-api/integrations.mjs +3 -0
- package/src/tui/session/session-flow/auto-clear.mjs +6 -7
- package/src/tui/session/tool-card-results.mjs +1 -1
- package/src/tui/session/turn.mjs +5 -0
- package/src/tui/session-local.mjs +3 -488
- package/src/tui/session.mjs +1 -1
- package/src/ui/statusline-agents.mjs +0 -1
- package/src/rules/agent/41-cycle2-agent.md +0 -24
- package/src/runtime/memory/lib/cycle-scheduler/cycle2-runs.mjs +0 -120
- package/src/runtime/memory/lib/memory-cycle2-mutations.mjs +0 -110
- package/src/runtime/memory/lib/memory-cycle2-quarantine.mjs +0 -99
- package/src/runtime/memory/lib/memory-cycle2-review.mjs +0 -240
- package/src/runtime/memory/lib/memory-cycle2.mjs +0 -191
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
emitCompactEvent,
|
|
16
16
|
resolveHandoffSummaryModel,
|
|
17
17
|
} from './loop/compact-policy.mjs';
|
|
18
|
-
import { runFreshContextCompact } from './loop/fresh-context.mjs';
|
|
18
|
+
import { previewFreshContextCompaction, runFreshContextCompact } from './loop/fresh-context.mjs';
|
|
19
19
|
import { estimateMessagesTokensSafe } from './loop/compact-debug.mjs';
|
|
20
20
|
import { messagesArrayChanged } from './loop/tool-helpers.mjs';
|
|
21
21
|
import { normalizeUsage, addUsage } from './loop/usage.mjs';
|
|
@@ -72,8 +72,8 @@ function transcriptPrefixHash(messages) {
|
|
|
72
72
|
// same event. A pending reactive-overflow retry makes THIS compact pass the
|
|
73
73
|
// recovery from a provider overflow refusal, not the proactive pressure
|
|
74
74
|
// trigger — the emitted events are tagged so telemetry can tell them apart.
|
|
75
|
-
//
|
|
76
|
-
//
|
|
75
|
+
// Cache expiry arms a cold-send compact regardless of the threshold, but all
|
|
76
|
+
// proactive triggers still need a smaller predicted transcript.
|
|
77
77
|
function preSendCompactDecision(state, compactPolicy) {
|
|
78
78
|
const { messages, sessionRef } = state;
|
|
79
79
|
const messageTokensEst = estimateMessagesTokensSafe(messages);
|
|
@@ -84,24 +84,45 @@ function preSendCompactDecision(state, compactPolicy) {
|
|
|
84
84
|
sessionRef,
|
|
85
85
|
});
|
|
86
86
|
const cacheExpired = shouldCompactForExpiredAgentCache(sessionRef, state.opts);
|
|
87
|
-
const
|
|
87
|
+
const mediaPressure = shouldCompactForRequestMedia(messages);
|
|
88
|
+
const requireReduction = !reactivePending && !mediaPressure;
|
|
89
|
+
let shouldCompact =
|
|
88
90
|
state.skipProactiveCompact !== true &&
|
|
89
91
|
(cacheExpired ||
|
|
90
|
-
|
|
92
|
+
mediaPressure ||
|
|
91
93
|
shouldCompactForSession(messageTokensEst, compactPolicy, {
|
|
92
94
|
forceReactive: reactivePending,
|
|
93
95
|
messages,
|
|
94
96
|
sessionRef,
|
|
95
97
|
pressureTokens,
|
|
96
98
|
}));
|
|
99
|
+
const compactBudgetTokens = shouldCompact
|
|
100
|
+
? compactTargetBudget({ ...compactPolicy, pressureTokens }) || compactPolicy.boundaryTokens
|
|
101
|
+
: compactPolicy.boundaryTokens;
|
|
102
|
+
if (shouldCompact && requireReduction) {
|
|
103
|
+
// Price the same Goal reminder the real pass will attach, without marking
|
|
104
|
+
// or acknowledging it on a session whose compaction may be skipped.
|
|
105
|
+
const previewSession = { ...sessionRef };
|
|
106
|
+
markPendingGoalReminder(previewSession, 'compaction');
|
|
107
|
+
const reminder = snapshotPendingGoalReminder(previewSession);
|
|
108
|
+
shouldCompact = previewFreshContextCompaction({
|
|
109
|
+
sessionRef,
|
|
110
|
+
messages,
|
|
111
|
+
compactBudgetTokens,
|
|
112
|
+
compactPolicy,
|
|
113
|
+
sessionId: state.sessionId,
|
|
114
|
+
provider: state.provider,
|
|
115
|
+
goalReminderText: reminder?.content || '',
|
|
116
|
+
activeTurn: true,
|
|
117
|
+
}).reducesTokens;
|
|
118
|
+
}
|
|
97
119
|
return {
|
|
98
120
|
messageTokensEst,
|
|
99
121
|
pressureTokens,
|
|
100
122
|
shouldCompact,
|
|
123
|
+
requireReduction,
|
|
101
124
|
compactTrigger: reactivePending ? 'reactive' : cacheExpired ? 'cache_expired' : 'auto',
|
|
102
|
-
compactBudgetTokens
|
|
103
|
-
? compactTargetBudget({ ...compactPolicy, pressureTokens }) || compactPolicy.boundaryTokens
|
|
104
|
-
: compactPolicy.boundaryTokens,
|
|
125
|
+
compactBudgetTokens,
|
|
105
126
|
};
|
|
106
127
|
}
|
|
107
128
|
|
|
@@ -243,6 +264,7 @@ async function compactTranscript(ctx, run) {
|
|
|
243
264
|
sendOpts: opts,
|
|
244
265
|
goalReminderText: run.inlineGoalReminder?.content || '',
|
|
245
266
|
activeTurn: true,
|
|
267
|
+
requireReduction: decision.requireReduction,
|
|
246
268
|
});
|
|
247
269
|
const freshMessages = Array.isArray(run.freshContextResult?.messages) ? run.freshContextResult.messages : null;
|
|
248
270
|
if (!freshMessages) throw new Error('fresh-context compact produced no messages');
|
|
@@ -461,6 +483,10 @@ async function compactBeforeSend(ctx) {
|
|
|
461
483
|
throwCompactFailure(ctx, run, compactErr);
|
|
462
484
|
}
|
|
463
485
|
await setStage(opts, 'requesting');
|
|
486
|
+
if (run.freshContextResult?.skipped) {
|
|
487
|
+
compactTelemetry(ctx, 'pre_send_check', { skipReason: 'no_token_reduction' });
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
464
490
|
ctx.compactChanged = messagesArrayChanged(messages, run.compacted);
|
|
465
491
|
if (ctx.compactChanged) adoptCompactedTranscript(ctx, run);
|
|
466
492
|
reportCompactOutcome(ctx, run);
|
|
@@ -190,10 +190,12 @@ function buildPreview(text, maxChars = TOOL_RESULT_PREVIEW_CHARS) {
|
|
|
190
190
|
};
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
function artifactMeta(sessionId, toolCallId, channel, content) {
|
|
193
|
+
function artifactMeta(sessionId, toolCallId, channel, content, preview = false) {
|
|
194
194
|
if (!sessionId || !toolCallId || typeof content !== 'string') return null;
|
|
195
195
|
const sha256 = createHash('sha256').update(content, 'utf8').digest('hex');
|
|
196
|
-
const dir =
|
|
196
|
+
const dir = preview
|
|
197
|
+
? join(getPluginData(), 'tool-results', safeSessionSegment(sessionId))
|
|
198
|
+
: ensureToolResultsDir(sessionId);
|
|
197
199
|
return {
|
|
198
200
|
stream: channel,
|
|
199
201
|
path: join(dir, artifactIdentity(sha256)),
|
|
@@ -208,6 +210,12 @@ function artifactShapeMatches(meta, info) {
|
|
|
208
210
|
return info.isFile() && info.size === meta.bytes;
|
|
209
211
|
}
|
|
210
212
|
|
|
213
|
+
// Same content-addressed reference as persistence, without creating a directory
|
|
214
|
+
// or a file. Compaction previews must not archive a transcript they will keep.
|
|
215
|
+
export function previewToolResultArtifact({ sessionId, toolCallId, channel = 'result', content } = {}) {
|
|
216
|
+
return artifactMeta(sessionId, toolCallId, channel, content, true);
|
|
217
|
+
}
|
|
218
|
+
|
|
211
219
|
export function persistToolResultArtifactSync({ sessionId, toolCallId, channel = 'result', content } = {}) {
|
|
212
220
|
let meta;
|
|
213
221
|
try {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* src/tui/session/agent-envelope.mjs - parse agent/background-task/shell
|
|
3
3
|
* notification envelopes into synthetic tool-item shapes, and derive
|
|
4
4
|
* status/result text. parseBackgroundTaskEnvelope
|
|
5
|
-
* remains part of session-
|
|
5
|
+
* remains part of local-session-runtime.mjs's public surface.
|
|
6
6
|
*/
|
|
7
7
|
import { isBackgroundErrorOnlyBody } from '../../../../shared/err-text.mjs';
|
|
8
8
|
import { textBetweenTag } from '../../../../shared/tool-result-summary.mjs';
|
|
@@ -619,7 +619,9 @@ export function preflightPowerShellHygiene(command, { shellType, shellName } = {
|
|
|
619
619
|
const POWERSHELL_ONLY_SYNTAX = [
|
|
620
620
|
/\$(?:null|true|false|env:|_\b|args\b|host\b|profile\b|pwd\b|psversiontable\b|psscriptroot\b|lastexitcode\b|erroractionpreference\b)/i,
|
|
621
621
|
/\$[A-Za-z_]\w*\s*=/,
|
|
622
|
-
|
|
622
|
+
// A verb joined to the previous character by a path/word char (`mixdog-test-scratch`, `a/test-x`) is part of a
|
|
623
|
+
// path or name, not a cmdlet.
|
|
624
|
+
/(?<![\w\-./\\:])(?:get|set|new|remove|select|where|foreach|invoke|out|write|start|stop|test|measure|sort|join|split|convert|import|export|add|copy|move|rename|resolve|compare|clear|push|pop)-[A-Za-z]+\b/i,
|
|
623
625
|
/\[[A-Za-z_][\w.]*\]::/,
|
|
624
626
|
/(?:^|\s)-(?:eq|ne|gt|lt|ge|le|match|notmatch|like|notlike|contains|replace|not|and|or|is|as|ErrorAction|Recurse|Force|Encoding|TotalCount|Tail|Pattern|Path|LiteralPath)\b/,
|
|
625
627
|
/2>\s*\$/,
|
|
@@ -48,13 +48,17 @@ function pageBodyText(content) {
|
|
|
48
48
|
if (typeof item?.str !== 'string') continue;
|
|
49
49
|
if (item.str) {
|
|
50
50
|
const placement = runPlacement(item);
|
|
51
|
+
// A run on another baseline is another line even when the writer marked no line end (a browser's
|
|
52
|
+
// print does not): "784" over its label read as "784office". A baseline shift under half the
|
|
53
|
+
// smaller run's size (a superscript, a mixed-size run) stays on the line.
|
|
54
|
+
const shift = placement && cursor ? Math.abs(placement.line - cursor.line) : 0;
|
|
55
|
+
const newLine = shift > Math.min(placement?.size || 0, cursor?.size || 0) * 0.5;
|
|
56
|
+
if (newLine && body && !body.endsWith('\n')) body += '\n';
|
|
51
57
|
// A writer splits one word into several runs for kerning, and a
|
|
52
58
|
// Korean line into a run per token; joining those with a space
|
|
53
59
|
// invents "2026 년". Only a gap the page itself leaves is a space.
|
|
54
60
|
const separated =
|
|
55
|
-
placement && cursor && placement.
|
|
56
|
-
? placement.start - cursor.end > cursor.size * 0.22
|
|
57
|
-
: !placement || !cursor;
|
|
61
|
+
placement && cursor && !newLine ? placement.start - cursor.end > cursor.size * 0.22 : !placement || !cursor;
|
|
58
62
|
const glued = !body || body.endsWith('\n') || body.endsWith(' ') || item.str.startsWith(' ') || !separated;
|
|
59
63
|
body += (glued ? '' : ' ') + item.str;
|
|
60
64
|
cursor = placement;
|
|
@@ -411,7 +411,7 @@ function computerToolResult(value, args) {
|
|
|
411
411
|
}
|
|
412
412
|
return {
|
|
413
413
|
content,
|
|
414
|
-
...(canonicalComputerResultIsError(text, args) ? { isError: true } : {}),
|
|
414
|
+
...(value.isError === true || canonicalComputerResultIsError(text, args) ? { isError: true } : {}),
|
|
415
415
|
};
|
|
416
416
|
}
|
|
417
417
|
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
shutdownEmbeddingProvider,
|
|
52
52
|
warmupEmbeddingProvider,
|
|
53
53
|
} from './lib/embedding-provider.mjs';
|
|
54
|
-
import { runCycle1,
|
|
54
|
+
import { runCycle1, parseInterval, flushEmbeddingDirty, flushRawEmbeddings } from './lib/memory-cycle.mjs';
|
|
55
55
|
import { callAgentDispatch } from './lib/agent-ipc.mjs';
|
|
56
56
|
import {
|
|
57
57
|
cancelCoalescedCycleRetries,
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
import { writeJsonAtomicSync } from '../shared/atomic-file.mjs';
|
|
74
74
|
import { safeIpcSend } from '../shared/safe-ipc-send.mjs';
|
|
75
75
|
import { resolvePluginData, mixdogHome } from '../shared/plugin-paths.mjs';
|
|
76
|
-
import { scheduledCycle1Signature
|
|
76
|
+
import { scheduledCycle1Signature } from './lib/cycle-signatures.mjs';
|
|
77
77
|
import { createTranscriptIngest } from './lib/transcript-ingest.mjs';
|
|
78
78
|
import { createCycleLlmAdapters } from './lib/cycle-llm-adapters.mjs';
|
|
79
79
|
import { createCycleScheduler } from './lib/cycle-scheduler.mjs';
|
|
@@ -333,20 +333,15 @@ async function getCycleLastRun() {
|
|
|
333
333
|
const obj = JSON.parse(raw);
|
|
334
334
|
return {
|
|
335
335
|
cycle1: Number(obj.cycle1) || 0,
|
|
336
|
-
cycle2: Number(obj.cycle2) || 0,
|
|
337
336
|
// Heartbeat (every attempt, success or skip) is tracked separately from
|
|
338
337
|
// the success timestamps above so a long string of failed/skipped runs
|
|
339
338
|
// cannot disguise itself as a healthy keeper.
|
|
340
339
|
cycle1_heartbeat: Number(obj.cycle1_heartbeat) || 0,
|
|
341
|
-
// Last cycle2 failure message; cleared to '' on success.
|
|
342
|
-
cycle2_last_error: typeof obj.cycle2_last_error === 'string' ? obj.cycle2_last_error : '',
|
|
343
340
|
};
|
|
344
341
|
} catch {
|
|
345
342
|
return {
|
|
346
343
|
cycle1: 0,
|
|
347
|
-
cycle2: 0,
|
|
348
344
|
cycle1_heartbeat: 0,
|
|
349
|
-
cycle2_last_error: '',
|
|
350
345
|
};
|
|
351
346
|
}
|
|
352
347
|
}
|
|
@@ -373,7 +368,7 @@ async function refreshCoreMemorySnapshot(reason = 'mutation') {
|
|
|
373
368
|
const CYCLE_STATE_FILE = path.join(DATA_DIR, 'memory-cycle-state.json');
|
|
374
369
|
|
|
375
370
|
const _cycleLlmAdapters = createCycleLlmAdapters({ callAgentDispatch });
|
|
376
|
-
const { getCycle1CallLlm
|
|
371
|
+
const { getCycle1CallLlm } = _cycleLlmAdapters;
|
|
377
372
|
|
|
378
373
|
const _cycleScheduler = createCycleScheduler({
|
|
379
374
|
getDb: () => db,
|
|
@@ -388,9 +383,7 @@ const _cycleScheduler = createCycleScheduler({
|
|
|
388
383
|
readMainConfig,
|
|
389
384
|
memoryCyclesEnabled,
|
|
390
385
|
getCycle1CallLlm,
|
|
391
|
-
getCycle2CallLlm,
|
|
392
386
|
runCycle1,
|
|
393
|
-
runCycle2,
|
|
394
387
|
parseInterval,
|
|
395
388
|
flushRawEmbeddings,
|
|
396
389
|
claimAndMarkScheduledCycle,
|
|
@@ -398,13 +391,11 @@ const _cycleScheduler = createCycleScheduler({
|
|
|
398
391
|
scheduleCoalescedCycleRetry,
|
|
399
392
|
cancelCoalescedCycleRetries,
|
|
400
393
|
scheduledCycle1Signature,
|
|
401
|
-
scheduledCycle2Signature,
|
|
402
394
|
cycleStateFile: CYCLE_STATE_FILE,
|
|
403
395
|
});
|
|
404
|
-
// Cycle1 run primitives
|
|
396
|
+
// Cycle1 run primitives used by MCP action handlers below.
|
|
405
397
|
const _startCycle1Run = _cycleScheduler.startCycle1Run;
|
|
406
398
|
const _awaitCycle1Run = _cycleScheduler.awaitCycle1Run;
|
|
407
|
-
const _finalizeCycle2Run = _cycleScheduler.finalizeCycle2Run;
|
|
408
399
|
|
|
409
400
|
// Transcript watcher lifecycle stays in the facade (owns _transcriptIngest);
|
|
410
401
|
// the cycle tick loop start/stop is delegated to the scheduler.
|
|
@@ -509,10 +500,8 @@ const _actionHandlers = createMemoryActionHandlers({
|
|
|
509
500
|
dumpSessionRootChunks,
|
|
510
501
|
awaitCycle1Run: _awaitCycle1Run,
|
|
511
502
|
startCycle1Run: _startCycle1Run,
|
|
512
|
-
finalizeCycle2Run: _finalizeCycle2Run,
|
|
513
503
|
refreshCoreMemoryFile: refreshCoreMemorySnapshot,
|
|
514
504
|
getSchedulerCycle1InFlight: () => _cycleScheduler.getCycle1InFlight(),
|
|
515
|
-
getCycle2CallLlm,
|
|
516
505
|
ingestTranscriptFile,
|
|
517
506
|
cwdFromTranscriptPath,
|
|
518
507
|
});
|
|
@@ -9,7 +9,7 @@ import { getDatabase, embeddingToSql } from './memory.mjs';
|
|
|
9
9
|
import { VALID_CATEGORY } from './memory-categories.mjs';
|
|
10
10
|
import { cachedEmbedTextBatch } from './memory-embed.mjs';
|
|
11
11
|
import { checkedConnect } from './pg/adapter.mjs';
|
|
12
|
-
import { throwIfAborted } from './memory-
|
|
12
|
+
import { throwIfAborted } from './memory-cycle-shared.mjs';
|
|
13
13
|
import { findCoreKeyRows } from './core-memory-uniqueness.mjs';
|
|
14
14
|
|
|
15
15
|
const CORE_ELEMENT_DERIVE_LENGTH = 40;
|
|
@@ -30,9 +30,7 @@ export function createCycleLlmAdapters({ callAgentDispatch }) {
|
|
|
30
30
|
// unhandled rejection that killed the memory runtime. Keep the factory
|
|
31
31
|
// contract: each getter returns the (memoized) adapter function.
|
|
32
32
|
const cycle1 = buildAdapter('cycle1-agent');
|
|
33
|
-
const cycle2 = buildAdapter('cycle2-agent');
|
|
34
33
|
return {
|
|
35
34
|
getCycle1CallLlm: () => cycle1,
|
|
36
|
-
getCycle2CallLlm: () => cycle2,
|
|
37
35
|
};
|
|
38
36
|
}
|
|
@@ -6,13 +6,6 @@ async function countRows(db, sql, params) {
|
|
|
6
6
|
return Number((await db.query(sql, params)).rows[0]?.c ?? 0);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
export function countPendingCycle2Roots(db) {
|
|
10
|
-
return countRows(
|
|
11
|
-
db,
|
|
12
|
-
`SELECT COUNT(*) c FROM entries WHERE is_root = 1 AND cycle2_reviewed_at IS NULL AND duplicate_of IS NULL`
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
9
|
// Per-tick backlog counts for the state file / statusline, the backlog
|
|
17
10
|
// warning, and the opportunistic raw-embedding flush while rows are unchunked.
|
|
18
11
|
export function createBacklogProbe({ getDb, ledger, log, flushRawEmbeddings }) {
|
|
@@ -46,10 +39,9 @@ export function createBacklogProbe({ getDb, ledger, log, flushRawEmbeddings }) {
|
|
|
46
39
|
AND (reviewed_at IS NULL OR reviewed_at < $1)`,
|
|
47
40
|
[now - CYCLE1_OMITTED_COOLDOWN_MS]
|
|
48
41
|
);
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
ledger.warn(`backlog unchunked=${unchunked} eligible=${unchunkedEligible} cycle2_pending=${cycle2Pending}`);
|
|
42
|
+
ledger.setBacklog({ unchunked, unchunked_eligible: unchunkedEligible, at: now });
|
|
43
|
+
if (unchunked > BACKLOG_WARN_PENDING) {
|
|
44
|
+
ledger.warn(`backlog unchunked=${unchunked} eligible=${unchunkedEligible}`);
|
|
53
45
|
}
|
|
54
46
|
if (unchunked > 0) flushRawEmbeddingsOnce(db);
|
|
55
47
|
} catch {
|
|
@@ -9,10 +9,9 @@ const BACKLOG_WARN_FAILURES = 5;
|
|
|
9
9
|
export function createCycleHealthLedger({ cycleStateFile, log }) {
|
|
10
10
|
const health = {
|
|
11
11
|
cycle1: { last_success_at: 0, last_error_at: 0, last_error: null, consecutive_failures: 0 },
|
|
12
|
-
cycle2: { last_success_at: 0, last_error_at: 0, last_error: null, consecutive_failures: 0 },
|
|
13
12
|
};
|
|
14
13
|
let running = null; // { cycle, started_at, pid }
|
|
15
|
-
let backlog = { unchunked: 0,
|
|
14
|
+
let backlog = { unchunked: 0, at: 0 };
|
|
16
15
|
let lastWarnAt = 0;
|
|
17
16
|
|
|
18
17
|
function write() {
|
|
@@ -74,7 +73,6 @@ export function createCycleHealthLedger({ cycleStateFile, log }) {
|
|
|
74
73
|
// state file reports 0 until the next run.
|
|
75
74
|
function hydrateSuccess(last) {
|
|
76
75
|
if (last?.cycle1 > 0 && !health.cycle1.last_success_at) health.cycle1.last_success_at = last.cycle1;
|
|
77
|
-
if (last?.cycle2 > 0 && !health.cycle2.last_success_at) health.cycle2.last_success_at = last.cycle2;
|
|
78
76
|
write();
|
|
79
77
|
}
|
|
80
78
|
|
|
@@ -5,9 +5,7 @@ export function createScheduledEnqueue({
|
|
|
5
5
|
getConfig,
|
|
6
6
|
claimAndMarkScheduledCycle,
|
|
7
7
|
scheduledCycle1Signature,
|
|
8
|
-
scheduledCycle2Signature,
|
|
9
8
|
scheduleScheduledCycle1,
|
|
10
|
-
scheduleScheduledCycle2,
|
|
11
9
|
}) {
|
|
12
10
|
function periodicCycle1Config() {
|
|
13
11
|
return {
|
|
@@ -38,13 +36,5 @@ export function createScheduledEnqueue({
|
|
|
38
36
|
}
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
|
|
42
|
-
const config = getConfig()?.cycle2 || {};
|
|
43
|
-
const signature = scheduledCycle2Signature(config);
|
|
44
|
-
if (await claimScheduledSlot('cycle2', intervalMs, signature, config)) {
|
|
45
|
-
scheduleScheduledCycle2(config, signature);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return { periodicCycle1Config, enqueueScheduledCycle1, enqueueScheduledCycle2 };
|
|
39
|
+
return { periodicCycle1Config, enqueueScheduledCycle1 };
|
|
50
40
|
}
|
|
@@ -30,12 +30,10 @@ export function createCycleTickLoop({
|
|
|
30
30
|
setConfig(mainConfig);
|
|
31
31
|
const cyclesOn = memoryCyclesEnabled();
|
|
32
32
|
const cycle1Ms = parseInterval(mainConfig?.cycle1?.interval || '10m');
|
|
33
|
-
const cycle2Ms = parseInterval(mainConfig?.cycle2?.interval || '1h');
|
|
34
33
|
const now = Date.now();
|
|
35
34
|
const last = await getCycleLastRun();
|
|
36
35
|
if (cyclesOn) {
|
|
37
36
|
if (periodicCycleDue(last.cycle1, startedAt, cycle1Ms, now)) await enqueue.enqueueScheduledCycle1(cycle1Ms);
|
|
38
|
-
if (periodicCycleDue(last.cycle2, startedAt, cycle2Ms, now)) await enqueue.enqueueScheduledCycle2(cycle2Ms);
|
|
39
37
|
}
|
|
40
38
|
await probeBacklog(now);
|
|
41
39
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Owns the mutually-referential cycle machinery: the cycle-health ledger and
|
|
4
4
|
// run-state file, the cycle1 outer coalesce layer, the scheduled enqueue /
|
|
5
|
-
// retry paths for cycle1
|
|
5
|
+
// retry paths for cycle1, checkCycles(), and the self-rescheduling tick
|
|
6
6
|
// loop. The phases live under cycle-scheduler/. index.mjs keeps lifecycle
|
|
7
7
|
// ownership by injecting live getters (getDb/getConfig/setConfig) plus the
|
|
8
8
|
// cycle runners and LLM adapters.
|
|
@@ -15,15 +15,14 @@
|
|
|
15
15
|
// log -> __mixdogMemoryLog
|
|
16
16
|
// getCycleLastRun / setCycleLastRun -> meta-backed cycle timestamps
|
|
17
17
|
// readMainConfig / memoryCyclesEnabled -> config-flag helpers
|
|
18
|
-
//
|
|
19
|
-
// runCycle1 /
|
|
18
|
+
// getCycle1CallLlm -> in-process LLM adapter
|
|
19
|
+
// runCycle1 / parseInterval / flushRawEmbeddings
|
|
20
20
|
// claimAndMarkScheduledCycle / resolveCoalesceMaxRetries /
|
|
21
21
|
// scheduleCoalescedCycleRetry -> coalesced queue primitives
|
|
22
|
-
//
|
|
22
|
+
// scheduledCycle1Signature -> queue signature
|
|
23
23
|
// cycleStateFile -> path to memory-cycle-state.json
|
|
24
24
|
import { createCycleHealthLedger } from './cycle-scheduler/health-ledger.mjs';
|
|
25
25
|
import { createCycle1Runs } from './cycle-scheduler/cycle1-runs.mjs';
|
|
26
|
-
import { createCycle2Runs } from './cycle-scheduler/cycle2-runs.mjs';
|
|
27
26
|
import { createScheduledEnqueue } from './cycle-scheduler/scheduled-enqueue.mjs';
|
|
28
27
|
import { createBacklogProbe } from './cycle-scheduler/backlog-probe.mjs';
|
|
29
28
|
import { createCycleTickLoop } from './cycle-scheduler/tick-loop.mjs';
|
|
@@ -42,9 +41,7 @@ export function createCycleScheduler(deps) {
|
|
|
42
41
|
readMainConfig,
|
|
43
42
|
memoryCyclesEnabled,
|
|
44
43
|
getCycle1CallLlm,
|
|
45
|
-
getCycle2CallLlm,
|
|
46
44
|
runCycle1,
|
|
47
|
-
runCycle2,
|
|
48
45
|
parseInterval,
|
|
49
46
|
flushRawEmbeddings,
|
|
50
47
|
claimAndMarkScheduledCycle,
|
|
@@ -52,7 +49,6 @@ export function createCycleScheduler(deps) {
|
|
|
52
49
|
scheduleCoalescedCycleRetry,
|
|
53
50
|
cancelCoalescedCycleRetries,
|
|
54
51
|
scheduledCycle1Signature,
|
|
55
|
-
scheduledCycle2Signature,
|
|
56
52
|
cycleStateFile,
|
|
57
53
|
} = deps;
|
|
58
54
|
|
|
@@ -68,15 +64,12 @@ export function createCycleScheduler(deps) {
|
|
|
68
64
|
setCycleLastRun,
|
|
69
65
|
...queue,
|
|
70
66
|
});
|
|
71
|
-
const cycle2 = createCycle2Runs({ ledger, getDb, log, getCycle2CallLlm, runCycle2, setCycleLastRun, ...queue });
|
|
72
67
|
const enqueue = createScheduledEnqueue({
|
|
73
68
|
getDb,
|
|
74
69
|
getConfig,
|
|
75
70
|
claimAndMarkScheduledCycle,
|
|
76
71
|
scheduledCycle1Signature,
|
|
77
|
-
scheduledCycle2Signature,
|
|
78
72
|
scheduleScheduledCycle1: cycle1.scheduleScheduledCycle1,
|
|
79
|
-
scheduleScheduledCycle2: cycle2.scheduleScheduledCycle2,
|
|
80
73
|
});
|
|
81
74
|
const backlog = createBacklogProbe({ getDb, ledger, log, flushRawEmbeddings });
|
|
82
75
|
const tick = createCycleTickLoop({
|
|
@@ -97,7 +90,6 @@ export function createCycleScheduler(deps) {
|
|
|
97
90
|
// running state.
|
|
98
91
|
function resetInFlight() {
|
|
99
92
|
cycle1.reset();
|
|
100
|
-
cycle2.reset();
|
|
101
93
|
backlog.reset();
|
|
102
94
|
tick.reset();
|
|
103
95
|
ledger.resetRunning();
|
|
@@ -113,7 +105,6 @@ export function createCycleScheduler(deps) {
|
|
|
113
105
|
// run primitives used by MCP action handlers
|
|
114
106
|
startCycle1Run: cycle1.startCycle1Run,
|
|
115
107
|
awaitCycle1Run: cycle1.awaitCycle1Run,
|
|
116
|
-
finalizeCycle2Run: cycle2.finalizeCycle2Run,
|
|
117
108
|
periodicCycle1Config: enqueue.periodicCycle1Config,
|
|
118
109
|
// lifecycle
|
|
119
110
|
startCycles: tick.start,
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// session fetch with its starvation backfill, session grouping, and the
|
|
4
4
|
// terminal / omitted sentinel updates.
|
|
5
5
|
import { __mixdogMemoryLog } from '../memory-log.mjs';
|
|
6
|
-
import { throwIfAborted } from '../memory-
|
|
6
|
+
import { throwIfAborted } from '../memory-cycle-shared.mjs';
|
|
7
7
|
import { CYCLE1_OMITTED_COOLDOWN_MS } from './cycle1-plan.mjs';
|
|
8
8
|
|
|
9
9
|
export function isStructurallyUnchunkableInput(row) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// through the LLM, commit each chunk as one transaction, and mark what was
|
|
4
4
|
// left out. Rows within the window are one session in chronological order.
|
|
5
5
|
import { __mixdogMemoryLog } from '../memory-log.mjs';
|
|
6
|
-
import { throwIfAborted } from '../memory-
|
|
6
|
+
import { throwIfAborted } from '../memory-cycle-shared.mjs';
|
|
7
7
|
import { assessChunkQuality, generateCycle1Chunks } from '../memory-chunk-quality.mjs';
|
|
8
8
|
import { inferChunkProjectId, syncRootEmbedding } from '../memory-embed.mjs';
|
|
9
9
|
import { isStructurallyUnchunkableInput, markOmittedRows, markTerminalRows, selectRootId } from './cycle1-rows.mjs';
|
|
@@ -42,7 +42,7 @@ async function commitCycle1Chunk(db, chunk, rootId, memberIds) {
|
|
|
42
42
|
`UPDATE entries
|
|
43
43
|
SET chunk_root = $1, is_root = 1, element = $2, category = $3, summary = $4,
|
|
44
44
|
status = 'pending', project_id = $5,
|
|
45
|
-
last_seen_at = $7, chunk_quality = $8::jsonb,
|
|
45
|
+
last_seen_at = $7, chunk_quality = $8::jsonb, duplicate_of = NULL
|
|
46
46
|
WHERE id = $6`,
|
|
47
47
|
[rootId, element, category, summary, projectId, rootId, Date.now(), JSON.stringify(quality)]
|
|
48
48
|
);
|
|
@@ -60,7 +60,6 @@ export function createLifecycleRoutes({
|
|
|
60
60
|
active_roots: stats.active_roots,
|
|
61
61
|
archived_roots: stats.archived_roots,
|
|
62
62
|
unchunked_leaves: stats.unchunked_leaves,
|
|
63
|
-
cycle2_pending_roots: stats.cycle2_pending_roots,
|
|
64
63
|
core_entries: stats.core_entries,
|
|
65
64
|
core_embed_null: stats.core_embed_null,
|
|
66
65
|
cycle_running: cycleScheduler.getCycleRunning(),
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* memory-action-handlers/cycle-actions.mjs — the cycle-driven memory actions:
|
|
3
|
-
* cycle1,
|
|
4
|
-
* primitives
|
|
3
|
+
* cycle1, flush, rebuild and backfill. Cycle scheduler
|
|
4
|
+
* primitives are injected; the whole-action
|
|
5
5
|
* backfill mutex lives here since it only guards this module's backfill path.
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
import { throwIfAborted } from '../memory-
|
|
7
|
+
import { flushSearchEmbeddings } from '../memory-cycle.mjs';
|
|
8
|
+
import { throwIfAborted } from '../memory-cycle-shared.mjs';
|
|
9
9
|
import { createBackfillAction } from './cycle-backfill-action.mjs';
|
|
10
10
|
import { createRebuildAction } from './cycle-rebuild-action.mjs';
|
|
11
11
|
|
|
@@ -56,41 +56,15 @@ function cycle1SummaryText(result) {
|
|
|
56
56
|
);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function cycle2SummaryResult(result) {
|
|
60
|
-
const counts = {
|
|
61
|
-
processed: result?.processed || 0,
|
|
62
|
-
merged: result?.merged || 0,
|
|
63
|
-
linked: result?.linked || 0,
|
|
64
|
-
kept: result?.kept || 0,
|
|
65
|
-
held: result?.held || 0,
|
|
66
|
-
deferred: result?.deferred || 0,
|
|
67
|
-
};
|
|
68
|
-
const parts = Object.entries(counts)
|
|
69
|
-
.filter(([, v]) => v > 0)
|
|
70
|
-
.map(([k, v]) => `${k}=${v}`);
|
|
71
|
-
if (result?.ok === false)
|
|
72
|
-
return { text: `cycle2 failed: ${result.error || 'unknown'} ${parts.join(' ')}`.trim(), isError: true };
|
|
73
|
-
if (parts.length) return { text: `cycle2 ${parts.join(' ')}` };
|
|
74
|
-
// No applied counts — distinguish an in-flight skip from an empty queue.
|
|
75
|
-
let cause = '';
|
|
76
|
-
if (result?.skippedInFlight) cause = ' (skipped: in-flight)';
|
|
77
|
-
return { text: `cycle2 noop${cause}` };
|
|
78
|
-
}
|
|
79
|
-
|
|
80
59
|
export function createCycleActions({
|
|
81
60
|
getDb,
|
|
82
61
|
dataDir,
|
|
83
62
|
awaitCycle1Run,
|
|
84
63
|
startCycle1Run,
|
|
85
|
-
finalizeCycle2Run,
|
|
86
64
|
getSchedulerCycle1InFlight,
|
|
87
|
-
getCycle2CallLlm,
|
|
88
65
|
ingestTranscriptFile,
|
|
89
66
|
cwdFromTranscriptPath,
|
|
90
67
|
}) {
|
|
91
|
-
const withCycle2Llm = (options) =>
|
|
92
|
-
typeof options.callLlm === 'function' ? options : { ...options, callLlm: getCycle2CallLlm() };
|
|
93
|
-
|
|
94
68
|
async function cycle1(args, config, signal) {
|
|
95
69
|
const cycle1Config = cycle1ConfigFromArgs(args, config?.cycle1 || {});
|
|
96
70
|
const callerDeadlineMs = Number(args?._callerDeadlineMs) || 0;
|
|
@@ -104,50 +78,31 @@ export function createCycleActions({
|
|
|
104
78
|
return { ...result, text: cycle1SummaryText(result) };
|
|
105
79
|
}
|
|
106
80
|
|
|
107
|
-
async function cycle2(args, config, signal) {
|
|
108
|
-
const db = getDb();
|
|
109
|
-
throwIfAborted(signal);
|
|
110
|
-
const cycle2Config = { ...(config?.cycle2 || {}) };
|
|
111
|
-
if (Number.isFinite(Number(args?.batch_size))) {
|
|
112
|
-
cycle2Config.batch_size = Math.max(1, Math.floor(Number(args.batch_size)));
|
|
113
|
-
}
|
|
114
|
-
const result = await runCycle2(db, cycle2Config, withCycle2Llm({ signal }));
|
|
115
|
-
throwIfAborted(signal);
|
|
116
|
-
await finalizeCycle2Run(result);
|
|
117
|
-
return cycle2SummaryResult(result);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
81
|
async function flush(_args, config, signal) {
|
|
121
82
|
const db = getDb();
|
|
122
83
|
throwIfAborted(signal);
|
|
123
84
|
const r1 = await awaitCycle1Run(config?.cycle1 || {}, { signal });
|
|
124
85
|
throwIfAborted(signal);
|
|
125
|
-
const
|
|
86
|
+
const embeddings = await flushSearchEmbeddings(db, { signal });
|
|
126
87
|
throwIfAborted(signal);
|
|
127
|
-
await finalizeCycle2Run(r2);
|
|
128
88
|
return {
|
|
129
|
-
text: `flush: cycle1 chunks=${r1.chunks} processed=${r1.processed},
|
|
130
|
-
isError: r2.ok === false,
|
|
89
|
+
text: `flush: cycle1 chunks=${r1.chunks} processed=${r1.processed}, embeddings=${embeddings.succeeded}`,
|
|
131
90
|
};
|
|
132
91
|
}
|
|
133
92
|
|
|
134
93
|
const rebuild = createRebuildAction({
|
|
135
94
|
getDb,
|
|
136
95
|
startCycle1Run,
|
|
137
|
-
finalizeCycle2Run,
|
|
138
96
|
getSchedulerCycle1InFlight,
|
|
139
|
-
withCycle2Llm,
|
|
140
97
|
});
|
|
141
98
|
|
|
142
99
|
const backfill = createBackfillAction({
|
|
143
100
|
getDb,
|
|
144
101
|
dataDir,
|
|
145
102
|
awaitCycle1Run,
|
|
146
|
-
finalizeCycle2Run,
|
|
147
|
-
withCycle2Llm,
|
|
148
103
|
ingestTranscriptFile,
|
|
149
104
|
cwdFromTranscriptPath,
|
|
150
105
|
});
|
|
151
106
|
|
|
152
|
-
return { cycle1,
|
|
107
|
+
return { cycle1, flush, rebuild, backfill };
|
|
153
108
|
}
|