@inneranimalmedia/agentsam-sdk 2.6.2 → 2.6.4

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 (661) hide show
  1. package/AGENTSAM.md +51 -1
  2. package/README.md +95 -0
  3. package/apps/README.md +34 -0
  4. package/apps/cad-creator/README.md +728 -0
  5. package/apps/cad-creator/shared/cad/package.json +19 -0
  6. package/apps/cad-creator/shared/cad/src/domain/operations.ts +7 -0
  7. package/apps/cad-creator/shared/cad/src/domain/project-contract.d.ts +3 -0
  8. package/apps/cad-creator/shared/cad/src/domain/project-contract.js +75 -0
  9. package/apps/cad-creator/shared/cad/src/domain/project-tools.d.ts +1 -0
  10. package/apps/cad-creator/shared/cad/src/domain/project-tools.js +24 -0
  11. package/apps/cad-creator/shared/cad/src/domain/validation.ts +191 -0
  12. package/apps/cad-creator/shared/cad/src/index.ts +4 -0
  13. package/apps/cad-creator/shared/cad/src/robotics/types.ts +232 -0
  14. package/apps/cad-creator/shared/cad/src/types.ts +507 -0
  15. package/apps/cad-creator/shared/cad/tsconfig.json +14 -0
  16. package/bin/agentsam +16 -1
  17. package/docs/AUTORAG.md +58 -0
  18. package/docs/BRAND_INTELLIGENCE.md +30 -0
  19. package/docs/CLI_SHELL.md +4 -2
  20. package/docs/CMS_CONTEXTUAL_COMPOSER.md +38 -0
  21. package/docs/MERKLE.md +4 -0
  22. package/docs/PROJECT_CONFIG.md +3 -0
  23. package/docs/REPOSITORY_KNOWLEDGE.md +2 -0
  24. package/docs/THEME_REFINERY.md +120 -0
  25. package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
  26. package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
  27. package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  28. package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
  29. package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
  30. package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
  31. package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
  32. package/docs/architecture/PROVIDER-TOOLS-AND-COMPACTION.md +60 -0
  33. package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
  34. package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
  35. package/docs/architecture/SAM_KERNEL.md +181 -0
  36. package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
  37. package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
  38. package/docs/architecture/STORAGE.md +87 -0
  39. package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
  40. package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  41. package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
  42. package/docs/cad-project-tools.md +69 -0
  43. package/docs/cms-scaffolding-pattern-reference.md +73 -0
  44. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS-codex-tui-20260919.md +113 -0
  45. package/docs/plans/AGENTSAM-INTERACTIVE-UI-REQUIREMENTS.md +85 -0
  46. package/docs/plans/AGENTSAM-MCP-CLIENT-2026-09-19.md +181 -0
  47. package/docs/plans/ASBD-PORTABLE-WORKGRAPH-UI-DEFERRED.md +34 -0
  48. package/docs/plans/ASTRA-BRIEF-2026-09-18.md +258 -0
  49. package/docs/plans/MULTI-AGENT-SPRINTS-2026-09-19.md +373 -0
  50. package/docs/plans/NEXT-AGENT-HANDOFF.md +167 -0
  51. package/docs/plans/RECONCILIATION-2026-09-19.md +178 -0
  52. package/docs/plugins.md +43 -0
  53. package/docs/tools/README.md +57 -0
  54. package/docs/tools/agent-and-orchestration.md +49 -0
  55. package/docs/tools/browser-and-research.md +46 -0
  56. package/docs/tools/cloudflare-platform.md +32 -0
  57. package/docs/tools/cms.md +25 -0
  58. package/docs/tools/communications.md +41 -0
  59. package/docs/tools/database-and-storage.md +62 -0
  60. package/docs/tools/design-and-media.md +64 -0
  61. package/docs/tools/filesystem-and-code.md +55 -0
  62. package/docs/tools/github.md +56 -0
  63. package/docs/tools/integrations-and-misc.md +16 -0
  64. package/docs/tools/memory.md +21 -0
  65. package/docs/tools/terminal-and-execution.md +29 -0
  66. package/docs/tools/tickets-and-platform.md +30 -0
  67. package/migrations/d1/0001_agentsam_plugin_runtime.sql +177 -0
  68. package/migrations/d1/0002_agentsam_ticket_ownership.sql +8 -0
  69. package/migrations/d1/0002_dynamic_model_policies.sql +23 -0
  70. package/migrations/d1/0003_expand_tool_handler_families.sql +18 -0
  71. package/migrations/d1/0004_project_aware_retrieval_lanes.sql +24 -0
  72. package/migrations/d1/0005_portable_knowledge_identity.sql +104 -0
  73. package/migrations/d1/0006_repair_ops_trail_account_scope.sql +14 -0
  74. package/migrations/d1/0007_repair_ops_trail_agent_run_account.sql +13 -0
  75. package/migrations/d1/0008_backfill_knowledge_run_legacy_tenant.sql +14 -0
  76. package/migrations/d1/0009_normalize_cloudflare_plugin_installations.sql +137 -0
  77. package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
  78. package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
  79. package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
  80. package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
  81. package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
  82. package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
  83. package/migrations/d1/0013_identity_oauth_states.sql +15 -0
  84. package/migrations/d1/0014_auth_event_log.sql +20 -0
  85. package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
  86. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
  87. package/migrations/runtime/0001_cli_runtime.sql +67 -0
  88. package/migrations/runtime/0002_project_sessions.sql +15 -0
  89. package/migrations/runtime/0003_provider_continuations.sql +8 -0
  90. package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
  91. package/package.json +107 -12
  92. package/packages/agentsam-brand/README.md +21 -0
  93. package/packages/agentsam-brand/package.json +22 -0
  94. package/packages/agentsam-brand/src/contract.js +59 -0
  95. package/packages/agentsam-brand/src/extract.js +126 -0
  96. package/packages/agentsam-brand/src/goap-actions.js +73 -0
  97. package/packages/agentsam-brand/src/index.js +48 -0
  98. package/packages/agentsam-brand/src/plan.js +115 -0
  99. package/packages/agentsam-brand/src/resolve.js +139 -0
  100. package/packages/agentsam-brand/src/scan.js +250 -0
  101. package/packages/agentsam-brand/test/brand-scan.test.mjs +106 -0
  102. package/packages/agentsam-contracts/README.md +23 -0
  103. package/packages/agentsam-contracts/package.json +32 -0
  104. package/packages/agentsam-contracts/src/adapter.ts +25 -0
  105. package/packages/agentsam-contracts/src/agent.ts +35 -0
  106. package/packages/agentsam-contracts/src/artifacts.ts +33 -0
  107. package/packages/agentsam-contracts/src/authority.ts +29 -0
  108. package/packages/agentsam-contracts/src/context.ts +16 -0
  109. package/packages/agentsam-contracts/src/errors.ts +62 -0
  110. package/packages/agentsam-contracts/src/events.ts +47 -0
  111. package/packages/agentsam-contracts/src/execution.ts +50 -0
  112. package/packages/agentsam-contracts/src/hooks.ts +40 -0
  113. package/packages/agentsam-contracts/src/identity.ts +16 -0
  114. package/packages/agentsam-contracts/src/index.ts +14 -0
  115. package/packages/agentsam-contracts/src/models.ts +9 -0
  116. package/packages/agentsam-contracts/src/providers.ts +33 -0
  117. package/packages/agentsam-contracts/src/repository.ts +64 -0
  118. package/packages/agentsam-contracts/src/tools.ts +98 -0
  119. package/packages/agentsam-contracts/test/contracts.test.mjs +16 -0
  120. package/packages/agentsam-contracts/test/errors-catalog.test.mjs +25 -0
  121. package/packages/agentsam-contracts/test/repository.test.mjs +18 -0
  122. package/packages/agentsam-contracts/tsconfig.json +12 -0
  123. package/packages/agentsam-errors/package.json +17 -0
  124. package/packages/agentsam-errors/src/adapters/anthropic.js +15 -0
  125. package/packages/agentsam-errors/src/adapters/cad.js +109 -0
  126. package/packages/agentsam-errors/src/adapters/cloudflare.js +21 -0
  127. package/packages/agentsam-errors/src/adapters/cursor.js +4 -0
  128. package/packages/agentsam-errors/src/adapters/device.js +38 -0
  129. package/packages/agentsam-errors/src/adapters/docker.js +28 -0
  130. package/packages/agentsam-errors/src/adapters/gcp.js +14 -0
  131. package/packages/agentsam-errors/src/adapters/github.js +22 -0
  132. package/packages/agentsam-errors/src/adapters/google.js +17 -0
  133. package/packages/agentsam-errors/src/adapters/index.js +55 -0
  134. package/packages/agentsam-errors/src/adapters/internal.js +40 -0
  135. package/packages/agentsam-errors/src/adapters/oauth.js +24 -0
  136. package/packages/agentsam-errors/src/adapters/openai.js +17 -0
  137. package/packages/agentsam-errors/src/adapters/process.js +35 -0
  138. package/packages/agentsam-errors/src/adapters/provider.js +114 -0
  139. package/packages/agentsam-errors/src/envelope.js +239 -0
  140. package/packages/agentsam-errors/src/error.js +24 -0
  141. package/packages/agentsam-errors/src/fingerprint.js +35 -0
  142. package/packages/agentsam-errors/src/index.js +11 -0
  143. package/packages/agentsam-errors/src/normalize.js +30 -0
  144. package/packages/agentsam-errors/src/recovery.js +301 -0
  145. package/packages/agentsam-errors/src/redaction.js +52 -0
  146. package/packages/agentsam-errors/src/render.js +16 -0
  147. package/packages/agentsam-errors/src/retry.js +10 -0
  148. package/packages/agentsam-errors/src/transport.js +52 -0
  149. package/packages/agentsam-errors/src/vocabulary.js +320 -0
  150. package/packages/agentsam-errors/test/envelope.test.mjs +70 -0
  151. package/packages/agentsam-errors/test/providers.test.mjs +99 -0
  152. package/packages/agentsam-errors/test/redaction.test.mjs +21 -0
  153. package/packages/agentsam-errors/test/runtime-cad-device.test.mjs +76 -0
  154. package/packages/agentsam-errors/test/transport.test.mjs +46 -0
  155. package/packages/agentsam-knowledge/package.json +15 -0
  156. package/packages/agentsam-knowledge/src/autorag/index.js +64 -0
  157. package/packages/agentsam-knowledge/src/backends/index.js +26 -0
  158. package/packages/agentsam-knowledge/src/index.js +3 -0
  159. package/packages/agentsam-knowledge/src/providers/index.js +107 -0
  160. package/packages/agentsam-knowledge/test/autorag.test.mjs +42 -0
  161. package/packages/agentsam-nav/README.md +40 -0
  162. package/packages/agentsam-nav/dist/Nav.d.ts +43 -0
  163. package/packages/agentsam-nav/dist/NavCollapsible.d.ts +10 -0
  164. package/packages/agentsam-nav/dist/NavContent.d.ts +2 -0
  165. package/packages/agentsam-nav/dist/NavFooter.d.ts +2 -0
  166. package/packages/agentsam-nav/dist/NavGroup.d.ts +3 -0
  167. package/packages/agentsam-nav/dist/NavHeader.d.ts +2 -0
  168. package/packages/agentsam-nav/dist/NavMenu.d.ts +22 -0
  169. package/packages/agentsam-nav/dist/NavProvider.d.ts +35 -0
  170. package/packages/agentsam-nav/dist/NavTrigger.d.ts +2 -0
  171. package/packages/agentsam-nav/dist/Surfaces.d.ts +41 -0
  172. package/packages/agentsam-nav/dist/browser.d.ts +11 -0
  173. package/packages/agentsam-nav/dist/browser.global.js +132 -0
  174. package/packages/agentsam-nav/dist/browser.js +613 -0
  175. package/packages/agentsam-nav/dist/contracts.d.ts +76 -0
  176. package/packages/agentsam-nav/dist/index.d.ts +11 -0
  177. package/packages/agentsam-nav/dist/index.js +614 -0
  178. package/packages/agentsam-nav/dist/legacy.css +83 -0
  179. package/packages/agentsam-nav/dist/shell.css +113 -0
  180. package/packages/agentsam-nav/dist/theme.css +113 -0
  181. package/packages/agentsam-nav/dist/utils.d.ts +1 -0
  182. package/packages/agentsam-nav/package.json +43 -0
  183. package/packages/agentsam-queue-control/README.md +107 -0
  184. package/packages/agentsam-queue-control/package.json +31 -0
  185. package/packages/agentsam-queue-control/schemas/job-envelope.schema.json +56 -0
  186. package/packages/agentsam-queue-control/src/adapters/cloudflare.js +152 -0
  187. package/packages/agentsam-queue-control/src/adapters/memory.js +38 -0
  188. package/packages/agentsam-queue-control/src/contracts.js +130 -0
  189. package/packages/agentsam-queue-control/src/control-plane.js +141 -0
  190. package/packages/agentsam-queue-control/src/dispatch.js +43 -0
  191. package/packages/agentsam-queue-control/src/index.js +7 -0
  192. package/packages/agentsam-queue-control/src/policy.js +88 -0
  193. package/packages/agentsam-queue-control/src/topology.js +66 -0
  194. package/packages/agentsam-queue-control/test/queue-control.test.mjs +100 -0
  195. package/packages/agentsam-repository/src/goap.js +718 -0
  196. package/packages/agentsam-repository/src/goap.js.bak-20260922011251 +670 -0
  197. package/packages/agentsam-repository/src/index.js +5 -0
  198. package/packages/agentsam-repository/src/merkle/cloudflare-persistence.js +2 -2
  199. package/packages/agentsam-repository/src/tickets.js +184 -0
  200. package/packages/agentsam-repository/src/work-tracking.js +199 -0
  201. package/packages/agentsam-repository/src/workspace-state.js +176 -0
  202. package/packages/agentsam-repository/test/goap-tickets-workspace-state.test.mjs +152 -0
  203. package/packages/connectors/cloudflare/src/index.js +297 -15
  204. package/packages/connectors/cloudflare/src/owner.js +43 -40
  205. package/packages/connectors/cloudflare/src/routes.js +176 -26
  206. package/packages/connectors/cloudflare/tests/connector.test.mjs +137 -2
  207. package/packages/heuristic-theme/README.md +11 -0
  208. package/packages/heuristic-theme/package.json +25 -0
  209. package/packages/heuristic-theme/src/index.js +2 -0
  210. package/packages/heuristic-theme/src/registry.js +36 -0
  211. package/packages/heuristic-theme/src/theme.js +41 -0
  212. package/packages/heuristic-theme/test/theme.test.mjs +26 -0
  213. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +64 -0
  214. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +96 -0
  215. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +47 -0
  216. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +83 -0
  217. package/packages/identity/.agentsam/features/oauth-login-portal/ui.json +35 -0
  218. package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
  219. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
  220. package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
  221. package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
  222. package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
  223. package/packages/identity/package.json +4 -3
  224. package/packages/identity/src/adapters/cloudflare-d1/ids.js +4 -0
  225. package/packages/identity/src/adapters/cloudflare-d1/index.js +156 -18
  226. package/packages/identity/src/adapters/sqlite/index.js +319 -0
  227. package/packages/identity/src/app/verify-app.js +95 -0
  228. package/packages/identity/src/contracts/identity-store.js +115 -0
  229. package/packages/identity/src/contracts/provider.js +3 -2
  230. package/packages/identity/src/contracts/route-ids.js +30 -0
  231. package/packages/identity/src/contracts/route-projection.js +218 -0
  232. package/packages/identity/src/contracts/routes.js +11 -0
  233. package/packages/identity/src/core/browser-paths.js +4 -5
  234. package/packages/identity/src/core/constants.js +13 -8
  235. package/packages/identity/src/core/session-policy.js +32 -0
  236. package/packages/identity/src/frontend/auth-portal/pages/login.html +16 -9
  237. package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
  238. package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
  239. package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
  240. package/packages/identity/src/index.js +27 -0
  241. package/packages/identity/src/oauth/README.md +10 -4
  242. package/packages/identity/src/oauth/credentials.js +31 -11
  243. package/packages/identity/src/oauth/finalize-inbound.js +1 -1
  244. package/packages/identity/src/oauth/iam-platform.js +13 -12
  245. package/packages/identity/src/oauth/redirect-paths.js +27 -36
  246. package/packages/identity/src/providers/cloudflare/index.js +19 -0
  247. package/packages/identity/src/providers/cloudflare/mapper.js +21 -0
  248. package/packages/identity/src/providers/cloudflare/oauth.js +48 -0
  249. package/packages/identity/src/providers/cloudflare/profile.js +28 -0
  250. package/packages/identity/src/providers/index.js +18 -2
  251. package/packages/identity/src/server/identity-service.js +35 -8
  252. package/packages/identity/src/server/mount-policy.js +30 -0
  253. package/packages/identity/src/server/post-auth.js +79 -0
  254. package/packages/identity/src/server/worker-router.js +153 -66
  255. package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
  256. package/packages/identity/tests/iam-provider.test.mjs +1 -1
  257. package/packages/identity/tests/identity-service.test.mjs +47 -1
  258. package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
  259. package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
  260. package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
  261. package/packages/providers/completeful/README.md +38 -0
  262. package/packages/providers/completeful/package.json +29 -0
  263. package/packages/providers/completeful/src/client.js +162 -0
  264. package/packages/providers/completeful/src/events.js +49 -0
  265. package/packages/providers/completeful/src/index.js +22 -0
  266. package/packages/providers/completeful/src/tools.js +579 -0
  267. package/packages/providers/completeful/src/webhooks.js +55 -0
  268. package/packages/providers/completeful/test/provider.test.mjs +196 -0
  269. package/packages/theme-church-site/README.md +10 -0
  270. package/packages/theme-church-site/package.json +31 -0
  271. package/packages/theme-church-site/src/harvest.json +14 -0
  272. package/packages/theme-church-site/src/index.js +85 -0
  273. package/packages/theme-church-site/test/theme.test.mjs +19 -0
  274. package/packages/theme-companions-site/README.md +10 -0
  275. package/packages/theme-companions-site/package.json +31 -0
  276. package/packages/theme-companions-site/src/harvest.json +12 -0
  277. package/packages/theme-companions-site/src/index.js +83 -0
  278. package/packages/theme-companions-site/test/theme.test.mjs +19 -0
  279. package/packages/theme-floors-site/README.md +10 -0
  280. package/packages/theme-floors-site/package.json +31 -0
  281. package/packages/theme-floors-site/src/harvest.json +14 -0
  282. package/packages/theme-floors-site/src/index.js +83 -0
  283. package/packages/theme-floors-site/test/theme.test.mjs +19 -0
  284. package/packages/theme-fuelnfree-site/README.md +10 -0
  285. package/packages/theme-fuelnfree-site/package.json +31 -0
  286. package/packages/theme-fuelnfree-site/src/harvest.json +13 -0
  287. package/packages/theme-fuelnfree-site/src/index.js +82 -0
  288. package/packages/theme-fuelnfree-site/test/theme.test.mjs +19 -0
  289. package/packages/theme-handyman-site/README.md +10 -0
  290. package/packages/theme-handyman-site/package.json +31 -0
  291. package/packages/theme-handyman-site/src/harvest.json +10 -0
  292. package/packages/theme-handyman-site/src/index.js +84 -0
  293. package/packages/theme-handyman-site/test/theme.test.mjs +19 -0
  294. package/packages/theme-insurance-site/README.md +10 -0
  295. package/packages/theme-insurance-site/package.json +31 -0
  296. package/packages/theme-insurance-site/src/harvest.json +10 -0
  297. package/packages/theme-insurance-site/src/index.js +84 -0
  298. package/packages/theme-insurance-site/test/theme.test.mjs +19 -0
  299. package/packages/theme-shinshu-site/README.md +10 -0
  300. package/packages/theme-shinshu-site/package.json +31 -0
  301. package/packages/theme-shinshu-site/src/harvest.json +12 -0
  302. package/packages/theme-shinshu-site/src/index.js +84 -0
  303. package/packages/theme-shinshu-site/test/theme.test.mjs +19 -0
  304. package/packages/work-graph/README.md +49 -0
  305. package/packages/work-graph/package.json +19 -0
  306. package/packages/work-graph/prototype/README.md +32 -0
  307. package/packages/work-graph/prototype/data/demo-workgraph.js +47 -0
  308. package/packages/work-graph/prototype/renderers/timeline-model.js +21 -0
  309. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +38 -0
  310. package/packages/work-graph/prototype-gnantt.html +655 -0
  311. package/packages/work-graph/src/adapters/business/projects.js +23 -0
  312. package/packages/work-graph/src/adapters/engineering/git.js +22 -0
  313. package/packages/work-graph/src/adapters/engineering/mcp.js +22 -0
  314. package/packages/work-graph/src/index.js +76 -0
  315. package/packages/work-graph/src/renderers/gantt-model.js +11 -0
  316. package/packages/work-graph/src/renderers/timeline.js +16 -0
  317. package/packages/work-graph/test/work-graph.test.mjs +37 -0
  318. package/protocol/README.md +12 -0
  319. package/protocol/apps/agentsam.app.v1.schema.json +51 -0
  320. package/protocol/brand/brandpack.v1.schema.json +43 -0
  321. package/protocol/capabilities/cloudflare-cpu-audit-input.schema.json +30 -6
  322. package/protocol/capabilities/cloudflare-cpu-profile-input.schema.json +18 -4
  323. package/protocol/capabilities/cloudflare-wrangler-native-input.schema.json +59 -10
  324. package/protocol/capabilities/knowledge-search-input.schema.json +35 -0
  325. package/protocol/capabilities/manifest.json +163 -1
  326. package/protocol/capabilities/repository-audit-input.schema.json +39 -6
  327. package/protocol/capabilities/repository-snapshot-input.schema.json +15 -3
  328. package/protocol/capabilities/terminal-exec-input.schema.json +55 -0
  329. package/protocol/commerce/catalog.v1.json +50 -0
  330. package/protocol/credentials/issue.v1.schema.json +38 -0
  331. package/protocol/database/connection.v1.schema.json +41 -0
  332. package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
  333. package/protocol/errors/error-catalog.json +164 -0
  334. package/protocol/errors/error-envelope.schema.json +678 -0
  335. package/protocol/errors/recovery.v1.schema.json +50 -0
  336. package/protocol/features/README.md +57 -0
  337. package/protocol/features/agentsam.feature.v1.schema.json +290 -0
  338. package/protocol/features/catalog.json +65 -0
  339. package/protocol/features/examples/provider-resend.feature.json +17 -0
  340. package/protocol/go/agentsam-go-runtime.v1.json +17 -0
  341. package/protocol/knowledge/LIFECYCLE.md +140 -0
  342. package/protocol/knowledge/README.md +4 -0
  343. package/protocol/presets/catalog.json +128 -19
  344. package/protocol/rpc/v1/errors.proto +24 -0
  345. package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
  346. package/protocol/sam/activity.v1.schema.json +48 -0
  347. package/protocol/sam/answer.v1.schema.json +35 -0
  348. package/protocol/sam/calibration.v1.schema.json +21 -0
  349. package/protocol/sam/decision-receipt.v1.schema.json +29 -0
  350. package/protocol/sam/evaluation.v1.schema.json +19 -0
  351. package/protocol/sam/operation.schema.json +66 -0
  352. package/protocol/sam/outcome.v1.schema.json +36 -0
  353. package/protocol/sam/question.v1.schema.json +26 -0
  354. package/protocol/sam/registry.seed.json +153 -0
  355. package/protocol/sam/result.schema.json +53 -0
  356. package/protocol/sam/state.v1.schema.json +23 -0
  357. package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
  358. package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
  359. package/protocol/theme-refinery/d1-reconciliation.md +48 -0
  360. package/protocol/theme-refinery/product-metadata.schema.json +27 -0
  361. package/protocol/theme-refinery/receipts/products-registry-batch-20260924.json +318 -0
  362. package/protocol/theme-refinery/receipts/theme-harvest-20260924.json +472 -0
  363. package/protocol/theme-refinery/reconciliation-receipt.schema.json +83 -0
  364. package/protocol/ui/icon-registry.mjs +226 -0
  365. package/protocol/ui/icon.v1.schema.json +51 -0
  366. package/services/cad/server.py +249 -2
  367. package/skills/README.md +22 -9
  368. package/skills/agentsam-codebaseindex/SKILL.md +225 -0
  369. package/skills/catalog.json +14 -0
  370. package/src/agent/capability-adapter.js +15 -5
  371. package/src/agent/index.js +2 -1
  372. package/src/agent/model-turn.js +51 -0
  373. package/src/agent/responses-runner.js +304 -38
  374. package/src/capabilities/index.js +1 -0
  375. package/src/capabilities/terminal-exec.js +78 -0
  376. package/src/cli/command-catalog.js +130 -0
  377. package/src/cli/dispatch.js +48 -0
  378. package/src/cli.js +160 -10
  379. package/src/cloudflare/index.js +6 -0
  380. package/src/cloudflare/runtime-status.js +393 -0
  381. package/src/cloudflare/wrangler.js +17 -1
  382. package/src/commands/api-key.js +244 -0
  383. package/src/commands/app.js +138 -0
  384. package/src/commands/autorag.js +77 -0
  385. package/src/commands/brand.js +291 -0
  386. package/src/commands/cad.js +1 -0
  387. package/src/commands/codebaseindex.js +688 -0
  388. package/src/commands/connections.js +126 -29
  389. package/src/commands/context-economics.js +8 -0
  390. package/src/commands/db.js +7 -0
  391. package/src/commands/env.js +155 -27
  392. package/src/commands/eval.js +209 -14
  393. package/src/commands/go.js +678 -0
  394. package/src/commands/goap.js +176 -0
  395. package/src/commands/identity-init.js +27 -3
  396. package/src/commands/identity-protocol.js +195 -0
  397. package/src/commands/interaction-clack.js +115 -0
  398. package/src/commands/knowledge.js +64 -5
  399. package/src/commands/mcp.js +341 -0
  400. package/src/commands/merkle-persist.js +3 -1
  401. package/src/commands/merkle.js +18 -3
  402. package/src/commands/models.js +110 -24
  403. package/src/commands/plugins.js +175 -0
  404. package/src/commands/preferences.js +28 -8
  405. package/src/commands/product.js +53 -10
  406. package/src/commands/providers.js +173 -44
  407. package/src/commands/resume.js +9 -5
  408. package/src/commands/runtime-status.js +154 -0
  409. package/src/commands/shell.js +508 -56
  410. package/src/commands/skill.js +248 -0
  411. package/src/commands/skills.js +1 -1
  412. package/src/commands/start-local.js +4 -0
  413. package/src/commands/status.js +82 -7
  414. package/src/commands/tunnel.js +228 -195
  415. package/src/commands/whoami.js +156 -12
  416. package/src/context/budget.js +6 -0
  417. package/src/context/index.js +2 -1
  418. package/src/context/project-card.js +75 -0
  419. package/src/errors/contract.js +34 -211
  420. package/src/errors/diagnostic.js +95 -51
  421. package/src/errors/index.js +6 -13
  422. package/src/eval/index.js +6 -0
  423. package/src/eval/live.js +439 -0
  424. package/src/features/resolve.js +242 -0
  425. package/src/go/build.js +298 -0
  426. package/src/go/cloudflare.js +608 -0
  427. package/src/go/container.js +120 -0
  428. package/src/go/contract.js +144 -0
  429. package/src/go/discover.js +212 -0
  430. package/src/go/index.js +25 -0
  431. package/src/go/native-probe-runner.mjs +119 -0
  432. package/src/go/official-registry.js +280 -0
  433. package/src/go/official-release.js +10 -0
  434. package/src/go/receipts.js +144 -0
  435. package/src/go/verify.js +38 -0
  436. package/src/index.js +127 -1
  437. package/src/indexing/ingest/discover-models.js +298 -0
  438. package/src/indexing/ingest/inventory.js +243 -0
  439. package/src/indexing/ingest/job-graph.js +181 -0
  440. package/src/indexing/ingest/materials.js +210 -0
  441. package/src/knowledge/config.js +13 -5
  442. package/src/knowledge/engine.js +23 -8
  443. package/src/knowledge/index.js +1 -0
  444. package/src/knowledge/lane-registry.js +46 -0
  445. package/src/knowledge/providers/gemini.js +48 -8
  446. package/src/knowledge/service/client.js +13 -1
  447. package/src/knowledge/service/grpc-codec.js +156 -53
  448. package/src/knowledge/service/job-engine.js +133 -11
  449. package/src/knowledge/service/job-worker.js +34 -5
  450. package/src/knowledge/service/server.js +10 -1
  451. package/src/knowledge/store-discovery.js +77 -0
  452. package/src/lib/account-session.js +8 -2
  453. package/src/lib/agent-instructions.js +3 -0
  454. package/src/lib/auth.js +7 -3
  455. package/src/lib/cad/blender.js +42 -3
  456. package/src/lib/cad/d1-project-store.js +43 -0
  457. package/src/lib/cad/discovery.js +616 -0
  458. package/src/lib/cad/docker-executor.js +352 -0
  459. package/src/lib/cad/freecad.js +253 -0
  460. package/src/lib/cad/index.js +40 -0
  461. package/src/lib/cad/openscad.js +198 -0
  462. package/src/lib/cad/project-cli.d.ts +2 -0
  463. package/src/lib/cad/project-cli.js +21 -0
  464. package/src/lib/cad/project-contract.d.ts +3 -0
  465. package/src/lib/cad/project-contract.js +1 -0
  466. package/src/lib/cad/project-recipe.js +30 -0
  467. package/src/lib/cad/project-runtime.d.ts +2 -0
  468. package/src/lib/cad/project-runtime.js +53 -0
  469. package/src/lib/cad/project-store.js +25 -0
  470. package/src/lib/cad/project-workflows.js +31 -0
  471. package/src/lib/cad-docker.js +21 -2
  472. package/src/lib/cli-preferences.js +17 -2
  473. package/src/lib/core-client.js +37 -18
  474. package/src/lib/deploy/local-studio.js +6 -5
  475. package/src/lib/dockerize.js +3 -0
  476. package/src/lib/execution-approvals.js +1 -0
  477. package/src/lib/identity-scaffold.js +4 -1
  478. package/src/lib/knowledge-docker.js +9 -1
  479. package/src/lib/local-sessions.js +124 -34
  480. package/src/lib/local-status.js +35 -14
  481. package/src/lib/project-config.js +9 -0
  482. package/src/lib/provider-credentials.js +136 -32
  483. package/src/lib/scaffold/resolve-cloudflare-account.js +37 -0
  484. package/src/lib/scaffold/wizards/cms.js +2 -8
  485. package/src/lib/scaffold/wizards/worker-api.js +2 -8
  486. package/src/lib/slash-commands.js +10 -2
  487. package/src/local/migrations.js +109 -1
  488. package/src/local/runtime-store.js +31 -5
  489. package/src/local/sqlite.js +36 -1
  490. package/src/local-fs/capability.js +121 -0
  491. package/src/local-fs/freshness.js +75 -0
  492. package/src/local-fs/index.js +385 -0
  493. package/src/local-fs/paths.js +100 -0
  494. package/src/local-pty/server.js +295 -19
  495. package/src/mcp/authority.js +348 -0
  496. package/src/mcp/client-adapters.js +431 -0
  497. package/src/mcp/client.js +172 -0
  498. package/src/mcp/index.js +47 -0
  499. package/src/mcp/telemetry.js +103 -0
  500. package/src/models/ai-access-onboarding.js +112 -0
  501. package/src/models/catalog.js +329 -51
  502. package/src/models/discovery.js +34 -6
  503. package/src/models/index.js +2 -0
  504. package/src/models/inventory-core.js +190 -0
  505. package/src/models/policy.js +20 -0
  506. package/src/plugins/cloudflare.js +103 -0
  507. package/src/plugins/completeful.js +69 -0
  508. package/src/plugins/contracts.js +86 -0
  509. package/src/plugins/index.js +11 -0
  510. package/src/plugins/registry.js +207 -0
  511. package/src/plugins/resource-scope.js +45 -0
  512. package/src/plugins/runtime.js +118 -0
  513. package/src/plugins/vectorize.js +31 -0
  514. package/src/progression/engine.js +171 -0
  515. package/src/progression/index.js +1 -0
  516. package/src/providers/cloudflare-chat.js +1 -1
  517. package/src/providers/gemini-generate-content.js +2 -1
  518. package/src/providers/openai-responses.js +45 -16
  519. package/src/providers/tool-schema.js +85 -0
  520. package/src/repository/index.js +29 -0
  521. package/src/rpc/generated/errors_pb.js +961 -1
  522. package/src/sam/activity/index.js +183 -0
  523. package/src/sam/client.js +252 -0
  524. package/src/sam/decision/calibration.js +109 -0
  525. package/src/sam/decision/confidence.js +126 -0
  526. package/src/sam/decision/evaluate.js +157 -0
  527. package/src/sam/decision/evaluators/deterministic.js +341 -0
  528. package/src/sam/decision/evaluators/heuristic.js +61 -0
  529. package/src/sam/decision/evaluators/select.js +50 -0
  530. package/src/sam/decision/evaluators/semantic.js +149 -0
  531. package/src/sam/decision/hierarchical.js +61 -0
  532. package/src/sam/decision/index.js +53 -0
  533. package/src/sam/decision/policy.js +86 -0
  534. package/src/sam/decision/questions.js +120 -0
  535. package/src/sam/decision/receipt.js +148 -0
  536. package/src/sam/decision/state.js +117 -0
  537. package/src/sam/decision/types.js +22 -0
  538. package/src/sam/decision/validate.js +200 -0
  539. package/src/sam/define.js +51 -0
  540. package/src/sam/index.js +65 -0
  541. package/src/sam/operations/brand-scan.js +62 -0
  542. package/src/sam/operations/cad-blender-inspect.js +36 -0
  543. package/src/sam/operations/codebaseindex-ingest.js +49 -0
  544. package/src/sam/operations/decision-evaluate.js +59 -0
  545. package/src/sam/operations/planning-astar.js +77 -0
  546. package/src/sam/operations/planning-goap.js +60 -0
  547. package/src/sam/operations/repository-inspect.js +72 -0
  548. package/src/sam/operations/security-scan.js +33 -0
  549. package/src/sam/operations/terminal-exec.js +29 -0
  550. package/src/sam/planning/astar.js +311 -0
  551. package/src/sam/planning/goap.js +177 -0
  552. package/src/sam/planning/index.js +21 -0
  553. package/src/sam/planning/state.js +84 -0
  554. package/src/sam/registry.js +48 -0
  555. package/src/sam/result.js +77 -0
  556. package/src/sam/seed.js +44 -0
  557. package/src/sam/types.js +91 -0
  558. package/src/security/local-vault.js +415 -0
  559. package/src/security/process.js +20 -4
  560. package/src/skills/catalog.js +64 -0
  561. package/src/skills/content-resolver.js +124 -0
  562. package/src/skills/hosted-store.js +37 -0
  563. package/src/skills/index.js +29 -64
  564. package/src/skills/interaction.js +102 -0
  565. package/src/skills/local-store.js +228 -0
  566. package/src/skills/manifest.js +104 -0
  567. package/src/skills/metrics.js +31 -0
  568. package/src/skills/registry.js +184 -0
  569. package/src/skills/runtime.js +287 -0
  570. package/src/skills/slash.js +44 -0
  571. package/src/status/actions.js +192 -0
  572. package/src/tools/hydrate.js +5 -1
  573. package/src/tools/index.js +7 -0
  574. package/src/tools/redact.js +64 -0
  575. package/src/tools/registry.js +83 -0
  576. package/src/tools/runtime.js +257 -0
  577. package/src/tools/search.js +21 -8
  578. package/src/ui/ansi.js +117 -3
  579. package/src/ui/cli/activity.js +76 -7
  580. package/src/ui/cli/footer.js +110 -9
  581. package/src/ui/cli/help.js +96 -96
  582. package/src/ui/wireframes.js +166 -0
  583. package/test/account-session.test.mjs +28 -0
  584. package/test/apps-scaffold-contract.test.mjs +16 -1
  585. package/test/capabilities.test.mjs +1 -1
  586. package/test/cli/api-key-env-whoami.test.mjs +129 -0
  587. package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
  588. package/test/cli/eval-live.test.mjs +219 -0
  589. package/test/cli/go.test.mjs +128 -0
  590. package/test/cli/local-vault-and-provider-setup.test.mjs +268 -0
  591. package/test/cli/mcp-client.test.mjs +245 -0
  592. package/test/cli/runtime-ui.test.mjs +69 -2
  593. package/test/cli/skill-npm-and-env.test.mjs +52 -0
  594. package/test/cli/status-actions.test.mjs +88 -0
  595. package/test/cli/wireframes-go-registry.test.mjs +139 -0
  596. package/test/cloudflare-connector.test.mjs +3 -6
  597. package/test/cloudflare-runtime.test.mjs +8 -1
  598. package/test/context.test.mjs +15 -0
  599. package/test/error-diagnostics.test.mjs +9 -0
  600. package/test/fixtures/cad/courtyard-house.json +208 -0
  601. package/test/go/build-source-identity.test.mjs +31 -0
  602. package/test/go/cloudflare-probe.test.mjs +317 -0
  603. package/test/go/distribution.test.mjs +28 -0
  604. package/test/integration/ai-access-onboarding.test.mjs +47 -0
  605. package/test/integration/app-command.test.mjs +55 -0
  606. package/test/integration/cad-discovery.test.mjs +158 -0
  607. package/test/integration/cad-docker-executor.test.mjs +249 -0
  608. package/test/integration/cad-execution.test.mjs +184 -0
  609. package/test/integration/cad-project-app.test.mjs +31 -0
  610. package/test/integration/cad-project-d1.test.mjs +25 -0
  611. package/test/integration/cad-project-native.test.mjs +24 -0
  612. package/test/integration/cad-project-workflow.test.mjs +9 -0
  613. package/test/integration/cad-project.test.mjs +82 -0
  614. package/test/integration/cli-help.test.mjs +5 -1
  615. package/test/integration/cms-site-tenancy-contract.test.mjs +256 -0
  616. package/test/integration/codebaseindex-ingest.test.mjs +166 -0
  617. package/test/integration/core-client.integration.test.mjs +55 -0
  618. package/test/integration/error-runtime-rpc.test.mjs +71 -0
  619. package/test/integration/features-resolve.test.mjs +128 -0
  620. package/test/integration/icon-registry.test.mjs +67 -0
  621. package/test/integration/ingest-discover-models.test.mjs +30 -0
  622. package/test/integration/install-script.test.mjs +110 -0
  623. package/test/integration/inventory-core.test.mjs +53 -0
  624. package/test/integration/local-fs.test.mjs +113 -0
  625. package/test/integration/plugins-cloudflare.integration.test.mjs +28 -0
  626. package/test/integration/provider-env-cli.test.mjs +3 -2
  627. package/test/integration/runtime-migrations.test.mjs +6 -1
  628. package/test/integration/runtime-status.integration.test.mjs +211 -0
  629. package/test/integration/sam-activity-recovery.test.mjs +147 -0
  630. package/test/integration/sam-decision.test.mjs +584 -0
  631. package/test/integration/sam-kernel.test.mjs +99 -0
  632. package/test/integration/sam-planning-astar.test.mjs +279 -0
  633. package/test/integration/scaffold-cloudflare.test.mjs +46 -0
  634. package/test/integration/skill-runtime.test.mjs +240 -0
  635. package/test/integration/storage-architecture.test.mjs +154 -0
  636. package/test/integration/store-discovery.test.mjs +44 -0
  637. package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
  638. package/test/integration/terminal-exec.integration.test.mjs +86 -0
  639. package/test/integration/tool-runtime.test.mjs +124 -0
  640. package/test/integration/tool-schema.test.mjs +59 -0
  641. package/test/knowledge-service.test.mjs +4 -0
  642. package/test/local-sessions.test.mjs +11 -2
  643. package/test/local-studio-deploy.test.mjs +1 -1
  644. package/test/model-catalog.test.mjs +28 -1
  645. package/test/models.test.mjs +172 -11
  646. package/test/openai-responses.test.mjs +60 -0
  647. package/test/provider-credentials.test.mjs +15 -5
  648. package/test/responses-runner.test.mjs +321 -6
  649. package/test/shell.test.mjs +151 -6
  650. package/test/smoke.mjs +2 -2
  651. package/test/tools-search.test.mjs +33 -0
  652. package/test/unit/website-assets-bindings.test.mjs +60 -0
  653. package/test/whoami-resume.test.mjs +82 -3
  654. package/examples/gorilla-shell/README.md +0 -15
  655. package/src/lib/gorilla-template.js +0 -54
  656. package/templates/gorilla-shell/App.tsx +0 -639
  657. package/templates/gorilla-shell/README.md +0 -34
  658. package/templates/gorilla-shell/index.html +0 -15
  659. package/templates/gorilla-shell/main.jsx +0 -9
  660. package/templates/gorilla-shell/package.json +0 -19
  661. package/templates/gorilla-shell/vite.config.js +0 -21
