@scotthamilton77/sidekick 0.1.18 → 0.1.20

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/bin.js CHANGED
@@ -1038,6 +1038,8 @@ var require_hook_events = __commonJS({
1038
1038
  exports2.isPostToolUseEvent = isPostToolUseEvent;
1039
1039
  exports2.isStopEvent = isStopEvent;
1040
1040
  exports2.isPreCompactEvent = isPreCompactEvent;
1041
+ exports2.isSubagentStartEvent = isSubagentStartEvent;
1042
+ exports2.isSubagentStopEvent = isSubagentStopEvent;
1041
1043
  exports2.HOOK_NAMES = [
1042
1044
  "SessionStart",
1043
1045
  "SessionEnd",
@@ -1045,7 +1047,9 @@ var require_hook_events = __commonJS({
1045
1047
  "PreToolUse",
1046
1048
  "PostToolUse",
1047
1049
  "Stop",
1048
- "PreCompact"
1050
+ "PreCompact",
1051
+ "SubagentStart",
1052
+ "SubagentStop"
1049
1053
  ];
1050
1054
  function isSessionStartEvent(event) {
1051
1055
  return event.hook === "SessionStart";
@@ -1068,6 +1072,12 @@ var require_hook_events = __commonJS({
1068
1072
  function isPreCompactEvent(event) {
1069
1073
  return event.hook === "PreCompact";
1070
1074
  }
1075
+ function isSubagentStartEvent(event) {
1076
+ return event.hook === "SubagentStart";
1077
+ }
1078
+ function isSubagentStopEvent(event) {
1079
+ return event.hook === "SubagentStop";
1080
+ }
1071
1081
  }
1072
1082
  });
1073
1083
 
@@ -17942,7 +17952,7 @@ var require_hook_input = __commonJS({
17942
17952
  "../types/dist/hook-input.js"(exports2) {
17943
17953
  "use strict";
17944
17954
  Object.defineProperty(exports2, "__esModule", { value: true });
17945
- exports2.HookInputSchema = exports2.StatuslineInputSchema = exports2.StatuslineWorkspaceSchema = exports2.StatuslineCostSchema = exports2.StatuslineContextWindowSchema = exports2.StatuslineModelSchema = exports2.NotificationInputSchema = exports2.PreCompactInputSchema = exports2.SessionEndInputSchema = exports2.SessionStartInputSchema = exports2.StopInputSchema = exports2.PostToolUseInputSchema = exports2.PreToolUseInputSchema = exports2.UserPromptSubmitInputSchema = exports2.HookInputBaseSchema = void 0;
17955
+ exports2.HookInputSchema = exports2.StatuslineInputSchema = exports2.StatuslineWorkspaceSchema = exports2.StatuslineCostSchema = exports2.StatuslineContextWindowSchema = exports2.StatuslineModelSchema = exports2.SubagentStopInputSchema = exports2.SubagentStartInputSchema = exports2.NotificationInputSchema = exports2.PreCompactInputSchema = exports2.SessionEndInputSchema = exports2.SessionStartInputSchema = exports2.StopInputSchema = exports2.PostToolUseInputSchema = exports2.PreToolUseInputSchema = exports2.UserPromptSubmitInputSchema = exports2.HookInputBaseSchema = void 0;
17946
17956
  var zod_1 = require_zod();
17947
17957
  exports2.HookInputBaseSchema = zod_1.z.object({
17948
17958
  /** Unique identifier for the current Claude session */
@@ -17954,7 +17964,11 @@ var require_hook_input = __commonJS({
17954
17964
  /** Current permission level: "default", "plan", "acceptEdits", or "bypassPermissions" */
17955
17965
  permission_mode: zod_1.z.string().optional(),
17956
17966
  /** Name of the triggered hook (e.g., "UserPromptSubmit", "SessionStart") */
17957
- hook_event_name: zod_1.z.string()
17967
+ hook_event_name: zod_1.z.string(),
17968
+ /** Unique identifier for the subagent (present when hook fires inside a subagent) */
17969
+ agent_id: zod_1.z.string().optional(),
17970
+ /** Agent type/name: "Bash", "Explore", "Plan", or custom (present when inside a subagent) */
17971
+ agent_type: zod_1.z.string().optional()
17958
17972
  });
17959
17973
  exports2.UserPromptSubmitInputSchema = exports2.HookInputBaseSchema.extend({
17960
17974
  /** The user's message text */
@@ -18002,6 +18016,26 @@ var require_hook_input = __commonJS({
18002
18016
  /** Type: "permission_prompt", "idle_prompt", "auth_success", or "elicitation_dialog" */
18003
18017
  notification_type: zod_1.z.string()
18004
18018
  });
18019
+ exports2.SubagentStartInputSchema = exports2.HookInputBaseSchema.extend({
18020
+ /** Unique identifier for the subagent (required per official docs) */
18021
+ agent_id: zod_1.z.string(),
18022
+ /** Agent name: "Bash", "Explore", "Plan", or custom agent name */
18023
+ agent_type: zod_1.z.string()
18024
+ });
18025
+ exports2.SubagentStopInputSchema = exports2.HookInputBaseSchema.extend({
18026
+ /** Unique identifier for the subagent */
18027
+ agent_id: zod_1.z.string(),
18028
+ /** Agent name */
18029
+ agent_type: zod_1.z.string(),
18030
+ /** Path to subagent's own transcript JSONL */
18031
+ agent_transcript_path: zod_1.z.string(),
18032
+ /** Text content of the subagent's final response */
18033
+ last_assistant_message: zod_1.z.string(),
18034
+ /** Permission mode for the subagent session */
18035
+ permission_mode: zod_1.z.string(),
18036
+ /** Optional: whether stop hook is active (probe doc says never populated; official docs show false) */
18037
+ stop_hook_active: zod_1.z.boolean().optional()
18038
+ });
18005
18039
  exports2.StatuslineModelSchema = zod_1.z.object({
18006
18040
  /** Full model identifier (e.g., "claude-opus-4-1") */
18007
18041
  id: zod_1.z.string(),
@@ -18057,13 +18091,15 @@ var require_hook_input = __commonJS({
18057
18091
  output_style: zod_1.z.object({ name: zod_1.z.string() }).optional()
18058
18092
  });
18059
18093
  exports2.HookInputSchema = zod_1.z.union([
18094
+ exports2.SessionStartInputSchema,
18095
+ exports2.SessionEndInputSchema,
18060
18096
  exports2.UserPromptSubmitInputSchema,
18061
18097
  exports2.PreToolUseInputSchema,
18062
18098
  exports2.PostToolUseInputSchema,
18063
18099
  exports2.StopInputSchema,
18064
- exports2.SessionStartInputSchema,
18065
- exports2.SessionEndInputSchema,
18066
18100
  exports2.PreCompactInputSchema,
18101
+ exports2.SubagentStartInputSchema,
18102
+ exports2.SubagentStopInputSchema,
18067
18103
  exports2.NotificationInputSchema,
18068
18104
  exports2.HookInputBaseSchema
18069
18105
  // Fallback for hooks without extra fields
@@ -18160,9 +18196,11 @@ var require_setup_status = __commonJS({
18160
18196
  "missing",
18161
18197
  // User declined or entries not present
18162
18198
  "incomplete",
18163
- // Section exists but missing end marker or required entries
18164
- "installed"
18165
- // Sidekick section present with all required entries
18199
+ // .sidekick/.gitignore exists but missing required entries (legacy: partial root section)
18200
+ "installed",
18201
+ // .sidekick/.gitignore present with all entries (new format)
18202
+ "legacy"
18203
+ // Root .gitignore has old marked section — functional, migrate recommended
18166
18204
  ]);
18167
18205
  exports2.ProjectApiKeyValueSchema = zod_1.z.union([exports2.ProjectApiKeyHealthSchema, exports2.ProjectApiKeyStatusSchema]);
18168
18206
  exports2.ProjectSetupStatusSchema = zod_1.z.object({
@@ -27199,6 +27237,18 @@ var require_dist2 = __commonJS({
27199
27237
  }
27200
27238
  });
27201
27239
 
27240
+ // ../sidekick-core/dist/error-utils.js
27241
+ var require_error_utils = __commonJS({
27242
+ "../sidekick-core/dist/error-utils.js"(exports2) {
27243
+ "use strict";
27244
+ Object.defineProperty(exports2, "__esModule", { value: true });
27245
+ exports2.toErrorMessage = toErrorMessage;
27246
+ function toErrorMessage(error) {
27247
+ return error instanceof Error ? error.message : String(error);
27248
+ }
27249
+ }
27250
+ });
27251
+
27202
27252
  // ../sidekick-core/dist/assets.js
27203
27253
  var require_assets = __commonJS({
27204
27254
  "../sidekick-core/dist/assets.js"(exports2) {
@@ -27212,6 +27262,7 @@ var require_assets = __commonJS({
27212
27262
  var yaml_1 = require_dist2();
27213
27263
  var node_os_1 = require("node:os");
27214
27264
  var node_path_1 = require("node:path");
27265
+ var error_utils_js_1 = require_error_utils();
27215
27266
  function createCascadingResolver(options) {
27216
27267
  const { cascadeLayers } = options;
27217
27268
  const findFile = (relativePath) => {
@@ -27261,7 +27312,7 @@ var require_assets = __commonJS({
27261
27312
  try {
27262
27313
  return (0, yaml_1.parse)(content);
27263
27314
  } catch (error) {
27264
- throw new Error(`Failed to parse YAML file ${relativePath}: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
27315
+ throw new Error(`Failed to parse YAML file ${relativePath}: ${(0, error_utils_js_1.toErrorMessage)(error)}`, { cause: error });
27265
27316
  }
27266
27317
  },
27267
27318
  cascadeLayers
@@ -27336,6 +27387,7 @@ var require_persona_loader = __commonJS({
27336
27387
  var node_path_1 = require("node:path");
27337
27388
  var types_1 = require_dist();
27338
27389
  var assets_js_1 = require_assets();
27390
+ var error_utils_js_1 = require_error_utils();
27339
27391
  function buildPersonaCascadeLayers(defaultPersonasDir, homeDir, projectRoot) {
27340
27392
  const layers = [];
27341
27393
  layers.push(defaultPersonasDir);
@@ -27363,7 +27415,7 @@ var require_persona_loader = __commonJS({
27363
27415
  }
27364
27416
  return result.data;
27365
27417
  } catch (error) {
27366
- const message = error instanceof Error ? error.message : String(error);
27418
+ const message = (0, error_utils_js_1.toErrorMessage)(error);
27367
27419
  logger?.warn(`Failed to load persona file ${filename}: ${message}`);
27368
27420
  return null;
27369
27421
  }
@@ -27946,6 +27998,7 @@ var require_config2 = __commonJS({
27946
27998
  var node_path_1 = require("node:path");
27947
27999
  var yaml_1 = require_dist2();
27948
28000
  var v4_1 = require_v4();
28001
+ var error_utils_js_1 = require_error_utils();
27949
28002
  function deepFreeze(obj) {
27950
28003
  if (obj === null || typeof obj !== "object") {
27951
28004
  return obj;
@@ -27972,7 +28025,7 @@ var require_config2 = __commonJS({
27972
28025
  consoleEnabled: v4_1.z.boolean(),
27973
28026
  /** Per-component log level overrides. Keys are component names (e.g., 'reminders', 'statusline'). */
27974
28027
  components: v4_1.z.record(v4_1.z.string(), LogLevelSchema).optional(),
27975
- /** Log rotation settings. Defaults to 10MB/5 files if not specified. */
28028
+ /** Log rotation settings. Defaults come from core.defaults.yaml (2MB/2 files). */
27976
28029
  rotation: v4_1.z.object({
27977
28030
  maxSizeBytes: v4_1.z.number().min(1),
27978
28031
  maxFiles: v4_1.z.number().min(1)
@@ -28022,7 +28075,10 @@ var require_config2 = __commonJS({
28022
28075
  fallbackProfileId: v4_1.z.string().optional(),
28023
28076
  // OpenRouter-specific provider routing (ignored for other providers)
28024
28077
  providerAllowlist: v4_1.z.array(v4_1.z.string()).optional(),
28025
- providerBlocklist: v4_1.z.array(v4_1.z.string()).optional()
28078
+ providerBlocklist: v4_1.z.array(v4_1.z.string()).optional(),
28079
+ // OpenRouter-specific: toggle the model's reasoning mode (maps to reasoning.enabled).
28080
+ // Ignored for non-openrouter providers.
28081
+ reasoning: v4_1.z.boolean().optional()
28026
28082
  });
28027
28083
  exports2.LlmConfigSchema = v4_1.z.object({
28028
28084
  defaultProfile: v4_1.z.string(),
@@ -28138,7 +28194,7 @@ var require_config2 = __commonJS({
28138
28194
  const parsed = (0, yaml_1.parse)(content);
28139
28195
  return parsed ?? {};
28140
28196
  } catch (err) {
28141
- const message = err instanceof Error ? err.message : String(err);
28197
+ const message = (0, error_utils_js_1.toErrorMessage)(err);
28142
28198
  throw new Error(`Failed to parse YAML at ${filePath}: ${message}`, { cause: err });
28143
28199
  }
28144
28200
  }
@@ -28446,6 +28502,7 @@ var require_config_writer = __commonJS({
28446
28502
  var node_os_1 = require("node:os");
28447
28503
  var node_path_1 = require("node:path");
28448
28504
  var yaml_1 = __importDefault2(require_dist2());
28505
+ var error_utils_js_1 = require_error_utils();
28449
28506
  var config_1 = require_config2();
28450
28507
  var VALID_DOMAINS = /* @__PURE__ */ new Set(["core", "llm", "transcript", "features"]);
28451
28508
  var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
@@ -28572,7 +28629,7 @@ var require_config_writer = __commonJS({
28572
28629
  } catch {
28573
28630
  }
28574
28631
  }
28575
- const message = err instanceof Error ? err.message : String(err);
28632
+ const message = (0, error_utils_js_1.toErrorMessage)(err);
28576
28633
  throw new Error(`Configuration validation failed after setting "${dotPath}": ${message}`, { cause: err });
28577
28634
  }
28578
28635
  return {
@@ -33736,7 +33793,12 @@ var require_log_events = __commonJS({
33736
33793
  "use strict";
33737
33794
  Object.defineProperty(exports2, "__esModule", { value: true });
33738
33795
  exports2.LogEvents = void 0;
33796
+ exports2.setSessionLogWriter = setSessionLogWriter;
33739
33797
  exports2.logEvent = logEvent;
33798
+ var sessionLogWriter = null;
33799
+ function setSessionLogWriter(writer) {
33800
+ sessionLogWriter = writer;
33801
+ }
33740
33802
  function buildContext(ctx) {
33741
33803
  return {
33742
33804
  sessionId: ctx.sessionId,
@@ -34143,10 +34205,219 @@ var require_log_events = __commonJS({
34143
34205
  source: event.source,
34144
34206
  ...meta
34145
34207
  });
34208
+ if (sessionLogWriter && event.context.sessionId) {
34209
+ const logFile = event.source === "cli" ? "sidekick.log" : "sidekickd.log";
34210
+ const line = JSON.stringify({
34211
+ time: event.time,
34212
+ type: event.type,
34213
+ source: event.source,
34214
+ context: event.context,
34215
+ ...meta
34216
+ }) + "\n";
34217
+ sessionLogWriter.write(event.context.sessionId, logFile, line).catch(() => {
34218
+ });
34219
+ }
34146
34220
  }
34147
34221
  }
34148
34222
  });
34149
34223
 
34224
+ // ../sidekick-core/dist/staging-paths.js
34225
+ var require_staging_paths = __commonJS({
34226
+ "../sidekick-core/dist/staging-paths.js"(exports2) {
34227
+ "use strict";
34228
+ Object.defineProperty(exports2, "__esModule", { value: true });
34229
+ exports2.CONSUMED_FILE_PATTERN = void 0;
34230
+ exports2.getStagingRoot = getStagingRoot;
34231
+ exports2.getHookDir = getHookDir;
34232
+ exports2.getReminderPath = getReminderPath;
34233
+ exports2.isValidPathSegment = isValidPathSegment;
34234
+ exports2.validatePathSegment = validatePathSegment;
34235
+ exports2.filterActiveReminderFiles = filterActiveReminderFiles;
34236
+ exports2.createConsumedFilePattern = createConsumedFilePattern;
34237
+ exports2.extractConsumedTimestamp = extractConsumedTimestamp;
34238
+ var node_path_1 = require("node:path");
34239
+ function getStagingRoot(stateDir, sessionId) {
34240
+ return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
34241
+ }
34242
+ function getHookDir(stateDir, sessionId, hookName) {
34243
+ return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
34244
+ }
34245
+ function getReminderPath(stateDir, sessionId, hookName, reminderName) {
34246
+ return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
34247
+ }
34248
+ function isValidPathSegment(s) {
34249
+ if (s === "")
34250
+ return false;
34251
+ if (s === "." || s === "..")
34252
+ return false;
34253
+ if (s.includes("/") || s.includes("\\"))
34254
+ return false;
34255
+ if ((0, node_path_1.basename)(s) !== s)
34256
+ return false;
34257
+ return /^[a-zA-Z0-9._-]+$/.test(s);
34258
+ }
34259
+ function validatePathSegment(segment, name) {
34260
+ if (!isValidPathSegment(segment)) {
34261
+ throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
34262
+ }
34263
+ }
34264
+ exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
34265
+ function filterActiveReminderFiles(files) {
34266
+ return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
34267
+ }
34268
+ function createConsumedFilePattern(reminderName) {
34269
+ return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
34270
+ }
34271
+ function extractConsumedTimestamp(filename, reminderName) {
34272
+ const pattern = createConsumedFilePattern(reminderName);
34273
+ const match = pattern.exec(filename);
34274
+ return match ? parseInt(match[1], 10) : null;
34275
+ }
34276
+ }
34277
+ });
34278
+
34279
+ // ../sidekick-core/dist/session-log-writer.js
34280
+ var require_session_log_writer = __commonJS({
34281
+ "../sidekick-core/dist/session-log-writer.js"(exports2) {
34282
+ "use strict";
34283
+ Object.defineProperty(exports2, "__esModule", { value: true });
34284
+ exports2.SessionLogWriter = void 0;
34285
+ var promises_12 = require("node:fs/promises");
34286
+ var node_path_1 = require("node:path");
34287
+ var node_fs_1 = require("node:fs");
34288
+ var staging_paths_js_1 = require_staging_paths();
34289
+ var SessionLogWriter = class {
34290
+ sessionsDir;
34291
+ maxHandles;
34292
+ idleTimeoutMs;
34293
+ /** Map key: `${sessionId}/${logFile}` */
34294
+ handles = /* @__PURE__ */ new Map();
34295
+ /** Sentinel map to prevent duplicate handle creation on concurrent writes */
34296
+ pendingCreation = /* @__PURE__ */ new Map();
34297
+ constructor(options) {
34298
+ this.sessionsDir = options.sessionsDir;
34299
+ this.maxHandles = options.maxHandles ?? 10;
34300
+ this.idleTimeoutMs = options.idleTimeoutMs ?? 30 * 60 * 1e3;
34301
+ }
34302
+ get handleCount() {
34303
+ return this.handles.size;
34304
+ }
34305
+ /**
34306
+ * Write an NDJSON line to a per-session log file.
34307
+ * Creates the directory and file handle lazily.
34308
+ * Skips if sessionId is empty (daemon lifecycle events before session exists).
34309
+ */
34310
+ async write(sessionId, logFile, line) {
34311
+ if (!sessionId)
34312
+ return;
34313
+ if (!(0, staging_paths_js_1.isValidPathSegment)(sessionId) || !(0, staging_paths_js_1.isValidPathSegment)(logFile))
34314
+ return;
34315
+ const key = `${sessionId}/${logFile}`;
34316
+ const pending = this.pendingCreation.get(key);
34317
+ if (pending) {
34318
+ try {
34319
+ await pending;
34320
+ } catch {
34321
+ }
34322
+ }
34323
+ let entry = this.handles.get(key);
34324
+ if (!entry) {
34325
+ if (this.handles.size >= this.maxHandles) {
34326
+ this.evictLRU();
34327
+ }
34328
+ const creationPromise = this.createHandle(sessionId, logFile);
34329
+ this.pendingCreation.set(key, creationPromise);
34330
+ try {
34331
+ entry = await creationPromise;
34332
+ this.handles.set(key, entry);
34333
+ } finally {
34334
+ this.pendingCreation.delete(key);
34335
+ }
34336
+ }
34337
+ await entry.ready;
34338
+ entry.lastUsed = Date.now();
34339
+ this.resetIdleTimer(key, entry);
34340
+ return new Promise((resolve3, reject) => {
34341
+ entry.stream.write(line, (err) => {
34342
+ if (err) {
34343
+ void this.closeHandle(key);
34344
+ reject(err);
34345
+ } else {
34346
+ resolve3();
34347
+ }
34348
+ });
34349
+ });
34350
+ }
34351
+ async createHandle(sessionId, logFile) {
34352
+ const logDir = (0, node_path_1.join)(this.sessionsDir, sessionId, "logs");
34353
+ await (0, promises_12.mkdir)(logDir, { recursive: true });
34354
+ const filePath = (0, node_path_1.join)(logDir, logFile);
34355
+ const stream = (0, node_fs_1.createWriteStream)(filePath, { flags: "a" });
34356
+ const ready = new Promise((resolve3, reject) => {
34357
+ stream.once("open", () => resolve3());
34358
+ stream.once("error", (err) => {
34359
+ stream.destroy();
34360
+ reject(err);
34361
+ });
34362
+ });
34363
+ return {
34364
+ stream,
34365
+ lastUsed: Date.now(),
34366
+ timer: null,
34367
+ ready
34368
+ };
34369
+ }
34370
+ /** Close all handles for a specific session. */
34371
+ async closeSession(sessionId) {
34372
+ const prefix = `${sessionId}/`;
34373
+ const toClose = [];
34374
+ for (const key of this.handles.keys()) {
34375
+ if (key.startsWith(prefix)) {
34376
+ toClose.push(key);
34377
+ }
34378
+ }
34379
+ await Promise.all(toClose.map((key) => this.closeHandle(key)));
34380
+ }
34381
+ /** Close all open handles. */
34382
+ async closeAll() {
34383
+ const keys = [...this.handles.keys()];
34384
+ await Promise.all(keys.map((key) => this.closeHandle(key)));
34385
+ }
34386
+ async closeHandle(key) {
34387
+ const entry = this.handles.get(key);
34388
+ if (!entry)
34389
+ return;
34390
+ if (entry.timer)
34391
+ clearTimeout(entry.timer);
34392
+ this.handles.delete(key);
34393
+ return new Promise((resolve3) => {
34394
+ entry.stream.end(() => resolve3());
34395
+ });
34396
+ }
34397
+ evictLRU() {
34398
+ let oldestKey = "";
34399
+ let oldestTime = Infinity;
34400
+ for (const [key, entry] of this.handles) {
34401
+ if (entry.lastUsed < oldestTime) {
34402
+ oldestTime = entry.lastUsed;
34403
+ oldestKey = key;
34404
+ }
34405
+ }
34406
+ void this.closeHandle(oldestKey);
34407
+ }
34408
+ resetIdleTimer(key, entry) {
34409
+ if (entry.timer)
34410
+ clearTimeout(entry.timer);
34411
+ entry.timer = setTimeout(() => {
34412
+ void this.closeHandle(key);
34413
+ }, this.idleTimeoutMs);
34414
+ entry.timer.unref();
34415
+ }
34416
+ };
34417
+ exports2.SessionLogWriter = SessionLogWriter;
34418
+ }
34419
+ });
34420
+
34150
34421
  // ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/constants.cjs
34151
34422
  var require_constants2 = __commonJS({
34152
34423
  "../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/constants.cjs"(exports2) {
@@ -45886,7 +46157,7 @@ var require_structured_logging = __commonJS({
45886
46157
  return mod && mod.__esModule ? mod : { "default": mod };
45887
46158
  };
45888
46159
  Object.defineProperty(exports2, "__esModule", { value: true });
45889
- exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.LOG_LEVELS = exports2.logEvent = exports2.LogEvents = void 0;
46160
+ exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.LOG_LEVELS = exports2.SessionLogWriter = exports2.setSessionLogWriter = exports2.logEvent = exports2.LogEvents = void 0;
45890
46161
  exports2.getComponentLogLevel = getComponentLogLevel;
45891
46162
  exports2.createLogManager = createLogManager;
45892
46163
  exports2.createContextLogger = createContextLogger;
@@ -45896,6 +46167,7 @@ var require_structured_logging = __commonJS({
45896
46167
  var node_fs_1 = require("node:fs");
45897
46168
  var node_path_1 = require("node:path");
45898
46169
  var node_stream_1 = require("node:stream");
46170
+ var error_utils_js_1 = require_error_utils();
45899
46171
  var log_events_1 = require_log_events();
45900
46172
  Object.defineProperty(exports2, "LogEvents", { enumerable: true, get: function() {
45901
46173
  return log_events_1.LogEvents;
@@ -45903,6 +46175,13 @@ var require_structured_logging = __commonJS({
45903
46175
  Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
45904
46176
  return log_events_1.logEvent;
45905
46177
  } });
46178
+ Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
46179
+ return log_events_1.setSessionLogWriter;
46180
+ } });
46181
+ var session_log_writer_1 = require_session_log_writer();
46182
+ Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
46183
+ return session_log_writer_1.SessionLogWriter;
46184
+ } });
45906
46185
  exports2.LOG_LEVELS = {
45907
46186
  trace: 10,
45908
46187
  debug: 20,
@@ -45918,8 +46197,8 @@ var require_structured_logging = __commonJS({
45918
46197
  }
45919
46198
  return defaultLevel;
45920
46199
  }
45921
- exports2.DEFAULT_ROTATE_SIZE_BYTES = 10 * 1024 * 1024;
45922
- exports2.DEFAULT_MAX_FILES = 5;
46200
+ exports2.DEFAULT_ROTATE_SIZE_BYTES = 2 * 1024 * 1024;
46201
+ exports2.DEFAULT_MAX_FILES = 2;
45923
46202
  var DEFAULT_REDACT_KEYS = [
45924
46203
  "apiKey",
45925
46204
  "token",
@@ -46260,7 +46539,7 @@ var require_structured_logging = __commonJS({
46260
46539
  upgradeOptions.onUpgradeError(err);
46261
46540
  }
46262
46541
  activeLogger.error("Failed to upgrade to Pino logger", {
46263
- error: err instanceof Error ? err.message : String(err)
46542
+ error: (0, error_utils_js_1.toErrorMessage)(err)
46264
46543
  });
46265
46544
  }
46266
46545
  },
@@ -46276,7 +46555,7 @@ var require_structured_logging = __commonJS({
46276
46555
  };
46277
46556
  const rejectionHandler = (reason) => {
46278
46557
  logger.fatal("Unhandled promise rejection", {
46279
- reason: reason instanceof Error ? reason.message : String(reason)
46558
+ reason: (0, error_utils_js_1.toErrorMessage)(reason)
46280
46559
  });
46281
46560
  };
46282
46561
  process.on("uncaughtException", uncaughtHandler);
@@ -46369,13 +46648,11 @@ var require_daemon_client2 = __commonJS({
46369
46648
  var client_js_1 = require_client();
46370
46649
  var transport_js_1 = require_transport();
46371
46650
  var sandbox_js_1 = require_sandbox();
46651
+ var error_utils_js_1 = require_error_utils();
46372
46652
  var LOCK_TIMEOUT_MS = 1e4;
46373
46653
  var LOCK_RETRY_INTERVAL_MS = 100;
46374
46654
  var LOCK_STALE_THRESHOLD_MS = 3e4;
46375
46655
  var CLIENT_VERSION = require_package3().version;
46376
- function toErrorMsg(err) {
46377
- return err instanceof Error ? err.message : String(err);
46378
- }
46379
46656
  var DaemonClient = class {
46380
46657
  projectDir;
46381
46658
  logger;
@@ -46741,7 +47018,7 @@ var require_daemon_client2 = __commonJS({
46741
47018
  } catch (err) {
46742
47019
  logger.debug("Graceful stop failed, falling back to SIGKILL", {
46743
47020
  pid: info.pid,
46744
- error: toErrorMsg(err)
47021
+ error: (0, error_utils_js_1.toErrorMessage)(err)
46745
47022
  });
46746
47023
  }
46747
47024
  }
@@ -46750,7 +47027,7 @@ var require_daemon_client2 = __commonJS({
46750
47027
  logger.info("Killed daemon", { pid: info.pid, projectDir: info.projectDir });
46751
47028
  results.push({ projectDir: info.projectDir, pid: info.pid, killed: true });
46752
47029
  } catch (err) {
46753
- const msg = toErrorMsg(err);
47030
+ const msg = (0, error_utils_js_1.toErrorMessage)(err);
46754
47031
  logger.warn("Failed to kill daemon", { pid: info.pid, error: msg });
46755
47032
  results.push({ projectDir: info.projectDir, pid: info.pid, killed: false, error: msg });
46756
47033
  }
@@ -46762,7 +47039,7 @@ var require_daemon_client2 = __commonJS({
46762
47039
  });
46763
47040
  }
46764
47041
  } catch (err) {
46765
- logger.warn("Invalid PID file, removing", { pidFile, error: toErrorMsg(err) });
47042
+ logger.warn("Invalid PID file, removing", { pidFile, error: (0, error_utils_js_1.toErrorMessage)(err) });
46766
47043
  await promises_12.default.unlink(pidPath).catch(() => {
46767
47044
  });
46768
47045
  }
@@ -46783,7 +47060,7 @@ var require_daemon_client2 = __commonJS({
46783
47060
  });
46784
47061
  } catch (err) {
46785
47062
  logger.warn("Failed to run ps \u2014 cannot detect zombie daemons", {
46786
- error: toErrorMsg(err)
47063
+ error: (0, error_utils_js_1.toErrorMessage)(err)
46787
47064
  });
46788
47065
  return [];
46789
47066
  }
@@ -46844,7 +47121,7 @@ var require_daemon_client2 = __commonJS({
46844
47121
  logger.info("Killed zombie daemon", { pid: zombie.pid, command: zombie.command });
46845
47122
  results.push({ projectDir: "unknown", pid: zombie.pid, killed: true });
46846
47123
  } catch (err) {
46847
- const msg = toErrorMsg(err);
47124
+ const msg = (0, error_utils_js_1.toErrorMessage)(err);
46848
47125
  logger.warn("Failed to kill zombie daemon", { pid: zombie.pid, error: msg });
46849
47126
  results.push({ projectDir: "unknown", pid: zombie.pid, killed: false, error: msg });
46850
47127
  }
@@ -46896,60 +47173,94 @@ var require_gitignore = __commonJS({
46896
47173
  };
46897
47174
  })();
46898
47175
  Object.defineProperty(exports2, "__esModule", { value: true });
46899
- exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = void 0;
47176
+ exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_GITIGNORE_HEADER = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = void 0;
46900
47177
  exports2.installGitignoreSection = installGitignoreSection;
46901
- exports2.removeGitignoreSection = removeGitignoreSection;
46902
47178
  exports2.detectGitignoreStatus = detectGitignoreStatus;
47179
+ exports2.removeGitignoreSection = removeGitignoreSection;
47180
+ exports2.detectLegacyGitignoreSection = detectLegacyGitignoreSection;
47181
+ exports2.removeLegacyGitignoreSection = removeLegacyGitignoreSection;
46903
47182
  var fs = __importStar(require("node:fs/promises"));
46904
47183
  var path = __importStar(require("node:path"));
46905
47184
  exports2.SIDEKICK_SECTION_START = "# >>> sidekick";
46906
47185
  exports2.SIDEKICK_SECTION_END = "# <<< sidekick";
47186
+ exports2.SIDEKICK_GITIGNORE_HEADER = "# Sidekick \u2014 managed file, do not edit manually";
46907
47187
  exports2.GITIGNORE_ENTRIES = [
46908
- ".sidekick/logs/",
46909
- ".sidekick/sessions/",
46910
- ".sidekick/state/",
46911
- ".sidekick/setup-status.json",
46912
- ".sidekick/.env",
46913
- ".sidekick/.env.local",
46914
- ".sidekick/sidekick*.pid",
46915
- ".sidekick/sidekick*.token",
46916
- ".sidekick/*.local.yaml"
47188
+ "logs/",
47189
+ "sessions/",
47190
+ "state/",
47191
+ "setup-status.json",
47192
+ ".env",
47193
+ ".env.local",
47194
+ "sidekick*.pid",
47195
+ "sidekick*.token",
47196
+ "*.local.yaml"
46917
47197
  ];
46918
47198
  async function installGitignoreSection(projectDir) {
46919
- const gitignorePath = path.join(projectDir, ".gitignore");
46920
- let content = "";
47199
+ let status;
46921
47200
  try {
46922
- content = await fs.readFile(gitignorePath, "utf-8");
47201
+ status = await detectGitignoreStatus(projectDir);
46923
47202
  } catch (err) {
46924
- if (err.code !== "ENOENT") {
46925
- return { status: "error", error: `Failed to read .gitignore: ${err.message}` };
46926
- }
47203
+ return { status: "error", error: `Failed to check gitignore status: ${err.message}` };
46927
47204
  }
46928
- const status = await detectGitignoreStatus(projectDir);
46929
47205
  if (status === "installed") {
46930
47206
  return { status: "already-installed" };
46931
47207
  }
46932
- if (status === "incomplete") {
46933
- await removeGitignoreSection(projectDir);
46934
- try {
46935
- content = await fs.readFile(gitignorePath, "utf-8");
46936
- } catch {
46937
- content = "";
46938
- }
47208
+ const sidekickDir = path.join(projectDir, ".sidekick");
47209
+ try {
47210
+ await fs.mkdir(sidekickDir, { recursive: true });
47211
+ } catch (err) {
47212
+ return { status: "error", error: `Failed to create .sidekick directory: ${err.message}` };
46939
47213
  }
46940
- const section = ["", exports2.SIDEKICK_SECTION_START, ...exports2.GITIGNORE_ENTRIES, exports2.SIDEKICK_SECTION_END].join("\n");
46941
- const newContent = content.trimEnd() + section + "\n";
47214
+ const content = [exports2.SIDEKICK_GITIGNORE_HEADER, ...exports2.GITIGNORE_ENTRIES].join("\n") + "\n";
46942
47215
  try {
46943
- await fs.writeFile(gitignorePath, newContent);
47216
+ await fs.writeFile(path.join(sidekickDir, ".gitignore"), content);
46944
47217
  return { status: "installed", entriesAdded: exports2.GITIGNORE_ENTRIES };
46945
47218
  } catch (err) {
46946
- return { status: "error", error: `Failed to write .gitignore: ${err.message}` };
47219
+ return { status: "error", error: `Failed to write .sidekick/.gitignore: ${err.message}` };
46947
47220
  }
46948
47221
  }
47222
+ async function detectGitignoreStatus(projectDir) {
47223
+ const sidekickGitignorePath = path.join(projectDir, ".sidekick", ".gitignore");
47224
+ try {
47225
+ const content = await fs.readFile(sidekickGitignorePath, "utf-8");
47226
+ const missingEntries = exports2.GITIGNORE_ENTRIES.filter((entry) => !content.includes(entry));
47227
+ return missingEntries.length === 0 ? "installed" : "incomplete";
47228
+ } catch (err) {
47229
+ if (err.code !== "ENOENT") {
47230
+ throw err;
47231
+ }
47232
+ }
47233
+ const hasLegacy = await detectLegacyGitignoreSection(projectDir);
47234
+ return hasLegacy ? "legacy" : "missing";
47235
+ }
46949
47236
  async function removeGitignoreSection(projectDir) {
46950
- const gitignorePath = path.join(projectDir, ".gitignore");
47237
+ let removed = false;
46951
47238
  try {
46952
- const content = await fs.readFile(gitignorePath, "utf-8");
47239
+ await fs.unlink(path.join(projectDir, ".sidekick", ".gitignore"));
47240
+ removed = true;
47241
+ } catch (err) {
47242
+ if (err.code !== "ENOENT") {
47243
+ throw err;
47244
+ }
47245
+ }
47246
+ const legacyRemoved = await removeLegacyGitignoreSection(projectDir);
47247
+ return removed || legacyRemoved;
47248
+ }
47249
+ async function detectLegacyGitignoreSection(projectDir) {
47250
+ try {
47251
+ const content = await fs.readFile(path.join(projectDir, ".gitignore"), "utf-8");
47252
+ return content.includes(exports2.SIDEKICK_SECTION_START);
47253
+ } catch (err) {
47254
+ if (err.code === "ENOENT") {
47255
+ return false;
47256
+ }
47257
+ throw err;
47258
+ }
47259
+ }
47260
+ async function removeLegacyGitignoreSection(projectDir) {
47261
+ const rootGitignorePath = path.join(projectDir, ".gitignore");
47262
+ try {
47263
+ const content = await fs.readFile(rootGitignorePath, "utf-8");
46953
47264
  const startIdx = content.indexOf(exports2.SIDEKICK_SECTION_START);
46954
47265
  const endIdx = content.indexOf(exports2.SIDEKICK_SECTION_END);
46955
47266
  if (startIdx === -1 || endIdx === -1 || endIdx < startIdx) {
@@ -46961,37 +47272,13 @@ var require_gitignore = __commonJS({
46961
47272
  const before = content.slice(0, lineStartIdx).trimEnd();
46962
47273
  const after = content.slice(actualEndIdx).trimStart();
46963
47274
  const newContent = before + (after ? "\n" + after : "") + "\n";
46964
- await fs.writeFile(gitignorePath, newContent);
47275
+ await fs.writeFile(rootGitignorePath, newContent);
46965
47276
  return true;
46966
- } catch {
46967
- return false;
46968
- }
46969
- }
46970
- async function detectGitignoreStatus(projectDir) {
46971
- const gitignorePath = path.join(projectDir, ".gitignore");
46972
- try {
46973
- const content = await fs.readFile(gitignorePath, "utf-8");
46974
- const hasStart = content.includes(exports2.SIDEKICK_SECTION_START);
46975
- const hasEnd = content.includes(exports2.SIDEKICK_SECTION_END);
46976
- if (!hasStart && !hasEnd) {
46977
- return "missing";
46978
- }
46979
- if (!hasStart || !hasEnd) {
46980
- return "incomplete";
46981
- }
46982
- const startIdx = content.indexOf(exports2.SIDEKICK_SECTION_START);
46983
- const endIdx = content.indexOf(exports2.SIDEKICK_SECTION_END);
46984
- if (endIdx <= startIdx) {
46985
- return "incomplete";
46986
- }
46987
- const sectionContent = content.slice(startIdx, endIdx + exports2.SIDEKICK_SECTION_END.length);
46988
- const missingEntries = exports2.GITIGNORE_ENTRIES.filter((entry) => !sectionContent.includes(entry));
46989
- if (missingEntries.length > 0) {
46990
- return "incomplete";
47277
+ } catch (err) {
47278
+ if (err.code === "ENOENT") {
47279
+ return false;
46991
47280
  }
46992
- return "installed";
46993
- } catch {
46994
- return "missing";
47281
+ throw err;
46995
47282
  }
46996
47283
  }
46997
47284
  }
@@ -47002,7 +47289,7 @@ var require_errors4 = __commonJS({
47002
47289
  "../shared-providers/dist/errors.js"(exports2) {
47003
47290
  "use strict";
47004
47291
  Object.defineProperty(exports2, "__esModule", { value: true });
47005
- exports2.TimeoutError = exports2.AuthError = exports2.RateLimitError = exports2.ProviderError = void 0;
47292
+ exports2.MalformedResponseError = exports2.TimeoutError = exports2.AuthError = exports2.RateLimitError = exports2.ProviderError = void 0;
47006
47293
  var ProviderError = class _ProviderError extends Error {
47007
47294
  provider;
47008
47295
  retryable;
@@ -47043,6 +47330,18 @@ var require_errors4 = __commonJS({
47043
47330
  }
47044
47331
  };
47045
47332
  exports2.TimeoutError = TimeoutError;
47333
+ var MalformedResponseError = class _MalformedResponseError extends ProviderError {
47334
+ code;
47335
+ providerMessage;
47336
+ constructor(provider, code, providerMessage, cause) {
47337
+ super(`Malformed response from ${provider}: ${code ?? "unknown"} - ${providerMessage ?? "no message"}`, provider, false, cause);
47338
+ this.name = "MalformedResponseError";
47339
+ this.code = code;
47340
+ this.providerMessage = providerMessage;
47341
+ Object.setPrototypeOf(this, _MalformedResponseError.prototype);
47342
+ }
47343
+ };
47344
+ exports2.MalformedResponseError = MalformedResponseError;
47046
47345
  }
47047
47346
  });
47048
47347
 
@@ -56021,6 +56320,7 @@ var require_base = __commonJS({
56021
56320
  model: response.model,
56022
56321
  durationMs,
56023
56322
  usage: response.usage,
56323
+ finishReason: response.finishReason,
56024
56324
  status: response.rawResponse.status,
56025
56325
  contentLength: response.content.length
56026
56326
  });
@@ -56068,6 +56368,7 @@ var require_openai_native = __commonJS({
56068
56368
  maxTokens;
56069
56369
  providerAllowlist;
56070
56370
  providerBlocklist;
56371
+ reasoning;
56071
56372
  constructor(config, logger) {
56072
56373
  super(logger);
56073
56374
  this.id = config.baseURL?.includes("openrouter") ? "openrouter" : "openai";
@@ -56076,6 +56377,7 @@ var require_openai_native = __commonJS({
56076
56377
  this.maxTokens = config.maxTokens;
56077
56378
  this.providerAllowlist = config.providerAllowlist;
56078
56379
  this.providerBlocklist = config.providerBlocklist;
56380
+ this.reasoning = config.reasoning;
56079
56381
  this.client = new openai_1.default({
56080
56382
  apiKey: config.apiKey,
56081
56383
  baseURL: config.baseURL,
@@ -56091,6 +56393,7 @@ var require_openai_native = __commonJS({
56091
56393
  maxTokens: this.maxTokens,
56092
56394
  providerAllowlist: this.providerAllowlist,
56093
56395
  providerBlocklist: this.providerBlocklist,
56396
+ reasoning: this.reasoning,
56094
56397
  apiKey: this.redactApiKey(config.apiKey)
56095
56398
  });
56096
56399
  }
@@ -56108,6 +56411,7 @@ var require_openai_native = __commonJS({
56108
56411
  }
56109
56412
  } : void 0;
56110
56413
  const providerRouting = this.buildProviderRouting();
56414
+ const reasoningParam = this.buildReasoningParam();
56111
56415
  const completion = await this.client.chat.completions.create({
56112
56416
  model: request.model ?? this.defaultModel,
56113
56417
  messages,
@@ -56115,8 +56419,13 @@ var require_openai_native = __commonJS({
56115
56419
  max_tokens: this.maxTokens,
56116
56420
  response_format: responseFormat,
56117
56421
  ...providerRouting,
56422
+ ...reasoningParam,
56118
56423
  ...request.additionalParams
56119
56424
  });
56425
+ if (!completion.choices || completion.choices.length === 0) {
56426
+ const errorPayload = completion.error;
56427
+ throw new errors_1.MalformedResponseError(this.id, errorPayload?.code, errorPayload?.message);
56428
+ }
56120
56429
  const response = {
56121
56430
  content: completion.choices[0]?.message?.content ?? "",
56122
56431
  model: completion.model,
@@ -56124,6 +56433,7 @@ var require_openai_native = __commonJS({
56124
56433
  inputTokens: completion.usage.prompt_tokens,
56125
56434
  outputTokens: completion.usage.completion_tokens
56126
56435
  } : void 0,
56436
+ finishReason: completion.choices[0]?.finish_reason ?? void 0,
56127
56437
  rawResponse: {
56128
56438
  status: 200,
56129
56439
  body: JSON.stringify(completion)
@@ -56159,7 +56469,25 @@ var require_openai_native = __commonJS({
56159
56469
  }
56160
56470
  return { provider: providerObj };
56161
56471
  }
56472
+ /**
56473
+ * Build OpenRouter reasoning param object.
56474
+ * Returns empty object if reasoning is unset or provider is not OpenRouter.
56475
+ * Maps `reasoning?: boolean` to OpenRouter's `reasoning: { enabled: <bool> }`.
56476
+ * @see https://openrouter.ai/docs/use-cases/reasoning-tokens
56477
+ */
56478
+ buildReasoningParam() {
56479
+ if (this.id !== "openrouter") {
56480
+ return {};
56481
+ }
56482
+ if (this.reasoning === void 0) {
56483
+ return {};
56484
+ }
56485
+ return { reasoning: { enabled: this.reasoning } };
56486
+ }
56162
56487
  mapError(error) {
56488
+ if (error instanceof errors_1.ProviderError) {
56489
+ return error;
56490
+ }
56163
56491
  if (error instanceof openai_1.default.APIError) {
56164
56492
  if (error.status === 401 || error.status === 403) {
56165
56493
  return new errors_1.AuthError(this.id, error);
@@ -56253,7 +56581,13 @@ var require_claude_cli_spawn = __commonJS({
56253
56581
  });
56254
56582
  const child = (0, node_child_process_1.spawn)(cliPath, args, {
56255
56583
  cwd,
56256
- stdio: ["pipe", "pipe", "pipe"]
56584
+ stdio: ["pipe", "pipe", "pipe"],
56585
+ // Recursion guard: Sidekick's own Claude Code hooks fire inside any
56586
+ // `claude -p` subprocess we spawn. Without this flag, the subprocess
56587
+ // hook handler would dispatch to the daemon, trigger another LLM call,
56588
+ // spawn another subprocess, and so on. handleHookCommand short-circuits
56589
+ // when SIDEKICK_SUBPROCESS=1 is set. See packages/sidekick-cli/src/commands/hook.ts.
56590
+ env: { ...process.env, SIDEKICK_SUBPROCESS: "1" }
56257
56591
  });
56258
56592
  let stdout = "";
56259
56593
  let stderr = "";
@@ -56315,6 +56649,31 @@ var require_claude_cli_spawn = __commonJS({
56315
56649
  }
56316
56650
  });
56317
56651
 
56652
+ // ../shared-providers/dist/providers/anthropic-stop-reason.js
56653
+ var require_anthropic_stop_reason = __commonJS({
56654
+ "../shared-providers/dist/providers/anthropic-stop-reason.js"(exports2) {
56655
+ "use strict";
56656
+ Object.defineProperty(exports2, "__esModule", { value: true });
56657
+ exports2.mapAnthropicStopReason = mapAnthropicStopReason;
56658
+ function mapAnthropicStopReason(stopReason) {
56659
+ if (!stopReason)
56660
+ return void 0;
56661
+ switch (stopReason) {
56662
+ case "end_turn":
56663
+ return "stop";
56664
+ case "max_tokens":
56665
+ return "length";
56666
+ case "stop_sequence":
56667
+ return "stop";
56668
+ case "tool_use":
56669
+ return "tool_calls";
56670
+ default:
56671
+ return stopReason;
56672
+ }
56673
+ }
56674
+ }
56675
+ });
56676
+
56318
56677
  // ../shared-providers/dist/providers/anthropic-cli.js
56319
56678
  var require_anthropic_cli = __commonJS({
56320
56679
  "../shared-providers/dist/providers/anthropic-cli.js"(exports2) {
@@ -56323,6 +56682,7 @@ var require_anthropic_cli = __commonJS({
56323
56682
  exports2.AnthropicCliProvider = void 0;
56324
56683
  var base_1 = require_base();
56325
56684
  var claude_cli_spawn_1 = require_claude_cli_spawn();
56685
+ var anthropic_stop_reason_1 = require_anthropic_stop_reason();
56326
56686
  var AnthropicCliProvider = class extends base_1.AbstractProvider {
56327
56687
  id = "claude-cli";
56328
56688
  defaultModel;
@@ -56384,6 +56744,7 @@ var require_anthropic_cli = __commonJS({
56384
56744
  inputTokens: parsed.usage.input_tokens ?? 0,
56385
56745
  outputTokens: parsed.usage.output_tokens ?? 0
56386
56746
  } : void 0,
56747
+ finishReason: (0, anthropic_stop_reason_1.mapAnthropicStopReason)(parsed.stop_reason),
56387
56748
  rawResponse: {
56388
56749
  status: 200,
56389
56750
  body: stdout
@@ -56655,6 +57016,7 @@ var require_openai_emulator = __commonJS({
56655
57016
  inputTokens,
56656
57017
  outputTokens
56657
57018
  },
57019
+ finishReason: "stop",
56658
57020
  rawResponse: {
56659
57021
  status: 200,
56660
57022
  body: JSON.stringify(rawBody)
@@ -56709,6 +57071,7 @@ var require_openrouter_emulator = __commonJS({
56709
57071
  inputTokens,
56710
57072
  outputTokens
56711
57073
  },
57074
+ finishReason: "stop",
56712
57075
  rawResponse: {
56713
57076
  status: 200,
56714
57077
  body: JSON.stringify(rawBody)
@@ -56729,6 +57092,7 @@ var require_claude_cli_emulator = __commonJS({
56729
57092
  var node_child_process_1 = require("node:child_process");
56730
57093
  var node_path_1 = require("node:path");
56731
57094
  var base_1 = require_base();
57095
+ var anthropic_stop_reason_1 = require_anthropic_stop_reason();
56732
57096
  var EMULATOR_SCRIPT = `#!/bin/bash
56733
57097
  # Claude CLI Emulator Script
56734
57098
  STATE_FILE="\${SIDEKICK_EMULATOR_STATE_PATH:-.sidekick/emulator-state/call-counts.json}"
@@ -56816,6 +57180,7 @@ echo "{\\"content\\":\\"\${CONTENT}\\",\\"message\\":\\"\${CONTENT}\\",\\"model\
56816
57180
  inputTokens,
56817
57181
  outputTokens
56818
57182
  },
57183
+ finishReason: (0, anthropic_stop_reason_1.mapAnthropicStopReason)(parsed.stop_reason),
56819
57184
  rawResponse: {
56820
57185
  status: 0,
56821
57186
  // Exit code
@@ -56952,7 +57317,8 @@ var require_factory = __commonJS({
56952
57317
  temperature: this.config.temperature,
56953
57318
  maxTokens: this.config.maxTokens,
56954
57319
  providerAllowlist: this.config.providerAllowlist,
56955
- providerBlocklist: this.config.providerBlocklist
57320
+ providerBlocklist: this.config.providerBlocklist,
57321
+ reasoning: this.config.reasoning
56956
57322
  };
56957
57323
  return new openai_native_1.OpenAINativeProvider(openrouterConfig, this.logger);
56958
57324
  }
@@ -57129,7 +57495,9 @@ var require_profile_factory = __commonJS({
57129
57495
  maxTokens: profile.maxTokens,
57130
57496
  // OpenRouter-specific provider routing
57131
57497
  providerAllowlist: profile.providerAllowlist ? [...profile.providerAllowlist] : void 0,
57132
- providerBlocklist: profile.providerBlocklist ? [...profile.providerBlocklist] : void 0
57498
+ providerBlocklist: profile.providerBlocklist ? [...profile.providerBlocklist] : void 0,
57499
+ // OpenRouter-specific reasoning toggle
57500
+ reasoning: profile.reasoning
57133
57501
  }, this.logger);
57134
57502
  return factory.create();
57135
57503
  }
@@ -57184,7 +57552,7 @@ var require_dist3 = __commonJS({
57184
57552
  "../shared-providers/dist/index.js"(exports2) {
57185
57553
  "use strict";
57186
57554
  Object.defineProperty(exports2, "__esModule", { value: true });
57187
- exports2.spawnClaudeCli = exports2.ClaudeCliEmulator = exports2.OpenRouterEmulator = exports2.OpenAIEmulator = exports2.EmulatorStateManager = exports2.AbstractEmulator = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.AbstractProvider = exports2.AnthropicCliProvider = exports2.OpenAINativeProvider = exports2.FallbackProvider = exports2.ProfileProviderFactory = exports2.ProviderFactory = exports2.TimeoutError = exports2.AuthError = exports2.RateLimitError = exports2.ProviderError = void 0;
57555
+ exports2.spawnClaudeCli = exports2.ClaudeCliEmulator = exports2.OpenRouterEmulator = exports2.OpenAIEmulator = exports2.EmulatorStateManager = exports2.AbstractEmulator = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.AbstractProvider = exports2.AnthropicCliProvider = exports2.OpenAINativeProvider = exports2.FallbackProvider = exports2.ProfileProviderFactory = exports2.ProviderFactory = exports2.MalformedResponseError = exports2.TimeoutError = exports2.AuthError = exports2.RateLimitError = exports2.ProviderError = void 0;
57188
57556
  var errors_1 = require_errors4();
57189
57557
  Object.defineProperty(exports2, "ProviderError", { enumerable: true, get: function() {
57190
57558
  return errors_1.ProviderError;
@@ -57198,6 +57566,9 @@ var require_dist3 = __commonJS({
57198
57566
  Object.defineProperty(exports2, "TimeoutError", { enumerable: true, get: function() {
57199
57567
  return errors_1.TimeoutError;
57200
57568
  } });
57569
+ Object.defineProperty(exports2, "MalformedResponseError", { enumerable: true, get: function() {
57570
+ return errors_1.MalformedResponseError;
57571
+ } });
57201
57572
  var factory_1 = require_factory();
57202
57573
  Object.defineProperty(exports2, "ProviderFactory", { enumerable: true, get: function() {
57203
57574
  return factory_1.ProviderFactory;
@@ -57487,6 +57858,7 @@ var require_plugin_detector = __commonJS({
57487
57858
  var crypto2 = __importStar(require("node:crypto"));
57488
57859
  var node_child_process_1 = require("node:child_process");
57489
57860
  var api_key_detector_js_1 = require_api_key_detector();
57861
+ var error_utils_js_1 = require_error_utils();
57490
57862
  function isSidekickStatuslineCommand(command) {
57491
57863
  return command?.toLowerCase().includes("sidekick") ?? false;
57492
57864
  }
@@ -57616,7 +57988,7 @@ var require_plugin_detector = __commonJS({
57616
57988
  return result;
57617
57989
  } catch (err) {
57618
57990
  logger?.warn("Failed to parse plugin list JSON", {
57619
- error: err instanceof Error ? err.message : String(err)
57991
+ error: (0, error_utils_js_1.toErrorMessage)(err)
57620
57992
  });
57621
57993
  logger?.info("Plugin detection completed", { result: "error" });
57622
57994
  return "error";
@@ -57820,7 +58192,16 @@ var require_doctor_engine = __commonJS({
57820
58192
  const expectedUserStatus = (0, api_key_detector_js_1.buildUserApiKeyStatus)(detection);
57821
58193
  const currentUserEntry = currentUserStatus.apiKeys[keyName];
57822
58194
  const currentStatus = typeof currentUserEntry === "object" ? currentUserEntry.status : currentUserEntry ?? "missing";
57823
- if (currentStatus !== "not-required" && (0, api_key_detector_js_1.toScopeStatus)(currentStatus) !== (0, api_key_detector_js_1.toScopeStatus)(expectedUserStatus.status)) {
58195
+ if (currentStatus === "not-required")
58196
+ continue;
58197
+ const isLegacyString = typeof currentUserEntry === "string";
58198
+ if (isLegacyString) {
58199
+ updatedUserApiKeys[keyName] = expectedUserStatus;
58200
+ userNeedsUpdate = true;
58201
+ } else if ((0, api_key_detector_js_1.toScopeStatus)(currentStatus) !== (0, api_key_detector_js_1.toScopeStatus)(expectedUserStatus.status)) {
58202
+ updatedUserApiKeys[keyName] = expectedUserStatus;
58203
+ userNeedsUpdate = true;
58204
+ } else if (typeof currentUserEntry === "object" && (currentUserEntry.used !== expectedUserStatus.used || JSON.stringify(currentUserEntry.scopes) !== JSON.stringify(expectedUserStatus.scopes))) {
57824
58205
  updatedUserApiKeys[keyName] = expectedUserStatus;
57825
58206
  userNeedsUpdate = true;
57826
58207
  }
@@ -57895,7 +58276,7 @@ var require_setup_status_service = __commonJS({
57895
58276
  };
57896
58277
  })();
57897
58278
  Object.defineProperty(exports2, "__esModule", { value: true });
57898
- exports2.SetupStatusService = exports2.LEGACY_USER_STATUS_FILENAME = exports2.PROJECT_STATUS_FILENAME = exports2.USER_STATUS_FILENAME = void 0;
58279
+ exports2.SetupStatusService = exports2.PROJECT_STATUS_FILENAME = exports2.USER_STATUS_FILENAME = void 0;
57899
58280
  exports2.createSetupStatusService = createSetupStatusService;
57900
58281
  var fs = __importStar(require("node:fs/promises"));
57901
58282
  var path = __importStar(require("node:path"));
@@ -57907,7 +58288,6 @@ var require_setup_status_service = __commonJS({
57907
58288
  var doctor_engine_js_1 = require_doctor_engine();
57908
58289
  exports2.USER_STATUS_FILENAME = "user-setup-status.json";
57909
58290
  exports2.PROJECT_STATUS_FILENAME = "setup-status.json";
57910
- exports2.LEGACY_USER_STATUS_FILENAME = exports2.PROJECT_STATUS_FILENAME;
57911
58291
  var SetupStatusService = class {
57912
58292
  projectDir;
57913
58293
  homeDir;
@@ -57921,10 +58301,6 @@ var require_setup_status_service = __commonJS({
57921
58301
  get userStatusPath() {
57922
58302
  return path.join(this.homeDir, ".sidekick", exports2.USER_STATUS_FILENAME);
57923
58303
  }
57924
- /** Legacy path for migration: old user-scope file that collided with project-scope */
57925
- get legacyUserStatusPath() {
57926
- return path.join(this.homeDir, ".sidekick", exports2.LEGACY_USER_STATUS_FILENAME);
57927
- }
57928
58304
  get projectStatusPath() {
57929
58305
  return path.join(this.projectDir, ".sidekick", exports2.PROJECT_STATUS_FILENAME);
57930
58306
  }
@@ -57958,7 +58334,7 @@ var require_setup_status_service = __commonJS({
57958
58334
  return parsed.data;
57959
58335
  } catch (err) {
57960
58336
  if (err.code === "ENOENT") {
57961
- return this.migrateFromLegacyUserStatus();
58337
+ return null;
57962
58338
  }
57963
58339
  if (err instanceof SyntaxError) {
57964
58340
  this.logger?.warn(`Corrupt ${exports2.USER_STATUS_FILENAME}, treating as missing`, {
@@ -57970,54 +58346,6 @@ var require_setup_status_service = __commonJS({
57970
58346
  throw err;
57971
58347
  }
57972
58348
  }
57973
- /**
57974
- * Migration: read user status from the legacy `setup-status.json` location,
57975
- * write it to the new `user-setup-status.json`, and remove the old file.
57976
- *
57977
- * Only migrates if the legacy file contains valid UserSetupStatus data
57978
- * (not project-format data that may have been written by the collision bug).
57979
- */
57980
- async migrateFromLegacyUserStatus() {
57981
- try {
57982
- const legacyContent = await fs.readFile(this.legacyUserStatusPath, "utf-8");
57983
- const parsed = types_1.UserSetupStatusSchema.safeParse(JSON.parse(legacyContent));
57984
- if (!parsed.success) {
57985
- this.logger?.debug("Legacy user status file exists but is not valid user format, skipping migration", {
57986
- path: this.legacyUserStatusPath
57987
- });
57988
- return null;
57989
- }
57990
- this.logger?.info("Migrating user status from legacy location", {
57991
- from: this.legacyUserStatusPath,
57992
- to: this.userStatusPath
57993
- });
57994
- await this.writeUserStatus(parsed.data);
57995
- try {
57996
- await fs.unlink(this.legacyUserStatusPath);
57997
- } catch (unlinkErr) {
57998
- if (unlinkErr.code !== "ENOENT") {
57999
- this.logger?.warn("Migrated user status but failed to remove legacy file", {
58000
- path: this.legacyUserStatusPath,
58001
- error: unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)
58002
- });
58003
- }
58004
- }
58005
- this.logger?.info("Legacy user status migration complete");
58006
- return parsed.data;
58007
- } catch (err) {
58008
- if (err.code === "ENOENT") {
58009
- return null;
58010
- }
58011
- if (err instanceof SyntaxError) {
58012
- this.logger?.warn(`Corrupt legacy ${exports2.LEGACY_USER_STATUS_FILENAME}, treating as missing`, {
58013
- path: this.legacyUserStatusPath,
58014
- error: err.message
58015
- });
58016
- return null;
58017
- }
58018
- throw err;
58019
- }
58020
- }
58021
58349
  async getProjectStatus() {
58022
58350
  if (path.resolve(this.projectDir) === path.resolve(this.homeDir)) {
58023
58351
  this.logger?.debug("Skipping project status read: projectDir is the home directory", {
@@ -58385,61 +58713,6 @@ var require_errors6 = __commonJS({
58385
58713
  }
58386
58714
  });
58387
58715
 
58388
- // ../sidekick-core/dist/staging-paths.js
58389
- var require_staging_paths = __commonJS({
58390
- "../sidekick-core/dist/staging-paths.js"(exports2) {
58391
- "use strict";
58392
- Object.defineProperty(exports2, "__esModule", { value: true });
58393
- exports2.CONSUMED_FILE_PATTERN = void 0;
58394
- exports2.getStagingRoot = getStagingRoot;
58395
- exports2.getHookDir = getHookDir;
58396
- exports2.getReminderPath = getReminderPath;
58397
- exports2.isValidPathSegment = isValidPathSegment;
58398
- exports2.validatePathSegment = validatePathSegment;
58399
- exports2.filterActiveReminderFiles = filterActiveReminderFiles;
58400
- exports2.createConsumedFilePattern = createConsumedFilePattern;
58401
- exports2.extractConsumedTimestamp = extractConsumedTimestamp;
58402
- var node_path_1 = require("node:path");
58403
- function getStagingRoot(stateDir, sessionId) {
58404
- return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
58405
- }
58406
- function getHookDir(stateDir, sessionId, hookName) {
58407
- return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
58408
- }
58409
- function getReminderPath(stateDir, sessionId, hookName, reminderName) {
58410
- return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
58411
- }
58412
- function isValidPathSegment(s) {
58413
- if (s === "")
58414
- return false;
58415
- if (s === "." || s === "..")
58416
- return false;
58417
- if (s.includes("/") || s.includes("\\"))
58418
- return false;
58419
- if ((0, node_path_1.basename)(s) !== s)
58420
- return false;
58421
- return /^[a-zA-Z0-9._-]+$/.test(s);
58422
- }
58423
- function validatePathSegment(segment, name) {
58424
- if (!isValidPathSegment(segment)) {
58425
- throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
58426
- }
58427
- }
58428
- exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
58429
- function filterActiveReminderFiles(files) {
58430
- return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
58431
- }
58432
- function createConsumedFilePattern(reminderName) {
58433
- return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
58434
- }
58435
- function extractConsumedTimestamp(filename, reminderName) {
58436
- const pattern = createConsumedFilePattern(reminderName);
58437
- const match = pattern.exec(filename);
58438
- return match ? parseInt(match[1], 10) : null;
58439
- }
58440
- }
58441
- });
58442
-
58443
58716
  // ../sidekick-core/dist/staging-service.js
58444
58717
  var require_staging_service = __commonJS({
58445
58718
  "../sidekick-core/dist/staging-service.js"(exports2) {
@@ -58453,6 +58726,7 @@ var require_staging_service = __commonJS({
58453
58726
  var structured_logging_1 = require_structured_logging();
58454
58727
  var errors_js_1 = require_errors6();
58455
58728
  var staging_paths_js_1 = require_staging_paths();
58729
+ var error_utils_js_1 = require_error_utils();
58456
58730
  var StagingServiceCore = class {
58457
58731
  options;
58458
58732
  constructor(options) {
@@ -58556,7 +58830,7 @@ var require_staging_service = __commonJS({
58556
58830
  hookName,
58557
58831
  reminderName,
58558
58832
  path: reminderPath,
58559
- error: err instanceof Error ? err.message : String(err)
58833
+ error: (0, error_utils_js_1.toErrorMessage)(err)
58560
58834
  });
58561
58835
  return null;
58562
58836
  }
@@ -58587,7 +58861,7 @@ var require_staging_service = __commonJS({
58587
58861
  }
58588
58862
  this.options.logger.warn("Skipping invalid reminder file", {
58589
58863
  path: reminderPath,
58590
- error: err instanceof Error ? err.message : String(err)
58864
+ error: (0, error_utils_js_1.toErrorMessage)(err)
58591
58865
  });
58592
58866
  }
58593
58867
  }
@@ -58648,7 +58922,7 @@ var require_staging_service = __commonJS({
58648
58922
  }
58649
58923
  this.options.logger.warn("Skipping invalid consumed reminder file", {
58650
58924
  path: reminderPath,
58651
- error: err instanceof Error ? err.message : String(err)
58925
+ error: (0, error_utils_js_1.toErrorMessage)(err)
58652
58926
  });
58653
58927
  }
58654
58928
  }
@@ -58800,6 +59074,7 @@ var require_handler_registry2 = __commonJS({
58800
59074
  exports2.HandlerRegistryImpl = void 0;
58801
59075
  var transcript_content_js_1 = require_transcript_content();
58802
59076
  var structured_logging_js_1 = require_structured_logging();
59077
+ var error_utils_js_1 = require_error_utils();
58803
59078
  var HandlerRegistryImpl = class {
58804
59079
  options;
58805
59080
  handlers = [];
@@ -58910,7 +59185,7 @@ var require_handler_registry2 = __commonJS({
58910
59185
  log.error("Handler execution failed", {
58911
59186
  handlerId: handler.id,
58912
59187
  hook,
58913
- error: err instanceof Error ? err.message : String(err)
59188
+ error: (0, error_utils_js_1.toErrorMessage)(err)
58914
59189
  });
58915
59190
  }
58916
59191
  }
@@ -58956,7 +59231,7 @@ var require_handler_registry2 = __commonJS({
58956
59231
  (0, structured_logging_js_1.logEvent)(this.options.logger, structured_logging_js_1.LogEvents.eventProcessed(logContext, { handlerId: handler.id, success: true }, { durationMs }));
58957
59232
  } catch (err) {
58958
59233
  const durationMs = Date.now() - startTime;
58959
- const errorMsg = err instanceof Error ? err.message : String(err);
59234
+ const errorMsg = (0, error_utils_js_1.toErrorMessage)(err);
58960
59235
  (0, structured_logging_js_1.logEvent)(this.options.logger, structured_logging_js_1.LogEvents.eventProcessed(logContext, { handlerId: handler.id, success: false }, { durationMs, error: errorMsg }));
58961
59236
  this.options.logger.error("Transcript handler failed", {
58962
59237
  handlerId: handler.id,
@@ -59315,6 +59590,9 @@ var require_path_resolver = __commonJS({
59315
59590
  sessionStagingDir(sessionId) {
59316
59591
  return (0, node_path_1.join)(this.sessionRootDir(sessionId), "stage");
59317
59592
  }
59593
+ sessionLogsDir(sessionId) {
59594
+ return (0, node_path_1.join)(this.sessionRootDir(sessionId), "logs");
59595
+ }
59318
59596
  hookStagingDir(sessionId, hookName) {
59319
59597
  return (0, node_path_1.join)(this.sessionStagingDir(sessionId), hookName);
59320
59598
  }
@@ -59384,6 +59662,7 @@ var require_state_service = __commonJS({
59384
59662
  var node_path_1 = require("node:path");
59385
59663
  var path_resolver_js_1 = require_path_resolver();
59386
59664
  var errors_js_1 = require_errors6();
59665
+ var error_utils_js_1 = require_error_utils();
59387
59666
  var errors_js_2 = require_errors6();
59388
59667
  Object.defineProperty(exports2, "StateNotFoundError", { enumerable: true, get: function() {
59389
59668
  return errors_js_2.StateNotFoundError;
@@ -59495,7 +59774,7 @@ var require_state_service = __commonJS({
59495
59774
  } catch (cleanupErr) {
59496
59775
  this.logger?.trace("Failed to cleanup temp file", {
59497
59776
  tmpPath,
59498
- error: cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr)
59777
+ error: (0, error_utils_js_1.toErrorMessage)(cleanupErr)
59499
59778
  });
59500
59779
  }
59501
59780
  throw err;
@@ -59621,7 +59900,7 @@ var require_state_service = __commonJS({
59621
59900
  } catch (err) {
59622
59901
  this.logger?.warn("Failed to preload state file", {
59623
59902
  file,
59624
- error: err instanceof Error ? err.message : String(err)
59903
+ error: (0, error_utils_js_1.toErrorMessage)(err)
59625
59904
  });
59626
59905
  }
59627
59906
  }
@@ -59647,7 +59926,7 @@ var require_state_service = __commonJS({
59647
59926
  this.logger?.warn("Corrupt state file detected", {
59648
59927
  path,
59649
59928
  reason,
59650
- error: error instanceof Error ? error.message : String(error)
59929
+ error: (0, error_utils_js_1.toErrorMessage)(error)
59651
59930
  });
59652
59931
  try {
59653
59932
  await fs.rename(path, bakPath);
@@ -59677,7 +59956,7 @@ var require_state_service = __commonJS({
59677
59956
  } catch (err) {
59678
59957
  this.logger?.warn("Failed to create dev mode backup", {
59679
59958
  path,
59680
- error: err instanceof Error ? err.message : String(err)
59959
+ error: (0, error_utils_js_1.toErrorMessage)(err)
59681
59960
  });
59682
59961
  }
59683
59962
  }
@@ -59740,12 +60019,17 @@ var require_typed_accessor = __commonJS({
59740
60019
  var SessionStateAccessor = class {
59741
60020
  stateService;
59742
60021
  descriptor;
59743
- constructor(stateService, descriptor) {
60022
+ journal;
60023
+ /** Descriptor filename without .json extension — used as journal file key */
60024
+ fileKey;
60025
+ constructor(stateService, descriptor, journal) {
59744
60026
  this.stateService = stateService;
59745
60027
  this.descriptor = descriptor;
60028
+ this.journal = journal;
59746
60029
  if (descriptor.scope !== "session") {
59747
60030
  throw new Error(`SessionStateAccessor requires a session-scoped descriptor, got: ${descriptor.scope}`);
59748
60031
  }
60032
+ this.fileKey = descriptor.filename.replace(/\.json$/, "");
59749
60033
  }
59750
60034
  /**
59751
60035
  * Read session state file.
@@ -59763,9 +60047,15 @@ var require_typed_accessor = __commonJS({
59763
60047
  */
59764
60048
  async write(sessionId, data) {
59765
60049
  const path = this.stateService.sessionStatePath(sessionId, this.descriptor.filename);
59766
- return this.stateService.write(path, data, this.descriptor.schema, {
60050
+ await this.stateService.write(path, data, this.descriptor.schema, {
59767
60051
  trackHistory: this.descriptor.trackHistory
59768
60052
  });
60053
+ if (this.journal) {
60054
+ try {
60055
+ await this.journal.appendIfChanged(sessionId, this.fileKey, data);
60056
+ } catch {
60057
+ }
60058
+ }
59769
60059
  }
59770
60060
  /**
59771
60061
  * Delete session state file.
@@ -59773,6 +60063,12 @@ var require_typed_accessor = __commonJS({
59773
60063
  async delete(sessionId) {
59774
60064
  const path = this.stateService.sessionStatePath(sessionId, this.descriptor.filename);
59775
60065
  await this.stateService.delete(path);
60066
+ if (this.journal) {
60067
+ try {
60068
+ await this.journal.appendDeletion(sessionId, this.fileKey);
60069
+ } catch {
60070
+ }
60071
+ }
59776
60072
  }
59777
60073
  /**
59778
60074
  * Get the path for a session state file.
@@ -60038,8 +60334,51 @@ var require_transcript_normalizer = __commonJS({
60038
60334
  exports2.parseUuid = parseUuid;
60039
60335
  exports2.renderTranscriptString = renderTranscriptString;
60040
60336
  var index_js_1 = require_state3();
60337
+ function buildRecapEntry(params) {
60338
+ const text = typeof params.rawText === "string" ? params.rawText.trim() : "";
60339
+ if (!text)
60340
+ return null;
60341
+ return {
60342
+ id: params.uuid ?? `line-${params.lineNumber}`,
60343
+ timestamp: new Date(params.timestamp ?? Date.now()),
60344
+ role: "system",
60345
+ type: "recap",
60346
+ content: text,
60347
+ metadata: {
60348
+ provider: "claude",
60349
+ lineNumber: params.lineNumber,
60350
+ recapSource: params.recapSource,
60351
+ leafUuid: params.leafUuid
60352
+ }
60353
+ };
60354
+ }
60041
60355
  function normalizeEntry(rawEntry, lineNumber) {
60042
60356
  const entryType = rawEntry.type;
60357
+ if (entryType === "summary") {
60358
+ const raw = rawEntry;
60359
+ const recap = buildRecapEntry({
60360
+ rawText: raw.summary,
60361
+ uuid: raw.uuid,
60362
+ timestamp: raw.timestamp,
60363
+ lineNumber,
60364
+ recapSource: "compaction",
60365
+ leafUuid: typeof raw.leafUuid === "string" ? raw.leafUuid : void 0
60366
+ });
60367
+ return recap ? [recap] : null;
60368
+ }
60369
+ if (entryType === "system") {
60370
+ const raw = rawEntry;
60371
+ if (raw.subtype !== "away_summary")
60372
+ return null;
60373
+ const recap = buildRecapEntry({
60374
+ rawText: raw.content,
60375
+ uuid: raw.uuid,
60376
+ timestamp: raw.timestamp,
60377
+ lineNumber,
60378
+ recapSource: "away"
60379
+ });
60380
+ return recap ? [recap] : null;
60381
+ }
60043
60382
  if (entryType !== "user" && entryType !== "assistant") {
60044
60383
  return null;
60045
60384
  }
@@ -60173,6 +60512,9 @@ var require_transcript_normalizer = __commonJS({
60173
60512
  return `[${timestamp}] ${role} TOOL_USE: ${String(toolContent.name)}`;
60174
60513
  } else if (type === "tool_result") {
60175
60514
  return `[${timestamp}] ${role} TOOL_RESULT`;
60515
+ } else if (type === "recap") {
60516
+ const content = typeof entry.content === "string" ? entry.content : "";
60517
+ return `[${timestamp}] RECAP: ${content}`;
60176
60518
  }
60177
60519
  return `[${timestamp}] ${role}: ${JSON.stringify(entry.content)}`;
60178
60520
  }).join("\n");
@@ -60191,6 +60533,7 @@ var require_transcript_excerpt_builder = __commonJS({
60191
60533
  exports2.extractTextContent = extractTextContent;
60192
60534
  exports2.getRawContentString = getRawContentString;
60193
60535
  var transcript_helpers_js_1 = require_transcript_helpers();
60536
+ var error_utils_js_1 = require_error_utils();
60194
60537
  function getBufferedEntries(buffer, head, count, bufferSize) {
60195
60538
  if (count === 0)
60196
60539
  return [];
@@ -60245,7 +60588,7 @@ var require_transcript_excerpt_builder = __commonJS({
60245
60588
  };
60246
60589
  } catch (err) {
60247
60590
  logger.error("Failed to extract transcript excerpt from buffer", {
60248
- error: err instanceof Error ? err.message : String(err)
60591
+ error: (0, error_utils_js_1.toErrorMessage)(err)
60249
60592
  });
60250
60593
  return {
60251
60594
  content: "",
@@ -60306,6 +60649,14 @@ var require_transcript_excerpt_builder = __commonJS({
60306
60649
  return null;
60307
60650
  }
60308
60651
  return `[SESSION_HINT]: ${entry.summary ?? ""}`;
60652
+ case "system": {
60653
+ if (entry.subtype !== "away_summary")
60654
+ return null;
60655
+ const content = entry.content;
60656
+ if (typeof content !== "string" || !content.trim())
60657
+ return null;
60658
+ return `[SESSION_RECAP]: ${content}`;
60659
+ }
60309
60660
  default:
60310
60661
  return null;
60311
60662
  }
@@ -63164,6 +63515,7 @@ var require_instrumented_llm_provider = __commonJS({
63164
63515
  var node_path_1 = require("node:path");
63165
63516
  var yaml_1 = __importDefault2(require_dist2());
63166
63517
  var types_1 = require_dist();
63518
+ var error_utils_js_1 = require_error_utils();
63167
63519
  var STATE_FILE = "llm-metrics.json";
63168
63520
  var DEFAULT_DEBOUNCE_MS = 500;
63169
63521
  function hasFallbackTracking(provider) {
@@ -63214,7 +63566,7 @@ var require_instrumented_llm_provider = __commonJS({
63214
63566
  }
63215
63567
  } catch (err) {
63216
63568
  this.config.logger.warn("Failed to load LLM metrics, starting fresh", {
63217
- error: err instanceof Error ? err.message : String(err)
63569
+ error: (0, error_utils_js_1.toErrorMessage)(err)
63218
63570
  });
63219
63571
  }
63220
63572
  }
@@ -63301,7 +63653,7 @@ var require_instrumented_llm_provider = __commonJS({
63301
63653
  this.config.logger.debug("Debug dump written", { path: basePath });
63302
63654
  } catch (dumpError) {
63303
63655
  this.config.logger.warn("Failed to write debug dump", {
63304
- error: dumpError instanceof Error ? dumpError.message : String(dumpError)
63656
+ error: (0, error_utils_js_1.toErrorMessage)(dumpError)
63305
63657
  });
63306
63658
  }
63307
63659
  }
@@ -63526,7 +63878,7 @@ var require_instrumented_llm_provider = __commonJS({
63526
63878
  });
63527
63879
  } catch (err) {
63528
63880
  this.config.logger.warn("Failed to persist LLM metrics", {
63529
- error: err instanceof Error ? err.message : String(err)
63881
+ error: (0, error_utils_js_1.toErrorMessage)(err)
63530
63882
  });
63531
63883
  }
63532
63884
  }
@@ -63802,6 +64154,7 @@ var require_daemon_health = __commonJS({
63802
64154
  var fs = __importStar(require("node:fs/promises"));
63803
64155
  var node_path_1 = require("node:path");
63804
64156
  var types_1 = require_dist();
64157
+ var error_utils_js_1 = require_error_utils();
63805
64158
  function healthFilePath(projectDir) {
63806
64159
  return (0, node_path_1.join)(projectDir, ".sidekick", "state", "daemon-health.json");
63807
64160
  }
@@ -63860,7 +64213,7 @@ var require_daemon_health = __commonJS({
63860
64213
  logger.warn("Failed to write daemon health", {
63861
64214
  from,
63862
64215
  to,
63863
- error: err instanceof Error ? err.message : String(err)
64216
+ error: (0, error_utils_js_1.toErrorMessage)(err)
63864
64217
  });
63865
64218
  return false;
63866
64219
  }
@@ -63947,6 +64300,7 @@ var require_user_profile_loader = __commonJS({
63947
64300
  var node_path_1 = require("node:path");
63948
64301
  var yaml_1 = require_dist2();
63949
64302
  var types_1 = require_dist();
64303
+ var error_utils_js_1 = require_error_utils();
63950
64304
  function loadUserProfile(options) {
63951
64305
  const home = options?.homeDir ?? (0, node_os_1.homedir)();
63952
64306
  const filePath = (0, node_path_1.join)(home, ".sidekick", "user.yaml");
@@ -63968,7 +64322,7 @@ var require_user_profile_loader = __commonJS({
63968
64322
  } catch (err) {
63969
64323
  options?.logger?.warn("Failed to read user profile", {
63970
64324
  path: filePath,
63971
- error: err instanceof Error ? err.message : String(err)
64325
+ error: (0, error_utils_js_1.toErrorMessage)(err)
63972
64326
  });
63973
64327
  return null;
63974
64328
  }
@@ -64035,9 +64389,9 @@ var require_dist4 = __commonJS({
64035
64389
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
64036
64390
  };
64037
64391
  Object.defineProperty(exports2, "__esModule", { value: true });
64038
- exports2.readKeyFromEnvFile = exports2.determineOverallStatus = exports2.toScopeStatus = exports2.LEGACY_USER_STATUS_FILENAME = exports2.PROJECT_STATUS_FILENAME = exports2.USER_STATUS_FILENAME = exports2.createSetupStatusService = exports2.SetupStatusService = exports2.DaemonClient = exports2.findZombieDaemons = exports2.killZombieDaemons = exports2.killAllDaemons = exports2.logEvent = exports2.LogEvents = exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.getComponentLogLevel = exports2.setupGlobalErrorHandlers = exports2.createLoggerFacade = exports2.createLogManager = exports2.createConsoleLogger = exports2.getUserDaemonsDir = exports2.getUserPidPath = exports2.getTokenPath = exports2.getSocketPath = exports2.getProjectHash = exports2.getPidPath = exports2.getLockPath = exports2.IpcService = exports2.IpcServer = exports2.loadPersonaFile = exports2.getDefaultPersonasDir = exports2.discoverPersonas = exports2.createPersonaLoader = exports2.reconstructTranscriptPath = exports2.encodeProjectPath = exports2.isPreCompactEvent = exports2.isStopEvent = exports2.isPostToolUseEvent = exports2.isPreToolUseEvent = exports2.isUserPromptSubmitEvent = exports2.isSessionEndEvent = exports2.isSessionStartEvent = exports2.isTranscriptEvent = exports2.isHookEvent = exports2.MetricsPersistPayloadSchema = exports2.CleanupPayloadSchema = exports2.ResumeGenerationPayloadSchema = exports2.SessionSummaryPayloadSchema = exports2.TaskTypes = void 0;
64039
- exports2.StateService = exports2.createHookableLogger = exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = exports2.detectGitignoreStatus = exports2.removeGitignoreSection = exports2.installGitignoreSection = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.runDoctorCheck = exports2.detectPluginLiveness = exports2.detectPluginInstallation = exports2.detectActualStatusline = exports2.spawnWithTimeout = exports2.getDoctorTimeout = exports2.DOCTOR_TIMEOUTS = exports2.projectApiKeyStatusFromHealth = exports2.userApiKeyStatusFromHealth = exports2.buildProjectApiKeyStatus = exports2.buildUserApiKeyStatus = exports2.detectAllApiKeys = exports2.detectActualApiKey = void 0;
64040
- exports2.CoalescingGuard = exports2.loadUserProfile = exports2.parseGitStatusOutput = exports2.getGitFileStatus = exports2.isInSandbox = exports2.updateDaemonHealth = exports2.readDaemonHealth = exports2.ProjectRegistryService = exports2.encodeProjectDir = exports2.DaemonGlobalLogMetricsDescriptor = exports2.CliLogMetricsDescriptor = exports2.DaemonLogMetricsDescriptor = exports2.CompactionHistoryDescriptor = exports2.TranscriptMetricsDescriptor = exports2.GlobalStateAccessor = exports2.SessionStateAccessor = exports2.globalState = exports2.sessionState = exports2.StateCorruptError = exports2.StateNotFoundError = void 0;
64392
+ exports2.PROJECT_STATUS_FILENAME = exports2.USER_STATUS_FILENAME = exports2.createSetupStatusService = exports2.SetupStatusService = exports2.DaemonClient = exports2.findZombieDaemons = exports2.killZombieDaemons = exports2.killAllDaemons = exports2.SessionLogWriter = exports2.setSessionLogWriter = exports2.logEvent = exports2.LogEvents = exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.getComponentLogLevel = exports2.setupGlobalErrorHandlers = exports2.createLoggerFacade = exports2.createLogManager = exports2.createConsoleLogger = exports2.getUserDaemonsDir = exports2.getUserPidPath = exports2.getTokenPath = exports2.getSocketPath = exports2.getProjectHash = exports2.getPidPath = exports2.getLockPath = exports2.IpcService = exports2.IpcServer = exports2.loadPersonaFile = exports2.getDefaultPersonasDir = exports2.discoverPersonas = exports2.createPersonaLoader = exports2.reconstructTranscriptPath = exports2.encodeProjectPath = exports2.isSubagentStopEvent = exports2.isSubagentStartEvent = exports2.isPreCompactEvent = exports2.isStopEvent = exports2.isPostToolUseEvent = exports2.isPreToolUseEvent = exports2.isUserPromptSubmitEvent = exports2.isSessionEndEvent = exports2.isSessionStartEvent = exports2.isTranscriptEvent = exports2.isHookEvent = exports2.MetricsPersistPayloadSchema = exports2.CleanupPayloadSchema = exports2.ResumeGenerationPayloadSchema = exports2.SessionSummaryPayloadSchema = exports2.TaskTypes = void 0;
64393
+ exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_GITIGNORE_HEADER = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = exports2.removeLegacyGitignoreSection = exports2.detectLegacyGitignoreSection = exports2.detectGitignoreStatus = exports2.removeGitignoreSection = exports2.installGitignoreSection = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.runDoctorCheck = exports2.detectPluginLiveness = exports2.detectPluginInstallation = exports2.detectActualStatusline = exports2.spawnWithTimeout = exports2.getDoctorTimeout = exports2.DOCTOR_TIMEOUTS = exports2.projectApiKeyStatusFromHealth = exports2.userApiKeyStatusFromHealth = exports2.buildProjectApiKeyStatus = exports2.buildUserApiKeyStatus = exports2.detectAllApiKeys = exports2.detectActualApiKey = exports2.readKeyFromEnvFile = exports2.determineOverallStatus = exports2.toScopeStatus = void 0;
64394
+ exports2.CoalescingGuard = exports2.loadUserProfile = exports2.parseGitStatusOutput = exports2.getGitFileStatus = exports2.toErrorMessage = exports2.isInSandbox = exports2.updateDaemonHealth = exports2.readDaemonHealth = exports2.ProjectRegistryService = exports2.encodeProjectDir = exports2.DaemonGlobalLogMetricsDescriptor = exports2.CliLogMetricsDescriptor = exports2.DaemonLogMetricsDescriptor = exports2.CompactionHistoryDescriptor = exports2.TranscriptMetricsDescriptor = exports2.GlobalStateAccessor = exports2.SessionStateAccessor = exports2.globalState = exports2.sessionState = exports2.StateCorruptError = exports2.StateNotFoundError = exports2.StateService = exports2.createHookableLogger = exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = void 0;
64041
64395
  var types_1 = require_dist();
64042
64396
  Object.defineProperty(exports2, "TaskTypes", { enumerable: true, get: function() {
64043
64397
  return types_1.TaskTypes;
@@ -64082,6 +64436,12 @@ var require_dist4 = __commonJS({
64082
64436
  Object.defineProperty(exports2, "isPreCompactEvent", { enumerable: true, get: function() {
64083
64437
  return types_2.isPreCompactEvent;
64084
64438
  } });
64439
+ Object.defineProperty(exports2, "isSubagentStartEvent", { enumerable: true, get: function() {
64440
+ return types_2.isSubagentStartEvent;
64441
+ } });
64442
+ Object.defineProperty(exports2, "isSubagentStopEvent", { enumerable: true, get: function() {
64443
+ return types_2.isSubagentStopEvent;
64444
+ } });
64085
64445
  __exportStar(require_assets(), exports2);
64086
64446
  var claude_paths_1 = require_claude_paths();
64087
64447
  Object.defineProperty(exports2, "encodeProjectPath", { enumerable: true, get: function() {
@@ -64170,6 +64530,12 @@ var require_dist4 = __commonJS({
64170
64530
  Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
64171
64531
  return structured_logging_1.logEvent;
64172
64532
  } });
64533
+ Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
64534
+ return structured_logging_1.setSessionLogWriter;
64535
+ } });
64536
+ Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
64537
+ return structured_logging_1.SessionLogWriter;
64538
+ } });
64173
64539
  var daemon_client_1 = require_daemon_client2();
64174
64540
  Object.defineProperty(exports2, "killAllDaemons", { enumerable: true, get: function() {
64175
64541
  return daemon_client_1.killAllDaemons;
@@ -64196,9 +64562,6 @@ var require_dist4 = __commonJS({
64196
64562
  Object.defineProperty(exports2, "PROJECT_STATUS_FILENAME", { enumerable: true, get: function() {
64197
64563
  return setup_status_service_1.PROJECT_STATUS_FILENAME;
64198
64564
  } });
64199
- Object.defineProperty(exports2, "LEGACY_USER_STATUS_FILENAME", { enumerable: true, get: function() {
64200
- return setup_status_service_1.LEGACY_USER_STATUS_FILENAME;
64201
- } });
64202
64565
  var api_key_detector_1 = require_api_key_detector();
64203
64566
  Object.defineProperty(exports2, "toScopeStatus", { enumerable: true, get: function() {
64204
64567
  return api_key_detector_1.toScopeStatus;
@@ -64267,12 +64630,21 @@ var require_dist4 = __commonJS({
64267
64630
  Object.defineProperty(exports2, "detectGitignoreStatus", { enumerable: true, get: function() {
64268
64631
  return gitignore_1.detectGitignoreStatus;
64269
64632
  } });
64633
+ Object.defineProperty(exports2, "detectLegacyGitignoreSection", { enumerable: true, get: function() {
64634
+ return gitignore_1.detectLegacyGitignoreSection;
64635
+ } });
64636
+ Object.defineProperty(exports2, "removeLegacyGitignoreSection", { enumerable: true, get: function() {
64637
+ return gitignore_1.removeLegacyGitignoreSection;
64638
+ } });
64270
64639
  Object.defineProperty(exports2, "SIDEKICK_SECTION_START", { enumerable: true, get: function() {
64271
64640
  return gitignore_1.SIDEKICK_SECTION_START;
64272
64641
  } });
64273
64642
  Object.defineProperty(exports2, "SIDEKICK_SECTION_END", { enumerable: true, get: function() {
64274
64643
  return gitignore_1.SIDEKICK_SECTION_END;
64275
64644
  } });
64645
+ Object.defineProperty(exports2, "SIDEKICK_GITIGNORE_HEADER", { enumerable: true, get: function() {
64646
+ return gitignore_1.SIDEKICK_GITIGNORE_HEADER;
64647
+ } });
64276
64648
  Object.defineProperty(exports2, "GITIGNORE_ENTRIES", { enumerable: true, get: function() {
64277
64649
  return gitignore_1.GITIGNORE_ENTRIES;
64278
64650
  } });
@@ -64425,6 +64797,10 @@ var require_dist4 = __commonJS({
64425
64797
  Object.defineProperty(exports2, "isInSandbox", { enumerable: true, get: function() {
64426
64798
  return sandbox_1.isInSandbox;
64427
64799
  } });
64800
+ var error_utils_1 = require_error_utils();
64801
+ Object.defineProperty(exports2, "toErrorMessage", { enumerable: true, get: function() {
64802
+ return error_utils_1.toErrorMessage;
64803
+ } });
64428
64804
  var git_status_1 = require_git_status();
64429
64805
  Object.defineProperty(exports2, "getGitFileStatus", { enumerable: true, get: function() {
64430
64806
  return git_status_1.getGitFileStatus;
@@ -64483,7 +64859,7 @@ var require_runtime = __commonJS({
64483
64859
  });
64484
64860
  } catch (err) {
64485
64861
  loggerFacade.error("Failed to load configuration", {
64486
- error: err instanceof Error ? err.message : String(err)
64862
+ error: (0, core_1.toErrorMessage)(err)
64487
64863
  });
64488
64864
  throw err;
64489
64865
  }
@@ -64498,8 +64874,9 @@ var require_runtime = __commonJS({
64498
64874
  const rotation = config.core.logging.rotation;
64499
64875
  const fileDestination = enableFileLogging ? {
64500
64876
  path: logFilePath,
64501
- maxSizeBytes: rotation?.maxSizeBytes ?? 10485760,
64502
- maxFiles: rotation?.maxFiles ?? 5
64877
+ maxSizeBytes: rotation?.maxSizeBytes ?? 2097152,
64878
+ // 2MB (ephemeral debug window)
64879
+ maxFiles: rotation?.maxFiles ?? 2
64503
64880
  } : void 0;
64504
64881
  const logManager = (0, core_1.createLogManager)({
64505
64882
  name: "sidekick:cli",
@@ -64541,6 +64918,14 @@ var require_runtime = __commonJS({
64541
64918
  }
64542
64919
  });
64543
64920
  const telemetry = logManager.getTelemetry();
64921
+ const sessionsDir = projectRoot ? (0, node_path_1.join)(projectRoot, ".sidekick", "sessions") : (0, node_path_1.join)((0, node_os_1.homedir)(), ".sidekick", "sessions");
64922
+ const sessionLogWriter = new core_1.SessionLogWriter({
64923
+ sessionsDir,
64924
+ maxHandles: 2,
64925
+ // CLI typically has 1 session
64926
+ idleTimeoutMs: 10 * 60 * 1e3
64927
+ });
64928
+ (0, core_1.setSessionLogWriter)(sessionLogWriter);
64544
64929
  const cleanupErrorHandlers = (0, core_1.setupGlobalErrorHandlers)(logger);
64545
64930
  logger.debug("Runtime bootstrap complete", {
64546
64931
  projectRoot: projectRoot ?? null,
@@ -64563,6 +64948,8 @@ var require_runtime = __commonJS({
64563
64948
  stateService,
64564
64949
  correlationId,
64565
64950
  cleanup: () => {
64951
+ (0, core_1.setSessionLogWriter)(null);
64952
+ void sessionLogWriter.closeAll();
64566
64953
  cleanupErrorHandlers();
64567
64954
  },
64568
64955
  bindSessionId: (sessionId) => {
@@ -64640,7 +65027,7 @@ var require_dev_mode_guard = __commonJS({
64640
65027
  }
64641
65028
  } catch (err) {
64642
65029
  logger.warn(`Failed to auto-correct devMode flag for ${callerLabel}`, {
64643
- error: err instanceof Error ? err.message : String(err),
65030
+ error: (0, core_1.toErrorMessage)(err),
64644
65031
  caller: callerLabel
64645
65032
  });
64646
65033
  }
@@ -64658,7 +65045,7 @@ var require_dev_mode_guard = __commonJS({
64658
65045
  }
64659
65046
  } catch (err) {
64660
65047
  logger.warn(`Failed to check plugin/dev-mode status for ${callerLabel}, proceeding normally`, {
64661
- error: err instanceof Error ? err.message : String(err),
65048
+ error: (0, core_1.toErrorMessage)(err),
64662
65049
  caller: callerLabel
64663
65050
  });
64664
65051
  }
@@ -71684,6 +72071,7 @@ var require_reminder_utils = __commonJS({
71684
72071
  var node_path_1 = require("node:path");
71685
72072
  var yaml = __importStar(require_js_yaml());
71686
72073
  var zod_1 = require_zod2();
72074
+ var core_1 = require_dist4();
71687
72075
  var ReminderDefinitionSchema = zod_1.z.object({
71688
72076
  id: zod_1.z.string(),
71689
72077
  blocking: zod_1.z.boolean(),
@@ -71736,7 +72124,7 @@ var require_reminder_utils = __commonJS({
71736
72124
  if (logger) {
71737
72125
  logger.error("Failed to load reminder", {
71738
72126
  reminderId,
71739
- error: err instanceof Error ? err.message : String(err)
72127
+ error: (0, core_1.toErrorMessage)(err)
71740
72128
  });
71741
72129
  } else {
71742
72130
  console.error(`Failed to load reminder ${reminderId}:`, err);
@@ -72476,7 +72864,7 @@ var require_stage_pause_and_reflect = __commonJS({
72476
72864
  (0, staging_handler_utils_js_1.createStagingHandler)(context, {
72477
72865
  id: "reminders:stage-pause-and-reflect",
72478
72866
  priority: 80,
72479
- filter: { kind: "transcript", eventTypes: ["ToolCall"] },
72867
+ filter: { kind: "transcript", eventTypes: ["ToolResult"] },
72480
72868
  execute: async (event, ctx) => {
72481
72869
  if (!(0, types_1.isTranscriptEvent)(event))
72482
72870
  return void 0;
@@ -74159,17 +74547,15 @@ var require_track_verification_tools = __commonJS({
74159
74547
  var state_js_1 = require_state4();
74160
74548
  var FILE_EDIT_TOOLS = ["Write", "Edit", "MultiEdit"];
74161
74549
  var VC_TOOL_NAME_SET = new Set(types_js_1.VC_TOOL_REMINDER_IDS);
74162
- function extractToolInput(event) {
74163
- const entry = event.payload.entry;
74164
- return entry?.input;
74165
- }
74550
+ var MAX_PENDING_TOOL_CALLS = 100;
74166
74551
  function registerTrackVerificationTools(context) {
74167
74552
  if (!(0, types_1.isDaemonContext)(context))
74168
74553
  return;
74554
+ const pendingBySession = /* @__PURE__ */ new Map();
74169
74555
  context.handlers.register({
74170
74556
  id: "reminders:track-verification-tools",
74171
74557
  priority: 60,
74172
- filter: { kind: "transcript", eventTypes: ["ToolCall"] },
74558
+ filter: { kind: "transcript", eventTypes: ["ToolCall", "ToolResult"] },
74173
74559
  handler: async (event, ctx) => {
74174
74560
  if (!(0, types_1.isTranscriptEvent)(event))
74175
74561
  return;
@@ -74181,22 +74567,66 @@ var require_track_verification_tools = __commonJS({
74181
74567
  const sessionId = event.context?.sessionId;
74182
74568
  if (!sessionId)
74183
74569
  return;
74184
- const toolName = event.payload.toolName;
74185
- if (!toolName)
74570
+ if (event.eventType === "ToolCall") {
74571
+ const toolUseId = event.payload.entry.id;
74572
+ const toolName = event.payload.toolName;
74573
+ if (!toolUseId || !toolName)
74574
+ return;
74575
+ const entry = event.payload.entry;
74576
+ const input = entry?.input ?? {};
74577
+ let sessionMap = pendingBySession.get(sessionId);
74578
+ if (!sessionMap) {
74579
+ sessionMap = /* @__PURE__ */ new Map();
74580
+ pendingBySession.set(sessionId, sessionMap);
74581
+ }
74582
+ if (sessionMap.size >= MAX_PENDING_TOOL_CALLS) {
74583
+ const oldest = sessionMap.keys().next().value;
74584
+ if (oldest)
74585
+ sessionMap.delete(oldest);
74586
+ }
74587
+ sessionMap.set(toolUseId, { toolName, input });
74186
74588
  return;
74187
- const config = (0, types_js_1.getRemindersConfig)(context.config);
74188
- const verificationTools = config.verification_tools ?? {};
74189
- const runners = config.command_runners ?? [];
74190
- const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
74191
- const stateResult = await remindersState.verificationTools.read(sessionId);
74192
- const toolsState = { ...stateResult.data };
74193
- if (FILE_EDIT_TOOLS.includes(toolName)) {
74194
- await handleFileEdit(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
74195
- } else if (toolName === "Bash") {
74196
- await handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners);
74589
+ }
74590
+ if (event.eventType === "ToolResult") {
74591
+ const toolUseId = event.payload.entry.tool_use_id;
74592
+ if (!toolUseId)
74593
+ return;
74594
+ const sessionMap = pendingBySession.get(sessionId);
74595
+ const pending = sessionMap?.get(toolUseId);
74596
+ if (!pending)
74597
+ return;
74598
+ sessionMap.delete(toolUseId);
74599
+ if (sessionMap.size === 0)
74600
+ pendingBySession.delete(sessionId);
74601
+ const { toolName, input } = pending;
74602
+ const config = (0, types_js_1.getRemindersConfig)(context.config);
74603
+ const verificationTools = config.verification_tools ?? {};
74604
+ const runners = config.command_runners ?? [];
74605
+ const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
74606
+ const stateResult = await remindersState.verificationTools.read(sessionId);
74607
+ const toolsState = { ...stateResult.data };
74608
+ if (FILE_EDIT_TOOLS.includes(toolName)) {
74609
+ await handleFileEdit(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
74610
+ } else if (toolName === "Bash") {
74611
+ await handleBashCommand(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners);
74612
+ }
74197
74613
  }
74198
74614
  }
74199
74615
  });
74616
+ context.handlers.register({
74617
+ id: "reminders:track-verification-tools-cleanup",
74618
+ priority: 60,
74619
+ filter: { kind: "hook", hooks: ["UserPromptSubmit", "Stop"] },
74620
+ // eslint-disable-next-line @typescript-eslint/require-await -- sync cleanup, async required by EventHandler type
74621
+ handler: async (event, _ctx) => {
74622
+ if (!(0, types_1.isHookEvent)(event))
74623
+ return;
74624
+ const sessionId = event.context?.sessionId;
74625
+ if (!sessionId)
74626
+ return;
74627
+ pendingBySession.delete(sessionId);
74628
+ }
74629
+ });
74200
74630
  }
74201
74631
  async function stageToolsForFiles(filePaths, daemonCtx, sessionId, verificationTools, toolsState, remindersState, triggeredBy = "file_edit") {
74202
74632
  const existingReminders = await daemonCtx.staging.listReminders("Stop");
@@ -74301,7 +74731,7 @@ var require_track_verification_tools = __commonJS({
74301
74731
  toolName,
74302
74732
  reminderId,
74303
74733
  sessionId,
74304
- error: error instanceof Error ? error.message : String(error)
74734
+ error: (0, core_1.toErrorMessage)(error)
74305
74735
  });
74306
74736
  }
74307
74737
  }
@@ -74315,8 +74745,8 @@ var require_track_verification_tools = __commonJS({
74315
74745
  await remindersState.verificationTools.write(sessionId, toolsState);
74316
74746
  return anyStaged;
74317
74747
  }
74318
- async function handleFileEdit(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState) {
74319
- const filePath = extractToolInput(event)?.file_path;
74748
+ async function handleFileEdit(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState) {
74749
+ const filePath = input.file_path;
74320
74750
  if (!filePath)
74321
74751
  return;
74322
74752
  const projectDir = daemonCtx.paths?.projectDir;
@@ -74324,8 +74754,8 @@ var require_track_verification_tools = __commonJS({
74324
74754
  return;
74325
74755
  await stageToolsForFiles([filePath], daemonCtx, sessionId, verificationTools, toolsState, remindersState);
74326
74756
  }
74327
- async function handleBashCommand(event, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners = []) {
74328
- const command = extractToolInput(event)?.command;
74757
+ async function handleBashCommand(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners = []) {
74758
+ const command = input.command;
74329
74759
  if (!command)
74330
74760
  return;
74331
74761
  let anyUnstaged = false;
@@ -74754,7 +75184,7 @@ var require_stage_persona_reminders = __commonJS({
74754
75184
  } catch (err) {
74755
75185
  logger.error("Failed to restage persona reminders", {
74756
75186
  sessionId,
74757
- error: err instanceof Error ? err.message : String(err)
75187
+ error: (0, core_1.toErrorMessage)(err)
74758
75188
  });
74759
75189
  }
74760
75190
  }
@@ -74990,6 +75420,38 @@ var require_stage_user_profile_reminders = __commonJS({
74990
75420
  }
74991
75421
  });
74992
75422
 
75423
+ // ../feature-reminders/dist/handlers/staging/cleanup-on-stop.js
75424
+ var require_cleanup_on_stop = __commonJS({
75425
+ "../feature-reminders/dist/handlers/staging/cleanup-on-stop.js"(exports2) {
75426
+ "use strict";
75427
+ Object.defineProperty(exports2, "__esModule", { value: true });
75428
+ exports2.registerCleanupOnStop = registerCleanupOnStop;
75429
+ var types_1 = require_dist();
75430
+ function registerCleanupOnStop(context) {
75431
+ if (!(0, types_1.isDaemonContext)(context))
75432
+ return;
75433
+ context.handlers.register({
75434
+ id: "reminders:cleanup-on-stop",
75435
+ priority: 50,
75436
+ filter: { kind: "hook", hooks: ["Stop"] },
75437
+ handler: async (event, ctx) => {
75438
+ if (!(0, types_1.isHookEvent)(event))
75439
+ return;
75440
+ if (!(0, types_1.isDaemonContext)(ctx))
75441
+ return;
75442
+ const daemonCtx = ctx;
75443
+ const sessionId = event.context?.sessionId;
75444
+ if (!sessionId)
75445
+ return;
75446
+ if (daemonCtx.orchestrator) {
75447
+ await daemonCtx.orchestrator.onStop(sessionId);
75448
+ }
75449
+ }
75450
+ });
75451
+ }
75452
+ }
75453
+ });
75454
+
74993
75455
  // ../feature-reminders/dist/handlers/staging/index.js
74994
75456
  var require_staging2 = __commonJS({
74995
75457
  "../feature-reminders/dist/handlers/staging/index.js"(exports2) {
@@ -75003,6 +75465,7 @@ var require_staging2 = __commonJS({
75003
75465
  var unstage_verify_completion_1 = require_unstage_verify_completion();
75004
75466
  var stage_persona_reminders_1 = require_stage_persona_reminders();
75005
75467
  var stage_user_profile_reminders_1 = require_stage_user_profile_reminders();
75468
+ var cleanup_on_stop_1 = require_cleanup_on_stop();
75006
75469
  function registerStagingHandlers(context) {
75007
75470
  (0, stage_default_user_prompt_1.registerStageDefaultUserPrompt)(context);
75008
75471
  (0, stage_pause_and_reflect_1.registerStagePauseAndReflect)(context);
@@ -75011,6 +75474,7 @@ var require_staging2 = __commonJS({
75011
75474
  (0, unstage_verify_completion_1.registerUnstageVerifyCompletion)(context);
75012
75475
  (0, stage_persona_reminders_1.registerStagePersonaReminders)(context);
75013
75476
  (0, stage_user_profile_reminders_1.registerStageUserProfileReminders)(context);
75477
+ (0, cleanup_on_stop_1.registerCleanupOnStop)(context);
75014
75478
  }
75015
75479
  }
75016
75480
  });
@@ -75731,7 +76195,7 @@ var require_orchestrator = __commonJS({
75731
76195
  } catch (err) {
75732
76196
  this.deps.logger.warn("Failed to unstage VC reminders after P&R staged", {
75733
76197
  sessionId,
75734
- error: err instanceof Error ? err.message : String(err)
76198
+ error: (0, core_1.toErrorMessage)(err)
75735
76199
  });
75736
76200
  }
75737
76201
  }
@@ -75755,27 +76219,10 @@ var require_orchestrator = __commonJS({
75755
76219
  } catch (err) {
75756
76220
  this.deps.logger.warn("Failed to reset P&R baseline after VC consumed", {
75757
76221
  sessionId,
75758
- error: err instanceof Error ? err.message : String(err)
75759
- });
75760
- }
75761
- try {
75762
- const staging = this.deps.getStagingService(sessionId);
75763
- const deleted = await staging.deleteReminder("PreToolUse", types_js_1.ReminderIds.PAUSE_AND_REFLECT);
75764
- if (deleted) {
75765
- (0, core_1.logEvent)(this.deps.logger.child({ context: { sessionId } }), events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
75766
- reminderName: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
75767
- hookName: "PreToolUse",
75768
- reason: "vc_consumed_cascade",
75769
- triggeredBy: "cascade_from_verify_completion"
75770
- }));
75771
- }
75772
- this.deps.logger.debug("VC unstage: P&R cascade from VC consumed", { sessionId, deleted });
75773
- } catch (err) {
75774
- this.deps.logger.warn("Failed to unstage P&R after VC consumed", {
75775
- sessionId,
75776
- error: err instanceof Error ? err.message : String(err)
76222
+ error: (0, core_1.toErrorMessage)(err)
75777
76223
  });
75778
76224
  }
76225
+ await this.unstagePauseAndReflect(sessionId, "vc_consumed_cascade", "cascade_from_verify_completion");
75779
76226
  }
75780
76227
  }
75781
76228
  /**
@@ -75792,7 +76239,43 @@ var require_orchestrator = __commonJS({
75792
76239
  } catch (err) {
75793
76240
  this.deps.logger.warn("Failed to clear P&R baseline on UserPromptSubmit", {
75794
76241
  sessionId,
75795
- error: err instanceof Error ? err.message : String(err)
76242
+ error: (0, core_1.toErrorMessage)(err)
76243
+ });
76244
+ }
76245
+ }
76246
+ /**
76247
+ * Called when Stop hook fires.
76248
+ *
76249
+ * P&R is designed to interrupt runaway execution — once the agent stops,
76250
+ * it's irrelevant. This is defensive: Rule 4 (VC consumed → unstage P&R)
76251
+ * covers the VC case, but this handles the no-VC case where P&R would
76252
+ * otherwise linger on PreToolUse.
76253
+ */
76254
+ async onStop(sessionId) {
76255
+ await this.unstagePauseAndReflect(sessionId, "agent_stopping", "stop_hook");
76256
+ }
76257
+ /**
76258
+ * Delete P&R from PreToolUse staging and log the event.
76259
+ * Shared by Rule 4 (VC consumed → unstage P&R) and onStop (agent stopping).
76260
+ */
76261
+ async unstagePauseAndReflect(sessionId, reason, triggeredBy) {
76262
+ try {
76263
+ const staging = this.deps.getStagingService(sessionId);
76264
+ const deleted = await staging.deleteReminder("PreToolUse", types_js_1.ReminderIds.PAUSE_AND_REFLECT);
76265
+ if (deleted) {
76266
+ (0, core_1.logEvent)(this.deps.logger.child({ context: { sessionId } }), events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
76267
+ reminderName: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
76268
+ hookName: "PreToolUse",
76269
+ reason,
76270
+ triggeredBy
76271
+ }));
76272
+ }
76273
+ this.deps.logger.debug("P&R unstaged", { sessionId, deleted, reason });
76274
+ } catch (err) {
76275
+ this.deps.logger.warn("Failed to unstage P&R", {
76276
+ sessionId,
76277
+ reason,
76278
+ error: (0, core_1.toErrorMessage)(err)
75796
76279
  });
75797
76280
  }
75798
76281
  }
@@ -75961,6 +76444,7 @@ var require_hook = __commonJS({
75961
76444
  exports2.isHookCommand = isHookCommand;
75962
76445
  exports2.getHookName = getHookName;
75963
76446
  var core_1 = require_dist4();
76447
+ var types_1 = require_dist();
75964
76448
  var context_js_1 = require_context2();
75965
76449
  function truncateForLog(raw) {
75966
76450
  const entries = Object.entries(raw);
@@ -75989,15 +76473,7 @@ var require_hook = __commonJS({
75989
76473
  }
75990
76474
  return truncateForLog(filtered);
75991
76475
  }
75992
- var VALID_HOOK_NAMES = /* @__PURE__ */ new Set([
75993
- "SessionStart",
75994
- "SessionEnd",
75995
- "UserPromptSubmit",
75996
- "PreToolUse",
75997
- "PostToolUse",
75998
- "Stop",
75999
- "PreCompact"
76000
- ]);
76476
+ var VALID_HOOK_NAMES = new Set(types_1.HOOK_NAMES);
76001
76477
  function validateHookName(hookEventName) {
76002
76478
  return VALID_HOOK_NAMES.has(hookEventName) ? hookEventName : void 0;
76003
76479
  }
@@ -76008,7 +76484,9 @@ var require_hook = __commonJS({
76008
76484
  "pre-tool-use": "PreToolUse",
76009
76485
  "post-tool-use": "PostToolUse",
76010
76486
  stop: "Stop",
76011
- "pre-compact": "PreCompact"
76487
+ "pre-compact": "PreCompact",
76488
+ "subagent-start": "SubagentStart",
76489
+ "subagent-stop": "SubagentStop"
76012
76490
  };
76013
76491
  function extractToolFields(raw) {
76014
76492
  const toolName = typeof raw.tool_name === "string" ? raw.tool_name : "unknown";
@@ -76110,11 +76588,46 @@ var require_hook = __commonJS({
76110
76588
  }
76111
76589
  };
76112
76590
  }
76591
+ function buildSubagentStartEvent(context, input) {
76592
+ return {
76593
+ kind: "hook",
76594
+ hook: "SubagentStart",
76595
+ context,
76596
+ payload: {
76597
+ transcriptPath: input.transcriptPath,
76598
+ agentId: context.agentId,
76599
+ agentType: context.agentType
76600
+ }
76601
+ };
76602
+ }
76603
+ function buildSubagentStopEvent(context, input) {
76604
+ const raw = input.raw;
76605
+ const agentTranscriptPath = typeof raw.agent_transcript_path === "string" ? raw.agent_transcript_path : "";
76606
+ const lastAssistantMessage = typeof raw.last_assistant_message === "string" ? raw.last_assistant_message : "";
76607
+ const permissionMode = input.permissionMode ?? "default";
76608
+ const stopHookActive = typeof raw.stop_hook_active === "boolean" ? raw.stop_hook_active : void 0;
76609
+ return {
76610
+ kind: "hook",
76611
+ hook: "SubagentStop",
76612
+ context,
76613
+ payload: {
76614
+ transcriptPath: input.transcriptPath,
76615
+ permissionMode,
76616
+ agentId: context.agentId,
76617
+ agentType: context.agentType,
76618
+ agentTranscriptPath,
76619
+ lastAssistantMessage,
76620
+ ...stopHookActive !== void 0 && { stopHookActive }
76621
+ }
76622
+ };
76623
+ }
76113
76624
  function buildHookEvent(hookName, input, correlationId) {
76114
76625
  const context = {
76115
76626
  sessionId: input.sessionId,
76116
76627
  timestamp: Date.now(),
76117
- correlationId
76628
+ correlationId,
76629
+ ...input.agentId !== void 0 && { agentId: input.agentId },
76630
+ ...input.agentType !== void 0 && { agentType: input.agentType }
76118
76631
  };
76119
76632
  switch (hookName) {
76120
76633
  case "SessionStart":
@@ -76131,6 +76644,22 @@ var require_hook = __commonJS({
76131
76644
  return buildStopEvent(context, input);
76132
76645
  case "PreCompact":
76133
76646
  return buildPreCompactEvent(context, input);
76647
+ case "SubagentStart": {
76648
+ const subagentContext = {
76649
+ ...context,
76650
+ agentId: input.agentId ?? "",
76651
+ agentType: input.agentType ?? ""
76652
+ };
76653
+ return buildSubagentStartEvent(subagentContext, input);
76654
+ }
76655
+ case "SubagentStop": {
76656
+ const subagentContext = {
76657
+ ...context,
76658
+ agentId: input.agentId ?? "",
76659
+ agentType: input.agentType ?? ""
76660
+ };
76661
+ return buildSubagentStopEvent(subagentContext, input);
76662
+ }
76134
76663
  }
76135
76664
  }
76136
76665
  function mergeHookResponses(daemonResponse, cliResponse) {
@@ -76152,6 +76681,10 @@ ${daemonResponse.additionalContext}` : cliResponse.additionalContext;
76152
76681
  return merged;
76153
76682
  }
76154
76683
  async function handleHookCommand(hookName, options, logger, stdout) {
76684
+ if (process.env.SIDEKICK_SUBPROCESS === "1") {
76685
+ stdout.write("{}\n");
76686
+ return { exitCode: 0, output: "{}" };
76687
+ }
76155
76688
  const { projectRoot, hookInput, correlationId, runtime } = options;
76156
76689
  const startTime = Date.now();
76157
76690
  const logContext = {
@@ -76260,7 +76793,7 @@ var require_hook_command = __commonJS({
76260
76793
  return void 0;
76261
76794
  } catch (err) {
76262
76795
  logger.error("Failed to load safe-word-liveness.yaml", {
76263
- error: err instanceof Error ? err.message : String(err),
76796
+ error: (0, core_1.toErrorMessage)(err),
76264
76797
  projectRoot
76265
76798
  });
76266
76799
  return void 0;
@@ -76343,6 +76876,17 @@ var require_hook_command = __commonJS({
76343
76876
  addUserMessage(response, internal.userMessage);
76344
76877
  return response;
76345
76878
  }
76879
+ function translateSubagentStart(internal) {
76880
+ const response = {};
76881
+ if (internal.additionalContext) {
76882
+ response.hookSpecificOutput = {
76883
+ hookEventName: "SubagentStart",
76884
+ additionalContext: internal.additionalContext
76885
+ };
76886
+ }
76887
+ addUserMessage(response, internal.userMessage);
76888
+ return response;
76889
+ }
76346
76890
  var TRANSLATORS = {
76347
76891
  SessionStart: translateSessionStart,
76348
76892
  SessionEnd: () => ({}),
@@ -76350,7 +76894,10 @@ var require_hook_command = __commonJS({
76350
76894
  PreToolUse: translatePreToolUse,
76351
76895
  PostToolUse: translatePostToolUse,
76352
76896
  Stop: translateStop,
76353
- PreCompact: () => ({})
76897
+ PreCompact: () => ({}),
76898
+ SubagentStart: translateSubagentStart,
76899
+ // SubagentStop shares Stop's blocking semantics verbatim per Claude Code docs.
76900
+ SubagentStop: translateStop
76354
76901
  };
76355
76902
  function translateToClaudeCodeFormat(hookName, internal) {
76356
76903
  return TRANSLATORS[hookName](internal);
@@ -76363,13 +76910,17 @@ var require_hook_command = __commonJS({
76363
76910
  "post-tool-use": "PostToolUse",
76364
76911
  stop: "Stop",
76365
76912
  "pre-compact": "PreCompact",
76913
+ "subagent-start": "SubagentStart",
76914
+ "subagent-stop": "SubagentStop",
76366
76915
  SessionStart: "SessionStart",
76367
76916
  SessionEnd: "SessionEnd",
76368
76917
  UserPromptSubmit: "UserPromptSubmit",
76369
76918
  PreToolUse: "PreToolUse",
76370
76919
  PostToolUse: "PostToolUse",
76371
76920
  Stop: "Stop",
76372
- PreCompact: "PreCompact"
76921
+ PreCompact: "PreCompact",
76922
+ SubagentStart: "SubagentStart",
76923
+ SubagentStop: "SubagentStop"
76373
76924
  };
76374
76925
  function parseHookArg(arg) {
76375
76926
  return arg ? HOOK_ARG_TO_NAME[arg] : void 0;
@@ -76402,7 +76953,7 @@ var require_hook_command = __commonJS({
76402
76953
  return configured;
76403
76954
  } catch (err) {
76404
76955
  logger.warn("Failed to auto-configure project", {
76405
- error: err instanceof Error ? err.message : String(err),
76956
+ error: (0, core_1.toErrorMessage)(err),
76406
76957
  projectRoot
76407
76958
  });
76408
76959
  return false;
@@ -76415,7 +76966,7 @@ var require_hook_command = __commonJS({
76415
76966
  state = await setupService.getSetupState();
76416
76967
  } catch (err) {
76417
76968
  logger.warn("Failed to check setup state, assuming healthy", {
76418
- error: err instanceof Error ? err.message : String(err),
76969
+ error: (0, core_1.toErrorMessage)(err),
76419
76970
  hookName,
76420
76971
  projectRoot
76421
76972
  });
@@ -76453,7 +77004,7 @@ var require_hook_command = __commonJS({
76453
77004
  }
76454
77005
  } catch (err) {
76455
77006
  logger.warn("Failed to check setup status for daemon start, proceeding anyway", {
76456
- error: err instanceof Error ? err.message : String(err)
77007
+ error: (0, core_1.toErrorMessage)(err)
76457
77008
  });
76458
77009
  }
76459
77010
  try {
@@ -76463,7 +77014,7 @@ var require_hook_command = __commonJS({
76463
77014
  await (0, core_1.updateDaemonHealth)(projectRoot, "healthy", logger);
76464
77015
  return true;
76465
77016
  } catch (err) {
76466
- const errorMessage = err instanceof Error ? err.message : String(err);
77017
+ const errorMessage = (0, core_1.toErrorMessage)(err);
76467
77018
  await (0, core_1.updateDaemonHealth)(projectRoot, "failed", logger, errorMessage);
76468
77019
  return false;
76469
77020
  }
@@ -76476,13 +77027,17 @@ var require_hook_command = __commonJS({
76476
77027
  } catch (err) {
76477
77028
  logger.warn("Failed to parse internal hook response", {
76478
77029
  hookName,
76479
- error: err instanceof Error ? err.message : String(err),
77030
+ error: (0, core_1.toErrorMessage)(err),
76480
77031
  output
76481
77032
  });
76482
77033
  return {};
76483
77034
  }
76484
77035
  }
76485
77036
  async function handleUnifiedHookCommand(hookName, options, logger, stdout) {
77037
+ if (process.env.SIDEKICK_SUBPROCESS === "1") {
77038
+ stdout.write("{}\n");
77039
+ return { exitCode: 0, output: "{}" };
77040
+ }
76486
77041
  const { projectRoot, hookInput, correlationId, runtime, forceDevMode } = options;
76487
77042
  logger.debug("Unified hook command invoked", { hookName, sessionId: hookInput.sessionId });
76488
77043
  const devModeGuard = await (0, dev_mode_guard_js_1.checkDevModeConflict)(projectRoot, forceDevMode, logger, hookName);
@@ -77251,7 +77806,7 @@ var require_persona_selection = __commonJS({
77251
77806
  } catch (err) {
77252
77807
  ctx.logger.warn("Failed to ensure persona for session", {
77253
77808
  sessionId,
77254
- error: err instanceof Error ? err.message : String(err)
77809
+ error: (0, core_1.toErrorMessage)(err)
77255
77810
  });
77256
77811
  }
77257
77812
  }
@@ -78011,7 +78566,7 @@ var require_update_summary = __commonJS({
78011
78566
  ctx.logger.error("performAnalysis failed", {
78012
78567
  sessionId,
78013
78568
  reason,
78014
- error: err instanceof Error ? err.message : String(err)
78569
+ error: (0, core_1.toErrorMessage)(err)
78015
78570
  });
78016
78571
  }
78017
78572
  }
@@ -78413,7 +78968,7 @@ var require_resume_discovery = __commonJS({
78413
78968
  }
78414
78969
  config.logger?.warn("Failed to discover previous resume message", {
78415
78970
  sessionsDir: config.sessionsDir,
78416
- error: error instanceof Error ? error.message : String(error)
78971
+ error: (0, core_1.toErrorMessage)(error)
78417
78972
  });
78418
78973
  return NOT_FOUND;
78419
78974
  }
@@ -80170,7 +80725,7 @@ Examples:
80170
80725
  }
80171
80726
  const event = core_1.LogEvents.statuslineError(eventContext, "unknown", {
80172
80727
  fallbackUsed: true,
80173
- error: error instanceof Error ? error.message : String(error)
80728
+ error: (0, core_1.toErrorMessage)(error)
80174
80729
  });
80175
80730
  (0, core_1.logEvent)(logger, event);
80176
80731
  logger.warn("Statusline render failed", { durationMs });
@@ -80188,6 +80743,7 @@ var require_ui = __commonJS({
80188
80743
  exports2.handleUiCommand = handleUiCommand;
80189
80744
  var node_child_process_1 = require("node:child_process");
80190
80745
  var node_path_1 = require("node:path");
80746
+ var core_1 = require_dist4();
80191
80747
  function resolveUiPackageDir() {
80192
80748
  const cliCommandsDir = __dirname;
80193
80749
  const cliPackageDir = (0, node_path_1.resolve)(cliCommandsDir, "..", "..");
@@ -80217,7 +80773,7 @@ var require_ui = __commonJS({
80217
80773
  logger.debug("Browser open command executed", { command, url });
80218
80774
  } catch (err) {
80219
80775
  logger.warn("Failed to open browser", {
80220
- error: err instanceof Error ? err.message : String(err)
80776
+ error: (0, core_1.toErrorMessage)(err)
80221
80777
  });
80222
80778
  }
80223
80779
  }
@@ -80523,7 +81079,7 @@ var require_persona2 = __commonJS({
80523
81079
  }
80524
81080
  return writeJsonResponse(stdout, { success: true, personaId, previousPersonaId }, 0);
80525
81081
  } catch (err) {
80526
- const errorMsg = err instanceof Error ? err.message : String(err);
81082
+ const errorMsg = (0, core_1.toErrorMessage)(err);
80527
81083
  logger.error("Failed to set persona", { error: errorMsg });
80528
81084
  return writeJsonResponse(stdout, { success: false, error: errorMsg }, 1);
80529
81085
  }
@@ -80547,7 +81103,7 @@ var require_persona2 = __commonJS({
80547
81103
  logger.info("Persona cleared", { previousPersonaId: previousPersonaId ?? "(none)" });
80548
81104
  return writeJsonResponse(stdout, { success: true, personaId: null, previousPersonaId }, 0);
80549
81105
  } catch (err) {
80550
- const errorMsg = err instanceof Error ? err.message : String(err);
81106
+ const errorMsg = (0, core_1.toErrorMessage)(err);
80551
81107
  logger.error("Failed to clear persona", { error: errorMsg });
80552
81108
  return writeJsonResponse(stdout, { success: false, error: errorMsg }, 1);
80553
81109
  }
@@ -80592,7 +81148,7 @@ var require_persona2 = __commonJS({
80592
81148
  return writeJsonResponse(stdout, { error: `Failed to read generated file: ${statePath}` }, 1);
80593
81149
  }
80594
81150
  } catch (err) {
80595
- const errorMsg = err instanceof Error ? err.message : String(err);
81151
+ const errorMsg = (0, core_1.toErrorMessage)(err);
80596
81152
  logger.error("Persona test failed", { error: errorMsg });
80597
81153
  return writeJsonResponse(stdout, { error: errorMsg }, 1);
80598
81154
  } finally {
@@ -80620,7 +81176,7 @@ var require_persona2 = __commonJS({
80620
81176
  filePath: result.filePath
80621
81177
  }, 0);
80622
81178
  } catch (err) {
80623
- const errorMsg = err instanceof Error ? err.message : String(err);
81179
+ const errorMsg = (0, core_1.toErrorMessage)(err);
80624
81180
  logger.error("Failed to pin persona", { error: errorMsg });
80625
81181
  return writeJsonResponse(stdout, { success: false, error: errorMsg }, 1);
80626
81182
  }
@@ -80644,7 +81200,7 @@ var require_persona2 = __commonJS({
80644
81200
  previousPersonaId
80645
81201
  }, 0);
80646
81202
  } catch (err) {
80647
- const errorMsg = err instanceof Error ? err.message : String(err);
81203
+ const errorMsg = (0, core_1.toErrorMessage)(err);
80648
81204
  logger.error("Failed to unpin persona", { error: errorMsg });
80649
81205
  return writeJsonResponse(stdout, { success: false, error: errorMsg }, 1);
80650
81206
  }
@@ -80755,7 +81311,7 @@ var require_config3 = __commonJS({
80755
81311
  logger
80756
81312
  });
80757
81313
  } catch (err) {
80758
- const message = err instanceof Error ? err.message : String(err);
81314
+ const message = (0, core_1.toErrorMessage)(err);
80759
81315
  const error = `Error: ${message}`;
80760
81316
  stdout.write(error + "\n");
80761
81317
  return { exitCode: 1, output: error };
@@ -80801,7 +81357,7 @@ var require_config3 = __commonJS({
80801
81357
  stdout.write(output + "\n");
80802
81358
  return { exitCode: 0, output };
80803
81359
  } catch (err) {
80804
- const message = err instanceof Error ? err.message : String(err);
81360
+ const message = (0, core_1.toErrorMessage)(err);
80805
81361
  const error = `Error: ${message}`;
80806
81362
  stdout.write(error + "\n");
80807
81363
  return { exitCode: 1, output: error };
@@ -80830,7 +81386,7 @@ var require_config3 = __commonJS({
80830
81386
  stdout.write(output + "\n");
80831
81387
  return { exitCode: 0, output };
80832
81388
  } catch (err) {
80833
- const message = err instanceof Error ? err.message : String(err);
81389
+ const message = (0, core_1.toErrorMessage)(err);
80834
81390
  const error = `Error: ${message}`;
80835
81391
  stdout.write(error + "\n");
80836
81392
  return { exitCode: 1, output: error };
@@ -80859,7 +81415,7 @@ var require_config3 = __commonJS({
80859
81415
  stdout.write(output + "\n");
80860
81416
  return { exitCode: 0, output };
80861
81417
  } catch (err) {
80862
- const message = err instanceof Error ? err.message : String(err);
81418
+ const message = (0, core_1.toErrorMessage)(err);
80863
81419
  const error = `Error: ${message}`;
80864
81420
  stdout.write(error + "\n");
80865
81421
  return { exitCode: 1, output: error };
@@ -81085,7 +81641,7 @@ Examples:
81085
81641
  logger.info("Listed sessions", { count: sessions.length });
81086
81642
  return { exitCode: 0, output: JSON.stringify({ count: sessions.length }) };
81087
81643
  } catch (err) {
81088
- const errorMsg = err instanceof Error ? err.message : String(err);
81644
+ const errorMsg = (0, core_1.toErrorMessage)(err);
81089
81645
  logger.error("Failed to list sessions", { error: errorMsg });
81090
81646
  stdout.write(JSON.stringify({ error: errorMsg }, null, 2) + "\n");
81091
81647
  return { exitCode: 1, output: errorMsg };
@@ -81738,14 +82294,63 @@ var require_dev_mode = __commonJS({
81738
82294
  log(stdout, "info", "Full clean complete.");
81739
82295
  return { exitCode: 0 };
81740
82296
  }
82297
+ async function doCleanAllProjects(logger, stdout, options = {}) {
82298
+ const { force = false, stdin = process.stdin } = options;
82299
+ const registryRoot = node_path_1.default.join(node_os_1.default.homedir(), ".sidekick", "projects");
82300
+ const registry = new core_1.ProjectRegistryService(registryRoot);
82301
+ const projects = await registry.list();
82302
+ if (projects.length === 0) {
82303
+ log(stdout, "info", `No registered projects found in ${registryRoot}`);
82304
+ return { exitCode: 0 };
82305
+ }
82306
+ log(stdout, "step", `Found ${projects.length} registered project(s):`);
82307
+ for (const project of projects) {
82308
+ stdout.write(` - ${project.displayName} (${project.path})
82309
+ `);
82310
+ }
82311
+ stdout.write("\n");
82312
+ let cleanedCount = 0;
82313
+ let skippedCount = 0;
82314
+ for (const project of projects) {
82315
+ let projectStats;
82316
+ try {
82317
+ projectStats = await (0, promises_12.stat)(project.path);
82318
+ } catch {
82319
+ log(stdout, "warn", `${project.displayName}: directory not found at ${project.path}, skipping`);
82320
+ skippedCount++;
82321
+ continue;
82322
+ }
82323
+ if (!projectStats.isDirectory()) {
82324
+ log(stdout, "warn", `${project.displayName}: path is not a directory at ${project.path}, skipping`);
82325
+ skippedCount++;
82326
+ continue;
82327
+ }
82328
+ if (!force) {
82329
+ const shouldClean = await (0, prompt_js_1.promptConfirm)({ stdin, stdout }, `Clean ${project.displayName} (${project.path})?`);
82330
+ if (!shouldClean) {
82331
+ log(stdout, "info", `Skipping ${project.displayName}`);
82332
+ skippedCount++;
82333
+ continue;
82334
+ }
82335
+ }
82336
+ stdout.write("\n");
82337
+ log(stdout, "step", `Cleaning ${project.displayName}...`);
82338
+ await doClean(project.path, logger, stdout, { force, stdin });
82339
+ cleanedCount++;
82340
+ }
82341
+ stdout.write("\n");
82342
+ log(stdout, "info", `Clean-all-projects complete: cleaned ${cleanedCount} project(s), skipped ${skippedCount}.`);
82343
+ return { exitCode: 0 };
82344
+ }
81741
82345
  var USAGE_TEXT = `Usage: sidekick dev-mode <command> [options]
81742
82346
 
81743
82347
  Commands:
81744
- enable Add dev-sidekick to .claude/settings.local.json
81745
- disable Remove dev-sidekick from settings.local.json
81746
- status Show current dev-mode state
81747
- clean Truncate logs, kill daemon, clean state folders
81748
- clean-all Full cleanup: clean + remove logs/sessions/state dirs
82348
+ enable Add dev-sidekick to .claude/settings.local.json
82349
+ disable Remove dev-sidekick from settings.local.json
82350
+ status Show current dev-mode state
82351
+ clean Truncate logs, kill daemon, clean state folders
82352
+ clean-all Full cleanup: clean + remove logs/sessions/state dirs
82353
+ clean-all-projects Clean all registered projects in ~/.sidekick/projects/
81749
82354
 
81750
82355
  Options:
81751
82356
  --force Skip confirmation prompts for destructive operations
@@ -81762,6 +82367,8 @@ Options:
81762
82367
  return doClean(projectDir, logger, stdout, options);
81763
82368
  case "clean-all":
81764
82369
  return doCleanAll(projectDir, logger, stdout, options);
82370
+ case "clean-all-projects":
82371
+ return doCleanAllProjects(logger, stdout, options);
81765
82372
  case "help":
81766
82373
  case "--help":
81767
82374
  case "-h":
@@ -82533,6 +83140,7 @@ var require_helpers = __commonJS({
82533
83140
  exports2.getPluginStatusLabel = getPluginStatusLabel;
82534
83141
  exports2.getApiKeyStatusType = getApiKeyStatusType;
82535
83142
  exports2.getPluginStatusIcon = getPluginStatusIcon;
83143
+ exports2.isPluginPresent = isPluginPresent;
82536
83144
  exports2.getLivenessIcon = getLivenessIcon;
82537
83145
  exports2.getLivenessLabel = getLivenessLabel;
82538
83146
  exports2.formatApiKeyScopes = formatApiKeyScopes;
@@ -82615,7 +83223,7 @@ var require_helpers = __commonJS({
82615
83223
  case "dev-mode":
82616
83224
  return "dev-mode (local)";
82617
83225
  case "both":
82618
- return "conflict (both plugin and dev-mode detected!)";
83226
+ return "plugin and dev-mode both active";
82619
83227
  case "none":
82620
83228
  return "not installed";
82621
83229
  case "timeout":
@@ -82640,6 +83248,7 @@ var require_helpers = __commonJS({
82640
83248
  case "dev-mode":
82641
83249
  return "\u2713";
82642
83250
  case "both":
83251
+ return "\u2022";
82643
83252
  case "timeout":
82644
83253
  case "error":
82645
83254
  return "\u26A0";
@@ -82647,6 +83256,9 @@ var require_helpers = __commonJS({
82647
83256
  return "\u2717";
82648
83257
  }
82649
83258
  }
83259
+ function isPluginPresent(status) {
83260
+ return status === "plugin" || status === "dev-mode" || status === "both";
83261
+ }
82650
83262
  function getLivenessIcon(status) {
82651
83263
  switch (status) {
82652
83264
  case "active":
@@ -82750,8 +83362,74 @@ var require_doctor = __commonJS({
82750
83362
  "liveness",
82751
83363
  "zombies",
82752
83364
  "auto-config",
82753
- "shell-alias"
83365
+ "shell-alias",
83366
+ "llm-config"
82754
83367
  ];
83368
+ var DEPRECATED_LLM_MODELS = [
83369
+ {
83370
+ model: "google/gemini-2.0-flash-lite-001",
83371
+ message: "Your llm.yaml references google/gemini-2.0-flash-lite-001, which Google deprecates in June 2026. Sidekick's default has moved to google/gemini-2.5-flash-lite. Update your override or accept the new default."
83372
+ }
83373
+ ];
83374
+ function collectLlmYamlModels(parsed) {
83375
+ if (!parsed)
83376
+ return [];
83377
+ const models = [];
83378
+ for (const key of ["profiles", "fallbackProfiles"]) {
83379
+ const section = parsed[key];
83380
+ if (!section || typeof section !== "object")
83381
+ continue;
83382
+ for (const profile of Object.values(section)) {
83383
+ if (profile && typeof profile === "object") {
83384
+ const model = profile.model;
83385
+ if (typeof model === "string") {
83386
+ models.push(model);
83387
+ }
83388
+ }
83389
+ }
83390
+ }
83391
+ return models;
83392
+ }
83393
+ function runLlmConfigCheck(projectDir, homeDir, stdout, logger) {
83394
+ const candidatePaths = [path.join(homeDir, ".sidekick", "llm.yaml"), path.join(projectDir, ".sidekick", "llm.yaml")];
83395
+ const matched = /* @__PURE__ */ new Set();
83396
+ const parseFailures = [];
83397
+ for (const yamlPath of candidatePaths) {
83398
+ let parsed;
83399
+ try {
83400
+ parsed = (0, core_1.tryReadYaml)(yamlPath);
83401
+ } catch (err) {
83402
+ logger.warn("Failed to parse llm.yaml during migration check", {
83403
+ path: yamlPath,
83404
+ error: (0, core_1.toErrorMessage)(err)
83405
+ });
83406
+ parseFailures.push(yamlPath);
83407
+ continue;
83408
+ }
83409
+ if (!parsed)
83410
+ continue;
83411
+ const models = collectLlmYamlModels(parsed);
83412
+ for (const { model, message } of DEPRECATED_LLM_MODELS) {
83413
+ if (models.includes(model) && !matched.has(model)) {
83414
+ matched.add(model);
83415
+ logger.warn("Deprecated LLM model referenced in user override", {
83416
+ path: yamlPath,
83417
+ model
83418
+ });
83419
+ stdout.write(`\u26A0 ${message}
83420
+ `);
83421
+ }
83422
+ }
83423
+ }
83424
+ if (parseFailures.length > 0) {
83425
+ stdout.write(`\u26A0 LLM Config: could not be parsed (${parseFailures.join(", ")}) \u2014 deprecation check skipped
83426
+ `);
83427
+ return;
83428
+ }
83429
+ if (matched.size === 0) {
83430
+ stdout.write("\u2713 LLM Config: no deprecated models referenced\n");
83431
+ }
83432
+ }
82755
83433
  function parseDoctorOnly(only) {
82756
83434
  if (!only)
82757
83435
  return null;
@@ -82762,6 +83440,13 @@ var require_doctor = __commonJS({
82762
83440
  }
82763
83441
  return new Set(requested);
82764
83442
  }
83443
+ async function tryRemoveLegacySection(projectDir) {
83444
+ try {
83445
+ return await (0, core_1.removeLegacyGitignoreSection)(projectDir);
83446
+ } catch {
83447
+ return false;
83448
+ }
83449
+ }
82765
83450
  async function runDoctorFixes(projectDir, logger, stdout, context) {
82766
83451
  const { homeDir, filter, doctorResult, gitignore, pluginStatus, liveness } = context;
82767
83452
  const isFullMode = filter === null;
@@ -82803,15 +83488,40 @@ var require_doctor = __commonJS({
82803
83488
  stdout.write(" \u26A0 Statusline managed by dev-mode (skipped)\n");
82804
83489
  }
82805
83490
  }
82806
- if (shouldFix("gitignore") && gitignore !== null && gitignore !== "installed") {
82807
- stdout.write("Fixing: Gitignore\n");
82808
- const result = await (0, core_1.installGitignoreSection)(projectDir);
82809
- if (result.status === "error") {
82810
- stdout.write(` \u26A0 Failed to update .gitignore: ${result.error}
83491
+ if (shouldFix("gitignore") && gitignore !== null) {
83492
+ if (gitignore === "legacy") {
83493
+ stdout.write("Fixing: Gitignore (migrating legacy format)\n");
83494
+ const result = await (0, core_1.installGitignoreSection)(projectDir);
83495
+ if (result.status === "error") {
83496
+ stdout.write(` \u26A0 Failed to create .sidekick/.gitignore: ${result.error}
82811
83497
  `);
83498
+ } else {
83499
+ const legacyRemoved = await tryRemoveLegacySection(projectDir);
83500
+ stdout.write(legacyRemoved ? " \u2713 Migrated to .sidekick/.gitignore and removed legacy root section\n" : " \u26A0 Created .sidekick/.gitignore, but legacy root section could not be removed\n");
83501
+ fixedCount++;
83502
+ }
83503
+ } else if (gitignore === "installed") {
83504
+ const hasLegacy = await (0, core_1.detectLegacyGitignoreSection)(projectDir);
83505
+ if (hasLegacy) {
83506
+ stdout.write("Fixing: Gitignore (removing redundant legacy section)\n");
83507
+ const legacyRemoved = await tryRemoveLegacySection(projectDir);
83508
+ if (legacyRemoved) {
83509
+ stdout.write(" \u2713 Removed legacy section from root .gitignore\n");
83510
+ fixedCount++;
83511
+ } else {
83512
+ stdout.write(" \u26A0 Legacy section detected but could not be removed from root .gitignore\n");
83513
+ }
83514
+ }
82812
83515
  } else {
82813
- stdout.write(" \u2713 Gitignore configured\n");
82814
- fixedCount++;
83516
+ stdout.write("Fixing: Gitignore\n");
83517
+ const result = await (0, core_1.installGitignoreSection)(projectDir);
83518
+ if (result.status === "error") {
83519
+ stdout.write(` \u26A0 Failed to update .sidekick/.gitignore: ${result.error}
83520
+ `);
83521
+ } else {
83522
+ stdout.write(" \u2713 Gitignore configured\n");
83523
+ fixedCount++;
83524
+ }
82815
83525
  }
82816
83526
  }
82817
83527
  if (shouldFix("plugin") && pluginStatus === "none") {
@@ -82833,7 +83543,7 @@ var require_doctor = __commonJS({
82833
83543
  fixedCount++;
82834
83544
  }
82835
83545
  } catch (err) {
82836
- stdout.write(` \u26A0 Plugin installation failed: ${err instanceof Error ? err.message : String(err)}
83546
+ stdout.write(` \u26A0 Plugin installation failed: ${(0, core_1.toErrorMessage)(err)}
82837
83547
  `);
82838
83548
  }
82839
83549
  }
@@ -82903,7 +83613,7 @@ var require_doctor = __commonJS({
82903
83613
  try {
82904
83614
  filter = parseDoctorOnly(options?.only);
82905
83615
  } catch (err) {
82906
- stdout.write(`${err instanceof Error ? err.message : String(err)}
83616
+ stdout.write(`${(0, core_1.toErrorMessage)(err)}
82907
83617
  `);
82908
83618
  return { exitCode: 1 };
82909
83619
  }
@@ -82953,7 +83663,12 @@ var require_doctor = __commonJS({
82953
83663
  promises.push((0, core_1.detectGitignoreStatus)(projectDir).then((result) => {
82954
83664
  gitignore = result;
82955
83665
  const gitignoreIcon = result === "installed" ? "\u2713" : "\u26A0";
82956
- stdout.write(`${gitignoreIcon} Gitignore: ${result}
83666
+ const gitignoreMessage = result === "legacy" ? `legacy section found in root .gitignore \u2014 run sidekick doctor --fix --only=gitignore to migrate` : result;
83667
+ stdout.write(`${gitignoreIcon} Gitignore: ${gitignoreMessage}
83668
+ `);
83669
+ }).catch((err) => {
83670
+ gitignore = "unknown";
83671
+ stdout.write(`\u26A0 Gitignore: could not read status \u2014 ${err.message}
82957
83672
  `);
82958
83673
  }));
82959
83674
  }
@@ -82968,8 +83683,7 @@ var require_doctor = __commonJS({
82968
83683
  stdout.write(`${pluginIcon} Plugin: ${pluginLabel}
82969
83684
  `);
82970
83685
  }
82971
- const isPluginPresent = status === "plugin" || status === "dev-mode" || status === "both";
82972
- if (shouldRun("liveness") && isPluginPresent) {
83686
+ if (shouldRun("liveness") && (0, helpers_js_1.isPluginPresent)(status)) {
82973
83687
  logger.info("Starting plugin liveness check");
82974
83688
  liveness = await setupService.detectPluginLiveness();
82975
83689
  const livenessIcon = (0, helpers_js_1.getLivenessIcon)(liveness);
@@ -82991,6 +83705,9 @@ var require_doctor = __commonJS({
82991
83705
  }));
82992
83706
  }
82993
83707
  await Promise.all(promises);
83708
+ if (shouldRun("llm-config")) {
83709
+ runLlmConfigCheck(projectDir, homeDir, stdout, logger);
83710
+ }
82994
83711
  if (shouldRun("auto-config")) {
82995
83712
  const userStatus = await setupService.getUserStatus();
82996
83713
  if (userStatus?.preferences.autoConfigureProjects) {
@@ -83016,7 +83733,7 @@ var require_doctor = __commonJS({
83016
83733
  }
83017
83734
  }
83018
83735
  if (filter === null) {
83019
- const isPluginOk = pluginStatus === "plugin" || pluginStatus === "dev-mode";
83736
+ const isPluginOk = (0, helpers_js_1.isPluginPresent)(pluginStatus);
83020
83737
  const isPluginLive = liveness === null || liveness === "active";
83021
83738
  const isHealthy = doctorResult.overallHealth === "healthy" && gitignore === "installed" && isPluginOk && isPluginLive && zombieCount === 0;
83022
83739
  const overallIcon = isHealthy ? "\u2713" : "\u26A0";
@@ -83456,12 +84173,18 @@ Examples:
83456
84173
  }
83457
84174
  async function runStep3Gitignore(wctx, force) {
83458
84175
  const { ctx, projectDir } = wctx;
83459
- const currentStatus = await (0, core_1.detectGitignoreStatus)(projectDir);
83460
- if (currentStatus === "installed") {
84176
+ let currentStatus;
84177
+ try {
84178
+ currentStatus = await (0, core_1.detectGitignoreStatus)(projectDir);
84179
+ } catch {
84180
+ currentStatus = "missing";
84181
+ }
84182
+ if (currentStatus === "installed" || currentStatus === "legacy") {
83461
84183
  if (!force) {
83462
- (0, prompts_js_1.printStatus)(ctx, "success", "Sidekick entries already present in .gitignore");
84184
+ const message2 = currentStatus === "legacy" ? "Sidekick entries already present in root .gitignore (legacy \u2014 run doctor --fix to migrate)" : "Sidekick already configured (.sidekick/.gitignore)";
84185
+ (0, prompts_js_1.printStatus)(ctx, "success", message2);
83463
84186
  }
83464
- return "installed";
84187
+ return currentStatus;
83465
84188
  }
83466
84189
  const needsRepair = currentStatus === "incomplete";
83467
84190
  if (force) {
@@ -83934,7 +84657,6 @@ var require_uninstall = __commonJS({
83934
84657
  await removeFile(path.join(userHome, ".sidekick", core_1.USER_STATUS_FILENAME), "user", core_1.USER_STATUS_FILENAME, actions, {
83935
84658
  dryRun
83936
84659
  });
83937
- await removeFile(path.join(userHome, ".sidekick", core_1.LEGACY_USER_STATUS_FILENAME), "user", core_1.LEGACY_USER_STATUS_FILENAME, actions, { dryRun });
83938
84660
  await removeFile(path.join(userHome, ".sidekick", "features.yaml"), "user", "features.yaml", actions, { dryRun });
83939
84661
  }
83940
84662
  if (projectDetected) {
@@ -84031,11 +84753,6 @@ var require_uninstall = __commonJS({
84031
84753
  try {
84032
84754
  await fs.access(path.join(userHome, ".sidekick", core_1.USER_STATUS_FILENAME));
84033
84755
  return true;
84034
- } catch {
84035
- }
84036
- try {
84037
- await fs.access(path.join(userHome, ".sidekick", core_1.LEGACY_USER_STATUS_FILENAME));
84038
- return true;
84039
84756
  } catch {
84040
84757
  try {
84041
84758
  const content = await fs.readFile(path.join(userHome, ".claude", "settings.json"), "utf-8");
@@ -84106,8 +84823,12 @@ var require_uninstall = __commonJS({
84106
84823
  summary.project.push({ label: ".env", details: envDetail });
84107
84824
  }
84108
84825
  if (!devModeActive) {
84109
- const gitignore = await (0, fs_js_1.readFileOrNull)(path.join(projectDir, ".gitignore"));
84110
- if (gitignore?.includes("# >>> sidekick")) {
84826
+ const sidekickGitignore = await (0, fs_js_1.readFileOrNull)(path.join(projectDir, ".sidekick", ".gitignore"));
84827
+ const rootGitignore = await (0, fs_js_1.readFileOrNull)(path.join(projectDir, ".gitignore"));
84828
+ if (sidekickGitignore !== null) {
84829
+ summary.project.push({ label: ".sidekick/.gitignore", details: "sidekick managed file" });
84830
+ }
84831
+ if (rootGitignore?.includes("# >>> sidekick")) {
84111
84832
  summary.project.push({ label: ".gitignore", details: "sidekick section" });
84112
84833
  }
84113
84834
  }
@@ -84124,11 +84845,7 @@ var require_uninstall = __commonJS({
84124
84845
  } catch {
84125
84846
  }
84126
84847
  }
84127
- const userConfigFiles = await detectExistingItems(userHome, [
84128
- core_1.USER_STATUS_FILENAME,
84129
- core_1.LEGACY_USER_STATUS_FILENAME,
84130
- "features.yaml"
84131
- ]);
84848
+ const userConfigFiles = await detectExistingItems(userHome, [core_1.USER_STATUS_FILENAME, "features.yaml"]);
84132
84849
  if (userConfigFiles.length > 0) {
84133
84850
  summary.user.push({ label: "Config", details: userConfigFiles.join(", ") });
84134
84851
  }
@@ -84506,7 +85223,7 @@ var require_cli = __commonJS({
84506
85223
  var promises_12 = require("node:fs/promises");
84507
85224
  var node_stream_1 = require("node:stream");
84508
85225
  var yargs_parser_1 = __importDefault2(require_build());
84509
- var VERSION = true ? "0.1.18" : "dev";
85226
+ var VERSION = true ? "0.1.20" : "dev";
84510
85227
  var SANDBOX_ERROR_MESSAGE = `Error: Daemon commands cannot run in sandbox mode.
84511
85228
 
84512
85229
  Claude Code's sandbox blocks Unix socket operations required for daemon IPC.
@@ -84639,6 +85356,8 @@ Example: { "command": "pnpm sidekick daemon status", "dangerouslyDisableSandbox"
84639
85356
  const cwd = typeof raw.cwd === "string" ? raw.cwd : void 0;
84640
85357
  const hookEventName = typeof raw.hook_event_name === "string" ? raw.hook_event_name : void 0;
84641
85358
  const permissionMode = typeof raw.permission_mode === "string" ? raw.permission_mode : void 0;
85359
+ const agentId = typeof raw.agent_id === "string" ? raw.agent_id : void 0;
85360
+ const agentType = typeof raw.agent_type === "string" ? raw.agent_type : void 0;
84642
85361
  if (!sessionId) {
84643
85362
  return void 0;
84644
85363
  }
@@ -84649,6 +85368,8 @@ Example: { "command": "pnpm sidekick daemon status", "dangerouslyDisableSandbox"
84649
85368
  // Optional - some hooks (Stop, SessionStart) may not include cwd
84650
85369
  hookEventName: hookEventName ?? "unknown",
84651
85370
  permissionMode,
85371
+ agentId,
85372
+ agentType,
84652
85373
  raw
84653
85374
  };
84654
85375
  } catch {
@@ -84946,7 +85667,7 @@ Run 'sidekick help' for available commands.
84946
85667
  } catch (err) {
84947
85668
  logger.warn("Failed to persist CLI log metrics", {
84948
85669
  sessionId,
84949
- error: err instanceof Error ? err.message : String(err)
85670
+ error: (0, core_1.toErrorMessage)(err)
84950
85671
  });
84951
85672
  }
84952
85673
  }