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.
Files changed (154) hide show
  1. package/README.md +12 -5
  2. package/dist/backup/cache.js +1 -5
  3. package/dist/backup/match.js +0 -6
  4. package/dist/backup/run.js +3 -35
  5. package/dist/captureExclusions.js +0 -12
  6. package/dist/captureLog.js +0 -28
  7. package/dist/captureReadiness.js +0 -58
  8. package/dist/captureSignals.js +0 -11
  9. package/dist/cli.js +11 -33
  10. package/dist/cliSession.js +3 -60
  11. package/dist/codexHookTrust.js +0 -28
  12. package/dist/codexLimitScan.js +0 -107
  13. package/dist/codie.js +64 -57
  14. package/dist/codieBrandInstall.js +0 -18
  15. package/dist/codieLauncher.js +1 -72
  16. package/dist/codieRuntime.js +27 -32
  17. package/dist/codieRuntimeInstall.js +11 -43
  18. package/dist/codieUsage.js +0 -49
  19. package/dist/commands/agentTemplates.generated.js +136 -0
  20. package/dist/commands/agents.js +1088 -0
  21. package/dist/commands/agentsSdk.generated.js +7 -0
  22. package/dist/commands/ask.js +0 -3
  23. package/dist/commands/capture.js +0 -2
  24. package/dist/commands/createTicket.js +0 -10
  25. package/dist/commands/doctor.js +2 -72
  26. package/dist/commands/evals.js +3 -9
  27. package/dist/commands/inbox.js +0 -2
  28. package/dist/commands/library.js +0 -3
  29. package/dist/commands/pack.js +0 -29
  30. package/dist/commands/ping.js +0 -2
  31. package/dist/commands/pull.js +0 -9
  32. package/dist/commands/push.js +0 -12
  33. package/dist/commands/search.js +0 -4
  34. package/dist/commands/send.js +0 -5
  35. package/dist/commands/share.js +0 -4
  36. package/dist/commands/shared.js +0 -35
  37. package/dist/commands/traces.js +0 -13
  38. package/dist/commands/tracesLabel.js +0 -8
  39. package/dist/configDir.js +1 -18
  40. package/dist/connect.js +3 -75
  41. package/dist/connectFlow.js +0 -15
  42. package/dist/copilotHooks.js +0 -67
  43. package/dist/copilotInstallation.js +0 -1
  44. package/dist/cursorHooks.js +1 -11
  45. package/dist/cursorLifecycle.js +1 -7
  46. package/dist/detection.js +0 -30
  47. package/dist/harnessDirs.js +0 -19
  48. package/dist/hook.js +43 -293
  49. package/dist/inboxFormat.js +0 -24
  50. package/dist/launchContext.js +0 -50
  51. package/dist/launcher.js +0 -33
  52. package/dist/limitEvent.js +2 -34
  53. package/dist/managedPi.js +2 -50
  54. package/dist/mcp.js +0 -48
  55. package/dist/nativeSteering.js +1 -4
  56. package/dist/packs/codie.js +0 -15
  57. package/dist/packs/harnesses.js +1 -38
  58. package/dist/packs/hookGate.js +0 -33
  59. package/dist/packs/install.js +0 -20
  60. package/dist/packs/manifest.js +1 -15
  61. package/dist/packs/paths.js +0 -8
  62. package/dist/packs/shim.js +0 -8
  63. package/dist/packs/store.js +0 -12
  64. package/dist/packs/sync.js +0 -20
  65. package/dist/piHooks.js +4 -45
  66. package/dist/piRuntime.js +0 -18
  67. package/dist/repoResolver.js +0 -19
  68. package/dist/secret.js +0 -3
  69. package/dist/selfUpdate.js +2 -77
  70. package/dist/skillMarker.js +0 -14
  71. package/dist/subagents.js +0 -18
  72. package/dist/teamSkillContext.js +0 -1
  73. package/dist/transcriptModels.js +0 -8
  74. package/dist/upgradeNudge.js +1 -30
  75. package/dist/utils.js +165 -768
  76. package/dist/version.js +0 -10
  77. package/dist/versionCheck.js +0 -33
  78. package/package.json +13 -8
  79. package/dist/backup/cache.d.ts +0 -14
  80. package/dist/backup/match.d.ts +0 -2
  81. package/dist/backup/run.d.ts +0 -25
  82. package/dist/captureExclusions.d.ts +0 -30
  83. package/dist/captureLog.d.ts +0 -20
  84. package/dist/captureReadiness.d.ts +0 -65
  85. package/dist/captureSignals.d.ts +0 -47
  86. package/dist/cli.d.ts +0 -15
  87. package/dist/cliSession.d.ts +0 -108
  88. package/dist/codexHookTrust.d.ts +0 -49
  89. package/dist/codexLimitScan.d.ts +0 -64
  90. package/dist/codie.d.ts +0 -2
  91. package/dist/codieBrandInstall.d.ts +0 -11
  92. package/dist/codieLauncher.d.ts +0 -87
  93. package/dist/codieRuntime.d.ts +0 -35
  94. package/dist/codieRuntimeInstall.d.ts +0 -56
  95. package/dist/codieUsage.d.ts +0 -64
  96. package/dist/commands/ask.d.ts +0 -1
  97. package/dist/commands/capture.d.ts +0 -14
  98. package/dist/commands/createTicket.d.ts +0 -27
  99. package/dist/commands/delete.d.ts +0 -1
  100. package/dist/commands/doctor.d.ts +0 -9
  101. package/dist/commands/evals.d.ts +0 -3
  102. package/dist/commands/inbox.d.ts +0 -3
  103. package/dist/commands/library.d.ts +0 -2
  104. package/dist/commands/note.d.ts +0 -1
  105. package/dist/commands/pack.d.ts +0 -54
  106. package/dist/commands/ping.d.ts +0 -1
  107. package/dist/commands/pull.d.ts +0 -2
  108. package/dist/commands/push.d.ts +0 -33
  109. package/dist/commands/search.d.ts +0 -2
  110. package/dist/commands/send.d.ts +0 -2
  111. package/dist/commands/share.d.ts +0 -2
  112. package/dist/commands/shared.d.ts +0 -64
  113. package/dist/commands/traces.d.ts +0 -72
  114. package/dist/commands/tracesLabel.d.ts +0 -24
  115. package/dist/configDir.d.ts +0 -10
  116. package/dist/connect.d.ts +0 -1
  117. package/dist/connectFlow.d.ts +0 -34
  118. package/dist/copilotHooks.d.ts +0 -85
  119. package/dist/copilotInstallation.d.ts +0 -10
  120. package/dist/cursorHooks.d.ts +0 -13
  121. package/dist/cursorLifecycle.d.ts +0 -2
  122. package/dist/detection.d.ts +0 -30
  123. package/dist/harnessDirs.d.ts +0 -15
  124. package/dist/hook.d.ts +0 -6
  125. package/dist/inboxFormat.d.ts +0 -38
  126. package/dist/launchContext.d.ts +0 -46
  127. package/dist/launcher.d.ts +0 -25
  128. package/dist/limitEvent.d.ts +0 -15
  129. package/dist/limitEventReporter.d.ts +0 -21
  130. package/dist/managedPi.d.ts +0 -48
  131. package/dist/mcp.d.ts +0 -12
  132. package/dist/nativeSteering.d.ts +0 -5
  133. package/dist/packs/codie.d.ts +0 -45
  134. package/dist/packs/harnesses.d.ts +0 -74
  135. package/dist/packs/hookGate.d.ts +0 -53
  136. package/dist/packs/install.d.ts +0 -46
  137. package/dist/packs/manifest.d.ts +0 -52
  138. package/dist/packs/paths.d.ts +0 -17
  139. package/dist/packs/shim.d.ts +0 -26
  140. package/dist/packs/store.d.ts +0 -42
  141. package/dist/packs/sync.d.ts +0 -40
  142. package/dist/piHooks.d.ts +0 -22
  143. package/dist/piRuntime.d.ts +0 -26
  144. package/dist/repoResolver.d.ts +0 -17
  145. package/dist/secret.d.ts +0 -1
  146. package/dist/selfUpdate.d.ts +0 -64
  147. package/dist/skillMarker.d.ts +0 -6
  148. package/dist/subagents.d.ts +0 -36
  149. package/dist/teamSkillContext.d.ts +0 -9
  150. package/dist/transcriptModels.d.ts +0 -20
  151. package/dist/upgradeNudge.d.ts +0 -24
  152. package/dist/utils.d.ts +0 -396
  153. package/dist/version.d.ts +0 -1
  154. package/dist/versionCheck.d.ts +0 -68
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.jsPackage = exports.jsTypes = exports.jsIndex = exports.python = void 0;
4
+ exports.python = "\"\"\"Codiedev agents SDK — the run primitive, from Python.\n\nInside a deployed agent (everything is already configured):\n\n import codiedev_agents as agents\n\n task = agents.input() # this run's input (JSON)\n llm = agents.openai() # OpenAI client on the Codiedev gateway, traced\n child = agents.run(\"summarize\", {\"text\": ...}) # start another agent as a child run\n agents.output({\"summary\": child[\"output\"]}) # this run's result\n agents.request() # webhook runs: method, headers, raw body\n agents.respond({\"text\": \"on it\"}) # what a webhook caller waiting (?wait=) gets back\n\n agents.state.get(\"cursor\") # per-agent storage that outlives runs\n agents.state.set(\"cursor\", 42)\n agents.step(\"fetch\", lambda: fetch()) # done once per run, even across retries\n agents.start(\"triage\", {...}, delay=3600) # start a run later (up to 7 days)\n agents.request_approval(\"Refund $120?\", context={...}) # a person decides; a run acts on it\n agents.attempt() # 1, or 2+ when this run is a retry\n\nOutside a run (a script, a notebook, another service), set CODIEDEV_TOKEN\n(your CLI token) and CODIEDEV_AGENTS_URL, then call agents.run() the same way.\nStandard library only, so it drops into any project.\n\"\"\"\n\nfrom __future__ import annotations\n\nimport json\nimport os\nimport time\nimport urllib.error\nimport urllib.parse\nimport urllib.request\nfrom typing import Any\n\n__all__ = [\n \"input\", \"output\", \"request\", \"respond\", \"run\", \"start\", \"get\", \"openai\", \"attempt\",\n \"state\", \"step\", \"request_approval\", \"get_approval\", \"AgentRunError\", \"StateConflict\",\n]\n\n_INPUT_PATH = os.environ.get(\"CODIEDEV_INPUT_PATH\", \"/agent/.codiedev/input.json\")\n_OUTPUT_PATH = os.environ.get(\"CODIEDEV_OUTPUT_PATH\", \"/agent/.codiedev/output.json\")\n_REQUEST_PATH = os.environ.get(\"CODIEDEV_REQUEST_PATH\", \"/agent/.codiedev/request.json\")\n_RESPONSE_PATH = os.environ.get(\"CODIEDEV_RESPONSE_PATH\", \"/agent/.codiedev/response.json\")\n# Set by `codiedev agents run --local`: state lives in this file instead of Codiedev.\n_STATE_PATH = os.environ.get(\"CODIEDEV_STATE_PATH\")\n_DONE = {\"succeeded\", \"failed\", \"cancelled\"}\n\n\nclass StateConflict(RuntimeError):\n \"\"\"state.set(..., if_version=n) found the key at another version.\"\"\"\n\n def __init__(self, key: str, version: int):\n super().__init__(f\"state {key!r} changed (now version {version})\")\n self.key = key\n self.version = version\n\n\nclass AgentRunError(RuntimeError):\n def __init__(self, run: dict):\n super().__init__(f\"{run.get('agent')} run {run.get('id')} {run.get('status')}: {run.get('error') or 'no error message'}\")\n self.run = run\n\n\ndef input(default: Any = None) -> Any: # noqa: A001 - mirrors output()\n \"\"\"This run's input, parsed from JSON (None when started without one).\"\"\"\n try:\n with open(_INPUT_PATH) as f:\n value = json.load(f)\n except FileNotFoundError:\n return default\n return default if value is None else value\n\n\ndef output(value: Any) -> None:\n \"\"\"Set this run's result. Must be JSON-serializable; the last call wins.\"\"\"\n os.makedirs(os.path.dirname(_OUTPUT_PATH), exist_ok=True)\n with open(_OUTPUT_PATH, \"w\") as f:\n json.dump(value, f)\n\n\ndef respond(body: Any = None, status: int = 200, headers: \"dict | None\" = None) -> None:\n \"\"\"What a webhook caller gets back when it waits for the run (?wait=N):\n a string is sent as text, anything else as JSON. Without respond(), a\n waiting caller gets the run's output.\"\"\"\n os.makedirs(os.path.dirname(_RESPONSE_PATH), exist_ok=True)\n with open(_RESPONSE_PATH, \"w\") as f:\n json.dump({\"status\": status, \"headers\": headers or {}, \"body\": body}, f)\n\n\ndef attempt() -> int:\n \"\"\"This run's attempt: 1, or 2+ when it's a retry of a failed attempt.\"\"\"\n return int(os.environ.get(\"CODIEDEV_ATTEMPT\", \"1\"))\n\n\ndef request() -> \"dict | None\":\n \"\"\"For a webhook run: {\"method\", \"query\", \"headers\", \"body\"} with the raw\n body, to verify the sender's signature. None for other runs.\"\"\"\n try:\n with open(_REQUEST_PATH) as f:\n return json.load(f)\n except FileNotFoundError:\n return None\n\n\ndef _base() -> str:\n url = os.environ.get(\"CODIEDEV_AGENTS_URL\", \"\").rstrip(\"/\")\n if not url:\n raise RuntimeError(\"Set CODIEDEV_AGENTS_URL (it's set for you inside a run)\")\n return url\n\n\ndef _token() -> str:\n # Inside a run: the run's token. A connected agent (running outside Codiedev): its own key.\n # Otherwise: your CLI token.\n key = os.environ.get(\"CODIEDEV_API_KEY\", \"\")\n token = os.environ.get(\"CODIEDEV_RUN_TOKEN\") or (key if key.startswith(\"cdvm_\") else None) or os.environ.get(\"CODIEDEV_TOKEN\")\n if not token:\n raise RuntimeError(\"Set CODIEDEV_API_KEY to your connected agent's key, or CODIEDEV_TOKEN to your CLI token (inside a run it's set for you)\")\n return token\n\n\ndef _request(method: str, path: str, body: dict | None = None, ok: tuple[int, ...] = ()) -> dict:\n req = urllib.request.Request(\n f\"{_base()}{path}\",\n method=method,\n data=json.dumps(body).encode() if body is not None else None,\n headers={\"Authorization\": f\"Bearer {_token()}\", \"Content-Type\": \"application/json\"},\n )\n try:\n with urllib.request.urlopen(req, timeout=30) as res:\n return json.loads(res.read() or b\"{}\")\n except urllib.error.HTTPError as err:\n detail = err.read().decode(errors=\"replace\")\n if err.code in ok:\n return {\"_status\": err.code, **json.loads(detail or \"{}\")}\n try:\n detail = json.loads(detail).get(\"error\", detail)\n except ValueError:\n pass\n raise RuntimeError(f\"Codiedev agents API {err.code}: {detail}\") from None\n\n\ndef start(\n agent: str,\n input: Any = None, # noqa: A002\n idempotency_key: str | None = None,\n delay: float | None = None,\n retries: int | None = None,\n) -> str:\n \"\"\"Start a run and return its id without waiting. With an idempotency key,\n a second start within a day returns the first run's id. delay (seconds,\n up to 7 days) starts it later; retries overrides the agent's retries.\"\"\"\n body: dict = {\"agent\": agent, \"input\": input}\n if idempotency_key:\n body[\"idempotencyKey\"] = idempotency_key\n if delay:\n body[\"delaySec\"] = int(delay)\n if retries is not None:\n body[\"retries\"] = retries\n return _request(\"POST\", \"/api/agents/v1/run\", body)[\"runId\"]\n\n\ndef get(run_id: str) -> dict:\n \"\"\"A run's status, input, output (parsed), error, log tail and children.\"\"\"\n run = _request(\"GET\", f\"/api/agents/v1/run?id={run_id}\")\n if isinstance(run.get(\"output\"), str):\n try:\n run[\"output\"] = json.loads(run[\"output\"])\n except ValueError:\n pass\n return run\n\n\ndef run(\n agent: str,\n input: Any = None, # noqa: A002\n timeout: float = 900,\n poll: float = 2.0,\n check: bool = True,\n idempotency_key: str | None = None,\n) -> dict:\n \"\"\"Run an agent and wait for it. Returns the run; its result is run[\"output\"].\n\n Inside a run this starts a child run, so the chain shows as one tree.\n Raises AgentRunError if it fails (pass check=False to get the run anyway).\n \"\"\"\n run_id = start(agent, input, idempotency_key)\n deadline = time.monotonic() + timeout\n while True:\n result = get(run_id)\n if result.get(\"status\") in _DONE:\n if check and result[\"status\"] != \"succeeded\":\n raise AgentRunError(result)\n return result\n if time.monotonic() > deadline:\n raise TimeoutError(f\"{agent} run {run_id} still {result.get('status')} after {timeout}s\")\n time.sleep(poll)\n\n\nclass _State:\n \"\"\"Per-agent key-value storage that outlives runs (values: any JSON, up\n to 64 KB; 1,000 keys). Every write bumps the key's version; pass\n if_version to write only if nobody else did since you read it.\"\"\"\n\n def get(self, key: str, default: Any = None) -> Any:\n value, _ = self.get_versioned(key)\n return default if value is None else value\n\n def get_versioned(self, key: str) -> \"tuple[Any, int]\":\n \"\"\"(value, version); (None, 0) when the key isn't set.\"\"\"\n if _STATE_PATH:\n row = _local_state().get(key)\n return (row[\"value\"], row[\"version\"]) if row else (None, 0)\n res = _request(\"GET\", f\"/api/agents/v1/state?{urllib.parse.urlencode({'key': key, 'agent': _agent()})}\", ok=(404,))\n if res.get(\"_status\") == 404:\n return None, 0\n return json.loads(res[\"value\"]), int(res[\"version\"])\n\n def set(self, key: str, value: Any, if_version: \"int | None\" = None, ttl: \"float | None\" = None) -> int:\n \"\"\"Store value; returns the new version. Raises StateConflict when\n if_version is given and the key is at another version (0 = unset).\"\"\"\n return self._write(key, value, if_version, ttl)\n\n def delete(self, key: str, if_version: \"int | None\" = None) -> None:\n self._write(key, None, if_version, None)\n\n def list(self, prefix: str = \"\", values: bool = False) -> \"list[dict]\": # noqa: A003\n \"\"\"Keys (and with values=True, values) starting with prefix.\"\"\"\n if _STATE_PATH:\n rows = sorted((k, r) for k, r in _local_state().items() if k.startswith(prefix))\n return [{\"key\": k, \"version\": r[\"version\"], **({\"value\": r[\"value\"]} if values else {})} for k, r in rows]\n keys: list = []\n after = None\n while True:\n params = {\"prefix\": prefix, \"values\": \"1\" if values else \"0\", \"limit\": 200, \"agent\": _agent()}\n if after:\n params[\"after\"] = after\n page = _request(\"GET\", f\"/api/agents/v1/state?{urllib.parse.urlencode(params)}\")\n for row in page[\"keys\"]:\n if \"value\" in row:\n row[\"value\"] = json.loads(row[\"value\"])\n keys.extend(page[\"keys\"])\n after = page.get(\"next\")\n if not after:\n return keys\n\n def update(self, key: str, fn, default: Any = None, retries: int = 10) -> Any:\n \"\"\"Read-modify-write that's safe with runs in parallel: fn(old) -> new,\n retried if another run wrote first. Returns the new value.\"\"\"\n for _ in range(retries):\n value, version = self.get_versioned(key)\n new = fn(default if value is None else value)\n try:\n self.set(key, new, if_version=version)\n return new\n except StateConflict:\n time.sleep(0.05)\n raise StateConflict(key, -1)\n\n def _write(self, key: str, value: Any, if_version: \"int | None\", ttl: \"float | None\") -> int:\n if _STATE_PATH:\n data = _local_state()\n current = data.get(key, {}).get(\"version\", 0)\n if if_version is not None and if_version != current:\n raise StateConflict(key, current)\n if value is None:\n data.pop(key, None)\n else:\n data[key] = {\"value\": value, \"version\": current + 1}\n with open(_STATE_PATH, \"w\") as f:\n json.dump(data, f, indent=2)\n return 0 if value is None else current + 1\n body: dict = {\"key\": key, \"value\": value, \"agent\": _agent()}\n if if_version is not None:\n body[\"ifVersion\"] = if_version\n if ttl:\n body[\"ttlSec\"] = int(ttl)\n res = _request(\"POST\", \"/api/agents/v1/state\", body, ok=(409,))\n if res.get(\"_status\") == 409:\n raise StateConflict(key, int(res.get(\"version\", 0)))\n return int(res.get(\"version\", 0))\n\n\ndef _agent() -> str:\n # Inside a run the run token picks the agent; a CLI token needs it named.\n return os.environ.get(\"CODIEDEV_AGENT\", \"\")\n\n\ndef _local_state() -> dict:\n try:\n with open(_STATE_PATH or \"\") as f:\n return json.load(f)\n except (FileNotFoundError, ValueError):\n return {}\n\n\nstate = _State()\n\n\ndef step(name: str, fn, ttl: float = 7 * 86400) -> Any:\n \"\"\"Run fn() once for this run and remember its (JSON) result: if the run\n is retried after a failure, finished steps return their saved result\n instead of running again. Use it around side effects (posting a reply,\n charging a card) so a retry doesn't repeat them.\"\"\"\n key = f\"step/{os.environ.get('CODIEDEV_RUN_ID', 'local')}/{name}\"\n value, version = state.get_versioned(key)\n if version:\n return value[\"result\"]\n result = fn()\n state.set(key, {\"result\": result}, ttl=ttl)\n return result\n\n\n_SELF = object()\n\n\ndef request_approval(\n title: str,\n details: Any = None,\n options: \"list[str] | None\" = None,\n approvers: \"list[str] | None\" = None,\n teams: \"list[str] | None\" = None,\n fields: \"list[dict] | None\" = None,\n then: Any = _SELF,\n context: Any = None,\n expires_in: \"float | None\" = None,\n) -> dict:\n \"\"\"Ask a person to decide. It shows in Codiedev (Agents → Approvals) and\n at the returned [\"url\"], which you can post anywhere (Slack, email).\n\n When it's decided, a run of `then` (this agent by default; None for no\n run) starts with input {\"approval\": {\"decision\", \"comment\", \"decidedBy\",\n ...}, \"context\": context}. If nobody decides within expires_in seconds\n (default 7 days), it starts with decision \"expired\". Usually the run\n ends after asking, so nothing runs (or costs) while it waits.\n options default to [\"approve\", \"reject\"]; approvers (emails) and teams\n (team names, e.g. [\"Finance\"]) limit who can decide (admins always can).\n Apps your company connects (Agents → Approvals → Apps) are told about it\n by webhook and can decide on a person's behalf.\n\n fields asks the person to fill something in as they decide, e.g.\n [{\"name\": \"rating\", \"type\": \"rating\"}, {\"name\": \"why\", \"type\": \"textarea\"}]\n (types: text, textarea, number, rating, select, multiselect, boolean;\n required, label, help, options, min, max, default). What they entered\n arrives as input[\"approval\"][\"values\"]. With fields and no options, the\n only choice is \"submit\".\"\"\"\n body: dict = {\"title\": title, \"details\": details, \"options\": options, \"approvers\": approvers, \"teams\": teams, \"fields\": fields, \"context\": context}\n if then is not _SELF:\n body[\"onDecision\"] = then\n if expires_in:\n body[\"expiresSec\"] = int(expires_in)\n if os.environ.get(\"CODIEDEV_LOCAL\") == \"1\":\n print(f\"[local] approval requested: {title} ({', '.join(options or (['submit'] if fields else ['approve', 'reject']))}); not sent on a local run\", flush=True)\n return {\"id\": f\"local-{int(time.time())}\", \"status\": \"pending\", \"url\": None, \"title\": title}\n return _request(\"POST\", \"/api/agents/v1/approvals\", {k: v for k, v in body.items() if v is not None or k == \"onDecision\"})\n\n\ndef get_approval(approval_id: str) -> dict:\n \"\"\"An approval's status (\"pending\", \"decided\", \"expired\"), decision and comment.\"\"\"\n return _request(\"GET\", f\"/api/agents/v1/approvals?id={urllib.parse.quote(approval_id)}\")\n\n\ndef wait_for_approval(approval_id: str, timeout: float = 3600, poll: float = 15) -> dict:\n \"\"\"Wait until a person decides (or it expires), then return the approval. For agents that keep\n running while they wait, like a connected agent; a run inside Codiedev usually ends instead and\n is started again with the decision.\"\"\"\n deadline = time.time() + timeout\n while True:\n a = get_approval(approval_id)\n if a.get(\"status\") != \"pending\":\n return a\n if time.time() > deadline:\n raise TimeoutError(f\"approval {approval_id} still pending after {timeout}s\")\n time.sleep(poll)\n\n\ndef openai(**kwargs):\n \"\"\"An OpenAI client on the Codiedev gateway, with trace headers for this run.\"\"\"\n from openai import OpenAI\n\n headers = {\n \"X-Codiedev-Workload\": os.environ.get(\"CODIEDEV_AGENT\", \"local-agent\"),\n \"X-Codiedev-Run-Id\": os.environ.get(\"CODIEDEV_RUN_ID\", f\"local-{int(time.time())}\"),\n \"X-Codiedev-Environment\": \"production\" if os.environ.get(\"CODIEDEV_RUN_ID\") else \"development\",\n }\n headers.update(kwargs.pop(\"default_headers\", {}) or {})\n return OpenAI(\n base_url=os.environ.get(\"CODIEDEV_GATEWAY_URL\", \"https://gateway.codiedev.com/api/v1\"),\n api_key=os.environ.get(\"CODIEDEV_API_KEY\") or os.environ.get(\"CODIEDEV_TOKEN\"),\n default_headers=headers,\n **kwargs,\n )\n";
5
+ exports.jsIndex = "// Codiedev agents SDK for JavaScript and TypeScript, preinstalled in every\n// run. Same primitive as the Python SDK (codiedev_agents.py):\n//\n// import * as agents from \"codiedev-agents\";\n// const task = agents.input(); // this run's input (JSON)\n// const llm = await agents.openai(); // OpenAI client on the Codiedev gateway, traced\n// const child = await agents.run(\"summarize\", { text }); // another agent, as a child run\n// agents.output({ summary: child.output }); // this run's result\n// agents.respond({ text: \"on it\" }); // what a webhook caller waiting (?wait=) gets back\n// await agents.state.get(\"cursor\"); // per-agent storage that outlives runs\n// await agents.step(\"post\", () => post()); // done once per run, even across retries\n// await agents.start(\"triage\", input, { delaySec: 3600 }); // start a run later\n// await agents.requestApproval(\"Refund $120?\", { context }); // a person decides; a run acts on it\n//\n// Outside a run, set CODIEDEV_TOKEN and CODIEDEV_AGENTS_URL and call run() the same way.\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nconst INPUT_PATH = process.env.CODIEDEV_INPUT_PATH || \"/agent/.codiedev/input.json\";\nconst OUTPUT_PATH = process.env.CODIEDEV_OUTPUT_PATH || \"/agent/.codiedev/output.json\";\nconst REQUEST_PATH = process.env.CODIEDEV_REQUEST_PATH || \"/agent/.codiedev/request.json\";\nconst RESPONSE_PATH = process.env.CODIEDEV_RESPONSE_PATH || \"/agent/.codiedev/response.json\";\n// Set by `codiedev agents run --local`: state lives in this file instead of Codiedev.\nconst STATE_PATH = process.env.CODIEDEV_STATE_PATH;\n// Inside a run the run token picks the agent; a CLI token needs it named.\nconst AGENT = process.env.CODIEDEV_AGENT || \"\";\nconst DONE = new Set([\"succeeded\", \"failed\", \"cancelled\"]);\n\n/** state.set(..., { ifVersion }) found the key at another version. */\nexport class StateConflict extends Error {\n constructor(key, version) {\n super(`state ${JSON.stringify(key)} changed (now version ${version})`);\n this.key = key;\n this.version = version;\n }\n}\n\nexport class AgentRunError extends Error {\n constructor(run) {\n super(`${run.agent} run ${run.id} ${run.status}: ${run.error || \"no error message\"}`);\n this.run = run;\n }\n}\n\nfunction readJson(file) {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch (err) {\n if (err.code === \"ENOENT\") return null;\n throw err;\n }\n}\n\n/** This run's input, parsed from JSON (`fallback` when started without one). */\nexport function input(fallback = null) {\n const value = readJson(INPUT_PATH);\n return value ?? fallback;\n}\n\n/** Set this run's result. Must be JSON-serializable; the last call wins. */\nexport function output(value) {\n fs.mkdirSync(path.dirname(OUTPUT_PATH), { recursive: true });\n fs.writeFileSync(OUTPUT_PATH, JSON.stringify(value));\n}\n\n/** What a webhook caller gets back when it waits for the run (?wait=N): a\n * string is sent as text, anything else as JSON. Without it, a waiting\n * caller gets the run's output. */\nexport function respond(body = null, { status = 200, headers = {} } = {}) {\n fs.mkdirSync(path.dirname(RESPONSE_PATH), { recursive: true });\n fs.writeFileSync(RESPONSE_PATH, JSON.stringify({ status, headers, body }));\n}\n\n/** This run's attempt: 1, or 2+ when it's a retry of a failed attempt. */\nexport function attempt() {\n return Number(process.env.CODIEDEV_ATTEMPT || \"1\");\n}\n\n/** For a webhook run: { method, query, headers, body } with the raw body, to verify a signature. */\nexport function request() {\n return readJson(REQUEST_PATH);\n}\n\nfunction base() {\n const url = (process.env.CODIEDEV_AGENTS_URL || \"\").replace(/\\/$/, \"\");\n if (!url) throw new Error(\"Set CODIEDEV_AGENTS_URL (it's set for you inside a run)\");\n return url;\n}\n\nfunction token() {\n // Inside a run: the run's token. A connected agent (running outside Codiedev): its own key.\n // Otherwise: your CLI token.\n const key = process.env.CODIEDEV_API_KEY || \"\";\n const t = process.env.CODIEDEV_RUN_TOKEN || (key.startsWith(\"cdvm_\") ? key : \"\") || process.env.CODIEDEV_TOKEN;\n if (!t) throw new Error(\"Set CODIEDEV_API_KEY to your connected agent's key, or CODIEDEV_TOKEN to your CLI token (inside a run it's set for you)\");\n return t;\n}\n\nasync function call(method, route, body, ok = []) {\n const res = await fetch(`${base()}${route}`, {\n method,\n headers: { Authorization: `Bearer ${token()}`, \"Content-Type\": \"application/json\" },\n body: body === undefined ? undefined : JSON.stringify(body),\n });\n const text = await res.text();\n let data = {};\n try {\n data = text ? JSON.parse(text) : {};\n } catch {\n data = { error: text };\n }\n if (ok.includes(res.status)) return { _status: res.status, ...data };\n if (!res.ok) throw new Error(`Codiedev agents API ${res.status}: ${data.error || text}`);\n return data;\n}\n\n/** Start a run and return its id without waiting. delaySec (up to 7 days)\n * starts it later; retries overrides the agent's retries. */\nexport async function start(agent, input = null, { idempotencyKey, delaySec, retries } = {}) {\n return (await call(\"POST\", \"/api/agents/v1/run\", {\n agent,\n input,\n ...(idempotencyKey ? { idempotencyKey } : {}),\n ...(delaySec ? { delaySec } : {}),\n ...(retries !== undefined ? { retries } : {}),\n })).runId;\n}\n\nfunction localState() {\n try {\n return JSON.parse(fs.readFileSync(STATE_PATH, \"utf8\"));\n } catch {\n return {};\n }\n}\n\nasync function writeState(key, value, { ifVersion, ttlSec } = {}) {\n if (STATE_PATH) {\n const data = localState();\n const current = data[key]?.version ?? 0;\n if (ifVersion !== undefined && ifVersion !== current) throw new StateConflict(key, current);\n if (value === null) delete data[key];\n else data[key] = { value, version: current + 1 };\n fs.writeFileSync(STATE_PATH, JSON.stringify(data, null, 2));\n return value === null ? 0 : current + 1;\n }\n const res = await call(\"POST\", \"/api/agents/v1/state\", { key, value, agent: AGENT, ...(ifVersion !== undefined ? { ifVersion } : {}), ...(ttlSec ? { ttlSec } : {}) }, [409]);\n if (res._status === 409) throw new StateConflict(key, res.version ?? 0);\n return res.version ?? 0;\n}\n\n/** Per-agent key-value storage that outlives runs (values: any JSON, up to\n * 64 KB; 1,000 keys). Every write bumps the key's version; pass ifVersion\n * to write only if nobody else did since you read it. */\nexport const state = {\n async get(key, fallback = null) {\n const { value } = await state.getVersioned(key);\n return value ?? fallback;\n },\n /** { value, version }; { value: null, version: 0 } when the key isn't set. */\n async getVersioned(key) {\n if (STATE_PATH) {\n const row = localState()[key];\n return row ? { value: row.value, version: row.version } : { value: null, version: 0 };\n }\n const res = await call(\"GET\", `/api/agents/v1/state?${new URLSearchParams({ key, agent: AGENT })}`, undefined, [404]);\n if (res._status === 404) return { value: null, version: 0 };\n return { value: JSON.parse(res.value), version: res.version };\n },\n /** Store value; returns the new version. Throws StateConflict on an ifVersion mismatch (0 = unset). */\n set(key, value, { ifVersion, ttlSec } = {}) {\n return writeState(key, value, { ifVersion, ttlSec });\n },\n async delete(key, { ifVersion } = {}) {\n await writeState(key, null, { ifVersion });\n },\n /** Keys (and with values: true, values) starting with prefix. */\n async list(prefix = \"\", { values = false } = {}) {\n if (STATE_PATH) {\n return Object.entries(localState())\n .filter(([k]) => k.startsWith(prefix))\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([key, row]) => ({ key, version: row.version, ...(values ? { value: row.value } : {}) }));\n }\n const out = [];\n let after = null;\n do {\n const q = new URLSearchParams({ prefix, values: values ? \"1\" : \"0\", limit: \"200\", agent: AGENT, ...(after ? { after } : {}) });\n const page = await call(\"GET\", `/api/agents/v1/state?${q}`);\n out.push(...page.keys.map((row) => (\"value\" in row ? { ...row, value: JSON.parse(row.value) } : row)));\n after = page.next;\n } while (after);\n return out;\n },\n /** Read-modify-write that's safe with runs in parallel: fn(old) => new, retried if another run wrote first. */\n async update(key, fn, fallback = null, retries = 10) {\n for (let i = 0; i < retries; i++) {\n const { value, version } = await state.getVersioned(key);\n const next = await fn(value ?? fallback);\n try {\n await state.set(key, next, { ifVersion: version });\n return next;\n } catch (err) {\n if (!(err instanceof StateConflict)) throw err;\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n }\n throw new StateConflict(key, -1);\n },\n};\n\n/** Run fn() once for this run and remember its (JSON) result: if the run is\n * retried after a failure, finished steps return their saved result instead\n * of running again. Use it around side effects so a retry doesn't repeat them. */\nexport async function step(name, fn, { ttlSec = 7 * 86400 } = {}) {\n const key = `step/${process.env.CODIEDEV_RUN_ID || \"local\"}/${name}`;\n const { value, version } = await state.getVersioned(key);\n if (version) return value.result;\n const result = await fn();\n await state.set(key, { result: result ?? null }, { ttlSec });\n return result;\n}\n\n/** Ask a person to decide. It shows in Codiedev (Agents → Approvals) and at\n * the returned .url, which you can post anywhere. When it's decided, a run of\n * `then` (this agent by default; null for none) starts with input\n * { approval: { decision, comment, decidedBy, ... }, context }. Undecided\n * after expiresSec (default 7 days): decision \"expired\". */\nexport async function requestApproval(title, { details, options, approvers, teams, fields, then, context, expiresSec } = {}) {\n if (process.env.CODIEDEV_LOCAL === \"1\") {\n console.log(`[local] approval requested: ${title} (${(options || (fields ? [\"submit\"] : [\"approve\", \"reject\"])).join(\", \")}); not sent on a local run`);\n return { id: `local-${Date.now()}`, status: \"pending\", url: null, title };\n }\n return call(\"POST\", \"/api/agents/v1/approvals\", {\n title,\n ...(details !== undefined ? { details } : {}),\n ...(options ? { options } : {}),\n ...(approvers ? { approvers } : {}),\n ...(teams ? { teams } : {}),\n ...(fields ? { fields } : {}),\n ...(then !== undefined ? { onDecision: then } : {}),\n ...(context !== undefined ? { context } : {}),\n ...(expiresSec ? { expiresSec } : {}),\n });\n}\n\n/** An approval's status (\"pending\", \"decided\", \"expired\"), decision and comment. */\nexport async function getApproval(id) {\n return call(\"GET\", `/api/agents/v1/approvals?id=${encodeURIComponent(id)}`);\n}\n\n/** Wait until a person decides (or it expires), then return the approval. For agents that keep\n * running while they wait, like a connected agent; a run inside Codiedev usually ends instead and\n * is started again with the decision. */\nexport async function waitForApproval(id, { timeoutMs = 3_600_000, pollMs = 15_000 } = {}) {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const a = await getApproval(id);\n if (a.status !== \"pending\") return a;\n if (Date.now() > deadline) throw new Error(`approval ${id} still pending after ${timeoutMs / 1000}s`);\n await new Promise((resolve) => setTimeout(resolve, pollMs));\n }\n}\n\n/** A run's status, input, output (parsed), error, log and children. */\nexport async function get(runId) {\n const run = await call(\"GET\", `/api/agents/v1/run?id=${encodeURIComponent(runId)}`);\n if (typeof run.output === \"string\") {\n try {\n run.output = JSON.parse(run.output);\n } catch {\n // not JSON: keep the string\n }\n }\n return run;\n}\n\n/** Run an agent and wait for it; its result is `.output`. Inside a run this\n * starts a child run. Throws AgentRunError if it fails unless check is false. */\nexport async function run(agent, input = null, { timeoutMs = 900_000, pollMs = 2000, check = true, idempotencyKey } = {}) {\n const id = await start(agent, input, { idempotencyKey });\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const r = await get(id);\n if (DONE.has(r.status)) {\n if (check && r.status !== \"succeeded\") throw new AgentRunError(r);\n return r;\n }\n if (Date.now() > deadline) throw new Error(`${agent} run ${id} still ${r.status} after ${timeoutMs / 1000}s`);\n await new Promise((resolve) => setTimeout(resolve, pollMs));\n }\n}\n\n/** Options for `new OpenAI(...)` on the Codiedev gateway, with this run's trace headers. */\nexport function openaiOptions(extra = {}) {\n const inRun = !!process.env.CODIEDEV_RUN_ID;\n return {\n baseURL: process.env.CODIEDEV_GATEWAY_URL || \"https://gateway.codiedev.com/api/v1\",\n apiKey: process.env.CODIEDEV_API_KEY || process.env.CODIEDEV_TOKEN,\n ...extra,\n defaultHeaders: {\n \"X-Codiedev-Workload\": process.env.CODIEDEV_AGENT || \"local-agent\",\n \"X-Codiedev-Run-Id\": process.env.CODIEDEV_RUN_ID || `local-${Date.now()}`,\n \"X-Codiedev-Environment\": inRun ? \"production\" : \"development\",\n ...(extra.defaultHeaders || {}),\n },\n };\n}\n\n/** An OpenAI client on the Codiedev gateway (the `openai` package is preinstalled). */\nexport async function openai(extra = {}) {\n const { default: OpenAI } = await import(\"openai\");\n return new OpenAI(openaiOptions(extra));\n}\n";
6
+ exports.jsTypes = "/* eslint-disable @typescript-eslint/no-explicit-any -- defaults are `any` on purpose: agent code reads its own JSON input/state without declaring types first. */\nexport type RunStatus = \"queued\" | \"running\" | \"succeeded\" | \"failed\" | \"cancelled\";\nexport interface Run<O = unknown> {\n id: string;\n agent: string;\n version: number;\n status: RunStatus;\n trigger: \"cli\" | \"api\" | \"portal\" | \"schedule\" | \"webhook\" | \"child\" | \"approval\";\n parentRunId: string | null;\n rootRunId: string | null;\n depth: number;\n attempt: number;\n maxAttempts: number;\n scheduledFor: number | null;\n input: string | null;\n output: O;\n error: string | null;\n logTail: string | null;\n durationMs: number | null;\n children: Run[];\n}\nexport interface WebhookRequest { method: string; query: Record<string, string>; headers: Record<string, string>; body: string }\nexport interface Approval {\n id: string;\n agent: string;\n title: string;\n details: string | null;\n options: string[];\n status: \"pending\" | \"decided\" | \"expired\" | \"cancelled\";\n decision: string | null;\n comment: string | null;\n decidedBy: string | null;\n /** The approval app that sent the decision on decidedBy's behalf; null when decided in Codiedev. */\n decidedVia: string | null;\n approvers: string[];\n approverTeams: Array<{ id: string; name: string }>;\n /** The form the person fills in, if the approval asked for one. */\n fields: ApprovalField[];\n /** What they entered, by field name (null until decided). */\n values: Record<string, any> | null;\n url: string | null;\n resumeRunId: string | null;\n}\n/** One thing a person fills in when they decide. */\nexport interface ApprovalField {\n name: string;\n type: \"text\" | \"textarea\" | \"number\" | \"rating\" | \"select\" | \"multiselect\" | \"boolean\";\n label?: string;\n help?: string;\n required?: boolean;\n /** select / multiselect choices */\n options?: string[];\n /** number bounds; rating scale 1–max (default 5) */\n min?: number;\n max?: number;\n /** prefilled, e.g. a proposed amount for the person to correct */\n default?: unknown;\n}\n/** The input a run started by a decision gets. */\nexport interface ApprovalInput<C = any, V = Record<string, any>> {\n approval: { id: string; title: string; decision: string; comment: string | null; values: V; decidedBy: string | null; decidedVia: string | null; decidedAt: number; requestedByRun: string | null };\n context: C;\n}\nexport class AgentRunError extends Error { run: Run }\nexport class StateConflict extends Error { key: string; version: number }\nexport function input<T = any>(fallback?: T): T;\nexport function output(value: unknown): void;\nexport function request(): WebhookRequest | null;\nexport function respond(body?: unknown, opts?: { status?: number; headers?: Record<string, string> }): void;\nexport function attempt(): number;\nexport function start(agent: string, input?: unknown, opts?: { idempotencyKey?: string; delaySec?: number; retries?: number }): Promise<string>;\nexport function get<O = any>(runId: string): Promise<Run<O>>;\nexport function run<O = any>(agent: string, input?: unknown, opts?: { timeoutMs?: number; pollMs?: number; check?: boolean; idempotencyKey?: string }): Promise<Run<O>>;\nexport const state: {\n get<T = any>(key: string, fallback?: T): Promise<T>;\n getVersioned<T = any>(key: string): Promise<{ value: T | null; version: number }>;\n set(key: string, value: unknown, opts?: { ifVersion?: number; ttlSec?: number }): Promise<number>;\n delete(key: string, opts?: { ifVersion?: number }): Promise<void>;\n list(prefix?: string, opts?: { values?: boolean }): Promise<Array<{ key: string; version: number; value?: any }>>;\n update<T = any>(key: string, fn: (old: T) => T | Promise<T>, fallback?: T, retries?: number): Promise<T>;\n};\nexport function step<T>(name: string, fn: () => T | Promise<T>, opts?: { ttlSec?: number }): Promise<T>;\nexport function requestApproval<C = any>(title: string, opts?: { details?: unknown; options?: string[]; approvers?: string[]; teams?: string[]; fields?: ApprovalField[]; then?: string | null; context?: C; expiresSec?: number }): Promise<Approval>;\nexport function getApproval(id: string): Promise<Approval>;\nexport function waitForApproval(id: string, opts?: { timeoutMs?: number; pollMs?: number }): Promise<Approval>;\nexport function openaiOptions(extra?: Record<string, unknown>): { baseURL: string; apiKey: string | undefined; defaultHeaders: Record<string, string> };\nexport function openai(extra?: Record<string, unknown>): Promise<import(\"openai\").default>;";
7
+ exports.jsPackage = "{\n \"name\": \"codiedev-agents\",\n \"version\": \"0.1.0\",\n \"description\": \"Codiedev agents SDK: this run's input and output, chaining, and a traced OpenAI client.\",\n \"type\": \"module\",\n \"main\": \"./index.mjs\",\n \"types\": \"./index.d.ts\",\n \"exports\": { \".\": { \"types\": \"./index.d.ts\", \"default\": \"./index.mjs\" } }\n}\n";
@@ -3,9 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runAsk = runAsk;
4
4
  const shared_1 = require("./shared");