@@ -13,25 +13,38 @@ import { runModels } from './models.js';
13
13
  import { runProviders } from './providers.js';
14
14
  import { configureCliPreferences } from './preferences.js';
15
15
  import { runCloudflare } from './cloudflare.js';
16
+ import { runConnections } from './connections.js';
17
+ import { runTunnel } from './tunnel.js';
16
18
  import { probeOllamaModel, resolveOllamaConfig } from './ollama.js';
17
19
  import { createInlineActivity } from '../ui/cli/activity.js';
18
20
  import { createCliRuntimePresenter } from '../ui/cli/runtime-events.js';
19
- import { renderCliFooter } from '../ui/cli/footer.js';
21
+ import { renderCliFooter, renderDiffPreview, renderUsagePanel } from '../ui/cli/footer.js';
20
22
  import { diagnosticFromError, renderDiagnosticError } from '../errors/index.js';
21
- import { getModelRecord } from '../models/index.js';
23
+ import { getModelRecord, mergeModelReference, listModelCatalog } from '../models/index.js';
22
24
  import { discoverProviderModels } from '../models/discovery.js';
23
- import { readCliPreferences, updateCliPreferences } from '../lib/cli-preferences.js';
25
+ import { detectCliProject, findCliProjectRoot, readCliPreferences, updateCliPreferences } from '../lib/cli-preferences.js';
24
26
  import { buildContextEconomicsReport, renderContextEconomics } from './context-economics.js';
