@synap-core/cli 1.11.0 → 1.13.0
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 +40 -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 +32 -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 +524 -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 +116 -66
- 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.d.ts +14 -1
- package/dist/commands/bridge-setup.js +395 -129
- 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 +3 -1
- package/dist/commands/capability.js +249 -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 +1 -13
- package/dist/commands/centrality.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 +36 -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 +79 -44
- package/dist/commands/context.js.map +1 -1
- package/dist/commands/data-extra.d.ts +34 -0
- package/dist/commands/data-extra.js +203 -25
- package/dist/commands/data-extra.js.map +1 -1
- package/dist/commands/data.d.ts +120 -2
- package/dist/commands/data.js +295 -21
- package/dist/commands/data.js.map +1 -1
- package/dist/commands/diagnose.d.ts +66 -4
- package/dist/commands/diagnose.js +285 -28
- package/dist/commands/diagnose.js.map +1 -1
- package/dist/commands/doc.d.ts +11 -4
- package/dist/commands/doc.js +39 -14
- package/dist/commands/doc.js.map +1 -1
- package/dist/commands/doctor.d.ts +133 -3
- package/dist/commands/doctor.js +761 -41
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/explain.js +5 -5
- package/dist/commands/explain.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 +393 -13
- package/dist/commands/import.js +1150 -54
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +34 -9
- package/dist/commands/init.js +481 -981
- 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 +22 -6
- package/dist/commands/knowledge.js +121 -57
- package/dist/commands/knowledge.js.map +1 -1
- package/dist/commands/lens.d.ts +37 -1
- package/dist/commands/lens.js +194 -72
- package/dist/commands/lens.js.map +1 -1
- package/dist/commands/market-authoring.d.ts +29 -2
- package/dist/commands/market-authoring.js +348 -7
- package/dist/commands/market-authoring.js.map +1 -1
- 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 +400 -16
- package/dist/commands/market.js +1802 -146
- package/dist/commands/market.js.map +1 -1
- package/dist/commands/mcp.d.ts +60 -25
- package/dist/commands/mcp.js +251 -64
- 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/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 +171 -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 +11 -1
- package/dist/commands/pods.js +129 -131
- package/dist/commands/pods.js.map +1 -1
- package/dist/commands/proposals-actions.d.ts +62 -0
- package/dist/commands/proposals-actions.js +143 -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 +579 -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-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 +116 -0
- package/dist/commands/session-wait.js +224 -0
- package/dist/commands/session-wait.js.map +1 -0
- package/dist/commands/sessions.d.ts +54 -0
- package/dist/commands/sessions.js +501 -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-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/skills.js +16 -0
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/status.d.ts +1 -4
- package/dist/commands/status.js +6 -35
- 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 +112 -0
- package/dist/commands/tracks.js +543 -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 +41 -3
- package/dist/commands/upload.js +120 -18
- package/dist/commands/upload.js.map +1 -1
- 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 +30 -3
- package/dist/commands/whoami.js +186 -23
- 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.d.ts +331 -0
- package/dist/commands/worker.js +1067 -0
- package/dist/commands/worker.js.map +1 -0
- package/dist/commands/worker.test.d.ts +1 -0
- package/dist/commands/worker.test.js +427 -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 +1043 -186
- 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 +136 -0
- package/dist/lib/agent-door.js +429 -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 +17 -11
- package/dist/lib/auth.js +47 -64
- 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/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 +246 -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/capture-lane.d.ts +6 -5
- package/dist/lib/capture-lane.js +6 -5
- package/dist/lib/capture-lane.js.map +1 -1
- package/dist/lib/capture-structure.d.ts +230 -11
- package/dist/lib/capture-structure.js +251 -13
- package/dist/lib/capture-structure.js.map +1 -1
- 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/client-header.test.d.ts +1 -0
- package/dist/lib/client-header.test.js +85 -0
- package/dist/lib/client-header.test.js.map +1 -0
- package/dist/lib/conversation-headers.d.ts +33 -0
- package/dist/lib/conversation-headers.js +69 -0
- package/dist/lib/conversation-headers.js.map +1 -0
- package/dist/lib/cp-packages.d.ts +167 -11
- package/dist/lib/cp-packages.js +253 -21
- package/dist/lib/cp-packages.js.map +1 -1
- package/dist/lib/credential-class.d.ts +144 -0
- package/dist/lib/credential-class.js +138 -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/goal-words.d.ts +38 -0
- package/dist/lib/goal-words.js +112 -0
- package/dist/lib/goal-words.js.map +1 -0
- package/dist/lib/hub-client.d.ts +57 -15
- package/dist/lib/hub-client.js +396 -82
- package/dist/lib/hub-client.js.map +1 -1
- 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 +24 -0
- package/dist/lib/init-handoff.js +26 -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 +68 -0
- package/dist/lib/key-source.js +109 -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 +25 -0
- package/dist/lib/knowledge-title.js +47 -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 +49 -0
- package/dist/lib/mcp-bridge.js +180 -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 +118 -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/openclaw.js +3 -2
- package/dist/lib/openclaw.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-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-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 +74 -112
- package/dist/lib/pod.js +146 -415
- 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/register-claude-code-mcp.test.d.ts +1 -0
- package/dist/lib/register-claude-code-mcp.test.js +78 -0
- package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
- package/dist/lib/review-credential.d.ts +119 -0
- package/dist/lib/review-credential.js +149 -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-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/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 +152 -10
- package/dist/lib/targets.js +974 -325
- package/dist/lib/targets.js.map +1 -1
- package/dist/lib/template-file.d.ts +4 -0
- package/dist/lib/template-file.js.map +1 -1
- 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/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/dist/utils/logger.js +5 -2
- package/dist/utils/logger.js.map +1 -1
- package/package.json +26 -17
- package/skills/README.md +13 -11
- package/skills/agent-os/SKILL.md +214 -99
- package/skills/manifest.json +1 -1
- package/skills/onboard/SKILL.md +55 -26
- package/skills/synap/README.md +5 -8
- package/skills/synap/SKILL.md +1149 -289
- 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 +5 -0
- package/skills/synap/cli-operations.md +24 -18
- package/skills/synap/code-skills.md +70 -0
- package/skills/synap/concepts.md +36 -0
- package/skills/synap/content-os.md +10 -1
- package/skills/synap/creative-loop.md +15 -10
- package/skills/synap/crm.md +21 -52
- package/skills/synap/document-embeds.md +143 -47
- package/skills/synap/escalation-ladder.md +20 -10
- package/skills/synap/focus-sessions.md +56 -21
- package/skills/synap/from-intent.md +158 -0
- package/skills/synap/governance-rules.md +5 -5
- 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 +34 -16
- package/skills/synap/linking.md +42 -41
- package/skills/synap/mcp-remote-servers.md +64 -0
- package/skills/synap/mental-model.md +17 -15
- package/skills/synap/operating-mode-rules.md +2 -2
- package/skills/synap/processes.md +118 -0
- package/skills/synap/quick-reference.md +7 -2
- 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 +110 -0
- package/skills/synap/worked-examples.md +4 -5
- package/skills/synap/workspace-design.md +15 -11
- package/skills/synap/writes.md +105 -25
- package/skills/synap/writing-titles.md +63 -0
- package/skills/synap-app/SKILL.md +149 -67
- package/skills/synap-app/_skill.yaml +1 -1
- 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-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 +306 -16
- package/skills/synap-market/_skill.yaml +1 -1
- package/skills/synap-market/author-and-publish.md +145 -8
- package/skills/synap-market/governance-and-catalog.md +7 -0
- package/skills/synap-market/install.md +79 -1
- package/skills/synap-market/overview.md +74 -6
- 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/box/runner.py +206 -0
- 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/node_modules/@synap/hub-rest-client/dist/index.cjs +0 -1261
- package/node_modules/@synap/hub-rest-client/dist/index.d.cts +0 -1647
- package/node_modules/@synap/hub-rest-client/dist/index.d.ts +0 -1647
- package/node_modules/@synap/hub-rest-client/dist/index.js +0 -1231
- package/node_modules/@synap/hub-rest-client/package.json +0 -45
- package/node_modules/@synap/hub-rest-client/src/client.ts +0 -1631
- package/node_modules/@synap/hub-rest-client/src/errors.ts +0 -30
- package/node_modules/@synap/hub-rest-client/src/index.ts +0 -153
- package/node_modules/@synap/hub-rest-client/src/setup.ts +0 -133
- package/node_modules/@synap/hub-rest-client/src/types.ts +0 -1299
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-kind wire envelopes and the ONE unwrap — import-free on purpose.
|
|
3
|
+
*
|
|
4
|
+
* Re-exported (with the workspace types) by `./wire`, the public subpath
|
|
5
|
+
* `@synap-core/workspace-templates/wire`. It has no imports so a consumer that
|
|
6
|
+
* still resolves an older npm copy of this package (the CLI, the CP, the pod)
|
|
7
|
+
* can carry it as a BYTE-IDENTICAL mirror pinned by a tripwire until it can
|
|
8
|
+
* import the subpath. Edit it here; the mirror copies it.
|
|
9
|
+
*
|
|
10
|
+
* What `GET {CP}/api/packages/:slug` serves as `package.definition`, per kind:
|
|
11
|
+
* the outputs of this package's producers (`scripts/catalog-lib.mjs`
|
|
12
|
+
* `toPublishBody`; `toOfficialPublishBody` for workspaces) plus what the CP
|
|
13
|
+
* adds on store/serve (`_meta.slug` via `withTemplateSlug`,
|
|
14
|
+
* `capability.contentHash`).
|
|
15
|
+
*
|
|
16
|
+
* WHY: a skill package is served as `{ _meta, skill: {…} }`. Read flat, every
|
|
17
|
+
* field is `undefined`: install refused a "bodiless" skill and the update door
|
|
18
|
+
* reported "no drift" forever (founder pod 2026-10-13, creative-director). Each
|
|
19
|
+
* consumer had its own cast; this is the one place the envelope is known.
|
|
20
|
+
*
|
|
21
|
+
* Element fields are pinned to the catalog schema (`SKILL_FIELDS`,
|
|
22
|
+
* `CapabilitySpec`) and `AutomationElement` to `PackageAutomationWire` by
|
|
23
|
+
* `schema/wire.parity.test.ts` (compile time).
|
|
24
|
+
*/
|
|
25
|
+
/** The kinds whose served definition this module describes. */
|
|
26
|
+
export declare const WIRE_KINDS: readonly ["workspace", "capability", "skill", "automation", "view"];
|
|
27
|
+
export type WireKind = (typeof WIRE_KINDS)[number];
|
|
28
|
+
/**
|
|
29
|
+
* Other names the same kinds go by: the pod's `market.install` says
|
|
30
|
+
* `template`, the CP category for an automation is `workflow`, and a pack is
|
|
31
|
+
* a workspace-shaped definition.
|
|
32
|
+
*/
|
|
33
|
+
export declare const WIRE_KIND_ALIASES: {
|
|
34
|
+
readonly template: "workspace";
|
|
35
|
+
readonly pack: "workspace";
|
|
36
|
+
readonly workflow: "automation";
|
|
37
|
+
};
|
|
38
|
+
export type WireKindName = WireKind | keyof typeof WIRE_KIND_ALIASES;
|
|
39
|
+
/** `template` → `workspace`, `workflow` → `automation`; `null` for a kind with no wire contract here (e.g. `cell`). */
|
|
40
|
+
export declare function toWireKind(kind: string): WireKind | null;
|
|
41
|
+
/**
|
|
42
|
+
* `definition._meta` as served: the CP stamps `slug` on every row (the pod
|
|
43
|
+
* keys "which space is this template's?" on it); the CLI adds the `version`
|
|
44
|
+
* label it installs.
|
|
45
|
+
*/
|
|
46
|
+
export interface WireMeta {
|
|
47
|
+
slug?: string;
|
|
48
|
+
version?: string;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
}
|
|
51
|
+
/** `meta.icon` / `color` / `domain`, mirrored onto the definition by every publish builder. */
|
|
52
|
+
export interface WireIdentity {
|
|
53
|
+
icon?: string;
|
|
54
|
+
color?: string;
|
|
55
|
+
domain?: string;
|
|
56
|
+
}
|
|
57
|
+
/** A composition dependency. */
|
|
58
|
+
export interface WireDependency {
|
|
59
|
+
slug: string;
|
|
60
|
+
kind?: "workspace" | "capability" | "skill" | "workflow" | "view" | "cell" | "automation";
|
|
61
|
+
relation?: "compose" | "require";
|
|
62
|
+
reason?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface WireEnvelope extends WireIdentity {
|
|
65
|
+
_meta?: WireMeta;
|
|
66
|
+
dependencies?: WireDependency[];
|
|
67
|
+
}
|
|
68
|
+
/** The capability itself (`CapabilityDefinition`). */
|
|
69
|
+
export interface CapabilityElement {
|
|
70
|
+
key: string;
|
|
71
|
+
name: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
params?: Array<Record<string, unknown>>;
|
|
74
|
+
vault?: Array<Record<string, unknown>>;
|
|
75
|
+
tools?: Array<Record<string, unknown>>;
|
|
76
|
+
skills?: Array<Record<string, unknown>>;
|
|
77
|
+
provides?: string[];
|
|
78
|
+
playbooks?: Array<Record<string, unknown>>;
|
|
79
|
+
/** Stamped by the CP on publish; the pod's drift marker. */
|
|
80
|
+
contentHash?: string;
|
|
81
|
+
automations?: Array<Record<string, unknown>>;
|
|
82
|
+
mcpServers?: unknown;
|
|
83
|
+
metadata?: Record<string, unknown>;
|
|
84
|
+
_generated?: unknown;
|
|
85
|
+
}
|
|
86
|
+
/** capability: `{ profiles: [], description, capability }`. */
|
|
87
|
+
export interface CapabilityWire extends WireEnvelope {
|
|
88
|
+
profiles: unknown[];
|
|
89
|
+
description?: string;
|
|
90
|
+
capability: CapabilityElement;
|
|
91
|
+
}
|
|
92
|
+
/** ONE standalone skill. Not a workspace's `skills[]` link list. */
|
|
93
|
+
export interface SkillElement {
|
|
94
|
+
/** The pod-side `load_skill` ref — its own identity, not the package slug. */
|
|
95
|
+
slug?: string;
|
|
96
|
+
name?: string;
|
|
97
|
+
displayName?: string;
|
|
98
|
+
description?: string;
|
|
99
|
+
kind?: "instruction" | "code" | "declarative" | "builtin";
|
|
100
|
+
scope?: "pod" | "user" | "workspace";
|
|
101
|
+
agentTypes?: string[];
|
|
102
|
+
body?: string;
|
|
103
|
+
code?: string;
|
|
104
|
+
providerSpec?: Record<string, unknown>;
|
|
105
|
+
parameters?: Record<string, unknown>;
|
|
106
|
+
category?: string;
|
|
107
|
+
executionMode?: "sync" | "async";
|
|
108
|
+
timeoutSeconds?: number;
|
|
109
|
+
intent?: string;
|
|
110
|
+
[key: string]: unknown;
|
|
111
|
+
}
|
|
112
|
+
/** skill: `{ skill, icon?, color?, domain?, dependencies? }`. */
|
|
113
|
+
export interface SkillWire extends WireEnvelope {
|
|
114
|
+
skill: SkillElement;
|
|
115
|
+
}
|
|
116
|
+
/** One graph automation (= `PackageAutomationWire`): `flowDefinition`, not the authored `flow`. */
|
|
117
|
+
export interface AutomationElement {
|
|
118
|
+
key?: string;
|
|
119
|
+
name: string;
|
|
120
|
+
description?: string;
|
|
121
|
+
triggerType: "event" | "cron" | "webhook" | "manual";
|
|
122
|
+
triggerConfig?: Record<string, unknown>;
|
|
123
|
+
flowDefinition?: {
|
|
124
|
+
nodes: unknown[];
|
|
125
|
+
edges: unknown[];
|
|
126
|
+
precondition?: string;
|
|
127
|
+
};
|
|
128
|
+
status?: "draft" | "active" | "paused";
|
|
129
|
+
}
|
|
130
|
+
/** automation (CP category `workflow`): `{ profiles: [], automations: [one] }`. */
|
|
131
|
+
export interface AutomationWire extends WireEnvelope {
|
|
132
|
+
profiles: unknown[];
|
|
133
|
+
automations: AutomationElement[];
|
|
134
|
+
}
|
|
135
|
+
/** One view, as the pod's view install and update doors read it. */
|
|
136
|
+
export interface ViewElement {
|
|
137
|
+
slug?: string;
|
|
138
|
+
name?: string;
|
|
139
|
+
displayName?: string;
|
|
140
|
+
description?: string;
|
|
141
|
+
type?: string;
|
|
142
|
+
config?: Record<string, unknown>;
|
|
143
|
+
query?: Record<string, unknown>;
|
|
144
|
+
metadata?: Record<string, unknown>;
|
|
145
|
+
scopeProfileSlugs?: string[];
|
|
146
|
+
scopeProfileIds?: string[];
|
|
147
|
+
[key: string]: unknown;
|
|
148
|
+
}
|
|
149
|
+
/** view: `{ views: [...] }`, or a legacy single view with its fields on top (has its own `type`). No catalog producer today. */
|
|
150
|
+
export type ViewWire = (WireEnvelope & {
|
|
151
|
+
views: ViewElement[];
|
|
152
|
+
}) | ViewElement;
|
|
153
|
+
/**
|
|
154
|
+
* What {@link unwrapPackage} returns per kind. `workspace` is the definition
|
|
155
|
+
* itself; `./wire` narrows it to `WorkspaceWire`.
|
|
156
|
+
*/
|
|
157
|
+
export interface PackageElementByKind<W = Record<string, unknown>> {
|
|
158
|
+
workspace: W;
|
|
159
|
+
capability: CapabilityElement;
|
|
160
|
+
skill: SkillElement;
|
|
161
|
+
automation: AutomationElement[];
|
|
162
|
+
view: ViewElement[];
|
|
163
|
+
}
|
|
164
|
+
export type ElementOf<K extends WireKindName, W = Record<string, unknown>> = PackageElementByKind<W>[K extends WireKind ? K : K extends keyof typeof WIRE_KIND_ALIASES ? (typeof WIRE_KIND_ALIASES)[K] : never];
|
|
165
|
+
/**
|
|
166
|
+
* The installable element(s) inside a served definition:
|
|
167
|
+
*
|
|
168
|
+
* skill → the `skill` object (a legacy flat definition is the skill itself)
|
|
169
|
+
* capability → the `capability` object (a flat `CapabilityDefinition` — the
|
|
170
|
+
* pod cache / CP by-key shape — passes through)
|
|
171
|
+
* automation → `automations[]` (`[]` when the definition declares none)
|
|
172
|
+
* view → `views[]`, or a legacy flat view (top-level `type`) as `[def]`, else `[]`
|
|
173
|
+
* workspace → the definition itself
|
|
174
|
+
*
|
|
175
|
+
* An empty array means the definition declares none; the install doors refuse
|
|
176
|
+
* that themselves. A definition that is not an object is a failed read, never
|
|
177
|
+
* an empty one: it throws.
|
|
178
|
+
*/
|
|
179
|
+
export declare function unwrapPackage<K extends WireKindName>(kind: K, definition: unknown): ElementOf<K>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The per-kind wire envelopes and the ONE unwrap — import-free on purpose.
|
|
3
|
+
*
|
|
4
|
+
* Re-exported (with the workspace types) by `./wire`, the public subpath
|
|
5
|
+
* `@synap-core/workspace-templates/wire`. It has no imports so a consumer that
|
|
6
|
+
* still resolves an older npm copy of this package (the CLI, the CP, the pod)
|
|
7
|
+
* can carry it as a BYTE-IDENTICAL mirror pinned by a tripwire until it can
|
|
8
|
+
* import the subpath. Edit it here; the mirror copies it.
|
|
9
|
+
*
|
|
10
|
+
* What `GET {CP}/api/packages/:slug` serves as `package.definition`, per kind:
|
|
11
|
+
* the outputs of this package's producers (`scripts/catalog-lib.mjs`
|
|
12
|
+
* `toPublishBody`; `toOfficialPublishBody` for workspaces) plus what the CP
|
|
13
|
+
* adds on store/serve (`_meta.slug` via `withTemplateSlug`,
|
|
14
|
+
* `capability.contentHash`).
|
|
15
|
+
*
|
|
16
|
+
* WHY: a skill package is served as `{ _meta, skill: {…} }`. Read flat, every
|
|
17
|
+
* field is `undefined`: install refused a "bodiless" skill and the update door
|
|
18
|
+
* reported "no drift" forever (founder pod 2026-10-13, creative-director). Each
|
|
19
|
+
* consumer had its own cast; this is the one place the envelope is known.
|
|
20
|
+
*
|
|
21
|
+
* Element fields are pinned to the catalog schema (`SKILL_FIELDS`,
|
|
22
|
+
* `CapabilitySpec`) and `AutomationElement` to `PackageAutomationWire` by
|
|
23
|
+
* `schema/wire.parity.test.ts` (compile time).
|
|
24
|
+
*/
|
|
25
|
+
// ─── Kinds ──────────────────────────────────────────────────────────────────
|
|
26
|
+
/** The kinds whose served definition this module describes. */
|
|
27
|
+
export const WIRE_KINDS = ["workspace", "capability", "skill", "automation", "view"];
|
|
28
|
+
/**
|
|
29
|
+
* Other names the same kinds go by: the pod's `market.install` says
|
|
30
|
+
* `template`, the CP category for an automation is `workflow`, and a pack is
|
|
31
|
+
* a workspace-shaped definition.
|
|
32
|
+
*/
|
|
33
|
+
export const WIRE_KIND_ALIASES = {
|
|
34
|
+
template: "workspace",
|
|
35
|
+
pack: "workspace",
|
|
36
|
+
workflow: "automation",
|
|
37
|
+
};
|
|
38
|
+
/** `template` → `workspace`, `workflow` → `automation`; `null` for a kind with no wire contract here (e.g. `cell`). */
|
|
39
|
+
export function toWireKind(kind) {
|
|
40
|
+
if (WIRE_KINDS.includes(kind))
|
|
41
|
+
return kind;
|
|
42
|
+
return WIRE_KIND_ALIASES[kind] ?? null;
|
|
43
|
+
}
|
|
44
|
+
// ─── The ONE unwrap ─────────────────────────────────────────────────────────
|
|
45
|
+
const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
46
|
+
export function unwrapPackage(kind, definition) {
|
|
47
|
+
const wireKind = toWireKind(kind);
|
|
48
|
+
if (!wireKind)
|
|
49
|
+
throw new Error(`unwrapPackage: "${kind}" has no wire contract`);
|
|
50
|
+
if (!isRecord(definition)) {
|
|
51
|
+
throw new TypeError(`unwrapPackage(${kind}): the definition is not an object (${definition === null ? "null" : Array.isArray(definition) ? "array" : typeof definition})`);
|
|
52
|
+
}
|
|
53
|
+
switch (wireKind) {
|
|
54
|
+
case "skill":
|
|
55
|
+
return isRecord(definition.skill) ? definition.skill : definition;
|
|
56
|
+
case "capability":
|
|
57
|
+
return isRecord(definition.capability) ? definition.capability : definition;
|
|
58
|
+
case "automation":
|
|
59
|
+
return Array.isArray(definition.automations) ? definition.automations : [];
|
|
60
|
+
case "view":
|
|
61
|
+
if (Array.isArray(definition.views) && definition.views.length > 0)
|
|
62
|
+
return definition.views;
|
|
63
|
+
return definition.type ? [definition] : [];
|
|
64
|
+
case "workspace":
|
|
65
|
+
return definition;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=package-wire.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-wire.js","sourceRoot":"","sources":["../../src/lib/package-wire.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,+EAA+E;AAE/E,+DAA+D;AAC/D,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,CAAU,CAAC;AAG9F;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,EAAE,WAAW;IACrB,IAAI,EAAE,WAAW;IACjB,QAAQ,EAAE,YAAY;CACqB,CAAC;AAG9C,uHAAuH;AACvH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAK,UAAgC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAgB,CAAC;IAC9E,OAAQ,iBAA8C,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACvE,CAAC;AA8ID,+EAA+E;AAE/E,MAAM,QAAQ,GAAG,CAAC,CAAU,EAAgC,EAAE,CAC5D,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAiB3D,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,UAAmB;IAC7D,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,wBAAwB,CAAC,CAAC;IAChF,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,SAAS,CACjB,iBAAiB,IAAI,uCAAuC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,UAAU,GAAG,CACtJ,CAAC;IACJ,CAAC;IACD,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,UAAU,CAAC;QACpE,KAAK,YAAY;YACf,OAAO,QAAQ,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QAC9E,KAAK,YAAY;YACf,OAAO,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,KAAK,MAAM;YACT,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;gBAAE,OAAO,UAAU,CAAC,KAAK,CAAC;YAC5F,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,KAAK,WAAW;YACd,OAAO,UAAU,CAAC;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phone pairing — the link `synap init` prints as a QR so Relay can reach this pod.
|
|
3
|
+
*
|
|
4
|
+
* Contract (Relay is the receiver; it owns the screen that consumes it):
|
|
5
|
+
*
|
|
6
|
+
* synap://pair?v=1&pod=<url-encoded pod origin>[&email=<CP account>]
|
|
7
|
+
*
|
|
8
|
+
* - `v` grammar version. A receiver that sees an unknown `v` must refuse
|
|
9
|
+
* and say "update Relay", never guess.
|
|
10
|
+
* - `pod` the pod's ORIGIN only (scheme + host + port, no path). https, or
|
|
11
|
+
* http for a LAN host only: a public host over plain http would
|
|
12
|
+
* send the phone's sign-in in the clear, so it is refused. Relay
|
|
13
|
+
* pre-fills its sign-in with this pod; it never trusts it for auth.
|
|
14
|
+
* - `email` OPTIONAL: the Synap account the CLI is signed in to. Relay
|
|
15
|
+
* pre-fills the sign-in email with it. Not a credential.
|
|
16
|
+
*
|
|
17
|
+
* `token` is RESERVED by Relay's parser (it ignores it) for a future
|
|
18
|
+
* short-lived pairing token. No pod or CP door mints one yet, so the builder
|
|
19
|
+
* takes none; add the parameter when that door exists.
|
|
20
|
+
*
|
|
21
|
+
* The scheme is `synap` (relay's app.json declares `["synap", "relay"]`), and a
|
|
22
|
+
* single-segment host (`pair`) is what relay's `useDeepLinkHandler` reads as
|
|
23
|
+
* `deepLinkPath === "pair"`.
|
|
24
|
+
*/
|
|
25
|
+
export declare const PAIR_LINK_VERSION = "1";
|
|
26
|
+
export type PairLinkResult = {
|
|
27
|
+
ok: true;
|
|
28
|
+
link: string;
|
|
29
|
+
} | {
|
|
30
|
+
ok: false;
|
|
31
|
+
reason: "invalid-url" | "loopback" | "insecure";
|
|
32
|
+
};
|
|
33
|
+
export declare function buildPairLink(opts: {
|
|
34
|
+
podUrl: string;
|
|
35
|
+
email?: string;
|
|
36
|
+
}): PairLinkResult;
|
|
37
|
+
/** The link as a terminal QR code (half-block characters, fits ~30 rows). */
|
|
38
|
+
export declare function renderTerminalQr(text: string): Promise<string>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phone pairing — the link `synap init` prints as a QR so Relay can reach this pod.
|
|
3
|
+
*
|
|
4
|
+
* Contract (Relay is the receiver; it owns the screen that consumes it):
|
|
5
|
+
*
|
|
6
|
+
* synap://pair?v=1&pod=<url-encoded pod origin>[&email=<CP account>]
|
|
7
|
+
*
|
|
8
|
+
* - `v` grammar version. A receiver that sees an unknown `v` must refuse
|
|
9
|
+
* and say "update Relay", never guess.
|
|
10
|
+
* - `pod` the pod's ORIGIN only (scheme + host + port, no path). https, or
|
|
11
|
+
* http for a LAN host only: a public host over plain http would
|
|
12
|
+
* send the phone's sign-in in the clear, so it is refused. Relay
|
|
13
|
+
* pre-fills its sign-in with this pod; it never trusts it for auth.
|
|
14
|
+
* - `email` OPTIONAL: the Synap account the CLI is signed in to. Relay
|
|
15
|
+
* pre-fills the sign-in email with it. Not a credential.
|
|
16
|
+
*
|
|
17
|
+
* `token` is RESERVED by Relay's parser (it ignores it) for a future
|
|
18
|
+
* short-lived pairing token. No pod or CP door mints one yet, so the builder
|
|
19
|
+
* takes none; add the parameter when that door exists.
|
|
20
|
+
*
|
|
21
|
+
* The scheme is `synap` (relay's app.json declares `["synap", "relay"]`), and a
|
|
22
|
+
* single-segment host (`pair`) is what relay's `useDeepLinkHandler` reads as
|
|
23
|
+
* `deepLinkPath === "pair"`.
|
|
24
|
+
*/
|
|
25
|
+
import QRCode from "qrcode";
|
|
26
|
+
export const PAIR_LINK_VERSION = "1";
|
|
27
|
+
/** Hosts a phone can never reach: the pod is only on this computer. */
|
|
28
|
+
function isLoopbackHost(h) {
|
|
29
|
+
return h === "localhost" || h.endsWith(".localhost") || h === "::1" || h === "0.0.0.0" || /^127\./.test(h);
|
|
30
|
+
}
|
|
31
|
+
/** A host only reachable on the local network, where plain http is tolerable. */
|
|
32
|
+
function isLanHost(h) {
|
|
33
|
+
if (h.endsWith(".local") || h.endsWith(".lan") || h.endsWith(".home.arpa"))
|
|
34
|
+
return true;
|
|
35
|
+
const m = /^(\d{1,3})\.(\d{1,3})\.\d{1,3}\.\d{1,3}$/.exec(h);
|
|
36
|
+
if (m) {
|
|
37
|
+
const a = Number(m[1]);
|
|
38
|
+
const b = Number(m[2]);
|
|
39
|
+
return a === 10 || (a === 172 && b >= 16 && b <= 31) || (a === 192 && b === 168) || (a === 169 && b === 254);
|
|
40
|
+
}
|
|
41
|
+
// IPv6 unique-local (fc00::/7) and link-local (fe80::/10).
|
|
42
|
+
return /^f[cd][0-9a-f]{2}:/.test(h) || /^fe[89ab][0-9a-f]:/.test(h);
|
|
43
|
+
}
|
|
44
|
+
export function buildPairLink(opts) {
|
|
45
|
+
let url;
|
|
46
|
+
try {
|
|
47
|
+
url = new URL(opts.podUrl);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return { ok: false, reason: "invalid-url" };
|
|
51
|
+
}
|
|
52
|
+
if (url.protocol !== "https:" && url.protocol !== "http:")
|
|
53
|
+
return { ok: false, reason: "invalid-url" };
|
|
54
|
+
const host = url.hostname.replace(/^\[|\]$/g, "").toLowerCase();
|
|
55
|
+
if (isLoopbackHost(host))
|
|
56
|
+
return { ok: false, reason: "loopback" };
|
|
57
|
+
if (url.protocol === "http:" && !isLanHost(host))
|
|
58
|
+
return { ok: false, reason: "insecure" };
|
|
59
|
+
const params = new URLSearchParams({ v: PAIR_LINK_VERSION, pod: url.origin });
|
|
60
|
+
if (opts.email)
|
|
61
|
+
params.set("email", opts.email);
|
|
62
|
+
return { ok: true, link: `synap://pair?${params.toString()}` };
|
|
63
|
+
}
|
|
64
|
+
/** The link as a terminal QR code (half-block characters, fits ~30 rows). */
|
|
65
|
+
export async function renderTerminalQr(text) {
|
|
66
|
+
return QRCode.toString(text, { type: "terminal", small: true });
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=pair-link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pair-link.js","sourceRoot":"","sources":["../../src/lib/pair-link.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A pod that moved to a new address.
|
|
3
|
+
*
|
|
4
|
+
* Hosted pods move from `{name}.synap.live` to `{name}.pod.synap.live`
|
|
5
|
+
* (Control Plane "tenant domains v2"). For 90 days the old name answers every
|
|
6
|
+
* request with a redirect to the new one. The CLI NEVER follows a redirect to
|
|
7
|
+
* another host for an API call: the request carries the pod key, and a
|
|
8
|
+
* redirect is something any server on the old name can send. Instead:
|
|
9
|
+
*
|
|
10
|
+
* 1. every pod call goes through `podFetch`, which refuses a cross-host
|
|
11
|
+
* redirect with `PodMovedError` (one line: what happened, what to run);
|
|
12
|
+
* 2. `synap doctor` asks the Control Plane where the pod lives now —
|
|
13
|
+
* `POST {cp}/pods/handshake {targetUrl: <old url>}` answers
|
|
14
|
+
* `410 {code: "POD_MOVED", podId, podUrl, consoleUrl}` for a moved pod
|
|
15
|
+
* (CP `src/routes/pods.ts`, `src/lib/pod-handshake-problem.ts`) —
|
|
16
|
+
* and `synap doctor --fix` rewrites the saved profile through the one
|
|
17
|
+
* door for a URL change (`synap pods update`).
|
|
18
|
+
*
|
|
19
|
+
* The new address comes ONLY from the Control Plane, never from the redirect.
|
|
20
|
+
*/
|
|
21
|
+
/** What to run when a pod has moved. */
|
|
22
|
+
export declare const POD_MOVED_HINT = "Run: synap doctor --fix (it finds the new address and updates your settings)";
|
|
23
|
+
/** The one line a command prints when its pod has moved. */
|
|
24
|
+
export declare function podMovedMessage(podUrl: string): string;
|
|
25
|
+
export declare class PodMovedError extends Error {
|
|
26
|
+
/** The address the CLI holds (origin). */
|
|
27
|
+
readonly podUrl: string;
|
|
28
|
+
/** Where the old address redirected — informational only, never used. */
|
|
29
|
+
readonly redirectedTo: string;
|
|
30
|
+
constructor(podUrl: string, redirectedTo: string);
|
|
31
|
+
}
|
|
32
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
33
|
+
/**
|
|
34
|
+
* `fetch` for calls to a pod: redirects within the same host are followed (at
|
|
35
|
+
* most 5), a redirect to another host throws `PodMovedError`. Network errors
|
|
36
|
+
* propagate unchanged, so callers keep their own transport classification.
|
|
37
|
+
*/
|
|
38
|
+
export declare function podFetch(url: string, init?: RequestInit, fetchImpl?: FetchLike): Promise<Response>;
|
|
39
|
+
/** What the Control Plane says about a pod address. */
|
|
40
|
+
export type PodMoveAnswer = {
|
|
41
|
+
kind: "moved";
|
|
42
|
+
podUrl: string;
|
|
43
|
+
consoleUrl?: string;
|
|
44
|
+
podId?: string;
|
|
45
|
+
}
|
|
46
|
+
/** The CP knows this address as the pod's own (or knows nothing to move). */
|
|
47
|
+
| {
|
|
48
|
+
kind: "not-moved";
|
|
49
|
+
code?: string;
|
|
50
|
+
}
|
|
51
|
+
/** No Control Plane sign-in on this computer, or it expired. */
|
|
52
|
+
| {
|
|
53
|
+
kind: "signed-out";
|
|
54
|
+
}
|
|
55
|
+
/** The CP could not be asked, or answered something unreadable. */
|
|
56
|
+
| {
|
|
57
|
+
kind: "unknown";
|
|
58
|
+
reason: string;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Ask the Control Plane where a pod lives now. Needs the CP sign-in from
|
|
62
|
+
* `synap login` (a bearer token); without one the answer is `signed-out`.
|
|
63
|
+
*/
|
|
64
|
+
export declare function askControlPlaneWherePodIs(params: {
|
|
65
|
+
podUrl: string;
|
|
66
|
+
cpUrl: string;
|
|
67
|
+
cpToken: string | undefined;
|
|
68
|
+
fetchImpl?: FetchLike;
|
|
69
|
+
}): Promise<PodMoveAnswer>;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A pod that moved to a new address.
|
|
3
|
+
*
|
|
4
|
+
* Hosted pods move from `{name}.synap.live` to `{name}.pod.synap.live`
|
|
5
|
+
* (Control Plane "tenant domains v2"). For 90 days the old name answers every
|
|
6
|
+
* request with a redirect to the new one. The CLI NEVER follows a redirect to
|
|
7
|
+
* another host for an API call: the request carries the pod key, and a
|
|
8
|
+
* redirect is something any server on the old name can send. Instead:
|
|
9
|
+
*
|
|
10
|
+
* 1. every pod call goes through `podFetch`, which refuses a cross-host
|
|
11
|
+
* redirect with `PodMovedError` (one line: what happened, what to run);
|
|
12
|
+
* 2. `synap doctor` asks the Control Plane where the pod lives now —
|
|
13
|
+
* `POST {cp}/pods/handshake {targetUrl: <old url>}` answers
|
|
14
|
+
* `410 {code: "POD_MOVED", podId, podUrl, consoleUrl}` for a moved pod
|
|
15
|
+
* (CP `src/routes/pods.ts`, `src/lib/pod-handshake-problem.ts`) —
|
|
16
|
+
* and `synap doctor --fix` rewrites the saved profile through the one
|
|
17
|
+
* door for a URL change (`synap pods update`).
|
|
18
|
+
*
|
|
19
|
+
* The new address comes ONLY from the Control Plane, never from the redirect.
|
|
20
|
+
*/
|
|
21
|
+
/** What to run when a pod has moved. */
|
|
22
|
+
export const POD_MOVED_HINT = "Run: synap doctor --fix (it finds the new address and updates your settings)";
|
|
23
|
+
/** The one line a command prints when its pod has moved. */
|
|
24
|
+
export function podMovedMessage(podUrl) {
|
|
25
|
+
return `The pod at ${podUrl} has a new address. Run: synap doctor --fix`;
|
|
26
|
+
}
|
|
27
|
+
export class PodMovedError extends Error {
|
|
28
|
+
/** The address the CLI holds (origin). */
|
|
29
|
+
podUrl;
|
|
30
|
+
/** Where the old address redirected — informational only, never used. */
|
|
31
|
+
redirectedTo;
|
|
32
|
+
constructor(podUrl, redirectedTo) {
|
|
33
|
+
super(podMovedMessage(podUrl));
|
|
34
|
+
this.name = "PodMovedError";
|
|
35
|
+
this.podUrl = podUrl;
|
|
36
|
+
this.redirectedTo = redirectedTo;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const MAX_SAME_HOST_HOPS = 5;
|
|
40
|
+
function isRedirect(status) {
|
|
41
|
+
return status === 301 || status === 302 || status === 303 || status === 307 || status === 308;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* A redirect the CLI may follow: the same origin, or the same host upgraded
|
|
45
|
+
* from http to https (default ports). Anything else is another host.
|
|
46
|
+
*/
|
|
47
|
+
function isSameHost(from, to) {
|
|
48
|
+
if (from.origin === to.origin)
|
|
49
|
+
return true;
|
|
50
|
+
return (from.protocol === "http:" &&
|
|
51
|
+
to.protocol === "https:" &&
|
|
52
|
+
from.hostname === to.hostname &&
|
|
53
|
+
from.port === "" &&
|
|
54
|
+
to.port === "");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* `fetch` for calls to a pod: redirects within the same host are followed (at
|
|
58
|
+
* most 5), a redirect to another host throws `PodMovedError`. Network errors
|
|
59
|
+
* propagate unchanged, so callers keep their own transport classification.
|
|
60
|
+
*/
|
|
61
|
+
export async function podFetch(url, init = {}, fetchImpl = fetch) {
|
|
62
|
+
const start = new URL(url);
|
|
63
|
+
let current = start;
|
|
64
|
+
let currentInit = init;
|
|
65
|
+
for (let hop = 0;; hop++) {
|
|
66
|
+
const res = await fetchImpl(current.toString(), { ...currentInit, redirect: "manual" });
|
|
67
|
+
if (!isRedirect(res.status))
|
|
68
|
+
return res;
|
|
69
|
+
const location = res.headers.get("location");
|
|
70
|
+
if (!location)
|
|
71
|
+
return res;
|
|
72
|
+
let next;
|
|
73
|
+
try {
|
|
74
|
+
next = new URL(location, current);
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return res;
|
|
78
|
+
}
|
|
79
|
+
if (!isSameHost(start, next)) {
|
|
80
|
+
throw new PodMovedError(start.origin, next.origin);
|
|
81
|
+
}
|
|
82
|
+
if (hop >= MAX_SAME_HOST_HOPS)
|
|
83
|
+
return res;
|
|
84
|
+
if (res.status === 303 && (currentInit.method ?? "GET").toUpperCase() !== "GET") {
|
|
85
|
+
const { body: _body, ...rest } = currentInit;
|
|
86
|
+
currentInit = { ...rest, method: "GET" };
|
|
87
|
+
}
|
|
88
|
+
current = next;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Ask the Control Plane where a pod lives now. Needs the CP sign-in from
|
|
93
|
+
* `synap login` (a bearer token); without one the answer is `signed-out`.
|
|
94
|
+
*/
|
|
95
|
+
export async function askControlPlaneWherePodIs(params) {
|
|
96
|
+
if (!params.cpToken)
|
|
97
|
+
return { kind: "signed-out" };
|
|
98
|
+
const fetchImpl = params.fetchImpl ?? fetch;
|
|
99
|
+
let res;
|
|
100
|
+
try {
|
|
101
|
+
res = await fetchImpl(`${params.cpUrl.replace(/\/+$/, "")}/pods/handshake`, {
|
|
102
|
+
method: "POST",
|
|
103
|
+
headers: {
|
|
104
|
+
Authorization: `Bearer ${params.cpToken}`,
|
|
105
|
+
"Content-Type": "application/json",
|
|
106
|
+
},
|
|
107
|
+
body: JSON.stringify({ targetUrl: params.podUrl }),
|
|
108
|
+
redirect: "manual",
|
|
109
|
+
signal: AbortSignal.timeout(10_000),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
return { kind: "unknown", reason: err instanceof Error ? err.message : String(err) };
|
|
114
|
+
}
|
|
115
|
+
if (res.status === 401)
|
|
116
|
+
return { kind: "signed-out" };
|
|
117
|
+
const body = (await res.json().catch(() => null));
|
|
118
|
+
if (res.status === 410 && body?.code === "POD_MOVED") {
|
|
119
|
+
const podUrl = typeof body.podUrl === "string" ? safeHttpsOrigin(body.podUrl) : null;
|
|
120
|
+
if (!podUrl)
|
|
121
|
+
return { kind: "unknown", reason: "the Control Plane named no usable new address" };
|
|
122
|
+
return {
|
|
123
|
+
kind: "moved",
|
|
124
|
+
podUrl,
|
|
125
|
+
...(typeof body.consoleUrl === "string" ? { consoleUrl: body.consoleUrl } : {}),
|
|
126
|
+
...(typeof body.podId === "string" ? { podId: body.podId } : {}),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (res.ok || res.status === 403 || res.status === 409) {
|
|
130
|
+
return { kind: "not-moved", ...(typeof body?.code === "string" ? { code: body.code } : {}) };
|
|
131
|
+
}
|
|
132
|
+
return { kind: "unknown", reason: `the Control Plane answered ${res.status}` };
|
|
133
|
+
}
|
|
134
|
+
/** An https origin, or null. A new pod address is never plain http. */
|
|
135
|
+
function safeHttpsOrigin(value) {
|
|
136
|
+
try {
|
|
137
|
+
const url = new URL(value);
|
|
138
|
+
if (url.protocol !== "https:" || url.username || url.password)
|
|
139
|
+
return null;
|
|
140
|
+
return url.origin;
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=pod-moved.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pod-moved.js","sourceRoot":"","sources":["../../src/lib/pod-moved.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Why a pod probe failed, told apart: the network between this machine and the
|
|
3
|
+
* pod (egress proxy, DNS, firewall, TLS) versus the pod itself answering badly.
|
|
4
|
+
*
|
|
5
|
+
* `checkPodHealth` used to fold every failure into `healthy: false`, so `synap
|
|
6
|
+
* init` behind an egress proxy that answers 403 to CONNECT printed a pod-side
|
|
7
|
+
* checklist ("is the container running?") for a pod that was never contacted.
|
|
8
|
+
* This is the one place that taxonomy lives for the probe.
|
|
9
|
+
*/
|
|
10
|
+
export type ReachKind =
|
|
11
|
+
/** An egress proxy refused the CONNECT tunnel — the pod was never contacted. */
|
|
12
|
+
"proxy"
|
|
13
|
+
/** DNS, refused, reset, unroutable, timeout, TLS — no HTTP answer from anything. */
|
|
14
|
+
| "network"
|
|
15
|
+
/** The pod host answered, but not with a healthy /health. */
|
|
16
|
+
| "pod";
|
|
17
|
+
export interface ReachFailure {
|
|
18
|
+
kind: ReachKind;
|
|
19
|
+
/** The underlying error, one line: status / error code / message. */
|
|
20
|
+
detail: string;
|
|
21
|
+
/** Env variable whose proxy this process used, with credentials stripped. */
|
|
22
|
+
proxy?: {
|
|
23
|
+
env: string;
|
|
24
|
+
url: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** The env proxy that applies to `podUrl`, credentials removed. Honors NO_PROXY. */
|
|
28
|
+
export declare function proxyInUse(podUrl: string, env?: NodeJS.ProcessEnv): {
|
|
29
|
+
env: string;
|
|
30
|
+
url: string;
|
|
31
|
+
} | undefined;
|
|
32
|
+
/** Classify a fetch that threw (no HTTP answer from the pod). */
|
|
33
|
+
export declare function classifyFetchError(err: unknown, podUrl: string, env?: NodeJS.ProcessEnv): ReachFailure;
|
|
34
|
+
/** Classify a /health that answered with a non-2xx status. */
|
|
35
|
+
export declare function classifyHttpStatus(status: number, podUrl: string, env?: NodeJS.ProcessEnv): ReachFailure;
|
|
36
|
+
/** The lines `synap init` / `synap doctor` print under "not reachable", by cause. */
|
|
37
|
+
export declare function reachChecklist(f: ReachFailure | undefined): string[];
|
|
38
|
+
/** The one-line headline: names the underlying error, not just "not reachable". */
|
|
39
|
+
export declare function unreachableMessage(podUrl: string, failure?: ReachFailure): string;
|