@gkorepanov/ccodex 0.4.9 → 0.4.11
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/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 +156 -21
- 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 +47 -50
- 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/sideFork.d.ts +3 -0
- package/dist/gateway/sideFork.js +11 -0
- package/dist/gateway/sideFork.js.map +1 -0
- package/dist/gateway/stockSideThreads.js +2 -4
- package/dist/gateway/stockSideThreads.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 +102 -0
- package/dist/handoff/lineageStore.js +515 -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 +502 -140
- 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/state/stockStateTracker.js +1 -0
- package/dist/state/stockStateTracker.js.map +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 +2 -2
- package/dist/store/sqliteStore.js +84 -24
- package/dist/store/sqliteStore.js.map +1 -1
- package/dist/store/threadFilter.js +2 -0
- package/dist/store/threadFilter.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,11 +340,13 @@ 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,
|
|
349
|
+
sessionId: targetThreadId,
|
|
345
350
|
forkedFromId: visibleForkedFromId,
|
|
346
351
|
ephemeral: true,
|
|
347
352
|
path: null,
|
|
@@ -417,6 +422,8 @@ export class ClaudeService {
|
|
|
417
422
|
if (record.thread.parentThreadId) {
|
|
418
423
|
return {
|
|
419
424
|
...threadResponse(record, !resume.excludeTurns),
|
|
425
|
+
turnsBackwardsCursor: record.thread.turns.length ? "hyb-turn:0" : null,
|
|
426
|
+
itemsBackwardsCursor: record.thread.turns.some((turn) => turn.items.length) ? "hyb-item:0" : null,
|
|
420
427
|
initialTurnsPage: resume.initialTurnsPage
|
|
421
428
|
? this.turnsPage({
|
|
422
429
|
threadId,
|
|
@@ -431,6 +438,8 @@ export class ClaudeService {
|
|
|
431
438
|
record = await this.sessions.submit(threadId, { type: "readThread", includeTurns: true });
|
|
432
439
|
return {
|
|
433
440
|
...threadResponse(record, !resume.excludeTurns),
|
|
441
|
+
turnsBackwardsCursor: record.thread.turns.length ? "hyb-turn:0" : null,
|
|
442
|
+
itemsBackwardsCursor: record.thread.turns.some((turn) => turn.items.length) ? "hyb-item:0" : null,
|
|
434
443
|
initialTurnsPage: resume.initialTurnsPage
|
|
435
444
|
? this.turnsPage({
|
|
436
445
|
threadId,
|
|
@@ -477,7 +486,7 @@ export class ClaudeService {
|
|
|
477
486
|
const record = this.store.getThreadRecord(threadId, includeTurns);
|
|
478
487
|
if (!record)
|
|
479
488
|
throw invalidParams(`Unknown Claude thread '${threadId}'.`);
|
|
480
|
-
return { thread: record
|
|
489
|
+
return { thread: this.withNativeMetadata(record) };
|
|
481
490
|
}
|
|
482
491
|
async prepareTurn(params, review) {
|
|
483
492
|
this.requireIndependentThread(params.threadId, "start a turn in");
|
|
@@ -794,8 +803,31 @@ export class ClaudeService {
|
|
|
794
803
|
}
|
|
795
804
|
listThreads(params) {
|
|
796
805
|
return this.store.listThreads(params)
|
|
806
|
+
.map((thread) => {
|
|
807
|
+
const record = this.store.getThreadRecord(thread.id, false);
|
|
808
|
+
return record ? this.withNativeMetadata({ ...record, thread }) : thread;
|
|
809
|
+
})
|
|
797
810
|
.filter((thread) => !this.pendingThreadRemoval(thread.id) && !this.hub.isSuppressed(thread.id));
|
|
798
811
|
}
|
|
812
|
+
refreshNativeMetadata() {
|
|
813
|
+
if (Date.now() - this.nativeMetadataReadAt < 30_000)
|
|
814
|
+
return Promise.resolve();
|
|
815
|
+
if (this.nativeMetadataRead)
|
|
816
|
+
return this.nativeMetadataRead;
|
|
817
|
+
const read = this.nativeSessionCatalog().then((sessions) => {
|
|
818
|
+
this.nativeMetadata = new Map(sessions.map((session) => [session.sessionId, session]));
|
|
819
|
+
this.nativeMetadataReadAt = Date.now();
|
|
820
|
+
}).catch((error) => {
|
|
821
|
+
this.logger.warn("claude.catalog.native-metadata-failed", {
|
|
822
|
+
error: error instanceof Error ? error.message : String(error),
|
|
823
|
+
});
|
|
824
|
+
}).finally(() => {
|
|
825
|
+
if (this.nativeMetadataRead === read)
|
|
826
|
+
this.nativeMetadataRead = undefined;
|
|
827
|
+
});
|
|
828
|
+
this.nativeMetadataRead = read;
|
|
829
|
+
return read;
|
|
830
|
+
}
|
|
799
831
|
async setThreadName(params) {
|
|
800
832
|
const record = this.requireRecord(params.threadId, false);
|
|
801
833
|
if (record.thread.parentThreadId) {
|
|
@@ -810,6 +842,14 @@ export class ClaudeService {
|
|
|
810
842
|
await this.threadAdminEffects.rename(prepared.record.claudeSessionId, params.name, prepared.record.thread.cwd);
|
|
811
843
|
}
|
|
812
844
|
}, params.name);
|
|
845
|
+
const native = this.nativeMetadata.get(record.claudeSessionId);
|
|
846
|
+
if (native)
|
|
847
|
+
this.nativeMetadata.set(record.claudeSessionId, {
|
|
848
|
+
...native,
|
|
849
|
+
customTitle: params.name,
|
|
850
|
+
summary: params.name,
|
|
851
|
+
lastModified: Date.now(),
|
|
852
|
+
});
|
|
813
853
|
return {};
|
|
814
854
|
}
|
|
815
855
|
updateThreadMetadata(params) {
|
|
@@ -921,7 +961,9 @@ export class ClaudeService {
|
|
|
921
961
|
listItems(params) {
|
|
922
962
|
this.assertThreadAvailable(params.threadId);
|
|
923
963
|
const items = this.store.listTurns(params.threadId)
|
|
924
|
-
.flatMap((turn) => params.turnId && turn.id !== params.turnId
|
|
964
|
+
.flatMap((turn) => params.turnId && turn.id !== params.turnId
|
|
965
|
+
? []
|
|
966
|
+
: turn.items.map((item) => ({ turnId: turn.id, item })));
|
|
925
967
|
const ordered = params.sortDirection === "desc" ? [...items].reverse() : items;
|
|
926
968
|
if (params.cursor && !params.cursor.startsWith("hyb-item:"))
|
|
927
969
|
throw invalidParams("Invalid Claude item cursor.");
|
|
@@ -936,10 +978,55 @@ export class ClaudeService {
|
|
|
936
978
|
backwardsCursor: data.length > 0 ? `hyb-item:${Math.max(0, offset - limit)}` : null,
|
|
937
979
|
};
|
|
938
980
|
}
|
|
981
|
+
searchOccurrences(params) {
|
|
982
|
+
this.assertThreadAvailable(params.threadId);
|
|
983
|
+
const searchTerm = params.searchTerm.trim();
|
|
984
|
+
if (!searchTerm)
|
|
985
|
+
throw invalidParams("thread/searchOccurrences requires a non-empty searchTerm.");
|
|
986
|
+
if (params.cursor && !params.cursor.startsWith("hyb-search:"))
|
|
987
|
+
throw invalidParams("Invalid Claude search cursor.");
|
|
988
|
+
const offset = params.cursor ? Number(params.cursor.slice("hyb-search:".length)) : 0;
|
|
989
|
+
if (!Number.isInteger(offset) || offset < 0)
|
|
990
|
+
throw invalidParams("Invalid Claude search cursor.");
|
|
991
|
+
const turns = this.store.listTurns(params.threadId);
|
|
992
|
+
const needle = searchTerm.toLocaleLowerCase();
|
|
993
|
+
const occurrences = turns.flatMap((turn, turnIndex) => turn.items.flatMap((item) => {
|
|
994
|
+
const text = item.type === "userMessage"
|
|
995
|
+
? item.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("\n")
|
|
996
|
+
: item.type === "agentMessage" && item.phase !== "commentary" ? item.text : undefined;
|
|
997
|
+
if (text === undefined)
|
|
998
|
+
return [];
|
|
999
|
+
const haystack = text.toLocaleLowerCase();
|
|
1000
|
+
const matches = [];
|
|
1001
|
+
for (let start = haystack.indexOf(needle); start >= 0; start = haystack.indexOf(needle, start + needle.length)) {
|
|
1002
|
+
matches.push({
|
|
1003
|
+
turnId: turn.id,
|
|
1004
|
+
itemId: item.id,
|
|
1005
|
+
snippet: text,
|
|
1006
|
+
snippetMatchRange: { start, end: start + needle.length },
|
|
1007
|
+
turnCursor: `hyb-turn:${turns.length - 1 - turnIndex}`,
|
|
1008
|
+
});
|
|
1009
|
+
}
|
|
1010
|
+
return matches;
|
|
1011
|
+
}));
|
|
1012
|
+
const limit = Math.max(1, Math.min(params.limit ?? 50, 100));
|
|
1013
|
+
const data = occurrences.slice(offset, offset + limit);
|
|
1014
|
+
return {
|
|
1015
|
+
data,
|
|
1016
|
+
nextCursor: offset + data.length < occurrences.length ? `hyb-search:${offset + data.length}` : null,
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
939
1019
|
async forkThread(params, visibleForkedFromId = params.threadId) {
|
|
940
1020
|
if (params.path)
|
|
941
1021
|
throw invalidParams("Claude thread forks must use threadId, not a Codex rollout path.");
|
|
942
1022
|
this.requireIndependentThread(params.threadId, "fork");
|
|
1023
|
+
if (params.lastTurnId && params.beforeTurnId)
|
|
1024
|
+
throw invalidParams("`beforeTurnId` cannot be combined with `lastTurnId`.");
|
|
1025
|
+
if (params.ephemeral && params.deferGoalContinuation)
|
|
1026
|
+
throw invalidParams("`deferGoalContinuation` cannot be combined with `ephemeral`.");
|
|
1027
|
+
const inheritedGoal = params.deferGoalContinuation
|
|
1028
|
+
? await this.sessions.submit(params.threadId, { type: "goal", command: { kind: "snapshotFork" } })
|
|
1029
|
+
: undefined;
|
|
943
1030
|
const source = await this.sessions.submit(params.threadId, { type: "snapshotBranch" });
|
|
944
1031
|
const sourceRecord = source.record;
|
|
945
1032
|
const sidePromotion = Boolean((this.config.features?.sideChatPromotion ?? true)
|
|
@@ -954,15 +1041,20 @@ export class ClaudeService {
|
|
|
954
1041
|
if (!claudeModelValue)
|
|
955
1042
|
throw invalidParams("Cannot fork a Claude thread to a Codex model.");
|
|
956
1043
|
const activeSideFork = Boolean(params.ephemeral === true && params.excludeTurns === true
|
|
957
|
-
&& params.threadSource === "user" && !params.lastTurnId);
|
|
1044
|
+
&& params.threadSource === "user" && !params.lastTurnId && !params.beforeTurnId);
|
|
958
1045
|
if (params.permissions && params.sandbox)
|
|
959
1046
|
throw invalidParams("Claude thread fork cannot combine permissions with sandbox.");
|
|
960
1047
|
const activeIndex = sourceRecord.thread.turns.findIndex((turn) => turn.status === "inProgress");
|
|
961
1048
|
const selectedIndex = params.lastTurnId
|
|
962
1049
|
? sourceRecord.thread.turns.findIndex((turn) => turn.id === params.lastTurnId)
|
|
963
1050
|
: -1;
|
|
1051
|
+
const beforeIndex = params.beforeTurnId
|
|
1052
|
+
? sourceRecord.thread.turns.findIndex((turn) => turn.id === params.beforeTurnId)
|
|
1053
|
+
: -1;
|
|
964
1054
|
if (params.lastTurnId && selectedIndex < 0)
|
|
965
1055
|
throw invalidParams(`Unknown Claude turn '${params.lastTurnId}'.`);
|
|
1056
|
+
if (params.beforeTurnId && beforeIndex < 0)
|
|
1057
|
+
throw invalidParams(`Unknown Claude turn '${params.beforeTurnId}'.`);
|
|
966
1058
|
const selectedTurn = selectedIndex >= 0 ? sourceRecord.thread.turns[selectedIndex] : undefined;
|
|
967
1059
|
const selectedBoundary = params.lastTurnId
|
|
968
1060
|
? source.boundaries.find((entry) => entry.turnId === params.lastTurnId)
|
|
@@ -974,7 +1066,9 @@ export class ClaudeService {
|
|
|
974
1066
|
? activeIndex >= 0 ? activeIndex - 1 : sourceRecord.thread.turns.length - 1
|
|
975
1067
|
: params.lastTurnId
|
|
976
1068
|
? selectedIndex
|
|
977
|
-
:
|
|
1069
|
+
: params.beforeTurnId
|
|
1070
|
+
? beforeIndex - 1
|
|
1071
|
+
: sourceRecord.thread.turns.length - 1;
|
|
978
1072
|
if (sidePromotion && through < 0) {
|
|
979
1073
|
throw invalidParams("Cannot promote a Claude side chat before it has a completed turn.");
|
|
980
1074
|
}
|
|
@@ -1008,11 +1102,13 @@ export class ClaudeService {
|
|
|
1008
1102
|
}
|
|
1009
1103
|
const createdAt = nowSeconds();
|
|
1010
1104
|
const cwd = existingThreadCwd(params.cwd ?? sourceRecord.thread.cwd);
|
|
1105
|
+
const threadId = uuidv7();
|
|
1011
1106
|
const thread = {
|
|
1012
|
-
...sourceRecord.thread, id:
|
|
1013
|
-
sessionId:
|
|
1107
|
+
...sourceRecord.thread, id: threadId, ephemeral: params.ephemeral ?? false,
|
|
1108
|
+
sessionId: threadId, forkedFromId: visibleForkedFromId,
|
|
1014
1109
|
cwd, modelProvider: "claude", createdAt, updatedAt: createdAt, recencyAt: createdAt,
|
|
1015
1110
|
status: params.ephemeral ? { type: "idle" } : { type: "notLoaded" },
|
|
1111
|
+
canAcceptDirectInput: true,
|
|
1016
1112
|
name: params.ephemeral
|
|
1017
1113
|
? sourceRecord.thread.name
|
|
1018
1114
|
: sourceRecord.thread.name ? `${sourceRecord.thread.name} (fork)` : null,
|
|
@@ -1036,6 +1132,7 @@ export class ClaudeService {
|
|
|
1036
1132
|
responseRecord = await this.sessions.submit(thread.id, {
|
|
1037
1133
|
type: "commitForkTarget", record, turns: copiedTurns,
|
|
1038
1134
|
sourceBoundaries, uuidMap: [...branch.uuidMap],
|
|
1135
|
+
...(inheritedGoal ? { inheritedGoal } : {}),
|
|
1039
1136
|
});
|
|
1040
1137
|
}
|
|
1041
1138
|
catch (error) {
|
|
@@ -1061,7 +1158,7 @@ export class ClaudeService {
|
|
|
1061
1158
|
}
|
|
1062
1159
|
}
|
|
1063
1160
|
if (sidePromotion)
|
|
1064
|
-
this.
|
|
1161
|
+
await this.releaseEphemeralThread(params.threadId);
|
|
1065
1162
|
return threadResponse(responseRecord, !params.excludeTurns);
|
|
1066
1163
|
}
|
|
1067
1164
|
async rollbackThread(params) {
|
|
@@ -1416,6 +1513,28 @@ export class ClaudeService {
|
|
|
1416
1513
|
throw invalidParams(`Unknown Claude thread '${threadId}'.`);
|
|
1417
1514
|
return record;
|
|
1418
1515
|
}
|
|
1516
|
+
withNativeMetadata(record) {
|
|
1517
|
+
const native = this.nativeMetadata.get(record.claudeSessionId);
|
|
1518
|
+
if (!native)
|
|
1519
|
+
return {
|
|
1520
|
+
...record.thread,
|
|
1521
|
+
canAcceptDirectInput: record.thread.parentThreadId ? false : true,
|
|
1522
|
+
};
|
|
1523
|
+
const createdAt = native.createdAt === undefined
|
|
1524
|
+
? record.thread.createdAt
|
|
1525
|
+
: Math.floor(native.createdAt / 1_000);
|
|
1526
|
+
const updatedAt = Math.floor(native.lastModified / 1_000);
|
|
1527
|
+
return {
|
|
1528
|
+
...record.thread,
|
|
1529
|
+
canAcceptDirectInput: record.thread.parentThreadId ? false : true,
|
|
1530
|
+
name: (native.customTitle ?? native.summary) || record.thread.name,
|
|
1531
|
+
preview: native.firstPrompt ?? record.thread.preview,
|
|
1532
|
+
cwd: native.cwd ?? record.thread.cwd,
|
|
1533
|
+
createdAt,
|
|
1534
|
+
updatedAt,
|
|
1535
|
+
recencyAt: updatedAt,
|
|
1536
|
+
};
|
|
1537
|
+
}
|
|
1419
1538
|
requireIndependentThread(threadId, operation) {
|
|
1420
1539
|
const record = this.requireRecord(threadId, false);
|
|
1421
1540
|
if (record.thread.parentThreadId) {
|
|
@@ -1492,6 +1611,7 @@ export class ClaudeService {
|
|
|
1492
1611
|
updatedAt: createdAt,
|
|
1493
1612
|
recencyAt: createdAt,
|
|
1494
1613
|
status: { type: "idle" },
|
|
1614
|
+
canAcceptDirectInput: true,
|
|
1495
1615
|
path: null,
|
|
1496
1616
|
cwd,
|
|
1497
1617
|
cliVersion: "claude-code",
|
|
@@ -1525,7 +1645,10 @@ export class ClaudeService {
|
|
|
1525
1645
|
? null
|
|
1526
1646
|
: syncedCollaborationMode(settings.collaborationMode, modelPickerId, reasoningEffort),
|
|
1527
1647
|
outputSchema: null,
|
|
1528
|
-
tokenUsageTotal: {
|
|
1648
|
+
tokenUsageTotal: {
|
|
1649
|
+
totalTokens: 0, inputTokens: 0, cachedInputTokens: 0, cacheWriteInputTokens: 0,
|
|
1650
|
+
outputTokens: 0, reasoningOutputTokens: 0,
|
|
1651
|
+
},
|
|
1529
1652
|
tokenUsageLast: null,
|
|
1530
1653
|
modelContextWindow: null,
|
|
1531
1654
|
providerCostUsdTotal: 0,
|
|
@@ -1535,6 +1658,18 @@ export class ClaudeService {
|
|
|
1535
1658
|
await this.applySettings({ ...params, effort: turnReasoningEffort(params) }, params.outputSchema ?? null);
|
|
1536
1659
|
}
|
|
1537
1660
|
async applySettings(params, outputSchema) {
|
|
1661
|
+
const previous = this.settingsUpdates.get(params.threadId) ?? Promise.resolve();
|
|
1662
|
+
const update = previous.catch(() => undefined).then(() => this.applySettingsNow(params, outputSchema));
|
|
1663
|
+
this.settingsUpdates.set(params.threadId, update);
|
|
1664
|
+
try {
|
|
1665
|
+
await update;
|
|
1666
|
+
}
|
|
1667
|
+
finally {
|
|
1668
|
+
if (this.settingsUpdates.get(params.threadId) === update)
|
|
1669
|
+
this.settingsUpdates.delete(params.threadId);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
async applySettingsNow(params, outputSchema) {
|
|
1538
1673
|
if (params.permissions && params.sandboxPolicy)
|
|
1539
1674
|
throw invalidParams("Claude thread settings cannot combine permissions with sandboxPolicy.");
|
|
1540
1675
|
if (params.effort && !["low", "medium", "high", "xhigh", "max"].includes(params.effort))
|