25
27
  import { createProviderAdapter } from '../providers/index.js';
26
28
  import { createCapabilityAdapter, runResponsesAgent } from '../agent/index.js';
27
29
  import { resolveProviderCredential } from '../lib/provider-credentials.js';
28
- import { createLocalSession, saveLocalSession, sessionTitleFromInput, localSessionElapsedMs } from '../lib/local-sessions.js';
30
+ import { createLocalSession, saveLocalSession, localSessionElapsedMs, loadSessionContinuation } from '../lib/local-sessions.js';
31
+ import { runtimeDatabasePath } from '../local/runtime-store.js';
29
32
  import { grantExecutionApproval, isExecutionApproved, toolApprovalKey } from '../lib/execution-approvals.js';
30
33
  import { runWhoami } from './whoami.js';
31
34
  import { runLogin, runLogout } from './account-auth.js';
32
35
  import { runHelp } from '../ui/cli/help.js';
36
+ import { hydrateSecureCredentials } from '../security/local-vault.js';
33
37
  import { readAccountSession } from '../lib/account-session.js';
34
38
  import { startRuntimeRun, finishRuntimeRun, recordRuntimeCompaction } from '../local/runtime-store.js';
39
+ import { tryResolveGitContext } from '../../packages/agentsam-repository/src/git-context.js';
40
+ import { syncWorkspaceStateToD1, readWorkspaceStateFromD1 } from '../../packages/agentsam-repository/src/workspace-state.js';
41
+ import { syncGitCommitsToD1 } from '../../packages/agentsam-repository/src/work-tracking.js';
42
+ import { readGoapState, listGoapTickets, createGoapGoal, switchGoapGoal, closeGoapGoal, renderGoapStatus, renderGoapList, renderGoapGoal, renderGoapWhy, renderGoapPlan } from '../../packages/agentsam-repository/src/goap.js';
43
+ import { SkillRegistry, SkillRuntime, SkillContentResolver } from '../skills/index.js';
44
+ import {
45
+ presentAgentSamInteraction,
46
+ handleSkillInteractionChoice,
47
+ } from './interaction-clack.js';
35
48
 
