@synap-core/cli 1.12.2 → 1.13.1-next.20261102.246dc73
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/LICENSE +21 -0
- package/README.md +38 -11
- package/dist/build-info.json +2 -3
- package/dist/commands/agents.d.ts +0 -1
- package/dist/commands/agents.js +13 -3
- package/dist/commands/agents.js.map +1 -1
- package/dist/commands/app.js +2 -1
- package/dist/commands/app.js.map +1 -1
- package/dist/commands/automation.js +46 -41
- package/dist/commands/automation.js.map +1 -1
- package/dist/commands/box.d.ts +42 -0
- package/dist/commands/box.js +89 -0
- package/dist/commands/box.js.map +1 -0
- package/dist/commands/bridge-setup.js +3 -1
- package/dist/commands/bridge-setup.js.map +1 -1
- package/dist/commands/capability.d.ts +87 -1
- package/dist/commands/capability.js +174 -64
- package/dist/commands/capability.js.map +1 -1
- package/dist/commands/close-questions.d.ts +27 -0
- package/dist/commands/close-questions.js +49 -0
- package/dist/commands/close-questions.js.map +1 -0
- package/dist/commands/close-questions.test.d.ts +1 -0
- package/dist/commands/close-questions.test.js +52 -0
- package/dist/commands/close-questions.test.js.map +1 -0
- package/dist/commands/connect.d.ts +1 -3
- package/dist/commands/connect.js +2 -2
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/context.js +74 -44
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +13 -0
- package/dist/commands/data-extra.js +35 -6
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.js +2 -1
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/doctor.d.ts +39 -0
- package/dist/commands/doctor.js +136 -14
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/hooks.d.ts +19 -0
- package/dist/commands/hooks.js +70 -0
- package/dist/commands/hooks.js.map +1 -0
- package/dist/commands/import.d.ts +25 -0
- package/dist/commands/import.js +98 -12
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +14 -0
- package/dist/commands/init.js +63 -21
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/keys-request.d.ts +48 -0
- package/dist/commands/keys-request.js +236 -0
- package/dist/commands/keys-request.js.map +1 -0
- package/dist/commands/keys-request.test.d.ts +1 -0
- package/dist/commands/keys-request.test.js +176 -0
- package/dist/commands/keys-request.test.js.map +1 -0
- package/dist/commands/knowledge.d.ts +42 -5
- package/dist/commands/knowledge.js +94 -29
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/lens.js +2 -1
- package/dist/commands/lens.js.map +1 -1
- package/dist/commands/market-authoring.js +1 -1
- package/dist/commands/market-authoring.js.map +1 -1
- package/dist/commands/market.d.ts +89 -31
- package/dist/commands/market.js +215 -222
- package/dist/commands/market.js.map +1 -1
- package/dist/commands/mcp.d.ts +1 -1
- package/dist/commands/mcp.js +14 -9
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/observe.category.test.d.ts +1 -0
- package/dist/commands/observe.category.test.js +59 -0
- package/dist/commands/observe.category.test.js.map +1 -0
- package/dist/commands/observe.d.ts +3 -0
- package/dist/commands/observe.js +7 -5
- package/dist/commands/observe.js.map +1 -1
- package/dist/commands/observe.title.test.d.ts +1 -0
- package/dist/commands/observe.title.test.js +37 -0
- package/dist/commands/observe.title.test.js.map +1 -0
- package/dist/commands/playbook.js +9 -0
- package/dist/commands/playbook.js.map +1 -1
- package/dist/commands/pods.d.ts +6 -1
- package/dist/commands/pods.js +38 -17
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.js +7 -1
- package/dist/commands/proposals-actions.js.map +1 -1
- package/dist/commands/proton-setup.js +3 -1
- package/dist/commands/proton-setup.js.map +1 -1
- package/dist/commands/providers.d.ts +22 -6
- package/dist/commands/providers.js +39 -32
- package/dist/commands/providers.js.map +1 -1
- package/dist/commands/raycast.d.ts +15 -0
- package/dist/commands/raycast.js +36 -10
- package/dist/commands/raycast.js.map +1 -1
- package/dist/commands/session-feed-wait.d.ts +48 -0
- package/dist/commands/session-feed-wait.js +261 -0
- package/dist/commands/session-feed-wait.js.map +1 -0
- package/dist/commands/session-post.d.ts +40 -0
- package/dist/commands/session-post.js +96 -0
- package/dist/commands/session-post.js.map +1 -0
- package/dist/commands/session-wait.d.ts +9 -4
- package/dist/commands/session-wait.js +20 -5
- package/dist/commands/session-wait.js.map +1 -1
- package/dist/commands/sessions.d.ts +2 -0
- package/dist/commands/sessions.js +23 -0
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/skills-commands.d.ts +2 -0
- package/dist/commands/skills-commands.js +9 -1
- package/dist/commands/skills-commands.js.map +1 -1
- package/dist/commands/skills-commands.test.d.ts +1 -0
- package/dist/commands/skills-commands.test.js +57 -0
- package/dist/commands/skills-commands.test.js.map +1 -0
- package/dist/commands/status.js +13 -7
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/statusline.backoff.test.js +13 -3
- package/dist/commands/statusline.backoff.test.js.map +1 -1
- package/dist/commands/statusline.d.ts +104 -9
- package/dist/commands/statusline.js +392 -148
- package/dist/commands/statusline.js.map +1 -1
- package/dist/commands/statusline.line2.test.d.ts +15 -0
- package/dist/commands/statusline.line2.test.js +226 -0
- package/dist/commands/statusline.line2.test.js.map +1 -0
- package/dist/commands/statusline.needs-you.test.d.ts +1 -0
- package/dist/commands/statusline.needs-you.test.js +17 -0
- package/dist/commands/statusline.needs-you.test.js.map +1 -0
- package/dist/commands/statusline.now.test.d.ts +10 -0
- package/dist/commands/statusline.now.test.js +250 -0
- package/dist/commands/statusline.now.test.js.map +1 -0
- package/dist/commands/tracks.d.ts +68 -6
- package/dist/commands/tracks.js +272 -16
- package/dist/commands/tracks.js.map +1 -1
- package/dist/commands/upload.js +12 -0
- package/dist/commands/upload.js.map +1 -1
- package/dist/commands/wait.d.ts +124 -0
- package/dist/commands/wait.js +384 -0
- package/dist/commands/wait.js.map +1 -0
- package/dist/commands/wait.test.d.ts +8 -0
- package/dist/commands/wait.test.js +308 -0
- package/dist/commands/wait.test.js.map +1 -0
- package/dist/commands/whoami.d.ts +7 -0
- package/dist/commands/whoami.js +17 -0
- package/dist/commands/whoami.js.map +1 -1
- package/dist/commands/worker-accounts.d.ts +149 -0
- package/dist/commands/worker-accounts.js +339 -0
- package/dist/commands/worker-accounts.js.map +1 -0
- package/dist/commands/worker-accounts.test.d.ts +1 -0
- package/dist/commands/worker-accounts.test.js +224 -0
- package/dist/commands/worker-accounts.test.js.map +1 -0
- package/dist/commands/worker-github-app.d.ts +63 -0
- package/dist/commands/worker-github-app.js +161 -0
- package/dist/commands/worker-github-app.js.map +1 -0
- package/dist/commands/worker-github-app.test.d.ts +1 -0
- package/dist/commands/worker-github-app.test.js +102 -0
- package/dist/commands/worker-github-app.test.js.map +1 -0
- package/dist/commands/worker-github-broker.d.ts +39 -0
- package/dist/commands/worker-github-broker.js +106 -0
- package/dist/commands/worker-github-broker.js.map +1 -0
- package/dist/commands/worker-github-broker.test.d.ts +1 -0
- package/dist/commands/worker-github-broker.test.js +90 -0
- package/dist/commands/worker-github-broker.test.js.map +1 -0
- package/dist/commands/worker-runs.test.d.ts +1 -0
- package/dist/commands/worker-runs.test.js +150 -0
- package/dist/commands/worker-runs.test.js.map +1 -0
- package/dist/commands/worker-worktrees.d.ts +34 -0
- package/dist/commands/worker-worktrees.js +87 -0
- package/dist/commands/worker-worktrees.js.map +1 -0
- package/dist/commands/worker.d.ts +406 -10
- package/dist/commands/worker.js +1180 -126
- package/dist/commands/worker.js.map +1 -1
- package/dist/commands/worker.test.js +588 -11
- package/dist/commands/worker.test.js.map +1 -1
- package/dist/index.js +220 -28
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-door.d.ts +1 -3
- package/dist/lib/agent-door.js +10 -7
- package/dist/lib/agent-door.js.map +1 -1
- package/dist/lib/agents-config.d.ts +9 -0
- package/dist/lib/agents-config.js +20 -0
- package/dist/lib/agents-config.js.map +1 -1
- package/dist/lib/atomic-file.d.ts +20 -1
- package/dist/lib/atomic-file.js +100 -2
- package/dist/lib/atomic-file.js.map +1 -1
- package/dist/lib/auth.d.ts +28 -2
- package/dist/lib/auth.js +52 -12
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/box/egress.d.ts +82 -0
- package/dist/lib/box/egress.js +264 -0
- package/dist/lib/box/egress.js.map +1 -0
- package/dist/lib/box/evidence.d.ts +86 -0
- package/dist/lib/box/evidence.js +121 -0
- package/dist/lib/box/evidence.js.map +1 -0
- package/dist/lib/box/job-server.d.ts +72 -0
- package/dist/lib/box/job-server.js +250 -0
- package/dist/lib/box/job-server.js.map +1 -0
- package/dist/lib/box/provisioner.d.ts +83 -0
- package/dist/lib/box/provisioner.js +312 -0
- package/dist/lib/box/provisioner.js.map +1 -0
- package/dist/lib/box/proxmox.d.ts +112 -0
- package/dist/lib/box/proxmox.js +211 -0
- package/dist/lib/box/proxmox.js.map +1 -0
- package/dist/lib/box/wire.d.ts +98 -0
- package/dist/lib/box/wire.js +70 -0
- package/dist/lib/box/wire.js.map +1 -0
- package/dist/lib/bridge-invocation.test.d.ts +1 -0
- package/dist/lib/bridge-invocation.test.js +75 -0
- package/dist/lib/bridge-invocation.test.js.map +1 -0
- package/dist/lib/bridge-status.d.ts +144 -0
- package/dist/lib/bridge-status.js +227 -0
- package/dist/lib/bridge-status.js.map +1 -0
- package/dist/lib/bridge-status.test.d.ts +6 -0
- package/dist/lib/bridge-status.test.js +197 -0
- package/dist/lib/bridge-status.test.js.map +1 -0
- package/dist/lib/client-header.test.d.ts +1 -0
- package/dist/lib/client-header.test.js +103 -0
- package/dist/lib/client-header.test.js.map +1 -0
- package/dist/lib/conversation-headers.d.ts +89 -9
- package/dist/lib/conversation-headers.js +156 -3
- package/dist/lib/conversation-headers.js.map +1 -1
- package/dist/lib/conversation-headers.test.d.ts +1 -0
- package/dist/lib/conversation-headers.test.js +78 -0
- package/dist/lib/conversation-headers.test.js.map +1 -0
- package/dist/lib/credential-class.d.ts +40 -2
- package/dist/lib/credential-class.js +48 -6
- package/dist/lib/credential-class.js.map +1 -1
- package/dist/lib/device-connect.d.ts +45 -0
- package/dist/lib/device-connect.js +60 -0
- package/dist/lib/device-connect.js.map +1 -1
- package/dist/lib/exporter-coverage.d.ts +1 -1
- package/dist/lib/exporter-coverage.js +1 -1
- package/dist/lib/goal-words.d.ts +38 -0
- package/dist/lib/goal-words.js +115 -0
- package/dist/lib/goal-words.js.map +1 -0
- package/dist/lib/hub-client.d.ts +87 -8
- package/dist/lib/hub-client.js +205 -70
- package/dist/lib/hub-client.js.map +1 -1
- package/dist/lib/init-handoff.d.ts +8 -0
- package/dist/lib/init-handoff.js +9 -2
- package/dist/lib/init-handoff.js.map +1 -1
- package/dist/lib/key-locations.d.ts +3 -3
- package/dist/lib/key-locations.js +3 -39
- package/dist/lib/key-locations.js.map +1 -1
- package/dist/lib/key-source.d.ts +3 -1
- package/dist/lib/key-source.js +7 -4
- package/dist/lib/key-source.js.map +1 -1
- package/dist/lib/knowledge-title.d.ts +3 -2
- package/dist/lib/knowledge-title.js +3 -2
- package/dist/lib/knowledge-title.js.map +1 -1
- package/dist/lib/machine-instance.d.ts +7 -5
- package/dist/lib/machine-instance.js +7 -5
- package/dist/lib/machine-instance.js.map +1 -1
- package/dist/lib/mcp-bridge.d.ts +50 -0
- package/dist/lib/mcp-bridge.js +232 -11
- package/dist/lib/mcp-bridge.js.map +1 -1
- package/dist/lib/mcp-bridge.test.js +224 -4
- package/dist/lib/mcp-bridge.test.js.map +1 -1
- package/dist/lib/mcp-call.d.ts +5 -1
- package/dist/lib/mcp-call.js +7 -6
- package/dist/lib/mcp-call.js.map +1 -1
- package/dist/lib/mcp-connector-url.test.d.ts +1 -0
- package/dist/lib/mcp-connector-url.test.js +13 -0
- package/dist/lib/mcp-connector-url.test.js.map +1 -0
- package/dist/lib/mcp-snippets.d.ts +16 -0
- package/dist/lib/mcp-snippets.js +20 -2
- package/dist/lib/mcp-snippets.js.map +1 -1
- package/dist/lib/now-line.d.ts +66 -0
- package/dist/lib/now-line.js +193 -0
- package/dist/lib/now-line.js.map +1 -0
- package/dist/lib/now-line.test.d.ts +5 -0
- package/dist/lib/now-line.test.js +177 -0
- package/dist/lib/now-line.test.js.map +1 -0
- package/dist/lib/package-updates.d.ts +66 -0
- package/dist/lib/package-updates.js +76 -0
- package/dist/lib/package-updates.js.map +1 -0
- package/dist/lib/pod-moved.d.ts +70 -0
- package/dist/lib/pod-moved.js +146 -0
- package/dist/lib/pod-moved.js.map +1 -0
- package/dist/lib/pod-reach.d.ts +39 -0
- package/dist/lib/pod-reach.js +117 -0
- package/dist/lib/pod-reach.js.map +1 -0
- package/dist/lib/pod-reach.test.d.ts +1 -0
- package/dist/lib/pod-reach.test.js +67 -0
- package/dist/lib/pod-reach.test.js.map +1 -0
- package/dist/lib/pod.d.ts +8 -4
- package/dist/lib/pod.js +12 -10
- package/dist/lib/pod.js.map +1 -1
- package/dist/lib/register-claude-code-mcp.test.d.ts +1 -0
- package/dist/lib/register-claude-code-mcp.test.js +97 -0
- package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
- package/dist/lib/review-credential.js +3 -1
- package/dist/lib/review-credential.js.map +1 -1
- package/dist/lib/safe-open.d.ts +5 -3
- package/dist/lib/safe-open.js +9 -8
- package/dist/lib/safe-open.js.map +1 -1
- package/dist/lib/self-host.d.ts +17 -0
- package/dist/lib/self-host.js +24 -0
- package/dist/lib/self-host.js.map +1 -0
- package/dist/lib/session-feed.d.ts +185 -0
- package/dist/lib/session-feed.js +257 -0
- package/dist/lib/session-feed.js.map +1 -0
- package/dist/lib/targets.d.ts +52 -3
- package/dist/lib/targets.js +150 -209
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/template-lifecycle.d.ts +0 -31
- package/dist/lib/template-lifecycle.js +0 -74
- package/dist/lib/template-lifecycle.js.map +1 -1
- package/dist/lib/term.d.ts +24 -0
- package/dist/lib/term.js +52 -0
- package/dist/lib/term.js.map +1 -0
- package/dist/lib/term.test.d.ts +1 -0
- package/dist/lib/term.test.js +29 -0
- package/dist/lib/term.test.js.map +1 -0
- package/dist/lib/transcript-index.d.ts +94 -0
- package/dist/lib/transcript-index.js +321 -0
- package/dist/lib/transcript-index.js.map +1 -0
- package/dist/lib/transcript-index.test.d.ts +10 -0
- package/dist/lib/transcript-index.test.js +200 -0
- package/dist/lib/transcript-index.test.js.map +1 -0
- package/dist/lib/wait-help.d.ts +11 -0
- package/dist/lib/wait-help.js +25 -0
- package/dist/lib/wait-help.js.map +1 -0
- package/dist/lib/wait-state.d.ts +57 -0
- package/dist/lib/wait-state.js +114 -0
- package/dist/lib/wait-state.js.map +1 -0
- package/dist/lib/wake-hook-settings.d.ts +57 -0
- package/dist/lib/wake-hook-settings.js +153 -0
- package/dist/lib/wake-hook-settings.js.map +1 -0
- package/dist/lib/wake-state.d.ts +65 -0
- package/dist/lib/wake-state.js +122 -0
- package/dist/lib/wake-state.js.map +1 -0
- package/package.json +5 -2
- package/skills/README.md +1 -1
- package/skills/agent-os/SKILL.md +8 -8
- package/skills/synap/SKILL.md +188 -94
- package/skills/synap/code-skills.md +84 -0
- package/skills/synap/concepts.md +38 -20
- package/skills/synap/creative-loop.md +1 -1
- package/skills/synap/document-embeds.md +17 -1
- package/skills/synap/focus-sessions.md +17 -8
- package/skills/synap/from-intent.md +33 -17
- package/skills/synap/governance-rules.md +3 -1
- package/skills/synap/hand-off.md +10 -6
- package/skills/synap/lenses.md +4 -4
- package/skills/synap/linking.md +2 -2
- package/skills/synap/mental-model.md +1 -1
- package/skills/synap/operating-mode-rules.md +1 -1
- package/skills/synap/quick-reference.md +2 -1
- package/skills/synap/reflexes.md +8 -8
- package/skills/synap/viewframe-cells.md +1 -1
- package/skills/synap/work-model.md +24 -10
- package/skills/synap/workspace-design.md +5 -5
- package/skills/synap/writes.md +16 -9
- package/skills/synap/writing-titles.md +7 -0
- package/skills/synap-app/SKILL.md +148 -66
- package/skills/synap-app/creating-the-base-app.md +12 -7
- package/skills/synap-app/governance.md +27 -16
- package/skills/synap-app/install-commands.md +18 -9
- package/skills/synap-app/overview.md +16 -9
- package/skills/synap-app/using-the-sdk.md +75 -25
- package/skills/synap-market/SKILL.md +1 -1
- package/skills/synap-market/governance-and-catalog.md +1 -1
- package/skills/synap-schema/SKILL.md +24 -21
- package/skills/synap-schema/intent-vocabulary-ssot.md +24 -21
- package/templates/box/runner.py +206 -0
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* A Capability is a named, installable PACK of what you (and your AI) can do
|
|
5
5
|
* (e.g. "Google Workspace", "Discord Bot"). Tools = its connection; skills = its
|
|
6
6
|
* verbs; templates = the catalog. The user only ever lists, adds, and enables a
|
|
7
|
-
* PACK — never a bare tool or skill (CAPABILITIES-NORTH-STAR
|
|
7
|
+
* PACK — never a bare tool or skill (CAPABILITIES-NORTH-STAR, team pod).
|
|
8
8
|
*
|
|
9
9
|
* A capability VERB is a runnable action backed by a skill (verbId = skill name).
|
|
10
10
|
* `run` is the launcher: it parses arbitrary `--key value` flags into the skill's
|
|
@@ -17,7 +17,7 @@ import ora from "ora";
|
|
|
17
17
|
import prompts from "prompts";
|
|
18
18
|
import { openExternalUrl } from "../lib/safe-open.js";
|
|
19
19
|
import { readFileSync } from "node:fs";
|
|
20
|
-
import { resolveHubConfig, hubGet, hubPost, hubDelete, HubError, renderHubError } from "../lib/hub-client.js";
|
|
20
|
+
import { resolveHubConfig, hubGet, hubPost, hubPatch, hubDelete, HubError, renderHubError } from "../lib/hub-client.js";
|
|
21
21
|
import { unwrapList } from "../lib/unwrapList.js";
|
|
22
22
|
import { log } from "../utils/logger.js";
|
|
23
23
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
@@ -499,8 +499,9 @@ async function connectProviderOAuth(cfg, provider, workspaceId, ctx) {
|
|
|
499
499
|
}
|
|
500
500
|
/**
|
|
501
501
|
* Ensure a capability's required connection is satisfied. Provider (nango://) →
|
|
502
|
-
* OAuth open + poll. Vault (vault://) →
|
|
503
|
-
*
|
|
502
|
+
* OAuth open + poll. Vault (vault://) → rotate the linked secret in place, or
|
|
503
|
+
* apply the template with the key as a param. Returns true when the connection
|
|
504
|
+
* is (now) satisfied, false otherwise.
|
|
504
505
|
*/
|
|
505
506
|
async function ensureConnection(cfg, workspaceId, card,
|
|
506
507
|
// Force a re-auth even when the card reports `state === "connected"`. The card
|
|
@@ -518,12 +519,20 @@ forceReconnect = false) {
|
|
|
518
519
|
// own diagnosis (which of not_declared / unauthenticated / unreachable, and
|
|
519
520
|
// the remedy). Only OPENING A BROWSER is doomed, and that is already guarded
|
|
520
521
|
// below. Short-circuiting on the card's cached state costs the real message.
|
|
521
|
-
// ── Vault credential
|
|
522
|
-
//
|
|
523
|
-
//
|
|
524
|
-
// credentialRef
|
|
525
|
-
//
|
|
522
|
+
// ── Vault credential ──────────────────────────────────────────────────────
|
|
523
|
+
// Every write here must land on the secret the capability's tools actually
|
|
524
|
+
// read. A bare /vault/secrets write creates an orphan secret NOT linked to the
|
|
525
|
+
// tool's credentialRef: the CLI used to fall back to it and print success
|
|
526
|
+
// while every run kept the old key (unipile-linkedin, 2026-10-27).
|
|
526
527
|
if (conn.kind === "vault") {
|
|
528
|
+
// Installed with a live key → rotate THAT secret in place. The tools keep
|
|
529
|
+
// their vault://<id>, so the new value is what the next run reads; no
|
|
530
|
+
// template re-apply, so optional install params are not blanked either.
|
|
531
|
+
if (card.id && conn.account && conn.state === "connected") {
|
|
532
|
+
return rotateLinkedSecret(cfg, card, card.id, conn.account);
|
|
533
|
+
}
|
|
534
|
+
// No live key yet → apply the template WITH params: the governed applier
|
|
535
|
+
// stores the secret AND links it into the tool's credentialRef.
|
|
527
536
|
const hasParams = (card.installParams ?? []).some((p) => p.required);
|
|
528
537
|
if (hasParams) {
|
|
529
538
|
const collected = await collectInstallParams(card);
|
|
@@ -531,30 +540,12 @@ forceReconnect = false) {
|
|
|
531
540
|
return false;
|
|
532
541
|
return applyTemplateWithParams(cfg, card, workspaceId, collected, "Connecting");
|
|
533
542
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
message: `Paste the ${chalk.bold(card.name)} credential (${service})`,
|
|
541
|
-
});
|
|
542
|
-
const value = answer.value;
|
|
543
|
-
if (!value) {
|
|
544
|
-
log.dim("Cancelled — no credential entered.");
|
|
545
|
-
return false;
|
|
546
|
-
}
|
|
547
|
-
const spinner = ora({ text: "Storing credential in the vault…", color: "cyan" }).start();
|
|
548
|
-
try {
|
|
549
|
-
await hubPost("/vault/secrets", { name: `${card.name} credential`, value, service, type: "credential", workspaceId }, cfg);
|
|
550
|
-
spinner.succeed(chalk.green(`Stored ${chalk.bold(service)} credential.`));
|
|
551
|
-
return true;
|
|
552
|
-
}
|
|
553
|
-
catch (err) {
|
|
554
|
-
spinner.fail(chalk.red("Failed to store credential"));
|
|
555
|
-
renderHubError(err);
|
|
556
|
-
return false;
|
|
557
|
-
}
|
|
543
|
+
log.error(`Can't connect ${card.name} from here.`);
|
|
544
|
+
log.dim(card.id
|
|
545
|
+
? "The pod lists no install params for it and its tools point at no vault key that still exists."
|
|
546
|
+
: "The pod lists no install params for it.");
|
|
547
|
+
log.dim(`Re-install it with its key: synap cap add "${card.key}"`);
|
|
548
|
+
return false;
|
|
558
549
|
}
|
|
559
550
|
// ── Provider OAuth (nango://) — open + poll ───────────────────────────────
|
|
560
551
|
const provider = conn.provider ?? card.key;
|
|
@@ -566,6 +557,36 @@ forceReconnect = false) {
|
|
|
566
557
|
forceReauth: forceReconnect,
|
|
567
558
|
});
|
|
568
559
|
}
|
|
560
|
+
/**
|
|
561
|
+
* Replace the value of the vault secret a capability's tools point at
|
|
562
|
+
* (`secretId` = the card's `connection.account`, the id in their
|
|
563
|
+
* `vault://<id>`), through the capability credentials door. The row keeps its
|
|
564
|
+
* id, so every reference to it now resolves to the new value and no second
|
|
565
|
+
* secret is written.
|
|
566
|
+
*/
|
|
567
|
+
async function rotateLinkedSecret(cfg, card, capabilityId, secretId) {
|
|
568
|
+
const answer = await prompts({
|
|
569
|
+
type: "password",
|
|
570
|
+
name: "value",
|
|
571
|
+
message: `Paste the new ${chalk.bold(card.name)} key`,
|
|
572
|
+
});
|
|
573
|
+
const value = answer.value;
|
|
574
|
+
if (!value) {
|
|
575
|
+
log.dim("Cancelled — no key entered. The current key is unchanged.");
|
|
576
|
+
return false;
|
|
577
|
+
}
|
|
578
|
+
const spinner = ora({ text: `Replacing the ${chalk.bold(card.name)} key…`, color: "cyan" }).start();
|
|
579
|
+
try {
|
|
580
|
+
await hubPatch(`/capabilities/${capabilityId}/credentials/${secretId}`, { value }, cfg);
|
|
581
|
+
spinner.succeed(chalk.green(`Replaced the ${chalk.bold(card.name)} key. Its tools use the new one from the next run.`));
|
|
582
|
+
return true;
|
|
583
|
+
}
|
|
584
|
+
catch (err) {
|
|
585
|
+
spinner.fail(chalk.red(`Couldn't replace the ${card.name} key — the current key is unchanged`));
|
|
586
|
+
renderHubError(err);
|
|
587
|
+
return false;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
569
590
|
/**
|
|
570
591
|
* Prompt for a template's REQUIRED install params (masked for secrets). Returns
|
|
571
592
|
* the params map, or null if the user cancelled. Empty map when nothing required.
|
|
@@ -614,9 +635,12 @@ async function applyTemplateWithParams(cfg, card, workspaceId, params, verb) {
|
|
|
614
635
|
}
|
|
615
636
|
catch (err) {
|
|
616
637
|
// Non-fatal — the connection itself succeeded; surface so it isn't
|
|
617
|
-
// silently stuck in the old "not approved" trap.
|
|
618
|
-
|
|
619
|
-
|
|
638
|
+
// silently stuck in the old "not approved" trap. Founder dogfood
|
|
639
|
+
// 2026-10-30 (Hetzner Cloud): this approve timed out, the old hint
|
|
640
|
+
// named no command, and every run was refused "installed but not
|
|
641
|
+
// enabled" while `cap enable` (verbs only) printed success.
|
|
642
|
+
log.warn(`Connected, but its access to "${t.name}" is still off: ${err.message}`);
|
|
643
|
+
log.dim(`Nothing it does can run until it is on. Turn it on: synap cap enable "${card.name}"`);
|
|
620
644
|
}
|
|
621
645
|
}
|
|
622
646
|
spinner.succeed(chalk.green(`${verb === "Adding" ? "Added" : "Connected"} ${chalk.bold(card.name)}.`));
|
|
@@ -960,8 +984,12 @@ export async function capabilityEnable(name, opts) {
|
|
|
960
984
|
if (after)
|
|
961
985
|
card = after;
|
|
962
986
|
}
|
|
987
|
+
// (a′) Its access to the service: a tool row the run gate refuses blocks
|
|
988
|
+
// every verb, so it is turned on before (and whatever) the verbs.
|
|
989
|
+
const accessOn = (card.toolsOff?.length ?? 0) === 0 || reportAccess(card, await turnOnAccess(cfg, card));
|
|
963
990
|
if (card.verbs.length === 0) {
|
|
964
|
-
|
|
991
|
+
if (accessOn)
|
|
992
|
+
log.heading(`${card.name} is on`);
|
|
965
993
|
log.dim("This capability has no selectable verbs yet.");
|
|
966
994
|
return;
|
|
967
995
|
}
|
|
@@ -991,7 +1019,11 @@ export async function capabilityEnable(name, opts) {
|
|
|
991
1019
|
const toEnable = card.verbs.filter((v) => selected.has(v.verbId) && !v.enabled);
|
|
992
1020
|
const toDisable = card.verbs.filter((v) => !selected.has(v.verbId) && v.enabled);
|
|
993
1021
|
if (toEnable.length === 0 && toDisable.length === 0) {
|
|
994
|
-
|
|
1022
|
+
if (!accessOn)
|
|
1023
|
+
return;
|
|
1024
|
+
log.success((card.toolsOff?.length ?? 0) > 0
|
|
1025
|
+
? `Nothing else changed — ${card.name}'s verbs are already set up that way.`
|
|
1026
|
+
: `Nothing changed — ${card.name} is already set up that way.`);
|
|
995
1027
|
return;
|
|
996
1028
|
}
|
|
997
1029
|
const work = ora({ text: "Applying your selection…", color: "cyan" }).start();
|
|
@@ -1040,6 +1072,42 @@ export async function capabilityEnable(name, opts) {
|
|
|
1040
1072
|
log.dim(`Run it: synap cap run ${example.verbId} --<param> <value>`);
|
|
1041
1073
|
}
|
|
1042
1074
|
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Turn ON a capability's access to its service: each member tool row the pod's
|
|
1077
|
+
* run gate refuses (`card.toolsOff`), through the same door the install uses
|
|
1078
|
+
* (`POST /tools/:id/approve`). A person's step: the pod refuses an agent key,
|
|
1079
|
+
* and that refusal is reported with where a person fixes it, never as success.
|
|
1080
|
+
*/
|
|
1081
|
+
export async function turnOnAccess(cfg, card) {
|
|
1082
|
+
const turnedOn = [];
|
|
1083
|
+
const refused = [];
|
|
1084
|
+
for (const t of card.toolsOff ?? []) {
|
|
1085
|
+
try {
|
|
1086
|
+
await hubPost(`/tools/${t.id}/approve`, { approved: true }, cfg);
|
|
1087
|
+
turnedOn.push(t.name);
|
|
1088
|
+
}
|
|
1089
|
+
catch (err) {
|
|
1090
|
+
refused.push({ name: t.name, reason: err.message });
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
return { turnedOn, refused };
|
|
1094
|
+
}
|
|
1095
|
+
/** Say what `turnOnAccess` did; returns false when some access is still off. */
|
|
1096
|
+
function reportAccess(card, res) {
|
|
1097
|
+
if (res.turnedOn.length > 0) {
|
|
1098
|
+
log.success(`Turned on its access to ${res.turnedOn.join(", ")}`);
|
|
1099
|
+
}
|
|
1100
|
+
for (const r of res.refused) {
|
|
1101
|
+
log.warn(`Its access to "${r.name}" is still off: ${r.reason}`);
|
|
1102
|
+
}
|
|
1103
|
+
if (res.refused.length > 0) {
|
|
1104
|
+
log.dim(card.nextAction.url
|
|
1105
|
+
? `Nothing it does can run until it is on. A person turns it on here: ${card.nextAction.url}`
|
|
1106
|
+
: "Nothing it does can run until it is on. A person turns it on in the pod admin, under Tools.");
|
|
1107
|
+
return false;
|
|
1108
|
+
}
|
|
1109
|
+
return true;
|
|
1110
|
+
}
|
|
1043
1111
|
export async function capabilityConnect(name, opts) {
|
|
1044
1112
|
let cfg;
|
|
1045
1113
|
try {
|
|
@@ -1050,26 +1118,42 @@ export async function capabilityConnect(name, opts) {
|
|
|
1050
1118
|
process.exit(1);
|
|
1051
1119
|
}
|
|
1052
1120
|
const workspaceId = requireWorkspace(opts, cfg);
|
|
1053
|
-
// No name → discovery picker:
|
|
1054
|
-
//
|
|
1055
|
-
//
|
|
1121
|
+
// No name → discovery picker: the connectable services (Nango providers) AND
|
|
1122
|
+
// the installed capabilities connected by an API key (vault://, e.g. Unipile).
|
|
1123
|
+
// Nango never lists a keyed one, so before 28 Oct the picker hid them and
|
|
1124
|
+
// `--reconnect` could not reach them. Pick an OAuth service → its OAuth flow;
|
|
1125
|
+
// pick a keyed capability → the named path below (rotate the key in place).
|
|
1056
1126
|
if (!name || !name.trim()) {
|
|
1057
1127
|
const spin = ora({ text: "Fetching connectable services…", color: "cyan" }).start();
|
|
1058
|
-
let providers;
|
|
1128
|
+
let providers = [];
|
|
1059
1129
|
let nangoStatus;
|
|
1060
1130
|
let nangoError;
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1131
|
+
let providersFailed = false;
|
|
1132
|
+
let keyed = [];
|
|
1133
|
+
let keyedFailed = false;
|
|
1134
|
+
const [provRes, catRes] = await Promise.allSettled([
|
|
1135
|
+
hubGet("/connectors/providers", {}, cfg),
|
|
1136
|
+
fetchCatalog(cfg, workspaceId),
|
|
1137
|
+
]);
|
|
1138
|
+
spin.stop();
|
|
1139
|
+
if (provRes.status === "fulfilled") {
|
|
1140
|
+
providers = provRes.value.providers ?? [];
|
|
1141
|
+
nangoStatus = provRes.value.nangoStatus;
|
|
1142
|
+
nangoError = provRes.value.nangoError;
|
|
1067
1143
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
renderHubError(
|
|
1144
|
+
else {
|
|
1145
|
+
providersFailed = true;
|
|
1146
|
+
renderHubError(provRes.reason);
|
|
1071
1147
|
log.dim("Couldn't reach the pod's connector service.");
|
|
1072
|
-
|
|
1148
|
+
}
|
|
1149
|
+
if (catRes.status === "fulfilled") {
|
|
1150
|
+
keyed = catRes.value.filter((c) => c.source === "installed" && c.connection?.required === true && c.connection.kind === "vault");
|
|
1151
|
+
}
|
|
1152
|
+
else {
|
|
1153
|
+
// A failed read is not "no keyed capabilities": say so, and name the door that still works.
|
|
1154
|
+
keyedFailed = true;
|
|
1155
|
+
log.warn("Couldn't list the capabilities connected by an API key.");
|
|
1156
|
+
log.dim('Connect one by name: synap cap connect "<name>" (names: synap cap list)');
|
|
1073
1157
|
}
|
|
1074
1158
|
// Distinguish "couldn't check" from "checked, genuinely empty" — the same
|
|
1075
1159
|
// fault-vs-absence signal the pod now returns. A guess ("may not be
|
|
@@ -1078,23 +1162,31 @@ export async function capabilityConnect(name, opts) {
|
|
|
1078
1162
|
log.warn(`Couldn't check connectors (${nangoError?.reason ?? "unknown"}) — connection state is unknown.`);
|
|
1079
1163
|
if (nangoError?.message)
|
|
1080
1164
|
log.dim(nangoError.message);
|
|
1081
|
-
|
|
1165
|
+
providers = [];
|
|
1166
|
+
providersFailed = true;
|
|
1082
1167
|
}
|
|
1083
|
-
if (providers.length === 0) {
|
|
1168
|
+
if (providers.length === 0 && keyed.length === 0) {
|
|
1169
|
+
if (providersFailed || keyedFailed)
|
|
1170
|
+
return;
|
|
1084
1171
|
log.warn("No connectable services available on this pod.");
|
|
1085
1172
|
log.dim("This pod's Nango declares no integrations. A pod admin declares them in the Nango dashboard.");
|
|
1086
1173
|
return;
|
|
1087
1174
|
}
|
|
1175
|
+
const keyedConnected = (c) => c.connection?.state === "connected";
|
|
1088
1176
|
const connectable = providers.filter((p) => !p.connected);
|
|
1089
1177
|
const connected = providers.filter((p) => p.connected);
|
|
1178
|
+
const keyedOpen = keyed.filter((c) => !keyedConnected(c));
|
|
1179
|
+
const keyedDone = keyed.filter(keyedConnected);
|
|
1090
1180
|
// --reconnect: the point is to re-auth an ALREADY-connected (but expired)
|
|
1091
|
-
// service, so connected rows become selectable (a fresh OAuth
|
|
1092
|
-
// disabled, and "everything already connected" is no longer a dead end.
|
|
1093
|
-
if (connectable.length === 0 && !opts.reconnect) {
|
|
1181
|
+
// service, so connected rows become selectable (a fresh OAuth, or a new key)
|
|
1182
|
+
// rather than disabled, and "everything already connected" is no longer a dead end.
|
|
1183
|
+
if (connectable.length === 0 && keyedOpen.length === 0 && !opts.reconnect) {
|
|
1094
1184
|
log.heading("Everything connectable here is already connected.");
|
|
1095
1185
|
for (const p of connected)
|
|
1096
1186
|
log.dim(` ${chalk.green("✓")} ${p.displayName ?? p.provider}`);
|
|
1097
|
-
|
|
1187
|
+
for (const c of keyedDone)
|
|
1188
|
+
log.dim(` ${chalk.green("✓")} ${c.name}`);
|
|
1189
|
+
log.dim("Reconnect an expired one, or replace a key: synap cap connect --reconnect");
|
|
1098
1190
|
return;
|
|
1099
1191
|
}
|
|
1100
1192
|
const answer = await prompts({
|
|
@@ -1102,25 +1194,41 @@ export async function capabilityConnect(name, opts) {
|
|
|
1102
1194
|
name: "id",
|
|
1103
1195
|
message: `${opts.reconnect ? "Reconnect" : "Connect"} a service ${chalk.dim(`→ ${podHostLabel(cfg)}`)}`,
|
|
1104
1196
|
// Connectable first; already-connected grouped at the end — disabled in the
|
|
1105
|
-
// normal flow, but SELECTABLE (for a forced re-auth) under --reconnect.
|
|
1197
|
+
// normal flow, but SELECTABLE (for a forced re-auth / a new key) under --reconnect.
|
|
1106
1198
|
choices: [
|
|
1107
1199
|
...connectable.map((p) => ({
|
|
1108
1200
|
title: p.displayName ?? p.provider,
|
|
1109
|
-
value: p.id
|
|
1201
|
+
value: `oauth:${p.id}`,
|
|
1202
|
+
})),
|
|
1203
|
+
...keyedOpen.map((c) => ({
|
|
1204
|
+
title: c.name,
|
|
1205
|
+
description: "API key",
|
|
1206
|
+
value: `key:${c.name}`,
|
|
1110
1207
|
})),
|
|
1111
1208
|
...connected.map((p) => ({
|
|
1112
1209
|
title: `${p.displayName ?? p.provider} ${chalk.green("✓ connected")}`,
|
|
1113
1210
|
description: opts.reconnect ? "re-authenticate" : "already connected",
|
|
1114
|
-
value: p.id
|
|
1211
|
+
value: `oauth:${p.id}`,
|
|
1212
|
+
disabled: !opts.reconnect,
|
|
1213
|
+
})),
|
|
1214
|
+
...keyedDone.map((c) => ({
|
|
1215
|
+
title: `${c.name} ${chalk.green("✓ connected")}`,
|
|
1216
|
+
description: opts.reconnect ? "replace its API key" : "already connected",
|
|
1217
|
+
value: `key:${c.name}`,
|
|
1115
1218
|
disabled: !opts.reconnect,
|
|
1116
1219
|
})),
|
|
1117
1220
|
],
|
|
1118
1221
|
});
|
|
1119
|
-
|
|
1222
|
+
const picked = typeof answer.id === "string" ? answer.id : "";
|
|
1223
|
+
if (!picked) {
|
|
1120
1224
|
log.dim("Cancelled.");
|
|
1121
1225
|
return;
|
|
1122
1226
|
}
|
|
1123
|
-
|
|
1227
|
+
if (picked.startsWith("key:")) {
|
|
1228
|
+
await capabilityConnect(picked.slice("key:".length), opts);
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
const chosen = providers.find((p) => p.id === picked.slice("oauth:".length));
|
|
1124
1232
|
const ok = await connectProviderOAuth(cfg, chosen.id, workspaceId, {
|
|
1125
1233
|
displayName: chosen.displayName ?? chosen.provider,
|
|
1126
1234
|
forceReauth: opts.reconnect ?? false,
|
|
@@ -1158,7 +1266,9 @@ export async function capabilityConnect(name, opts) {
|
|
|
1158
1266
|
}
|
|
1159
1267
|
if (opts.reconnect) {
|
|
1160
1268
|
log.heading(`Reconnecting ${card.name}`);
|
|
1161
|
-
log.dim(
|
|
1269
|
+
log.dim(card.connection.kind === "vault"
|
|
1270
|
+
? "Replacing the key its tools use."
|
|
1271
|
+
: "Forcing a fresh sign-in — your previous access had expired or was revoked.");
|
|
1162
1272
|
}
|
|
1163
1273
|
const ok = await ensureConnection(cfg, workspaceId, card, opts.reconnect ?? false);
|
|
1164
1274
|
if (!ok)
|