@inneranimalmedia/agentsam-sdk 2.6.4 → 2.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (418) hide show
  1. package/AGENTSAM.md +11 -0
  2. package/README.md +15 -9
  3. package/apps/client-cms-editor/AGENTS.md +12 -0
  4. package/apps/client-cms-editor/IMPORT_PROVENANCE.json +8 -0
  5. package/apps/client-cms-editor/README.md +72 -0
  6. package/apps/client-cms-editor/agentsam.app.json +57 -0
  7. package/apps/client-cms-editor/backend/README.md +5 -0
  8. package/apps/client-cms-editor/backend/package.json +22 -0
  9. package/apps/client-cms-editor/backend/src/api/client.ts +200 -0
  10. package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +145 -0
  11. package/apps/client-cms-editor/backend/src/index.ts +6 -0
  12. package/apps/client-cms-editor/backend/src/model.ts +115 -0
  13. package/apps/client-cms-editor/backend/src/preview/bridge.ts +79 -0
  14. package/apps/client-cms-editor/backend/src/preview/urls.ts +55 -0
  15. package/apps/client-cms-editor/backend/src/routing/cms-route.js +293 -0
  16. package/apps/client-cms-editor/backend/src/routing/index.js +10 -0
  17. package/apps/client-cms-editor/backend/src/storefront.ts +52 -0
  18. package/apps/client-cms-editor/backend/tsconfig.json +15 -0
  19. package/apps/client-cms-editor/backend/worker/index.js +34 -0
  20. package/apps/client-cms-editor/backend/wrangler.jsonc +11 -0
  21. package/apps/client-cms-editor/bin/agentsam-cms.mjs +229 -0
  22. package/apps/client-cms-editor/frontend/index.html +12 -0
  23. package/apps/client-cms-editor/frontend/package.json +33 -0
  24. package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +188 -0
  25. package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +191 -0
  26. package/apps/client-cms-editor/frontend/src/CmsEditor.tsx +1345 -0
  27. package/apps/client-cms-editor/frontend/src/env.d.ts +14 -0
  28. package/apps/client-cms-editor/frontend/src/index.ts +8 -0
  29. package/apps/client-cms-editor/frontend/src/lib/content-safety.ts +63 -0
  30. package/apps/client-cms-editor/frontend/src/main.tsx +17 -0
  31. package/apps/client-cms-editor/frontend/src/mount.tsx +51 -0
  32. package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +214 -0
  33. package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +1739 -0
  34. package/apps/client-cms-editor/frontend/src/styles/studio.css +106 -0
  35. package/apps/client-cms-editor/frontend/src/surfaces/CmsDashboard.tsx +313 -0
  36. package/apps/client-cms-editor/frontend/src/surfaces/CmsGuidedChatHero.tsx +121 -0
  37. package/apps/client-cms-editor/frontend/src/surfaces/CmsHubPage.tsx +132 -0
  38. package/apps/client-cms-editor/frontend/src/surfaces/CmsSiteSwitcher.tsx +176 -0
  39. package/apps/client-cms-editor/frontend/src/surfaces/index.ts +5 -0
  40. package/apps/client-cms-editor/frontend/src/surfaces/types.ts +48 -0
  41. package/apps/client-cms-editor/frontend/tsconfig.json +25 -0
  42. package/apps/client-cms-editor/frontend/vite.config.ts +13 -0
  43. package/apps/client-cms-editor/package-lock.json +3832 -0
  44. package/apps/client-cms-editor/package.json +23 -0
  45. package/apps/client-cms-editor/reference/DONOR_README.md +52 -0
  46. package/apps/client-cms-editor/reference/DONOR_package-lock.json +1253 -0
  47. package/apps/client-cms-editor/reference/DONOR_tsconfig.json +15 -0
  48. package/apps/client-cms-editor/shared/cms/package.json +21 -0
  49. package/apps/client-cms-editor/shared/cms/src/agent-context.ts +35 -0
  50. package/apps/client-cms-editor/shared/cms/src/cloudflare-bindings.ts +51 -0
  51. package/apps/client-cms-editor/shared/cms/src/editor-types.ts +58 -0
  52. package/apps/client-cms-editor/shared/cms/src/index.ts +5 -0
  53. package/apps/client-cms-editor/shared/cms/src/publication.ts +24 -0
  54. package/apps/client-cms-editor/shared/cms/src/routes.ts +11 -0
  55. package/apps/client-cms-editor/shared/cms/tsconfig.json +12 -0
  56. package/bin/agentsam-rapid-rust +36 -0
  57. package/docs/AUTH_IDENTITY_CONTRACT.md +2 -0
  58. package/docs/MACHINE_INTELLIGENCE.md +120 -0
  59. package/docs/WINDOWS_RUNTIME_INSTALL.md +30 -0
  60. package/docs/architecture/AGENTSAM_APPLICATION_CONTRACT.md +188 -0
  61. package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +151 -0
  62. package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +12 -4
  63. package/docs/architecture/R2_SLUG_NAMESPACE.md +20 -0
  64. package/docs/architecture/WORK_PRODUCT_EXTRACTION.md +97 -0
  65. package/docs/brand/AGENT_SAM_ICON_GRAMMAR.md +70 -0
  66. package/docs/content-studio/HOST_MOUNT_CHECKLIST.md +71 -0
  67. package/docs/content-studio/REVISION_GATE_2026-09-27.md +501 -0
  68. package/docs/contracts/capability-install-planner.md +67 -0
  69. package/docs/contracts/environment-vocabulary.md +195 -0
  70. package/docs/contracts/google-cloud-oauth-setup.md +199 -0
  71. package/docs/local-studio/WORKMODE_DONOR_NOTES.md +1 -1
  72. package/docs/plans/LOCAL-STUDIO-GRADUATION-2026-09-26.md +290 -0
  73. package/docs/plans/LOCAL-STUDIO-REAL-APP-CONTRACT-ADDENDUM-2026-09-27.md +394 -0
  74. package/docs/plans/MACHINE-FIRST-APPS-TUI-2026-09-24.md +227 -0
  75. package/docs/plans/TOMORROW-EXTENSIVE-TODO-2026-09-26.md +221 -0
  76. package/docs/plans/TOMORROW-MACHINE-FIRST-BRIEFING.md +145 -0
  77. package/docs/plans/UNIVERSAL-INGEST-MACHINE-FIRST-2026-09-24.md +215 -0
  78. package/docs/plugins.md +2 -2
  79. package/docs/product/AGENTSAM_PRODUCT_EXPERIENCE_STANDARD.md +280 -0
  80. package/docs/product/LOCAL_STUDIO_DESKTOP_EXPERIENCE.md +139 -0
  81. package/docs/product/README.md +8 -0
  82. package/docs/rapid-rust-wasm.md +35 -0
  83. package/migrations/d1/0016_cloudflare_oauth_user_oauth_tokens_ssot.sql +14 -0
  84. package/package.json +73 -14
  85. package/packages/agentsam-brand/README.md +106 -11
  86. package/packages/agentsam-brand/bin/agentsam-brand.mjs +9 -0
  87. package/packages/agentsam-brand/package.json +39 -7
  88. package/packages/agentsam-brand/src/adapters/cloudflare-images.js +453 -0
  89. package/packages/agentsam-brand/src/adapters/cloudflare-r2.js +74 -0
  90. package/packages/agentsam-brand/src/adapters/d1-registry.js +26 -0
  91. package/packages/agentsam-brand/src/adapters/filesystem.js +59 -0
  92. package/packages/agentsam-brand/src/adapters/memory.js +31 -0
  93. package/packages/agentsam-brand/src/cli/controller.js +503 -0
  94. package/packages/agentsam-brand/src/cli/wizard.js +526 -0
  95. package/packages/agentsam-brand/src/core/capabilities.js +201 -0
  96. package/packages/agentsam-brand/src/core/derivatives.js +211 -0
  97. package/packages/agentsam-brand/src/core/errors.js +12 -0
  98. package/packages/agentsam-brand/src/core/ingest.js +195 -0
  99. package/packages/agentsam-brand/src/core/inspect.js +109 -0
  100. package/packages/agentsam-brand/src/core/keys.js +83 -0
  101. package/packages/agentsam-brand/src/core/naming.js +142 -0
  102. package/packages/agentsam-brand/src/core/optimize.js +316 -0
  103. package/packages/agentsam-brand/src/core/pack.js +305 -0
  104. package/packages/agentsam-brand/src/core/plan.js +276 -0
  105. package/packages/agentsam-brand/src/core/preview.js +159 -0
  106. package/packages/agentsam-brand/src/core/processors/cloudflare.js +68 -0
  107. package/packages/agentsam-brand/src/core/processors/contract.js +203 -0
  108. package/packages/agentsam-brand/src/core/processors/index.js +148 -0
  109. package/packages/agentsam-brand/src/core/processors/native.js +82 -0
  110. package/packages/agentsam-brand/src/core/processors/sharp.js +113 -0
  111. package/packages/agentsam-brand/src/core/processors/squoosh-binary.js +195 -0
  112. package/packages/agentsam-brand/src/core/promote.js +288 -0
  113. package/packages/agentsam-brand/src/core/receipts.js +155 -0
  114. package/packages/agentsam-brand/src/core/v2/compile.js +280 -0
  115. package/packages/agentsam-brand/src/core/v2/derivatives-semantic.js +207 -0
  116. package/packages/agentsam-brand/src/core/v2/ingest-graph.js +387 -0
  117. package/packages/agentsam-brand/src/core/v2/roles.js +180 -0
  118. package/packages/agentsam-brand/src/core/v2/schema.js +209 -0
  119. package/packages/agentsam-brand/src/core/v2/templates.js +114 -0
  120. package/packages/agentsam-brand/src/index.js +193 -36
  121. package/packages/agentsam-brand/src/presets/app-icon.json +16 -0
  122. package/packages/agentsam-brand/src/presets/favicon.json +17 -0
  123. package/packages/agentsam-brand/src/presets/hero.json +12 -0
  124. package/packages/agentsam-brand/src/presets/index.js +40 -0
  125. package/packages/agentsam-brand/src/presets/logo.json +12 -0
  126. package/packages/agentsam-brand/src/presets/model.json +8 -0
  127. package/packages/agentsam-brand/src/presets/og-image.json +10 -0
  128. package/packages/agentsam-brand/src/presets/product-shot.json +11 -0
  129. package/packages/agentsam-brand/src/presets/social-image.json +10 -0
  130. package/packages/agentsam-brand/src/presets/web-image.json +10 -0
  131. package/packages/agentsam-contracts/src/artifacts.ts +41 -0
  132. package/packages/agentsam-knowledge/src/autorag/index.js +1 -1
  133. package/packages/agentsam-knowledge/src/providers/index.js +6 -4
  134. package/packages/agentsam-knowledge/src/providers/ollama-endpoint.js +31 -0
  135. package/packages/agentsam-knowledge/test/autorag.test.mjs +22 -1
  136. package/packages/agentsam-nav/package.json +2 -2
  137. package/packages/agentsam-rapid-rust/Cargo.lock +344 -0
  138. package/packages/agentsam-rapid-rust/Cargo.toml +18 -0
  139. package/packages/agentsam-rapid-rust/README.md +5 -0
  140. package/packages/agentsam-rapid-rust/src/main.rs +718 -0
  141. package/packages/agentsam-rapid-rust/templates/api/Cargo.toml.tmpl +18 -0
  142. package/packages/agentsam-rapid-rust/templates/api/src/lib.rs.tmpl +17 -0
  143. package/packages/agentsam-rapid-rust/templates/common/README.md.tmpl +22 -0
  144. package/packages/agentsam-rapid-rust/templates/common/package.json.tmpl +12 -0
  145. package/packages/agentsam-rapid-rust/templates/common/wrangler.toml.tmpl +6 -0
  146. package/packages/agentsam-rapid-rust/templates/crypto-auth/Cargo.toml.tmpl +21 -0
  147. package/packages/agentsam-rapid-rust/templates/crypto-auth/src/lib.rs.tmpl +32 -0
  148. package/packages/agentsam-rapid-rust/templates/data-processor/Cargo.toml.tmpl +18 -0
  149. package/packages/agentsam-rapid-rust/templates/data-processor/src/lib.rs.tmpl +41 -0
  150. package/packages/agentsam-rapid-rust/templates/shared-core/Cargo.toml.tmpl +9 -0
  151. package/packages/agentsam-rapid-rust/templates/shared-core/core/Cargo.toml.tmpl +7 -0
  152. package/packages/agentsam-rapid-rust/templates/shared-core/core/src/lib.rs.tmpl +23 -0
  153. package/packages/agentsam-rapid-rust/templates/shared-core/worker/Cargo.toml.tmpl +12 -0
  154. package/packages/agentsam-rapid-rust/templates/shared-core/worker/src/lib.rs.tmpl +16 -0
  155. package/packages/agentsam-rapid-rust/templates/shared-core/wrangler.toml.tmpl +6 -0
  156. package/packages/agentsam-repository/src/index.js +1 -0
  157. package/packages/agentsam-repository/src/merkle/semantic.js +3 -10
  158. package/packages/agentsam-repository/src/source-types.js +85 -0
  159. package/packages/agentsam-vault/README.md +96 -0
  160. package/packages/agentsam-vault/package.json +32 -0
  161. package/packages/agentsam-vault/src/contracts/credential.d.ts +78 -0
  162. package/packages/agentsam-vault/src/contracts/credential.js +132 -0
  163. package/packages/agentsam-vault/src/crypto/aes-gcm.d.ts +30 -0
  164. package/packages/agentsam-vault/src/crypto/aes-gcm.js +107 -0
  165. package/packages/agentsam-vault/src/crypto/oauth-envelope.js +150 -0
  166. package/packages/agentsam-vault/src/index.d.ts +9 -0
  167. package/packages/agentsam-vault/src/index.js +27 -0
  168. package/packages/agentsam-vault/src/providers/registry.js +90 -0
  169. package/packages/agentsam-vault/src/runtime/resolver.js +77 -0
  170. package/packages/agentsam-workbench/README.md +24 -0
  171. package/packages/agentsam-workbench/package.json +38 -0
  172. package/packages/agentsam-workbench/src/agent/AgentPanel.tsx +41 -0
  173. package/packages/agentsam-workbench/src/agent/ArtifactCard.tsx +9 -0
  174. package/packages/agentsam-workbench/src/agent/Composer.tsx +102 -0
  175. package/packages/agentsam-workbench/src/agent/ConnectedAgentPanel.tsx +194 -0
  176. package/packages/agentsam-workbench/src/agent/ContextualComposer.tsx +788 -0
  177. package/packages/agentsam-workbench/src/agent/GoalStatusStrip.tsx +38 -0
  178. package/packages/agentsam-workbench/src/agent/MiniAgentSam.tsx +86 -0
  179. package/packages/agentsam-workbench/src/agent/ModelSelect.tsx +19 -0
  180. package/packages/agentsam-workbench/src/agent/Thread.tsx +56 -0
  181. package/packages/agentsam-workbench/src/agent/ToolReceipt.tsx +11 -0
  182. package/packages/agentsam-workbench/src/agent/contextual-composer.css +611 -0
  183. package/packages/agentsam-workbench/src/agent/index.ts +10 -0
  184. package/packages/agentsam-workbench/src/agent/mini-agentsam.css +12 -0
  185. package/packages/agentsam-workbench/src/browser/BrowserFrame.tsx +37 -0
  186. package/packages/agentsam-workbench/src/browser/index.ts +1 -0
  187. package/packages/agentsam-workbench/src/index.ts +6 -0
  188. package/packages/agentsam-workbench/src/project-control.css +160 -0
  189. package/packages/agentsam-workbench/src/projects/ProjectsSurface.tsx +131 -0
  190. package/packages/agentsam-workbench/src/projects/index.ts +1 -0
  191. package/packages/agentsam-workbench/src/shell/Breadcrumb.tsx +35 -0
  192. package/packages/agentsam-workbench/src/shell/ResizableStage.tsx +99 -0
  193. package/packages/agentsam-workbench/src/shell/SidePanel.tsx +5 -0
  194. package/packages/agentsam-workbench/src/shell/index.ts +4 -0
  195. package/packages/agentsam-workbench/src/shell/surfaceRegistry.ts +29 -0
  196. package/packages/agentsam-workbench/src/terminal/TerminalSurface.tsx +5 -0
  197. package/packages/agentsam-workbench/src/terminal/index.ts +1 -0
  198. package/packages/agentsam-workbench/src/timeline/GanttBoard.tsx +258 -0
  199. package/packages/agentsam-workbench/src/timeline/index.ts +1 -0
  200. package/packages/agentsam-workbench/tsconfig.json +13 -0
  201. package/packages/connectors/cloudflare/OAUTH_STORAGE_AUDIT.md +53 -0
  202. package/packages/connectors/cloudflare/package.json +3 -1
  203. package/packages/connectors/cloudflare/src/api-client.js +279 -0
  204. package/packages/connectors/cloudflare/src/capabilities.js +585 -0
  205. package/packages/connectors/cloudflare/src/credential.js +318 -0
  206. package/packages/connectors/cloudflare/src/families/brand-protection.js +123 -0
  207. package/packages/connectors/cloudflare/src/families/keyless.js +114 -0
  208. package/packages/connectors/cloudflare/src/families/pages.js +151 -0
  209. package/packages/connectors/cloudflare/src/families/scanner.js +123 -0
  210. package/packages/connectors/cloudflare/src/families/snippets.js +207 -0
  211. package/packages/connectors/cloudflare/src/families/tag-gateway.js +46 -0
  212. package/packages/connectors/cloudflare/src/families/tags.js +124 -0
  213. package/packages/connectors/cloudflare/src/families/token-validation.js +95 -0
  214. package/packages/connectors/cloudflare/src/families/workflows.js +156 -0
  215. package/packages/connectors/cloudflare/src/index.js +102 -265
  216. package/packages/connectors/cloudflare/src/oauth-persist.js +336 -0
  217. package/packages/connectors/cloudflare/src/owner.js +42 -12
  218. package/packages/connectors/cloudflare/src/permission-options.js +1064 -0
  219. package/packages/connectors/cloudflare/src/routes.js +309 -144
  220. package/packages/connectors/cloudflare/src/scope-catalog.js +345 -0
  221. package/packages/connectors/cloudflare/src/vault.js +2 -2
  222. package/packages/connectors/cloudflare/tests/capabilities.test.mjs +276 -0
  223. package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -30
  224. package/packages/connectors/cloudflare/tests/oauth-persist.test.mjs +125 -0
  225. package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +22 -2
  226. package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +10 -4
  227. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +20 -0
  228. package/packages/identity/README.md +1 -1
  229. package/packages/identity/backend/README.md +1 -1
  230. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +3 -2
  231. package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +48 -0
  232. package/packages/identity/package.json +4 -3
  233. package/packages/identity/scripts/local-identity-bridge.mjs +184 -0
  234. package/packages/identity/scripts/preview-auth-portal.mjs +7 -7
  235. package/packages/identity/src/adapters/cloudflare-d1/index.js +31 -2
  236. package/packages/identity/src/adapters/sqlite/index.js +4 -1
  237. package/packages/identity/src/contracts/auth-config.js +28 -8
  238. package/packages/identity/src/contracts/external-identity.js +1 -1
  239. package/packages/identity/src/contracts/provider.js +1 -0
  240. package/packages/identity/src/frontend/auth-portal/README.md +2 -1
  241. package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -5
  242. package/packages/identity/src/frontend/auth-portal/pages/reset.html +6 -5
  243. package/packages/identity/src/frontend/auth-portal/pages/signup.html +6 -5
  244. package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
  245. package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +207 -0
  246. package/packages/identity/src/index.js +16 -0
  247. package/packages/identity/src/migrations/0001_identity_core.sql +19 -2
  248. package/packages/identity/src/migrations/0003_accounts_ssot.sql +20 -0
  249. package/packages/identity/src/migrations/README.md +5 -2
  250. package/packages/identity/src/oauth/README.md +10 -5
  251. package/packages/identity/src/oauth/consent-view.js +388 -0
  252. package/packages/identity/src/oauth/credentials.js +31 -11
  253. package/packages/identity/src/oauth/google-desktop-exchange.js +173 -0
  254. package/packages/identity/src/providers/cloudflare/oauth.js +3 -4
  255. package/packages/identity/src/providers/cloudflare/profile.js +49 -14
  256. package/packages/identity/src/providers/iam/index.js +27 -5
  257. package/packages/identity/src/server/identity-service.js +31 -2
  258. package/packages/identity/src/server/worker-router.js +111 -81
  259. package/packages/identity/tests/auth-config.test.mjs +3 -2
  260. package/packages/identity/tests/identity-init-scaffold.test.mjs +3 -0
  261. package/packages/identity/tests/identity-service.test.mjs +16 -0
  262. package/packages/identity/tests/native-session-worker.test.mjs +64 -0
  263. package/packages/identity/tests/oauth-consent-view.test.mjs +106 -0
  264. package/packages/identity/tests/oauth-credentials.test.mjs +17 -4
  265. package/packages/identity/tests/oauth-presets-accounts-ssot.test.mjs +58 -0
  266. package/packages/identity/tests/preview-auth-portal.test.mjs +3 -3
  267. package/packages/runtime-protocol/src/index.js +154 -0
  268. package/packages/theme-scenes/README.md +164 -0
  269. package/packages/theme-scenes/package.json +53 -0
  270. package/packages/theme-scenes/src/blocks/index.js +30 -0
  271. package/packages/theme-scenes/src/contracts/index.js +286 -0
  272. package/packages/theme-scenes/src/demos/index.js +65 -0
  273. package/packages/theme-scenes/src/index.js +75 -0
  274. package/packages/theme-scenes/src/presets/index.js +263 -0
  275. package/packages/theme-scenes/src/runtime/compile.js +119 -0
  276. package/packages/theme-scenes/src/scenes/index.js +146 -0
  277. package/packages/theme-scenes/src/shell/index.js +47 -0
  278. package/packages/theme-scenes/src/themes/index.js +129 -0
  279. package/packages/theme-scenes/src/visuals/index.js +41 -0
  280. package/packages/theme-scenes/test/theme-scenes.test.mjs +179 -0
  281. package/packages/work-graph/src/index.js +34 -1
  282. package/packages/work-graph/src/renderers/gantt-model.js +24 -0
  283. package/packages/work-graph/test/work-graph.test.mjs +27 -7
  284. package/protocol/README.md +15 -7
  285. package/protocol/apps/agentsam.app.v1.schema.json +89 -7
  286. package/protocol/apps/agentsam.host-install.v1.schema.json +36 -0
  287. package/protocol/assets/README.md +9 -0
  288. package/protocol/assets/asset-record.v1.schema.json +64 -0
  289. package/protocol/runtime/agentsam.runtime.v1.schema.json +75 -0
  290. package/protocol/scoring/README.md +10 -0
  291. package/protocol/scoring/scorecard.v1.schema.json +65 -0
  292. package/protocol/ui/icon-registry.mjs +1 -0
  293. package/registry/cms-rust-machine-20260928/installable-products.json +31 -0
  294. package/registry/cms-rust-machine-20260928/manifest.json +22 -0
  295. package/registry/cms-rust-machine-20260928/migration.sql +237 -0
  296. package/registry/cms-rust-machine-20260928/receipt.json +21 -0
  297. package/registry/cms-rust-machine-20260928/receipt.sql +27 -0
  298. package/scripts/build_rapid_rust_cli.py +83 -0
  299. package/src/attachments/index.js +6 -0
  300. package/src/attachments/intake.js +235 -0
  301. package/src/capabilities/repository-snapshot.js +19 -2
  302. package/src/cli/command-catalog.js +8 -0
  303. package/src/cli.js +182 -26
  304. package/src/commands/account-auth.js +94 -8
  305. package/src/commands/app.js +307 -3
  306. package/src/commands/billing.js +127 -0
  307. package/src/commands/brand.js +74 -60
  308. package/src/commands/cheat-sheet.js +154 -0
  309. package/src/commands/cloudflare-login.js +222 -0
  310. package/src/commands/cloudflare.js +453 -23
  311. package/src/commands/codebaseindex.js +6 -1
  312. package/src/commands/compute.js +4 -0
  313. package/src/commands/connections.js +11 -5
  314. package/src/commands/credentials.js +116 -0
  315. package/src/commands/gcloud-auth.js +427 -0
  316. package/src/commands/google-cloud.js +375 -0
  317. package/src/commands/identity-init.js +2 -2
  318. package/src/commands/mcp.js +226 -33
  319. package/src/commands/ollama.js +3 -2
  320. package/src/commands/plugins.js +7 -2
  321. package/src/commands/product.js +36 -0
  322. package/src/commands/runtime-status.js +28 -9
  323. package/src/commands/runtime.js +313 -0
  324. package/src/commands/rust.js +24 -0
  325. package/src/commands/setup.js +279 -0
  326. package/src/commands/shell.js +16 -3
  327. package/src/commands/start-local.js +2 -2
  328. package/src/commands/terminal.js +171 -0
  329. package/src/commands/update.js +140 -0
  330. package/src/commands/whoami.js +329 -65
  331. package/src/features/resolve.js +1 -0
  332. package/src/index.js +4 -0
  333. package/src/indexing/ingest/inventory.js +254 -19
  334. package/src/indexing/ingest/materials.js +3 -9
  335. package/src/indexing/ingest/style-evidence.js +181 -0
  336. package/src/knowledge/source.js +3 -3
  337. package/src/lib/account-session.js +11 -4
  338. package/src/lib/app-authority.js +172 -0
  339. package/src/lib/auth.js +94 -21
  340. package/src/lib/core-client.js +5 -6
  341. package/src/lib/credentials-audit.js +451 -0
  342. package/src/lib/deploy/health.js +24 -6
  343. package/src/lib/detect-context.js +7 -1
  344. package/src/lib/google-cloud-connection.js +270 -0
  345. package/src/lib/google-cloud-inventory.js +385 -0
  346. package/src/lib/google-desktop-oauth.js +372 -0
  347. package/src/lib/google-studio-brokered-oauth.js +158 -0
  348. package/src/lib/identity-scaffold.js +24 -6
  349. package/src/lib/init-options.js +192 -0
  350. package/src/lib/local-scaffold.js +48 -16
  351. package/src/lib/provider-command-remediation.js +308 -0
  352. package/src/lib/provider-credentials.js +8 -0
  353. package/src/lib/scaffold/index.js +8 -2
  354. package/src/lib/scaffold/mcp-server.js +43 -0
  355. package/src/lib/scaffold/templates/mcp-server/index.js +397 -0
  356. package/src/lib/scaffold/templates/mcp-server/presets.js +39 -0
  357. package/src/lib/scaffold/wizards/cms.js +93 -0
  358. package/src/lib/scaffold/wizards/mcp-server.js +61 -0
  359. package/src/lib/setup/contract.js +26 -0
  360. package/src/lib/setup/discover.js +116 -0
  361. package/src/lib/setup/execute.js +205 -0
  362. package/src/lib/setup/planner.js +134 -0
  363. package/src/lib/setup/recipes.js +235 -0
  364. package/src/lib/setup/runtime-persist.js +197 -0
  365. package/src/lib/setup/runtime.js +394 -0
  366. package/src/lib/slash-commands.js +2 -0
  367. package/src/lib/terminal/machine-identity.js +95 -0
  368. package/src/lib/terminal-local.js +164 -0
  369. package/src/lib/terminal-scopes.js +52 -0
  370. package/src/lib/whoami-capabilities.js +184 -0
  371. package/src/local-pty/server.js +34 -5
  372. package/src/mcp/authority.js +58 -108
  373. package/src/mcp/client-adapters.js +68 -144
  374. package/src/mcp/client.js +142 -122
  375. package/src/mcp/cloudflare-bundles.js +225 -0
  376. package/src/mcp/index.js +12 -0
  377. package/src/plugins/cloudflare.js +1 -1
  378. package/src/providers/ollama-chat.js +2 -1
  379. package/src/sam/types.js +27 -2
  380. package/src/security/inventory.js +12 -2
  381. package/src/security/local-vault.js +2 -0
  382. package/src/security/scan.js +1 -1
  383. package/test/account-session.test.mjs +3 -3
  384. package/test/app-authority-context.test.mjs +32 -0
  385. package/test/cli/codebaseindex-plan-ux.test.mjs +1 -1
  386. package/test/cli/mcp-client.test.mjs +21 -10
  387. package/test/cli/runtime-persist.test.mjs +56 -0
  388. package/test/cli/rust-command.test.mjs +21 -0
  389. package/test/credentials-audit.test.mjs +113 -0
  390. package/test/deploy-health-scan.test.mjs +29 -1
  391. package/test/gcloud-auth.test.mjs +111 -0
  392. package/test/google-cloud-connection.test.mjs +83 -0
  393. package/test/google-cloud-inventory.test.mjs +64 -0
  394. package/test/init-options.test.mjs +35 -0
  395. package/test/integration/app-command.test.mjs +30 -0
  396. package/test/integration/cad-project.test.mjs +4 -1
  397. package/test/integration/cms-app-scaffold.test.mjs +71 -0
  398. package/test/integration/cms-site-tenancy-contract.test.mjs +3 -2
  399. package/test/integration/codebaseindex-ingest.test.mjs +48 -0
  400. package/test/integration/features-resolve.test.mjs +30 -11
  401. package/test/integration/inspect-path-cli.test.mjs +46 -0
  402. package/test/integration/inventory-evidence.test.mjs +125 -0
  403. package/test/integration/runtime-status.integration.test.mjs +2 -1
  404. package/test/knowledge.test.mjs +35 -1
  405. package/test/loopback-oauth.test.mjs +53 -0
  406. package/test/ollama.test.mjs +22 -0
  407. package/test/security.test.mjs +23 -0
  408. package/test/setup-planner.test.mjs +74 -0
  409. package/test/setup-runtime.test.mjs +51 -0
  410. package/test/terminal/local-pty.mock.test.mjs +3 -1
  411. package/test/terminal-machine-identity.test.mjs +88 -0
  412. package/test/whoami-resume.test.mjs +27 -6
  413. package/packages/agentsam-brand/test/brand-scan.test.mjs +0 -106
  414. package/packages/work-graph/prototype/README.md +0 -32
  415. package/packages/work-graph/prototype/data/demo-workgraph.js +0 -47
  416. package/packages/work-graph/prototype/renderers/timeline-model.js +0 -21
  417. package/packages/work-graph/prototype/renderers/workgraph-runtime.js +0 -38
  418. package/packages/work-graph/prototype-gnantt.html +0 -655
