@synap-core/cli 1.10.0 → 1.12.2
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/README.md +23 -198
- package/dist/build-info.json +6 -0
- package/dist/commands/agent-run.js +3 -2
- package/dist/commands/agent-run.js.map +1 -1
- package/dist/commands/agents.d.ts +33 -17
- package/dist/commands/agents.js +203 -237
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/app.d.ts +143 -0
- package/dist/commands/app.js +523 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/automate.d.ts +21 -0
- package/dist/commands/automate.js +42 -0
- package/dist/commands/automate.js.map +1 -0
- package/dist/commands/automation-schema.test.d.ts +16 -0
- package/dist/commands/automation-schema.test.js +77 -0
- package/dist/commands/automation-schema.test.js.map +1 -0
- package/dist/commands/automation.d.ts +12 -0
- package/dist/commands/automation.js +80 -35
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/bridge-setup.d.ts +14 -1
- package/dist/commands/bridge-setup.js +392 -128
- package/dist/commands/bridge-setup.js.map +1 -1
- package/dist/commands/cap-connections.d.ts +4 -4
- package/dist/commands/cap-connections.js +14 -14
- package/dist/commands/cap-connections.js.map +1 -1
- package/dist/commands/capability.d.ts +2 -0
- package/dist/commands/capability.js +297 -176
- package/dist/commands/capability.js.map +1 -1
- package/dist/commands/catalog.d.ts +275 -0
- package/dist/commands/catalog.js +481 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/cell.d.ts +155 -8
- package/dist/commands/cell.js +416 -40
- package/dist/commands/cell.js.map +1 -1
- package/dist/commands/centrality.js +3 -14
- package/dist/commands/centrality.js.map +1 -1
- package/dist/commands/connect.d.ts +38 -13
- package/dist/commands/connect.js +68 -167
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/connections.d.ts +3 -2
- package/dist/commands/connections.js +95 -25
- package/dist/commands/connections.js.map +1 -1
- package/dist/commands/context.js +9 -2
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +34 -0
- package/dist/commands/data-extra.js +198 -25
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.d.ts +120 -2
- package/dist/commands/data.js +307 -24
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/diagnose.d.ts +66 -4
- package/dist/commands/diagnose.js +329 -29
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/digest.js +2 -1
- package/dist/commands/digest.js.map +1 -1
- package/dist/commands/doc.d.ts +25 -4
- package/dist/commands/doc.js +100 -18
- package/dist/commands/doc.js.map +1 -1
- package/dist/commands/doctor.d.ts +130 -0
- package/dist/commands/doctor.js +814 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/events.js +3 -1
- package/dist/commands/events.js.map +1 -1
- package/dist/commands/explain.js +5 -5
- package/dist/commands/explain.js.map +1 -1
- package/dist/commands/graph.js +5 -3
- package/dist/commands/graph.js.map +1 -1
- package/dist/commands/import.d.ts +368 -13
- package/dist/commands/import.js +1096 -55
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +20 -9
- package/dist/commands/init.js +433 -973
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys.d.ts +1 -0
- package/dist/commands/keys.js +15 -2
- package/dist/commands/keys.js.map +1 -1
- package/dist/commands/knowledge.d.ts +28 -6
- package/dist/commands/knowledge.js +358 -73
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/launch.js +2 -2
- package/dist/commands/launch.js.map +1 -1
- package/dist/commands/lens.d.ts +37 -1
- package/dist/commands/lens.js +193 -72
- package/dist/commands/lens.js.map +1 -1
- package/dist/commands/market-authoring.d.ts +72 -0
- package/dist/commands/market-authoring.js +566 -0
- package/dist/commands/market-authoring.js.map +1 -0
- package/dist/commands/market-official.d.ts +58 -0
- package/dist/commands/market-official.js +84 -0
- package/dist/commands/market-official.js.map +1 -0
- package/dist/commands/market.d.ts +419 -20
- package/dist/commands/market.js +2124 -193
- package/dist/commands/market.js.map +1 -1
- package/dist/commands/mcp.d.ts +70 -13
- package/dist/commands/mcp.js +308 -40
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/open.d.ts +39 -9
- package/dist/commands/open.js +80 -25
- package/dist/commands/open.js.map +1 -1
- package/dist/commands/playbook.d.ts +42 -0
- package/dist/commands/playbook.js +162 -0
- package/dist/commands/playbook.js.map +1 -0
- package/dist/commands/pod.js +1 -1
- package/dist/commands/pod.js.map +1 -1
- package/dist/commands/pods.d.ts +19 -0
- package/dist/commands/pods.js +220 -85
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.d.ts +62 -0
- package/dist/commands/proposals-actions.js +146 -8
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/proposals-await.d.ts +68 -0
- package/dist/commands/proposals-await.js +248 -0
- package/dist/commands/proposals-await.js.map +1 -0
- package/dist/commands/proton-setup.d.ts +73 -0
- package/dist/commands/proton-setup.js +577 -0
- package/dist/commands/proton-setup.js.map +1 -0
- package/dist/commands/providers.d.ts +23 -0
- package/dist/commands/providers.js +126 -1
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/raycast.js +6 -2
- package/dist/commands/raycast.js.map +1 -1
- package/dist/commands/rule.d.ts +150 -0
- package/dist/commands/rule.js +447 -0
- package/dist/commands/rule.js.map +1 -0
- package/dist/commands/session-wait.d.ts +111 -0
- package/dist/commands/session-wait.js +209 -0
- package/dist/commands/session-wait.js.map +1 -0
- package/dist/commands/sessions.d.ts +52 -0
- package/dist/commands/sessions.js +479 -58
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skill-manage.d.ts +21 -0
- package/dist/commands/skill-manage.js +136 -19
- package/dist/commands/skill-manage.js.map +1 -1
- package/dist/commands/skills.js +19 -1
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts +1 -4
- package/dist/commands/status.js +5 -34
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.backoff.test.d.ts +13 -0
- package/dist/commands/statusline.backoff.test.js +100 -0
- package/dist/commands/statusline.backoff.test.js.map +1 -0
- package/dist/commands/statusline.js +16 -9
- package/dist/commands/statusline.js.map +1 -1
- package/dist/commands/sync-status.d.ts +12 -0
- package/dist/commands/sync-status.js +125 -0
- package/dist/commands/sync-status.js.map +1 -0
- package/dist/commands/templates-retire.d.ts +34 -0
- package/dist/commands/templates-retire.js +192 -0
- package/dist/commands/templates-retire.js.map +1 -0
- package/dist/commands/tools.js +6 -21
- package/dist/commands/tools.js.map +1 -1
- package/dist/commands/tracks.d.ts +51 -0
- package/dist/commands/tracks.js +291 -0
- package/dist/commands/tracks.js.map +1 -0
- package/dist/commands/update.d.ts +3 -11
- package/dist/commands/update.js +5 -134
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/upload.d.ts +68 -0
- package/dist/commands/upload.js +257 -0
- package/dist/commands/upload.js.map +1 -0
- package/dist/commands/vendor.d.ts +28 -0
- package/dist/commands/vendor.js +110 -0
- package/dist/commands/vendor.js.map +1 -0
- package/dist/commands/versions.js +6 -0
- package/dist/commands/versions.js.map +1 -1
- package/dist/commands/view.js +10 -5
- package/dist/commands/view.js.map +1 -1
- package/dist/commands/whoami.d.ts +23 -3
- package/dist/commands/whoami.js +169 -23
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/worker.d.ts +122 -0
- package/dist/commands/worker.js +435 -0
- package/dist/commands/worker.js.map +1 -0
- package/dist/commands/worker.test.d.ts +1 -0
- package/dist/commands/worker.test.js +116 -0
- package/dist/commands/worker.test.js.map +1 -0
- package/dist/commands/workspace-ops.d.ts +35 -0
- package/dist/commands/workspace-ops.js +153 -0
- package/dist/commands/workspace-ops.js.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +1009 -171
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-connections.d.ts +31 -0
- package/dist/lib/agent-connections.js +33 -0
- package/dist/lib/agent-connections.js.map +1 -0
- package/dist/lib/agent-detect.d.ts +27 -0
- package/dist/lib/agent-detect.js +71 -0
- package/dist/lib/agent-detect.js.map +1 -0
- package/dist/lib/agent-door.d.ts +138 -0
- package/dist/lib/agent-door.js +426 -0
- package/dist/lib/agent-door.js.map +1 -0
- package/dist/lib/agents-config.d.ts +2 -0
- package/dist/lib/agents-config.js +4 -9
- package/dist/lib/agents-config.js.map +1 -1
- package/dist/lib/approval-poll.d.ts +31 -2
- package/dist/lib/approval-poll.js +20 -7
- package/dist/lib/approval-poll.js.map +1 -1
- package/dist/lib/atomic-file.d.ts +48 -0
- package/dist/lib/atomic-file.js +129 -0
- package/dist/lib/atomic-file.js.map +1 -0
- package/dist/lib/auth.d.ts +14 -9
- package/dist/lib/auth.js +44 -61
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/batch-approval.d.ts +85 -0
- package/dist/lib/batch-approval.js +170 -0
- package/dist/lib/batch-approval.js.map +1 -0
- package/dist/lib/capture-lane.d.ts +6 -5
- package/dist/lib/capture-lane.js +11 -8
- package/dist/lib/capture-lane.js.map +1 -1
- package/dist/lib/capture-structure.d.ts +342 -0
- package/dist/lib/capture-structure.js +295 -0
- package/dist/lib/capture-structure.js.map +1 -0
- package/dist/lib/catalog-templates.d.ts +59 -0
- package/dist/lib/catalog-templates.js +126 -0
- package/dist/lib/catalog-templates.js.map +1 -0
- package/dist/lib/cli-build.d.ts +19 -0
- package/dist/lib/cli-build.js +37 -0
- package/dist/lib/cli-build.js.map +1 -0
- package/dist/lib/conversation-headers.d.ts +18 -0
- package/dist/lib/conversation-headers.js +32 -0
- package/dist/lib/conversation-headers.js.map +1 -0
- package/dist/lib/cp-packages.d.ts +216 -4
- package/dist/lib/cp-packages.js +414 -11
- package/dist/lib/cp-packages.js.map +1 -1
- package/dist/lib/credential-class.d.ts +117 -0
- package/dist/lib/credential-class.js +116 -0
- package/dist/lib/credential-class.js.map +1 -0
- package/dist/lib/describe-lens.d.ts +35 -0
- package/dist/lib/describe-lens.js +40 -0
- package/dist/lib/describe-lens.js.map +1 -1
- package/dist/lib/device-connect.d.ts +125 -0
- package/dist/lib/device-connect.js +256 -0
- package/dist/lib/device-connect.js.map +1 -0
- package/dist/lib/directory-lens.d.ts +99 -0
- package/dist/lib/directory-lens.js +187 -0
- package/dist/lib/directory-lens.js.map +1 -0
- package/dist/lib/exporter-coverage.d.ts +71 -0
- package/dist/lib/exporter-coverage.js +97 -0
- package/dist/lib/exporter-coverage.js.map +1 -0
- package/dist/lib/hub-client.d.ts +43 -9
- package/dist/lib/hub-client.js +429 -65
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/id.d.ts +23 -0
- package/dist/lib/id.js +35 -0
- package/dist/lib/id.js.map +1 -0
- package/dist/lib/init-connect.d.ts +41 -0
- package/dist/lib/init-connect.js +75 -0
- package/dist/lib/init-connect.js.map +1 -0
- package/dist/lib/init-exit.d.ts +24 -0
- package/dist/lib/init-exit.js +41 -0
- package/dist/lib/init-exit.js.map +1 -0
- package/dist/lib/init-flow.d.ts +25 -0
- package/dist/lib/init-flow.js +40 -0
- package/dist/lib/init-flow.js.map +1 -0
- package/dist/lib/init-handoff.d.ts +16 -0
- package/dist/lib/init-handoff.js +19 -0
- package/dist/lib/init-handoff.js.map +1 -0
- package/dist/lib/init-output.d.ts +18 -0
- package/dist/lib/init-output.js +43 -0
- package/dist/lib/init-output.js.map +1 -0
- package/dist/lib/init-pod.d.ts +45 -0
- package/dist/lib/init-pod.js +36 -0
- package/dist/lib/init-pod.js.map +1 -0
- package/dist/lib/installed.d.ts +210 -11
- package/dist/lib/installed.js +234 -36
- package/dist/lib/installed.js.map +1 -1
- package/dist/lib/key-approval.d.ts +57 -0
- package/dist/lib/key-approval.js +117 -0
- package/dist/lib/key-approval.js.map +1 -0
- package/dist/lib/key-diagnosis.d.ts +56 -0
- package/dist/lib/key-diagnosis.js +227 -0
- package/dist/lib/key-diagnosis.js.map +1 -0
- package/dist/lib/key-doctor.d.ts +136 -0
- package/dist/lib/key-doctor.js +286 -0
- package/dist/lib/key-doctor.js.map +1 -0
- package/dist/lib/key-locations.d.ts +120 -0
- package/dist/lib/key-locations.js +326 -0
- package/dist/lib/key-locations.js.map +1 -0
- package/dist/lib/key-source.d.ts +66 -0
- package/dist/lib/key-source.js +106 -0
- package/dist/lib/key-source.js.map +1 -0
- package/dist/lib/key-state.d.ts +70 -0
- package/dist/lib/key-state.js +115 -0
- package/dist/lib/key-state.js.map +1 -0
- package/dist/lib/kind-package.d.ts +181 -0
- package/dist/lib/kind-package.js +679 -0
- package/dist/lib/kind-package.js.map +1 -0
- package/dist/lib/knowledge-title.d.ts +24 -0
- package/dist/lib/knowledge-title.js +46 -0
- package/dist/lib/knowledge-title.js.map +1 -0
- package/dist/lib/knowledge-title.test.d.ts +1 -0
- package/dist/lib/knowledge-title.test.js +34 -0
- package/dist/lib/knowledge-title.test.js.map +1 -0
- package/dist/lib/machine-instance.d.ts +64 -0
- package/dist/lib/machine-instance.js +142 -0
- package/dist/lib/machine-instance.js.map +1 -0
- package/dist/lib/mcp-bridge.d.ts +42 -0
- package/dist/lib/mcp-bridge.js +147 -0
- package/dist/lib/mcp-bridge.js.map +1 -0
- package/dist/lib/mcp-bridge.test.d.ts +1 -0
- package/dist/lib/mcp-bridge.test.js +90 -0
- package/dist/lib/mcp-bridge.test.js.map +1 -0
- package/dist/lib/mcp-call.d.ts +30 -0
- package/dist/lib/mcp-call.js +107 -0
- package/dist/lib/mcp-call.js.map +1 -0
- package/dist/lib/mcp-snippets.d.ts +53 -0
- package/dist/lib/mcp-snippets.js +82 -0
- package/dist/lib/mcp-snippets.js.map +1 -0
- package/dist/lib/next-steps.d.ts +8 -0
- package/dist/lib/next-steps.js +31 -1
- package/dist/lib/next-steps.js.map +1 -1
- package/dist/lib/package-wire.d.ts +179 -0
- package/dist/lib/package-wire.js +68 -0
- package/dist/lib/package-wire.js.map +1 -0
- package/dist/lib/pair-link.d.ts +38 -0
- package/dist/lib/pair-link.js +68 -0
- package/dist/lib/pair-link.js.map +1 -0
- package/dist/lib/pod-wide.d.ts +40 -0
- package/dist/lib/pod-wide.js +46 -0
- package/dist/lib/pod-wide.js.map +1 -0
- package/dist/lib/pod.d.ts +119 -115
- package/dist/lib/pod.js +206 -412
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/project-ref.d.ts +9 -3
- package/dist/lib/project-ref.js +10 -4
- package/dist/lib/project-ref.js.map +1 -1
- package/dist/lib/review-credential.d.ts +119 -0
- package/dist/lib/review-credential.js +147 -0
- package/dist/lib/review-credential.js.map +1 -0
- package/dist/lib/safe-open.d.ts +49 -0
- package/dist/lib/safe-open.js +119 -0
- package/dist/lib/safe-open.js.map +1 -0
- package/dist/lib/session-lens.d.ts +40 -1
- package/dist/lib/session-lens.js +54 -4
- package/dist/lib/session-lens.js.map +1 -1
- package/dist/lib/superwhisper-import.d.ts +8 -0
- package/dist/lib/superwhisper-import.js +14 -7
- package/dist/lib/superwhisper-import.js.map +1 -1
- package/dist/lib/superwhisper-title.test.d.ts +1 -0
- package/dist/lib/superwhisper-title.test.js +18 -0
- package/dist/lib/superwhisper-title.test.js.map +1 -0
- package/dist/lib/targets.d.ts +134 -10
- package/dist/lib/targets.js +962 -258
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/template-file.d.ts +78 -0
- package/dist/lib/template-file.js +140 -0
- package/dist/lib/template-file.js.map +1 -0
- package/dist/lib/template-lifecycle.d.ts +217 -0
- package/dist/lib/template-lifecycle.js +433 -0
- package/dist/lib/template-lifecycle.js.map +1 -0
- package/dist/lib/template-steps.d.ts +88 -0
- package/dist/lib/template-steps.js +118 -0
- package/dist/lib/template-steps.js.map +1 -0
- package/dist/lib/time-ago.d.ts +2 -0
- package/dist/lib/time-ago.js +15 -0
- package/dist/lib/time-ago.js.map +1 -0
- package/dist/utils/logger.js +5 -2
- package/dist/utils/logger.js.map +1 -1
- package/package.json +25 -18
- package/skills/README.md +12 -10
- package/skills/agent-os/SKILL.md +220 -99
- package/skills/manifest.json +2 -2
- package/skills/onboard/SKILL.md +61 -25
- package/skills/synap/README.md +5 -8
- package/skills/synap/SKILL.md +1185 -301
- package/skills/synap/_order.txt +7 -0
- package/skills/synap/_skill.yaml +1 -1
- package/skills/synap/automations.md +15 -0
- package/skills/synap/capture.md +54 -151
- package/skills/synap/cli-operations.md +24 -18
- package/skills/synap/common-mistakes.md +1 -0
- package/skills/synap/concepts.md +28 -0
- package/skills/synap/content-os.md +92 -0
- package/skills/synap/creative-loop.md +15 -10
- package/skills/synap/crm.md +21 -52
- package/skills/synap/digesting-a-channel.md +25 -0
- package/skills/synap/document-embeds.md +141 -47
- package/skills/synap/escalation-ladder.md +20 -10
- package/skills/synap/focus-sessions.md +47 -21
- package/skills/synap/from-intent.md +142 -0
- package/skills/synap/governance-rules.md +4 -4
- package/skills/synap/governance.md +10 -7
- package/skills/synap/hand-off.md +33 -0
- package/skills/synap/inline-patterns.md +15 -7
- package/skills/synap/lenses.md +33 -15
- package/skills/synap/linking.md +41 -40
- package/skills/synap/mcp-remote-servers.md +64 -0
- package/skills/synap/mental-model.md +24 -22
- package/skills/synap/multi-entity-capture.md +6 -4
- package/skills/synap/operating-mode-rules.md +1 -1
- package/skills/synap/processes.md +118 -0
- package/skills/synap/quick-reference.md +5 -1
- package/skills/synap/reading.md +3 -1
- package/skills/synap/reflexes.md +12 -42
- package/skills/synap/viewframe-cells.md +38 -5
- package/skills/synap/work-flow.md +1 -1
- package/skills/synap/work-model.md +96 -0
- package/skills/synap/worked-examples.md +21 -1
- package/skills/synap/workspace-design.md +14 -10
- package/skills/synap/writes.md +165 -35
- package/skills/synap/writing-titles.md +63 -0
- package/skills/synap-app/SKILL.md +319 -0
- package/skills/synap-app/_order.txt +5 -0
- package/skills/synap-app/_skill.yaml +20 -0
- package/skills/synap-app/creating-the-base-app.md +64 -0
- package/skills/synap-app/governance.md +42 -0
- package/skills/synap-app/install-commands.md +55 -0
- package/skills/synap-app/overview.md +50 -0
- package/skills/synap-app/using-the-sdk.md +73 -0
- package/skills/synap-design/SKILL.md +474 -0
- package/skills/synap-design/_order.txt +4 -0
- package/skills/synap-design/_skill.yaml +21 -0
- package/skills/synap-design/loop.md +134 -0
- package/skills/synap-design/overview.md +44 -0
- package/skills/synap-design/principles.md +130 -0
- package/skills/synap-design/system.md +133 -0
- package/skills/synap-market/SKILL.md +625 -0
- package/skills/synap-market/_order.txt +5 -0
- package/skills/synap-market/_skill.yaml +24 -0
- package/skills/synap-market/author-and-publish.md +212 -0
- package/skills/synap-market/discover-and-fetch.md +59 -0
- package/skills/synap-market/governance-and-catalog.md +63 -0
- package/skills/synap-market/install.md +133 -0
- package/skills/synap-market/overview.md +119 -0
- package/skills/synap-schema/SKILL.md +172 -10
- package/skills/synap-schema/_order.txt +2 -0
- package/skills/synap-schema/_skill.yaml +4 -2
- package/skills/synap-schema/common-mistakes.md +4 -2
- package/skills/synap-schema/discover-profiles.md +1 -1
- package/skills/synap-schema/entity-scope.md +15 -3
- package/skills/synap-schema/extend-first.md +29 -0
- package/skills/synap-schema/extend-vs-create.md +1 -1
- package/skills/synap-schema/intent-vocabulary-ssot.md +111 -0
- package/skills/synap-schema/property-types.md +1 -1
- package/skills/synap-schema/relations.md +1 -1
- package/skills/synap-ui/SKILL.md +19 -12
- package/skills/synap-ui/_skill.yaml +1 -1
- package/skills/synap-ui/ai-companion.md +1 -1
- package/skills/synap-ui/arranging-bento.md +2 -0
- package/skills/synap-ui/bento-layouts.md +10 -10
- package/skills/synap-ui/bento-recipes.md +313 -543
- package/skills/synap-ui/four-builds.md +5 -0
- package/skills/synap-ui/view-types.md +2 -2
- package/skills/synap-ui/widget-catalog.md +22 -278
- package/templates/automations/bookmark-enrichment.automation.json +290 -13
- package/templates/automations/url-bookmark-capture.automation.json +73 -11
- package/templates/skills/authoring-playbooks/SKILL.md +6 -3
- package/templates/skills/authoring-playbooks/reference/stages-contract.md +15 -0
- package/templates/skills/authoring-playbooks/reference/worked-example.md +3 -0
- package/dist/commands/infra.d.ts +0 -21
- package/dist/commands/infra.js +0 -262
- package/dist/commands/infra.js.map +0 -1
- package/dist/lib/browser-auth.d.ts +0 -35
- package/dist/lib/browser-auth.js +0 -170
- package/dist/lib/browser-auth.js.map +0 -1
- package/dist/lib/openclaw.d.ts +0 -32
- package/dist/lib/openclaw.js +0 -164
- package/dist/lib/openclaw.js.map +0 -1
- package/dist/lib/seed.d.ts +0 -13
- package/dist/lib/seed.js +0 -135
- package/dist/lib/seed.js.map +0 -1
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
import chalk from "chalk";
|
|
16
16
|
import ora from "ora";
|
|
17
17
|
import prompts from "prompts";
|
|
18
|
-
import {
|
|
18
|
+
import { openExternalUrl } from "../lib/safe-open.js";
|
|
19
19
|
import { readFileSync } from "node:fs";
|
|
20
20
|
import { resolveHubConfig, hubGet, hubPost, hubDelete, HubError, renderHubError } from "../lib/hub-client.js";
|
|
21
21
|
import { unwrapList } from "../lib/unwrapList.js";
|
|
@@ -150,6 +150,20 @@ function findCard(cards, name) {
|
|
|
150
150
|
return (cards.find((c) => c.name.toLowerCase() === q) ??
|
|
151
151
|
cards.find((c) => c.key.toLowerCase() === q));
|
|
152
152
|
}
|
|
153
|
+
/**
|
|
154
|
+
* When a name doesn't match a pack, it's often a VERB (e.g. `exa_search`) rather
|
|
155
|
+
* than its pack (`exa`). Find the pack that owns a verb by that id/label so the
|
|
156
|
+
* caller can point the user at the right `enable` target instead of a dead end.
|
|
157
|
+
*/
|
|
158
|
+
function findCardByVerb(cards, name) {
|
|
159
|
+
const q = name.trim().toLowerCase();
|
|
160
|
+
for (const card of cards) {
|
|
161
|
+
const verb = card.verbs.find((v) => v.verbId.toLowerCase() === q || v.label.toLowerCase() === q);
|
|
162
|
+
if (verb)
|
|
163
|
+
return { card, verb };
|
|
164
|
+
}
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
153
167
|
/** Status → badge glyph (●/◑/○) per §6. */
|
|
154
168
|
function statusBadge(status) {
|
|
155
169
|
switch (status) {
|
|
@@ -217,7 +231,12 @@ function accountLabel(account) {
|
|
|
217
231
|
const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(account);
|
|
218
232
|
return isUuid ? null : account;
|
|
219
233
|
}
|
|
220
|
-
/**
|
|
234
|
+
/**
|
|
235
|
+
* A USABLE pack: name + its verbs grouped by exec-mode as compact NAME lists.
|
|
236
|
+
* The full `--param` signature is NOT dumped per verb here — that turned a pack
|
|
237
|
+
* with 20+ verbs into an unscannable wall. The list answers "what can this do?";
|
|
238
|
+
* `synap cap show <verb>` gives the exact run command for the one you pick.
|
|
239
|
+
*/
|
|
221
240
|
function renderUsable(card) {
|
|
222
241
|
const label = accountLabel(card.connection?.account);
|
|
223
242
|
const acct = label
|
|
@@ -225,13 +244,19 @@ function renderUsable(card) {
|
|
|
225
244
|
: card.connection?.provider
|
|
226
245
|
? chalk.dim(` · ${card.connection.provider} connected`)
|
|
227
246
|
: "";
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
247
|
+
const runnable = card.verbs.filter((x) => x.runnable);
|
|
248
|
+
const instant = runnable.filter((v) => v.type === "read");
|
|
249
|
+
const approval = runnable.filter((v) => v.type !== "read");
|
|
250
|
+
const count = chalk.dim(` · ${runnable.length} verb${runnable.length === 1 ? "" : "s"}` +
|
|
251
|
+
(approval.length ? `, ${approval.length} need approval` : ""));
|
|
252
|
+
console.log(` ${chalk.green("●")} ${chalk.bold(card.name)}${acct}${count}`);
|
|
253
|
+
if (instant.length > 0) {
|
|
254
|
+
console.log(` ${chalk.green("▸")} ${chalk.dim("instant ")} ` +
|
|
255
|
+
instant.map((v) => chalk.cyan(v.verbId)).join(" "));
|
|
256
|
+
}
|
|
257
|
+
if (approval.length > 0) {
|
|
258
|
+
console.log(` ${chalk.yellow("✋")} ${chalk.dim("approval")} ` +
|
|
259
|
+
approval.map((v) => chalk.cyan(v.verbId)).join(" "));
|
|
235
260
|
}
|
|
236
261
|
const off = card.verbs.filter((v) => !v.runnable);
|
|
237
262
|
if (off.length > 0) {
|
|
@@ -243,6 +268,12 @@ function renderUsable(card) {
|
|
|
243
268
|
function renderSetup(card) {
|
|
244
269
|
console.log(` ${chalk.yellow("◌")} ${chalk.bold(card.name)} ${chalk.dim(statusSummary(card))}`);
|
|
245
270
|
console.log(` ${chalk.cyan("→")} ${card.nextAction.hint || `synap cap enable "${card.name}"`}`);
|
|
271
|
+
// An expired connection reads as "needs a step", but the fix is a RECONNECT, not
|
|
272
|
+
// an enable — show the exact command so the hint's "Reconnect …" prose is
|
|
273
|
+
// actionable (the state word tells WHAT, this tells HOW).
|
|
274
|
+
if (card.connection?.state === "expired") {
|
|
275
|
+
console.log(` ${chalk.dim(`synap cap connect "${card.name}" --reconnect`)}`);
|
|
276
|
+
}
|
|
246
277
|
}
|
|
247
278
|
/** An AVAILABLE pack: one line — name · what it offers · add command. */
|
|
248
279
|
function renderAvailable(card) {
|
|
@@ -266,7 +297,7 @@ export async function capabilityList(opts) {
|
|
|
266
297
|
cfg = await resolveHubConfig();
|
|
267
298
|
}
|
|
268
299
|
catch (err) {
|
|
269
|
-
|
|
300
|
+
renderHubError(err);
|
|
270
301
|
process.exit(1);
|
|
271
302
|
}
|
|
272
303
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -283,7 +314,7 @@ export async function capabilityList(opts) {
|
|
|
283
314
|
return;
|
|
284
315
|
}
|
|
285
316
|
spinner?.fail(chalk.red("Failed to fetch capabilities"));
|
|
286
|
-
|
|
317
|
+
renderHubError(err);
|
|
287
318
|
process.exit(1);
|
|
288
319
|
}
|
|
289
320
|
if (opts.json) {
|
|
@@ -335,18 +366,8 @@ export async function capabilityList(opts) {
|
|
|
335
366
|
// ── Connection sub-flow (shared by enable + connect) ────────────────────────
|
|
336
367
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
337
368
|
function openBrowser(url) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
? `open "${url}"`
|
|
341
|
-
: platform === "win32"
|
|
342
|
-
? `start "" "${url}"`
|
|
343
|
-
: `xdg-open "${url}"`;
|
|
344
|
-
try {
|
|
345
|
-
exec(cmd);
|
|
346
|
-
}
|
|
347
|
-
catch {
|
|
348
|
-
// silently ignore — caller already prints the URL
|
|
349
|
-
}
|
|
369
|
+
// argv only, http(s) only — never a shell string (`safe-open.ts`).
|
|
370
|
+
openExternalUrl(url);
|
|
350
371
|
}
|
|
351
372
|
/** Short host label for a pod (for picker headers: "→ pod.perso…"). */
|
|
352
373
|
function podHostLabel(cfg) {
|
|
@@ -380,14 +401,117 @@ async function pollUntilConnected(cfg, provider, workspaceId, timeoutMs = 180_00
|
|
|
380
401
|
}
|
|
381
402
|
return null;
|
|
382
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* The ONE "connect a provider" path: resolve `/connectors/connect`, open the
|
|
406
|
+
* browser on the returned `redirectUrl`, and poll (self-completing door) until
|
|
407
|
+
* the provider flips to `connected`. Shared by the capability-card flow
|
|
408
|
+
* (`ensureConnection`) and the raw-provider discovery picker
|
|
409
|
+
* (`capabilityConnect` with no name), so both reach the identical endpoint,
|
|
410
|
+
* status handling, browser-open and poll semantics.
|
|
411
|
+
*
|
|
412
|
+
* `cardName` is the discriminator: when present the caller is connecting on
|
|
413
|
+
* behalf of a capability card, which enables the card-aware `provider_required`
|
|
414
|
+
* / `provider_unavailable` branches and the named re-run + timeout hints. The
|
|
415
|
+
* raw-picker path already holds an explicit provider id, so those branches do
|
|
416
|
+
* not apply to it — it goes straight from `connected` to the `redirectUrl`
|
|
417
|
+
* check, exactly as before.
|
|
418
|
+
*
|
|
419
|
+
* `displayName` is the local fallback name: the provider's list label for the
|
|
420
|
+
* raw picker, the provider id for the card flow (a card has no separate label).
|
|
421
|
+
*/
|
|
422
|
+
async function connectProviderOAuth(cfg, provider, workspaceId, ctx) {
|
|
423
|
+
const isCard = ctx.cardName !== undefined;
|
|
424
|
+
// Card flow prefers the server's displayName (falling back to the provider
|
|
425
|
+
// id); the raw picker uses its own list label verbatim.
|
|
426
|
+
const name = (r) => isCard ? String(r.displayName ?? ctx.displayName) : ctx.displayName;
|
|
427
|
+
const spinner = ora({
|
|
428
|
+
text: isCard ? `Resolving ${chalk.bold(provider)} connection…` : `Connecting ${chalk.bold(ctx.displayName)}…`,
|
|
429
|
+
color: "cyan",
|
|
430
|
+
}).start();
|
|
431
|
+
let res;
|
|
432
|
+
try {
|
|
433
|
+
const body = { provider };
|
|
434
|
+
if (workspaceId)
|
|
435
|
+
body.workspaceId = workspaceId;
|
|
436
|
+
if (ctx.forceReauth)
|
|
437
|
+
body.forceReauth = true;
|
|
438
|
+
res = (await hubPost("/connectors/connect", body, cfg));
|
|
439
|
+
spinner.stop();
|
|
440
|
+
}
|
|
441
|
+
catch (err) {
|
|
442
|
+
if (isCard)
|
|
443
|
+
spinner.fail(chalk.red("Failed to resolve connection"));
|
|
444
|
+
else
|
|
445
|
+
spinner.stop();
|
|
446
|
+
renderHubError(err);
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
const status = String(res.status);
|
|
450
|
+
if (status === "connected") {
|
|
451
|
+
// Both flows prefer the server's displayName here (falling back locally).
|
|
452
|
+
log.success(`${res.displayName ?? ctx.displayName} is already connected.`);
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
455
|
+
if (isCard && status === "provider_required") {
|
|
456
|
+
log.warn(`Couldn't resolve a single provider for ${ctx.cardName}.`);
|
|
457
|
+
log.dim(`Connect it directly: synap cap connect "${ctx.cardName}"`);
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
if (isCard && status === "provider_unavailable") {
|
|
461
|
+
// The pod can't offer this provider (not declared / unreachable / malformed).
|
|
462
|
+
// The server message already names the real cause + remedy — print it as-is.
|
|
463
|
+
// No browser, and no "re-run connect": re-running cannot fix a server-side gap.
|
|
464
|
+
log.warn(`${ctx.cardName} is unavailable on this pod.`);
|
|
465
|
+
if (res.message)
|
|
466
|
+
log.dim(String(res.message));
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
// setup_required (or any status this CLI doesn't know) → only ever open a
|
|
470
|
+
// browser when the server actually handed us a URL. An older/newer pod that
|
|
471
|
+
// returns a status we don't handle must NOT send the user to "undefined".
|
|
472
|
+
const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
|
|
473
|
+
if (!redirectUrl) {
|
|
474
|
+
log.warn(`Couldn't start a connection for ${name(res)}.`);
|
|
475
|
+
if (res.message)
|
|
476
|
+
log.dim(String(res.message));
|
|
477
|
+
else if (isCard)
|
|
478
|
+
log.dim(`The pod returned status "${status}" with no connect URL. Check the pod's connector configuration.`);
|
|
479
|
+
return false;
|
|
480
|
+
}
|
|
481
|
+
log.heading(`Connect ${name(res)}`);
|
|
482
|
+
console.log();
|
|
483
|
+
console.log(` Opening OAuth flow in your browser…`);
|
|
484
|
+
console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
|
|
485
|
+
console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
|
|
486
|
+
console.log();
|
|
487
|
+
openBrowser(redirectUrl);
|
|
488
|
+
const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
|
|
489
|
+
const connected = await pollUntilConnected(cfg, provider, workspaceId);
|
|
490
|
+
if (connected) {
|
|
491
|
+
waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(name(connected))}!`));
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
waitSpinner.stop();
|
|
495
|
+
log.dim(isCard
|
|
496
|
+
? `Didn't detect a connection yet — finish the browser flow, then re-run \`synap cap enable "${ctx.cardName}"\`.`
|
|
497
|
+
: `Didn't detect a connection yet — finish the browser flow, then re-run.`);
|
|
498
|
+
return false;
|
|
499
|
+
}
|
|
383
500
|
/**
|
|
384
501
|
* Ensure a capability's required connection is satisfied. Provider (nango://) →
|
|
385
502
|
* OAuth open + poll. Vault (vault://) → prompt for the key, POST /vault/secrets.
|
|
386
503
|
* Returns true when the connection is (now) satisfied, false otherwise.
|
|
387
504
|
*/
|
|
388
|
-
async function ensureConnection(cfg, workspaceId, card
|
|
505
|
+
async function ensureConnection(cfg, workspaceId, card,
|
|
506
|
+
// Force a re-auth even when the card reports `state === "connected"`. The card
|
|
507
|
+
// reflects a connection RECORD's existence, not its token's HEALTH, so an
|
|
508
|
+
// expired/revoked token still reads "connected" — only a forced fresh OAuth
|
|
509
|
+
// fixes it. Threaded to the provider door as `forceReauth`.
|
|
510
|
+
forceReconnect = false) {
|
|
389
511
|
const conn = card.connection;
|
|
390
|
-
if (!conn || !conn.required
|
|
512
|
+
if (!conn || !conn.required)
|
|
513
|
+
return true;
|
|
514
|
+
if (conn.state === "connected" && !forceReconnect)
|
|
391
515
|
return true;
|
|
392
516
|
// NOTE: `state === "unavailable"` is deliberately NOT short-circuited here.
|
|
393
517
|
// Resolving the door is not an OAuth attempt — it returns 200 with the pod's
|
|
@@ -428,70 +552,19 @@ async function ensureConnection(cfg, workspaceId, card) {
|
|
|
428
552
|
}
|
|
429
553
|
catch (err) {
|
|
430
554
|
spinner.fail(chalk.red("Failed to store credential"));
|
|
431
|
-
|
|
555
|
+
renderHubError(err);
|
|
432
556
|
return false;
|
|
433
557
|
}
|
|
434
558
|
}
|
|
435
559
|
// ── Provider OAuth (nango://) — open + poll ───────────────────────────────
|
|
436
560
|
const provider = conn.provider ?? card.key;
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
spinner.fail(chalk.red("Failed to resolve connection"));
|
|
445
|
-
log.error(err.message);
|
|
446
|
-
return false;
|
|
447
|
-
}
|
|
448
|
-
const status = String(res.status);
|
|
449
|
-
if (status === "connected") {
|
|
450
|
-
log.success(`${res.displayName ?? provider} is already connected.`);
|
|
451
|
-
return true;
|
|
452
|
-
}
|
|
453
|
-
if (status === "provider_required") {
|
|
454
|
-
log.warn(`Couldn't resolve a single provider for ${card.name}.`);
|
|
455
|
-
log.dim(`Connect it directly: synap cap connect "${card.name}"`);
|
|
456
|
-
return false;
|
|
457
|
-
}
|
|
458
|
-
if (status === "provider_unavailable") {
|
|
459
|
-
// The pod can't offer this provider (not declared / unreachable / malformed).
|
|
460
|
-
// The server message already names the real cause + remedy — print it as-is.
|
|
461
|
-
// No browser, and no "re-run connect": re-running cannot fix a server-side gap.
|
|
462
|
-
log.warn(`${card.name} is unavailable on this pod.`);
|
|
463
|
-
if (res.message)
|
|
464
|
-
log.dim(String(res.message));
|
|
465
|
-
return false;
|
|
466
|
-
}
|
|
467
|
-
// setup_required (or any status this CLI doesn't know) → only ever open a
|
|
468
|
-
// browser when the server actually handed us a URL. An older/newer pod that
|
|
469
|
-
// returns a status we don't handle must NOT send the user to "undefined".
|
|
470
|
-
const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
|
|
471
|
-
if (!redirectUrl) {
|
|
472
|
-
log.warn(`Couldn't start a connection for ${res.displayName ?? provider}.`);
|
|
473
|
-
if (res.message)
|
|
474
|
-
log.dim(String(res.message));
|
|
475
|
-
else
|
|
476
|
-
log.dim(`The pod returned status "${status}" with no connect URL. Check the pod's connector configuration.`);
|
|
477
|
-
return false;
|
|
478
|
-
}
|
|
479
|
-
log.heading(`Connect ${res.displayName ?? provider}`);
|
|
480
|
-
console.log();
|
|
481
|
-
console.log(` Opening OAuth flow in your browser…`);
|
|
482
|
-
console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
|
|
483
|
-
console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
|
|
484
|
-
console.log();
|
|
485
|
-
openBrowser(redirectUrl);
|
|
486
|
-
const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
|
|
487
|
-
const connected = await pollUntilConnected(cfg, provider, workspaceId);
|
|
488
|
-
if (connected) {
|
|
489
|
-
waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(String(connected.displayName ?? provider))}!`));
|
|
490
|
-
return true;
|
|
491
|
-
}
|
|
492
|
-
waitSpinner.stop();
|
|
493
|
-
log.dim(`Didn't detect a connection yet — finish the browser flow, then re-run \`synap cap enable "${card.name}"\`.`);
|
|
494
|
-
return false;
|
|
561
|
+
return connectProviderOAuth(cfg, provider, workspaceId, {
|
|
562
|
+
// A card has no separate display name — the provider id is the fallback the
|
|
563
|
+
// server's displayName (when sent) takes precedence over.
|
|
564
|
+
displayName: provider,
|
|
565
|
+
cardName: card.name,
|
|
566
|
+
forceReauth: forceReconnect,
|
|
567
|
+
});
|
|
495
568
|
}
|
|
496
569
|
/**
|
|
497
570
|
* Prompt for a template's REQUIRED install params (masked for secrets). Returns
|
|
@@ -551,58 +624,9 @@ async function applyTemplateWithParams(cfg, card, workspaceId, params, verb) {
|
|
|
551
624
|
}
|
|
552
625
|
catch (err) {
|
|
553
626
|
spinner.fail(chalk.red(`Failed to ${verb.toLowerCase()} ${card.name}`));
|
|
554
|
-
log.error(err.message);
|
|
555
|
-
return false;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
/**
|
|
559
|
-
* Connect a RAW provider chosen from the discovery picker (not tied to a
|
|
560
|
-
* capability card): start OAuth via `/connectors/connect`, open the browser, and
|
|
561
|
-
* poll until it flips to connected. Same door + poll the card flow uses.
|
|
562
|
-
*/
|
|
563
|
-
async function connectProviderFlow(cfg, provider, displayName, workspaceId) {
|
|
564
|
-
const spinner = ora({ text: `Connecting ${chalk.bold(displayName)}…`, color: "cyan" }).start();
|
|
565
|
-
let res;
|
|
566
|
-
try {
|
|
567
|
-
const body = { provider };
|
|
568
|
-
if (workspaceId)
|
|
569
|
-
body.workspaceId = workspaceId;
|
|
570
|
-
res = (await hubPost("/connectors/connect", body, cfg));
|
|
571
|
-
spinner.stop();
|
|
572
|
-
}
|
|
573
|
-
catch (err) {
|
|
574
|
-
spinner.stop();
|
|
575
627
|
renderHubError(err);
|
|
576
628
|
return false;
|
|
577
629
|
}
|
|
578
|
-
if (String(res.status) === "connected") {
|
|
579
|
-
log.success(`${res.displayName ?? displayName} is already connected.`);
|
|
580
|
-
return true;
|
|
581
|
-
}
|
|
582
|
-
const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
|
|
583
|
-
if (!redirectUrl) {
|
|
584
|
-
log.warn(`Couldn't start a connection for ${displayName}.`);
|
|
585
|
-
// Covers provider_unavailable too — the server message names the real cause.
|
|
586
|
-
if (res.message)
|
|
587
|
-
log.dim(String(res.message));
|
|
588
|
-
return false;
|
|
589
|
-
}
|
|
590
|
-
log.heading(`Connect ${displayName}`);
|
|
591
|
-
console.log();
|
|
592
|
-
console.log(` Opening OAuth flow in your browser…`);
|
|
593
|
-
console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
|
|
594
|
-
console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
|
|
595
|
-
console.log();
|
|
596
|
-
openBrowser(redirectUrl);
|
|
597
|
-
const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
|
|
598
|
-
const connected = await pollUntilConnected(cfg, provider, workspaceId);
|
|
599
|
-
if (connected) {
|
|
600
|
-
waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(displayName)}!`));
|
|
601
|
-
return true;
|
|
602
|
-
}
|
|
603
|
-
waitSpinner.stop();
|
|
604
|
-
log.dim(`Didn't detect a connection yet — finish the browser flow, then re-run.`);
|
|
605
|
-
return false;
|
|
606
630
|
}
|
|
607
631
|
export async function capabilityAdd(name, opts) {
|
|
608
632
|
let cfg;
|
|
@@ -610,7 +634,7 @@ export async function capabilityAdd(name, opts) {
|
|
|
610
634
|
cfg = await resolveHubConfig();
|
|
611
635
|
}
|
|
612
636
|
catch (err) {
|
|
613
|
-
|
|
637
|
+
renderHubError(err);
|
|
614
638
|
process.exit(1);
|
|
615
639
|
}
|
|
616
640
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -630,7 +654,7 @@ export async function capabilityAdd(name, opts) {
|
|
|
630
654
|
return;
|
|
631
655
|
}
|
|
632
656
|
spinner.fail(chalk.red("Failed to fetch catalog"));
|
|
633
|
-
|
|
657
|
+
renderHubError(err);
|
|
634
658
|
process.exit(1);
|
|
635
659
|
}
|
|
636
660
|
// No name given → open an interactive picker over the AVAILABLE (not-yet-
|
|
@@ -736,23 +760,85 @@ export async function capabilityAdd(name, opts) {
|
|
|
736
760
|
}
|
|
737
761
|
catch (err) {
|
|
738
762
|
addSpinner.fail(chalk.red(`Failed to add ${card.name}`));
|
|
739
|
-
|
|
763
|
+
renderHubError(err);
|
|
740
764
|
process.exit(1);
|
|
741
765
|
}
|
|
742
766
|
}
|
|
743
|
-
// Re-fetch to
|
|
767
|
+
// Re-fetch to get the installed card (verbs + skillIds).
|
|
768
|
+
let after;
|
|
744
769
|
try {
|
|
745
|
-
|
|
746
|
-
if (after) {
|
|
747
|
-
console.log();
|
|
748
|
-
renderCardAny(after);
|
|
749
|
-
}
|
|
770
|
+
after = findCard(await fetchCatalog(cfg, workspaceId), card.name);
|
|
750
771
|
}
|
|
751
772
|
catch {
|
|
752
773
|
// best-effort — the add already succeeded
|
|
753
774
|
}
|
|
775
|
+
// CONNECT-first: a provider capability that isn't connected yet runs the OAuth
|
|
776
|
+
// flow now, so `cap add` is the ONE happy-path door (apply → connect → enable
|
|
777
|
+
// reads). `ensureConnection` is the shared provider+OAuth path; a failed or
|
|
778
|
+
// timed-out OAuth returns false and leaves the card un-connected — recover
|
|
779
|
+
// with `synap cap connect "<name>"`. No-connection / already-connected cards
|
|
780
|
+
// skip this.
|
|
781
|
+
if (after?.connection?.required && after.connection.state !== "connected") {
|
|
782
|
+
await ensureConnection(cfg, workspaceId, after);
|
|
783
|
+
try {
|
|
784
|
+
after = findCard(await fetchCatalog(cfg, workspaceId), card.name) ?? after;
|
|
785
|
+
}
|
|
786
|
+
catch {
|
|
787
|
+
// keep the pre-connect card
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
// AUTO-ENABLE the read verbs, so install is ONE step, not two. Reads are the
|
|
791
|
+
// `auto`-governance, no-side-effect verbs — safe to turn on without asking.
|
|
792
|
+
// Write/action verbs stay OFF (they ask approval per run); enable them later
|
|
793
|
+
// with `cap enable`. This also removes the wrong-pod footgun the second command
|
|
794
|
+
// caused: `cap enable` (no --pod) targets the ACTIVE pod, not the install's
|
|
795
|
+
// --pod, so it "couldn't find" a capability installed on a different pod.
|
|
796
|
+
const autoEnabled = [];
|
|
797
|
+
const connectionReady = !after?.connection?.required || after?.connection?.state === "connected";
|
|
798
|
+
if (after && after.verbs.length > 0 && connectionReady) {
|
|
799
|
+
const reads = after.verbs.filter((v) => v.type === "read" && !v.enabled);
|
|
800
|
+
if (reads.length > 0) {
|
|
801
|
+
const idByName = reads.some((v) => !v.skillId)
|
|
802
|
+
? new Map((await fetchSkills(cfg, workspaceId).catch(() => [])).map((s) => [s.name, s.id]))
|
|
803
|
+
: new Map();
|
|
804
|
+
const work = ora({ text: "Turning on read verbs…", color: "cyan" }).start();
|
|
805
|
+
try {
|
|
806
|
+
for (const v of reads) {
|
|
807
|
+
const skillId = v.skillId ?? idByName.get(v.verbId);
|
|
808
|
+
if (!skillId)
|
|
809
|
+
continue;
|
|
810
|
+
await hubPost(`/skills/${skillId}/approve`, { approved: true }, cfg);
|
|
811
|
+
autoEnabled.push(v.label);
|
|
812
|
+
}
|
|
813
|
+
work.stop();
|
|
814
|
+
}
|
|
815
|
+
catch (err) {
|
|
816
|
+
work.stop();
|
|
817
|
+
log.dim(`(Couldn't auto-enable read verbs — run \`synap cap enable "${card.name}"\`. ${err.message})`);
|
|
818
|
+
}
|
|
819
|
+
try {
|
|
820
|
+
after = findCard(await fetchCatalog(cfg, workspaceId), card.name) ?? after;
|
|
821
|
+
}
|
|
822
|
+
catch {
|
|
823
|
+
// keep the pre-enable card for the render below
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (after) {
|
|
828
|
+
console.log();
|
|
829
|
+
renderCardAny(after);
|
|
830
|
+
}
|
|
754
831
|
console.log();
|
|
755
|
-
|
|
832
|
+
if (autoEnabled.length > 0) {
|
|
833
|
+
log.success(`Enabled ${autoEnabled.length} read verb${autoEnabled.length === 1 ? "" : "s"}: ${autoEnabled.join(", ")}`);
|
|
834
|
+
}
|
|
835
|
+
const pendingWrites = (after?.verbs ?? []).filter((v) => v.type !== "read" && !v.enabled);
|
|
836
|
+
if (pendingWrites.length > 0) {
|
|
837
|
+
log.dim(`${pendingWrites.length} write/action verb${pendingWrites.length === 1 ? "" : "s"} stay off (they ask approval per run). Turn on: synap cap enable "${card.name}"`);
|
|
838
|
+
}
|
|
839
|
+
else if (autoEnabled.length === 0) {
|
|
840
|
+
log.dim(`Turn it on: synap cap enable "${card.name}"`);
|
|
841
|
+
}
|
|
756
842
|
}
|
|
757
843
|
export async function capabilityEnable(name, opts) {
|
|
758
844
|
let cfg;
|
|
@@ -760,7 +846,7 @@ export async function capabilityEnable(name, opts) {
|
|
|
760
846
|
cfg = await resolveHubConfig();
|
|
761
847
|
}
|
|
762
848
|
catch (err) {
|
|
763
|
-
|
|
849
|
+
renderHubError(err);
|
|
764
850
|
process.exit(1);
|
|
765
851
|
}
|
|
766
852
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -780,7 +866,7 @@ export async function capabilityEnable(name, opts) {
|
|
|
780
866
|
catalogNeedsDeploy();
|
|
781
867
|
return;
|
|
782
868
|
}
|
|
783
|
-
|
|
869
|
+
renderHubError(err);
|
|
784
870
|
process.exit(1);
|
|
785
871
|
}
|
|
786
872
|
if (cards.length === 0) {
|
|
@@ -827,8 +913,10 @@ export async function capabilityEnable(name, opts) {
|
|
|
827
913
|
}
|
|
828
914
|
const spinner = ora({ text: `Resolving ${chalk.bold(name)}…`, color: "cyan" }).start();
|
|
829
915
|
let card;
|
|
916
|
+
let catalog = [];
|
|
830
917
|
try {
|
|
831
|
-
|
|
918
|
+
catalog = await fetchCatalog(cfg, workspaceId);
|
|
919
|
+
card = findCard(catalog, name);
|
|
832
920
|
spinner.stop();
|
|
833
921
|
}
|
|
834
922
|
catch (err) {
|
|
@@ -838,10 +926,18 @@ export async function capabilityEnable(name, opts) {
|
|
|
838
926
|
return;
|
|
839
927
|
}
|
|
840
928
|
spinner.fail(chalk.red("Failed to fetch catalog"));
|
|
841
|
-
|
|
929
|
+
renderHubError(err);
|
|
842
930
|
process.exit(1);
|
|
843
931
|
}
|
|
844
932
|
if (!card) {
|
|
933
|
+
// A verb name (e.g. `exa_search`) isn't a pack — `enable` takes the PACK
|
|
934
|
+
// (`exa`). Point at the owning pack instead of dead-ending.
|
|
935
|
+
const owner = findCardByVerb(catalog, name);
|
|
936
|
+
if (owner) {
|
|
937
|
+
log.error(`"${name}" is a verb of the "${owner.card.name}" pack, not a capability itself.`);
|
|
938
|
+
log.dim(`Enable the pack (it lets you pick verbs): synap cap enable "${owner.card.name}"`);
|
|
939
|
+
process.exit(1);
|
|
940
|
+
}
|
|
845
941
|
log.error(`No capability named "${name}".`);
|
|
846
942
|
log.dim("Run `synap cap list` to see what's available, or `synap cap add <name>` first.");
|
|
847
943
|
process.exit(1);
|
|
@@ -929,7 +1025,7 @@ export async function capabilityEnable(name, opts) {
|
|
|
929
1025
|
}
|
|
930
1026
|
catch (err) {
|
|
931
1027
|
work.fail(chalk.red("Failed while applying your selection"));
|
|
932
|
-
|
|
1028
|
+
renderHubError(err);
|
|
933
1029
|
process.exit(1);
|
|
934
1030
|
}
|
|
935
1031
|
// (d) Report what changed + an example run.
|
|
@@ -950,7 +1046,7 @@ export async function capabilityConnect(name, opts) {
|
|
|
950
1046
|
cfg = await resolveHubConfig();
|
|
951
1047
|
}
|
|
952
1048
|
catch (err) {
|
|
953
|
-
|
|
1049
|
+
renderHubError(err);
|
|
954
1050
|
process.exit(1);
|
|
955
1051
|
}
|
|
956
1052
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -971,7 +1067,7 @@ export async function capabilityConnect(name, opts) {
|
|
|
971
1067
|
}
|
|
972
1068
|
catch (err) {
|
|
973
1069
|
spin.stop();
|
|
974
|
-
|
|
1070
|
+
renderHubError(err);
|
|
975
1071
|
log.dim("Couldn't reach the pod's connector service.");
|
|
976
1072
|
return;
|
|
977
1073
|
}
|
|
@@ -991,18 +1087,22 @@ export async function capabilityConnect(name, opts) {
|
|
|
991
1087
|
}
|
|
992
1088
|
const connectable = providers.filter((p) => !p.connected);
|
|
993
1089
|
const connected = providers.filter((p) => p.connected);
|
|
994
|
-
|
|
1090
|
+
// --reconnect: the point is to re-auth an ALREADY-connected (but expired)
|
|
1091
|
+
// service, so connected rows become selectable (a fresh OAuth) rather than
|
|
1092
|
+
// disabled, and "everything already connected" is no longer a dead end.
|
|
1093
|
+
if (connectable.length === 0 && !opts.reconnect) {
|
|
995
1094
|
log.heading("Everything connectable here is already connected.");
|
|
996
1095
|
for (const p of connected)
|
|
997
1096
|
log.dim(` ${chalk.green("✓")} ${p.displayName ?? p.provider}`);
|
|
1097
|
+
log.dim("Reconnect an expired one: synap cap connect --reconnect");
|
|
998
1098
|
return;
|
|
999
1099
|
}
|
|
1000
1100
|
const answer = await prompts({
|
|
1001
1101
|
type: "select",
|
|
1002
1102
|
name: "id",
|
|
1003
|
-
message:
|
|
1004
|
-
// Connectable first; already-connected
|
|
1005
|
-
//
|
|
1103
|
+
message: `${opts.reconnect ? "Reconnect" : "Connect"} a service ${chalk.dim(`→ ${podHostLabel(cfg)}`)}`,
|
|
1104
|
+
// Connectable first; already-connected grouped at the end — disabled in the
|
|
1105
|
+
// normal flow, but SELECTABLE (for a forced re-auth) under --reconnect.
|
|
1006
1106
|
choices: [
|
|
1007
1107
|
...connectable.map((p) => ({
|
|
1008
1108
|
title: p.displayName ?? p.provider,
|
|
@@ -1010,9 +1110,9 @@ export async function capabilityConnect(name, opts) {
|
|
|
1010
1110
|
})),
|
|
1011
1111
|
...connected.map((p) => ({
|
|
1012
1112
|
title: `${p.displayName ?? p.provider} ${chalk.green("✓ connected")}`,
|
|
1013
|
-
description: "already connected",
|
|
1113
|
+
description: opts.reconnect ? "re-authenticate" : "already connected",
|
|
1014
1114
|
value: p.id,
|
|
1015
|
-
disabled:
|
|
1115
|
+
disabled: !opts.reconnect,
|
|
1016
1116
|
})),
|
|
1017
1117
|
],
|
|
1018
1118
|
});
|
|
@@ -1021,7 +1121,10 @@ export async function capabilityConnect(name, opts) {
|
|
|
1021
1121
|
return;
|
|
1022
1122
|
}
|
|
1023
1123
|
const chosen = providers.find((p) => p.id === answer.id);
|
|
1024
|
-
const ok = await
|
|
1124
|
+
const ok = await connectProviderOAuth(cfg, chosen.id, workspaceId, {
|
|
1125
|
+
displayName: chosen.displayName ?? chosen.provider,
|
|
1126
|
+
forceReauth: opts.reconnect ?? false,
|
|
1127
|
+
});
|
|
1025
1128
|
// A connect that did not connect must not report success to a caller/script.
|
|
1026
1129
|
if (!ok)
|
|
1027
1130
|
process.exit(1);
|
|
@@ -1040,7 +1143,7 @@ export async function capabilityConnect(name, opts) {
|
|
|
1040
1143
|
return;
|
|
1041
1144
|
}
|
|
1042
1145
|
spinner.fail(chalk.red("Failed to fetch catalog"));
|
|
1043
|
-
|
|
1146
|
+
renderHubError(err);
|
|
1044
1147
|
process.exit(1);
|
|
1045
1148
|
}
|
|
1046
1149
|
if (!card) {
|
|
@@ -1053,7 +1156,11 @@ export async function capabilityConnect(name, opts) {
|
|
|
1053
1156
|
log.dim(`Enable its verbs: synap cap enable "${card.name}"`);
|
|
1054
1157
|
return;
|
|
1055
1158
|
}
|
|
1056
|
-
|
|
1159
|
+
if (opts.reconnect) {
|
|
1160
|
+
log.heading(`Reconnecting ${card.name}`);
|
|
1161
|
+
log.dim("Forcing a fresh sign-in — your previous access had expired or was revoked.");
|
|
1162
|
+
}
|
|
1163
|
+
const ok = await ensureConnection(cfg, workspaceId, card, opts.reconnect ?? false);
|
|
1057
1164
|
if (!ok)
|
|
1058
1165
|
process.exit(1);
|
|
1059
1166
|
log.dim(`Now enable its verbs: synap cap enable "${card.name}"`);
|
|
@@ -1076,7 +1183,7 @@ export async function capabilityDisconnect(name, opts) {
|
|
|
1076
1183
|
cfg = await resolveHubConfig();
|
|
1077
1184
|
}
|
|
1078
1185
|
catch (err) {
|
|
1079
|
-
|
|
1186
|
+
renderHubError(err);
|
|
1080
1187
|
process.exit(1);
|
|
1081
1188
|
}
|
|
1082
1189
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -1160,7 +1267,7 @@ export async function capabilityShow(name, opts) {
|
|
|
1160
1267
|
cfg = await resolveHubConfig();
|
|
1161
1268
|
}
|
|
1162
1269
|
catch (err) {
|
|
1163
|
-
|
|
1270
|
+
renderHubError(err);
|
|
1164
1271
|
process.exit(1);
|
|
1165
1272
|
}
|
|
1166
1273
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -1177,7 +1284,7 @@ export async function capabilityShow(name, opts) {
|
|
|
1177
1284
|
return;
|
|
1178
1285
|
}
|
|
1179
1286
|
spinner?.fail(chalk.red("Failed to fetch catalog"));
|
|
1180
|
-
|
|
1287
|
+
renderHubError(err);
|
|
1181
1288
|
process.exit(1);
|
|
1182
1289
|
}
|
|
1183
1290
|
if (!card) {
|
|
@@ -1198,20 +1305,34 @@ export async function capabilityShow(name, opts) {
|
|
|
1198
1305
|
const c = card.connection;
|
|
1199
1306
|
// `unavailable` is dim, not red: it isn't the user's fault and isn't fixable
|
|
1200
1307
|
// by connecting — red reads as "you have a missing credential to go fix".
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1308
|
+
// Unverified: the pod could not actually check (a broker/list fault), not a
|
|
1309
|
+
// checked absence. Render distinctly from a plain "missing" — that would
|
|
1310
|
+
// falsely claim "you never connected this".
|
|
1311
|
+
const stateColor = c.unverified
|
|
1312
|
+
? chalk.yellow
|
|
1313
|
+
: c.state === "connected"
|
|
1314
|
+
? chalk.green
|
|
1315
|
+
: c.state === "expired"
|
|
1316
|
+
? chalk.yellow
|
|
1317
|
+
: c.state === "unavailable"
|
|
1318
|
+
? chalk.dim
|
|
1319
|
+
: chalk.red;
|
|
1320
|
+
const stateLabel = c.unverified ? "couldn't check" : c.state;
|
|
1208
1321
|
const parts = [
|
|
1209
1322
|
c.kind ?? "connection",
|
|
1210
1323
|
c.provider ? chalk.dim(`(${c.provider})`) : "",
|
|
1211
1324
|
c.account ? chalk.dim(c.account) : "",
|
|
1212
|
-
stateColor(
|
|
1325
|
+
stateColor(stateLabel),
|
|
1213
1326
|
].filter(Boolean);
|
|
1214
1327
|
console.log(` ${chalk.bold("Connection")} ${parts.join(" ")}`);
|
|
1328
|
+
// Expired = previously connected, token now dead. Surface the exact command to
|
|
1329
|
+
// fix it — the state word alone tells WHAT, not HOW (the user's original ask).
|
|
1330
|
+
if (c.state === "expired") {
|
|
1331
|
+
console.log(` ${chalk.yellow("→")} its access expired — reconnect: synap cap connect "${card.name}" --reconnect`);
|
|
1332
|
+
}
|
|
1333
|
+
else if (c.unverified) {
|
|
1334
|
+
console.log(` ${chalk.yellow("→")} ${c.unverified.message || c.unverified.reason} — retry: synap cap show "${card.name}"`);
|
|
1335
|
+
}
|
|
1215
1336
|
}
|
|
1216
1337
|
else {
|
|
1217
1338
|
console.log(` ${chalk.bold("Connection")} ${chalk.dim("none required")}`);
|
|
@@ -1246,7 +1367,7 @@ export async function capabilityRun(verb, params, opts) {
|
|
|
1246
1367
|
cfg = await resolveHubConfig();
|
|
1247
1368
|
}
|
|
1248
1369
|
catch (err) {
|
|
1249
|
-
|
|
1370
|
+
renderHubError(err);
|
|
1250
1371
|
process.exit(1);
|
|
1251
1372
|
}
|
|
1252
1373
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -1324,7 +1445,7 @@ export async function capabilityTest(verb, opts) {
|
|
|
1324
1445
|
cfg = await resolveHubConfig();
|
|
1325
1446
|
}
|
|
1326
1447
|
catch (err) {
|
|
1327
|
-
|
|
1448
|
+
renderHubError(err);
|
|
1328
1449
|
process.exit(1);
|
|
1329
1450
|
}
|
|
1330
1451
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -1335,7 +1456,7 @@ export async function capabilityTest(verb, opts) {
|
|
|
1335
1456
|
}
|
|
1336
1457
|
catch (err) {
|
|
1337
1458
|
spinner.fail(chalk.red("Failed to resolve capability"));
|
|
1338
|
-
|
|
1459
|
+
renderHubError(err);
|
|
1339
1460
|
process.exit(1);
|
|
1340
1461
|
}
|
|
1341
1462
|
if (!skillId) {
|
|
@@ -1351,7 +1472,7 @@ export async function capabilityTest(verb, opts) {
|
|
|
1351
1472
|
}
|
|
1352
1473
|
catch (err) {
|
|
1353
1474
|
spinner.fail(chalk.red(`Dry-run failed for ${verb}`));
|
|
1354
|
-
|
|
1475
|
+
renderHubError(err);
|
|
1355
1476
|
process.exit(1);
|
|
1356
1477
|
}
|
|
1357
1478
|
log.heading(`Dry-run preview — ${chalk.bold(verb)}`);
|
|
@@ -1387,7 +1508,7 @@ export async function capabilityCreate(file, opts) {
|
|
|
1387
1508
|
cfg = await resolveHubConfig();
|
|
1388
1509
|
}
|
|
1389
1510
|
catch (err) {
|
|
1390
|
-
|
|
1511
|
+
renderHubError(err);
|
|
1391
1512
|
process.exit(1);
|
|
1392
1513
|
}
|
|
1393
1514
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
@@ -1430,7 +1551,7 @@ export async function capabilityCreate(file, opts) {
|
|
|
1430
1551
|
}
|
|
1431
1552
|
catch (err) {
|
|
1432
1553
|
spinner.fail(chalk.red("Failed to create capability"));
|
|
1433
|
-
|
|
1554
|
+
renderHubError(err);
|
|
1434
1555
|
process.exit(1);
|
|
1435
1556
|
}
|
|
1436
1557
|
const created = (res.created ?? {});
|