codiedev 0.10.0-beta.4 → 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 (146) hide show
  1. package/README.md +7 -1
  2. package/assets/tui-brand-plugin.tsx +14 -2
  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 +27 -40
  14. package/dist/codieBrandInstall.js +0 -18
  15. package/dist/codieLauncher.js +2 -70
  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 +38 -41
  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 +7 -6
  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/codieBrandInstall.d.ts +0 -11
  96. package/dist/codieLauncher.d.ts +0 -86
  97. package/dist/codieRuntime.d.ts +0 -29
  98. package/dist/codieRuntimeInstall.d.ts +0 -28
  99. package/dist/codieStartup.d.ts +0 -26
  100. package/dist/codieUsage.d.ts +0 -57
  101. package/dist/commands/ask.d.ts +0 -1
  102. package/dist/commands/capture.d.ts +0 -14
  103. package/dist/commands/createTicket.d.ts +0 -27
  104. package/dist/commands/delete.d.ts +0 -1
  105. package/dist/commands/doctor.d.ts +0 -1
  106. package/dist/commands/inbox.d.ts +0 -3
  107. package/dist/commands/library.d.ts +0 -2
  108. package/dist/commands/note.d.ts +0 -1
  109. package/dist/commands/ping.d.ts +0 -1
  110. package/dist/commands/promote.d.ts +0 -1
  111. package/dist/commands/pull.d.ts +0 -2
  112. package/dist/commands/push.d.ts +0 -33
  113. package/dist/commands/react.d.ts +0 -2
  114. package/dist/commands/reverseTicket.d.ts +0 -2
  115. package/dist/commands/search.d.ts +0 -2
  116. package/dist/commands/security.d.ts +0 -1
  117. package/dist/commands/send.d.ts +0 -2
  118. package/dist/commands/share.d.ts +0 -2
  119. package/dist/commands/shared.d.ts +0 -64
  120. package/dist/configDir.d.ts +0 -1
  121. package/dist/connect.d.ts +0 -1
  122. package/dist/connectFlow.d.ts +0 -13
  123. package/dist/cursorHooks.d.ts +0 -23
  124. package/dist/detection.d.ts +0 -30
  125. package/dist/hook.d.ts +0 -6
  126. package/dist/inboxFormat.d.ts +0 -38
  127. package/dist/limitEvent.d.ts +0 -16
  128. package/dist/limitEventReporter.d.ts +0 -21
  129. package/dist/mcp.d.ts +0 -12
  130. package/dist/prUrl.d.ts +0 -9
  131. package/dist/repoResolver.d.ts +0 -17
  132. package/dist/secret.d.ts +0 -1
  133. package/dist/security.d.ts +0 -102
  134. package/dist/securityDeepScan.d.ts +0 -41
  135. package/dist/securityDoctor.d.ts +0 -32
  136. package/dist/securityFeature.d.ts +0 -5
  137. package/dist/securityInstall.d.ts +0 -63
  138. package/dist/securityInventory.d.ts +0 -54
  139. package/dist/securityPilot.d.ts +0 -19
  140. package/dist/securityPolicy.d.ts +0 -33
  141. package/dist/securitySession.d.ts +0 -6
  142. package/dist/transcriptModels.d.ts +0 -18
  143. package/dist/upgradeNudge.d.ts +0 -25
  144. package/dist/utils.d.ts +0 -346
  145. package/dist/version.d.ts +0 -1
  146. package/dist/versionCheck.d.ts +0 -68
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);
@@ -45,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
45
35
  })();
46
36
  Object.defineProperty(exports, "__esModule", { value: true });
47
37
  const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
38
+ const skillMarker_1 = require("./skillMarker");
48
39
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
49
40
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
50
41
  const fs = __importStar(require("fs"));
@@ -53,8 +44,6 @@ const utils_1 = require("./utils");
53
44
  const shared_1 = require("./commands/shared");
54
45
  const inboxFormat_1 = require("./inboxFormat");
55
46
  const PKG_NAME = "codiedev";
