sidekick-shared 0.22.0 → 0.23.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/README.md +75 -63
- package/dist/accountManager.js +10 -0
- package/dist/accountRegistry.d.ts +2 -0
- package/dist/accountStatus.d.ts +1 -0
- package/dist/accountStatus.js +6 -0
- package/dist/accounts.js +2 -0
- package/dist/aggregation/EventAggregator.d.ts +36 -2
- package/dist/aggregation/EventAggregator.js +259 -33
- package/dist/aggregation/snapshot.d.ts +1 -1
- package/dist/aggregation/snapshot.js +2 -1
- package/dist/aggregation/types.d.ts +25 -1
- package/dist/analytics/codeImpact.d.ts +20 -0
- package/dist/analytics/codeImpact.js +21 -0
- package/dist/analytics/compactionLedger.d.ts +11 -0
- package/dist/analytics/compactionLedger.js +31 -0
- package/dist/analytics/qualityScore.d.ts +26 -0
- package/dist/analytics/qualityScore.js +115 -0
- package/dist/autoSwitch.d.ts +1 -1
- package/dist/autoSwitch.js +14 -3
- package/dist/codexProfiles.js +2 -0
- package/dist/codexQuota.d.ts +2 -0
- package/dist/codexQuota.js +27 -0
- package/dist/codexQuotaWatcher.d.ts +7 -0
- package/dist/codexQuotaWatcher.js +37 -19
- package/dist/context/composer.d.ts +3 -2
- package/dist/context/composer.js +5 -5
- package/dist/context/sessionContext.js +35 -9
- package/dist/credentialIO.js +19 -5
- package/dist/doctor.d.ts +55 -0
- package/dist/doctor.js +244 -0
- package/dist/errorHistory.d.ts +33 -0
- package/dist/errorHistory.js +95 -0
- package/dist/extractors/errorTaxonomy.d.ts +6 -0
- package/dist/extractors/errorTaxonomy.js +47 -0
- package/dist/extractors/toolCall.d.ts +9 -0
- package/dist/extractors/toolCall.js +79 -0
- package/dist/handoffUrl.d.ts +7 -0
- package/dist/handoffUrl.js +26 -0
- package/dist/index.d.ts +32 -9
- package/dist/index.js +64 -24
- package/dist/modelInfo.js +6 -0
- package/dist/multiProviderQuotaService.js +13 -2
- package/dist/parsers/codexParser.js +17 -1
- package/dist/parsers/openCodeParser.js +13 -0
- package/dist/parsers/planExtractor.js +17 -6
- package/dist/parsers/sessionActivityDetector.js +2 -0
- package/dist/parsers/sessionPathResolver.js +19 -16
- package/dist/parsers/subagentScanner.d.ts +1 -1
- package/dist/parsers/subagentScanner.js +4 -5
- package/dist/parsers/subagentTraceParser.js +4 -7
- package/dist/paths.d.ts +10 -0
- package/dist/paths.js +18 -5
- package/dist/projectMigration.d.ts +23 -0
- package/dist/projectMigration.js +95 -0
- package/dist/providerStatus.js +13 -2
- package/dist/providers/claudeCode.js +18 -4
- package/dist/providers/codex.js +42 -13
- package/dist/providers/codexDatabase.d.ts +1 -11
- package/dist/providers/detect.js +32 -3
- package/dist/providers/openCodeDatabase.d.ts +1 -31
- package/dist/providers/openCodeDatabase.js +21 -11
- package/dist/providers/types.d.ts +1 -0
- package/dist/quota.js +8 -0
- package/dist/quotaPoller.js +17 -6
- package/dist/quotaSnapshots.js +80 -26
- package/dist/readers/decisions.d.ts +2 -1
- package/dist/readers/decisions.js +5 -5
- package/dist/readers/handoff.d.ts +2 -1
- package/dist/readers/handoff.js +13 -8
- package/dist/readers/helpers.d.ts +3 -0
- package/dist/readers/helpers.js +12 -0
- package/dist/readers/notes.d.ts +2 -1
- package/dist/readers/notes.js +11 -8
- package/dist/readers/plans.js +3 -5
- package/dist/readers/tasks.d.ts +2 -1
- package/dist/readers/tasks.js +5 -5
- package/dist/report/htmlHelpers.js +6 -1
- package/dist/report/openBrowser.js +3 -3
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.js +10 -1
- package/dist/schemas/observedSessionV1.d.ts +499 -0
- package/dist/schemas/observedSessionV1.js +69 -0
- package/dist/schemas/sessionEvent.d.ts +13 -0
- package/dist/schemas/sessionEvent.js +19 -0
- package/dist/search/sessionSearch.d.ts +2 -2
- package/dist/search/sessionSearch.js +2 -3
- package/dist/sessionMonitor.d.ts +29 -0
- package/dist/sessionMonitor.js +71 -0
- package/dist/statusline/BurnRateCalculator.d.ts +14 -0
- package/dist/statusline/BurnRateCalculator.js +45 -0
- package/dist/statusline/formatter.d.ts +16 -0
- package/dist/statusline/formatter.js +84 -0
- package/dist/statusline/index.d.ts +7 -0
- package/dist/statusline/index.js +13 -0
- package/dist/terminalSync.js +16 -7
- package/dist/types/codex.d.ts +2 -0
- package/dist/types/historicalData.d.ts +49 -1
- package/dist/types/historicalData.js +28 -2
- package/dist/types/observedSessionV1.d.ts +70 -0
- package/dist/types/observedSessionV1.js +186 -0
- package/dist/types/opencode.d.ts +1 -0
- package/dist/types/sessionEvent.d.ts +19 -1
- package/dist/watchers/eventBridge.js +1 -0
- package/dist/watchers/factory.js +14 -3
- package/dist/watchers/jsonlTail.js +34 -14
- package/dist/watchers/jsonlWatcher.js +5 -3
- package/dist/watchers/providerReaderWatcher.js +4 -2
- package/dist/watchers/sqliteWatcher.d.ts +2 -0
- package/dist/watchers/sqliteWatcher.js +27 -14
- package/dist/watchers/types.d.ts +5 -0
- package/dist/writers/atomic.d.ts +4 -0
- package/dist/writers/atomic.js +200 -0
- package/dist/writers/decisions.d.ts +12 -0
- package/dist/writers/decisions.js +88 -0
- package/dist/writers/notes.d.ts +8 -0
- package/dist/writers/notes.js +82 -0
- package/dist/writers/tasks.d.ts +6 -0
- package/dist/writers/tasks.js +100 -0
- package/dist/zaiQuotaWatcher.js +6 -0
- package/package.json +5 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.atomicWriteJson = atomicWriteJson;
|
|
37
|
+
exports.atomicWriteJsonSync = atomicWriteJsonSync;
|
|
38
|
+
exports.updateJsonStoreAtomic = updateJsonStoreAtomic;
|
|
39
|
+
const crypto = __importStar(require("crypto"));
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const LOCK_STALE_MS = 10_000;
|
|
43
|
+
async function syncDirectory(directory) {
|
|
44
|
+
let handle;
|
|
45
|
+
try {
|
|
46
|
+
handle = await fs.promises.open(directory, 'r');
|
|
47
|
+
await handle.sync();
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
const code = error.code;
|
|
51
|
+
if (!['EISDIR', 'EINVAL', 'ENOSYS', 'EPERM', 'EACCES'].includes(code ?? ''))
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
await handle?.close().catch(() => undefined);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function syncDirectorySync(directory) {
|
|
59
|
+
let descriptor;
|
|
60
|
+
try {
|
|
61
|
+
descriptor = fs.openSync(directory, 'r');
|
|
62
|
+
fs.fsyncSync(descriptor);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
const code = error.code;
|
|
66
|
+
if (!['EISDIR', 'EINVAL', 'ENOSYS', 'EPERM', 'EACCES'].includes(code ?? ''))
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
if (descriptor !== undefined)
|
|
71
|
+
fs.closeSync(descriptor);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function atomicWriteJson(filePath, value) {
|
|
75
|
+
await fs.promises.mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
76
|
+
const tempPath = `${filePath}.${process.pid}.${crypto.randomBytes(8).toString('hex')}.tmp`;
|
|
77
|
+
let handle;
|
|
78
|
+
try {
|
|
79
|
+
handle = await fs.promises.open(tempPath, 'wx', 0o600);
|
|
80
|
+
await handle.writeFile(JSON.stringify(value, null, 2), 'utf8');
|
|
81
|
+
await handle.sync();
|
|
82
|
+
await handle.close();
|
|
83
|
+
handle = undefined;
|
|
84
|
+
await fs.promises.rename(tempPath, filePath);
|
|
85
|
+
await syncDirectory(path.dirname(filePath));
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
await handle?.close().catch(() => undefined);
|
|
89
|
+
await fs.promises.rm(tempPath, { force: true }).catch(() => undefined);
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function atomicWriteJsonSync(filePath, value) {
|
|
94
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
95
|
+
const tempPath = `${filePath}.${process.pid}.${crypto.randomBytes(8).toString('hex')}.tmp`;
|
|
96
|
+
let descriptor;
|
|
97
|
+
try {
|
|
98
|
+
descriptor = fs.openSync(tempPath, 'wx', 0o600);
|
|
99
|
+
fs.writeFileSync(descriptor, JSON.stringify(value, null, 2), { encoding: 'utf8' });
|
|
100
|
+
fs.fsyncSync(descriptor);
|
|
101
|
+
fs.closeSync(descriptor);
|
|
102
|
+
descriptor = undefined;
|
|
103
|
+
fs.renameSync(tempPath, filePath);
|
|
104
|
+
syncDirectorySync(path.dirname(filePath));
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (descriptor !== undefined)
|
|
108
|
+
fs.closeSync(descriptor);
|
|
109
|
+
fs.rmSync(tempPath, { force: true });
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** Serializes read-modify-write cycles across Sidekick processes. */
|
|
114
|
+
async function updateJsonStoreAtomic(filePath, createEmpty, update) {
|
|
115
|
+
await fs.promises.mkdir(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
116
|
+
const lockPath = `${filePath}.lock`;
|
|
117
|
+
const lock = await acquireLock(lockPath);
|
|
118
|
+
try {
|
|
119
|
+
let latest = createEmpty();
|
|
120
|
+
let raw;
|
|
121
|
+
try {
|
|
122
|
+
raw = await fs.promises.readFile(filePath, 'utf8');
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (error.code !== 'ENOENT')
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
if (raw !== undefined) {
|
|
129
|
+
try {
|
|
130
|
+
latest = JSON.parse(raw);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
const corruptPath = `${filePath}.corrupt-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
|
|
134
|
+
await fs.promises.rename(filePath, corruptPath);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const next = await update(latest);
|
|
138
|
+
await atomicWriteJson(filePath, next);
|
|
139
|
+
return next;
|
|
140
|
+
}
|
|
141
|
+
finally {
|
|
142
|
+
await releaseLock(lockPath, lock);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async function acquireLock(lockPath) {
|
|
146
|
+
const deadline = Date.now() + 3000;
|
|
147
|
+
while (true) {
|
|
148
|
+
try {
|
|
149
|
+
const handle = await fs.promises.open(lockPath, 'wx', 0o600);
|
|
150
|
+
const token = `${process.pid}:${crypto.randomBytes(16).toString('hex')}`;
|
|
151
|
+
await handle.writeFile(token, 'utf8');
|
|
152
|
+
await handle.sync();
|
|
153
|
+
const heartbeat = setInterval(() => {
|
|
154
|
+
fs.promises.utimes(lockPath, new Date(), new Date()).catch(() => undefined);
|
|
155
|
+
}, Math.floor(LOCK_STALE_MS / 3));
|
|
156
|
+
heartbeat.unref();
|
|
157
|
+
return { handle, token, heartbeat };
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
if (error.code !== 'EEXIST')
|
|
161
|
+
throw error;
|
|
162
|
+
try {
|
|
163
|
+
const stat = await fs.promises.stat(lockPath);
|
|
164
|
+
if (Date.now() - stat.mtimeMs > LOCK_STALE_MS) {
|
|
165
|
+
const owner = await fs.promises.readFile(lockPath, 'utf8').catch(() => '');
|
|
166
|
+
const ownerPid = Number.parseInt(owner.split(':', 1)[0], 10);
|
|
167
|
+
let ownerAlive = Number.isInteger(ownerPid) && ownerPid > 0;
|
|
168
|
+
if (ownerAlive) {
|
|
169
|
+
try {
|
|
170
|
+
process.kill(ownerPid, 0);
|
|
171
|
+
}
|
|
172
|
+
catch (ownerError) {
|
|
173
|
+
ownerAlive = ownerError.code === 'EPERM';
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (!ownerAlive)
|
|
177
|
+
await fs.promises.rm(lockPath, { force: true });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// The other writer released between checks.
|
|
182
|
+
}
|
|
183
|
+
if (Date.now() >= deadline)
|
|
184
|
+
throw new Error(`Timed out waiting for store lock: ${lockPath}`);
|
|
185
|
+
await new Promise((resolve) => setTimeout(resolve, 15));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
async function releaseLock(lockPath, lock) {
|
|
190
|
+
clearInterval(lock.heartbeat);
|
|
191
|
+
await lock.handle.close().catch(() => undefined);
|
|
192
|
+
try {
|
|
193
|
+
const currentToken = await fs.promises.readFile(lockPath, 'utf8');
|
|
194
|
+
if (currentToken === lock.token)
|
|
195
|
+
await fs.promises.rm(lockPath, { force: true });
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
// The lock was already released or replaced; never delete another owner's lock.
|
|
199
|
+
}
|
|
200
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type DecisionEntry, type DecisionSource } from '../types/decisionLog';
|
|
2
|
+
export declare function decisionFingerprint(decision: Pick<DecisionEntry, 'source' | 'description'>): string;
|
|
3
|
+
export declare function addDecision(cwd: string, description: string, options?: {
|
|
4
|
+
rationale?: string;
|
|
5
|
+
chosenOption?: string;
|
|
6
|
+
alternatives?: string[];
|
|
7
|
+
tags?: string[];
|
|
8
|
+
source?: DecisionSource;
|
|
9
|
+
}): Promise<{
|
|
10
|
+
decision: DecisionEntry;
|
|
11
|
+
added: boolean;
|
|
12
|
+
}>;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.decisionFingerprint = decisionFingerprint;
|
|
37
|
+
exports.addDecision = addDecision;
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
const paths_1 = require("../paths");
|
|
40
|
+
const projectMigration_1 = require("../projectMigration");
|
|
41
|
+
const decisionLog_1 = require("../types/decisionLog");
|
|
42
|
+
const atomic_1 = require("./atomic");
|
|
43
|
+
function emptyDecisionStore() {
|
|
44
|
+
return {
|
|
45
|
+
schemaVersion: decisionLog_1.DECISION_LOG_SCHEMA_VERSION,
|
|
46
|
+
decisions: {},
|
|
47
|
+
lastSessionId: 'cli',
|
|
48
|
+
lastSaved: new Date().toISOString(),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function decisionFingerprint(decision) {
|
|
52
|
+
return `${decision.source}::${decision.description.toLowerCase().trim()}`;
|
|
53
|
+
}
|
|
54
|
+
async function addDecision(cwd, description, options = {}) {
|
|
55
|
+
const project = (0, paths_1.resolveProjectIdentity)(cwd);
|
|
56
|
+
(0, projectMigration_1.migrateLegacyProjectStores)(project);
|
|
57
|
+
const filePath = (0, paths_1.getProjectDataPath)(project.canonicalSlug, 'decisions');
|
|
58
|
+
const decision = {
|
|
59
|
+
id: crypto.randomUUID(),
|
|
60
|
+
description: description.trim(),
|
|
61
|
+
rationale: options.rationale?.trim() || 'Captured from the Sidekick CLI.',
|
|
62
|
+
chosenOption: options.chosenOption?.trim() || description.trim(),
|
|
63
|
+
alternatives: options.alternatives,
|
|
64
|
+
source: options.source ?? 'text_pattern',
|
|
65
|
+
sessionId: 'cli',
|
|
66
|
+
timestamp: new Date().toISOString(),
|
|
67
|
+
tags: options.tags,
|
|
68
|
+
};
|
|
69
|
+
let added = false;
|
|
70
|
+
let persisted = decision;
|
|
71
|
+
await (0, atomic_1.updateJsonStoreAtomic)(filePath, emptyDecisionStore, (store) => {
|
|
72
|
+
const fingerprint = decisionFingerprint(decision);
|
|
73
|
+
const duplicate = Object.values(store.decisions).find((entry) => decisionFingerprint(entry) === fingerprint);
|
|
74
|
+
if (duplicate) {
|
|
75
|
+
persisted = duplicate;
|
|
76
|
+
return store;
|
|
77
|
+
}
|
|
78
|
+
added = true;
|
|
79
|
+
return {
|
|
80
|
+
...store,
|
|
81
|
+
schemaVersion: decisionLog_1.DECISION_LOG_SCHEMA_VERSION,
|
|
82
|
+
decisions: { ...store.decisions, [decision.id]: decision },
|
|
83
|
+
lastSessionId: 'cli',
|
|
84
|
+
lastSaved: decision.timestamp,
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
return { decision: persisted, added };
|
|
88
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type KnowledgeNote, type KnowledgeNoteImportance, type KnowledgeNoteType } from '../types/knowledgeNote';
|
|
2
|
+
export declare function addNote(cwd: string, content: string, options?: {
|
|
3
|
+
filePath?: string;
|
|
4
|
+
title?: string;
|
|
5
|
+
noteType?: KnowledgeNoteType;
|
|
6
|
+
importance?: KnowledgeNoteImportance;
|
|
7
|
+
tags?: string[];
|
|
8
|
+
}): Promise<KnowledgeNote>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.addNote = addNote;
|
|
37
|
+
const crypto = __importStar(require("crypto"));
|
|
38
|
+
const paths_1 = require("../paths");
|
|
39
|
+
const projectMigration_1 = require("../projectMigration");
|
|
40
|
+
const knowledgeNote_1 = require("../types/knowledgeNote");
|
|
41
|
+
const atomic_1 = require("./atomic");
|
|
42
|
+
function emptyNoteStore() {
|
|
43
|
+
return {
|
|
44
|
+
schemaVersion: knowledgeNote_1.KNOWLEDGE_NOTE_SCHEMA_VERSION,
|
|
45
|
+
notesByFile: {},
|
|
46
|
+
lastSaved: new Date().toISOString(),
|
|
47
|
+
totalNotes: 0,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async function addNote(cwd, content, options = {}) {
|
|
51
|
+
const project = (0, paths_1.resolveProjectIdentity)(cwd);
|
|
52
|
+
(0, projectMigration_1.migrateLegacyProjectStores)(project);
|
|
53
|
+
const filePath = (0, paths_1.getProjectDataPath)(project.canonicalSlug, 'knowledge-notes');
|
|
54
|
+
const now = new Date().toISOString();
|
|
55
|
+
const notePath = options.filePath?.trim() || '.';
|
|
56
|
+
const note = {
|
|
57
|
+
id: crypto.randomUUID(),
|
|
58
|
+
noteType: options.noteType ?? 'tip',
|
|
59
|
+
content: content.trim(),
|
|
60
|
+
title: options.title,
|
|
61
|
+
filePath: notePath,
|
|
62
|
+
source: 'manual',
|
|
63
|
+
status: 'active',
|
|
64
|
+
importance: options.importance ?? 'medium',
|
|
65
|
+
createdAt: now,
|
|
66
|
+
updatedAt: now,
|
|
67
|
+
lastReviewedAt: now,
|
|
68
|
+
tags: options.tags,
|
|
69
|
+
};
|
|
70
|
+
await (0, atomic_1.updateJsonStoreAtomic)(filePath, emptyNoteStore, (store) => {
|
|
71
|
+
const existing = store.notesByFile[notePath] ?? [];
|
|
72
|
+
const notesByFile = { ...store.notesByFile, [notePath]: [...existing, note] };
|
|
73
|
+
return {
|
|
74
|
+
...store,
|
|
75
|
+
schemaVersion: knowledgeNote_1.KNOWLEDGE_NOTE_SCHEMA_VERSION,
|
|
76
|
+
notesByFile,
|
|
77
|
+
totalNotes: Object.values(notesByFile).reduce((sum, notes) => sum + notes.length, 0),
|
|
78
|
+
lastSaved: now,
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
return note;
|
|
82
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type PersistedTask } from '../types/taskPersistence';
|
|
2
|
+
export declare function addTask(cwd: string, subject: string, options?: {
|
|
3
|
+
description?: string;
|
|
4
|
+
tags?: string[];
|
|
5
|
+
}): Promise<PersistedTask>;
|
|
6
|
+
export declare function completeTask(cwd: string, taskIdOrPrefix: string): Promise<PersistedTask>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.addTask = addTask;
|
|
37
|
+
exports.completeTask = completeTask;
|
|
38
|
+
const crypto = __importStar(require("crypto"));
|
|
39
|
+
const paths_1 = require("../paths");
|
|
40
|
+
const projectMigration_1 = require("../projectMigration");
|
|
41
|
+
const taskPersistence_1 = require("../types/taskPersistence");
|
|
42
|
+
const atomic_1 = require("./atomic");
|
|
43
|
+
function emptyTaskStore() {
|
|
44
|
+
return {
|
|
45
|
+
schemaVersion: taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION,
|
|
46
|
+
tasks: {},
|
|
47
|
+
lastSessionId: 'cli',
|
|
48
|
+
sessionCount: 0,
|
|
49
|
+
lastSaved: new Date().toISOString(),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
async function addTask(cwd, subject, options = {}) {
|
|
53
|
+
const project = (0, paths_1.resolveProjectIdentity)(cwd);
|
|
54
|
+
(0, projectMigration_1.migrateLegacyProjectStores)(project);
|
|
55
|
+
const filePath = (0, paths_1.getProjectDataPath)(project.canonicalSlug, 'tasks');
|
|
56
|
+
const now = new Date().toISOString();
|
|
57
|
+
const task = {
|
|
58
|
+
taskId: crypto.randomUUID(),
|
|
59
|
+
subject: subject.trim(),
|
|
60
|
+
description: options.description,
|
|
61
|
+
status: 'pending',
|
|
62
|
+
createdAt: now,
|
|
63
|
+
updatedAt: now,
|
|
64
|
+
toolCallCount: 0,
|
|
65
|
+
blockedBy: [],
|
|
66
|
+
blocks: [],
|
|
67
|
+
sessionOrigin: 'cli',
|
|
68
|
+
carriedOver: false,
|
|
69
|
+
sessionAge: 0,
|
|
70
|
+
tags: options.tags,
|
|
71
|
+
};
|
|
72
|
+
await (0, atomic_1.updateJsonStoreAtomic)(filePath, emptyTaskStore, (store) => ({
|
|
73
|
+
...store,
|
|
74
|
+
schemaVersion: taskPersistence_1.TASK_PERSISTENCE_SCHEMA_VERSION,
|
|
75
|
+
tasks: { ...store.tasks, [task.taskId]: task },
|
|
76
|
+
lastSessionId: store.lastSessionId || 'cli',
|
|
77
|
+
lastSaved: now,
|
|
78
|
+
}));
|
|
79
|
+
return task;
|
|
80
|
+
}
|
|
81
|
+
async function completeTask(cwd, taskIdOrPrefix) {
|
|
82
|
+
const project = (0, paths_1.resolveProjectIdentity)(cwd);
|
|
83
|
+
(0, projectMigration_1.migrateLegacyProjectStores)(project);
|
|
84
|
+
const filePath = (0, paths_1.getProjectDataPath)(project.canonicalSlug, 'tasks');
|
|
85
|
+
let completed;
|
|
86
|
+
await (0, atomic_1.updateJsonStoreAtomic)(filePath, emptyTaskStore, (store) => {
|
|
87
|
+
const matches = Object.values(store.tasks).filter((task) => task.taskId === taskIdOrPrefix || task.taskId.startsWith(taskIdOrPrefix));
|
|
88
|
+
if (matches.length !== 1) {
|
|
89
|
+
throw new Error(matches.length === 0 ? `Task not found: ${taskIdOrPrefix}` : 'Task ID is ambiguous');
|
|
90
|
+
}
|
|
91
|
+
const now = new Date().toISOString();
|
|
92
|
+
completed = { ...matches[0], status: 'completed', updatedAt: now };
|
|
93
|
+
return {
|
|
94
|
+
...store,
|
|
95
|
+
tasks: { ...store.tasks, [completed.taskId]: completed },
|
|
96
|
+
lastSaved: now,
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
return completed;
|
|
100
|
+
}
|
package/dist/zaiQuotaWatcher.js
CHANGED
|
@@ -169,6 +169,12 @@ class ZaiQuotaWatcher {
|
|
|
169
169
|
}
|
|
170
170
|
recomputeAndEmit() {
|
|
171
171
|
const nowMs = this.now();
|
|
172
|
+
if (this.lastError?.resetsAt) {
|
|
173
|
+
const resetsAt = Date.parse(this.lastError.resetsAt);
|
|
174
|
+
if (Number.isFinite(resetsAt) && resetsAt <= nowMs) {
|
|
175
|
+
this.lastError = null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
172
178
|
const accumulated = (0, zaiQuota_1.accumulateZaiUsage)(this.turns, nowMs);
|
|
173
179
|
const tier = this.resolveTier(this.tier, accumulated);
|
|
174
180
|
const state = accumulated.fiveHourTurns > 0 || accumulated.weeklyTurns > 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sidekick-shared",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.1",
|
|
4
4
|
"description": "Shared data access layer for Sidekick — readers, types, providers, credentials, quota",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -37,6 +37,10 @@
|
|
|
37
37
|
"types": "./dist/formatting.d.ts",
|
|
38
38
|
"default": "./dist/formatting.js"
|
|
39
39
|
},
|
|
40
|
+
"./statusline": {
|
|
41
|
+
"types": "./dist/statusline/index.d.ts",
|
|
42
|
+
"default": "./dist/statusline/index.js"
|
|
43
|
+
},
|
|
40
44
|
"./dist/*": {
|
|
41
45
|
"types": "./dist/*.d.ts",
|
|
42
46
|
"default": "./dist/*.js"
|