guidemode 0.2.0
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/LICENSE +21 -0
- package/README.md +85 -0
- package/dist/cjs/auth.d.ts +4 -0
- package/dist/cjs/auth.d.ts.map +1 -0
- package/dist/cjs/auth.js +191 -0
- package/dist/cjs/auth.js.map +1 -0
- package/dist/cjs/config.d.ts +24 -0
- package/dist/cjs/config.d.ts.map +1 -0
- package/dist/cjs/config.js +55 -0
- package/dist/cjs/config.js.map +1 -0
- package/dist/cjs/deploy.d.ts +18 -0
- package/dist/cjs/deploy.d.ts.map +1 -0
- package/dist/cjs/deploy.js +89 -0
- package/dist/cjs/deploy.js.map +1 -0
- package/dist/cjs/issue.d.ts +18 -0
- package/dist/cjs/issue.d.ts.map +1 -0
- package/dist/cjs/issue.js +79 -0
- package/dist/cjs/issue.js.map +1 -0
- package/dist/cjs/logs.d.ts +7 -0
- package/dist/cjs/logs.d.ts.map +1 -0
- package/dist/cjs/logs.js +75 -0
- package/dist/cjs/logs.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/setup.d.ts +8 -0
- package/dist/cjs/setup.d.ts.map +1 -0
- package/dist/cjs/setup.js +110 -0
- package/dist/cjs/setup.js.map +1 -0
- package/dist/cjs/status.d.ts +6 -0
- package/dist/cjs/status.d.ts.map +1 -0
- package/dist/cjs/status.js +171 -0
- package/dist/cjs/status.js.map +1 -0
- package/dist/cjs/sync.d.ts +8 -0
- package/dist/cjs/sync.d.ts.map +1 -0
- package/dist/cjs/sync.js +201 -0
- package/dist/cjs/sync.js.map +1 -0
- package/dist/cjs/utils/brand.d.ts +5 -0
- package/dist/cjs/utils/brand.d.ts.map +1 -0
- package/dist/cjs/utils/brand.js +8 -0
- package/dist/cjs/utils/brand.js.map +1 -0
- package/dist/cjs/utils/git.d.ts +11 -0
- package/dist/cjs/utils/git.d.ts.map +1 -0
- package/dist/cjs/utils/git.js +92 -0
- package/dist/cjs/utils/git.js.map +1 -0
- package/dist/cjs/utils/logger.d.ts +2 -0
- package/dist/cjs/utils/logger.d.ts.map +1 -0
- package/dist/cjs/utils/logger.js +26 -0
- package/dist/cjs/utils/logger.js.map +1 -0
- package/dist/cjs/validate.d.ts +22 -0
- package/dist/cjs/validate.d.ts.map +1 -0
- package/dist/cjs/validate.js +169 -0
- package/dist/cjs/validate.js.map +1 -0
- package/dist/esm/auth.d.ts +4 -0
- package/dist/esm/auth.d.ts.map +1 -0
- package/dist/esm/auth.js +191 -0
- package/dist/esm/auth.js.map +1 -0
- package/dist/esm/cli.d.ts +3 -0
- package/dist/esm/cli.d.ts.map +1 -0
- package/dist/esm/cli.js +348 -0
- package/dist/esm/cli.js.map +1 -0
- package/dist/esm/config.d.ts +24 -0
- package/dist/esm/config.d.ts.map +1 -0
- package/dist/esm/config.js +55 -0
- package/dist/esm/config.js.map +1 -0
- package/dist/esm/deploy.d.ts +18 -0
- package/dist/esm/deploy.d.ts.map +1 -0
- package/dist/esm/deploy.js +89 -0
- package/dist/esm/deploy.js.map +1 -0
- package/dist/esm/issue.d.ts +18 -0
- package/dist/esm/issue.d.ts.map +1 -0
- package/dist/esm/issue.js +79 -0
- package/dist/esm/issue.js.map +1 -0
- package/dist/esm/logs.d.ts +7 -0
- package/dist/esm/logs.d.ts.map +1 -0
- package/dist/esm/logs.js +75 -0
- package/dist/esm/logs.js.map +1 -0
- package/dist/esm/setup.d.ts +8 -0
- package/dist/esm/setup.d.ts.map +1 -0
- package/dist/esm/setup.js +110 -0
- package/dist/esm/setup.js.map +1 -0
- package/dist/esm/status.d.ts +6 -0
- package/dist/esm/status.d.ts.map +1 -0
- package/dist/esm/status.js +171 -0
- package/dist/esm/status.js.map +1 -0
- package/dist/esm/sync.d.ts +8 -0
- package/dist/esm/sync.d.ts.map +1 -0
- package/dist/esm/sync.js +201 -0
- package/dist/esm/sync.js.map +1 -0
- package/dist/esm/utils/brand.d.ts +5 -0
- package/dist/esm/utils/brand.d.ts.map +1 -0
- package/dist/esm/utils/brand.js +8 -0
- package/dist/esm/utils/brand.js.map +1 -0
- package/dist/esm/utils/git.d.ts +11 -0
- package/dist/esm/utils/git.d.ts.map +1 -0
- package/dist/esm/utils/git.js +92 -0
- package/dist/esm/utils/git.js.map +1 -0
- package/dist/esm/utils/logger.d.ts +2 -0
- package/dist/esm/utils/logger.d.ts.map +1 -0
- package/dist/esm/utils/logger.js +26 -0
- package/dist/esm/utils/logger.js.map +1 -0
- package/dist/esm/validate.d.ts +22 -0
- package/dist/esm/validate.d.ts.map +1 -0
- package/dist/esm/validate.js +169 -0
- package/dist/esm/validate.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +54 -0
package/dist/esm/sync.js
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
3
|
+
import { gzip } from 'node:zlib';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
import { DEFAULT_SYNC_HOOKS, loadConfig } from './config.js';
|
|
6
|
+
import { logToFile } from './utils/logger.js';
|
|
7
|
+
import { detectProjectType, getGitMetadata } from './utils/git.js';
|
|
8
|
+
const gzipAsync = promisify(gzip);
|
|
9
|
+
const FETCH_TIMEOUT = 30_000;
|
|
10
|
+
function parseStdin(raw) {
|
|
11
|
+
try {
|
|
12
|
+
const d = JSON.parse(raw);
|
|
13
|
+
return {
|
|
14
|
+
sessionId: d.session_id || '',
|
|
15
|
+
transcriptPath: d.transcript_path || '',
|
|
16
|
+
cwd: d.cwd || '',
|
|
17
|
+
hookEvent: d.hook_event_name || '',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function readStdin() {
|
|
25
|
+
return new Promise(resolve => {
|
|
26
|
+
let data = '';
|
|
27
|
+
process.stdin.setEncoding('utf8');
|
|
28
|
+
process.stdin.on('data', chunk => {
|
|
29
|
+
data += chunk;
|
|
30
|
+
});
|
|
31
|
+
process.stdin.on('end', () => resolve(data));
|
|
32
|
+
// If stdin is a TTY (not piped), resolve immediately
|
|
33
|
+
if (process.stdin.isTTY) {
|
|
34
|
+
resolve('');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
async function fetchWithTimeout(url, options) {
|
|
39
|
+
const controller = new AbortController();
|
|
40
|
+
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT);
|
|
41
|
+
try {
|
|
42
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
clearTimeout(timer);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async function triggerProcessing(apiKey, serverUrl, sessionId, hookEvent) {
|
|
49
|
+
try {
|
|
50
|
+
const response = await fetchWithTimeout(`${serverUrl}/api/session-processing/process/${encodeURIComponent(sessionId)}`, {
|
|
51
|
+
method: 'POST',
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: `Bearer ${apiKey}`,
|
|
54
|
+
'Content-Type': 'application/json',
|
|
55
|
+
},
|
|
56
|
+
body: '{}',
|
|
57
|
+
});
|
|
58
|
+
if (response.ok) {
|
|
59
|
+
await logToFile('INFO', `[${hookEvent}] Triggered processing for session ${sessionId}`);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const body = await response.text().catch(() => '');
|
|
63
|
+
await logToFile('WARN', `[${hookEvent}] Processing trigger returned HTTP ${response.status}: ${body}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
await logToFile('WARN', `[${hookEvent}] Processing trigger failed for session ${sessionId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export async function runSync(options) {
|
|
71
|
+
let input = null;
|
|
72
|
+
if (options?.sessionId && options?.transcriptPath) {
|
|
73
|
+
// CLI arg mode
|
|
74
|
+
input = {
|
|
75
|
+
sessionId: options.sessionId,
|
|
76
|
+
transcriptPath: options.transcriptPath,
|
|
77
|
+
cwd: options.cwd || process.cwd(),
|
|
78
|
+
hookEvent: options.hookEvent || 'Manual',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
// Stdin mode (hook invocation)
|
|
83
|
+
const raw = await readStdin();
|
|
84
|
+
if (!raw) {
|
|
85
|
+
await logToFile('ERROR', 'No input received on stdin');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
input = parseStdin(raw);
|
|
89
|
+
if (!input) {
|
|
90
|
+
await logToFile('ERROR', 'Failed to parse stdin JSON');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (!input.sessionId || !input.transcriptPath) {
|
|
95
|
+
await logToFile('ERROR', 'Missing session_id or transcript_path in input');
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const hookEvent = input.hookEvent;
|
|
99
|
+
// Load config
|
|
100
|
+
const config = await loadConfig();
|
|
101
|
+
if (!config.apiKey || !config.serverUrl) {
|
|
102
|
+
await logToFile('INFO', 'No apiKey or serverUrl in config - skipping upload (run setup first)');
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Check if this hook event is enabled
|
|
106
|
+
const enabledHooks = config.syncHooks || DEFAULT_SYNC_HOOKS;
|
|
107
|
+
if (hookEvent && !enabledHooks.includes(hookEvent) && hookEvent !== 'Manual') {
|
|
108
|
+
await logToFile('INFO', `Hook ${hookEvent} not enabled in syncHooks config - skipping`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Check transcript file exists
|
|
112
|
+
try {
|
|
113
|
+
await stat(input.transcriptPath);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
await logToFile('ERROR', `Transcript file not found: ${input.transcriptPath}`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
await logToFile('INFO', `[${hookEvent}] Processing session ${input.sessionId} from ${input.transcriptPath}`);
|
|
120
|
+
const { apiKey, serverUrl } = config;
|
|
121
|
+
// Compute SHA256 hash
|
|
122
|
+
const fileContent = await readFile(input.transcriptPath);
|
|
123
|
+
const fileHash = createHash('sha256').update(fileContent).digest('hex');
|
|
124
|
+
// Check hash with server (dedup)
|
|
125
|
+
try {
|
|
126
|
+
const checkUrl = `${serverUrl}/api/agent-sessions/check-hash?sessionId=${encodeURIComponent(input.sessionId)}&fileHash=${fileHash}`;
|
|
127
|
+
const checkResponse = await fetchWithTimeout(checkUrl, {
|
|
128
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
129
|
+
});
|
|
130
|
+
if (checkResponse.ok) {
|
|
131
|
+
const checkData = (await checkResponse.json());
|
|
132
|
+
if (checkData.needsUpload === false) {
|
|
133
|
+
await logToFile('INFO', `[${hookEvent}] Session ${input.sessionId} unchanged (hash match) - skipping upload`);
|
|
134
|
+
// On SessionEnd, still trigger processing even if upload was skipped
|
|
135
|
+
if (hookEvent === 'SessionEnd') {
|
|
136
|
+
await triggerProcessing(apiKey, serverUrl, input.sessionId, hookEvent);
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
await logToFile('WARN', `Hash check returned ${checkResponse.status} - proceeding with upload`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
await logToFile('ERROR', `Hash check request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Gzip and base64 encode
|
|
150
|
+
const compressed = await gzipAsync(fileContent);
|
|
151
|
+
const content = compressed.toString('base64');
|
|
152
|
+
const fileSize = fileContent.length;
|
|
153
|
+
// Extract git metadata
|
|
154
|
+
const gitMeta = await getGitMetadata(input.cwd);
|
|
155
|
+
const detectedRepoType = await detectProjectType(input.cwd);
|
|
156
|
+
// Build upload payload
|
|
157
|
+
const payload = {
|
|
158
|
+
provider: 'claude-code',
|
|
159
|
+
repositoryName: gitMeta.repoName,
|
|
160
|
+
sessionId: input.sessionId,
|
|
161
|
+
fileName: `${input.sessionId}.jsonl`,
|
|
162
|
+
fileHash,
|
|
163
|
+
content,
|
|
164
|
+
contentEncoding: 'gzip',
|
|
165
|
+
fileSize,
|
|
166
|
+
...(gitMeta.branch && { gitBranch: gitMeta.branch }),
|
|
167
|
+
...(gitMeta.commitHash && { latestCommitHash: gitMeta.commitHash }),
|
|
168
|
+
...(gitMeta.commitHash && { firstCommitHash: gitMeta.commitHash }),
|
|
169
|
+
repositoryMetadata: {
|
|
170
|
+
cwd: input.cwd || '.',
|
|
171
|
+
gitRemoteUrl: gitMeta.remoteUrl,
|
|
172
|
+
detectedRepositoryType: detectedRepoType,
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
// Upload to server
|
|
176
|
+
try {
|
|
177
|
+
const uploadResponse = await fetchWithTimeout(`${serverUrl}/api/agent-sessions/upload-v2`, {
|
|
178
|
+
method: 'POST',
|
|
179
|
+
headers: {
|
|
180
|
+
Authorization: `Bearer ${apiKey}`,
|
|
181
|
+
'Content-Type': 'application/json',
|
|
182
|
+
},
|
|
183
|
+
body: JSON.stringify(payload),
|
|
184
|
+
});
|
|
185
|
+
if (uploadResponse.ok) {
|
|
186
|
+
await logToFile('INFO', `[${hookEvent}] Successfully uploaded session ${input.sessionId} (HTTP ${uploadResponse.status})`);
|
|
187
|
+
// On SessionEnd, trigger server-side processing
|
|
188
|
+
if (hookEvent === 'SessionEnd') {
|
|
189
|
+
await triggerProcessing(apiKey, serverUrl, input.sessionId, hookEvent);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
const body = await uploadResponse.text().catch(() => '');
|
|
194
|
+
await logToFile('ERROR', `[${hookEvent}] Upload failed with HTTP ${uploadResponse.status}: ${body}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
await logToFile('ERROR', `[${hookEvent}] Upload request failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../../../src/utils/brand.ts"],"names":[],"mappings":"AAEA,0CAA0C;AAC1C,eAAO,MAAM,MAAM,QAA6D,CAAA;AAEhF,gDAAgD;AAChD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
/** Colored >> prefix: orange > green > */
|
|
3
|
+
export const PREFIX = `${chalk.hex('#FF8C00')('>')}${chalk.hex('#22C55E')('>')}`;
|
|
4
|
+
/** Prefix a title string with the branded >> */
|
|
5
|
+
export function brandTitle(text) {
|
|
6
|
+
return `${PREFIX} ${text}`;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=brand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand.js","sourceRoot":"","sources":["../../../src/utils/brand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,0CAA0C;AAC1C,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,EAAE,CAAA;AAEhF,gDAAgD;AAChD,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,GAAG,MAAM,IAAI,IAAI,EAAE,CAAA;AAC5B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface GitMetadata {
|
|
2
|
+
remoteUrl: string | null;
|
|
3
|
+
branch: string | null;
|
|
4
|
+
commitHash: string | null;
|
|
5
|
+
repoName: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function normalizeGitUrl(url: string): string;
|
|
8
|
+
export declare function extractRepoName(url: string): string;
|
|
9
|
+
export declare function detectProjectType(cwd: string): Promise<string>;
|
|
10
|
+
export declare function getGitMetadata(cwd: string): Promise<GitMetadata>;
|
|
11
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../src/utils/git.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAOD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBpE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA+CtE"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { execFile as execFileCb } from 'node:child_process';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { promisify } from 'node:util';
|
|
5
|
+
const execFile = promisify(execFileCb);
|
|
6
|
+
const GIT_TIMEOUT = 5000;
|
|
7
|
+
async function gitCommand(args, cwd) {
|
|
8
|
+
const { stdout } = await execFile('git', args, { cwd, timeout: GIT_TIMEOUT });
|
|
9
|
+
return stdout.trim();
|
|
10
|
+
}
|
|
11
|
+
export function normalizeGitUrl(url) {
|
|
12
|
+
if (url.startsWith('git@github.com:')) {
|
|
13
|
+
return `https://github.com/${url.slice('git@github.com:'.length)}`;
|
|
14
|
+
}
|
|
15
|
+
if (url.startsWith('ssh://git@github.com/')) {
|
|
16
|
+
return `https://github.com/${url.slice('ssh://git@github.com/'.length)}`;
|
|
17
|
+
}
|
|
18
|
+
return url;
|
|
19
|
+
}
|
|
20
|
+
export function extractRepoName(url) {
|
|
21
|
+
const match = url.match(/[:/]([^/]+\/[^/.]+?)(?:\.git)?$/);
|
|
22
|
+
return match ? match[1] : '';
|
|
23
|
+
}
|
|
24
|
+
export async function detectProjectType(cwd) {
|
|
25
|
+
const checks = [
|
|
26
|
+
['package.json', 'nodejs'],
|
|
27
|
+
['Cargo.toml', 'rust'],
|
|
28
|
+
['go.mod', 'go'],
|
|
29
|
+
['requirements.txt', 'python'],
|
|
30
|
+
['pyproject.toml', 'python'],
|
|
31
|
+
['setup.py', 'python'],
|
|
32
|
+
];
|
|
33
|
+
for (const [file, type] of checks) {
|
|
34
|
+
try {
|
|
35
|
+
await access(join(cwd, file));
|
|
36
|
+
return type;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// File doesn't exist, continue
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return 'generic';
|
|
43
|
+
}
|
|
44
|
+
export async function getGitMetadata(cwd) {
|
|
45
|
+
const fallback = {
|
|
46
|
+
remoteUrl: null,
|
|
47
|
+
branch: null,
|
|
48
|
+
commitHash: null,
|
|
49
|
+
repoName: 'unknown',
|
|
50
|
+
};
|
|
51
|
+
if (!cwd)
|
|
52
|
+
return fallback;
|
|
53
|
+
try {
|
|
54
|
+
let remoteUrl = null;
|
|
55
|
+
try {
|
|
56
|
+
const raw = await gitCommand(['remote', 'get-url', 'origin'], cwd);
|
|
57
|
+
remoteUrl = normalizeGitUrl(raw);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// No git remote
|
|
61
|
+
}
|
|
62
|
+
let branch = null;
|
|
63
|
+
try {
|
|
64
|
+
branch = await gitCommand(['rev-parse', '--abbrev-ref', 'HEAD'], cwd);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Not in a git repo
|
|
68
|
+
}
|
|
69
|
+
let commitHash = null;
|
|
70
|
+
try {
|
|
71
|
+
commitHash = await gitCommand(['rev-parse', 'HEAD'], cwd);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// Not in a git repo
|
|
75
|
+
}
|
|
76
|
+
let repoName = 'unknown';
|
|
77
|
+
if (remoteUrl) {
|
|
78
|
+
const extracted = extractRepoName(remoteUrl);
|
|
79
|
+
if (extracted)
|
|
80
|
+
repoName = extracted;
|
|
81
|
+
}
|
|
82
|
+
if (repoName === 'unknown' && cwd) {
|
|
83
|
+
const { basename } = await import('node:path');
|
|
84
|
+
repoName = basename(cwd);
|
|
85
|
+
}
|
|
86
|
+
return { remoteUrl, branch, commitHash, repoName };
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return fallback;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/utils/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAeA,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS7E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { appendFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { LOG_DIR, LOG_FILE } from '../config.js';
|
|
3
|
+
let logDirEnsured = false;
|
|
4
|
+
async function ensureLogDir() {
|
|
5
|
+
if (logDirEnsured)
|
|
6
|
+
return;
|
|
7
|
+
try {
|
|
8
|
+
await mkdir(LOG_DIR, { recursive: true, mode: 0o700 });
|
|
9
|
+
logDirEnsured = true;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
// Ignore - best effort
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export async function logToFile(level, message) {
|
|
16
|
+
try {
|
|
17
|
+
await ensureLogDir();
|
|
18
|
+
const timestamp = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
19
|
+
const line = `[${timestamp}] ${level}: ${message}\n`;
|
|
20
|
+
await appendFile(LOG_FILE, line, { mode: 0o600 });
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Never throw - logging must be silent
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAEhD,IAAI,aAAa,GAAG,KAAK,CAAA;AAEzB,KAAK,UAAU,YAAY;IACzB,IAAI,aAAa;QAAE,OAAM;IACzB,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACtD,aAAa,GAAG,IAAI,CAAA;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa,EAAE,OAAe;IAC5D,IAAI,CAAC;QACH,MAAM,YAAY,EAAE,CAAA;QACpB,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAA;QACpE,MAAM,IAAI,GAAG,IAAI,SAAS,KAAK,KAAK,KAAK,OAAO,IAAI,CAAA;QACpD,MAAM,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Command
|
|
3
|
+
*
|
|
4
|
+
* Validates canonical JSONL files for correctness.
|
|
5
|
+
*/
|
|
6
|
+
interface ValidateOptions {
|
|
7
|
+
strict?: boolean;
|
|
8
|
+
json?: boolean;
|
|
9
|
+
verbose?: boolean;
|
|
10
|
+
watch?: boolean;
|
|
11
|
+
provider?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Validate command implementation
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateCommand(path: string, options: ValidateOptions): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Watch mode implementation
|
|
19
|
+
*/
|
|
20
|
+
export declare function validateWatch(_path: string, _options: ValidateOptions): Promise<void>;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,UAAU,eAAe;IACvB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AA+DD;;GAEG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA+H3F;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAa3F"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate Command
|
|
3
|
+
*
|
|
4
|
+
* Validates canonical JSONL files for correctness.
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync, readdirSync, statSync } from 'node:fs';
|
|
7
|
+
import { extname, join } from 'node:path';
|
|
8
|
+
import { generateValidationReport, validateJSONL, } from '@guidemode/session-processing/validation';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
/**
|
|
11
|
+
* Find all JSONL files in a directory
|
|
12
|
+
*/
|
|
13
|
+
function findJSONLFiles(path) {
|
|
14
|
+
const files = [];
|
|
15
|
+
try {
|
|
16
|
+
const stat = statSync(path);
|
|
17
|
+
if (stat.isFile()) {
|
|
18
|
+
if (extname(path) === '.jsonl') {
|
|
19
|
+
files.push(path);
|
|
20
|
+
}
|
|
21
|
+
return files;
|
|
22
|
+
}
|
|
23
|
+
if (stat.isDirectory()) {
|
|
24
|
+
const entries = readdirSync(path);
|
|
25
|
+
for (const entry of entries) {
|
|
26
|
+
const fullPath = join(path, entry);
|
|
27
|
+
files.push(...findJSONLFiles(fullPath));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.error(chalk.red('Error reading path:'), error instanceof Error ? error.message : String(error));
|
|
33
|
+
}
|
|
34
|
+
return files;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Validate a single JSONL file
|
|
38
|
+
*/
|
|
39
|
+
function validateFile(filePath, options) {
|
|
40
|
+
if (!options.json) {
|
|
41
|
+
console.log(chalk.cyan(`\nValidating: ${filePath}`));
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
// Read file content
|
|
45
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
46
|
+
// Validate JSONL content
|
|
47
|
+
const result = validateJSONL(content, {
|
|
48
|
+
skipInvalidJSON: !options.strict,
|
|
49
|
+
includeWarnings: true,
|
|
50
|
+
});
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error(chalk.red('Validation error:'), error instanceof Error ? error.message : String(error));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Validate command implementation
|
|
60
|
+
*/
|
|
61
|
+
export async function validateCommand(path, options) {
|
|
62
|
+
// Only show headers if not in JSON mode
|
|
63
|
+
if (!options.json) {
|
|
64
|
+
console.log(chalk.bold('GuideMode Canonical JSONL Validator'));
|
|
65
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
66
|
+
}
|
|
67
|
+
// Find all JSONL files
|
|
68
|
+
const files = findJSONLFiles(path);
|
|
69
|
+
if (files.length === 0) {
|
|
70
|
+
if (!options.json) {
|
|
71
|
+
console.log(chalk.yellow('No JSONL files found'));
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (!options.json) {
|
|
76
|
+
console.log(chalk.cyan(`Found ${files.length} JSONL file(s)`));
|
|
77
|
+
}
|
|
78
|
+
// Filter by provider if specified
|
|
79
|
+
const filesToValidate = options.provider
|
|
80
|
+
? files.filter(f => f.includes(`/${options.provider}/`))
|
|
81
|
+
: files;
|
|
82
|
+
if (filesToValidate.length === 0) {
|
|
83
|
+
if (!options.json) {
|
|
84
|
+
console.log(chalk.yellow(`No files found for provider: ${options.provider}`));
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (options.provider && !options.json) {
|
|
89
|
+
console.log(chalk.cyan(`Filtering for provider "${options.provider}": ${filesToValidate.length} file(s)`));
|
|
90
|
+
}
|
|
91
|
+
// Validate each file
|
|
92
|
+
const results = [];
|
|
93
|
+
for (const file of filesToValidate) {
|
|
94
|
+
const result = validateFile(file, options);
|
|
95
|
+
results.push({ file, result });
|
|
96
|
+
}
|
|
97
|
+
// Generate reports
|
|
98
|
+
if (options.json) {
|
|
99
|
+
// JSON output
|
|
100
|
+
const jsonOutput = results.map(r => ({
|
|
101
|
+
file: r.file,
|
|
102
|
+
valid: r.result.valid,
|
|
103
|
+
totalLines: r.result.totalLines,
|
|
104
|
+
validMessages: r.result.validMessages,
|
|
105
|
+
errors: r.result.errors,
|
|
106
|
+
warnings: r.result.sessionResult?.warnings || [],
|
|
107
|
+
sessionId: r.result.sessionResult?.sessionId,
|
|
108
|
+
provider: r.result.sessionResult?.provider,
|
|
109
|
+
}));
|
|
110
|
+
console.log(JSON.stringify(jsonOutput, null, 2));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// Human-readable output
|
|
114
|
+
for (const { file, result } of results) {
|
|
115
|
+
console.log(chalk.gray(`\n${'─'.repeat(50)}`));
|
|
116
|
+
console.log(chalk.bold(`File: ${file}`));
|
|
117
|
+
console.log(generateValidationReport(result, {
|
|
118
|
+
verbose: options.verbose,
|
|
119
|
+
colorize: true,
|
|
120
|
+
}));
|
|
121
|
+
}
|
|
122
|
+
// Summary
|
|
123
|
+
console.log(chalk.gray(`\n${'='.repeat(50)}`));
|
|
124
|
+
console.log(chalk.bold('Summary'));
|
|
125
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
126
|
+
const totalFiles = results.length;
|
|
127
|
+
const validFiles = results.filter(r => r.result.valid).length;
|
|
128
|
+
const invalidFiles = totalFiles - validFiles;
|
|
129
|
+
const totalMessages = results.reduce((sum, r) => sum + r.result.parsedLines, 0);
|
|
130
|
+
const validMessages = results.reduce((sum, r) => sum + r.result.validMessages, 0);
|
|
131
|
+
const totalErrors = results.reduce((sum, r) => sum + r.result.errors.length, 0);
|
|
132
|
+
const totalWarnings = results.reduce((sum, r) => sum + (r.result.sessionResult?.warnings.length || 0), 0);
|
|
133
|
+
console.log(`Total Files: ${totalFiles}`);
|
|
134
|
+
console.log(`Valid Files: ${chalk.green(validFiles)} / Invalid: ${invalidFiles > 0 ? chalk.red(invalidFiles) : invalidFiles}`);
|
|
135
|
+
console.log(`Total Messages: ${totalMessages} / Valid: ${chalk.green(validMessages)}`);
|
|
136
|
+
console.log(`Total Errors: ${totalErrors > 0 ? chalk.red(totalErrors) : totalErrors}`);
|
|
137
|
+
console.log(`Total Warnings: ${totalWarnings > 0 ? chalk.yellow(totalWarnings) : totalWarnings}`);
|
|
138
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
139
|
+
if (invalidFiles === 0 && totalErrors === 0) {
|
|
140
|
+
console.log(chalk.green(chalk.bold('\n✓ All validations passed!')));
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
console.log(chalk.red(chalk.bold(`\n✗ Validation failed with ${totalErrors} error(s) across ${invalidFiles} file(s)`)));
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Exit code
|
|
147
|
+
const hasErrors = results.some(r => !r.result.valid);
|
|
148
|
+
const hasWarnings = results.some(r => r.result.sessionResult && r.result.sessionResult.warnings.length > 0);
|
|
149
|
+
if (hasErrors || (options.strict && hasWarnings)) {
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Watch mode implementation
|
|
155
|
+
*/
|
|
156
|
+
export async function validateWatch(_path, _options) {
|
|
157
|
+
console.log(chalk.cyan('Watch mode not yet implemented'));
|
|
158
|
+
console.log(chalk.gray('Use --help for available options'));
|
|
159
|
+
process.exit(1);
|
|
160
|
+
// TODO: Implement watch mode with chokidar
|
|
161
|
+
// import { watch } from 'chokidar'
|
|
162
|
+
// const watcher = watch(path, { ignoreInitial: false })
|
|
163
|
+
// watcher.on('change', async (filePath) => {
|
|
164
|
+
// if (extname(filePath) === '.jsonl') {
|
|
165
|
+
// await validateFile(filePath, options)
|
|
166
|
+
// }
|
|
167
|
+
// })
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/validate.ts"],"names":[],"mappings":"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"}
|