@kaelio/ktx 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/python/{kaelio_ktx-0.9.0-py3-none-any.whl → kaelio_ktx-0.11.0-py3-none-any.whl} +0 -0
- package/assets/python/manifest.json +4 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/clack.d.ts +6 -0
- package/dist/clack.js +17 -2
- package/dist/cli-program.d.ts +3 -0
- package/dist/cli-program.js +46 -2
- package/dist/cli-runtime.d.ts +5 -0
- package/dist/cli-runtime.js +50 -0
- package/dist/commands/setup-commands.js +2 -3
- package/dist/community-cta.d.ts +11 -0
- package/dist/community-cta.js +19 -0
- package/dist/connection.js +23 -1
- package/dist/connectors/bigquery/connector.d.ts +2 -5
- package/dist/connectors/bigquery/connector.js +2 -2
- package/dist/connectors/clickhouse/connector.d.ts +2 -5
- package/dist/connectors/clickhouse/connector.js +2 -2
- package/dist/connectors/mysql/connector.d.ts +7 -6
- package/dist/connectors/mysql/connector.js +25 -5
- package/dist/connectors/mysql/dialect.d.ts +1 -1
- package/dist/connectors/mysql/dialect.js +12 -2
- package/dist/connectors/postgres/connector.d.ts +2 -5
- package/dist/connectors/postgres/connector.js +2 -2
- package/dist/connectors/snowflake/connector.d.ts +2 -5
- package/dist/connectors/snowflake/connector.js +2 -2
- package/dist/connectors/sqlite/connector.d.ts +2 -5
- package/dist/connectors/sqlite/connector.js +2 -2
- package/dist/connectors/sqlserver/connector.d.ts +2 -5
- package/dist/connectors/sqlserver/connector.js +2 -2
- package/dist/context/connections/drivers.d.ts +0 -1
- package/dist/context/connections/drivers.js +0 -7
- package/dist/context/connections/query-executor.d.ts +2 -1
- package/dist/context/core/abort.d.ts +9 -0
- package/dist/context/core/abort.js +36 -0
- package/dist/context/core/git-env.d.ts +12 -1
- package/dist/context/core/git-env.js +17 -2
- package/dist/context/core/git.service.js +15 -7
- package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.d.ts +1 -0
- package/dist/context/ingest/adapters/historic-sql/query-history-filter-picker.js +6 -2
- package/dist/context/ingest/context-candidates/curator-pagination.service.d.ts +1 -5
- package/dist/context/ingest/context-candidates/curator-pagination.service.js +1 -3
- package/dist/context/ingest/context-evidence/sqlite-context-evidence-store.d.ts +1 -1
- package/dist/context/ingest/final-gate-repair.d.ts +1 -0
- package/dist/context/ingest/final-gate-repair.js +1 -0
- package/dist/context/ingest/ingest-bundle.runner.d.ts +3 -0
- package/dist/context/ingest/ingest-bundle.runner.js +127 -53
- package/dist/context/ingest/isolated-diff/textual-conflict-resolver.d.ts +1 -0
- package/dist/context/ingest/isolated-diff/textual-conflict-resolver.js +1 -0
- package/dist/context/ingest/isolated-diff/work-unit-executor.d.ts +1 -0
- package/dist/context/ingest/local-bundle-runtime.js +11 -4
- package/dist/context/ingest/local-ingest.d.ts +1 -0
- package/dist/context/ingest/local-ingest.js +13 -3
- package/dist/context/ingest/memory-flow/events.js +1 -1
- package/dist/context/ingest/memory-flow/schema.js +8 -3
- package/dist/context/ingest/memory-flow/types.d.ts +7 -3
- package/dist/context/ingest/ports.d.ts +3 -5
- package/dist/context/ingest/stages/stage-3-work-units.d.ts +1 -4
- package/dist/context/ingest/stages/stage-3-work-units.js +5 -1
- package/dist/context/ingest/stages/stage-4-reconciliation.d.ts +1 -4
- package/dist/context/ingest/stages/stage-4-reconciliation.js +1 -1
- package/dist/context/ingest/types.d.ts +1 -0
- package/dist/context/llm/ai-sdk-runtime.d.ts +3 -0
- package/dist/context/llm/ai-sdk-runtime.js +152 -16
- package/dist/context/llm/claude-code-runtime.d.ts +6 -4
- package/dist/context/llm/claude-code-runtime.js +127 -48
- package/dist/context/llm/codex-runtime.d.ts +3 -3
- package/dist/context/llm/codex-runtime.js +90 -47
- package/dist/context/llm/local-config.d.ts +15 -5
- package/dist/context/llm/local-config.js +6 -1
- package/dist/context/llm/rate-limit-governor.d.ts +103 -0
- package/dist/context/llm/rate-limit-governor.js +285 -0
- package/dist/context/llm/runtime-port.d.ts +3 -6
- package/dist/context/mcp/context-tools.js +43 -13
- package/dist/context/project/config.d.ts +12 -0
- package/dist/context/project/config.js +35 -0
- package/dist/context/scan/types.d.ts +15 -2
- package/dist/context/scan/types.js +12 -0
- package/dist/context/sl/description-normalization.js +4 -14
- package/dist/context/tools/context-candidate-mark.tool.d.ts +2 -2
- package/dist/context-build-view.d.ts +13 -0
- package/dist/context-build-view.js +60 -1
- package/dist/demo-metrics.d.ts +0 -2
- package/dist/demo-metrics.js +1 -11
- package/dist/ingest.d.ts +1 -0
- package/dist/ingest.js +32 -3
- package/dist/io/symbols.d.ts +2 -0
- package/dist/io/symbols.js +2 -0
- package/dist/io/tty.d.ts +9 -0
- package/dist/io/tty.js +5 -0
- package/dist/links.d.ts +1 -0
- package/dist/links.js +1 -0
- package/dist/memory-flow-hud.js +8 -16
- package/dist/public-ingest.js +50 -15
- package/dist/reveal-password-prompt.d.ts +24 -0
- package/dist/reveal-password-prompt.js +78 -0
- package/dist/scan.js +18 -2
- package/dist/setup-agents.js +1 -5
- package/dist/setup-databases.d.ts +1 -0
- package/dist/setup-databases.js +23 -3
- package/dist/setup-demo-tour.js +1 -0
- package/dist/setup-embeddings.js +1 -1
- package/dist/setup-models.d.ts +1 -14
- package/dist/setup-models.js +116 -340
- package/dist/setup-prompts.js +4 -7
- package/dist/setup-sources.js +7 -7
- package/dist/setup.d.ts +26 -1
- package/dist/setup.js +78 -7
- package/dist/sl.d.ts +2 -2
- package/dist/sl.js +20 -4
- package/dist/sql.js +18 -2
- package/dist/star-prompt/cache.d.ts +16 -0
- package/dist/star-prompt/cache.js +45 -0
- package/dist/star-prompt/star-count.d.ts +7 -0
- package/dist/star-prompt/star-count.js +66 -0
- package/dist/star-prompt/star-line.d.ts +12 -0
- package/dist/star-prompt/star-line.js +26 -0
- package/dist/telemetry/command-hook.d.ts +24 -0
- package/dist/telemetry/command-hook.js +37 -3
- package/dist/telemetry/emitter.d.ts +10 -0
- package/dist/telemetry/emitter.js +31 -0
- package/dist/telemetry/events.d.ts +24 -0
- package/dist/telemetry/events.js +15 -0
- package/dist/telemetry/exception.d.ts +18 -0
- package/dist/telemetry/exception.js +162 -0
- package/dist/telemetry/index.d.ts +4 -3
- package/dist/telemetry/index.js +3 -2
- package/dist/telemetry/redaction-secrets.d.ts +11 -0
- package/dist/telemetry/redaction-secrets.js +92 -0
- package/dist/update-check/cache.d.ts +21 -0
- package/dist/update-check/cache.js +38 -0
- package/dist/update-check/channel.d.ts +15 -0
- package/dist/update-check/channel.js +30 -0
- package/dist/update-check/registry.d.ts +1 -0
- package/dist/update-check/registry.js +45 -0
- package/dist/update-check/update-check.d.ts +43 -0
- package/dist/update-check/update-check.js +116 -0
- package/package.json +8 -1
- package/dist/context/connections/local-query-executor.d.ts +0 -6
- package/dist/context/connections/local-query-executor.js +0 -39
- package/dist/context/connections/postgres-query-executor.d.ts +0 -25
- package/dist/context/connections/postgres-query-executor.js +0 -53
- package/dist/context/connections/sqlite-query-executor.d.ts +0 -4
- package/dist/context/connections/sqlite-query-executor.js +0 -74
|
@@ -115,6 +115,10 @@ export class IngestBundleRunner {
|
|
|
115
115
|
this.logger = deps.logger ?? noopLogger;
|
|
116
116
|
}
|
|
117
117
|
async run(job, ctx) {
|
|
118
|
+
const unsubscribeRateLimitGovernor = this.subscribeRateLimitGovernor({
|
|
119
|
+
trace: this.createTrace(job),
|
|
120
|
+
memoryFlow: ctx?.memoryFlow,
|
|
121
|
+
});
|
|
118
122
|
const key = job.connectionId;
|
|
119
123
|
const previous = this.chainByConnection.get(key);
|
|
120
124
|
if (previous) {
|
|
@@ -139,9 +143,64 @@ export class IngestBundleRunner {
|
|
|
139
143
|
throw error;
|
|
140
144
|
}
|
|
141
145
|
finally {
|
|
146
|
+
unsubscribeRateLimitGovernor();
|
|
142
147
|
await this.maybeEmitIngestProfile(job.jobId);
|
|
143
148
|
}
|
|
144
149
|
}
|
|
150
|
+
formatRateLimitWait(state) {
|
|
151
|
+
const seconds = Math.ceil(state.remainingMs / 1_000);
|
|
152
|
+
const minutes = Math.floor(seconds / 60);
|
|
153
|
+
const remainder = seconds % 60;
|
|
154
|
+
const duration = minutes > 0 ? `${minutes}m${String(remainder).padStart(2, '0')}s` : `${seconds}s`;
|
|
155
|
+
const type = state.rateLimitType ? ` ${state.rateLimitType}` : '';
|
|
156
|
+
return `Rate-limited (${state.provider}${type}); resuming in ${duration}; Ctrl+C to stop`;
|
|
157
|
+
}
|
|
158
|
+
subscribeRateLimitGovernor(input) {
|
|
159
|
+
const governor = this.deps.settings.rateLimitGovernor;
|
|
160
|
+
if (!governor) {
|
|
161
|
+
return () => undefined;
|
|
162
|
+
}
|
|
163
|
+
return governor.subscribe((state) => {
|
|
164
|
+
if (state.kind === 'rate_limit_observed') {
|
|
165
|
+
void input.trace.event('info', 'rate_limit', 'rate_limit_observed', { ...state });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (state.kind === 'concurrency_adjusted') {
|
|
169
|
+
void input.trace.event('info', 'rate_limit', 'concurrency_adjusted', { ...state });
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
void input.trace.event('info', 'rate_limit', state.kind, { ...state });
|
|
173
|
+
if (state.kind === 'wait_tick' || state.kind === 'wait_started') {
|
|
174
|
+
input.memoryFlow?.emit({
|
|
175
|
+
type: 'rate_limit_wait',
|
|
176
|
+
provider: state.provider,
|
|
177
|
+
...(state.rateLimitType ? { rateLimitType: state.rateLimitType } : {}),
|
|
178
|
+
resumeAtMs: state.resumeAtMs,
|
|
179
|
+
remainingMs: state.remainingMs,
|
|
180
|
+
});
|
|
181
|
+
input.memoryFlow?.emit({
|
|
182
|
+
type: 'stage_progress',
|
|
183
|
+
stage: 'integration',
|
|
184
|
+
percent: 50,
|
|
185
|
+
message: this.formatRateLimitWait(state),
|
|
186
|
+
transient: true,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async withRateLimitWorkSlot(abortSignal, fn) {
|
|
192
|
+
const governor = this.deps.settings.rateLimitGovernor;
|
|
193
|
+
if (!governor) {
|
|
194
|
+
return fn();
|
|
195
|
+
}
|
|
196
|
+
const release = await governor.acquireWorkSlot(abortSignal);
|
|
197
|
+
try {
|
|
198
|
+
return await fn();
|
|
199
|
+
}
|
|
200
|
+
finally {
|
|
201
|
+
release();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
145
204
|
/**
|
|
146
205
|
* When profiling is enabled — via the `KTX_PROFILE_INGEST` env var or the
|
|
147
206
|
* `ingest.profile` config setting — read the job's trace + tool transcripts
|
|
@@ -711,7 +770,6 @@ export class IngestBundleRunner {
|
|
|
711
770
|
type: 'work_unit_started',
|
|
712
771
|
unitKey: input.wu.unitKey,
|
|
713
772
|
skills: input.wuSkillNames,
|
|
714
|
-
stepBudget: input.workUnitSettings.stepBudget,
|
|
715
773
|
});
|
|
716
774
|
return executeWorkUnit({
|
|
717
775
|
sessionWorktreeGit: input.worktree.git,
|
|
@@ -731,14 +789,30 @@ export class IngestBundleRunner {
|
|
|
731
789
|
slIndex: input.slIndex,
|
|
732
790
|
priorProvenance: input.priorProvenance,
|
|
733
791
|
}),
|
|
734
|
-
buildToolSet: (wuInner) =>
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
792
|
+
buildToolSet: (wuInner) => {
|
|
793
|
+
const transcriptPath = join(input.transcriptDir, `${wuInner.unitKey}.jsonl`);
|
|
794
|
+
const record = input.recordTranscriptEntry(transcriptPath);
|
|
795
|
+
return wrapToolsWithLogger(buildWuToolSet({
|
|
796
|
+
sourceKey: input.job.sourceKey,
|
|
797
|
+
stagedDir: input.stagedDir,
|
|
798
|
+
wu: wuInner,
|
|
799
|
+
loadSkillTool,
|
|
800
|
+
emitUnmappedFallbackTool: wuEmitUnmappedFallbackTool,
|
|
801
|
+
toolsetTools: wuToolset.toRuntimeTools(wuToolContext),
|
|
802
|
+
}), transcriptPath, wuInner.unitKey, {
|
|
803
|
+
// Drive the live HUD heartbeat from real tool calls: each invocation
|
|
804
|
+
// ticks the running per-unit count. This is an observed signal, not a
|
|
805
|
+
// re-derived turn count, so it can never overshoot a budget.
|
|
806
|
+
onEntry: (entry) => {
|
|
807
|
+
const summary = record(entry);
|
|
808
|
+
input.memoryFlow?.emit({
|
|
809
|
+
type: 'work_unit_step',
|
|
810
|
+
unitKey: wuInner.unitKey,
|
|
811
|
+
toolCalls: summary.toolCallCount,
|
|
812
|
+
});
|
|
813
|
+
},
|
|
814
|
+
});
|
|
815
|
+
},
|
|
742
816
|
captureSession: session,
|
|
743
817
|
sessionActions,
|
|
744
818
|
modelRole: 'candidateExtraction',
|
|
@@ -747,7 +821,7 @@ export class IngestBundleRunner {
|
|
|
747
821
|
connectionId: input.job.connectionId,
|
|
748
822
|
jobId: input.job.jobId,
|
|
749
823
|
toolFailureCount: (unitKey) => input.transcriptSummaries.get(unitKey)?.fatalErrorCount ?? 0,
|
|
750
|
-
|
|
824
|
+
abortSignal: input.abortSignal,
|
|
751
825
|
}, input.wu);
|
|
752
826
|
}
|
|
753
827
|
async runInner(job, ctx) {
|
|
@@ -797,6 +871,7 @@ export class IngestBundleRunner {
|
|
|
797
871
|
const current = transcriptSummaries.get(entry.wuKey) ?? createMutableToolTranscriptSummary(entry.wuKey, path);
|
|
798
872
|
recordToolTranscriptEntry(current, entry);
|
|
799
873
|
transcriptSummaries.set(entry.wuKey, current);
|
|
874
|
+
return current;
|
|
800
875
|
};
|
|
801
876
|
const overrideReport = await this.loadOverrideReport(job);
|
|
802
877
|
const stage1 = ctx?.startPhase(0.08);
|
|
@@ -1111,7 +1186,7 @@ export class IngestBundleRunner {
|
|
|
1111
1186
|
await stage3?.updateProgress(1.0, '0 of 0 work units complete');
|
|
1112
1187
|
}
|
|
1113
1188
|
try {
|
|
1114
|
-
await Promise.all(workUnits.map((wu, index) => limitWorkUnit(async () => {
|
|
1189
|
+
await Promise.all(workUnits.map((wu, index) => limitWorkUnit(() => this.withRateLimitWorkSlot(ctx?.abortSignal, async () => {
|
|
1115
1190
|
const outcome = await runIsolatedWorkUnit({
|
|
1116
1191
|
unitIndex: index,
|
|
1117
1192
|
ingestionBaseSha,
|
|
@@ -1119,6 +1194,7 @@ export class IngestBundleRunner {
|
|
|
1119
1194
|
patchDir,
|
|
1120
1195
|
trace: runTrace,
|
|
1121
1196
|
workUnit: wu,
|
|
1197
|
+
abortSignal: ctx?.abortSignal,
|
|
1122
1198
|
afterSuccess: (child) => copyTransientIngestEvidence(child.workdir, sessionWorktree.workdir),
|
|
1123
1199
|
run: async (child) => {
|
|
1124
1200
|
const scopedWikiService = this.deps.wikiService.forWorktree(child.workdir);
|
|
@@ -1147,11 +1223,9 @@ export class IngestBundleRunner {
|
|
|
1147
1223
|
stageIndex,
|
|
1148
1224
|
includeContextEvidenceTools: adapter.evidenceIndexing === 'documents' && !!contextReport,
|
|
1149
1225
|
currentTableExists: (tableRef) => this.tableRefExistsInSemanticLayer(scopedSemanticLayerService, slConnectionIds, tableRef),
|
|
1226
|
+
abortSignal: ctx?.abortSignal,
|
|
1150
1227
|
memoryFlow,
|
|
1151
1228
|
wuSkillNames,
|
|
1152
|
-
onStepFinish: ({ stepIndex, stepBudget }) => {
|
|
1153
|
-
memoryFlow?.emit({ type: 'work_unit_step', unitKey: wu.unitKey, stepIndex, stepBudget });
|
|
1154
|
-
},
|
|
1155
1229
|
});
|
|
1156
1230
|
},
|
|
1157
1231
|
});
|
|
@@ -1173,7 +1247,7 @@ export class IngestBundleRunner {
|
|
|
1173
1247
|
});
|
|
1174
1248
|
completedWorkUnits += 1;
|
|
1175
1249
|
await stage3?.updateProgress(completedWorkUnits / workUnits.length, `${completedWorkUnits} of ${workUnits.length} work units complete`);
|
|
1176
|
-
})));
|
|
1250
|
+
}))));
|
|
1177
1251
|
}
|
|
1178
1252
|
catch (error) {
|
|
1179
1253
|
await this.deps.runs.markFailed(runRow.id);
|
|
@@ -1250,6 +1324,7 @@ export class IngestBundleRunner {
|
|
|
1250
1324
|
reason: context.reason,
|
|
1251
1325
|
maxAttempts: 1,
|
|
1252
1326
|
stepBudget: 12,
|
|
1327
|
+
abortSignal: ctx?.abortSignal,
|
|
1253
1328
|
});
|
|
1254
1329
|
emitStageProgress('integration', 82, result.status === 'repaired'
|
|
1255
1330
|
? `Resolved text conflict for ${context.unitKey}`
|
|
@@ -1267,6 +1342,7 @@ export class IngestBundleRunner {
|
|
|
1267
1342
|
repairKind: 'patch_semantic_gate',
|
|
1268
1343
|
maxAttempts: 1,
|
|
1269
1344
|
stepBudget: 16,
|
|
1345
|
+
abortSignal: ctx?.abortSignal,
|
|
1270
1346
|
});
|
|
1271
1347
|
emitStageProgress('integration', 83, result.status === 'repaired'
|
|
1272
1348
|
? `Repaired semantic gate for ${context.unitKey}`
|
|
@@ -1451,6 +1527,37 @@ export class IngestBundleRunner {
|
|
|
1451
1527
|
let curatorReport = null;
|
|
1452
1528
|
let curatorWarnings = [];
|
|
1453
1529
|
let reconcileOutcome;
|
|
1530
|
+
// Reconcile shares the work-unit liveness model: the HUD heartbeat is driven
|
|
1531
|
+
// by real tool calls (a monotonic, observed count), not a re-derived turn
|
|
1532
|
+
// counter. The soft cap only paces the phase progress bar; it is never shown
|
|
1533
|
+
// to the user, so it cannot read as a misleading "X/Y" fraction.
|
|
1534
|
+
const reconcileTranscriptPath = join(transcriptDir, 'reconcile.jsonl');
|
|
1535
|
+
const reconcileProgressSoftCap = 40;
|
|
1536
|
+
const buildReconcileToolSetWithHeartbeat = () => {
|
|
1537
|
+
const record = recordTranscriptEntry(reconcileTranscriptPath);
|
|
1538
|
+
return wrapToolsWithLogger(buildReconcileToolSet({
|
|
1539
|
+
loadSkillTool: rcLoadSkill,
|
|
1540
|
+
stageListTool: rcStageListTool,
|
|
1541
|
+
stageDiffTool: rcStageDiffTool,
|
|
1542
|
+
evictionListTool: rcEvictionListTool,
|
|
1543
|
+
emitConflictResolutionTool: rcEmitConflictResolutionTool,
|
|
1544
|
+
emitEvictionDecisionTool: rcEmitEvictionDecisionTool,
|
|
1545
|
+
emitArtifactResolutionTool: rcEmitArtifactResolutionTool,
|
|
1546
|
+
emitUnmappedFallbackTool: rcEmitUnmappedFallbackTool,
|
|
1547
|
+
readRawSpanTool: rcRawSpanTool,
|
|
1548
|
+
toolsetTools: rcToolset.toRuntimeTools(rcToolContext),
|
|
1549
|
+
}), reconcileTranscriptPath, 'reconcile', {
|
|
1550
|
+
onEntry: (entry) => {
|
|
1551
|
+
const summary = record(entry);
|
|
1552
|
+
if (!stage4) {
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
const label = `Reconciling results · ${summary.toolCallCount} action${summary.toolCallCount === 1 ? '' : 's'}`;
|
|
1556
|
+
emitStageProgress('reconciliation', 85, label, { transient: true });
|
|
1557
|
+
void stage4.updateProgress(Math.min(0.95, summary.toolCallCount / reconcileProgressSoftCap), label);
|
|
1558
|
+
},
|
|
1559
|
+
});
|
|
1560
|
+
};
|
|
1454
1561
|
const reconcileStartedAt = Date.now();
|
|
1455
1562
|
const reconcileMode = contextReport && this.deps.curatorPagination ? 'curator' : 'single';
|
|
1456
1563
|
if (contextReport && this.deps.curatorPagination) {
|
|
@@ -1471,25 +1578,9 @@ export class IngestBundleRunner {
|
|
|
1471
1578
|
canonicalPins: relevantCanonicalPins,
|
|
1472
1579
|
}),
|
|
1473
1580
|
buildUserPrompt: ({ summary, items, runState }) => buildReconcileUserPrompt(stageIndex, eviction, { summary, items }, reconcileNotes, runState),
|
|
1474
|
-
buildToolSet: (_passNumber) =>
|
|
1475
|
-
loadSkillTool: rcLoadSkill,
|
|
1476
|
-
stageListTool: rcStageListTool,
|
|
1477
|
-
stageDiffTool: rcStageDiffTool,
|
|
1478
|
-
evictionListTool: rcEvictionListTool,
|
|
1479
|
-
emitConflictResolutionTool: rcEmitConflictResolutionTool,
|
|
1480
|
-
emitEvictionDecisionTool: rcEmitEvictionDecisionTool,
|
|
1481
|
-
emitArtifactResolutionTool: rcEmitArtifactResolutionTool,
|
|
1482
|
-
emitUnmappedFallbackTool: rcEmitUnmappedFallbackTool,
|
|
1483
|
-
readRawSpanTool: rcRawSpanTool,
|
|
1484
|
-
toolsetTools: rcToolset.toRuntimeTools(rcToolContext),
|
|
1485
|
-
}), join(transcriptDir, 'reconcile.jsonl'), 'reconcile', { onEntry: recordTranscriptEntry(join(transcriptDir, 'reconcile.jsonl')) }),
|
|
1581
|
+
buildToolSet: (_passNumber) => buildReconcileToolSetWithHeartbeat(),
|
|
1486
1582
|
getReconciliationActions: () => reconcileActions,
|
|
1487
|
-
|
|
1488
|
-
? ({ passNumber, stepIndex, stepBudget }) => {
|
|
1489
|
-
emitStageProgress('reconciliation', 85, `Reconciling results: pass ${passNumber} step ${stepIndex}/${stepBudget}`, { transient: true });
|
|
1490
|
-
void stage4.updateProgress(stepIndex / stepBudget, `Reconciling results · pass ${passNumber} step ${stepIndex}`);
|
|
1491
|
-
}
|
|
1492
|
-
: undefined,
|
|
1583
|
+
abortSignal: ctx?.abortSignal,
|
|
1493
1584
|
});
|
|
1494
1585
|
curatorReport = curatorOutcome.report;
|
|
1495
1586
|
curatorWarnings = curatorOutcome.warnings;
|
|
@@ -1512,31 +1603,13 @@ export class IngestBundleRunner {
|
|
|
1512
1603
|
canonicalPins: relevantCanonicalPins,
|
|
1513
1604
|
}),
|
|
1514
1605
|
buildUserPrompt: (idx, ev) => buildReconcileUserPrompt(idx, ev, undefined, reconcileNotes),
|
|
1515
|
-
buildToolSet: () =>
|
|
1516
|
-
loadSkillTool: rcLoadSkill,
|
|
1517
|
-
stageListTool: rcStageListTool,
|
|
1518
|
-
stageDiffTool: rcStageDiffTool,
|
|
1519
|
-
evictionListTool: rcEvictionListTool,
|
|
1520
|
-
emitConflictResolutionTool: rcEmitConflictResolutionTool,
|
|
1521
|
-
emitEvictionDecisionTool: rcEmitEvictionDecisionTool,
|
|
1522
|
-
emitArtifactResolutionTool: rcEmitArtifactResolutionTool,
|
|
1523
|
-
emitUnmappedFallbackTool: rcEmitUnmappedFallbackTool,
|
|
1524
|
-
readRawSpanTool: rcRawSpanTool,
|
|
1525
|
-
toolsetTools: rcToolset.toRuntimeTools(rcToolContext),
|
|
1526
|
-
}), join(transcriptDir, 'reconcile.jsonl'), 'reconcile', { onEntry: recordTranscriptEntry(join(transcriptDir, 'reconcile.jsonl')) }),
|
|
1606
|
+
buildToolSet: () => buildReconcileToolSetWithHeartbeat(),
|
|
1527
1607
|
modelRole: 'reconcile',
|
|
1528
1608
|
stepBudget: 60,
|
|
1529
1609
|
sourceKey: job.sourceKey,
|
|
1530
1610
|
jobId: job.jobId,
|
|
1531
1611
|
force: !!overrideReport,
|
|
1532
|
-
|
|
1533
|
-
? ({ stepIndex, stepBudget }) => {
|
|
1534
|
-
emitStageProgress('reconciliation', 85, `Reconciling results: step ${stepIndex}/${stepBudget}`, {
|
|
1535
|
-
transient: true,
|
|
1536
|
-
});
|
|
1537
|
-
void stage4.updateProgress(stepIndex / stepBudget, `Reconciling results · step ${stepIndex}`);
|
|
1538
|
-
}
|
|
1539
|
-
: undefined,
|
|
1612
|
+
abortSignal: ctx?.abortSignal,
|
|
1540
1613
|
});
|
|
1541
1614
|
}
|
|
1542
1615
|
await runTrace.event('debug', 'reconciliation', 'reconciliation_executed', {
|
|
@@ -1890,6 +1963,7 @@ export class IngestBundleRunner {
|
|
|
1890
1963
|
repairKind: 'final_artifact_gate',
|
|
1891
1964
|
maxAttempts: 1,
|
|
1892
1965
|
stepBudget: 16,
|
|
1966
|
+
abortSignal: ctx?.abortSignal,
|
|
1893
1967
|
});
|
|
1894
1968
|
isolatedDiffSummary.gateRepairAttempts += gateRepair.attempts;
|
|
1895
1969
|
if (gateRepair.status === 'failed') {
|
|
@@ -19,5 +19,6 @@ export interface ResolveTextualConflictInput {
|
|
|
19
19
|
reason: string;
|
|
20
20
|
maxAttempts?: number;
|
|
21
21
|
stepBudget?: number;
|
|
22
|
+
abortSignal?: AbortSignal;
|
|
22
23
|
}
|
|
23
24
|
export declare function resolveTextualConflict(input: ResolveTextualConflictInput): Promise<TextualConflictResolutionResult>;
|
|
@@ -165,6 +165,7 @@ export async function resolveTextualConflict(input) {
|
|
|
165
165
|
jobId: input.trace.context.jobId,
|
|
166
166
|
unitKey: input.unitKey,
|
|
167
167
|
},
|
|
168
|
+
abortSignal: input.abortSignal,
|
|
168
169
|
}));
|
|
169
170
|
if (result.stopReason === 'error') {
|
|
170
171
|
lastFailure = result.error?.message ?? 'resolver agent loop errored';
|
|
@@ -9,6 +9,7 @@ export interface RunIsolatedWorkUnitInput {
|
|
|
9
9
|
patchDir: string;
|
|
10
10
|
trace: IngestTraceWriter;
|
|
11
11
|
workUnit: WorkUnit;
|
|
12
|
+
abortSignal?: AbortSignal;
|
|
12
13
|
run(child: IngestSessionWorktree): Promise<WorkUnitOutcome>;
|
|
13
14
|
afterSuccess?(child: IngestSessionWorktree): Promise<void>;
|
|
14
15
|
}
|
|
@@ -8,6 +8,7 @@ import { SessionWorktreeService } from '../../context/core/session-worktree.serv
|
|
|
8
8
|
import { createRuntimeToolDescriptorFromAiTool } from '../../context/llm/runtime-tools.js';
|
|
9
9
|
import { createLocalKtxLlmRuntimeFromConfig } from '../../context/llm/local-config.js';
|
|
10
10
|
import { KtxIngestEmbeddingPortAdapter } from '../../context/llm/embedding-port.js';
|
|
11
|
+
import { createRateLimitGovernorConfig, RateLimitGovernor } from '../../context/llm/rate-limit-governor.js';
|
|
11
12
|
import { RuntimeAgentRunner } from '../../context/llm/runtime-port.js';
|
|
12
13
|
import { ktxLocalStateDbPath } from '../../context/project/local-state-db.js';
|
|
13
14
|
import { PromptService } from '../../context/prompts/prompt.service.js';
|
|
@@ -491,15 +492,16 @@ function localIngestLlmProviderGuardMessage(projectDir) {
|
|
|
491
492
|
'ktx ingest requires llm.provider.backend: anthropic, vertex, gateway, claude-code, or codex, or an injected agentRunner.',
|
|
492
493
|
'Configure a local Claude Code/Codex session or API-backed LLM, then rerun ingest:',
|
|
493
494
|
` ktx setup --project-dir ${projectDir} --llm-backend claude-code --no-input`,
|
|
494
|
-
` ktx setup --project-dir ${projectDir} --llm-backend codex --
|
|
495
|
-
` ktx setup --project-dir ${projectDir} --llm-backend anthropic --anthropic-api-key-env ANTHROPIC_API_KEY --
|
|
495
|
+
` ktx setup --project-dir ${projectDir} --llm-backend codex --no-input`,
|
|
496
|
+
` ktx setup --project-dir ${projectDir} --llm-backend anthropic --anthropic-api-key-env ANTHROPIC_API_KEY --no-input`,
|
|
496
497
|
].join('\n');
|
|
497
498
|
}
|
|
498
|
-
function resolveAgentRunner(options) {
|
|
499
|
+
function resolveAgentRunner(options, rateLimitGovernor) {
|
|
499
500
|
const llmRuntime = options.llmRuntime ??
|
|
500
501
|
(options.createLlmRuntime ?? createLocalKtxLlmRuntimeFromConfig)(options.project.config.llm, {
|
|
501
502
|
projectDir: options.project.projectDir,
|
|
502
503
|
env: process.env,
|
|
504
|
+
rateLimitGovernor,
|
|
503
505
|
}) ??
|
|
504
506
|
undefined;
|
|
505
507
|
if (options.agentRunner) {
|
|
@@ -536,7 +538,11 @@ export function createLocalBundleIngestRuntime(options) {
|
|
|
536
538
|
const knowledgeIndex = new LocalKnowledgeIndex(options.project, embedding);
|
|
537
539
|
const knowledgeEvents = new NoopKnowledgeEventPort();
|
|
538
540
|
const wikiService = new KnowledgeWikiService(rootFileStore, embedding, knowledgeIndex, options.project.git, logger);
|
|
539
|
-
const
|
|
541
|
+
const rateLimitGovernor = new RateLimitGovernor(createRateLimitGovernorConfig({
|
|
542
|
+
...options.project.config.ingest.rateLimit,
|
|
543
|
+
maxConcurrency: options.project.config.ingest.workUnits.maxConcurrency,
|
|
544
|
+
}));
|
|
545
|
+
const { agentRunner, llmRuntime } = resolveAgentRunner(options, rateLimitGovernor);
|
|
540
546
|
const promptService = new PromptService({ promptsDir, partials: [], logger });
|
|
541
547
|
const storage = new LocalIngestStorage(options.project);
|
|
542
548
|
const registry = registerAdapters(options.adapters);
|
|
@@ -575,6 +581,7 @@ export function createLocalBundleIngestRuntime(options) {
|
|
|
575
581
|
workUnitMaxConcurrency: options.project.config.ingest.workUnits.maxConcurrency,
|
|
576
582
|
workUnitStepBudget: options.project.config.ingest.workUnits.stepBudget,
|
|
577
583
|
workUnitFailureMode: options.project.config.ingest.workUnits.failureMode,
|
|
584
|
+
rateLimitGovernor,
|
|
578
585
|
profileIngest: options.project.config.ingest.profile,
|
|
579
586
|
ingestTraceLevel: ingestTraceLevelFromEnv(),
|
|
580
587
|
},
|
|
@@ -25,6 +25,7 @@ export interface RunLocalIngestOptions {
|
|
|
25
25
|
queryExecutor?: KtxSqlQueryExecutorPort;
|
|
26
26
|
logger?: KtxLogger;
|
|
27
27
|
embeddingProvider?: import('../../llm/types.js').KtxEmbeddingProvider | null;
|
|
28
|
+
abortSignal?: AbortSignal;
|
|
28
29
|
}
|
|
29
30
|
export interface LocalIngestResult {
|
|
30
31
|
result: IngestBundleResult;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { cp, mkdir, rm } from 'node:fs/promises';
|
|
3
3
|
import { isAbsolute, resolve } from 'node:path';
|
|
4
|
+
import { createAbortError, isAbortError } from '../../context/core/abort.js';
|
|
4
5
|
import { ktxLocalStateDbPath } from '../../context/project/local-state-db.js';
|
|
5
6
|
import { planMetabaseFanoutChildren } from './adapters/metabase/fanout-planner.js';
|
|
6
7
|
import { KtxYamlMetabaseSourceStateReader, LocalMetabaseDiscoveryCache } from './adapters/metabase/local-source-state-store.js';
|
|
@@ -36,10 +37,11 @@ function findAdapter(adapters, source) {
|
|
|
36
37
|
}
|
|
37
38
|
return adapter;
|
|
38
39
|
}
|
|
39
|
-
function localJobContext(jobId, memoryFlow) {
|
|
40
|
+
function localJobContext(jobId, memoryFlow, abortSignal) {
|
|
40
41
|
return {
|
|
41
42
|
jobId,
|
|
42
43
|
...(memoryFlow ? { memoryFlow } : {}),
|
|
44
|
+
...(abortSignal ? { abortSignal } : {}),
|
|
43
45
|
startPhase() {
|
|
44
46
|
return new LocalIngestPhase();
|
|
45
47
|
},
|
|
@@ -62,7 +64,7 @@ async function runScheduledPullJob(options) {
|
|
|
62
64
|
sourceKey: options.adapter.source,
|
|
63
65
|
trigger: options.trigger ?? 'manual_resync',
|
|
64
66
|
bundleRef: { kind: 'scheduled_pull', config: options.pullConfig },
|
|
65
|
-
}, localJobContext(jobId, options.memoryFlow));
|
|
67
|
+
}, localJobContext(jobId, options.memoryFlow, options.abortSignal));
|
|
66
68
|
const report = await runtime.store.findByJobId(jobId);
|
|
67
69
|
if (!report) {
|
|
68
70
|
throw new Error(`Local ingest report for job "${jobId}" was not created`);
|
|
@@ -102,6 +104,7 @@ export async function runLocalIngest(options) {
|
|
|
102
104
|
queryExecutor: options.queryExecutor,
|
|
103
105
|
logger: options.logger,
|
|
104
106
|
embeddingProvider: options.embeddingProvider,
|
|
107
|
+
abortSignal: options.abortSignal,
|
|
105
108
|
});
|
|
106
109
|
}
|
|
107
110
|
const result = await runtime.runner.run({
|
|
@@ -110,7 +113,7 @@ export async function runLocalIngest(options) {
|
|
|
110
113
|
sourceKey: adapter.source,
|
|
111
114
|
trigger: options.trigger ?? (options.sourceDir ? 'upload' : 'manual_resync'),
|
|
112
115
|
bundleRef,
|
|
113
|
-
}, localJobContext(jobId, options.memoryFlow));
|
|
116
|
+
}, localJobContext(jobId, options.memoryFlow, options.abortSignal));
|
|
114
117
|
const report = await runtime.store.findByJobId(jobId);
|
|
115
118
|
if (!report) {
|
|
116
119
|
throw new Error(`Local ingest report for job "${jobId}" was not created`);
|
|
@@ -226,6 +229,9 @@ export async function runLocalMetabaseIngest(options) {
|
|
|
226
229
|
});
|
|
227
230
|
const children = [];
|
|
228
231
|
for (const childPlan of childPlans) {
|
|
232
|
+
if (options.abortSignal?.aborted) {
|
|
233
|
+
throw createAbortError();
|
|
234
|
+
}
|
|
229
235
|
const targetConnectionId = safeSegment('target connection id', childPlan.targetConnectionId);
|
|
230
236
|
if (!options.project.config.connections[targetConnectionId]) {
|
|
231
237
|
throw new Error(`Target connection "${targetConnectionId}" is not configured in ktx.yaml`);
|
|
@@ -255,9 +261,13 @@ export async function runLocalMetabaseIngest(options) {
|
|
|
255
261
|
queryExecutor: options.queryExecutor,
|
|
256
262
|
logger: options.logger,
|
|
257
263
|
embeddingProvider: options.embeddingProvider,
|
|
264
|
+
abortSignal: options.abortSignal,
|
|
258
265
|
});
|
|
259
266
|
}
|
|
260
267
|
catch (error) {
|
|
268
|
+
if (isAbortError(error)) {
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
261
271
|
child = await recordLocalMetabaseChildFailure({
|
|
262
272
|
project: options.project,
|
|
263
273
|
jobId: childJobId,
|
|
@@ -127,7 +127,7 @@ export function ingestReportToMemoryFlowReplay(report, options = {}) {
|
|
|
127
127
|
}
|
|
128
128
|
const actions = allReportActions(report);
|
|
129
129
|
const workUnitEvents = report.body.workUnits.flatMap((workUnit) => [
|
|
130
|
-
{ type: 'work_unit_started', unitKey: workUnit.unitKey, skills: []
|
|
130
|
+
{ type: 'work_unit_started', unitKey: workUnit.unitKey, skills: [] },
|
|
131
131
|
...workUnit.actions.map((action) => ({
|
|
132
132
|
type: 'candidate_action',
|
|
133
133
|
unitKey: workUnit.unitKey,
|
|
@@ -64,17 +64,22 @@ const memoryFlowEventSchema = z.discriminatedUnion('type', [
|
|
|
64
64
|
message: z.string().min(1),
|
|
65
65
|
transient: z.boolean().optional(),
|
|
66
66
|
}),
|
|
67
|
+
eventSchema({
|
|
68
|
+
type: z.literal('rate_limit_wait'),
|
|
69
|
+
provider: z.string(),
|
|
70
|
+
rateLimitType: z.string().optional(),
|
|
71
|
+
resumeAtMs: z.number().int().nonnegative(),
|
|
72
|
+
remainingMs: z.number().int().nonnegative(),
|
|
73
|
+
}),
|
|
67
74
|
eventSchema({
|
|
68
75
|
type: z.literal('work_unit_started'),
|
|
69
76
|
unitKey: z.string().min(1),
|
|
70
77
|
skills: z.array(z.string().min(1)),
|
|
71
|
-
stepBudget: z.number().int().min(0),
|
|
72
78
|
}),
|
|
73
79
|
eventSchema({
|
|
74
80
|
type: z.literal('work_unit_step'),
|
|
75
81
|
unitKey: z.string().min(1),
|
|
76
|
-
|
|
77
|
-
stepBudget: z.number().int().min(0),
|
|
82
|
+
toolCalls: z.number().int().min(0),
|
|
78
83
|
}),
|
|
79
84
|
eventSchema({
|
|
80
85
|
type: z.literal('candidate_action'),
|
|
@@ -44,16 +44,20 @@ type MemoryFlowEventPayload = {
|
|
|
44
44
|
percent: number;
|
|
45
45
|
message: string;
|
|
46
46
|
transient?: boolean;
|
|
47
|
+
} | {
|
|
48
|
+
type: 'rate_limit_wait';
|
|
49
|
+
provider: string;
|
|
50
|
+
rateLimitType?: string;
|
|
51
|
+
resumeAtMs: number;
|
|
52
|
+
remainingMs: number;
|
|
47
53
|
} | {
|
|
48
54
|
type: 'work_unit_started';
|
|
49
55
|
unitKey: string;
|
|
50
56
|
skills: string[];
|
|
51
|
-
stepBudget: number;
|
|
52
57
|
} | {
|
|
53
58
|
type: 'work_unit_step';
|
|
54
59
|
unitKey: string;
|
|
55
|
-
|
|
56
|
-
stepBudget: number;
|
|
60
|
+
toolCalls: number;
|
|
57
61
|
} | {
|
|
58
62
|
type: 'candidate_action';
|
|
59
63
|
unitKey: string;
|
|
@@ -5,6 +5,7 @@ import type { KtxFileStorePort } from '../../context/core/file-store.js';
|
|
|
5
5
|
import type { KtxLogger } from '../../context/core/config.js';
|
|
6
6
|
import type { SessionOutcome } from '../../context/core/session-worktree.service.js';
|
|
7
7
|
import type { AgentRunnerPort, KtxLlmRuntimePort, KtxRuntimeToolSet } from '../../context/llm/runtime-port.js';
|
|
8
|
+
import type { RateLimitGovernor } from '../llm/rate-limit-governor.js';
|
|
8
9
|
import type { MemoryAction, MemoryKnowledgeSlRefsPort } from '../../context/memory/types.js';
|
|
9
10
|
import type { PromptService } from '../../context/prompts/prompt.service.js';
|
|
10
11
|
import type { SkillsRegistryService } from '../../context/skills/skills-registry.service.js';
|
|
@@ -111,6 +112,7 @@ interface IngestSettingsPort {
|
|
|
111
112
|
workUnitMaxConcurrency?: number;
|
|
112
113
|
workUnitStepBudget?: number;
|
|
113
114
|
workUnitFailureMode?: 'abort' | 'continue';
|
|
115
|
+
rateLimitGovernor?: RateLimitGovernor;
|
|
114
116
|
/** Print a timing breakdown to stderr at the end of each run (config-driven; see also KTX_PROFILE_INGEST). `'json'` emits the raw structured profile. */
|
|
115
117
|
profileIngest?: boolean | 'json';
|
|
116
118
|
ingestTraceLevel?: IngestTraceLevel;
|
|
@@ -282,11 +284,7 @@ export interface CuratorPaginationPort {
|
|
|
282
284
|
}) => string;
|
|
283
285
|
buildToolSet: (passNumber: number) => KtxRuntimeToolSet;
|
|
284
286
|
getReconciliationActions: () => MemoryAction[];
|
|
285
|
-
|
|
286
|
-
passNumber: number;
|
|
287
|
-
stepIndex: number;
|
|
288
|
-
stepBudget: number;
|
|
289
|
-
}) => void;
|
|
287
|
+
abortSignal?: AbortSignal;
|
|
290
288
|
}): Promise<ReconciliationOutcome & {
|
|
291
289
|
report: CuratorPaginationReport;
|
|
292
290
|
warnings: string[];
|
|
@@ -25,10 +25,7 @@ export interface WorkUnitExecutionDeps {
|
|
|
25
25
|
sourceKey: string;
|
|
26
26
|
connectionId: string;
|
|
27
27
|
jobId: string;
|
|
28
|
-
|
|
29
|
-
stepIndex: number;
|
|
30
|
-
stepBudget: number;
|
|
31
|
-
}) => void;
|
|
28
|
+
abortSignal?: AbortSignal;
|
|
32
29
|
toolFailureCount?: (unitKey: string) => number;
|
|
33
30
|
}
|
|
34
31
|
export interface WorkUnitOutcome {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isAbortError } from '../../core/abort.js';
|
|
1
2
|
import { listTouchedSlSources } from '../../../context/tools/touched-sl-sources.js';
|
|
2
3
|
const MAX_WORK_UNIT_PROMPT_CHARS = 240_000;
|
|
3
4
|
export async function executeWorkUnit(deps, wu) {
|
|
@@ -51,10 +52,13 @@ export async function executeWorkUnit(deps, wu) {
|
|
|
51
52
|
unitKey: wu.unitKey,
|
|
52
53
|
jobId: deps.jobId,
|
|
53
54
|
},
|
|
54
|
-
|
|
55
|
+
abortSignal: deps.abortSignal,
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
58
|
catch (error) {
|
|
59
|
+
if (isAbortError(error)) {
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
58
62
|
return failWithResetFromCurrentHead(error instanceof Error ? error.message : String(error));
|
|
59
63
|
}
|
|
60
64
|
const postSha = (await deps.sessionWorktreeGit.revParseHead()) ?? preSha;
|
|
@@ -14,10 +14,7 @@ export interface ReconciliationContext {
|
|
|
14
14
|
sourceKey: string;
|
|
15
15
|
jobId: string;
|
|
16
16
|
force?: boolean;
|
|
17
|
-
|
|
18
|
-
stepIndex: number;
|
|
19
|
-
stepBudget: number;
|
|
20
|
-
}) => void;
|
|
17
|
+
abortSignal?: AbortSignal;
|
|
21
18
|
forceRun?: boolean;
|
|
22
19
|
}
|
|
23
20
|
export interface ReconciliationOutcome {
|
|
@@ -11,7 +11,7 @@ export async function runReconciliationStage4(ctx) {
|
|
|
11
11
|
toolSet: ctx.buildToolSet(),
|
|
12
12
|
stepBudget: ctx.stepBudget,
|
|
13
13
|
telemetryTags: { operationName: 'ingest-bundle-reconcile', source: ctx.sourceKey, jobId: ctx.jobId },
|
|
14
|
-
|
|
14
|
+
abortSignal: ctx.abortSignal,
|
|
15
15
|
});
|
|
16
16
|
return { skipped: false, stopReason: run.stopReason, error: run.error, ...(run.metrics ? { metrics: run.metrics } : {}) };
|
|
17
17
|
}
|
|
@@ -3,6 +3,7 @@ import { type TelemetrySettings } from 'ai';
|
|
|
3
3
|
import type { z } from 'zod';
|
|
4
4
|
import { type KtxLogger } from '../../context/core/config.js';
|
|
5
5
|
import { type KtxLlmDebugRequestRecorder } from './debug-request-recorder.js';
|
|
6
|
+
import type { RateLimitGovernor } from './rate-limit-governor.js';
|
|
6
7
|
import type { KtxGenerateObjectInput, KtxGenerateTextInput, KtxLlmRuntimePort, RunLoopParams, RunLoopResult } from './runtime-port.js';
|
|
7
8
|
interface AgentTelemetryPort {
|
|
8
9
|
createTelemetry(tags: Record<string, string>): TelemetrySettings;
|
|
@@ -12,11 +13,13 @@ export interface AiSdkKtxLlmRuntimeDeps {
|
|
|
12
13
|
telemetry?: AgentTelemetryPort;
|
|
13
14
|
logger?: KtxLogger;
|
|
14
15
|
debugRequestRecorder?: KtxLlmDebugRequestRecorder;
|
|
16
|
+
rateLimitGovernor?: Pick<RateLimitGovernor, 'waitForReady' | 'report' | 'maxRetryAttempts'>;
|
|
15
17
|
}
|
|
16
18
|
export declare class AiSdkKtxLlmRuntime implements KtxLlmRuntimePort {
|
|
17
19
|
private readonly deps;
|
|
18
20
|
private readonly logger;
|
|
19
21
|
constructor(deps: AiSdkKtxLlmRuntimeDeps);
|
|
22
|
+
private generateTextWithRateLimitRetry;
|
|
20
23
|
generateText(input: KtxGenerateTextInput): Promise<string>;
|
|
21
24
|
generateObject<TOutput, TSchema extends z.ZodType<TOutput>>(input: KtxGenerateObjectInput<TOutput, TSchema>): Promise<TOutput>;
|
|
22
25
|
runAgentLoop(params: RunLoopParams): Promise<RunLoopResult>;
|