@@ -7,19 +7,27 @@
7
7
 
8
8
  import fs from 'node:fs';
9
9
  import path from 'node:path';
10
-
11
- const EXT_LANG = new Map([
12
- ['.js', 'JavaScript'], ['.mjs', 'JavaScript'], ['.cjs', 'JavaScript'],
13
- ['.ts', 'TypeScript'], ['.tsx', 'TypeScript'], ['.jsx', 'JavaScript'],
14
- ['.py', 'Python'], ['.go', 'Go'], ['.rs', 'Rust'], ['.md', 'Markdown'],
15
- ['.json', 'JSON'], ['.css', 'CSS'], ['.html', 'HTML'], ['.htm', 'HTML'],
16
- ['.yml', 'YAML'], ['.yaml', 'YAML'], ['.sql', 'SQL'], ['.sh', 'Shell'],
17
- ]);
10
+ import { execFileSync } from 'node:child_process';
11
+ import {
12
+ sourceLanguageForExtension,
13
+ sourceTypeForExtension,
14
+ } from '../../../packages/agentsam-repository/src/source-types.js';
15
+ import {
16
+ finalizeStyleEvidence,
17
+ inspectStyleEvidenceFile,
18
+ mergeStyleEvidence,
19
+ } from './style-evidence.js';
18
20
 
