codiedev 0.10.0-beta.3 → 0.10.0-beta.5

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.
Files changed (144) hide show
  1. package/README.md +7 -1
  2. package/assets/tui-brand-plugin.tsx +73 -0
  3. package/dist/backup/cache.js +1 -5
  4. package/dist/backup/match.js +0 -6
  5. package/dist/backup/run.js +3 -35
  6. package/dist/captureExclusions.js +0 -12
  7. package/dist/captureLog.js +0 -28
  8. package/dist/captureReadiness.js +0 -58
  9. package/dist/captureSignals.js +66 -3
  10. package/dist/cli.js +41 -18
  11. package/dist/codexHookTrust.js +61 -5
  12. package/dist/codexLimitScan.js +2 -109
  13. package/dist/codie.js +41 -56
  14. package/dist/codieBrandInstall.js +80 -0
  15. package/dist/codieLauncher.js +59 -59
  16. package/dist/codieRuntime.js +19 -23
  17. package/dist/codieRuntimeInstall.js +108 -23
  18. package/dist/codieStartup.js +0 -3
  19. package/dist/codieUsage.js +181 -0
  20. package/dist/commands/ask.js +0 -3
  21. package/dist/commands/capture.js +0 -2
  22. package/dist/commands/createTicket.js +0 -10
  23. package/dist/commands/doctor.js +41 -82
  24. package/dist/commands/inbox.js +0 -2
  25. package/dist/commands/library.js +0 -3
  26. package/dist/commands/pack.js +573 -0
  27. package/dist/commands/ping.js +0 -2
  28. package/dist/commands/pull.js +6 -10
  29. package/dist/commands/push.js +2 -12
  30. package/dist/commands/react.js +0 -2
  31. package/dist/commands/reverseTicket.js +0 -33
  32. package/dist/commands/search.js +0 -4
  33. package/dist/commands/send.js +0 -5
  34. package/dist/commands/share.js +0 -4
  35. package/dist/commands/shared.js +0 -35
  36. package/dist/commands/traces.js +280 -0
  37. package/dist/configDir.js +0 -10
  38. package/dist/connect.js +21 -77
  39. package/dist/connectFlow.js +0 -9
  40. package/dist/copilotHooks.js +395 -0
  41. package/dist/copilotInstallation.js +64 -0
  42. package/dist/cursorHooks.js +40 -17
  43. package/dist/cursorLifecycle.js +109 -0
  44. package/dist/detection.js +0 -30
  45. package/dist/harnessDirs.js +73 -0
  46. package/dist/hook.js +193 -316
  47. package/dist/inboxFormat.js +0 -24
  48. package/dist/launchContext.js +150 -0
  49. package/dist/launcher.js +140 -0
  50. package/dist/limitEvent.js +41 -35
  51. package/dist/limitEventReporter.js +1 -1
  52. package/dist/mcp.js +3 -77
  53. package/dist/nativeSteering.js +24 -0
  54. package/dist/packs/codie.js +182 -0
  55. package/dist/packs/harnesses.js +374 -0
  56. package/dist/packs/hookGate.js +256 -0
  57. package/dist/packs/install.js +285 -0
  58. package/dist/packs/manifest.js +126 -0
  59. package/dist/packs/paths.js +81 -0
  60. package/dist/packs/shim.js +214 -0
  61. package/dist/packs/store.js +155 -0
  62. package/dist/packs/sync.js +170 -0
  63. package/dist/prUrl.js +0 -5
  64. package/dist/repoResolver.js +0 -19
  65. package/dist/secret.js +0 -3
  66. package/dist/security.js +0 -20
  67. package/dist/securityDeepScan.js +1 -14
  68. package/dist/securityDoctor.js +0 -2
  69. package/dist/securityFeature.js +0 -1
  70. package/dist/securityInstall.js +6 -13
  71. package/dist/securityInventory.js +23 -13
  72. package/dist/securityPilot.js +0 -2
  73. package/dist/securityPolicy.js +0 -7
  74. package/dist/selfUpdate.js +331 -0
  75. package/dist/skillMarker.js +23 -0
  76. package/dist/subagents.js +135 -0
  77. package/dist/teamSkillContext.js +10 -0
  78. package/dist/transcriptModels.js +6 -8
  79. package/dist/upgradeNudge.js +0 -30
  80. package/dist/utils.js +286 -733
  81. package/dist/version.js +0 -10
  82. package/dist/versionCheck.js +0 -33
  83. package/package.json +8 -7
  84. package/dist/backup/cache.d.ts +0 -14
  85. package/dist/backup/match.d.ts +0 -2
  86. package/dist/backup/run.d.ts +0 -25
  87. package/dist/captureExclusions.d.ts +0 -30
  88. package/dist/captureLog.d.ts +0 -20
  89. package/dist/captureReadiness.d.ts +0 -65
  90. package/dist/captureSignals.d.ts +0 -19
  91. package/dist/cli.d.ts +0 -16
  92. package/dist/codexHookTrust.d.ts +0 -34
  93. package/dist/codexLimitScan.d.ts +0 -64
  94. package/dist/codie.d.ts +0 -2
  95. package/dist/codieLauncher.d.ts +0 -53
  96. package/dist/codieRuntime.d.ts +0 -29
  97. package/dist/codieRuntimeInstall.d.ts +0 -28
  98. package/dist/codieStartup.d.ts +0 -26
  99. package/dist/commands/ask.d.ts +0 -1
  100. package/dist/commands/capture.d.ts +0 -14
  101. package/dist/commands/createTicket.d.ts +0 -27
  102. package/dist/commands/delete.d.ts +0 -1
  103. package/dist/commands/doctor.d.ts +0 -1
  104. package/dist/commands/inbox.d.ts +0 -3
  105. package/dist/commands/library.d.ts +0 -2
  106. package/dist/commands/note.d.ts +0 -1
  107. package/dist/commands/ping.d.ts +0 -1
  108. package/dist/commands/promote.d.ts +0 -1
  109. package/dist/commands/pull.d.ts +0 -2
  110. package/dist/commands/push.d.ts +0 -33
  111. package/dist/commands/react.d.ts +0 -2
  112. package/dist/commands/reverseTicket.d.ts +0 -2
  113. package/dist/commands/search.d.ts +0 -2
  114. package/dist/commands/security.d.ts +0 -1
  115. package/dist/commands/send.d.ts +0 -2
  116. package/dist/commands/share.d.ts +0 -2
  117. package/dist/commands/shared.d.ts +0 -64
  118. package/dist/configDir.d.ts +0 -1
  119. package/dist/connect.d.ts +0 -1
  120. package/dist/connectFlow.d.ts +0 -13
  121. package/dist/cursorHooks.d.ts +0 -23
  122. package/dist/detection.d.ts +0 -30
  123. package/dist/hook.d.ts +0 -6
  124. package/dist/inboxFormat.d.ts +0 -38
  125. package/dist/limitEvent.d.ts +0 -16
  126. package/dist/limitEventReporter.d.ts +0 -21
  127. package/dist/mcp.d.ts +0 -12
  128. package/dist/prUrl.d.ts +0 -9
  129. package/dist/repoResolver.d.ts +0 -17
  130. package/dist/secret.d.ts +0 -1
  131. package/dist/security.d.ts +0 -102
  132. package/dist/securityDeepScan.d.ts +0 -41
  133. package/dist/securityDoctor.d.ts +0 -32
  134. package/dist/securityFeature.d.ts +0 -5
  135. package/dist/securityInstall.d.ts +0 -63
  136. package/dist/securityInventory.d.ts +0 -54
  137. package/dist/securityPilot.d.ts +0 -19
  138. package/dist/securityPolicy.d.ts +0 -33
  139. package/dist/securitySession.d.ts +0 -6
  140. package/dist/transcriptModels.d.ts +0 -18
  141. package/dist/upgradeNudge.d.ts +0 -25
  142. package/dist/utils.d.ts +0 -346
  143. package/dist/version.d.ts +0 -1
  144. package/dist/versionCheck.d.ts +0 -68
