codiedev 0.9.89 → 0.9.90

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/utils.d.ts CHANGED
@@ -111,6 +111,10 @@ export declare function openCodeInstalled(): boolean;
111
111
  * keeps `codiedev connect` as the only setup step even when Codie/OpenCode is
112
112
  * installed later. OpenCode loads this file from its documented plugin dir. */
113
113
  export declare function installOpenCodeCapturePlugin(): void;
114
+ /** Rewrite an OpenCode plugin installed by an older CLI: one that still wires
115
+ * the retired Agent Security tool hooks, or predates the prompt guard (it
116
+ * would let a stopped prompt through). Only touches an existing Codiedev plugin. */
117
+ export declare function ensureOpenCodePluginCurrent(): void;
114
118
  export declare function piInstalled(): boolean;
115
119
  /** Subcommands the pi extension calls, in the order inspectPiExtension checks. */
116
120
  export declare const PI_EXTENSION_SUBCOMMANDS: readonly ["session-start-pi", "backup-pi", "capture-pi-final", "discover-pi", "security-pre-pi", "security-post-pi", "security-failure-pi"];
package/dist/utils.js CHANGED
@@ -64,6 +64,7 @@ exports.cursorInstalled = cursorInstalled;
64
64
  exports.copilotInstalled = copilotInstalled;
65
65
  exports.openCodeInstalled = openCodeInstalled;
66
66
  exports.installOpenCodeCapturePlugin = installOpenCodeCapturePlugin;
67
+ exports.ensureOpenCodePluginCurrent = ensureOpenCodePluginCurrent;
67
68
  exports.piInstalled = piInstalled;
68
69
  exports.piExtensionSource = piExtensionSource;
69
70
  exports.installPiExtension = installPiExtension;
