codiedev 0.9.78 → 0.9.80
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/assets/opencode-plugin.mjs +6 -0
- package/assets/session-key.mjs +48 -0
- package/dist/cli.js +70 -10
- package/dist/cliSession.d.ts +108 -0
- package/dist/cliSession.js +513 -0
- package/dist/codie.js +21 -1
- package/dist/commands/traces.js +57 -1
- package/dist/commands/tracesLabel.d.ts +24 -0
- package/dist/commands/tracesLabel.js +356 -0
- package/dist/configDir.d.ts +9 -0
- package/dist/configDir.js +25 -1
- package/dist/connect.js +45 -2
- package/dist/connectFlow.d.ts +21 -0
- package/dist/connectFlow.js +41 -0
- package/dist/hook.js +7 -0
- package/dist/launcher.d.ts +7 -2
- package/dist/launcher.js +36 -2
- package/dist/managedPi.js +18 -2
- package/dist/mcp.js +3 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +16 -8
- package/package.json +1 -1
package/dist/launcher.js
CHANGED
|
@@ -48,6 +48,7 @@ exports.LAUNCHER_FILE = void 0;
|
|
|
48
48
|
exports.launcherPath = launcherPath;
|
|
49
49
|
exports.usesLauncher = usesLauncher;
|
|
50
50
|
exports.readInstallRecord = readInstallRecord;
|
|
51
|
+
exports.stableHookScript = stableHookScript;
|
|
51
52
|
exports.recordCurrentInstall = recordCurrentInstall;
|
|
52
53
|
exports.ensureLauncher = ensureLauncher;
|
|
53
54
|
exports.resetLauncherCacheForTests = resetLauncherCacheForTests;
|
|
@@ -114,8 +115,35 @@ function packageVersionFor(hookScript) {
|
|
|
114
115
|
return undefined;
|
|
115
116
|
}
|
|
116
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* The hook script worth recording: absolute and present, and a global install over an npx cache
|
|
120
|
+
* copy (npm prunes ~/.npm/_npx, and hooks pointed there go quietly dead). Null = don't record.
|
|
121
|
+
*/
|
|
122
|
+
function stableHookScript(hookScript, globalCandidates = globalHookScripts()) {
|
|
123
|
+
if (!hookScript || !path.isAbsolute(hookScript) || hookScript.includes(`${path.sep}~${path.sep}`))
|
|
124
|
+
return null;
|
|
125
|
+
if (!fs.existsSync(hookScript))
|
|
126
|
+
return null;
|
|
127
|
+
if (hookScript.includes(`${path.sep}_npx${path.sep}`)) {
|
|
128
|
+
const global = globalCandidates.find((p) => path.isAbsolute(p) && fs.existsSync(p));
|
|
129
|
+
if (global)
|
|
130
|
+
return global;
|
|
131
|
+
}
|
|
132
|
+
return hookScript;
|
|
133
|
+
}
|
|
134
|
+
/** Where a global `npm i -g codiedev` puts hook.js, next to the node running this. */
|
|
135
|
+
function globalHookScripts() {
|
|
136
|
+
const prefix = path.dirname(path.dirname(process.execPath));
|
|
137
|
+
return [
|
|
138
|
+
path.join(prefix, "lib", "node_modules", "codiedev", "dist", "hook.js"),
|
|
139
|
+
path.join(prefix, "node_modules", "codiedev", "dist", "hook.js"),
|
|
140
|
+
];
|
|
141
|
+
}
|
|
117
142
|
/** Point the launcher at `hookScript`. Atomic, so a hook mid-launch never reads half a file. */
|
|
118
|
-
function recordCurrentInstall(
|
|
143
|
+
function recordCurrentInstall(requested) {
|
|
144
|
+
const hookScript = stableHookScript(requested);
|
|
145
|
+
if (!hookScript)
|
|
146
|
+
return false;
|
|
119
147
|
try {
|
|
120
148
|
const record = {
|
|
121
149
|
hookScript,
|
|
@@ -136,11 +164,17 @@ let ensuredFor;
|
|
|
136
164
|
* writable, in which case callers keep baking the direct path. Memoized:
|
|
137
165
|
* one connect writes ~20 hook entries.
|
|
138
166
|
*/
|
|
139
|
-
function ensureLauncher(
|
|
167
|
+
function ensureLauncher(requested) {
|
|
168
|
+
const hookScript = stableHookScript(requested);
|
|
169
|
+
if (!hookScript)
|
|
170
|
+
return null;
|
|
140
171
|
if (ensuredFor !== undefined && ensuredFor === hookScript)
|
|
141
172
|
return launcherPath();
|
|
142
173
|
try {
|
|
143
174
|
const target = launcherPath();
|
|
175
|
+
// A relative launcher path in a hook config only works from one folder; never bake one.
|
|
176
|
+
if (!path.isAbsolute(target))
|
|
177
|
+
return null;
|
|
144
178
|
const source = launcherSource(hookScript);
|
|
145
179
|
let current = null;
|
|
146
180
|
try {
|
package/dist/managedPi.js
CHANGED
|
@@ -94,7 +94,8 @@ exports.BLOCKED_BASE_URL = "http://127.0.0.1:9/blocked-by-codiedev";
|
|
|
94
94
|
* joins the captured pi session (same headers as the OpenCode metadata
|
|
95
95
|
* plugin, assets/git-refs.mjs). */
|
|
96
96
|
exports.GUARD_SOURCE = `// Written by Codiedev on every \`codie --pi\` launch. Edits are overwritten.
|
|
97
|
-
import { execFileSync } from "node:child_process";
|
|
97
|
+
import { execFile, execFileSync } from "node:child_process";
|
|
98
|
+
import { readFileSync } from "node:fs";
|
|
98
99
|
import { getProviders } from "@mariozechner/pi-ai";
|
|
99
100
|
|
|
100
101
|
const PROVIDER = ${JSON.stringify(exports.PI_PROVIDER_ID)};
|
|
@@ -153,8 +154,23 @@ export default function (pi) {
|
|
|
153
154
|
const p = String(event?.input?.path ?? "").replace(/\\\\/g, "/").match(/\\/([a-z0-9][a-z0-9_.:-]{0,119})\\/SKILL\\.md$/i);
|
|
154
155
|
if (event?.toolName === "read" && !event.isError && p && skills.size < 50) skills.add(p[1]);
|
|
155
156
|
});
|
|
157
|
+
// Browser sign-in: pi reads CODIEDEV_GATEWAY_KEY at request time, so put
|
|
158
|
+
// the current token there, refreshing it as it nears expiry (same logic as
|
|
159
|
+
// assets/session-key.mjs). Pasted API tokens: no variables, nothing changes.
|
|
160
|
+
const freshKey = async () => {
|
|
161
|
+
const env = process.env;
|
|
162
|
+
if (!env.CODIEDEV_SESSION_CONFIG || !env.CODIEDEV_CLI_JS || !env.CODIEDEV_NODE) return;
|
|
163
|
+
const read = () => { try { const c = JSON.parse(readFileSync(env.CODIEDEV_SESSION_CONFIG, "utf8")); return c && c.auth && c.token ? c : null; } catch { return null; } };
|
|
164
|
+
let s = read();
|
|
165
|
+
if (!s) return;
|
|
166
|
+
if (!(Number(s.auth.accessTokenExpiresAt) - Date.now() > 30 * 60000)) {
|
|
167
|
+
await new Promise((r) => execFile(env.CODIEDEV_NODE, [env.CODIEDEV_CLI_JS, "session-refresh"], { timeout: 30000 }, () => r()));
|
|
168
|
+
s = read() ?? s;
|
|
169
|
+
}
|
|
170
|
+
env.CODIEDEV_GATEWAY_KEY = s.token;
|
|
171
|
+
};
|
|
156
172
|
// Before every model call in the turn: the agent may have switched branch.
|
|
157
|
-
pi.on("turn_start", async (_event, ctx) => tag(ctx));
|
|
173
|
+
pi.on("turn_start", async (_event, ctx) => { await freshKey(); tag(ctx); });
|
|
158
174
|
pi.on("before_provider_request", (_event, ctx) => {
|
|
159
175
|
// Belt and braces: the request is already headed for BLOCKED.
|
|
160
176
|
if (!ours(ctx.model)) ctx.abort();
|
package/dist/mcp.js
CHANGED
|
@@ -51,6 +51,7 @@ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
|
51
51
|
const fs = __importStar(require("fs"));
|
|
52
52
|
const path = __importStar(require("path"));
|
|
53
53
|
const utils_1 = require("./utils");
|
|
54
|
+
const cliSession_1 = require("./cliSession");
|
|
54
55
|
const shared_1 = require("./commands/shared");
|
|
55
56
|
const inboxFormat_1 = require("./inboxFormat");
|
|
56
57
|
const PKG_NAME = "codiedev";
|
|
@@ -399,6 +400,8 @@ function emitTelemetry(config, event) {
|
|
|
399
400
|
});
|
|
400
401
|
}
|
|
401
402
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
403
|
+
// Long-lived process: the access token may expire while it runs.
|
|
404
|
+
await (0, cliSession_1.ensureFreshToken)({ configPath: utils_1.CONFIG_PATH }).catch(() => undefined);
|
|
402
405
|
const config = (0, utils_1.readConfig)();
|
|
403
406
|
if (!config) {
|
|
404
407
|
return {
|
package/dist/utils.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { CaptureLogEntry } from "./captureLog";
|
|
|
6
6
|
import { codiedevStateDir } from "./configDir";
|
|
7
7
|
export { inspectPiExtension, piExtensionPath } from "./piHooks";
|
|
8
8
|
export { codiedevStateDir };
|
|
9
|
+
import type { BrowserAuth } from "./cliSession";
|
|
9
10
|
export interface CodiedevConfig {
|
|
10
11
|
token: string;
|
|
11
12
|
companyId: string;
|
|
@@ -20,6 +21,7 @@ export interface CodiedevConfig {
|
|
|
20
21
|
deviceId?: string;
|
|
21
22
|
deviceName?: string;
|
|
22
23
|
captureIgnoredPaths?: string[];
|
|
24
|
+
auth?: BrowserAuth;
|
|
23
25
|
}
|
|
24
26
|
export declare const CONFIG_PATH: string;
|
|
25
27
|
export declare function readConfig(): CodiedevConfig | null;
|
package/dist/utils.js
CHANGED
|
@@ -150,6 +150,7 @@ const piHooks_1 = require("./piHooks");
|
|
|
150
150
|
var piHooks_2 = require("./piHooks");
|
|
151
151
|
Object.defineProperty(exports, "inspectPiExtension", { enumerable: true, get: function () { return piHooks_2.inspectPiExtension; } });
|
|
152
152
|
Object.defineProperty(exports, "piExtensionPath", { enumerable: true, get: function () { return piHooks_2.piExtensionPath; } });
|
|
153
|
+
const cliSession_1 = require("./cliSession");
|
|
153
154
|
const CONFIG_DIR = (0, configDir_1.codiedevStateDir)();
|
|
154
155
|
exports.CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
|
|
155
156
|
function readConfig() {
|
|
@@ -171,12 +172,9 @@ function writeConfigAtPath(config, configDir, configPath) {
|
|
|
171
172
|
if (!fs.existsSync(configDir)) {
|
|
172
173
|
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
|
173
174
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
});
|
|
178
|
-
// writeFile's mode does not replace permissions on a pre-existing file.
|
|
179
|
-
fs.chmodSync(configPath, 0o600);
|
|
175
|
+
// Temp file + rename: hooks read this file concurrently, and a torn read
|
|
176
|
+
// looks like "not connected". The temp file is created 0600.
|
|
177
|
+
(0, cliSession_1.writeConfigAtomic)(configPath, config);
|
|
180
178
|
}
|
|
181
179
|
// Parse a remote URL out of git-config INI text WITHOUT invoking git. Prefers
|
|
182
180
|
// the "origin" remote; falls back to the first remote found. Returns null if
|
|
@@ -1038,7 +1036,11 @@ function resolveHookInvocation(subcommand, preferredNodePath) {
|
|
|
1038
1036
|
// Bake the stable launcher, not this install's path, so later
|
|
1039
1037
|
// upgrades (including pnpm's hashed dirs) never strand the hook.
|
|
1040
1038
|
const launcher = (0, launcher_1.ensureLauncher)(hookScript);
|
|
1041
|
-
|
|
1039
|
+
// No launcher and no stable install to point at (e.g. an npx cache under a bogus "~"):
|
|
1040
|
+
// the npx fallback below beats baking a path that won't exist tomorrow.
|
|
1041
|
+
if (launcher || (0, launcher_1.stableHookScript)(hookScript)) {
|
|
1042
|
+
return { command: nodePath, args: [launcher ?? hookScript, subcommand] };
|
|
1043
|
+
}
|
|
1042
1044
|
}
|
|
1043
1045
|
}
|
|
1044
1046
|
}
|
|
@@ -1681,7 +1683,13 @@ thought, use the \`codiedev\` CLI via Bash:**
|
|
|
1681
1683
|
| "find something about X" / "has anyone solved Y?" | \`codiedev search "<query>" [--limit N]\` |
|
|
1682
1684
|
| "why did we…?" / "what does the team know about X?" | \`codiedev ask "<question>"\` (synthesized answer + citations) |
|
|
1683
1685
|
| "show my library" / "what artifacts exist?" | \`codiedev library [--scope mine\\|shared\\|all] [--kind doc\\|skill]\` |
|
|
1684
|
-
| "run my agent's test cases" / "check the dataset on model Y" | \`codiedev traces cases <agent> [--dataset <name>] [--model <id>]\` (writes cases + RUN_CASES.md + results.json; follow it, then \`codiedev traces report <results.json>\`) |
|
|
1686
|
+
| "run my agent's test cases" / "check the dataset on model Y" / "run v2 of the dataset" | \`codiedev traces cases <agent> [--dataset <name> [--version <n>]] [--model <id>]\` (writes cases + RUN_CASES.md + results.json; follow it, then \`codiedev traces report <results.json>\`) |
|
|
1687
|
+
| "how are my agents doing?" / "what's failing this week?" / "show the booking agent's failed runs" / "why did run X fail?" | \`codiedev traces overview\`; \`codiedev traces runs <agent> [--failed] [--flag <issue>] [--days n]\`; \`codiedev traces run <run> --agent <name>\` (add \`--json\` to read the data yourself) |
|
|
1688
|
+
| "add a helpfulness 1–5 score" / "make a review queue for tone" | \`codiedev traces score-kinds add <name> --type number --min 1 --max 5\`; \`codiedev traces queue create <name> --scores <a,b>\` |
|
|
1689
|
+
| "score that run 4 for helpfulness" / "how is my agent scoring?" | \`codiedev traces score <run> <score> <value> [--agent <name>] [--comment <why>]\`; \`codiedev traces scores <agent>\` |
|
|
1690
|
+
| "put this week's failed runs in the review queue" | \`codiedev traces queue list\`; \`codiedev traces queue add <queue> --agent <name> [--failed] [--days n]\` |
|
|
1691
|
+
| "have a judge score 10% of my agent's runs" / "turn off automatic scoring" | \`codiedev traces judge <agent> --on --scores <a,b> --sample 10 [--budget 25]\`; \`--off\`; no flags shows it |
|
|
1692
|
+
| "import these test cases from a CSV" / "add an example to the dataset" / "save the dataset as a version" | \`codiedev traces import <agent> <file> --dataset <name>\`; \`codiedev traces add-example <agent> --dataset <name> --input "…" [--expected "…"]\`; \`codiedev traces save-version <dataset>\`; \`codiedev traces versions <dataset>\` |
|
|
1685
1693
|
| "what was the last eval on X?" / "file these eval results" | \`codiedev evals last <subject>\` before starting a related eval; \`codiedev evals report <run.json>\` after each variant runs (scores only — \`codiedev evals help\` for the shape) |
|
|
1686
1694
|
|
|
1687
1695
|
**Just push the file — we'll figure out where it goes.** Every artifact
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codiedev",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.80",
|
|
4
4
|
"description": "Connect Claude Code, Codex, Cursor, OpenCode, or VS Code Copilot to Codiedev for team session capture and artifact collaboration — and run the governed Codie harness",
|
|
5
5
|
"bin": {
|
|
6
6
|
"codiedev": "dist/cli.js",
|