@@ -39,9 +39,6 @@ const child_process_1 = require("child_process");
39
39
  const fs = __importStar(require("fs"));
40
40
  const os = __importStar(require("os"));
41
41
  const path = __importStar(require("path"));
42
- /** Adds component-addressable OSS scanner findings to the uploadable inventory.
43
- * Workspace-level findings (for example OSV dependency results) stay in the
44
- * deep-scan report because they do not identify one agent component. */
45
42
  function mergeDeepScanFindings(report, deep) {
46
43
  const byComponent = new Map();
47
44
  for (const finding of deep.findings) {
@@ -102,8 +99,6 @@ function collectFindingObjects(value, scanner, componentKey) {
102
99
  return;
103
100
  const row = child;
104
101
  const ruleId = row.rule_id ?? row.ruleId ?? row.id ?? row.code;
105
- // Do not import scanner messages/descriptions: several engines include the
106
- // matched source snippet there. Titles and rule names are bounded metadata.
107
102
  const title = row.title ?? row.rule_name ?? row.ruleName ?? row.name ??
108
103
  (ruleId !== undefined ? `Scanner finding ${String(ruleId)}` : undefined);
109
104
  const severityValue = row.severity ?? row.level ?? row.risk;
@@ -145,7 +140,7 @@ function runJsonScanner(args) {
145
140
  try {
146
141
  parsed = JSON.parse(stdout.slice(start, end + 1));
147
142
  }
148
- catch { /* handled below */ }
143
+ catch { }
149
144
  }
150
145
  }
151
146
  }
@@ -171,11 +166,6 @@ function pathsFor(report, kind, homeDir, workspace) {
171
166
  .map((component) => ({ component, filePath: actualPath(component.source, homeDir, workspace) }))
172
167
  .filter((item) => Boolean(item.filePath && fs.existsSync(item.filePath)));
173
168
  }
174
- /**
175
- * Runs optional open-source scanners. No scanner is downloaded implicitly.
176
- * MCP server connection is a separate opt-in because scanning a live stdio
177
- * server starts third-party code; the normal deep scan remains static.
178
- */
179
169
  function runDeepSecurityScan(report, options = {}) {
180
170
  const homeDir = path.resolve(options.homeDir ?? os.homedir());
181
171
  const workspace = path.resolve(options.workspace ?? process.cwd());
@@ -184,9 +174,6 @@ function runDeepSecurityScan(report, options = {}) {
184
174
  const runs = [];
185
175
  const skillPaths = pathsFor(report, "skill", homeDir, workspace);
186
176
  for (const { component, filePath } of skillPaths) {
187
- // Cisco's scanner is preferred when present; ATR is the lightweight
188
- // fallback. The current ATR CLI does not expose its internal detection
189
- // lanes, so only high/critical findings are imported for review.
190
177
  const cisco = runJsonScanner({
191
178
  scanner: "cisco-skill-scanner", command: "skill-scanner",
192
179
  commandArgs: ["scan", filePath, "--format", "json"], componentKey: component.componentKey,
@@ -5,7 +5,6 @@ exports.securityDoctorChecks = securityDoctorChecks;
5
5
  const securityInstall_1 = require("./securityInstall");
6
6
  const securityPilot_1 = require("./securityPilot");
7
7
  const securityPolicy_1 = require("./securityPolicy");
8
- /** One security-health model shared by `doctor` and its legacy alias. */
9
8
  function collectSecurityDoctorReport(companyId) {
10
9
  const manifest = (0, securityInstall_1.readSecurityInstallManifest)();
11
10
  const integrity = (0, securityInstall_1.verifySecurityInstallManifest)(manifest);
@@ -27,7 +26,6 @@ function collectSecurityDoctorReport(companyId) {
27
26
  policySelfTest: { ok: pilot.ok, cases: pilot.cases.length },
28
27
  };
29
28
  }
30
- /** Convert security health into the same compact rows used by core doctor. */
31
29
  function securityDoctorChecks(report) {
32
30
  const checks = [
33
31
  {
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isAgentSecurityEnabled = isAgentSecurityEnabled;
4
- /** Security is opt-in per company. Missing/stale entitlement data is dormant. */
5
4
  function isAgentSecurityEnabled(config) {
6
5
  return config?.agentSecurityEnabled === true;
7
6
  }
@@ -47,6 +47,8 @@ const configDir_1 = require("./configDir");
47
47
  const detection_1 = require("./detection");
48
48
  const codexHookTrust_1 = require("./codexHookTrust");
49
49
  const version_1 = require("./version");
50
+ const copilotInstallation_1 = require("./copilotInstallation");
51
+ const harnessDirs_1 = require("./harnessDirs");
50
52
  const MANIFEST_FILE = "security-install.json";
51
53
  function sha256File(filePath) {
52
54
  return crypto.createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
@@ -55,11 +57,6 @@ function safeSnapshotName(index, filePath) {
55
57
  const digest = crypto.createHash("sha256").update(filePath).digest("hex").slice(0, 12);
56
58
  return `${String(index + 1).padStart(2, "0")}-${digest}-${path.basename(filePath)}`;
57
59
  }
58
- /**
59
- * Capture the exact pre-update hook configuration. This function never removes
60
- * or restores anything; it creates the evidence needed for an explicit,
61
- * administrator-approved rollback later.
62
- */
63
60
  function createSecurityInstallSnapshot(configPaths, stateDir = (0, configDir_1.codiedevStateDir)(), now = Date.now) {
64
61
  const timestamp = now();
65
62
  const id = `${timestamp}-${process.pid}`;
@@ -124,11 +121,6 @@ function verifySecurityInstallManifest(manifest) {
124
121
  detail: `v${manifest.cliVersion}; rollback snapshot ${manifest.rollbackSnapshotId} available`,
125
122
  };
126
123
  }
127
- /**
128
- * Restore only files recorded in the selected install manifest. The snapshot
129
- * location is validated before any write and each replacement is atomic, so a
130
- * partial copy cannot leave a hook configuration truncated.
131
- */
132
124
  function restoreSecurityInstallSnapshot(manifest) {
133
125
  if (!manifest)
134
126
  throw new Error("security install manifest is missing");
@@ -215,14 +207,15 @@ function inspectJsonSurface(surface, filePath, codexConfigPath) {
215
207
  }
216
208
  function inspectSecurityInstallation(paths = {}) {
217
209
  const home = os.homedir();
218
- const claude = paths.claudeSettingsPath ?? path.join(home, ".claude", "settings.json");
219
- const codex = paths.codexHooksPath ?? path.join(home, ".codex", "hooks.json");
210
+ const claude = paths.claudeSettingsPath ?? path.join((0, harnessDirs_1.claudeConfigDir)(), "settings.json");
211
+ const codex = paths.codexHooksPath ?? path.join((0, harnessDirs_1.codexHome)(), "hooks.json");
220
212
  const cursor = paths.cursorHooksPath ?? path.join(home, ".cursor", "hooks.json");
221
- const codie = paths.codiePluginPath ?? path.join(home, ".config", "opencode", "plugins", "codiedev.js");
213
+ const codie = paths.codiePluginPath ?? path.join((0, harnessDirs_1.openCodeConfigDir)(), "plugins", "codiedev.js");
222
214
  const results = [
223
215
  inspectJsonSurface("claude-code", claude),
224
216
  inspectJsonSurface("codex", codex, paths.codexConfigPath),
225
217
  inspectJsonSurface("cursor", cursor),
218
+ { surface: "copilot", ...(0, copilotInstallation_1.inspectCopilotHooks)(paths.copilotHooksPath, true) },
226
219
  ];
227
220
  if (!fs.existsSync(codie)) {
228
221
  results.push({ surface: "codie-harness", status: "not-installed", detail: `${codie} not found` });
@@ -43,6 +43,8 @@ const fs = __importStar(require("fs"));
43
43
  const http = __importStar(require("http"));
44
44
  const https = __importStar(require("https"));
45
45
  const os = __importStar(require("os"));
46
+ const copilotHooks_1 = require("./copilotHooks");
47
+ const harnessDirs_1 = require("./harnessDirs");
46
48
  const path = __importStar(require("path"));
47
49
  const child_process_1 = require("child_process");
48
50
  const configDir_1 = require("./configDir");
@@ -89,8 +91,6 @@ function displayPath(filePath, homeDir, workspace) {
89
91
  if (resolved.startsWith(`${resolvedHome}${path.sep}`)) {
90
92
  return `~/${path.relative(resolvedHome, resolved)}`;
91
93
  }
92
- // Never upload arbitrary absolute paths. The basename plus a short digest is
93
- // enough to distinguish two external locations without exposing usernames.
94
94
  return `[external:${hash(resolved).slice(0, 10)}]/${path.basename(resolved)}`;
95
95
  }
96
96
  function fileScope(filePath, workspace) {
@@ -197,8 +197,6 @@ function jsoncToJson(text) {
197
197
  }
198
198
  output += char;
199
199
  }
200
- // JSONC permits trailing commas. Comments are already gone, so remove a
201
- // comma only when the next non-whitespace token closes an array or object.
202
200
  let withoutTrailingCommas = "";
203
201
  inString = false;
204
202
  escaped = false;
@@ -441,44 +439,56 @@ function securityInventoryDue(stateDir = (0, configDir_1.codiedevStateDir)(), ma
441
439
  }
442
440
  function buildSecurityInventory(options = {}) {
443
441
  const homeDir = path.resolve(options.homeDir ?? os.homedir());
442
+ const copilotDir = options.homeDir ? path.join(homeDir, ".copilot") : (0, copilotHooks_1.copilotHome)();
443
+ const claudeDir = options.homeDir ? path.join(homeDir, ".claude") : (0, harnessDirs_1.claudeConfigDir)();
444
+ const claudeJson = options.homeDir ? path.join(homeDir, ".claude.json") : (0, harnessDirs_1.claudeUserConfigPath)();
445
+ const codexDir = options.homeDir ? path.join(homeDir, ".codex") : (0, harnessDirs_1.codexHome)();
446
+ const openCodeDir = options.homeDir ? path.join(homeDir, ".config", "opencode") : (0, harnessDirs_1.openCodeConfigDir)();
444
447
  const workspace = path.resolve(options.workspace ?? process.cwd());
445
448
  const stateDir = options.stateDir ?? (0, configDir_1.codiedevStateDir)();
446
449
  const components = [];
447
450
  const jsonConfigs = [
448
- path.join(homeDir, ".claude.json"), path.join(homeDir, ".claude", "settings.json"),
449
- path.join(homeDir, ".claude", "settings.local.json"),
450
- path.join(homeDir, ".cursor", "mcp.json"), path.join(homeDir, ".config", "opencode", "opencode.json"),
451
- path.join(homeDir, ".config", "opencode", "opencode.jsonc"),
451
+ claudeJson, path.join(claudeDir, "settings.json"),
452
+ path.join(claudeDir, "settings.local.json"),
453
+ path.join(homeDir, ".cursor", "mcp.json"), path.join(openCodeDir, "opencode.json"),
454
+ path.join(openCodeDir, "opencode.jsonc"),
452
455
  path.join(homeDir, ".config", "Code", "User", "mcp.json"),
453
456
  path.join(homeDir, ".config", "Cursor", "User", "mcp.json"),
454
- path.join(homeDir, ".codex", "hooks.json"),
457
+ path.join(codexDir, "hooks.json"),
458
+ path.join(homeDir, ".cursor", "hooks.json"),
459
+ ...walkFiles(path.join(copilotDir, "hooks"), (_file, name) => name.endsWith(".json"), 1),
455
460
  path.join(homeDir, "Library", "Application Support", "Code", "User", "mcp.json"),
456
461
  path.join(homeDir, "Library", "Application Support", "Cursor", "User", "mcp.json"),
457
462
  path.join(homeDir, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
458
463
  path.join(workspace, ".mcp.json"), path.join(workspace, ".cursor", "mcp.json"),
459
464
  path.join(workspace, ".vscode", "mcp.json"),
460
465
  path.join(workspace, ".codex", "hooks.json"),
466
+ path.join(workspace, ".cursor", "hooks.json"),
467
+ ...walkFiles(path.join(workspace, ".github", "hooks"), (_file, name) => name.endsWith(".json"), 1),
461
468
  path.join(workspace, ".claude", "settings.json"), path.join(workspace, ".claude", "settings.local.json"),
462
469
  path.join(workspace, "opencode.json"), path.join(workspace, "opencode.jsonc"),
463
470
  ];
464
471
  for (const filePath of jsonConfigs)
465
472
  collectJsonConfig(filePath, homeDir, workspace, components);
466
- for (const filePath of [path.join(homeDir, ".codex", "config.toml"), path.join(workspace, ".codex", "config.toml")]) {
473
+ for (const filePath of [path.join(codexDir, "config.toml"), path.join(workspace, ".codex", "config.toml")]) {
467
474
  collectCodexToml(filePath, homeDir, workspace, components);
468
475
  }
469
476
  collectSkills([
470
- path.join(homeDir, ".claude", "skills"), path.join(homeDir, ".codex", "skills"),
477
+ path.join(claudeDir, "skills"), path.join(codexDir, "skills"),
471
478
  path.join(homeDir, ".agents", "skills"), path.join(homeDir, ".cursor", "skills"),
479
+ path.join(copilotDir, "skills"), path.join(workspace, ".github", "skills"),
472
480
  path.join(workspace, ".claude", "skills"), path.join(workspace, ".codex", "skills"),
473
481
  path.join(workspace, ".agents", "skills"), path.join(workspace, ".cursor", "skills"),
474
482
  ], homeDir, workspace, components);
475
483
  collectExtensions([
476
484
  path.join(homeDir, ".vscode", "extensions"), path.join(homeDir, ".cursor", "extensions"),
477
485
  ], homeDir, workspace, components);
478
- const pluginDirs = [path.join(homeDir, ".config", "opencode", "plugins"), path.join(workspace, ".opencode", "plugins")];
486
+ const pluginDirs = [path.join(openCodeDir, "plugins"), path.join(workspace, ".opencode", "plugins")];
479
487
  collectLooseFiles(pluginDirs.flatMap((dir) => walkFiles(dir, (_file, name) => /\.(?:js|mjs|cjs|ts)$/.test(name), 2)), "plugin", homeDir, workspace, components);
480
488
  collectLooseFiles([
481
- path.join(homeDir, ".claude", "CLAUDE.md"), path.join(homeDir, ".codex", "AGENTS.md"),
489
+ path.join(claudeDir, "CLAUDE.md"), path.join(codexDir, "AGENTS.md"),
490
+ path.join(copilotDir, "copilot-instructions.md"), path.join(workspace, ".github", "copilot-instructions.md"),
491
+ ...walkFiles(path.join(homeDir, ".cursor", "rules"), (_file, name) => /\.(?:md|mdc)$/.test(name), 3),
482
492
  path.join(workspace, "CLAUDE.md"), path.join(workspace, "AGENTS.md"),
483
493
  ...walkFiles(path.join(workspace, ".cursor", "rules"), (_file, name) => /\.(?:md|mdc)$/.test(name), 3),
484
494
  ], "instruction", homeDir, workspace, components);
@@ -26,8 +26,6 @@ function constrainedPolicy(now) {
26
26
  fetchedAt: now,
27
27
  };
28
28
  }
29
- /** Safe, side-effect-free policy validation. No command is executed and none
30
- * of the synthetic values are real credentials. */
31
29
  function runSyntheticSecurityPilot(cwd = process.cwd(), now = Date.now) {
32
30
  const cases = [];
33
31
  const policy = constrainedPolicy(now());
@@ -55,13 +55,6 @@ function policyFile(companyId) {
55
55
  const scope = companyId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128);
56
56
  return `security-policy.${scope}.json`;
57
57
  }
58
- /**
59
- * Vendor policy roots are compiled into the endpoint binary. This prevents a
60
- * compromised control-plane response from introducing the key that verifies
61
- * that same response. Additional customer-managed roots may still be supplied
62
- * through CODIEDEV_SECURITY_POLICY_PUBLIC_KEYS, but they cannot replace the
63
- * Codiedev production root with the same key id.
64
- */
65
58
  exports.BUILT_IN_POLICY_KEYS = {
66
59
  "codiedev-prod-2026-01": "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEA0H+UISjTn4zhd6Pk9YmrMBqnJEJmv9fXoavXorlV2cU=\n-----END PUBLIC KEY-----\n",
67
60
  };
@@ -0,0 +1,331 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.planSelfUpdate = planSelfUpdate;
37
+ exports.isSelfUpdateDue = isSelfUpdateDue;
38
+ exports.readSelfUpdateState = readSelfUpdateState;
39
+ exports.maybeSpawnSelfUpdate = maybeSpawnSelfUpdate;
40
+ exports.findInstalledHookScript = findInstalledHookScript;
41
+ exports.runSelfUpdate = runSelfUpdate;
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ const child_process_1 = require("child_process");
45
+ const version_1 = require("./version");
46
+ const versionCheck_1 = require("./versionCheck");
47
+ const configDir_1 = require("./configDir");
48
+ const captureLog_1 = require("./captureLog");
49
+ const launcher_1 = require("./launcher");
50
+ const PKG = "codiedev";
51
+ const DAY_MS = 24 * 60 * 60 * 1000;
52
+ const LOCK_STALE_MS = 10 * 60 * 1000;
53
+ const INSTALL_TIMEOUT_MS = 5 * 60 * 1000;
54
+ const FETCH_TIMEOUT_MS = 5_000;
55
+ function planSelfUpdate(deps) {
56
+ const { env } = deps;
57
+ if (env.CODIEDEV_NO_UPDATE_CHECK || env.CODIEDEV_NO_AUTO_UPDATE) {
58
+ return { kind: "skip", reason: "disabled" };
59
+ }
60
+ if (env.CI || env.CONTINUOUS_INTEGRATION || env.GITHUB_ACTIONS || env.BUILD_NUMBER) {
61
+ return { kind: "skip", reason: "ci" };
62
+ }
63
+ if (deps.isContainer)
64
+ return { kind: "skip", reason: "container" };
65
+ const p = deps.hookScriptReal.replace(/\\/g, "/");
66
+ if (/\/(?:_npx|\.npm\/_npx)\//.test(p))
67
+ return { kind: "skip", reason: "npx" };
68
+ const pkgDir = path.dirname(path.dirname(deps.hookScriptReal));
69
+ if (!deps.isWritable(pkgDir))
70
+ return { kind: "skip", reason: "readonly" };
71
+ if (/\/\.pnpm\/|\/pnpm\/global\/|\/global\/v\d+\/[^/]+\/node_modules\/codiedev\/|\/store\/v\d+\/links\//.test(p)) {
72
+ return deps.viaLauncher ? { kind: "pnpm" } : { kind: "skip", reason: "pnpm-direct" };
73
+ }
74
+ if (/\/install\/global\/node_modules\/codiedev\/dist\/hook\.js$/.test(p))
75
+ return { kind: "bun" };
76
+ const unix = p.match(/^(.*)\/lib\/node_modules\/codiedev\/dist\/hook\.js$/);
77
+ if (unix && deps.platform !== "win32")
78
+ return { kind: "npm", prefix: unix[1] };
79
+ const win = p.match(/^(.*)\/node_modules\/codiedev\/dist\/hook\.js$/);
80
+ if (win && deps.platform === "win32")
81
+ return { kind: "npm", prefix: win[1] };
82
+ return { kind: "skip", reason: "unmanaged" };
83
+ }
84
+ function isSelfUpdateDue(state, nowMs) {
85
+ return !state || nowMs - state.lastAttemptAt > DAY_MS;
86
+ }
87
+ function statePath() {
88
+ return path.join((0, configDir_1.codiedevStateDir)(), ".self-update.json");
89
+ }
90
+ function lockPath() {
91
+ return path.join((0, configDir_1.codiedevStateDir)(), ".self-update.lock");
92
+ }
93
+ function readSelfUpdateState() {
94
+ try {
95
+ const parsed = JSON.parse(fs.readFileSync(statePath(), "utf8"));
96
+ return typeof parsed.lastAttemptAt === "number" ? parsed : null;
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
102
+ function writeState(state) {
103
+ try {
104
+ fs.mkdirSync((0, configDir_1.codiedevStateDir)(), { recursive: true });
105
+ fs.writeFileSync(statePath(), JSON.stringify(state), "utf8");
106
+ return true;
107
+ }
108
+ catch {
109
+ return false;
110
+ }
111
+ }
112
+ function maybeSpawnSelfUpdate(hookEntry) {
113
+ try {
114
+ if (!hookEntry || process.env.CODIEDEV_NO_AUTO_UPDATE || process.env.CODIEDEV_NO_UPDATE_CHECK)
115
+ return;
116
+ const now = Date.now();
117
+ if (!isSelfUpdateDue(readSelfUpdateState(), now))
118
+ return;
119
+ if (!writeState({ lastAttemptAt: now, lastResult: "spawned" }))
120
+ return;
121
+ const child = (0, child_process_1.spawn)(process.execPath, [hookEntry, "self-update"], {
122
+ detached: true,
123
+ stdio: "ignore",
124
+ windowsHide: true,
125
+ });
126
+ child.unref();
127
+ }
128
+ catch {
129
+ }
130
+ }
131
+ function acquireLock() {
132
+ const lock = lockPath();
133
+ try {
134
+ fs.mkdirSync(lock);
135
+ return true;
136
+ }
137
+ catch {
138
+ try {
139
+ if (Date.now() - fs.statSync(lock).mtimeMs > LOCK_STALE_MS) {
140
+ fs.rmSync(lock, { recursive: true, force: true });
141
+ fs.mkdirSync(lock);
142
+ return true;
143
+ }
144
+ }
145
+ catch {
146
+ }
147
+ return false;
148
+ }
149
+ }
150
+ function detectContainer(env) {
151
+ if (env.KUBERNETES_SERVICE_HOST)
152
+ return true;
153
+ if (fs.existsSync("/.dockerenv") || fs.existsSync("/run/.containerenv"))
154
+ return true;
155
+ try {
156
+ return /docker|containerd|kubepods|lxc/.test(fs.readFileSync("/proc/1/cgroup", "utf8"));
157
+ }
158
+ catch {
159
+ return false;
160
+ }
161
+ }
162
+ function registryBase(env) {
163
+ const configured = env.npm_config_registry || env.NPM_CONFIG_REGISTRY;
164
+ return (configured || "https://registry.npmjs.org").replace(/\/+$/, "");
165
+ }
166
+ async function fetchLatest(env) {
167
+ const controller = new AbortController();
168
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
169
+ try {
170
+ const res = await fetch(`${registryBase(env)}/${PKG}/latest`, {
171
+ headers: { Accept: "application/json" },
172
+ signal: controller.signal,
173
+ });
174
+ if (!res.ok)
175
+ return null;
176
+ const json = (await res.json());
177
+ return typeof json.version === "string" ? json.version : null;
178
+ }
179
+ catch {
180
+ return null;
181
+ }
182
+ finally {
183
+ clearTimeout(timer);
184
+ }
185
+ }
186
+ function installCommand(plan, version, env) {
187
+ const spec = `${PKG}@${version}`;
188
+ const configured = env.npm_config_registry || env.NPM_CONFIG_REGISTRY;
189
+ const registry = configured ? ["--registry", registryBase(env)] : [];
190
+ switch (plan.kind) {
191
+ case "npm": {
192
+ const args = ["i", "-g", "--prefix", plan.prefix, "--no-fund", "--no-audit", ...registry, spec];
193
+ const execDir = path.dirname(process.execPath);
194
+ const npmCli = [
195
+ path.join(execDir, "node_modules", "npm", "bin", "npm-cli.js"),
196
+ path.join(execDir, "..", "lib", "node_modules", "npm", "bin", "npm-cli.js"),
197
+ ].find((p) => fs.existsSync(p));
198
+ if (npmCli)
199
+ return { cmd: process.execPath, args: [npmCli, ...args] };
200
+ return { cmd: process.platform === "win32" ? "npm.cmd" : "npm", args, shell: process.platform === "win32" };
201
+ }
202
+ case "pnpm":
203
+ return { cmd: "pnpm", args: ["add", "-g", ...registry, spec], shell: process.platform === "win32" };
204
+ case "bun":
205
+ return { cmd: "bun", args: ["add", "-g", ...registry, spec] };
206
+ default:
207
+ return null;
208
+ }
209
+ }
210
+ function readVersionAt(hookScript) {
211
+ try {
212
+ const pkg = JSON.parse(fs.readFileSync(path.join(path.dirname(path.dirname(hookScript)), "package.json"), "utf8"));
213
+ return typeof pkg.version === "string" ? pkg.version : null;
214
+ }
215
+ catch {
216
+ return null;
217
+ }
218
+ }
219
+ function findInstalledHookScript(plan, hookEntry, version, pnpmRoot = pnpmGlobalRoot) {
220
+ if (plan.kind !== "pnpm")
221
+ return readVersionAt(hookEntry) === version ? hookEntry : null;
222
+ const root = pnpmRoot();
223
+ if (!root)
224
+ return null;
225
+ const candidates = [path.join(root, PKG, "dist", "hook.js")];
226
+ try {
227
+ for (const entry of fs.readdirSync(root)) {
228
+ candidates.push(path.join(root, entry, "node_modules", PKG, "dist", "hook.js"));
229
+ }
230
+ }
231
+ catch {
232
+ }
233
+ for (const candidate of candidates) {
234
+ if (readVersionAt(candidate) !== version)
235
+ continue;
236
+ try {
237
+ return fs.realpathSync(candidate);
238
+ }
239
+ catch {
240
+ }
241
+ }
242
+ return null;
243
+ }
244
+ function pnpmGlobalRoot() {
245
+ const root = (0, child_process_1.spawnSync)("pnpm", ["root", "-g"], {
246
+ encoding: "utf8",
247
+ timeout: 30_000,
248
+ shell: process.platform === "win32",
249
+ windowsHide: true,
250
+ });
251
+ const dir = root.status === 0 ? root.stdout.trim() : "";
252
+ return dir || null;
253
+ }
254
+ async function runSelfUpdate(hookEntry) {
255
+ const env = process.env;
256
+ const now = Date.now();
257
+ const finish = (lastResult, extra = {}) => {
258
+ const state = { lastAttemptAt: now, lastResult, fromVersion: version_1.CLI_VERSION, ...extra };
259
+ writeState(state);
260
+ (0, captureLog_1.appendCaptureLog)({
261
+ stage: "self-update",
262
+ sessionId: undefined,
263
+ outcome: lastResult.startsWith("error") ? "ERROR" : "ok",
264
+ detail: `result=${lastResult} from=${version_1.CLI_VERSION} to=${extra.toVersion ?? "-"} elapsedMs=${Date.now() - now}`,
265
+ });
266
+ return state;
267
+ };
268
+ let hookScriptReal;
269
+ try {
270
+ hookScriptReal = fs.realpathSync(hookEntry);
271
+ }
272
+ catch {
273
+ return finish("skip:unresolved");
274
+ }
275
+ const plan = planSelfUpdate({
276
+ hookScriptReal,
277
+ env,
278
+ platform: process.platform,
279
+ isContainer: detectContainer(env),
280
+ viaLauncher: Boolean(env.CODIEDEV_VIA_LAUNCHER),
281
+ isWritable: (dir) => {
282
+ try {
283
+ fs.accessSync(dir, fs.constants.W_OK);
284
+ return true;
285
+ }
286
+ catch {
287
+ return false;
288
+ }
289
+ },
290
+ });
291
+ if (plan.kind === "skip")
292
+ return finish(`skip:${plan.reason}`);
293
+ if (!acquireLock()) {
294
+ (0, captureLog_1.appendCaptureLog)({ stage: "self-update", sessionId: undefined, outcome: "ok", detail: "result=skip:locked" });
295
+ return { lastAttemptAt: now, lastResult: "skip:locked" };
296
+ }
297
+ try {
298
+ const latest = await fetchLatest(env);
299
+ if (!latest)
300
+ return finish("error:registry");
301
+ if ((0, versionCheck_1.compareSemver)(version_1.CLI_VERSION, latest) !== -1)
302
+ return finish("current", { toVersion: latest });
303
+ const install = installCommand(plan, latest, env);
304
+ if (!install)
305
+ return finish("skip:no-installer");
306
+ const result = (0, child_process_1.spawnSync)(install.cmd, install.args, {
307
+ stdio: "ignore",
308
+ timeout: INSTALL_TIMEOUT_MS,
309
+ env: { ...env, CODIEDEV_NO_AUTO_UPDATE: "1" },
310
+ shell: install.shell ?? false,
311
+ windowsHide: true,
312
+ });
313
+ if (result.error || result.status !== 0) {
314
+ return finish(`error:install-exit-${result.status ?? "spawn"}`, { toVersion: latest });
315
+ }
316
+ const installed = findInstalledHookScript(plan, hookScriptReal, latest);
317
+ if (!installed) {
318
+ return finish("error:not-found-after-install", { toVersion: latest });
319
+ }
320
+ if (!(0, launcher_1.recordCurrentInstall)(installed))
321
+ return finish("error:record", { toVersion: latest });
322
+ return finish("updated", { toVersion: latest });
323
+ }
324
+ finally {
325
+ try {
326
+ fs.rmSync(lockPath(), { recursive: true, force: true });
327
+ }
328
+ catch {
329
+ }
330
+ }
331
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.looksLikeSkill = looksLikeSkill;
4
+ exports.stripSkillMarker = stripSkillMarker;
5
+ exports.stampSkillMarker = stampSkillMarker;
6
+ const ID = /^[a-z0-9]{16,64}$/i;
7
+ const LINE = /^[ \t]*<!--\s*codiedev:artifact=[a-z0-9]+\s*-->[ \t]*(?:\r?\n|$)/gim;
8
+ function looksLikeSkill(markdown) {
9
+ const fm = markdown.match(/^?---\r?\n([\s\S]*?)\r?\n---/);
10
+ if (!fm)
11
+ return false;
12
+ return /^name\s*:/im.test(fm[1]) && /^description\s*:/im.test(fm[1]);
13
+ }
14
+ function stripSkillMarker(markdown) {
15
+ return markdown.replace(LINE, "");
16
+ }
17
+ function stampSkillMarker(markdown, artifactId) {
18
+ if (!artifactId || !ID.test(artifactId))
19
+ return markdown;
20
+ const body = stripSkillMarker(markdown);
21
+ const sep = body.endsWith("\n") ? "" : "\n";
22
+ return `${body}${sep}<!-- codiedev:artifact=${artifactId} -->\n`;
23
+ }