@gkorepanov/ccodex 0.4.14 → 0.4.16
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/config/compatibility.json +1 -1
- package/dist/claude/service.js +30 -3
- package/dist/claude/service.js.map +1 -1
- package/dist/claude/session/commands.d.ts +4 -0
- package/dist/claude/session/session.d.ts +5 -0
- package/dist/claude/session/session.js +134 -19
- package/dist/claude/session/session.js.map +1 -1
- package/dist/claude/streamingFilePreview.d.ts +16 -0
- package/dist/claude/streamingFilePreview.js +206 -0
- package/dist/claude/streamingFilePreview.js.map +1 -0
- package/dist/claude/toolMapper.d.ts +1 -0
- package/dist/claude/toolMapper.js +1 -1
- package/dist/claude/toolMapper.js.map +1 -1
- package/dist/claude/transcriptBrancher.d.ts +6 -2
- package/dist/claude/transcriptBrancher.js +42 -5
- package/dist/claude/transcriptBrancher.js.map +1 -1
- package/dist/store/memoryStore.js +7 -2
- package/dist/store/memoryStore.js.map +1 -1
- package/dist/store/sqliteStore.js +4 -0
- package/dist/store/sqliteStore.js.map +1 -1
- package/package.json +4 -4
|
@@ -27,6 +27,7 @@ import { StaleClaudeRuntimeSettingsError, createProviderRuntime, providerPermiss
|
|
|
27
27
|
import { isRetryableClaudeRuntimeStartupError, } from "./providerRuntime.js";
|
|
28
28
|
import { assistantHasTools, backgroundOutputFile, backgroundTaskId, isNoQueryAcknowledgement, serverToolResult, toolResults, } from "./providerFacts.js";
|
|
29
29
|
import { normalizeClaudeModelIdentifier } from "../modelSelection.js";
|
|
30
|
+
import { StreamingFileChangePreview } from "../streamingFilePreview.js";
|
|
30
31
|
const nullSource = { providerEventId: null, providerEventType: null };
|
|
31
32
|
const providerJournalMaxEvents = 20_000;
|
|
32
33
|
const providerJournalMaxBytes = 256 * 1_024 * 1_024;
|
|
@@ -100,7 +101,7 @@ function commandLane(command) {
|
|
|
100
101
|
return "control";
|
|
101
102
|
if (["providerEventStarted", "providerEventFinished", "providerBoundary", "providerRetract",
|
|
102
103
|
"conversationReset", "modelFallback", "fastModeStatus", "systemNotice", "runtimeNotification", "mainStream",
|
|
103
|
-
"accountUsage", "accountCost", "publishUsage", "lifecycle", "compactBoundary", "compactFailed",
|
|
104
|
+
"accountUsage", "accountCost", "publishUsage", "lifecycle", "autoCompactStarted", "compactBoundary", "compactFailed",
|
|
104
105
|
"postCompact",
|
|
105
106
|
].includes(command.type))
|
|
106
107
|
return "provider";
|
|
@@ -134,6 +135,7 @@ export class ClaudeSession {
|
|
|
134
135
|
scopes = new Map();
|
|
135
136
|
tasks = new Map();
|
|
136
137
|
compaction;
|
|
138
|
+
automaticCompaction;
|
|
137
139
|
compactionActions = [];
|
|
138
140
|
lastPublishedUsage;
|
|
139
141
|
lifecycle;
|
|
@@ -594,6 +596,7 @@ export class ClaudeSession {
|
|
|
594
596
|
const projection = {
|
|
595
597
|
context: new AsyncLocalStorage(),
|
|
596
598
|
processEpoch: uuidv7(),
|
|
599
|
+
filePreviews: new Map(),
|
|
597
600
|
providerSequence: 0,
|
|
598
601
|
};
|
|
599
602
|
try {
|
|
@@ -1340,6 +1343,13 @@ export class ClaudeSession {
|
|
|
1340
1343
|
if (status === "requesting") {
|
|
1341
1344
|
await this.providerSubmitLifecycle(projection, runtimeGeneration, { type: "request", messageStarted: false });
|
|
1342
1345
|
}
|
|
1346
|
+
else if (status === "compacting") {
|
|
1347
|
+
await this.submitProviderProjection(runtimeGeneration, {
|
|
1348
|
+
type: "autoCompactStarted",
|
|
1349
|
+
runtimeGeneration,
|
|
1350
|
+
source: this.providerFactSource(projection),
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1343
1353
|
return "stateOnly";
|
|
1344
1354
|
}
|
|
1345
1355
|
if (message.type === "system" && message.subtype === "session_state_changed") {
|
|
@@ -1762,6 +1772,37 @@ export class ClaudeSession {
|
|
|
1762
1772
|
fact,
|
|
1763
1773
|
});
|
|
1764
1774
|
}
|
|
1775
|
+
async applyProviderToolInput(projection, runtimeGeneration, index, delta, ownerThreadId = this.threadId) {
|
|
1776
|
+
const projected = await this.applyProviderMainStream(projection, runtimeGeneration, {
|
|
1777
|
+
kind: "toolInput", index, delta,
|
|
1778
|
+
}, ownerThreadId);
|
|
1779
|
+
const tool = projected?.tool;
|
|
1780
|
+
if (tool?.name !== "Write" && tool?.name !== "Edit")
|
|
1781
|
+
return;
|
|
1782
|
+
const key = `${ownerThreadId}\0${index}`;
|
|
1783
|
+
let state = projection.filePreviews.get(key);
|
|
1784
|
+
if (!state) {
|
|
1785
|
+
state = { providerId: tool.providerId, preview: new StreamingFileChangePreview(tool.name, tool.cwd) };
|
|
1786
|
+
projection.filePreviews.set(key, state);
|
|
1787
|
+
}
|
|
1788
|
+
const change = await state.preview.push(delta);
|
|
1789
|
+
if (change)
|
|
1790
|
+
await this.applyProviderMainStream(projection, runtimeGeneration, {
|
|
1791
|
+
kind: "toolFiles", providerId: state.providerId, changes: [change],
|
|
1792
|
+
}, ownerThreadId);
|
|
1793
|
+
}
|
|
1794
|
+
async finishProviderToolInput(projection, runtimeGeneration, index, ownerThreadId = this.threadId) {
|
|
1795
|
+
const key = `${ownerThreadId}\0${index}`;
|
|
1796
|
+
const state = projection.filePreviews.get(key);
|
|
1797
|
+
if (!state)
|
|
1798
|
+
return;
|
|
1799
|
+
projection.filePreviews.delete(key);
|
|
1800
|
+
const change = await state.preview.finish();
|
|
1801
|
+
if (change)
|
|
1802
|
+
await this.applyProviderMainStream(projection, runtimeGeneration, {
|
|
1803
|
+
kind: "toolFiles", providerId: state.providerId, changes: [change],
|
|
1804
|
+
}, ownerThreadId);
|
|
1805
|
+
}
|
|
1765
1806
|
async canUseProviderTool(projection, runtimeGeneration, name, input, options) {
|
|
1766
1807
|
const context = await this.providerCallbackContext(runtimeGeneration);
|
|
1767
1808
|
if (!context)
|
|
@@ -2183,15 +2224,12 @@ export class ClaudeSession {
|
|
|
2183
2224
|
}, childThreadId);
|
|
2184
2225
|
}
|
|
2185
2226
|
else if (event.delta.type === "input_json_delta") {
|
|
2186
|
-
await this.
|
|
2187
|
-
kind: "toolInput",
|
|
2188
|
-
index: event.index,
|
|
2189
|
-
delta: event.delta.partial_json,
|
|
2190
|
-
}, childThreadId);
|
|
2227
|
+
await this.applyProviderToolInput(projection, runtimeGeneration, event.index, event.delta.partial_json, childThreadId);
|
|
2191
2228
|
}
|
|
2192
2229
|
return;
|
|
2193
2230
|
}
|
|
2194
2231
|
if (event.type === "content_block_stop") {
|
|
2232
|
+
await this.finishProviderToolInput(projection, runtimeGeneration, event.index, childThreadId);
|
|
2195
2233
|
await this.applyProviderMainStream(projection, runtimeGeneration, { kind: "blockStop", index: event.index }, childThreadId);
|
|
2196
2234
|
}
|
|
2197
2235
|
}
|
|
@@ -2510,15 +2548,12 @@ export class ClaudeSession {
|
|
|
2510
2548
|
});
|
|
2511
2549
|
}
|
|
2512
2550
|
else if (event.delta.type === "input_json_delta") {
|
|
2513
|
-
await this.
|
|
2514
|
-
kind: "toolInput",
|
|
2515
|
-
index: event.index,
|
|
2516
|
-
delta: event.delta.partial_json,
|
|
2517
|
-
});
|
|
2551
|
+
await this.applyProviderToolInput(projection, runtimeGeneration, event.index, event.delta.partial_json);
|
|
2518
2552
|
}
|
|
2519
2553
|
return;
|
|
2520
2554
|
}
|
|
2521
2555
|
if (event.type === "content_block_stop") {
|
|
2556
|
+
await this.finishProviderToolInput(projection, runtimeGeneration, event.index);
|
|
2522
2557
|
await this.applyProviderMainStream(projection, runtimeGeneration, { kind: "blockStop", index: event.index });
|
|
2523
2558
|
}
|
|
2524
2559
|
}
|
|
@@ -4472,10 +4507,15 @@ export class ClaudeSession {
|
|
|
4472
4507
|
if (command.runtimeGeneration !== this.runtimeGeneration)
|
|
4473
4508
|
return { admitted: false, hidden: false };
|
|
4474
4509
|
return {
|
|
4475
|
-
admitted: command.trigger === "auto"
|
|
4510
|
+
admitted: command.trigger === "auto"
|
|
4511
|
+
? !this.compaction && Boolean(this.automaticCompaction || this.activeNormalTurn())
|
|
4476
4512
|
: Boolean(this.compaction && !this.compaction.cancellation),
|
|
4477
4513
|
hidden: Boolean(this.compaction?.hidden),
|
|
4478
4514
|
};
|
|
4515
|
+
case "autoCompactStarted":
|
|
4516
|
+
if (command.runtimeGeneration !== this.runtimeGeneration)
|
|
4517
|
+
return undefined;
|
|
4518
|
+
return this.startAutomaticCompaction(command.runtimeGeneration, command.source);
|
|
4479
4519
|
case "compactBoundary":
|
|
4480
4520
|
if (command.runtimeGeneration !== this.runtimeGeneration)
|
|
4481
4521
|
return undefined;
|
|
@@ -4501,8 +4541,10 @@ export class ClaudeSession {
|
|
|
4501
4541
|
: this.compactionProjection();
|
|
4502
4542
|
}
|
|
4503
4543
|
case "compactFailed":
|
|
4504
|
-
if (command.runtimeGeneration !== this.runtimeGeneration
|
|
4544
|
+
if (command.runtimeGeneration !== this.runtimeGeneration)
|
|
4505
4545
|
return undefined;
|
|
4546
|
+
if (!this.compaction)
|
|
4547
|
+
return this.completeAutomaticCompaction(command.source);
|
|
4506
4548
|
if (this.compaction.cancellation)
|
|
4507
4549
|
return this.compactionProjection();
|
|
4508
4550
|
return this.completeCompaction("failed", command.message, command.codexErrorInfo, command.source);
|
|
@@ -4842,21 +4884,77 @@ export class ClaudeSession {
|
|
|
4842
4884
|
if (this.compaction)
|
|
4843
4885
|
return this.compactionProjection();
|
|
4844
4886
|
const record = this.requireRecord(true);
|
|
4845
|
-
const
|
|
4887
|
+
const automatic = this.automaticCompaction;
|
|
4888
|
+
const turn = automatic
|
|
4889
|
+
? this.repository.readTurn(this.threadId, automatic.turnId)
|
|
4890
|
+
: this.activeNormalTurn(record);
|
|
4846
4891
|
if (!turn)
|
|
4847
4892
|
return undefined;
|
|
4893
|
+
const item = automatic
|
|
4894
|
+
? turn.items.find((candidate) => candidate.id === automatic.itemId)
|
|
4895
|
+
: undefined;
|
|
4848
4896
|
const updated = { ...record, lastClaudeMessageUuid: boundary };
|
|
4849
|
-
this.commitState(updated, [
|
|
4897
|
+
this.commitState(updated, [
|
|
4898
|
+
...(item?.type === "contextCompaction" ? [{
|
|
4899
|
+
turnId: turn.id,
|
|
4900
|
+
method: "item/completed",
|
|
4901
|
+
params: { item, threadId: this.threadId, turnId: turn.id, completedAtMs: Date.now() },
|
|
4902
|
+
providerEventId: source.providerEventId,
|
|
4903
|
+
providerEventType: source.providerEventType,
|
|
4904
|
+
}] : []),
|
|
4905
|
+
{
|
|
4850
4906
|
turnId: turn.id,
|
|
4851
4907
|
method: "thread/compacted",
|
|
4852
4908
|
params: { threadId: this.threadId, turnId: turn.id },
|
|
4853
4909
|
providerEventId: source.providerEventId,
|
|
4854
4910
|
providerEventType: source.providerEventType,
|
|
4855
|
-
}
|
|
4911
|
+
},
|
|
4912
|
+
], turn, false, {
|
|
4856
4913
|
ownerThreadId: this.threadId,
|
|
4857
4914
|
turnId: turn.id,
|
|
4858
4915
|
messageUuid: boundary,
|
|
4859
4916
|
});
|
|
4917
|
+
if (automatic)
|
|
4918
|
+
this.automaticCompaction = undefined;
|
|
4919
|
+
return { turnId: turn.id, terminal: false };
|
|
4920
|
+
}
|
|
4921
|
+
startAutomaticCompaction(runtimeGeneration, source) {
|
|
4922
|
+
if (this.compaction)
|
|
4923
|
+
return this.compactionProjection();
|
|
4924
|
+
const turn = this.activeNormalTurn();
|
|
4925
|
+
if (!turn)
|
|
4926
|
+
return undefined;
|
|
4927
|
+
if (this.automaticCompaction?.turnId === turn.id) {
|
|
4928
|
+
return { turnId: turn.id, terminal: false };
|
|
4929
|
+
}
|
|
4930
|
+
const item = {
|
|
4931
|
+
type: "contextCompaction",
|
|
4932
|
+
id: uuidv7(),
|
|
4933
|
+
};
|
|
4934
|
+
turn.items.push(item);
|
|
4935
|
+
this.publishTurn(turn, "item/started", {
|
|
4936
|
+
item, threadId: this.threadId, turnId: turn.id, startedAtMs: Date.now(),
|
|
4937
|
+
}, source);
|
|
4938
|
+
this.automaticCompaction = { turnId: turn.id, itemId: item.id, runtimeGeneration };
|
|
4939
|
+
return { turnId: turn.id, terminal: false };
|
|
4940
|
+
}
|
|
4941
|
+
completeAutomaticCompaction(source) {
|
|
4942
|
+
const automatic = this.automaticCompaction;
|
|
4943
|
+
if (!automatic)
|
|
4944
|
+
return undefined;
|
|
4945
|
+
const record = this.requireRecord(false);
|
|
4946
|
+
const turn = this.repository.readTurn(this.threadId, automatic.turnId);
|
|
4947
|
+
const item = turn?.items.find((candidate) => candidate.id === automatic.itemId);
|
|
4948
|
+
if (!turn || item?.type !== "contextCompaction")
|
|
4949
|
+
return undefined;
|
|
4950
|
+
this.commitState(record, [{
|
|
4951
|
+
turnId: turn.id,
|
|
4952
|
+
method: "item/completed",
|
|
4953
|
+
params: { item, threadId: this.threadId, turnId: turn.id, completedAtMs: Date.now() },
|
|
4954
|
+
providerEventId: source.providerEventId,
|
|
4955
|
+
providerEventType: source.providerEventType,
|
|
4956
|
+
}], turn);
|
|
4957
|
+
this.automaticCompaction = undefined;
|
|
4860
4958
|
return { turnId: turn.id, terminal: false };
|
|
4861
4959
|
}
|
|
4862
4960
|
completeCompaction(status, errorMessage, codexErrorInfo, source, boundary) {
|
|
@@ -4906,7 +5004,7 @@ export class ClaudeSession {
|
|
|
4906
5004
|
}
|
|
4907
5005
|
activeNormalTurn(record = this.requireRecord(true)) {
|
|
4908
5006
|
return record.thread.turns.findLast((turn) => turn.status === "inProgress"
|
|
4909
|
-
&&
|
|
5007
|
+
&& turn.items.some((item) => item.type !== "contextCompaction"));
|
|
4910
5008
|
}
|
|
4911
5009
|
startTurn(items, threadPatch = {}, id = uuidv7(), emitEvents = true) {
|
|
4912
5010
|
const record = this.requireRecord(false);
|
|
@@ -5076,7 +5174,21 @@ export class ClaudeSession {
|
|
|
5076
5174
|
updatedAt: turn.completedAt, recencyAt: turn.completedAt,
|
|
5077
5175
|
},
|
|
5078
5176
|
};
|
|
5079
|
-
const
|
|
5177
|
+
const automatic = this.automaticCompaction?.turnId === turn.id
|
|
5178
|
+
? this.automaticCompaction
|
|
5179
|
+
: undefined;
|
|
5180
|
+
const automaticItem = automatic
|
|
5181
|
+
? turn.items.find((item) => item.id === automatic.itemId)
|
|
5182
|
+
: undefined;
|
|
5183
|
+
const events = [
|
|
5184
|
+
...(automaticItem?.type === "contextCompaction" ? [{
|
|
5185
|
+
turnId: turn.id,
|
|
5186
|
+
method: "item/completed",
|
|
5187
|
+
params: { item: automaticItem, threadId: this.threadId, turnId: turn.id, completedAtMs: Date.now() },
|
|
5188
|
+
providerEventId: source.providerEventId,
|
|
5189
|
+
providerEventType: source.providerEventType,
|
|
5190
|
+
}] : []),
|
|
5191
|
+
...terminalEvents.map((event) => ({
|
|
5080
5192
|
...event,
|
|
5081
5193
|
providerEventId: event.providerEventId ?? source.providerEventId,
|
|
5082
5194
|
providerEventType: event.providerEventType ?? source.providerEventType,
|
|
@@ -5086,7 +5198,8 @@ export class ClaudeSession {
|
|
|
5086
5198
|
params: { threadId: this.threadId, status: updated.thread.status },
|
|
5087
5199
|
providerEventId: source.providerEventId,
|
|
5088
5200
|
providerEventType: source.providerEventType,
|
|
5089
|
-
}
|
|
5201
|
+
}
|
|
5202
|
+
];
|
|
5090
5203
|
if (turn.error && emitError)
|
|
5091
5204
|
events.push({
|
|
5092
5205
|
turnId: turn.id,
|
|
@@ -5105,6 +5218,8 @@ export class ClaudeSession {
|
|
|
5105
5218
|
providerEventType: source.providerEventType,
|
|
5106
5219
|
});
|
|
5107
5220
|
this.commitState(updated, events, turn, false, providerBoundary, emitEvents);
|
|
5221
|
+
if (automatic)
|
|
5222
|
+
this.automaticCompaction = undefined;
|
|
5108
5223
|
return { record: updated, turn };
|
|
5109
5224
|
}
|
|
5110
5225
|
goalContext() {
|