19
21
  const IMAGE = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico']);
20
22
  const MODEL3D = new Set(['.glb', '.gltf', '.obj', '.fbx', '.stl']);
21
23
  const ARCHIVE = new Set(['.zip', '.tar', '.tgz', '.gz']);
22
24
 
25
+ const ROOT_SECRET = /^(\.env(\..+)?|\.dev\.vars(\..+)?|.+\.(pem|key|p12|pfx))$/i;
26
+ const ROOT_TEMPLATE = /\.(example|sample|template)$/i;
27
+ const ROOT_LOCKFILE = /^(package-lock\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|Cargo\.lock|poetry\.lock|uv\.lock)$/;
28
+ const ROOT_MANIFEST = /^(package\.json|Cargo\.toml|go\.mod|pyproject\.toml|requirements[\w.-]*\.txt|wrangler(?:\.[\w-]+)?\.(toml|jsonc?)|tsconfig[\w.-]*\.json|.+\.config\.[cm]?[jt]s)$/i;
29
+ const ROOT_DOCS = /^(README|CHANGELOG|CONTRIBUTING|SECURITY|AGENTS|AGENTSAM|CLAUDE|LICENSE)(\..+)?$/i;
30
+
23
31
  /** Usually exclude — dependency / build caches (candidates only). */
