sidekick-agent-hub 0.17.7 → 0.18.1
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/sidekick-cli.mjs +1271 -268
- package/package.json +1 -1
package/dist/sidekick-cli.mjs
CHANGED
|
@@ -12272,6 +12272,230 @@ var require_eventBridge = __commonJS({
|
|
|
12272
12272
|
}
|
|
12273
12273
|
});
|
|
12274
12274
|
|
|
12275
|
+
// ../sidekick-shared/dist/watchers/jsonlTail.js
|
|
12276
|
+
var require_jsonlTail = __commonJS({
|
|
12277
|
+
"../sidekick-shared/dist/watchers/jsonlTail.js"(exports) {
|
|
12278
|
+
"use strict";
|
|
12279
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
12280
|
+
if (k2 === void 0) k2 = k;
|
|
12281
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
12282
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12283
|
+
desc = { enumerable: true, get: function() {
|
|
12284
|
+
return m[k];
|
|
12285
|
+
} };
|
|
12286
|
+
}
|
|
12287
|
+
Object.defineProperty(o, k2, desc);
|
|
12288
|
+
} : function(o, m, k, k2) {
|
|
12289
|
+
if (k2 === void 0) k2 = k;
|
|
12290
|
+
o[k2] = m[k];
|
|
12291
|
+
});
|
|
12292
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
12293
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
12294
|
+
} : function(o, v) {
|
|
12295
|
+
o["default"] = v;
|
|
12296
|
+
});
|
|
12297
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
|
|
12298
|
+
var ownKeys = function(o) {
|
|
12299
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
12300
|
+
var ar = [];
|
|
12301
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
12302
|
+
return ar;
|
|
12303
|
+
};
|
|
12304
|
+
return ownKeys(o);
|
|
12305
|
+
};
|
|
12306
|
+
return function(mod) {
|
|
12307
|
+
if (mod && mod.__esModule) return mod;
|
|
12308
|
+
var result = {};
|
|
12309
|
+
if (mod != null) {
|
|
12310
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
12311
|
+
}
|
|
12312
|
+
__setModuleDefault(result, mod);
|
|
12313
|
+
return result;
|
|
12314
|
+
};
|
|
12315
|
+
}();
|
|
12316
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12317
|
+
exports.createJsonlTail = createJsonlTail;
|
|
12318
|
+
var fs9 = __importStar(__require("fs"));
|
|
12319
|
+
var jsonl_1 = require_jsonl();
|
|
12320
|
+
var DEFAULT_DEBOUNCE_MS = 100;
|
|
12321
|
+
var DEFAULT_CATCHUP_INTERVAL_MS = 3e4;
|
|
12322
|
+
function createJsonlTail(options) {
|
|
12323
|
+
return new JsonlTailReader(options);
|
|
12324
|
+
}
|
|
12325
|
+
var JsonlTailReader = class {
|
|
12326
|
+
options;
|
|
12327
|
+
active = false;
|
|
12328
|
+
offset;
|
|
12329
|
+
fsWatcher = null;
|
|
12330
|
+
debounceTimer = null;
|
|
12331
|
+
catchupTimer = null;
|
|
12332
|
+
eventsInCurrentBatch = 0;
|
|
12333
|
+
parser;
|
|
12334
|
+
constructor(options) {
|
|
12335
|
+
this.options = options;
|
|
12336
|
+
this.offset = options.startOffset ?? 0;
|
|
12337
|
+
this.parser = new jsonl_1.JsonlParser({
|
|
12338
|
+
onEvent: (event) => {
|
|
12339
|
+
this.eventsInCurrentBatch += 1;
|
|
12340
|
+
this.options.onEvent(event);
|
|
12341
|
+
},
|
|
12342
|
+
onError: (error, line) => this.options.onError?.(error, line)
|
|
12343
|
+
}, { schema: options.schema });
|
|
12344
|
+
}
|
|
12345
|
+
get isActive() {
|
|
12346
|
+
return this.active;
|
|
12347
|
+
}
|
|
12348
|
+
start() {
|
|
12349
|
+
if (this.active)
|
|
12350
|
+
return;
|
|
12351
|
+
this.active = true;
|
|
12352
|
+
if (this.options.startAtEnd && this.options.startOffset === void 0) {
|
|
12353
|
+
try {
|
|
12354
|
+
this.offset = fs9.statSync(this.options.path).size;
|
|
12355
|
+
} catch {
|
|
12356
|
+
this.offset = 0;
|
|
12357
|
+
}
|
|
12358
|
+
}
|
|
12359
|
+
this.readNow();
|
|
12360
|
+
this.watchFile();
|
|
12361
|
+
const catchupIntervalMs = this.options.catchupIntervalMs ?? DEFAULT_CATCHUP_INTERVAL_MS;
|
|
12362
|
+
if (catchupIntervalMs > 0) {
|
|
12363
|
+
this.catchupTimer = setInterval(() => this.readNow(), catchupIntervalMs);
|
|
12364
|
+
}
|
|
12365
|
+
}
|
|
12366
|
+
stop() {
|
|
12367
|
+
if (!this.active)
|
|
12368
|
+
return;
|
|
12369
|
+
this.active = false;
|
|
12370
|
+
if (this.debounceTimer) {
|
|
12371
|
+
clearTimeout(this.debounceTimer);
|
|
12372
|
+
this.debounceTimer = null;
|
|
12373
|
+
}
|
|
12374
|
+
if (this.fsWatcher) {
|
|
12375
|
+
this.fsWatcher.close();
|
|
12376
|
+
this.fsWatcher = null;
|
|
12377
|
+
}
|
|
12378
|
+
if (this.catchupTimer) {
|
|
12379
|
+
clearInterval(this.catchupTimer);
|
|
12380
|
+
this.catchupTimer = null;
|
|
12381
|
+
}
|
|
12382
|
+
this.parser.flush();
|
|
12383
|
+
}
|
|
12384
|
+
dispose() {
|
|
12385
|
+
this.stop();
|
|
12386
|
+
}
|
|
12387
|
+
readNow() {
|
|
12388
|
+
let fd = null;
|
|
12389
|
+
try {
|
|
12390
|
+
const stat = fs9.statSync(this.options.path);
|
|
12391
|
+
if (stat.size < this.offset) {
|
|
12392
|
+
this.offset = 0;
|
|
12393
|
+
this.parser.reset();
|
|
12394
|
+
}
|
|
12395
|
+
if (stat.size <= this.offset)
|
|
12396
|
+
return;
|
|
12397
|
+
const bytesToRead = stat.size - this.offset;
|
|
12398
|
+
const buffer = Buffer.alloc(bytesToRead);
|
|
12399
|
+
fd = fs9.openSync(this.options.path, "r");
|
|
12400
|
+
const bytesRead = fs9.readSync(fd, buffer, 0, bytesToRead, this.offset);
|
|
12401
|
+
fs9.closeSync(fd);
|
|
12402
|
+
fd = null;
|
|
12403
|
+
if (bytesRead <= 0)
|
|
12404
|
+
return;
|
|
12405
|
+
this.offset += bytesRead;
|
|
12406
|
+
this.eventsInCurrentBatch = 0;
|
|
12407
|
+
this.parser.processChunk(buffer.toString("utf-8", 0, bytesRead));
|
|
12408
|
+
this.options.onBatchComplete?.({
|
|
12409
|
+
bytesRead,
|
|
12410
|
+
eventsRead: this.eventsInCurrentBatch,
|
|
12411
|
+
offset: this.offset
|
|
12412
|
+
});
|
|
12413
|
+
} catch (error) {
|
|
12414
|
+
if (fd !== null) {
|
|
12415
|
+
try {
|
|
12416
|
+
fs9.closeSync(fd);
|
|
12417
|
+
} catch {
|
|
12418
|
+
}
|
|
12419
|
+
}
|
|
12420
|
+
this.options.onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
12421
|
+
}
|
|
12422
|
+
}
|
|
12423
|
+
getOffset() {
|
|
12424
|
+
return this.offset;
|
|
12425
|
+
}
|
|
12426
|
+
seekTo(offset) {
|
|
12427
|
+
this.offset = Math.max(0, offset);
|
|
12428
|
+
this.parser.reset();
|
|
12429
|
+
}
|
|
12430
|
+
watchFile() {
|
|
12431
|
+
try {
|
|
12432
|
+
this.fsWatcher = fs9.watch(this.options.path, { persistent: false }, () => {
|
|
12433
|
+
this.debouncedRead();
|
|
12434
|
+
});
|
|
12435
|
+
this.fsWatcher.on("error", (error) => this.options.onError?.(error));
|
|
12436
|
+
} catch {
|
|
12437
|
+
}
|
|
12438
|
+
}
|
|
12439
|
+
debouncedRead() {
|
|
12440
|
+
if (this.debounceTimer)
|
|
12441
|
+
clearTimeout(this.debounceTimer);
|
|
12442
|
+
const debounceMs = this.options.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
12443
|
+
this.debounceTimer = setTimeout(() => this.readNow(), debounceMs);
|
|
12444
|
+
}
|
|
12445
|
+
};
|
|
12446
|
+
}
|
|
12447
|
+
});
|
|
12448
|
+
|
|
12449
|
+
// ../sidekick-shared/dist/formatting.js
|
|
12450
|
+
var require_formatting = __commonJS({
|
|
12451
|
+
"../sidekick-shared/dist/formatting.js"(exports) {
|
|
12452
|
+
"use strict";
|
|
12453
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12454
|
+
exports.formatTokenCount = formatTokenCount2;
|
|
12455
|
+
exports.formatDurationMs = formatDurationMs2;
|
|
12456
|
+
function formatTokenCount2(value, options = {}) {
|
|
12457
|
+
if (!Number.isFinite(value))
|
|
12458
|
+
return "0";
|
|
12459
|
+
const n = Math.trunc(value);
|
|
12460
|
+
const sign = n < 0 ? "-" : "";
|
|
12461
|
+
const abs = Math.abs(n);
|
|
12462
|
+
const thousandsSuffix = options.suffixCase === "upper" ? "K" : "k";
|
|
12463
|
+
if (abs >= 1e6)
|
|
12464
|
+
return `${sign}${(abs / 1e6).toFixed(1)}M`;
|
|
12465
|
+
if (abs >= 1e3)
|
|
12466
|
+
return `${sign}${(abs / 1e3).toFixed(1)}${thousandsSuffix}`;
|
|
12467
|
+
return `${n}`;
|
|
12468
|
+
}
|
|
12469
|
+
function formatDurationMs2(ms, options = {}) {
|
|
12470
|
+
const invalid = options.invalid ?? "N/A";
|
|
12471
|
+
if (!Number.isFinite(ms) || ms < 0)
|
|
12472
|
+
return invalid;
|
|
12473
|
+
const style = options.style ?? "spaced";
|
|
12474
|
+
const separator = style === "compact" ? "" : " ";
|
|
12475
|
+
const secondsFractionDigits = options.secondsFractionDigits ?? 0;
|
|
12476
|
+
if (ms < 1e3) {
|
|
12477
|
+
if (options.includeMilliseconds)
|
|
12478
|
+
return `${Math.round(ms)}ms`;
|
|
12479
|
+
return `${(ms / 1e3).toFixed(Math.max(1, secondsFractionDigits))}s`;
|
|
12480
|
+
}
|
|
12481
|
+
const seconds = ms / 1e3;
|
|
12482
|
+
if (seconds < 60) {
|
|
12483
|
+
if (secondsFractionDigits > 0)
|
|
12484
|
+
return `${seconds.toFixed(secondsFractionDigits)}s`;
|
|
12485
|
+
return `${Math.floor(seconds)}s`;
|
|
12486
|
+
}
|
|
12487
|
+
const totalSeconds = Math.floor(seconds);
|
|
12488
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
12489
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
12490
|
+
const remainingSeconds = totalSeconds % 60;
|
|
12491
|
+
if (hours > 0) {
|
|
12492
|
+
return `${hours}h${separator}${minutes}m${separator}${remainingSeconds}s`;
|
|
12493
|
+
}
|
|
12494
|
+
return `${minutes}m${separator}${remainingSeconds}s`;
|
|
12495
|
+
}
|
|
12496
|
+
}
|
|
12497
|
+
});
|
|
12498
|
+
|
|
12275
12499
|
// ../sidekick-shared/dist/formatters/sessionDump.js
|
|
12276
12500
|
var require_sessionDump = __commonJS({
|
|
12277
12501
|
"../sidekick-shared/dist/formatters/sessionDump.js"(exports) {
|
|
@@ -12284,6 +12508,7 @@ var require_sessionDump = __commonJS({
|
|
|
12284
12508
|
exports.fmtCost = fmtCost;
|
|
12285
12509
|
exports.formatTimestamp = formatTimestamp2;
|
|
12286
12510
|
exports.formatDuration = formatDuration2;
|
|
12511
|
+
var formatting_1 = require_formatting();
|
|
12287
12512
|
function formatSessionJson2(metrics) {
|
|
12288
12513
|
return JSON.stringify(metrics, null, 2) + "\n";
|
|
12289
12514
|
}
|
|
@@ -12473,11 +12698,7 @@ var require_sessionDump = __commonJS({
|
|
|
12473
12698
|
return line + ")";
|
|
12474
12699
|
}
|
|
12475
12700
|
function fmtTokens2(n) {
|
|
12476
|
-
|
|
12477
|
-
return `${(n / 1e6).toFixed(1)}M`;
|
|
12478
|
-
if (n >= 1e3)
|
|
12479
|
-
return `${(n / 1e3).toFixed(1)}k`;
|
|
12480
|
-
return String(n);
|
|
12701
|
+
return (0, formatting_1.formatTokenCount)(n);
|
|
12481
12702
|
}
|
|
12482
12703
|
function fmtCost(cost) {
|
|
12483
12704
|
if (cost <= 0)
|
|
@@ -12504,17 +12725,7 @@ var require_sessionDump = __commonJS({
|
|
|
12504
12725
|
return "N/A";
|
|
12505
12726
|
try {
|
|
12506
12727
|
const ms = new Date(end).getTime() - new Date(start).getTime();
|
|
12507
|
-
|
|
12508
|
-
return "N/A";
|
|
12509
|
-
const totalSec = Math.floor(ms / 1e3);
|
|
12510
|
-
const hours = Math.floor(totalSec / 3600);
|
|
12511
|
-
const minutes = Math.floor(totalSec % 3600 / 60);
|
|
12512
|
-
const seconds = totalSec % 60;
|
|
12513
|
-
if (hours > 0)
|
|
12514
|
-
return `${hours}h ${minutes}m ${seconds}s`;
|
|
12515
|
-
if (minutes > 0)
|
|
12516
|
-
return `${minutes}m ${seconds}s`;
|
|
12517
|
-
return `${seconds}s`;
|
|
12728
|
+
return (0, formatting_1.formatDurationMs)(ms);
|
|
12518
12729
|
} catch {
|
|
12519
12730
|
return "N/A";
|
|
12520
12731
|
}
|
|
@@ -12864,7 +13075,7 @@ var require_phrases = __commonJS({
|
|
|
12864
13075
|
"../sidekick-shared/dist/phrases.js"(exports) {
|
|
12865
13076
|
"use strict";
|
|
12866
13077
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12867
|
-
exports.ALL_PHRASES = exports.STACK_OVERFLOW = exports.DEPENDENCY_HELL = exports.RUBBER_DUCK = exports.TONGUE_TWISTERS = exports.INTERVIEW_HELL = exports.FORTUNE_COOKIE = exports.COMMIT_SINS = exports.OVERHEARD = exports.ERROR_MESSAGES = exports.LOADING_TIPS = exports.AFTER_HOURS = exports.VIBE_CODING = exports.OBSOLESCENCE = exports.SYCOPHANCY = exports.MOTIVATION = exports.AI_INDUSTRY = exports.THE_ECOSYSTEM = exports.FOURTH_WALL = exports.META_MONITORING = exports.PUNCHY = exports.DRAMATIC = exports.DEV_RELATABLE = exports.AI_COMMENTARY = exports.SIDEKICK_ENERGY = void 0;
|
|
13078
|
+
exports.ALL_PHRASES = exports.PHRASE_CATEGORIES = exports.STACK_OVERFLOW = exports.DEPENDENCY_HELL = exports.RUBBER_DUCK = exports.TONGUE_TWISTERS = exports.INTERVIEW_HELL = exports.FORTUNE_COOKIE = exports.COMMIT_SINS = exports.OVERHEARD = exports.ERROR_MESSAGES = exports.LOADING_TIPS = exports.AFTER_HOURS = exports.VIBE_CODING = exports.OBSOLESCENCE = exports.SYCOPHANCY = exports.MOTIVATION = exports.AI_INDUSTRY = exports.THE_ECOSYSTEM = exports.FOURTH_WALL = exports.META_MONITORING = exports.PUNCHY = exports.DRAMATIC = exports.DEV_RELATABLE = exports.AI_COMMENTARY = exports.SIDEKICK_ENERGY = void 0;
|
|
12868
13079
|
exports.getRandomPhrase = getRandomPhrase3;
|
|
12869
13080
|
exports.SIDEKICK_ENERGY = [
|
|
12870
13081
|
"Your friendly neighborhood sidekick, reporting for duty.",
|
|
@@ -14140,32 +14351,33 @@ var require_phrases = __commonJS({
|
|
|
14140
14351
|
"The real dependency is not npm. It is the mass-copied Stack Overflow snippets holding your app together.",
|
|
14141
14352
|
"You mass-searched, mass-copied, and mass-deployed. The Stack Overflow-driven development lifecycle."
|
|
14142
14353
|
];
|
|
14143
|
-
exports.
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
|
|
14147
|
-
|
|
14148
|
-
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
|
|
14156
|
-
|
|
14157
|
-
|
|
14158
|
-
|
|
14159
|
-
|
|
14160
|
-
|
|
14161
|
-
|
|
14162
|
-
|
|
14163
|
-
|
|
14164
|
-
|
|
14165
|
-
|
|
14166
|
-
|
|
14167
|
-
|
|
14354
|
+
exports.PHRASE_CATEGORIES = [
|
|
14355
|
+
{ id: "sidekick-energy", phrases: exports.SIDEKICK_ENERGY },
|
|
14356
|
+
{ id: "ai-commentary", phrases: exports.AI_COMMENTARY },
|
|
14357
|
+
{ id: "dev-relatable", phrases: exports.DEV_RELATABLE },
|
|
14358
|
+
{ id: "dramatic", phrases: exports.DRAMATIC },
|
|
14359
|
+
{ id: "punchy", phrases: exports.PUNCHY },
|
|
14360
|
+
{ id: "meta-monitoring", phrases: exports.META_MONITORING },
|
|
14361
|
+
{ id: "fourth-wall", phrases: exports.FOURTH_WALL },
|
|
14362
|
+
{ id: "ecosystem", phrases: exports.THE_ECOSYSTEM },
|
|
14363
|
+
{ id: "ai-industry", phrases: exports.AI_INDUSTRY },
|
|
14364
|
+
{ id: "motivation", phrases: exports.MOTIVATION },
|
|
14365
|
+
{ id: "sycophancy", phrases: exports.SYCOPHANCY },
|
|
14366
|
+
{ id: "obsolescence", phrases: exports.OBSOLESCENCE },
|
|
14367
|
+
{ id: "vibe-coding", phrases: exports.VIBE_CODING },
|
|
14368
|
+
{ id: "after-hours", phrases: exports.AFTER_HOURS },
|
|
14369
|
+
{ id: "loading-tips", phrases: exports.LOADING_TIPS },
|
|
14370
|
+
{ id: "error-messages", phrases: exports.ERROR_MESSAGES },
|
|
14371
|
+
{ id: "overheard", phrases: exports.OVERHEARD },
|
|
14372
|
+
{ id: "commit-sins", phrases: exports.COMMIT_SINS },
|
|
14373
|
+
{ id: "fortune-cookie", phrases: exports.FORTUNE_COOKIE },
|
|
14374
|
+
{ id: "interview-hell", phrases: exports.INTERVIEW_HELL },
|
|
14375
|
+
{ id: "tongue-twisters", phrases: exports.TONGUE_TWISTERS },
|
|
14376
|
+
{ id: "rubber-duck", phrases: exports.RUBBER_DUCK },
|
|
14377
|
+
{ id: "dependency-hell", phrases: exports.DEPENDENCY_HELL },
|
|
14378
|
+
{ id: "stack-overflow", phrases: exports.STACK_OVERFLOW }
|
|
14168
14379
|
];
|
|
14380
|
+
exports.ALL_PHRASES = exports.PHRASE_CATEGORIES.flatMap((category) => category.phrases);
|
|
14169
14381
|
function getRandomPhrase3() {
|
|
14170
14382
|
return exports.ALL_PHRASES[Math.floor(Math.random() * exports.ALL_PHRASES.length)];
|
|
14171
14383
|
}
|
|
@@ -14502,6 +14714,12 @@ var require_modelInfo = __commonJS({
|
|
|
14502
14714
|
exports.getModelInfo = getModelInfo2;
|
|
14503
14715
|
exports.calculateCostWithPricing = calculateCostWithPricing;
|
|
14504
14716
|
exports.calculateCost = calculateCost;
|
|
14717
|
+
exports.calculateCostWithProvenance = calculateCostWithProvenance;
|
|
14718
|
+
exports.mergeCostSources = mergeCostSources;
|
|
14719
|
+
exports.shortModelName = shortModelName;
|
|
14720
|
+
exports.getModelDisplayInfo = getModelDisplayInfo;
|
|
14721
|
+
exports.compareModelIds = compareModelIds;
|
|
14722
|
+
exports.sortModelIds = sortModelIds;
|
|
14505
14723
|
exports.formatCost = formatCost5;
|
|
14506
14724
|
var modelContext_1 = require_modelContext();
|
|
14507
14725
|
var PRICING_TABLE = {
|
|
@@ -14647,6 +14865,7 @@ var require_modelInfo = __commonJS({
|
|
|
14647
14865
|
overrideSortedKeys = [];
|
|
14648
14866
|
}
|
|
14649
14867
|
var CLAUDE_RE = /^claude-(haiku|sonnet|opus)-([0-9.]+)/i;
|
|
14868
|
+
var LEGACY_CLAUDE_RE = /^claude-([0-9]+(?:[-.][0-9]+)?)-(haiku|sonnet|opus)(?:-|$)/i;
|
|
14650
14869
|
var GPT_RE = /^gpt-([0-9][0-9.A-Za-z-]*)/i;
|
|
14651
14870
|
var O_SERIES_RE = /^o([0-9]+)(-mini|-pro)?/i;
|
|
14652
14871
|
var GEMINI_RE = /^gemini-([0-9][0-9.A-Za-z-]*)/i;
|
|
@@ -14658,6 +14877,14 @@ var require_modelInfo = __commonJS({
|
|
|
14658
14877
|
if (claude) {
|
|
14659
14878
|
return { provider: "anthropic", family: claude[1].toLowerCase(), version: claude[2] };
|
|
14660
14879
|
}
|
|
14880
|
+
const legacyClaude = normalized.match(LEGACY_CLAUDE_RE);
|
|
14881
|
+
if (legacyClaude) {
|
|
14882
|
+
return {
|
|
14883
|
+
provider: "anthropic",
|
|
14884
|
+
family: legacyClaude[2].toLowerCase(),
|
|
14885
|
+
version: legacyClaude[1].replace("-", ".")
|
|
14886
|
+
};
|
|
14887
|
+
}
|
|
14661
14888
|
const gpt = normalized.match(GPT_RE);
|
|
14662
14889
|
if (gpt) {
|
|
14663
14890
|
return { provider: "openai", family: "gpt", version: gpt[1] };
|
|
@@ -14716,6 +14943,92 @@ var require_modelInfo = __commonJS({
|
|
|
14716
14943
|
return null;
|
|
14717
14944
|
return calculateCostWithPricing(usage, pricing);
|
|
14718
14945
|
}
|
|
14946
|
+
function calculateCostWithProvenance(input) {
|
|
14947
|
+
if (typeof input.reportedCostUsd === "number" && Number.isFinite(input.reportedCostUsd)) {
|
|
14948
|
+
return { costUsd: input.reportedCostUsd, source: "reported" };
|
|
14949
|
+
}
|
|
14950
|
+
const estimated = calculateCost(input.usage, input.modelId);
|
|
14951
|
+
if (estimated === null)
|
|
14952
|
+
return { source: "unpriced" };
|
|
14953
|
+
return { costUsd: estimated, source: "estimated" };
|
|
14954
|
+
}
|
|
14955
|
+
function mergeCostSources(a, b) {
|
|
14956
|
+
const rank = {
|
|
14957
|
+
reported: 0,
|
|
14958
|
+
estimated: 1,
|
|
14959
|
+
unpriced: 2
|
|
14960
|
+
};
|
|
14961
|
+
return rank[a] >= rank[b] ? a : b;
|
|
14962
|
+
}
|
|
14963
|
+
function normalizeModelId(modelId) {
|
|
14964
|
+
return modelId.trim().toLowerCase().replace(/^[a-z]+\//, "").replace(/-\d{8}$/, "").replace(/-latest$/, "").replace(/\[1m\]/gi, "");
|
|
14965
|
+
}
|
|
14966
|
+
function shortModelName(modelId) {
|
|
14967
|
+
const normalized = normalizeModelId(modelId);
|
|
14968
|
+
const parsed = parseModelId(normalized);
|
|
14969
|
+
if (normalized.includes("codex"))
|
|
14970
|
+
return "Codex";
|
|
14971
|
+
if (parsed?.provider === "anthropic") {
|
|
14972
|
+
const family = parsed.family.toLowerCase();
|
|
14973
|
+
return family.charAt(0).toUpperCase() + family.slice(1);
|
|
14974
|
+
}
|
|
14975
|
+
if (parsed?.provider === "openai") {
|
|
14976
|
+
if (parsed.family === "o")
|
|
14977
|
+
return `o${parsed.version}`;
|
|
14978
|
+
if (normalized.startsWith("gpt-4o-mini"))
|
|
14979
|
+
return "GPT-4o mini";
|
|
14980
|
+
if (normalized.startsWith("gpt-4o"))
|
|
14981
|
+
return "GPT-4o";
|
|
14982
|
+
if (parsed.family === "gpt")
|
|
14983
|
+
return `GPT-${parsed.version}`;
|
|
14984
|
+
}
|
|
14985
|
+
return modelId;
|
|
14986
|
+
}
|
|
14987
|
+
var CLAUDE_FAMILY_RANK = {
|
|
14988
|
+
opus: 0,
|
|
14989
|
+
sonnet: 1,
|
|
14990
|
+
haiku: 2
|
|
14991
|
+
};
|
|
14992
|
+
function versionRank(version) {
|
|
14993
|
+
if (!version)
|
|
14994
|
+
return Number.MAX_SAFE_INTEGER;
|
|
14995
|
+
const numeric = Number(version.replace("-", ".").match(/[0-9]+(?:\.[0-9]+)?/)?.[0]);
|
|
14996
|
+
if (!Number.isFinite(numeric))
|
|
14997
|
+
return Number.MAX_SAFE_INTEGER;
|
|
14998
|
+
return -numeric;
|
|
14999
|
+
}
|
|
15000
|
+
function getModelDisplayInfo(modelId) {
|
|
15001
|
+
const parsed = parseModelId(modelId);
|
|
15002
|
+
const normalized = normalizeModelId(modelId);
|
|
15003
|
+
let rank = 1e3;
|
|
15004
|
+
if (parsed?.provider === "anthropic") {
|
|
15005
|
+
rank = (CLAUDE_FAMILY_RANK[parsed.family] ?? 9) * 100 + versionRank(parsed.version);
|
|
15006
|
+
} else if (normalized.includes("codex")) {
|
|
15007
|
+
rank = 200;
|
|
15008
|
+
} else if (parsed?.provider === "openai") {
|
|
15009
|
+
rank = parsed.family === "gpt" ? 300 + versionRank(parsed.version) : 400 + versionRank(parsed.version);
|
|
15010
|
+
} else if (parsed?.provider === "google") {
|
|
15011
|
+
rank = 500 + versionRank(parsed.version);
|
|
15012
|
+
}
|
|
15013
|
+
return {
|
|
15014
|
+
modelId,
|
|
15015
|
+
provider: parsed?.provider ?? null,
|
|
15016
|
+
family: parsed?.family ?? null,
|
|
15017
|
+
version: parsed?.version ?? null,
|
|
15018
|
+
shortName: shortModelName(modelId),
|
|
15019
|
+
rank
|
|
15020
|
+
};
|
|
15021
|
+
}
|
|
15022
|
+
function compareModelIds(a, b) {
|
|
15023
|
+
const left = getModelDisplayInfo(a);
|
|
15024
|
+
const right = getModelDisplayInfo(b);
|
|
15025
|
+
if (left.rank !== right.rank)
|
|
15026
|
+
return left.rank - right.rank;
|
|
15027
|
+
return a.localeCompare(b);
|
|
15028
|
+
}
|
|
15029
|
+
function sortModelIds(modelIds) {
|
|
15030
|
+
return [...modelIds].sort(compareModelIds);
|
|
15031
|
+
}
|
|
14719
15032
|
function formatCost5(cost) {
|
|
14720
15033
|
if (cost === null || cost === void 0)
|
|
14721
15034
|
return "\u2014";
|
|
@@ -18128,6 +18441,49 @@ var require_ensureDefaultAccounts = __commonJS({
|
|
|
18128
18441
|
}
|
|
18129
18442
|
});
|
|
18130
18443
|
|
|
18444
|
+
// ../sidekick-shared/dist/accountStatus.js
|
|
18445
|
+
var require_accountStatus = __commonJS({
|
|
18446
|
+
"../sidekick-shared/dist/accountStatus.js"(exports) {
|
|
18447
|
+
"use strict";
|
|
18448
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18449
|
+
exports.getActiveAccountStatus = getActiveAccountStatus;
|
|
18450
|
+
var accounts_1 = require_accounts();
|
|
18451
|
+
var codexProfiles_1 = require_codexProfiles();
|
|
18452
|
+
function errorMessage(error) {
|
|
18453
|
+
return error instanceof Error ? error.message : String(error);
|
|
18454
|
+
}
|
|
18455
|
+
function getActiveAccountStatus(error) {
|
|
18456
|
+
try {
|
|
18457
|
+
const claudeAccount = (0, accounts_1.readActiveClaudeAccount)();
|
|
18458
|
+
const codexAccount = (0, codexProfiles_1.getActiveCodexAccount)();
|
|
18459
|
+
const claude = claudeAccount ? {
|
|
18460
|
+
present: true,
|
|
18461
|
+
email: claudeAccount.email,
|
|
18462
|
+
label: claudeAccount.email
|
|
18463
|
+
} : { present: false };
|
|
18464
|
+
const codex = codexAccount ? {
|
|
18465
|
+
present: true,
|
|
18466
|
+
email: codexAccount.email ?? codexAccount.metadata?.email,
|
|
18467
|
+
label: codexAccount.label ?? codexAccount.email ?? codexAccount.metadata?.email ?? codexAccount.id
|
|
18468
|
+
} : { present: false };
|
|
18469
|
+
return {
|
|
18470
|
+
ok: claude.present || codex.present,
|
|
18471
|
+
claude,
|
|
18472
|
+
codex,
|
|
18473
|
+
error
|
|
18474
|
+
};
|
|
18475
|
+
} catch (caught) {
|
|
18476
|
+
return {
|
|
18477
|
+
ok: false,
|
|
18478
|
+
claude: { present: false },
|
|
18479
|
+
codex: { present: false },
|
|
18480
|
+
error: error ?? errorMessage(caught)
|
|
18481
|
+
};
|
|
18482
|
+
}
|
|
18483
|
+
}
|
|
18484
|
+
}
|
|
18485
|
+
});
|
|
18486
|
+
|
|
18131
18487
|
// ../sidekick-shared/dist/quota.js
|
|
18132
18488
|
var require_quota = __commonJS({
|
|
18133
18489
|
"../sidekick-shared/dist/quota.js"(exports) {
|
|
@@ -18590,6 +18946,656 @@ var require_codexQuota = __commonJS({
|
|
|
18590
18946
|
}
|
|
18591
18947
|
});
|
|
18592
18948
|
|
|
18949
|
+
// ../sidekick-shared/dist/codexQuotaWatcher.js
|
|
18950
|
+
var require_codexQuotaWatcher = __commonJS({
|
|
18951
|
+
"../sidekick-shared/dist/codexQuotaWatcher.js"(exports) {
|
|
18952
|
+
"use strict";
|
|
18953
|
+
var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
18954
|
+
if (k2 === void 0) k2 = k;
|
|
18955
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
18956
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
18957
|
+
desc = { enumerable: true, get: function() {
|
|
18958
|
+
return m[k];
|
|
18959
|
+
} };
|
|
18960
|
+
}
|
|
18961
|
+
Object.defineProperty(o, k2, desc);
|
|
18962
|
+
} : function(o, m, k, k2) {
|
|
18963
|
+
if (k2 === void 0) k2 = k;
|
|
18964
|
+
o[k2] = m[k];
|
|
18965
|
+
});
|
|
18966
|
+
var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) {
|
|
18967
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18968
|
+
} : function(o, v) {
|
|
18969
|
+
o["default"] = v;
|
|
18970
|
+
});
|
|
18971
|
+
var __importStar = exports && exports.__importStar || /* @__PURE__ */ function() {
|
|
18972
|
+
var ownKeys = function(o) {
|
|
18973
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
18974
|
+
var ar = [];
|
|
18975
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
18976
|
+
return ar;
|
|
18977
|
+
};
|
|
18978
|
+
return ownKeys(o);
|
|
18979
|
+
};
|
|
18980
|
+
return function(mod) {
|
|
18981
|
+
if (mod && mod.__esModule) return mod;
|
|
18982
|
+
var result = {};
|
|
18983
|
+
if (mod != null) {
|
|
18984
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
18985
|
+
}
|
|
18986
|
+
__setModuleDefault(result, mod);
|
|
18987
|
+
return result;
|
|
18988
|
+
};
|
|
18989
|
+
}();
|
|
18990
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18991
|
+
exports.CodexQuotaWatcher = void 0;
|
|
18992
|
+
var fs9 = __importStar(__require("fs"));
|
|
18993
|
+
var codexProfiles_1 = require_codexProfiles();
|
|
18994
|
+
var codexQuota_1 = require_codexQuota();
|
|
18995
|
+
var quotaSnapshots_1 = require_quotaSnapshots();
|
|
18996
|
+
var codex_1 = require_codex();
|
|
18997
|
+
var DEFAULT_DISCOVERY_POLL_INTERVAL_MS = 3e4;
|
|
18998
|
+
function accountEmail(account) {
|
|
18999
|
+
return account?.email ?? account?.metadata?.email;
|
|
19000
|
+
}
|
|
19001
|
+
function enrichQuotaState(state, account) {
|
|
19002
|
+
return {
|
|
19003
|
+
...state,
|
|
19004
|
+
runtimeProvider: "codex",
|
|
19005
|
+
providerId: "codex",
|
|
19006
|
+
accountLabel: account?.label,
|
|
19007
|
+
accountDetail: accountEmail(account)
|
|
19008
|
+
};
|
|
19009
|
+
}
|
|
19010
|
+
function makeUnavailableState(account, error = "Run a Codex session to view rate limits") {
|
|
19011
|
+
return {
|
|
19012
|
+
runtimeProvider: "codex",
|
|
19013
|
+
fiveHour: { utilization: 0, resetsAt: "" },
|
|
19014
|
+
sevenDay: { utilization: 0, resetsAt: "" },
|
|
19015
|
+
available: false,
|
|
19016
|
+
error,
|
|
19017
|
+
providerId: "codex",
|
|
19018
|
+
accountLabel: account?.label,
|
|
19019
|
+
accountDetail: accountEmail(account),
|
|
19020
|
+
fiveHourLabel: "Primary",
|
|
19021
|
+
sevenDayLabel: "Secondary"
|
|
19022
|
+
};
|
|
19023
|
+
}
|
|
19024
|
+
var CodexQuotaWatcher = class {
|
|
19025
|
+
workspacePath;
|
|
19026
|
+
discoveryPollIntervalMs;
|
|
19027
|
+
providerFactory;
|
|
19028
|
+
getActiveAccount;
|
|
19029
|
+
readSnapshot;
|
|
19030
|
+
writeSnapshot;
|
|
19031
|
+
watchFile;
|
|
19032
|
+
listeners = [];
|
|
19033
|
+
discoveryTimer;
|
|
19034
|
+
provider = null;
|
|
19035
|
+
reader = null;
|
|
19036
|
+
fileWatcher = null;
|
|
19037
|
+
sessionPath = null;
|
|
19038
|
+
lastEmissionKey = null;
|
|
19039
|
+
running = false;
|
|
19040
|
+
constructor(workspacePath, options = {}) {
|
|
19041
|
+
this.workspacePath = workspacePath;
|
|
19042
|
+
this.discoveryPollIntervalMs = options.discoveryPollIntervalMs ?? DEFAULT_DISCOVERY_POLL_INTERVAL_MS;
|
|
19043
|
+
this.providerFactory = options.providerFactory ?? (() => new codex_1.CodexProvider());
|
|
19044
|
+
this.getActiveAccount = options.getActiveAccount ?? codexProfiles_1.getActiveCodexAccount;
|
|
19045
|
+
this.readSnapshot = options.readSnapshot ?? quotaSnapshots_1.readQuotaSnapshot;
|
|
19046
|
+
this.writeSnapshot = options.writeSnapshot ?? quotaSnapshots_1.writeQuotaSnapshot;
|
|
19047
|
+
this.watchFile = options.watchFile ?? fs9.watch;
|
|
19048
|
+
}
|
|
19049
|
+
start() {
|
|
19050
|
+
if (this.running)
|
|
19051
|
+
return;
|
|
19052
|
+
this.running = true;
|
|
19053
|
+
this.refreshActiveSession();
|
|
19054
|
+
this.discoveryTimer = setInterval(() => {
|
|
19055
|
+
this.refreshActiveSession();
|
|
19056
|
+
}, this.discoveryPollIntervalMs);
|
|
19057
|
+
}
|
|
19058
|
+
stop() {
|
|
19059
|
+
if (!this.running)
|
|
19060
|
+
return;
|
|
19061
|
+
this.running = false;
|
|
19062
|
+
if (this.discoveryTimer) {
|
|
19063
|
+
clearInterval(this.discoveryTimer);
|
|
19064
|
+
this.discoveryTimer = void 0;
|
|
19065
|
+
}
|
|
19066
|
+
this.teardownActiveSession();
|
|
19067
|
+
}
|
|
19068
|
+
dispose() {
|
|
19069
|
+
this.stop();
|
|
19070
|
+
this.listeners.splice(0, this.listeners.length);
|
|
19071
|
+
}
|
|
19072
|
+
onUpdate(cb) {
|
|
19073
|
+
this.listeners.push(cb);
|
|
19074
|
+
return {
|
|
19075
|
+
dispose: () => {
|
|
19076
|
+
const index = this.listeners.indexOf(cb);
|
|
19077
|
+
if (index >= 0)
|
|
19078
|
+
this.listeners.splice(index, 1);
|
|
19079
|
+
}
|
|
19080
|
+
};
|
|
19081
|
+
}
|
|
19082
|
+
onQuotaUpdate(cb) {
|
|
19083
|
+
return this.onUpdate(cb);
|
|
19084
|
+
}
|
|
19085
|
+
refresh() {
|
|
19086
|
+
this.refreshActiveSession();
|
|
19087
|
+
}
|
|
19088
|
+
refreshActiveSession() {
|
|
19089
|
+
const provider = this.getProvider();
|
|
19090
|
+
const nextSessionPath = provider.findActiveSession(this.workspacePath);
|
|
19091
|
+
if (!nextSessionPath) {
|
|
19092
|
+
this.teardownActiveSession();
|
|
19093
|
+
this.emitCachedOrUnavailable();
|
|
19094
|
+
return;
|
|
19095
|
+
}
|
|
19096
|
+
if (nextSessionPath !== this.sessionPath || this.reader == null) {
|
|
19097
|
+
this.attachToSession(nextSessionPath);
|
|
19098
|
+
return;
|
|
19099
|
+
}
|
|
19100
|
+
this.ingestSessionUpdate("readNew");
|
|
19101
|
+
}
|
|
19102
|
+
attachToSession(nextSessionPath) {
|
|
19103
|
+
this.teardownActiveSession();
|
|
19104
|
+
this.provider = this.providerFactory();
|
|
19105
|
+
this.reader = this.provider.createReader(nextSessionPath);
|
|
19106
|
+
this.sessionPath = nextSessionPath;
|
|
19107
|
+
this.ingestSessionUpdate("readAll");
|
|
19108
|
+
try {
|
|
19109
|
+
this.fileWatcher = this.watchFile(nextSessionPath, (eventType) => {
|
|
19110
|
+
if (!this.running)
|
|
19111
|
+
return;
|
|
19112
|
+
if (eventType === "change") {
|
|
19113
|
+
this.ingestSessionUpdate("readNew");
|
|
19114
|
+
return;
|
|
19115
|
+
}
|
|
19116
|
+
this.refreshActiveSession();
|
|
19117
|
+
});
|
|
19118
|
+
} catch {
|
|
19119
|
+
this.emitCachedOrUnavailable();
|
|
19120
|
+
}
|
|
19121
|
+
}
|
|
19122
|
+
ingestSessionUpdate(mode) {
|
|
19123
|
+
if (!this.provider || !this.reader) {
|
|
19124
|
+
this.emitCachedOrUnavailable();
|
|
19125
|
+
return;
|
|
19126
|
+
}
|
|
19127
|
+
if (!this.reader.exists()) {
|
|
19128
|
+
this.refreshActiveSession();
|
|
19129
|
+
return;
|
|
19130
|
+
}
|
|
19131
|
+
if (mode === "readAll") {
|
|
19132
|
+
this.reader.readAll();
|
|
19133
|
+
} else {
|
|
19134
|
+
this.reader.readNew();
|
|
19135
|
+
}
|
|
19136
|
+
const liveQuota = (0, codexQuota_1.quotaFromCodexRateLimits)(this.provider.getLastRateLimits(), "session");
|
|
19137
|
+
if (!liveQuota) {
|
|
19138
|
+
this.emitCachedOrUnavailable();
|
|
19139
|
+
return;
|
|
19140
|
+
}
|
|
19141
|
+
const account = this.getActiveAccount();
|
|
19142
|
+
if (account) {
|
|
19143
|
+
this.writeSnapshot("codex", account.id, liveQuota);
|
|
19144
|
+
}
|
|
19145
|
+
this.emitState(enrichQuotaState({
|
|
19146
|
+
...liveQuota,
|
|
19147
|
+
runtimeProvider: "codex",
|
|
19148
|
+
providerId: "codex"
|
|
19149
|
+
}, account));
|
|
19150
|
+
}
|
|
19151
|
+
emitCachedOrUnavailable() {
|
|
19152
|
+
const account = this.getActiveAccount();
|
|
19153
|
+
const cached = account ? this.readSnapshot("codex", account.id) : null;
|
|
19154
|
+
if (cached) {
|
|
19155
|
+
this.emitState(enrichQuotaState({
|
|
19156
|
+
...cached,
|
|
19157
|
+
runtimeProvider: "codex",
|
|
19158
|
+
providerId: "codex",
|
|
19159
|
+
source: "cache",
|
|
19160
|
+
stale: true,
|
|
19161
|
+
fiveHourLabel: cached.fiveHourLabel ?? "Primary",
|
|
19162
|
+
sevenDayLabel: cached.sevenDayLabel ?? "Secondary"
|
|
19163
|
+
}, account));
|
|
19164
|
+
return;
|
|
19165
|
+
}
|
|
19166
|
+
this.emitState(makeUnavailableState(account));
|
|
19167
|
+
}
|
|
19168
|
+
emitState(state) {
|
|
19169
|
+
const nextKey = JSON.stringify(state);
|
|
19170
|
+
if (this.lastEmissionKey === nextKey)
|
|
19171
|
+
return;
|
|
19172
|
+
this.lastEmissionKey = nextKey;
|
|
19173
|
+
for (const listener of this.listeners) {
|
|
19174
|
+
try {
|
|
19175
|
+
listener(state);
|
|
19176
|
+
} catch {
|
|
19177
|
+
}
|
|
19178
|
+
}
|
|
19179
|
+
}
|
|
19180
|
+
getProvider() {
|
|
19181
|
+
if (!this.provider) {
|
|
19182
|
+
this.provider = this.providerFactory();
|
|
19183
|
+
}
|
|
19184
|
+
return this.provider;
|
|
19185
|
+
}
|
|
19186
|
+
teardownActiveSession() {
|
|
19187
|
+
if (this.fileWatcher) {
|
|
19188
|
+
this.fileWatcher.close();
|
|
19189
|
+
this.fileWatcher = null;
|
|
19190
|
+
}
|
|
19191
|
+
this.reader?.flush();
|
|
19192
|
+
this.reader = null;
|
|
19193
|
+
this.provider?.dispose();
|
|
19194
|
+
this.provider = null;
|
|
19195
|
+
this.sessionPath = null;
|
|
19196
|
+
}
|
|
19197
|
+
};
|
|
19198
|
+
exports.CodexQuotaWatcher = CodexQuotaWatcher;
|
|
19199
|
+
}
|
|
19200
|
+
});
|
|
19201
|
+
|
|
19202
|
+
// ../sidekick-shared/dist/peakHours.js
|
|
19203
|
+
var require_peakHours = __commonJS({
|
|
19204
|
+
"../sidekick-shared/dist/peakHours.js"(exports) {
|
|
19205
|
+
"use strict";
|
|
19206
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19207
|
+
exports.fetchPeakHoursStatus = fetchPeakHoursStatus4;
|
|
19208
|
+
var PROMOCLOCK_ENDPOINT = "https://promoclock.co/api/status";
|
|
19209
|
+
function unavailableState() {
|
|
19210
|
+
return {
|
|
19211
|
+
status: "unknown",
|
|
19212
|
+
isPeak: false,
|
|
19213
|
+
sessionLimitSpeed: "unknown",
|
|
19214
|
+
label: "Peak-hours status unavailable",
|
|
19215
|
+
peakHoursDescription: "",
|
|
19216
|
+
nextChange: null,
|
|
19217
|
+
minutesUntilChange: null,
|
|
19218
|
+
note: "",
|
|
19219
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19220
|
+
unavailable: true
|
|
19221
|
+
};
|
|
19222
|
+
}
|
|
19223
|
+
function normalizeStatus(raw) {
|
|
19224
|
+
if (raw === "peak" || raw === "off_peak")
|
|
19225
|
+
return raw;
|
|
19226
|
+
return "unknown";
|
|
19227
|
+
}
|
|
19228
|
+
function normalizeSpeed(raw) {
|
|
19229
|
+
if (raw === "normal" || raw === "faster")
|
|
19230
|
+
return raw;
|
|
19231
|
+
return "unknown";
|
|
19232
|
+
}
|
|
19233
|
+
async function fetchPeakHoursStatus4() {
|
|
19234
|
+
try {
|
|
19235
|
+
const res = await fetch(PROMOCLOCK_ENDPOINT);
|
|
19236
|
+
if (!res.ok)
|
|
19237
|
+
return unavailableState();
|
|
19238
|
+
const data = await res.json();
|
|
19239
|
+
const status = normalizeStatus(data.status);
|
|
19240
|
+
const sessionLimitSpeed = normalizeSpeed(data.sessionLimitSpeed);
|
|
19241
|
+
const isPeak = typeof data.isPeak === "boolean" ? data.isPeak : status === "peak";
|
|
19242
|
+
return {
|
|
19243
|
+
status,
|
|
19244
|
+
isPeak,
|
|
19245
|
+
sessionLimitSpeed,
|
|
19246
|
+
label: data.label ?? (isPeak ? "Peak Hours" : "Off-Peak"),
|
|
19247
|
+
peakHoursDescription: data.peakHours ?? "",
|
|
19248
|
+
nextChange: data.nextChange ?? null,
|
|
19249
|
+
minutesUntilChange: typeof data.minutesUntilChange === "number" ? data.minutesUntilChange : null,
|
|
19250
|
+
note: data.note ?? "",
|
|
19251
|
+
updatedAt: data.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
19252
|
+
unavailable: false
|
|
19253
|
+
};
|
|
19254
|
+
} catch {
|
|
19255
|
+
return unavailableState();
|
|
19256
|
+
}
|
|
19257
|
+
}
|
|
19258
|
+
}
|
|
19259
|
+
});
|
|
19260
|
+
|
|
19261
|
+
// ../sidekick-shared/dist/multiProviderQuotaService.js
|
|
19262
|
+
var require_multiProviderQuotaService = __commonJS({
|
|
19263
|
+
"../sidekick-shared/dist/multiProviderQuotaService.js"(exports) {
|
|
19264
|
+
"use strict";
|
|
19265
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19266
|
+
exports.MultiProviderQuotaService = void 0;
|
|
19267
|
+
var accounts_1 = require_accounts();
|
|
19268
|
+
var codexQuotaWatcher_1 = require_codexQuotaWatcher();
|
|
19269
|
+
var credentials_1 = require_credentials();
|
|
19270
|
+
var peakHours_1 = require_peakHours();
|
|
19271
|
+
var quota_1 = require_quota();
|
|
19272
|
+
var quotaPresentation_1 = require_quotaPresentation();
|
|
19273
|
+
var ACTIVE_POLL_INTERVAL_MS = 6e4;
|
|
19274
|
+
var IDLE_POLL_INTERVAL_MS = 3e5;
|
|
19275
|
+
var TRANSIENT_FAILURE_BACKOFF_MS = [3e4, 6e4, 12e4, 24e4, 3e5];
|
|
19276
|
+
var PEAK_HOURS_CACHE_MAX_AGE_MS = 10 * 60 * 1e3;
|
|
19277
|
+
function makeUnavailableClaudeState(error, failureKind) {
|
|
19278
|
+
return {
|
|
19279
|
+
runtimeProvider: "claude",
|
|
19280
|
+
fiveHour: { utilization: 0, resetsAt: "" },
|
|
19281
|
+
sevenDay: { utilization: 0, resetsAt: "" },
|
|
19282
|
+
available: false,
|
|
19283
|
+
error,
|
|
19284
|
+
failureKind,
|
|
19285
|
+
providerId: "claude-code",
|
|
19286
|
+
source: "api"
|
|
19287
|
+
};
|
|
19288
|
+
}
|
|
19289
|
+
function formatDelay(ms) {
|
|
19290
|
+
if (ms % 6e4 === 0)
|
|
19291
|
+
return `${ms / 6e4}m`;
|
|
19292
|
+
if (ms % 1e3 === 0)
|
|
19293
|
+
return `${ms / 1e3}s`;
|
|
19294
|
+
return `${ms}ms`;
|
|
19295
|
+
}
|
|
19296
|
+
function unavailablePeakHoursState() {
|
|
19297
|
+
return {
|
|
19298
|
+
status: "unknown",
|
|
19299
|
+
isPeak: false,
|
|
19300
|
+
sessionLimitSpeed: "unknown",
|
|
19301
|
+
label: "Peak hours unavailable",
|
|
19302
|
+
peakHoursDescription: "",
|
|
19303
|
+
nextChange: null,
|
|
19304
|
+
minutesUntilChange: null,
|
|
19305
|
+
note: "",
|
|
19306
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
19307
|
+
unavailable: true
|
|
19308
|
+
};
|
|
19309
|
+
}
|
|
19310
|
+
var MultiProviderQuotaService = class {
|
|
19311
|
+
activeIntervalMs;
|
|
19312
|
+
idleIntervalMs;
|
|
19313
|
+
transientFailureBackoffMs;
|
|
19314
|
+
peakHoursCacheMaxAgeMs;
|
|
19315
|
+
includePeakHours;
|
|
19316
|
+
readClaudeCredentials;
|
|
19317
|
+
readClaudeAccount;
|
|
19318
|
+
fetchClaudeQuota;
|
|
19319
|
+
fetchPeakHours;
|
|
19320
|
+
log;
|
|
19321
|
+
listeners = [];
|
|
19322
|
+
codexWatcher;
|
|
19323
|
+
ownsCodexWatcher;
|
|
19324
|
+
codexSubscription = null;
|
|
19325
|
+
timer;
|
|
19326
|
+
polling = false;
|
|
19327
|
+
quotaByProvider = {};
|
|
19328
|
+
lastEmittedClaudeState = null;
|
|
19329
|
+
lastSuccessfulClaudeState = null;
|
|
19330
|
+
pollingMode = "idle";
|
|
19331
|
+
transientFailureStreak = 0;
|
|
19332
|
+
cachedFallbackActive = false;
|
|
19333
|
+
authUnavailableActive = false;
|
|
19334
|
+
currentPeakHours;
|
|
19335
|
+
lastFreshPeakHoursAt = 0;
|
|
19336
|
+
peakHoursErrorLogged = false;
|
|
19337
|
+
constructor(options = {}) {
|
|
19338
|
+
this.activeIntervalMs = options.activeIntervalMs ?? ACTIVE_POLL_INTERVAL_MS;
|
|
19339
|
+
this.idleIntervalMs = options.idleIntervalMs ?? IDLE_POLL_INTERVAL_MS;
|
|
19340
|
+
this.transientFailureBackoffMs = options.transientFailureBackoffMs ?? TRANSIENT_FAILURE_BACKOFF_MS;
|
|
19341
|
+
this.peakHoursCacheMaxAgeMs = options.peakHoursCacheMaxAgeMs ?? PEAK_HOURS_CACHE_MAX_AGE_MS;
|
|
19342
|
+
this.includePeakHours = options.includePeakHours ?? true;
|
|
19343
|
+
this.readClaudeCredentials = options.readClaudeCredentials ?? credentials_1.readClaudeMaxCredentials;
|
|
19344
|
+
this.readClaudeAccount = options.readClaudeAccount ?? accounts_1.readActiveClaudeAccount;
|
|
19345
|
+
this.fetchClaudeQuota = options.fetchClaudeQuota ?? quota_1.fetchQuota;
|
|
19346
|
+
this.fetchPeakHours = options.fetchPeakHours ?? peakHours_1.fetchPeakHoursStatus;
|
|
19347
|
+
this.log = options.log;
|
|
19348
|
+
if (options.codexWatcher !== void 0) {
|
|
19349
|
+
this.codexWatcher = options.codexWatcher;
|
|
19350
|
+
this.ownsCodexWatcher = false;
|
|
19351
|
+
} else if (options.codexWorkspacePath) {
|
|
19352
|
+
this.codexWatcher = new codexQuotaWatcher_1.CodexQuotaWatcher(options.codexWorkspacePath);
|
|
19353
|
+
this.ownsCodexWatcher = true;
|
|
19354
|
+
} else {
|
|
19355
|
+
this.codexWatcher = null;
|
|
19356
|
+
this.ownsCodexWatcher = false;
|
|
19357
|
+
}
|
|
19358
|
+
this.codexSubscription = this.codexWatcher?.onUpdate((state) => {
|
|
19359
|
+
this.updateProviderQuota("codex", state);
|
|
19360
|
+
}) ?? null;
|
|
19361
|
+
}
|
|
19362
|
+
startPolling() {
|
|
19363
|
+
if (this.polling)
|
|
19364
|
+
return;
|
|
19365
|
+
this.polling = true;
|
|
19366
|
+
this.codexWatcher?.start();
|
|
19367
|
+
void this.poll();
|
|
19368
|
+
this.log?.("[Quota] Polling started");
|
|
19369
|
+
}
|
|
19370
|
+
stopPolling() {
|
|
19371
|
+
if (!this.polling)
|
|
19372
|
+
return;
|
|
19373
|
+
this.polling = false;
|
|
19374
|
+
if (this.timer) {
|
|
19375
|
+
clearTimeout(this.timer);
|
|
19376
|
+
this.timer = void 0;
|
|
19377
|
+
}
|
|
19378
|
+
this.codexWatcher?.stop();
|
|
19379
|
+
this.log?.("[Quota] Polling stopped");
|
|
19380
|
+
}
|
|
19381
|
+
setPollingMode(mode) {
|
|
19382
|
+
if (this.pollingMode === mode)
|
|
19383
|
+
return;
|
|
19384
|
+
this.pollingMode = mode;
|
|
19385
|
+
if (!this.polling)
|
|
19386
|
+
return;
|
|
19387
|
+
if (this.transientFailureStreak > 0 && this.timer)
|
|
19388
|
+
return;
|
|
19389
|
+
if (this.timer) {
|
|
19390
|
+
clearTimeout(this.timer);
|
|
19391
|
+
this.timer = void 0;
|
|
19392
|
+
}
|
|
19393
|
+
this.scheduleNextPoll();
|
|
19394
|
+
}
|
|
19395
|
+
onUpdate(cb) {
|
|
19396
|
+
this.listeners.push(cb);
|
|
19397
|
+
return {
|
|
19398
|
+
dispose: () => {
|
|
19399
|
+
const index = this.listeners.indexOf(cb);
|
|
19400
|
+
if (index >= 0)
|
|
19401
|
+
this.listeners.splice(index, 1);
|
|
19402
|
+
}
|
|
19403
|
+
};
|
|
19404
|
+
}
|
|
19405
|
+
onQuotaUpdate(cb) {
|
|
19406
|
+
return this.onUpdate(cb);
|
|
19407
|
+
}
|
|
19408
|
+
getLatest() {
|
|
19409
|
+
return { ...this.quotaByProvider };
|
|
19410
|
+
}
|
|
19411
|
+
updateProviderQuota(provider, state) {
|
|
19412
|
+
if (provider === "claude") {
|
|
19413
|
+
const nextState2 = this.withClaudeAccountDetails({
|
|
19414
|
+
...state,
|
|
19415
|
+
runtimeProvider: "claude",
|
|
19416
|
+
providerId: "claude-code"
|
|
19417
|
+
});
|
|
19418
|
+
this.lastEmittedClaudeState = nextState2;
|
|
19419
|
+
if (nextState2.available) {
|
|
19420
|
+
this.lastSuccessfulClaudeState = nextState2;
|
|
19421
|
+
}
|
|
19422
|
+
this.quotaByProvider = {
|
|
19423
|
+
...this.quotaByProvider,
|
|
19424
|
+
claude: nextState2
|
|
19425
|
+
};
|
|
19426
|
+
this.emit();
|
|
19427
|
+
return;
|
|
19428
|
+
}
|
|
19429
|
+
const nextState = {
|
|
19430
|
+
...state,
|
|
19431
|
+
runtimeProvider: "codex",
|
|
19432
|
+
providerId: "codex"
|
|
19433
|
+
};
|
|
19434
|
+
this.quotaByProvider = {
|
|
19435
|
+
...this.quotaByProvider,
|
|
19436
|
+
codex: nextState
|
|
19437
|
+
};
|
|
19438
|
+
this.emit();
|
|
19439
|
+
}
|
|
19440
|
+
dispose() {
|
|
19441
|
+
this.stopPolling();
|
|
19442
|
+
this.codexSubscription?.dispose();
|
|
19443
|
+
this.codexSubscription = null;
|
|
19444
|
+
if (this.ownsCodexWatcher) {
|
|
19445
|
+
this.codexWatcher?.dispose();
|
|
19446
|
+
}
|
|
19447
|
+
this.listeners.splice(0, this.listeners.length);
|
|
19448
|
+
}
|
|
19449
|
+
async refreshPeakHours() {
|
|
19450
|
+
if (!this.includePeakHours)
|
|
19451
|
+
return;
|
|
19452
|
+
let result;
|
|
19453
|
+
try {
|
|
19454
|
+
result = await this.fetchPeakHours();
|
|
19455
|
+
} catch (error) {
|
|
19456
|
+
if (!this.peakHoursErrorLogged) {
|
|
19457
|
+
this.log?.("[Quota] Peak-hours fetch threw unexpectedly", error);
|
|
19458
|
+
this.peakHoursErrorLogged = true;
|
|
19459
|
+
}
|
|
19460
|
+
result = unavailablePeakHoursState();
|
|
19461
|
+
}
|
|
19462
|
+
if (!result.unavailable) {
|
|
19463
|
+
this.currentPeakHours = result;
|
|
19464
|
+
this.lastFreshPeakHoursAt = Date.now();
|
|
19465
|
+
this.peakHoursErrorLogged = false;
|
|
19466
|
+
return;
|
|
19467
|
+
}
|
|
19468
|
+
const cachedIsFresh = this.currentPeakHours !== void 0 && !this.currentPeakHours.unavailable && Date.now() - this.lastFreshPeakHoursAt < this.peakHoursCacheMaxAgeMs;
|
|
19469
|
+
if (cachedIsFresh)
|
|
19470
|
+
return;
|
|
19471
|
+
this.currentPeakHours = result;
|
|
19472
|
+
}
|
|
19473
|
+
async poll() {
|
|
19474
|
+
await this.refreshPeakHours();
|
|
19475
|
+
try {
|
|
19476
|
+
const creds = await this.readClaudeCredentials();
|
|
19477
|
+
if (!creds) {
|
|
19478
|
+
this.handleUnavailableState(makeUnavailableClaudeState("Renew your Claude Max OAuth to view quota", "auth"));
|
|
19479
|
+
return;
|
|
19480
|
+
}
|
|
19481
|
+
const state = await this.fetchClaudeQuota(creds.accessToken);
|
|
19482
|
+
if (!state.available) {
|
|
19483
|
+
this.handleUnavailableState({
|
|
19484
|
+
...state,
|
|
19485
|
+
runtimeProvider: "claude",
|
|
19486
|
+
providerId: "claude-code",
|
|
19487
|
+
source: state.source ?? "api"
|
|
19488
|
+
});
|
|
19489
|
+
return;
|
|
19490
|
+
}
|
|
19491
|
+
const recoveredAttempts = this.transientFailureStreak;
|
|
19492
|
+
const recoveredFromFallback = recoveredAttempts > 0;
|
|
19493
|
+
this.resetTransientFailureState();
|
|
19494
|
+
this.authUnavailableActive = false;
|
|
19495
|
+
if (recoveredFromFallback) {
|
|
19496
|
+
this.log?.(`[Quota] Fetch recovered after ${recoveredAttempts} failed attempt(s)`);
|
|
19497
|
+
}
|
|
19498
|
+
this.emitClaudeState({
|
|
19499
|
+
...state,
|
|
19500
|
+
runtimeProvider: "claude",
|
|
19501
|
+
providerId: "claude-code",
|
|
19502
|
+
source: state.source ?? "api"
|
|
19503
|
+
});
|
|
19504
|
+
} catch (error) {
|
|
19505
|
+
if (this.transientFailureStreak === 0) {
|
|
19506
|
+
this.log?.("[Quota] Poll error", error);
|
|
19507
|
+
}
|
|
19508
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
19509
|
+
this.handleTransientFailure(makeUnavailableClaudeState(message));
|
|
19510
|
+
} finally {
|
|
19511
|
+
this.scheduleNextPoll();
|
|
19512
|
+
}
|
|
19513
|
+
}
|
|
19514
|
+
emitClaudeState(state) {
|
|
19515
|
+
const withPeakHours = this.currentPeakHours !== void 0 ? { ...state, peakHours: this.currentPeakHours } : state;
|
|
19516
|
+
const withFailure = {
|
|
19517
|
+
...withPeakHours,
|
|
19518
|
+
failure: (0, quotaPresentation_1.describeQuotaFailure)(withPeakHours)
|
|
19519
|
+
};
|
|
19520
|
+
this.updateProviderQuota("claude", withFailure);
|
|
19521
|
+
}
|
|
19522
|
+
handleUnavailableState(state) {
|
|
19523
|
+
if (state.failureKind === "auth") {
|
|
19524
|
+
this.resetTransientFailureState();
|
|
19525
|
+
this.authUnavailableActive = true;
|
|
19526
|
+
this.emitClaudeState(state);
|
|
19527
|
+
return;
|
|
19528
|
+
}
|
|
19529
|
+
this.handleTransientFailure(state);
|
|
19530
|
+
}
|
|
19531
|
+
handleTransientFailure(state) {
|
|
19532
|
+
this.authUnavailableActive = false;
|
|
19533
|
+
this.transientFailureStreak += 1;
|
|
19534
|
+
const retryDelay = this.getTransientFailureDelay();
|
|
19535
|
+
const hasVisibleCachedSuccess = this.lastSuccessfulClaudeState !== null && this.lastEmittedClaudeState?.available === true;
|
|
19536
|
+
if (this.transientFailureStreak === 1) {
|
|
19537
|
+
if (hasVisibleCachedSuccess) {
|
|
19538
|
+
this.log?.(`[Quota] Fetch failed, using cached data; retrying in ${formatDelay(retryDelay)}`);
|
|
19539
|
+
} else {
|
|
19540
|
+
this.log?.(`[Quota] Fetch unavailable; retrying in ${formatDelay(retryDelay)}`);
|
|
19541
|
+
}
|
|
19542
|
+
}
|
|
19543
|
+
this.cachedFallbackActive = hasVisibleCachedSuccess;
|
|
19544
|
+
if (!hasVisibleCachedSuccess) {
|
|
19545
|
+
this.emitClaudeState(state);
|
|
19546
|
+
}
|
|
19547
|
+
}
|
|
19548
|
+
getTransientFailureDelay() {
|
|
19549
|
+
return this.transientFailureBackoffMs[Math.min(this.transientFailureStreak - 1, this.transientFailureBackoffMs.length - 1)];
|
|
19550
|
+
}
|
|
19551
|
+
resetTransientFailureState() {
|
|
19552
|
+
this.transientFailureStreak = 0;
|
|
19553
|
+
this.cachedFallbackActive = false;
|
|
19554
|
+
}
|
|
19555
|
+
scheduleNextPoll() {
|
|
19556
|
+
if (!this.polling)
|
|
19557
|
+
return;
|
|
19558
|
+
if (this.timer) {
|
|
19559
|
+
clearTimeout(this.timer);
|
|
19560
|
+
}
|
|
19561
|
+
let delay = this.pollingMode === "active" ? this.activeIntervalMs : this.idleIntervalMs;
|
|
19562
|
+
if (this.transientFailureStreak > 0) {
|
|
19563
|
+
delay = this.getTransientFailureDelay();
|
|
19564
|
+
} else if (this.authUnavailableActive || this.lastEmittedClaudeState?.available !== true) {
|
|
19565
|
+
delay = this.idleIntervalMs;
|
|
19566
|
+
} else if (this.cachedFallbackActive) {
|
|
19567
|
+
delay = this.idleIntervalMs;
|
|
19568
|
+
}
|
|
19569
|
+
this.timer = setTimeout(() => void this.poll(), delay);
|
|
19570
|
+
}
|
|
19571
|
+
withClaudeAccountDetails(state) {
|
|
19572
|
+
const accountEmail = this.readClaudeAccount()?.email;
|
|
19573
|
+
if (!accountEmail) {
|
|
19574
|
+
const nextState = { ...state };
|
|
19575
|
+
delete nextState.accountLabel;
|
|
19576
|
+
delete nextState.accountDetail;
|
|
19577
|
+
return nextState;
|
|
19578
|
+
}
|
|
19579
|
+
return {
|
|
19580
|
+
...state,
|
|
19581
|
+
accountLabel: accountEmail,
|
|
19582
|
+
accountDetail: accountEmail
|
|
19583
|
+
};
|
|
19584
|
+
}
|
|
19585
|
+
emit() {
|
|
19586
|
+
const snapshot = { ...this.quotaByProvider };
|
|
19587
|
+
for (const listener of this.listeners) {
|
|
19588
|
+
try {
|
|
19589
|
+
listener(snapshot);
|
|
19590
|
+
} catch {
|
|
19591
|
+
}
|
|
19592
|
+
}
|
|
19593
|
+
}
|
|
19594
|
+
};
|
|
19595
|
+
exports.MultiProviderQuotaService = MultiProviderQuotaService;
|
|
19596
|
+
}
|
|
19597
|
+
});
|
|
19598
|
+
|
|
18593
19599
|
// ../sidekick-shared/dist/pricingCatalog.js
|
|
18594
19600
|
var require_pricingCatalog = __commonJS({
|
|
18595
19601
|
"../sidekick-shared/dist/pricingCatalog.js"(exports) {
|
|
@@ -18793,6 +19799,7 @@ var require_toolCall = __commonJS({
|
|
|
18793
19799
|
"use strict";
|
|
18794
19800
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18795
19801
|
exports.extractToolCalls = extractToolCalls;
|
|
19802
|
+
exports.extractToolCall = extractToolCall;
|
|
18796
19803
|
function extractToolCalls(event) {
|
|
18797
19804
|
if (event.type !== "assistant")
|
|
18798
19805
|
return [];
|
|
@@ -18816,6 +19823,15 @@ var require_toolCall = __commonJS({
|
|
|
18816
19823
|
}
|
|
18817
19824
|
return calls;
|
|
18818
19825
|
}
|
|
19826
|
+
function extractToolCall(event) {
|
|
19827
|
+
if (event.type !== "tool_use" || !event.tool?.name)
|
|
19828
|
+
return null;
|
|
19829
|
+
return {
|
|
19830
|
+
name: event.tool.name,
|
|
19831
|
+
input: event.tool.input ?? {},
|
|
19832
|
+
timestamp: new Date(event.timestamp)
|
|
19833
|
+
};
|
|
19834
|
+
}
|
|
18819
19835
|
}
|
|
18820
19836
|
});
|
|
18821
19837
|
|
|
@@ -34938,74 +35954,15 @@ var require_providerStatus = __commonJS({
|
|
|
34938
35954
|
}
|
|
34939
35955
|
});
|
|
34940
35956
|
|
|
34941
|
-
// ../sidekick-shared/dist/peakHours.js
|
|
34942
|
-
var require_peakHours = __commonJS({
|
|
34943
|
-
"../sidekick-shared/dist/peakHours.js"(exports) {
|
|
34944
|
-
"use strict";
|
|
34945
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
34946
|
-
exports.fetchPeakHoursStatus = fetchPeakHoursStatus4;
|
|
34947
|
-
var PROMOCLOCK_ENDPOINT = "https://promoclock.co/api/status";
|
|
34948
|
-
function unavailableState() {
|
|
34949
|
-
return {
|
|
34950
|
-
status: "unknown",
|
|
34951
|
-
isPeak: false,
|
|
34952
|
-
sessionLimitSpeed: "unknown",
|
|
34953
|
-
label: "Peak-hours status unavailable",
|
|
34954
|
-
peakHoursDescription: "",
|
|
34955
|
-
nextChange: null,
|
|
34956
|
-
minutesUntilChange: null,
|
|
34957
|
-
note: "",
|
|
34958
|
-
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34959
|
-
unavailable: true
|
|
34960
|
-
};
|
|
34961
|
-
}
|
|
34962
|
-
function normalizeStatus(raw) {
|
|
34963
|
-
if (raw === "peak" || raw === "off_peak")
|
|
34964
|
-
return raw;
|
|
34965
|
-
return "unknown";
|
|
34966
|
-
}
|
|
34967
|
-
function normalizeSpeed(raw) {
|
|
34968
|
-
if (raw === "normal" || raw === "faster")
|
|
34969
|
-
return raw;
|
|
34970
|
-
return "unknown";
|
|
34971
|
-
}
|
|
34972
|
-
async function fetchPeakHoursStatus4() {
|
|
34973
|
-
try {
|
|
34974
|
-
const res = await fetch(PROMOCLOCK_ENDPOINT);
|
|
34975
|
-
if (!res.ok)
|
|
34976
|
-
return unavailableState();
|
|
34977
|
-
const data = await res.json();
|
|
34978
|
-
const status = normalizeStatus(data.status);
|
|
34979
|
-
const sessionLimitSpeed = normalizeSpeed(data.sessionLimitSpeed);
|
|
34980
|
-
const isPeak = typeof data.isPeak === "boolean" ? data.isPeak : status === "peak";
|
|
34981
|
-
return {
|
|
34982
|
-
status,
|
|
34983
|
-
isPeak,
|
|
34984
|
-
sessionLimitSpeed,
|
|
34985
|
-
label: data.label ?? (isPeak ? "Peak Hours" : "Off-Peak"),
|
|
34986
|
-
peakHoursDescription: data.peakHours ?? "",
|
|
34987
|
-
nextChange: data.nextChange ?? null,
|
|
34988
|
-
minutesUntilChange: typeof data.minutesUntilChange === "number" ? data.minutesUntilChange : null,
|
|
34989
|
-
note: data.note ?? "",
|
|
34990
|
-
updatedAt: data.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
34991
|
-
unavailable: false
|
|
34992
|
-
};
|
|
34993
|
-
} catch {
|
|
34994
|
-
return unavailableState();
|
|
34995
|
-
}
|
|
34996
|
-
}
|
|
34997
|
-
}
|
|
34998
|
-
});
|
|
34999
|
-
|
|
35000
35957
|
// ../sidekick-shared/dist/index.js
|
|
35001
35958
|
var require_dist = __commonJS({
|
|
35002
35959
|
"../sidekick-shared/dist/index.js"(exports) {
|
|
35003
35960
|
"use strict";
|
|
35004
35961
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35005
35962
|
exports.findActiveClaudeSession = exports.discoverSessionDirectory = exports.getClaudeSessionDirectory = exports.encodeClaudeWorkspacePath = exports.detectSessionActivity = exports.extractTaskInfo = exports.scanSubagentDir = exports.normalizeCodexToolInput = exports.normalizeCodexToolName = exports.extractPatchFilePaths = exports.CodexRolloutParser = exports.parseDbPartData = exports.parseDbMessageData = exports.convertOpenCodeMessage = exports.detectPlanModeFromText = exports.normalizeToolInput = exports.normalizeToolName = exports.TRUNCATION_PATTERNS = exports.JsonlParser = exports.CodexProvider = exports.OpenCodeProvider = exports.ClaudeCodeProvider = exports.getAllDetectedProviders = exports.detectProvider = exports.readClaudeCodePlanFiles = exports.getPlanAnalytics = exports.writePlans = exports.getLatestPlan = exports.readPlans = exports.readLatestHandoff = exports.readHistory = exports.readNotes = exports.readDecisions = exports.readTasks = exports.getProjectSlugRaw = exports.getProjectSlug = exports.encodeWorkspacePath = exports.getGlobalDataPath = exports.getProjectDataPath = exports.getConfigDir = exports.MAX_PLANS_PER_PROJECT = exports.PLAN_SCHEMA_VERSION = exports.createEmptyTokenTotals = exports.HISTORICAL_DATA_SCHEMA_VERSION = exports.STALENESS_THRESHOLDS = exports.IMPORTANCE_DECAY_FACTORS = exports.KNOWLEDGE_NOTE_SCHEMA_VERSION = exports.DECISION_LOG_SCHEMA_VERSION = exports.normalizeTaskStatus = exports.TASK_PERSISTENCE_SCHEMA_VERSION = void 0;
|
|
35006
|
-
exports.
|
|
35007
|
-
exports.
|
|
35008
|
-
exports.fetchPeakHoursStatus = exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractTokenUsage = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.formatCost = exports.calculateCostWithPricing = exports.calculateCost = void 0;
|
|
35963
|
+
exports.deleteSnapshot = exports.loadSnapshot = exports.saveSnapshot = exports.parseTodoDependencies = exports.EventAggregator = exports.getRandomPhrase = exports.PHRASE_CATEGORIES = exports.ALL_PHRASES = exports.HIGHLIGHT_CSS = exports.clearHighlightCache = exports.highlightEvent = exports.formatSessionJson = exports.formatSessionMarkdown = exports.formatSessionText = exports.classifyNoise = exports.shouldMergeWithPrevious = exports.classifyFollowEvent = exports.classifyMessage = exports.getSoftNoiseReason = exports.isHardNoiseFollowEvent = exports.isHardNoise = exports.formatToolSummary = exports.formatTokenCount = exports.formatDurationMs = exports.createJsonlTail = exports.toFollowEvents = exports.createWatcher = exports.parseChangelog = exports.extractProposedPlanShared = exports.parsePlanMarkdownShared = exports.PlanExtractor = exports.composeContext = exports.FilterEngine = exports.searchSessions = exports.CodexDatabase = exports.OpenCodeDatabase = exports.discoverDebugLogs = exports.collapseDuplicates = exports.filterByLevel = exports.parseDebugLog = exports.scanSubagentTraces = exports.findAllSessionsWithWorktrees = exports.discoverWorktreeSiblings = exports.resolveWorktreeMainRepo = exports.getAllClaudeProjectFolders = exports.decodeEncodedPath = exports.getMostRecentlyActiveSessionDir = exports.findSubdirectorySessionDirs = exports.findSessionsInDirectory = exports.findAllClaudeSessions = void 0;
|
|
35964
|
+
exports.quotaFromCodexRateLimits = exports.writeQuotaSnapshot = exports.readQuotaSnapshot = exports.QuotaPoller = exports.describeQuotaFailure = exports.fetchQuota = exports.removeCodexAccount = exports.switchToCodexAccount = exports.finalizeCodexAccount = exports.prepareCodexAccount = exports.getCodexExecutionEnv = exports.resolveSidekickCodexHome = exports.getActiveCodexAccount = exports.listCodexAccounts = exports.getSystemCodexHome = exports.getCodexMonitoringHomes = exports.getCodexProfileHome = exports.getCodexProfilesDir = exports.getActiveAccountStatus = exports.removeSavedAccountProfile = exports.replaceSavedAccountProfiles = exports.setActiveSavedAccount = exports.upsertSavedAccountProfile = exports.getActiveSavedAccount = exports.listSavedAccountProfiles = exports.writeSavedAccountRegistry = exports.readSavedAccountRegistry = exports.getAccountsDir = exports.isMultiAccountEnabled = exports.getActiveAccount = exports.listAccounts = exports.removeAccount = exports.switchToAccount = exports.addCurrentAccount = exports.readActiveClaudeAccount = exports.writeAccountRegistry = exports.readAccountRegistry = exports.ensureDefaultAccounts = exports.readClaudeMaxAccessTokenSync = exports.readClaudeMaxCredentials = exports.writeActiveCredentials = exports.readActiveCredentials = exports.openInBrowser = exports.parseTranscript = exports.generateHtmlReport = exports.PatternExtractor = exports.HeatmapTracker = exports.FrequencyTracker = exports.getSnapshotPath = exports.isSnapshotValid = void 0;
|
|
35965
|
+
exports.fetchPeakHoursStatus = exports.fetchOpenAIStatus = exports.fetchProviderStatus = exports.permissionModeSchema = exports.sessionEventSchema = exports.sessionMessageSchema = exports.messageUsageSchema = exports.extractToolCalls = exports.extractToolCall = exports.extractTokenUsage = exports.LITELLM_CATALOG_URL = exports.normalizeLiteLlmCatalog = exports.hydratePricingCatalog = exports.formatCost = exports.sortModelIds = exports.compareModelIds = exports.getModelDisplayInfo = exports.shortModelName = exports.mergeCostSources = exports.calculateCostWithProvenance = exports.calculateCostWithPricing = exports.calculateCost = exports.getModelInfo = exports.getModelPricing = exports.parseModelId = exports.DEFAULT_CONTEXT_WINDOW = exports.getModelContextWindowSize = exports.MultiProviderQuotaService = exports.CodexQuotaWatcher = void 0;
|
|
35009
35966
|
var taskPersistence_1 = require_taskPersistence();
|
|
35010
35967
|
Object.defineProperty(exports, "TASK_PERSISTENCE_SCHEMA_VERSION", { enumerable: true, get: function() {
|
|
35011
35968
|
return taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION;
|
|
@@ -35264,6 +36221,17 @@ var require_dist = __commonJS({
|
|
|
35264
36221
|
Object.defineProperty(exports, "toFollowEvents", { enumerable: true, get: function() {
|
|
35265
36222
|
return eventBridge_1.toFollowEvents;
|
|
35266
36223
|
} });
|
|
36224
|
+
var jsonlTail_1 = require_jsonlTail();
|
|
36225
|
+
Object.defineProperty(exports, "createJsonlTail", { enumerable: true, get: function() {
|
|
36226
|
+
return jsonlTail_1.createJsonlTail;
|
|
36227
|
+
} });
|
|
36228
|
+
var formatting_1 = require_formatting();
|
|
36229
|
+
Object.defineProperty(exports, "formatDurationMs", { enumerable: true, get: function() {
|
|
36230
|
+
return formatting_1.formatDurationMs;
|
|
36231
|
+
} });
|
|
36232
|
+
Object.defineProperty(exports, "formatTokenCount", { enumerable: true, get: function() {
|
|
36233
|
+
return formatting_1.formatTokenCount;
|
|
36234
|
+
} });
|
|
35267
36235
|
var toolSummary_1 = require_toolSummary();
|
|
35268
36236
|
Object.defineProperty(exports, "formatToolSummary", { enumerable: true, get: function() {
|
|
35269
36237
|
return toolSummary_1.formatToolSummary;
|
|
@@ -35314,6 +36282,9 @@ var require_dist = __commonJS({
|
|
|
35314
36282
|
Object.defineProperty(exports, "ALL_PHRASES", { enumerable: true, get: function() {
|
|
35315
36283
|
return phrases_1.ALL_PHRASES;
|
|
35316
36284
|
} });
|
|
36285
|
+
Object.defineProperty(exports, "PHRASE_CATEGORIES", { enumerable: true, get: function() {
|
|
36286
|
+
return phrases_1.PHRASE_CATEGORIES;
|
|
36287
|
+
} });
|
|
35317
36288
|
Object.defineProperty(exports, "getRandomPhrase", { enumerable: true, get: function() {
|
|
35318
36289
|
return phrases_1.getRandomPhrase;
|
|
35319
36290
|
} });
|
|
@@ -35436,6 +36407,10 @@ var require_dist = __commonJS({
|
|
|
35436
36407
|
Object.defineProperty(exports, "removeSavedAccountProfile", { enumerable: true, get: function() {
|
|
35437
36408
|
return accountRegistry_1.removeSavedAccountProfile;
|
|
35438
36409
|
} });
|
|
36410
|
+
var accountStatus_1 = require_accountStatus();
|
|
36411
|
+
Object.defineProperty(exports, "getActiveAccountStatus", { enumerable: true, get: function() {
|
|
36412
|
+
return accountStatus_1.getActiveAccountStatus;
|
|
36413
|
+
} });
|
|
35439
36414
|
var codexProfiles_1 = require_codexProfiles();
|
|
35440
36415
|
Object.defineProperty(exports, "getCodexProfilesDir", { enumerable: true, get: function() {
|
|
35441
36416
|
return codexProfiles_1.getCodexProfilesDir;
|
|
@@ -35496,6 +36471,14 @@ var require_dist = __commonJS({
|
|
|
35496
36471
|
Object.defineProperty(exports, "quotaFromCodexRateLimits", { enumerable: true, get: function() {
|
|
35497
36472
|
return codexQuota_1.quotaFromCodexRateLimits;
|
|
35498
36473
|
} });
|
|
36474
|
+
var codexQuotaWatcher_1 = require_codexQuotaWatcher();
|
|
36475
|
+
Object.defineProperty(exports, "CodexQuotaWatcher", { enumerable: true, get: function() {
|
|
36476
|
+
return codexQuotaWatcher_1.CodexQuotaWatcher;
|
|
36477
|
+
} });
|
|
36478
|
+
var multiProviderQuotaService_1 = require_multiProviderQuotaService();
|
|
36479
|
+
Object.defineProperty(exports, "MultiProviderQuotaService", { enumerable: true, get: function() {
|
|
36480
|
+
return multiProviderQuotaService_1.MultiProviderQuotaService;
|
|
36481
|
+
} });
|
|
35499
36482
|
var modelContext_1 = require_modelContext();
|
|
35500
36483
|
Object.defineProperty(exports, "getModelContextWindowSize", { enumerable: true, get: function() {
|
|
35501
36484
|
return modelContext_1.getModelContextWindowSize;
|
|
@@ -35519,6 +36502,24 @@ var require_dist = __commonJS({
|
|
|
35519
36502
|
Object.defineProperty(exports, "calculateCostWithPricing", { enumerable: true, get: function() {
|
|
35520
36503
|
return modelInfo_1.calculateCostWithPricing;
|
|
35521
36504
|
} });
|
|
36505
|
+
Object.defineProperty(exports, "calculateCostWithProvenance", { enumerable: true, get: function() {
|
|
36506
|
+
return modelInfo_1.calculateCostWithProvenance;
|
|
36507
|
+
} });
|
|
36508
|
+
Object.defineProperty(exports, "mergeCostSources", { enumerable: true, get: function() {
|
|
36509
|
+
return modelInfo_1.mergeCostSources;
|
|
36510
|
+
} });
|
|
36511
|
+
Object.defineProperty(exports, "shortModelName", { enumerable: true, get: function() {
|
|
36512
|
+
return modelInfo_1.shortModelName;
|
|
36513
|
+
} });
|
|
36514
|
+
Object.defineProperty(exports, "getModelDisplayInfo", { enumerable: true, get: function() {
|
|
36515
|
+
return modelInfo_1.getModelDisplayInfo;
|
|
36516
|
+
} });
|
|
36517
|
+
Object.defineProperty(exports, "compareModelIds", { enumerable: true, get: function() {
|
|
36518
|
+
return modelInfo_1.compareModelIds;
|
|
36519
|
+
} });
|
|
36520
|
+
Object.defineProperty(exports, "sortModelIds", { enumerable: true, get: function() {
|
|
36521
|
+
return modelInfo_1.sortModelIds;
|
|
36522
|
+
} });
|
|
35522
36523
|
Object.defineProperty(exports, "formatCost", { enumerable: true, get: function() {
|
|
35523
36524
|
return modelInfo_1.formatCost;
|
|
35524
36525
|
} });
|
|
@@ -35537,6 +36538,9 @@ var require_dist = __commonJS({
|
|
|
35537
36538
|
return tokenUsage_1.extractTokenUsage;
|
|
35538
36539
|
} });
|
|
35539
36540
|
var toolCall_1 = require_toolCall();
|
|
36541
|
+
Object.defineProperty(exports, "extractToolCall", { enumerable: true, get: function() {
|
|
36542
|
+
return toolCall_1.extractToolCall;
|
|
36543
|
+
} });
|
|
35540
36544
|
Object.defineProperty(exports, "extractToolCalls", { enumerable: true, get: function() {
|
|
35541
36545
|
return toolCall_1.extractToolCalls;
|
|
35542
36546
|
} });
|
|
@@ -37799,7 +38803,7 @@ var init_UpdateCheckService = __esm({
|
|
|
37799
38803
|
/** Run the update check (one-shot). */
|
|
37800
38804
|
async check() {
|
|
37801
38805
|
try {
|
|
37802
|
-
const current = "0.
|
|
38806
|
+
const current = "0.18.1";
|
|
37803
38807
|
const cached = this.readCache();
|
|
37804
38808
|
let latest;
|
|
37805
38809
|
if (cached && Date.now() - cached.checkedAt < CACHE_TTL_MS) {
|
|
@@ -37864,17 +38868,14 @@ function shortenPath(p) {
|
|
|
37864
38868
|
return ".../" + parts.slice(-3).join("/");
|
|
37865
38869
|
}
|
|
37866
38870
|
function fmtNum(n) {
|
|
37867
|
-
|
|
37868
|
-
if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
|
|
37869
|
-
return n.toLocaleString();
|
|
38871
|
+
return (0, import_sidekick_shared9.formatTokenCount)(n, { suffixCase: "upper" });
|
|
37870
38872
|
}
|
|
37871
38873
|
function formatDuration(ms) {
|
|
37872
|
-
|
|
37873
|
-
|
|
37874
|
-
|
|
37875
|
-
|
|
37876
|
-
|
|
37877
|
-
return `${mins}m${remSecs}s`;
|
|
38874
|
+
return (0, import_sidekick_shared9.formatDurationMs)(ms, {
|
|
38875
|
+
style: "compact",
|
|
38876
|
+
includeMilliseconds: true,
|
|
38877
|
+
secondsFractionDigits: 1
|
|
38878
|
+
});
|
|
37878
38879
|
}
|
|
37879
38880
|
function stripBlessedTags(text) {
|
|
37880
38881
|
return text.replace(/\{[^}]*\}/g, "");
|
|
@@ -37983,9 +38984,11 @@ function wordWrap(text, width, continuationIndent = "") {
|
|
|
37983
38984
|
return wrapped.map((l, i) => i === 0 ? l : continuationIndent + l).join("\n");
|
|
37984
38985
|
}).join("\n");
|
|
37985
38986
|
}
|
|
38987
|
+
var import_sidekick_shared9;
|
|
37986
38988
|
var init_formatters = __esm({
|
|
37987
38989
|
"src/dashboard/formatters.ts"() {
|
|
37988
38990
|
"use strict";
|
|
38991
|
+
import_sidekick_shared9 = __toESM(require_dist(), 1);
|
|
37989
38992
|
}
|
|
37990
38993
|
});
|
|
37991
38994
|
|
|
@@ -38822,11 +39825,11 @@ function spawnWithStdin(cmd, args, prompt, env3) {
|
|
|
38822
39825
|
proc.stdin.end();
|
|
38823
39826
|
});
|
|
38824
39827
|
}
|
|
38825
|
-
var
|
|
39828
|
+
var import_sidekick_shared10, DEFAULT_ANTHROPIC_MODEL, DEFAULT_OPENAI_MODEL, EXEC_OPTS, CliInferenceClient;
|
|
38826
39829
|
var init_CliInferenceClient = __esm({
|
|
38827
39830
|
"src/inference/CliInferenceClient.ts"() {
|
|
38828
39831
|
"use strict";
|
|
38829
|
-
|
|
39832
|
+
import_sidekick_shared10 = __toESM(require_dist(), 1);
|
|
38830
39833
|
DEFAULT_ANTHROPIC_MODEL = "claude-haiku-4-5-20251001";
|
|
38831
39834
|
DEFAULT_OPENAI_MODEL = "gpt-4o-mini";
|
|
38832
39835
|
EXEC_OPTS = {
|
|
@@ -38974,7 +39977,7 @@ var init_CliInferenceClient = __esm({
|
|
|
38974
39977
|
}
|
|
38975
39978
|
}
|
|
38976
39979
|
completeViaCodexCli(prompt) {
|
|
38977
|
-
return spawnWithStdin("codex", ["exec"], prompt, (0,
|
|
39980
|
+
return spawnWithStdin("codex", ["exec"], prompt, (0, import_sidekick_shared10.getCodexExecutionEnv)());
|
|
38978
39981
|
}
|
|
38979
39982
|
};
|
|
38980
39983
|
}
|
|
@@ -38986,7 +39989,7 @@ function buildNarrativePrompt(metrics, diffStats) {
|
|
|
38986
39989
|
const durationMin = Math.round(durationMs / 6e4);
|
|
38987
39990
|
const t = metrics.tokens;
|
|
38988
39991
|
const totalTokens = t.input + t.output + t.cacheRead + t.cacheWrite;
|
|
38989
|
-
const costStr = (0,
|
|
39992
|
+
const costStr = (0, import_sidekick_shared11.formatCost)(t.cost);
|
|
38990
39993
|
const completed = metrics.tasks.filter((tk) => tk.status === "completed").length;
|
|
38991
39994
|
const completionRate = metrics.tasks.length > 0 ? completed / metrics.tasks.length : 0;
|
|
38992
39995
|
const taskLines = metrics.tasks.length > 0 ? metrics.tasks.map((tk) => ` - "${tk.subject}" (${tk.status}, ${tk.toolCallCount} tool calls)`).join("\n") : " (no tasks tracked)";
|
|
@@ -39015,7 +40018,7 @@ function buildNarrativePrompt(metrics, diffStats) {
|
|
|
39015
40018
|
}
|
|
39016
40019
|
}
|
|
39017
40020
|
const fileSection = fileLines.length > 0 ? fileLines.join("\n") : " (no file changes)";
|
|
39018
|
-
const modelLines = metrics.modelStats.length > 0 ? metrics.modelStats.map((m) => ` - ${m.model}: ${(0,
|
|
40021
|
+
const modelLines = metrics.modelStats.length > 0 ? metrics.modelStats.map((m) => ` - ${m.model}: ${(0, import_sidekick_shared11.formatCost)(m.cost)} (${m.calls} calls, ${fmtNum(m.tokens)} tokens)`).join("\n") : " (no model data)";
|
|
39019
40022
|
const totalToolCalls = metrics.toolStats.reduce((s, ts) => s + ts.calls, 0);
|
|
39020
40023
|
const topTools = metrics.toolStats.slice(0, 5).map((ts) => `${ts.name}(${ts.calls})`).join(", ");
|
|
39021
40024
|
return `You are a helpful assistant summarizing a Claude Code session. Write a concise 2-3 paragraph natural language summary based on this data. Focus on what was accomplished, notable patterns, and any suggestions for future sessions.
|
|
@@ -39042,12 +40045,12 @@ ${modelLines}
|
|
|
39042
40045
|
|
|
39043
40046
|
Write a brief, informative summary in plain English. Do not use bullet points or headers. Be specific about what was accomplished based on the task subjects and file changes.`;
|
|
39044
40047
|
}
|
|
39045
|
-
var
|
|
40048
|
+
var import_sidekick_shared11;
|
|
39046
40049
|
var init_narrativePrompt = __esm({
|
|
39047
40050
|
"src/inference/narrativePrompt.ts"() {
|
|
39048
40051
|
"use strict";
|
|
39049
40052
|
init_formatters();
|
|
39050
|
-
|
|
40053
|
+
import_sidekick_shared11 = __toESM(require_dist(), 1);
|
|
39051
40054
|
}
|
|
39052
40055
|
});
|
|
39053
40056
|
|
|
@@ -39088,17 +40091,17 @@ function renderContextAttribution(attr) {
|
|
|
39088
40091
|
}
|
|
39089
40092
|
return lines;
|
|
39090
40093
|
}
|
|
39091
|
-
var
|
|
40094
|
+
var import_sidekick_shared12, import_sidekick_shared13, MINDMAP_FILTERS, SessionsPanel, EVENT_COLORS;
|
|
39092
40095
|
var init_SessionsPanel = __esm({
|
|
39093
40096
|
"src/dashboard/panels/SessionsPanel.ts"() {
|
|
39094
40097
|
"use strict";
|
|
39095
40098
|
init_formatters();
|
|
39096
|
-
|
|
40099
|
+
import_sidekick_shared12 = __toESM(require_dist(), 1);
|
|
39097
40100
|
init_MindMapBuilder();
|
|
39098
40101
|
init_GitDiffCache();
|
|
39099
40102
|
init_CliInferenceClient();
|
|
39100
40103
|
init_narrativePrompt();
|
|
39101
|
-
|
|
40104
|
+
import_sidekick_shared13 = __toESM(require_dist(), 1);
|
|
39102
40105
|
MINDMAP_FILTERS = ["all", "file", "tool", "task", "subagent", "command", "plan", "knowledge-note"];
|
|
39103
40106
|
SessionsPanel = class {
|
|
39104
40107
|
id = "sessions";
|
|
@@ -39322,7 +40325,7 @@ ${hint}{/grey-fg}`;
|
|
|
39322
40325
|
lines.push(
|
|
39323
40326
|
"",
|
|
39324
40327
|
sectionHeader("Tokens", w2),
|
|
39325
|
-
`{grey-fg}In{/grey-fg} {bold}${fmtNum(t.input)}{/bold} {grey-fg}Out{/grey-fg} {bold}${fmtNum(t.output)}{/bold} ${cacheRate} {green-fg}${(0,
|
|
40328
|
+
`{grey-fg}In{/grey-fg} {bold}${fmtNum(t.input)}{/bold} {grey-fg}Out{/grey-fg} {bold}${fmtNum(t.output)}{/bold} ${cacheRate} {green-fg}${(0, import_sidekick_shared12.formatCost)(t.cost)}{/green-fg}`
|
|
39326
40329
|
);
|
|
39327
40330
|
const contextBar = makeColorBar(c.percent, 30, contextColor);
|
|
39328
40331
|
lines.push(
|
|
@@ -39369,7 +40372,7 @@ ${hint}{/grey-fg}`;
|
|
|
39369
40372
|
lines.push("", sectionHeader("Model Usage", w2));
|
|
39370
40373
|
for (const ms of m.modelStats) {
|
|
39371
40374
|
const modelName = ms.model.length > 20 ? ms.model.substring(0, 17) + "..." : ms.model;
|
|
39372
|
-
const costDisplay = ms.priced === false ? "{yellow-fg}\u2014{/yellow-fg}" : `{green-fg}${(0,
|
|
40375
|
+
const costDisplay = ms.priced === false ? "{yellow-fg}\u2014{/yellow-fg}" : `{green-fg}${(0, import_sidekick_shared12.formatCost)(ms.cost)}{/green-fg}`;
|
|
39373
40376
|
lines.push(` ${modelName.padEnd(20)} {bold}${String(ms.calls).padStart(4)}{/bold}{grey-fg} calls{/grey-fg} ${costDisplay}`);
|
|
39374
40377
|
}
|
|
39375
40378
|
}
|
|
@@ -39392,7 +40395,7 @@ ${hint}{/grey-fg}`;
|
|
|
39392
40395
|
})() : "";
|
|
39393
40396
|
lines.push(` {grey-fg}7d{/grey-fg} ${sevenBar} {bold}${q.sevenDay.utilization.toFixed(0)}%{/bold}${sevenProj}`);
|
|
39394
40397
|
} else if ((m.providerId === "claude-code" || m.providerId === "codex") && m.quota) {
|
|
39395
|
-
const descriptor = (0,
|
|
40398
|
+
const descriptor = (0, import_sidekick_shared13.describeQuotaFailure)(m.quota);
|
|
39396
40399
|
if (descriptor) {
|
|
39397
40400
|
const severityColor = descriptor.severity === "warning" ? "yellow" : descriptor.severity === "info" ? "cyan" : "red";
|
|
39398
40401
|
lines.push("", sectionHeader(quotaLabel, w2));
|
|
@@ -39436,7 +40439,7 @@ ${hint}{/grey-fg}`;
|
|
|
39436
40439
|
const totalTokens = s.inputTokens + s.outputTokens;
|
|
39437
40440
|
return [
|
|
39438
40441
|
`{bold}${s.date}{/bold} {bold}${s.sessionCount}{/bold}{grey-fg} sessions{/grey-fg} {bold}${s.messageCount}{/bold}{grey-fg} messages{/grey-fg}`,
|
|
39439
|
-
`{grey-fg}Tokens{/grey-fg} {bold}${fmtNum(totalTokens)}{/bold} ({grey-fg}In{/grey-fg} ${fmtNum(s.inputTokens)} {grey-fg}Out{/grey-fg} ${fmtNum(s.outputTokens)}) {green-fg}${(0,
|
|
40442
|
+
`{grey-fg}Tokens{/grey-fg} {bold}${fmtNum(totalTokens)}{/bold} ({grey-fg}In{/grey-fg} ${fmtNum(s.inputTokens)} {grey-fg}Out{/grey-fg} ${fmtNum(s.outputTokens)}) {green-fg}${(0, import_sidekick_shared12.formatCost)(s.totalCost)}{/green-fg}`,
|
|
39440
40443
|
"",
|
|
39441
40444
|
sectionHeader("Models", w),
|
|
39442
40445
|
...s.modelUsage.map((u) => ` ${u.model}: {bold}${u.calls}{/bold} calls`),
|
|
@@ -39462,12 +40465,12 @@ ${hint}{/grey-fg}`;
|
|
|
39462
40465
|
let suffix = "";
|
|
39463
40466
|
if (ev.tokens) {
|
|
39464
40467
|
suffix = ` (${fmtNum(ev.tokens.input)} in / ${fmtNum(ev.tokens.output)} out)`;
|
|
39465
|
-
if (ev.cost) suffix += ` ${(0,
|
|
40468
|
+
if (ev.cost) suffix += ` ${(0, import_sidekick_shared12.formatCost)(ev.cost)}`;
|
|
39466
40469
|
}
|
|
39467
40470
|
const prefixLen = 1 + time.length + 2 + 12;
|
|
39468
40471
|
const summaryMax = Math.max(10, w - prefixLen - suffix.length);
|
|
39469
40472
|
const rawSummary = truncate(ev.summary || "", summaryMax);
|
|
39470
|
-
const summary = (0,
|
|
40473
|
+
const summary = (0, import_sidekick_shared13.highlightEvent)(rawSummary, "blessed");
|
|
39471
40474
|
let line = `{${color}-fg}[${time}] ${label}{/${color}-fg} ${summary}`;
|
|
39472
40475
|
if (suffix) {
|
|
39473
40476
|
line += ` {grey-fg}${suffix.trimStart()}{/grey-fg}`;
|
|
@@ -39633,7 +40636,7 @@ function mergeTasks(live, persisted) {
|
|
|
39633
40636
|
map.set(p.taskId, {
|
|
39634
40637
|
taskId: p.taskId,
|
|
39635
40638
|
subject: p.subject,
|
|
39636
|
-
status: (0,
|
|
40639
|
+
status: (0, import_sidekick_shared14.normalizeTaskStatus)(p.status),
|
|
39637
40640
|
blockedBy: p.blockedBy || [],
|
|
39638
40641
|
blocks: p.blocks || [],
|
|
39639
40642
|
subagentType: p.subagentType,
|
|
@@ -39649,11 +40652,11 @@ function mergeTasks(live, persisted) {
|
|
|
39649
40652
|
}
|
|
39650
40653
|
return Array.from(map.values());
|
|
39651
40654
|
}
|
|
39652
|
-
var
|
|
40655
|
+
var import_sidekick_shared14;
|
|
39653
40656
|
var init_taskMerger = __esm({
|
|
39654
40657
|
"src/dashboard/utils/taskMerger.ts"() {
|
|
39655
40658
|
"use strict";
|
|
39656
|
-
|
|
40659
|
+
import_sidekick_shared14 = __toESM(require_dist(), 1);
|
|
39657
40660
|
}
|
|
39658
40661
|
});
|
|
39659
40662
|
|
|
@@ -40256,12 +41259,12 @@ var init_PlansPanel = __esm({
|
|
|
40256
41259
|
});
|
|
40257
41260
|
|
|
40258
41261
|
// src/dashboard/panels/EventStreamPanel.ts
|
|
40259
|
-
var
|
|
41262
|
+
var import_sidekick_shared15, EVENT_TYPE_BADGES, EventStreamPanel;
|
|
40260
41263
|
var init_EventStreamPanel = __esm({
|
|
40261
41264
|
"src/dashboard/panels/EventStreamPanel.ts"() {
|
|
40262
41265
|
"use strict";
|
|
40263
41266
|
init_formatters();
|
|
40264
|
-
|
|
41267
|
+
import_sidekick_shared15 = __toESM(require_dist(), 1);
|
|
40265
41268
|
EVENT_TYPE_BADGES = {
|
|
40266
41269
|
user: "{green-fg}[USR]{/green-fg}",
|
|
40267
41270
|
assistant: "{blue-fg}[AST]{/blue-fg}",
|
|
@@ -40285,7 +41288,7 @@ var init_EventStreamPanel = __esm({
|
|
|
40285
41288
|
return events.map((ev, i) => {
|
|
40286
41289
|
const time = formatTime(ev.timestamp);
|
|
40287
41290
|
const badge = EVENT_TYPE_BADGES[ev.type] || "{grey-fg}[???]{/grey-fg}";
|
|
40288
|
-
const summary = (0,
|
|
41291
|
+
const summary = (0, import_sidekick_shared15.highlightEvent)(ev.summary || "", "blessed");
|
|
40289
41292
|
const label = `{grey-fg}${time}{/grey-fg} ${badge} ${summary}`;
|
|
40290
41293
|
return {
|
|
40291
41294
|
id: `ev-${i}`,
|
|
@@ -40326,7 +41329,7 @@ var init_EventStreamPanel = __esm({
|
|
|
40326
41329
|
lines.push(sectionHeader("Summary", w));
|
|
40327
41330
|
lines.push("");
|
|
40328
41331
|
const summary = String(ev.summary || "(no summary)");
|
|
40329
|
-
lines.push(wordWrap((0,
|
|
41332
|
+
lines.push(wordWrap((0, import_sidekick_shared15.highlightEvent)(summary, "blessed"), w));
|
|
40330
41333
|
lines.push("");
|
|
40331
41334
|
lines.push(sectionHeader("Raw JSON", w));
|
|
40332
41335
|
lines.push("");
|
|
@@ -40355,7 +41358,7 @@ var init_EventStreamPanel = __esm({
|
|
|
40355
41358
|
const ev = events[i];
|
|
40356
41359
|
const time = formatTime(ev.timestamp);
|
|
40357
41360
|
const badge = EVENT_TYPE_BADGES[ev.type] || "{grey-fg}[???]{/grey-fg}";
|
|
40358
|
-
const summary = (0,
|
|
41361
|
+
const summary = (0, import_sidekick_shared15.highlightEvent)(ev.summary || "", "blessed");
|
|
40359
41362
|
if (i === idx) {
|
|
40360
41363
|
lines.push(`{bold}{magenta-fg}\u25B8 ${time} ${badge} ${summary}{/magenta-fg}{/bold}`);
|
|
40361
41364
|
} else {
|
|
@@ -78023,13 +79026,13 @@ var init_SessionPickerInk = __esm({
|
|
|
78023
79026
|
|
|
78024
79027
|
// src/phraseFormatters.ts
|
|
78025
79028
|
function getRandomPhraseBlessedTag() {
|
|
78026
|
-
return `{grey-fg}${(0,
|
|
79029
|
+
return `{grey-fg}${(0, import_sidekick_shared16.getRandomPhrase)()}{/grey-fg}`;
|
|
78027
79030
|
}
|
|
78028
|
-
var
|
|
79031
|
+
var import_sidekick_shared16;
|
|
78029
79032
|
var init_phraseFormatters = __esm({
|
|
78030
79033
|
"src/phraseFormatters.ts"() {
|
|
78031
79034
|
"use strict";
|
|
78032
|
-
|
|
79035
|
+
import_sidekick_shared16 = __toESM(require_dist(), 1);
|
|
78033
79036
|
}
|
|
78034
79037
|
});
|
|
78035
79038
|
|
|
@@ -78417,7 +79420,7 @@ function StatusBar({
|
|
|
78417
79420
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Text, { children: parseBlessedTags(BRAND_INLINE) }),
|
|
78418
79421
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { dimColor: true, children: [
|
|
78419
79422
|
" v",
|
|
78420
|
-
"0.
|
|
79423
|
+
"0.18.1"
|
|
78421
79424
|
] }),
|
|
78422
79425
|
updateInfo && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Text, { color: "yellow", children: [
|
|
78423
79426
|
" (v",
|
|
@@ -78554,7 +79557,7 @@ var init_useSpinner = __esm({
|
|
|
78554
79557
|
// src/dashboard/ink/SplashOverlay.tsx
|
|
78555
79558
|
function SplashOverlay() {
|
|
78556
79559
|
const spinner = useSpinner();
|
|
78557
|
-
const phrase = (0, import_react33.useMemo)(() => (0,
|
|
79560
|
+
const phrase = (0, import_react33.useMemo)(() => (0, import_sidekick_shared17.getRandomPhrase)(), []);
|
|
78558
79561
|
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
78559
79562
|
Box_default,
|
|
78560
79563
|
{
|
|
@@ -78604,14 +79607,14 @@ function SplashOverlay() {
|
|
|
78604
79607
|
}
|
|
78605
79608
|
);
|
|
78606
79609
|
}
|
|
78607
|
-
var import_react33,
|
|
79610
|
+
var import_react33, import_sidekick_shared17, import_jsx_runtime8;
|
|
78608
79611
|
var init_SplashOverlay = __esm({
|
|
78609
79612
|
async "src/dashboard/ink/SplashOverlay.tsx"() {
|
|
78610
79613
|
"use strict";
|
|
78611
79614
|
import_react33 = __toESM(require_react(), 1);
|
|
78612
79615
|
await init_build2();
|
|
78613
79616
|
init_useSpinner();
|
|
78614
|
-
|
|
79617
|
+
import_sidekick_shared17 = __toESM(require_dist(), 1);
|
|
78615
79618
|
init_branding();
|
|
78616
79619
|
await init_parseBlessedTags();
|
|
78617
79620
|
import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -78807,7 +79810,7 @@ function ChangelogOverlay({ entries, scrollOffset }) {
|
|
|
78807
79810
|
" ",
|
|
78808
79811
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { bold: true, color: "cyan", children: [
|
|
78809
79812
|
"Terminal Dashboard v",
|
|
78810
|
-
"0.
|
|
79813
|
+
"0.18.1"
|
|
78811
79814
|
] }),
|
|
78812
79815
|
latestDate ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Text, { color: "gray", children: [
|
|
78813
79816
|
" \u2014 ",
|
|
@@ -79129,7 +80132,7 @@ var init_mouse = __esm({
|
|
|
79129
80132
|
var CHANGELOG_default;
|
|
79130
80133
|
var init_CHANGELOG = __esm({
|
|
79131
80134
|
"CHANGELOG.md"() {
|
|
79132
|
-
CHANGELOG_default = '# Changelog\n\nAll notable changes to the Sidekick Agent Hub CLI will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [0.17.7] - 2026-04-28\n\n### Fixed\n\n- **Quota snapshot write race**: Updated the bundled `sidekick-shared` snapshot writer so concurrent `sidekick quota` / Codex session updates no longer collide on `quota-snapshots.json.tmp` or throw `ENOENT`. Failed writes now also clean up their partial temp files instead of leaving orphans in `~/.config/sidekick/`\n\n## [0.17.6] - 2026-04-19\n\n### Added\n\n- **`sidekick peak` command**: One-shot check for Claude\'s current peak-hours state \u2014 weekdays 13:00\u201319:00 UTC, when session limits drain faster on Free/Pro/Max/Team subscriptions. Prints a color-coded status block with a countdown to the next transition. Data comes from the public `promoclock.co/api/status` endpoint (third-party, unaffiliated with Anthropic) with a graceful fallback when unreachable. `--json` emits the full raw state\n- **Peak-hours block in `sidekick status`**: When the active provider is `claude-code`, the Claude + OpenAI health blocks are now followed by a **Claude Peak Hours** block (off-peak or in-peak, with countdown). Gated on the provider so OpenCode / Codex users don\'t trigger an unnecessary third-party fetch. `--json` output includes the new `peak` field\n- **Peak-hours summary in `sidekick quota`**: Claude subscription quota output now shows a **Peak** line under the 5-hour / 7-day bars \u2014 green dot off-peak, orange dot during an active peak, with a countdown to the next transition. `--json` output includes the new `peak` field\n\n## [0.17.5] - 2026-04-18\n\n### Added\n\n- **Default account bootstrap at CLI startup**: The CLI now calls `ensureDefaultAccounts()` from `sidekick-shared` at module load and awaits the result inside a Commander `preAction` hook, so the first real subcommand blocks briefly on the bootstrap while `--version` and `--help` stay instant. When a system Claude Code or Codex credential exists and no saved account is active for that provider yet, the CLI registers it as "Default" \u2014 `sidekick quota`, `sidekick account`, and `sidekick stats` now reflect the active account on first run without requiring an explicit `sidekick account --add` first. Idempotent, never overwrites manually saved accounts, and all errors are swallowed so startup is never blocked\n\nThanks to [@B33pBeeps](https://github.com/B33pBeeps) (Juan Fourie) for contributing this feature in [#16](https://github.com/cesarandreslopez/sidekick-agent-hub/pull/16).\n\n## [0.17.4] - 2026-04-17\n\n### Changed\n\n- **Pricing hydration import migrated to `sidekick-shared/node`**: `cli.ts` now imports `hydratePricingCatalog` from the new Node-only subpath and keeps `detectProvider` on the package root. Runtime behavior is unchanged; the split makes the CLI\'s import surface self-documenting (hydration is explicitly a Node API) and aligns the CLI with the shared library\'s new versioned public API contract\n\n## [0.17.3] - 2026-04-17\n\n### Changed\n\n- **Version sync with the VS Code extension**: Republished to keep CLI, extension, and shared-library versions aligned after a cosmetic changelog fix in 0.17.3. No CLI code changes \u2014 functionally identical to 0.17.2\n\n## [0.17.2] - 2026-04-17\n\n### Added\n\n- **LiteLLM pricing hydration on startup**: The CLI now fetches the LiteLLM pricing catalog on startup and caches to `~/.config/sidekick/pricing-catalog.json` with a 24-hour TTL, 3s timeout, and stale-cache fallback \u2014 new model prices are picked up without a CLI upgrade\n- **Expanded pricing coverage**: GPT-4o, GPT-4.1, GPT-5.x, o1, o3, and o3-mini families are now priced alongside the existing Claude entries\n- **Real-dollar Codex / Claude Code costs**: `EventAggregator` computes cost from the pricing table when the session provider doesn\'t report one, so `sidekick` live dashboards now show actual dollars for Codex and Claude Code sessions\n- **`stats` footer lists unpriced models**: `sidekick stats` prints any models encountered with no pricing entry so missing coverage is visible\n\n### Fixed\n\n- **Context-gauge % wrong for Opus 4.7 (1M) and other new models**: The dashboard\'s context gauge was dividing by 200K for Claude Opus 4.7 (native 1M), inflating the displayed %. The shared model \u2192 context-window map now includes Opus/Sonnet 4.7 (1M), GPT-5.4 (1.05M), GPT-5.3-Codex (400K), and GPT-5.3-Codex-Spark (128K). Claude Code\'s `[1m]` suffix is now also honored as an explicit 1M marker\n- **Silent Sonnet-priced fallback for unknown models**: Codex, GPT-5.x, and o-series rows were being rendered at Sonnet rates. Unknown-model rows now render as `\u2014` in yellow instead of inventing a dollar figure\n\n### Changed\n\n- **`historical-data.json` schema v2**: reads `priced` flag and `unpricedModelIds` from records written by the latest VS Code extension; v1 records still read correctly\n\n## [0.17.1] - 2026-04-13\n\n### Fixed\n\n- **Codex multi-home session discovery**: Provider detection now scans all candidate Codex home directories, fixing missed sessions when the managed profile home is empty but the system `~/.codex/` has activity\n\n## [0.17.0] - 2026-04-13\n\n### Added\n\n- **Multi-provider account management**: `sidekick account` now supports `--provider codex` for Codex profile management alongside Claude Code accounts\n- **Codex account lifecycle**: `--add` prepares a profile and spawns `codex login`; `--switch-to` and `--remove` accept email, label, or profile ID\n- **Quota snapshot fallback**: `sidekick quota` for Codex shows cached rate-limit snapshots when no active session exists, with "cached from" timestamp\n\n### Fixed\n\n- **Email normalization**: Claude account lookup normalizes email case for reliable matching\n\n## [0.16.1] - 2026-03-27\n\n### Fixed\n\n- **Dashboard provider status scoping**: The TUI now shows degraded-service notices only for the monitored provider \u2014 Claude for Claude Code sessions, OpenAI for Codex sessions, and no status banner for OpenCode\n\n## [0.16.0] - 2026-03-23\n\n### Changed\n\n- **Consistent cost formatting**: All cost displays (`stats`, `context`, Sessions panel, narrative prompt) now use shared `formatCost()` with intelligent decimal precision (4 places for < $0.01, 2 otherwise)\n- **QuotaService**: Rewritten to wrap shared `QuotaPoller` with exponential backoff instead of manual polling loop\n- **modelContext**: Now re-exports `getModelInfo` from shared library alongside `getContextWindowSize`\n\n## [0.15.2] - 2026-03-18\n\n### Fixed\n\n- **CLI help descriptions**: Updated `quota` and `status` command descriptions to reflect provider-aware behavior\n- **`sidekick quota --provider`**: Added local `--provider` option so `sidekick quota --provider codex` works naturally\n\n## [0.15.0] - 2026-03-18\n\n### Added\n\n- **OpenAI status page monitoring**: CLI dashboard now shows OpenAI API status alongside Claude API status\n- **Codex rate limits in dashboard**: Sessions panel displays Codex rate-limit data with "Rate Limits" header instead of "Quota"\n- **Provider-aware `sidekick quota` command**: Detects active provider and shows Codex rate limits, Claude subscription quota, or an informational message for OpenCode\n\n### Fixed\n\n- **QuotaService polling for Codex**: Dashboard no longer starts Claude OAuth quota polling when the active provider is Codex\n\n## [0.14.2] - 2026-03-16\n\n### Fixed\n\n- **Quota polling interval**: Reduced quota refresh from every 30 seconds to every 5 minutes to avoid unnecessary API calls\n- **SessionsPanel `detailWidth()` call**: Removed unused parameter from `detailWidth()` in the Sessions panel quota rendering\n\n## [0.14.1] - 2026-03-14\n\n### Fixed\n\n- **Per-model context window sizes**: Dashboard context gauge now shows correct utilization for Claude Opus 4.6 (1M context) and other models with non-200K windows\n\n### Changed\n\n- **Shared model context lookup**: CLI dashboard now uses the centralized `getModelContextWindowSize()` from `sidekick-shared` instead of a local duplicate map\n\n## [0.14.0] - 2026-03-12\n\n### Added\n\n- **`sidekick account` Command**: Manage Claude Code accounts from the terminal \u2014 list saved accounts, add the current account with an optional label, switch to the next or a specific account, and remove accounts. Supports `--json` output for scripting\n- **Quota Account Label**: `sidekick quota` now shows the active account email and label above the quota bars when multi-account is enabled\n- **macOS Keychain Support**: `sidekick account` and `sidekick quota` now read and write credentials via the system Keychain on macOS, fixing account switching and quota checks on Mac\n\n## [0.13.8] - 2026-03-12\n\n### Changed\n\n- **Structured quota failure output**: `sidekick quota` now renders consistent auth, rate-limit, server, network, and unexpected-failure copy from shared quota failure descriptors while preserving `--json` machine-readable output\n- **Dashboard unavailable quota rendering**: The Sessions panel now shows Claude Code quota failures inline instead of hiding the quota section whenever subscription data is unavailable\n- **Quota transition toasts**: The Ink dashboard now fires low-noise toast notifications only when Claude Code quota failure state changes, avoiding repeated alerts every polling interval\n\n## [0.13.7] - 2026-03-11\n\n### Changed\n\n- **npm README sync**: Updated the published CLI package README to reflect current OpenCode monitoring behavior, platform-specific data directories, and the `sqlite3` runtime requirement\n- **README badge cleanup**: Removed the Ask DeepWiki badge from the published CLI package README; the repo root README still keeps it\n\n## [0.13.6] - 2026-03-11\n\n### Changed\n\n- **Refreshed CLI Dashboard Wordmark**: Updated the dashboard wordmark/header styling for a cleaner splash and dashboard identity\n\n### Fixed\n\n- **OpenCode dashboard startup**: OpenCode DB-backed session discovery now resolves projects by worktree, sandboxes, and session directory instead of quietly behaving like no session exists\n- **OpenCode runtime notices**: The CLI now prints an OpenCode-only actionable notice when `opencode.db` exists but `sqlite3` is missing, blocked, or otherwise unusable in the current shell environment\n\n## [0.13.5] - 2026-03-10\n\n### Added\n\n- **`sidekick status` Command**: One-shot Claude API status check with color-coded text output and `--json` mode\n- **Dashboard Status Banner**: Status bar shows a colored `\u25CF API minor/major/critical` indicator when Claude is degraded; Sessions panel Summary tab shows an "API Status" section with affected components and active incident details. Polls every 60s\n\n## [0.13.4] - 2026-03-08\n\n### Fixed\n\n- **Onboarding Phrase Spam**: Splash screen and detail pane motivational phrases memoized \u2014 no longer flicker every render tick (fixes [#13](https://github.com/cesarandreslopez/sidekick-agent-hub/issues/13))\n\n### Changed\n\n- **Simplified Logo**: Replaced 6-line ASCII robot art with compact text header in splash, help, and changelog overlays\n- **Removed Dead Code**: Removed unused `getSplashContent()` and `HELP_HEADER` exports from branding module\n\n## [0.13.3] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.2] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.1] - 2026-03-04\n\n### Added\n\n- **`sidekick quota` Command**: One-shot subscription quota check showing 5-hour and 7-day utilization with color-coded progress bars and reset countdowns \u2014 supports `--json` for machine-readable output\n- **Quota Projections**: Elapsed-time projections shown in `sidekick quota` output and TUI dashboard quota section \u2014 displays projected end-of-window utilization next to current value (e.g., `40% \u2192 100%`), included in `--json` output as `projectedFiveHour` / `projectedSevenDay`\n\n## [0.13.0] - 2026-03-03\n\n_No CLI-specific changes in this release._\n\n## [0.12.10] - 2026-03-01\n\n### Added\n\n- **Events Panel** (key 7): Scrollable live event stream with colored type badges (`[USR]`, `[AST]`, `[TOOL]`, `[RES]`), timestamps, and keyword-highlighted summaries; detail tabs for full event JSON and surrounding context\n- **Charts Panel** (key 8): Tool frequency horizontal bars, event type distribution, 60-minute activity heatmap using `\u2591\u2592\u2593\u2588` intensity characters, and pattern analysis with frequency bars and template text\n- **Multi-Mode Filter**: `/` filter overlay now supports four modes \u2014 substring, fuzzy, regex, and date range \u2014 Tab cycles modes, regex mode shows red validation errors\n- **Search Term Highlighting**: Active filter terms highlighted in blue within side list items\n- **Timeline Keyword Coloring**: Event summaries in the Sessions panel Timeline tab now use semantic keyword coloring \u2014 errors red, success green, tool names cyan, file paths magenta\n\n### Removed\n\n- **Search Panel**: Removed redundant Search panel (previously key 7) \u2014 the `/` filter with multi-mode support serves the same purpose\n\n## [0.12.9] - 2026-02-28\n\n### Added\n\n- **Standalone Data Commands**: `sidekick tasks`, `sidekick decisions`, `sidekick notes`, `sidekick stats`, `sidekick handoff` for accessing project data without launching the TUI\n- **`sidekick search <query>`**: Cross-session full-text search from the terminal\n- **`sidekick context`**: Composite output of tasks, decisions, notes, and handoff for piping into other tools\n- **`--list` flag on `sidekick dump`**: Discover available session IDs before requiring `--session <id>`\n- **Search Panel**: Search panel (panel 7) wired into the TUI dashboard\n\n### Changed\n\n- **`taskMerger` utility**: Duplicate `mergeTasks` logic extracted into shared `taskMerger` utility\n- **Model constants**: Hardcoded model IDs extracted to named constants\n\n### Fixed\n\n- **`convention` icon**: Notes panel icon replaced with valid `tip` type\n- **Linux clipboard**: Now supports Wayland (`wl-copy`) and `xsel` fallbacks, with error messages instead of silent failure\n- **`provider.dispose()`**: Added to `dump` and `report` commands (prevents SQLite connection leaks)\n\n## [0.12.8] - 2026-02-28\n\n### Changed\n\n- **Dashboard UI/UX Polish**: Visual overhaul for better hierarchy, consistency, and readability\n - Splash screen and help overlay now display the robot ASCII logo\n - Toast notifications show severity icons (\u2718 error, \u26A0 warning, \u25CF info) with inner padding\n - Focused pane uses double-border for clear focus indication\n - Section dividers (`\u2500\u2500 Title \u2500\u2500\u2500\u2500`) replace bare bold headers in summary, agents, and context attribution\n - Tab bar: active tab underlined in magenta, inactive tabs dimmed, bracket syntax removed\n - Status bar: segmented layout with `\u2502` separators; keys bold, labels dim\n - Summary metrics condensed: elapsed/events/compactions on one line, tokens on one line with cache rate and cost\n - Sparklines display peak metadata annotations\n - Progress bars use blessed color tags for consistent coloring\n - Help overlay uses dot-leader alignment for all keybinding rows\n - Empty state hints per panel (e.g. "Tasks appear as your agent works.")\n - Session picker groups sessions by provider with section headers when multiple providers are present\n\n## [0.12.7] - 2026-02-27\n\n### Added\n\n- **HTML Session Report**: `sidekick report` command generates a self-contained HTML report and opens it in the default browser\n - Options: `--session`, `--output`, `--theme` (dark/light), `--no-open`, `--no-thinking`\n - TUI Dashboard: press `r` to generate and open an HTML report for the current session\n\n## [0.12.6] - 2026-02-26\n\n### Added\n\n- **Session Dump Command**: `sidekick dump` exports session data in text, markdown, or JSON format with `--format`, `--width`, and `--expand` options\n- **Plans Panel Re-enabled**: Plans panel restored in CLI dashboard with plan file discovery from `~/.claude/plans/`\n- **Enhanced Status Bar**: Session info display improved with richer metadata\n\n### Fixed\n\n- **Old snapshot format migration**: Restoring pre-0.12.3 session snapshots no longer shows empty timeline entries\n\n### Changed\n\n- **Phrase library moved to shared**: CLI-specific phrase formatting kept local, all phrase content now from `sidekick-shared`\n\n## [0.12.5] - 2026-02-24\n\n### Fixed\n\n- **Update check too slow to notice new versions**: Reduced npm registry cache TTL from 24 hours to 4 hours so upgrade notices appear sooner after a new release\n\n## [0.12.4] - 2026-02-24\n\n### Fixed\n\n- **Session crash on upgrade**: Fixed `d.timestamp.getTime is not a function` error when restoring tool call data from session snapshots \u2014 `Date` objects were serialized to strings by JSON but not rehydrated on restore, causing the session monitor to crash on first run after upgrading from 0.12.2 to 0.12.3\n\n## [0.12.3] - 2026-02-24\n\n### Added\n\n- **Latest-node indicator**: The most recently added node in tree and boxed mind map views is now marked with a yellow indicator\n- **Plan analytics in mind map**: Tree and boxed views now display plan progress and per-step metrics\n - Tree view: plan header shows completion stats; steps show complexity, duration, tokens, tool calls, and errors in metadata brackets\n - Box view: progress bar with completion percentage; steps show right-aligned metrics; subtitle shows step count and total duration\n- **Cross-provider plan extraction**: Shared `PlanExtractor` now handles Claude Code (EnterPlanMode/ExitPlanMode) and OpenCode (`<proposed_plan>` XML) plans \u2014 previously only Codex plans were shown\n- **Enriched plan data model**: Plan steps include duration, token count, tool call count, and error messages\n- **Phase-grouped plan display**: When a plan has phase structure, tree and boxed views group steps under phase headers with context lines from the original plan markdown\n- **Node type filter**: Press `f` on the Mind Map tab to cycle through node type filters (file, tool, task, subagent, command, plan, knowledge-note) \u2014 non-matching sections render dimmed in grey\n\n### Fixed\n\n- **Kanban board regression**: Subagent and plan-step tasks now correctly appear in the kanban board\n\n### Changed\n\n- **Plans panel temporarily disabled**: The Plans panel in the CLI dashboard is disabled until plan-mode event capture is reliably working end-to-end. Plan nodes in the mind map remain active.\n- `DashboardState` now delegates to shared `EventAggregator` instead of maintaining its own aggregation logic\n\n## [0.12.2] - 2026-02-23\n\n### Added\n\n- **Update notifications**: The dashboard now checks the npm registry for newer versions on startup and shows a yellow banner in the status bar when an update is available (e.g., `v0.13.0 available \u2014 npm i -g sidekick-agent-hub`). Results are cached for 24 hours to avoid repeated network requests.\n\n## [0.12.1] - 2026-02-23\n\n### Fixed\n\n- **VS Code integration**: Fixed exit code 127 when the extension launches the CLI dashboard on systems using nvm or volta (node binary not found when shell init is bypassed)\n\n## [0.12.0] - 2026-02-22\n\n### Added\n\n- **"Open CLI Dashboard" VS Code Integration**: New VS Code command `Sidekick: Open CLI Dashboard` launches the TUI dashboard in an integrated terminal\n - Install the CLI with `npm install -g sidekick-agent-hub`\n\n## [0.11.0] - 2026-02-19\n\n### Added\n\n- **Initial Release**: Full-screen TUI dashboard for monitoring agent sessions from the terminal\n - Ink-based terminal UI with panels for sessions, tasks, kanban, mind map, notes, decisions, search, files, and git diff\n - Multi-provider support: auto-detects Claude Code, OpenCode, and Codex sessions\n - Reads from `~/.config/sidekick/` \u2014 the same data files the VS Code extension writes\n - Usage: `sidekick dashboard [--project <path>] [--provider <id>]`\n';
|
|
80135
|
+
CHANGELOG_default = '# Changelog\n\nAll notable changes to the Sidekick Agent Hub CLI will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [0.18.1] - 2026-05-08\n\n### Changed\n\n- **Shared dashboard formatting**: terminal dashboard `fmtNum()` and `formatDuration()` now delegate to `formatTokenCount()` and `formatDurationMs()` from `sidekick-shared`, keeping the existing CLI surface (uppercase `K`/`M` suffix, compact `1m5s` style) while removing forked rounding logic\n\n## [0.18.0] - 2026-05-08\n\n### Changed\n\n- **Bundled `sidekick-shared` 0.18.0**: Picks up the new provider-aware quota orchestration surface \u2014 `MultiProviderQuotaService`, `CodexQuotaWatcher`, `getActiveAccountStatus()`, `extractToolCall()`, cost-provenance helpers (`calculateCostWithProvenance`, `mergeCostSources`), and model display helpers (`shortModelName`, `getModelDisplayInfo`, `compareModelIds`, `sortModelIds`). `parseModelId()` also now recognizes legacy Claude IDs such as `claude-3-opus-20240229` and `claude-3-5-sonnet-20241022`\n- **No CLI runtime changes**: This release ships the shared library upgrade for downstream tooling alignment; `sidekick quota`, `sidekick status`, and the live dashboard keep using the existing polling path. Wiring the new orchestrator into the CLI will land in a follow-up release\n\n## [0.17.7] - 2026-04-28\n\n### Fixed\n\n- **Quota snapshot write race**: Updated the bundled `sidekick-shared` snapshot writer so concurrent `sidekick quota` / Codex session updates no longer collide on `quota-snapshots.json.tmp` or throw `ENOENT`. Failed writes now also clean up their partial temp files instead of leaving orphans in `~/.config/sidekick/`\n\n## [0.17.6] - 2026-04-19\n\n### Added\n\n- **`sidekick peak` command**: One-shot check for Claude\'s current peak-hours state \u2014 weekdays 13:00\u201319:00 UTC, when session limits drain faster on Free/Pro/Max/Team subscriptions. Prints a color-coded status block with a countdown to the next transition. Data comes from the public `promoclock.co/api/status` endpoint (third-party, unaffiliated with Anthropic) with a graceful fallback when unreachable. `--json` emits the full raw state\n- **Peak-hours block in `sidekick status`**: When the active provider is `claude-code`, the Claude + OpenAI health blocks are now followed by a **Claude Peak Hours** block (off-peak or in-peak, with countdown). Gated on the provider so OpenCode / Codex users don\'t trigger an unnecessary third-party fetch. `--json` output includes the new `peak` field\n- **Peak-hours summary in `sidekick quota`**: Claude subscription quota output now shows a **Peak** line under the 5-hour / 7-day bars \u2014 green dot off-peak, orange dot during an active peak, with a countdown to the next transition. `--json` output includes the new `peak` field\n\n## [0.17.5] - 2026-04-18\n\n### Added\n\n- **Default account bootstrap at CLI startup**: The CLI now calls `ensureDefaultAccounts()` from `sidekick-shared` at module load and awaits the result inside a Commander `preAction` hook, so the first real subcommand blocks briefly on the bootstrap while `--version` and `--help` stay instant. When a system Claude Code or Codex credential exists and no saved account is active for that provider yet, the CLI registers it as "Default" \u2014 `sidekick quota`, `sidekick account`, and `sidekick stats` now reflect the active account on first run without requiring an explicit `sidekick account --add` first. Idempotent, never overwrites manually saved accounts, and all errors are swallowed so startup is never blocked\n\nThanks to [@B33pBeeps](https://github.com/B33pBeeps) (Juan Fourie) for contributing this feature in [#16](https://github.com/cesarandreslopez/sidekick-agent-hub/pull/16).\n\n## [0.17.4] - 2026-04-17\n\n### Changed\n\n- **Pricing hydration import migrated to `sidekick-shared/node`**: `cli.ts` now imports `hydratePricingCatalog` from the new Node-only subpath and keeps `detectProvider` on the package root. Runtime behavior is unchanged; the split makes the CLI\'s import surface self-documenting (hydration is explicitly a Node API) and aligns the CLI with the shared library\'s new versioned public API contract\n\n## [0.17.3] - 2026-04-17\n\n### Changed\n\n- **Version sync with the VS Code extension**: Republished to keep CLI, extension, and shared-library versions aligned after a cosmetic changelog fix in 0.17.3. No CLI code changes \u2014 functionally identical to 0.17.2\n\n## [0.17.2] - 2026-04-17\n\n### Added\n\n- **LiteLLM pricing hydration on startup**: The CLI now fetches the LiteLLM pricing catalog on startup and caches to `~/.config/sidekick/pricing-catalog.json` with a 24-hour TTL, 3s timeout, and stale-cache fallback \u2014 new model prices are picked up without a CLI upgrade\n- **Expanded pricing coverage**: GPT-4o, GPT-4.1, GPT-5.x, o1, o3, and o3-mini families are now priced alongside the existing Claude entries\n- **Real-dollar Codex / Claude Code costs**: `EventAggregator` computes cost from the pricing table when the session provider doesn\'t report one, so `sidekick` live dashboards now show actual dollars for Codex and Claude Code sessions\n- **`stats` footer lists unpriced models**: `sidekick stats` prints any models encountered with no pricing entry so missing coverage is visible\n\n### Fixed\n\n- **Context-gauge % wrong for Opus 4.7 (1M) and other new models**: The dashboard\'s context gauge was dividing by 200K for Claude Opus 4.7 (native 1M), inflating the displayed %. The shared model \u2192 context-window map now includes Opus/Sonnet 4.7 (1M), GPT-5.4 (1.05M), GPT-5.3-Codex (400K), and GPT-5.3-Codex-Spark (128K). Claude Code\'s `[1m]` suffix is now also honored as an explicit 1M marker\n- **Silent Sonnet-priced fallback for unknown models**: Codex, GPT-5.x, and o-series rows were being rendered at Sonnet rates. Unknown-model rows now render as `\u2014` in yellow instead of inventing a dollar figure\n\n### Changed\n\n- **`historical-data.json` schema v2**: reads `priced` flag and `unpricedModelIds` from records written by the latest VS Code extension; v1 records still read correctly\n\n## [0.17.1] - 2026-04-13\n\n### Fixed\n\n- **Codex multi-home session discovery**: Provider detection now scans all candidate Codex home directories, fixing missed sessions when the managed profile home is empty but the system `~/.codex/` has activity\n\n## [0.17.0] - 2026-04-13\n\n### Added\n\n- **Multi-provider account management**: `sidekick account` now supports `--provider codex` for Codex profile management alongside Claude Code accounts\n- **Codex account lifecycle**: `--add` prepares a profile and spawns `codex login`; `--switch-to` and `--remove` accept email, label, or profile ID\n- **Quota snapshot fallback**: `sidekick quota` for Codex shows cached rate-limit snapshots when no active session exists, with "cached from" timestamp\n\n### Fixed\n\n- **Email normalization**: Claude account lookup normalizes email case for reliable matching\n\n## [0.16.1] - 2026-03-27\n\n### Fixed\n\n- **Dashboard provider status scoping**: The TUI now shows degraded-service notices only for the monitored provider \u2014 Claude for Claude Code sessions, OpenAI for Codex sessions, and no status banner for OpenCode\n\n## [0.16.0] - 2026-03-23\n\n### Changed\n\n- **Consistent cost formatting**: All cost displays (`stats`, `context`, Sessions panel, narrative prompt) now use shared `formatCost()` with intelligent decimal precision (4 places for < $0.01, 2 otherwise)\n- **QuotaService**: Rewritten to wrap shared `QuotaPoller` with exponential backoff instead of manual polling loop\n- **modelContext**: Now re-exports `getModelInfo` from shared library alongside `getContextWindowSize`\n\n## [0.15.2] - 2026-03-18\n\n### Fixed\n\n- **CLI help descriptions**: Updated `quota` and `status` command descriptions to reflect provider-aware behavior\n- **`sidekick quota --provider`**: Added local `--provider` option so `sidekick quota --provider codex` works naturally\n\n## [0.15.0] - 2026-03-18\n\n### Added\n\n- **OpenAI status page monitoring**: CLI dashboard now shows OpenAI API status alongside Claude API status\n- **Codex rate limits in dashboard**: Sessions panel displays Codex rate-limit data with "Rate Limits" header instead of "Quota"\n- **Provider-aware `sidekick quota` command**: Detects active provider and shows Codex rate limits, Claude subscription quota, or an informational message for OpenCode\n\n### Fixed\n\n- **QuotaService polling for Codex**: Dashboard no longer starts Claude OAuth quota polling when the active provider is Codex\n\n## [0.14.2] - 2026-03-16\n\n### Fixed\n\n- **Quota polling interval**: Reduced quota refresh from every 30 seconds to every 5 minutes to avoid unnecessary API calls\n- **SessionsPanel `detailWidth()` call**: Removed unused parameter from `detailWidth()` in the Sessions panel quota rendering\n\n## [0.14.1] - 2026-03-14\n\n### Fixed\n\n- **Per-model context window sizes**: Dashboard context gauge now shows correct utilization for Claude Opus 4.6 (1M context) and other models with non-200K windows\n\n### Changed\n\n- **Shared model context lookup**: CLI dashboard now uses the centralized `getModelContextWindowSize()` from `sidekick-shared` instead of a local duplicate map\n\n## [0.14.0] - 2026-03-12\n\n### Added\n\n- **`sidekick account` Command**: Manage Claude Code accounts from the terminal \u2014 list saved accounts, add the current account with an optional label, switch to the next or a specific account, and remove accounts. Supports `--json` output for scripting\n- **Quota Account Label**: `sidekick quota` now shows the active account email and label above the quota bars when multi-account is enabled\n- **macOS Keychain Support**: `sidekick account` and `sidekick quota` now read and write credentials via the system Keychain on macOS, fixing account switching and quota checks on Mac\n\n## [0.13.8] - 2026-03-12\n\n### Changed\n\n- **Structured quota failure output**: `sidekick quota` now renders consistent auth, rate-limit, server, network, and unexpected-failure copy from shared quota failure descriptors while preserving `--json` machine-readable output\n- **Dashboard unavailable quota rendering**: The Sessions panel now shows Claude Code quota failures inline instead of hiding the quota section whenever subscription data is unavailable\n- **Quota transition toasts**: The Ink dashboard now fires low-noise toast notifications only when Claude Code quota failure state changes, avoiding repeated alerts every polling interval\n\n## [0.13.7] - 2026-03-11\n\n### Changed\n\n- **npm README sync**: Updated the published CLI package README to reflect current OpenCode monitoring behavior, platform-specific data directories, and the `sqlite3` runtime requirement\n- **README badge cleanup**: Removed the Ask DeepWiki badge from the published CLI package README; the repo root README still keeps it\n\n## [0.13.6] - 2026-03-11\n\n### Changed\n\n- **Refreshed CLI Dashboard Wordmark**: Updated the dashboard wordmark/header styling for a cleaner splash and dashboard identity\n\n### Fixed\n\n- **OpenCode dashboard startup**: OpenCode DB-backed session discovery now resolves projects by worktree, sandboxes, and session directory instead of quietly behaving like no session exists\n- **OpenCode runtime notices**: The CLI now prints an OpenCode-only actionable notice when `opencode.db` exists but `sqlite3` is missing, blocked, or otherwise unusable in the current shell environment\n\n## [0.13.5] - 2026-03-10\n\n### Added\n\n- **`sidekick status` Command**: One-shot Claude API status check with color-coded text output and `--json` mode\n- **Dashboard Status Banner**: Status bar shows a colored `\u25CF API minor/major/critical` indicator when Claude is degraded; Sessions panel Summary tab shows an "API Status" section with affected components and active incident details. Polls every 60s\n\n## [0.13.4] - 2026-03-08\n\n### Fixed\n\n- **Onboarding Phrase Spam**: Splash screen and detail pane motivational phrases memoized \u2014 no longer flicker every render tick (fixes [#13](https://github.com/cesarandreslopez/sidekick-agent-hub/issues/13))\n\n### Changed\n\n- **Simplified Logo**: Replaced 6-line ASCII robot art with compact text header in splash, help, and changelog overlays\n- **Removed Dead Code**: Removed unused `getSplashContent()` and `HELP_HEADER` exports from branding module\n\n## [0.13.3] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.2] - 2026-03-04\n\n_No CLI-specific changes in this release._\n\n## [0.13.1] - 2026-03-04\n\n### Added\n\n- **`sidekick quota` Command**: One-shot subscription quota check showing 5-hour and 7-day utilization with color-coded progress bars and reset countdowns \u2014 supports `--json` for machine-readable output\n- **Quota Projections**: Elapsed-time projections shown in `sidekick quota` output and TUI dashboard quota section \u2014 displays projected end-of-window utilization next to current value (e.g., `40% \u2192 100%`), included in `--json` output as `projectedFiveHour` / `projectedSevenDay`\n\n## [0.13.0] - 2026-03-03\n\n_No CLI-specific changes in this release._\n\n## [0.12.10] - 2026-03-01\n\n### Added\n\n- **Events Panel** (key 7): Scrollable live event stream with colored type badges (`[USR]`, `[AST]`, `[TOOL]`, `[RES]`), timestamps, and keyword-highlighted summaries; detail tabs for full event JSON and surrounding context\n- **Charts Panel** (key 8): Tool frequency horizontal bars, event type distribution, 60-minute activity heatmap using `\u2591\u2592\u2593\u2588` intensity characters, and pattern analysis with frequency bars and template text\n- **Multi-Mode Filter**: `/` filter overlay now supports four modes \u2014 substring, fuzzy, regex, and date range \u2014 Tab cycles modes, regex mode shows red validation errors\n- **Search Term Highlighting**: Active filter terms highlighted in blue within side list items\n- **Timeline Keyword Coloring**: Event summaries in the Sessions panel Timeline tab now use semantic keyword coloring \u2014 errors red, success green, tool names cyan, file paths magenta\n\n### Removed\n\n- **Search Panel**: Removed redundant Search panel (previously key 7) \u2014 the `/` filter with multi-mode support serves the same purpose\n\n## [0.12.9] - 2026-02-28\n\n### Added\n\n- **Standalone Data Commands**: `sidekick tasks`, `sidekick decisions`, `sidekick notes`, `sidekick stats`, `sidekick handoff` for accessing project data without launching the TUI\n- **`sidekick search <query>`**: Cross-session full-text search from the terminal\n- **`sidekick context`**: Composite output of tasks, decisions, notes, and handoff for piping into other tools\n- **`--list` flag on `sidekick dump`**: Discover available session IDs before requiring `--session <id>`\n- **Search Panel**: Search panel (panel 7) wired into the TUI dashboard\n\n### Changed\n\n- **`taskMerger` utility**: Duplicate `mergeTasks` logic extracted into shared `taskMerger` utility\n- **Model constants**: Hardcoded model IDs extracted to named constants\n\n### Fixed\n\n- **`convention` icon**: Notes panel icon replaced with valid `tip` type\n- **Linux clipboard**: Now supports Wayland (`wl-copy`) and `xsel` fallbacks, with error messages instead of silent failure\n- **`provider.dispose()`**: Added to `dump` and `report` commands (prevents SQLite connection leaks)\n\n## [0.12.8] - 2026-02-28\n\n### Changed\n\n- **Dashboard UI/UX Polish**: Visual overhaul for better hierarchy, consistency, and readability\n - Splash screen and help overlay now display the robot ASCII logo\n - Toast notifications show severity icons (\u2718 error, \u26A0 warning, \u25CF info) with inner padding\n - Focused pane uses double-border for clear focus indication\n - Section dividers (`\u2500\u2500 Title \u2500\u2500\u2500\u2500`) replace bare bold headers in summary, agents, and context attribution\n - Tab bar: active tab underlined in magenta, inactive tabs dimmed, bracket syntax removed\n - Status bar: segmented layout with `\u2502` separators; keys bold, labels dim\n - Summary metrics condensed: elapsed/events/compactions on one line, tokens on one line with cache rate and cost\n - Sparklines display peak metadata annotations\n - Progress bars use blessed color tags for consistent coloring\n - Help overlay uses dot-leader alignment for all keybinding rows\n - Empty state hints per panel (e.g. "Tasks appear as your agent works.")\n - Session picker groups sessions by provider with section headers when multiple providers are present\n\n## [0.12.7] - 2026-02-27\n\n### Added\n\n- **HTML Session Report**: `sidekick report` command generates a self-contained HTML report and opens it in the default browser\n - Options: `--session`, `--output`, `--theme` (dark/light), `--no-open`, `--no-thinking`\n - TUI Dashboard: press `r` to generate and open an HTML report for the current session\n\n## [0.12.6] - 2026-02-26\n\n### Added\n\n- **Session Dump Command**: `sidekick dump` exports session data in text, markdown, or JSON format with `--format`, `--width`, and `--expand` options\n- **Plans Panel Re-enabled**: Plans panel restored in CLI dashboard with plan file discovery from `~/.claude/plans/`\n- **Enhanced Status Bar**: Session info display improved with richer metadata\n\n### Fixed\n\n- **Old snapshot format migration**: Restoring pre-0.12.3 session snapshots no longer shows empty timeline entries\n\n### Changed\n\n- **Phrase library moved to shared**: CLI-specific phrase formatting kept local, all phrase content now from `sidekick-shared`\n\n## [0.12.5] - 2026-02-24\n\n### Fixed\n\n- **Update check too slow to notice new versions**: Reduced npm registry cache TTL from 24 hours to 4 hours so upgrade notices appear sooner after a new release\n\n## [0.12.4] - 2026-02-24\n\n### Fixed\n\n- **Session crash on upgrade**: Fixed `d.timestamp.getTime is not a function` error when restoring tool call data from session snapshots \u2014 `Date` objects were serialized to strings by JSON but not rehydrated on restore, causing the session monitor to crash on first run after upgrading from 0.12.2 to 0.12.3\n\n## [0.12.3] - 2026-02-24\n\n### Added\n\n- **Latest-node indicator**: The most recently added node in tree and boxed mind map views is now marked with a yellow indicator\n- **Plan analytics in mind map**: Tree and boxed views now display plan progress and per-step metrics\n - Tree view: plan header shows completion stats; steps show complexity, duration, tokens, tool calls, and errors in metadata brackets\n - Box view: progress bar with completion percentage; steps show right-aligned metrics; subtitle shows step count and total duration\n- **Cross-provider plan extraction**: Shared `PlanExtractor` now handles Claude Code (EnterPlanMode/ExitPlanMode) and OpenCode (`<proposed_plan>` XML) plans \u2014 previously only Codex plans were shown\n- **Enriched plan data model**: Plan steps include duration, token count, tool call count, and error messages\n- **Phase-grouped plan display**: When a plan has phase structure, tree and boxed views group steps under phase headers with context lines from the original plan markdown\n- **Node type filter**: Press `f` on the Mind Map tab to cycle through node type filters (file, tool, task, subagent, command, plan, knowledge-note) \u2014 non-matching sections render dimmed in grey\n\n### Fixed\n\n- **Kanban board regression**: Subagent and plan-step tasks now correctly appear in the kanban board\n\n### Changed\n\n- **Plans panel temporarily disabled**: The Plans panel in the CLI dashboard is disabled until plan-mode event capture is reliably working end-to-end. Plan nodes in the mind map remain active.\n- `DashboardState` now delegates to shared `EventAggregator` instead of maintaining its own aggregation logic\n\n## [0.12.2] - 2026-02-23\n\n### Added\n\n- **Update notifications**: The dashboard now checks the npm registry for newer versions on startup and shows a yellow banner in the status bar when an update is available (e.g., `v0.13.0 available \u2014 npm i -g sidekick-agent-hub`). Results are cached for 24 hours to avoid repeated network requests.\n\n## [0.12.1] - 2026-02-23\n\n### Fixed\n\n- **VS Code integration**: Fixed exit code 127 when the extension launches the CLI dashboard on systems using nvm or volta (node binary not found when shell init is bypassed)\n\n## [0.12.0] - 2026-02-22\n\n### Added\n\n- **"Open CLI Dashboard" VS Code Integration**: New VS Code command `Sidekick: Open CLI Dashboard` launches the TUI dashboard in an integrated terminal\n - Install the CLI with `npm install -g sidekick-agent-hub`\n\n## [0.11.0] - 2026-02-19\n\n### Added\n\n- **Initial Release**: Full-screen TUI dashboard for monitoring agent sessions from the terminal\n - Ink-based terminal UI with panels for sessions, tasks, kanban, mind map, notes, decisions, search, files, and git diff\n - Multi-provider support: auto-detects Claude Code, OpenCode, and Codex sessions\n - Reads from `~/.config/sidekick/` \u2014 the same data files the VS Code extension writes\n - Usage: `sidekick dashboard [--project <path>] [--provider <id>]`\n';
|
|
79133
80136
|
}
|
|
79134
80137
|
});
|
|
79135
80138
|
|
|
@@ -79298,7 +80301,7 @@ function Dashboard({ panels, metrics, staticData, isPinned, pendingSessionPath,
|
|
|
79298
80301
|
lastQuotaAlertKeyRef.current = null;
|
|
79299
80302
|
return;
|
|
79300
80303
|
}
|
|
79301
|
-
const descriptor = (0,
|
|
80304
|
+
const descriptor = (0, import_sidekick_shared18.describeQuotaFailure)(metrics.quota);
|
|
79302
80305
|
if (!descriptor) {
|
|
79303
80306
|
lastQuotaAlertKeyRef.current = null;
|
|
79304
80307
|
return;
|
|
@@ -79874,7 +80877,7 @@ function filterKanbanColumn(item, filter) {
|
|
|
79874
80877
|
data: { status: colData.status, tasks: filtered }
|
|
79875
80878
|
};
|
|
79876
80879
|
}
|
|
79877
|
-
var import_react36,
|
|
80880
|
+
var import_react36, import_sidekick_shared18, import_jsx_runtime16, changelogEntries, SIDE_PANEL_WIDTH, NARROW_SIDE_WIDTH, MIN_SCREEN_WIDTH, MIN_SCREEN_HEIGHT, WIDE_SIDE_WIDTH, initialState;
|
|
79878
80881
|
var init_Dashboard = __esm({
|
|
79879
80882
|
async "src/dashboard/ink/Dashboard.tsx"() {
|
|
79880
80883
|
"use strict";
|
|
@@ -79897,9 +80900,9 @@ var init_Dashboard = __esm({
|
|
|
79897
80900
|
await init_ToastNotification();
|
|
79898
80901
|
await init_mouse();
|
|
79899
80902
|
init_CHANGELOG();
|
|
79900
|
-
|
|
80903
|
+
import_sidekick_shared18 = __toESM(require_dist(), 1);
|
|
79901
80904
|
import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
79902
|
-
changelogEntries = (0,
|
|
80905
|
+
changelogEntries = (0, import_sidekick_shared18.parseChangelog)(CHANGELOG_default, 5);
|
|
79903
80906
|
SIDE_PANEL_WIDTH = 26;
|
|
79904
80907
|
NARROW_SIDE_WIDTH = 22;
|
|
79905
80908
|
MIN_SCREEN_WIDTH = 60;
|
|
@@ -79938,12 +80941,12 @@ import * as fs6 from "fs";
|
|
|
79938
80941
|
function createProviderById(id) {
|
|
79939
80942
|
switch (id) {
|
|
79940
80943
|
case "opencode":
|
|
79941
|
-
return new
|
|
80944
|
+
return new import_sidekick_shared20.OpenCodeProvider();
|
|
79942
80945
|
case "codex":
|
|
79943
|
-
return new
|
|
80946
|
+
return new import_sidekick_shared20.CodexProvider();
|
|
79944
80947
|
case "claude-code":
|
|
79945
80948
|
default:
|
|
79946
|
-
return new
|
|
80949
|
+
return new import_sidekick_shared20.ClaudeCodeProvider();
|
|
79947
80950
|
}
|
|
79948
80951
|
}
|
|
79949
80952
|
function getProviderRuntimeIssue(provider) {
|
|
@@ -79967,7 +80970,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
79967
80970
|
let replay = !!opts.replay;
|
|
79968
80971
|
let activeProvider = provider;
|
|
79969
80972
|
const providerIssue = getProviderRuntimeIssue(provider);
|
|
79970
|
-
const detectedIds = (0,
|
|
80973
|
+
const detectedIds = (0, import_sidekick_shared19.getAllDetectedProviders)();
|
|
79971
80974
|
const additionalProviders = detectedIds.filter((id) => id !== provider.id).map((id) => createProviderById(id));
|
|
79972
80975
|
if (!sessionId) {
|
|
79973
80976
|
const sessions = providerIssue ? [] : provider.findAllSessions(workspacePath);
|
|
@@ -80065,7 +81068,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80065
81068
|
const newSessionId = path4.basename(newSessionPath, path4.extname(newSessionPath));
|
|
80066
81069
|
state.setSessionId(newSessionId);
|
|
80067
81070
|
try {
|
|
80068
|
-
const result = (0,
|
|
81071
|
+
const result = (0, import_sidekick_shared19.createWatcher)({
|
|
80069
81072
|
provider: activeProvider,
|
|
80070
81073
|
workspacePath,
|
|
80071
81074
|
sessionId: newSessionId,
|
|
@@ -80140,7 +81143,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80140
81143
|
const generateReport = () => {
|
|
80141
81144
|
if (!sessionPath) return;
|
|
80142
81145
|
const events = [];
|
|
80143
|
-
const replayResult = (0,
|
|
81146
|
+
const replayResult = (0, import_sidekick_shared19.createWatcher)({
|
|
80144
81147
|
provider: activeProvider,
|
|
80145
81148
|
workspacePath,
|
|
80146
81149
|
sessionId: path4.basename(sessionPath, path4.extname(sessionPath)),
|
|
@@ -80149,11 +81152,11 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80149
81152
|
});
|
|
80150
81153
|
replayResult.watcher.start(true);
|
|
80151
81154
|
replayResult.watcher.stop();
|
|
80152
|
-
const aggregator = new
|
|
81155
|
+
const aggregator = new import_sidekick_shared19.EventAggregator({ providerId: activeProvider.id });
|
|
80153
81156
|
for (const e of events) aggregator.processFollowEvent(e);
|
|
80154
81157
|
const metrics = aggregator.getMetrics();
|
|
80155
|
-
const transcript = (0,
|
|
80156
|
-
const html = (0,
|
|
81158
|
+
const transcript = (0, import_sidekick_shared19.parseTranscript)(sessionPath);
|
|
81159
|
+
const html = (0, import_sidekick_shared19.generateHtmlReport)(metrics, transcript, {
|
|
80157
81160
|
sessionFileName: path4.basename(sessionPath),
|
|
80158
81161
|
includeThinking: true,
|
|
80159
81162
|
includeToolDetail: true,
|
|
@@ -80161,7 +81164,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80161
81164
|
});
|
|
80162
81165
|
const outFile = path4.join(os3.tmpdir(), `sidekick-report-${Date.now()}.html`);
|
|
80163
81166
|
fs6.writeFileSync(outFile, html, "utf-8");
|
|
80164
|
-
(0,
|
|
81167
|
+
(0, import_sidekick_shared19.openInBrowser)(outFile);
|
|
80165
81168
|
};
|
|
80166
81169
|
const instance = render2(
|
|
80167
81170
|
import_react37.default.createElement(Dashboard, {
|
|
@@ -80259,7 +81262,7 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80259
81262
|
let lastSnapshotTime = 0;
|
|
80260
81263
|
const SNAPSHOT_INTERVAL_MS = 3e4;
|
|
80261
81264
|
try {
|
|
80262
|
-
const result = (0,
|
|
81265
|
+
const result = (0, import_sidekick_shared19.createWatcher)({
|
|
80263
81266
|
provider: activeProvider,
|
|
80264
81267
|
workspacePath,
|
|
80265
81268
|
sessionId,
|
|
@@ -80334,13 +81337,13 @@ async function dashboardAction(_opts, cmd) {
|
|
|
80334
81337
|
cleanup();
|
|
80335
81338
|
process.exit(0);
|
|
80336
81339
|
}
|
|
80337
|
-
var import_react37,
|
|
81340
|
+
var import_react37, import_sidekick_shared19, import_sidekick_shared20;
|
|
80338
81341
|
var init_dashboard = __esm({
|
|
80339
81342
|
async "src/commands/dashboard.ts"() {
|
|
80340
81343
|
"use strict";
|
|
80341
81344
|
import_react37 = __toESM(require_react(), 1);
|
|
80342
|
-
import_sidekick_shared18 = __toESM(require_dist(), 1);
|
|
80343
81345
|
import_sidekick_shared19 = __toESM(require_dist(), 1);
|
|
81346
|
+
import_sidekick_shared20 = __toESM(require_dist(), 1);
|
|
80344
81347
|
init_cli();
|
|
80345
81348
|
init_DashboardState();
|
|
80346
81349
|
init_StaticDataLoader();
|
|
@@ -80471,7 +81474,7 @@ async function dumpAction(_opts, cmd) {
|
|
|
80471
81474
|
let sessionPath;
|
|
80472
81475
|
try {
|
|
80473
81476
|
try {
|
|
80474
|
-
const result = (0,
|
|
81477
|
+
const result = (0, import_sidekick_shared21.createWatcher)({
|
|
80475
81478
|
provider,
|
|
80476
81479
|
workspacePath,
|
|
80477
81480
|
sessionId,
|
|
@@ -80492,7 +81495,7 @@ async function dumpAction(_opts, cmd) {
|
|
|
80492
81495
|
`);
|
|
80493
81496
|
process.exit(1);
|
|
80494
81497
|
}
|
|
80495
|
-
const aggregator = new
|
|
81498
|
+
const aggregator = new import_sidekick_shared21.EventAggregator({ providerId: provider.id });
|
|
80496
81499
|
for (const event of events) {
|
|
80497
81500
|
aggregator.processFollowEvent(event);
|
|
80498
81501
|
}
|
|
@@ -80500,14 +81503,14 @@ async function dumpAction(_opts, cmd) {
|
|
|
80500
81503
|
const sessionFileName = path5.basename(sessionPath);
|
|
80501
81504
|
switch (format) {
|
|
80502
81505
|
case "json":
|
|
80503
|
-
process.stdout.write((0,
|
|
81506
|
+
process.stdout.write((0, import_sidekick_shared21.formatSessionJson)(metrics));
|
|
80504
81507
|
break;
|
|
80505
81508
|
case "markdown":
|
|
80506
|
-
process.stdout.write((0,
|
|
81509
|
+
process.stdout.write((0, import_sidekick_shared21.formatSessionMarkdown)(metrics, { expand, sessionFileName }));
|
|
80507
81510
|
break;
|
|
80508
81511
|
case "text":
|
|
80509
81512
|
default:
|
|
80510
|
-
process.stdout.write((0,
|
|
81513
|
+
process.stdout.write((0, import_sidekick_shared21.formatSessionText)(metrics, { width: termWidth, expand }));
|
|
80511
81514
|
break;
|
|
80512
81515
|
}
|
|
80513
81516
|
} finally {
|
|
@@ -80517,11 +81520,11 @@ async function dumpAction(_opts, cmd) {
|
|
|
80517
81520
|
}
|
|
80518
81521
|
}
|
|
80519
81522
|
}
|
|
80520
|
-
var
|
|
81523
|
+
var import_sidekick_shared21;
|
|
80521
81524
|
var init_dump = __esm({
|
|
80522
81525
|
"src/commands/dump.ts"() {
|
|
80523
81526
|
"use strict";
|
|
80524
|
-
|
|
81527
|
+
import_sidekick_shared21 = __toESM(require_dist(), 1);
|
|
80525
81528
|
init_cli();
|
|
80526
81529
|
}
|
|
80527
81530
|
});
|
|
@@ -80591,7 +81594,7 @@ function formatContextText(ctx, slug) {
|
|
|
80591
81594
|
const t = ctx.stats.tokens;
|
|
80592
81595
|
lines.push(`Tokens: ${t.inputTokens.toLocaleString()} in / ${t.outputTokens.toLocaleString()} out`);
|
|
80593
81596
|
lines.push(`Cache: ${t.cacheReadTokens.toLocaleString()} read / ${t.cacheWriteTokens.toLocaleString()} write`);
|
|
80594
|
-
lines.push(`Cost: ${(0,
|
|
81597
|
+
lines.push(`Cost: ${(0, import_sidekick_shared22.formatCost)(ctx.stats.cost)}`);
|
|
80595
81598
|
lines.push("");
|
|
80596
81599
|
}
|
|
80597
81600
|
if (ctx.sessionSummaries.length > 0) {
|
|
@@ -80611,11 +81614,11 @@ async function contextAction(_opts, cmd) {
|
|
|
80611
81614
|
const workspacePath = globalOpts.project || process.cwd();
|
|
80612
81615
|
const jsonOutput = !!globalOpts.json || !!opts.json;
|
|
80613
81616
|
const fidelity = opts.fidelity || "full";
|
|
80614
|
-
const slug = (0,
|
|
80615
|
-
const slugRaw = (0,
|
|
81617
|
+
const slug = (0, import_sidekick_shared22.getProjectSlug)(workspacePath);
|
|
81618
|
+
const slugRaw = (0, import_sidekick_shared22.getProjectSlugRaw)(workspacePath);
|
|
80616
81619
|
const effectiveSlug = slug !== slugRaw ? slugRaw : slug;
|
|
80617
81620
|
try {
|
|
80618
|
-
const ctx = await (0,
|
|
81621
|
+
const ctx = await (0, import_sidekick_shared22.composeContext)(effectiveSlug, fidelity, provider, workspacePath);
|
|
80619
81622
|
if (jsonOutput) {
|
|
80620
81623
|
process.stdout.write(JSON.stringify(ctx, null, 2) + "\n");
|
|
80621
81624
|
} else {
|
|
@@ -80633,11 +81636,11 @@ async function contextAction(_opts, cmd) {
|
|
|
80633
81636
|
}
|
|
80634
81637
|
}
|
|
80635
81638
|
}
|
|
80636
|
-
var
|
|
81639
|
+
var import_sidekick_shared22;
|
|
80637
81640
|
var init_context = __esm({
|
|
80638
81641
|
"src/commands/context.ts"() {
|
|
80639
81642
|
"use strict";
|
|
80640
|
-
|
|
81643
|
+
import_sidekick_shared22 = __toESM(require_dist(), 1);
|
|
80641
81644
|
init_cli();
|
|
80642
81645
|
}
|
|
80643
81646
|
});
|
|
@@ -80664,7 +81667,7 @@ async function reportAction(_opts, cmd) {
|
|
|
80664
81667
|
let sessionPath;
|
|
80665
81668
|
try {
|
|
80666
81669
|
try {
|
|
80667
|
-
const result = (0,
|
|
81670
|
+
const result = (0, import_sidekick_shared23.createWatcher)({
|
|
80668
81671
|
provider,
|
|
80669
81672
|
workspacePath,
|
|
80670
81673
|
sessionId,
|
|
@@ -80685,12 +81688,12 @@ async function reportAction(_opts, cmd) {
|
|
|
80685
81688
|
`);
|
|
80686
81689
|
process.exit(1);
|
|
80687
81690
|
}
|
|
80688
|
-
const aggregator = new
|
|
81691
|
+
const aggregator = new import_sidekick_shared23.EventAggregator({ providerId: provider.id });
|
|
80689
81692
|
for (const event of events) {
|
|
80690
81693
|
aggregator.processFollowEvent(event);
|
|
80691
81694
|
}
|
|
80692
81695
|
const metrics = aggregator.getMetrics();
|
|
80693
|
-
const transcript = (0,
|
|
81696
|
+
const transcript = (0, import_sidekick_shared23.parseTranscript)(sessionPath);
|
|
80694
81697
|
const sessionFileName = path6.basename(sessionPath);
|
|
80695
81698
|
const reportOptions = {
|
|
80696
81699
|
sessionFileName,
|
|
@@ -80698,13 +81701,13 @@ async function reportAction(_opts, cmd) {
|
|
|
80698
81701
|
includeToolDetail: true,
|
|
80699
81702
|
theme
|
|
80700
81703
|
};
|
|
80701
|
-
const html = (0,
|
|
81704
|
+
const html = (0, import_sidekick_shared23.generateHtmlReport)(metrics, transcript, reportOptions);
|
|
80702
81705
|
const outFile = outputPath || path6.join(os4.tmpdir(), `sidekick-report-${Date.now()}.html`);
|
|
80703
81706
|
fs8.writeFileSync(outFile, html, "utf-8");
|
|
80704
81707
|
process.stderr.write(`Report written to: ${outFile}
|
|
80705
81708
|
`);
|
|
80706
81709
|
if (!noOpen) {
|
|
80707
|
-
(0,
|
|
81710
|
+
(0, import_sidekick_shared23.openInBrowser)(outFile);
|
|
80708
81711
|
}
|
|
80709
81712
|
} finally {
|
|
80710
81713
|
try {
|
|
@@ -80713,11 +81716,11 @@ async function reportAction(_opts, cmd) {
|
|
|
80713
81716
|
}
|
|
80714
81717
|
}
|
|
80715
81718
|
}
|
|
80716
|
-
var
|
|
81719
|
+
var import_sidekick_shared23;
|
|
80717
81720
|
var init_report = __esm({
|
|
80718
81721
|
"src/commands/report.ts"() {
|
|
80719
81722
|
"use strict";
|
|
80720
|
-
|
|
81723
|
+
import_sidekick_shared23 = __toESM(require_dist(), 1);
|
|
80721
81724
|
init_cli();
|
|
80722
81725
|
}
|
|
80723
81726
|
});
|
|
@@ -80767,7 +81770,7 @@ async function searchAction(_opts, cmd) {
|
|
|
80767
81770
|
const { encodeWorkspacePath } = await Promise.resolve().then(() => __toESM(require_dist(), 1));
|
|
80768
81771
|
projectSlug = encodeWorkspacePath(resolved);
|
|
80769
81772
|
}
|
|
80770
|
-
const results = await (0,
|
|
81773
|
+
const results = await (0, import_sidekick_shared24.searchSessions)(provider, query.trim(), {
|
|
80771
81774
|
projectSlug,
|
|
80772
81775
|
maxResults: limit
|
|
80773
81776
|
});
|
|
@@ -80803,12 +81806,12 @@ async function searchAction(_opts, cmd) {
|
|
|
80803
81806
|
}
|
|
80804
81807
|
}
|
|
80805
81808
|
}
|
|
80806
|
-
var
|
|
81809
|
+
var import_sidekick_shared24;
|
|
80807
81810
|
var init_search = __esm({
|
|
80808
81811
|
"src/commands/search.ts"() {
|
|
80809
81812
|
"use strict";
|
|
80810
81813
|
init_source();
|
|
80811
|
-
|
|
81814
|
+
import_sidekick_shared24 = __toESM(require_dist(), 1);
|
|
80812
81815
|
init_cli();
|
|
80813
81816
|
}
|
|
80814
81817
|
});
|
|
@@ -80867,12 +81870,12 @@ async function tasksAction(_opts, cmd) {
|
|
|
80867
81870
|
const jsonOutput = !!globalOpts.json;
|
|
80868
81871
|
const statusFilter = opts.status || "all";
|
|
80869
81872
|
try {
|
|
80870
|
-
const rawSlug = (0,
|
|
80871
|
-
const resolvedSlug = (0,
|
|
81873
|
+
const rawSlug = (0, import_sidekick_shared25.getProjectSlugRaw)(workspacePath);
|
|
81874
|
+
const resolvedSlug = (0, import_sidekick_shared25.getProjectSlug)(workspacePath);
|
|
80872
81875
|
const slugs = rawSlug !== resolvedSlug ? [rawSlug, resolvedSlug] : [rawSlug];
|
|
80873
81876
|
let tasks = [];
|
|
80874
81877
|
for (const slug of slugs) {
|
|
80875
|
-
tasks = await (0,
|
|
81878
|
+
tasks = await (0, import_sidekick_shared25.readTasks)(slug, { status: statusFilter });
|
|
80876
81879
|
if (tasks.length > 0) break;
|
|
80877
81880
|
}
|
|
80878
81881
|
if (jsonOutput) {
|
|
@@ -80887,12 +81890,12 @@ async function tasksAction(_opts, cmd) {
|
|
|
80887
81890
|
process.exit(1);
|
|
80888
81891
|
}
|
|
80889
81892
|
}
|
|
80890
|
-
var
|
|
81893
|
+
var import_sidekick_shared25, STATUS_COLORS, STATUS_ICONS2;
|
|
80891
81894
|
var init_tasks = __esm({
|
|
80892
81895
|
"src/commands/tasks.ts"() {
|
|
80893
81896
|
"use strict";
|
|
80894
81897
|
init_source();
|
|
80895
|
-
|
|
81898
|
+
import_sidekick_shared25 = __toESM(require_dist(), 1);
|
|
80896
81899
|
STATUS_COLORS = {
|
|
80897
81900
|
pending: source_default.yellow,
|
|
80898
81901
|
in_progress: source_default.blue,
|
|
@@ -80958,12 +81961,12 @@ async function decisionsAction(_opts, cmd) {
|
|
|
80958
81961
|
const search = opts.search;
|
|
80959
81962
|
const limit = opts.limit ? parseInt(opts.limit, 10) : void 0;
|
|
80960
81963
|
try {
|
|
80961
|
-
const rawSlug = (0,
|
|
80962
|
-
const resolvedSlug = (0,
|
|
81964
|
+
const rawSlug = (0, import_sidekick_shared26.getProjectSlugRaw)(workspacePath);
|
|
81965
|
+
const resolvedSlug = (0, import_sidekick_shared26.getProjectSlug)(workspacePath);
|
|
80963
81966
|
const slugs = rawSlug !== resolvedSlug ? [rawSlug, resolvedSlug] : [rawSlug];
|
|
80964
81967
|
let decisions = [];
|
|
80965
81968
|
for (const slug of slugs) {
|
|
80966
|
-
decisions = await (0,
|
|
81969
|
+
decisions = await (0, import_sidekick_shared26.readDecisions)(slug, { search, limit });
|
|
80967
81970
|
if (decisions.length > 0) break;
|
|
80968
81971
|
}
|
|
80969
81972
|
if (jsonOutput) {
|
|
@@ -80978,12 +81981,12 @@ async function decisionsAction(_opts, cmd) {
|
|
|
80978
81981
|
process.exit(1);
|
|
80979
81982
|
}
|
|
80980
81983
|
}
|
|
80981
|
-
var
|
|
81984
|
+
var import_sidekick_shared26, SOURCE_LABELS;
|
|
80982
81985
|
var init_decisions = __esm({
|
|
80983
81986
|
"src/commands/decisions.ts"() {
|
|
80984
81987
|
"use strict";
|
|
80985
81988
|
init_source();
|
|
80986
|
-
|
|
81989
|
+
import_sidekick_shared26 = __toESM(require_dist(), 1);
|
|
80987
81990
|
SOURCE_LABELS = {
|
|
80988
81991
|
recovery_pattern: "recovery",
|
|
80989
81992
|
plan_mode: "plan",
|
|
@@ -81045,12 +82048,12 @@ async function notesAction(_opts, cmd) {
|
|
|
81045
82048
|
const type = opts.type;
|
|
81046
82049
|
const status = opts.status;
|
|
81047
82050
|
try {
|
|
81048
|
-
const rawSlug = (0,
|
|
81049
|
-
const resolvedSlug = (0,
|
|
82051
|
+
const rawSlug = (0, import_sidekick_shared27.getProjectSlugRaw)(workspacePath);
|
|
82052
|
+
const resolvedSlug = (0, import_sidekick_shared27.getProjectSlug)(workspacePath);
|
|
81050
82053
|
const slugs = rawSlug !== resolvedSlug ? [rawSlug, resolvedSlug] : [rawSlug];
|
|
81051
82054
|
let notes = [];
|
|
81052
82055
|
for (const slug of slugs) {
|
|
81053
|
-
notes = await (0,
|
|
82056
|
+
notes = await (0, import_sidekick_shared27.readNotes)(slug, { file, type, status });
|
|
81054
82057
|
if (notes.length > 0) break;
|
|
81055
82058
|
}
|
|
81056
82059
|
if (jsonOutput) {
|
|
@@ -81065,12 +82068,12 @@ async function notesAction(_opts, cmd) {
|
|
|
81065
82068
|
process.exit(1);
|
|
81066
82069
|
}
|
|
81067
82070
|
}
|
|
81068
|
-
var
|
|
82071
|
+
var import_sidekick_shared27, TYPE_COLORS, IMPORTANCE_COLORS;
|
|
81069
82072
|
var init_notes = __esm({
|
|
81070
82073
|
"src/commands/notes.ts"() {
|
|
81071
82074
|
"use strict";
|
|
81072
82075
|
init_source();
|
|
81073
|
-
|
|
82076
|
+
import_sidekick_shared27 = __toESM(require_dist(), 1);
|
|
81074
82077
|
TYPE_COLORS = {
|
|
81075
82078
|
gotcha: source_default.red,
|
|
81076
82079
|
pattern: source_default.blue,
|
|
@@ -81115,7 +82118,7 @@ function printStatsSummary(history) {
|
|
|
81115
82118
|
`);
|
|
81116
82119
|
process.stdout.write(` ${source_default.dim(" Cache read:")} ${formatNumber(at.tokens.cacheReadTokens)}
|
|
81117
82120
|
`);
|
|
81118
|
-
process.stdout.write(` ${source_default.dim("Total cost:")} ${source_default.green((0,
|
|
82121
|
+
process.stdout.write(` ${source_default.dim("Total cost:")} ${source_default.green((0, import_sidekick_shared28.formatCost)(at.totalCost))}
|
|
81119
82122
|
`);
|
|
81120
82123
|
process.stdout.write(` ${source_default.dim("Period:")} ${at.firstDate} \u2014 ${at.lastDate}
|
|
81121
82124
|
`);
|
|
@@ -81131,7 +82134,7 @@ function printStatsSummary(history) {
|
|
|
81131
82134
|
costStr = source_default.yellow(" (\u2014)");
|
|
81132
82135
|
unpricedModels.push(m.model);
|
|
81133
82136
|
} else if (m.cost > 0) {
|
|
81134
|
-
costStr = source_default.dim(` (${(0,
|
|
82137
|
+
costStr = source_default.dim(` (${(0, import_sidekick_shared28.formatCost)(m.cost)})`);
|
|
81135
82138
|
}
|
|
81136
82139
|
process.stdout.write(` ${source_default.cyan(m.model.padEnd(30))} ${formatNumber(m.calls).padStart(8)} calls${costStr}
|
|
81137
82140
|
`);
|
|
@@ -81166,7 +82169,7 @@ function printStatsSummary(history) {
|
|
|
81166
82169
|
for (const day of recent) {
|
|
81167
82170
|
const tokens = day.tokens.inputTokens + day.tokens.outputTokens;
|
|
81168
82171
|
process.stdout.write(
|
|
81169
|
-
` ${day.date.padEnd(14)}${String(day.sessionCount).padStart(10)}${String(day.messageCount).padStart(10)}${formatNumber(tokens).padStart(12)}${(0,
|
|
82172
|
+
` ${day.date.padEnd(14)}${String(day.sessionCount).padStart(10)}${String(day.messageCount).padStart(10)}${formatNumber(tokens).padStart(12)}${(0, import_sidekick_shared28.formatCost)(day.totalCost).padStart(10)}
|
|
81170
82173
|
`
|
|
81171
82174
|
);
|
|
81172
82175
|
}
|
|
@@ -81177,7 +82180,7 @@ async function statsAction(_opts, cmd) {
|
|
|
81177
82180
|
const globalOpts = cmd.parent.opts();
|
|
81178
82181
|
const jsonOutput = !!globalOpts.json;
|
|
81179
82182
|
try {
|
|
81180
|
-
const history = await (0,
|
|
82183
|
+
const history = await (0, import_sidekick_shared28.readHistory)();
|
|
81181
82184
|
if (!history) {
|
|
81182
82185
|
if (jsonOutput) {
|
|
81183
82186
|
process.stdout.write(JSON.stringify(null) + "\n");
|
|
@@ -81199,12 +82202,12 @@ async function statsAction(_opts, cmd) {
|
|
|
81199
82202
|
process.exit(1);
|
|
81200
82203
|
}
|
|
81201
82204
|
}
|
|
81202
|
-
var
|
|
82205
|
+
var import_sidekick_shared28;
|
|
81203
82206
|
var init_stats = __esm({
|
|
81204
82207
|
"src/commands/stats.ts"() {
|
|
81205
82208
|
"use strict";
|
|
81206
82209
|
init_source();
|
|
81207
|
-
|
|
82210
|
+
import_sidekick_shared28 = __toESM(require_dist(), 1);
|
|
81208
82211
|
}
|
|
81209
82212
|
});
|
|
81210
82213
|
|
|
@@ -81323,14 +82326,14 @@ async function claudeQuotaAction(jsonOutput) {
|
|
|
81323
82326
|
const service = new QuotaService();
|
|
81324
82327
|
const [quota, peak] = await Promise.all([
|
|
81325
82328
|
service.fetchOnce(),
|
|
81326
|
-
(0,
|
|
82329
|
+
(0, import_sidekick_shared29.fetchPeakHoursStatus)()
|
|
81327
82330
|
]);
|
|
81328
82331
|
if (!quota.available) {
|
|
81329
82332
|
if (jsonOutput) {
|
|
81330
82333
|
process.stdout.write(JSON.stringify({ ...quota, peak }, null, 2) + "\n");
|
|
81331
82334
|
return;
|
|
81332
82335
|
}
|
|
81333
|
-
const descriptor = (0,
|
|
82336
|
+
const descriptor = (0, import_sidekick_shared29.describeQuotaFailure)(quota);
|
|
81334
82337
|
let msg;
|
|
81335
82338
|
let color = source_default.red;
|
|
81336
82339
|
if (descriptor) {
|
|
@@ -81365,7 +82368,7 @@ async function claudeQuotaAction(jsonOutput) {
|
|
|
81365
82368
|
const sevenReset = formatTimeUntil(quota.sevenDay.resetsAt);
|
|
81366
82369
|
const fiveProj = quota.projectedFiveHour != null ? ` ${source_default.dim("\u2192")} ${getUtilizationColor2(quota.projectedFiveHour)(String(Math.round(quota.projectedFiveHour)).padStart(3) + "%")}` : "";
|
|
81367
82370
|
const sevenProj = quota.projectedSevenDay != null ? ` ${source_default.dim("\u2192")} ${getUtilizationColor2(quota.projectedSevenDay)(String(Math.round(quota.projectedSevenDay)).padStart(3) + "%")}` : "";
|
|
81368
|
-
const active = (0,
|
|
82371
|
+
const active = (0, import_sidekick_shared29.getActiveAccount)();
|
|
81369
82372
|
if (active) {
|
|
81370
82373
|
process.stdout.write(source_default.dim(`Account: ${active.email}${active.label ? ` (${active.label})` : ""}
|
|
81371
82374
|
`));
|
|
@@ -81386,13 +82389,13 @@ function printPeakHoursSummary(peak) {
|
|
|
81386
82389
|
}
|
|
81387
82390
|
async function codexQuotaAction(provider, globalOpts, jsonOutput) {
|
|
81388
82391
|
const workspacePath = globalOpts.project || process.cwd();
|
|
81389
|
-
const activeAccount = (0,
|
|
81390
|
-
let quota = activeAccount ? (0,
|
|
82392
|
+
const activeAccount = (0, import_sidekick_shared29.getActiveCodexAccount)();
|
|
82393
|
+
let quota = activeAccount ? (0, import_sidekick_shared29.readQuotaSnapshot)("codex", activeAccount.id) : null;
|
|
81391
82394
|
const sessions = provider.findAllSessions(workspacePath);
|
|
81392
82395
|
if (sessions.length > 0) {
|
|
81393
82396
|
const captured = { rl: void 0 };
|
|
81394
82397
|
try {
|
|
81395
|
-
const result = (0,
|
|
82398
|
+
const result = (0, import_sidekick_shared29.createWatcher)({
|
|
81396
82399
|
provider,
|
|
81397
82400
|
workspacePath,
|
|
81398
82401
|
callbacks: {
|
|
@@ -81409,7 +82412,7 @@ async function codexQuotaAction(provider, globalOpts, jsonOutput) {
|
|
|
81409
82412
|
result.watcher.stop();
|
|
81410
82413
|
} catch {
|
|
81411
82414
|
}
|
|
81412
|
-
const liveQuota = captured.rl ? (0,
|
|
82415
|
+
const liveQuota = captured.rl ? (0, import_sidekick_shared29.quotaFromCodexRateLimits)({
|
|
81413
82416
|
primary: captured.rl.primary ? {
|
|
81414
82417
|
used_percent: captured.rl.primary.usedPercent,
|
|
81415
82418
|
window_minutes: captured.rl.primary.windowMinutes,
|
|
@@ -81424,7 +82427,7 @@ async function codexQuotaAction(provider, globalOpts, jsonOutput) {
|
|
|
81424
82427
|
if (liveQuota) {
|
|
81425
82428
|
quota = liveQuota;
|
|
81426
82429
|
if (activeAccount) {
|
|
81427
|
-
(0,
|
|
82430
|
+
(0, import_sidekick_shared29.writeQuotaSnapshot)("codex", activeAccount.id, liveQuota);
|
|
81428
82431
|
}
|
|
81429
82432
|
}
|
|
81430
82433
|
}
|
|
@@ -81468,12 +82471,12 @@ async function codexQuotaAction(provider, globalOpts, jsonOutput) {
|
|
|
81468
82471
|
`);
|
|
81469
82472
|
}
|
|
81470
82473
|
}
|
|
81471
|
-
var
|
|
82474
|
+
var import_sidekick_shared29;
|
|
81472
82475
|
var init_quota = __esm({
|
|
81473
82476
|
"src/commands/quota.ts"() {
|
|
81474
82477
|
"use strict";
|
|
81475
82478
|
init_source();
|
|
81476
|
-
|
|
82479
|
+
import_sidekick_shared29 = __toESM(require_dist(), 1);
|
|
81477
82480
|
init_cli();
|
|
81478
82481
|
init_QuotaService();
|
|
81479
82482
|
init_peakHoursRender();
|
|
@@ -81526,9 +82529,9 @@ async function statusAction(_opts, cmd) {
|
|
|
81526
82529
|
const providerId = resolveProviderId(globalOpts);
|
|
81527
82530
|
const wantsPeak = providerId === "claude-code";
|
|
81528
82531
|
const [claude, openai, peak] = await Promise.all([
|
|
81529
|
-
(0,
|
|
81530
|
-
(0,
|
|
81531
|
-
wantsPeak ? (0,
|
|
82532
|
+
(0, import_sidekick_shared30.fetchProviderStatus)(),
|
|
82533
|
+
(0, import_sidekick_shared30.fetchOpenAIStatus)(),
|
|
82534
|
+
wantsPeak ? (0, import_sidekick_shared30.fetchPeakHoursStatus)() : Promise.resolve(null)
|
|
81532
82535
|
]);
|
|
81533
82536
|
if (jsonOutput) {
|
|
81534
82537
|
process.stdout.write(JSON.stringify({ claude, openai, peak }, null, 2) + "\n");
|
|
@@ -81542,12 +82545,12 @@ async function statusAction(_opts, cmd) {
|
|
|
81542
82545
|
printPeakHoursBlock(peak);
|
|
81543
82546
|
}
|
|
81544
82547
|
}
|
|
81545
|
-
var
|
|
82548
|
+
var import_sidekick_shared30;
|
|
81546
82549
|
var init_status = __esm({
|
|
81547
82550
|
"src/commands/status.ts"() {
|
|
81548
82551
|
"use strict";
|
|
81549
82552
|
init_source();
|
|
81550
|
-
|
|
82553
|
+
import_sidekick_shared30 = __toESM(require_dist(), 1);
|
|
81551
82554
|
init_peakHoursRender();
|
|
81552
82555
|
init_cli();
|
|
81553
82556
|
}
|
|
@@ -81561,18 +82564,18 @@ __export(peak_exports, {
|
|
|
81561
82564
|
async function peakAction(_opts, cmd) {
|
|
81562
82565
|
const globalOpts = cmd.parent.opts();
|
|
81563
82566
|
const jsonOutput = !!globalOpts.json;
|
|
81564
|
-
const state = await (0,
|
|
82567
|
+
const state = await (0, import_sidekick_shared31.fetchPeakHoursStatus)();
|
|
81565
82568
|
if (jsonOutput) {
|
|
81566
82569
|
process.stdout.write(JSON.stringify(state, null, 2) + "\n");
|
|
81567
82570
|
return;
|
|
81568
82571
|
}
|
|
81569
82572
|
printPeakHoursBlock(state);
|
|
81570
82573
|
}
|
|
81571
|
-
var
|
|
82574
|
+
var import_sidekick_shared31;
|
|
81572
82575
|
var init_peak = __esm({
|
|
81573
82576
|
"src/commands/peak.ts"() {
|
|
81574
82577
|
"use strict";
|
|
81575
|
-
|
|
82578
|
+
import_sidekick_shared31 = __toESM(require_dist(), 1);
|
|
81576
82579
|
init_peakHoursRender();
|
|
81577
82580
|
}
|
|
81578
82581
|
});
|
|
@@ -81604,13 +82607,13 @@ async function accountAction(_opts, cmd) {
|
|
|
81604
82607
|
}
|
|
81605
82608
|
function claudeAccountAction(opts, jsonOutput) {
|
|
81606
82609
|
if (opts.add) {
|
|
81607
|
-
const result = (0,
|
|
82610
|
+
const result = (0, import_sidekick_shared32.addCurrentAccount)(opts.label);
|
|
81608
82611
|
if (!result.success) {
|
|
81609
82612
|
process.stderr.write(source_default.red(result.error ?? "Failed to save account.") + "\n");
|
|
81610
82613
|
process.exit(1);
|
|
81611
82614
|
return;
|
|
81612
82615
|
}
|
|
81613
|
-
const active2 = (0,
|
|
82616
|
+
const active2 = (0, import_sidekick_shared32.readActiveClaudeAccount)();
|
|
81614
82617
|
if (jsonOutput) {
|
|
81615
82618
|
process.stdout.write(JSON.stringify({ action: "added", provider: "claude-code", email: active2?.email, label: opts.label }) + "\n");
|
|
81616
82619
|
} else {
|
|
@@ -81619,14 +82622,14 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81619
82622
|
return;
|
|
81620
82623
|
}
|
|
81621
82624
|
if (opts.remove) {
|
|
81622
|
-
const accounts2 = (0,
|
|
82625
|
+
const accounts2 = (0, import_sidekick_shared32.listAccounts)();
|
|
81623
82626
|
const target = findClaudeAccount(opts.remove, accounts2);
|
|
81624
82627
|
if (!target) {
|
|
81625
82628
|
process.stderr.write(source_default.red(`Account "${opts.remove}" not found.`) + "\n");
|
|
81626
82629
|
process.exit(1);
|
|
81627
82630
|
return;
|
|
81628
82631
|
}
|
|
81629
|
-
const result = (0,
|
|
82632
|
+
const result = (0, import_sidekick_shared32.removeAccount)(target.uuid);
|
|
81630
82633
|
if (!result.success) {
|
|
81631
82634
|
process.stderr.write(source_default.red(result.error ?? "Failed to remove account.") + "\n");
|
|
81632
82635
|
process.exit(1);
|
|
@@ -81640,14 +82643,14 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81640
82643
|
return;
|
|
81641
82644
|
}
|
|
81642
82645
|
if (opts.switchTo) {
|
|
81643
|
-
const accounts2 = (0,
|
|
82646
|
+
const accounts2 = (0, import_sidekick_shared32.listAccounts)();
|
|
81644
82647
|
const target = findClaudeAccount(opts.switchTo, accounts2);
|
|
81645
82648
|
if (!target) {
|
|
81646
82649
|
process.stderr.write(source_default.red(`Account "${opts.switchTo}" not found.`) + "\n");
|
|
81647
82650
|
process.exit(1);
|
|
81648
82651
|
return;
|
|
81649
82652
|
}
|
|
81650
|
-
const result = (0,
|
|
82653
|
+
const result = (0, import_sidekick_shared32.switchToAccount)(target.uuid);
|
|
81651
82654
|
if (!result.success) {
|
|
81652
82655
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch.") + "\n");
|
|
81653
82656
|
process.exit(1);
|
|
@@ -81661,17 +82664,17 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81661
82664
|
return;
|
|
81662
82665
|
}
|
|
81663
82666
|
if (opts.switch) {
|
|
81664
|
-
const accounts2 = (0,
|
|
82667
|
+
const accounts2 = (0, import_sidekick_shared32.listAccounts)();
|
|
81665
82668
|
if (accounts2.length < 2) {
|
|
81666
82669
|
process.stderr.write(source_default.yellow("Need at least 2 saved accounts to switch.") + "\n");
|
|
81667
82670
|
process.exit(1);
|
|
81668
82671
|
return;
|
|
81669
82672
|
}
|
|
81670
|
-
const active2 = (0,
|
|
82673
|
+
const active2 = (0, import_sidekick_shared32.getActiveAccount)();
|
|
81671
82674
|
const currentIdx = active2 ? accounts2.findIndex((a) => a.uuid === active2.uuid) : -1;
|
|
81672
82675
|
const nextIdx = (currentIdx + 1) % accounts2.length;
|
|
81673
82676
|
const target = accounts2[nextIdx];
|
|
81674
|
-
const result = (0,
|
|
82677
|
+
const result = (0, import_sidekick_shared32.switchToAccount)(target.uuid);
|
|
81675
82678
|
if (!result.success) {
|
|
81676
82679
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch.") + "\n");
|
|
81677
82680
|
process.exit(1);
|
|
@@ -81684,9 +82687,9 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81684
82687
|
}
|
|
81685
82688
|
return;
|
|
81686
82689
|
}
|
|
81687
|
-
const accounts = (0,
|
|
82690
|
+
const accounts = (0, import_sidekick_shared32.listAccounts)();
|
|
81688
82691
|
if (accounts.length === 0) {
|
|
81689
|
-
const current = (0,
|
|
82692
|
+
const current = (0, import_sidekick_shared32.readActiveClaudeAccount)();
|
|
81690
82693
|
if (jsonOutput) {
|
|
81691
82694
|
process.stdout.write(JSON.stringify({ provider: "claude-code", accounts: [], current: current ?? null }) + "\n");
|
|
81692
82695
|
} else if (current) {
|
|
@@ -81698,14 +82701,14 @@ function claudeAccountAction(opts, jsonOutput) {
|
|
|
81698
82701
|
return;
|
|
81699
82702
|
}
|
|
81700
82703
|
if (jsonOutput) {
|
|
81701
|
-
const active2 = (0,
|
|
82704
|
+
const active2 = (0, import_sidekick_shared32.getActiveAccount)();
|
|
81702
82705
|
process.stdout.write(JSON.stringify({
|
|
81703
82706
|
provider: "claude-code",
|
|
81704
82707
|
accounts: accounts.map((a) => ({ ...a, active: a.uuid === active2?.uuid }))
|
|
81705
82708
|
}, null, 2) + "\n");
|
|
81706
82709
|
return;
|
|
81707
82710
|
}
|
|
81708
|
-
const active = (0,
|
|
82711
|
+
const active = (0, import_sidekick_shared32.getActiveAccount)();
|
|
81709
82712
|
process.stdout.write(source_default.bold("Claude Accounts\n"));
|
|
81710
82713
|
process.stdout.write(source_default.dim("\u2500".repeat(50) + "\n"));
|
|
81711
82714
|
for (const account of accounts) {
|
|
@@ -81752,7 +82755,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81752
82755
|
process.exit(1);
|
|
81753
82756
|
return;
|
|
81754
82757
|
}
|
|
81755
|
-
const prepared = (0,
|
|
82758
|
+
const prepared = (0, import_sidekick_shared32.prepareCodexAccount)(opts.label);
|
|
81756
82759
|
if (!prepared.success) {
|
|
81757
82760
|
process.stderr.write(source_default.red(prepared.error ?? "Failed to prepare Codex account.") + "\n");
|
|
81758
82761
|
process.exit(1);
|
|
@@ -81770,14 +82773,14 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81770
82773
|
process.exit(1);
|
|
81771
82774
|
return;
|
|
81772
82775
|
}
|
|
81773
|
-
const finalized = (0,
|
|
82776
|
+
const finalized = (0, import_sidekick_shared32.finalizeCodexAccount)(prepared.profileId);
|
|
81774
82777
|
if (!finalized.success) {
|
|
81775
82778
|
process.stderr.write(source_default.red(finalized.error ?? "Failed to finalize Codex account.") + "\n");
|
|
81776
82779
|
process.exit(1);
|
|
81777
82780
|
return;
|
|
81778
82781
|
}
|
|
81779
82782
|
}
|
|
81780
|
-
const active2 = (0,
|
|
82783
|
+
const active2 = (0, import_sidekick_shared32.getActiveCodexAccount)();
|
|
81781
82784
|
if (jsonOutput) {
|
|
81782
82785
|
process.stdout.write(JSON.stringify({
|
|
81783
82786
|
action: "added",
|
|
@@ -81793,14 +82796,14 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81793
82796
|
return;
|
|
81794
82797
|
}
|
|
81795
82798
|
if (opts.remove) {
|
|
81796
|
-
const accounts2 = (0,
|
|
82799
|
+
const accounts2 = (0, import_sidekick_shared32.listCodexAccounts)();
|
|
81797
82800
|
const target = findCodexAccount(opts.remove, accounts2);
|
|
81798
82801
|
if (!target) {
|
|
81799
82802
|
process.stderr.write(source_default.red(`Codex account "${opts.remove}" not found.`) + "\n");
|
|
81800
82803
|
process.exit(1);
|
|
81801
82804
|
return;
|
|
81802
82805
|
}
|
|
81803
|
-
const result = (0,
|
|
82806
|
+
const result = (0, import_sidekick_shared32.removeCodexAccount)(target.id);
|
|
81804
82807
|
if (!result.success) {
|
|
81805
82808
|
process.stderr.write(source_default.red(result.error ?? "Failed to remove Codex account.") + "\n");
|
|
81806
82809
|
process.exit(1);
|
|
@@ -81814,14 +82817,14 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81814
82817
|
return;
|
|
81815
82818
|
}
|
|
81816
82819
|
if (opts.switchTo) {
|
|
81817
|
-
const accounts2 = (0,
|
|
82820
|
+
const accounts2 = (0, import_sidekick_shared32.listCodexAccounts)();
|
|
81818
82821
|
const target = findCodexAccount(opts.switchTo, accounts2);
|
|
81819
82822
|
if (!target) {
|
|
81820
82823
|
process.stderr.write(source_default.red(`Codex account "${opts.switchTo}" not found.`) + "\n");
|
|
81821
82824
|
process.exit(1);
|
|
81822
82825
|
return;
|
|
81823
82826
|
}
|
|
81824
|
-
const result = (0,
|
|
82827
|
+
const result = (0, import_sidekick_shared32.switchToCodexAccount)(target.id);
|
|
81825
82828
|
if (!result.success) {
|
|
81826
82829
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch Codex account.") + "\n");
|
|
81827
82830
|
process.exit(1);
|
|
@@ -81835,17 +82838,17 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81835
82838
|
return;
|
|
81836
82839
|
}
|
|
81837
82840
|
if (opts.switch) {
|
|
81838
|
-
const accounts2 = (0,
|
|
82841
|
+
const accounts2 = (0, import_sidekick_shared32.listCodexAccounts)();
|
|
81839
82842
|
if (accounts2.length < 2) {
|
|
81840
82843
|
process.stderr.write(source_default.yellow("Need at least 2 saved Codex accounts to switch.") + "\n");
|
|
81841
82844
|
process.exit(1);
|
|
81842
82845
|
return;
|
|
81843
82846
|
}
|
|
81844
|
-
const active2 = (0,
|
|
82847
|
+
const active2 = (0, import_sidekick_shared32.getActiveCodexAccount)();
|
|
81845
82848
|
const currentIdx = active2 ? accounts2.findIndex((account) => account.id === active2.id) : -1;
|
|
81846
82849
|
const nextIdx = (currentIdx + 1) % accounts2.length;
|
|
81847
82850
|
const target = accounts2[nextIdx];
|
|
81848
|
-
const result = (0,
|
|
82851
|
+
const result = (0, import_sidekick_shared32.switchToCodexAccount)(target.id);
|
|
81849
82852
|
if (!result.success) {
|
|
81850
82853
|
process.stderr.write(source_default.red(result.error ?? "Failed to switch Codex account.") + "\n");
|
|
81851
82854
|
process.exit(1);
|
|
@@ -81858,7 +82861,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81858
82861
|
}
|
|
81859
82862
|
return;
|
|
81860
82863
|
}
|
|
81861
|
-
const accounts = (0,
|
|
82864
|
+
const accounts = (0, import_sidekick_shared32.listCodexAccounts)();
|
|
81862
82865
|
if (accounts.length === 0) {
|
|
81863
82866
|
if (jsonOutput) {
|
|
81864
82867
|
process.stdout.write(JSON.stringify({ provider: "codex", accounts: [], current: null }) + "\n");
|
|
@@ -81868,7 +82871,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81868
82871
|
return;
|
|
81869
82872
|
}
|
|
81870
82873
|
if (jsonOutput) {
|
|
81871
|
-
const active2 = (0,
|
|
82874
|
+
const active2 = (0, import_sidekick_shared32.getActiveCodexAccount)();
|
|
81872
82875
|
process.stdout.write(JSON.stringify({
|
|
81873
82876
|
provider: "codex",
|
|
81874
82877
|
accounts: accounts.map((account) => ({
|
|
@@ -81878,7 +82881,7 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81878
82881
|
}, null, 2) + "\n");
|
|
81879
82882
|
return;
|
|
81880
82883
|
}
|
|
81881
|
-
const active = (0,
|
|
82884
|
+
const active = (0, import_sidekick_shared32.getActiveCodexAccount)();
|
|
81882
82885
|
process.stdout.write(source_default.bold("Codex Accounts\n"));
|
|
81883
82886
|
process.stdout.write(source_default.dim("\u2500".repeat(50) + "\n"));
|
|
81884
82887
|
for (const account of accounts) {
|
|
@@ -81889,12 +82892,12 @@ function codexAccountAction(opts, jsonOutput) {
|
|
|
81889
82892
|
`);
|
|
81890
82893
|
}
|
|
81891
82894
|
}
|
|
81892
|
-
var
|
|
82895
|
+
var import_sidekick_shared32;
|
|
81893
82896
|
var init_account = __esm({
|
|
81894
82897
|
"src/commands/account.ts"() {
|
|
81895
82898
|
"use strict";
|
|
81896
82899
|
init_source();
|
|
81897
|
-
|
|
82900
|
+
import_sidekick_shared32 = __toESM(require_dist(), 1);
|
|
81898
82901
|
init_cli();
|
|
81899
82902
|
}
|
|
81900
82903
|
});
|
|
@@ -81909,12 +82912,12 @@ async function handoffAction(_opts, cmd) {
|
|
|
81909
82912
|
const workspacePath = globalOpts.project || process.cwd();
|
|
81910
82913
|
const jsonOutput = !!globalOpts.json;
|
|
81911
82914
|
try {
|
|
81912
|
-
const rawSlug = (0,
|
|
81913
|
-
const resolvedSlug = (0,
|
|
82915
|
+
const rawSlug = (0, import_sidekick_shared33.getProjectSlugRaw)(workspacePath);
|
|
82916
|
+
const resolvedSlug = (0, import_sidekick_shared33.getProjectSlug)(workspacePath);
|
|
81914
82917
|
const slugs = rawSlug !== resolvedSlug ? [rawSlug, resolvedSlug] : [rawSlug];
|
|
81915
82918
|
let content = null;
|
|
81916
82919
|
for (const slug of slugs) {
|
|
81917
|
-
content = await (0,
|
|
82920
|
+
content = await (0, import_sidekick_shared33.readLatestHandoff)(slug);
|
|
81918
82921
|
if (content) break;
|
|
81919
82922
|
}
|
|
81920
82923
|
if (!content) {
|
|
@@ -81939,12 +82942,12 @@ async function handoffAction(_opts, cmd) {
|
|
|
81939
82942
|
process.exit(1);
|
|
81940
82943
|
}
|
|
81941
82944
|
}
|
|
81942
|
-
var
|
|
82945
|
+
var import_sidekick_shared33;
|
|
81943
82946
|
var init_handoff = __esm({
|
|
81944
82947
|
"src/commands/handoff.ts"() {
|
|
81945
82948
|
"use strict";
|
|
81946
82949
|
init_source();
|
|
81947
|
-
|
|
82950
|
+
import_sidekick_shared33 = __toESM(require_dist(), 1);
|
|
81948
82951
|
}
|
|
81949
82952
|
});
|
|
81950
82953
|
|
|
@@ -81958,35 +82961,35 @@ function resolveProviderId(opts, defaultProvider = "auto") {
|
|
|
81958
82961
|
if (defaultProvider !== "auto") {
|
|
81959
82962
|
return defaultProvider;
|
|
81960
82963
|
}
|
|
81961
|
-
return (0,
|
|
82964
|
+
return (0, import_sidekick_shared34.detectProvider)();
|
|
81962
82965
|
}
|
|
81963
82966
|
function resolveProvider(opts) {
|
|
81964
82967
|
const id = resolveProviderId(opts);
|
|
81965
82968
|
switch (id) {
|
|
81966
82969
|
case "opencode":
|
|
81967
|
-
return new
|
|
82970
|
+
return new import_sidekick_shared35.OpenCodeProvider();
|
|
81968
82971
|
case "codex":
|
|
81969
|
-
return new
|
|
82972
|
+
return new import_sidekick_shared35.CodexProvider();
|
|
81970
82973
|
case "claude-code":
|
|
81971
82974
|
default:
|
|
81972
|
-
return new
|
|
82975
|
+
return new import_sidekick_shared35.ClaudeCodeProvider();
|
|
81973
82976
|
}
|
|
81974
82977
|
}
|
|
81975
|
-
var
|
|
82978
|
+
var import_sidekick_shared34, import_node, import_sidekick_shared35, defaultAccountsReady, program2, dashCmd, dumpCmd, ctxCmd, reportCmd, searchCmd, tasksCmd, decisionsCmd, notesCmd, statsCmd, quotaCmd, statusCmd, peakCmd, accountCmd, handoffCmd;
|
|
81976
82979
|
var init_cli = __esm({
|
|
81977
82980
|
"src/cli.ts"() {
|
|
81978
82981
|
init_esm();
|
|
81979
|
-
import_sidekick_shared33 = __toESM(require_dist(), 1);
|
|
81980
|
-
import_node = __toESM(require_node(), 1);
|
|
81981
82982
|
import_sidekick_shared34 = __toESM(require_dist(), 1);
|
|
82983
|
+
import_node = __toESM(require_node(), 1);
|
|
82984
|
+
import_sidekick_shared35 = __toESM(require_dist(), 1);
|
|
81982
82985
|
(0, import_node.hydratePricingCatalog)({
|
|
81983
82986
|
cacheDir: path7.join(os5.homedir(), ".config", "sidekick")
|
|
81984
82987
|
}).catch(() => {
|
|
81985
82988
|
});
|
|
81986
|
-
defaultAccountsReady = (0,
|
|
82989
|
+
defaultAccountsReady = (0, import_sidekick_shared34.ensureDefaultAccounts)().catch(() => {
|
|
81987
82990
|
});
|
|
81988
82991
|
program2 = new Command();
|
|
81989
|
-
program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.
|
|
82992
|
+
program2.name("sidekick").description("Query Sidekick project intelligence from the command line").version("0.18.1").option("--json", "Output as JSON").option("--project <path>", "Override project path (default: cwd)").option("--provider <id>", "Provider: claude-code, opencode, codex, auto (default: auto)");
|
|
81990
82993
|
program2.hook("preAction", async () => {
|
|
81991
82994
|
await defaultAccountsReady;
|
|
81992
82995
|
});
|