codiedev 0.10.0-beta.10 → 0.10.0-beta.13
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 +39 -0
- package/dist/commands/agents.js +21 -8
- package/dist/commands/scrub.js +91 -0
- package/dist/hook.js +13 -0
- package/dist/localScrub.js +689 -0
- package/dist/localScrubReport.js +249 -0
- package/dist/scrub/rules.js +389 -0
- package/package.json +4 -3
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
3
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
37
|
const connect_1 = require("./connect");
|
|
5
38
|
const cliSession_1 = require("./cliSession");
|
|
@@ -110,6 +143,7 @@ Privacy:
|
|
|
110
143
|
codiedev ignore <path> Never capture this folder or its children
|
|
111
144
|
codiedev unignore <path> Stop ignoring a folder
|
|
112
145
|
codiedev ignored [path] List ignored folders, or check one path
|
|
146
|
+
codiedev scrub [--dry-run] Remove keys from past agent sessions on this machine
|
|
113
147
|
|
|
114
148
|
Capture:
|
|
115
149
|
codiedev note "<text>" Capture a passing thought
|
|
@@ -545,6 +579,11 @@ async function main() {
|
|
|
545
579
|
case "read":
|
|
546
580
|
await (0, inbox_1.runRead)(rest);
|
|
547
581
|
return;
|
|
582
|
+
case "scrub": {
|
|
583
|
+
const { runScrubCommand } = await Promise.resolve().then(() => __importStar(require("./commands/scrub")));
|
|
584
|
+
process.exitCode = await runScrubCommand(rest);
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
548
587
|
case "note":
|
|
549
588
|
await (0, note_1.runNote)(rest);
|
|
550
589
|
return;
|
package/dist/commands/agents.js
CHANGED
|
@@ -154,7 +154,7 @@ result to \`/agent/.codiedev/output.json\`.
|
|
|
154
154
|
Preinstalled: Python 3.12 with openai, mcp, httpx, pydantic; Node 22 with
|
|
155
155
|
openai, @modelcontextprotocol/sdk, tsx; git, curl.
|
|
156
156
|
- **Exit code:** 0 = succeeded. An exception or non-zero exit = failed, with
|
|
157
|
-
the last log line as the error. Everything printed goes to the run's log.
|
|
157
|
+
the exception (or the last log line) as the error. Everything printed goes to the run's log.
|
|
158
158
|
|
|
159
159
|
## The sandbox
|
|
160
160
|
|
|
@@ -168,12 +168,16 @@ variables:
|
|
|
168
168
|
| \`CODIEDEV_GATEWAY_URL\`, \`CODIEDEV_API_KEY\` | The same two, under Codiedev names |
|
|
169
169
|
| \`CODIEDEV_AGENT\`, \`CODIEDEV_RUN_ID\` | This agent's name and this run's id |
|
|
170
170
|
| \`CODIEDEV_ATTEMPT\`, \`CODIEDEV_MAX_ATTEMPTS\` | Which try this is, out of how many |
|
|
171
|
+
| \`CODIEDEV_MODEL\` | The agent's default model: the first one its key allows (unset when it allows every model) |
|
|
171
172
|
| your secrets | Each by its own name, e.g. \`GITHUB_TOKEN\` |
|
|
172
173
|
|
|
173
174
|
**Models:** use a model id from your company's **Models** page, like
|
|
174
175
|
\`openai/gpt-5.1-codex-mini\`. A model your company hasn't approved fails with
|
|
175
176
|
\`model_not_allowed\`. Calls are traced under the agent's name and count
|
|
176
177
|
toward its \`budgetUsd\` (a monthly budget for the agent, not per run).
|
|
178
|
+
A call counts toward a run's cost when it sends the header
|
|
179
|
+
\`X-Codiedev-Run-Id: $CODIEDEV_RUN_ID\`. \`agents.openai()\` does; for any other
|
|
180
|
+
client or tool, add the header yourself (see opencode below).
|
|
177
181
|
|
|
178
182
|
**Dependencies** from \`package.json\` install into \`/agent/node_modules\`, so
|
|
179
183
|
their binaries are in \`/agent/node_modules/.bin\`. Python packages are importable
|
|
@@ -193,7 +197,9 @@ config = {
|
|
|
193
197
|
"autoupdate": False, "share": "disabled", "permission": "allow",
|
|
194
198
|
"provider": {"codiedev": {
|
|
195
199
|
"npm": "@ai-sdk/openai-compatible",
|
|
196
|
-
"options": {"baseURL": os.environ["OPENAI_BASE_URL"], "apiKey": "{env:OPENAI_API_KEY}"
|
|
200
|
+
"options": {"baseURL": os.environ["OPENAI_BASE_URL"], "apiKey": "{env:OPENAI_API_KEY}",
|
|
201
|
+
# Counts its model calls toward this run's cost.
|
|
202
|
+
"headers": {"X-Codiedev-Run-Id": os.environ["CODIEDEV_RUN_ID"]}},
|
|
197
203
|
"models": {MODEL: {}},
|
|
198
204
|
}},
|
|
199
205
|
}
|
|
@@ -455,13 +461,21 @@ function writeGuides(dir) {
|
|
|
455
461
|
if (!fs.existsSync(path.join(dir, "CLAUDE.md")))
|
|
456
462
|
fs.writeFileSync(path.join(dir, "CLAUDE.md"), "@AGENTS.md\n");
|
|
457
463
|
}
|
|
464
|
+
function fillTemplate(text, file, name, model) {
|
|
465
|
+
let out = text.replace(/%NAME%/g, name);
|
|
466
|
+
if (!model) {
|
|
467
|
+
const fallback = file.endsWith(".py") ? 'os.environ.get("CODIEDEV_MODEL", "codiedev/fast")' : '(process.env.CODIEDEV_MODEL ?? "codiedev/fast")';
|
|
468
|
+
out = out.replace(/"%MODEL%"/g, fallback);
|
|
469
|
+
}
|
|
470
|
+
return out.replace(/%MODEL%/g, model ?? "codiedev/fast");
|
|
471
|
+
}
|
|
458
472
|
async function initFromTemplate(name, dir, id, args) {
|
|
459
|
-
const model = flag(args, "--model")
|
|
473
|
+
const model = flag(args, "--model");
|
|
460
474
|
const starter = agentTemplates_generated_1.TEMPLATES.find((t) => t.id === id);
|
|
461
475
|
if (starter) {
|
|
462
476
|
for (const [rel, text] of Object.entries(starter.files)) {
|
|
463
477
|
fs.mkdirSync(path.dirname(path.join(dir, rel)), { recursive: true });
|
|
464
|
-
fs.writeFileSync(path.join(dir, rel), text
|
|
478
|
+
fs.writeFileSync(path.join(dir, rel), fillTemplate(text, rel, name, model));
|
|
465
479
|
}
|
|
466
480
|
writeGuides(dir);
|
|
467
481
|
console.log(`Created ${path.relative(process.cwd(), dir) || "."}/ from the ${starter.title} template.`);
|
|
@@ -502,16 +516,15 @@ async function cmdInit(args) {
|
|
|
502
516
|
if (existing)
|
|
503
517
|
fail(`${dir} already has an ${existing}`);
|
|
504
518
|
fs.mkdirSync(dir, { recursive: true });
|
|
505
|
-
const model = flag(args, "--model")
|
|
506
|
-
const fill = (t) => t.replace(/%NAME%/g, name).replace(/%MODEL%/g, model);
|
|
519
|
+
const model = flag(args, "--model");
|
|
507
520
|
let entrypoint = "agent.py";
|
|
508
521
|
if (lang.startsWith("py")) {
|
|
509
|
-
fs.writeFileSync(path.join(dir, "agent.py"),
|
|
522
|
+
fs.writeFileSync(path.join(dir, "agent.py"), fillTemplate(STARTER_AGENT, "agent.py", name, model));
|
|
510
523
|
fs.writeFileSync(path.join(dir, "requirements.txt"), "# Extra packages for this agent, one per line. openai, mcp, httpx and pydantic are preinstalled.\n");
|
|
511
524
|
}
|
|
512
525
|
else {
|
|
513
526
|
entrypoint = lang.startsWith("t") ? "agent.ts" : "agent.mjs";
|
|
514
|
-
fs.writeFileSync(path.join(dir, entrypoint),
|
|
527
|
+
fs.writeFileSync(path.join(dir, entrypoint), fillTemplate(STARTER_TS, entrypoint, name, model));
|
|
515
528
|
fs.writeFileSync(path.join(dir, "package.json"), JSON.stringify({ name, private: true, type: "module", dependencies: {} }, null, 2) + "\n");
|
|
516
529
|
}
|
|
517
530
|
fs.writeFileSync(path.join(dir, "agent.json"), JSON.stringify({ name, entrypoint, timeoutSec: 600 }, null, 2) + "\n");
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SCRUB_HELP = void 0;
|
|
4
|
+
exports.parseScrubArgs = parseScrubArgs;
|
|
5
|
+
exports.formatScrubSummary = formatScrubSummary;
|
|
6
|
+
exports.runScrubCommand = runScrubCommand;
|
|
7
|
+
const localScrub_1 = require("../localScrub");
|
|
8
|
+
exports.SCRUB_HELP = `codiedev scrub — remove keys from past agent sessions on this machine
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
codiedev scrub [--dry-run] [--path <file>]... [--session <id>]... [--min-age <minutes>]
|
|
12
|
+
|
|
13
|
+
Cleans the session files Claude Code, Codex, Cursor, Copilot, OpenCode/Codie
|
|
14
|
+
and pi keep locally, using the same rules as the Codiedev server. Each key is
|
|
15
|
+
replaced with [REDACTED:<kind>]. Sessions changed in the last hour are skipped
|
|
16
|
+
so open sessions are never touched. When signed in, what was found (session,
|
|
17
|
+
key type and last 4, removed or not) shows on your Security page; the keys
|
|
18
|
+
themselves never leave this machine.
|
|
19
|
+
|
|
20
|
+
--dry-run Count what would be cleaned; change nothing
|
|
21
|
+
--path <file> Only this file (repeatable)
|
|
22
|
+
--session <id> With --path <opencode.db>: only this OpenCode/Codie session
|
|
23
|
+
--min-age <min> Skip files changed in the last <min> minutes (default 60)
|
|
24
|
+
`;
|
|
25
|
+
function parseScrubArgs(args) {
|
|
26
|
+
let dryRun = false;
|
|
27
|
+
let help = false;
|
|
28
|
+
const only = [];
|
|
29
|
+
const sessions = [];
|
|
30
|
+
let minAgeMs = localScrub_1.MIN_AGE_MS;
|
|
31
|
+
for (let i = 0; i < args.length; i++) {
|
|
32
|
+
const a = args[i];
|
|
33
|
+
if (a === "--dry-run")
|
|
34
|
+
dryRun = true;
|
|
35
|
+
else if (a === "--help" || a === "-h")
|
|
36
|
+
help = true;
|
|
37
|
+
else if (a === "--path" && args[i + 1])
|
|
38
|
+
only.push(args[++i]);
|
|
39
|
+
else if (a === "--session" && args[i + 1])
|
|
40
|
+
sessions.push(args[++i]);
|
|
41
|
+
else if (a === "--min-age" && args[i + 1]) {
|
|
42
|
+
const m = Number(args[++i]);
|
|
43
|
+
if (Number.isFinite(m) && m >= 0)
|
|
44
|
+
minAgeMs = m * 60_000;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { dryRun, help, minAgeMs, ...(only.length ? { only } : {}), ...(sessions.length ? { onlySessions: sessions } : {}) };
|
|
48
|
+
}
|
|
49
|
+
function formatScrubSummary(s) {
|
|
50
|
+
const lines = [];
|
|
51
|
+
const verb = s.dryRun ? "Would remove" : "Removed";
|
|
52
|
+
lines.push(s.redactions === 0
|
|
53
|
+
? `No keys found in ${s.scanned} session file${s.scanned === 1 ? "" : "s"} checked.`
|
|
54
|
+
: `${verb} ${s.redactions} key${s.redactions === 1 ? "" : "s"}${s.dryRun ? "" : ` from ${s.cleaned} file${s.cleaned === 1 ? "" : "s"}`} (${s.scanned} checked).`);
|
|
55
|
+
for (const [h, t] of Object.entries(s.byHarness))
|
|
56
|
+
lines.push(` ${h}: ${t.redactions} in ${t.files} file${t.files === 1 ? "" : "s"}`);
|
|
57
|
+
if (s.skippedRecent)
|
|
58
|
+
lines.push(`Skipped ${s.skippedRecent} changed in the last hour (may be open).`);
|
|
59
|
+
if (s.skippedLarge)
|
|
60
|
+
lines.push(`Skipped ${s.skippedLarge} over 100 MB.`);
|
|
61
|
+
if (s.changedWhileCleaning)
|
|
62
|
+
lines.push(`Left ${s.changedWhileCleaning} alone: changed while cleaning.`);
|
|
63
|
+
if (s.errors)
|
|
64
|
+
lines.push(`${s.errors} couldn't be read or written.`);
|
|
65
|
+
if (s.unfinished)
|
|
66
|
+
lines.push("Stopped at the time limit; the next run continues.");
|
|
67
|
+
if (s.leftInCursor.keys > 0) {
|
|
68
|
+
const { keys, chats } = s.leftInCursor;
|
|
69
|
+
lines.push(`${keys} key${keys === 1 ? " is" : "s are"} still in ${chats} Cursor chat${chats === 1 ? "" : "s"}. ` +
|
|
70
|
+
"Cursor's own chat store can't be cleaned without breaking the chat; delete those chats in Cursor to remove them.");
|
|
71
|
+
}
|
|
72
|
+
return lines.join("\n");
|
|
73
|
+
}
|
|
74
|
+
async function runScrubCommand(args) {
|
|
75
|
+
const opts = parseScrubArgs(args);
|
|
76
|
+
if (opts.help) {
|
|
77
|
+
console.log(exports.SCRUB_HELP);
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
const summary = await (0, localScrub_1.runAndReport)({
|
|
81
|
+
dryRun: opts.dryRun,
|
|
82
|
+
only: opts.only,
|
|
83
|
+
onlySessions: opts.onlySessions,
|
|
84
|
+
minAgeMs: opts.minAgeMs,
|
|
85
|
+
budgetMs: 10 * 60_000,
|
|
86
|
+
});
|
|
87
|
+
console.log(formatScrubSummary(summary));
|
|
88
|
+
if (summary.reported)
|
|
89
|
+
console.log("Sent to your Security page in Codiedev (key type and last 4 only, never the key).");
|
|
90
|
+
return summary.errors > 0 ? 1 : 0;
|
|
91
|
+
}
|
package/dist/hook.js
CHANGED
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
})();
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
exports.buildDiscoveryContext = buildDiscoveryContext;
|
|
38
|
+
const localScrub_1 = require("./localScrub");
|
|
38
39
|
const captureSignals_1 = require("./captureSignals");
|
|
39
40
|
const transcriptModels_1 = require("./transcriptModels");
|
|
40
41
|
const fs = __importStar(require("fs"));
|
|
@@ -442,6 +443,15 @@ async function main() {
|
|
|
442
443
|
}
|
|
443
444
|
process.exit(0);
|
|
444
445
|
}
|
|
446
|
+
if (process.argv[2] === "local-scrub") {
|
|
447
|
+
try {
|
|
448
|
+
const { runAndReport } = await Promise.resolve().then(() => __importStar(require("./localScrub")));
|
|
449
|
+
await runAndReport();
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
}
|
|
453
|
+
process.exit(0);
|
|
454
|
+
}
|
|
445
455
|
if (process.argv[2] === "self-update") {
|
|
446
456
|
await (0, selfUpdate_1.runSelfUpdate)(process.argv[1]);
|
|
447
457
|
process.exit(0);
|
|
@@ -489,6 +499,8 @@ async function main() {
|
|
|
489
499
|
await runCodexLimitSweep(hookInput.session_id);
|
|
490
500
|
if (source === "codex")
|
|
491
501
|
(0, sync_1.maybeSpawnPackSync)({ connected: Boolean((0, utils_1.readConfig)()), cli: path.join(__dirname, "cli.js") });
|
|
502
|
+
if (source === "codex")
|
|
503
|
+
(0, localScrub_1.maybeSpawnLocalScrub)({ connected: Boolean((0, utils_1.readConfig)()) });
|
|
492
504
|
if (source !== "copilot")
|
|
493
505
|
await runDiscover(hookInput.prompt);
|
|
494
506
|
return;
|
|
@@ -530,6 +542,7 @@ async function main() {
|
|
|
530
542
|
process.argv[2] === "session-start-opencode" ||
|
|
531
543
|
process.argv[2] === "session-start-pi") {
|
|
532
544
|
(0, sync_1.maybeSpawnPackSync)({ connected: Boolean((0, utils_1.readConfig)()), cli: path.join(__dirname, "cli.js") });
|
|
545
|
+
(0, localScrub_1.maybeSpawnLocalScrub)({ connected: Boolean((0, utils_1.readConfig)()) });
|
|
533
546
|
const packNag = process.argv[2] === "session-start-opencode" || process.argv[2] === "session-start-pi" ? null : (0, sync_1.packNagLine)();
|
|
534
547
|
if (packNag && process.argv[2] === "session-start")
|
|
535
548
|
process.stdout.write(`${packNag}\n`);
|