56
- // Read version from the bundled package.json so the startup log + tool reports
57
- // always reflect the actually-installed version, rather than a stale constant.
58
47
  const PKG_VERSION = (() => {
59
48
  try {
60
49
  const pkgPath = path.resolve(__dirname, "..", "package.json");
@@ -64,10 +53,6 @@ const PKG_VERSION = (() => {
64
53
  return "unknown";
65
54
  }
66
55
  })();
67
- // ─────────────────────────────────────────────────────────────────────────────
68
- // Tool definitions — descriptions tuned so Claude/Codex resolve natural-language
69
- // requests into the right tool without manual steering.
70
- // ─────────────────────────────────────────────────────────────────────────────
71
56
  const TOOLS = [
72
57
  {
73
58
  name: "codiedev_push",
@@ -449,17 +434,10 @@ const TOOLS = [
449
434
  },
450
435
  },
451
436
  ];
452
- // ─────────────────────────────────────────────────────────────────────────────
453
- // Server
454
- // ─────────────────────────────────────────────────────────────────────────────
455
437
  const server = new index_js_1.Server({ name: PKG_NAME, version: PKG_VERSION }, { capabilities: { tools: {} } });
456
438
  server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
457
439
  tools: TOOLS,
458
440
  }));
459
- /**
460
- * Fire-and-forget telemetry — POST one event per tool invocation. Never blocks,
461
- * never throws into the user-facing path. Drop silently on any failure.
462
- */
463
441
  function emitTelemetry(config, event) {
464
442
  if (!config)
465
443
  return;
@@ -473,7 +451,6 @@ function emitTelemetry(config, event) {
473
451
  mcpVersion: PKG_VERSION,
474
452
  },
475
453
  }).catch(() => {
476
- // Swallow — telemetry should never affect the user's session.
477
454
  });
478
455
  }
479
456
  server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
@@ -577,7 +554,7 @@ async function handlePush(args, config) {
577
554
  }
578
555
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/push", {
579
556
  config,
580
- body: { filename, markdown, type, kind, tags, force },
557
+ body: { filename, markdown: (0, skillMarker_1.stripSkillMarker)(markdown), type, kind, tags, force },
581
558
  });
582
559
  const tagSummary = res.tags && res.tags.length > 0 ? `, tags=[${res.tags.join(", ")}]` : "";
583
560
  return {
@@ -598,10 +575,6 @@ async function handlePull(args, config) {
598
575
  throw new Error("key required");
599
576
  const res = await (0, shared_1.apiRequest)("GET", "/api/cli/pull", { config, query: { key, version } });
600
577
  const a = res.artifact;
601
- // Lead with the new-vocab kind. Legacy doc-shape (spec/decision/...) is
602
- // surfaced as a tag list after, so callers still see it but it's no
603
- // longer the primary label. Falls back to "doc" if the row pre-dates the
604
- // kind field.
605
578
  const kindLabel = a.kind ?? "doc";
606
579
  const tagList = (a.tags ?? []).filter((t) => t).join(", ");
607
580
  const tagSuffix = tagList ? ` · tags: ${tagList}` : "";
@@ -609,7 +582,7 @@ async function handlePull(args, config) {
609
582
  `**${kindLabel}** · v${a.version ?? 1} · ${a.lifecycle ?? "draft"}${tagSuffix} · ` +
610
583
  `updated ${(0, shared_1.timeAgo)(a.updatedAt ?? a.createdAt)}\n\n---\n\n`;
611
584
  return {
612
- content: [{ type: "text", text: header + a.markdown }],
585
+ 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) }],
613
586
  };
614
587
  }
615
588
  async function handleDelete(args, config) {
@@ -685,9 +658,6 @@ async function handleInbox(args, config) {
685
658
  config,
686
659
  query: { unreadOnly: unreadOnly ? "1" : undefined, limit },
687
660
  });
688
- // Shared with `codiedev inbox` so this agent-facing path can never drift
689
- // back to pings-only. CLAUDE.md routes "any messages?" here, so a
690
- // mentions-blind version reproduces the bug for agents.
691
661
  const text = (0, inboxFormat_1.formatInbox)({
692
662
  pings: res.pings,
693
663
  mentions: res.mentions,
@@ -754,8 +724,6 @@ async function handleShareWith(args, config) {
754
724
  ],
755
725
  };
756
726
  }
757
- // noop / duplicate path — surface where the existing grant came from so
758
- // the user knows whether to expect it next time.
759
727
  const e = res.existing;
760
728
  let why = "";