@@ -1165,6 +1166,22 @@ function installOpenCodeCapturePlugin() {
1165
1166
  ` const cwd = worktree || directory || process.cwd();\n` +
1166
1167
  ` const prompt = Array.isArray(output?.parts) ? output.parts.filter((part) => part?.type === "text").map((part) => part.text || "").join("\\n") : "";\n` +
1167
1168
  ` const decision = invokeSync(PROMPT, { session_id: id, cwd, prompt });\n` +
1169
+ ` if (decision?.decision === "block") {\n` +
1170
+ ` // A key in the prompt (Team Security setting): stop it before the model.\n` +
1171
+ ` const reason = String(decision.reason || "Codiedev stopped this prompt.");\n` +
1172
+ ` const toast = { title: "Prompt not sent", message: reason, variant: "error", duration: 12000 };\n` +
1173
+ ` // Older SDKs take { body }, newer ones the fields themselves. The TUI\n` +
1174
+ ` // follows a stopped prompt with its own generic \"Failed to send\n` +
1175
+ ` // prompt\" toast; show ours now and again just after, so ours stays up.\n` +
1176
+ ` const show = () => { try { Promise.resolve(client.tui.showToast({ body: toast, ...toast })).catch(() => {}); } catch {} };\n` +
1177
+ ` show();\n` +
1178
+ ` setTimeout(show, 600);\n` +
1179
+ ` if (process.env.CODIEDEV_PROMPT_BLOCK_OUTPUT === "marker") {\n` +
1180
+ ` process.stderr.write("__CODIEDEV_PROMPT_BLOCKED__" + JSON.stringify({ reason }) + "\\n");\n` +
1181
+ ` process.exit(3);\n` +
1182
+ ` }\n` +
1183
+ ` throw new Error(reason);\n` +
1184
+ ` }\n` +
1168
1185
  ` const context = decision?.hookSpecificOutput?.additionalContext;\n` +
1169
1186
  ` if (context && Array.isArray(output?.parts)) {\n` +
1170
1187
  ` // Preserve the native part IDs required by current engine schemas.\n` +
@@ -1215,6 +1232,20 @@ function installOpenCodeCapturePlugin() {
1215
1232
  fs.writeFileSync(OPENCODE_PLUGIN_PATH, source, { encoding: "utf8", mode: 0o600 });
1216
1233
  fs.chmodSync(OPENCODE_PLUGIN_PATH, 0o600);
1217
1234
  }
1235
+ /** Rewrite an OpenCode plugin installed by an older CLI: one that still wires
1236
+ * the retired Agent Security tool hooks, or predates the prompt guard (it
1237
+ * would let a stopped prompt through). Only touches an existing Codiedev plugin. */
1238
+ function ensureOpenCodePluginCurrent() {
1239
+ try {
1240
+ if (!fs.existsSync(OPENCODE_PLUGIN_PATH))
1241
+ return;
1242
+ const current = fs.readFileSync(OPENCODE_PLUGIN_PATH, "utf8");
1243
+ if (!current.includes("SECURITY_PRE") && current.includes("CODIEDEV_PROMPT_BLOCK_OUTPUT"))
1244
+ return;
1245
+ installOpenCodeCapturePlugin();
1246
+ }
1247
+ catch { /* best-effort */ }
1248
+ }
1218
1249
  function piInstalled() {
1219
1250
  if (fs.existsSync((0, harnessDirs_1.piAgentDir)()))
1220
1251
  return true;
@@ -1318,8 +1349,14 @@ function piExtensionSource(agentSecurityEnabled) {
1318
1349
  ` if (event?.source === "extension") return { action: "continue" };\n` +
1319
1350
  ` const s = current(ctx);\n` +
1320
1351
  ` const decision = invokeSync(PROMPT, { session_id: s.id, cwd: s.cwd, prompt: event?.text ?? "" });\n` +
1321
- ` const reason = blockReason(decision);\n` +
1322
- ` if (reason) { warn(ctx, reason); return { action: "handled" }; }\n` +
1352
+ ` if (decision?.decision === "block") {\n` +
1353
+ ` // A key in the prompt (Team Security setting): pi never sends it.\n` +
1354
+ ` const reason = String(decision.reason || "Codiedev stopped this prompt.");\n` +
1355
+ ` if (ctx?.hasUI) { try { ctx.ui.notify(reason, "error"); } catch { process.stderr.write("\\n" + reason + "\\n"); } }\n` +
1356
+ ` else process.stderr.write("\\n" + reason + "\\n");\n` +
1357
+ ` pendingContext = null;\n` +
1358
+ ` return { action: "handled" };\n` +
1359
+ ` }\n` +
1323
1360
  ` pendingContext = decision?.hookSpecificOutput?.additionalContext || null;\n` +
1324
1361
  ` return { action: "continue" };\n` +
1325
1362
  ` });\n\n` +
@@ -2259,10 +2296,10 @@ function installCursorHook() {
2259
2296
  replaceManaged("stop", ["backup-cursor"]);
2260
2297
  for (const event of ["postToolUse", "postToolUseFailure", "subagentStart", "subagentStop"])
2261
2298
  replaceManaged(event, ["observe-cursor"]);
2262
- // Cursor cannot inject dynamic context from beforeSubmitPrompt today.
2263
- // Remove older Codiedev discovery entries so prompts are not uploaded for
2264
- // a response the host will discard; preserve any third-party hooks.
2265
- replaceManaged("beforeSubmitPrompt", []);
2299
+ // Stops a prompt with a key in it when the company turned that on (a quick
2300
+ // local no-op otherwise). It also replaces older Codiedev discovery entries,
2301
+ // so prompts are not uploaded for a response the host will discard.
2302
+ replaceManaged("beforeSubmitPrompt", ["prompt-guard-cursor"]);
2266
2303
  fs.writeFileSync(CURSOR_HOOKS_PATH, JSON.stringify(hooksFile, null, 2), "utf8");
2267
2304
  }
2268
2305
  // GitHub Copilot reads every `$COPILOT_HOME/hooks/*.json`, so Codiedev owns
@@ -2358,6 +2395,7 @@ function ensureCursorCodiedevHooksInstalled() {
2358
2395
  ["postToolUseFailure", "observe-cursor"],
2359
2396
  ["subagentStart", "observe-cursor"],
2360
2397
  ["subagentStop", "observe-cursor"],
2398
+ ["beforeSubmitPrompt", "prompt-guard-cursor"],
2361
2399
  ];
2362
2400
  const has = (eventName, subcommand) => {
2363
2401
  const entries = hooks[eventName];
@@ -2369,7 +2407,8 @@ function ensureCursorCodiedevHooksInstalled() {
2369
2407
  });
2370
2408
  };
2371
2409
  const promptEntries = hooks.beforeSubmitPrompt;
2372
- const hasStalePromptHook = Array.isArray(promptEntries) && promptEntries.some((entry) => (0, detection_1.isCodiedevHookCommand)(entry.command));
2410
+ const hasStalePromptHook = Array.isArray(promptEntries) && promptEntries.some((entry) => (0, detection_1.isCodiedevHookCommand)(entry.command)
2411
+ && !String(entry.command ?? "").trim().endsWith("prompt-guard-cursor"));
2373
2412
  if (!required.every(([eventName, subcommand]) => has(eventName, subcommand)) ||
2374
2413
  hasStalePromptHook) {
2375
2414
  installCursorHook();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codiedev",
3
- "version": "0.9.89",
3
+ "version": "0.9.90",
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",