36
49
  function writeLine(write, value = '') { write(`${value}\n`); }
37
50
 
@@ -54,6 +67,134 @@ export function renderShellPrompt(cwd, env = process.env) {
54
67
  return `${shellUsername(env)} ${compactCwd(cwd, env.HOME || env.USERPROFILE || '')} > `;
55
68
  }
56
69
 
70
+ export const PASTE_COLLAPSE_LINE_THRESHOLD = 5;
71
+ export const PASTE_COLLAPSE_CHAR_THRESHOLD = 300;
72
+ const BRACKETED_PASTE_START = '\x1b[200~';
73
+ const BRACKETED_PASTE_END = '\x1b[201~';
74
+ const BRACKETED_PASTE_ENABLE = '\x1b[?2004h';
75
+ const BRACKETED_PASTE_DISABLE = '\x1b[?2004l';
76
+
77
+ export function countPasteLines(text) {
78
+ const source = String(text ?? '').replace(/\r\n/g, '\n').replace(/\r/g, '\n');
79
+ if (!source) return 0;
80
+ const parts = source.split('\n');
81
+ if (parts[parts.length - 1] === '') parts.pop();
82
+ return Math.max(parts.length, source ? 1 : 0);
83
+ }
84
+
85
+ export function shouldCollapsePaste(text) {
86
+ const source = String(text ?? '');
87
+ return countPasteLines(source) > PASTE_COLLAPSE_LINE_THRESHOLD || source.length > PASTE_COLLAPSE_CHAR_THRESHOLD;
88
+ }
89
+
90
+ export function renderCollapsedPaste(text) {
91
+ return `[Pasted ${countPasteLines(text)} lines — Enter to run, Backspace to clear]`;
92
+ }
93
+
94
+ export function installPasteCollapse(rl, options = {}) {
95
+ if (!rl || rl.terminal === false || typeof rl._ttyWrite !== 'function') return () => {};
96
+ const original = rl._ttyWrite.bind(rl);
97
+ let collapsed = null;
98
+ let collecting = '';
99
+ let inPaste = false;
100
+
101
+ function refresh(line) {
102
+ rl.line = line;
103
+ rl.cursor = line.length;
104
+ if (typeof rl._refreshLine === 'function') rl._refreshLine();
105
+ }
106
+
107
+ function showCollapsed(text) {
108
+ collapsed = text;
109
+ refresh(renderCollapsedPaste(text));
110
+ }
111
+
112
+ function consumePaste(body) {
113
+ inPaste = false;
114
+ collecting = '';
115
+ if (shouldCollapsePaste(body)) {
116
+ showCollapsed(body);
117
+ return true;
118
+ }
119
+ original(body);
120
+ return true;
121
+ }
122
+
123
+ rl._ttyWrite = (s, key) => {
124
+ const str = s == null ? '' : String(s);
125
+
126
+ if (str.includes(BRACKETED_PASTE_START) || key?.name === 'paste-start') {
127
+ inPaste = true;
128
+ collecting = str.replace(BRACKETED_PASTE_START, '');
129
+ if (collecting.includes(BRACKETED_PASTE_END) || key?.name === 'paste-end') {
130
+ return consumePaste(collecting.replace(BRACKETED_PASTE_END, ''));
131
+ }
132
+ return undefined;
133
+ }
134
+ if (inPaste) {
135
+ collecting += str;
136
+ if (collecting.includes(BRACKETED_PASTE_END) || key?.name === 'paste-end') {
137
+ return consumePaste(collecting.replace(BRACKETED_PASTE_END, ''));
138
+ }
139
+ return undefined;
140
+ }
141
+
142
+ if (collapsed) {
143
+ if (key?.name === 'backspace' || key?.name === 'delete') {
144
+ collapsed = null;
145
+ refresh('');
146
+ return undefined;
147
+ }
148
+ if (key?.name === 'return' || key?.name === 'enter') {
149
+ const text = collapsed;
150
+ collapsed = null;
151
+ rl.line = text;
152
+ rl.cursor = text.length;
153
+ return original('\n', { name: 'return' });
154
+ }
155
+ }
156
+
157
+ if (str && !key?.name && shouldCollapsePaste(str.replace(/\n$/, ''))) {
158
+ const payload = str.endsWith('\n') ? str.slice(0, -1) : str;
159
+ showCollapsed(payload);
160
+ return undefined;
161
+ }
162
+
163
+ return original(s, key);
164
+ };
165
+
166
+ try { options.output?.write?.(BRACKETED_PASTE_ENABLE); } catch { /* ignore */ }
167
+ return () => {
168
+ rl._ttyWrite = original;
169
+ try { options.output?.write?.(BRACKETED_PASTE_DISABLE); } catch { /* ignore */ }
170
+ };
171
+ }
172
+
173
+ function resolveShellIdentity(state) {
174
+ if (state.identity && state.identityCwd === state.cwd) return state.identity;
175
+ try { state.identity = detectCliProject(state.cwd); }
176
+ catch { state.identity = { project: path.basename(state.cwd || ''), branch: '', root: state.cwd }; }
177
+ state.identityCwd = state.cwd;
178
+ return state.identity;
179
+ }
180
+
181
+ function renderShellSessionFooter(state) {
182
+ const identity = resolveShellIdentity(state);
183
+ const preferences = readCliPreferences(state.cwd) || {};
184
+ return renderCliFooter({
185
+ projectName: identity.project,
186
+ branch: identity.branch,
187
+ cwd: compactCwd(state.cwd),
188
+ model: state.session?.provider_model_id || state.session?.model_key || preferences.modelPreference,
189
+ provider: state.providerState?.provider || state.session?.provider_state?.provider,
190
+ effort: state.session?.reasoning_effort || preferences.reasoningEffort,
191
+ tier: state.session?.actual_service_tier || state.session?.requested_service_tier || preferences.serviceTier,
192
+ usageSnapshot: state.usageSnapshot || state.session?.usage_snapshot,
193
+ elapsedMs: state.lastTurnElapsedMs ?? (state.session ? localSessionElapsedMs(state.session) : undefined),
194
+ action: state.activity?.active ? 'working' : '',
195
+ });
196
+ }
197
+
57
198
  export function tokenizeShellLine(input = '') {
58
199
  const source = String(input);
59
200
  const tokens = [];
@@ -121,9 +262,12 @@ function spawnGit(cwd, args) {
121
262
  function selectedModel(cwd) {
122
263
  const preferences = readCliPreferences(cwd) || {};
123
264
  const snapshot = preferences.modelSnapshot?.model_key === preferences.modelPreference
124
- ? preferences.modelSnapshot
265
+ ? mergeModelReference(preferences.modelSnapshot)
125
266
  : null;
126
- const model = snapshot || getModelRecord(preferences.modelPreference);
267
+ let model = snapshot || getModelRecord(preferences.modelPreference);
268
+ if (!model && (preferences.modelPreference === 'auto' || !preferences.modelPreference)) {
269
+ model = mergeModelReference(preferences.modelSnapshot) || listModelCatalog()[0];
270
+ }
127
271
  if (!model) throw new Error('Select an exact provider-verified model with /model first so Agent Sam can verify supported runtime controls.');
128
272
  return { preferences, model };
129
273
  }
@@ -169,24 +313,32 @@ async function resolveModelForTurn(cwd, state) {
169
313
 
170
314
  async function chooseReasoning(cwd, args, state) {
171
315
  const { preferences, model } = selectedModel(cwd);
316
+ const supported = ['auto', ...model.reasoning_efforts.filter((value) => value !== 'auto')];
172
317
  let effort = String(args[0] || '').trim().toLowerCase();
173
318
  if (!effort) {
174
319
  if (!state.interactive) {
175
- writeLine(state.write, ` ${model.provider_model_id} reasoning: ${model.reasoning_efforts.join(' | ')}`);
176
- writeLine(state.write, ` current: ${preferences.reasoningEffort || 'auto'}`);
320
+ writeLine(state.write, ' ' + model.provider_model_id + ' reasoning: ' + supported.join(' | '));
321
+ writeLine(state.write, ' provider default: ' + (model.default_reasoning_effort || 'unknown'));
322
+ writeLine(state.write, ' current: ' + (preferences.reasoningEffort || 'auto'));
177
323
  return;
178
324
  }
179
325
  const choice = await select({
180
- message: `Reasoning level · ${model.provider_model_id}`,
181
- initialValue: model.reasoning_efforts.includes(preferences.reasoningEffort) ? preferences.reasoningEffort : model.reasoning_efforts[0],
182
- options: model.reasoning_efforts.map((value) => ({ value, label: value === 'xhigh' ? 'Extra high' : value === 'max' ? 'Max' : value[0].toUpperCase() + value.slice(1) })),
326
+ message: 'Reasoning level · ' + model.provider_model_id,
327
+ initialValue: supported.includes(preferences.reasoningEffort) ? preferences.reasoningEffort : 'auto',
328
+ options: supported.map((value) => ({
329
+ value,
330
+ label: value === 'auto' ? 'Automatic' : value === 'xhigh' ? 'Extra high' : value === 'max' ? 'Max' : value[0].toUpperCase() + value.slice(1),
331
+ hint: value === 'auto'
332
+ ? 'omit reasoning.effort · provider default ' + (model.default_reasoning_effort || 'unknown')
333
+ : value === model.default_reasoning_effort ? 'provider default' : undefined,
334
+ })),
183
335
  });
184
336
  if (isCancel(choice)) return;
185
337
  effort = choice;
186
338
  }
187
- if (!model.reasoning_efforts.includes(effort)) throw new Error(`unsupported reasoning level for ${model.provider_model_id}: ${effort}`);
339
+ if (!supported.includes(effort)) throw new Error('unsupported reasoning level for ' + model.provider_model_id + ': ' + effort);
188
340
  updateCliPreferences(cwd, { reasoningEffort: effort });
189
- writeLine(state.write, ` reasoning → ${effort}`);
341
+ writeLine(state.write, ' reasoning → ' + effort);
190
342
  }
191
343
 
192
344
  function setServiceTier(cwd, tier, write) {
@@ -241,15 +393,15 @@ export async function runLocalAgent(goal, write, options = {}) {
241
393
  }
242
394
 
243
395
  async function showLocalLogs(cwd, write) {
244
- const dbPath = path.join(cwd, '.agentsam', 'data', 'agentsam.sqlite');
245
- if (!fs.existsSync(dbPath)) { writeLine(write, ' No local Agent Sam DB found. Run `agentsam init . --yes` first.'); return; }
396
+ const dbPath = runtimeDatabasePath(cwd);
397
+ if (!fs.existsSync(dbPath)) { writeLine(write, ' No local Agent Sam runs yet.'); return; }
246
398
  const { createLocalSqliteDatabase } = await import('../local/sqlite.js');
247
399
  const db = await createLocalSqliteDatabase(dbPath);
248
400
  try {
249
- const calls = await db.prepare('SELECT id, session_id, tool_name, status, created_at, completed_at FROM agent_tool_calls ORDER BY created_at DESC LIMIT 20').all();
250
- if (!calls.results.length) { writeLine(write, ' No local Agent Sam tool-call events yet.'); return; }
251
- writeLine(write, '\n Recent Agent Sam tool calls');
252
- for (const row of calls.results) writeLine(write, ` ${String(row.created_at || '').padEnd(20)} ${String(row.status || '').padEnd(10)} ${row.tool_name}`);
401
+ const runs = await db.prepare('SELECT id, model_key, status, started_at_unix FROM agentsam_agent_run ORDER BY started_at_unix DESC LIMIT 20').all();
402
+ if (!runs.results.length) { writeLine(write, ' No local Agent Sam runs yet.'); return; }
403
+ writeLine(write, '\n Recent Agent Sam runs');
404
+ for (const row of runs.results) writeLine(write, ` ${new Date(Number(row.started_at_unix) * 1000).toISOString()} ${String(row.status || '').padEnd(10)} ${row.model_key || 'model unknown'} · ${row.id}`);
253
405
  writeLine(write, '');
254
406
  } finally { db.close(); }
255
407
  }
@@ -300,6 +452,7 @@ export function renderSessionReceipt(session) {
300
452
  if (componentTotal > 0) {
301
453
  lines.push(`Cost breakdown: input ${formatUsd(breakdown.input)} · cached ${formatUsd(breakdown.cached_input)} · cache write ${formatUsd(breakdown.cache_write)} · output ${formatUsd(breakdown.output)}`);
302
454
  }
455
+ if (session.latest_compaction) lines.push(`Latest compaction: ${session.latest_compaction.compaction_id || 'completed'} · ${formatUsd(session.latest_compaction.cost_usd)}`);
303
456
  if (active) lines.push(`Active context: ${formatCount(active)} tokens`);
304
457
  lines.push('', 'To continue this session, run:', ` agentsam resume ${session.id}`, '', 'Or run:', ' agentsam resume', '', 'and select:', ` ${session.title || 'this session'}`, '');
305
458
  return lines.join('\n');
@@ -307,7 +460,7 @@ export function renderSessionReceipt(session) {
307
460
 
308
461
  function persistSession(state, patch = {}) {
309
462
  if (!state.session) return null;
310
- state.session = saveLocalSession({ ...state.session, ...patch }, { home: state.home });
463
+ state.session = saveLocalSession({ ...state.session, ...patch }, { home: state.home, projectRoot: state.projectRoot });
311
464
  return state.session;
312
465
  }
313
466
 
@@ -318,8 +471,6 @@ function recordSessionInput(state, input) {
318
471
  if (housekeeping.has(value.toLowerCase())) return;
319
472
  persistSession(state, {
320
473
  status: 'active',
321
- last_input: value,
322
- title: sessionTitleFromInput(value),
323
474
  });
324
475
  }
325
476
 
@@ -392,6 +543,55 @@ async function approveToolExecution(request, state) {
392
543
  return true;
393
544
  }
394
545
 
546
+ async function runInteractiveCompaction(args, state) {
547
+ if (args.length > 1 || (args.length && args[0] !== 'status')) throw new Error('Usage: /compact [status]');
548
+ const { model } = selectedModel(state.cwd);
549
+ const supported = ['openai', 'grok'].includes(model.provider) && model.capabilities?.compaction === true;
550
+ const report = buildContextEconomicsReport(state.cwd, { activeInputTokens: state.usageSnapshot?.current_context?.input_tokens ?? state.session?.usage_snapshot?.current_context?.input_tokens });
551
+ if (args[0] === 'status') {
552
+ writeLine(state.write, ` Compaction · ${model.provider}/${model.provider_model_id}`);
553
+ writeLine(state.write, ` support ${supported ? 'native' : 'unavailable'}`);
554
+ writeLine(state.write, ` active ${report.active_input_tokens ?? 'unknown'} tokens`);
555
+ writeLine(state.write, ` threshold ${report.compact_at_tokens ?? 'unknown'} tokens`);
556
+ writeLine(state.write, ` automatic ${supported && state.session?.auto_compact !== false ? 'enabled' : 'disabled'}`);
557
+ const receipt = state.session?.latest_compaction;
558
+ writeLine(state.write, ` latest ${receipt ? `${receipt.compaction_id} · ${receipt.created_at} · ${formatUsd(receipt.cost_usd)}` : 'none'}`);
559
+ return;
560
+ }
561
+ if (!supported) throw new Error(`native_compaction_unavailable:${model.provider}`);
562
+ if (!state.session || state.session.model_key !== model.model_key) throw new Error('compaction_active_model_session_required');
563
+ const previous = state.providerState || loadSessionContinuation(state.session);
564
+ if (!previous?.previous_response_id && !previous?.compacted_input?.length && !previous?.compaction_input?.length) throw new Error('compaction_context_unavailable');
565
+ const credential = resolveProviderCredential(model.provider, { home: state.home });
566
+ const provider = createProviderAdapter({ modelRecord: model, credential, fetchImpl: state.providerFetchImpl });
567
+ if (typeof provider.compact !== 'function') throw new Error(`native_compaction_unavailable:${model.provider}`);
568
+ const result = await provider.compact({
569
+ model: model.provider_model_id, modelRecord: model, providerState: previous,
570
+ promptCacheKey: state.session.id,
571
+ tokensBefore: report.active_input_tokens, cumulativeUsage: state.session.cumulative_usage,
572
+ });
573
+ if (!Array.isArray(result.output) || !result.output.length) throw new Error('provider_compaction_output_missing');
574
+ const receipt = checkpointCompaction(state, model, result);
575
+ writeLine(state.write, ` Compacted · ${receipt.compaction_id} · ${formatUsd(receipt.cost_usd)} · continuation saved`);
576
+ }
577
+
578
+ function checkpointCompaction(state, model, result) {
579
+ const delta = result.usage_delta || result.usage || {};
580
+ const cumulative = Object.fromEntries(['input_tokens', 'output_tokens', 'cached_input_tokens', 'cache_write_tokens', 'reasoning_tokens'].map(key => [key, Number(state.session.cumulative_usage?.[key] || 0) + Number(delta[key] || 0)]));
581
+ const providerState = { provider: model.provider, ...(result.provider_state || {}), previous_response_id: null, compacted_input: result.output };
582
+ const usageSnapshot = { current_context: { input_tokens: Math.ceil(JSON.stringify(result.output).length / 4), window_tokens: model.context_window }, cumulative, estimate_kind: 'local' };
583
+ const receipt = { compaction_id: result.compaction_id, provider: model.provider, model: model.provider_model_id, created_at: new Date().toISOString(), usage: delta, cost_usd: result.cost?.total_usd || 0 };
584
+ persistSession(state, {
585
+ provider_state: providerState, usage_snapshot: usageSnapshot, cumulative_usage: cumulative,
586
+ latest_compaction: receipt,
587
+ total_cost_usd: Number(state.session.total_cost_usd || 0) + Number(result.cost?.total_usd || 0),
588
+ cost_breakdown_usd: Object.fromEntries(['input', 'cached_input', 'cache_write', 'output'].map(key => [key, Number(state.session.cost_breakdown_usd?.[key] || 0) + Number(result.cost?.components_usd?.[key] || 0)])),
589
+ });
590
+ state.providerState = providerState;
591
+ state.usageSnapshot = usageSnapshot;
592
+ return receipt;
593
+ }
594
+
395
595
  async function runInteractiveModelTurn(prompt, state) {
396
596
  const resolved = await resolveModelForTurn(state.cwd, state);
397
597
  const { preferences, model, credential } = resolved;
@@ -403,17 +603,15 @@ async function runInteractiveModelTurn(prompt, state) {
403
603
  });
404
604
  const capabilityAdapter = createCapabilityAdapter();
405
605
 
406
- const samePolicy = state.session
407
- && state.session.model_key === model.model_key
408
- && state.session.reasoning_effort === preferences.reasoningEffort
409
- && state.session.requested_service_tier === preferences.serviceTier;
410
- const previousProviderState = samePolicy ? state.session?.provider_state : null;
606
+ // Reasoning/tier changes do not change the provider conversation's owner.
607
+ const samePolicy = state.session && state.session.model_key === model.model_key;
608
+ const previousProviderState = samePolicy ? (state.providerState || loadSessionContinuation(state.session)) : null;
411
609
  const previousUsageSnapshot = samePolicy ? state.session?.usage_snapshot : null;
412
610
  const accountId = readAccountSession({ home: state.home })?.account_id || null;
413
611
  let runtimeRunId = null;
414
612
  try {
415
613
  runtimeRunId = await startRuntimeRun({
416
- cwd: state.cwd,
614
+ projectRoot: state.projectRoot,
417
615
  account_id: accountId,
418
616
  mode: 'agent',
419
617
  model_key: model.model_key,
@@ -431,6 +629,8 @@ async function runInteractiveModelTurn(prompt, state) {
431
629
  });
432
630
  state.activity = activity;
433
631
  const presenter = createCliRuntimePresenter({ activity, write: state.write, state });
632
+ const startingCostUsd = Number(state.session?.total_cost_usd || 0);
633
+ const startingCostBreakdown = { ...state.session?.cost_breakdown_usd };
434
634
  const startedAt = Date.now();
435
635
  activity.start(`Thinking · ${model.provider_model_id}`);
436
636
 
@@ -445,9 +645,17 @@ async function runInteractiveModelTurn(prompt, state) {
445
645
  modelRecord: model,
446
646
  reasoningEffort: preferences.reasoningEffort,
447
647
  serviceTier: preferences.serviceTier,
648
+ // The interactive CLI turn is the main agentic engineering loop, not a
649
+ // one-shot lookup -- the previous unconfigurable default (quick: 8
650
+ // rounds) killed genuine multi-step work for no reason tied to risk,
651
+ // cost, or progress. `agent` (128 rounds) is the right default here;
652
+ // preferences.runMode leaves room for a future explicit override.
653
+ runMode: preferences.runMode || 'agent',
448
654
  previousProviderState,
449
655
  previousUsageSnapshot,
450
656
  cumulativeUsage: state.session?.cumulative_usage || null,
657
+ autoCompact: state.session?.auto_compact !== false,
658
+ onCompaction: result => { if (state.session) checkpointCompaction(state, model, result); },
451
659
  promptCacheKey: state.session?.id || undefined,
452
660
  runId: runtimeRunId || state.session?.id || undefined,
453
661
  beforeRequest: (preflight) => approveModelRequest(preflight, state),
@@ -463,7 +671,7 @@ async function runInteractiveModelTurn(prompt, state) {
463
671
  if (runtimeRunId) {
464
672
  try {
465
673
  await finishRuntimeRun({
466
- cwd: state.cwd,
674
+ projectRoot: state.projectRoot,
467
675
  id: runtimeRunId,
468
676
  status: 'failed',
469
677
  error_code: error?.code || 'interactive_error',
@@ -488,10 +696,12 @@ async function runInteractiveModelTurn(prompt, state) {
488
696
  }
489
697
 
490
698
  state.usageSnapshot = result.usage_snapshot;
699
+ state.providerState = result.provider_state || null;
700
+ state.lastTurnElapsedMs = Date.now() - startedAt;
491
701
  if (runtimeRunId) {
492
702
  try {
493
703
  await finishRuntimeRun({
494
- cwd: state.cwd,
704
+ projectRoot: state.projectRoot,
495
705
  id: runtimeRunId,
496
706
  status: 'completed',
497
707
  actual_service_tier: result.actual_service_tier,
@@ -501,7 +711,7 @@ async function runInteractiveModelTurn(prompt, state) {
501
711
  });
502
712
  if (presenter.state.lastCompaction) {
503
713
  await recordRuntimeCompaction({
504
- cwd: state.cwd,
714
+ projectRoot: state.projectRoot,
505
715
  account_id: accountId,
506
716
  agent_run_id: runtimeRunId,
507
717
  session_id: state.session?.id,
@@ -527,30 +737,66 @@ async function runInteractiveModelTurn(prompt, state) {
527
737
  provider_state: { provider: model.provider, ...(result.provider_state || {}) },
528
738
  usage_snapshot: result.usage_snapshot,
529
739
  cumulative_usage: result.cumulative_usage,
530
- total_cost_usd: Number(state.session.total_cost_usd || 0) + Number(result.total_cost_usd || 0),
740
+ latest_compaction: result.compaction || state.session.latest_compaction,
741
+ total_cost_usd: startingCostUsd + Number(result.total_cost_usd || 0),
531
742
  cost_breakdown_usd: Object.fromEntries(['input', 'cached_input', 'cache_write', 'output'].map((key) => [
532
- key, Number(state.session.cost_breakdown_usd?.[key] || 0) + Number(result.cost_breakdown_usd?.[key] || 0),
743
+ key, Number(startingCostBreakdown[key] || 0) + Number(result.cost_breakdown_usd?.[key] || 0),
533
744
  ])),
534
745
  last_error: null,
535
746
  });
536
747
  }
537
748
 
749
+ const identity = resolveShellIdentity(state);
538
750
  writeLine(state.write, renderCliFooter({
751
+ projectName: identity.project,
752
+ branch: identity.branch,
753
+ cwd: compactCwd(state.cwd),
539
754
  model: result.model || model.provider_model_id,
755
+ provider: model.provider,
756
+ effort: result.reasoning_effort,
540
757
  usageSnapshot: result.usage_snapshot,
541
758
  tier: result.actual_service_tier,
542
- elapsedMs: Date.now() - startedAt,
759
+ elapsedMs: state.lastTurnElapsedMs,
543
760
  }));
544
761
  writeLine(state.write, '');
762
+ state.wroteTurnFooter = true;
545
763
  return result;
546
764
  }
547
765
 
548
766
  export async function dispatchShellLine(line, state = {}) {
549
- const tokens = tokenizeShellLine(line);
767
+ let tokens = tokenizeShellLine(line);
550
768
  const write = state.write || ((text) => process.stdout.write(text));
551
769
  state.write = write;
552
770
  state.cwd = path.resolve(state.cwd || process.cwd());
771
+ state.projectRoot ||= findCliProjectRoot(state.cwd);
553
772
  if (!tokens.length) return { handled: true, exit: false, cwd: state.cwd };
773
+
774
+ // Strip a leading "agentsam" prefix if present -- it should never change
775
+ // whether the rest of the line resolves, only whether it was typed at all.
776
+ if (tokens[0].toLowerCase() === 'agentsam') {
777
+ tokens = tokens.slice(1);
778
+ if (!tokens.length) tokens = ['help'];
779
+ }
780
+
781
+ // Recognized short verbs (with or without a stripped "agentsam" prefix)
782
+ // become their slash command. Anything unrecognized -- typo, a host-CLI-only
783
+ // verb like "merkle" typed here, whatever -- is left as plain text and
784
+ // falls through to the natural-language model turn below. There is no
785
+ // path left that hard-errors on an unrecognized word; "unknown command"
786
+ // only fires for input that explicitly starts with "/".
787
+ if (!tokens[0].startsWith('/')) {
788
+ const bare = tokens[0].toLowerCase();
789
+ const commonVerbs = [
790
+ 'help', 'exit', 'quit', 'clear', 'status', 'models', 'model',
791
+ 'whoami', 'cf', 'cloudflare', 'db', 'tunnel', 'connections',
792
+ 'connect', 'usage', 'session', 'providers', 'settings', 'logs',
793
+ 'git', 'diff', 'pwd', 'cd', 'fast', 'flex', 'standard', 'reasoning',
794
+ ];
795
+ if (commonVerbs.includes(bare)) {
796
+ tokens[0] = `/${bare}`;
797
+ }
798
+ }
799
+
554
800
  const [command, ...args] = tokens;
555
801
  try {
556
802
  switch (command.toLowerCase()) {
@@ -565,8 +811,15 @@ export async function dispatchShellLine(line, state = {}) {
565
811
  case '/quit':
566
812
  return { handled: true, exit: true, cwd: state.cwd };
567
813
  case '/model': {
568
- const configured = await configureCliPreferences({ cwd: state.cwd, firstRun: false, section: 'model', home: state.home });
569
- state.cwd = configured.identity.root;
814
+ state.rl?.pause?.();
815
+ try {
816
+ const configured = await configureCliPreferences({ cwd: state.cwd, firstRun: false, section: 'model', home: state.home });
817
+ state.cwd = configured.identity.root;
818
+ state.projectRoot = findCliProjectRoot(state.cwd);
819
+ } finally {
820
+ if (process.stdin.isPaused()) process.stdin.resume();
821
+ state.rl?.resume?.();
822
+ }
570
823
  break;
571
824
  }
572
825
  case '/reasoning':
@@ -581,21 +834,37 @@ export async function dispatchShellLine(line, state = {}) {
581
834
  case '/standard':
582
835
  setServiceTier(state.cwd, 'default', write);
583
836
  break;
837
+ case '/compact':
838
+ await runInteractiveCompaction(args, state);
839
+ break;
584
840
  case '/context':
585
841
  if (args[0] === 'repo' || args[0] === 'git') await runContext(['--cwd', state.cwd, ...args.slice(1)]);
586
842
  else write(renderContextEconomics(buildContextEconomicsReport(state.cwd, {
587
843
  activeInputTokens: state.usageSnapshot?.current_context?.input_tokens,
588
844
  estimateKind: state.usageSnapshot?.estimate_kind,
845
+ autoCompact: state.session?.auto_compact,
589
846
  })));
590
847
  break;
591
848
  case '/status':
592
849
  await runStatus(args, { cwd: state.cwd });
593
850
  break;
594
851
  case '/models':
595
- await runModels(args, { cwd: state.cwd, write, home: state.home });
852
+ state.rl?.pause?.();
853
+ try {
854
+ await runModels(args, { cwd: state.cwd, write, home: state.home, interactive: state.interactive });
855
+ } finally {
856
+ if (process.stdin.isPaused()) process.stdin.resume();
857
+ state.rl?.resume?.();
858
+ }
596
859
  break;
597
860
  case '/providers':
598
- await runProviders(args, { write, home: state.home, interactive: state.interactive });
861
+ state.rl?.pause?.();
862
+ try {
863
+ await runProviders(args, { write, home: state.home, interactive: state.interactive });
864
+ } finally {
865
+ if (process.stdin.isPaused()) process.stdin.resume();
866
+ state.rl?.resume?.();
867
+ }
599
868
  break;
600
869
  case '/login':
601
870
  await runLogin(args, { write, home: state.home });
@@ -608,17 +877,43 @@ export async function dispatchShellLine(line, state = {}) {
608
877
  await runWhoami(args, { write, home: state.home });
609
878
  break;
610
879
  case '/session':
611
- case '/usage':
612
880
  if (state.session) write(renderSessionReceipt(state.session));
613
881
  else writeLine(write, ' No persistent session is active in this shell invocation.');
614
882
  break;
883
+ case '/usage':
884
+ write(renderUsagePanel({
885
+ session: state.session,
886
+ usage: state.usageSnapshot || state.session?.usage_snapshot,
887
+ provider: state.providerState?.provider || state.session?.provider,
888
+ model: state.providerState?.model || state.session?.model,
889
+ effort: state.providerState?.reasoning_effort || state.session?.reasoning_effort,
890
+ tier: state.providerState?.service_tier || state.session?.service_tier,
891
+ estimateKind: state.usageSnapshot?.estimate_kind,
892
+ elapsedMs: state.session ? localSessionElapsedMs(state.session) : null,
893
+ cost: state.usageSnapshot?.cumulative?.cost_usd ?? state.session?.cumulative_usage?.cost_usd,
894
+ }));
895
+ break;
615
896
  case '/cf':
616
897
  case '/cloudflare':
617
898
  await runCloudflare(args.length ? args : ['commands'], { cwd: state.cwd, write });
618
899
  break;
900
+ case '/connections':
901
+ case '/connect':
902
+ await runConnections(args, { cwd: state.cwd, write, home: state.home });
903
+ break;
904
+ case '/tunnel':
905
+ await runTunnel(args, { cwd: state.cwd, write, home: state.home, interactive: state.interactive });
906
+ break;
619
907
  case '/settings': {
620
- const configured = await configureCliPreferences({ cwd: state.cwd, firstRun: false, home: state.home });
621
- state.cwd = configured.identity.root;
908
+ state.rl?.pause?.();
909
+ try {
910
+ const configured = await configureCliPreferences({ cwd: state.cwd, firstRun: false, home: state.home });
911
+ state.cwd = configured.identity.root;
912
+ state.projectRoot = findCliProjectRoot(state.cwd);
913
+ } finally {
914
+ if (process.stdin.isPaused()) process.stdin.resume();
915
+ state.rl?.resume?.();
916
+ }
622
917
  break;
623
918
  }
624
919
  case '/pwd':
@@ -628,22 +923,100 @@ export async function dispatchShellLine(line, state = {}) {
628
923
  const destination = args.length ? args.join(' ') : process.env.HOME || process.env.USERPROFILE || state.cwd;
629
924
  const next = path.resolve(state.cwd, destination);
630
925
  if (!fs.existsSync(next) || !fs.statSync(next).isDirectory()) throw new Error(`directory not found: ${next}`);
926
+ const nextRoot = findCliProjectRoot(next);
927
+ if (nextRoot !== (state.projectRoot || findCliProjectRoot(state.cwd))) {
928
+ if (state.session) {
929
+ persistSession(state, { status: 'paused', active_elapsed_ms: localSessionElapsedMs(state.session), active_started_at: null });
930
+ state.session = createLocalSession({ cwd: next, project_root: nextRoot }, { projectRoot: nextRoot, home: state.home });
931
+ }
932
+ state.projectRoot = nextRoot;
933
+ state.usageSnapshot = null;
934
+ state.providerState = null;
935
+ }
631
936
  state.cwd = next;
937
+ state.identity = null;
938
+ state.identityCwd = null;
632
939
  writeLine(write, state.cwd);
633
940
  break;
634
941
  }
635
942
  case '/git':
636
943
  spawnGit(state.cwd, args.length ? args : ['status', '--short', '--branch']);
637
944
  break;
638
- case '/diff':
639
- spawnGit(state.cwd, ['diff', ...args]);
945
+ case '/diff': {
946
+ const result = spawnSync('git', ['diff', '--no-color', ...args], { cwd: state.cwd, encoding: 'utf8', shell: false });
947
+ if (result.error) throw result.error;
948
+ if (result.status !== 0 && !String(result.stdout || '').trim()) {
949
+ throw new Error(String(result.stderr || `git exited ${result.status}`).trim());
950
+ }
951
+ write(renderDiffPreview(result.stdout || ''));
640
952
  break;
953
+ }
641
954
  case '/db':
642
- await runDb(args.length ? args : ['status'], { cwd: state.cwd });
955
+ await runDb(args.length ? args : ['status'], { cwd: state.projectRoot || state.cwd, write });
643
956
  break;
644
957
  case '/agent':
645
958
  await runLocalAgent(args.join(' '), write, { interactive: state.interactive });
646
959
  break;
960
+ case '/goap': {
961
+ const sub = (args[0] || 'status').toLowerCase();
962
+ if (sub === 'list' || sub === 'ls') {
963
+ const listState = await listGoapTickets({ cwd: state.cwd });
964
+ if (!listState.ok) {
965
+ writeLine(write, ` Failed to list GOAP tickets: ${listState.error || 'unknown error'}`);
966
+ } else {
967
+ writeLine(write, renderGoapList(listState));
968
+ }
969
+ break;
970
+ }
971
+ if (sub === 'new' || sub === 'create') {
972
+ const title = args.slice(1).join(' ').trim();
973
+ if (!title) {
974
+ writeLine(write, ' Usage: /goap new <title>');
975
+ break;
976
+ }
977
+ const res = await createGoapGoal({ cwd: state.cwd, title, accountId: readAccountSession({ home: state.home })?.account_id || null });
978
+ if (!res.ok) {
979
+ writeLine(write, ` Failed to create GOAP goal: ${res.error || 'unknown error'}`);
980
+ } else {
981
+ writeLine(write, ` Created and activated goal: ${res.ticketId} ("${res.title}")`);
982
+ }
983
+ break;
984
+ }
985
+ if (sub === 'switch' || sub === 'select') {
986
+ const tid = args[1]?.trim();
987
+ if (!tid) {
988
+ writeLine(write, ' Usage: /goap switch <ticket_id>');
989
+ break;
990
+ }
991
+ const res = await switchGoapGoal({ cwd: state.cwd, ticketId: tid, accountId: readAccountSession({ home: state.home })?.account_id || null });
992
+ if (!res.ok) {
993
+ writeLine(write, ` Failed to switch GOAP goal: ${res.error || 'unknown error'}`);
994
+ } else {
995
+ writeLine(write, ` Switched active GOAP goal to: ${res.ticketId}`);
996
+ }
997
+ break;
998
+ }
999
+ if (sub === 'close') {
1000
+ const tid = args[1]?.trim() || null;
1001
+ const res = await closeGoapGoal({ cwd: state.cwd, ticketId: tid, accountId: readAccountSession({ home: state.home })?.account_id || null });
1002
+ if (!res.ok) {
1003
+ writeLine(write, ` Failed to close GOAP goal: ${res.error || 'unknown error'}`);
1004
+ } else {
1005
+ writeLine(write, ` Closed GOAP goal: ${res.ticketId} [${res.status}]`);
1006
+ }
1007
+ break;
1008
+ }
1009
+ const goapState = await readGoapState({ cwd: state.cwd, accountId: readAccountSession({ home: state.home })?.account_id || null });
1010
+ if (!goapState.ok) {
1011
+ writeLine(write, ` Failed to read GOAP state: ${goapState.error || 'unknown error'}`);
1012
+ break;
1013
+ }
1014
+ if (sub === 'goal') writeLine(write, renderGoapGoal(goapState));
1015
+ else if (sub === 'why') writeLine(write, renderGoapWhy(goapState));
1016
+ else if (sub === 'plan') writeLine(write, renderGoapPlan(goapState));
1017
+ else writeLine(write, renderGoapStatus(goapState));
1018
+ break;
1019
+ }
647
1020
  case '/logs':
648
1021
  await showLocalLogs(state.cwd, write);
649
1022
  break;
@@ -658,8 +1031,44 @@ export async function dispatchShellLine(line, state = {}) {
658
1031
  await runInteractiveModelTurn(line, state);
659
1032
  break;
660
1033
  }
1034
+ {
1035
+ // Explicit slash → portable skill registry (no D1 / R2 / subagents).
1036
+ const skillRuntime = new SkillRuntime({
1037
+ registry: new SkillRegistry({ home: state.home }),
1038
+ contentResolver: new SkillContentResolver(),
1039
+ });
1040
+ const skillResult = await skillRuntime.invoke({ input: line });
1041
+ if (skillResult.matched) {
1042
+ const interactiveStatuses = new Set(['needs_input', 'needs_approval', 'blocked']);
1043
+ if (
1044
+ state.interactive &&
1045
+ interactiveStatuses.has(skillResult.interaction?.status) &&
1046
+ skillResult.interaction?.prompt
1047
+ ) {
1048
+ const choice = await presentAgentSamInteraction(skillResult.interaction, {
1049
+ write,
1050
+ interactive: state.interactive,
1051
+ });
1052
+ if (choice.action === 'create' || String(choice.value || '').startsWith('create')) {
1053
+ await handleSkillInteractionChoice(choice, { write, home: state.home });
1054
+ } else if (choice.action === 'list' || choice.value === 'list') {
1055
+ await handleSkillInteractionChoice(choice, { write, home: state.home });
1056
+ } else if (choice.action === 'install' || choice.value === 'install') {
1057
+ await handleSkillInteractionChoice(choice, { write, home: state.home });
1058
+ }
1059
+ } else if (skillResult.interaction?.prompt?.message) {
1060
+ for (const msgLine of String(skillResult.interaction.prompt.message).split('\n')) {
1061
+ writeLine(write, ` ${msgLine}`);
1062
+ }
1063
+ } else if (skillResult.modelInstructions?.content) {
1064
+ writeLine(write, ` skill ${skillResult.skill?.id} · ${skillResult.receipt?.checksum || 'resolved'}`);
1065
+ writeLine(write, ` (turn instructions ready · ${skillResult.tools?.length || 0} tools declared)`);
1066
+ }
1067
+ break;
1068
+ }
1069
+ }
661
1070
  writeLine(write, ` Unknown Agent Sam command: ${command}`);
662
- writeLine(write, ' Type / or /help for available commands.');
1071
+ writeLine(write, ' Type / or /help for available commands. Use /skills for installable slash skills.');
663
1072
  return { handled: false, exit: false, cwd: state.cwd };
664
1073
  }
665
1074
  } catch (error) {
@@ -667,9 +1076,15 @@ export async function dispatchShellLine(line, state = {}) {
667
1076
  persistSession(state, { last_error: diagnosticFromError(error, { source: 'shell', kind: 'interactive_error' }) });
668
1077
  }
669
1078
  if (!error?.reported) {
670
- for (const line of renderDiagnosticError(error).split('\n')) writeLine(write, ` ${line}`);
1079
+ for (const errorLine of renderDiagnosticError(error).split('\n')) writeLine(write, ` ${errorLine}`);
671
1080
  }
672
1081
  }
1082
+ const skipFooter = state.wroteTurnFooter;
1083
+ state.wroteTurnFooter = false;
1084
+ if (state.persistFooter && !skipFooter) {
1085
+ writeLine(write, renderShellSessionFooter(state));
1086
+ writeLine(write, '');
1087
+ }
673
1088
  return { handled: true, exit: false, cwd: state.cwd };
674
1089
  }
675
1090
 
@@ -677,14 +1092,18 @@ export async function runShell(argv = [], options = {}) {
677
1092
  const write = options.write || ((text) => process.stdout.write(text));
678
1093
  const state = {
679
1094
  cwd: path.resolve(options.cwd || process.cwd()),
1095
+ projectRoot: findCliProjectRoot(options.session?.project_root || options.cwd || process.cwd()),
680
1096
  write,
681
1097
  interactive: options.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY),
682
1098
  usageSnapshot: options.usageSnapshot || options.session?.usage_snapshot || null,
1099
+ providerState: null,
683
1100
  session: options.session || null,
684
1101
  home: options.home,
685
1102
  providerFetchImpl: options.providerFetchImpl,
1103
+ persistFooter: options.persistFooter === true,
686
1104
  };
687
1105
  const sub = argv[0] || '';
1106
+ hydrateSecureCredentials(process.env, { home: state.home });
688
1107
  if (sub === 'list' || sub === 'status') { write(renderShellCatalog()); return; }
689
1108
  if (sub === '--command' || sub === '--once') {
690
1109
  const line = argv.slice(1).join(' ');
@@ -701,40 +1120,73 @@ export async function runShell(argv = [], options = {}) {
701
1120
  status: 'active',
702
1121
  cwd: state.cwd,
703
1122
  active_started_at: new Date().toISOString(),
704
- }, { home: state.home });
1123
+ }, { home: state.home, projectRoot: state.projectRoot });
705
1124
  state.usageSnapshot = state.session.usage_snapshot || state.usageSnapshot;
706
1125
  } else {
707
1126
  const preferences = readCliPreferences(state.cwd) || {};
708
1127
  state.session = createLocalSession({
709
1128
  cwd: state.cwd,
1129
+ project_root: state.projectRoot,
710
1130
  status: 'active',
711
1131
  model_key: preferences.modelPreference !== 'auto' ? preferences.modelPreference : null,
712
1132
  reasoning_effort: preferences.reasoningEffort !== 'auto' ? preferences.reasoningEffort : null,
713
1133
  requested_service_tier: preferences.serviceTier || 'default',
714
- }, { home: state.home });
1134
+ }, { home: state.home, projectRoot: state.projectRoot });
715
1135
  }
716
1136
 
717
1137
  if (options.intro !== 'quiet') {
718
1138
  write(renderShellCatalog());
719
1139
  writeLine(write, ' Interactive shell ready. Type / for the command picker; /exit to return to your host shell.\n');
720
1140
  }
1141
+ state.persistFooter = options.persistFooter !== false;
1142
+ writeLine(write, renderShellSessionFooter(state));
1143
+ writeLine(write, '');
721
1144
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: Boolean(process.stdin.isTTY && process.stdout.isTTY) });
1145
+ state.rl = rl;
1146
+ let promptTextRef = () => renderShellPrompt(state.cwd);
1147
+ const restorePaste = installPasteCollapse(rl, { output: process.stdout });
722
1148
  let interrupted = false;
1149
+ let lastSigintAt = 0;
1150
+ const SIGINT_EXIT_WINDOW_MS = 2000;
723
1151
  rl.on('SIGINT', () => {
724
- interrupted = true;
725
- rl.close();
1152
+ const now = Date.now();
1153
+ if (now - lastSigintAt < SIGINT_EXIT_WINDOW_MS) {
1154
+ // Second Ctrl+C within the window: actually exit, matching the
1155
+ // near-universal CLI convention (bash, node REPL, Claude Code, Codex).
1156
+ interrupted = true;
1157
+ rl.close();
1158
+ return;
1159
+ }
1160
+ // First Ctrl+C: cancel the current line/prompt only, matching what the
1161
+ // footer already tells the user ("ctrl-c to cancel"). A single press
1162
+ // used to close the whole session outright -- that's the discrepancy
1163
+ // being fixed here, not the intended behavior.
1164
+ lastSigintAt = now;
1165
+ write('\n (Ctrl+C again within 2s to exit)\n');
1166
+ rl.line = '';
1167
+ rl.cursor = 0;
1168
+ if (rl.terminal) { rl.setPrompt(promptTextRef()); rl.prompt(); }
726
1169
  });
727
1170
  const promptText = () => {
728
1171
  if (typeof options.prompt === 'function') return options.prompt(state);
729
1172
  if (typeof options.prompt === 'string' && options.prompt) return options.prompt;
730
1173
  return renderShellPrompt(state.cwd);
731
1174
  };
732
- if (rl.terminal) { rl.setPrompt(promptText()); rl.prompt(); }
733
- for await (const line of rl) {
734
- recordSessionInput(state, line);
735
- const result = await dispatchShellLine(line, state);
736
- if (result.exit) { rl.close(); break; }
1175
+ promptTextRef = promptText;
1176
+ try {
737
1177
  if (rl.terminal) { rl.setPrompt(promptText()); rl.prompt(); }
1178
+ for await (const line of rl) {
1179
+ recordSessionInput(state, line);
1180
+ const result = await dispatchShellLine(line, state);
1181
+ if (result.exit) { rl.close(); break; }
1182
+ if (process.stdin.isPaused()) {
1183
+ process.stdin.resume();
1184
+ }
1185
+ if (rl.terminal) { rl.setPrompt(promptText()); rl.prompt(); }
1186
+ }
1187
+ } finally {
1188
+ restorePaste();
1189
+ state.rl = null;
738
1190
  }
739
1191
  if (state.session) {
740
1192
  const activeElapsedMs = localSessionElapsedMs(state.session);