761
729
  if (e) {
@@ -908,9 +876,6 @@ async function handleGetLibrary(args, config) {
908
876
  const v = a.version ? ` v${a.version}` : "";
909
877
  const life = a.lifecycle ? ` · ${a.lifecycle}` : "";
910
878
  const when = a.updatedAt ? ` · ${(0, shared_1.timeAgo)(a.updatedAt)}` : "";
911
- // Lead with the canonical kind (doc | skill). Tags carry the legacy
912
- // doc-shape (spec/decision/...) plus any author-added labels — surface
913
- // them after the kind so the row is self-describing.
914
879
  const k = a.kind ?? (a.type === "note" ? "doc" : "doc");
915
880
  const tagList = (a.tags ?? []).length > 0 ? ` [${a.tags.join(", ")}]` : "";
916
881
  lines.push(`[${k}]${tagList} ${loc}${a.key ?? a.title}${v}${life}${when}`);
@@ -941,7 +906,6 @@ async function handleReverseTicket(args, config) {
941
906
  const explicitTitle = asStringOrUndefined(args.title);
942
907
  const explicitBase = asStringOrUndefined(args.base);
943
908
  const forcedKey = asStringOrUndefined(args.forcedArtifactKey);
944
- // Helper that runs git from cwd with a hard-fail on error.
945
909
  const { execSync } = await Promise.resolve().then(() => __importStar(require("child_process")));
946
910
  const git = (cmd) => {
947
911
  try {
@@ -956,14 +920,12 @@ async function handleReverseTicket(args, config) {
956
920
  throw new Error(`git ${cmd} failed: ${err.message}`);
957
921
  }
958
922
  };
959
- // Confirm we're in a git repo.
960
923
  try {
961
924
  git("rev-parse --is-inside-work-tree");
962
925
  }
963
926
  catch {
964
927
  throw new Error("Not inside a git repository. Run this from a checked-out repo.");
965
928
  }
966
- // Resolve base ref — explicit, then origin/main, then origin/master.
967
929
  const candidates = explicitBase
968
930
  ? [explicitBase]
969
931
  : ["origin/main", "origin/master"];
@@ -975,7 +937,6 @@ async function handleReverseTicket(args, config) {
975
937
  break;
976
938
  }
977
939
  catch {
978
- // try next
979
940
  }
980
941
  }
981
942
  if (!baseRef) {
@@ -988,10 +949,6 @@ async function handleReverseTicket(args, config) {
988
949
  }
989
950
  const baseSha = git(`merge-base HEAD ${baseRef}`);
990
951
  const headSha = git("rev-parse HEAD");
991
- // Filter generated/lockfile noise so the LLM's diff budget gets spent on
992
- // real source. The --stat block (collected separately below) still includes
993
- // every file untouched, so excluded files still appear in the ticket's
994
- // "Other files touched" section if relevant.
995
952
  const isNoise = (p) => /(^|\/)(node_modules|dist|build|\.next|\.turbo|coverage|out)\//.test(p) ||
996
953
  /(^|\/)package-lock\.json$/.test(p) ||
997
954
  /(^|\/)yarn\.lock$/.test(p) ||
@@ -1001,9 +958,6 @@ async function handleReverseTicket(args, config) {
1001
958
  /(^|\/)Gemfile\.lock$/.test(p) ||
1002
959
  /(^|\/)poetry\.lock$/.test(p) ||
1003
960
  /(^|\/)go\.sum$/.test(p);
1004
- // Helper: run a shell command tolerating non-zero exit codes (git diff
1005
- // --no-index exits 1 when files differ, which is the normal case).
1006
- // Reuses the execSync already imported above for the git() helper.
1007
961
  const shellTolerant = (cmd) => {
1008
962
  try {
1009
963
  return execSync(`${cmd} || true`, {
@@ -1018,12 +972,6 @@ async function handleReverseTicket(args, config) {
1018
972
  }
1019
973
  };
1020
974
  const shQuote = (s) => `'${s.replace(/'/g, "'\\''")}'`;
1021
- // Capture all work the developer has done relative to the base ref:
1022
- // - committed changes between base and HEAD
1023
- // - uncommitted modifications to tracked files
1024
- // - new untracked files (path listed + content via synthetic diff)
1025
- // Matches the user's intent ("ticket my current changes") rather than the
1026
- // narrower "only what's been committed" interpretation.
1027
975
  const trackedRaw = git(`diff --name-only ${baseSha}`);
1028
976
  const trackedFiles = trackedRaw ? trackedRaw.split("\n").filter(Boolean) : [];
1029
977
  const untrackedRaw = safeGit(() => git("ls-files --others --exclude-standard"));
@@ -1034,9 +982,6 @@ async function handleReverseTicket(args, config) {
1034
982
  if (filesChanged.length === 0) {
1035
983
  throw new Error(`No changes detected between ${baseRef} and your working tree on ${branch}.`);
1036
984
  }
1037
- // --stat block: compact ground truth for "every file touched". Tracked
1038
- // changes from `git diff --stat baseSha`; untracked files appended as
1039
- // synthesized stat rows so the LLM sees them with line counts.
1040
985
  let stat = "";
1041
986
  try {
1042
987
  const trackedStat = git(`diff --stat=200 ${baseSha}`);
@@ -1051,10 +996,7 @@ async function handleReverseTicket(args, config) {
1051
996
  .slice(0, 8_000);
1052
997
  }
1053
998
  catch {
1054
- // Best effort.
1055
999
  }
1056
- // Diff body: 40k cap, noise-filtered. Tracked changes via `git diff baseSha`,
1057
- // plus synthetic add-only diffs for untracked files via `git diff --no-index`.
1058
1000
  let diff = "";
1059
1001
  try {
1060
1002
  const sourceTracked = trackedFiles.filter((f) => !isNoise(f));
@@ -1069,9 +1011,7 @@ async function handleReverseTicket(args, config) {
1069
1011
  .slice(0, 40_000);
1070
1012
  }
1071
1013
  catch {
1072
- // Best effort.
1073
1014
  }
1074
- // Repo name from origin remote.
1075
1015
  let repo;
1076
1016
  try {
1077
1017
  const remoteUrl = git("config --get remote.origin.url");
@@ -1087,7 +1027,6 @@ async function handleReverseTicket(args, config) {
1087
1027
  const title = explicitTitle ?? safeGit(() => git("log -1 --format=%s")) ?? `WIP: ${branch}`;
1088
1028
  const author = safeGit(() => git("config --get user.name"));
1089
1029
  const authorEmail = safeGit(() => git("config --get user.email"));
1090
- // Post to backend.
1091
1030
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/reverseTicketFromBranch", {
1092
1031
  config,
1093
1032
  body: {
@@ -1120,9 +1059,6 @@ async function handleReverseTicket(args, config) {
1120
1059
  ],
1121
1060
  };
1122
1061
  }
1123
- // Always return an absolute URL so MCP clients (Copilot Chat, Claude Code,
1124
- // etc.) can render the link correctly without guessing a host. Default to
1125
- // codiedev.com; allow override via CODIEDEV_PORTAL_URL for self-hosted.
1126
1062
  const portalHost = (process.env.CODIEDEV_PORTAL_URL || "https://codiedev.com").replace(/\/$/, "");
1127
1063
  const portalLink = res.portalUrl.startsWith("http")
1128
1064
  ? res.portalUrl
@@ -1145,7 +1081,6 @@ async function handleReverseTicket(args, config) {
1145
1081
  ],
1146
1082
  };
1147
1083
  }
1148
- // Run a git invocation; return undefined instead of throwing.
1149
1084
  function safeGit(fn) {
1150
1085
  try {
1151
1086
  return fn();
@@ -1154,9 +1089,6 @@ function safeGit(fn) {
1154
1089
  return undefined;
1155
1090
  }
1156
1091
  }
1157
- // ─────────────────────────────────────────────────────────────────────────────
1158
- // Helpers
1159
- // ─────────────────────────────────────────────────────────────────────────────
1160
1092
  function asString(v) {
1161
1093
  return typeof v === "string" ? v : "";
1162
1094
  }
@@ -1174,20 +1106,14 @@ function asStringArrayOrUndefined(v) {
1174
1106
  return undefined;
1175
1107
  return v.filter((x) => typeof x === "string");
1176
1108
  }
1177
- // ─────────────────────────────────────────────────────────────────────────────
1178
- // Main
1179
- // ─────────────────────────────────────────────────────────────────────────────
1180
1109
  async function main() {
1181
1110
  const transport = new stdio_js_1.StdioServerTransport();
1182
1111
  await server.connect(transport);
1183
- // stdio transport handles I/O until process exits.
1184
- // Log to stderr only — stdout is reserved for MCP protocol.
1185
1112
  process.stderr.write(`[codiedev-mcp] ready (v${PKG_VERSION}, config ${(0, utils_1.readConfig)() ? "present" : "missing"})\n`);
1186
1113
  }
1187
1114
  main().catch((err) => {
1188
1115
  process.stderr.write(`[codiedev-mcp] fatal: ${err.message}\n`);
1189
1116
  process.exit(1);
1190
1117
  });
1191
- // Avoid "Cannot find name 'path', 'fs'" since we imported them but may not use.
1192
1118
  void path;
1193
1119
  void fs;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseNativeSteering = parseNativeSteering;
4
+ function parseNativeSteering(content) {
5
+ const interrupts = new Set();
6
+ const abortedTurns = new Set();
7
+ const rejections = new Set();
8
+ for (const [index, line] of content.split("\n").entries()) {
9
+ try {
10
+ const event = JSON.parse(line);
11
+ const id = String(event.id ?? event.uuid ?? event.toolCallId ?? index);
12
+ if (event.type === "agent.interruption")
13
+ interrupts.add(id);
14
+ if (event.type === "turn_ended" && event.status === "aborted")
15
+ abortedTurns.add(id);
16
+ if (event.type === "agent.rejection")
17
+ rejections.add(id);
18
+ if (event.type === "tool_result" && event.error?.code === "user_denied")
19
+ rejections.add(id);
20
+ }
21
+ catch { }
22
+ }
23
+ return { interrupts: Math.max(interrupts.size, abortedTurns.size), rejections: rejections.size };
24
+ }
@@ -0,0 +1,182 @@
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.levelToModel = levelToModel;
37
+ exports.mapAgentModel = mapAgentModel;
38
+ exports.codiePackConfig = codiePackConfig;
39
+ exports.mergeCodiePackConfig = mergeCodiePackConfig;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const url_1 = require("url");
43
+ const manifest_1 = require("./manifest");
44
+ const paths_1 = require("./paths");
45
+ const shim_1 = require("./shim");
46
+ const store_1 = require("./store");
47
+ const LEVEL_LABEL = { opus: "Strongest", sonnet: "Balanced", haiku: "Fastest" };
48
+ function newestFirst(a, b) {
49
+ return b.id.localeCompare(a.id, undefined, { numeric: true });
50
+ }
51
+ function levelToModel(level, catalog) {
52
+ const key = level.toLowerCase();
53
+ const tierNames = {
54
+ opus: ["strongest", "opus", "high", "max"],
55
+ sonnet: ["balanced", "sonnet", "medium", "default"],
56
+ haiku: ["fastest", "haiku", "low", "fast"],
57
+ };
58
+ const tiered = catalog.filter((m) => [m.tier, m.level].some((t) => typeof t === "string" && tierNames[key].includes(t.toLowerCase())));
59
+ if (tiered.length)
60
+ return { model: [...tiered].sort(newestFirst)[0].id, how: "tier" };
61
+ const family = catalog.filter((m) => new RegExp(`(^|[^a-z])${key}([^a-z]|$)`, "i").test(m.id));
62
+ if (family.length)
63
+ return { model: [...family].sort(newestFirst)[0].id, how: "family" };
64
+ const priced = catalog
65
+ .filter((m) => m.cost && Number.isFinite(m.cost.input) && Number.isFinite(m.cost.output))
66
+ .sort((a, b) => a.cost.input + a.cost.output - (b.cost.input + b.cost.output) || a.id.localeCompare(b.id));
67
+ if (priced.length) {
68
+ const index = key === "haiku" ? 0 : key === "opus" ? priced.length - 1 : Math.floor((priced.length - 1) / 2);
69
+ return { model: priced[index].id, how: "price" };
70
+ }
71
+ return { how: "none" };
72
+ }
73
+ function mapAgentModel(value, approved, catalog) {
74
+ const model = (value ?? "").trim();
75
+ if (!model || model === "inherit")
76
+ return {};
77
+ const key = model.toLowerCase();
78
+ if (LEVEL_LABEL[key]) {
79
+ const usable = (catalog ?? []).filter((m) => !approved || approved.has(m.id.replace(/^codiedev\//, "")));
80
+ const picked = levelToModel(key, usable);
81
+ if (!picked.model) {
82
+ return { note: `level ${LEVEL_LABEL[key]} (${model}): no matching approved model, using the governed default` };
83
+ }
84
+ return { model: picked.model, note: `level ${LEVEL_LABEL[key]} (${model}) → ${picked.model} (by ${picked.how})` };
85
+ }
86
+ if (!model.includes("/"))
87
+ return { note: `unknown level "${model}", using the governed default` };
88
+ if (approved) {
89
+ const bare = model.replace(/^codiedev\//, "");
90
+ if (!approved.has(bare))
91
+ return { note: `dropped model "${model}" (not approved for this Codiedev account)` };
92
+ }
93
+ return { model };
94
+ }
95
+ function codiePackConfig(root, options = {}) {
96
+ const registry = (0, store_1.readRegistry)(root);
97
+ const result = { skillPaths: [], agents: {}, plugins: [], notes: [] };
98
+ for (const [slug, entry] of Object.entries(registry.packs).sort(([a], [b]) => a.localeCompare(b))) {
99
+ if (!(0, manifest_1.isSafeSegment)(slug) || !Array.isArray(entry.harnesses) || !entry.harnesses.includes("codie"))
100
+ continue;
101
+ const dir = typeof entry.dir === "string" ? entry.dir : "";
102
+ if (!dir || !fs.existsSync(dir))
103
+ continue;
104
+ try {
105
+ const hooks = JSON.parse(fs.readFileSync(path.join(dir, "hooks", "hooks.json"), "utf8"))?.hooks;
106
+ const skipped = (0, shim_1.unsupportedShimEvents)([{ slug, root: dir, hooks: hooks ?? {} }]).get(slug);
107
+ if (skipped?.length)
108
+ result.notes.push(`pack ${slug}: hooks Codie can't run were skipped: ${skipped.join(", ")}`);
109
+ }
110
+ catch {
111
+ }
112
+ const skills = path.join(dir, "skills");
113
+ if (fs.existsSync(skills))
114
+ result.skillPaths.push(skills);
115
+ const agentsDir = path.join(dir, "agents");
116
+ let agentFiles = [];
117
+ try {
118
+ agentFiles = fs.readdirSync(agentsDir).filter((f) => f.endsWith(".md")).sort();
119
+ }
120
+ catch {
121
+ agentFiles = [];
122
+ }
123
+ for (const file of agentFiles) {
124
+ const fallbackName = file.slice(0, -3);
125
+ let content;
126
+ try {
127
+ content = fs.readFileSync(path.join(agentsDir, file), "utf8");
128
+ }
129
+ catch {
130
+ continue;
131
+ }
132
+ const { data, body } = (0, manifest_1.parseFrontmatter)(content);
133
+ const name = (0, manifest_1.isSafeSegment)(data.name) ? data.name : fallbackName;
134
+ if (result.agents[name]) {
135
+ result.notes.push(`agent "${name}" from pack ${slug} skipped (already defined by another pack)`);
136
+ continue;
137
+ }
138
+ const mapped = mapAgentModel(data.model, options.approvedModels, options.catalog);
139
+ if (mapped.note)
140
+ result.notes.push(`agent "${name}" (${slug}): ${mapped.note}`);
141
+ result.agents[name] = {
142
+ description: data.description || `${name} (from starter pack ${slug})`,
143
+ prompt: body.trim(),
144
+ mode: "subagent",
145
+ ...(mapped.model ? { model: mapped.model } : {}),
146
+ };
147
+ }
148
+ }
149
+ const shim = (0, paths_1.shimPath)(root);
150
+ const anyCodie = Object.values(registry.packs).some((e) => Array.isArray(e.harnesses) && e.harnesses.includes("codie"));
151
+ if (anyCodie && fs.existsSync(shim))
152
+ result.plugins.push((0, url_1.pathToFileURL)(shim).href);
153
+ return result;
154
+ }
155
+ function mergeCodiePackConfig(existing, packs) {
156
+ const next = { ...existing };
157
+ if (packs.skillPaths.length) {
158
+ const current = existing.skills;
159
+ const base = Array.isArray(current)
160
+ ? { paths: current.filter((p) => typeof p === "string") }
161
+ : current && typeof current === "object"
162
+ ? { ...current }
163
+ : {};
164
+ const paths = Array.isArray(base.paths) ? [...base.paths] : [];
165
+ for (const p of packs.skillPaths)
166
+ if (!paths.includes(p))
167
+ paths.push(p);
168
+ next.skills = { ...base, paths };
169
+ }
170
+ if (Object.keys(packs.agents).length) {
171
+ const current = existing.agent && typeof existing.agent === "object" ? existing.agent : {};
172
+ next.agent = { ...packs.agents, ...current };
173
+ }
174
+ if (packs.plugins.length) {
175
+ const current = Array.isArray(existing.plugin) ? [...existing.plugin] : [];
176
+ for (const p of packs.plugins)
177
+ if (!current.includes(p))
178
+ current.push(p);
179
+ next.plugin = current;
180
+ }
181
+ return next;
182
+ }