@scotthamilton77/sidekick 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +281 -78
- package/dist/daemon.js +258 -67
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -33736,7 +33736,12 @@ var require_log_events = __commonJS({
|
|
|
33736
33736
|
"use strict";
|
|
33737
33737
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
33738
33738
|
exports2.LogEvents = void 0;
|
|
33739
|
+
exports2.setSessionLogWriter = setSessionLogWriter;
|
|
33739
33740
|
exports2.logEvent = logEvent;
|
|
33741
|
+
var sessionLogWriter = null;
|
|
33742
|
+
function setSessionLogWriter(writer) {
|
|
33743
|
+
sessionLogWriter = writer;
|
|
33744
|
+
}
|
|
33740
33745
|
function buildContext(ctx) {
|
|
33741
33746
|
return {
|
|
33742
33747
|
sessionId: ctx.sessionId,
|
|
@@ -34143,7 +34148,199 @@ var require_log_events = __commonJS({
|
|
|
34143
34148
|
source: event.source,
|
|
34144
34149
|
...meta
|
|
34145
34150
|
});
|
|
34151
|
+
if (sessionLogWriter && event.context.sessionId) {
|
|
34152
|
+
const logFile = event.source === "cli" ? "sidekick.log" : "sidekickd.log";
|
|
34153
|
+
const line = JSON.stringify({
|
|
34154
|
+
time: event.time,
|
|
34155
|
+
type: event.type,
|
|
34156
|
+
source: event.source,
|
|
34157
|
+
context: event.context,
|
|
34158
|
+
...meta
|
|
34159
|
+
}) + "\n";
|
|
34160
|
+
sessionLogWriter.write(event.context.sessionId, logFile, line).catch(() => {
|
|
34161
|
+
});
|
|
34162
|
+
}
|
|
34163
|
+
}
|
|
34164
|
+
}
|
|
34165
|
+
});
|
|
34166
|
+
|
|
34167
|
+
// ../sidekick-core/dist/staging-paths.js
|
|
34168
|
+
var require_staging_paths = __commonJS({
|
|
34169
|
+
"../sidekick-core/dist/staging-paths.js"(exports2) {
|
|
34170
|
+
"use strict";
|
|
34171
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
34172
|
+
exports2.CONSUMED_FILE_PATTERN = void 0;
|
|
34173
|
+
exports2.getStagingRoot = getStagingRoot;
|
|
34174
|
+
exports2.getHookDir = getHookDir;
|
|
34175
|
+
exports2.getReminderPath = getReminderPath;
|
|
34176
|
+
exports2.isValidPathSegment = isValidPathSegment;
|
|
34177
|
+
exports2.validatePathSegment = validatePathSegment;
|
|
34178
|
+
exports2.filterActiveReminderFiles = filterActiveReminderFiles;
|
|
34179
|
+
exports2.createConsumedFilePattern = createConsumedFilePattern;
|
|
34180
|
+
exports2.extractConsumedTimestamp = extractConsumedTimestamp;
|
|
34181
|
+
var node_path_1 = require("node:path");
|
|
34182
|
+
function getStagingRoot(stateDir, sessionId) {
|
|
34183
|
+
return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
|
|
34184
|
+
}
|
|
34185
|
+
function getHookDir(stateDir, sessionId, hookName) {
|
|
34186
|
+
return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
|
|
34187
|
+
}
|
|
34188
|
+
function getReminderPath(stateDir, sessionId, hookName, reminderName) {
|
|
34189
|
+
return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
|
|
34190
|
+
}
|
|
34191
|
+
function isValidPathSegment(s) {
|
|
34192
|
+
if (s === "")
|
|
34193
|
+
return false;
|
|
34194
|
+
if (s === "." || s === "..")
|
|
34195
|
+
return false;
|
|
34196
|
+
if (s.includes("/") || s.includes("\\"))
|
|
34197
|
+
return false;
|
|
34198
|
+
if ((0, node_path_1.basename)(s) !== s)
|
|
34199
|
+
return false;
|
|
34200
|
+
return /^[a-zA-Z0-9._-]+$/.test(s);
|
|
34201
|
+
}
|
|
34202
|
+
function validatePathSegment(segment, name) {
|
|
34203
|
+
if (!isValidPathSegment(segment)) {
|
|
34204
|
+
throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
|
|
34205
|
+
}
|
|
34146
34206
|
}
|
|
34207
|
+
exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
|
|
34208
|
+
function filterActiveReminderFiles(files) {
|
|
34209
|
+
return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
|
|
34210
|
+
}
|
|
34211
|
+
function createConsumedFilePattern(reminderName) {
|
|
34212
|
+
return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
|
|
34213
|
+
}
|
|
34214
|
+
function extractConsumedTimestamp(filename, reminderName) {
|
|
34215
|
+
const pattern = createConsumedFilePattern(reminderName);
|
|
34216
|
+
const match = pattern.exec(filename);
|
|
34217
|
+
return match ? parseInt(match[1], 10) : null;
|
|
34218
|
+
}
|
|
34219
|
+
}
|
|
34220
|
+
});
|
|
34221
|
+
|
|
34222
|
+
// ../sidekick-core/dist/session-log-writer.js
|
|
34223
|
+
var require_session_log_writer = __commonJS({
|
|
34224
|
+
"../sidekick-core/dist/session-log-writer.js"(exports2) {
|
|
34225
|
+
"use strict";
|
|
34226
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
34227
|
+
exports2.SessionLogWriter = void 0;
|
|
34228
|
+
var promises_12 = require("node:fs/promises");
|
|
34229
|
+
var node_path_1 = require("node:path");
|
|
34230
|
+
var node_fs_1 = require("node:fs");
|
|
34231
|
+
var staging_paths_js_1 = require_staging_paths();
|
|
34232
|
+
var SessionLogWriter = class {
|
|
34233
|
+
sessionsDir;
|
|
34234
|
+
maxHandles;
|
|
34235
|
+
idleTimeoutMs;
|
|
34236
|
+
/** Map key: `${sessionId}/${logFile}` */
|
|
34237
|
+
handles = /* @__PURE__ */ new Map();
|
|
34238
|
+
constructor(options) {
|
|
34239
|
+
this.sessionsDir = options.sessionsDir;
|
|
34240
|
+
this.maxHandles = options.maxHandles ?? 10;
|
|
34241
|
+
this.idleTimeoutMs = options.idleTimeoutMs ?? 30 * 60 * 1e3;
|
|
34242
|
+
}
|
|
34243
|
+
get handleCount() {
|
|
34244
|
+
return this.handles.size;
|
|
34245
|
+
}
|
|
34246
|
+
/**
|
|
34247
|
+
* Write an NDJSON line to a per-session log file.
|
|
34248
|
+
* Creates the directory and file handle lazily.
|
|
34249
|
+
* Skips if sessionId is empty (daemon lifecycle events before session exists).
|
|
34250
|
+
*/
|
|
34251
|
+
async write(sessionId, logFile, line) {
|
|
34252
|
+
if (!sessionId)
|
|
34253
|
+
return;
|
|
34254
|
+
if (!(0, staging_paths_js_1.isValidPathSegment)(sessionId) || !(0, staging_paths_js_1.isValidPathSegment)(logFile))
|
|
34255
|
+
return;
|
|
34256
|
+
const key = `${sessionId}/${logFile}`;
|
|
34257
|
+
let entry = this.handles.get(key);
|
|
34258
|
+
if (!entry) {
|
|
34259
|
+
if (this.handles.size >= this.maxHandles) {
|
|
34260
|
+
this.evictLRU();
|
|
34261
|
+
}
|
|
34262
|
+
const logDir = (0, node_path_1.join)(this.sessionsDir, sessionId, "logs");
|
|
34263
|
+
await (0, promises_12.mkdir)(logDir, { recursive: true });
|
|
34264
|
+
const filePath = (0, node_path_1.join)(logDir, logFile);
|
|
34265
|
+
const stream = (0, node_fs_1.createWriteStream)(filePath, { flags: "a" });
|
|
34266
|
+
const ready = new Promise((resolve3, reject) => {
|
|
34267
|
+
stream.once("open", () => resolve3());
|
|
34268
|
+
stream.once("error", (err) => {
|
|
34269
|
+
this.handles.delete(key);
|
|
34270
|
+
stream.destroy();
|
|
34271
|
+
reject(err);
|
|
34272
|
+
});
|
|
34273
|
+
});
|
|
34274
|
+
entry = {
|
|
34275
|
+
stream,
|
|
34276
|
+
lastUsed: Date.now(),
|
|
34277
|
+
timer: null,
|
|
34278
|
+
ready
|
|
34279
|
+
};
|
|
34280
|
+
this.handles.set(key, entry);
|
|
34281
|
+
}
|
|
34282
|
+
await entry.ready;
|
|
34283
|
+
entry.lastUsed = Date.now();
|
|
34284
|
+
this.resetIdleTimer(key, entry);
|
|
34285
|
+
return new Promise((resolve3, reject) => {
|
|
34286
|
+
entry.stream.write(line, (err) => {
|
|
34287
|
+
if (err) {
|
|
34288
|
+
void this.closeHandle(key);
|
|
34289
|
+
reject(err);
|
|
34290
|
+
} else {
|
|
34291
|
+
resolve3();
|
|
34292
|
+
}
|
|
34293
|
+
});
|
|
34294
|
+
});
|
|
34295
|
+
}
|
|
34296
|
+
/** Close all handles for a specific session. */
|
|
34297
|
+
async closeSession(sessionId) {
|
|
34298
|
+
const prefix = `${sessionId}/`;
|
|
34299
|
+
const toClose = [];
|
|
34300
|
+
for (const key of this.handles.keys()) {
|
|
34301
|
+
if (key.startsWith(prefix)) {
|
|
34302
|
+
toClose.push(key);
|
|
34303
|
+
}
|
|
34304
|
+
}
|
|
34305
|
+
await Promise.all(toClose.map((key) => this.closeHandle(key)));
|
|
34306
|
+
}
|
|
34307
|
+
/** Close all open handles. */
|
|
34308
|
+
async closeAll() {
|
|
34309
|
+
const keys = [...this.handles.keys()];
|
|
34310
|
+
await Promise.all(keys.map((key) => this.closeHandle(key)));
|
|
34311
|
+
}
|
|
34312
|
+
async closeHandle(key) {
|
|
34313
|
+
const entry = this.handles.get(key);
|
|
34314
|
+
if (!entry)
|
|
34315
|
+
return;
|
|
34316
|
+
if (entry.timer)
|
|
34317
|
+
clearTimeout(entry.timer);
|
|
34318
|
+
this.handles.delete(key);
|
|
34319
|
+
return new Promise((resolve3) => {
|
|
34320
|
+
entry.stream.end(() => resolve3());
|
|
34321
|
+
});
|
|
34322
|
+
}
|
|
34323
|
+
evictLRU() {
|
|
34324
|
+
let oldestKey = "";
|
|
34325
|
+
let oldestTime = Infinity;
|
|
34326
|
+
for (const [key, entry] of this.handles) {
|
|
34327
|
+
if (entry.lastUsed < oldestTime) {
|
|
34328
|
+
oldestTime = entry.lastUsed;
|
|
34329
|
+
oldestKey = key;
|
|
34330
|
+
}
|
|
34331
|
+
}
|
|
34332
|
+
void this.closeHandle(oldestKey);
|
|
34333
|
+
}
|
|
34334
|
+
resetIdleTimer(key, entry) {
|
|
34335
|
+
if (entry.timer)
|
|
34336
|
+
clearTimeout(entry.timer);
|
|
34337
|
+
entry.timer = setTimeout(() => {
|
|
34338
|
+
void this.closeHandle(key);
|
|
34339
|
+
}, this.idleTimeoutMs);
|
|
34340
|
+
entry.timer.unref();
|
|
34341
|
+
}
|
|
34342
|
+
};
|
|
34343
|
+
exports2.SessionLogWriter = SessionLogWriter;
|
|
34147
34344
|
}
|
|
34148
34345
|
});
|
|
34149
34346
|
|
|
@@ -45886,7 +46083,7 @@ var require_structured_logging = __commonJS({
|
|
|
45886
46083
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
45887
46084
|
};
|
|
45888
46085
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
45889
|
-
exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.LOG_LEVELS = exports2.logEvent = exports2.LogEvents = void 0;
|
|
46086
|
+
exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.LOG_LEVELS = exports2.SessionLogWriter = exports2.setSessionLogWriter = exports2.logEvent = exports2.LogEvents = void 0;
|
|
45890
46087
|
exports2.getComponentLogLevel = getComponentLogLevel;
|
|
45891
46088
|
exports2.createLogManager = createLogManager;
|
|
45892
46089
|
exports2.createContextLogger = createContextLogger;
|
|
@@ -45903,6 +46100,13 @@ var require_structured_logging = __commonJS({
|
|
|
45903
46100
|
Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
|
|
45904
46101
|
return log_events_1.logEvent;
|
|
45905
46102
|
} });
|
|
46103
|
+
Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
|
|
46104
|
+
return log_events_1.setSessionLogWriter;
|
|
46105
|
+
} });
|
|
46106
|
+
var session_log_writer_1 = require_session_log_writer();
|
|
46107
|
+
Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
|
|
46108
|
+
return session_log_writer_1.SessionLogWriter;
|
|
46109
|
+
} });
|
|
45906
46110
|
exports2.LOG_LEVELS = {
|
|
45907
46111
|
trace: 10,
|
|
45908
46112
|
debug: 20,
|
|
@@ -57726,8 +57930,8 @@ var require_doctor_engine = __commonJS({
|
|
|
57726
57930
|
});
|
|
57727
57931
|
}
|
|
57728
57932
|
} else {
|
|
57729
|
-
const
|
|
57730
|
-
if (
|
|
57933
|
+
const userStatus = await io.getUserStatus();
|
|
57934
|
+
if (userStatus) {
|
|
57731
57935
|
await io.updateUserStatus({ statusline: actualStatusline });
|
|
57732
57936
|
} else {
|
|
57733
57937
|
await io.writeUserStatus({
|
|
@@ -57783,8 +57987,8 @@ var require_doctor_engine = __commonJS({
|
|
|
57783
57987
|
},
|
|
57784
57988
|
gitignore: "unknown"
|
|
57785
57989
|
});
|
|
57786
|
-
const
|
|
57787
|
-
if (!
|
|
57990
|
+
const userStatus = await io.getUserStatus();
|
|
57991
|
+
if (!userStatus) {
|
|
57788
57992
|
await io.writeUserStatus({
|
|
57789
57993
|
version: 1,
|
|
57790
57994
|
lastUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -57810,8 +58014,29 @@ var require_doctor_engine = __commonJS({
|
|
|
57810
58014
|
scopes: projectApiKeyStatus.scopes
|
|
57811
58015
|
};
|
|
57812
58016
|
}
|
|
57813
|
-
const
|
|
57814
|
-
|
|
58017
|
+
const currentUserStatus = await io.getUserStatus();
|
|
58018
|
+
if (currentUserStatus) {
|
|
58019
|
+
let userNeedsUpdate = false;
|
|
58020
|
+
const updatedUserApiKeys = { ...currentUserStatus.apiKeys };
|
|
58021
|
+
for (let i = 0; i < keysToCheck.length; i++) {
|
|
58022
|
+
const keyName = keysToCheck[i];
|
|
58023
|
+
const detection = detections[i];
|
|
58024
|
+
const expectedUserStatus = (0, api_key_detector_js_1.buildUserApiKeyStatus)(detection);
|
|
58025
|
+
const currentUserEntry = currentUserStatus.apiKeys[keyName];
|
|
58026
|
+
const currentStatus = typeof currentUserEntry === "object" ? currentUserEntry.status : currentUserEntry ?? "missing";
|
|
58027
|
+
if (currentStatus !== "not-required" && (0, api_key_detector_js_1.toScopeStatus)(currentStatus) !== (0, api_key_detector_js_1.toScopeStatus)(expectedUserStatus.status)) {
|
|
58028
|
+
updatedUserApiKeys[keyName] = expectedUserStatus;
|
|
58029
|
+
userNeedsUpdate = true;
|
|
58030
|
+
}
|
|
58031
|
+
}
|
|
58032
|
+
if (userNeedsUpdate) {
|
|
58033
|
+
await io.updateUserStatus({
|
|
58034
|
+
apiKeys: updatedUserApiKeys
|
|
58035
|
+
});
|
|
58036
|
+
fixes.push("Updated stale user setup-status with current API key status");
|
|
58037
|
+
}
|
|
58038
|
+
}
|
|
58039
|
+
const userSetupExists = currentUserStatus !== null;
|
|
57815
58040
|
const isStatuslineHealthy = actualStatusline !== "none";
|
|
57816
58041
|
const openRouterActual = apiKeyResults.OPENROUTER_API_KEY.actual;
|
|
57817
58042
|
const openRouterCached = apiKeyResults.OPENROUTER_API_KEY.cached;
|
|
@@ -58364,61 +58589,6 @@ var require_errors6 = __commonJS({
|
|
|
58364
58589
|
}
|
|
58365
58590
|
});
|
|
58366
58591
|
|
|
58367
|
-
// ../sidekick-core/dist/staging-paths.js
|
|
58368
|
-
var require_staging_paths = __commonJS({
|
|
58369
|
-
"../sidekick-core/dist/staging-paths.js"(exports2) {
|
|
58370
|
-
"use strict";
|
|
58371
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
58372
|
-
exports2.CONSUMED_FILE_PATTERN = void 0;
|
|
58373
|
-
exports2.getStagingRoot = getStagingRoot;
|
|
58374
|
-
exports2.getHookDir = getHookDir;
|
|
58375
|
-
exports2.getReminderPath = getReminderPath;
|
|
58376
|
-
exports2.isValidPathSegment = isValidPathSegment;
|
|
58377
|
-
exports2.validatePathSegment = validatePathSegment;
|
|
58378
|
-
exports2.filterActiveReminderFiles = filterActiveReminderFiles;
|
|
58379
|
-
exports2.createConsumedFilePattern = createConsumedFilePattern;
|
|
58380
|
-
exports2.extractConsumedTimestamp = extractConsumedTimestamp;
|
|
58381
|
-
var node_path_1 = require("node:path");
|
|
58382
|
-
function getStagingRoot(stateDir, sessionId) {
|
|
58383
|
-
return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
|
|
58384
|
-
}
|
|
58385
|
-
function getHookDir(stateDir, sessionId, hookName) {
|
|
58386
|
-
return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
|
|
58387
|
-
}
|
|
58388
|
-
function getReminderPath(stateDir, sessionId, hookName, reminderName) {
|
|
58389
|
-
return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
|
|
58390
|
-
}
|
|
58391
|
-
function isValidPathSegment(s) {
|
|
58392
|
-
if (s === "")
|
|
58393
|
-
return false;
|
|
58394
|
-
if (s === "." || s === "..")
|
|
58395
|
-
return false;
|
|
58396
|
-
if (s.includes("/") || s.includes("\\"))
|
|
58397
|
-
return false;
|
|
58398
|
-
if ((0, node_path_1.basename)(s) !== s)
|
|
58399
|
-
return false;
|
|
58400
|
-
return /^[a-zA-Z0-9._-]+$/.test(s);
|
|
58401
|
-
}
|
|
58402
|
-
function validatePathSegment(segment, name) {
|
|
58403
|
-
if (!isValidPathSegment(segment)) {
|
|
58404
|
-
throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
|
|
58405
|
-
}
|
|
58406
|
-
}
|
|
58407
|
-
exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
|
|
58408
|
-
function filterActiveReminderFiles(files) {
|
|
58409
|
-
return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
|
|
58410
|
-
}
|
|
58411
|
-
function createConsumedFilePattern(reminderName) {
|
|
58412
|
-
return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
|
|
58413
|
-
}
|
|
58414
|
-
function extractConsumedTimestamp(filename, reminderName) {
|
|
58415
|
-
const pattern = createConsumedFilePattern(reminderName);
|
|
58416
|
-
const match = pattern.exec(filename);
|
|
58417
|
-
return match ? parseInt(match[1], 10) : null;
|
|
58418
|
-
}
|
|
58419
|
-
}
|
|
58420
|
-
});
|
|
58421
|
-
|
|
58422
58592
|
// ../sidekick-core/dist/staging-service.js
|
|
58423
58593
|
var require_staging_service = __commonJS({
|
|
58424
58594
|
"../sidekick-core/dist/staging-service.js"(exports2) {
|
|
@@ -59294,6 +59464,9 @@ var require_path_resolver = __commonJS({
|
|
|
59294
59464
|
sessionStagingDir(sessionId) {
|
|
59295
59465
|
return (0, node_path_1.join)(this.sessionRootDir(sessionId), "stage");
|
|
59296
59466
|
}
|
|
59467
|
+
sessionLogsDir(sessionId) {
|
|
59468
|
+
return (0, node_path_1.join)(this.sessionRootDir(sessionId), "logs");
|
|
59469
|
+
}
|
|
59297
59470
|
hookStagingDir(sessionId, hookName) {
|
|
59298
59471
|
return (0, node_path_1.join)(this.sessionStagingDir(sessionId), hookName);
|
|
59299
59472
|
}
|
|
@@ -64014,9 +64187,9 @@ var require_dist4 = __commonJS({
|
|
|
64014
64187
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
64015
64188
|
};
|
|
64016
64189
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
64017
|
-
exports2.
|
|
64018
|
-
exports2.
|
|
64019
|
-
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;
|
|
64190
|
+
exports2.toScopeStatus = exports2.LEGACY_USER_STATUS_FILENAME = exports2.PROJECT_STATUS_FILENAME = exports2.USER_STATUS_FILENAME = exports2.createSetupStatusService = exports2.SetupStatusService = exports2.DaemonClient = exports2.findZombieDaemons = exports2.killZombieDaemons = exports2.killAllDaemons = exports2.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.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;
|
|
64191
|
+
exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = exports2.detectGitignoreStatus = exports2.removeGitignoreSection = exports2.installGitignoreSection = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.runDoctorCheck = exports2.detectPluginLiveness = exports2.detectPluginInstallation = exports2.detectActualStatusline = exports2.spawnWithTimeout = exports2.getDoctorTimeout = exports2.DOCTOR_TIMEOUTS = exports2.projectApiKeyStatusFromHealth = exports2.userApiKeyStatusFromHealth = exports2.buildProjectApiKeyStatus = exports2.buildUserApiKeyStatus = exports2.detectAllApiKeys = exports2.detectActualApiKey = exports2.readKeyFromEnvFile = exports2.determineOverallStatus = void 0;
|
|
64192
|
+
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 = exports2.StateService = exports2.createHookableLogger = void 0;
|
|
64020
64193
|
var types_1 = require_dist();
|
|
64021
64194
|
Object.defineProperty(exports2, "TaskTypes", { enumerable: true, get: function() {
|
|
64022
64195
|
return types_1.TaskTypes;
|
|
@@ -64149,6 +64322,12 @@ var require_dist4 = __commonJS({
|
|
|
64149
64322
|
Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
|
|
64150
64323
|
return structured_logging_1.logEvent;
|
|
64151
64324
|
} });
|
|
64325
|
+
Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
|
|
64326
|
+
return structured_logging_1.setSessionLogWriter;
|
|
64327
|
+
} });
|
|
64328
|
+
Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
|
|
64329
|
+
return structured_logging_1.SessionLogWriter;
|
|
64330
|
+
} });
|
|
64152
64331
|
var daemon_client_1 = require_daemon_client2();
|
|
64153
64332
|
Object.defineProperty(exports2, "killAllDaemons", { enumerable: true, get: function() {
|
|
64154
64333
|
return daemon_client_1.killAllDaemons;
|
|
@@ -64477,8 +64656,9 @@ var require_runtime = __commonJS({
|
|
|
64477
64656
|
const rotation = config.core.logging.rotation;
|
|
64478
64657
|
const fileDestination = enableFileLogging ? {
|
|
64479
64658
|
path: logFilePath,
|
|
64480
|
-
maxSizeBytes: rotation?.maxSizeBytes ??
|
|
64481
|
-
|
|
64659
|
+
maxSizeBytes: rotation?.maxSizeBytes ?? 2097152,
|
|
64660
|
+
// 2MB (ephemeral debug window)
|
|
64661
|
+
maxFiles: rotation?.maxFiles ?? 2
|
|
64482
64662
|
} : void 0;
|
|
64483
64663
|
const logManager = (0, core_1.createLogManager)({
|
|
64484
64664
|
name: "sidekick:cli",
|
|
@@ -64520,6 +64700,14 @@ var require_runtime = __commonJS({
|
|
|
64520
64700
|
}
|
|
64521
64701
|
});
|
|
64522
64702
|
const telemetry = logManager.getTelemetry();
|
|
64703
|
+
const sessionsDir = projectRoot ? (0, node_path_1.join)(projectRoot, ".sidekick", "sessions") : (0, node_path_1.join)((0, node_os_1.homedir)(), ".sidekick", "sessions");
|
|
64704
|
+
const sessionLogWriter = new core_1.SessionLogWriter({
|
|
64705
|
+
sessionsDir,
|
|
64706
|
+
maxHandles: 2,
|
|
64707
|
+
// CLI typically has 1 session
|
|
64708
|
+
idleTimeoutMs: 10 * 60 * 1e3
|
|
64709
|
+
});
|
|
64710
|
+
(0, core_1.setSessionLogWriter)(sessionLogWriter);
|
|
64523
64711
|
const cleanupErrorHandlers = (0, core_1.setupGlobalErrorHandlers)(logger);
|
|
64524
64712
|
logger.debug("Runtime bootstrap complete", {
|
|
64525
64713
|
projectRoot: projectRoot ?? null,
|
|
@@ -64542,6 +64730,8 @@ var require_runtime = __commonJS({
|
|
|
64542
64730
|
stateService,
|
|
64543
64731
|
correlationId,
|
|
64544
64732
|
cleanup: () => {
|
|
64733
|
+
(0, core_1.setSessionLogWriter)(null);
|
|
64734
|
+
void sessionLogWriter.closeAll();
|
|
64545
64735
|
cleanupErrorHandlers();
|
|
64546
64736
|
},
|
|
64547
64737
|
bindSessionId: (sessionId) => {
|
|
@@ -81142,8 +81332,18 @@ var require_prompt = __commonJS({
|
|
|
81142
81332
|
};
|
|
81143
81333
|
})();
|
|
81144
81334
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
81335
|
+
exports2.createSafeResolver = createSafeResolver;
|
|
81145
81336
|
exports2.promptConfirm = promptConfirm;
|
|
81146
81337
|
var readline = __importStar(require("node:readline"));
|
|
81338
|
+
function createSafeResolver(resolve3) {
|
|
81339
|
+
let resolved = false;
|
|
81340
|
+
return (value) => {
|
|
81341
|
+
if (!resolved) {
|
|
81342
|
+
resolved = true;
|
|
81343
|
+
resolve3(value);
|
|
81344
|
+
}
|
|
81345
|
+
};
|
|
81346
|
+
}
|
|
81147
81347
|
var colors = {
|
|
81148
81348
|
yellow: "\x1B[1;33m",
|
|
81149
81349
|
reset: "\x1B[0m"
|
|
@@ -81157,13 +81357,7 @@ var require_prompt = __commonJS({
|
|
|
81157
81357
|
});
|
|
81158
81358
|
const prompt = `${question} ${hint} `;
|
|
81159
81359
|
return new Promise((resolve3) => {
|
|
81160
|
-
|
|
81161
|
-
const safeResolve = (value) => {
|
|
81162
|
-
if (!resolved) {
|
|
81163
|
-
resolved = true;
|
|
81164
|
-
resolve3(value);
|
|
81165
|
-
}
|
|
81166
|
-
};
|
|
81360
|
+
const safeResolve = createSafeResolver(resolve3);
|
|
81167
81361
|
rl.once("close", () => {
|
|
81168
81362
|
safeResolve(defaultYes);
|
|
81169
81363
|
});
|
|
@@ -81804,6 +81998,7 @@ var require_prompts = __commonJS({
|
|
|
81804
81998
|
Object.defineProperty(exports2, "promptConfirm", { enumerable: true, get: function() {
|
|
81805
81999
|
return prompt_js_1.promptConfirm;
|
|
81806
82000
|
} });
|
|
82001
|
+
var prompt_js_2 = require_prompt();
|
|
81807
82002
|
var colors = {
|
|
81808
82003
|
reset: "\x1B[0m",
|
|
81809
82004
|
bold: "\x1B[1m",
|
|
@@ -81851,18 +82046,22 @@ var require_prompts = __commonJS({
|
|
|
81851
82046
|
const defaultNum = defaultIndex + 1;
|
|
81852
82047
|
const prompt = `Enter choice (1-${options.length}) [${defaultNum}]: `;
|
|
81853
82048
|
return new Promise((resolve3) => {
|
|
82049
|
+
const safeResolve = (0, prompt_js_2.createSafeResolver)(resolve3);
|
|
82050
|
+
rl.once("close", () => {
|
|
82051
|
+
safeResolve(options[defaultIndex].value);
|
|
82052
|
+
});
|
|
81854
82053
|
const ask = () => {
|
|
81855
82054
|
ctx.stdout.write(prompt);
|
|
81856
82055
|
rl.once("line", (answer) => {
|
|
81857
82056
|
const trimmed = answer.trim();
|
|
81858
82057
|
if (trimmed === "") {
|
|
82058
|
+
safeResolve(options[defaultIndex].value);
|
|
81859
82059
|
rl.close();
|
|
81860
|
-
resolve3(options[defaultIndex].value);
|
|
81861
82060
|
} else {
|
|
81862
82061
|
const num = parseInt(trimmed, 10);
|
|
81863
82062
|
if (num >= 1 && num <= options.length) {
|
|
82063
|
+
safeResolve(options[num - 1].value);
|
|
81864
82064
|
rl.close();
|
|
81865
|
-
resolve3(options[num - 1].value);
|
|
81866
82065
|
} else {
|
|
81867
82066
|
ctx.stdout.write(`${colors.yellow}Invalid choice. Enter a number between 1 and ${options.length}.${colors.reset}
|
|
81868
82067
|
`);
|
|
@@ -81881,10 +82080,14 @@ var require_prompts = __commonJS({
|
|
|
81881
82080
|
terminal: false
|
|
81882
82081
|
});
|
|
81883
82082
|
return new Promise((resolve3) => {
|
|
82083
|
+
const safeResolve = (0, prompt_js_2.createSafeResolver)(resolve3);
|
|
82084
|
+
rl.once("close", () => {
|
|
82085
|
+
safeResolve("");
|
|
82086
|
+
});
|
|
81884
82087
|
ctx.stdout.write(`${question}: `);
|
|
81885
82088
|
rl.once("line", (answer) => {
|
|
82089
|
+
safeResolve(answer.trim());
|
|
81886
82090
|
rl.close();
|
|
81887
|
-
resolve3(answer.trim());
|
|
81888
82091
|
});
|
|
81889
82092
|
});
|
|
81890
82093
|
}
|
|
@@ -84472,7 +84675,7 @@ var require_cli = __commonJS({
|
|
|
84472
84675
|
var promises_12 = require("node:fs/promises");
|
|
84473
84676
|
var node_stream_1 = require("node:stream");
|
|
84474
84677
|
var yargs_parser_1 = __importDefault2(require_build());
|
|
84475
|
-
var VERSION = true ? "0.1.
|
|
84678
|
+
var VERSION = true ? "0.1.19" : "dev";
|
|
84476
84679
|
var SANDBOX_ERROR_MESSAGE = `Error: Daemon commands cannot run in sandbox mode.
|
|
84477
84680
|
|
|
84478
84681
|
Claude Code's sandbox blocks Unix socket operations required for daemon IPC.
|
package/dist/daemon.js
CHANGED
|
@@ -32760,7 +32760,12 @@ var require_log_events = __commonJS({
|
|
|
32760
32760
|
"use strict";
|
|
32761
32761
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
32762
32762
|
exports2.LogEvents = void 0;
|
|
32763
|
+
exports2.setSessionLogWriter = setSessionLogWriter;
|
|
32763
32764
|
exports2.logEvent = logEvent;
|
|
32765
|
+
var sessionLogWriter = null;
|
|
32766
|
+
function setSessionLogWriter(writer) {
|
|
32767
|
+
sessionLogWriter = writer;
|
|
32768
|
+
}
|
|
32764
32769
|
function buildContext(ctx) {
|
|
32765
32770
|
return {
|
|
32766
32771
|
sessionId: ctx.sessionId,
|
|
@@ -33167,10 +33172,202 @@ var require_log_events = __commonJS({
|
|
|
33167
33172
|
source: event.source,
|
|
33168
33173
|
...meta
|
|
33169
33174
|
});
|
|
33175
|
+
if (sessionLogWriter && event.context.sessionId) {
|
|
33176
|
+
const logFile = event.source === "cli" ? "sidekick.log" : "sidekickd.log";
|
|
33177
|
+
const line = JSON.stringify({
|
|
33178
|
+
time: event.time,
|
|
33179
|
+
type: event.type,
|
|
33180
|
+
source: event.source,
|
|
33181
|
+
context: event.context,
|
|
33182
|
+
...meta
|
|
33183
|
+
}) + "\n";
|
|
33184
|
+
sessionLogWriter.write(event.context.sessionId, logFile, line).catch(() => {
|
|
33185
|
+
});
|
|
33186
|
+
}
|
|
33170
33187
|
}
|
|
33171
33188
|
}
|
|
33172
33189
|
});
|
|
33173
33190
|
|
|
33191
|
+
// ../sidekick-core/dist/staging-paths.js
|
|
33192
|
+
var require_staging_paths = __commonJS({
|
|
33193
|
+
"../sidekick-core/dist/staging-paths.js"(exports2) {
|
|
33194
|
+
"use strict";
|
|
33195
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
33196
|
+
exports2.CONSUMED_FILE_PATTERN = void 0;
|
|
33197
|
+
exports2.getStagingRoot = getStagingRoot;
|
|
33198
|
+
exports2.getHookDir = getHookDir;
|
|
33199
|
+
exports2.getReminderPath = getReminderPath;
|
|
33200
|
+
exports2.isValidPathSegment = isValidPathSegment;
|
|
33201
|
+
exports2.validatePathSegment = validatePathSegment;
|
|
33202
|
+
exports2.filterActiveReminderFiles = filterActiveReminderFiles;
|
|
33203
|
+
exports2.createConsumedFilePattern = createConsumedFilePattern;
|
|
33204
|
+
exports2.extractConsumedTimestamp = extractConsumedTimestamp;
|
|
33205
|
+
var node_path_1 = require("node:path");
|
|
33206
|
+
function getStagingRoot(stateDir, sessionId) {
|
|
33207
|
+
return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
|
|
33208
|
+
}
|
|
33209
|
+
function getHookDir(stateDir, sessionId, hookName) {
|
|
33210
|
+
return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
|
|
33211
|
+
}
|
|
33212
|
+
function getReminderPath(stateDir, sessionId, hookName, reminderName) {
|
|
33213
|
+
return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
|
|
33214
|
+
}
|
|
33215
|
+
function isValidPathSegment(s) {
|
|
33216
|
+
if (s === "")
|
|
33217
|
+
return false;
|
|
33218
|
+
if (s === "." || s === "..")
|
|
33219
|
+
return false;
|
|
33220
|
+
if (s.includes("/") || s.includes("\\"))
|
|
33221
|
+
return false;
|
|
33222
|
+
if ((0, node_path_1.basename)(s) !== s)
|
|
33223
|
+
return false;
|
|
33224
|
+
return /^[a-zA-Z0-9._-]+$/.test(s);
|
|
33225
|
+
}
|
|
33226
|
+
function validatePathSegment(segment, name) {
|
|
33227
|
+
if (!isValidPathSegment(segment)) {
|
|
33228
|
+
throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
|
|
33229
|
+
}
|
|
33230
|
+
}
|
|
33231
|
+
exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
|
|
33232
|
+
function filterActiveReminderFiles(files) {
|
|
33233
|
+
return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
|
|
33234
|
+
}
|
|
33235
|
+
function createConsumedFilePattern(reminderName) {
|
|
33236
|
+
return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
|
|
33237
|
+
}
|
|
33238
|
+
function extractConsumedTimestamp(filename, reminderName) {
|
|
33239
|
+
const pattern = createConsumedFilePattern(reminderName);
|
|
33240
|
+
const match = pattern.exec(filename);
|
|
33241
|
+
return match ? parseInt(match[1], 10) : null;
|
|
33242
|
+
}
|
|
33243
|
+
}
|
|
33244
|
+
});
|
|
33245
|
+
|
|
33246
|
+
// ../sidekick-core/dist/session-log-writer.js
|
|
33247
|
+
var require_session_log_writer = __commonJS({
|
|
33248
|
+
"../sidekick-core/dist/session-log-writer.js"(exports2) {
|
|
33249
|
+
"use strict";
|
|
33250
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
33251
|
+
exports2.SessionLogWriter = void 0;
|
|
33252
|
+
var promises_1 = require("node:fs/promises");
|
|
33253
|
+
var node_path_1 = require("node:path");
|
|
33254
|
+
var node_fs_1 = require("node:fs");
|
|
33255
|
+
var staging_paths_js_1 = require_staging_paths();
|
|
33256
|
+
var SessionLogWriter = class {
|
|
33257
|
+
sessionsDir;
|
|
33258
|
+
maxHandles;
|
|
33259
|
+
idleTimeoutMs;
|
|
33260
|
+
/** Map key: `${sessionId}/${logFile}` */
|
|
33261
|
+
handles = /* @__PURE__ */ new Map();
|
|
33262
|
+
constructor(options) {
|
|
33263
|
+
this.sessionsDir = options.sessionsDir;
|
|
33264
|
+
this.maxHandles = options.maxHandles ?? 10;
|
|
33265
|
+
this.idleTimeoutMs = options.idleTimeoutMs ?? 30 * 60 * 1e3;
|
|
33266
|
+
}
|
|
33267
|
+
get handleCount() {
|
|
33268
|
+
return this.handles.size;
|
|
33269
|
+
}
|
|
33270
|
+
/**
|
|
33271
|
+
* Write an NDJSON line to a per-session log file.
|
|
33272
|
+
* Creates the directory and file handle lazily.
|
|
33273
|
+
* Skips if sessionId is empty (daemon lifecycle events before session exists).
|
|
33274
|
+
*/
|
|
33275
|
+
async write(sessionId, logFile, line) {
|
|
33276
|
+
if (!sessionId)
|
|
33277
|
+
return;
|
|
33278
|
+
if (!(0, staging_paths_js_1.isValidPathSegment)(sessionId) || !(0, staging_paths_js_1.isValidPathSegment)(logFile))
|
|
33279
|
+
return;
|
|
33280
|
+
const key = `${sessionId}/${logFile}`;
|
|
33281
|
+
let entry = this.handles.get(key);
|
|
33282
|
+
if (!entry) {
|
|
33283
|
+
if (this.handles.size >= this.maxHandles) {
|
|
33284
|
+
this.evictLRU();
|
|
33285
|
+
}
|
|
33286
|
+
const logDir = (0, node_path_1.join)(this.sessionsDir, sessionId, "logs");
|
|
33287
|
+
await (0, promises_1.mkdir)(logDir, { recursive: true });
|
|
33288
|
+
const filePath = (0, node_path_1.join)(logDir, logFile);
|
|
33289
|
+
const stream = (0, node_fs_1.createWriteStream)(filePath, { flags: "a" });
|
|
33290
|
+
const ready = new Promise((resolve3, reject) => {
|
|
33291
|
+
stream.once("open", () => resolve3());
|
|
33292
|
+
stream.once("error", (err) => {
|
|
33293
|
+
this.handles.delete(key);
|
|
33294
|
+
stream.destroy();
|
|
33295
|
+
reject(err);
|
|
33296
|
+
});
|
|
33297
|
+
});
|
|
33298
|
+
entry = {
|
|
33299
|
+
stream,
|
|
33300
|
+
lastUsed: Date.now(),
|
|
33301
|
+
timer: null,
|
|
33302
|
+
ready
|
|
33303
|
+
};
|
|
33304
|
+
this.handles.set(key, entry);
|
|
33305
|
+
}
|
|
33306
|
+
await entry.ready;
|
|
33307
|
+
entry.lastUsed = Date.now();
|
|
33308
|
+
this.resetIdleTimer(key, entry);
|
|
33309
|
+
return new Promise((resolve3, reject) => {
|
|
33310
|
+
entry.stream.write(line, (err) => {
|
|
33311
|
+
if (err) {
|
|
33312
|
+
void this.closeHandle(key);
|
|
33313
|
+
reject(err);
|
|
33314
|
+
} else {
|
|
33315
|
+
resolve3();
|
|
33316
|
+
}
|
|
33317
|
+
});
|
|
33318
|
+
});
|
|
33319
|
+
}
|
|
33320
|
+
/** Close all handles for a specific session. */
|
|
33321
|
+
async closeSession(sessionId) {
|
|
33322
|
+
const prefix = `${sessionId}/`;
|
|
33323
|
+
const toClose = [];
|
|
33324
|
+
for (const key of this.handles.keys()) {
|
|
33325
|
+
if (key.startsWith(prefix)) {
|
|
33326
|
+
toClose.push(key);
|
|
33327
|
+
}
|
|
33328
|
+
}
|
|
33329
|
+
await Promise.all(toClose.map((key) => this.closeHandle(key)));
|
|
33330
|
+
}
|
|
33331
|
+
/** Close all open handles. */
|
|
33332
|
+
async closeAll() {
|
|
33333
|
+
const keys = [...this.handles.keys()];
|
|
33334
|
+
await Promise.all(keys.map((key) => this.closeHandle(key)));
|
|
33335
|
+
}
|
|
33336
|
+
async closeHandle(key) {
|
|
33337
|
+
const entry = this.handles.get(key);
|
|
33338
|
+
if (!entry)
|
|
33339
|
+
return;
|
|
33340
|
+
if (entry.timer)
|
|
33341
|
+
clearTimeout(entry.timer);
|
|
33342
|
+
this.handles.delete(key);
|
|
33343
|
+
return new Promise((resolve3) => {
|
|
33344
|
+
entry.stream.end(() => resolve3());
|
|
33345
|
+
});
|
|
33346
|
+
}
|
|
33347
|
+
evictLRU() {
|
|
33348
|
+
let oldestKey = "";
|
|
33349
|
+
let oldestTime = Infinity;
|
|
33350
|
+
for (const [key, entry] of this.handles) {
|
|
33351
|
+
if (entry.lastUsed < oldestTime) {
|
|
33352
|
+
oldestTime = entry.lastUsed;
|
|
33353
|
+
oldestKey = key;
|
|
33354
|
+
}
|
|
33355
|
+
}
|
|
33356
|
+
void this.closeHandle(oldestKey);
|
|
33357
|
+
}
|
|
33358
|
+
resetIdleTimer(key, entry) {
|
|
33359
|
+
if (entry.timer)
|
|
33360
|
+
clearTimeout(entry.timer);
|
|
33361
|
+
entry.timer = setTimeout(() => {
|
|
33362
|
+
void this.closeHandle(key);
|
|
33363
|
+
}, this.idleTimeoutMs);
|
|
33364
|
+
entry.timer.unref();
|
|
33365
|
+
}
|
|
33366
|
+
};
|
|
33367
|
+
exports2.SessionLogWriter = SessionLogWriter;
|
|
33368
|
+
}
|
|
33369
|
+
});
|
|
33370
|
+
|
|
33174
33371
|
// ../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/constants.cjs
|
|
33175
33372
|
var require_constants2 = __commonJS({
|
|
33176
33373
|
"../../node_modules/.pnpm/date-fns@4.1.0/node_modules/date-fns/constants.cjs"(exports2) {
|
|
@@ -44910,7 +45107,7 @@ var require_structured_logging = __commonJS({
|
|
|
44910
45107
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
44911
45108
|
};
|
|
44912
45109
|
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;
|
|
45110
|
+
exports2.DEFAULT_MAX_FILES = exports2.DEFAULT_ROTATE_SIZE_BYTES = exports2.LOG_LEVELS = exports2.SessionLogWriter = exports2.setSessionLogWriter = exports2.logEvent = exports2.LogEvents = void 0;
|
|
44914
45111
|
exports2.getComponentLogLevel = getComponentLogLevel;
|
|
44915
45112
|
exports2.createLogManager = createLogManager;
|
|
44916
45113
|
exports2.createContextLogger = createContextLogger;
|
|
@@ -44927,6 +45124,13 @@ var require_structured_logging = __commonJS({
|
|
|
44927
45124
|
Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
|
|
44928
45125
|
return log_events_1.logEvent;
|
|
44929
45126
|
} });
|
|
45127
|
+
Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
|
|
45128
|
+
return log_events_1.setSessionLogWriter;
|
|
45129
|
+
} });
|
|
45130
|
+
var session_log_writer_1 = require_session_log_writer();
|
|
45131
|
+
Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
|
|
45132
|
+
return session_log_writer_1.SessionLogWriter;
|
|
45133
|
+
} });
|
|
44930
45134
|
exports2.LOG_LEVELS = {
|
|
44931
45135
|
trace: 10,
|
|
44932
45136
|
debug: 20,
|
|
@@ -56750,8 +56954,8 @@ var require_doctor_engine = __commonJS({
|
|
|
56750
56954
|
});
|
|
56751
56955
|
}
|
|
56752
56956
|
} else {
|
|
56753
|
-
const
|
|
56754
|
-
if (
|
|
56957
|
+
const userStatus = await io.getUserStatus();
|
|
56958
|
+
if (userStatus) {
|
|
56755
56959
|
await io.updateUserStatus({ statusline: actualStatusline });
|
|
56756
56960
|
} else {
|
|
56757
56961
|
await io.writeUserStatus({
|
|
@@ -56807,8 +57011,8 @@ var require_doctor_engine = __commonJS({
|
|
|
56807
57011
|
},
|
|
56808
57012
|
gitignore: "unknown"
|
|
56809
57013
|
});
|
|
56810
|
-
const
|
|
56811
|
-
if (!
|
|
57014
|
+
const userStatus = await io.getUserStatus();
|
|
57015
|
+
if (!userStatus) {
|
|
56812
57016
|
await io.writeUserStatus({
|
|
56813
57017
|
version: 1,
|
|
56814
57018
|
lastUpdatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -56834,8 +57038,29 @@ var require_doctor_engine = __commonJS({
|
|
|
56834
57038
|
scopes: projectApiKeyStatus.scopes
|
|
56835
57039
|
};
|
|
56836
57040
|
}
|
|
56837
|
-
const
|
|
56838
|
-
|
|
57041
|
+
const currentUserStatus = await io.getUserStatus();
|
|
57042
|
+
if (currentUserStatus) {
|
|
57043
|
+
let userNeedsUpdate = false;
|
|
57044
|
+
const updatedUserApiKeys = { ...currentUserStatus.apiKeys };
|
|
57045
|
+
for (let i = 0; i < keysToCheck.length; i++) {
|
|
57046
|
+
const keyName = keysToCheck[i];
|
|
57047
|
+
const detection = detections[i];
|
|
57048
|
+
const expectedUserStatus = (0, api_key_detector_js_1.buildUserApiKeyStatus)(detection);
|
|
57049
|
+
const currentUserEntry = currentUserStatus.apiKeys[keyName];
|
|
57050
|
+
const currentStatus = typeof currentUserEntry === "object" ? currentUserEntry.status : currentUserEntry ?? "missing";
|
|
57051
|
+
if (currentStatus !== "not-required" && (0, api_key_detector_js_1.toScopeStatus)(currentStatus) !== (0, api_key_detector_js_1.toScopeStatus)(expectedUserStatus.status)) {
|
|
57052
|
+
updatedUserApiKeys[keyName] = expectedUserStatus;
|
|
57053
|
+
userNeedsUpdate = true;
|
|
57054
|
+
}
|
|
57055
|
+
}
|
|
57056
|
+
if (userNeedsUpdate) {
|
|
57057
|
+
await io.updateUserStatus({
|
|
57058
|
+
apiKeys: updatedUserApiKeys
|
|
57059
|
+
});
|
|
57060
|
+
fixes.push("Updated stale user setup-status with current API key status");
|
|
57061
|
+
}
|
|
57062
|
+
}
|
|
57063
|
+
const userSetupExists = currentUserStatus !== null;
|
|
56839
57064
|
const isStatuslineHealthy = actualStatusline !== "none";
|
|
56840
57065
|
const openRouterActual = apiKeyResults.OPENROUTER_API_KEY.actual;
|
|
56841
57066
|
const openRouterCached = apiKeyResults.OPENROUTER_API_KEY.cached;
|
|
@@ -57388,61 +57613,6 @@ var require_errors6 = __commonJS({
|
|
|
57388
57613
|
}
|
|
57389
57614
|
});
|
|
57390
57615
|
|
|
57391
|
-
// ../sidekick-core/dist/staging-paths.js
|
|
57392
|
-
var require_staging_paths = __commonJS({
|
|
57393
|
-
"../sidekick-core/dist/staging-paths.js"(exports2) {
|
|
57394
|
-
"use strict";
|
|
57395
|
-
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
57396
|
-
exports2.CONSUMED_FILE_PATTERN = void 0;
|
|
57397
|
-
exports2.getStagingRoot = getStagingRoot;
|
|
57398
|
-
exports2.getHookDir = getHookDir;
|
|
57399
|
-
exports2.getReminderPath = getReminderPath;
|
|
57400
|
-
exports2.isValidPathSegment = isValidPathSegment;
|
|
57401
|
-
exports2.validatePathSegment = validatePathSegment;
|
|
57402
|
-
exports2.filterActiveReminderFiles = filterActiveReminderFiles;
|
|
57403
|
-
exports2.createConsumedFilePattern = createConsumedFilePattern;
|
|
57404
|
-
exports2.extractConsumedTimestamp = extractConsumedTimestamp;
|
|
57405
|
-
var node_path_1 = require("node:path");
|
|
57406
|
-
function getStagingRoot(stateDir, sessionId) {
|
|
57407
|
-
return (0, node_path_1.join)(stateDir, "sessions", sessionId, "stage");
|
|
57408
|
-
}
|
|
57409
|
-
function getHookDir(stateDir, sessionId, hookName) {
|
|
57410
|
-
return (0, node_path_1.join)(getStagingRoot(stateDir, sessionId), hookName);
|
|
57411
|
-
}
|
|
57412
|
-
function getReminderPath(stateDir, sessionId, hookName, reminderName) {
|
|
57413
|
-
return (0, node_path_1.join)(getHookDir(stateDir, sessionId, hookName), `${reminderName}.json`);
|
|
57414
|
-
}
|
|
57415
|
-
function isValidPathSegment(s) {
|
|
57416
|
-
if (s === "")
|
|
57417
|
-
return false;
|
|
57418
|
-
if (s === "." || s === "..")
|
|
57419
|
-
return false;
|
|
57420
|
-
if (s.includes("/") || s.includes("\\"))
|
|
57421
|
-
return false;
|
|
57422
|
-
if ((0, node_path_1.basename)(s) !== s)
|
|
57423
|
-
return false;
|
|
57424
|
-
return /^[a-zA-Z0-9._-]+$/.test(s);
|
|
57425
|
-
}
|
|
57426
|
-
function validatePathSegment(segment, name) {
|
|
57427
|
-
if (!isValidPathSegment(segment)) {
|
|
57428
|
-
throw new Error(`Invalid ${name}: must be a non-empty alphanumeric string without path separators`);
|
|
57429
|
-
}
|
|
57430
|
-
}
|
|
57431
|
-
exports2.CONSUMED_FILE_PATTERN = /\.\d+\.json$/;
|
|
57432
|
-
function filterActiveReminderFiles(files) {
|
|
57433
|
-
return files.filter((f) => f.endsWith(".json") && !exports2.CONSUMED_FILE_PATTERN.test(f));
|
|
57434
|
-
}
|
|
57435
|
-
function createConsumedFilePattern(reminderName) {
|
|
57436
|
-
return new RegExp(`^${reminderName}\\.(\\d+)\\.json$`);
|
|
57437
|
-
}
|
|
57438
|
-
function extractConsumedTimestamp(filename, reminderName) {
|
|
57439
|
-
const pattern = createConsumedFilePattern(reminderName);
|
|
57440
|
-
const match = pattern.exec(filename);
|
|
57441
|
-
return match ? parseInt(match[1], 10) : null;
|
|
57442
|
-
}
|
|
57443
|
-
}
|
|
57444
|
-
});
|
|
57445
|
-
|
|
57446
57616
|
// ../sidekick-core/dist/staging-service.js
|
|
57447
57617
|
var require_staging_service = __commonJS({
|
|
57448
57618
|
"../sidekick-core/dist/staging-service.js"(exports2) {
|
|
@@ -58318,6 +58488,9 @@ var require_path_resolver = __commonJS({
|
|
|
58318
58488
|
sessionStagingDir(sessionId) {
|
|
58319
58489
|
return (0, node_path_1.join)(this.sessionRootDir(sessionId), "stage");
|
|
58320
58490
|
}
|
|
58491
|
+
sessionLogsDir(sessionId) {
|
|
58492
|
+
return (0, node_path_1.join)(this.sessionRootDir(sessionId), "logs");
|
|
58493
|
+
}
|
|
58321
58494
|
hookStagingDir(sessionId, hookName) {
|
|
58322
58495
|
return (0, node_path_1.join)(this.sessionStagingDir(sessionId), hookName);
|
|
58323
58496
|
}
|
|
@@ -63038,9 +63211,9 @@ var require_dist4 = __commonJS({
|
|
|
63038
63211
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports3, p)) __createBinding(exports3, m, p);
|
|
63039
63212
|
};
|
|
63040
63213
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
63041
|
-
exports2.
|
|
63042
|
-
exports2.
|
|
63043
|
-
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;
|
|
63214
|
+
exports2.toScopeStatus = exports2.LEGACY_USER_STATUS_FILENAME = exports2.PROJECT_STATUS_FILENAME = exports2.USER_STATUS_FILENAME = exports2.createSetupStatusService = exports2.SetupStatusService = exports2.DaemonClient = exports2.findZombieDaemons = exports2.killZombieDaemons = exports2.killAllDaemons = exports2.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.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;
|
|
63215
|
+
exports2.InstrumentedProfileProviderFactory = exports2.InstrumentedLLMProvider = exports2.ServiceFactoryImpl = exports2.TranscriptServiceImpl = exports2.createDefaultTokenUsage = exports2.createDefaultMetrics = exports2.copyWithTimestampSync = exports2.renameWithTimestampSync = exports2.renameWithTimestamp = exports2.copyWithTimestamp = exports2.getTimestampedPath = exports2.extractToolResultPreview = exports2.extractToolCallPreview = exports2.extractTextFromContent = exports2.extractContentPreview = exports2.HandlerRegistryImpl = exports2.extractConsumedTimestamp = exports2.createConsumedFilePattern = exports2.CONSUMED_FILE_PATTERN = exports2.filterActiveReminderFiles = exports2.validatePathSegment = exports2.isValidPathSegment = exports2.getReminderPath = exports2.getHookDir = exports2.getStagingRoot = exports2.SessionScopedStagingService = exports2.StagingServiceCore = exports2.GITIGNORE_ENTRIES = exports2.SIDEKICK_SECTION_END = exports2.SIDEKICK_SECTION_START = exports2.detectGitignoreStatus = exports2.removeGitignoreSection = exports2.installGitignoreSection = exports2.validateOpenAIKey = exports2.validateOpenRouterKey = exports2.runDoctorCheck = exports2.detectPluginLiveness = exports2.detectPluginInstallation = exports2.detectActualStatusline = exports2.spawnWithTimeout = exports2.getDoctorTimeout = exports2.DOCTOR_TIMEOUTS = exports2.projectApiKeyStatusFromHealth = exports2.userApiKeyStatusFromHealth = exports2.buildProjectApiKeyStatus = exports2.buildUserApiKeyStatus = exports2.detectAllApiKeys = exports2.detectActualApiKey = exports2.readKeyFromEnvFile = exports2.determineOverallStatus = void 0;
|
|
63216
|
+
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 = exports2.StateService = exports2.createHookableLogger = void 0;
|
|
63044
63217
|
var types_1 = require_dist();
|
|
63045
63218
|
Object.defineProperty(exports2, "TaskTypes", { enumerable: true, get: function() {
|
|
63046
63219
|
return types_1.TaskTypes;
|
|
@@ -63173,6 +63346,12 @@ var require_dist4 = __commonJS({
|
|
|
63173
63346
|
Object.defineProperty(exports2, "logEvent", { enumerable: true, get: function() {
|
|
63174
63347
|
return structured_logging_1.logEvent;
|
|
63175
63348
|
} });
|
|
63349
|
+
Object.defineProperty(exports2, "setSessionLogWriter", { enumerable: true, get: function() {
|
|
63350
|
+
return structured_logging_1.setSessionLogWriter;
|
|
63351
|
+
} });
|
|
63352
|
+
Object.defineProperty(exports2, "SessionLogWriter", { enumerable: true, get: function() {
|
|
63353
|
+
return structured_logging_1.SessionLogWriter;
|
|
63354
|
+
} });
|
|
63176
63355
|
var daemon_client_1 = require_daemon_client2();
|
|
63177
63356
|
Object.defineProperty(exports2, "killAllDaemons", { enumerable: true, get: function() {
|
|
63178
63357
|
return daemon_client_1.killAllDaemons;
|
|
@@ -78117,6 +78296,7 @@ var require_daemon = __commonJS({
|
|
|
78117
78296
|
token = "";
|
|
78118
78297
|
registryService;
|
|
78119
78298
|
timerManager;
|
|
78299
|
+
sessionLogWriter;
|
|
78120
78300
|
/** Cache persona for handoff on clear. */
|
|
78121
78301
|
cachePersonaForClear(personaId) {
|
|
78122
78302
|
this.lastClearedPersona = { personaId, timestamp: Date.now() };
|
|
@@ -78159,8 +78339,9 @@ var require_daemon = __commonJS({
|
|
|
78159
78339
|
destinations: {
|
|
78160
78340
|
file: {
|
|
78161
78341
|
path: path_1.default.join(logDir, "sidekickd.log"),
|
|
78162
|
-
maxSizeBytes: this.configService.core.logging.rotation?.maxSizeBytes ??
|
|
78163
|
-
|
|
78342
|
+
maxSizeBytes: this.configService.core.logging.rotation?.maxSizeBytes ?? 2097152,
|
|
78343
|
+
// 2MB (ephemeral debug window)
|
|
78344
|
+
maxFiles: this.configService.core.logging.rotation?.maxFiles ?? 2
|
|
78164
78345
|
},
|
|
78165
78346
|
console: { enabled: this.configService.core.logging.consoleEnabled }
|
|
78166
78347
|
}
|
|
@@ -78172,6 +78353,13 @@ var require_daemon = __commonJS({
|
|
|
78172
78353
|
getStartTime: () => this.timerManager.startTime
|
|
78173
78354
|
});
|
|
78174
78355
|
this.logger = this.logMetrics.createCountingLogger();
|
|
78356
|
+
const sessionsDir = path_1.default.join(projectDir2, ".sidekick", "sessions");
|
|
78357
|
+
this.sessionLogWriter = new core_1.SessionLogWriter({
|
|
78358
|
+
sessionsDir,
|
|
78359
|
+
maxHandles: 10,
|
|
78360
|
+
idleTimeoutMs: 30 * 60 * 1e3
|
|
78361
|
+
});
|
|
78362
|
+
(0, core_1.setSessionLogWriter)(this.sessionLogWriter);
|
|
78175
78363
|
this.stateService = new core_1.StateService(projectDir2, {
|
|
78176
78364
|
cache: true,
|
|
78177
78365
|
logger: this.logger,
|
|
@@ -78279,6 +78467,8 @@ var require_daemon = __commonJS({
|
|
|
78279
78467
|
}
|
|
78280
78468
|
async stop() {
|
|
78281
78469
|
this.logger.info("Daemon stopping");
|
|
78470
|
+
(0, core_1.setSessionLogWriter)(null);
|
|
78471
|
+
await this.sessionLogWriter.closeAll();
|
|
78282
78472
|
this.timerManager.stopAll();
|
|
78283
78473
|
this.configWatcher.stop();
|
|
78284
78474
|
this.personaWatcher.stop();
|
|
@@ -78604,6 +78794,7 @@ var require_daemon = __commonJS({
|
|
|
78604
78794
|
await this.llmManager.shutdownSessionProvider(sessionId, log);
|
|
78605
78795
|
this.logMetrics.deleteSessionCounters(sessionId);
|
|
78606
78796
|
await this.serviceFactory.shutdownSession(sessionId);
|
|
78797
|
+
await this.sessionLogWriter.closeSession(sessionId);
|
|
78607
78798
|
log.info("Session ended");
|
|
78608
78799
|
}
|
|
78609
78800
|
}
|