@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/assets/sidekick/defaults/core.defaults.yaml +2 -2
- package/assets/sidekick/defaults/llm.defaults.yaml +7 -3
- package/dist/bin.js +1072 -351
- package/dist/daemon.js +779 -292
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -62,6 +62,8 @@ var require_hook_events = __commonJS({
|
|
|
62
62
|
exports2.isPostToolUseEvent = isPostToolUseEvent;
|
|
63
63
|
exports2.isStopEvent = isStopEvent;
|
|
64
64
|
exports2.isPreCompactEvent = isPreCompactEvent;
|
|
65
|
+
exports2.isSubagentStartEvent = isSubagentStartEvent;
|
|
66
|
+
exports2.isSubagentStopEvent = isSubagentStopEvent;
|
|
65
67
|
exports2.HOOK_NAMES = [
|
|
66
68
|
"SessionStart",
|
|
67
69
|
"SessionEnd",
|
|
@@ -69,7 +71,9 @@ var require_hook_events = __commonJS({
|
|
|
69
71
|
"PreToolUse",
|
|
70
72
|
"PostToolUse",
|
|
71
73
|
"Stop",
|
|
72
|
-
"PreCompact"
|
|
74
|
+
"PreCompact",
|
|
75
|
+
"SubagentStart",
|
|
76
|
+
"SubagentStop"
|
|
73
77
|
];
|
|
74
78
|
function isSessionStartEvent(event) {
|
|
75
79
|
return event.hook === "SessionStart";
|
|
@@ -92,6 +96,12 @@ var require_hook_events = __commonJS({
|
|
|
92
96
|
function isPreCompactEvent(event) {
|
|
93
97
|
return event.hook === "PreCompact";
|
|
94
98
|
}
|
|
99
|
+
function isSubagentStartEvent(event) {
|
|
100
|
+
return event.hook === "SubagentStart";
|
|
101
|
+
}
|
|
102
|
+
function isSubagentStopEvent(event) {
|
|
103
|
+
return event.hook === "SubagentStop";
|
|
104
|
+
}
|
|
95
105
|
}
|
|
96
106
|
});
|
|
97
107
|
|
|
@@ -16966,7 +16976,7 @@ var require_hook_input = __commonJS({
|
|
|
16966
16976
|
"../types/dist/hook-input.js"(exports2) {
|
|
16967
16977
|
"use strict";
|
|
16968
16978
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16969
|
-
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;
|
|
16979
|
+
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;
|
|
16970
16980
|
var zod_1 = require_zod();
|
|
16971
16981
|
exports2.HookInputBaseSchema = zod_1.z.object({
|
|
16972
16982
|
/** Unique identifier for the current Claude session */
|
|
@@ -16978,7 +16988,11 @@ var require_hook_input = __commonJS({
|
|
|
16978
16988
|
/** Current permission level: "default", "plan", "acceptEdits", or "bypassPermissions" */
|
|
16979
16989
|
permission_mode: zod_1.z.string().optional(),
|
|
16980
16990
|
/** Name of the triggered hook (e.g., "UserPromptSubmit", "SessionStart") */
|
|
16981
|
-
hook_event_name: zod_1.z.string()
|
|
16991
|
+
hook_event_name: zod_1.z.string(),
|
|
16992
|
+
/** Unique identifier for the subagent (present when hook fires inside a subagent) */
|
|
16993
|
+
agent_id: zod_1.z.string().optional(),
|
|
16994
|
+
/** Agent type/name: "Bash", "Explore", "Plan", or custom (present when inside a subagent) */
|
|
16995
|
+
agent_type: zod_1.z.string().optional()
|
|
16982
16996
|
});
|
|
16983
16997
|
exports2.UserPromptSubmitInputSchema = exports2.HookInputBaseSchema.extend({
|
|
16984
16998
|
/** The user's message text */
|
|
@@ -17026,6 +17040,26 @@ var require_hook_input = __commonJS({
|
|
|
17026
17040
|
/** Type: "permission_prompt", "idle_prompt", "auth_success", or "elicitation_dialog" */
|
|
17027
17041
|
notification_type: zod_1.z.string()
|
|
17028
17042
|
});
|
|
17043
|
+
exports2.SubagentStartInputSchema = exports2.HookInputBaseSchema.extend({
|
|
17044
|
+
/** Unique identifier for the subagent (required per official docs) */
|
|
17045
|
+
agent_id: zod_1.z.string(),
|
|
17046
|
+
/** Agent name: "Bash", "Explore", "Plan", or custom agent name */
|
|
17047
|
+
agent_type: zod_1.z.string()
|
|
17048
|
+
});
|
|
17049
|
+
exports2.SubagentStopInputSchema = exports2.HookInputBaseSchema.extend({
|
|
17050
|
+
/** Unique identifier for the subagent */
|
|
17051
|
+
agent_id: zod_1.z.string(),
|
|
17052
|
+
/** Agent name */
|
|
17053
|
+
agent_type: zod_1.z.string(),
|
|
17054
|
+
/** Path to subagent's own transcript JSONL */
|
|
17055
|
+
agent_transcript_path: zod_1.z.string(),
|
|
17056
|
+
/** Text content of the subagent's final response */
|
|
17057
|
+
last_assistant_message: zod_1.z.string(),
|
|
17058
|
+
/** Permission mode for the subagent session */
|
|
17059
|
+
permission_mode: zod_1.z.string(),
|
|
17060
|
+
/** Optional: whether stop hook is active (probe doc says never populated; official docs show false) */
|
|
17061
|
+
stop_hook_active: zod_1.z.boolean().optional()
|
|
17062
|
+
});
|
|
17029
17063
|
exports2.StatuslineModelSchema = zod_1.z.object({
|
|
17030
17064
|
/** Full model identifier (e.g., "claude-opus-4-1") */
|
|
17031
17065
|
id: zod_1.z.string(),
|
|
@@ -17081,13 +17115,15 @@ var require_hook_input = __commonJS({
|
|
|
17081
17115
|
output_style: zod_1.z.object({ name: zod_1.z.string() }).optional()
|
|
17082
17116
|
});
|
|
17083
17117
|
exports2.HookInputSchema = zod_1.z.union([
|
|
17118
|
+
exports2.SessionStartInputSchema,
|
|
17119
|
+
exports2.SessionEndInputSchema,
|
|
17084
17120
|
exports2.UserPromptSubmitInputSchema,
|
|
17085
17121
|
exports2.PreToolUseInputSchema,
|
|
17086
17122
|
exports2.PostToolUseInputSchema,
|
|
17087
17123
|
exports2.StopInputSchema,
|
|
17088
|
-
exports2.SessionStartInputSchema,
|
|
17089
|
-
exports2.SessionEndInputSchema,
|
|
17090
17124
|
exports2.PreCompactInputSchema,
|
|
17125
|
+
exports2.SubagentStartInputSchema,
|
|
17126
|
+
exports2.SubagentStopInputSchema,
|
|
17091
17127
|
exports2.NotificationInputSchema,
|
|
17092
17128
|
exports2.HookInputBaseSchema
|
|
17093
17129
|
// Fallback for hooks without extra fields
|
|
@@ -17184,9 +17220,11 @@ var require_setup_status = __commonJS({
|
|
|
17184
17220
|
"missing",
|
|
17185
17221
|
// User declined or entries not present
|
|
17186
17222
|
"incomplete",
|
|
17187
|
-
//
|
|
17188
|
-
"installed"
|
|
17189
|
-
//
|
|
17223
|
+
// .sidekick/.gitignore exists but missing required entries (legacy: partial root section)
|
|
17224
|
+
"installed",
|
|
17225
|
+
// .sidekick/.gitignore present with all entries (new format)
|
|
17226
|
+
"legacy"
|
|
17227
|
+
// Root .gitignore has old marked section — functional, migrate recommended
|
|
17190
17228
|
]);
|
|
17191
17229
|
exports2.ProjectApiKeyValueSchema = zod_1.z.union([exports2.ProjectApiKeyHealthSchema, exports2.ProjectApiKeyStatusSchema]);
|
|
17192
17230
|
exports2.ProjectSetupStatusSchema = zod_1.z.object({
|
|
@@ -26223,6 +26261,18 @@ var require_dist2 = __commonJS({
|
|
|
26223
26261
|
}
|
|
26224
26262
|
});
|
|
26225
26263
|
|
|
26264
|
+
// ../sidekick-core/dist/error-utils.js
|
|
26265
|
+
var require_error_utils = __commonJS({
|
|
26266
|
+
"../sidekick-core/dist/error-utils.js"(exports2) {
|
|
26267
|
+
"use strict";
|
|
26268
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
26269
|
+
exports2.toErrorMessage = toErrorMessage;
|
|
26270
|
+
function toErrorMessage(error) {
|
|
26271
|
+
return error instanceof Error ? error.message : String(error);
|
|
26272
|
+
}
|
|
26273
|
+
}
|
|
26274
|
+
});
|
|
26275
|
+
|
|
26226
26276
|
// ../sidekick-core/dist/assets.js
|
|
26227
26277
|
var require_assets = __commonJS({
|
|
26228
26278
|
"../sidekick-core/dist/assets.js"(exports2) {
|
|
@@ -26236,6 +26286,7 @@ var require_assets = __commonJS({
|
|
|
26236
26286
|
var yaml_1 = require_dist2();
|
|
26237
26287
|
var node_os_1 = require("node:os");
|
|
26238
26288
|
var node_path_1 = require("node:path");
|
|
26289
|
+
var error_utils_js_1 = require_error_utils();
|
|
26239
26290
|
function createCascadingResolver(options) {
|
|
26240
26291
|
const { cascadeLayers } = options;
|
|
26241
26292
|
const findFile = (relativePath) => {
|
|
@@ -26285,7 +26336,7 @@ var require_assets = __commonJS({
|
|
|
26285
26336
|
try {
|
|
26286
26337
|
return (0, yaml_1.parse)(content);
|
|
26287
26338
|
} catch (error) {
|
|
26288
|
-
throw new Error(`Failed to parse YAML file ${relativePath}: ${
|
|
26339
|
+
throw new Error(`Failed to parse YAML file ${relativePath}: ${(0, error_utils_js_1.toErrorMessage)(error)}`, { cause: error });
|
|
26289
26340
|
}
|
|
26290
26341
|
},
|
|
26291
26342
|
cascadeLayers
|
|
@@ -26360,6 +26411,7 @@ var require_persona_loader = __commonJS({
|
|
|
26360
26411
|
var node_path_1 = require("node:path");
|
|
26361
26412
|
var types_1 = require_dist();
|
|
26362
26413
|
var assets_js_1 = require_assets();
|
|
26414
|
+
var error_utils_js_1 = require_error_utils();
|
|
26363
26415
|
function buildPersonaCascadeLayers(defaultPersonasDir, homeDir, projectRoot) {
|
|
26364
26416
|
const layers = [];
|
|
26365
26417
|
layers.push(defaultPersonasDir);
|
|
@@ -26387,7 +26439,7 @@ var require_persona_loader = __commonJS({
|
|
|
26387
26439
|
}
|
|
26388
26440
|
return result.data;
|
|
26389
26441
|
} catch (error) {
|
|
26390
|
-
const message =
|
|
26442
|
+
const message = (0, error_utils_js_1.toErrorMessage)(error);
|
|
26391
26443
|
logger?.warn(`Failed to load persona file ${filename}: ${message}`);
|
|
26392
26444
|
return null;
|
|
26393
26445
|
}
|
|
@@ -26970,6 +27022,7 @@ var require_config2 = __commonJS({
|
|
|
26970
27022
|
var node_path_1 = require("node:path");
|
|
26971
27023
|
var yaml_1 = require_dist2();
|
|
26972
27024
|
var v4_1 = require_v4();
|
|
27025
|
+
var error_utils_js_1 = require_error_utils();
|
|
26973
27026
|
function deepFreeze(obj) {
|
|
26974
27027
|
if (obj === null || typeof obj !== "object") {
|
|
26975
27028
|
return obj;
|
|
@@ -26996,7 +27049,7 @@ var require_config2 = __commonJS({
|
|
|
26996
27049
|
consoleEnabled: v4_1.z.boolean(),
|
|
26997
27050
|
/** Per-component log level overrides. Keys are component names (e.g., 'reminders', 'statusline'). */
|
|
26998
27051
|
components: v4_1.z.record(v4_1.z.string(), LogLevelSchema).optional(),
|
|
26999
|
-
/** Log rotation settings. Defaults
|
|
27052
|
+
/** Log rotation settings. Defaults come from core.defaults.yaml (2MB/2 files). */
|
|
27000
27053
|
rotation: v4_1.z.object({
|
|
27001
27054
|
maxSizeBytes: v4_1.z.number().min(1),
|
|
27002
27055
|
maxFiles: v4_1.z.number().min(1)
|
|
@@ -27046,7 +27099,10 @@ var require_config2 = __commonJS({
|
|
|
27046
27099
|
fallbackProfileId: v4_1.z.string().optional(),
|
|
27047
27100
|
// OpenRouter-specific provider routing (ignored for other providers)
|
|
27048
27101
|
providerAllowlist: v4_1.z.array(v4_1.z.string()).optional(),
|
|
27049
|
-
providerBlocklist: v4_1.z.array(v4_1.z.string()).optional()
|
|
27102
|
+
providerBlocklist: v4_1.z.array(v4_1.z.string()).optional(),
|
|
27103
|
+
// OpenRouter-specific: toggle the model's reasoning mode (maps to reasoning.enabled).
|
|
27104
|
+
// Ignored for non-openrouter providers.
|
|
27105
|
+
reasoning: v4_1.z.boolean().optional()
|
|
27050
27106
|
});
|
|
27051
27107
|
exports2.LlmConfigSchema = v4_1.z.object({
|
|
27052
27108
|
defaultProfile: v4_1.z.string(),
|
|
@@ -27162,7 +27218,7 @@ var require_config2 = __commonJS({
|
|
|
27162
27218
|
const parsed = (0, yaml_1.parse)(content);
|
|
27163
27219
|
return parsed ?? {};
|
|
27164
27220
|
} catch (err) {
|
|
27165
|
-
const message =
|
|
27221
|
+
const message = (0, error_utils_js_1.toErrorMessage)(err);
|
|
27166
27222
|
throw new Error(`Failed to parse YAML at ${filePath}: ${message}`, { cause: err });
|
|
27167
27223
|
}
|
|
27168
27224
|
}
|
|
@@ -27470,6 +27526,7 @@ var require_config_writer = __commonJS({
|
|
|
27470
27526
|
var node_os_1 = require("node:os");
|
|
27471
27527
|
var node_path_1 = require("node:path");
|
|
27472
27528
|
var yaml_1 = __importDefault(require_dist2());
|
|
27529
|
+
var error_utils_js_1 = require_error_utils();
|
|
27473
27530
|
var config_1 = require_config2();
|
|
27474
27531
|
var VALID_DOMAINS = /* @__PURE__ */ new Set(["core", "llm", "transcript", "features"]);
|
|
27475
27532
|
var FORBIDDEN_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
|
|
@@ -27596,7 +27653,7 @@ var require_config_writer = __commonJS({
|
|
|
27596
27653
|
} catch {
|
|
27597
27654
|
}
|
|
27598
27655
|
}
|
|
27599
|
-
const message =
|
|
27656
|
+
const message = (0, error_utils_js_1.toErrorMessage)(err);
|
|
27600
27657
|
throw new Error(`Configuration validation failed after setting "${dotPath}": ${message}`, { cause: err });
|
|
27601
27658
|
}
|
|
27602
27659
|
return {
|
|
@@ -32760,7 +32817,12 @@ var require_log_events = __commonJS({
|
|
|
32760
32817
|
"use strict";
|
|
32761
32818
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
32762
32819
|
exports2.LogEvents = void 0;
|
|
32820
|
+
exports2.setSessionLogWriter = setSessionLogWriter;
|
|
32763
32821
|
exports2.logEvent = logEvent;
|
|
32822
|
+
var sessionLogWriter = null;
|
|
32823
|
+
function setSessionLogWriter(writer) {
|
|
32824
|
+
sessionLogWriter = writer;
|
|
32825
|
+
}
|
|
32764
32826
|
function buildContext(ctx) {
|
|
32765
32827
|
return {
|
|
32766
32828
|
sessionId: ctx.sessionId,
|
|
@@ -33167,10 +33229,219 @@ var require_log_events = __commonJS({
|
|
|
33167
33229
|
source: event.source,
|
|
33168
33230
|
...meta
|
|
33169
33231
|
});
|
|
33232
|
+
if (sessionLogWriter && event.context.sessionId) {
|
|
33233
|
+
const logFile = event.source === "cli" ? "sidekick.log" : "sidekickd.log";
|
|
33234
|
+
const line = JSON.stringify({
|
|
33235
|
+
time: event.time,
|
|
33236
|
+
type: event.type,
|
|
33237
|
+
source: event.source,
|
|
33238
|
+
context: event.context,
|
|
33239
|
+
...meta
|
|
33240
|
+
}) + "\n";
|
|
33241
|
+
sessionLogWriter.write(event.context.sessionId, logFile, line).catch(() => {
|
|
33242
|
+
});
|
|
33243
|
+
}
|
|
33244
|
+
}
|
|
33245
|
+
}
|
|
33246
|
+
});
|
|
33247
|
+
|
|
33248
|
+
// ../sidekick-core/dist/staging-paths.js
|
|
33249
|
+
var require_staging_paths = __commonJS({
|
|
33250
|
+
"../sidekick-core/dist/staging-paths.js"(exports2) {
|
|
33251
|
+
"use strict";
|
|
33252
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
33253
|
+
exports2.CONSUMED_FILE_PATTERN = void 0;
|
|
33254
|
+
exports2.getStagingRoot = getStagingRoot;
|
|
33255
|
+
exports2.getHookDir = getHookDir;
|
|
33256
|
+
exports2.getReminderPath = getReminderPath;
|
|
33257
|
+
exports2.isValidPathSegment = isValidPathSegment;
|
|
33258
|
+
exports2.validatePathSegment = validatePathSegment;
|
|
33259
|
+
exports2.filterActiveReminderFiles = filterActiveReminderFiles;
|
|
33260
|
+
exports2.createConsumedFilePattern = createConsumedFilePattern;
|
|
33261
|
+
exports2.extractConsumedTimestamp = extractConsumedTimestamp;
|
|
33262
|
+
var node_path_1 = require("node:path");
|
|
33263
|
+
function getStagingRoot(stateDir, sessionId) {
|
|
33264
|
+
return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
|
|
33265
|
+
}
|
|
33266
|
+
function getHookDir(stateDir, sessionId, hookName) {
|
|
33267
|
+
return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
|
|
33268
|
+
}
|
|
33269
|
+
function getReminderPath(stateDir, sessionId, hookName, reminderName) {
|
|
33270
|
+
return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
|
|
33271
|
+
}
|
|
33272
|
+
function isValidPathSegment(s) {
|
|
33273
|
+
if (s === "")
|
|
33274
|
+
return false;
|
|
33275
|
+
if (s === "." || s === "..")
|
|
33276
|
+
return false;
|
|
33277
|
+
if (s.includes("/") || s.includes("\\"))
|
|
33278
|
+
return false;
|
|
33279
|
+
if ((0, node_path_1.basename)(s) !== s)
|
|
33280
|
+
return false;
|
|
33281
|
+
return /^[a-zA-Z0-9._-]+$/.test(s);
|
|
33282
|
+
}
|
|
33283
|
+
function validatePathSegment(segment, name) {
|
|
33284
|
+
if (!isValidPathSegment(segment)) {
|
|
33285
|
+
throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
|
|
33286
|
+
}
|
|
33287
|
+
}
|
|
33288
|
+
exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
|
|
33289
|
+
function filterActiveReminderFiles(files) {
|
|
33290
|
+
return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
|
|
33291
|
+
}
|
|
33292
|
+
function createConsumedFilePattern(reminderName) {
|
|
33293
|
+
return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
|
|
33294
|
+
}
|
|
33295
|
+
function extractConsumedTimestamp(filename, reminderName) {
|
|
33296
|
+
const pattern = createConsumedFilePattern(reminderName);
|
|
33297
|
+
const match = pattern.exec(filename);
|
|
33298
|
+
return match ? parseInt(match[1], 10) : null;
|
|
33170
33299
|
}
|
|
33171
33300
|
}
|
|
33172
33301
|
});
|
|
33173
33302
|
|
|
33303
|
+
// ../sidekick-core/dist/session-log-writer.js
|
|
33304
|
+
var require_session_log_writer = __commonJS({
|
|
33305
|
+
"../sidekick-core/dist/session-log-writer.js"(exports2) {
|
|
33306
|
+
"use strict";
|
|
33307
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
33308
|
+
exports2.SessionLogWriter = void 0;
|
|
33309
|
+
var promises_1 = require("node:fs/promises");
|
|
33310
|
+
var node_path_1 = require("node:path");
|
|
33311
|
+
var node_fs_1 = require("node:fs");
|
|
33312
|
+
var staging_paths_js_1 = require_staging_paths();
|
|
33313
|
+
var SessionLogWriter = class {
|
|
33314
|
+
sessionsDir;
|
|
33315
|
+
maxHandles;
|
|
33316
|
+
idleTimeoutMs;
|
|
33317
|
+
/** Map key: `${sessionId}/${logFile}` */
|
|
33318
|
+
handles = /* @__PURE__ */ new Map();
|
|
33319
|
+
/** Sentinel map to prevent duplicate handle creation on concurrent writes */
|
|
33320
|
+
pendingCreation = /* @__PURE__ */ new Map();
|
|
33321
|
+
constructor(options) {
|
|
33322
|
+
this.sessionsDir = options.sessionsDir;
|
|
33323
|
+
this.maxHandles = options.maxHandles ?? 10;
|
|
33324
|
+
this.idleTimeoutMs = options.idleTimeoutMs ?? 30 * 60 * 1e3;
|
|
33325
|
+
}
|
|
33326
|
+
get handleCount() {
|
|
33327
|
+
return this.handles.size;
|
|
33328
|
+
}
|
|
33329
|
+
/**
|
|
33330
|
+
* Write an NDJSON line to a per-session log file.
|
|
33331
|
+
* Creates the directory and file handle lazily.
|
|
33332
|
+
* Skips if sessionId is empty (daemon lifecycle events before session exists).
|
|
33333
|
+
*/
|
|
33334
|
+
async write(sessionId, logFile, line) {
|
|
33335
|
+
if (!sessionId)
|
|
33336
|
+
return;
|
|
33337
|
+
if (!(0, staging_paths_js_1.isValidPathSegment)(sessionId) || !(0, staging_paths_js_1.isValidPathSegment)(logFile))
|
|
33338
|
+
return;
|
|
33339
|
+
const key = `${sessionId}/${logFile}`;
|
|
33340
|
+
const pending = this.pendingCreation.get(key);
|
|
33341
|
+
if (pending) {
|
|
33342
|
+
try {
|
|
33343
|
+
await pending;
|
|
33344
|
+
} catch {
|
|
33345
|
+
}
|
|
33346
|
+
}
|
|
33347
|
+
let entry = this.handles.get(key);
|
|
33348
|
+
if (!entry) {
|
|
33349
|
+
if (this.handles.size >= this.maxHandles) {
|
|
33350
|
+
this.evictLRU();
|
|
33351
|
+
}
|
|
33352
|
+
const creationPromise = this.createHandle(sessionId, logFile);
|
|
33353
|
+
this.pendingCreation.set(key, creationPromise);
|
|
33354
|
+
try {
|
|
33355
|
+
entry = await creationPromise;
|
|
33356
|
+
this.handles.set(key, entry);
|
|
33357
|
+
} finally {
|
|
33358
|
+
this.pendingCreation.delete(key);
|
|
33359
|
+
}
|
|
33360
|
+
}
|
|
33361
|
+
await entry.ready;
|
|
33362
|
+
entry.lastUsed = Date.now();
|
|
33363
|
+
this.resetIdleTimer(key, entry);
|
|
33364
|
+
return new Promise((resolve3, reject) => {
|
|
33365
|
+
entry.stream.write(line, (err) => {
|
|
33366
|
+
if (err) {
|
|
33367
|
+
void this.closeHandle(key);
|
|
33368
|
+
reject(err);
|
|
33369
|
+
} else {
|
|
33370
|
+
resolve3();
|
|
33371
|
+
}
|
|
33372
|
+
});
|
|
33373
|
+
});
|
|
33374
|
+
}
|
|
33375
|
+
async createHandle(sessionId, logFile) {
|
|
33376
|
+
const logDir = (0, node_path_1.join)(this.sessionsDir, sessionId, "logs");
|
|
33377
|
+
await (0, promises_1.mkdir)(logDir, { recursive: true });
|
|
33378
|
+
const filePath = (0, node_path_1.join)(logDir, logFile);
|
|
33379
|
+
const stream = (0, node_fs_1.createWriteStream)(filePath, { flags: "a" });
|
|
33380
|
+
const ready = new Promise((resolve3, reject) => {
|
|
33381
|
+
stream.once("open", () => resolve3());
|
|
33382
|
+
stream.once("error", (err) => {
|
|
33383
|
+
stream.destroy();
|
|
33384
|
+
reject(err);
|
|
33385
|
+
});
|
|
33386
|
+
});
|
|
33387
|
+
return {
|
|
33388
|
+
stream,
|
|
33389
|
+
lastUsed: Date.now(),
|
|
33390
|
+
timer: null,
|
|
33391
|
+
ready
|
|
33392
|
+
};
|
|
33393
|
+
}
|
|
33394
|
+
/** Close all handles for a specific session. */
|
|
33395
|
+
async closeSession(sessionId) {
|
|
33396
|
+
const prefix = `${sessionId}/`;
|
|
33397
|
+
const toClose = [];
|
|
33398
|
+
for (const key of this.handles.keys()) {
|
|
33399
|
+
if (key.startsWith(prefix)) {
|
|
33400
|
+
toClose.push(key);
|
|
33401
|
+
}
|
|
33402
|
+
}
|
|
33403
|
+
await Promise.all(toClose.map((key) => this.closeHandle(key)));
|
|
33404
|
+
}
|
|
33405
|
+
/** Close all open handles. */
|
|
33406
|
+
async closeAll() {
|
|
33407
|
+
const keys = [...this.handles.keys()];
|
|
33408
|
+
await Promise.all(keys.map((key) => this.closeHandle(key)));
|
|
33409
|
+
}
|
|
33410
|
+
async closeHandle(key) {
|
|
33411
|
+
const entry = this.handles.get(key);
|
|
33412
|
+
if (!entry)
|
|
33413
|
+
return;
|
|
33414
|
+
if (entry.timer)
|
|
33415
|
+
clearTimeout(entry.timer);
|
|
33416
|
+
this.handles.delete(key);
|
|
33417
|
+
return new Promise((resolve3) => {
|
|
33418
|
+
entry.stream.end(() => resolve3());
|
|
33419
|
+
});
|
|
33420
|
+
}
|
|
33421
|
+
evictLRU() {
|
|
33422
|
+
let oldestKey = "";
|
|
33423
|
+
let oldestTime = Infinity;
|
|
33424
|
+
for (const [key, entry] of this.handles) {
|
|
33425
|
+
if (entry.lastUsed < oldestTime) {
|
|
33426
|
+
oldestTime = entry.lastUsed;
|
|
33427
|
+
oldestKey = key;
|
|
33428
|
+
}
|
|
33429
|
+
}
|
|
33430
|
+
void this.closeHandle(oldestKey);
|
|
33431
|
+
}
|
|
33432
|
+
resetIdleTimer(key, entry) {
|
|
33433
|
+
if (entry.timer)
|
|
33434
|
+
clearTimeout(entry.timer);
|
|
33435
|
+
entry.timer = setTimeout(() => {
|
|
33436
|
+
void this.closeHandle(key);
|
|
33437
|
+
}, this.idleTimeoutMs);
|
|
33438
|
+
entry.timer.unref();
|
|
33439
|
+
}
|
|
33440
|
+
};
|
|
33441
|
+
exports2.SessionLogWriter = SessionLogWriter;
|
|
33442
|
+
}
|
|
33443
|
+
});
|
|
33444
|
+
|
|
33174
33445
|
// ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/constants.cjs
|
|
33175
33446
|
var require_constants2 = __commonJS({
|
|
33176
33447
|
"../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/constants.cjs"(exports2) {
|
|
@@ -44910,7 +45181,7 @@ var require_structured_logging = __commonJS({
|
|
|
44910
45181
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
44911
45182
|
};
|
|
44912
45183
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
44913
|
-
exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.LOG_LEVELS = exports2.logEvent = exports2.LogEvents = void 0;
|
|
45184
|
+
exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.LOG_LEVELS = exports2.SessionLogWriter = exports2.setSessionLogWriter = exports2.logEvent = exports2.LogEvents = void 0;
|
|
44914
45185
|
exports2.getComponentLogLevel = getComponentLogLevel;
|
|
44915
45186
|
exports2.createLogManager = createLogManager;
|
|
44916
45187
|
exports2.createContextLogger = createContextLogger;
|
|
@@ -44920,6 +45191,7 @@ var require_structured_logging = __commonJS({
|
|
|
44920
45191
|
var node_fs_1 = require("node:fs");
|
|
44921
45192
|
var node_path_1 = require("node:path");
|
|
44922
45193
|
var node_stream_1 = require("node:stream");
|
|
45194
|
+
var error_utils_js_1 = require_error_utils();
|
|
44923
45195
|
var log_events_1 = require_log_events();
|
|
44924
45196
|
Object.defineProperty(exports2, "LogEvents", { enumerable: true, get: function() {
|
|
44925
45197
|
return log_events_1.LogEvents;
|
|
@@ -44927,6 +45199,13 @@ var require_structured_logging = __commonJS({
|
|
|
44927
45199
|
Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
|
|
44928
45200
|
return log_events_1.logEvent;
|
|
44929
45201
|
} });
|
|
45202
|
+
Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
|
|
45203
|
+
return log_events_1.setSessionLogWriter;
|
|
45204
|
+
} });
|
|
45205
|
+
var session_log_writer_1 = require_session_log_writer();
|
|
45206
|
+
Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
|
|
45207
|
+
return session_log_writer_1.SessionLogWriter;
|
|
45208
|
+
} });
|
|
44930
45209
|
exports2.LOG_LEVELS = {
|
|
44931
45210
|
trace: 10,
|
|
44932
45211
|
debug: 20,
|
|
@@ -44942,8 +45221,8 @@ var require_structured_logging = __commonJS({
|
|
|
44942
45221
|
}
|
|
44943
45222
|
return defaultLevel;
|
|
44944
45223
|
}
|
|
44945
|
-
exports2.DEFAULT_ROTATE_SIZE_BYTES =
|
|
44946
|
-
exports2.DEFAULT_MAX_FILES =
|
|
45224
|
+
exports2.DEFAULT_ROTATE_SIZE_BYTES = 2 * 1024 * 1024;
|
|
45225
|
+
exports2.DEFAULT_MAX_FILES = 2;
|
|
44947
45226
|
var DEFAULT_REDACT_KEYS = [
|
|
44948
45227
|
"apiKey",
|
|
44949
45228
|
"token",
|
|
@@ -45284,7 +45563,7 @@ var require_structured_logging = __commonJS({
|
|
|
45284
45563
|
upgradeOptions.onUpgradeError(err);
|
|
45285
45564
|
}
|
|
45286
45565
|
activeLogger.error("Failed to upgrade to Pino logger", {
|
|
45287
|
-
error:
|
|
45566
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
45288
45567
|
});
|
|
45289
45568
|
}
|
|
45290
45569
|
},
|
|
@@ -45300,7 +45579,7 @@ var require_structured_logging = __commonJS({
|
|
|
45300
45579
|
};
|
|
45301
45580
|
const rejectionHandler = (reason) => {
|
|
45302
45581
|
logger.fatal("Unhandled promise rejection", {
|
|
45303
|
-
reason:
|
|
45582
|
+
reason: (0, error_utils_js_1.toErrorMessage)(reason)
|
|
45304
45583
|
});
|
|
45305
45584
|
};
|
|
45306
45585
|
process.on("uncaughtException", uncaughtHandler);
|
|
@@ -45393,13 +45672,11 @@ var require_daemon_client2 = __commonJS({
|
|
|
45393
45672
|
var client_js_1 = require_client();
|
|
45394
45673
|
var transport_js_1 = require_transport();
|
|
45395
45674
|
var sandbox_js_1 = require_sandbox();
|
|
45675
|
+
var error_utils_js_1 = require_error_utils();
|
|
45396
45676
|
var LOCK_TIMEOUT_MS = 1e4;
|
|
45397
45677
|
var LOCK_RETRY_INTERVAL_MS = 100;
|
|
45398
45678
|
var LOCK_STALE_THRESHOLD_MS = 3e4;
|
|
45399
45679
|
var CLIENT_VERSION = require_package3().version;
|
|
45400
|
-
function toErrorMsg(err) {
|
|
45401
|
-
return err instanceof Error ? err.message : String(err);
|
|
45402
|
-
}
|
|
45403
45680
|
var DaemonClient = class {
|
|
45404
45681
|
projectDir;
|
|
45405
45682
|
logger;
|
|
@@ -45765,7 +46042,7 @@ var require_daemon_client2 = __commonJS({
|
|
|
45765
46042
|
} catch (err) {
|
|
45766
46043
|
logger.debug("Graceful stop failed, falling back to SIGKILL", {
|
|
45767
46044
|
pid: info.pid,
|
|
45768
|
-
error:
|
|
46045
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
45769
46046
|
});
|
|
45770
46047
|
}
|
|
45771
46048
|
}
|
|
@@ -45774,7 +46051,7 @@ var require_daemon_client2 = __commonJS({
|
|
|
45774
46051
|
logger.info("Killed daemon", { pid: info.pid, projectDir: info.projectDir });
|
|
45775
46052
|
results.push({ projectDir: info.projectDir, pid: info.pid, killed: true });
|
|
45776
46053
|
} catch (err) {
|
|
45777
|
-
const msg =
|
|
46054
|
+
const msg = (0, error_utils_js_1.toErrorMessage)(err);
|
|
45778
46055
|
logger.warn("Failed to kill daemon", { pid: info.pid, error: msg });
|
|
45779
46056
|
results.push({ projectDir: info.projectDir, pid: info.pid, killed: false, error: msg });
|
|
45780
46057
|
}
|
|
@@ -45786,7 +46063,7 @@ var require_daemon_client2 = __commonJS({
|
|
|
45786
46063
|
});
|
|
45787
46064
|
}
|
|
45788
46065
|
} catch (err) {
|
|
45789
|
-
logger.warn("Invalid PID file, removing", { pidFile, error:
|
|
46066
|
+
logger.warn("Invalid PID file, removing", { pidFile, error: (0, error_utils_js_1.toErrorMessage)(err) });
|
|
45790
46067
|
await promises_1.default.unlink(pidPath).catch(() => {
|
|
45791
46068
|
});
|
|
45792
46069
|
}
|
|
@@ -45807,7 +46084,7 @@ var require_daemon_client2 = __commonJS({
|
|
|
45807
46084
|
});
|
|
45808
46085
|
} catch (err) {
|
|
45809
46086
|
logger.warn("Failed to run ps \u2014 cannot detect zombie daemons", {
|
|
45810
|
-
error:
|
|
46087
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
45811
46088
|
});
|
|
45812
46089
|
return [];
|
|
45813
46090
|
}
|
|
@@ -45868,7 +46145,7 @@ var require_daemon_client2 = __commonJS({
|
|
|
45868
46145
|
logger.info("Killed zombie daemon", { pid: zombie.pid, command: zombie.command });
|
|
45869
46146
|
results.push({ projectDir: "unknown", pid: zombie.pid, killed: true });
|
|
45870
46147
|
} catch (err) {
|
|
45871
|
-
const msg =
|
|
46148
|
+
const msg = (0, error_utils_js_1.toErrorMessage)(err);
|
|
45872
46149
|
logger.warn("Failed to kill zombie daemon", { pid: zombie.pid, error: msg });
|
|
45873
46150
|
results.push({ projectDir: "unknown", pid: zombie.pid, killed: false, error: msg });
|
|
45874
46151
|
}
|
|
@@ -45920,60 +46197,94 @@ var require_gitignore = __commonJS({
|
|
|
45920
46197
|
};
|
|
45921
46198
|
})();
|
|
45922
46199
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
45923
|
-
exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = void 0;
|
|
46200
|
+
exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_GITIGNORE_HEADER = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = void 0;
|
|
45924
46201
|
exports2.installGitignoreSection = installGitignoreSection;
|
|
45925
|
-
exports2.removeGitignoreSection = removeGitignoreSection;
|
|
45926
46202
|
exports2.detectGitignoreStatus = detectGitignoreStatus;
|
|
46203
|
+
exports2.removeGitignoreSection = removeGitignoreSection;
|
|
46204
|
+
exports2.detectLegacyGitignoreSection = detectLegacyGitignoreSection;
|
|
46205
|
+
exports2.removeLegacyGitignoreSection = removeLegacyGitignoreSection;
|
|
45927
46206
|
var fs = __importStar(require("node:fs/promises"));
|
|
45928
46207
|
var path = __importStar(require("node:path"));
|
|
45929
46208
|
exports2.SIDEKICK_SECTION_START = "# >>> sidekick";
|
|
45930
46209
|
exports2.SIDEKICK_SECTION_END = "# <<< sidekick";
|
|
46210
|
+
exports2.SIDEKICK_GITIGNORE_HEADER = "# Sidekick \u2014 managed file, do not edit manually";
|
|
45931
46211
|
exports2.GITIGNORE_ENTRIES = [
|
|
45932
|
-
"
|
|
45933
|
-
"
|
|
45934
|
-
"
|
|
45935
|
-
"
|
|
45936
|
-
".
|
|
45937
|
-
".
|
|
45938
|
-
"
|
|
45939
|
-
"
|
|
45940
|
-
"
|
|
46212
|
+
"logs/",
|
|
46213
|
+
"sessions/",
|
|
46214
|
+
"state/",
|
|
46215
|
+
"setup-status.json",
|
|
46216
|
+
".env",
|
|
46217
|
+
".env.local",
|
|
46218
|
+
"sidekick*.pid",
|
|
46219
|
+
"sidekick*.token",
|
|
46220
|
+
"*.local.yaml"
|
|
45941
46221
|
];
|
|
45942
46222
|
async function installGitignoreSection(projectDir2) {
|
|
45943
|
-
|
|
45944
|
-
let content = "";
|
|
46223
|
+
let status;
|
|
45945
46224
|
try {
|
|
45946
|
-
|
|
46225
|
+
status = await detectGitignoreStatus(projectDir2);
|
|
45947
46226
|
} catch (err) {
|
|
45948
|
-
|
|
45949
|
-
return { status: "error", error: `Failed to read .gitignore: ${err.message}` };
|
|
45950
|
-
}
|
|
46227
|
+
return { status: "error", error: `Failed to check gitignore status: ${err.message}` };
|
|
45951
46228
|
}
|
|
45952
|
-
const status = await detectGitignoreStatus(projectDir2);
|
|
45953
46229
|
if (status === "installed") {
|
|
45954
46230
|
return { status: "already-installed" };
|
|
45955
46231
|
}
|
|
45956
|
-
|
|
45957
|
-
|
|
45958
|
-
|
|
45959
|
-
|
|
45960
|
-
|
|
45961
|
-
content = "";
|
|
45962
|
-
}
|
|
46232
|
+
const sidekickDir = path.join(projectDir2, ".sidekick");
|
|
46233
|
+
try {
|
|
46234
|
+
await fs.mkdir(sidekickDir, { recursive: true });
|
|
46235
|
+
} catch (err) {
|
|
46236
|
+
return { status: "error", error: `Failed to create .sidekick directory: ${err.message}` };
|
|
45963
46237
|
}
|
|
45964
|
-
const
|
|
45965
|
-
const newContent = content.trimEnd() + section + "\n";
|
|
46238
|
+
const content = [exports2.SIDEKICK_GITIGNORE_HEADER, ...exports2.GITIGNORE_ENTRIES].join("\n") + "\n";
|
|
45966
46239
|
try {
|
|
45967
|
-
await fs.writeFile(
|
|
46240
|
+
await fs.writeFile(path.join(sidekickDir, ".gitignore"), content);
|
|
45968
46241
|
return { status: "installed", entriesAdded: exports2.GITIGNORE_ENTRIES };
|
|
45969
46242
|
} catch (err) {
|
|
45970
|
-
return { status: "error", error: `Failed to write .gitignore: ${err.message}` };
|
|
46243
|
+
return { status: "error", error: `Failed to write .sidekick/.gitignore: ${err.message}` };
|
|
45971
46244
|
}
|
|
45972
46245
|
}
|
|
46246
|
+
async function detectGitignoreStatus(projectDir2) {
|
|
46247
|
+
const sidekickGitignorePath = path.join(projectDir2, ".sidekick", ".gitignore");
|
|
46248
|
+
try {
|
|
46249
|
+
const content = await fs.readFile(sidekickGitignorePath, "utf-8");
|
|
46250
|
+
const missingEntries = exports2.GITIGNORE_ENTRIES.filter((entry) => !content.includes(entry));
|
|
46251
|
+
return missingEntries.length === 0 ? "installed" : "incomplete";
|
|
46252
|
+
} catch (err) {
|
|
46253
|
+
if (err.code !== "ENOENT") {
|
|
46254
|
+
throw err;
|
|
46255
|
+
}
|
|
46256
|
+
}
|
|
46257
|
+
const hasLegacy = await detectLegacyGitignoreSection(projectDir2);
|
|
46258
|
+
return hasLegacy ? "legacy" : "missing";
|
|
46259
|
+
}
|
|
45973
46260
|
async function removeGitignoreSection(projectDir2) {
|
|
45974
|
-
|
|
46261
|
+
let removed = false;
|
|
45975
46262
|
try {
|
|
45976
|
-
|
|
46263
|
+
await fs.unlink(path.join(projectDir2, ".sidekick", ".gitignore"));
|
|
46264
|
+
removed = true;
|
|
46265
|
+
} catch (err) {
|
|
46266
|
+
if (err.code !== "ENOENT") {
|
|
46267
|
+
throw err;
|
|
46268
|
+
}
|
|
46269
|
+
}
|
|
46270
|
+
const legacyRemoved = await removeLegacyGitignoreSection(projectDir2);
|
|
46271
|
+
return removed || legacyRemoved;
|
|
46272
|
+
}
|
|
46273
|
+
async function detectLegacyGitignoreSection(projectDir2) {
|
|
46274
|
+
try {
|
|
46275
|
+
const content = await fs.readFile(path.join(projectDir2, ".gitignore"), "utf-8");
|
|
46276
|
+
return content.includes(exports2.SIDEKICK_SECTION_START);
|
|
46277
|
+
} catch (err) {
|
|
46278
|
+
if (err.code === "ENOENT") {
|
|
46279
|
+
return false;
|
|
46280
|
+
}
|
|
46281
|
+
throw err;
|
|
46282
|
+
}
|
|
46283
|
+
}
|
|
46284
|
+
async function removeLegacyGitignoreSection(projectDir2) {
|
|
46285
|
+
const rootGitignorePath = path.join(projectDir2, ".gitignore");
|
|
46286
|
+
try {
|
|
46287
|
+
const content = await fs.readFile(rootGitignorePath, "utf-8");
|
|
45977
46288
|
const startIdx = content.indexOf(exports2.SIDEKICK_SECTION_START);
|
|
45978
46289
|
const endIdx = content.indexOf(exports2.SIDEKICK_SECTION_END);
|
|
45979
46290
|
if (startIdx === -1 || endIdx === -1 || endIdx < startIdx) {
|
|
@@ -45985,37 +46296,13 @@ var require_gitignore = __commonJS({
|
|
|
45985
46296
|
const before = content.slice(0, lineStartIdx).trimEnd();
|
|
45986
46297
|
const after = content.slice(actualEndIdx).trimStart();
|
|
45987
46298
|
const newContent = before + (after ? "\n" + after : "") + "\n";
|
|
45988
|
-
await fs.writeFile(
|
|
46299
|
+
await fs.writeFile(rootGitignorePath, newContent);
|
|
45989
46300
|
return true;
|
|
45990
|
-
} catch {
|
|
45991
|
-
|
|
45992
|
-
|
|
45993
|
-
}
|
|
45994
|
-
async function detectGitignoreStatus(projectDir2) {
|
|
45995
|
-
const gitignorePath = path.join(projectDir2, ".gitignore");
|
|
45996
|
-
try {
|
|
45997
|
-
const content = await fs.readFile(gitignorePath, "utf-8");
|
|
45998
|
-
const hasStart = content.includes(exports2.SIDEKICK_SECTION_START);
|
|
45999
|
-
const hasEnd = content.includes(exports2.SIDEKICK_SECTION_END);
|
|
46000
|
-
if (!hasStart && !hasEnd) {
|
|
46001
|
-
return "missing";
|
|
46002
|
-
}
|
|
46003
|
-
if (!hasStart || !hasEnd) {
|
|
46004
|
-
return "incomplete";
|
|
46005
|
-
}
|
|
46006
|
-
const startIdx = content.indexOf(exports2.SIDEKICK_SECTION_START);
|
|
46007
|
-
const endIdx = content.indexOf(exports2.SIDEKICK_SECTION_END);
|
|
46008
|
-
if (endIdx <= startIdx) {
|
|
46009
|
-
return "incomplete";
|
|
46010
|
-
}
|
|
46011
|
-
const sectionContent = content.slice(startIdx, endIdx + exports2.SIDEKICK_SECTION_END.length);
|
|
46012
|
-
const missingEntries = exports2.GITIGNORE_ENTRIES.filter((entry) => !sectionContent.includes(entry));
|
|
46013
|
-
if (missingEntries.length > 0) {
|
|
46014
|
-
return "incomplete";
|
|
46301
|
+
} catch (err) {
|
|
46302
|
+
if (err.code === "ENOENT") {
|
|
46303
|
+
return false;
|
|
46015
46304
|
}
|
|
46016
|
-
|
|
46017
|
-
} catch {
|
|
46018
|
-
return "missing";
|
|
46305
|
+
throw err;
|
|
46019
46306
|
}
|
|
46020
46307
|
}
|
|
46021
46308
|
}
|
|
@@ -46026,7 +46313,7 @@ var require_errors4 = __commonJS({
|
|
|
46026
46313
|
"../shared-providers/dist/errors.js"(exports2) {
|
|
46027
46314
|
"use strict";
|
|
46028
46315
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
46029
|
-
exports2.TimeoutError = exports2.AuthError = exports2.RateLimitError = exports2.ProviderError = void 0;
|
|
46316
|
+
exports2.MalformedResponseError = exports2.TimeoutError = exports2.AuthError = exports2.RateLimitError = exports2.ProviderError = void 0;
|
|
46030
46317
|
var ProviderError = class _ProviderError extends Error {
|
|
46031
46318
|
provider;
|
|
46032
46319
|
retryable;
|
|
@@ -46067,6 +46354,18 @@ var require_errors4 = __commonJS({
|
|
|
46067
46354
|
}
|
|
46068
46355
|
};
|
|
46069
46356
|
exports2.TimeoutError = TimeoutError;
|
|
46357
|
+
var MalformedResponseError = class _MalformedResponseError extends ProviderError {
|
|
46358
|
+
code;
|
|
46359
|
+
providerMessage;
|
|
46360
|
+
constructor(provider, code, providerMessage, cause) {
|
|
46361
|
+
super(`Malformed response from ${provider}: ${code ?? "unknown"} - ${providerMessage ?? "no message"}`, provider, false, cause);
|
|
46362
|
+
this.name = "MalformedResponseError";
|
|
46363
|
+
this.code = code;
|
|
46364
|
+
this.providerMessage = providerMessage;
|
|
46365
|
+
Object.setPrototypeOf(this, _MalformedResponseError.prototype);
|
|
46366
|
+
}
|
|
46367
|
+
};
|
|
46368
|
+
exports2.MalformedResponseError = MalformedResponseError;
|
|
46070
46369
|
}
|
|
46071
46370
|
});
|
|
46072
46371
|
|
|
@@ -55045,6 +55344,7 @@ var require_base = __commonJS({
|
|
|
55045
55344
|
model: response.model,
|
|
55046
55345
|
durationMs,
|
|
55047
55346
|
usage: response.usage,
|
|
55347
|
+
finishReason: response.finishReason,
|
|
55048
55348
|
status: response.rawResponse.status,
|
|
55049
55349
|
contentLength: response.content.length
|
|
55050
55350
|
});
|
|
@@ -55092,6 +55392,7 @@ var require_openai_native = __commonJS({
|
|
|
55092
55392
|
maxTokens;
|
|
55093
55393
|
providerAllowlist;
|
|
55094
55394
|
providerBlocklist;
|
|
55395
|
+
reasoning;
|
|
55095
55396
|
constructor(config, logger) {
|
|
55096
55397
|
super(logger);
|
|
55097
55398
|
this.id = config.baseURL?.includes("openrouter") ? "openrouter" : "openai";
|
|
@@ -55100,6 +55401,7 @@ var require_openai_native = __commonJS({
|
|
|
55100
55401
|
this.maxTokens = config.maxTokens;
|
|
55101
55402
|
this.providerAllowlist = config.providerAllowlist;
|
|
55102
55403
|
this.providerBlocklist = config.providerBlocklist;
|
|
55404
|
+
this.reasoning = config.reasoning;
|
|
55103
55405
|
this.client = new openai_1.default({
|
|
55104
55406
|
apiKey: config.apiKey,
|
|
55105
55407
|
baseURL: config.baseURL,
|
|
@@ -55115,6 +55417,7 @@ var require_openai_native = __commonJS({
|
|
|
55115
55417
|
maxTokens: this.maxTokens,
|
|
55116
55418
|
providerAllowlist: this.providerAllowlist,
|
|
55117
55419
|
providerBlocklist: this.providerBlocklist,
|
|
55420
|
+
reasoning: this.reasoning,
|
|
55118
55421
|
apiKey: this.redactApiKey(config.apiKey)
|
|
55119
55422
|
});
|
|
55120
55423
|
}
|
|
@@ -55132,6 +55435,7 @@ var require_openai_native = __commonJS({
|
|
|
55132
55435
|
}
|
|
55133
55436
|
} : void 0;
|
|
55134
55437
|
const providerRouting = this.buildProviderRouting();
|
|
55438
|
+
const reasoningParam = this.buildReasoningParam();
|
|
55135
55439
|
const completion = await this.client.chat.completions.create({
|
|
55136
55440
|
model: request.model ?? this.defaultModel,
|
|
55137
55441
|
messages,
|
|
@@ -55139,8 +55443,13 @@ var require_openai_native = __commonJS({
|
|
|
55139
55443
|
max_tokens: this.maxTokens,
|
|
55140
55444
|
response_format: responseFormat,
|
|
55141
55445
|
...providerRouting,
|
|
55446
|
+
...reasoningParam,
|
|
55142
55447
|
...request.additionalParams
|
|
55143
55448
|
});
|
|
55449
|
+
if (!completion.choices || completion.choices.length === 0) {
|
|
55450
|
+
const errorPayload = completion.error;
|
|
55451
|
+
throw new errors_1.MalformedResponseError(this.id, errorPayload?.code, errorPayload?.message);
|
|
55452
|
+
}
|
|
55144
55453
|
const response = {
|
|
55145
55454
|
content: completion.choices[0]?.message?.content ?? "",
|
|
55146
55455
|
model: completion.model,
|
|
@@ -55148,6 +55457,7 @@ var require_openai_native = __commonJS({
|
|
|
55148
55457
|
inputTokens: completion.usage.prompt_tokens,
|
|
55149
55458
|
outputTokens: completion.usage.completion_tokens
|
|
55150
55459
|
} : void 0,
|
|
55460
|
+
finishReason: completion.choices[0]?.finish_reason ?? void 0,
|
|
55151
55461
|
rawResponse: {
|
|
55152
55462
|
status: 200,
|
|
55153
55463
|
body: JSON.stringify(completion)
|
|
@@ -55183,7 +55493,25 @@ var require_openai_native = __commonJS({
|
|
|
55183
55493
|
}
|
|
55184
55494
|
return { provider: providerObj };
|
|
55185
55495
|
}
|
|
55496
|
+
/**
|
|
55497
|
+
* Build OpenRouter reasoning param object.
|
|
55498
|
+
* Returns empty object if reasoning is unset or provider is not OpenRouter.
|
|
55499
|
+
* Maps `reasoning?: boolean` to OpenRouter's `reasoning: { enabled: <bool> }`.
|
|
55500
|
+
* @see https://openrouter.ai/docs/use-cases/reasoning-tokens
|
|
55501
|
+
*/
|
|
55502
|
+
buildReasoningParam() {
|
|
55503
|
+
if (this.id !== "openrouter") {
|
|
55504
|
+
return {};
|
|
55505
|
+
}
|
|
55506
|
+
if (this.reasoning === void 0) {
|
|
55507
|
+
return {};
|
|
55508
|
+
}
|
|
55509
|
+
return { reasoning: { enabled: this.reasoning } };
|
|
55510
|
+
}
|
|
55186
55511
|
mapError(error) {
|
|
55512
|
+
if (error instanceof errors_1.ProviderError) {
|
|
55513
|
+
return error;
|
|
55514
|
+
}
|
|
55187
55515
|
if (error instanceof openai_1.default.APIError) {
|
|
55188
55516
|
if (error.status === 401 || error.status === 403) {
|
|
55189
55517
|
return new errors_1.AuthError(this.id, error);
|
|
@@ -55277,7 +55605,13 @@ var require_claude_cli_spawn = __commonJS({
|
|
|
55277
55605
|
});
|
|
55278
55606
|
const child = (0, node_child_process_1.spawn)(cliPath, args, {
|
|
55279
55607
|
cwd,
|
|
55280
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
55608
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
55609
|
+
// Recursion guard: Sidekick's own Claude Code hooks fire inside any
|
|
55610
|
+
// `claude -p` subprocess we spawn. Without this flag, the subprocess
|
|
55611
|
+
// hook handler would dispatch to the daemon, trigger another LLM call,
|
|
55612
|
+
// spawn another subprocess, and so on. handleHookCommand short-circuits
|
|
55613
|
+
// when SIDEKICK_SUBPROCESS=1 is set. See packages/sidekick-cli/src/commands/hook.ts.
|
|
55614
|
+
env: { ...process.env, SIDEKICK_SUBPROCESS: "1" }
|
|
55281
55615
|
});
|
|
55282
55616
|
let stdout = "";
|
|
55283
55617
|
let stderr = "";
|
|
@@ -55339,6 +55673,31 @@ var require_claude_cli_spawn = __commonJS({
|
|
|
55339
55673
|
}
|
|
55340
55674
|
});
|
|
55341
55675
|
|
|
55676
|
+
// ../shared-providers/dist/providers/anthropic-stop-reason.js
|
|
55677
|
+
var require_anthropic_stop_reason = __commonJS({
|
|
55678
|
+
"../shared-providers/dist/providers/anthropic-stop-reason.js"(exports2) {
|
|
55679
|
+
"use strict";
|
|
55680
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
55681
|
+
exports2.mapAnthropicStopReason = mapAnthropicStopReason;
|
|
55682
|
+
function mapAnthropicStopReason(stopReason) {
|
|
55683
|
+
if (!stopReason)
|
|
55684
|
+
return void 0;
|
|
55685
|
+
switch (stopReason) {
|
|
55686
|
+
case "end_turn":
|
|
55687
|
+
return "stop";
|
|
55688
|
+
case "max_tokens":
|
|
55689
|
+
return "length";
|
|
55690
|
+
case "stop_sequence":
|
|
55691
|
+
return "stop";
|
|
55692
|
+
case "tool_use":
|
|
55693
|
+
return "tool_calls";
|
|
55694
|
+
default:
|
|
55695
|
+
return stopReason;
|
|
55696
|
+
}
|
|
55697
|
+
}
|
|
55698
|
+
}
|
|
55699
|
+
});
|
|
55700
|
+
|
|
55342
55701
|
// ../shared-providers/dist/providers/anthropic-cli.js
|
|
55343
55702
|
var require_anthropic_cli = __commonJS({
|
|
55344
55703
|
"../shared-providers/dist/providers/anthropic-cli.js"(exports2) {
|
|
@@ -55347,6 +55706,7 @@ var require_anthropic_cli = __commonJS({
|
|
|
55347
55706
|
exports2.AnthropicCliProvider = void 0;
|
|
55348
55707
|
var base_1 = require_base();
|
|
55349
55708
|
var claude_cli_spawn_1 = require_claude_cli_spawn();
|
|
55709
|
+
var anthropic_stop_reason_1 = require_anthropic_stop_reason();
|
|
55350
55710
|
var AnthropicCliProvider = class extends base_1.AbstractProvider {
|
|
55351
55711
|
id = "claude-cli";
|
|
55352
55712
|
defaultModel;
|
|
@@ -55408,6 +55768,7 @@ var require_anthropic_cli = __commonJS({
|
|
|
55408
55768
|
inputTokens: parsed.usage.input_tokens ?? 0,
|
|
55409
55769
|
outputTokens: parsed.usage.output_tokens ?? 0
|
|
55410
55770
|
} : void 0,
|
|
55771
|
+
finishReason: (0, anthropic_stop_reason_1.mapAnthropicStopReason)(parsed.stop_reason),
|
|
55411
55772
|
rawResponse: {
|
|
55412
55773
|
status: 200,
|
|
55413
55774
|
body: stdout
|
|
@@ -55679,6 +56040,7 @@ var require_openai_emulator = __commonJS({
|
|
|
55679
56040
|
inputTokens,
|
|
55680
56041
|
outputTokens
|
|
55681
56042
|
},
|
|
56043
|
+
finishReason: "stop",
|
|
55682
56044
|
rawResponse: {
|
|
55683
56045
|
status: 200,
|
|
55684
56046
|
body: JSON.stringify(rawBody)
|
|
@@ -55733,6 +56095,7 @@ var require_openrouter_emulator = __commonJS({
|
|
|
55733
56095
|
inputTokens,
|
|
55734
56096
|
outputTokens
|
|
55735
56097
|
},
|
|
56098
|
+
finishReason: "stop",
|
|
55736
56099
|
rawResponse: {
|
|
55737
56100
|
status: 200,
|
|
55738
56101
|
body: JSON.stringify(rawBody)
|
|
@@ -55753,6 +56116,7 @@ var require_claude_cli_emulator = __commonJS({
|
|
|
55753
56116
|
var node_child_process_1 = require("node:child_process");
|
|
55754
56117
|
var node_path_1 = require("node:path");
|
|
55755
56118
|
var base_1 = require_base();
|
|
56119
|
+
var anthropic_stop_reason_1 = require_anthropic_stop_reason();
|
|
55756
56120
|
var EMULATOR_SCRIPT = `#!/bin/bash
|
|
55757
56121
|
# Claude CLI Emulator Script
|
|
55758
56122
|
STATE_FILE="\${SIDEKICK_EMULATOR_STATE_PATH:-.sidekick/emulator-state/call-counts.json}"
|
|
@@ -55840,6 +56204,7 @@ echo "{\\"content\\":\\"\${CONTENT}\\",\\"message\\":\\"\${CONTENT}\\",\\"model\
|
|
|
55840
56204
|
inputTokens,
|
|
55841
56205
|
outputTokens
|
|
55842
56206
|
},
|
|
56207
|
+
finishReason: (0, anthropic_stop_reason_1.mapAnthropicStopReason)(parsed.stop_reason),
|
|
55843
56208
|
rawResponse: {
|
|
55844
56209
|
status: 0,
|
|
55845
56210
|
// Exit code
|
|
@@ -55976,7 +56341,8 @@ var require_factory = __commonJS({
|
|
|
55976
56341
|
temperature: this.config.temperature,
|
|
55977
56342
|
maxTokens: this.config.maxTokens,
|
|
55978
56343
|
providerAllowlist: this.config.providerAllowlist,
|
|
55979
|
-
providerBlocklist: this.config.providerBlocklist
|
|
56344
|
+
providerBlocklist: this.config.providerBlocklist,
|
|
56345
|
+
reasoning: this.config.reasoning
|
|
55980
56346
|
};
|
|
55981
56347
|
return new openai_native_1.OpenAINativeProvider(openrouterConfig, this.logger);
|
|
55982
56348
|
}
|
|
@@ -56153,7 +56519,9 @@ var require_profile_factory = __commonJS({
|
|
|
56153
56519
|
maxTokens: profile.maxTokens,
|
|
56154
56520
|
// OpenRouter-specific provider routing
|
|
56155
56521
|
providerAllowlist: profile.providerAllowlist ? [...profile.providerAllowlist] : void 0,
|
|
56156
|
-
providerBlocklist: profile.providerBlocklist ? [...profile.providerBlocklist] : void 0
|
|
56522
|
+
providerBlocklist: profile.providerBlocklist ? [...profile.providerBlocklist] : void 0,
|
|
56523
|
+
// OpenRouter-specific reasoning toggle
|
|
56524
|
+
reasoning: profile.reasoning
|
|
56157
56525
|
}, this.logger);
|
|
56158
56526
|
return factory.create();
|
|
56159
56527
|
}
|
|
@@ -56208,7 +56576,7 @@ var require_dist3 = __commonJS({
|
|
|
56208
56576
|
"../shared-providers/dist/index.js"(exports2) {
|
|
56209
56577
|
"use strict";
|
|
56210
56578
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
56211
|
-
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;
|
|
56579
|
+
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;
|
|
56212
56580
|
var errors_1 = require_errors4();
|
|
56213
56581
|
Object.defineProperty(exports2, "ProviderError", { enumerable: true, get: function() {
|
|
56214
56582
|
return errors_1.ProviderError;
|
|
@@ -56222,6 +56590,9 @@ var require_dist3 = __commonJS({
|
|
|
56222
56590
|
Object.defineProperty(exports2, "TimeoutError", { enumerable: true, get: function() {
|
|
56223
56591
|
return errors_1.TimeoutError;
|
|
56224
56592
|
} });
|
|
56593
|
+
Object.defineProperty(exports2, "MalformedResponseError", { enumerable: true, get: function() {
|
|
56594
|
+
return errors_1.MalformedResponseError;
|
|
56595
|
+
} });
|
|
56225
56596
|
var factory_1 = require_factory();
|
|
56226
56597
|
Object.defineProperty(exports2, "ProviderFactory", { enumerable: true, get: function() {
|
|
56227
56598
|
return factory_1.ProviderFactory;
|
|
@@ -56511,6 +56882,7 @@ var require_plugin_detector = __commonJS({
|
|
|
56511
56882
|
var crypto2 = __importStar(require("node:crypto"));
|
|
56512
56883
|
var node_child_process_1 = require("node:child_process");
|
|
56513
56884
|
var api_key_detector_js_1 = require_api_key_detector();
|
|
56885
|
+
var error_utils_js_1 = require_error_utils();
|
|
56514
56886
|
function isSidekickStatuslineCommand(command) {
|
|
56515
56887
|
return command?.toLowerCase().includes("sidekick") ?? false;
|
|
56516
56888
|
}
|
|
@@ -56640,7 +57012,7 @@ var require_plugin_detector = __commonJS({
|
|
|
56640
57012
|
return result;
|
|
56641
57013
|
} catch (err) {
|
|
56642
57014
|
logger?.warn("Failed to parse plugin list JSON", {
|
|
56643
|
-
error:
|
|
57015
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
56644
57016
|
});
|
|
56645
57017
|
logger?.info("Plugin detection completed", { result: "error" });
|
|
56646
57018
|
return "error";
|
|
@@ -56844,7 +57216,16 @@ var require_doctor_engine = __commonJS({
|
|
|
56844
57216
|
const expectedUserStatus = (0, api_key_detector_js_1.buildUserApiKeyStatus)(detection);
|
|
56845
57217
|
const currentUserEntry = currentUserStatus.apiKeys[keyName];
|
|
56846
57218
|
const currentStatus = typeof currentUserEntry === "object" ? currentUserEntry.status : currentUserEntry ?? "missing";
|
|
56847
|
-
if (currentStatus
|
|
57219
|
+
if (currentStatus === "not-required")
|
|
57220
|
+
continue;
|
|
57221
|
+
const isLegacyString = typeof currentUserEntry === "string";
|
|
57222
|
+
if (isLegacyString) {
|
|
57223
|
+
updatedUserApiKeys[keyName] = expectedUserStatus;
|
|
57224
|
+
userNeedsUpdate = true;
|
|
57225
|
+
} else if ((0, api_key_detector_js_1.toScopeStatus)(currentStatus) !== (0, api_key_detector_js_1.toScopeStatus)(expectedUserStatus.status)) {
|
|
57226
|
+
updatedUserApiKeys[keyName] = expectedUserStatus;
|
|
57227
|
+
userNeedsUpdate = true;
|
|
57228
|
+
} else if (typeof currentUserEntry === "object" && (currentUserEntry.used !== expectedUserStatus.used || JSON.stringify(currentUserEntry.scopes) !== JSON.stringify(expectedUserStatus.scopes))) {
|
|
56848
57229
|
updatedUserApiKeys[keyName] = expectedUserStatus;
|
|
56849
57230
|
userNeedsUpdate = true;
|
|
56850
57231
|
}
|
|
@@ -56919,7 +57300,7 @@ var require_setup_status_service = __commonJS({
|
|
|
56919
57300
|
};
|
|
56920
57301
|
})();
|
|
56921
57302
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
56922
|
-
exports2.SetupStatusService = exports2.
|
|
57303
|
+
exports2.SetupStatusService = exports2.PROJECT_STATUS_FILENAME = exports2.USER_STATUS_FILENAME = void 0;
|
|
56923
57304
|
exports2.createSetupStatusService = createSetupStatusService;
|
|
56924
57305
|
var fs = __importStar(require("node:fs/promises"));
|
|
56925
57306
|
var path = __importStar(require("node:path"));
|
|
@@ -56931,7 +57312,6 @@ var require_setup_status_service = __commonJS({
|
|
|
56931
57312
|
var doctor_engine_js_1 = require_doctor_engine();
|
|
56932
57313
|
exports2.USER_STATUS_FILENAME = "user-setup-status.json";
|
|
56933
57314
|
exports2.PROJECT_STATUS_FILENAME = "setup-status.json";
|
|
56934
|
-
exports2.LEGACY_USER_STATUS_FILENAME = exports2.PROJECT_STATUS_FILENAME;
|
|
56935
57315
|
var SetupStatusService = class {
|
|
56936
57316
|
projectDir;
|
|
56937
57317
|
homeDir;
|
|
@@ -56945,10 +57325,6 @@ var require_setup_status_service = __commonJS({
|
|
|
56945
57325
|
get userStatusPath() {
|
|
56946
57326
|
return path.join(this.homeDir, ".sidekick", exports2.USER_STATUS_FILENAME);
|
|
56947
57327
|
}
|
|
56948
|
-
/** Legacy path for migration: old user-scope file that collided with project-scope */
|
|
56949
|
-
get legacyUserStatusPath() {
|
|
56950
|
-
return path.join(this.homeDir, ".sidekick", exports2.LEGACY_USER_STATUS_FILENAME);
|
|
56951
|
-
}
|
|
56952
57328
|
get projectStatusPath() {
|
|
56953
57329
|
return path.join(this.projectDir, ".sidekick", exports2.PROJECT_STATUS_FILENAME);
|
|
56954
57330
|
}
|
|
@@ -56982,7 +57358,7 @@ var require_setup_status_service = __commonJS({
|
|
|
56982
57358
|
return parsed.data;
|
|
56983
57359
|
} catch (err) {
|
|
56984
57360
|
if (err.code === "ENOENT") {
|
|
56985
|
-
return
|
|
57361
|
+
return null;
|
|
56986
57362
|
}
|
|
56987
57363
|
if (err instanceof SyntaxError) {
|
|
56988
57364
|
this.logger?.warn(`Corrupt ${exports2.USER_STATUS_FILENAME}, treating as missing`, {
|
|
@@ -56994,54 +57370,6 @@ var require_setup_status_service = __commonJS({
|
|
|
56994
57370
|
throw err;
|
|
56995
57371
|
}
|
|
56996
57372
|
}
|
|
56997
|
-
/**
|
|
56998
|
-
* Migration: read user status from the legacy `setup-status.json` location,
|
|
56999
|
-
* write it to the new `user-setup-status.json`, and remove the old file.
|
|
57000
|
-
*
|
|
57001
|
-
* Only migrates if the legacy file contains valid UserSetupStatus data
|
|
57002
|
-
* (not project-format data that may have been written by the collision bug).
|
|
57003
|
-
*/
|
|
57004
|
-
async migrateFromLegacyUserStatus() {
|
|
57005
|
-
try {
|
|
57006
|
-
const legacyContent = await fs.readFile(this.legacyUserStatusPath, "utf-8");
|
|
57007
|
-
const parsed = types_1.UserSetupStatusSchema.safeParse(JSON.parse(legacyContent));
|
|
57008
|
-
if (!parsed.success) {
|
|
57009
|
-
this.logger?.debug("Legacy user status file exists but is not valid user format, skipping migration", {
|
|
57010
|
-
path: this.legacyUserStatusPath
|
|
57011
|
-
});
|
|
57012
|
-
return null;
|
|
57013
|
-
}
|
|
57014
|
-
this.logger?.info("Migrating user status from legacy location", {
|
|
57015
|
-
from: this.legacyUserStatusPath,
|
|
57016
|
-
to: this.userStatusPath
|
|
57017
|
-
});
|
|
57018
|
-
await this.writeUserStatus(parsed.data);
|
|
57019
|
-
try {
|
|
57020
|
-
await fs.unlink(this.legacyUserStatusPath);
|
|
57021
|
-
} catch (unlinkErr) {
|
|
57022
|
-
if (unlinkErr.code !== "ENOENT") {
|
|
57023
|
-
this.logger?.warn("Migrated user status but failed to remove legacy file", {
|
|
57024
|
-
path: this.legacyUserStatusPath,
|
|
57025
|
-
error: unlinkErr instanceof Error ? unlinkErr.message : String(unlinkErr)
|
|
57026
|
-
});
|
|
57027
|
-
}
|
|
57028
|
-
}
|
|
57029
|
-
this.logger?.info("Legacy user status migration complete");
|
|
57030
|
-
return parsed.data;
|
|
57031
|
-
} catch (err) {
|
|
57032
|
-
if (err.code === "ENOENT") {
|
|
57033
|
-
return null;
|
|
57034
|
-
}
|
|
57035
|
-
if (err instanceof SyntaxError) {
|
|
57036
|
-
this.logger?.warn(`Corrupt legacy ${exports2.LEGACY_USER_STATUS_FILENAME}, treating as missing`, {
|
|
57037
|
-
path: this.legacyUserStatusPath,
|
|
57038
|
-
error: err.message
|
|
57039
|
-
});
|
|
57040
|
-
return null;
|
|
57041
|
-
}
|
|
57042
|
-
throw err;
|
|
57043
|
-
}
|
|
57044
|
-
}
|
|
57045
57373
|
async getProjectStatus() {
|
|
57046
57374
|
if (path.resolve(this.projectDir) === path.resolve(this.homeDir)) {
|
|
57047
57375
|
this.logger?.debug("Skipping project status read: projectDir is the home directory", {
|
|
@@ -57409,61 +57737,6 @@ var require_errors6 = __commonJS({
|
|
|
57409
57737
|
}
|
|
57410
57738
|
});
|
|
57411
57739
|
|
|
57412
|
-
// ../sidekick-core/dist/staging-paths.js
|
|
57413
|
-
var require_staging_paths = __commonJS({
|
|
57414
|
-
"../sidekick-core/dist/staging-paths.js"(exports2) {
|
|
57415
|
-
"use strict";
|
|
57416
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
57417
|
-
exports2.CONSUMED_FILE_PATTERN = void 0;
|
|
57418
|
-
exports2.getStagingRoot = getStagingRoot;
|
|
57419
|
-
exports2.getHookDir = getHookDir;
|
|
57420
|
-
exports2.getReminderPath = getReminderPath;
|
|
57421
|
-
exports2.isValidPathSegment = isValidPathSegment;
|
|
57422
|
-
exports2.validatePathSegment = validatePathSegment;
|
|
57423
|
-
exports2.filterActiveReminderFiles = filterActiveReminderFiles;
|
|
57424
|
-
exports2.createConsumedFilePattern = createConsumedFilePattern;
|
|
57425
|
-
exports2.extractConsumedTimestamp = extractConsumedTimestamp;
|
|
57426
|
-
var node_path_1 = require("node:path");
|
|
57427
|
-
function getStagingRoot(stateDir, sessionId) {
|
|
57428
|
-
return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
|
|
57429
|
-
}
|
|
57430
|
-
function getHookDir(stateDir, sessionId, hookName) {
|
|
57431
|
-
return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
|
|
57432
|
-
}
|
|
57433
|
-
function getReminderPath(stateDir, sessionId, hookName, reminderName) {
|
|
57434
|
-
return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
|
|
57435
|
-
}
|
|
57436
|
-
function isValidPathSegment(s) {
|
|
57437
|
-
if (s === "")
|
|
57438
|
-
return false;
|
|
57439
|
-
if (s === "." || s === "..")
|
|
57440
|
-
return false;
|
|
57441
|
-
if (s.includes("/") || s.includes("\\"))
|
|
57442
|
-
return false;
|
|
57443
|
-
if ((0, node_path_1.basename)(s) !== s)
|
|
57444
|
-
return false;
|
|
57445
|
-
return /^[a-zA-Z0-9._-]+$/.test(s);
|
|
57446
|
-
}
|
|
57447
|
-
function validatePathSegment(segment, name) {
|
|
57448
|
-
if (!isValidPathSegment(segment)) {
|
|
57449
|
-
throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
|
|
57450
|
-
}
|
|
57451
|
-
}
|
|
57452
|
-
exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
|
|
57453
|
-
function filterActiveReminderFiles(files) {
|
|
57454
|
-
return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
|
|
57455
|
-
}
|
|
57456
|
-
function createConsumedFilePattern(reminderName) {
|
|
57457
|
-
return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
|
|
57458
|
-
}
|
|
57459
|
-
function extractConsumedTimestamp(filename, reminderName) {
|
|
57460
|
-
const pattern = createConsumedFilePattern(reminderName);
|
|
57461
|
-
const match = pattern.exec(filename);
|
|
57462
|
-
return match ? parseInt(match[1], 10) : null;
|
|
57463
|
-
}
|
|
57464
|
-
}
|
|
57465
|
-
});
|
|
57466
|
-
|
|
57467
57740
|
// ../sidekick-core/dist/staging-service.js
|
|
57468
57741
|
var require_staging_service = __commonJS({
|
|
57469
57742
|
"../sidekick-core/dist/staging-service.js"(exports2) {
|
|
@@ -57477,6 +57750,7 @@ var require_staging_service = __commonJS({
|
|
|
57477
57750
|
var structured_logging_1 = require_structured_logging();
|
|
57478
57751
|
var errors_js_1 = require_errors6();
|
|
57479
57752
|
var staging_paths_js_1 = require_staging_paths();
|
|
57753
|
+
var error_utils_js_1 = require_error_utils();
|
|
57480
57754
|
var StagingServiceCore = class {
|
|
57481
57755
|
options;
|
|
57482
57756
|
constructor(options) {
|
|
@@ -57580,7 +57854,7 @@ var require_staging_service = __commonJS({
|
|
|
57580
57854
|
hookName,
|
|
57581
57855
|
reminderName,
|
|
57582
57856
|
path: reminderPath,
|
|
57583
|
-
error:
|
|
57857
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
57584
57858
|
});
|
|
57585
57859
|
return null;
|
|
57586
57860
|
}
|
|
@@ -57611,7 +57885,7 @@ var require_staging_service = __commonJS({
|
|
|
57611
57885
|
}
|
|
57612
57886
|
this.options.logger.warn("Skipping invalid reminder file", {
|
|
57613
57887
|
path: reminderPath,
|
|
57614
|
-
error:
|
|
57888
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
57615
57889
|
});
|
|
57616
57890
|
}
|
|
57617
57891
|
}
|
|
@@ -57672,7 +57946,7 @@ var require_staging_service = __commonJS({
|
|
|
57672
57946
|
}
|
|
57673
57947
|
this.options.logger.warn("Skipping invalid consumed reminder file", {
|
|
57674
57948
|
path: reminderPath,
|
|
57675
|
-
error:
|
|
57949
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
57676
57950
|
});
|
|
57677
57951
|
}
|
|
57678
57952
|
}
|
|
@@ -57824,6 +58098,7 @@ var require_handler_registry2 = __commonJS({
|
|
|
57824
58098
|
exports2.HandlerRegistryImpl = void 0;
|
|
57825
58099
|
var transcript_content_js_1 = require_transcript_content();
|
|
57826
58100
|
var structured_logging_js_1 = require_structured_logging();
|
|
58101
|
+
var error_utils_js_1 = require_error_utils();
|
|
57827
58102
|
var HandlerRegistryImpl = class {
|
|
57828
58103
|
options;
|
|
57829
58104
|
handlers = [];
|
|
@@ -57934,7 +58209,7 @@ var require_handler_registry2 = __commonJS({
|
|
|
57934
58209
|
log.error("Handler execution failed", {
|
|
57935
58210
|
handlerId: handler.id,
|
|
57936
58211
|
hook,
|
|
57937
|
-
error:
|
|
58212
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
57938
58213
|
});
|
|
57939
58214
|
}
|
|
57940
58215
|
}
|
|
@@ -57980,7 +58255,7 @@ var require_handler_registry2 = __commonJS({
|
|
|
57980
58255
|
(0, structured_logging_js_1.logEvent)(this.options.logger, structured_logging_js_1.LogEvents.eventProcessed(logContext, { handlerId: handler.id, success: true }, { durationMs }));
|
|
57981
58256
|
} catch (err) {
|
|
57982
58257
|
const durationMs = Date.now() - startTime;
|
|
57983
|
-
const errorMsg =
|
|
58258
|
+
const errorMsg = (0, error_utils_js_1.toErrorMessage)(err);
|
|
57984
58259
|
(0, structured_logging_js_1.logEvent)(this.options.logger, structured_logging_js_1.LogEvents.eventProcessed(logContext, { handlerId: handler.id, success: false }, { durationMs, error: errorMsg }));
|
|
57985
58260
|
this.options.logger.error("Transcript handler failed", {
|
|
57986
58261
|
handlerId: handler.id,
|
|
@@ -58339,6 +58614,9 @@ var require_path_resolver = __commonJS({
|
|
|
58339
58614
|
sessionStagingDir(sessionId) {
|
|
58340
58615
|
return (0, node_path_1.join)(this.sessionRootDir(sessionId), "stage");
|
|
58341
58616
|
}
|
|
58617
|
+
sessionLogsDir(sessionId) {
|
|
58618
|
+
return (0, node_path_1.join)(this.sessionRootDir(sessionId), "logs");
|
|
58619
|
+
}
|
|
58342
58620
|
hookStagingDir(sessionId, hookName) {
|
|
58343
58621
|
return (0, node_path_1.join)(this.sessionStagingDir(sessionId), hookName);
|
|
58344
58622
|
}
|
|
@@ -58408,6 +58686,7 @@ var require_state_service = __commonJS({
|
|
|
58408
58686
|
var node_path_1 = require("node:path");
|
|
58409
58687
|
var path_resolver_js_1 = require_path_resolver();
|
|
58410
58688
|
var errors_js_1 = require_errors6();
|
|
58689
|
+
var error_utils_js_1 = require_error_utils();
|
|
58411
58690
|
var errors_js_2 = require_errors6();
|
|
58412
58691
|
Object.defineProperty(exports2, "StateNotFoundError", { enumerable: true, get: function() {
|
|
58413
58692
|
return errors_js_2.StateNotFoundError;
|
|
@@ -58519,7 +58798,7 @@ var require_state_service = __commonJS({
|
|
|
58519
58798
|
} catch (cleanupErr) {
|
|
58520
58799
|
this.logger?.trace("Failed to cleanup temp file", {
|
|
58521
58800
|
tmpPath,
|
|
58522
|
-
error:
|
|
58801
|
+
error: (0, error_utils_js_1.toErrorMessage)(cleanupErr)
|
|
58523
58802
|
});
|
|
58524
58803
|
}
|
|
58525
58804
|
throw err;
|
|
@@ -58645,7 +58924,7 @@ var require_state_service = __commonJS({
|
|
|
58645
58924
|
} catch (err) {
|
|
58646
58925
|
this.logger?.warn("Failed to preload state file", {
|
|
58647
58926
|
file,
|
|
58648
|
-
error:
|
|
58927
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
58649
58928
|
});
|
|
58650
58929
|
}
|
|
58651
58930
|
}
|
|
@@ -58671,7 +58950,7 @@ var require_state_service = __commonJS({
|
|
|
58671
58950
|
this.logger?.warn("Corrupt state file detected", {
|
|
58672
58951
|
path,
|
|
58673
58952
|
reason,
|
|
58674
|
-
error:
|
|
58953
|
+
error: (0, error_utils_js_1.toErrorMessage)(error)
|
|
58675
58954
|
});
|
|
58676
58955
|
try {
|
|
58677
58956
|
await fs.rename(path, bakPath);
|
|
@@ -58701,7 +58980,7 @@ var require_state_service = __commonJS({
|
|
|
58701
58980
|
} catch (err) {
|
|
58702
58981
|
this.logger?.warn("Failed to create dev mode backup", {
|
|
58703
58982
|
path,
|
|
58704
|
-
error:
|
|
58983
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
58705
58984
|
});
|
|
58706
58985
|
}
|
|
58707
58986
|
}
|
|
@@ -58764,12 +59043,17 @@ var require_typed_accessor = __commonJS({
|
|
|
58764
59043
|
var SessionStateAccessor = class {
|
|
58765
59044
|
stateService;
|
|
58766
59045
|
descriptor;
|
|
58767
|
-
|
|
59046
|
+
journal;
|
|
59047
|
+
/** Descriptor filename without .json extension — used as journal file key */
|
|
59048
|
+
fileKey;
|
|
59049
|
+
constructor(stateService, descriptor, journal) {
|
|
58768
59050
|
this.stateService = stateService;
|
|
58769
59051
|
this.descriptor = descriptor;
|
|
59052
|
+
this.journal = journal;
|
|
58770
59053
|
if (descriptor.scope !== "session") {
|
|
58771
59054
|
throw new Error(`SessionStateAccessor requires a session-scoped descriptor, got: ${descriptor.scope}`);
|
|
58772
59055
|
}
|
|
59056
|
+
this.fileKey = descriptor.filename.replace(/\.json$/, "");
|
|
58773
59057
|
}
|
|
58774
59058
|
/**
|
|
58775
59059
|
* Read session state file.
|
|
@@ -58787,9 +59071,15 @@ var require_typed_accessor = __commonJS({
|
|
|
58787
59071
|
*/
|
|
58788
59072
|
async write(sessionId, data) {
|
|
58789
59073
|
const path = this.stateService.sessionStatePath(sessionId, this.descriptor.filename);
|
|
58790
|
-
|
|
59074
|
+
await this.stateService.write(path, data, this.descriptor.schema, {
|
|
58791
59075
|
trackHistory: this.descriptor.trackHistory
|
|
58792
59076
|
});
|
|
59077
|
+
if (this.journal) {
|
|
59078
|
+
try {
|
|
59079
|
+
await this.journal.appendIfChanged(sessionId, this.fileKey, data);
|
|
59080
|
+
} catch {
|
|
59081
|
+
}
|
|
59082
|
+
}
|
|
58793
59083
|
}
|
|
58794
59084
|
/**
|
|
58795
59085
|
* Delete session state file.
|
|
@@ -58797,6 +59087,12 @@ var require_typed_accessor = __commonJS({
|
|
|
58797
59087
|
async delete(sessionId) {
|
|
58798
59088
|
const path = this.stateService.sessionStatePath(sessionId, this.descriptor.filename);
|
|
58799
59089
|
await this.stateService.delete(path);
|
|
59090
|
+
if (this.journal) {
|
|
59091
|
+
try {
|
|
59092
|
+
await this.journal.appendDeletion(sessionId, this.fileKey);
|
|
59093
|
+
} catch {
|
|
59094
|
+
}
|
|
59095
|
+
}
|
|
58800
59096
|
}
|
|
58801
59097
|
/**
|
|
58802
59098
|
* Get the path for a session state file.
|
|
@@ -59062,8 +59358,51 @@ var require_transcript_normalizer = __commonJS({
|
|
|
59062
59358
|
exports2.parseUuid = parseUuid;
|
|
59063
59359
|
exports2.renderTranscriptString = renderTranscriptString;
|
|
59064
59360
|
var index_js_1 = require_state3();
|
|
59361
|
+
function buildRecapEntry(params) {
|
|
59362
|
+
const text = typeof params.rawText === "string" ? params.rawText.trim() : "";
|
|
59363
|
+
if (!text)
|
|
59364
|
+
return null;
|
|
59365
|
+
return {
|
|
59366
|
+
id: params.uuid ?? `line-${params.lineNumber}`,
|
|
59367
|
+
timestamp: new Date(params.timestamp ?? Date.now()),
|
|
59368
|
+
role: "system",
|
|
59369
|
+
type: "recap",
|
|
59370
|
+
content: text,
|
|
59371
|
+
metadata: {
|
|
59372
|
+
provider: "claude",
|
|
59373
|
+
lineNumber: params.lineNumber,
|
|
59374
|
+
recapSource: params.recapSource,
|
|
59375
|
+
leafUuid: params.leafUuid
|
|
59376
|
+
}
|
|
59377
|
+
};
|
|
59378
|
+
}
|
|
59065
59379
|
function normalizeEntry(rawEntry, lineNumber) {
|
|
59066
59380
|
const entryType = rawEntry.type;
|
|
59381
|
+
if (entryType === "summary") {
|
|
59382
|
+
const raw = rawEntry;
|
|
59383
|
+
const recap = buildRecapEntry({
|
|
59384
|
+
rawText: raw.summary,
|
|
59385
|
+
uuid: raw.uuid,
|
|
59386
|
+
timestamp: raw.timestamp,
|
|
59387
|
+
lineNumber,
|
|
59388
|
+
recapSource: "compaction",
|
|
59389
|
+
leafUuid: typeof raw.leafUuid === "string" ? raw.leafUuid : void 0
|
|
59390
|
+
});
|
|
59391
|
+
return recap ? [recap] : null;
|
|
59392
|
+
}
|
|
59393
|
+
if (entryType === "system") {
|
|
59394
|
+
const raw = rawEntry;
|
|
59395
|
+
if (raw.subtype !== "away_summary")
|
|
59396
|
+
return null;
|
|
59397
|
+
const recap = buildRecapEntry({
|
|
59398
|
+
rawText: raw.content,
|
|
59399
|
+
uuid: raw.uuid,
|
|
59400
|
+
timestamp: raw.timestamp,
|
|
59401
|
+
lineNumber,
|
|
59402
|
+
recapSource: "away"
|
|
59403
|
+
});
|
|
59404
|
+
return recap ? [recap] : null;
|
|
59405
|
+
}
|
|
59067
59406
|
if (entryType !== "user" && entryType !== "assistant") {
|
|
59068
59407
|
return null;
|
|
59069
59408
|
}
|
|
@@ -59197,6 +59536,9 @@ var require_transcript_normalizer = __commonJS({
|
|
|
59197
59536
|
return `[${timestamp}] ${role} TOOL_USE: ${String(toolContent.name)}`;
|
|
59198
59537
|
} else if (type === "tool_result") {
|
|
59199
59538
|
return `[${timestamp}] ${role} TOOL_RESULT`;
|
|
59539
|
+
} else if (type === "recap") {
|
|
59540
|
+
const content = typeof entry.content === "string" ? entry.content : "";
|
|
59541
|
+
return `[${timestamp}] RECAP: ${content}`;
|
|
59200
59542
|
}
|
|
59201
59543
|
return `[${timestamp}] ${role}: ${JSON.stringify(entry.content)}`;
|
|
59202
59544
|
}).join("\n");
|
|
@@ -59215,6 +59557,7 @@ var require_transcript_excerpt_builder = __commonJS({
|
|
|
59215
59557
|
exports2.extractTextContent = extractTextContent;
|
|
59216
59558
|
exports2.getRawContentString = getRawContentString;
|
|
59217
59559
|
var transcript_helpers_js_1 = require_transcript_helpers();
|
|
59560
|
+
var error_utils_js_1 = require_error_utils();
|
|
59218
59561
|
function getBufferedEntries(buffer, head, count, bufferSize) {
|
|
59219
59562
|
if (count === 0)
|
|
59220
59563
|
return [];
|
|
@@ -59269,7 +59612,7 @@ var require_transcript_excerpt_builder = __commonJS({
|
|
|
59269
59612
|
};
|
|
59270
59613
|
} catch (err) {
|
|
59271
59614
|
logger.error("Failed to extract transcript excerpt from buffer", {
|
|
59272
|
-
error:
|
|
59615
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
59273
59616
|
});
|
|
59274
59617
|
return {
|
|
59275
59618
|
content: "",
|
|
@@ -59330,6 +59673,14 @@ var require_transcript_excerpt_builder = __commonJS({
|
|
|
59330
59673
|
return null;
|
|
59331
59674
|
}
|
|
59332
59675
|
return `[SESSION_HINT]: ${entry.summary ?? ""}`;
|
|
59676
|
+
case "system": {
|
|
59677
|
+
if (entry.subtype !== "away_summary")
|
|
59678
|
+
return null;
|
|
59679
|
+
const content = entry.content;
|
|
59680
|
+
if (typeof content !== "string" || !content.trim())
|
|
59681
|
+
return null;
|
|
59682
|
+
return `[SESSION_RECAP]: ${content}`;
|
|
59683
|
+
}
|
|
59333
59684
|
default:
|
|
59334
59685
|
return null;
|
|
59335
59686
|
}
|
|
@@ -62188,6 +62539,7 @@ var require_instrumented_llm_provider = __commonJS({
|
|
|
62188
62539
|
var node_path_1 = require("node:path");
|
|
62189
62540
|
var yaml_1 = __importDefault(require_dist2());
|
|
62190
62541
|
var types_1 = require_dist();
|
|
62542
|
+
var error_utils_js_1 = require_error_utils();
|
|
62191
62543
|
var STATE_FILE = "llm-metrics.json";
|
|
62192
62544
|
var DEFAULT_DEBOUNCE_MS = 500;
|
|
62193
62545
|
function hasFallbackTracking(provider) {
|
|
@@ -62238,7 +62590,7 @@ var require_instrumented_llm_provider = __commonJS({
|
|
|
62238
62590
|
}
|
|
62239
62591
|
} catch (err) {
|
|
62240
62592
|
this.config.logger.warn("Failed to load LLM metrics, starting fresh", {
|
|
62241
|
-
error:
|
|
62593
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
62242
62594
|
});
|
|
62243
62595
|
}
|
|
62244
62596
|
}
|
|
@@ -62325,7 +62677,7 @@ var require_instrumented_llm_provider = __commonJS({
|
|
|
62325
62677
|
this.config.logger.debug("Debug dump written", { path: basePath });
|
|
62326
62678
|
} catch (dumpError) {
|
|
62327
62679
|
this.config.logger.warn("Failed to write debug dump", {
|
|
62328
|
-
error:
|
|
62680
|
+
error: (0, error_utils_js_1.toErrorMessage)(dumpError)
|
|
62329
62681
|
});
|
|
62330
62682
|
}
|
|
62331
62683
|
}
|
|
@@ -62550,7 +62902,7 @@ var require_instrumented_llm_provider = __commonJS({
|
|
|
62550
62902
|
});
|
|
62551
62903
|
} catch (err) {
|
|
62552
62904
|
this.config.logger.warn("Failed to persist LLM metrics", {
|
|
62553
|
-
error:
|
|
62905
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
62554
62906
|
});
|
|
62555
62907
|
}
|
|
62556
62908
|
}
|
|
@@ -62826,6 +63178,7 @@ var require_daemon_health = __commonJS({
|
|
|
62826
63178
|
var fs = __importStar(require("node:fs/promises"));
|
|
62827
63179
|
var node_path_1 = require("node:path");
|
|
62828
63180
|
var types_1 = require_dist();
|
|
63181
|
+
var error_utils_js_1 = require_error_utils();
|
|
62829
63182
|
function healthFilePath(projectDir2) {
|
|
62830
63183
|
return (0, node_path_1.join)(projectDir2, ".sidekick", "state", "daemon-health.json");
|
|
62831
63184
|
}
|
|
@@ -62884,7 +63237,7 @@ var require_daemon_health = __commonJS({
|
|
|
62884
63237
|
logger.warn("Failed to write daemon health", {
|
|
62885
63238
|
from,
|
|
62886
63239
|
to,
|
|
62887
|
-
error:
|
|
63240
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
62888
63241
|
});
|
|
62889
63242
|
return false;
|
|
62890
63243
|
}
|
|
@@ -62971,6 +63324,7 @@ var require_user_profile_loader = __commonJS({
|
|
|
62971
63324
|
var node_path_1 = require("node:path");
|
|
62972
63325
|
var yaml_1 = require_dist2();
|
|
62973
63326
|
var types_1 = require_dist();
|
|
63327
|
+
var error_utils_js_1 = require_error_utils();
|
|
62974
63328
|
function loadUserProfile(options) {
|
|
62975
63329
|
const home = options?.homeDir ?? (0, node_os_1.homedir)();
|
|
62976
63330
|
const filePath = (0, node_path_1.join)(home, ".sidekick", "user.yaml");
|
|
@@ -62992,7 +63346,7 @@ var require_user_profile_loader = __commonJS({
|
|
|
62992
63346
|
} catch (err) {
|
|
62993
63347
|
options?.logger?.warn("Failed to read user profile", {
|
|
62994
63348
|
path: filePath,
|
|
62995
|
-
error:
|
|
63349
|
+
error: (0, error_utils_js_1.toErrorMessage)(err)
|
|
62996
63350
|
});
|
|
62997
63351
|
return null;
|
|
62998
63352
|
}
|
|
@@ -63059,9 +63413,9 @@ var require_dist4 = __commonJS({
|
|
|
63059
63413
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
63060
63414
|
};
|
|
63061
63415
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
63062
|
-
exports2.
|
|
63063
|
-
exports2.
|
|
63064
|
-
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;
|
|
63416
|
+
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;
|
|
63417
|
+
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;
|
|
63418
|
+
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;
|
|
63065
63419
|
var types_1 = require_dist();
|
|
63066
63420
|
Object.defineProperty(exports2, "TaskTypes", { enumerable: true, get: function() {
|
|
63067
63421
|
return types_1.TaskTypes;
|
|
@@ -63106,6 +63460,12 @@ var require_dist4 = __commonJS({
|
|
|
63106
63460
|
Object.defineProperty(exports2, "isPreCompactEvent", { enumerable: true, get: function() {
|
|
63107
63461
|
return types_2.isPreCompactEvent;
|
|
63108
63462
|
} });
|
|
63463
|
+
Object.defineProperty(exports2, "isSubagentStartEvent", { enumerable: true, get: function() {
|
|
63464
|
+
return types_2.isSubagentStartEvent;
|
|
63465
|
+
} });
|
|
63466
|
+
Object.defineProperty(exports2, "isSubagentStopEvent", { enumerable: true, get: function() {
|
|
63467
|
+
return types_2.isSubagentStopEvent;
|
|
63468
|
+
} });
|
|
63109
63469
|
__exportStar(require_assets(), exports2);
|
|
63110
63470
|
var claude_paths_1 = require_claude_paths();
|
|
63111
63471
|
Object.defineProperty(exports2, "encodeProjectPath", { enumerable: true, get: function() {
|
|
@@ -63194,6 +63554,12 @@ var require_dist4 = __commonJS({
|
|
|
63194
63554
|
Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
|
|
63195
63555
|
return structured_logging_1.logEvent;
|
|
63196
63556
|
} });
|
|
63557
|
+
Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
|
|
63558
|
+
return structured_logging_1.setSessionLogWriter;
|
|
63559
|
+
} });
|
|
63560
|
+
Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
|
|
63561
|
+
return structured_logging_1.SessionLogWriter;
|
|
63562
|
+
} });
|
|
63197
63563
|
var daemon_client_1 = require_daemon_client2();
|
|
63198
63564
|
Object.defineProperty(exports2, "killAllDaemons", { enumerable: true, get: function() {
|
|
63199
63565
|
return daemon_client_1.killAllDaemons;
|
|
@@ -63220,9 +63586,6 @@ var require_dist4 = __commonJS({
|
|
|
63220
63586
|
Object.defineProperty(exports2, "PROJECT_STATUS_FILENAME", { enumerable: true, get: function() {
|
|
63221
63587
|
return setup_status_service_1.PROJECT_STATUS_FILENAME;
|
|
63222
63588
|
} });
|
|
63223
|
-
Object.defineProperty(exports2, "LEGACY_USER_STATUS_FILENAME", { enumerable: true, get: function() {
|
|
63224
|
-
return setup_status_service_1.LEGACY_USER_STATUS_FILENAME;
|
|
63225
|
-
} });
|
|
63226
63589
|
var api_key_detector_1 = require_api_key_detector();
|
|
63227
63590
|
Object.defineProperty(exports2, "toScopeStatus", { enumerable: true, get: function() {
|
|
63228
63591
|
return api_key_detector_1.toScopeStatus;
|
|
@@ -63291,12 +63654,21 @@ var require_dist4 = __commonJS({
|
|
|
63291
63654
|
Object.defineProperty(exports2, "detectGitignoreStatus", { enumerable: true, get: function() {
|
|
63292
63655
|
return gitignore_1.detectGitignoreStatus;
|
|
63293
63656
|
} });
|
|
63657
|
+
Object.defineProperty(exports2, "detectLegacyGitignoreSection", { enumerable: true, get: function() {
|
|
63658
|
+
return gitignore_1.detectLegacyGitignoreSection;
|
|
63659
|
+
} });
|
|
63660
|
+
Object.defineProperty(exports2, "removeLegacyGitignoreSection", { enumerable: true, get: function() {
|
|
63661
|
+
return gitignore_1.removeLegacyGitignoreSection;
|
|
63662
|
+
} });
|
|
63294
63663
|
Object.defineProperty(exports2, "SIDEKICK_SECTION_START", { enumerable: true, get: function() {
|
|
63295
63664
|
return gitignore_1.SIDEKICK_SECTION_START;
|
|
63296
63665
|
} });
|
|
63297
63666
|
Object.defineProperty(exports2, "SIDEKICK_SECTION_END", { enumerable: true, get: function() {
|
|
63298
63667
|
return gitignore_1.SIDEKICK_SECTION_END;
|
|
63299
63668
|
} });
|
|
63669
|
+
Object.defineProperty(exports2, "SIDEKICK_GITIGNORE_HEADER", { enumerable: true, get: function() {
|
|
63670
|
+
return gitignore_1.SIDEKICK_GITIGNORE_HEADER;
|
|
63671
|
+
} });
|
|
63300
63672
|
Object.defineProperty(exports2, "GITIGNORE_ENTRIES", { enumerable: true, get: function() {
|
|
63301
63673
|
return gitignore_1.GITIGNORE_ENTRIES;
|
|
63302
63674
|
} });
|
|
@@ -63449,6 +63821,10 @@ var require_dist4 = __commonJS({
|
|
|
63449
63821
|
Object.defineProperty(exports2, "isInSandbox", { enumerable: true, get: function() {
|
|
63450
63822
|
return sandbox_1.isInSandbox;
|
|
63451
63823
|
} });
|
|
63824
|
+
var error_utils_1 = require_error_utils();
|
|
63825
|
+
Object.defineProperty(exports2, "toErrorMessage", { enumerable: true, get: function() {
|
|
63826
|
+
return error_utils_1.toErrorMessage;
|
|
63827
|
+
} });
|
|
63452
63828
|
var git_status_1 = require_git_status();
|
|
63453
63829
|
Object.defineProperty(exports2, "getGitFileStatus", { enumerable: true, get: function() {
|
|
63454
63830
|
return git_status_1.getGitFileStatus;
|
|
@@ -70484,6 +70860,7 @@ var require_reminder_utils = __commonJS({
|
|
|
70484
70860
|
var node_path_1 = require("node:path");
|
|
70485
70861
|
var yaml = __importStar(require_js_yaml());
|
|
70486
70862
|
var zod_1 = require_zod2();
|
|
70863
|
+
var core_1 = require_dist4();
|
|
70487
70864
|
var ReminderDefinitionSchema = zod_1.z.object({
|
|
70488
70865
|
id: zod_1.z.string(),
|
|
70489
70866
|
blocking: zod_1.z.boolean(),
|
|
@@ -70536,7 +70913,7 @@ var require_reminder_utils = __commonJS({
|
|
|
70536
70913
|
if (logger) {
|
|
70537
70914
|
logger.error("Failed to load reminder", {
|
|
70538
70915
|
reminderId,
|
|
70539
|
-
error:
|
|
70916
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
70540
70917
|
});
|
|
70541
70918
|
} else {
|
|
70542
70919
|
console.error(`Failed to load reminder ${reminderId}:`, err);
|
|
@@ -71276,7 +71653,7 @@ var require_stage_pause_and_reflect = __commonJS({
|
|
|
71276
71653
|
(0, staging_handler_utils_js_1.createStagingHandler)(context, {
|
|
71277
71654
|
id: "reminders:stage-pause-and-reflect",
|
|
71278
71655
|
priority: 80,
|
|
71279
|
-
filter: { kind: "transcript", eventTypes: ["
|
|
71656
|
+
filter: { kind: "transcript", eventTypes: ["ToolResult"] },
|
|
71280
71657
|
execute: async (event, ctx) => {
|
|
71281
71658
|
if (!(0, types_1.isTranscriptEvent)(event))
|
|
71282
71659
|
return void 0;
|
|
@@ -72959,17 +73336,15 @@ var require_track_verification_tools = __commonJS({
|
|
|
72959
73336
|
var state_js_1 = require_state4();
|
|
72960
73337
|
var FILE_EDIT_TOOLS = ["Write", "Edit", "MultiEdit"];
|
|
72961
73338
|
var VC_TOOL_NAME_SET = new Set(types_js_1.VC_TOOL_REMINDER_IDS);
|
|
72962
|
-
|
|
72963
|
-
const entry = event.payload.entry;
|
|
72964
|
-
return entry?.input;
|
|
72965
|
-
}
|
|
73339
|
+
var MAX_PENDING_TOOL_CALLS = 100;
|
|
72966
73340
|
function registerTrackVerificationTools(context) {
|
|
72967
73341
|
if (!(0, types_1.isDaemonContext)(context))
|
|
72968
73342
|
return;
|
|
73343
|
+
const pendingBySession = /* @__PURE__ */ new Map();
|
|
72969
73344
|
context.handlers.register({
|
|
72970
73345
|
id: "reminders:track-verification-tools",
|
|
72971
73346
|
priority: 60,
|
|
72972
|
-
filter: { kind: "transcript", eventTypes: ["ToolCall"] },
|
|
73347
|
+
filter: { kind: "transcript", eventTypes: ["ToolCall", "ToolResult"] },
|
|
72973
73348
|
handler: async (event, ctx) => {
|
|
72974
73349
|
if (!(0, types_1.isTranscriptEvent)(event))
|
|
72975
73350
|
return;
|
|
@@ -72981,22 +73356,66 @@ var require_track_verification_tools = __commonJS({
|
|
|
72981
73356
|
const sessionId = event.context?.sessionId;
|
|
72982
73357
|
if (!sessionId)
|
|
72983
73358
|
return;
|
|
72984
|
-
|
|
72985
|
-
|
|
73359
|
+
if (event.eventType === "ToolCall") {
|
|
73360
|
+
const toolUseId = event.payload.entry.id;
|
|
73361
|
+
const toolName = event.payload.toolName;
|
|
73362
|
+
if (!toolUseId || !toolName)
|
|
73363
|
+
return;
|
|
73364
|
+
const entry = event.payload.entry;
|
|
73365
|
+
const input = entry?.input ?? {};
|
|
73366
|
+
let sessionMap = pendingBySession.get(sessionId);
|
|
73367
|
+
if (!sessionMap) {
|
|
73368
|
+
sessionMap = /* @__PURE__ */ new Map();
|
|
73369
|
+
pendingBySession.set(sessionId, sessionMap);
|
|
73370
|
+
}
|
|
73371
|
+
if (sessionMap.size >= MAX_PENDING_TOOL_CALLS) {
|
|
73372
|
+
const oldest = sessionMap.keys().next().value;
|
|
73373
|
+
if (oldest)
|
|
73374
|
+
sessionMap.delete(oldest);
|
|
73375
|
+
}
|
|
73376
|
+
sessionMap.set(toolUseId, { toolName, input });
|
|
72986
73377
|
return;
|
|
72987
|
-
|
|
72988
|
-
|
|
72989
|
-
|
|
72990
|
-
|
|
72991
|
-
|
|
72992
|
-
|
|
72993
|
-
|
|
72994
|
-
|
|
72995
|
-
|
|
72996
|
-
|
|
73378
|
+
}
|
|
73379
|
+
if (event.eventType === "ToolResult") {
|
|
73380
|
+
const toolUseId = event.payload.entry.tool_use_id;
|
|
73381
|
+
if (!toolUseId)
|
|
73382
|
+
return;
|
|
73383
|
+
const sessionMap = pendingBySession.get(sessionId);
|
|
73384
|
+
const pending = sessionMap?.get(toolUseId);
|
|
73385
|
+
if (!pending)
|
|
73386
|
+
return;
|
|
73387
|
+
sessionMap.delete(toolUseId);
|
|
73388
|
+
if (sessionMap.size === 0)
|
|
73389
|
+
pendingBySession.delete(sessionId);
|
|
73390
|
+
const { toolName, input } = pending;
|
|
73391
|
+
const config = (0, types_js_1.getRemindersConfig)(context.config);
|
|
73392
|
+
const verificationTools = config.verification_tools ?? {};
|
|
73393
|
+
const runners = config.command_runners ?? [];
|
|
73394
|
+
const remindersState = (0, state_js_1.createRemindersState)(daemonCtx.stateService);
|
|
73395
|
+
const stateResult = await remindersState.verificationTools.read(sessionId);
|
|
73396
|
+
const toolsState = { ...stateResult.data };
|
|
73397
|
+
if (FILE_EDIT_TOOLS.includes(toolName)) {
|
|
73398
|
+
await handleFileEdit(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
73399
|
+
} else if (toolName === "Bash") {
|
|
73400
|
+
await handleBashCommand(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners);
|
|
73401
|
+
}
|
|
72997
73402
|
}
|
|
72998
73403
|
}
|
|
72999
73404
|
});
|
|
73405
|
+
context.handlers.register({
|
|
73406
|
+
id: "reminders:track-verification-tools-cleanup",
|
|
73407
|
+
priority: 60,
|
|
73408
|
+
filter: { kind: "hook", hooks: ["UserPromptSubmit", "Stop"] },
|
|
73409
|
+
// eslint-disable-next-line @typescript-eslint/require-await -- sync cleanup, async required by EventHandler type
|
|
73410
|
+
handler: async (event, _ctx) => {
|
|
73411
|
+
if (!(0, types_1.isHookEvent)(event))
|
|
73412
|
+
return;
|
|
73413
|
+
const sessionId = event.context?.sessionId;
|
|
73414
|
+
if (!sessionId)
|
|
73415
|
+
return;
|
|
73416
|
+
pendingBySession.delete(sessionId);
|
|
73417
|
+
}
|
|
73418
|
+
});
|
|
73000
73419
|
}
|
|
73001
73420
|
async function stageToolsForFiles(filePaths, daemonCtx, sessionId, verificationTools, toolsState, remindersState, triggeredBy = "file_edit") {
|
|
73002
73421
|
const existingReminders = await daemonCtx.staging.listReminders("Stop");
|
|
@@ -73101,7 +73520,7 @@ var require_track_verification_tools = __commonJS({
|
|
|
73101
73520
|
toolName,
|
|
73102
73521
|
reminderId,
|
|
73103
73522
|
sessionId,
|
|
73104
|
-
error:
|
|
73523
|
+
error: (0, core_1.toErrorMessage)(error)
|
|
73105
73524
|
});
|
|
73106
73525
|
}
|
|
73107
73526
|
}
|
|
@@ -73115,8 +73534,8 @@ var require_track_verification_tools = __commonJS({
|
|
|
73115
73534
|
await remindersState.verificationTools.write(sessionId, toolsState);
|
|
73116
73535
|
return anyStaged;
|
|
73117
73536
|
}
|
|
73118
|
-
async function handleFileEdit(
|
|
73119
|
-
const filePath =
|
|
73537
|
+
async function handleFileEdit(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState) {
|
|
73538
|
+
const filePath = input.file_path;
|
|
73120
73539
|
if (!filePath)
|
|
73121
73540
|
return;
|
|
73122
73541
|
const projectDir2 = daemonCtx.paths?.projectDir;
|
|
@@ -73124,8 +73543,8 @@ var require_track_verification_tools = __commonJS({
|
|
|
73124
73543
|
return;
|
|
73125
73544
|
await stageToolsForFiles([filePath], daemonCtx, sessionId, verificationTools, toolsState, remindersState);
|
|
73126
73545
|
}
|
|
73127
|
-
async function handleBashCommand(
|
|
73128
|
-
const command =
|
|
73546
|
+
async function handleBashCommand(input, daemonCtx, sessionId, verificationTools, toolsState, remindersState, runners = []) {
|
|
73547
|
+
const command = input.command;
|
|
73129
73548
|
if (!command)
|
|
73130
73549
|
return;
|
|
73131
73550
|
let anyUnstaged = false;
|
|
@@ -73554,7 +73973,7 @@ var require_stage_persona_reminders = __commonJS({
|
|
|
73554
73973
|
} catch (err) {
|
|
73555
73974
|
logger.error("Failed to restage persona reminders", {
|
|
73556
73975
|
sessionId,
|
|
73557
|
-
error:
|
|
73976
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
73558
73977
|
});
|
|
73559
73978
|
}
|
|
73560
73979
|
}
|
|
@@ -73790,6 +74209,38 @@ var require_stage_user_profile_reminders = __commonJS({
|
|
|
73790
74209
|
}
|
|
73791
74210
|
});
|
|
73792
74211
|
|
|
74212
|
+
// ../feature-reminders/dist/handlers/staging/cleanup-on-stop.js
|
|
74213
|
+
var require_cleanup_on_stop = __commonJS({
|
|
74214
|
+
"../feature-reminders/dist/handlers/staging/cleanup-on-stop.js"(exports2) {
|
|
74215
|
+
"use strict";
|
|
74216
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
74217
|
+
exports2.registerCleanupOnStop = registerCleanupOnStop;
|
|
74218
|
+
var types_1 = require_dist();
|
|
74219
|
+
function registerCleanupOnStop(context) {
|
|
74220
|
+
if (!(0, types_1.isDaemonContext)(context))
|
|
74221
|
+
return;
|
|
74222
|
+
context.handlers.register({
|
|
74223
|
+
id: "reminders:cleanup-on-stop",
|
|
74224
|
+
priority: 50,
|
|
74225
|
+
filter: { kind: "hook", hooks: ["Stop"] },
|
|
74226
|
+
handler: async (event, ctx) => {
|
|
74227
|
+
if (!(0, types_1.isHookEvent)(event))
|
|
74228
|
+
return;
|
|
74229
|
+
if (!(0, types_1.isDaemonContext)(ctx))
|
|
74230
|
+
return;
|
|
74231
|
+
const daemonCtx = ctx;
|
|
74232
|
+
const sessionId = event.context?.sessionId;
|
|
74233
|
+
if (!sessionId)
|
|
74234
|
+
return;
|
|
74235
|
+
if (daemonCtx.orchestrator) {
|
|
74236
|
+
await daemonCtx.orchestrator.onStop(sessionId);
|
|
74237
|
+
}
|
|
74238
|
+
}
|
|
74239
|
+
});
|
|
74240
|
+
}
|
|
74241
|
+
}
|
|
74242
|
+
});
|
|
74243
|
+
|
|
73793
74244
|
// ../feature-reminders/dist/handlers/staging/index.js
|
|
73794
74245
|
var require_staging2 = __commonJS({
|
|
73795
74246
|
"../feature-reminders/dist/handlers/staging/index.js"(exports2) {
|
|
@@ -73803,6 +74254,7 @@ var require_staging2 = __commonJS({
|
|
|
73803
74254
|
var unstage_verify_completion_1 = require_unstage_verify_completion();
|
|
73804
74255
|
var stage_persona_reminders_1 = require_stage_persona_reminders();
|
|
73805
74256
|
var stage_user_profile_reminders_1 = require_stage_user_profile_reminders();
|
|
74257
|
+
var cleanup_on_stop_1 = require_cleanup_on_stop();
|
|
73806
74258
|
function registerStagingHandlers(context) {
|
|
73807
74259
|
(0, stage_default_user_prompt_1.registerStageDefaultUserPrompt)(context);
|
|
73808
74260
|
(0, stage_pause_and_reflect_1.registerStagePauseAndReflect)(context);
|
|
@@ -73811,6 +74263,7 @@ var require_staging2 = __commonJS({
|
|
|
73811
74263
|
(0, unstage_verify_completion_1.registerUnstageVerifyCompletion)(context);
|
|
73812
74264
|
(0, stage_persona_reminders_1.registerStagePersonaReminders)(context);
|
|
73813
74265
|
(0, stage_user_profile_reminders_1.registerStageUserProfileReminders)(context);
|
|
74266
|
+
(0, cleanup_on_stop_1.registerCleanupOnStop)(context);
|
|
73814
74267
|
}
|
|
73815
74268
|
}
|
|
73816
74269
|
});
|
|
@@ -74531,7 +74984,7 @@ var require_orchestrator = __commonJS({
|
|
|
74531
74984
|
} catch (err) {
|
|
74532
74985
|
this.deps.logger.warn("Failed to unstage VC reminders after P&R staged", {
|
|
74533
74986
|
sessionId,
|
|
74534
|
-
error:
|
|
74987
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
74535
74988
|
});
|
|
74536
74989
|
}
|
|
74537
74990
|
}
|
|
@@ -74555,27 +75008,10 @@ var require_orchestrator = __commonJS({
|
|
|
74555
75008
|
} catch (err) {
|
|
74556
75009
|
this.deps.logger.warn("Failed to reset P&R baseline after VC consumed", {
|
|
74557
75010
|
sessionId,
|
|
74558
|
-
error:
|
|
74559
|
-
});
|
|
74560
|
-
}
|
|
74561
|
-
try {
|
|
74562
|
-
const staging = this.deps.getStagingService(sessionId);
|
|
74563
|
-
const deleted = await staging.deleteReminder("PreToolUse", types_js_1.ReminderIds.PAUSE_AND_REFLECT);
|
|
74564
|
-
if (deleted) {
|
|
74565
|
-
(0, core_1.logEvent)(this.deps.logger.child({ context: { sessionId } }), events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
74566
|
-
reminderName: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
|
|
74567
|
-
hookName: "PreToolUse",
|
|
74568
|
-
reason: "vc_consumed_cascade",
|
|
74569
|
-
triggeredBy: "cascade_from_verify_completion"
|
|
74570
|
-
}));
|
|
74571
|
-
}
|
|
74572
|
-
this.deps.logger.debug("VC unstage: P&R cascade from VC consumed", { sessionId, deleted });
|
|
74573
|
-
} catch (err) {
|
|
74574
|
-
this.deps.logger.warn("Failed to unstage P&R after VC consumed", {
|
|
74575
|
-
sessionId,
|
|
74576
|
-
error: err instanceof Error ? err.message : String(err)
|
|
75011
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
74577
75012
|
});
|
|
74578
75013
|
}
|
|
75014
|
+
await this.unstagePauseAndReflect(sessionId, "vc_consumed_cascade", "cascade_from_verify_completion");
|
|
74579
75015
|
}
|
|
74580
75016
|
}
|
|
74581
75017
|
/**
|
|
@@ -74592,7 +75028,43 @@ var require_orchestrator = __commonJS({
|
|
|
74592
75028
|
} catch (err) {
|
|
74593
75029
|
this.deps.logger.warn("Failed to clear P&R baseline on UserPromptSubmit", {
|
|
74594
75030
|
sessionId,
|
|
74595
|
-
error:
|
|
75031
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
75032
|
+
});
|
|
75033
|
+
}
|
|
75034
|
+
}
|
|
75035
|
+
/**
|
|
75036
|
+
* Called when Stop hook fires.
|
|
75037
|
+
*
|
|
75038
|
+
* P&R is designed to interrupt runaway execution — once the agent stops,
|
|
75039
|
+
* it's irrelevant. This is defensive: Rule 4 (VC consumed → unstage P&R)
|
|
75040
|
+
* covers the VC case, but this handles the no-VC case where P&R would
|
|
75041
|
+
* otherwise linger on PreToolUse.
|
|
75042
|
+
*/
|
|
75043
|
+
async onStop(sessionId) {
|
|
75044
|
+
await this.unstagePauseAndReflect(sessionId, "agent_stopping", "stop_hook");
|
|
75045
|
+
}
|
|
75046
|
+
/**
|
|
75047
|
+
* Delete P&R from PreToolUse staging and log the event.
|
|
75048
|
+
* Shared by Rule 4 (VC consumed → unstage P&R) and onStop (agent stopping).
|
|
75049
|
+
*/
|
|
75050
|
+
async unstagePauseAndReflect(sessionId, reason, triggeredBy) {
|
|
75051
|
+
try {
|
|
75052
|
+
const staging = this.deps.getStagingService(sessionId);
|
|
75053
|
+
const deleted = await staging.deleteReminder("PreToolUse", types_js_1.ReminderIds.PAUSE_AND_REFLECT);
|
|
75054
|
+
if (deleted) {
|
|
75055
|
+
(0, core_1.logEvent)(this.deps.logger.child({ context: { sessionId } }), events_js_1.ReminderEvents.reminderUnstaged({ sessionId }, {
|
|
75056
|
+
reminderName: types_js_1.ReminderIds.PAUSE_AND_REFLECT,
|
|
75057
|
+
hookName: "PreToolUse",
|
|
75058
|
+
reason,
|
|
75059
|
+
triggeredBy
|
|
75060
|
+
}));
|
|
75061
|
+
}
|
|
75062
|
+
this.deps.logger.debug("P&R unstaged", { sessionId, deleted, reason });
|
|
75063
|
+
} catch (err) {
|
|
75064
|
+
this.deps.logger.warn("Failed to unstage P&R", {
|
|
75065
|
+
sessionId,
|
|
75066
|
+
reason,
|
|
75067
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
74596
75068
|
});
|
|
74597
75069
|
}
|
|
74598
75070
|
}
|
|
@@ -74988,7 +75460,7 @@ var require_persona_selection = __commonJS({
|
|
|
74988
75460
|
} catch (err) {
|
|
74989
75461
|
ctx.logger.warn("Failed to ensure persona for session", {
|
|
74990
75462
|
sessionId,
|
|
74991
|
-
error:
|
|
75463
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
74992
75464
|
});
|
|
74993
75465
|
}
|
|
74994
75466
|
}
|
|
@@ -75748,7 +76220,7 @@ var require_update_summary = __commonJS({
|
|
|
75748
76220
|
ctx.logger.error("performAnalysis failed", {
|
|
75749
76221
|
sessionId,
|
|
75750
76222
|
reason,
|
|
75751
|
-
error:
|
|
76223
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
75752
76224
|
});
|
|
75753
76225
|
}
|
|
75754
76226
|
}
|
|
@@ -76075,6 +76547,7 @@ var require_config_watcher = __commonJS({
|
|
|
76075
76547
|
};
|
|
76076
76548
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
76077
76549
|
exports2.ConfigWatcher = void 0;
|
|
76550
|
+
var core_1 = require_dist4();
|
|
76078
76551
|
var chokidar_1 = (init_chokidar(), __toCommonJS(chokidar_exports));
|
|
76079
76552
|
var os_1 = require("os");
|
|
76080
76553
|
var path_1 = __importDefault(require("path"));
|
|
@@ -76205,7 +76678,7 @@ var require_config_watcher = __commonJS({
|
|
|
76205
76678
|
} catch (err) {
|
|
76206
76679
|
this.logger.error("Error in config change handler", {
|
|
76207
76680
|
file: filename,
|
|
76208
|
-
error:
|
|
76681
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
76209
76682
|
});
|
|
76210
76683
|
}
|
|
76211
76684
|
}, this.debounceMs);
|
|
@@ -76238,6 +76711,7 @@ var require_session_persona_watcher = __commonJS({
|
|
|
76238
76711
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
76239
76712
|
exports2.SessionPersonaWatcher = void 0;
|
|
76240
76713
|
exports2.extractSessionIdFromPath = extractSessionIdFromPath;
|
|
76714
|
+
var core_1 = require_dist4();
|
|
76241
76715
|
var chokidar_1 = (init_chokidar(), __toCommonJS(chokidar_exports));
|
|
76242
76716
|
var path_1 = __importDefault(require("path"));
|
|
76243
76717
|
var PERSONA_FILENAME = "session-persona.json";
|
|
@@ -76358,7 +76832,7 @@ var require_session_persona_watcher = __commonJS({
|
|
|
76358
76832
|
} catch (err) {
|
|
76359
76833
|
this.logger.error("Error in persona change handler", {
|
|
76360
76834
|
sessionId,
|
|
76361
|
-
error:
|
|
76835
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
76362
76836
|
});
|
|
76363
76837
|
}
|
|
76364
76838
|
}, this.debounceMs);
|
|
@@ -76655,7 +77129,7 @@ var require_context_metrics_service = __commonJS({
|
|
|
76655
77129
|
this.logger.info("Triggering async CLI capture for base metrics");
|
|
76656
77130
|
void this.captureBaseMetrics().catch((err) => {
|
|
76657
77131
|
this.logger.warn("Failed to capture base metrics via CLI", {
|
|
76658
|
-
error:
|
|
77132
|
+
error: (0, core_1.toErrorMessage)(err),
|
|
76659
77133
|
stack: err instanceof Error ? err.stack : void 0
|
|
76660
77134
|
});
|
|
76661
77135
|
});
|
|
@@ -76781,7 +77255,7 @@ var require_context_metrics_service = __commonJS({
|
|
|
76781
77255
|
sessionId
|
|
76782
77256
|
});
|
|
76783
77257
|
} catch (err) {
|
|
76784
|
-
const errorMessage =
|
|
77258
|
+
const errorMessage = (0, core_1.toErrorMessage)(err);
|
|
76785
77259
|
this.logger.warn("CLI capture failed", {
|
|
76786
77260
|
error: errorMessage,
|
|
76787
77261
|
stack: err instanceof Error ? err.stack : void 0
|
|
@@ -77073,7 +77547,7 @@ var require_cleanup_handler = __commonJS({
|
|
|
77073
77547
|
} catch (statErr) {
|
|
77074
77548
|
ctx.logger.warn("Failed to stat session directory", {
|
|
77075
77549
|
session: entry.name,
|
|
77076
|
-
error:
|
|
77550
|
+
error: (0, core_1.toErrorMessage)(statErr)
|
|
77077
77551
|
});
|
|
77078
77552
|
}
|
|
77079
77553
|
}
|
|
@@ -77089,7 +77563,7 @@ var require_cleanup_handler = __commonJS({
|
|
|
77089
77563
|
return;
|
|
77090
77564
|
}
|
|
77091
77565
|
ctx.logger.error("Cleanup task failed", {
|
|
77092
|
-
error:
|
|
77566
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
77093
77567
|
});
|
|
77094
77568
|
throw err;
|
|
77095
77569
|
}
|
|
@@ -77265,6 +77739,7 @@ var require_task_engine = __commonJS({
|
|
|
77265
77739
|
};
|
|
77266
77740
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
77267
77741
|
exports2.TaskEngine = exports2.TaskTimeoutError = void 0;
|
|
77742
|
+
var core_1 = require_dist4();
|
|
77268
77743
|
var crypto_1 = __importDefault(require("crypto"));
|
|
77269
77744
|
var DEFAULT_TASK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
77270
77745
|
var TaskTimeoutError = class extends Error {
|
|
@@ -77393,7 +77868,7 @@ var require_task_engine = __commonJS({
|
|
|
77393
77868
|
this.logger.error("Task failed", {
|
|
77394
77869
|
type: task.type,
|
|
77395
77870
|
id: task.id,
|
|
77396
|
-
error:
|
|
77871
|
+
error: (0, core_1.toErrorMessage)(err),
|
|
77397
77872
|
stack: err instanceof Error ? err.stack : void 0,
|
|
77398
77873
|
durationMs
|
|
77399
77874
|
});
|
|
@@ -77713,7 +78188,7 @@ var require_daemon_timer_manager = __commonJS({
|
|
|
77713
78188
|
this.deps.logger.info("Project registered for UI discovery", { projectDir: this.deps.projectDir });
|
|
77714
78189
|
} catch (err) {
|
|
77715
78190
|
this.deps.logger.warn("Failed to register project", {
|
|
77716
|
-
error:
|
|
78191
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
77717
78192
|
});
|
|
77718
78193
|
}
|
|
77719
78194
|
}
|
|
@@ -77877,7 +78352,7 @@ var require_daemon_log_metrics = __commonJS({
|
|
|
77877
78352
|
await this.daemonStatusAccessor.write(status);
|
|
77878
78353
|
} catch (err) {
|
|
77879
78354
|
this.logger?.warn("Failed to write heartbeat status", {
|
|
77880
|
-
error:
|
|
78355
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
77881
78356
|
});
|
|
77882
78357
|
}
|
|
77883
78358
|
await this.persistLogMetrics();
|
|
@@ -77919,7 +78394,7 @@ var require_daemon_log_metrics = __commonJS({
|
|
|
77919
78394
|
} catch (err) {
|
|
77920
78395
|
this.logger?.warn("Failed to persist log metrics", {
|
|
77921
78396
|
sessionId,
|
|
77922
|
-
error:
|
|
78397
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
77923
78398
|
});
|
|
77924
78399
|
}
|
|
77925
78400
|
}
|
|
@@ -77932,7 +78407,7 @@ var require_daemon_log_metrics = __commonJS({
|
|
|
77932
78407
|
await this.globalLogMetricsAccessor.write(globalMetrics);
|
|
77933
78408
|
} catch (err) {
|
|
77934
78409
|
this.logger?.warn("Failed to persist global log metrics", {
|
|
77935
|
-
error:
|
|
78410
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
77936
78411
|
});
|
|
77937
78412
|
}
|
|
77938
78413
|
}
|
|
@@ -78138,6 +78613,7 @@ var require_daemon = __commonJS({
|
|
|
78138
78613
|
token = "";
|
|
78139
78614
|
registryService;
|
|
78140
78615
|
timerManager;
|
|
78616
|
+
sessionLogWriter;
|
|
78141
78617
|
/** Cache persona for handoff on clear. */
|
|
78142
78618
|
cachePersonaForClear(personaId) {
|
|
78143
78619
|
this.lastClearedPersona = { personaId, timestamp: Date.now() };
|
|
@@ -78180,8 +78656,9 @@ var require_daemon = __commonJS({
|
|
|
78180
78656
|
destinations: {
|
|
78181
78657
|
file: {
|
|
78182
78658
|
path: path_1.default.join(logDir, "sidekickd.log"),
|
|
78183
|
-
maxSizeBytes: this.configService.core.logging.rotation?.maxSizeBytes ??
|
|
78184
|
-
|
|
78659
|
+
maxSizeBytes: this.configService.core.logging.rotation?.maxSizeBytes ?? 2097152,
|
|
78660
|
+
// 2MB (ephemeral debug window)
|
|
78661
|
+
maxFiles: this.configService.core.logging.rotation?.maxFiles ?? 2
|
|
78185
78662
|
},
|
|
78186
78663
|
console: { enabled: this.configService.core.logging.consoleEnabled }
|
|
78187
78664
|
}
|
|
@@ -78193,6 +78670,13 @@ var require_daemon = __commonJS({
|
|
|
78193
78670
|
getStartTime: () => this.timerManager.startTime
|
|
78194
78671
|
});
|
|
78195
78672
|
this.logger = this.logMetrics.createCountingLogger();
|
|
78673
|
+
const sessionsDir = path_1.default.join(projectDir2, ".sidekick", "sessions");
|
|
78674
|
+
this.sessionLogWriter = new core_1.SessionLogWriter({
|
|
78675
|
+
sessionsDir,
|
|
78676
|
+
maxHandles: 10,
|
|
78677
|
+
idleTimeoutMs: 30 * 60 * 1e3
|
|
78678
|
+
});
|
|
78679
|
+
(0, core_1.setSessionLogWriter)(this.sessionLogWriter);
|
|
78196
78680
|
this.stateService = new core_1.StateService(projectDir2, {
|
|
78197
78681
|
cache: true,
|
|
78198
78682
|
logger: this.logger,
|
|
@@ -78300,6 +78784,8 @@ var require_daemon = __commonJS({
|
|
|
78300
78784
|
}
|
|
78301
78785
|
async stop() {
|
|
78302
78786
|
this.logger.info("Daemon stopping");
|
|
78787
|
+
(0, core_1.setSessionLogWriter)(null);
|
|
78788
|
+
await this.sessionLogWriter.closeAll();
|
|
78303
78789
|
this.timerManager.stopAll();
|
|
78304
78790
|
this.configWatcher.stop();
|
|
78305
78791
|
this.personaWatcher.stop();
|
|
@@ -78374,7 +78860,7 @@ var require_daemon = __commonJS({
|
|
|
78374
78860
|
this.logger.info("Configuration reloaded successfully");
|
|
78375
78861
|
} catch (err) {
|
|
78376
78862
|
this.logger.error("Failed to reload configuration", {
|
|
78377
|
-
error:
|
|
78863
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
78378
78864
|
});
|
|
78379
78865
|
}
|
|
78380
78866
|
}
|
|
@@ -78417,7 +78903,7 @@ var require_daemon = __commonJS({
|
|
|
78417
78903
|
} catch (err) {
|
|
78418
78904
|
this.logger.error("Failed to stage persona reminders on change", {
|
|
78419
78905
|
sessionId: event.sessionId,
|
|
78420
|
-
error:
|
|
78906
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
78421
78907
|
});
|
|
78422
78908
|
}
|
|
78423
78909
|
}
|
|
@@ -78449,7 +78935,7 @@ var require_daemon = __commonJS({
|
|
|
78449
78935
|
} catch (err) {
|
|
78450
78936
|
this.logger.error("Failed to regenerate messages after persona change", {
|
|
78451
78937
|
sessionId,
|
|
78452
|
-
error:
|
|
78938
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
78453
78939
|
});
|
|
78454
78940
|
}
|
|
78455
78941
|
}
|
|
@@ -78613,7 +79099,7 @@ var require_daemon = __commonJS({
|
|
|
78613
79099
|
}
|
|
78614
79100
|
} catch (err) {
|
|
78615
79101
|
log.warn("Failed to cache persona for clear handoff", {
|
|
78616
|
-
error:
|
|
79102
|
+
error: (0, core_1.toErrorMessage)(err)
|
|
78617
79103
|
});
|
|
78618
79104
|
}
|
|
78619
79105
|
} else {
|
|
@@ -78625,6 +79111,7 @@ var require_daemon = __commonJS({
|
|
|
78625
79111
|
await this.llmManager.shutdownSessionProvider(sessionId, log);
|
|
78626
79112
|
this.logMetrics.deleteSessionCounters(sessionId);
|
|
78627
79113
|
await this.serviceFactory.shutdownSession(sessionId);
|
|
79114
|
+
await this.sessionLogWriter.closeSession(sessionId);
|
|
78628
79115
|
log.info("Session ended");
|
|
78629
79116
|
}
|
|
78630
79117
|
}
|