5
5
  function parseArgs(args) {
6
- // Everything after the command, joined back into a question string. Allows
7
- // both quoted and unquoted forms: `codiedev ask "why pg-bouncer?"` or
8
- // `codiedev ask why did we drop pg-bouncer`.
9
6
  const question = args
10
7
  .filter((a) => !a.startsWith("--"))
11
8
  .join(" ")
@@ -123,7 +123,6 @@ async function runCaptureCommand(args, depsOverride = {}) {
123
123
  return;
124
124
  }
125
125
  if (subcommand === "ignored") {
126
- // `ignored` lists everything; `ignored <path>` answers "is this ignored?".
127
126
  const query = args.slice(1).join(" ").trim();
128
127
  if (query) {
129
128
  reportCheck(query, current, deps);
@@ -139,7 +138,6 @@ async function runCaptureCommand(args, depsOverride = {}) {
139
138
  deps.log(` ${value}`);
140
139
  return;
141
140
  }
142
- // Back-compat: the earlier `codiedev capture check <path>` form.
143
141
  if (subcommand === "check") {
144
142
  reportCheck(requirePath(args), current, deps);
145
143
  return;
@@ -100,7 +100,6 @@ async function runCreateTicket(args) {
100
100
  await runBare(config, parsed.prompt);
101
101
  return;
102
102
  }
103
- // submit mode
104
103
  if (!parsed.submitSource) {
105
104
  console.error("--submit requires a path or '-' for stdin");
106
105
  process.exit(1);
@@ -114,7 +113,6 @@ async function runCreateTicket(args) {
114
113
  console.error(`Failed to read plan: ${err.message}`);
115
114
  process.exit(1);
116
115
  }
117
- // Translate fullNames → IDs before submitting
118
116
  let parsedPlan;
119
117
  try {
120
118
  parsedPlan = JSON.parse(raw);
@@ -141,14 +139,6 @@ async function runCreateTicket(args) {
141
139
  }
142
140
  await runSubmit(config, JSON.stringify(parsedPlan));
143
141
  }
144
- /**
145
- * Bare-mode entrypoint. Fetches the protocol body from the backend so we can
146
- * iterate on it without shipping a new CLI, substitutes the user's prompt,
147
- * and writes the result to stdout for the agent to follow. Hard-errors on
148
- * fetch failure rather than falling back to a stale local copy — the whole
149
- * point of moving the protocol server-side is that the freshest version is
150
- * the only version.
151
- */
152
142
  async function runBare(config, prompt) {
153
143
  let res;
154
144
  try {
@@ -81,12 +81,6 @@ function codexInstalled() {
81
81
  function cursorInstalled() {
82
82
  return fs.existsSync(path.join(os.homedir(), ".cursor"));
83
83
  }
84
- // `isCodiedevHookCommand` lives in ../detection alongside detectClaudeCode
85
- // so utils.ts and doctor.ts share one definition (they used to drift —
86
- // each had its own copy).
87
- // Cursor's hooks.json schema is { hooks: { sessionEnd: [{ command, ... }] } }
88
- // — flat array of objects with `command`, not the Claude/Codex nested
89
- // `{ hooks: [{ command }] }` wrapper.
90
84
  function hasCursorHook() {
91
85
  try {
92
86
  if (!fs.existsSync(CURSOR_HOOKS_PATH))
@@ -137,7 +131,6 @@ async function runDoctor(_args) {
137
131
  const checks = [];
138
132
  console.log("\nCodiedev doctor — checking your setup…\n");
139
133
  await (0, upgradeNudge_1.maybePrintUpgradeNudge)();
140
- // 1. Config file
141
134
  const config = (0, utils_1.readConfig)();
142
135
  if (!config) {
143
136
  checks.push({
@@ -153,19 +146,12 @@ async function runDoctor(_args) {
153
146
  status: "pass",
154
147
  detail: `connected to ${config.companyName}`,
155
148
  });
156
- // 2. Token still valid + backend reachable (re-validate). The detail names
157
- // the backend host so users (and their IT) can confirm which domain the CLI
158
- // talks to — the same host capture uploads use, so this check exercises the
159
- // exact TLS path a corporate proxy would intercept.
160
149
  let backendHost = "the capture host";
161
150
  try {
162
151
  backendHost = new URL(config.backendUrl).host;
163
152
  }
164
153
  catch {
165
- // malformed backendUrl in config — keep the generic placeholder
166
154
  }
167
- // Live tracked-repo list fetched from validateToken below. Null until (and
168
- // unless) the backend answers; the checks fall back to `config.repos`.
169
155
  let liveRepos = null;
170
156
  try {
171
157
  const res = await fetch(`${config.backendUrl}/api/cli/validateToken`, {
@@ -182,20 +168,13 @@ async function runDoctor(_args) {
182
168
  status: "pass",
183
169
  detail: backendHost,
184
170
  });
185
- // validateToken returns the company's CURRENT tracked repos. Capture
186
- // them: the repo-resolution checks below must reflect what the SERVER
187
- // will resolve at capture time (repoResolver.ts resolves against the
188
- // live list), not the possibly-stale `config.repos` frozen at the last
189
- // `connect`. A repo linked in the portal after that connect otherwise
190
- // reports a false "isn't a tracked repo — link it in the portal" here
191
- // even though sessions/MRs for it attribute fine server-side.
192
171
  try {
193
172
  const data = (await res.json());
194
173
  if (Array.isArray(data.repos))
195
174
  liveRepos = data.repos;
196
175
  }
197
176
  catch {
198
- liveRepos = null; // malformed body → fall back to the cached list
177
+ liveRepos = null;
199
178
  }
200
179
  }
201
180
  else {
@@ -207,9 +186,6 @@ async function runDoctor(_args) {
207
186
  }
208
187
  }
209
188
  catch (err) {
210
- // fetch buries the real TLS/socket error in .cause ("fetch failed" alone
211
- // is undiagnosable); unwrap it and, when it's an SSL-inspection signature,
212
- // say what actually fixes it.
213
189
  const desc = (0, captureReadiness_1.describeFetchError)(err);
214
190
  const tlsHint = (0, captureReadiness_1.tlsInterceptionHint)(desc, backendHost);
215
191
  checks.push({
@@ -218,7 +194,6 @@ async function runDoctor(_args) {
218
194
  detail: tlsHint ? `${desc} — ${tlsHint}` : `${desc} (host: ${backendHost})`,
219
195
  });
220
196
  }
221
- // 3. Authenticated endpoint smoke test (inbox query)
222
197
  try {
223
198
  await (0, shared_1.apiRequest)("GET", "/api/cli/inbox", {
224
199
  config,
@@ -236,38 +211,16 @@ async function runDoctor(_args) {
236
211
  detail: err.message,
237
212
  });
238
213
  }
239
- // 4. Tracked repos. Prefer the live list from validateToken over the cache:
240
- // a repo linked after the last `connect` is tracked server-side but absent
241
- // from `config.repos`, and resolving against the stale cache is exactly what
242
- // produced the false "isn't a tracked repo — link it in the portal" warning.
243
- // Treat an EMPTY live list as "no usable live data", NOT an authoritative
244
- // zero: a transient permission glitch / backend hiccup can return `repos: []`,
245
- // and both driving the checks from it AND healing the cache to empty would be
246
- // wrong — the write would durably break every offline doctor run (and the
247
- // capture hook's providedRepoId) until the next successful connect. So when
248
- // live is empty, fall back to the cache and skip the write, exactly like
249
- // backend-unreachable. A genuinely repo-less company also has an empty cache,
250
- // so it still reports "0 repos" correctly.
251
214
  const trackedRepos = liveRepos !== null && liveRepos.length > 0 ? liveRepos : (config.repos ?? []);
252
- // Detect drift by CONTENT, not count: a same-size swap (one repo removed +
253
- // another added between connects) or a repo whose path/URL changed while its
254
- // id stayed stable (GitLab move/rename — exactly the SONIFI migration case)
255
- // both leave the count unchanged. A length-only check would skip the heal and
256
- // leave the capture hook's cache — and its advisory providedRepoId — stale.
257
215
  const canonRepos = (rs) => JSON.stringify([...rs].map((r) => [r.repoId, r.url, r.fullName]).sort());
258
216
  const cacheRefreshed = liveRepos !== null &&
259
217
  liveRepos.length > 0 &&
260
218
  canonRepos(liveRepos) !== canonRepos(config.repos ?? []);
261
- // Heal the on-disk cache so the capture hook (which reads `config.repos` for
262
- // the advisory providedRepoId) stops trailing the portal too. Best-effort:
263
- // doctor must never fail because the config couldn't be rewritten.
264
219
  if (cacheRefreshed && liveRepos) {
265
220
  try {
266
221
  (0, utils_1.writeConfig)({ ...config, repos: liveRepos, lastSynced: new Date().toISOString() });
267
222
  }
268
223
  catch {
269
- // read-only home / permission issue — the in-memory list still drives
270
- // the checks below; the user just re-syncs on the next `connect`.
271
224
  }
272
225
  }
273
226
  const repoCount = trackedRepos.length;
@@ -278,11 +231,6 @@ async function runDoctor(_args) {
278
231
  ? `${repoCount} repo${repoCount === 1 ? "" : "s"}${cacheRefreshed ? " (refreshed from portal)" : ""}`
279
232
  : "0 — link repos in the portal so sessions get captured",
280
233
  });
281
- // 4b. Capture readiness — the part that actually decides whether a session
282
- // lands. doctor used to verify only that the hook was *installed*; these
283
- // checks answer "from this directory, would a session capture, and did my
284
- // last one?" — the blind spot behind lean-container / submodule / no-remote
285
- // zeros.
286
234
  const cwd = process.cwd();
287
235
  const readiness = (0, captureReadiness_1.assessCaptureReadiness)(cwd, trackedRepos, {
288
236
  exec: (cmd, dir) => (0, child_process_1.execSync)(cmd, { cwd: dir, stdio: ["pipe", "pipe", "pipe"] }).toString(),
@@ -291,11 +239,6 @@ async function runDoctor(_args) {
291
239
  getBranch: utils_1.getGitBranch,
292
240
  getHeadSha: utils_1.getGitHeadSha,
293
241
  });
294
- // Workspace-root mode: the cwd isn't a repo itself, but git repos sit
295
- // directly under it (one `.devcontainer/` at a parent folder of several
296
- // cloned repos). Capture tags the sub-repo a session edits, so report that
297
- // instead of flatly warning "not a work tree / no remote" — the exact output
298
- // that made working workspace-root setups read as broken.
299
242
  const workspaceScan = readiness.gitOnPath && !readiness.insideWorkTree
300
243
  ? (0, captureReadiness_1.assessWorkspaceRepos)(cwd, trackedRepos, {
301
244
  listChildDirs: (dir) => fs
@@ -310,8 +253,6 @@ async function runDoctor(_args) {
310
253
  const workspaceMode = workspaceScan.repoCount > 0;
311
254
  checks.push({
312
255
  name: "git on PATH",
313
- // A warning, not a failure: sessions still capture without git, they just
314
- // aren't tagged to a repo. Non-engineer installs often skip git entirely.
315
256
  status: readiness.gitOnPath ? "pass" : "warn",
316
257
  detail: readiness.gitOnPath
317
258
  ? undefined
@@ -348,9 +289,6 @@ async function runDoctor(_args) {
348
289
  ? "branch/sha resolve from the sub-repo each session writes to"
349
290
  : "no branch/sha resolved — session→merge attribution will be weaker",
350
291
  });
351
- // 4c. The payoff: did the last session actually land? Ask the server for
352
- // portal truth (does the row exist for this user?), falling back to the local
353
- // 2xx breadcrumb if the endpoint is unreachable or predates this CLI/backend.
354
292
  const localMarker = (0, utils_1.readLastCapture)();
355
293
  let server = null;
356
294
  try {
@@ -371,7 +309,7 @@ async function runDoctor(_args) {
371
309
  server = (await res.json());
372
310
  }
373
311
  catch {
374
- server = null; // unreachable / old backend → fall back to the local marker
312
+ server = null;
375
313
  }
376
314
  const lastCapture = (0, captureReadiness_1.summarizeServerCapture)(server, localMarker, Date.now());
377
315
  checks.push({
@@ -379,7 +317,6 @@ async function runDoctor(_args) {
379
317
  status: lastCapture.status,
380
318
  detail: lastCapture.detail,
381
319
  });
382
- // 4d. Capture-log activity: did recent uploads succeed? Are there pending jobs?
383
320
  const logTail = (0, captureLog_1.readCaptureLogTail)(40);
384
321
  let pendingJobCount = 0;
385
322
  try {
@@ -396,17 +333,12 @@ async function runDoctor(_args) {
396
333
  status: captureActivity.status,
397
334
  detail: captureActivity.detail,
398
335
  });
399
- // 5. Claude Code setup (if present)
400
336
  if ((0, utils_1.claudeCodeInstalled)()) {
401
337
  checks.push({
402
338
  name: "Claude Code detected",
403
339
  status: "pass",
404
340
  detail: (0, harnessDirs_1.displayPath)(CLAUDE_DIR),
405
341
  });
406
- // A hook in settings.json only fires if Claude Code actually reads this
407
- // dir. If it holds nothing Claude Code writes on use, it's running from
408
- // somewhere else (CLAUDE_CONFIG_DIR unset in this shell, another user,
409
- // the host vs. a container) and the ✓s below are hollow.
410
342
  checks.push(configDirInUseCheck("Claude Code", CLAUDE_DIR, (0, harnessDirs_1.claudeConfigDirInUse)(CLAUDE_DIR), "CLAUDE_CONFIG_DIR"));
411
343
  checks.push({
412
344
  name: "Claude Code SessionEnd hook",
@@ -430,7 +362,6 @@ async function runDoctor(_args) {
430
362
  detail: "not installed on this machine",
431
363
  });
432
364
  }
433
- // 6. Codex setup (if present)
434
365
  if (codexInstalled()) {
435
366
  checks.push({
436
367
  name: "Codex detected",
@@ -460,7 +391,6 @@ async function runDoctor(_args) {
460
391
  detail: "not installed on this machine",
461
392
  });
462
393
  }
463
- // 7. Cursor setup (if present)
464
394
  if (cursorInstalled()) {
465
395
  checks.push({
466
396
  name: "Cursor detected",
@@ -1,13 +1,4 @@
1
1
  "use strict";
2
- // `codiedev evals report <run.json> [--harness name]`
3
- // `codiedev evals last <subject> [--json]`
4
- //
5
- // Evals are experiments (a question about a subject: an agent, or a workload
6
- // like session-summaries) and the runs that answer them, one per variant. The
7
- // eval runs wherever it runs (a script, a coding agent); `report` files the
8
- // scores under the experiment in Codiedev → Traces → Evals, shared with the
9
- // team. `last` is where to start the next one: the latest experiment on the
10
- // subject, its runs, and the champion the subject runs today.
11
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
12
3
  if (k2 === undefined) k2 = k;
13
4
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -67,6 +58,7 @@ codiedev evals — experiments and their runs, shared with the team
67
58
  "provider": "openai", "reasoningEffort": "medium", "prompt": "summary_extract_v2",
68
59
  "gitSha": "…", "isControl": false, "judgeModel": "anthropic/claude-sonnet-5.5",
69
60
  "casesTotal": 30, "casesScored": 30, "errors": 0,
61
+ "scoringRevision": 1, // required once experiment scoring rules are defined
70
62
  "score": 3.85, "metrics": { "fidelity": 3.6 },
71
63
  "costPerCaseUsd": 0.026, "latencyMsAvg": 21000,
72
64
  "wins": 20, "losses": 8, "ties": 2, "note": "…",
@@ -74,6 +66,8 @@ codiedev evals — experiments and their runs, shared with the team
74
66
  }
75
67
  }
76
68
 
69
+ Read scoring rules and their current revision with: codiedev evals last <subject> --json
70
+
77
71
  Scores and notes only: never put prompts, transcripts or outputs in it.
78
72
  `.trim();
79
73
  function flag(args, i, name) {
@@ -70,8 +70,6 @@ async function runRead(args) {
70
70
  const config = (0, shared_1.requireConfig)();
71
71
  const start = Date.now();
72
72
  try {
73
- // First, fetch inbox so we can show the full body (markRead endpoint
74
- // doesn't return content).
75
73
  const listRes = await (0, shared_1.apiRequest)("GET", "/api/cli/inbox", {
76
74
  config,
77
75
  query: { limit: 100 },
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- // `codiedev library [--scope mine|shared|all] [--kind doc|skill] [--tag X]
3
- // [--type spec|...] [--limit N]` — list artifacts in your Codiedev workspace.
4
- // Server applies companyId scoping; --scope filters within that.
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.runLibrary = runLibrary;
7
4
  const shared_1 = require("./shared");
@@ -59,10 +59,7 @@ const harnesses_2 = require("../packs/harnesses");
59
59
  const os = __importStar(require("os"));
60
60
  const utils_1 = require("../utils");
61
61
  const shared_1 = require("./shared");
62
- // --- CI (pack-scoped `cdvci_` keys) ------------------------------------------
63
62
  exports.DEFAULT_BACKEND_URL = "https://cli.codiedev.com";
64
- /** CODIEDEV_TOKEN alone is enough: no ~/.codiedev/config.json needed (CI).
65
- * CODIEDEV_URL defaults to production. Otherwise the connected config. */
66
63
  function resolvePackConfig(env = process.env) {
67
64
  const token = env.CODIEDEV_TOKEN?.trim();
68
65
  if (token) {
@@ -78,8 +75,6 @@ function resolvePackConfig(env = process.env) {
78
75
  const config = (0, utils_1.readConfig)();
79
76
  return config ? (0, shared_1.applyConfigEnvOverrides)(config) : null;
80
77
  }
81
- /** In CI, `--harness` defaults to claude when it's on PATH; anything else is
82
- * ambiguous on a build box, so say what was found. */
83
78
  function ciHarnesses(args, env, home) {
84
79
  if (args.harnesses?.length)
85
80
  return args.harnesses;
@@ -223,8 +218,6 @@ async function runInstall(config, args, overrides = {}) {
223
218
  const ci = (0, sync_1.isPackCiMode)(overrides.env ?? process.env);
224
219
  const harnesses = ci && !args.dryRun ? ciHarnesses(args, overrides.env ?? process.env, overrides.home) : args.harnesses;
225
220
  const listed = args.slug ? [args.slug] : (await listPacks(config)).map((p) => p.slug);
226
- // With no slug, also re-check every locally installed pack: one that was
227
- // unassigned or archived 404s and must be removed locally. Not in CI: no pruning.
228
221
  const slugs = args.slug || ci ? listed : [...new Set([...listed, ...Object.keys(registry.packs)])];
229
222
  const manifests = [];
230
223
  const revoked = [];
@@ -241,7 +234,6 @@ async function runInstall(config, args, overrides = {}) {
241
234
  revoked.push(slug);
242
235
  else if (args.slug)
243
236
  throw new Error(`Pack not found or not assigned to your team: ${slug}`);
244
- // A listed pack that 404s a moment later (race with an unassign) is skipped.
245
237
  }
246
238
  }
247
239
  let installed = manifests.length
@@ -249,8 +241,6 @@ async function runInstall(config, args, overrides = {}) {
249
241
  : [];
250
242
  let removed = [];
251
243
  if (!args.dryRun && !ci) {
252
- // A 404 on the installed report means the pack stopped applying between
253
- // the manifest fetch and now: treat it exactly like a revoked pack.
254
244
  const lateRevoked = await reportInstalled(config, installed);
255
245
  installed = installed.filter((p) => !lateRevoked.includes(p.slug));
256
246
  removed = await removePacks(config, [...revoked, ...lateRevoked], overrides);
@@ -285,11 +275,7 @@ async function runInstall(config, args, overrides = {}) {
285
275
  for (const line of (0, install_1.formatUninstallLines)(removed))
286
276
  console.log(line);
287
277
  }
288
- // Exit non-zero when a pack reached no tool because of a failure, or the
289
- // pack explicitly asked for is no longer available.
290
278
  const failed = installed.some((p) => p.results.some((r) => r.status === "failed") && !p.results.some((r) => r.status === "ok"));
291
- // CI is strict: every requested tool must have taken every pack, and there
292
- // must have been a pack to install at all.
293
279
  const ciFailed = ci && !args.dryRun && (installed.length === 0 || installed.some((p) => p.results.some((r) => r.status !== "ok")));
294
280
  if (ci && !args.dryRun && installed.length === 0)
295
281
  console.error("No pack is visible to this key.");
@@ -297,8 +283,6 @@ async function runInstall(config, args, overrides = {}) {
297
283
  process.exitCode = 1;
298
284
  return run;
299
285
  }
300
- /** POST each install. Returns slugs the server answered 404 for (revoked);
301
- * any other failure is only a warning. */
302
286
  async function reportInstalled(config, results) {
303
287
  const revoked = [];
304
288
  for (const pack of results) {
@@ -317,7 +301,6 @@ async function reportInstalled(config, results) {
317
301
  }
318
302
  return revoked;
319
303
  }
320
- /** Uninstall packs locally, then tell the server (best-effort, idempotent). */
321
304
  async function removePacks(config, slugs, overrides) {
322
305
  if (slugs.length === 0)
323
306
  return [];
@@ -365,7 +348,6 @@ async function runStatus(config, json, overrides = {}, options = {}) {
365
348
  }
366
349
  rows.push({ slug, ...entry, upToDate, latestVersion, latestChannel });
367
350
  }
368
- // --no-prune (background check when auto-update is off) and CI: report only.
369
351
  const ci = (0, sync_1.isPackCiMode)(overrides.env ?? process.env);
370
352
  const removed = options.prune === false || ci ? [] : await removePacks(config, revoked, overrides);
371
353
  if (available && !ci) {
@@ -414,9 +396,7 @@ async function runPack(args) {
414
396
  }
415
397
  const config = resolvePackConfig() ?? (0, shared_1.requireConfig)();
416
398
  const ci = (0, sync_1.isPackCiMode)();
417
- // --quiet (the background auto-update): no output at all.
418
399
  const restore = parsed.quiet ? silenceConsole() : () => { };
419
- // CI keys can only read packs: no telemetry POST either.
420
400
  const track = ci ? (_c, _t, fn) => fn() : shared_1.withTelemetry;
421
401
  try {
422
402
  await track(config, `codiedev_pack_${parsed.sub === "ls" ? "list" : parsed.sub}`, async () => {
@@ -449,13 +429,10 @@ function silenceConsole() {
449
429
  console.error = error;
450
430
  };
451
431
  }
452
- // --- pack export / apply ---------------------------------------------------
453
432
  function gitIn(dir, args) {
454
433
  const r = (0, child_process_1.spawnSync)("git", args, { cwd: dir, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
455
434
  return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? (r.error?.message ?? "") };
456
435
  }
457
- /** Init (if needed) and commit everything under `dir`. Uses the user's git
458
- * identity when configured, a neutral Codiedev one otherwise (fresh CI). */
459
436
  function commitExport(dir, message) {
460
437
  if (!fs.existsSync(path.join(dir, ".git"))) {
461
438
  const init = gitIn(dir, ["init", "-q"]);
@@ -491,9 +468,6 @@ function readMarketplaceEntries(dir) {
491
468
  return [];
492
469
  }
493
470
  }
494
- /** Write a CI-committable copy of the pack: `<out>/plugins/<slug>/…` plus
495
- * `<out>/.claude-plugin/marketplace.json` (existing entries for other packs
496
- * in the same folder are kept). */
497
471
  function exportPluginFolder(out, manifest) {
498
472
  fs.mkdirSync(out, { recursive: true });
499
473
  const dir = (0, store_1.writePluginDir)(out, manifest);
@@ -522,7 +496,6 @@ async function runExport(config, args) {
522
496
  if (typeof res.markdown !== "string")
523
497
  throw new Error("Server returned no markdown");
524
498
  fs.mkdirSync(out, { recursive: true });
525
- // <slug>.pack.md so several packs can share one folder.
526
499
  written = path.join(out, `${args.slug}.pack.md`);
527
500
  (0, store_1.writeFileAtomic)(written, res.markdown.endsWith("\n") ? res.markdown : `${res.markdown}\n`);
528
501
  message = `codiedev pack export ${args.slug} (${args.slug}.pack.md)`;
@@ -576,8 +549,6 @@ async function runApply(config, args) {
576
549
  res = await (0, shared_1.apiRequest)("POST", "/api/cli/packs/apply", { config, body: { markdown } });
577
550
  }
578
551
  catch (error) {
579
- // The server reports pack.md problems with line numbers; show them as-is.
580
- // The server's 400 is already "pack.md line N: …" — print it verbatim.
581
552
  const e = error;
582
553
  if (e.status === 403)
583
554
  throw new Error(`You can't edit this pack (${e.message})`);
@@ -23,8 +23,6 @@ function parseArgs(args) {
23
23
  process.exit(1);
24
24
  }
25
25
  to = positional[0];
26
- // Join remaining positionals in case the shell split the message on spaces
27
- // despite quoting (happens with some escape sequences).
28
26
  const body = (0, shared_1.stripQuotes)(positional.slice(1).join(" "));
29
27
  return { to, body, subjectKey };
30
28
  }
@@ -71,10 +71,6 @@ function parseArgs(args) {
71
71
  }
72
72
  return { key, version, out };
73
73
  }
74
- // The backend stores skills under extension-bearing keys (e.g. "pr-push.md"),
75
- // and lookup is exact-match, so a bare "pr-push" 404s. Make pull forgiving: try
76
- // the key as given, then a ".md" fallback when it has no extension, so the
77
- // intuitive bare name (and the hook's suggested key) both resolve.
78
74
  function candidateKeys(key) {
79
75
  if (/\.[a-z0-9]+$/i.test(key))
80
76
  return [key];
@@ -97,16 +93,12 @@ async function runPull(args) {
97
93
  }
98
94
  catch (err) {
99
95
  const e = err;
100
- // A 404 on a non-final candidate is retryable (fall through to ".md");
101
- // anything else — or the last candidate — propagates to the handler.
102
96
  if (e.status === 404 && i < keys.length - 1)
103
97
  continue;
104
98
  throw err;
105
99
  }
106
100
  }
107
101
  const a = res.artifact;
108
- // A skill carries its identity onto disk so its runs attribute exactly
109
- // (see skillMarker.ts). Docs are written verbatim.
110
102
  const isSkill = a.kind ? a.kind === "skill" : (0, skillMarker_1.looksLikeSkill)(a.markdown);
111
103
  const markdown = isSkill ? (0, skillMarker_1.stampSkillMarker)(a.markdown, a._id) : a.markdown;
112
104
  (0, shared_1.recordAgentEvent)(config, {
@@ -123,7 +115,6 @@ async function runPull(args) {
123
115
  console.log(` updated: ${(0, shared_1.timeAgo)(a.updatedAt ?? a.createdAt)}`);
124
116
  }
125
117
  else {
126
- // Stream to stdout — preserves shell pipes like `codiedev pull spec-214.md | less`.
127
118
  process.stdout.write(markdown);
128
119
  if (!markdown.endsWith("\n"))
129
120
  process.stdout.write("\n");
@@ -107,10 +107,6 @@ function parseArgs(args) {
107
107
  console.error(`Invalid --kind. Valid kinds: ${[...VALID_KINDS].join(", ")}`);
108
108
  process.exit(1);
109
109
  }
110
- // The override key is stored verbatim by the server (docs key off it, and a
111
- // path-y value like "specs/feature-a/plan.md" populates folderPath). Strip a
112
- // leading slash so it can't be confused with an absolute path, and reject an
113
- // empty value — but otherwise allow slashes so callers can namespace.
114
110
  if (as !== undefined) {
115
111
  as = as.replace(/^\/+/, "").trim();
116
112
  if (!as) {
@@ -121,7 +117,6 @@ function parseArgs(args) {
121
117
  return { file, type, kind, tags, force, as, private: priv };
122
118
  }
123
119
  async function pushFile(config, opts) {
124
- // Never upload another artifact's identity marker (skillMarker.ts).
125
120
  const markdown = (0, skillMarker_1.stripSkillMarker)(fs.readFileSync(opts.absPath, "utf8"));
126
121
  const gitRemoteUrl = (0, utils_1.getGitRemoteUrl)(process.cwd()) ?? undefined;
127
122
  return shared.apiRequest("POST", "/api/cli/push", {
@@ -155,10 +150,6 @@ async function runPush(args) {
155
150
  console.error(`File is empty: ${absolute}`);
156
151
  process.exit(1);
157
152
  }
158
- // Stored key defaults to the basename (legacy behavior). `--as` overrides it
159
- // so callers can namespace generically-named files — e.g. Spec Kit emits a
160
- // `plan.md`/`spec.md` per feature, which would otherwise all collide on one
161
- // key and silently version over each other.
162
153
  const filename = as ?? path.basename(absolute);
163
154
  const start = Date.now();
164
155
  try {
@@ -179,9 +170,6 @@ async function runPush(args) {
179
170
  const tagSummary = res.tags && res.tags.length > 0 ? ` tags=[${res.tags.join(", ")}]` : "";
180
171
  console.log(`✓ Pushed ${filename} (kind=${res.kind}${tagSummary}).`);
181
172
  console.log(` Visible under: ${res.destination}`);
182
- // Echo the *resolved* key the server stored, not the local filename —
183
- // skills are keyed by their frontmatter name (so two `SKILL.md` files
184
- // don't collide), so the stored key can differ from what was pushed.
185
173
  if (res.key && res.key !== filename) {
186
174
  console.log(` Stored as: ${res.key}`);
187
175
  }
@@ -1,8 +1,4 @@
1
1
  "use strict";
2
- // `codiedev search "<query>"` — semantic + keyword search across the org's
3
- // captured sessions, artifacts, and skills. Hits are filtered by companyId
4
- // server-side, so a single search surfaces results from every teammate's
5
- // prior sessions in the same workspace.
6
2
  Object.defineProperty(exports, "__esModule", { value: true });
7
3
  exports.runSearch = runSearch;
8
4
  const shared_1 = require("./shared");