@gkorepanov/ccodex 0.4.8 → 0.4.10
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 +1 -1
- package/config/compatibility.json +3 -3
- package/dist/claude/goalTools.js +1 -1
- package/dist/claude/goalTools.js.map +1 -1
- package/dist/claude/hookMapper.d.ts +1 -0
- package/dist/claude/hookMapper.js +1 -0
- package/dist/claude/hookMapper.js.map +1 -1
- package/dist/claude/inputMapper.js +4 -1
- package/dist/claude/inputMapper.js.map +1 -1
- package/dist/claude/modelCatalog.d.ts +1 -0
- package/dist/claude/modelCatalog.js +12 -9
- package/dist/claude/modelCatalog.js.map +1 -1
- package/dist/claude/rateLimits.d.ts +1 -0
- package/dist/claude/rateLimits.js +2 -1
- package/dist/claude/rateLimits.js.map +1 -1
- package/dist/claude/service.d.ts +13 -1
- package/dist/claude/service.js +152 -19
- package/dist/claude/service.js.map +1 -1
- package/dist/claude/session/commands.d.ts +3 -0
- package/dist/claude/session/goalState.js +9 -0
- package/dist/claude/session/goalState.js.map +1 -1
- package/dist/claude/session/repository.d.ts +1 -1
- package/dist/claude/session/repository.js +2 -2
- package/dist/claude/session/repository.js.map +1 -1
- package/dist/claude/session/scopeState.js +3 -1
- package/dist/claude/session/scopeState.js.map +1 -1
- package/dist/claude/session/session.js +13 -2
- package/dist/claude/session/session.js.map +1 -1
- package/dist/claude/session/usage.js +1 -0
- package/dist/claude/session/usage.js.map +1 -1
- package/dist/claude/toolMapper.js +2 -2
- package/dist/claude/toolMapper.js.map +1 -1
- package/dist/codex/generated/ClientRequest.d.ts +20 -0
- package/dist/codex/generated/CodexResponseHandoffMode.d.ts +1 -0
- package/dist/codex/generated/CodexResponseHandoffMode.js +3 -0
- package/dist/codex/generated/CodexResponseHandoffMode.js.map +1 -0
- package/dist/codex/generated/ContentItem.d.ts +3 -0
- package/dist/codex/generated/FunctionCallOutputContentItem.d.ts +3 -0
- package/dist/codex/generated/InputModality.d.ts +1 -1
- package/dist/codex/generated/LegacyAppPathString.d.ts +7 -6
- package/dist/codex/generated/RealtimeConversationVersion.d.ts +1 -1
- package/dist/codex/generated/ResponseItem.d.ts +15 -14
- package/dist/codex/generated/ResponseItemId.d.ts +5 -0
- package/dist/codex/generated/ResponseItemId.js +3 -0
- package/dist/codex/generated/ResponseItemId.js.map +1 -0
- package/dist/codex/generated/ResponseItemRuntimeSchema.js +2 -2
- package/dist/codex/generated/ResponseItemRuntimeSchema.js.map +1 -1
- package/dist/codex/generated/ReviewDecision.d.ts +5 -1
- package/dist/codex/generated/ServerNotification.d.ts +11 -0
- package/dist/codex/generated/ServerNotificationEnvelope.d.ts +302 -0
- package/dist/codex/generated/ServerNotificationEnvelope.js +3 -0
- package/dist/codex/generated/ServerNotificationEnvelope.js.map +1 -0
- package/dist/codex/generated/SleepItem.d.ts +7 -0
- package/dist/codex/generated/SleepItem.js +3 -0
- package/dist/codex/generated/SleepItem.js.map +1 -0
- package/dist/codex/generated/WebSearchItem.d.ts +8 -0
- package/dist/codex/generated/index.d.ts +4 -1
- package/dist/codex/generated/index.js.map +1 -1
- package/dist/codex/generated/v2/Account.d.ts +1 -2
- package/dist/codex/generated/v2/AppToolSummary.d.ts +8 -0
- package/dist/codex/generated/v2/AppToolSummary.js +3 -0
- package/dist/codex/generated/v2/AppToolSummary.js.map +1 -0
- package/dist/codex/generated/v2/AppsInstalledParams.d.ts +14 -0
- package/dist/codex/generated/v2/AppsInstalledParams.js +3 -0
- package/dist/codex/generated/v2/AppsInstalledParams.js.map +1 -0
- package/dist/codex/generated/v2/AppsInstalledResponse.d.ts +7 -0
- package/dist/codex/generated/v2/AppsInstalledResponse.js +3 -0
- package/dist/codex/generated/v2/AppsInstalledResponse.js.map +1 -0
- package/dist/codex/generated/v2/AppsReadParams.d.ts +14 -0
- package/dist/codex/generated/v2/AppsReadParams.js +3 -0
- package/dist/codex/generated/v2/AppsReadParams.js.map +1 -0
- package/dist/codex/generated/v2/AppsReadResponse.d.ts +8 -0
- package/dist/codex/generated/v2/AppsReadResponse.js +3 -0
- package/dist/codex/generated/v2/AppsReadResponse.js.map +1 -0
- package/dist/codex/generated/v2/ConfiguredHookHandler.d.ts +7 -0
- package/dist/codex/generated/v2/ConnectorMetadata.d.ts +15 -0
- package/dist/codex/generated/v2/ConnectorMetadata.js +3 -0
- package/dist/codex/generated/v2/ConnectorMetadata.js.map +1 -0
- package/dist/codex/generated/v2/DynamicToolCallOutputContentItem.d.ts +3 -0
- package/dist/codex/generated/v2/EnvironmentConnectionNotification.d.ts +4 -0
- package/dist/codex/generated/v2/EnvironmentConnectionNotification.js +3 -0
- package/dist/codex/generated/v2/EnvironmentConnectionNotification.js.map +1 -0
- package/dist/codex/generated/v2/EnvironmentStatusKind.d.ts +7 -0
- package/dist/codex/generated/v2/EnvironmentStatusKind.js +3 -0
- package/dist/codex/generated/v2/EnvironmentStatusKind.js.map +1 -0
- package/dist/codex/generated/v2/EnvironmentStatusParams.d.ts +9 -0
- package/dist/codex/generated/v2/EnvironmentStatusParams.js +3 -0
- package/dist/codex/generated/v2/EnvironmentStatusParams.js.map +1 -0
- package/dist/codex/generated/v2/EnvironmentStatusResponse.d.ts +14 -0
- package/dist/codex/generated/v2/EnvironmentStatusResponse.js +3 -0
- package/dist/codex/generated/v2/EnvironmentStatusResponse.js.map +1 -0
- package/dist/codex/generated/v2/ExternalAgentConfigDetectParams.d.ts +9 -0
- package/dist/codex/generated/v2/ExternalAgentConfigImportHistoriesReadResponse.d.ts +2 -0
- package/dist/codex/generated/v2/ExternalAgentConfigImportItemTypeFailure.d.ts +1 -0
- package/dist/codex/generated/v2/ExternalAgentConfigImportParams.d.ts +6 -1
- package/dist/codex/generated/v2/ExternalAgentConfigMigrationItemType.d.ts +1 -1
- package/dist/codex/generated/v2/ExternalAgentImportedConnectorCandidate.d.ts +6 -0
- package/dist/codex/generated/v2/ExternalAgentImportedConnectorCandidate.js +3 -0
- package/dist/codex/generated/v2/ExternalAgentImportedConnectorCandidate.js.map +1 -0
- package/dist/codex/generated/v2/ExternalAgentImportedConnectorSource.d.ts +1 -0
- package/dist/codex/generated/v2/ExternalAgentImportedConnectorSource.js +3 -0
- package/dist/codex/generated/v2/ExternalAgentImportedConnectorSource.js.map +1 -0
- package/dist/codex/generated/v2/FileSystemSpecialPath.d.ts +3 -2
- package/dist/codex/generated/v2/HookEventName.d.ts +1 -1
- package/dist/codex/generated/v2/HookMetadata.d.ts +5 -0
- package/dist/codex/generated/v2/InstalledApp.d.ts +21 -0
- package/dist/codex/generated/v2/InstalledApp.js +3 -0
- package/dist/codex/generated/v2/InstalledApp.js.map +1 -0
- package/dist/codex/generated/v2/LoginAccountParams.d.ts +4 -0
- package/dist/codex/generated/v2/LoginAccountResponse.d.ts +2 -0
- package/dist/codex/generated/v2/ManagedHooksRequirements.d.ts +1 -0
- package/dist/codex/generated/v2/McpToolCallAppContext.d.ts +0 -1
- package/dist/codex/generated/v2/MigrationDetails.d.ts +1 -0
- package/dist/codex/generated/v2/PluginDetail.d.ts +2 -0
- package/dist/codex/generated/v2/PluginShareUpdateDiscoverability.d.ts +1 -1
- package/dist/codex/generated/v2/PluginSummary.d.ts +1 -0
- package/dist/codex/generated/v2/RateLimitSnapshot.d.ts +4 -0
- package/dist/codex/generated/v2/RawResponseCompletedNotification.d.ts +11 -0
- package/dist/codex/generated/v2/RawResponseCompletedNotification.js +3 -0
- package/dist/codex/generated/v2/RawResponseCompletedNotification.js.map +1 -0
- package/dist/codex/generated/v2/ScheduledTaskSchedule.d.ts +16 -0
- package/dist/codex/generated/v2/ScheduledTaskSchedule.js +3 -0
- package/dist/codex/generated/v2/ScheduledTaskSchedule.js.map +1 -0
- package/dist/codex/generated/v2/ScheduledTaskSummary.d.ts +7 -0
- package/dist/codex/generated/v2/ScheduledTaskSummary.js +3 -0
- package/dist/codex/generated/v2/ScheduledTaskSummary.js.map +1 -0
- package/dist/codex/generated/v2/ScheduledTaskWeekday.d.ts +1 -0
- package/dist/codex/generated/v2/ScheduledTaskWeekday.js +3 -0
- package/dist/codex/generated/v2/ScheduledTaskWeekday.js.map +1 -0
- package/dist/codex/generated/v2/Thread.d.ts +5 -0
- package/dist/codex/generated/v2/ThreadForkParams.d.ts +11 -0
- package/dist/codex/generated/v2/ThreadItem.d.ts +2 -3
- package/dist/codex/generated/v2/ThreadItemEntry.d.ts +8 -0
- package/dist/codex/generated/v2/ThreadItemEntry.js +3 -0
- package/dist/codex/generated/v2/ThreadItemEntry.js.map +1 -0
- package/dist/codex/generated/v2/ThreadItemsListResponse.d.ts +2 -2
- package/dist/codex/generated/v2/ThreadRealtimeInitialItem.d.ts +8 -0
- package/dist/codex/generated/v2/ThreadRealtimeInitialItem.js +3 -0
- package/dist/codex/generated/v2/ThreadRealtimeInitialItem.js.map +1 -0
- package/dist/codex/generated/v2/ThreadRealtimeStartParams.d.ts +11 -4
- package/dist/codex/generated/v2/ThreadResumeResponse.d.ts +14 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrence.d.ts +17 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrence.js +3 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrence.js.map +1 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrencesParams.d.ts +19 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrencesParams.js +3 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrencesParams.js.map +1 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrencesResponse.d.ts +11 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrencesResponse.js +3 -0
- package/dist/codex/generated/v2/ThreadSearchOccurrencesResponse.js.map +1 -0
- package/dist/codex/generated/v2/ThreadSearchTextRange.d.ts +13 -0
- package/dist/codex/generated/v2/ThreadSearchTextRange.js +3 -0
- package/dist/codex/generated/v2/ThreadSearchTextRange.js.map +1 -0
- package/dist/codex/generated/v2/TokenUsageBreakdown.d.ts +1 -0
- package/dist/codex/generated/v2/TurnEnvironmentParams.d.ts +4 -0
- package/dist/codex/generated/v2/UserInput.d.ts +6 -0
- package/dist/codex/generated/v2/index.d.ts +23 -0
- package/dist/daemon/daemon.js +5 -20
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/probe.js +1 -1
- package/dist/daemon/settings.d.ts +6 -0
- package/dist/daemon/settings.js +23 -0
- package/dist/daemon/settings.js.map +1 -0
- package/dist/gateway/clientConnection.d.ts +3 -2
- package/dist/gateway/clientConnection.js +41 -44
- package/dist/gateway/clientConnection.js.map +1 -1
- package/dist/gateway/logicalThreadProjection.d.ts +5 -0
- package/dist/gateway/logicalThreadProjection.js +58 -1
- package/dist/gateway/logicalThreadProjection.js.map +1 -1
- package/dist/gateway/remoteControlController.d.ts +29 -0
- package/dist/gateway/remoteControlController.js +78 -0
- package/dist/gateway/remoteControlController.js.map +1 -0
- package/dist/gateway/remoteControlHub.js +2 -1
- package/dist/gateway/remoteControlHub.js.map +1 -1
- package/dist/gateway/remoteControlMode.js +2 -12
- package/dist/gateway/remoteControlMode.js.map +1 -1
- package/dist/gateway/server.js +42 -15
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/subscriptions.d.ts +9 -2
- package/dist/gateway/subscriptions.js +40 -9
- package/dist/gateway/subscriptions.js.map +1 -1
- package/dist/gateway/threadList.d.ts +25 -0
- package/dist/gateway/threadList.js +112 -26
- package/dist/gateway/threadList.js.map +1 -1
- package/dist/handoff/lineageStore.d.ts +101 -0
- package/dist/handoff/lineageStore.js +502 -0
- package/dist/handoff/lineageStore.js.map +1 -0
- package/dist/handoff/providerEpochs.d.ts +19 -5
- package/dist/handoff/providerEpochs.js +119 -41
- package/dist/handoff/providerEpochs.js.map +1 -1
- package/dist/handoff/service.d.ts +16 -2
- package/dist/handoff/service.js +595 -174
- package/dist/handoff/service.js.map +1 -1
- package/dist/handoff/startupMigration.d.ts +22 -0
- package/dist/handoff/startupMigration.js +52 -0
- package/dist/handoff/startupMigration.js.map +1 -0
- package/dist/handoff/store.d.ts +10 -0
- package/dist/handoff/store.js +141 -28
- package/dist/handoff/store.js.map +1 -1
- package/dist/runtime/dependencies.js +1 -1
- package/dist/store/HybridStore.d.ts +3 -1
- package/dist/store/HybridStore.js.map +1 -1
- package/dist/store/memoryStore.d.ts +3 -2
- package/dist/store/memoryStore.js +18 -4
- package/dist/store/memoryStore.js.map +1 -1
- package/dist/store/sqliteStore.d.ts +1 -2
- package/dist/store/sqliteStore.js +57 -24
- package/dist/store/sqliteStore.js.map +1 -1
- package/legal/LICENSES.md +1 -1
- package/legal/THIRD_PARTY_NOTICES.md +136 -124
- package/package.json +5 -5
- package/dist/codex/generated/AmazonBedrockCredentialSource.d.ts +0 -1
- package/dist/codex/generated/AmazonBedrockCredentialSource.js +0 -3
- package/dist/codex/generated/AmazonBedrockCredentialSource.js.map +0 -1
package/dist/claude/service.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { join, resolve } from "node:path";
|
|
2
2
|
import { statSync } from "node:fs";
|
|
3
|
-
import { deleteSession, renameSession, } from "@anthropic-ai/claude-agent-sdk";
|
|
3
|
+
import { deleteSession, listSessions, renameSession, } from "@anthropic-ai/claude-agent-sdk";
|
|
4
4
|
import { v7 as uuidv7 } from "uuid";
|
|
5
5
|
import { settingsGeneration } from "../store/HybridStore.js";
|
|
6
6
|
import { SqliteHybridStore } from "../store/sqliteStore.js";
|
|
@@ -79,7 +79,11 @@ function threadResponse(record, includeTurns) {
|
|
|
79
79
|
const { sandboxPolicy: sandbox, effort: reasoningEffort, summary: _summary, collaborationMode: _collaborationMode, personality: _personality, ...settings } = threadSettings(record);
|
|
80
80
|
return {
|
|
81
81
|
...settings,
|
|
82
|
-
thread: {
|
|
82
|
+
thread: {
|
|
83
|
+
...record.thread,
|
|
84
|
+
canAcceptDirectInput: record.thread.parentThreadId ? false : true,
|
|
85
|
+
turns: includeTurns ? record.thread.turns : [],
|
|
86
|
+
},
|
|
83
87
|
runtimeWorkspaceRoots: [record.thread.cwd],
|
|
84
88
|
instructionSources: [],
|
|
85
89
|
sandbox,
|
|
@@ -169,10 +173,12 @@ export class ClaudeService {
|
|
|
169
173
|
threadAdminEffects;
|
|
170
174
|
availabilityProbe;
|
|
171
175
|
skillsChanged;
|
|
176
|
+
nativeSessionCatalog;
|
|
172
177
|
ephemeralReleases = new Map();
|
|
173
178
|
ephemeralReleaseTimers = new Map();
|
|
174
179
|
removalRetries = new Map();
|
|
175
180
|
terminalAdmins = new Map();
|
|
181
|
+
settingsUpdates = new Map();
|
|
176
182
|
idleTimer;
|
|
177
183
|
store;
|
|
178
184
|
sessionOutput;
|
|
@@ -183,10 +189,13 @@ export class ClaudeService {
|
|
|
183
189
|
closing = false;
|
|
184
190
|
closePromise;
|
|
185
191
|
standaloneStatusRead;
|
|
192
|
+
nativeMetadata = new Map();
|
|
193
|
+
nativeMetadataRead;
|
|
194
|
+
nativeMetadataReadAt = 0;
|
|
186
195
|
constructor(config, hub, logger, durableStore = new SqliteHybridStore(join(config.dataDir, "state.sqlite")), queryFactory = createClaudeQuery, modelCatalog, metrics = new MetricsRegistry(), transcripts = new SdkTranscriptBrancher(), threadAdminEffects = sdkThreadAdminEffects, shellRunner = new ShellRunner(), availabilityProbe = async () => ({
|
|
187
196
|
provider: "claude",
|
|
188
197
|
state: "ready",
|
|
189
|
-
}), skillsChanged) {
|
|
198
|
+
}), skillsChanged, nativeSessionCatalog = () => listSessions()) {
|
|
190
199
|
this.config = config;
|
|
191
200
|
this.hub = hub;
|
|
192
201
|
this.logger = logger;
|
|
@@ -197,6 +206,7 @@ export class ClaudeService {
|
|
|
197
206
|
this.threadAdminEffects = threadAdminEffects;
|
|
198
207
|
this.availabilityProbe = availabilityProbe;
|
|
199
208
|
this.skillsChanged = skillsChanged;
|
|
209
|
+
this.nativeSessionCatalog = nativeSessionCatalog;
|
|
200
210
|
this.store = new LayeredHybridStore(durableStore);
|
|
201
211
|
const sessionRepository = new ClaudeSessionRepository(this.store);
|
|
202
212
|
this.sessionOutput = new ClaudeOutputAdapter(hub);
|
|
@@ -260,14 +270,7 @@ export class ClaudeService {
|
|
|
260
270
|
}
|
|
261
271
|
}
|
|
262
272
|
this.restartRecovery = this.resumeThreadRemovals(pendingRemovals.map((removal) => removal.rootThreadId))
|
|
263
|
-
.then(() => this.reconcileAfterRestart(orphanProjectionIds, restartRecoveryRootIds))
|
|
264
|
-
.then(() => {
|
|
265
|
-
for (const record of this.store.allThreadRecords()) {
|
|
266
|
-
if (record.thread.ephemeral && !record.thread.parentThreadId) {
|
|
267
|
-
this.scheduleEphemeralRelease(record.thread.id);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
});
|
|
273
|
+
.then(() => this.reconcileAfterRestart(orphanProjectionIds, restartRecoveryRootIds));
|
|
271
274
|
for (const record of this.store.allThreadRecords()) {
|
|
272
275
|
if (orphanProjectionIds.has(record.thread.id))
|
|
273
276
|
continue;
|
|
@@ -326,7 +329,7 @@ export class ClaudeService {
|
|
|
326
329
|
throw invalidParams(`Unknown Claude turn '${lastTurnId}'.`);
|
|
327
330
|
const turns = snapshot.record.thread.turns.slice(0, through + 1);
|
|
328
331
|
return {
|
|
329
|
-
thread: { ...snapshot.record
|
|
332
|
+
thread: { ...this.withNativeMetadata(snapshot.record), turns },
|
|
330
333
|
turns,
|
|
331
334
|
settings: threadSettings(snapshot.record),
|
|
332
335
|
};
|
|
@@ -337,10 +340,11 @@ export class ClaudeService {
|
|
|
337
340
|
sideSnapshot(sourceThreadId, targetThreadId, visibleForkedFromId) {
|
|
338
341
|
const record = this.requireRecord(sourceThreadId, false);
|
|
339
342
|
const response = threadResponse(record, false);
|
|
343
|
+
const source = this.withNativeMetadata(record);
|
|
340
344
|
return {
|
|
341
345
|
...response,
|
|
342
346
|
thread: {
|
|
343
|
-
...
|
|
347
|
+
...source,
|
|
344
348
|
id: targetThreadId,
|
|
345
349
|
forkedFromId: visibleForkedFromId,
|
|
346
350
|
ephemeral: true,
|
|
@@ -417,6 +421,8 @@ export class ClaudeService {
|
|
|
417
421
|
if (record.thread.parentThreadId) {
|
|
418
422
|
return {
|
|
419
423
|
...threadResponse(record, !resume.excludeTurns),
|
|
424
|
+
turnsBackwardsCursor: record.thread.turns.length ? "hyb-turn:0" : null,
|
|
425
|
+
itemsBackwardsCursor: record.thread.turns.some((turn) => turn.items.length) ? "hyb-item:0" : null,
|
|
420
426
|
initialTurnsPage: resume.initialTurnsPage
|
|
421
427
|
? this.turnsPage({
|
|
422
428
|
threadId,
|
|
@@ -431,6 +437,8 @@ export class ClaudeService {
|
|
|
431
437
|
record = await this.sessions.submit(threadId, { type: "readThread", includeTurns: true });
|
|
432
438
|
return {
|
|
433
439
|
...threadResponse(record, !resume.excludeTurns),
|
|
440
|
+
turnsBackwardsCursor: record.thread.turns.length ? "hyb-turn:0" : null,
|
|
441
|
+
itemsBackwardsCursor: record.thread.turns.some((turn) => turn.items.length) ? "hyb-item:0" : null,
|
|
434
442
|
initialTurnsPage: resume.initialTurnsPage
|
|
435
443
|
? this.turnsPage({
|
|
436
444
|
threadId,
|
|
@@ -477,7 +485,7 @@ export class ClaudeService {
|
|
|
477
485
|
const record = this.store.getThreadRecord(threadId, includeTurns);
|
|
478
486
|
if (!record)
|
|
479
487
|
throw invalidParams(`Unknown Claude thread '${threadId}'.`);
|
|
480
|
-
return { thread: record
|
|
488
|
+
return { thread: this.withNativeMetadata(record) };
|
|
481
489
|
}
|
|
482
490
|
async prepareTurn(params, review) {
|
|
483
491
|
this.requireIndependentThread(params.threadId, "start a turn in");
|
|
@@ -794,8 +802,31 @@ export class ClaudeService {
|
|
|
794
802
|
}
|
|
795
803
|
listThreads(params) {
|
|
796
804
|
return this.store.listThreads(params)
|
|
805
|
+
.map((thread) => {
|
|
806
|
+
const record = this.store.getThreadRecord(thread.id, false);
|
|
807
|
+
return record ? this.withNativeMetadata({ ...record, thread }) : thread;
|
|
808
|
+
})
|
|
797
809
|
.filter((thread) => !this.pendingThreadRemoval(thread.id) && !this.hub.isSuppressed(thread.id));
|
|
798
810
|
}
|
|
811
|
+
refreshNativeMetadata() {
|
|
812
|
+
if (Date.now() - this.nativeMetadataReadAt < 30_000)
|
|
813
|
+
return Promise.resolve();
|
|
814
|
+
if (this.nativeMetadataRead)
|
|
815
|
+
return this.nativeMetadataRead;
|
|
816
|
+
const read = this.nativeSessionCatalog().then((sessions) => {
|
|
817
|
+
this.nativeMetadata = new Map(sessions.map((session) => [session.sessionId, session]));
|
|
818
|
+
this.nativeMetadataReadAt = Date.now();
|
|
819
|
+
}).catch((error) => {
|
|
820
|
+
this.logger.warn("claude.catalog.native-metadata-failed", {
|
|
821
|
+
error: error instanceof Error ? error.message : String(error),
|
|
822
|
+
});
|
|
823
|
+
}).finally(() => {
|
|
824
|
+
if (this.nativeMetadataRead === read)
|
|
825
|
+
this.nativeMetadataRead = undefined;
|
|
826
|
+
});
|
|
827
|
+
this.nativeMetadataRead = read;
|
|
828
|
+
return read;
|
|
829
|
+
}
|
|
799
830
|
async setThreadName(params) {
|
|
800
831
|
const record = this.requireRecord(params.threadId, false);
|
|
801
832
|
if (record.thread.parentThreadId) {
|
|
@@ -810,6 +841,14 @@ export class ClaudeService {
|
|
|
810
841
|
await this.threadAdminEffects.rename(prepared.record.claudeSessionId, params.name, prepared.record.thread.cwd);
|
|
811
842
|
}
|
|
812
843
|
}, params.name);
|
|
844
|
+
const native = this.nativeMetadata.get(record.claudeSessionId);
|
|
845
|
+
if (native)
|
|
846
|
+
this.nativeMetadata.set(record.claudeSessionId, {
|
|
847
|
+
...native,
|
|
848
|
+
customTitle: params.name,
|
|
849
|
+
summary: params.name,
|
|
850
|
+
lastModified: Date.now(),
|
|
851
|
+
});
|
|
813
852
|
return {};
|
|
814
853
|
}
|
|
815
854
|
updateThreadMetadata(params) {
|
|
@@ -921,7 +960,9 @@ export class ClaudeService {
|
|
|
921
960
|
listItems(params) {
|
|
922
961
|
this.assertThreadAvailable(params.threadId);
|
|
923
962
|
const items = this.store.listTurns(params.threadId)
|
|
924
|
-
.flatMap((turn) => params.turnId && turn.id !== params.turnId
|
|
963
|
+
.flatMap((turn) => params.turnId && turn.id !== params.turnId
|
|
964
|
+
? []
|
|
965
|
+
: turn.items.map((item) => ({ turnId: turn.id, item })));
|
|
925
966
|
const ordered = params.sortDirection === "desc" ? [...items].reverse() : items;
|
|
926
967
|
if (params.cursor && !params.cursor.startsWith("hyb-item:"))
|
|
927
968
|
throw invalidParams("Invalid Claude item cursor.");
|
|
@@ -936,10 +977,55 @@ export class ClaudeService {
|
|
|
936
977
|
backwardsCursor: data.length > 0 ? `hyb-item:${Math.max(0, offset - limit)}` : null,
|
|
937
978
|
};
|
|
938
979
|
}
|
|
980
|
+
searchOccurrences(params) {
|
|
981
|
+
this.assertThreadAvailable(params.threadId);
|
|
982
|
+
const searchTerm = params.searchTerm.trim();
|
|
983
|
+
if (!searchTerm)
|
|
984
|
+
throw invalidParams("thread/searchOccurrences requires a non-empty searchTerm.");
|
|
985
|
+
if (params.cursor && !params.cursor.startsWith("hyb-search:"))
|
|
986
|
+
throw invalidParams("Invalid Claude search cursor.");
|
|
987
|
+
const offset = params.cursor ? Number(params.cursor.slice("hyb-search:".length)) : 0;
|
|
988
|
+
if (!Number.isInteger(offset) || offset < 0)
|
|
989
|
+
throw invalidParams("Invalid Claude search cursor.");
|
|
990
|
+
const turns = this.store.listTurns(params.threadId);
|
|
991
|
+
const needle = searchTerm.toLocaleLowerCase();
|
|
992
|
+
const occurrences = turns.flatMap((turn, turnIndex) => turn.items.flatMap((item) => {
|
|
993
|
+
const text = item.type === "userMessage"
|
|
994
|
+
? item.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("\n")
|
|
995
|
+
: item.type === "agentMessage" && item.phase !== "commentary" ? item.text : undefined;
|
|
996
|
+
if (text === undefined)
|
|
997
|
+
return [];
|
|
998
|
+
const haystack = text.toLocaleLowerCase();
|
|
999
|
+
const matches = [];
|
|
1000
|
+
for (let start = haystack.indexOf(needle); start >= 0; start = haystack.indexOf(needle, start + needle.length)) {
|
|
1001
|
+
matches.push({
|
|
1002
|
+
turnId: turn.id,
|
|
1003
|
+
itemId: item.id,
|
|
1004
|
+
snippet: text,
|
|
1005
|
+
snippetMatchRange: { start, end: start + needle.length },
|
|
1006
|
+
turnCursor: `hyb-turn:${turns.length - 1 - turnIndex}`,
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
return matches;
|
|
1010
|
+
}));
|
|
1011
|
+
const limit = Math.max(1, Math.min(params.limit ?? 50, 100));
|
|
1012
|
+
const data = occurrences.slice(offset, offset + limit);
|
|
1013
|
+
return {
|
|
1014
|
+
data,
|
|
1015
|
+
nextCursor: offset + data.length < occurrences.length ? `hyb-search:${offset + data.length}` : null,
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
939
1018
|
async forkThread(params, visibleForkedFromId = params.threadId) {
|
|
940
1019
|
if (params.path)
|
|
941
1020
|
throw invalidParams("Claude thread forks must use threadId, not a Codex rollout path.");
|
|
942
1021
|
this.requireIndependentThread(params.threadId, "fork");
|
|
1022
|
+
if (params.lastTurnId && params.beforeTurnId)
|
|
1023
|
+
throw invalidParams("`beforeTurnId` cannot be combined with `lastTurnId`.");
|
|
1024
|
+
if (params.ephemeral && params.deferGoalContinuation)
|
|
1025
|
+
throw invalidParams("`deferGoalContinuation` cannot be combined with `ephemeral`.");
|
|
1026
|
+
const inheritedGoal = params.deferGoalContinuation
|
|
1027
|
+
? await this.sessions.submit(params.threadId, { type: "goal", command: { kind: "snapshotFork" } })
|
|
1028
|
+
: undefined;
|
|
943
1029
|
const source = await this.sessions.submit(params.threadId, { type: "snapshotBranch" });
|
|
944
1030
|
const sourceRecord = source.record;
|
|
945
1031
|
const sidePromotion = Boolean((this.config.features?.sideChatPromotion ?? true)
|
|
@@ -954,15 +1040,20 @@ export class ClaudeService {
|
|
|
954
1040
|
if (!claudeModelValue)
|
|
955
1041
|
throw invalidParams("Cannot fork a Claude thread to a Codex model.");
|
|
956
1042
|
const activeSideFork = Boolean(params.ephemeral === true && params.excludeTurns === true
|
|
957
|
-
&& params.threadSource === "user" && !params.lastTurnId);
|
|
1043
|
+
&& params.threadSource === "user" && !params.lastTurnId && !params.beforeTurnId);
|
|
958
1044
|
if (params.permissions && params.sandbox)
|
|
959
1045
|
throw invalidParams("Claude thread fork cannot combine permissions with sandbox.");
|
|
960
1046
|
const activeIndex = sourceRecord.thread.turns.findIndex((turn) => turn.status === "inProgress");
|
|
961
1047
|
const selectedIndex = params.lastTurnId
|
|
962
1048
|
? sourceRecord.thread.turns.findIndex((turn) => turn.id === params.lastTurnId)
|
|
963
1049
|
: -1;
|
|
1050
|
+
const beforeIndex = params.beforeTurnId
|
|
1051
|
+
? sourceRecord.thread.turns.findIndex((turn) => turn.id === params.beforeTurnId)
|
|
1052
|
+
: -1;
|
|
964
1053
|
if (params.lastTurnId && selectedIndex < 0)
|
|
965
1054
|
throw invalidParams(`Unknown Claude turn '${params.lastTurnId}'.`);
|
|
1055
|
+
if (params.beforeTurnId && beforeIndex < 0)
|
|
1056
|
+
throw invalidParams(`Unknown Claude turn '${params.beforeTurnId}'.`);
|
|
966
1057
|
const selectedTurn = selectedIndex >= 0 ? sourceRecord.thread.turns[selectedIndex] : undefined;
|
|
967
1058
|
const selectedBoundary = params.lastTurnId
|
|
968
1059
|
? source.boundaries.find((entry) => entry.turnId === params.lastTurnId)
|
|
@@ -974,7 +1065,9 @@ export class ClaudeService {
|
|
|
974
1065
|
? activeIndex >= 0 ? activeIndex - 1 : sourceRecord.thread.turns.length - 1
|
|
975
1066
|
: params.lastTurnId
|
|
976
1067
|
? selectedIndex
|
|
977
|
-
:
|
|
1068
|
+
: params.beforeTurnId
|
|
1069
|
+
? beforeIndex - 1
|
|
1070
|
+
: sourceRecord.thread.turns.length - 1;
|
|
978
1071
|
if (sidePromotion && through < 0) {
|
|
979
1072
|
throw invalidParams("Cannot promote a Claude side chat before it has a completed turn.");
|
|
980
1073
|
}
|
|
@@ -1013,6 +1106,7 @@ export class ClaudeService {
|
|
|
1013
1106
|
sessionId: sourceRecord.thread.sessionId, forkedFromId: visibleForkedFromId,
|
|
1014
1107
|
cwd, modelProvider: "claude", createdAt, updatedAt: createdAt, recencyAt: createdAt,
|
|
1015
1108
|
status: params.ephemeral ? { type: "idle" } : { type: "notLoaded" },
|
|
1109
|
+
canAcceptDirectInput: true,
|
|
1016
1110
|
name: params.ephemeral
|
|
1017
1111
|
? sourceRecord.thread.name
|
|
1018
1112
|
: sourceRecord.thread.name ? `${sourceRecord.thread.name} (fork)` : null,
|
|
@@ -1036,6 +1130,7 @@ export class ClaudeService {
|
|
|
1036
1130
|
responseRecord = await this.sessions.submit(thread.id, {
|
|
1037
1131
|
type: "commitForkTarget", record, turns: copiedTurns,
|
|
1038
1132
|
sourceBoundaries, uuidMap: [...branch.uuidMap],
|
|
1133
|
+
...(inheritedGoal ? { inheritedGoal } : {}),
|
|
1039
1134
|
});
|
|
1040
1135
|
}
|
|
1041
1136
|
catch (error) {
|
|
@@ -1061,7 +1156,7 @@ export class ClaudeService {
|
|
|
1061
1156
|
}
|
|
1062
1157
|
}
|
|
1063
1158
|
if (sidePromotion)
|
|
1064
|
-
this.
|
|
1159
|
+
await this.releaseEphemeralThread(params.threadId);
|
|
1065
1160
|
return threadResponse(responseRecord, !params.excludeTurns);
|
|
1066
1161
|
}
|
|
1067
1162
|
async rollbackThread(params) {
|
|
@@ -1416,6 +1511,28 @@ export class ClaudeService {
|
|
|
1416
1511
|
throw invalidParams(`Unknown Claude thread '${threadId}'.`);
|
|
1417
1512
|
return record;
|
|
1418
1513
|
}
|
|
1514
|
+
withNativeMetadata(record) {
|
|
1515
|
+
const native = this.nativeMetadata.get(record.claudeSessionId);
|
|
1516
|
+
if (!native)
|
|
1517
|
+
return {
|
|
1518
|
+
...record.thread,
|
|
1519
|
+
canAcceptDirectInput: record.thread.parentThreadId ? false : true,
|
|
1520
|
+
};
|
|
1521
|
+
const createdAt = native.createdAt === undefined
|
|
1522
|
+
? record.thread.createdAt
|
|
1523
|
+
: Math.floor(native.createdAt / 1_000);
|
|
1524
|
+
const updatedAt = Math.floor(native.lastModified / 1_000);
|
|
1525
|
+
return {
|
|
1526
|
+
...record.thread,
|
|
1527
|
+
canAcceptDirectInput: record.thread.parentThreadId ? false : true,
|
|
1528
|
+
name: (native.customTitle ?? native.summary) || record.thread.name,
|
|
1529
|
+
preview: native.firstPrompt ?? record.thread.preview,
|
|
1530
|
+
cwd: native.cwd ?? record.thread.cwd,
|
|
1531
|
+
createdAt,
|
|
1532
|
+
updatedAt,
|
|
1533
|
+
recencyAt: updatedAt,
|
|
1534
|
+
};
|
|
1535
|
+
}
|
|
1419
1536
|
requireIndependentThread(threadId, operation) {
|
|
1420
1537
|
const record = this.requireRecord(threadId, false);
|
|
1421
1538
|
if (record.thread.parentThreadId) {
|
|
@@ -1492,6 +1609,7 @@ export class ClaudeService {
|
|
|
1492
1609
|
updatedAt: createdAt,
|
|
1493
1610
|
recencyAt: createdAt,
|
|
1494
1611
|
status: { type: "idle" },
|
|
1612
|
+
canAcceptDirectInput: true,
|
|
1495
1613
|
path: null,
|
|
1496
1614
|
cwd,
|
|
1497
1615
|
cliVersion: "claude-code",
|
|
@@ -1525,7 +1643,10 @@ export class ClaudeService {
|
|
|
1525
1643
|
? null
|
|
1526
1644
|
: syncedCollaborationMode(settings.collaborationMode, modelPickerId, reasoningEffort),
|
|
1527
1645
|
outputSchema: null,
|
|
1528
|
-
tokenUsageTotal: {
|
|
1646
|
+
tokenUsageTotal: {
|
|
1647
|
+
totalTokens: 0, inputTokens: 0, cachedInputTokens: 0, cacheWriteInputTokens: 0,
|
|
1648
|
+
outputTokens: 0, reasoningOutputTokens: 0,
|
|
1649
|
+
},
|
|
1529
1650
|
tokenUsageLast: null,
|
|
1530
1651
|
modelContextWindow: null,
|
|
1531
1652
|
providerCostUsdTotal: 0,
|
|
@@ -1535,6 +1656,18 @@ export class ClaudeService {
|
|
|
1535
1656
|
await this.applySettings({ ...params, effort: turnReasoningEffort(params) }, params.outputSchema ?? null);
|
|
1536
1657
|
}
|
|
1537
1658
|
async applySettings(params, outputSchema) {
|
|
1659
|
+
const previous = this.settingsUpdates.get(params.threadId) ?? Promise.resolve();
|
|
1660
|
+
const update = previous.catch(() => undefined).then(() => this.applySettingsNow(params, outputSchema));
|
|
1661
|
+
this.settingsUpdates.set(params.threadId, update);
|
|
1662
|
+
try {
|
|
1663
|
+
await update;
|
|
1664
|
+
}
|
|
1665
|
+
finally {
|
|
1666
|
+
if (this.settingsUpdates.get(params.threadId) === update)
|
|
1667
|
+
this.settingsUpdates.delete(params.threadId);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
async applySettingsNow(params, outputSchema) {
|
|
1538
1671
|
if (params.permissions && params.sandboxPolicy)
|
|
1539
1672
|
throw invalidParams("Claude thread settings cannot combine permissions with sandboxPolicy.");
|
|
1540
1673
|
if (params.effort && !["low", "medium", "high", "xhigh", "max"].includes(params.effort))
|