codiedev 0.9.80 → 0.10.0-beta.10
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 +12 -5
- package/dist/backup/cache.js +1 -5
- package/dist/backup/match.js +0 -6
- package/dist/backup/run.js +3 -35
- package/dist/captureExclusions.js +0 -12
- package/dist/captureLog.js +0 -28
- package/dist/captureReadiness.js +0 -58
- package/dist/captureSignals.js +0 -11
- package/dist/cli.js +11 -33
- package/dist/cliSession.js +3 -60
- package/dist/codexHookTrust.js +0 -28
- package/dist/codexLimitScan.js +0 -107
- package/dist/codie.js +64 -57
- package/dist/codieBrandInstall.js +0 -18
- package/dist/codieLauncher.js +1 -72
- package/dist/codieRuntime.js +27 -32
- package/dist/codieRuntimeInstall.js +11 -43
- package/dist/codieUsage.js +0 -49
- package/dist/commands/agentTemplates.generated.js +136 -0
- package/dist/commands/agents.js +1088 -0
- package/dist/commands/agentsSdk.generated.js +7 -0
- package/dist/commands/ask.js +0 -3
- package/dist/commands/capture.js +0 -2
- package/dist/commands/createTicket.js +0 -10
- package/dist/commands/doctor.js +2 -72
- package/dist/commands/evals.js +3 -9
- package/dist/commands/inbox.js +0 -2
- package/dist/commands/library.js +0 -3
- package/dist/commands/pack.js +0 -29
- package/dist/commands/ping.js +0 -2
- package/dist/commands/pull.js +0 -9
- package/dist/commands/push.js +0 -12
- package/dist/commands/search.js +0 -4
- package/dist/commands/send.js +0 -5
- package/dist/commands/share.js +0 -4
- package/dist/commands/shared.js +0 -35
- package/dist/commands/traces.js +0 -13
- package/dist/commands/tracesLabel.js +0 -8
- package/dist/configDir.js +1 -18
- package/dist/connect.js +3 -75
- package/dist/connectFlow.js +0 -15
- package/dist/copilotHooks.js +0 -67
- package/dist/copilotInstallation.js +0 -1
- package/dist/cursorHooks.js +1 -11
- package/dist/cursorLifecycle.js +1 -7
- package/dist/detection.js +0 -30
- package/dist/harnessDirs.js +0 -19
- package/dist/hook.js +43 -293
- package/dist/inboxFormat.js +0 -24
- package/dist/launchContext.js +0 -50
- package/dist/launcher.js +0 -33
- package/dist/limitEvent.js +2 -34
- package/dist/managedPi.js +2 -50
- package/dist/mcp.js +0 -48
- package/dist/nativeSteering.js +1 -4
- package/dist/packs/codie.js +0 -15
- package/dist/packs/harnesses.js +1 -38
- package/dist/packs/hookGate.js +0 -33
- package/dist/packs/install.js +0 -20
- package/dist/packs/manifest.js +1 -15
- package/dist/packs/paths.js +0 -8
- package/dist/packs/shim.js +0 -8
- package/dist/packs/store.js +0 -12
- package/dist/packs/sync.js +0 -20
- package/dist/piHooks.js +4 -45
- package/dist/piRuntime.js +0 -18
- package/dist/repoResolver.js +0 -19
- package/dist/secret.js +0 -3
- package/dist/selfUpdate.js +2 -77
- package/dist/skillMarker.js +0 -14
- package/dist/subagents.js +0 -18
- package/dist/teamSkillContext.js +0 -1
- package/dist/transcriptModels.js +0 -8
- package/dist/upgradeNudge.js +1 -30
- package/dist/utils.js +165 -768
- package/dist/version.js +0 -10
- package/dist/versionCheck.js +0 -33
- package/package.json +13 -8
- package/dist/backup/cache.d.ts +0 -14
- package/dist/backup/match.d.ts +0 -2
- package/dist/backup/run.d.ts +0 -25
- package/dist/captureExclusions.d.ts +0 -30
- package/dist/captureLog.d.ts +0 -20
- package/dist/captureReadiness.d.ts +0 -65
- package/dist/captureSignals.d.ts +0 -47
- package/dist/cli.d.ts +0 -15
- package/dist/cliSession.d.ts +0 -108
- package/dist/codexHookTrust.d.ts +0 -49
- package/dist/codexLimitScan.d.ts +0 -64
- package/dist/codie.d.ts +0 -2
- package/dist/codieBrandInstall.d.ts +0 -11
- package/dist/codieLauncher.d.ts +0 -87
- package/dist/codieRuntime.d.ts +0 -35
- package/dist/codieRuntimeInstall.d.ts +0 -56
- package/dist/codieUsage.d.ts +0 -64
- package/dist/commands/ask.d.ts +0 -1
- package/dist/commands/capture.d.ts +0 -14
- package/dist/commands/createTicket.d.ts +0 -27
- package/dist/commands/delete.d.ts +0 -1
- package/dist/commands/doctor.d.ts +0 -9
- package/dist/commands/evals.d.ts +0 -3
- package/dist/commands/inbox.d.ts +0 -3
- package/dist/commands/library.d.ts +0 -2
- package/dist/commands/note.d.ts +0 -1
- package/dist/commands/pack.d.ts +0 -54
- package/dist/commands/ping.d.ts +0 -1
- package/dist/commands/pull.d.ts +0 -2
- package/dist/commands/push.d.ts +0 -33
- package/dist/commands/search.d.ts +0 -2
- package/dist/commands/send.d.ts +0 -2
- package/dist/commands/share.d.ts +0 -2
- package/dist/commands/shared.d.ts +0 -64
- package/dist/commands/traces.d.ts +0 -72
- package/dist/commands/tracesLabel.d.ts +0 -24
- package/dist/configDir.d.ts +0 -10
- package/dist/connect.d.ts +0 -1
- package/dist/connectFlow.d.ts +0 -34
- package/dist/copilotHooks.d.ts +0 -85
- package/dist/copilotInstallation.d.ts +0 -10
- package/dist/cursorHooks.d.ts +0 -13
- package/dist/cursorLifecycle.d.ts +0 -2
- package/dist/detection.d.ts +0 -30
- package/dist/harnessDirs.d.ts +0 -15
- package/dist/hook.d.ts +0 -6
- package/dist/inboxFormat.d.ts +0 -38
- package/dist/launchContext.d.ts +0 -46
- package/dist/launcher.d.ts +0 -25
- package/dist/limitEvent.d.ts +0 -15
- package/dist/limitEventReporter.d.ts +0 -21
- package/dist/managedPi.d.ts +0 -48
- package/dist/mcp.d.ts +0 -12
- package/dist/nativeSteering.d.ts +0 -5
- package/dist/packs/codie.d.ts +0 -45
- package/dist/packs/harnesses.d.ts +0 -74
- package/dist/packs/hookGate.d.ts +0 -53
- package/dist/packs/install.d.ts +0 -46
- package/dist/packs/manifest.d.ts +0 -52
- package/dist/packs/paths.d.ts +0 -17
- package/dist/packs/shim.d.ts +0 -26
- package/dist/packs/store.d.ts +0 -42
- package/dist/packs/sync.d.ts +0 -40
- package/dist/piHooks.d.ts +0 -22
- package/dist/piRuntime.d.ts +0 -26
- package/dist/repoResolver.d.ts +0 -17
- package/dist/secret.d.ts +0 -1
- package/dist/selfUpdate.d.ts +0 -64
- package/dist/skillMarker.d.ts +0 -6
- package/dist/subagents.d.ts +0 -36
- package/dist/teamSkillContext.d.ts +0 -9
- package/dist/transcriptModels.d.ts +0 -20
- package/dist/upgradeNudge.d.ts +0 -24
- package/dist/utils.d.ts +0 -396
- package/dist/version.d.ts +0 -1
- package/dist/versionCheck.d.ts +0 -68
package/dist/inboxFormat.js
CHANGED
|
@@ -2,32 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.formatInbox = formatInbox;
|
|
4
4
|
const shared_1 = require("./commands/shared");
|
|
5
|
-
/**
|
|
6
|
-
* Render the inbox for BOTH surfaces — `codiedev inbox` and the MCP
|
|
7
|
-
* `codiedev_inbox` tool an agent calls for "any messages?". Shared so the
|
|
8
|
-
* agent path can never drift back to pings-only while the human path shows
|
|
9
|
-
* mentions.
|
|
10
|
-
*/
|
|
11
5
|
function formatInbox(opts) {
|
|
12
6
|
const mentions = opts.mentions ?? [];
|
|
13
|
-
// The backend applies `limit` to each source independently, so asking for N
|
|
14
|
-
// can return up to 2N — and with no `--limit` it defaults to 50 per source,
|
|
15
|
-
// i.e. 100 rows, twice the pre-change maximum. Cap the COMBINED list by
|
|
16
|
-
// recency, always (matching the backend's own default), so the header is
|
|
17
|
-
// truthful and `--limit` actually holds.
|
|
18
|
-
//
|
|
19
|
-
// Selected by identity rather than by a `createdAt >= cutoff` filter: rows
|
|
20
|
-
// tied on the cutoff millisecond are reachable (Convex freezes Date.now()
|
|
21
|
-
// per transaction, and seeded activity carries synthetic stamps) and a
|
|
22
|
-
// threshold filter lets every tied row through, overshooting the limit.
|
|
23
7
|
const DEFAULT_LIMIT = 50;
|
|
24
8
|
const cap = opts.limit ?? DEFAULT_LIMIT;
|
|
25
|
-
// Pings claim the budget first, then mentions fill whatever is left — both
|
|
26
|
-
// newest-first. Before this change pings owned the whole budget, so this is
|
|
27
|
-
// purely additive and can never hide a ping that used to be visible. A flat
|
|
28
|
-
// recency cap would instead let a busy feed evict every direct ping, and
|
|
29
|
-
// pings are the actionable half: they carry the id you reply to, and losing
|
|
30
|
-
// them all takes the mark-read footer with them.
|
|
31
9
|
const byRecency = (xs) => [...xs].sort((a, b) => b.createdAt - a.createdAt);
|
|
32
10
|
const keptPings = byRecency(opts.pings).slice(0, cap);
|
|
33
11
|
const keptMentions = byRecency(mentions).slice(0, Math.max(0, cap - keptPings.length));
|
|
@@ -50,8 +28,6 @@ function formatInbox(opts) {
|
|
|
50
28
|
lines.push(` id: ${p.pingId}`);
|
|
51
29
|
lines.push("");
|
|
52
30
|
}
|
|
53
|
-
// Mentions carry no CLI-side body to reply to — the thread lives in the feed
|
|
54
|
-
// — so each row ends in the deep link rather than an id.
|
|
55
31
|
for (const m of keptMentions) {
|
|
56
32
|
const dot = m.readAt ? "·" : "●";
|
|
57
33
|
const from = m.from?.name ?? "someone";
|
package/dist/launchContext.js
CHANGED
|
@@ -8,38 +8,22 @@ exports.detectCursorLaunch = detectCursorLaunch;
|
|
|
8
8
|
exports.detectCopilotLaunch = detectCopilotLaunch;
|
|
9
9
|
exports.hookLaunch = hookLaunch;
|
|
10
10
|
const node_child_process_1 = require("node:child_process");
|
|
11
|
-
/**
|
|
12
|
-
* How a harness that records nothing about its own launch was started.
|
|
13
|
-
* Claude Code (`entrypoint`) and Codex (`session_meta.source`) stamp this in
|
|
14
|
-
* the transcript; Cursor, Codie and the Copilot CLI do not, so the hook reads
|
|
15
|
-
* it from the process that launched it. Raw, namespaced values; what counts as
|
|
16
|
-
* "automated" is decided in reporting, not here.
|
|
17
|
-
*/
|
|
18
11
|
const VALUE = /^[a-z0-9][a-z0-9_.:-]{0,39}$/;
|
|
19
|
-
/** Codie (OpenCode) subcommands, read in-process by the capture plugin. */
|
|
20
12
|
const CODIE_SUBCOMMANDS = ["run", "serve", "acp", "web", "attach"];
|
|
21
13
|
function codieLaunchFromArgv(argv) {
|
|
22
14
|
const sub = argv.find((a) => CODIE_SUBCOMMANDS.includes(a));
|
|
23
15
|
return sub ? `codie:${sub}` : "codie:tui";
|
|
24
16
|
}
|
|
25
|
-
/**
|
|
26
|
-
* Split a command line into tokens, honouring double quotes (Windows quotes
|
|
27
|
-
* paths with spaces: "C:\\Program Files\\…\\node.exe" "…\\index.js" -p hi).
|
|
28
|
-
*/
|
|
29
17
|
function tokenize(command) {
|
|
30
18
|
const tokens = [];
|
|
31
19
|
for (const m of command.matchAll(/"([^"]*)"|(\S+)/g))
|
|
32
20
|
tokens.push(m[1] ?? m[2]);
|
|
33
21
|
return tokens;
|
|
34
22
|
}
|
|
35
|
-
/** A path segment named cursor-agent / agent (Unix or Windows separators). */
|
|
36
23
|
const CURSOR_AGENT_PATH = /(^|[/\\])cursor-agent([/\\]|\.(exe|cmd|ps1)$|$)/i;
|
|
37
24
|
const AGENT_BIN = /(^|[/\\])(cursor-)?agent(\.(exe|cmd|ps1))?$/i;
|
|
38
|
-
/** One launching process's command line → a Cursor launch value. */
|
|
39
25
|
function cursorLaunchFromCommand(command) {
|
|
40
26
|
const tokens = tokenize(command);
|
|
41
|
-
// The CLI runs as `<launcher> [node] …/cursor-agent/versions/<v>/index.js [flags] [prompt]`
|
|
42
|
-
// on macOS/Linux (~/.local/share/cursor-agent) and Windows (%LOCALAPPDATA%\cursor-agent).
|
|
43
27
|
const isAgent = tokens.some((t) => CURSOR_AGENT_PATH.test(t) || /[/\\]\.local[/\\]share[/\\]cursor/i.test(t))
|
|
44
28
|
&& tokens.some((t) => AGENT_BIN.test(t) || /index\.js$/i.test(t));
|
|
45
29
|
if (isAgent) {
|
|
@@ -51,14 +35,7 @@ function cursorLaunchFromCommand(command) {
|
|
|
51
35
|
return "cursor:ide";
|
|
52
36
|
return undefined;
|
|
53
37
|
}
|
|
54
|
-
/** Cursor flags that take a value; the token after them is not the prompt. */
|
|
55
38
|
const CURSOR_VALUE_FLAGS = new Set(["--model", "-m", "--output-format", "--api-key", "--resume", "--workspace", "--mode", "-H", "--header"]);
|
|
56
|
-
/**
|
|
57
|
-
* The flags before the prompt. The prompt is on the command line too, so a
|
|
58
|
-
* prompt mentioning "-p" must not read as headless: stop at the first token
|
|
59
|
-
* that is neither a flag nor a flag's value. Starts after the launcher script
|
|
60
|
-
* (`…/index.js`) when present, else after the agent binary.
|
|
61
|
-
*/
|
|
62
39
|
function cursorFlags(tokens) {
|
|
63
40
|
let start = tokens.findIndex((t) => /index\.js$/i.test(t));
|
|
64
41
|
if (start < 0)
|
|
@@ -74,20 +51,10 @@ function cursorFlags(tokens) {
|
|
|
74
51
|
}
|
|
75
52
|
return flags;
|
|
76
53
|
}
|
|
77
|
-
/** The Copilot CLI binary or its npm launcher (`copilot`, `copilot.exe`, `copilot.cmd`). */
|
|
78
54
|
const COPILOT_BIN = /(^|[/\\])copilot(\.(exe|cmd|ps1|js))?$/i;
|
|
79
55
|
const NODE_BIN = /(^|[/\\])node(\.exe)?$/i;
|
|
80
|
-
/**
|
|
81
|
-
* One launching process's command line → a Copilot CLI launch value. The CLI
|
|
82
|
-
* runs as `…/@github/copilot-<platform>/copilot [flags]` under
|
|
83
|
-
* `node …/bin/copilot [flags]`; `-p`/`--prompt` is headless (scripted). VS
|
|
84
|
-
* Code's agent (`copilot-runtime --headless`) is named by workspace.yaml
|
|
85
|
-
* instead, so it never matches here.
|
|
86
|
-
*/
|
|
87
56
|
function copilotLaunchFromCommand(command) {
|
|
88
57
|
const tokens = tokenize(command);
|
|
89
|
-
// Only the program itself (or the script `node` runs): a shell command line
|
|
90
|
-
// that merely mentions "copilot" as a word is not the Copilot CLI.
|
|
91
58
|
const bin = COPILOT_BIN.test(tokens[0] ?? "")
|
|
92
59
|
? 0
|
|
93
60
|
: NODE_BIN.test(tokens[0] ?? "") && COPILOT_BIN.test(tokens[1] ?? "")
|
|
@@ -99,7 +66,6 @@ function copilotLaunchFromCommand(command) {
|
|
|
99
66
|
const t = tokens[i];
|
|
100
67
|
if (t === "-p" || t === "--prompt" || t.startsWith("--prompt="))
|
|
101
68
|
return "copilot:print";
|
|
102
|
-
// The prompt itself can mention "-p": stop at the first non-flag token.
|
|
103
69
|
if (!t.startsWith("-"))
|
|
104
70
|
break;
|
|
105
71
|
if (COPILOT_VALUE_FLAGS.has(t))
|
|
@@ -107,7 +73,6 @@ function copilotLaunchFromCommand(command) {
|
|
|
107
73
|
}
|
|
108
74
|
return "copilot:cli";
|
|
109
75
|
}
|
|
110
|
-
/** Copilot CLI flags that take a value; the token after them is not a flag. */
|
|
111
76
|
const COPILOT_VALUE_FLAGS = new Set([
|
|
112
77
|
"--model", "--add-dir", "--allow-tool", "--deny-tool", "--resume", "--log-dir",
|
|
113
78
|
"--log-level", "--agent", "--config-dir", "--allow-url", "--deny-url",
|
|
@@ -119,11 +84,6 @@ const psPosix = (pid) => {
|
|
|
119
84
|
const match = line.match(/^(\d+)\s+(.*)$/s);
|
|
120
85
|
return match ? { ppid: Number(match[1]), command: match[2] } : null;
|
|
121
86
|
};
|
|
122
|
-
/**
|
|
123
|
-
* Windows: one PowerShell call returns the whole ancestor chain (spawning
|
|
124
|
-
* PowerShell per level would cost ~0.5s each). CommandLine needs CIM, which
|
|
125
|
-
* every supported Windows has; any failure means "unknown", never a guess.
|
|
126
|
-
*/
|
|
127
87
|
function windowsAncestors(startPid, depth) {
|
|
128
88
|
const script = `$p=${Math.trunc(startPid)};$o=@();for($i=0;$i -lt ${Math.trunc(depth)} -and $p -gt 0;$i++){` +
|
|
129
89
|
`$x=Get-CimInstance Win32_Process -Filter "ProcessId=$p" -ErrorAction SilentlyContinue;if(!$x){break};` +
|
|
@@ -131,8 +91,6 @@ function windowsAncestors(startPid, depth) {
|
|
|
131
91
|
`ConvertTo-Json -InputObject @($o) -Compress`;
|
|
132
92
|
const result = (0, node_child_process_1.spawnSync)("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], {
|
|
133
93
|
encoding: "utf8",
|
|
134
|
-
// A cold PowerShell start can take several seconds on a busy machine; the
|
|
135
|
-
// capture hook has 30s, and an unanswered walk just means "unknown".
|
|
136
94
|
timeout: 10000,
|
|
137
95
|
windowsHide: true,
|
|
138
96
|
});
|
|
@@ -146,7 +104,6 @@ function windowsAncestors(startPid, depth) {
|
|
|
146
104
|
return null;
|
|
147
105
|
}
|
|
148
106
|
}
|
|
149
|
-
/** First launch value `fromCommand` finds among up to `depth` ancestors. */
|
|
150
107
|
function detectLaunch(fromCommand, startPid, deps) {
|
|
151
108
|
const depth = deps.depth ?? 5;
|
|
152
109
|
if ((deps.platform ?? process.platform) === "win32" && !deps.ps) {
|
|
@@ -173,25 +130,18 @@ function detectLaunch(fromCommand, startPid, deps) {
|
|
|
173
130
|
}
|
|
174
131
|
return undefined;
|
|
175
132
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Walk up to `depth` ancestors (a shell or `npx` usually sits between Cursor
|
|
178
|
-
* and the hook) and return the first Cursor launch found.
|
|
179
|
-
*/
|
|
180
133
|
function detectCursorLaunch(startPid = process.ppid, deps = {}) {
|
|
181
134
|
return detectLaunch(cursorLaunchFromCommand, startPid, deps);
|
|
182
135
|
}
|
|
183
|
-
/** The Copilot CLI that launched this hook (`copilot:print` / `copilot:cli`). */
|
|
184
136
|
function detectCopilotLaunch(startPid = process.ppid, deps = {}) {
|
|
185
137
|
return detectLaunch(copilotLaunchFromCommand, startPid, deps);
|
|
186
138
|
}
|
|
187
|
-
/** The launch value a hook invocation should carry into its capture job. */
|
|
188
139
|
function hookLaunch(hookCommand, input, deps = {}) {
|
|
189
140
|
if (typeof input.launch === "string" && VALUE.test(input.launch))
|
|
190
141
|
return input.launch;
|
|
191
142
|
if (hookCommand?.endsWith("-cursor"))
|
|
192
143
|
return detectCursorLaunch();
|
|
193
144
|
if (hookCommand?.endsWith("-copilot")) {
|
|
194
|
-
// VS Code names itself in workspace.yaml; only the CLI needs the walk.
|
|
195
145
|
if (deps.copilotClientName === "vscode-agent-host")
|
|
196
146
|
return "copilot:vscode";
|
|
197
147
|
return (deps.detectCopilot ?? detectCopilotLaunch)();
|
package/dist/launcher.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
// Stable hook launcher.
|
|
3
|
-
//
|
|
4
|
-
// Harness configs used to bake the absolute path of whichever install ran
|
|
5
|
-
// `connect` (…/node_modules/codiedev/dist/hook.js). That path is only stable
|
|
6
|
-
// for npm/bun globals: pnpm puts every global install in a fresh hashed dir,
|
|
7
|
-
// and repo checkouts, Homebrew cellar moves, etc. can strand it too. Instead,
|
|
8
|
-
// every hook config points at one file we own —
|
|
9
|
-
// <codiedevStateDir()>/bin/codiedev-hook-launcher.cjs — which forwards to the
|
|
10
|
-
// install recorded in <codiedevStateDir()>/install.json. Moving to a new
|
|
11
|
-
// install (self-update, re-connect) rewrites one JSON file, never the
|
|
12
|
-
// harness configs, so Codex hook trust and IT-managed dotfiles stay put.
|
|
13
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
3
|
if (k2 === undefined) k2 = k;
|
|
15
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -56,7 +45,6 @@ const fs = __importStar(require("fs"));
|
|
|
56
45
|
const path = __importStar(require("path"));
|
|
57
46
|
const configDir_1 = require("./configDir");
|
|
58
47
|
exports.LAUNCHER_FILE = "codiedev-hook-launcher.cjs";
|
|
59
|
-
// Bump when LAUNCHER_SOURCE changes so existing launchers get rewritten.
|
|
60
48
|
const LAUNCHER_REVISION = 1;
|
|
61
49
|
function launcherPath() {
|
|
62
50
|
return path.join((0, configDir_1.codiedevStateDir)(), "bin", exports.LAUNCHER_FILE);
|
|
@@ -64,15 +52,9 @@ function launcherPath() {
|
|
|
64
52
|
function installRecordPath() {
|
|
65
53
|
return path.join((0, configDir_1.codiedevStateDir)(), "install.json");
|
|
66
54
|
}
|
|
67
|
-
/** True iff `cmd` invokes the stable launcher (from any state dir). */
|
|
68
55
|
function usesLauncher(cmd) {
|
|
69
56
|
return typeof cmd === "string" && cmd.includes(exports.LAUNCHER_FILE);
|
|
70
57
|
}
|
|
71
|
-
// Plain CommonJS with no dependencies: it runs under whatever node the harness
|
|
72
|
-
// config names, before any of our modules load. `fallback` is the install the
|
|
73
|
-
// launcher was written for, used if install.json is missing or points at a
|
|
74
|
-
// directory that no longer exists. If neither exists it exits 0 so a stranded
|
|
75
|
-
// hook can never fail the developer's session.
|
|
76
58
|
function launcherSource(fallback) {
|
|
77
59
|
return `// codiedev-hook-launcher revision ${LAUNCHER_REVISION}. Managed by codiedev; safe to delete (re-run \`codiedev connect\`).
|
|
78
60
|
"use strict";
|
|
@@ -115,10 +97,6 @@ function packageVersionFor(hookScript) {
|
|
|
115
97
|
return undefined;
|
|
116
98
|
}
|
|
117
99
|
}
|
|
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
100
|
function stableHookScript(hookScript, globalCandidates = globalHookScripts()) {
|
|
123
101
|
if (!hookScript || !path.isAbsolute(hookScript) || hookScript.includes(`${path.sep}~${path.sep}`))
|
|
124
102
|
return null;
|
|
@@ -131,7 +109,6 @@ function stableHookScript(hookScript, globalCandidates = globalHookScripts()) {
|
|
|
131
109
|
}
|
|
132
110
|
return hookScript;
|
|
133
111
|
}
|
|
134
|
-
/** Where a global `npm i -g codiedev` puts hook.js, next to the node running this. */
|
|
135
112
|
function globalHookScripts() {
|
|
136
113
|
const prefix = path.dirname(path.dirname(process.execPath));
|
|
137
114
|
return [
|
|
@@ -139,7 +116,6 @@ function globalHookScripts() {
|
|
|
139
116
|
path.join(prefix, "node_modules", "codiedev", "dist", "hook.js"),
|
|
140
117
|
];
|
|
141
118
|
}
|
|
142
|
-
/** Point the launcher at `hookScript`. Atomic, so a hook mid-launch never reads half a file. */
|
|
143
119
|
function recordCurrentInstall(requested) {
|
|
144
120
|
const hookScript = stableHookScript(requested);
|
|
145
121
|
if (!hookScript)
|
|
@@ -158,12 +134,6 @@ function recordCurrentInstall(requested) {
|
|
|
158
134
|
}
|
|
159
135
|
}
|
|
160
136
|
let ensuredFor;
|
|
161
|
-
/**
|
|
162
|
-
* Make sure the launcher exists and forwards to `hookScript`, returning the
|
|
163
|
-
* launcher path to bake into hook configs — or null if the state dir is not
|
|
164
|
-
* writable, in which case callers keep baking the direct path. Memoized:
|
|
165
|
-
* one connect writes ~20 hook entries.
|
|
166
|
-
*/
|
|
167
137
|
function ensureLauncher(requested) {
|
|
168
138
|
const hookScript = stableHookScript(requested);
|
|
169
139
|
if (!hookScript)
|
|
@@ -172,7 +142,6 @@ function ensureLauncher(requested) {
|
|
|
172
142
|
return launcherPath();
|
|
173
143
|
try {
|
|
174
144
|
const target = launcherPath();
|
|
175
|
-
// A relative launcher path in a hook config only works from one folder; never bake one.
|
|
176
145
|
if (!path.isAbsolute(target))
|
|
177
146
|
return null;
|
|
178
147
|
const source = launcherSource(hookScript);
|
|
@@ -181,7 +150,6 @@ function ensureLauncher(requested) {
|
|
|
181
150
|
current = fs.readFileSync(target, "utf8");
|
|
182
151
|
}
|
|
183
152
|
catch {
|
|
184
|
-
// first install
|
|
185
153
|
}
|
|
186
154
|
if (current !== source)
|
|
187
155
|
writeAtomic(target, source);
|
|
@@ -195,7 +163,6 @@ function ensureLauncher(requested) {
|
|
|
195
163
|
return null;
|
|
196
164
|
}
|
|
197
165
|
}
|
|
198
|
-
// Test-only: the memo lives for the process lifetime.
|
|
199
166
|
function resetLauncherCacheForTests() {
|
|
200
167
|
ensuredFor = undefined;
|
|
201
168
|
}
|
package/dist/limitEvent.js
CHANGED
|
@@ -14,7 +14,6 @@ function classifyLimitKind(text) {
|
|
|
14
14
|
return "org_spend";
|
|
15
15
|
return "other";
|
|
16
16
|
}
|
|
17
|
-
// "… · resets 9:50pm (UTC)" → "9:50pm (UTC)". Null when absent.
|
|
18
17
|
function parseResetText(text) {
|
|
19
18
|
const m = text.match(/resets\s+(.+?)\s*$/i);
|
|
20
19
|
return m ? m[1].trim() : null;
|
|
@@ -27,8 +26,6 @@ function messageText(entry) {
|
|
|
27
26
|
return c.map((x) => (x && typeof x === "object" ? x.text ?? "" : "")).join(" ");
|
|
28
27
|
return "";
|
|
29
28
|
}
|
|
30
|
-
// Scans transcript JSONL for the LAST top-level `error: "rate_limit"` entry.
|
|
31
|
-
// (Validated shape: error/isApiErrorMessage are top-level, not under message.)
|
|
32
29
|
function parseLimitEventFromTranscript(transcript) {
|
|
33
30
|
let found = null;
|
|
34
31
|
for (const line of transcript.split("\n")) {
|
|
@@ -53,29 +50,6 @@ function parseLimitEventFromTranscript(transcript) {
|
|
|
53
50
|
}
|
|
54
51
|
return found;
|
|
55
52
|
}
|
|
56
|
-
/**
|
|
57
|
-
* Codex's `rate_limit_reached_type` is exactly five values (read off the 0.154
|
|
58
|
-
* binary): `rate_limit_reached`, `workspace_{owner,member}_credits_depleted`
|
|
59
|
-
* and `workspace_{owner,member}_usage_limit_reached`.
|
|
60
|
-
*
|
|
61
|
-
* The split that matters to a reader of the dashboard is "someone must act on
|
|
62
|
-
* money" vs "this dev is throttled and it will reset" — so map on what the
|
|
63
|
-
* snapshot actually asserts, not on the word "credits":
|
|
64
|
-
*
|
|
65
|
-
* - A member out of their OWN allowance is a rate limit. Real snapshots carry
|
|
66
|
-
* `spend_control_reached: null` and `individual_limit: null` — nobody
|
|
67
|
-
* configured a budget, the window is simply used up. Calling that personal
|
|
68
|
-
* spend tells a manager the dev overspent, which is not what happened.
|
|
69
|
-
*
|
|
70
|
-
* Deliberately NOT gated on `individual_limit`: it has only ever been
|
|
71
|
-
* observed null, so its populated shape and meaning are unknown, and a
|
|
72
|
-
* wrong guess reinstates the mislabel this exists to remove. The reason
|
|
73
|
-
* string is the causal signal; `individual_limit` is at best correlative.
|
|
74
|
-
* - A member whose ADMIN capped them (`usage_limit_reached`) is personal spend:
|
|
75
|
-
* there really is a cap, and someone can raise it.
|
|
76
|
-
* - Anything owner-scoped is org spend — the org's allowance or credits are
|
|
77
|
-
* gone and somebody has to act.
|
|
78
|
-
*/
|
|
79
53
|
function codexLimitKind(reason, spendControlReached) {
|
|
80
54
|
if (spendControlReached || reason.startsWith("workspace_owner_"))
|
|
81
55
|
return "org_spend";
|
|
@@ -96,7 +70,6 @@ function codexResetText(rateLimits) {
|
|
|
96
70
|
.sort((a, b) => a - b)[0];
|
|
97
71
|
return resetAt ? new Date(resetAt * 1000).toISOString() : null;
|
|
98
72
|
}
|
|
99
|
-
/** Parse the structured rate-limit snapshot written to Codex rollout JSONL. */
|
|
100
73
|
function parseCodexLimitEventFromTranscript(transcript) {
|
|
101
74
|
let found = null;
|
|
102
75
|
for (const line of transcript.split("\n")) {
|
|
@@ -131,7 +104,6 @@ function parseCodexLimitEventFromTranscript(transcript) {
|
|
|
131
104
|
}
|
|
132
105
|
return found;
|
|
133
106
|
}
|
|
134
|
-
/** Only explicit provider errors qualify; never scan user/assistant prose. */
|
|
135
107
|
function parseNativeLimitError(input, now = Date.now()) {
|
|
136
108
|
const context = input.errorContext ?? input.error_context;
|
|
137
109
|
if (context !== undefined && context !== "model_call")
|
|
@@ -162,19 +134,15 @@ function parseNativeLimitEventFromTranscript(transcript) {
|
|
|
162
134
|
continue;
|
|
163
135
|
}
|
|
164
136
|
if (!entry.timestamp)
|
|
165
|
-
continue;
|
|
137
|
+
continue;
|
|
166
138
|
if (entry.type === "agent.error" || entry.type === "session.error") {
|
|
167
139
|
found = parseNativeLimitError({ ...(entry.data ?? entry), timestamp: entry.timestamp }) ?? found;
|
|
168
140
|
}
|
|
169
141
|
}
|
|
170
|
-
catch {
|
|
142
|
+
catch { }
|
|
171
143
|
}
|
|
172
144
|
return found;
|
|
173
145
|
}
|
|
174
|
-
// Tail of the raw transcript to ship with the limit event so the server can
|
|
175
|
-
// summarize "what they were working on" immediately — without waiting for the
|
|
176
|
-
// SessionEnd capture (which can lag hours, or drop entirely on Windows).
|
|
177
|
-
// Resumes at a line boundary so every JSONL line in the tail still parses.
|
|
178
146
|
const DEFAULT_TAIL_CHARS = 65536;
|
|
179
147
|
function tailForLimitEvent(transcript, maxChars = DEFAULT_TAIL_CHARS) {
|
|
180
148
|
if (transcript.length <= maxChars)
|
package/dist/managedPi.js
CHANGED
|
@@ -40,28 +40,6 @@ exports.prepareManagedPiDir = prepareManagedPiDir;
|
|
|
40
40
|
exports.managedPiEnv = managedPiEnv;
|
|
41
41
|
exports.managedPiArgs = managedPiArgs;
|
|
42
42
|
exports.runManagedPi = runManagedPi;
|
|
43
|
-
// `codie --pi [args]`: pi as a Codiedev harness, on the company's approved
|
|
44
|
-
// gateway models (the same catalog and key the OpenCode engine uses).
|
|
45
|
-
//
|
|
46
|
-
// The managed launch closes every path to a model that skips the gateway
|
|
47
|
-
// instead of trusting the user's ~/.pi:
|
|
48
|
-
// - pi runs from a Codiedev-owned agent dir (PI_CODING_AGENT_DIR), rewritten
|
|
49
|
-
// on every launch: only the `codiedev` provider, no packages, no
|
|
50
|
-
// extensions and no auth.json (so no stored provider credentials).
|
|
51
|
-
// - provider API keys pi would read from the environment are removed.
|
|
52
|
-
// - extension discovery is off (`--no-extensions`, which also skips
|
|
53
|
-
// project-local .pi/extensions); the only extensions are the guard below
|
|
54
|
-
// and the Codiedev capture extension.
|
|
55
|
-
// - flags that bring their own credentials or code (--api-key, --provider,
|
|
56
|
-
// -e) and the package subcommands are refused.
|
|
57
|
-
// - the guard points every other provider at a dead loopback address and
|
|
58
|
-
// keeps the session on an approved model, which covers an in-session
|
|
59
|
-
// /login too. Throwing from pi's before_provider_request does NOT stop a
|
|
60
|
-
// request (pi logs it and sends anyway), hence the base-URL override.
|
|
61
|
-
//
|
|
62
|
-
// Sessions, skills, prompts, themes and context files keep working; they
|
|
63
|
-
// don't reach a model on their own. Ported from #1783, minus the harness-pack
|
|
64
|
-
// proxy: pi talks to the gateway directly, like `codie`.
|
|
65
43
|
const child_process_1 = require("child_process");
|
|
66
44
|
const fs = __importStar(require("fs"));
|
|
67
45
|
const path = __importStar(require("path"));
|
|
@@ -69,7 +47,6 @@ const codieLauncher_1 = require("./codieLauncher");
|
|
|
69
47
|
const piRuntime_1 = require("./piRuntime");
|
|
70
48
|
const utils_1 = require("./utils");
|
|
71
49
|
exports.PI_PROVIDER_ID = "codiedev";
|
|
72
|
-
/** Env vars pi reads provider credentials from (`pi --help`, pi 0.73). */
|
|
73
50
|
exports.PI_PROVIDER_ENV = [
|
|
74
51
|
"ANTHROPIC_API_KEY", "ANTHROPIC_OAUTH_TOKEN", "OPENAI_API_KEY", "AZURE_OPENAI_API_KEY",
|
|
75
52
|
"AZURE_OPENAI_BASE_URL", "AZURE_OPENAI_RESOURCE_NAME", "DEEPSEEK_API_KEY", "GEMINI_API_KEY",
|
|
@@ -81,18 +58,10 @@ exports.PI_PROVIDER_ENV = [
|
|
|
81
58
|
"AWS_BEARER_TOKEN_BEDROCK", "GOOGLE_APPLICATION_CREDENTIALS", "GOOGLE_CLOUD_API_KEY",
|
|
82
59
|
"COPILOT_GITHUB_TOKEN",
|
|
83
60
|
];
|
|
84
|
-
/** pi subcommands that install or change extension sources. */
|
|
85
61
|
const BLOCKED_SUBCOMMANDS = new Set(["install", "remove", "uninstall", "config"]);
|
|
86
62
|
exports.GUARD_FILE = "codie-guard.ts";
|
|
87
63
|
exports.CAPTURE_FILE = "codiedev-capture.ts";
|
|
88
|
-
/** Where the guard points every other provider: a loopback port nothing
|
|
89
|
-
* listens on, so a request (and whatever key it carries) never leaves the
|
|
90
|
-
* machine. */
|
|
91
64
|
exports.BLOCKED_BASE_URL = "http://127.0.0.1:9/blocked-by-codiedev";
|
|
92
|
-
/** The pi extension that keeps a managed session on Codiedev models and tags
|
|
93
|
-
* each gateway request with the session, repo and skills, so gateway billing
|
|
94
|
-
* joins the captured pi session (same headers as the OpenCode metadata
|
|
95
|
-
* plugin, assets/git-refs.mjs). */
|
|
96
65
|
exports.GUARD_SOURCE = `// Written by Codiedev on every \`codie --pi\` launch. Edits are overwritten.
|
|
97
66
|
import { execFile, execFileSync } from "node:child_process";
|
|
98
67
|
import { readFileSync } from "node:fs";
|
|
@@ -180,8 +149,6 @@ export default function (pi) {
|
|
|
180
149
|
function managedPiAgentDir(stateDir) {
|
|
181
150
|
return path.join(stateDir, "managed", "pi", "agent");
|
|
182
151
|
}
|
|
183
|
-
/** pi's models.json entry for the gateway. The key is read from
|
|
184
|
-
* CODIEDEV_GATEWAY_KEY at request time (pi resolves an env var name). */
|
|
185
152
|
function piProviderConfig(gatewayUrl, catalog) {
|
|
186
153
|
return {
|
|
187
154
|
baseUrl: gatewayUrl.replace(/\/+$/, ""),
|
|
@@ -192,9 +159,6 @@ function piProviderConfig(gatewayUrl, catalog) {
|
|
|
192
159
|
id: (0, codieLauncher_1.bareModel)(model.id),
|
|
193
160
|
name: model.name || (0, codieLauncher_1.bareModel)(model.id),
|
|
194
161
|
...(model.limit ? { contextWindow: model.limit.context, maxTokens: model.limit.output } : {}),
|
|
195
|
-
// pi shows a session's spend from this. The gateway publishes prompt and
|
|
196
|
-
// completion prices only, so cache is unpriced; gateway settlement is
|
|
197
|
-
// the true figure.
|
|
198
162
|
...(model.cost ? { cost: { input: model.cost.input, output: model.cost.output, cacheRead: 0, cacheWrite: 0 } } : {}),
|
|
199
163
|
})),
|
|
200
164
|
};
|
|
@@ -204,8 +168,6 @@ function writeJsonAtomic(file, value) {
|
|
|
204
168
|
fs.writeFileSync(tmp, JSON.stringify(value, null, 2) + "\n", { mode: 0o600 });
|
|
205
169
|
fs.renameSync(tmp, file);
|
|
206
170
|
}
|
|
207
|
-
/** Rewrite everything Codiedev owns in the managed agent dir. Sessions (and
|
|
208
|
-
* anything else pi keeps there) are left alone. Returns the extensions to load. */
|
|
209
171
|
function prepareManagedPiDir(opts) {
|
|
210
172
|
const { agentDir, gatewayUrl, catalog } = opts;
|
|
211
173
|
if (!catalog.length)
|
|
@@ -226,22 +188,18 @@ function prepareManagedPiDir(opts) {
|
|
|
226
188
|
skills: opts.skillPaths ?? [],
|
|
227
189
|
enableInstallTelemetry: false,
|
|
228
190
|
});
|
|
229
|
-
// Stored provider credentials (a /login from an earlier session) and any
|
|
230
|
-
// extensions dropped into the dir go away on every launch.
|
|
231
191
|
fs.rmSync(path.join(agentDir, "auth.json"), { force: true });
|
|
232
192
|
fs.rmSync(path.join(agentDir, "extensions"), { recursive: true, force: true });
|
|
233
193
|
const guard = path.join(agentDir, exports.GUARD_FILE);
|
|
234
194
|
fs.writeFileSync(guard, exports.GUARD_SOURCE, { mode: 0o600 });
|
|
235
195
|
const capture = path.join(agentDir, exports.CAPTURE_FILE);
|
|
236
|
-
fs.writeFileSync(capture, (0, utils_1.piExtensionSource)(
|
|
196
|
+
fs.writeFileSync(capture, (0, utils_1.piExtensionSource)(), { mode: 0o600 });
|
|
237
197
|
return [guard, capture];
|
|
238
198
|
}
|
|
239
|
-
/** The child env: no provider credentials, pi pointed at the managed dir. */
|
|
240
199
|
function managedPiEnv(env, agentDir, key, platform = process.platform) {
|
|
241
200
|
const blocked = new Set([...exports.PI_PROVIDER_ENV, "PI_CODING_AGENT_DIR"]);
|
|
242
201
|
const out = {};
|
|
243
202
|
for (const [k, v] of Object.entries(env)) {
|
|
244
|
-
// Windows env names are case-insensitive.
|
|
245
203
|
if (blocked.has(platform === "win32" ? k.toUpperCase() : k))
|
|
246
204
|
continue;
|
|
247
205
|
out[k] = v;
|
|
@@ -254,8 +212,6 @@ function managedPiEnv(env, agentDir, key, platform = process.platform) {
|
|
|
254
212
|
class ManagedPiArgError extends Error {
|
|
255
213
|
}
|
|
256
214
|
exports.ManagedPiArgError = ManagedPiArgError;
|
|
257
|
-
/** Refuse what would bring other credentials or code into the session, then
|
|
258
|
-
* pin extension loading to the managed extensions. */
|
|
259
215
|
function managedPiArgs(args, extensions) {
|
|
260
216
|
if (args.length && BLOCKED_SUBCOMMANDS.has(args[0])) {
|
|
261
217
|
throw new ManagedPiArgError(`\`pi ${args[0]}\` changes extension sources, which codie --pi manages. Ask your Codiedev admin to approve a package instead.`);
|
|
@@ -282,12 +238,9 @@ function runManagedPi(opts) {
|
|
|
282
238
|
const agentDir = managedPiAgentDir(opts.stateDir);
|
|
283
239
|
const extensions = prepareManagedPiDir({
|
|
284
240
|
agentDir, gatewayUrl: opts.gatewayUrl, catalog: opts.catalog, model: env.CODIEDEV_MODEL,
|
|
285
|
-
skillPaths: opts.skillPaths,
|
|
241
|
+
skillPaths: opts.skillPaths,
|
|
286
242
|
});
|
|
287
243
|
const args = managedPiArgs(opts.args, extensions);
|
|
288
|
-
// CODIEDEV_PI_BIN runs a specific pi binary (tests, canaries pinned to a
|
|
289
|
-
// version). Otherwise pi is Codiedev's own pinned install, fetched on first
|
|
290
|
-
// use like the Codie engine and run on this Node.
|
|
291
244
|
const bin = env.CODIEDEV_PI_BIN?.trim();
|
|
292
245
|
const [command, commandArgs] = bin
|
|
293
246
|
? [bin, args]
|
|
@@ -295,7 +248,6 @@ function runManagedPi(opts) {
|
|
|
295
248
|
const result = (0, child_process_1.spawnSync)(command, commandArgs, {
|
|
296
249
|
stdio: "inherit",
|
|
297
250
|
env: managedPiEnv(env, agentDir, opts.key),
|
|
298
|
-
// A pi binary given as an npm launcher is a .cmd shim on Windows.
|
|
299
251
|
shell: Boolean(bin) && process.platform === "win32",
|
|
300
252
|
});
|
|
301
253
|
if (result.error)
|
package/dist/mcp.js
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* Codiedev MCP server.
|
|
5
|
-
*
|
|
6
|
-
* Exposes the Codiedev artifact-collaboration surface as Model Context
|
|
7
|
-
* Protocol tools so Claude Code / Codex / any MCP-capable agent can invoke
|
|
8
|
-
* them natively from natural language (e.g. "push the spec we just worked on").
|
|
9
|
-
*
|
|
10
|
-
* Reads the same ~/.codiedev/config.json the CLI uses. Install + wire up by
|
|
11
|
-
* running `npx codiedev connect`.
|
|
12
|
-
*/
|
|
13
3
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
4
|
if (k2 === undefined) k2 = k;
|
|
15
5
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -55,8 +45,6 @@ const cliSession_1 = require("./cliSession");
|
|
|
55
45
|
const shared_1 = require("./commands/shared");
|
|
56
46
|
const inboxFormat_1 = require("./inboxFormat");
|
|
57
47
|
const PKG_NAME = "codiedev";
|
|
58
|
-
// Read version from the bundled package.json so the startup log + tool reports
|
|
59
|
-
// always reflect the actually-installed version, rather than a stale constant.
|
|
60
48
|
const PKG_VERSION = (() => {
|
|
61
49
|
try {
|
|
62
50
|
const pkgPath = path.resolve(__dirname, "..", "package.json");
|
|
@@ -66,10 +54,6 @@ const PKG_VERSION = (() => {
|
|
|
66
54
|
return "unknown";
|
|
67
55
|
}
|
|
68
56
|
})();
|
|
69
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
70
|
-
// Tool definitions — descriptions tuned so Claude/Codex resolve natural-language
|
|
71
|
-
// requests into the right tool without manual steering.
|
|
72
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
73
57
|
const TOOLS = [
|
|
74
58
|
{
|
|
75
59
|
name: "codiedev_push",
|
|
@@ -372,17 +356,10 @@ const TOOLS = [
|
|
|
372
356
|
},
|
|
373
357
|
},
|
|
374
358
|
];
|
|
375
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
376
|
-
// Server
|
|
377
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
378
359
|
const server = new index_js_1.Server({ name: PKG_NAME, version: PKG_VERSION }, { capabilities: { tools: {} } });
|
|
379
360
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
380
361
|
tools: TOOLS,
|
|
381
362
|
}));
|
|
382
|
-
/**
|
|
383
|
-
* Fire-and-forget telemetry — POST one event per tool invocation. Never blocks,
|
|
384
|
-
* never throws into the user-facing path. Drop silently on any failure.
|
|
385
|
-
*/
|
|
386
363
|
function emitTelemetry(config, event) {
|
|
387
364
|
if (!config)
|
|
388
365
|
return;
|
|
@@ -396,11 +373,9 @@ function emitTelemetry(config, event) {
|
|
|
396
373
|
mcpVersion: PKG_VERSION,
|
|
397
374
|
},
|
|
398
375
|
}).catch(() => {
|
|
399
|
-
// Swallow — telemetry should never affect the user's session.
|
|
400
376
|
});
|
|
401
377
|
}
|
|
402
378
|
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
403
|
-
// Long-lived process: the access token may expire while it runs.
|
|
404
379
|
await (0, cliSession_1.ensureFreshToken)({ configPath: utils_1.CONFIG_PATH }).catch(() => undefined);
|
|
405
380
|
const config = (0, utils_1.readConfig)();
|
|
406
381
|
if (!config) {
|
|
@@ -517,10 +492,6 @@ async function handlePull(args, config) {
|
|
|
517
492
|
throw new Error("key required");
|
|
518
493
|
const res = await (0, shared_1.apiRequest)("GET", "/api/cli/pull", { config, query: { key, version } });
|
|
519
494
|
const a = res.artifact;
|
|
520
|
-
// Lead with the new-vocab kind. Legacy doc-shape (spec/decision/...) is
|
|
521
|
-
// surfaced as a tag list after, so callers still see it but it's no
|
|
522
|
-
// longer the primary label. Falls back to "doc" if the row pre-dates the
|
|
523
|
-
// kind field.
|
|
524
495
|
const kindLabel = a.kind ?? "doc";
|
|
525
496
|
const tagList = (a.tags ?? []).filter((t) => t).join(", ");
|
|
526
497
|
const tagSuffix = tagList ? ` · tags: ${tagList}` : "";
|
|
@@ -528,8 +499,6 @@ async function handlePull(args, config) {
|
|
|
528
499
|
`**${kindLabel}** · v${a.version ?? 1} · ${a.lifecycle ?? "draft"}${tagSuffix} · ` +
|
|
529
500
|
`updated ${(0, shared_1.timeAgo)(a.updatedAt ?? a.createdAt)}\n\n---\n\n`;
|
|
530
501
|
return {
|
|
531
|
-
// A skill's text carries its identity marker, so a copy the agent writes
|
|
532
|
-
// to disk still attributes its runs exactly (skillMarker.ts).
|
|
533
502
|
content: [{ type: "text", text: header + (a.kind === "skill" || (!a.kind && (0, skillMarker_1.looksLikeSkill)(a.markdown)) ? (0, skillMarker_1.stampSkillMarker)(a.markdown, a._id) : a.markdown) }],
|
|
534
503
|
};
|
|
535
504
|
}
|
|
@@ -606,9 +575,6 @@ async function handleInbox(args, config) {
|
|
|
606
575
|
config,
|
|
607
576
|
query: { unreadOnly: unreadOnly ? "1" : undefined, limit },
|
|
608
577
|
});
|
|
609
|
-
// Shared with `codiedev inbox` so this agent-facing path can never drift
|
|
610
|
-
// back to pings-only. CLAUDE.md routes "any messages?" here, so a
|
|
611
|
-
// mentions-blind version reproduces the bug for agents.
|
|
612
578
|
const text = (0, inboxFormat_1.formatInbox)({
|
|
613
579
|
pings: res.pings,
|
|
614
580
|
mentions: res.mentions,
|
|
@@ -660,8 +626,6 @@ async function handleShareWith(args, config) {
|
|
|
660
626
|
],
|
|
661
627
|
};
|
|
662
628
|
}
|
|
663
|
-
// noop / duplicate path — surface where the existing grant came from so
|
|
664
|
-
// the user knows whether to expect it next time.
|
|
665
629
|
const e = res.existing;
|
|
666
630
|
let why = "";
|
|
667
631
|
if (e) {
|
|
@@ -794,9 +758,6 @@ async function handleGetLibrary(args, config) {
|
|
|
794
758
|
const v = a.version ? ` v${a.version}` : "";
|
|
795
759
|
const life = a.lifecycle ? ` · ${a.lifecycle}` : "";
|
|
796
760
|
const when = a.updatedAt ? ` · ${(0, shared_1.timeAgo)(a.updatedAt)}` : "";
|
|
797
|
-
// Lead with the canonical kind (doc | skill). Tags carry the legacy
|
|
798
|
-
// doc-shape (spec/decision/...) plus any author-added labels — surface
|
|
799
|
-
// them after the kind so the row is self-describing.
|
|
800
761
|
const k = a.kind ?? (a.type === "note" ? "doc" : "doc");
|
|
801
762
|
const tagList = (a.tags ?? []).length > 0 ? ` [${a.tags.join(", ")}]` : "";
|
|
802
763
|
lines.push(`[${k}]${tagList} ${loc}${a.key ?? a.title}${v}${life}${when}`);
|
|
@@ -823,9 +784,6 @@ function formatAmbiguousRecipient(err, to) {
|
|
|
823
784
|
}
|
|
824
785
|
throw err;
|
|
825
786
|
}
|
|
826
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
827
|
-
// Helpers
|
|
828
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
829
787
|
function asString(v) {
|
|
830
788
|
return typeof v === "string" ? v : "";
|
|
831
789
|
}
|
|
@@ -843,20 +801,14 @@ function asStringArrayOrUndefined(v) {
|
|
|
843
801
|
return undefined;
|
|
844
802
|
return v.filter((x) => typeof x === "string");
|
|
845
803
|
}
|
|
846
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
847
|
-
// Main
|
|
848
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
849
804
|
async function main() {
|
|
850
805
|
const transport = new stdio_js_1.StdioServerTransport();
|
|
851
806
|
await server.connect(transport);
|
|
852
|
-
// stdio transport handles I/O until process exits.
|
|
853
|
-
// Log to stderr only — stdout is reserved for MCP protocol.
|
|
854
807
|
process.stderr.write(`[codiedev-mcp] ready (v${PKG_VERSION}, config ${(0, utils_1.readConfig)() ? "present" : "missing"})\n`);
|
|
855
808
|
}
|
|
856
809
|
main().catch((err) => {
|
|
857
810
|
process.stderr.write(`[codiedev-mcp] fatal: ${err.message}\n`);
|
|
858
811
|
process.exit(1);
|
|
859
812
|
});
|
|
860
|
-
// Avoid "Cannot find name 'path', 'fs'" since we imported them but may not use.
|
|
861
813
|
void path;
|
|
862
814
|
void fs;
|