@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.
- package/AGENTSAM.md +11 -0
- package/README.md +15 -9
- package/apps/client-cms-editor/AGENTS.md +12 -0
- package/apps/client-cms-editor/IMPORT_PROVENANCE.json +8 -0
- package/apps/client-cms-editor/README.md +72 -0
- package/apps/client-cms-editor/agentsam.app.json +57 -0
- package/apps/client-cms-editor/backend/README.md +5 -0
- package/apps/client-cms-editor/backend/package.json +22 -0
- package/apps/client-cms-editor/backend/src/api/client.ts +200 -0
- package/apps/client-cms-editor/backend/src/demo-bootstrap.ts +145 -0
- package/apps/client-cms-editor/backend/src/index.ts +6 -0
- package/apps/client-cms-editor/backend/src/model.ts +115 -0
- package/apps/client-cms-editor/backend/src/preview/bridge.ts +79 -0
- package/apps/client-cms-editor/backend/src/preview/urls.ts +55 -0
- package/apps/client-cms-editor/backend/src/routing/cms-route.js +293 -0
- package/apps/client-cms-editor/backend/src/routing/index.js +10 -0
- package/apps/client-cms-editor/backend/src/storefront.ts +52 -0
- package/apps/client-cms-editor/backend/tsconfig.json +15 -0
- package/apps/client-cms-editor/backend/worker/index.js +34 -0
- package/apps/client-cms-editor/backend/wrangler.jsonc +11 -0
- package/apps/client-cms-editor/bin/agentsam-cms.mjs +229 -0
- package/apps/client-cms-editor/frontend/index.html +12 -0
- package/apps/client-cms-editor/frontend/package.json +33 -0
- package/apps/client-cms-editor/frontend/src/AgentSamDrawer.tsx +188 -0
- package/apps/client-cms-editor/frontend/src/CmsAgentSurface.tsx +191 -0
- package/apps/client-cms-editor/frontend/src/CmsEditor.tsx +1345 -0
- package/apps/client-cms-editor/frontend/src/env.d.ts +14 -0
- package/apps/client-cms-editor/frontend/src/index.ts +8 -0
- package/apps/client-cms-editor/frontend/src/lib/content-safety.ts +63 -0
- package/apps/client-cms-editor/frontend/src/main.tsx +17 -0
- package/apps/client-cms-editor/frontend/src/mount.tsx +51 -0
- package/apps/client-cms-editor/frontend/src/styles/agentsam-drawer.css +214 -0
- package/apps/client-cms-editor/frontend/src/styles/cmsShell.css +1739 -0
- package/apps/client-cms-editor/frontend/src/styles/studio.css +106 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsDashboard.tsx +313 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsGuidedChatHero.tsx +121 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsHubPage.tsx +132 -0
- package/apps/client-cms-editor/frontend/src/surfaces/CmsSiteSwitcher.tsx +176 -0
- package/apps/client-cms-editor/frontend/src/surfaces/index.ts +5 -0
- package/apps/client-cms-editor/frontend/src/surfaces/types.ts +48 -0
- package/apps/client-cms-editor/frontend/tsconfig.json +25 -0
- package/apps/client-cms-editor/frontend/vite.config.ts +13 -0
- package/apps/client-cms-editor/package-lock.json +3832 -0
- package/apps/client-cms-editor/package.json +23 -0
- package/apps/client-cms-editor/reference/DONOR_README.md +52 -0
- package/apps/client-cms-editor/reference/DONOR_package-lock.json +1253 -0
- package/apps/client-cms-editor/reference/DONOR_tsconfig.json +15 -0
- package/apps/client-cms-editor/shared/cms/package.json +21 -0
- package/apps/client-cms-editor/shared/cms/src/agent-context.ts +35 -0
- package/apps/client-cms-editor/shared/cms/src/cloudflare-bindings.ts +51 -0
- package/apps/client-cms-editor/shared/cms/src/editor-types.ts +58 -0
- package/apps/client-cms-editor/shared/cms/src/index.ts +5 -0
- package/apps/client-cms-editor/shared/cms/src/publication.ts +24 -0
- package/apps/client-cms-editor/shared/cms/src/routes.ts +11 -0
- package/apps/client-cms-editor/shared/cms/tsconfig.json +12 -0
- package/bin/agentsam-rapid-rust +36 -0
- package/docs/AUTH_IDENTITY_CONTRACT.md +2 -0
- package/docs/MACHINE_INTELLIGENCE.md +120 -0
- package/docs/WINDOWS_RUNTIME_INSTALL.md +30 -0
- package/docs/architecture/AGENTSAM_APPLICATION_CONTRACT.md +188 -0
- package/docs/architecture/AGENTSAM_RUNTIME_PROTOCOL.md +151 -0
- package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +12 -4
- package/docs/architecture/R2_SLUG_NAMESPACE.md +20 -0
- package/docs/architecture/WORK_PRODUCT_EXTRACTION.md +97 -0
- package/docs/brand/AGENT_SAM_ICON_GRAMMAR.md +70 -0
- package/docs/content-studio/HOST_MOUNT_CHECKLIST.md +71 -0
- package/docs/content-studio/REVISION_GATE_2026-09-27.md +501 -0
- package/docs/contracts/capability-install-planner.md +67 -0
- package/docs/contracts/environment-vocabulary.md +195 -0
- package/docs/contracts/google-cloud-oauth-setup.md +199 -0
- package/docs/local-studio/WORKMODE_DONOR_NOTES.md +1 -1
- package/docs/plans/LOCAL-STUDIO-GRADUATION-2026-09-26.md +290 -0
- package/docs/plans/LOCAL-STUDIO-REAL-APP-CONTRACT-ADDENDUM-2026-09-27.md +394 -0
- package/docs/plans/MACHINE-FIRST-APPS-TUI-2026-09-24.md +227 -0
- package/docs/plans/TOMORROW-EXTENSIVE-TODO-2026-09-26.md +221 -0
- package/docs/plans/TOMORROW-MACHINE-FIRST-BRIEFING.md +145 -0
- package/docs/plans/UNIVERSAL-INGEST-MACHINE-FIRST-2026-09-24.md +215 -0
- package/docs/plugins.md +2 -2
- package/docs/product/AGENTSAM_PRODUCT_EXPERIENCE_STANDARD.md +280 -0
- package/docs/product/LOCAL_STUDIO_DESKTOP_EXPERIENCE.md +139 -0
- package/docs/product/README.md +8 -0
- package/docs/rapid-rust-wasm.md +35 -0
- package/migrations/d1/0016_cloudflare_oauth_user_oauth_tokens_ssot.sql +14 -0
- package/package.json +73 -14
- package/packages/agentsam-brand/README.md +106 -11
- package/packages/agentsam-brand/bin/agentsam-brand.mjs +9 -0
- package/packages/agentsam-brand/package.json +39 -7
- package/packages/agentsam-brand/src/adapters/cloudflare-images.js +453 -0
- package/packages/agentsam-brand/src/adapters/cloudflare-r2.js +74 -0
- package/packages/agentsam-brand/src/adapters/d1-registry.js +26 -0
- package/packages/agentsam-brand/src/adapters/filesystem.js +59 -0
- package/packages/agentsam-brand/src/adapters/memory.js +31 -0
- package/packages/agentsam-brand/src/cli/controller.js +503 -0
- package/packages/agentsam-brand/src/cli/wizard.js +526 -0
- package/packages/agentsam-brand/src/core/capabilities.js +201 -0
- package/packages/agentsam-brand/src/core/derivatives.js +211 -0
- package/packages/agentsam-brand/src/core/errors.js +12 -0
- package/packages/agentsam-brand/src/core/ingest.js +195 -0
- package/packages/agentsam-brand/src/core/inspect.js +109 -0
- package/packages/agentsam-brand/src/core/keys.js +83 -0
- package/packages/agentsam-brand/src/core/naming.js +142 -0
- package/packages/agentsam-brand/src/core/optimize.js +316 -0
- package/packages/agentsam-brand/src/core/pack.js +305 -0
- package/packages/agentsam-brand/src/core/plan.js +276 -0
- package/packages/agentsam-brand/src/core/preview.js +159 -0
- package/packages/agentsam-brand/src/core/processors/cloudflare.js +68 -0
- package/packages/agentsam-brand/src/core/processors/contract.js +203 -0
- package/packages/agentsam-brand/src/core/processors/index.js +148 -0
- package/packages/agentsam-brand/src/core/processors/native.js +82 -0
- package/packages/agentsam-brand/src/core/processors/sharp.js +113 -0
- package/packages/agentsam-brand/src/core/processors/squoosh-binary.js +195 -0
- package/packages/agentsam-brand/src/core/promote.js +288 -0
- package/packages/agentsam-brand/src/core/receipts.js +155 -0
- package/packages/agentsam-brand/src/core/v2/compile.js +280 -0
- package/packages/agentsam-brand/src/core/v2/derivatives-semantic.js +207 -0
- package/packages/agentsam-brand/src/core/v2/ingest-graph.js +387 -0
- package/packages/agentsam-brand/src/core/v2/roles.js +180 -0
- package/packages/agentsam-brand/src/core/v2/schema.js +209 -0
- package/packages/agentsam-brand/src/core/v2/templates.js +114 -0
- package/packages/agentsam-brand/src/index.js +193 -36
- package/packages/agentsam-brand/src/presets/app-icon.json +16 -0
- package/packages/agentsam-brand/src/presets/favicon.json +17 -0
- package/packages/agentsam-brand/src/presets/hero.json +12 -0
- package/packages/agentsam-brand/src/presets/index.js +40 -0
- package/packages/agentsam-brand/src/presets/logo.json +12 -0
- package/packages/agentsam-brand/src/presets/model.json +8 -0
- package/packages/agentsam-brand/src/presets/og-image.json +10 -0
- package/packages/agentsam-brand/src/presets/product-shot.json +11 -0
- package/packages/agentsam-brand/src/presets/social-image.json +10 -0
- package/packages/agentsam-brand/src/presets/web-image.json +10 -0
- package/packages/agentsam-contracts/src/artifacts.ts +41 -0
- package/packages/agentsam-knowledge/src/autorag/index.js +1 -1
- package/packages/agentsam-knowledge/src/providers/index.js +6 -4
- package/packages/agentsam-knowledge/src/providers/ollama-endpoint.js +31 -0
- package/packages/agentsam-knowledge/test/autorag.test.mjs +22 -1
- package/packages/agentsam-nav/package.json +2 -2
- package/packages/agentsam-rapid-rust/Cargo.lock +344 -0
- package/packages/agentsam-rapid-rust/Cargo.toml +18 -0
- package/packages/agentsam-rapid-rust/README.md +5 -0
- package/packages/agentsam-rapid-rust/src/main.rs +718 -0
- package/packages/agentsam-rapid-rust/templates/api/Cargo.toml.tmpl +18 -0
- package/packages/agentsam-rapid-rust/templates/api/src/lib.rs.tmpl +17 -0
- package/packages/agentsam-rapid-rust/templates/common/README.md.tmpl +22 -0
- package/packages/agentsam-rapid-rust/templates/common/package.json.tmpl +12 -0
- package/packages/agentsam-rapid-rust/templates/common/wrangler.toml.tmpl +6 -0
- package/packages/agentsam-rapid-rust/templates/crypto-auth/Cargo.toml.tmpl +21 -0
- package/packages/agentsam-rapid-rust/templates/crypto-auth/src/lib.rs.tmpl +32 -0
- package/packages/agentsam-rapid-rust/templates/data-processor/Cargo.toml.tmpl +18 -0
- package/packages/agentsam-rapid-rust/templates/data-processor/src/lib.rs.tmpl +41 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/Cargo.toml.tmpl +9 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/core/Cargo.toml.tmpl +7 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/core/src/lib.rs.tmpl +23 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/worker/Cargo.toml.tmpl +12 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/worker/src/lib.rs.tmpl +16 -0
- package/packages/agentsam-rapid-rust/templates/shared-core/wrangler.toml.tmpl +6 -0
- package/packages/agentsam-repository/src/index.js +1 -0
- package/packages/agentsam-repository/src/merkle/semantic.js +3 -10
- package/packages/agentsam-repository/src/source-types.js +85 -0
- package/packages/agentsam-vault/README.md +96 -0
- package/packages/agentsam-vault/package.json +32 -0
- package/packages/agentsam-vault/src/contracts/credential.d.ts +78 -0
- package/packages/agentsam-vault/src/contracts/credential.js +132 -0
- package/packages/agentsam-vault/src/crypto/aes-gcm.d.ts +30 -0
- package/packages/agentsam-vault/src/crypto/aes-gcm.js +107 -0
- package/packages/agentsam-vault/src/crypto/oauth-envelope.js +150 -0
- package/packages/agentsam-vault/src/index.d.ts +9 -0
- package/packages/agentsam-vault/src/index.js +27 -0
- package/packages/agentsam-vault/src/providers/registry.js +90 -0
- package/packages/agentsam-vault/src/runtime/resolver.js +77 -0
- package/packages/agentsam-workbench/README.md +24 -0
- package/packages/agentsam-workbench/package.json +38 -0
- package/packages/agentsam-workbench/src/agent/AgentPanel.tsx +41 -0
- package/packages/agentsam-workbench/src/agent/ArtifactCard.tsx +9 -0
- package/packages/agentsam-workbench/src/agent/Composer.tsx +102 -0
- package/packages/agentsam-workbench/src/agent/ConnectedAgentPanel.tsx +194 -0
- package/packages/agentsam-workbench/src/agent/ContextualComposer.tsx +788 -0
- package/packages/agentsam-workbench/src/agent/GoalStatusStrip.tsx +38 -0
- package/packages/agentsam-workbench/src/agent/MiniAgentSam.tsx +86 -0
- package/packages/agentsam-workbench/src/agent/ModelSelect.tsx +19 -0
- package/packages/agentsam-workbench/src/agent/Thread.tsx +56 -0
- package/packages/agentsam-workbench/src/agent/ToolReceipt.tsx +11 -0
- package/packages/agentsam-workbench/src/agent/contextual-composer.css +611 -0
- package/packages/agentsam-workbench/src/agent/index.ts +10 -0
- package/packages/agentsam-workbench/src/agent/mini-agentsam.css +12 -0
- package/packages/agentsam-workbench/src/browser/BrowserFrame.tsx +37 -0
- package/packages/agentsam-workbench/src/browser/index.ts +1 -0
- package/packages/agentsam-workbench/src/index.ts +6 -0
- package/packages/agentsam-workbench/src/project-control.css +160 -0
- package/packages/agentsam-workbench/src/projects/ProjectsSurface.tsx +131 -0
- package/packages/agentsam-workbench/src/projects/index.ts +1 -0
- package/packages/agentsam-workbench/src/shell/Breadcrumb.tsx +35 -0
- package/packages/agentsam-workbench/src/shell/ResizableStage.tsx +99 -0
- package/packages/agentsam-workbench/src/shell/SidePanel.tsx +5 -0
- package/packages/agentsam-workbench/src/shell/index.ts +4 -0
- package/packages/agentsam-workbench/src/shell/surfaceRegistry.ts +29 -0
- package/packages/agentsam-workbench/src/terminal/TerminalSurface.tsx +5 -0
- package/packages/agentsam-workbench/src/terminal/index.ts +1 -0
- package/packages/agentsam-workbench/src/timeline/GanttBoard.tsx +258 -0
- package/packages/agentsam-workbench/src/timeline/index.ts +1 -0
- package/packages/agentsam-workbench/tsconfig.json +13 -0
- package/packages/connectors/cloudflare/OAUTH_STORAGE_AUDIT.md +53 -0
- package/packages/connectors/cloudflare/package.json +3 -1
- package/packages/connectors/cloudflare/src/api-client.js +279 -0
- package/packages/connectors/cloudflare/src/capabilities.js +585 -0
- package/packages/connectors/cloudflare/src/credential.js +318 -0
- package/packages/connectors/cloudflare/src/families/brand-protection.js +123 -0
- package/packages/connectors/cloudflare/src/families/keyless.js +114 -0
- package/packages/connectors/cloudflare/src/families/pages.js +151 -0
- package/packages/connectors/cloudflare/src/families/scanner.js +123 -0
- package/packages/connectors/cloudflare/src/families/snippets.js +207 -0
- package/packages/connectors/cloudflare/src/families/tag-gateway.js +46 -0
- package/packages/connectors/cloudflare/src/families/tags.js +124 -0
- package/packages/connectors/cloudflare/src/families/token-validation.js +95 -0
- package/packages/connectors/cloudflare/src/families/workflows.js +156 -0
- package/packages/connectors/cloudflare/src/index.js +102 -265
- package/packages/connectors/cloudflare/src/oauth-persist.js +336 -0
- package/packages/connectors/cloudflare/src/owner.js +42 -12
- package/packages/connectors/cloudflare/src/permission-options.js +1064 -0
- package/packages/connectors/cloudflare/src/routes.js +309 -144
- package/packages/connectors/cloudflare/src/scope-catalog.js +345 -0
- package/packages/connectors/cloudflare/src/vault.js +2 -2
- package/packages/connectors/cloudflare/tests/capabilities.test.mjs +276 -0
- package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -30
- package/packages/connectors/cloudflare/tests/oauth-persist.test.mjs +125 -0
- package/packages/identity/.agentsam/features/oauth-login-portal/providers.json +22 -2
- package/packages/identity/.agentsam/features/oauth-login-portal/resources.json +10 -4
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +20 -0
- package/packages/identity/README.md +1 -1
- package/packages/identity/backend/README.md +1 -1
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +3 -2
- package/packages/identity/migrations/sqlite/004_identity_oauth_consent_catalog.sql +48 -0
- package/packages/identity/package.json +4 -3
- package/packages/identity/scripts/local-identity-bridge.mjs +184 -0
- package/packages/identity/scripts/preview-auth-portal.mjs +7 -7
- package/packages/identity/src/adapters/cloudflare-d1/index.js +31 -2
- package/packages/identity/src/adapters/sqlite/index.js +4 -1
- package/packages/identity/src/contracts/auth-config.js +28 -8
- package/packages/identity/src/contracts/external-identity.js +1 -1
- package/packages/identity/src/contracts/provider.js +1 -0
- package/packages/identity/src/frontend/auth-portal/README.md +2 -1
- package/packages/identity/src/frontend/auth-portal/pages/login.html +6 -5
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +6 -5
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +6 -5
- package/packages/identity/src/frontend/auth-portal/shared/company-branding.js +1 -1
- package/packages/identity/src/frontend/auth-portal/shared/desktop-identity-bridge.js +207 -0
- package/packages/identity/src/index.js +16 -0
- package/packages/identity/src/migrations/0001_identity_core.sql +19 -2
- package/packages/identity/src/migrations/0003_accounts_ssot.sql +20 -0
- package/packages/identity/src/migrations/README.md +5 -2
- package/packages/identity/src/oauth/README.md +10 -5
- package/packages/identity/src/oauth/consent-view.js +388 -0
- package/packages/identity/src/oauth/credentials.js +31 -11
- package/packages/identity/src/oauth/google-desktop-exchange.js +173 -0
- package/packages/identity/src/providers/cloudflare/oauth.js +3 -4
- package/packages/identity/src/providers/cloudflare/profile.js +49 -14
- package/packages/identity/src/providers/iam/index.js +27 -5
- package/packages/identity/src/server/identity-service.js +31 -2
- package/packages/identity/src/server/worker-router.js +111 -81
- package/packages/identity/tests/auth-config.test.mjs +3 -2
- package/packages/identity/tests/identity-init-scaffold.test.mjs +3 -0
- package/packages/identity/tests/identity-service.test.mjs +16 -0
- package/packages/identity/tests/native-session-worker.test.mjs +64 -0
- package/packages/identity/tests/oauth-consent-view.test.mjs +106 -0
- package/packages/identity/tests/oauth-credentials.test.mjs +17 -4
- package/packages/identity/tests/oauth-presets-accounts-ssot.test.mjs +58 -0
- package/packages/identity/tests/preview-auth-portal.test.mjs +3 -3
- package/packages/runtime-protocol/src/index.js +154 -0
- package/packages/theme-scenes/README.md +164 -0
- package/packages/theme-scenes/package.json +53 -0
- package/packages/theme-scenes/src/blocks/index.js +30 -0
- package/packages/theme-scenes/src/contracts/index.js +286 -0
- package/packages/theme-scenes/src/demos/index.js +65 -0
- package/packages/theme-scenes/src/index.js +75 -0
- package/packages/theme-scenes/src/presets/index.js +263 -0
- package/packages/theme-scenes/src/runtime/compile.js +119 -0
- package/packages/theme-scenes/src/scenes/index.js +146 -0
- package/packages/theme-scenes/src/shell/index.js +47 -0
- package/packages/theme-scenes/src/themes/index.js +129 -0
- package/packages/theme-scenes/src/visuals/index.js +41 -0
- package/packages/theme-scenes/test/theme-scenes.test.mjs +179 -0
- package/packages/work-graph/src/index.js +34 -1
- package/packages/work-graph/src/renderers/gantt-model.js +24 -0
- package/packages/work-graph/test/work-graph.test.mjs +27 -7
- package/protocol/README.md +15 -7
- package/protocol/apps/agentsam.app.v1.schema.json +89 -7
- package/protocol/apps/agentsam.host-install.v1.schema.json +36 -0
- package/protocol/assets/README.md +9 -0
- package/protocol/assets/asset-record.v1.schema.json +64 -0
- package/protocol/runtime/agentsam.runtime.v1.schema.json +75 -0
- package/protocol/scoring/README.md +10 -0
- package/protocol/scoring/scorecard.v1.schema.json +65 -0
- package/protocol/ui/icon-registry.mjs +1 -0
- package/registry/cms-rust-machine-20260928/installable-products.json +31 -0
- package/registry/cms-rust-machine-20260928/manifest.json +22 -0
- package/registry/cms-rust-machine-20260928/migration.sql +237 -0
- package/registry/cms-rust-machine-20260928/receipt.json +21 -0
- package/registry/cms-rust-machine-20260928/receipt.sql +27 -0
- package/scripts/build_rapid_rust_cli.py +83 -0
- package/src/attachments/index.js +6 -0
- package/src/attachments/intake.js +235 -0
- package/src/capabilities/repository-snapshot.js +19 -2
- package/src/cli/command-catalog.js +8 -0
- package/src/cli.js +182 -26
- package/src/commands/account-auth.js +94 -8
- package/src/commands/app.js +307 -3
- package/src/commands/billing.js +127 -0
- package/src/commands/brand.js +74 -60
- package/src/commands/cheat-sheet.js +154 -0
- package/src/commands/cloudflare-login.js +222 -0
- package/src/commands/cloudflare.js +453 -23
- package/src/commands/codebaseindex.js +6 -1
- package/src/commands/compute.js +4 -0
- package/src/commands/connections.js +11 -5
- package/src/commands/credentials.js +116 -0
- package/src/commands/gcloud-auth.js +427 -0
- package/src/commands/google-cloud.js +375 -0
- package/src/commands/identity-init.js +2 -2
- package/src/commands/mcp.js +226 -33
- package/src/commands/ollama.js +3 -2
- package/src/commands/plugins.js +7 -2
- package/src/commands/product.js +36 -0
- package/src/commands/runtime-status.js +28 -9
- package/src/commands/runtime.js +313 -0
- package/src/commands/rust.js +24 -0
- package/src/commands/setup.js +279 -0
- package/src/commands/shell.js +16 -3
- package/src/commands/start-local.js +2 -2
- package/src/commands/terminal.js +171 -0
- package/src/commands/update.js +140 -0
- package/src/commands/whoami.js +329 -65
- package/src/features/resolve.js +1 -0
- package/src/index.js +4 -0
- package/src/indexing/ingest/inventory.js +254 -19
- package/src/indexing/ingest/materials.js +3 -9
- package/src/indexing/ingest/style-evidence.js +181 -0
- package/src/knowledge/source.js +3 -3
- package/src/lib/account-session.js +11 -4
- package/src/lib/app-authority.js +172 -0
- package/src/lib/auth.js +94 -21
- package/src/lib/core-client.js +5 -6
- package/src/lib/credentials-audit.js +451 -0
- package/src/lib/deploy/health.js +24 -6
- package/src/lib/detect-context.js +7 -1
- package/src/lib/google-cloud-connection.js +270 -0
- package/src/lib/google-cloud-inventory.js +385 -0
- package/src/lib/google-desktop-oauth.js +372 -0
- package/src/lib/google-studio-brokered-oauth.js +158 -0
- package/src/lib/identity-scaffold.js +24 -6
- package/src/lib/init-options.js +192 -0
- package/src/lib/local-scaffold.js +48 -16
- package/src/lib/provider-command-remediation.js +308 -0
- package/src/lib/provider-credentials.js +8 -0
- package/src/lib/scaffold/index.js +8 -2
- package/src/lib/scaffold/mcp-server.js +43 -0
- package/src/lib/scaffold/templates/mcp-server/index.js +397 -0
- package/src/lib/scaffold/templates/mcp-server/presets.js +39 -0
- package/src/lib/scaffold/wizards/cms.js +93 -0
- package/src/lib/scaffold/wizards/mcp-server.js +61 -0
- package/src/lib/setup/contract.js +26 -0
- package/src/lib/setup/discover.js +116 -0
- package/src/lib/setup/execute.js +205 -0
- package/src/lib/setup/planner.js +134 -0
- package/src/lib/setup/recipes.js +235 -0
- package/src/lib/setup/runtime-persist.js +197 -0
- package/src/lib/setup/runtime.js +394 -0
- package/src/lib/slash-commands.js +2 -0
- package/src/lib/terminal/machine-identity.js +95 -0
- package/src/lib/terminal-local.js +164 -0
- package/src/lib/terminal-scopes.js +52 -0
- package/src/lib/whoami-capabilities.js +184 -0
- package/src/local-pty/server.js +34 -5
- package/src/mcp/authority.js +58 -108
- package/src/mcp/client-adapters.js +68 -144
- package/src/mcp/client.js +142 -122
- package/src/mcp/cloudflare-bundles.js +225 -0
- package/src/mcp/index.js +12 -0
- package/src/plugins/cloudflare.js +1 -1
- package/src/providers/ollama-chat.js +2 -1
- package/src/sam/types.js +27 -2
- package/src/security/inventory.js +12 -2
- package/src/security/local-vault.js +2 -0
- package/src/security/scan.js +1 -1
- package/test/account-session.test.mjs +3 -3
- package/test/app-authority-context.test.mjs +32 -0
- package/test/cli/codebaseindex-plan-ux.test.mjs +1 -1
- package/test/cli/mcp-client.test.mjs +21 -10
- package/test/cli/runtime-persist.test.mjs +56 -0
- package/test/cli/rust-command.test.mjs +21 -0
- package/test/credentials-audit.test.mjs +113 -0
- package/test/deploy-health-scan.test.mjs +29 -1
- package/test/gcloud-auth.test.mjs +111 -0
- package/test/google-cloud-connection.test.mjs +83 -0
- package/test/google-cloud-inventory.test.mjs +64 -0
- package/test/init-options.test.mjs +35 -0
- package/test/integration/app-command.test.mjs +30 -0
- package/test/integration/cad-project.test.mjs +4 -1
- package/test/integration/cms-app-scaffold.test.mjs +71 -0
- package/test/integration/cms-site-tenancy-contract.test.mjs +3 -2
- package/test/integration/codebaseindex-ingest.test.mjs +48 -0
- package/test/integration/features-resolve.test.mjs +30 -11
- package/test/integration/inspect-path-cli.test.mjs +46 -0
- package/test/integration/inventory-evidence.test.mjs +125 -0
- package/test/integration/runtime-status.integration.test.mjs +2 -1
- package/test/knowledge.test.mjs +35 -1
- package/test/loopback-oauth.test.mjs +53 -0
- package/test/ollama.test.mjs +22 -0
- package/test/security.test.mjs +23 -0
- package/test/setup-planner.test.mjs +74 -0
- package/test/setup-runtime.test.mjs +51 -0
- package/test/terminal/local-pty.mock.test.mjs +3 -1
- package/test/terminal-machine-identity.test.mjs +88 -0
- package/test/whoami-resume.test.mjs +27 -6
- package/packages/agentsam-brand/test/brand-scan.test.mjs +0 -106
- package/packages/work-graph/prototype/README.md +0 -32
- package/packages/work-graph/prototype/data/demo-workgraph.js +0 -47
- package/packages/work-graph/prototype/renderers/timeline-model.js +0 -21
- package/packages/work-graph/prototype/renderers/workgraph-runtime.js +0 -38
- package/packages/work-graph/prototype-gnantt.html +0 -655
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
|
|
9
|
+
async function which(bin) {
|
|
10
|
+
try {
|
|
11
|
+
const cmd = process.platform === 'win32' ? 'where' : 'which';
|
|
12
|
+
const { stdout } = await execFileAsync(cmd, [bin], { timeout: 5000 });
|
|
13
|
+
const path = String(stdout || '').trim().split(/\r?\n/)[0];
|
|
14
|
+
return path || null;
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function versionOf(bin, args = ['--version']) {
|
|
21
|
+
try {
|
|
22
|
+
const { stdout, stderr } = await execFileAsync(bin, args, { timeout: 8000 });
|
|
23
|
+
const text = `${stdout || ''}${stderr || ''}`.trim().split(/\n/)[0];
|
|
24
|
+
return text.slice(0, 120) || null;
|
|
25
|
+
} catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Discover host environment for setup planning.
|
|
32
|
+
*/
|
|
33
|
+
export async function discoverEnvironment(options = {}) {
|
|
34
|
+
const env = options.env || process.env;
|
|
35
|
+
const platform = options.platform || process.platform;
|
|
36
|
+
const arch = options.arch || os.arch();
|
|
37
|
+
const hostname = os.hostname().replace(/\.local$/i, '');
|
|
38
|
+
|
|
39
|
+
const nodeVersion = process.versions.node;
|
|
40
|
+
const brew = platform === 'darwin' || platform === 'linux' ? await which('brew') : null;
|
|
41
|
+
const git = await which('git');
|
|
42
|
+
const docker = await which('docker');
|
|
43
|
+
const gcloud = await which('gcloud');
|
|
44
|
+
const wrangler = await which('wrangler');
|
|
45
|
+
const magick = (await which('magick')) || (await which('convert'));
|
|
46
|
+
const potrace = await which('potrace');
|
|
47
|
+
const ffmpeg = await which('ffmpeg');
|
|
48
|
+
const svgo = await which('svgo');
|
|
49
|
+
|
|
50
|
+
let wranglerVersion = null;
|
|
51
|
+
if (wrangler) wranglerVersion = await versionOf(wrangler, ['--version']);
|
|
52
|
+
else {
|
|
53
|
+
try {
|
|
54
|
+
wranglerVersion = require('wrangler/package.json').version;
|
|
55
|
+
} catch {
|
|
56
|
+
wranglerVersion = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const hostLabel =
|
|
61
|
+
platform === 'darwin' ? 'Mac'
|
|
62
|
+
: platform === 'win32' ? 'PC'
|
|
63
|
+
: 'host';
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
schema_version: 'agentsam-setup-environment-v1',
|
|
67
|
+
hostname,
|
|
68
|
+
host_label: hostLabel,
|
|
69
|
+
platform,
|
|
70
|
+
arch,
|
|
71
|
+
os_release: os.release(),
|
|
72
|
+
node: nodeVersion,
|
|
73
|
+
tools: {
|
|
74
|
+
brew: brew ? { path: brew, version: await versionOf('brew', ['--version']) } : null,
|
|
75
|
+
git: git ? { path: git, version: await versionOf('git', ['--version']) } : null,
|
|
76
|
+
docker: docker ? { path: docker, version: await versionOf('docker', ['--version']) } : null,
|
|
77
|
+
gcloud: gcloud ? { path: gcloud, version: await versionOf('gcloud', ['--version']) } : null,
|
|
78
|
+
wrangler: wrangler || wranglerVersion
|
|
79
|
+
? { path: wrangler, version: wranglerVersion }
|
|
80
|
+
: null,
|
|
81
|
+
magick: magick ? { path: magick, version: await versionOf(magick, ['--version']) } : null,
|
|
82
|
+
potrace: potrace ? { path: potrace, version: await versionOf('potrace', ['-v']) } : null,
|
|
83
|
+
ffmpeg: ffmpeg ? { path: ffmpeg, version: await versionOf('ffmpeg', ['-version']) } : null,
|
|
84
|
+
svgo: svgo ? { path: svgo, version: await versionOf('svgo', ['--version']) } : null,
|
|
85
|
+
},
|
|
86
|
+
env_flags: {
|
|
87
|
+
AGENTSAM_API_KEY: Boolean(String(env.AGENTSAM_API_KEY || '').trim()),
|
|
88
|
+
GOOGLE_CLIENT_ID: Boolean(String(env.GOOGLE_CLIENT_ID || '').trim()),
|
|
89
|
+
GOOGLE_DESKTOP_CLIENT_ID: Boolean(String(env.GOOGLE_DESKTOP_CLIENT_ID || '').trim()),
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function renderEnvironment(env) {
|
|
95
|
+
const lines = [
|
|
96
|
+
'',
|
|
97
|
+
' Environment',
|
|
98
|
+
` ${env.host_label} · ${env.hostname}`,
|
|
99
|
+
` ${env.platform} ${env.arch} · Node ${env.node}`,
|
|
100
|
+
];
|
|
101
|
+
const rows = [
|
|
102
|
+
['Homebrew', env.tools.brew],
|
|
103
|
+
['Git', env.tools.git],
|
|
104
|
+
['Docker', env.tools.docker],
|
|
105
|
+
['Google Cloud CLI', env.tools.gcloud],
|
|
106
|
+
['Wrangler', env.tools.wrangler],
|
|
107
|
+
['ImageMagick', env.tools.magick],
|
|
108
|
+
['Potrace', env.tools.potrace],
|
|
109
|
+
['ffmpeg', env.tools.ffmpeg],
|
|
110
|
+
];
|
|
111
|
+
for (const [label, tool] of rows) {
|
|
112
|
+
lines.push(` ${tool ? '✓' : '○'} ${label}${tool?.version ? ` · ${String(tool.version).slice(0, 40)}` : ''}`);
|
|
113
|
+
}
|
|
114
|
+
lines.push('');
|
|
115
|
+
return lines.join('\n');
|
|
116
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { execFile, spawn } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { SETUP_RECEIPT_SCHEMA } from './contract.js';
|
|
7
|
+
import { getCapabilityRecipe } from './recipes.js';
|
|
8
|
+
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
10
|
+
|
|
11
|
+
function homeDir(options = {}) {
|
|
12
|
+
return path.resolve(options.home || options.env?.HOME || os.homedir());
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function setupReceiptsDir(options = {}) {
|
|
16
|
+
return path.join(homeDir(options), '.agentsam', 'receipts');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function runStreaming(command, args, { cwd, env, write } = {}) {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
const child = spawn(command, args, {
|
|
22
|
+
cwd,
|
|
23
|
+
env: env || process.env,
|
|
24
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
25
|
+
});
|
|
26
|
+
let stdout = '';
|
|
27
|
+
let stderr = '';
|
|
28
|
+
child.stdout.on('data', (buf) => {
|
|
29
|
+
const text = String(buf);
|
|
30
|
+
stdout += text;
|
|
31
|
+
write?.(text);
|
|
32
|
+
});
|
|
33
|
+
child.stderr.on('data', (buf) => {
|
|
34
|
+
const text = String(buf);
|
|
35
|
+
stderr += text;
|
|
36
|
+
write?.(text);
|
|
37
|
+
});
|
|
38
|
+
child.on('error', (error) => {
|
|
39
|
+
resolve({ ok: false, code: 1, stdout, stderr: error.message });
|
|
40
|
+
});
|
|
41
|
+
child.on('close', (code) => {
|
|
42
|
+
resolve({ ok: code === 0, code: code ?? 1, stdout, stderr });
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Execute approved install plan steps via native providers.
|
|
49
|
+
*/
|
|
50
|
+
export async function executeSetupPlan(plan, options = {}) {
|
|
51
|
+
const write = options.write || ((s) => process.stdout.write(s));
|
|
52
|
+
const env = options.env || process.env;
|
|
53
|
+
const results = [];
|
|
54
|
+
|
|
55
|
+
for (const step of plan.would_install || []) {
|
|
56
|
+
write(`\n Installing ${step.capability} via ${step.provider}\n`);
|
|
57
|
+
let result;
|
|
58
|
+
if (step.provider === 'homebrew') {
|
|
59
|
+
if (!plan.platform || (plan.platform !== 'darwin' && plan.platform !== 'linux')) {
|
|
60
|
+
result = { ok: false, error: 'homebrew_unsupported_platform' };
|
|
61
|
+
} else {
|
|
62
|
+
const pkgs = step.packages || [];
|
|
63
|
+
// Support ["--cask", "gcloud-cli"] style.
|
|
64
|
+
result = await runStreaming('brew', ['install', ...pkgs], { env, write });
|
|
65
|
+
}
|
|
66
|
+
} else if (step.provider === 'npm') {
|
|
67
|
+
const pkgs = step.packages || [];
|
|
68
|
+
result = await runStreaming('npm', ['install', '-g', ...pkgs], { env, write });
|
|
69
|
+
} else if (step.provider === 'winget') {
|
|
70
|
+
const pkgs = step.packages || [];
|
|
71
|
+
result = await runStreaming('winget', ['install', '-e', '--id', ...pkgs], { env, write });
|
|
72
|
+
} else if (step.provider === 'manual') {
|
|
73
|
+
write(' Manual install required:\n');
|
|
74
|
+
for (const cmd of step.commands || []) write(` ${cmd}\n`);
|
|
75
|
+
for (const note of step.notes || []) write(` ${note}\n`);
|
|
76
|
+
result = { ok: false, error: 'manual_required', notes: step.notes || [] };
|
|
77
|
+
} else {
|
|
78
|
+
result = { ok: false, error: `unsupported_provider:${step.provider}` };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const recipe = getCapabilityRecipe(step.capability);
|
|
82
|
+
let verified = null;
|
|
83
|
+
if (result.ok && recipe?.verify) {
|
|
84
|
+
verified = await recipe.verify({ env });
|
|
85
|
+
write(verified.ok
|
|
86
|
+
? ` ✓ verified ${step.capability}${verified.version ? ` · ${verified.version}` : ''}\n`
|
|
87
|
+
: ` ✕ verify failed for ${step.capability}\n`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
results.push({
|
|
91
|
+
capability: step.capability,
|
|
92
|
+
provider: step.provider,
|
|
93
|
+
packages: step.packages || null,
|
|
94
|
+
ok: Boolean(result.ok) && (verified ? verified.ok : true),
|
|
95
|
+
code: result.code ?? null,
|
|
96
|
+
error: result.error || null,
|
|
97
|
+
verified,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const receipt = {
|
|
102
|
+
schema_version: SETUP_RECEIPT_SCHEMA,
|
|
103
|
+
generated_at: new Date().toISOString(),
|
|
104
|
+
hostname: plan.hostname,
|
|
105
|
+
platform: plan.platform,
|
|
106
|
+
results,
|
|
107
|
+
ok: results.every((r) => r.ok) || results.length === 0,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const dir = setupReceiptsDir(options);
|
|
111
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
112
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
113
|
+
const file = path.join(dir, `setup-${stamp}.json`);
|
|
114
|
+
fs.writeFileSync(file, `${JSON.stringify(receipt, null, 2)}\n`, { mode: 0o600 });
|
|
115
|
+
receipt.path = file;
|
|
116
|
+
return receipt;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Read-only Google Cloud permission inventory (for setup google.cloud / doctor).
|
|
121
|
+
*/
|
|
122
|
+
export async function collectGooglePermissionInventory(options = {}) {
|
|
123
|
+
const env = options.env || process.env;
|
|
124
|
+
const out = {
|
|
125
|
+
schema_version: 'agentsam-gcp-permission-inventory-v1',
|
|
126
|
+
generated_at: new Date().toISOString(),
|
|
127
|
+
auth_list: null,
|
|
128
|
+
config: null,
|
|
129
|
+
user_token_scopes: null,
|
|
130
|
+
projects: null,
|
|
131
|
+
billing_accounts: null,
|
|
132
|
+
iam_roles_for_active_user: null,
|
|
133
|
+
errors: [],
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
try {
|
|
137
|
+
const { stdout } = await execFileAsync('gcloud', ['auth', 'list', '--format=json'], { env, timeout: 20000 });
|
|
138
|
+
out.auth_list = JSON.parse(stdout || '[]');
|
|
139
|
+
} catch (error) {
|
|
140
|
+
out.errors.push(`auth_list: ${error.message}`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
const { stdout } = await execFileAsync(
|
|
145
|
+
'gcloud',
|
|
146
|
+
['config', 'list', '--format=json'],
|
|
147
|
+
{ env, timeout: 15000 },
|
|
148
|
+
);
|
|
149
|
+
out.config = JSON.parse(stdout || '{}');
|
|
150
|
+
} catch (error) {
|
|
151
|
+
out.errors.push(`config: ${error.message}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const { stdout: token } = await execFileAsync('gcloud', ['auth', 'print-access-token'], { env, timeout: 15000 });
|
|
156
|
+
const t = String(token || '').trim();
|
|
157
|
+
if (t) {
|
|
158
|
+
const info = await fetch(`https://oauth2.googleapis.com/tokeninfo?access_token=${encodeURIComponent(t)}`);
|
|
159
|
+
out.user_token_scopes = await info.json();
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
out.errors.push(`tokeninfo: ${error.message}`);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const { stdout } = await execFileAsync('gcloud', ['projects', 'list', '--format=json'], { env, timeout: 45000 });
|
|
167
|
+
out.projects = JSON.parse(stdout || '[]');
|
|
168
|
+
} catch (error) {
|
|
169
|
+
out.errors.push(`projects: ${error.message}`);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const { stdout } = await execFileAsync('gcloud', ['billing', 'accounts', 'list', '--format=json'], { env, timeout: 30000 });
|
|
174
|
+
out.billing_accounts = JSON.parse(stdout || '[]');
|
|
175
|
+
} catch (error) {
|
|
176
|
+
out.errors.push(`billing: ${error.message}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const project = out.config?.core?.project;
|
|
180
|
+
const account = out.config?.core?.account;
|
|
181
|
+
if (project && account && !String(account).includes('.gserviceaccount.com')) {
|
|
182
|
+
try {
|
|
183
|
+
const { stdout } = await execFileAsync(
|
|
184
|
+
'gcloud',
|
|
185
|
+
[
|
|
186
|
+
'projects', 'get-iam-policy', project,
|
|
187
|
+
'--flatten=bindings[].members',
|
|
188
|
+
`--filter=bindings.members:user:${account}`,
|
|
189
|
+
'--format=json',
|
|
190
|
+
],
|
|
191
|
+
{ env, timeout: 45000 },
|
|
192
|
+
);
|
|
193
|
+
const rows = JSON.parse(stdout || '[]');
|
|
194
|
+
out.iam_roles_for_active_user = {
|
|
195
|
+
project,
|
|
196
|
+
account,
|
|
197
|
+
roles: [...new Set((rows || []).map((r) => r.bindings?.role).filter(Boolean))],
|
|
198
|
+
};
|
|
199
|
+
} catch (error) {
|
|
200
|
+
out.errors.push(`iam: ${error.message}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { SETUP_PLAN_SCHEMA } from './contract.js';
|
|
2
|
+
import { getCapabilityRecipe, listCapabilityRecipes } from './recipes.js';
|
|
3
|
+
|
|
4
|
+
function platformKey(platform) {
|
|
5
|
+
if (platform === 'darwin') return 'darwin';
|
|
6
|
+
if (platform === 'win32') return 'win32';
|
|
7
|
+
return 'linux';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Build an install plan for requested capability IDs (or all known recipes).
|
|
12
|
+
*/
|
|
13
|
+
export async function buildSetupPlan(options = {}) {
|
|
14
|
+
const environment = options.environment;
|
|
15
|
+
if (!environment) throw new Error('environment_required');
|
|
16
|
+
const requested = Array.isArray(options.capabilityIds) && options.capabilityIds.length
|
|
17
|
+
? options.capabilityIds
|
|
18
|
+
: listCapabilityRecipes().map((r) => r.id);
|
|
19
|
+
|
|
20
|
+
const capabilities = [];
|
|
21
|
+
const wouldInstall = [];
|
|
22
|
+
const providers = new Set();
|
|
23
|
+
const mutations = new Set();
|
|
24
|
+
let blocked = false;
|
|
25
|
+
|
|
26
|
+
for (const id of requested) {
|
|
27
|
+
const recipe = getCapabilityRecipe(id);
|
|
28
|
+
if (!recipe) {
|
|
29
|
+
capabilities.push({ id, ok: false, error: 'unknown_capability' });
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const detection = await recipe.detect({ environment });
|
|
33
|
+
const plan = recipe.installPlans[platformKey(environment.platform)] || null;
|
|
34
|
+
const entry = {
|
|
35
|
+
id: recipe.id,
|
|
36
|
+
displayName: recipe.displayName,
|
|
37
|
+
description: recipe.description,
|
|
38
|
+
risk: recipe.risk,
|
|
39
|
+
requiresApproval: recipe.requiresApproval !== false,
|
|
40
|
+
capabilityProvided: recipe.capabilityProvided || [],
|
|
41
|
+
detected: detection,
|
|
42
|
+
installPlan: plan,
|
|
43
|
+
mutations: recipe.mutations || [],
|
|
44
|
+
uninstallHint: recipe.uninstallHint?.() || null,
|
|
45
|
+
};
|
|
46
|
+
capabilities.push(entry);
|
|
47
|
+
if (detection.ok) continue;
|
|
48
|
+
if (!plan) {
|
|
49
|
+
blocked = true;
|
|
50
|
+
entry.error = 'no_install_plan_for_platform';
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
providers.add(plan.provider);
|
|
54
|
+
for (const m of entry.mutations) mutations.add(m);
|
|
55
|
+
if (plan.packages?.length) {
|
|
56
|
+
wouldInstall.push({
|
|
57
|
+
capability: recipe.id,
|
|
58
|
+
provider: plan.provider,
|
|
59
|
+
packages: plan.packages,
|
|
60
|
+
notes: plan.notes || [],
|
|
61
|
+
});
|
|
62
|
+
} else if (plan.commands?.length) {
|
|
63
|
+
wouldInstall.push({
|
|
64
|
+
capability: recipe.id,
|
|
65
|
+
provider: plan.provider,
|
|
66
|
+
commands: plan.commands,
|
|
67
|
+
notes: plan.notes || [],
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
schema_version: SETUP_PLAN_SCHEMA,
|
|
74
|
+
ok: !blocked,
|
|
75
|
+
hostname: environment.hostname,
|
|
76
|
+
host_label: environment.host_label,
|
|
77
|
+
platform: environment.platform,
|
|
78
|
+
capabilities,
|
|
79
|
+
would_install: wouldInstall,
|
|
80
|
+
providers: [...providers],
|
|
81
|
+
mutations: [...mutations],
|
|
82
|
+
trust_notes: [
|
|
83
|
+
'Agent Sam will not silently trust third-party package taps/repos.',
|
|
84
|
+
'No shell profiles, project files, or provider credentials are modified unless a recipe explicitly lists them and you approve.',
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function renderSetupPlan(plan) {
|
|
90
|
+
const lines = [
|
|
91
|
+
'',
|
|
92
|
+
' Agent Sam Setup',
|
|
93
|
+
' ────────────────────────────────────────',
|
|
94
|
+
'',
|
|
95
|
+
` Host ${plan.host_label} · ${plan.hostname} · ${plan.platform}`,
|
|
96
|
+
'',
|
|
97
|
+
' Capabilities',
|
|
98
|
+
];
|
|
99
|
+
for (const cap of plan.capabilities) {
|
|
100
|
+
const mark = cap.detected?.ok ? '✓' : '○';
|
|
101
|
+
const ver = cap.detected?.version ? ` · ${String(cap.detected.version).slice(0, 36)}` : '';
|
|
102
|
+
lines.push(` ${mark} ${cap.displayName || cap.id}${ver}`);
|
|
103
|
+
if (!cap.detected?.ok && cap.detected?.detail) {
|
|
104
|
+
lines.push(` ${cap.detected.detail}`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
lines.push('');
|
|
108
|
+
if (!plan.would_install.length) {
|
|
109
|
+
lines.push(' Suggested installation');
|
|
110
|
+
lines.push(' Nothing missing from the requested set.');
|
|
111
|
+
lines.push('');
|
|
112
|
+
return lines.join('\n');
|
|
113
|
+
}
|
|
114
|
+
lines.push(' Suggested installation');
|
|
115
|
+
lines.push(` Would install ${plan.would_install.length} capability package group(s):`);
|
|
116
|
+
for (const row of plan.would_install) {
|
|
117
|
+
const pkgs = (row.packages || row.commands || []).join(' ');
|
|
118
|
+
lines.push(` ${row.provider.padEnd(12)} ${pkgs}`);
|
|
119
|
+
}
|
|
120
|
+
lines.push('');
|
|
121
|
+
lines.push(' Would use');
|
|
122
|
+
for (const p of plan.providers) lines.push(` ${p}`);
|
|
123
|
+
lines.push('');
|
|
124
|
+
lines.push(' Would modify');
|
|
125
|
+
if (!plan.mutations.length) {
|
|
126
|
+
lines.push(' no project files / shell profiles / credentials (package install only)');
|
|
127
|
+
} else {
|
|
128
|
+
for (const m of plan.mutations) lines.push(` • ${m}`);
|
|
129
|
+
}
|
|
130
|
+
lines.push('');
|
|
131
|
+
for (const note of plan.trust_notes || []) lines.push(` Note ${note}`);
|
|
132
|
+
lines.push('');
|
|
133
|
+
return lines.join('\n');
|
|
134
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import { createRequire } from 'node:module';
|
|
4
|
+
|
|
5
|
+
const execFileAsync = promisify(execFile);
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
|
|
8
|
+
async function which(bin) {
|
|
9
|
+
try {
|
|
10
|
+
const { stdout } = await execFileAsync(process.platform === 'win32' ? 'where' : 'which', [bin], { timeout: 5000 });
|
|
11
|
+
return String(stdout || '').trim().split(/\r?\n/)[0] || null;
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function versionOf(bin, args) {
|
|
18
|
+
try {
|
|
19
|
+
const { stdout, stderr } = await execFileAsync(bin, args, { timeout: 8000 });
|
|
20
|
+
return `${stdout || ''}${stderr || ''}`.trim().split(/\n/)[0].slice(0, 80);
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** @type {import('./contract.js').InstallableCapability} */
|
|
27
|
+
export const imageRasterTransformCapability = {
|
|
28
|
+
id: 'image.raster.transform',
|
|
29
|
+
displayName: 'Raster image transforms',
|
|
30
|
+
description: 'Resize/convert PNG/JPEG/WebP/AVIF via Sharp (preferred) or ImageMagick (optional)',
|
|
31
|
+
risk: 'low',
|
|
32
|
+
requiresApproval: false,
|
|
33
|
+
capabilityProvided: ['image.raster.transform', 'image.raster.inspect'],
|
|
34
|
+
supportedPlatforms: ['darwin', 'linux', 'win32'],
|
|
35
|
+
dependencies: ['sharp'],
|
|
36
|
+
mutations: ['may npm-install sharp in the AgentSam package; optional ImageMagick via OS package manager'],
|
|
37
|
+
installPlans: {
|
|
38
|
+
darwin: {
|
|
39
|
+
provider: 'npm',
|
|
40
|
+
packages: ['sharp'],
|
|
41
|
+
notes: [
|
|
42
|
+
'Sharp is the portable default (declared dependency of @inneranimalmedia/agentsam-sdk-brand).',
|
|
43
|
+
'Optional enrichment: Homebrew imagemagick for ICNS / exotic formats.',
|
|
44
|
+
'Brand packs: agentsam brand promote → pack → preview → optional publish',
|
|
45
|
+
' agentsam brand pack --brand acme --asset app-icon --source ./master.png --preset app-icon --out ./acme.zip',
|
|
46
|
+
' agentsam brand preview --from ./acme.zip',
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
linux: {
|
|
50
|
+
provider: 'npm',
|
|
51
|
+
packages: ['sharp'],
|
|
52
|
+
notes: ['Optional: apt/dnf/pacman imagemagick for extended tooling'],
|
|
53
|
+
},
|
|
54
|
+
win32: {
|
|
55
|
+
provider: 'npm',
|
|
56
|
+
packages: ['sharp'],
|
|
57
|
+
notes: ['Optional: winget install ImageMagick.ImageMagick'],
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
async detect() {
|
|
61
|
+
let sharpOk = false;
|
|
62
|
+
try {
|
|
63
|
+
require.resolve('sharp');
|
|
64
|
+
sharpOk = true;
|
|
65
|
+
} catch {
|
|
66
|
+
sharpOk = false;
|
|
67
|
+
}
|
|
68
|
+
const magick = (await which('magick')) || (await which('convert'));
|
|
69
|
+
const ok = sharpOk || Boolean(magick);
|
|
70
|
+
return {
|
|
71
|
+
ok,
|
|
72
|
+
detail: sharpOk
|
|
73
|
+
? 'Sharp available'
|
|
74
|
+
: magick
|
|
75
|
+
? 'ImageMagick available (Sharp preferred)'
|
|
76
|
+
: 'missing Sharp and ImageMagick',
|
|
77
|
+
version: sharpOk ? 'sharp' : magick ? await versionOf(magick, ['--version']) : null,
|
|
78
|
+
backends: { sharp: sharpOk, imagemagick: Boolean(magick) },
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
async verify() {
|
|
82
|
+
return this.detect();
|
|
83
|
+
},
|
|
84
|
+
uninstallHint() {
|
|
85
|
+
return 'Remove optional ImageMagick via your package manager; Sharp uninstalls with the npm package.';
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/** @type {import('./contract.js').InstallableCapability} */
|
|
90
|
+
export const imageVectorizeCapability = {
|
|
91
|
+
id: 'image.vectorize',
|
|
92
|
+
displayName: 'Vector image tooling',
|
|
93
|
+
description: 'Potrace (+ optional ImageMagick/SVGO) for raster→SVG workflows',
|
|
94
|
+
risk: 'low',
|
|
95
|
+
requiresApproval: true,
|
|
96
|
+
capabilityProvided: ['image.vectorize', 'image.optimize'],
|
|
97
|
+
supportedPlatforms: ['darwin', 'linux', 'win32'],
|
|
98
|
+
dependencies: ['potrace'],
|
|
99
|
+
mutations: ['installs OS packages via detected package manager — no shell profile edits'],
|
|
100
|
+
installPlans: {
|
|
101
|
+
darwin: {
|
|
102
|
+
provider: 'homebrew',
|
|
103
|
+
packages: ['potrace'],
|
|
104
|
+
notes: ['Optional: brew install imagemagick; npm i -g svgo'],
|
|
105
|
+
},
|
|
106
|
+
linux: {
|
|
107
|
+
provider: 'apt',
|
|
108
|
+
packages: ['potrace'],
|
|
109
|
+
notes: [
|
|
110
|
+
'Debian/Ubuntu: apt',
|
|
111
|
+
'Fedora: dnf install potrace',
|
|
112
|
+
'Arch: pacman -S potrace',
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
win32: {
|
|
116
|
+
provider: 'winget',
|
|
117
|
+
packages: [],
|
|
118
|
+
notes: ['Install Potrace from https://potrace.sourceforge.net/ or chocolatey if available'],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
async detect() {
|
|
122
|
+
const potrace = await which('potrace');
|
|
123
|
+
const magick = (await which('magick')) || (await which('convert'));
|
|
124
|
+
const ok = Boolean(potrace);
|
|
125
|
+
return {
|
|
126
|
+
ok,
|
|
127
|
+
detail: ok ? 'Potrace available' : 'missing potrace',
|
|
128
|
+
version: potrace ? await versionOf(potrace, ['-v']) : null,
|
|
129
|
+
backends: { potrace: Boolean(potrace), imagemagick: Boolean(magick) },
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
async verify() {
|
|
133
|
+
return this.detect();
|
|
134
|
+
},
|
|
135
|
+
uninstallHint() {
|
|
136
|
+
return 'Remove potrace with your platform package manager (brew/apt/dnf/winget) — AgentSam will not invent a command.';
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/** @type {import('./contract.js').InstallableCapability} */
|
|
141
|
+
export const googleCloudCapability = {
|
|
142
|
+
id: 'google.cloud',
|
|
143
|
+
displayName: 'Google Cloud connection',
|
|
144
|
+
description: 'gcloud CLI + Agent Sam Desktop/Web OAuth + connection preference',
|
|
145
|
+
risk: 'medium',
|
|
146
|
+
requiresApproval: true,
|
|
147
|
+
capabilityProvided: ['google.cloud.auth', 'google.cloud.doctor'],
|
|
148
|
+
supportedPlatforms: ['darwin', 'linux', 'win32'],
|
|
149
|
+
dependencies: ['gcloud'],
|
|
150
|
+
mutations: [
|
|
151
|
+
'may open browser for OAuth',
|
|
152
|
+
'writes ~/.agentsam/connections/google-cloud.json',
|
|
153
|
+
'may store google-cloud token in OS keychain / vault',
|
|
154
|
+
],
|
|
155
|
+
installPlans: {
|
|
156
|
+
darwin: {
|
|
157
|
+
provider: 'homebrew',
|
|
158
|
+
packages: ['--cask', 'google-cloud-sdk'],
|
|
159
|
+
notes: [
|
|
160
|
+
'After gcloud: agentsam gcloud auth login',
|
|
161
|
+
'Then: agentsam google-cloud connection set --identity EMAIL --project PROJECT',
|
|
162
|
+
'Inspect: agentsam setup google.cloud --inventory',
|
|
163
|
+
'Doctor: agentsam google-cloud doctor --json',
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
linux: {
|
|
167
|
+
provider: 'manual',
|
|
168
|
+
commands: ['# install Google Cloud SDK: https://cloud.google.com/sdk/docs/install'],
|
|
169
|
+
notes: ['Then agentsam gcloud auth login'],
|
|
170
|
+
},
|
|
171
|
+
win32: {
|
|
172
|
+
provider: 'winget',
|
|
173
|
+
packages: ['Google.CloudSDK'],
|
|
174
|
+
notes: ['Then agentsam gcloud auth login'],
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
async detect() {
|
|
178
|
+
const gcloud = await which('gcloud');
|
|
179
|
+
if (!gcloud) return { ok: false, detail: 'gcloud not on PATH' };
|
|
180
|
+
const version = await versionOf('gcloud', ['--version']);
|
|
181
|
+
return { ok: true, detail: 'gcloud available', version };
|
|
182
|
+
},
|
|
183
|
+
async verify() {
|
|
184
|
+
return this.detect();
|
|
185
|
+
},
|
|
186
|
+
uninstallHint() {
|
|
187
|
+
return 'brew uninstall --cask gcloud-cli # or remove Google Cloud SDK';
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/** @type {import('./contract.js').InstallableCapability} */
|
|
192
|
+
export const cloudflareWranglerCapability = {
|
|
193
|
+
id: 'cloudflare.wrangler',
|
|
194
|
+
displayName: 'Cloudflare Wrangler',
|
|
195
|
+
description: 'Wrangler CLI for Workers / D1 / deploy',
|
|
196
|
+
risk: 'low',
|
|
197
|
+
requiresApproval: true,
|
|
198
|
+
capabilityProvided: ['cloudflare.wrangler'],
|
|
199
|
+
supportedPlatforms: ['darwin', 'linux', 'win32'],
|
|
200
|
+
dependencies: ['wrangler'],
|
|
201
|
+
mutations: ['npm/global or project-local install'],
|
|
202
|
+
installPlans: {
|
|
203
|
+
darwin: { provider: 'npm', packages: ['wrangler@latest'], notes: ['Prefer repo-local npx wrangler'] },
|
|
204
|
+
linux: { provider: 'npm', packages: ['wrangler@latest'] },
|
|
205
|
+
win32: { provider: 'npm', packages: ['wrangler@latest'] },
|
|
206
|
+
},
|
|
207
|
+
async detect() {
|
|
208
|
+
const wrangler = await which('wrangler');
|
|
209
|
+
if (wrangler) {
|
|
210
|
+
return { ok: true, detail: 'wrangler on PATH', version: await versionOf('wrangler', ['--version']) };
|
|
211
|
+
}
|
|
212
|
+
return { ok: false, detail: 'wrangler not on PATH (npx wrangler may still work in this repo)' };
|
|
213
|
+
},
|
|
214
|
+
async verify() {
|
|
215
|
+
return this.detect();
|
|
216
|
+
},
|
|
217
|
+
uninstallHint() {
|
|
218
|
+
return 'npm uninstall -g wrangler';
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
export const CAPABILITY_RECIPES = Object.freeze({
|
|
223
|
+
[imageRasterTransformCapability.id]: imageRasterTransformCapability,
|
|
224
|
+
[imageVectorizeCapability.id]: imageVectorizeCapability,
|
|
225
|
+
[googleCloudCapability.id]: googleCloudCapability,
|
|
226
|
+
[cloudflareWranglerCapability.id]: cloudflareWranglerCapability,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
export function listCapabilityRecipes() {
|
|
230
|
+
return Object.values(CAPABILITY_RECIPES);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function getCapabilityRecipe(id) {
|
|
234
|
+
return CAPABILITY_RECIPES[String(id || '').trim()] || null;
|
|
235
|
+
}
|