codiedev 0.9.0 → 0.9.2
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/cli.js +0 -0
- package/dist/commands/push.js +7 -1
- package/dist/hook.js +26 -2
- package/dist/utils.d.ts +21 -0
- package/dist/utils.js +33 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
File without changes
|
package/dist/commands/push.js
CHANGED
|
@@ -136,7 +136,13 @@ async function runPush(args) {
|
|
|
136
136
|
const tagSummary = res.tags && res.tags.length > 0 ? ` tags=[${res.tags.join(", ")}]` : "";
|
|
137
137
|
console.log(`✓ Pushed ${filename} (kind=${res.kind}${tagSummary}).`);
|
|
138
138
|
console.log(` Visible under: ${res.destination}`);
|
|
139
|
-
|
|
139
|
+
// Echo the *resolved* key the server stored, not the local filename —
|
|
140
|
+
// skills are keyed by their frontmatter name (so two `SKILL.md` files
|
|
141
|
+
// don't collide), so the stored key can differ from what was pushed.
|
|
142
|
+
if (res.key && res.key !== filename) {
|
|
143
|
+
console.log(` Stored as: ${res.key}`);
|
|
144
|
+
}
|
|
145
|
+
console.log(` Pull with: codiedev pull ${res.key ?? filename}`);
|
|
140
146
|
}
|
|
141
147
|
catch (err) {
|
|
142
148
|
(0, shared_1.recordAgentEvent)(config, {
|
package/dist/hook.js
CHANGED
|
@@ -35,8 +35,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
const fs = __importStar(require("fs"));
|
|
38
|
+
const os = __importStar(require("os"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
38
40
|
const https = __importStar(require("https"));
|
|
39
41
|
const http = __importStar(require("http"));
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
40
43
|
const utils_1 = require("./utils");
|
|
41
44
|
const version_1 = require("./version");
|
|
42
45
|
function getJson(url, bearerToken) {
|
|
@@ -155,6 +158,20 @@ function resolveMode(arg) {
|
|
|
155
158
|
return "claude-code";
|
|
156
159
|
}
|
|
157
160
|
async function main() {
|
|
161
|
+
// Detached uploader child (spawned by the capture path below). The job —
|
|
162
|
+
// including transcript and token — is on disk; no stdin is needed, so handle
|
|
163
|
+
// this before readStdin() to avoid blocking on the ignored stdin pipe.
|
|
164
|
+
if (process.argv[2] === "upload") {
|
|
165
|
+
const jobFile = process.argv[3];
|
|
166
|
+
if (jobFile) {
|
|
167
|
+
await (0, utils_1.runCaptureUpload)(jobFile, {
|
|
168
|
+
post: postJson,
|
|
169
|
+
readFileSync: fs.readFileSync,
|
|
170
|
+
unlinkSync: fs.unlinkSync,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
process.exit(0);
|
|
174
|
+
}
|
|
158
175
|
let hookInput = {};
|
|
159
176
|
try {
|
|
160
177
|
const raw = await readStdin();
|
|
@@ -226,11 +243,18 @@ async function main() {
|
|
|
226
243
|
capturedAt: Date.now(),
|
|
227
244
|
source: mode,
|
|
228
245
|
};
|
|
246
|
+
// Fire the upload from a fully detached child and exit immediately. Awaiting
|
|
247
|
+
// it inline let Claude Code's SessionEnd shutdown window elapse and kill the
|
|
248
|
+
// still-running hook ("Hook cancelled") on large transcripts — even though
|
|
249
|
+
// the body had already reached the server. The detached child outlives this
|
|
250
|
+
// process and finishes the POST in the background.
|
|
229
251
|
try {
|
|
230
|
-
|
|
252
|
+
const hookScriptPath = process.argv[1];
|
|
253
|
+
const tmpFile = path.join(os.tmpdir(), `codiedev-capture-${session_id ?? process.pid}.json`);
|
|
254
|
+
(0, utils_1.dispatchCaptureDetached)({ url: `${config.backendUrl}/api/captureSession`, token: config.token, body: payload }, hookScriptPath, { spawn: child_process_1.spawn, writeFileSync: fs.writeFileSync, tmpFile });
|
|
231
255
|
}
|
|
232
256
|
catch (err) {
|
|
233
|
-
process.stderr.write(`[codiedev-hook] Warning: Failed to
|
|
257
|
+
process.stderr.write(`[codiedev-hook] Warning: Failed to dispatch session capture — ${err.message}\n`);
|
|
234
258
|
}
|
|
235
259
|
process.exit(0);
|
|
236
260
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import { spawn as nodeSpawn } from "child_process";
|
|
1
3
|
export interface CodiedevConfig {
|
|
2
4
|
token: string;
|
|
3
5
|
companyId: string;
|
|
@@ -101,3 +103,22 @@ export interface ParsedStats {
|
|
|
101
103
|
export declare function parseClaudeCodeStats(content: string): ParsedStats;
|
|
102
104
|
export declare function parseCodexStats(content: string): ParsedStats;
|
|
103
105
|
export declare function extractCodexRepoUrl(content: string): string | null;
|
|
106
|
+
export interface CaptureUploadJob {
|
|
107
|
+
url: string;
|
|
108
|
+
token: string;
|
|
109
|
+
body: Record<string, unknown>;
|
|
110
|
+
}
|
|
111
|
+
interface DispatchDeps {
|
|
112
|
+
spawn: typeof nodeSpawn;
|
|
113
|
+
writeFileSync: typeof fs.writeFileSync;
|
|
114
|
+
tmpFile: string;
|
|
115
|
+
nodePath?: string;
|
|
116
|
+
}
|
|
117
|
+
export declare function dispatchCaptureDetached(job: CaptureUploadJob, hookScriptPath: string, deps: DispatchDeps): void;
|
|
118
|
+
interface UploadDeps {
|
|
119
|
+
post: (url: string, body: Record<string, unknown>, token: string) => Promise<void>;
|
|
120
|
+
readFileSync: typeof fs.readFileSync;
|
|
121
|
+
unlinkSync: typeof fs.unlinkSync;
|
|
122
|
+
}
|
|
123
|
+
export declare function runCaptureUpload(jobFile: string, deps: UploadDeps): Promise<void>;
|
|
124
|
+
export {};
|
package/dist/utils.js
CHANGED
|
@@ -62,6 +62,8 @@ exports.installCursorHook = installCursorHook;
|
|
|
62
62
|
exports.parseClaudeCodeStats = parseClaudeCodeStats;
|
|
63
63
|
exports.parseCodexStats = parseCodexStats;
|
|
64
64
|
exports.extractCodexRepoUrl = extractCodexRepoUrl;
|
|
65
|
+
exports.dispatchCaptureDetached = dispatchCaptureDetached;
|
|
66
|
+
exports.runCaptureUpload = runCaptureUpload;
|
|
65
67
|
const fs = __importStar(require("fs"));
|
|
66
68
|
const path = __importStar(require("path"));
|
|
67
69
|
const os = __importStar(require("os"));
|
|
@@ -854,3 +856,34 @@ function extractCodexRepoUrl(content) {
|
|
|
854
856
|
}
|
|
855
857
|
return null;
|
|
856
858
|
}
|
|
859
|
+
// Fire-and-forget the session-capture upload from a fully detached child so the
|
|
860
|
+
// SessionEnd hook can exit 0 immediately. Awaiting the upload inline let Claude
|
|
861
|
+
// Code's shutdown window elapse and kill the hook ("Hook cancelled") on large
|
|
862
|
+
// transcripts. The job (incl. bearer token) is written to a file rather than
|
|
863
|
+
// passed via argv so it never shows up in the process list.
|
|
864
|
+
function dispatchCaptureDetached(job, hookScriptPath, deps) {
|
|
865
|
+
deps.writeFileSync(deps.tmpFile, JSON.stringify(job), { mode: 0o600 });
|
|
866
|
+
const child = deps.spawn(deps.nodePath ?? process.execPath, [hookScriptPath, "upload", deps.tmpFile], { detached: true, stdio: "ignore" });
|
|
867
|
+
child.unref();
|
|
868
|
+
}
|
|
869
|
+
// Runs inside the detached child spawned by `dispatchCaptureDetached`: read the
|
|
870
|
+
// persisted job, POST it, and ALWAYS delete the temp file afterwards (even on
|
|
871
|
+
// failure) so we don't litter the tmp dir. Never throws — capture is
|
|
872
|
+
// best-effort.
|
|
873
|
+
async function runCaptureUpload(jobFile, deps) {
|
|
874
|
+
try {
|
|
875
|
+
const job = JSON.parse(deps.readFileSync(jobFile, "utf8"));
|
|
876
|
+
await deps.post(job.url, job.body, job.token);
|
|
877
|
+
}
|
|
878
|
+
catch {
|
|
879
|
+
// best-effort — the parent already exited; nothing to report to.
|
|
880
|
+
}
|
|
881
|
+
finally {
|
|
882
|
+
try {
|
|
883
|
+
deps.unlinkSync(jobFile);
|
|
884
|
+
}
|
|
885
|
+
catch {
|
|
886
|
+
// temp file already gone — fine.
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
}
|
package/package.json
CHANGED