@adhdev/daemon-core 0.9.4 → 0.9.6

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/dist/index.mjs CHANGED
@@ -4451,31 +4451,6 @@ function getSavedProviderSessions(state, filters) {
4451
4451
  init_config();
4452
4452
  import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
4453
4453
  import { join as join3 } from "path";
4454
-
4455
- // src/providers/provider-session-id.ts
4456
- var HERMES_SESSION_ID_RE = /^\d{8}_\d{6}_[a-z0-9]+$/i;
4457
- var CLAUDE_SESSION_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
4458
- function normalizeProviderSessionId(providerType, providerSessionId) {
4459
- const normalizedProviderType = typeof providerType === "string" ? providerType.trim() : "";
4460
- const normalizedId = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
4461
- if (!normalizedId) return "";
4462
- const lowered = normalizedId.toLowerCase();
4463
- if (lowered === "undefined" || lowered === "null") return "";
4464
- if (normalizedProviderType === "hermes-cli" && !HERMES_SESSION_ID_RE.test(normalizedId)) {
4465
- return "";
4466
- }
4467
- if (normalizedProviderType === "claude-cli" && !CLAUDE_SESSION_ID_RE.test(normalizedId)) {
4468
- return "";
4469
- }
4470
- return normalizedId;
4471
- }
4472
- function isLegacyVolatileSessionReadKey(key) {
4473
- const normalizedKey = typeof key === "string" ? key.trim() : "";
4474
- if (!normalizedKey) return false;
4475
- return normalizedKey.startsWith("provider:codex:vscode-webview://");
4476
- }
4477
-
4478
- // src/config/state-store.ts
4479
4454
  var DEFAULT_STATE = {
4480
4455
  recentActivity: [],
4481
4456
  savedProviderSessions: [],
@@ -4494,31 +4469,24 @@ function normalizeState(raw) {
4494
4469
  const parsed = isPlainObject2(raw) ? raw : {};
4495
4470
  const recentActivity = (Array.isArray(parsed.recentActivity) ? parsed.recentActivity : []).filter((entry) => {
4496
4471
  if (!isPlainObject2(entry)) return false;
4497
- const normalizedId = normalizeProviderSessionId(
4498
- typeof entry.providerType === "string" ? entry.providerType : "",
4499
- typeof entry.providerSessionId === "string" ? entry.providerSessionId : ""
4500
- );
4501
- if (typeof entry.providerSessionId === "string" && !normalizedId) return false;
4472
+ if (typeof entry.providerSessionId === "string" && !entry.providerSessionId.trim()) return false;
4502
4473
  return true;
4503
4474
  });
4504
4475
  const savedProviderSessions = (Array.isArray(parsed.savedProviderSessions) ? parsed.savedProviderSessions : []).filter((entry) => {
4505
4476
  if (!isPlainObject2(entry)) return false;
4506
- return !!normalizeProviderSessionId(
4507
- typeof entry.providerType === "string" ? entry.providerType : "",
4508
- typeof entry.providerSessionId === "string" ? entry.providerSessionId : ""
4509
- );
4477
+ return typeof entry.providerSessionId === "string" && !!entry.providerSessionId.trim();
4510
4478
  });
4511
4479
  const sessionReads = Object.fromEntries(
4512
- Object.entries(isPlainObject2(parsed.sessionReads) ? parsed.sessionReads : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "number" && Number.isFinite(value))
4480
+ Object.entries(isPlainObject2(parsed.sessionReads) ? parsed.sessionReads : {}).filter(([, value]) => typeof value === "number" && Number.isFinite(value))
4513
4481
  );
4514
4482
  const sessionReadMarkers = Object.fromEntries(
4515
- Object.entries(isPlainObject2(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string")
4483
+ Object.entries(isPlainObject2(parsed.sessionReadMarkers) ? parsed.sessionReadMarkers : {}).filter(([, value]) => typeof value === "string")
4516
4484
  );
4517
4485
  const sessionNotificationDismissals = Object.fromEntries(
4518
- Object.entries(isPlainObject2(parsed.sessionNotificationDismissals) ? parsed.sessionNotificationDismissals : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string" && value.length > 0)
4486
+ Object.entries(isPlainObject2(parsed.sessionNotificationDismissals) ? parsed.sessionNotificationDismissals : {}).filter(([, value]) => typeof value === "string" && value.length > 0)
4519
4487
  );
4520
4488
  const sessionNotificationUnreadOverrides = Object.fromEntries(
4521
- Object.entries(isPlainObject2(parsed.sessionNotificationUnreadOverrides) ? parsed.sessionNotificationUnreadOverrides : {}).filter(([key, value]) => !isLegacyVolatileSessionReadKey(key) && typeof value === "string" && value.length > 0)
4489
+ Object.entries(isPlainObject2(parsed.sessionNotificationUnreadOverrides) ? parsed.sessionNotificationUnreadOverrides : {}).filter(([, value]) => typeof value === "string" && value.length > 0)
4522
4490
  );
4523
4491
  return {
4524
4492
  recentActivity,
@@ -6610,16 +6578,24 @@ var savedHistorySessionCache = /* @__PURE__ */ new Map();
6610
6578
  var savedHistoryFileSummaryCache = /* @__PURE__ */ new Map();
6611
6579
  var savedHistoryBackgroundRefresh = /* @__PURE__ */ new Set();
6612
6580
  var savedHistoryRollupInFlight = /* @__PURE__ */ new Set();
6613
- var CODEX_STARTER_PROMPT_RE = /^(?:[›❯]\s*)?(?:Find and fix a bug in @filename|Improve documentation in @filename|Write tests for @filename|Explain this codebase|Summarize recent commits|Implement \{feature\}|Use \/skills(?: to list available skills)?|Run \/review on my current changes)$/i;
6614
6581
  function normalizeHistoryComparable(text) {
6615
6582
  return String(text || "").replace(/\s+/g, " ").trim();
6616
6583
  }
6617
- function cleanupHistoryContent(agentType, role, content) {
6584
+ function cleanupHistoryContent(agentType, role, content, historyBehavior) {
6618
6585
  let value = String(content || "").replace(/\r\n/g, "\n").trim();
6619
6586
  if (!value) return "";
6620
- if (agentType === "codex-cli" && role === "assistant") {
6621
- const filtered = value.split("\n").filter((line) => !CODEX_STARTER_PROMPT_RE.test(line.trim())).join("\n").replace(/\n{3,}/g, "\n\n").trim();
6622
- value = filtered;
6587
+ if (role === "assistant" && historyBehavior?.filterAssistantPatterns?.length) {
6588
+ const filters = historyBehavior.filterAssistantPatterns.map((p) => {
6589
+ try {
6590
+ return new RegExp(p, "i");
6591
+ } catch {
6592
+ return null;
6593
+ }
6594
+ }).filter(Boolean);
6595
+ if (filters.length > 0) {
6596
+ const filtered = value.split("\n").filter((line) => !filters.some((re) => re.test(line.trim()))).join("\n").replace(/\n{3,}/g, "\n\n").trim();
6597
+ value = filtered;
6598
+ }
6623
6599
  }
6624
6600
  return value;
6625
6601
  }
@@ -6636,8 +6612,8 @@ function isAdjacentHistoryDuplicate(agentType, previous, next) {
6636
6612
  if (!previous || !next) return false;
6637
6613
  return buildHistoryMessageSignature(agentType, previous) === buildHistoryMessageSignature(agentType, next);
6638
6614
  }
6639
- function collapseReplayAssistantTurns(agentType, messages) {
6640
- if (agentType !== "codex-cli") return messages;
6615
+ function collapseReplayAssistantTurns(messages, historyBehavior) {
6616
+ if (!historyBehavior?.collapseConsecutiveAssistantTurns) return messages;
6641
6617
  const collapsed = [];
6642
6618
  let sawAssistantSinceLastUser = false;
6643
6619
  for (const message of messages) {
@@ -6742,16 +6718,12 @@ function listHistoryFiles(dir, historySessionId) {
6742
6718
  return true;
6743
6719
  }).sort().reverse();
6744
6720
  }
6745
- function normalizeSavedHistorySessionId(agentType, historySessionId) {
6746
- const normalizedId = String(historySessionId || "").trim();
6747
- if (!normalizedId) return "";
6748
- const strictProviderId = normalizeProviderSessionId(agentType, normalizedId);
6749
- if (strictProviderId) return strictProviderId;
6750
- return agentType === "hermes-cli" ? "" : normalizedId;
6721
+ function normalizeSavedHistorySessionId(historySessionId) {
6722
+ return String(historySessionId || "").trim();
6751
6723
  }
6752
- function extractSavedHistorySessionIdFromFile(agentType, file) {
6724
+ function extractSavedHistorySessionIdFromFile(file) {
6753
6725
  const match = file.match(/^([A-Za-z0-9_-]+)_\d{4}-\d{2}-\d{2}\.jsonl$/);
6754
- return normalizeSavedHistorySessionId(agentType, match?.[1] || "");
6726
+ return normalizeSavedHistorySessionId(match?.[1] || "");
6755
6727
  }
6756
6728
  function buildSavedHistoryFileSignatureMap(dir, files) {
6757
6729
  return new Map(files.map((file) => {
@@ -6930,7 +6902,7 @@ function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
6930
6902
  }
6931
6903
  }
6932
6904
  function updateSavedHistoryIndexForSessionStart(agentType, dir, file, historySessionId, workspace) {
6933
- const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId);
6905
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
6934
6906
  const normalizedWorkspace = String(workspace || "").trim();
6935
6907
  if (!normalizedSessionId || !normalizedWorkspace) return;
6936
6908
  persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => ({
@@ -6945,7 +6917,7 @@ function updateSavedHistoryIndexForSessionStart(agentType, dir, file, historySes
6945
6917
  }));
6946
6918
  }
6947
6919
  function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, historySessionId, messages) {
6948
- const normalizedSessionId = normalizeSavedHistorySessionId(agentType, historySessionId || "");
6920
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId || "");
6949
6921
  if (!normalizedSessionId || messages.length === 0) return;
6950
6922
  persistSavedHistoryFileSummaryEntry(agentType, dir, file, (currentSummary) => {
6951
6923
  const nextSummary = {
@@ -6982,8 +6954,8 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
6982
6954
  return nextSummary;
6983
6955
  });
6984
6956
  }
6985
- function computeSavedHistoryFileSummary(agentType, dir, file) {
6986
- const historySessionId = extractSavedHistorySessionIdFromFile(agentType, file);
6957
+ function computeSavedHistoryFileSummary(dir, file) {
6958
+ const historySessionId = extractSavedHistorySessionIdFromFile(file);
6987
6959
  if (!historySessionId) return null;
6988
6960
  const filePath = path7.join(dir, file);
6989
6961
  const content = fs3.readFileSync(filePath, "utf-8");
@@ -7077,7 +7049,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
7077
7049
  const cached = savedHistoryFileSummaryCache.get(filePath);
7078
7050
  const persisted = persistedEntries.get(file);
7079
7051
  const reusableEntry = cached?.signature === signature ? cached : persisted?.signature === signature ? persisted : null;
7080
- const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(agentType, dir, file);
7052
+ const fileSummary = reusableEntry?.summary || computeSavedHistoryFileSummary(dir, file);
7081
7053
  const nextEntry = reusableEntry || {
7082
7054
  signature,
7083
7055
  summary: fileSummary
@@ -7375,7 +7347,7 @@ var ChatHistoryWriter = class {
7375
7347
  } catch {
7376
7348
  }
7377
7349
  }
7378
- compactHistorySession(agentType, historySessionId) {
7350
+ compactHistorySession(agentType, historySessionId, historyBehavior) {
7379
7351
  const sessionId = String(historySessionId || "").trim();
7380
7352
  if (!sessionId) return;
7381
7353
  try {
@@ -7413,7 +7385,7 @@ var ChatHistoryWriter = class {
7413
7385
  dedupedAdjacent.push(entry);
7414
7386
  if (entry.role !== "system") lastTurn = entry;
7415
7387
  }
7416
- const collapsed = collapseReplayAssistantTurns(agentType, dedupedAdjacent);
7388
+ const collapsed = collapseReplayAssistantTurns(dedupedAdjacent, historyBehavior);
7417
7389
  if (collapsed.length === 0) {
7418
7390
  fs3.unlinkSync(filePath);
7419
7391
  continue;
@@ -7462,7 +7434,7 @@ var ChatHistoryWriter = class {
7462
7434
  return name.replace(/[^a-zA-Z0-9_-]/g, "_");
7463
7435
  }
7464
7436
  };
7465
- function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0) {
7437
+ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
7466
7438
  try {
7467
7439
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
7468
7440
  const dir = path7.join(HISTORY_DIR, sanitized);
@@ -7497,7 +7469,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
7497
7469
  chronological.push(message);
7498
7470
  if (message.role !== "system") lastTurn = message;
7499
7471
  }
7500
- const collapsed = collapseReplayAssistantTurns(agentType, chronological);
7472
+ const collapsed = collapseReplayAssistantTurns(chronological, historyBehavior);
7501
7473
  const boundedLimit = Math.max(1, limit);
7502
7474
  const boundedOffset = Math.max(0, offset);
7503
7475
  const boundedExclude = Math.max(0, Math.min(excludeRecentCount, collapsed.length));
@@ -7510,7 +7482,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
7510
7482
  return { messages: [], hasMore: false };
7511
7483
  }
7512
7484
  }
7513
- function listSavedHistorySessions(agentType, options = {}) {
7485
+ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
7514
7486
  try {
7515
7487
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
7516
7488
  const dir = path7.join(HISTORY_DIR, sanitized);
@@ -7641,7 +7613,7 @@ function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
7641
7613
  }
7642
7614
  }
7643
7615
  function rebuildHermesSavedHistoryFromCanonicalSession(historySessionId) {
7644
- const normalizedSessionId = normalizeSavedHistorySessionId("hermes-cli", historySessionId);
7616
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
7645
7617
  if (!normalizedSessionId) return false;
7646
7618
  try {
7647
7619
  const sessionFilePath = path7.join(os5.homedir(), ".hermes", "sessions", `session_${normalizedSessionId}.json`);
@@ -7790,7 +7762,7 @@ function extractClaudeUserContentParts(content) {
7790
7762
  return parts;
7791
7763
  }
7792
7764
  function rebuildClaudeSavedHistoryFromNativeProject(historySessionId, workspace) {
7793
- const normalizedSessionId = normalizeSavedHistorySessionId("claude-cli", historySessionId);
7765
+ const normalizedSessionId = normalizeSavedHistorySessionId(historySessionId);
7794
7766
  if (!normalizedSessionId) return false;
7795
7767
  try {
7796
7768
  const transcriptPath = resolveClaudeProjectTranscriptPath(normalizedSessionId, workspace);
@@ -11956,7 +11928,8 @@ async function executeProviderScript(h, args, scriptName) {
11956
11928
  }
11957
11929
  const managed = runtimeSessionId ? h.agentStream?.getManagedSession(runtimeSessionId) : null;
11958
11930
  const targetSessionId = managed?.cdpSessionId || null;
11959
- const IDE_LEVEL_SCRIPTS = provider.type === "claude-code-vscode" ? ["listModes", "setMode", "listModels", "setModel", "setModelGui"] : ["listModes", "setMode", "listModels", "setModel"];
11931
+ const DEFAULT_IDE_LEVEL_SCRIPTS = ["listModes", "setMode", "listModels", "setModel"];
11932
+ const IDE_LEVEL_SCRIPTS = provider.ideLevelScripts ?? DEFAULT_IDE_LEVEL_SCRIPTS;
11960
11933
  if (IDE_LEVEL_SCRIPTS.includes(scriptName)) {
11961
11934
  if (targetSessionId) {
11962
11935
  try {
@@ -12681,6 +12654,25 @@ import * as fs5 from "fs";
12681
12654
  import { createRequire } from "module";
12682
12655
  init_provider_cli_adapter();
12683
12656
  init_logger();
12657
+
12658
+ // src/providers/provider-session-id.ts
12659
+ function normalizeProviderSessionId(provider, providerSessionId) {
12660
+ const normalizedId = typeof providerSessionId === "string" ? providerSessionId.trim() : "";
12661
+ if (!normalizedId) return "";
12662
+ const lowered = normalizedId.toLowerCase();
12663
+ if (lowered === "undefined" || lowered === "null") return "";
12664
+ const sessionIdPattern = provider?.sessionIdPattern;
12665
+ if (sessionIdPattern) {
12666
+ try {
12667
+ const re = new RegExp(sessionIdPattern, "i");
12668
+ if (!re.test(normalizedId)) return "";
12669
+ } catch {
12670
+ }
12671
+ }
12672
+ return normalizedId;
12673
+ }
12674
+
12675
+ // src/providers/cli-provider-instance.ts
12684
12676
  init_chat_message_normalization();
12685
12677
  function normalizePersistableCliHistoryContent(content) {
12686
12678
  return flattenContent(content).replace(/\s+/g, " ").trim();
@@ -12787,6 +12779,13 @@ var CliProviderInstance = class {
12787
12779
  runtimeMessages = [];
12788
12780
  lastPersistedHistoryMessages = [];
12789
12781
  lastCanonicalHermesSyncMtimeMs = 0;
12782
+ lastCanonicalHermesExistCheckAt = 0;
12783
+ lastCanonicalHermesWatchPath = void 0;
12784
+ lastCanonicalClaudeRebuildMtimeMs = 0;
12785
+ lastCanonicalClaudeCheckAt = 0;
12786
+ cachedSqliteDb = null;
12787
+ cachedSqliteDbPath = null;
12788
+ cachedSqliteDbMissingUntil = 0;
12790
12789
  instanceId;
12791
12790
  suppressIdleHistoryReplay = false;
12792
12791
  errorMessage = void 0;
@@ -12837,32 +12836,10 @@ var CliProviderInstance = class {
12837
12836
  }
12838
12837
  async onTick() {
12839
12838
  if (this.providerSessionId) return;
12840
- if (this.type === "hermes-cli" && this.launchMode === "new") return;
12841
- let probedSessionId = null;
12839
+ if (this.provider.resume?.skipProbeOnNewSession && this.launchMode === "new") return;
12842
12840
  const probeConfig = this.provider.sessionProbe;
12843
- if (probeConfig) {
12844
- probedSessionId = this.probeSessionIdFromConfig(probeConfig);
12845
- } else {
12846
- if (this.type === "opencode-cli") {
12847
- probedSessionId = this.probeSessionIdFromConfig({
12848
- dbPath: "~/.local/share/opencode/opencode.db",
12849
- query: "select id from session where directory in ({dirs}) and time_created >= ? and time_archived is null order by time_updated desc limit 1",
12850
- timestampFormat: "unix_ms"
12851
- });
12852
- } else if (this.type === "codex-cli") {
12853
- probedSessionId = this.probeSessionIdFromConfig({
12854
- dbPath: "~/.codex/state_5.sqlite",
12855
- query: "select id from threads where cwd in ({dirs}) and updated_at >= ? and archived = 0 order by updated_at desc limit 1",
12856
- timestampFormat: "unix_s"
12857
- });
12858
- } else if (this.type === "goose-cli") {
12859
- probedSessionId = this.probeSessionIdFromConfig({
12860
- dbPath: "~/.local/share/goose/sessions/sessions.db",
12861
- query: "select id from sessions where working_dir in ({dirs}) and created_at >= ? order by updated_at desc limit 1",
12862
- timestampFormat: "iso"
12863
- });
12864
- }
12865
- }
12841
+ if (!probeConfig) return;
12842
+ const probedSessionId = this.probeSessionIdFromConfig(probeConfig);
12866
12843
  if (probedSessionId) {
12867
12844
  this.promoteProviderSessionId(probedSessionId);
12868
12845
  }
@@ -12873,7 +12850,12 @@ var CliProviderInstance = class {
12873
12850
  */
12874
12851
  probeSessionIdFromConfig(probe) {
12875
12852
  const resolvedDbPath = probe.dbPath.replace(/^~/, os11.homedir());
12876
- if (!fs5.existsSync(resolvedDbPath)) return null;
12853
+ const now = Date.now();
12854
+ if (this.cachedSqliteDbMissingUntil > now) return null;
12855
+ if (!fs5.existsSync(resolvedDbPath)) {
12856
+ this.cachedSqliteDbMissingUntil = now + 1e4;
12857
+ return null;
12858
+ }
12877
12859
  const directories = this.getProbeDirectories();
12878
12860
  const minCreatedAt = Math.max(0, this.startedAt - 6e4);
12879
12861
  const tsFormat = probe.timestampFormat || "unix_ms";
@@ -12914,7 +12896,7 @@ var CliProviderInstance = class {
12914
12896
  const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
12915
12897
  const visibleStatus = parseErrorMessage ? "error" : autoApproveActive ? "generating" : adapterStatus.status;
12916
12898
  const parsedProviderSessionId = normalizeProviderSessionId(
12917
- this.type,
12899
+ this.provider,
12918
12900
  typeof parsedStatus?.providerSessionId === "string" ? parsedStatus.providerSessionId : ""
12919
12901
  );
12920
12902
  if (parsedProviderSessionId) {
@@ -13044,6 +13026,12 @@ var CliProviderInstance = class {
13044
13026
  this.adapter.shutdown();
13045
13027
  this.monitor.reset();
13046
13028
  this.appliedEffectKeys.clear();
13029
+ try {
13030
+ this.cachedSqliteDb?.close();
13031
+ } catch {
13032
+ }
13033
+ this.cachedSqliteDb = null;
13034
+ this.cachedSqliteDbPath = null;
13047
13035
  }
13048
13036
  completedDebounceTimer = null;
13049
13037
  completedDebouncePending = null;
@@ -13204,7 +13192,7 @@ var CliProviderInstance = class {
13204
13192
  applyProviderResponse(data, options) {
13205
13193
  if (!data || typeof data !== "object") return;
13206
13194
  const patchedProviderSessionId = normalizeProviderSessionId(
13207
- this.type,
13195
+ this.provider,
13208
13196
  typeof data.providerSessionId === "string" ? data.providerSessionId : ""
13209
13197
  );
13210
13198
  if (patchedProviderSessionId) {
@@ -13442,52 +13430,61 @@ ${effect.notification.body || ""}`.trim();
13442
13430
  }
13443
13431
  syncCanonicalSavedHistoryIfNeeded() {
13444
13432
  if (!this.providerSessionId) return false;
13445
- if (this.type === "hermes-cli") {
13446
- try {
13447
- const canonicalPath = path11.join(os11.homedir(), ".hermes", "sessions", `session_${this.providerSessionId}.json`);
13448
- if (!fs5.existsSync(canonicalPath)) return false;
13449
- const stat = fs5.statSync(canonicalPath);
13433
+ const canonicalHistory = this.provider.canonicalHistory;
13434
+ if (!canonicalHistory) return false;
13435
+ try {
13436
+ let rebuilt = false;
13437
+ if (canonicalHistory.format === "hermes-json") {
13438
+ const watchPath = canonicalHistory.watchPath.replace(/^~/, os11.homedir()).replace("{{sessionId}}", this.providerSessionId);
13439
+ const now = Date.now();
13440
+ if (watchPath !== this.lastCanonicalHermesWatchPath || now - this.lastCanonicalHermesExistCheckAt >= 2e3) {
13441
+ this.lastCanonicalHermesWatchPath = watchPath;
13442
+ this.lastCanonicalHermesExistCheckAt = now;
13443
+ if (!fs5.existsSync(watchPath)) return false;
13444
+ } else if (this.lastCanonicalHermesSyncMtimeMs === 0) {
13445
+ if (!fs5.existsSync(watchPath)) return false;
13446
+ }
13447
+ const stat = fs5.statSync(watchPath);
13450
13448
  if (stat.mtimeMs <= this.lastCanonicalHermesSyncMtimeMs) return true;
13451
- const rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
13452
- if (!rebuilt) return false;
13453
- this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
13454
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13455
- this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13456
- role: message.role,
13457
- content: message.content,
13458
- kind: message.kind,
13459
- senderName: message.senderName,
13460
- receivedAt: message.receivedAt
13461
- }));
13462
- return true;
13463
- } catch {
13464
- return false;
13465
- }
13466
- }
13467
- if (this.type === "claude-cli") {
13468
- try {
13469
- const rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
13470
- if (!rebuilt) return false;
13471
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13472
- this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13473
- role: message.role,
13474
- content: message.content,
13475
- kind: message.kind,
13476
- senderName: message.senderName,
13477
- receivedAt: message.receivedAt
13478
- }));
13479
- return true;
13480
- } catch {
13481
- return false;
13449
+ rebuilt = rebuildHermesSavedHistoryFromCanonicalSession(this.providerSessionId);
13450
+ if (rebuilt) this.lastCanonicalHermesSyncMtimeMs = stat.mtimeMs;
13451
+ } else if (canonicalHistory.format === "claude-jsonl") {
13452
+ const now = Date.now();
13453
+ if (now - this.lastCanonicalClaudeCheckAt < 2e3 && this.lastCanonicalClaudeRebuildMtimeMs !== 0) {
13454
+ return true;
13455
+ }
13456
+ this.lastCanonicalClaudeCheckAt = now;
13457
+ const claudeProjectsDir = path11.join(os11.homedir(), ".claude", "projects");
13458
+ const workspaceSegment = typeof this.workingDir === "string" ? this.workingDir.replace(/[\\/]/g, "-").replace(/^-+/, "") : "";
13459
+ const transcriptFile = path11.join(claudeProjectsDir, workspaceSegment, `${this.providerSessionId}.jsonl`);
13460
+ let transcriptMtime = 0;
13461
+ try {
13462
+ transcriptMtime = fs5.statSync(transcriptFile).mtimeMs;
13463
+ } catch {
13464
+ }
13465
+ if (transcriptMtime > 0 && transcriptMtime <= this.lastCanonicalClaudeRebuildMtimeMs) return true;
13466
+ rebuilt = rebuildClaudeSavedHistoryFromNativeProject(this.providerSessionId, this.workingDir);
13467
+ if (rebuilt) this.lastCanonicalClaudeRebuildMtimeMs = transcriptMtime || Date.now();
13482
13468
  }
13469
+ if (!rebuilt) return false;
13470
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
13471
+ this.lastPersistedHistoryMessages = restoredHistory.messages.map((message) => ({
13472
+ role: message.role,
13473
+ content: message.content,
13474
+ kind: message.kind,
13475
+ senderName: message.senderName,
13476
+ receivedAt: message.receivedAt
13477
+ }));
13478
+ return true;
13479
+ } catch {
13480
+ return false;
13483
13481
  }
13484
- return false;
13485
13482
  }
13486
13483
  restorePersistedHistoryFromCurrentSession() {
13487
13484
  if (!this.providerSessionId) return;
13488
13485
  this.syncCanonicalSavedHistoryIfNeeded();
13489
- this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
13490
- const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId);
13486
+ this.historyWriter.compactHistorySession(this.type, this.providerSessionId, this.provider.historyBehavior);
13487
+ const restoredHistory = readChatHistory(this.type, 0, Number.MAX_SAFE_INTEGER, this.providerSessionId, 0, this.provider.historyBehavior);
13491
13488
  this.historyWriter.seedSessionHistory(
13492
13489
  this.type,
13493
13490
  restoredHistory.messages,
@@ -13532,20 +13529,29 @@ ${effect.notification.body || ""}`.trim();
13532
13529
  return Array.from({ length: count }, () => "?").join(", ");
13533
13530
  }
13534
13531
  querySqliteText(dbPath, query, params) {
13535
- let db = null;
13536
13532
  try {
13537
- const DatabaseSync = getDatabaseSync();
13538
- db = new DatabaseSync(dbPath, { readOnly: true });
13539
- const row = db.prepare(query).get(...params);
13533
+ if (this.cachedSqliteDb === null || this.cachedSqliteDbPath !== dbPath) {
13534
+ try {
13535
+ this.cachedSqliteDb?.close();
13536
+ } catch {
13537
+ }
13538
+ this.cachedSqliteDb = null;
13539
+ this.cachedSqliteDbPath = null;
13540
+ const DatabaseSync = getDatabaseSync();
13541
+ this.cachedSqliteDb = new DatabaseSync(dbPath, { readOnly: true });
13542
+ this.cachedSqliteDbPath = dbPath;
13543
+ }
13544
+ const row = this.cachedSqliteDb.prepare(query).get(...params);
13540
13545
  const sessionId = typeof row?.id === "string" ? row.id.trim() : "";
13541
13546
  return sessionId || null;
13542
13547
  } catch {
13543
- return null;
13544
- } finally {
13545
13548
  try {
13546
- db?.close();
13549
+ this.cachedSqliteDb?.close();
13547
13550
  } catch {
13548
13551
  }
13552
+ this.cachedSqliteDb = null;
13553
+ this.cachedSqliteDbPath = null;
13554
+ return null;
13549
13555
  }
13550
13556
  }
13551
13557
  };
@@ -14733,14 +14739,15 @@ function expandResumeArgs(template, sessionId) {
14733
14739
  if (!Array.isArray(template) || template.length === 0) return void 0;
14734
14740
  return template.map((part) => part === "{{id}}" ? sessionId : part);
14735
14741
  }
14736
- function readCodexResumeSessionId(args) {
14737
- const resumeIndex = args.findIndex((arg) => arg === "resume" || arg === "fork");
14742
+ function readSubcommandSessionId(args, subcommands) {
14743
+ const resumeIndex = args.findIndex((arg) => subcommands.includes(arg));
14738
14744
  if (resumeIndex < 0) return void 0;
14739
14745
  const candidate = args[resumeIndex + 1];
14740
14746
  if (!candidate || candidate.startsWith("-")) return void 0;
14741
14747
  return candidate;
14742
14748
  }
14743
- function detectExplicitProviderSessionId(normalizedType, args) {
14749
+ function detectExplicitProviderSessionId(provider, args) {
14750
+ const resume = provider?.resume;
14744
14751
  const explicitResumeId = readArgValue(args, ["--resume", "-r"]);
14745
14752
  if (explicitResumeId) {
14746
14753
  return { providerSessionId: explicitResumeId, launchMode: "resume" };
@@ -14754,19 +14761,20 @@ function detectExplicitProviderSessionId(normalizedType, args) {
14754
14761
  }
14755
14762
  const explicitSessionId = readArgValue(args, ["--session-id"]);
14756
14763
  if (explicitSessionId) {
14757
- if (normalizedType === "goose-cli" && !hasArg(args, ["--resume", "-r"])) {
14764
+ if (resume?.sessionIdIsNewByDefault && !hasArg(args, ["--resume", "-r"])) {
14758
14765
  return { launchMode: "manual" };
14759
14766
  }
14760
- const isResume = normalizedType === "goose-cli" ? hasArg(args, ["--resume", "-r"]) : hasArg(args, ["--continue"]) || hasArg(args, ["--resume", "-r"]);
14767
+ const isResume = resume?.sessionIdIsNewByDefault ? hasArg(args, ["--resume", "-r"]) : hasArg(args, ["--continue"]) || hasArg(args, ["--resume", "-r"]);
14761
14768
  return {
14762
14769
  providerSessionId: explicitSessionId,
14763
14770
  launchMode: isResume ? "resume" : "new"
14764
14771
  };
14765
14772
  }
14766
- if (normalizedType === "codex-cli") {
14767
- const codexSessionId = readCodexResumeSessionId(args);
14768
- if (codexSessionId) {
14769
- return { providerSessionId: codexSessionId, launchMode: "resume" };
14773
+ const subcommands = resume?.sessionIdFromSubcommand;
14774
+ if (Array.isArray(subcommands) && subcommands.length > 0) {
14775
+ const subcommandSessionId = readSubcommandSessionId(args, subcommands);
14776
+ if (subcommandSessionId) {
14777
+ return { providerSessionId: subcommandSessionId, launchMode: "resume" };
14770
14778
  }
14771
14779
  }
14772
14780
  return { launchMode: "manual" };
@@ -14783,7 +14791,7 @@ function resolveCliSessionBinding(provider, normalizedType, cliArgs, requestedRe
14783
14791
  if (!resume?.supported) {
14784
14792
  return { cliArgs: baseArgs, launchMode: "manual" };
14785
14793
  }
14786
- const explicit = detectExplicitProviderSessionId(normalizedType, baseArgs || []);
14794
+ const explicit = detectExplicitProviderSessionId(provider, baseArgs || []);
14787
14795
  if (explicit.providerSessionId) {
14788
14796
  return {
14789
14797
  cliArgs: baseArgs,
@@ -14791,6 +14799,12 @@ function resolveCliSessionBinding(provider, normalizedType, cliArgs, requestedRe
14791
14799
  launchMode: explicit.launchMode
14792
14800
  };
14793
14801
  }
14802
+ if (explicit.launchMode === "manual" && hasArg(baseArgs || [], ["--session-id"])) {
14803
+ return {
14804
+ cliArgs: baseArgs,
14805
+ launchMode: "manual"
14806
+ };
14807
+ }
14794
14808
  if (requestedResumeSessionId) {
14795
14809
  if (resume.sessionIdFormat === "uuid" && !isUuid(requestedResumeSessionId)) {
14796
14810
  throw new Error(`Invalid ${provider?.displayName || provider?.name || normalizedType} session ID: ${requestedResumeSessionId}`);
@@ -15495,6 +15509,12 @@ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
15495
15509
  "resume",
15496
15510
  "sessionProbe",
15497
15511
  "approvalPositiveHints",
15512
+ "sessionIdPattern",
15513
+ "historyBehavior",
15514
+ "canonicalHistory",
15515
+ "autoFixProfile",
15516
+ "ideLevelScripts",
15517
+ "allowInputDuringGeneration",
15498
15518
  "scripts",
15499
15519
  "vscodeCommands",
15500
15520
  "inputMethod",
@@ -22824,20 +22844,13 @@ function tryKillAutoImplProcess(processRef, signal) {
22824
22844
  } catch {
22825
22845
  }
22826
22846
  }
22847
+ function shouldScheduleAutoStopOnQuiet(options) {
22848
+ return !!options.verification && options.autoImpl?.autoStopOnQuiet === true;
22849
+ }
22827
22850
  function getDefaultAutoImplReference(ctx, category, type) {
22828
- if (category === "cli") {
22829
- return type === "codex-cli" ? "claude-cli" : "codex-cli";
22830
- }
22831
- if (category === "extension") {
22832
- const preferred = ["claude-code-vscode", "codex", "cline", "roo-code"];
22833
- for (const ref of preferred) {
22834
- if (ref === type) continue;
22835
- if (ctx.providerLoader.resolve(ref) || ctx.providerLoader.getMeta(ref)) return ref;
22836
- }
22837
- const all = ctx.providerLoader.getAll();
22838
- const fb = all.find((p) => p.category === "extension" && p.type !== type);
22839
- if (fb?.type) return fb.type;
22840
- }
22851
+ const all = ctx.providerLoader.getAll();
22852
+ const sameCategoryOther = all.find((p) => p.category === category && p.type !== type);
22853
+ if (sameCategoryOther?.type) return sameCategoryOther.type;
22841
22854
  return "antigravity";
22842
22855
  }
22843
22856
  function resolveAutoImplReference(ctx, category, requestedReference, targetType) {
@@ -23155,37 +23168,33 @@ async function handleAutoImplement(ctx, type, req, res) {
23155
23168
  return;
23156
23169
  }
23157
23170
  const command = spawn4.command;
23171
+ const autoImpl = spawn4.autoImpl;
23158
23172
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
23159
23173
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
23160
23174
  let shellCmd;
23161
23175
  const isWin = os19.platform() === "win32";
23162
23176
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
23163
- if (command === "claude") {
23164
- const args = [...baseArgs, "--dangerously-skip-permissions"];
23177
+ const promptMode = autoImpl?.promptMode ?? "stdin";
23178
+ const extraArgs = autoImpl?.extraArgs ?? [];
23179
+ const rawMetaPrompt = autoImpl?.metaPrompt ? autoImpl.metaPrompt.replace("{{promptFile}}", promptFile) : `Read the file at ${promptFile} and follow ALL the instructions in it exactly. Do not ask questions, just execute.`;
23180
+ if (promptMode === "flag") {
23181
+ const flag = autoImpl?.promptFlag ?? "-p";
23182
+ const args = [...baseArgs, ...extraArgs];
23165
23183
  if (model) args.push("--model", model);
23166
23184
  const escapedArgs = args.map(escapeArg).join(" ");
23167
- const metaPrompt = `Read the file at ${promptFile} and follow ALL the instructions. Implement the specific function requested, then test it via CDP curl targeting 127.0.0.1:19280, wait for confirmation of success, and then close. DO NOT start working on other features not listed in the prompt constraint.`;
23168
- shellCmd = `${command} ${escapedArgs} -p ${escapeArg(metaPrompt)}`;
23169
- } else if (command === "gemini") {
23170
- const args = [...baseArgs, "-y", "-s", "false"];
23171
- if (model) args.push("-m", model);
23172
- const escapedArgs = args.map(escapeArg).join(" ");
23173
- const metaPrompt = `Read the file at ${promptFile} and follow ALL the instructions in it exactly. Do not ask questions, just execute.`;
23174
- shellCmd = `${command} ${escapedArgs} -p ${escapeArg(metaPrompt)}`;
23175
- } else if (command === "codex") {
23176
- const args = ["exec", ...baseArgs];
23177
- if (!args.includes("--dangerously-bypass-approvals-and-sandbox")) {
23178
- args.push("--dangerously-bypass-approvals-and-sandbox");
23179
- }
23180
- if (!args.includes("--skip-git-repo-check")) {
23181
- args.push("--skip-git-repo-check");
23185
+ shellCmd = `${command} ${escapedArgs} ${flag} ${escapeArg(rawMetaPrompt)}`;
23186
+ } else if (promptMode === "subcommand") {
23187
+ const subcommand = autoImpl?.subcommand ?? "";
23188
+ const args = subcommand ? [subcommand, ...baseArgs] : [...baseArgs];
23189
+ for (const extra of extraArgs) {
23190
+ if (!args.includes(extra)) args.push(extra);
23182
23191
  }
23183
23192
  if (model) args.push("--model", model);
23184
23193
  const escapedArgs = args.map(escapeArg).join(" ");
23185
- const metaPrompt = `Read the file at ${promptFile} and follow ALL instructions strictly. DO NOT spend time exploring the filesystem or other providers. You have full authority to implement ALL required script files and independently test them against 127.0.0.1:19280 via CDP CURL. Upon complete validation of ALL assigned files, print exactly "_PIPELINE_COMPLETE_SIGNAL_" to gracefully close the pipeline. DO NOT WAIT FOR APPROVAL, execute completely autonomously.`;
23186
- shellCmd = `${command} ${escapedArgs} ${escapeArg(metaPrompt)}`;
23194
+ shellCmd = `${command} ${escapedArgs} ${escapeArg(rawMetaPrompt)}`;
23187
23195
  } else {
23188
- const escapedArgs = baseArgs.map(escapeArg).join(" ");
23196
+ const args = [...baseArgs, ...extraArgs];
23197
+ const escapedArgs = args.map(escapeArg).join(" ");
23189
23198
  if (isWin) {
23190
23199
  shellCmd = `type "${promptFile}" | ${command} ${escapedArgs}`;
23191
23200
  } else {
@@ -23220,8 +23229,7 @@ async function handleAutoImplement(ctx, type, req, res) {
23220
23229
  stdio: ["pipe", "pipe", "pipe"],
23221
23230
  env: {
23222
23231
  ...process.env,
23223
- ...spawn4.env || {},
23224
- ...command === "gemini" ? { SANDBOX: "1", GEMINI_CLI_NO_RELAUNCH: "1" } : {}
23232
+ ...spawn4.env || {}
23225
23233
  }
23226
23234
  });
23227
23235
  child.on("error", (err2) => {
@@ -23283,7 +23291,7 @@ async function handleAutoImplement(ctx, type, req, res) {
23283
23291
  }
23284
23292
  };
23285
23293
  const scheduleAutoStopForVerification = () => {
23286
- if (!verification || command !== "codex" || completionSignalSeen || autoStopIssued) return;
23294
+ if (!shouldScheduleAutoStopOnQuiet({ verification, autoImpl }) || completionSignalSeen || autoStopIssued) return;
23287
23295
  const elapsed = Date.now() - spawnedAt;
23288
23296
  if (elapsed < 3e4) return;
23289
23297
  clearAutoStopTimer();