24
32
  const CATEGORY_DEPENDENCIES = new Set([
25
33
  'node_modules', '.git', 'dist', 'build', '.next', 'coverage', '.turbo',
@@ -37,6 +45,9 @@ const CATEGORY_DOCS = new Set([
37
45
  'docs', 'examples', 'guides', 'handbook', 'README', 'changelog',
38
46
  ]);
39
47
 
48
+ /** Static/public assets — review before including as searchable source. */
49
+ const CATEGORY_ASSETS = new Set(['public', 'static']);
50
+
40
51
  /** Tooling / CI — review before including. */
41
52
  const CATEGORY_TOOLING = new Set([
42
53
  'bin', 'scripts', 'tools', '.github', '.changeset', '.husky', '.vscode',
@@ -45,22 +56,95 @@ const CATEGORY_TOOLING = new Set([
45
56
 
46
57
  /** Generated / historical — review before including. */
47
58
  const CATEGORY_GENERATED = new Set([
48
- 'generated', 'fixtures', 'snapshots', 'artifacts', 'public', 'static',
59
+ 'generated', 'fixtures', 'snapshots', 'artifacts',
49
60
  'site', 'sites', 'templates', 'level-1', 'focus-timer',
50
61
  ]);
51
62
 
52
63
  /** AgentSam / config control plane — review. */
53
64
  const CATEGORY_CONFIG = new Set([
54
- '.agentsam', 'migrations', 'registry', 'wrangler', 'deploy',
65
+ 'migrations', 'registry', 'wrangler', 'deploy',
55
66
  ]);
56
67
 
68
+ const CATEGORY_OPERATIONAL = new Set(['.agentsam']);
69
+
57
70
  const SUGGEST_EXCLUDE_NAMES = CATEGORY_DEPENDENCIES;
58
71
 
59
- function classifyTopLevel(name) {
72
+ function cargoWorkspaceSourceRoots(root) {
73
+ const manifest = path.join(root, 'Cargo.toml');
74
+ let text;
75
+ try { text = fs.readFileSync(manifest, 'utf8'); } catch { return []; }
76
+
77
+ let inWorkspace = false;
78
+ let collectingMembers = false;
79
+ let membersText = '';
80
+
81
+ for (const rawLine of text.split(String.fromCharCode(10))) {
82
+ const line = rawLine.trim();
83
+ if (line.startsWith('[') && line.endsWith(']')) {
84
+ inWorkspace = line === '[workspace]';
85
+ collectingMembers = false;
86
+ continue;
87
+ }
88
+ if (!inWorkspace) continue;
89
+
90
+ if (!collectingMembers && line.startsWith('members')) {
91
+ const equals = line.indexOf('=');
92
+ if (equals < 0) continue;
93
+ membersText = line.slice(equals + 1).trim();
94
+ collectingMembers = !membersText.includes(']');
95
+ } else if (collectingMembers) {
96
+ membersText += ' ' + line;
97
+ collectingMembers = !line.includes(']');
98
+ }
99
+
100
+ if (membersText && !collectingMembers) break;
101
+ }
102
+
103
+ const open = membersText.indexOf('[');
104
+ const close = membersText.lastIndexOf(']');
105
+ if (open < 0 || close <= open) return [];
106
+
107
+ const members = [];
108
+ const body = membersText.slice(open + 1, close);
109
+ let quote = '';
110
+ let value = '';
111
+ for (const char of body) {
112
+ if (!quote && (char === '"' || char === "'")) {
113
+ quote = char;
114
+ value = '';
115
+ continue;
116
+ }
117
+ if (quote && char === quote) {
118
+ members.push(value);
119
+ quote = '';
120
+ value = '';
121
+ continue;
122
+ }
123
+ if (quote) value += char;
124
+ }
125
+
126
+ const roots = [];
127
+ for (let member of members) {
128
+ member = member.trim();
129
+ if (member.startsWith('./')) member = member.slice(2);
130
+ if (!member || member === '.') continue;
131
+ let rootName = member.split('/')[0];
132
+ const wildcardPositions = ['?', '*', '[', '{']
133
+ .map((token) => rootName.indexOf(token))
134
+ .filter((index) => index >= 0);
135
+ if (wildcardPositions.length) rootName = rootName.slice(0, Math.min(...wildcardPositions));
136
+ if (rootName && fs.existsSync(path.join(root, rootName))) roots.push(rootName);
137
+ }
138
+ return [...new Set(roots)].sort();
139
+ }
140
+
141
+ function classifyTopLevel(name, sourceRoots = []) {
60
142
  if (CATEGORY_DEPENDENCIES.has(name)) return 'dependencies';
61
- if (CATEGORY_SOURCE.has(name)) return 'source';
143
+ if (sourceRoots.includes(name) || CATEGORY_SOURCE.has(name)) return 'source';
62
144
  if (CATEGORY_DOCS.has(name)) return 'docs';
145
+ if (CATEGORY_ASSETS.has(name)) return 'assets';
63
146
  if (CATEGORY_GENERATED.has(name)) return 'generated';
147
+ if (CATEGORY_OPERATIONAL.has(name)) return 'operational';
64
148
  if (CATEGORY_CONFIG.has(name)) return 'config';
65
149
  if (CATEGORY_TOOLING.has(name)) return 'tooling';
66
150
  if (/^(old|legacy|archive|backup|tmp|temp)/i.test(name)) return 'historical';
@@ -68,6 +152,66 @@ function classifyTopLevel(name) {
68
152
  return 'unknown';
69
153
  }
70
154
 
155
+ function isGitIgnored(root, relPath) {
156
+ try {
157
+ execFileSync('git', ['check-ignore', '-q', '--', relPath], {
158
+ cwd: root,
159
+ stdio: 'ignore',
160
+ });
161
+ return true;
162
+ } catch {
163
+ return false;
164
+ }
165
+ }
166
+
167
+ function directoryEvidence(entries, name) {
168
+ const prefix = `${name}/`;
169
+ const evidence = { code: 0, docs: 0, data: 0, media: 0 };
170
+ for (const entry of entries) {
171
+ if (entry.kind !== 'file' || !entry.path.startsWith(prefix)) continue;
172
+ const sourceType = sourceTypeForExtension(entry.ext);
173
+ if (sourceType?.kind === 'code') evidence.code += 1;
174
+ else if (sourceType?.id === 'markdown' || sourceType?.id === 'text') evidence.docs += 1;
175
+ else if (sourceType?.kind === 'document') evidence.data += 1;
176
+ else if (entry.media === 'image' || entry.media === 'model3d') evidence.media += 1;
177
+ }
178
+ return evidence;
179
+ }
180
+
181
+ function classifyByEvidence(root, name, entries) {
182
+ if (isGitIgnored(root, name)) return name.startsWith('.') ? 'operational' : 'generated';
183
+ const evidence = directoryEvidence(entries, name);
184
+ const ranked = [
185
+ ['source', evidence.code],
186
+ ['docs', evidence.docs],
187
+ ['data', evidence.data],
188
+ ['assets', evidence.media],
189
+ ].sort((a, b) => b[1] - a[1]);
190
+ return ranked[0][1] > 0 ? ranked[0][0] : null;
191
+ }
192
+
193
+ function classifyRootFile(entry) {
194
+ const name = entry.name;
195
+ if (ROOT_SECRET.test(name) && !ROOT_TEMPLATE.test(name)) return 'secret';
196
+ if (ROOT_LOCKFILE.test(name)) return 'lockfile';
197
+ if (ROOT_MANIFEST.test(name)) return 'manifest';
198
+ if (ROOT_DOCS.test(name)) return 'docs';
199
+ return sourceTypeForExtension(entry.ext)?.kind === 'code' ? 'source' : 'config';
200
+ }
201
+
202
+ function isGitTrackedPath(root, relPath) {
203
+ try {
204
+ const output = execFileSync('git', ['ls-files', '-z', '--', relPath], {
205
+ cwd: root,
206
+ encoding: 'utf8',
207
+ stdio: ['ignore', 'pipe', 'ignore'],
208
+ });
209
+ return Boolean(output);
210
+ } catch {
211
+ return false;
212
+ }
213
+ }
214
+
71
215
  function walk(root, rel = '', acc = [], depth = 0) {
72
216
  if (depth > 6 || acc.length > 8000) return acc;
73
217
  const abs = rel ? path.join(root, rel) : root;
@@ -80,7 +224,9 @@ function walk(root, rel = '', acc = [], depth = 0) {
80
224
  const full = path.join(root, child);
81
225
  if (ent.isDirectory()) {
82
226
  acc.push({ path: child, kind: 'directory', name: ent.name });
83
- if (!SUGGEST_EXCLUDE_NAMES.has(ent.name)) walk(root, child, acc, depth + 1);
227
+ if (SUGGEST_EXCLUDE_NAMES.has(ent.name)) continue;
228
+ if (depth === 0 && isGitIgnored(root, child)) continue;
229
+ walk(root, child, acc, depth + 1);
84
230
  } else if (ent.isFile()) {
85
231
  let bytes = 0;
86
232
  try { bytes = fs.statSync(full).size; } catch { /* ignore */ }
@@ -91,7 +237,7 @@ function walk(root, rel = '', acc = [], depth = 0) {
91
237
  name: ent.name,
92
238
  ext,
93
239
  bytes,
94
- language: EXT_LANG.get(ext) || null,
240
+ language: sourceLanguageForExtension(ext),
95
241
  media: IMAGE.has(ext) ? 'image' : MODEL3D.has(ext) ? 'model3d' : ARCHIVE.has(ext) ? 'archive' : null,
96
242
  });
97
243
  }
@@ -121,13 +267,41 @@ export function buildInventory(opts) {
121
267
  const files = entries.filter((e) => e.kind === 'file');
122
268
  const dirs = entries.filter((e) => e.kind === 'directory');
123
269
  const top = dirs.filter((d) => !d.path.includes('/')).map((d) => d.name);
270
+ const rootEntries = files.filter((f) => !f.path.includes('/'));
271
+ const cargoWorkspaceRoots = cargoWorkspaceSourceRoots(root);
124
272
  const languages = {};
273
+ const topLevelDetails = {};
274
+ let styleEvidence = null;
125
275
  let locTotal = 0;
276
+ for (const name of top) {
277
+ topLevelDetails[name] = {
278
+ files: 0,
279
+ loc: 0,
280
+ dominant_language: null,
281
+ language_loc: {},
282
+ evidence: directoryEvidence(entries, name),
283
+ };
284
+ }
126
285
  for (const f of files.slice(0, opts.maxFiles || 4000)) {
286
+ const topName = f.path.includes('/') ? f.path.split('/')[0] : null;
287
+ if (topName && topLevelDetails[topName]) topLevelDetails[topName].files += 1;
288
+
289
+ const style = inspectStyleEvidenceFile(root, f.path);
290
+ if (style) styleEvidence = mergeStyleEvidence(styleEvidence, style);
291
+
127
292
  if (!f.language) continue;
128
293
  const loc = countLoc(root, f.path);
129
294
  languages[f.language] = (languages[f.language] || 0) + loc;
130
295
  locTotal += loc;
296
+ if (topName && topLevelDetails[topName]) {
297
+ const detail = topLevelDetails[topName];
298
+ detail.loc += loc;
299
+ detail.language_loc[f.language] = (detail.language_loc[f.language] || 0) + loc;
300
+ }
301
+ }
302
+ for (const detail of Object.values(topLevelDetails)) {
303
+ const ranked = Object.entries(detail.language_loc).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
304
+ detail.dominant_language = ranked[0]?.[0] || null;
131
305
  }
132
306
  const images = files.filter((f) => f.media === 'image').length;
133
307
  const models3d = files.filter((f) => f.media === 'model3d').length;
@@ -138,28 +312,63 @@ export function buildInventory(opts) {
138
312
  const categories = {
139
313
  source: [],
140
314
  docs: [],
315
+ data: [],
316
+ assets: [],
141
317
  config: [],
142
318
  generated: [],
143
319
  dependencies: [],
320
+ operational: [],
144
321
  tooling: [],
145
322
  historical: [],
146
323
  unknown: [],
147
324
  };
148
325
  for (const name of top) {
149
- categories[classifyTopLevel(name)].push(name);
326
+ let category;
327
+ if (isGitIgnored(root, name)) {
328
+ category = name.startsWith('.') ? 'operational' : 'generated';
329
+ } else {
330
+ category = classifyTopLevel(name, cargoWorkspaceRoots);
331
+ if (category === 'unknown') category = classifyByEvidence(root, name, entries) || category;
332
+ }
333
+ categories[category].push(name);
150
334
  }
151
335
 
336
+ const rootFiles = {
337
+ manifest: [],
338
+ docs: [],
339
+ source: [],
340
+ config: [],
341
+ lockfile: [],
342
+ secret: [],
343
+ };
344
+ for (const entry of rootEntries) rootFiles[classifyRootFile(entry)].push(entry.path);
345
+ for (const values of Object.values(rootFiles)) values.sort();
346
+
347
+ const topLanguages = Object.entries(languages)
348
+ .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
349
+ .slice(0, 2)
350
+ .map(([language]) => language);
351
+ const promotedTooling = categories.tooling.filter((name) => {
352
+ const detail = topLevelDetails[name];
353
+ return isGitTrackedPath(root, name)
354
+ && topLanguages.some((language) => (detail?.language_loc?.[language] || 0) > 0);
355
+ });
356
+
152
357
  const primaryInclude = [
153
358
  ...categories.source,
154
359
  ...categories.docs,
360
+ ...promotedTooling,
155
361
  ];
156
362
  const reviewInclude = [
363
+ ...categories.data,
364
+ ...categories.assets,
157
365
  ...categories.config,
158
366
  ...categories.generated,
159
- ...categories.tooling.filter((n) => n === 'test' || n === 'tests' || n === 'scripts'),
367
+ ...categories.tooling.filter((n) => !promotedTooling.includes(n)),
160
368
  ];
161
369
  const usuallyExclude = [
162
370
  ...categories.dependencies,
371
+ ...categories.operational,
163
372
  ...categories.tooling.filter((n) => !reviewInclude.includes(n) && n !== 'scripts' && n !== 'test' && n !== 'tests'),
164
373
  ...categories.historical,
165
374
  ];
@@ -169,6 +378,11 @@ export function buildInventory(opts) {
169
378
  const suggestedInclude = (primaryInclude.length ? primaryInclude : top.filter((n) => !CATEGORY_DEPENDENCIES.has(n))).slice(0, 24);
170
379
  if (!suggestedInclude.length) suggestedInclude.push('.');
171
380
  const suggestedExclude = [...new Set(usuallyExclude)];
381
+ const suggestedIncludeFiles = [
382
+ ...rootFiles.manifest,
383
+ ...rootFiles.docs,
384
+ ...rootFiles.source,
385
+ ];
172
386
 
173
387
  /** @type {object} */
174
388
  const inventory = {
@@ -185,10 +399,15 @@ export function buildInventory(opts) {
185
399
  package_manifests: packageManifests,
186
400
  },
187
401
  languages,
402
+ style_evidence: finalizeStyleEvidence(styleEvidence),
403
+ cargo_workspace_roots: cargoWorkspaceRoots,
188
404
  top_level: top,
405
+ top_level_details: topLevelDetails,
189
406
  categories,
407
+ root_files: rootFiles,
190
408
  suggested: {
191
409
  include: suggestedInclude,
410
+ include_files: suggestedIncludeFiles,
192
411
  exclude: suggestedExclude,
193
412
  review: reviewInclude,
194
413
  note: 'Categories are machine inventory. Suggestions are advisory — no exclusions applied automatically. User confirmations are authoritative.',
@@ -212,8 +431,12 @@ export function formatInventoryTree(inventory) {
212
431
  const cat = inventory.categories
213
432
  ? Object.entries(inventory.categories).find(([, names]) => names.includes(name))?.[0]
214
433
  : null;
434
+ const detail = inventory.top_level_details?.[name];
215
435
  const mark = cat ? ` · ${cat}` : '';
216
- lines.push(`├── ${name}/${mark}`);
436
+ const evidence = detail
437
+ ? ` · ${detail.files} files · LOC~${detail.loc}${detail.dominant_language ? ` · ${detail.dominant_language}` : ''}`
438
+ : '';
439
+ lines.push(`├── ${name}/${mark}${evidence}`);
217
440
  }
218
441
  if (inventory.top_level.length > 24) lines.push('└── …');
219
442
  lines.push('');
@@ -226,6 +449,17 @@ export function formatInventoryTree(inventory) {
226
449
  lines.push('Detected');
227
450
  lines.push(` ${inventory.counts.package_manifests} package.json`);
228
451
  lines.push(` ${inventory.counts.images} images · ${inventory.counts.models3d} 3D · ${inventory.counts.archives} archives`);
452
+ const style = inventory.style_evidence;
453
+ if (style?.theme_candidate) {
454
+ const presets = Object.keys(style.theme_presets || {});
455
+ const namespaces = (style.namespaces || []).filter((row) => row.candidate).slice(0, 5);
456
+ lines.push(` theme evidence presets=${presets.join(', ') || '(none)'} namespaces=${namespaces.map((row) => row.prefix).join(', ') || '(none)'}`);
457
+ }
458
+ lines.push('');
459
+ lines.push('Root files');
460
+ for (const [kind, names] of Object.entries(inventory.root_files || {})) {
461
+ if (names.length) lines.push(` ${kind.padEnd(10)} ${names.join(', ')}`);
462
+ }
229
463
  lines.push('');
230
464
  lines.push('Recommended scope candidates');
231
465
  lines.push(` Primary source ${(inventory.categories?.source || []).join(', ') || '(none)'}`);
@@ -235,8 +469,9 @@ export function formatInventoryTree(inventory) {
235
469
  lines.push(' (No exclusions applied automatically.)');
236
470
  lines.push('');
237
471
  lines.push('Starting suggestion (editable)');
238
- lines.push(` include: ${(inventory.suggested.include || []).join(', ') || '(none)'}`);
239
- lines.push(` exclude: ${(inventory.suggested.exclude || []).join(', ') || '(none)'}`);
472
+ lines.push(` include dirs: ${(inventory.suggested.include || []).join(', ') || '(none)'}`);
473
+ lines.push(` include files: ${(inventory.suggested.include_files || []).join(', ') || '(none)'}`);
474
+ lines.push(` exclude: ${(inventory.suggested.exclude || []).join(', ') || '(none)'}`);
240
475
  return lines.join('\n');
241
476
  }
242
477
 
@@ -7,17 +7,11 @@ import fs from 'node:fs';
7
7
  import path from 'node:path';
8
8
  import { createHash, randomUUID } from 'node:crypto';
9
9
  import { execFileSync, spawnSync } from 'node:child_process';
10
+ import { isCodeSourceExtension, isDocumentSourceExtension } from '../../../packages/agentsam-repository/src/source-types.js';
10
11
 
11
12
  const ARCHIVE_EXT = new Set(['.zip', '.tar', '.tgz', '.gz', '.tar.gz', '.tbz2', '.tar.bz2']);
12
13
  const IMAGE_EXT = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg', '.ico', '.bmp', '.avif']);
13
14
  const MODEL_3D_EXT = new Set(['.glb', '.gltf', '.obj', '.fbx', '.stl', '.usdz']);
14
- const DOC_EXT = new Set(['.html', '.htm', '.md', '.txt', '.css', '.scss', '.json', '.xml', '.csv']);
15
- const CODE_EXT = new Set([
16
- '.js', '.mjs', '.cjs', '.ts', '.tsx', '.jsx', '.py', '.go', '.rs', '.java', '.kt',
17
- '.swift', '.c', '.h', '.cpp', '.cc', '.cs', '.rb', '.php', '.sql', '.sh', '.bash',
18
- '.zsh', '.yaml', '.yml', '.toml', '.vue', '.svelte',
19
- ]);
20
-
21
15
  function clean(value) {
22
16
  return value == null ? '' : String(value).trim();
23
17
  }
@@ -62,8 +56,8 @@ export function classifyMaterial(filePath) {
62
56
  else if (ARCHIVE_EXT.has(ext) || resolved.toLowerCase().endsWith('.tar.gz')) kind = 'archive';
63
57
  else if (IMAGE_EXT.has(ext)) kind = 'image';
64
58
  else if (MODEL_3D_EXT.has(ext)) kind = 'model3d';
65
- else if (DOC_EXT.has(ext)) kind = 'document';
66
- else if (CODE_EXT.has(ext)) kind = 'code';
59
+ else if (isDocumentSourceExtension(ext)) kind = 'document';
60
+ else if (isCodeSourceExtension(ext)) kind = 'code';
67
61
  else if (stat?.isFile()) kind = 'file';
68
62
  return {
69
63
  path: resolved,
@@ -0,0 +1,181 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ const TEXT_EXT = new Set([
5
+ '.html', '.htm', '.css', '.scss',
6
+ '.js', '.mjs', '.cjs', '.jsx', '.ts', '.tsx',
7
+ '.vue', '.svelte',
8
+ ]);
9
+
10
+ function bump(map, key, amount = 1) {
11
+ if (!key) return;
12
+ map.set(key, (map.get(key) || 0) + amount);
13
+ }
14
+
15
+ function namespaceOf(token) {
16
+ const match = /^([a-z][a-z0-9]{1,15})[-_][a-z0-9]/i.exec(token);
17
+ return match?.[1]?.toLowerCase() || null;
18
+ }
19
+
20
+ export function extractStyleEvidence(text) {
21
+ const source = String(text || '');
22
+ const namespaces = new Map();
23
+ const namespaceSignals = new Map();
24
+ const themePresets = new Map();
25
+ const headerPresets = new Map();
26
+ const dataAttributes = new Map();
27
+ const stylesheets = new Map();
28
+ const customProperties = new Map();
29
+
30
+ const signal = (prefix, kind) => {
31
+ if (!prefix || prefix.length < 2) return;
32
+ bump(namespaces, prefix);
33
+ const row = namespaceSignals.get(prefix) || {};
34
+ row[kind] = (row[kind] || 0) + 1;
35
+ namespaceSignals.set(prefix, row);
36
+ };
37
+
38
+ for (const match of source.matchAll(/\bclass\s*=\s*["']([^"']+)["']/gi)) {
39
+ for (const token of match[1].split(/\s+/).filter(Boolean)) {
40
+ signal(namespaceOf(token), 'class_tokens');
41
+ }
42
+ }
43
+
44
+ for (const match of source.matchAll(/\.([a-zA-Z][\w-]*)/g)) {
45
+ signal(namespaceOf(match[1]), 'css_selectors');
46
+ }
47
+
48
+ for (const match of source.matchAll(/--([a-zA-Z][a-zA-Z0-9_-]*)\s*:/g)) {
49
+ const token = match[1].toLowerCase();
50
+ bump(customProperties, '--' + token);
51
+ signal(namespaceOf(token), 'custom_properties');
52
+ }
53
+
54
+ const literalAttributeValue = (value) => {
55
+ const trimmed = String(value || '').trim();
56
+ if (!trimmed || trimmed.includes('${') || trimmed.includes('{{') || trimmed.includes('<%')) return null;
57
+ return trimmed;
58
+ };
59
+
60
+ for (const match of source.matchAll(/\bdata-theme-preset\s*=\s*["']([^"']+)["']/gi)) {
61
+ bump(themePresets, literalAttributeValue(match[1]));
62
+ }
63
+ for (const match of source.matchAll(/\bdata-header-preset\s*=\s*["']([^"']+)["']/gi)) {
64
+ bump(headerPresets, literalAttributeValue(match[1]));
65
+ }
66
+ for (const match of source.matchAll(/\b(data-[a-z0-9_-]+)(?:\s*=|\s|>)/gi)) {
67
+ bump(dataAttributes, match[1].toLowerCase());
68
+ }
69
+ for (const match of source.matchAll(/<link\b[^>]*\brel\s*=\s*["']stylesheet["'][^>]*\bhref\s*=\s*["']([^"']+)["'][^>]*>/gi)) {
70
+ bump(stylesheets, match[1]);
71
+ }
72
+ for (const match of source.matchAll(/<link\b[^>]*\bhref\s*=\s*["']([^"']+)["'][^>]*\brel\s*=\s*["']stylesheet["'][^>]*>/gi)) {
73
+ bump(stylesheets, match[1]);
74
+ }
75
+
76
+ const namespaceRows = [...namespaces.entries()]
77
+ .map(([prefix, occurrences]) => {
78
+ const signals = namespaceSignals.get(prefix) || {};
79
+ const signalKinds = Object.keys(signals).length;
80
+ const score = occurrences + (signalKinds * 3);
81
+ return { prefix, occurrences, signal_kinds: signalKinds, signals, score };
82
+ })
83
+ .filter((row) => row.occurrences >= 2 || row.signal_kinds >= 2)
84
+ .sort((a, b) => b.score - a.score || a.prefix.localeCompare(b.prefix));
85
+
86
+ return {
87
+ theme_presets: Object.fromEntries([...themePresets.entries()].sort()),
88
+ header_presets: Object.fromEntries([...headerPresets.entries()].sort()),
89
+ namespaces: namespaceRows,
90
+ data_attributes: Object.fromEntries([...dataAttributes.entries()].sort()),
91
+ stylesheets: Object.fromEntries([...stylesheets.entries()].sort()),
92
+ custom_properties: Object.fromEntries([...customProperties.entries()].sort()),
93
+ };
94
+ }
95
+
96
+ export function mergeStyleEvidence(target, incoming) {
97
+ const merged = target || {
98
+ theme_presets: {},
99
+ header_presets: {},
100
+ namespaces: {},
101
+ data_attributes: {},
102
+ stylesheets: {},
103
+ custom_properties: {},
104
+ files_scanned: 0,
105
+ };
106
+ merged.files_scanned += 1;
107
+
108
+ for (const key of ['theme_presets', 'header_presets', 'data_attributes', 'stylesheets', 'custom_properties']) {
109
+ for (const [name, count] of Object.entries(incoming[key] || {})) {
110
+ merged[key][name] = (merged[key][name] || 0) + count;
111
+ }
112
+ }
113
+
114
+ for (const row of incoming.namespaces || []) {
115
+ const current = merged.namespaces[row.prefix] || {
116
+ occurrences: 0,
117
+ signal_kinds: new Set(),
118
+ signals: {},
119
+ score: 0,
120
+ };
121
+ current.occurrences += row.occurrences;
122
+ for (const [kind, count] of Object.entries(row.signals || {})) {
123
+ current.signals[kind] = (current.signals[kind] || 0) + count;
124
+ current.signal_kinds.add(kind);
125
+ }
126
+ merged.namespaces[row.prefix] = current;
127
+ }
128
+ return merged;
129
+ }
130
+
131
+ export function finalizeStyleEvidence(merged) {
132
+ const namespaces = Object.entries(merged?.namespaces || {})
133
+ .map(([prefix, row]) => {
134
+ const signalKinds = row.signal_kinds instanceof Set
135
+ ? row.signal_kinds.size
136
+ : Number(row.signal_kinds || 0);
137
+ const score = row.occurrences + (signalKinds * 3);
138
+ const classTokens = row.signals?.class_tokens || 0;
139
+ const cssSelectors = row.signals?.css_selectors || 0;
140
+ const customProperties = row.signals?.custom_properties || 0;
141
+ return {
142
+ prefix,
143
+ occurrences: row.occurrences,
144
+ signal_kinds: signalKinds,
145
+ signals: row.signals,
146
+ score,
147
+ candidate: prefix.length >= 3
148
+ && classTokens >= 2
149
+ && cssSelectors >= 2
150
+ && customProperties >= 2,
151
+ };
152
+ })
153
+ .sort((a, b) => b.score - a.score || a.prefix.localeCompare(b.prefix));
154
+
155
+ const explicitPresets = Object.keys(merged?.theme_presets || {});
156
+ return {
157
+ files_scanned: merged?.files_scanned || 0,
158
+ theme_presets: merged?.theme_presets || {},
159
+ header_presets: merged?.header_presets || {},
160
+ namespaces,
161
+ data_attributes: merged?.data_attributes || {},
162
+ stylesheets: merged?.stylesheets || {},
163
+ custom_properties: merged?.custom_properties || {},
164
+ theme_candidate: explicitPresets.length > 0 || namespaces.some((row) => row.candidate),
165
+ };
166
+ }
167
+
168
+ export function inspectStyleEvidenceFile(root, filePath, maxBytes = 512_000) {
169
+ const ext = path.extname(filePath).toLowerCase();
170
+ if (!TEXT_EXT.has(ext)) return null;
171
+ const full = path.join(root, filePath);
172
+ try {
173
+ const stat = fs.statSync(full);
174
+ if (!stat.isFile() || stat.size > maxBytes) return null;
175
+ const text = fs.readFileSync(full, 'utf8');
176
+ if (text.includes('\0')) return null;
177
+ return extractStyleEvidence(text);
178
+ } catch {
179
+ return null;
180
+ }
181
+ }
@@ -3,11 +3,11 @@ import path from 'node:path';
3
3
  import { execFileSync } from 'node:child_process';
4
4
  import ts from 'typescript';
5
5
  import { fileHasher } from '../../packages/agentsam-repository/src/merkle/hash.js';
6
+ import { isKnowledgeSourcePath } from '../../packages/agentsam-repository/src/source-types.js';
6
7
  import { fingerprint } from './config.js';
7
8
 
8
9
  export const PARSER = `typescript:${ts.version}:agentsam-1`;
9
- const EXTENSIONS = /\.(?:[cm]?[jt]sx?|md|mdx|sql|json)$/i;
10
- const OMIT = /(^|\/)(?:\.git|\.agentsam|node_modules|dist|build|coverage|vendor|\.next|\.wrangler|\.venv|__pycache__)(\/|$)|(^|\/)(?:\.env[^/]*|\.dev\.vars[^/]*|package-lock\.json|pnpm-lock\.yaml|yarn\.lock|[^/]*\.(?:min\.js|map))$/i;
10
+ const OMIT = /(^|\/)(?:\.git|\.agentsam|node_modules|dist|build|coverage|vendor|\.next|\.wrangler|\.venv|__pycache__)(\/|$)|(^|\/)(?:\.env[^/]*|\.dev\.vars[^/]*|package-lock\.json|npm-shrinkwrap\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb?|Cargo\.lock|poetry\.lock|uv\.lock|[^/]*\.(?:pem|key|p12|pfx|min\.js|map))$/i;
11
11
  const under = (file, scope) => scope === '.' || file === scope || file.startsWith(scope + '/');
12
12
  export function inventory(root, scope) {
13
13
  let files;
@@ -24,7 +24,7 @@ export function inventory(root, scope) {
24
24
  };
25
25
  walk();
26
26
  }
27
- return [...new Set(files)].filter(file => EXTENSIONS.test(file) && !OMIT.test(file) && scope.include.some(s => under(file, s)) && !scope.exclude.some(s => under(file, s))).sort();
27
+ return [...new Set(files)].filter(file => isKnowledgeSourcePath(file) && !OMIT.test(file) && scope.include.some(s => under(file, s)) && !scope.exclude.some(s => under(file, s))).sort();
28
28
  }
29
29
  export function readSource(root, file) {
30
30
  // Refuse all symlink components, including tracked links into another repository.
@@ -122,8 +122,15 @@ export function resolveAccountApiKey(options = {}) {
122
122
  const explicit = clean(options.explicit);
123
123
  const value = resolveApiKey(env, explicit);
124
124
  if (!value) return { value: '', source: null, kind: null };
125
- if (!isApiKey(value)) return { value: '', source: explicit ? 'explicit' : 'environment', kind: 'api_key', error: 'invalid_api_key_prefix' };
126
- return { value, source: explicit ? 'explicit' : 'environment', kind: 'api_key' };
125
+ if (!isApiKey(value)) {
126
+ return {
127
+ value: '',
128
+ source: explicit ? 'explicit' : 'environment',
129
+ kind: 'agentsam_api_key',
130
+ error: 'invalid_api_key_prefix',
131
+ };
132
+ }
133
+ return { value, source: explicit ? 'explicit' : 'environment', kind: 'agentsam_api_key' };
127
134
  }
128
135
 
129
136
  export function resolveBrowserSessionCredential(options = {}) {
@@ -133,7 +140,7 @@ export function resolveBrowserSessionCredential(options = {}) {
133
140
  return {
134
141
  value: expired ? '' : session.access_token,
135
142
  source: 'agentsam_browser_oauth',
136
- kind: 'browser_oauth',
143
+ kind: 'agentsam_browser_oauth',
137
144
  session,
138
145
  expired,
139
146
  error: expired ? 'browser_oauth_session_expired' : null,
@@ -162,7 +169,7 @@ export function describeAccountSession(options = {}) {
162
169
  return {
163
170
  configured: Boolean(session?.access_token),
164
171
  source: session?.access_token ? 'agentsam_browser_oauth' : null,
165
- kind: session?.access_token ? 'browser_oauth' : null,
172
+ kind: session?.access_token ? 'agentsam_browser_oauth' : null,
166
173
  refreshable: Boolean(session?.refresh_token),
167
174
  expires_at: session?.expires_at || null,
168
175
  expired: session ? isBrowserSessionExpired(session, options) : false,