@kosuke-ai/kosuke 1.0.6 → 1.0.8
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/CHANGELOG.md +21 -0
- package/README.md +11 -11
- package/dist/agent/summary.js +2 -2
- package/dist/commands/agent.js +4 -3
- package/dist/commands/auth.js +6 -7
- package/dist/commands/hand-written.js +93 -0
- package/dist/commands/integrations.js +9 -12
- package/dist/commands/skill-runs.js +15 -12
- package/dist/commands/watch.js +5 -5
- package/dist/generated/commands/{user/crons-artifacts-list.js → crons/artifacts-list--personal.js} +3 -1
- package/dist/generated/commands/{user/crons-create.js → crons/create--personal.js} +5 -3
- package/dist/generated/commands/crons/create.js +3 -3
- package/dist/generated/commands/{user/crons-get.js → crons/get--personal.js} +3 -1
- package/dist/generated/commands/{user/crons-list.js → crons/list--personal.js} +3 -1
- package/dist/generated/commands/{user/crons-run.js → crons/run--personal.js} +3 -1
- package/dist/generated/commands/{user/crons-runs-artifacts-get.js → crons/runs-artifacts-get--personal.js} +3 -1
- package/dist/generated/commands/{user/crons-runs-artifacts-list.js → crons/runs-artifacts-list--personal.js} +3 -1
- package/dist/generated/commands/{user/crons-runs-get.js → crons/runs-get--personal.js} +3 -1
- package/dist/generated/commands/{user/crons-runs-list.js → crons/runs-list--personal.js} +3 -1
- package/dist/generated/commands/crons/{runs-messages.js → runs-messages-list.js} +2 -1
- package/dist/generated/commands/{user/crons-update.js → crons/update--personal.js} +4 -2
- package/dist/generated/commands/crons/update.js +2 -2
- package/dist/generated/commands/{deploy → deploys}/cancel.js +1 -1
- package/dist/generated/commands/{deploy → deploys}/list.js +1 -1
- package/dist/generated/commands/{deploy/message.js → deploys/messages-get.js} +4 -3
- package/dist/generated/commands/{deploy/messages.js → deploys/messages-list.js} +4 -3
- package/dist/generated/commands/{deploy/set-model.js → deploys/model-set.js} +3 -2
- package/dist/generated/commands/{deploy → deploys}/queue-delete.js +1 -1
- package/dist/generated/commands/{deploy → deploys}/queue-list.js +1 -1
- package/dist/generated/commands/{deploy → deploys}/queue-move.js +1 -1
- package/dist/generated/commands/{deploy → deploys}/queue-resume.js +1 -1
- package/dist/generated/commands/{deploy → deploys}/queue-send.js +1 -1
- package/dist/generated/commands/{deploy → deploys}/queue-steer.js +1 -1
- package/dist/generated/commands/{deploy → deploys}/queue-update.js +1 -1
- package/dist/generated/commands/{deploy/run.js → deploys/start.js} +2 -2
- package/dist/generated/commands/devices/list.js +1 -1
- package/dist/generated/commands/devices/{request.js → requests-create.js} +3 -2
- package/dist/generated/commands/{user/files-delete.js → files/delete--personal.js} +3 -1
- package/dist/generated/commands/{user/files-mkdir.js → files/folders-create--personal.js} +5 -2
- package/dist/generated/commands/files/{mkdir.js → folders-create.js} +2 -1
- package/dist/generated/commands/{user/files-get.js → files/get--personal.js} +3 -1
- package/dist/generated/commands/{user/files-list.js → files/list--personal.js} +3 -1
- package/dist/generated/commands/{user/files-move.js → files/move--personal.js} +3 -1
- package/dist/generated/commands/{user/files-put.js → files/set--personal.js} +4 -2
- package/dist/generated/commands/files/{put.js → set.js} +1 -1
- package/dist/generated/commands/github/{status.js → connection-get.js} +2 -1
- package/dist/generated/commands/github/{repositories.js → repositories-list.js} +2 -1
- package/dist/generated/commands/index.js +330 -324
- package/dist/generated/commands/{user/integrations-linkedin-connect.js → integrations/browser-connections-create--personal-network-linkedin.js} +9 -3
- package/dist/generated/commands/{user/integrations-x-connect.js → integrations/browser-connections-create--personal-network-x.js} +9 -3
- package/dist/generated/commands/{user/integrations-linkedin-list.js → integrations/browser-connections-list--personal-network-linkedin.js} +8 -2
- package/dist/generated/commands/{user/integrations-x-list.js → integrations/browser-connections-list--personal-network-x.js} +8 -2
- package/dist/generated/commands/{user/integrations-linkedin-reconnect.js → integrations/browser-connections-reconnect--personal-network-linkedin.js} +8 -2
- package/dist/generated/commands/{user/integrations-x-reconnect.js → integrations/browser-connections-reconnect--personal-network-x.js} +8 -2
- package/dist/generated/commands/{user/integrations-remove.js → integrations/connections-delete--personal.js} +6 -3
- package/dist/generated/commands/{workspaces/integrations-remove.js → integrations/connections-delete.js} +2 -2
- package/dist/generated/commands/{workspaces/integrations-get.js → integrations/connections-get.js} +1 -1
- package/dist/generated/commands/{user/integrations-list.js → integrations/connections-list--personal.js} +4 -1
- package/dist/generated/commands/{workspaces/integrations-list.js → integrations/connections-list.js} +1 -1
- package/dist/generated/commands/integrations/{execute.js → tools-call.js} +3 -1
- package/dist/generated/commands/integrations/{tools.js → tools-list.js} +4 -2
- package/dist/generated/commands/mac/{apps.js → apps-list.js} +2 -1
- package/dist/generated/commands/mac/{ax-tree.js → ax-tree-get.js} +3 -2
- package/dist/generated/commands/mac/{browser-connections.js → browser-connections-list.js} +3 -1
- package/dist/generated/commands/mac/{browser-connection-check.js → browser-connections-update.js} +6 -4
- package/dist/generated/commands/mac/{browser-sign-in.js → browser-login.js} +2 -1
- package/dist/generated/commands/mac/{browser-profiles.js → browser-profiles-list.js} +3 -1
- package/dist/generated/commands/mac/{browser.js → browser-run.js} +2 -1
- package/dist/generated/commands/mac/click.js +2 -2
- package/dist/generated/commands/mac/{file-delete.js → files-delete.js} +2 -1
- package/dist/generated/commands/mac/{file-read.js → files-get.js} +2 -1
- package/dist/generated/commands/mac/{file-list.js → files-list.js} +2 -1
- package/dist/generated/commands/mac/{file-move.js → files-move.js} +2 -1
- package/dist/generated/commands/mac/{file-write.js → files-set.js} +2 -1
- package/dist/generated/commands/mac/key.js +1 -1
- package/dist/generated/commands/mac/{screenshot.js → screenshots-create.js} +3 -2
- package/dist/generated/commands/mac/scroll.js +2 -2
- package/dist/generated/commands/mac/{tools.js → status-get.js} +2 -1
- package/dist/generated/commands/mac/type.js +2 -2
- package/dist/generated/commands/mac/{windows.js → windows-list.js} +2 -1
- package/dist/generated/commands/{user/plugins-list.js → plugins/list--personal.js} +3 -1
- package/dist/generated/commands/{workspaces/plugins-list.js → plugins/list.js} +0 -1
- package/dist/generated/commands/{user/plugins-update.js → plugins/update--personal.js} +3 -1
- package/dist/generated/commands/{workspaces/plugins-update.js → plugins/update.js} +0 -1
- package/dist/generated/commands/preview/{health.js → health-get.js} +2 -1
- package/dist/generated/commands/preview/{shared-artifact.js → shared-artifacts-get.js} +2 -1
- package/dist/generated/commands/preview/{shared.js → shared-get.js} +2 -1
- package/dist/generated/commands/projects/{batch-merging-add-member.js → batch-merging-members-create.js} +2 -1
- package/dist/generated/commands/projects/{batch-merging-eject.js → batch-merging-members-delete.js} +2 -1
- package/dist/generated/commands/projects/{branches.js → branches-list.js} +2 -1
- package/dist/generated/commands/projects/create.js +1 -1
- package/dist/generated/commands/projects/{env-vars-add.js → env-vars-create.js} +1 -1
- package/dist/generated/commands/projects/{env-vars-remove.js → env-vars-delete.js} +1 -1
- package/dist/generated/commands/projects/{labels.js → labels-list.js} +2 -1
- package/dist/generated/commands/projects/{labels-usage.js → labels-sessions-list.js} +2 -1
- package/dist/generated/commands/projects/{labels-color.js → labels-update.js} +1 -1
- package/dist/generated/commands/projects/{live-logs.js → live-logs-list.js} +2 -1
- package/dist/generated/commands/projects/{live-query.js → live-queries-run.js} +2 -1
- package/dist/generated/commands/projects/{live-traffic.js → live-traffic-get.js} +2 -1
- package/dist/generated/commands/projects/{live-write.js → live-writes-create.js} +2 -1
- package/dist/generated/commands/projects/{live-write-status.js → live-writes-get.js} +2 -1
- package/dist/generated/commands/projects/{releases.js → releases-list.js} +2 -1
- package/dist/generated/commands/projects/{services-add.js → services-create.js} +1 -1
- package/dist/generated/commands/projects/{services-remove.js → services-delete.js} +1 -1
- package/dist/generated/commands/projects/{settings-import.js → settings-set.js} +1 -1
- package/dist/generated/commands/projects/{skills.js → skills-list.js} +3 -2
- package/dist/generated/commands/projects/{versions.js → versions-list.js} +2 -1
- package/dist/generated/commands/projects/{switch-workflow.js → workflow-set.js} +3 -2
- package/dist/generated/commands/prototypes/create.js +69 -0
- package/dist/generated/commands/{workspaces/access-status.js → providers/access-get.js} +3 -2
- package/dist/generated/commands/{user/subscriptions-set-default-model.js → providers/default-model-set--personal.js} +6 -3
- package/dist/generated/commands/{user/subscriptions-delete.js → providers/delete--personal.js} +4 -2
- package/dist/generated/commands/{workspaces/ai-provider-remove.js → providers/delete.js} +2 -3
- package/dist/generated/commands/{user/subscriptions-get.js → providers/get--personal.js} +4 -2
- package/dist/generated/commands/{workspaces/ai-provider-get.js → providers/get.js} +1 -2
- package/dist/generated/commands/{workspaces/ai-provider-google-remove.js → providers/google-delete.js} +2 -3
- package/dist/generated/commands/{workspaces/ai-provider-google-get.js → providers/google-get.js} +1 -2
- package/dist/generated/commands/{workspaces/ai-provider-google-delete-method.js → providers/google-methods-delete.js} +3 -3
- package/dist/generated/commands/{workspaces/ai-provider-google-select-method.js → providers/google-methods-set.js} +3 -3
- package/dist/generated/commands/{workspaces/ai-provider-google-save.js → providers/google-set.js} +2 -3
- package/dist/generated/commands/{user/subscriptions-grok-get.js → providers/grok-get--personal.js} +4 -2
- package/dist/generated/commands/{workspaces → providers}/grok-get.js +1 -1
- package/dist/generated/commands/{user/subscriptions-grok-change.js → providers/grok-update--personal.js} +5 -3
- package/dist/generated/commands/{workspaces/grok-change.js → providers/grok-update.js} +2 -2
- package/dist/generated/commands/{user/subscriptions-set-key.js → providers/keys-set--personal.js} +6 -3
- package/dist/generated/commands/{user/subscriptions-login-antigravity-cancel.js → providers/logins-cancel--personal-provider-antigravity.js} +9 -4
- package/dist/generated/commands/{workspaces/ai-provider-login-antigravity-cancel.js → providers/logins-cancel--provider-antigravity.js} +8 -4
- package/dist/generated/commands/{user/subscriptions-login-antigravity-complete.js → providers/logins-complete--personal-provider-antigravity.js} +9 -4
- package/dist/generated/commands/{user/subscriptions-login-claude-complete.js → providers/logins-complete--personal-provider-claude-code.js} +9 -4
- package/dist/generated/commands/{user/subscriptions-login-codex-complete.js → providers/logins-complete--personal-provider-codex.js} +9 -4
- package/dist/generated/commands/{user/subscriptions-login-muse-complete.js → providers/logins-complete--personal-provider-muse-code.js} +9 -4
- package/dist/generated/commands/{workspaces/ai-provider-login-antigravity-complete.js → providers/logins-complete--provider-antigravity.js} +8 -4
- package/dist/generated/commands/{workspaces/provider-login-claude-complete.js → providers/logins-complete--provider-claude-code.js} +8 -3
- package/dist/generated/commands/{workspaces/provider-login-codex-complete.js → providers/logins-complete--provider-codex.js} +8 -3
- package/dist/generated/commands/{workspaces/provider-login-muse-complete.js → providers/logins-complete--provider-muse-code.js} +8 -3
- package/dist/generated/commands/{user/subscriptions-logins-delete.js → providers/logins-delete--personal.js} +4 -2
- package/dist/generated/commands/{user/subscriptions-logins-recheck.js → providers/logins-recheck--personal.js} +4 -2
- package/dist/generated/commands/{workspaces/ai-provider-logins-recheck.js → providers/logins-recheck.js} +1 -2
- package/dist/generated/commands/{user/subscriptions-login-antigravity-start.js → providers/logins-start--personal-provider-antigravity.js} +9 -4
- package/dist/generated/commands/{user/subscriptions-login-claude-start.js → providers/logins-start--personal-provider-claude-code.js} +9 -4
- package/dist/generated/commands/{user/subscriptions-login-codex-start.js → providers/logins-start--personal-provider-codex.js} +9 -4
- package/dist/generated/commands/{user/subscriptions-login-muse-start.js → providers/logins-start--personal-provider-muse-code.js} +9 -4
- package/dist/generated/commands/{workspaces/ai-provider-login-antigravity-start.js → providers/logins-start--provider-antigravity.js} +8 -4
- package/dist/generated/commands/{workspaces/provider-login-claude-start.js → providers/logins-start--provider-claude-code.js} +8 -3
- package/dist/generated/commands/{workspaces/provider-login-codex-start.js → providers/logins-start--provider-codex.js} +8 -3
- package/dist/generated/commands/{workspaces/provider-login-muse-start.js → providers/logins-start--provider-muse-code.js} +8 -3
- package/dist/generated/commands/{workspaces/ai-provider-set.js → providers/set.js} +1 -2
- package/dist/generated/commands/{user/subscriptions-token-usage.js → providers/token-usage-get--personal.js} +6 -3
- package/dist/generated/commands/{workspaces/ai-provider-token-usage.js → providers/token-usage-get.js} +3 -3
- package/dist/generated/commands/{user/subscriptions-usage.js → providers/usage-get--personal.js} +6 -3
- package/dist/generated/commands/{workspaces/ai-provider-google-usage.js → providers/usage-get--provider-antigravity.js} +9 -4
- package/dist/generated/commands/{workspaces/ai-provider-usage-claude.js → providers/usage-get--provider-claude-code.js} +8 -3
- package/dist/generated/commands/{workspaces/ai-provider-usage-codex.js → providers/usage-get--provider-codex.js} +8 -3
- package/dist/generated/commands/{workspaces/ai-provider-usage-coding-plan.js → providers/usage-get--provider-coding-plan.js} +8 -3
- package/dist/generated/commands/{workspaces/ai-provider-usage-deepseek.js → providers/usage-get--provider-deepseek-api.js} +8 -3
- package/dist/generated/commands/{workspaces/ai-provider-usage-grok.js → providers/usage-get--provider-grok.js} +8 -3
- package/dist/generated/commands/{workspaces/ai-provider-usage-kimi-code.js → providers/usage-get--provider-kimi-code.js} +8 -3
- package/dist/generated/commands/{workspaces/ai-provider-usage-muse.js → providers/usage-get--provider-muse-code.js} +8 -3
- package/dist/generated/commands/sensei/{cards.js → cards-list.js} +2 -1
- package/dist/generated/commands/sensei/{cards-send-reply.js → cards-reply.js} +1 -1
- package/dist/generated/commands/sensei/{cards-put.js → cards-set.js} +1 -1
- package/dist/generated/commands/sensei/{chat.js → chat-get.js} +2 -1
- package/dist/generated/commands/sensei/{connect.js → connect-buttons-create.js} +2 -1
- package/dist/generated/commands/sensei/delegates-list.js +25 -0
- package/dist/generated/commands/sensei/{delegates-note.js → delegates-notes-create.js} +2 -1
- package/dist/generated/commands/sensei/{describe.js → describe-cards-create.js} +2 -1
- package/dist/generated/commands/sensei/{device-requests-decide.js → device-requests-update.js} +1 -1
- package/dist/generated/commands/sensei/memory-get.js +1 -1
- package/dist/generated/commands/sensei/{memory-put.js → memory-set.js} +4 -4
- package/dist/generated/commands/sensei/{merge-rule.js → merge-rule-set.js} +2 -1
- package/dist/generated/commands/sensei/{messages-reroute.js → messages-move.js} +1 -1
- package/dist/generated/commands/sensei/messages-send.js +2 -2
- package/dist/generated/commands/sensei/{notifications-open.js → notifications-mark-read.js} +1 -1
- package/dist/generated/commands/sensei/{reels-activity.js → reels-activity-list.js} +2 -1
- package/dist/generated/commands/sensei/{reels-ranks.js → reels-ranks-list.js} +2 -1
- package/dist/generated/commands/sensei/{repository.js → repository-cards-create.js} +2 -1
- package/dist/generated/commands/sensei/{review-approve.js → review-approvals-create.js} +2 -1
- package/dist/generated/commands/sensei/{review-context.js → review-context-get.js} +2 -1
- package/dist/generated/commands/sensei/{review-ask.js → review-requests-create.js} +3 -2
- package/dist/generated/commands/sensei/{sessions-assess.js → sessions-assessments-create.js} +2 -1
- package/dist/generated/commands/sensei/{sessions-facts.js → sessions-facts-get.js} +2 -1
- package/dist/generated/commands/sensei/{suggest.js → suggestions-create.js} +3 -2
- package/dist/generated/commands/sensei/{thread-done.js → threads-close.js} +2 -2
- package/dist/generated/commands/sensei/{thread-read.js → threads-get.js} +2 -2
- package/dist/generated/commands/sensei/{threads.js → threads-list.js} +2 -1
- package/dist/generated/commands/sensei/{thread-move.js → threads-move.js} +2 -2
- package/dist/generated/commands/sensei/{thread-split.js → threads-split.js} +2 -2
- package/dist/generated/commands/sensei/{widgets.js → widgets-get.js} +2 -1
- package/dist/generated/commands/sessions/app-stack-start.js +2 -1
- package/dist/generated/commands/sessions/{artifacts-attach.js → artifacts-create.js} +1 -1
- package/dist/generated/commands/sessions/artifacts-get.js +1 -1
- package/dist/generated/commands/sessions/create.js +3 -3
- package/dist/generated/commands/sessions/{desktop-control.js → desktop-control-set.js} +3 -1
- package/dist/generated/commands/sessions/{desktop.js → desktop-get.js} +2 -1
- package/dist/generated/commands/sessions/desktop-start.js +2 -1
- package/dist/generated/commands/sessions/{diff-comments-add.js → diff-comments-create.js} +1 -1
- package/dist/generated/commands/sessions/{diff-commits.js → diff-commits-list.js} +2 -1
- package/dist/generated/commands/sessions/{diff-files.js → diff-files-list.js} +2 -1
- package/dist/generated/commands/sessions/{diff-patch.js → diff-patch-get.js} +2 -1
- package/dist/generated/commands/sessions/{files-write.js → files-set.js} +1 -1
- package/dist/generated/commands/sessions/get.js +1 -1
- package/dist/generated/commands/sessions/{git-commit-message.js → git-commit-message-create.js} +2 -1
- package/dist/generated/commands/sessions/{git-state.js → git-state-get.js} +2 -1
- package/dist/generated/commands/sessions/{go-ahead-clear.js → go-ahead-delete.js} +1 -1
- package/dist/generated/commands/sessions/{labels-edit.js → labels-update.js} +1 -1
- package/dist/generated/commands/sessions/{all.js → list--all.js} +4 -1
- package/dist/generated/commands/sessions/{message.js → messages-get.js} +4 -3
- package/dist/generated/commands/sessions/{messages.js → messages-list.js} +3 -2
- package/dist/generated/commands/sessions/{edit-prompt.js → prompt-update.js} +3 -2
- package/dist/generated/commands/sessions/pull-request-mark-ready.js +40 -0
- package/dist/generated/commands/sessions/qa-runs-finish.js +66 -0
- package/dist/generated/commands/sessions/qa-runs-fixes-create.js +65 -0
- package/dist/generated/commands/sessions/qa-runs-get.js +22 -0
- package/dist/generated/commands/sessions/qa-runs-results-create.js +45 -0
- package/dist/generated/commands/sessions/qa-runs-start.js +75 -0
- package/dist/generated/commands/sessions/qa-runs-stop.js +43 -0
- package/dist/generated/commands/sessions/qa-set.js +1 -1
- package/dist/generated/commands/sessions/review-set.js +53 -0
- package/dist/generated/commands/sessions/{runtime-command.js → runtime-commands-run.js} +2 -1
- package/dist/generated/commands/sessions/send.js +1 -1
- package/dist/generated/commands/sessions/{activate.js → start.js} +1 -1
- package/dist/generated/commands/sessions/steer.js +1 -1
- package/dist/generated/commands/sessions/update.js +2 -2
- package/dist/generated/commands/{user/skills-create.js → skills/create--personal.js} +3 -1
- package/dist/generated/commands/{workspaces/skills-create.js → skills/create.js} +0 -1
- package/dist/generated/commands/{user/skills-delete.js → skills/delete--personal.js} +3 -1
- package/dist/generated/commands/{workspaces/skills-delete.js → skills/delete.js} +0 -1
- package/dist/generated/commands/{user/skills-get.js → skills/get--personal.js} +3 -1
- package/dist/generated/commands/{workspaces/skills-get.js → skills/get.js} +0 -1
- package/dist/generated/commands/{user/skills-list.js → skills/list--personal.js} +3 -1
- package/dist/generated/commands/{workspaces/skills-list.js → skills/list.js} +0 -1
- package/dist/generated/commands/{user/skills-update.js → skills/update--personal.js} +3 -1
- package/dist/generated/commands/{workspaces/skills-update.js → skills/update.js} +0 -1
- package/dist/generated/commands/{personal-tasks/create.js → tasks/create--personal.js} +5 -2
- package/dist/generated/commands/tasks/create.js +7 -5
- package/dist/generated/commands/{personal-tasks/delete.js → tasks/delete--personal.js} +4 -1
- package/dist/generated/commands/{personal-tasks/get.js → tasks/get--personal.js} +4 -1
- package/dist/generated/commands/tasks/{labels.js → labels-list.js} +2 -1
- package/dist/generated/commands/tasks/{all.js → list--all.js} +7 -3
- package/dist/generated/commands/{personal-tasks/list.js → tasks/list--personal.js} +4 -1
- package/dist/generated/commands/tasks/list.js +3 -2
- package/dist/generated/commands/{personal-tasks/move.js → tasks/move--personal.js} +5 -2
- package/dist/generated/commands/{personal-tasks/start.js → tasks/start--personal.js} +7 -3
- package/dist/generated/commands/tasks/start.js +4 -3
- package/dist/generated/commands/{personal-tasks/update.js → tasks/update--personal.js} +4 -1
- package/dist/generated/commands/tasks/update.js +5 -3
- package/dist/generated/commands/user/{auth-token-revoke.js → api-keys-delete.js} +2 -2
- package/dist/generated/commands/user/{profile.js → profile-get.js} +2 -1
- package/dist/generated/commands/user/{push-devices-register.js → push-devices-create.js} +1 -1
- package/dist/generated/commands/user/{push-devices-remove.js → push-devices-delete.js} +1 -1
- package/dist/generated/commands/workspaces/{artifacts.js → artifacts-search.js} +2 -1
- package/dist/generated/commands/workspaces/{credits.js → credits-get.js} +2 -1
- package/dist/generated/commands/{members/list.js → workspaces/members-list--all.js} +4 -0
- package/dist/generated/commands/workspaces/{members.js → members-list.js} +2 -1
- package/dist/generated/commands/workspaces/{sandbox-limit.js → sandbox-limit-get.js} +2 -1
- package/dist/generated/commands/workspaces/{stop-sandboxes.js → sandboxes-stop.js} +2 -1
- package/dist/generated/commands/workspaces/timezone-set.js +2 -1
- package/dist/generated/commands/workspaces/{usage.js → usage-get.js} +2 -1
- package/dist/integrations/api.js +1 -1
- package/dist/integrations/render.js +1 -1
- package/dist/program.js +15 -9
- package/dist/runtime/agent-tokens.js +2 -8
- package/dist/runtime/aliases.js +516 -0
- package/dist/runtime/attach.js +296 -83
- package/dist/runtime/former-commands.js +89 -0
- package/dist/runtime/job-watch.js +1 -1
- package/dist/runtime/variants.js +205 -0
- package/openapi.json +2230 -1083
- package/package.json +15 -5
- package/dist/generated/commands/crons/projects-resume.js +0 -21
- package/dist/generated/commands/crons/runs-diagnostics.js +0 -21
- package/dist/generated/commands/sessions/needs-you.js +0 -16
- package/dist/generated/commands/sessions/qa-clear.js +0 -22
- package/dist/generated/commands/sessions/title-generate.js +0 -29
- package/dist/generated/commands/user/memory-list.js +0 -17
- package/dist/generated/commands/user/memory-put.js +0 -37
package/dist/runtime/attach.js
CHANGED
|
@@ -1,103 +1,284 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
1
2
|
import { Argument, Command, InvalidArgumentError, Option } from 'commander';
|
|
2
3
|
import { buildRequest, execute, readWholeBody, UsageError } from './invoke.js';
|
|
4
|
+
import { fieldsOf, formLabel, formUsage, leafShape, pathParamsFor, PERSONAL, scopeOf, selectForm, } from './variants.js';
|
|
3
5
|
/**
|
|
4
|
-
* One commander command per
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* the
|
|
6
|
+
* One commander command per command name: positionals for path params, a flag per
|
|
7
|
+
* top-level field, `--body`/`--body-file` for a whole body and `--attach` where the
|
|
8
|
+
* operation takes files. A command with several forms (personal, all, a selector flag)
|
|
9
|
+
* is one leaf over all of them; `variants.ts` picks the form a call reaches. The help is
|
|
10
|
+
* the contract's summary, verbatim, and a `Forms:` list when there are several.
|
|
8
11
|
*/
|
|
9
|
-
export function
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
});
|
|
18
|
-
}
|
|
12
|
+
export function attachCommand(root, forms, runtime, { reachable = () => true } = {}) {
|
|
13
|
+
const [only] = forms;
|
|
14
|
+
if (forms.length === 1 && !only.variant) {
|
|
15
|
+
// A hidden operation sits beside a hand-written command in a visible group.
|
|
16
|
+
return attachLeaf(root, only.command, only, runtime, {
|
|
17
|
+
hidden: only.hidden === true,
|
|
18
|
+
groupsHidden: false,
|
|
19
|
+
});
|
|
19
20
|
}
|
|
20
|
-
return
|
|
21
|
+
return attachForms(root, forms, runtime, reachable);
|
|
21
22
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// person. The workspace they take goes to `--workspace` where the command reads one.
|
|
26
|
-
const COMMAND_ALIASES = new Map([
|
|
27
|
-
['cards', 'sensei cards'],
|
|
28
|
-
['merge', 'sensei merge'],
|
|
29
|
-
['notifications open', 'sensei notifications open'],
|
|
30
|
-
].flatMap(([old, target]) => [
|
|
31
|
-
[`workspaces sensei-${old}`, target],
|
|
32
|
-
[`workspaces lead-${old}`, target],
|
|
33
|
-
]));
|
|
34
|
-
function attachLeaf(root, path, operation, runtime, { hidden, workspaceArgument = false }) {
|
|
35
|
-
const parent = groupFor(root, path.slice(0, -1), { hidden });
|
|
23
|
+
/** A single-form leaf: the command as it was before forms, which aliases reuse. */
|
|
24
|
+
export function attachLeaf(root, path, operation, runtime, { hidden, groupsHidden = hidden, fixed = {}, formerFlags = {} }) {
|
|
25
|
+
const parent = groupFor(root, path.slice(0, -1), { hidden: groupsHidden });
|
|
36
26
|
const leaf = parent.command(path[path.length - 1], { hidden });
|
|
37
27
|
leaf.description(operation.summary);
|
|
38
|
-
if (workspaceArgument)
|
|
39
|
-
leaf.addArgument(new Argument('<workspaceId>', 'Workspace id'));
|
|
40
28
|
for (const name of operation.pathParams) {
|
|
41
29
|
leaf.addArgument(new Argument(`<${name}>`, humanize(name)));
|
|
42
30
|
}
|
|
43
|
-
const fields =
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
// Both spellings, so a field whose meaningful value is false (members
|
|
51
|
-
// --no-include-invitations) can be said; neither given leaves it unsent.
|
|
52
|
-
if (field.kind === 'boolean') {
|
|
53
|
-
leaf.addOption(new Option(`--no-${field.flag}`, `Send ${field.name} as false.`));
|
|
31
|
+
const fields = fieldsOf(operation);
|
|
32
|
+
for (const field of fields)
|
|
33
|
+
addFieldOptions(leaf, field, field.description ?? '');
|
|
34
|
+
for (const [former, current] of Object.entries(formerFlags)) {
|
|
35
|
+
const field = fields.find((candidate) => candidate.flag === current);
|
|
36
|
+
if (!field) {
|
|
37
|
+
throw new Error(`kosuke ${path.join(' ')}: --${former} names --${current}, not a flag.`);
|
|
54
38
|
}
|
|
39
|
+
const option = new Option(`--${former} <value>`).hideHelp();
|
|
40
|
+
// Repeated as it was, `--project-ids a --project-ids b`, or one JSON list.
|
|
41
|
+
if (field.repeated)
|
|
42
|
+
option.argParser(collect).default(undefined);
|
|
43
|
+
leaf.addOption(option);
|
|
55
44
|
}
|
|
56
|
-
|
|
57
|
-
if (takesBody) {
|
|
58
|
-
leaf.option('--body <json>', 'The whole request body as JSON; overrides field flags.');
|
|
59
|
-
leaf.option('--body-file <path>', 'Read the whole request body from a file, or - for stdin.');
|
|
60
|
-
}
|
|
61
|
-
if (operation.attachments) {
|
|
62
|
-
leaf.option('--attach <path>', 'Attach a file; repeat for several. Sends the request as multipart.', collect, []);
|
|
63
|
-
}
|
|
45
|
+
addBodyOptions(leaf, operation);
|
|
64
46
|
leaf.action(async (...args) => {
|
|
65
47
|
const options = args[args.length - 2];
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
48
|
+
const positionals = args.slice(0, operation.pathParams.length);
|
|
49
|
+
try {
|
|
50
|
+
checkFileFlags(options, fields.filter((field) => field.file).map((field) => field.flag));
|
|
51
|
+
// `personal` where a workspace id goes, on a command with no personal form. An alias
|
|
52
|
+
// leaf runs a personal form by its old path, which takes no workspace id at all.
|
|
53
|
+
if (!operation.variant)
|
|
54
|
+
selectForm([operation], { first: positionals[0], flags: {} });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof UsageError)
|
|
58
|
+
leaf.error(error.message);
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
const values = Object.fromEntries(fields.map((field) => {
|
|
62
|
+
const former = Object.entries(formerFlags).find(([, current]) => current === field.flag);
|
|
63
|
+
const formerValue = former
|
|
64
|
+
? formerValueOf(field, options[optionKey(former[0])])
|
|
65
|
+
: undefined;
|
|
66
|
+
return [
|
|
67
|
+
field.name,
|
|
68
|
+
options[optionKey(field.flag)] ?? fileValue(field, options) ?? formerValue,
|
|
69
|
+
];
|
|
70
|
+
}));
|
|
71
|
+
await run(leaf, runtime, operation, {
|
|
70
72
|
pathParams: Object.fromEntries(operation.pathParams.map((name, i) => [name, positionals[i]])),
|
|
71
|
-
fields:
|
|
72
|
-
const given = options[optionKey(field.flag)];
|
|
73
|
-
// The old command's workspace filters a read that takes one; a write names its own.
|
|
74
|
-
const value = given ?? (field.name === 'workspace' ? workspace : undefined);
|
|
75
|
-
return [field.name, value];
|
|
76
|
-
})),
|
|
73
|
+
fields: { ...values, ...fixed },
|
|
77
74
|
wholeBody: readWholeBody({
|
|
78
75
|
body: options.body,
|
|
79
76
|
bodyFile: options.bodyFile,
|
|
80
77
|
}),
|
|
81
78
|
attachments: options.attach ?? [],
|
|
82
|
-
};
|
|
83
|
-
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
return leaf;
|
|
82
|
+
}
|
|
83
|
+
/** A leaf over several forms: the union of their flags, the form picked per call. */
|
|
84
|
+
function attachForms(root, forms, runtime, reachable) {
|
|
85
|
+
const path = forms[0].command;
|
|
86
|
+
const shape = leafShape(forms);
|
|
87
|
+
const parent = groupFor(root, path.slice(0, -1));
|
|
88
|
+
const leaf = parent.command(path[path.length - 1]);
|
|
89
|
+
const visible = forms.filter(reachable);
|
|
90
|
+
const lead = forms.find((form) => scopeOf(form) === 'workspace') ?? forms[0];
|
|
91
|
+
leaf.description(lead.summary);
|
|
92
|
+
if (shape.scope) {
|
|
93
|
+
leaf.addArgument(new Argument(shape.scope.label, shape.scope.label === `<${PERSONAL}>`
|
|
94
|
+
? 'The word personal: this command works on your own only.'
|
|
95
|
+
: `A ${humanize(shape.scope.name).toLowerCase()}` +
|
|
96
|
+
(shape.scope.label.includes(PERSONAL) ? ', or personal for your own' : '') +
|
|
97
|
+
(shape.scope.optional ? '; left out, every one you can reach' : '')));
|
|
98
|
+
}
|
|
99
|
+
for (const name of shape.positionals) {
|
|
100
|
+
leaf.addArgument(new Argument(`<${name}>`, humanize(name)));
|
|
101
|
+
}
|
|
102
|
+
for (const leafFlag of shape.flags) {
|
|
103
|
+
const fields = [...leafFlag.forms.values()];
|
|
104
|
+
const note = whoTakes(leafFlag, forms);
|
|
105
|
+
if (leafFlag.uniform && fields.length) {
|
|
106
|
+
const [field] = fields;
|
|
107
|
+
const required = fields.every((f) => f.required) && leafFlag.forms.size === forms.length;
|
|
108
|
+
addFieldOptions(leaf, { ...field, required }, appendNote(field.description ?? '', note));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const values = forms
|
|
112
|
+
.filter((form) => form.variant?.when?.flag === leafFlag.flag)
|
|
113
|
+
.map((form) => form.variant.when.equals);
|
|
114
|
+
const choices = [...new Set([...values, ...fields.flatMap((field) => field.choices ?? [])])];
|
|
115
|
+
const description = [
|
|
116
|
+
fields.find((field) => field.description)?.description ?? '',
|
|
117
|
+
choices.length ? `One of ${choices.join(', ')}.` : '',
|
|
118
|
+
]
|
|
119
|
+
.filter(Boolean)
|
|
120
|
+
.join(' ');
|
|
121
|
+
leaf.addOption(new Option(`--${leafFlag.flag} <value>`, appendNote(description, note)));
|
|
122
|
+
if (fields.some((field) => field.file)) {
|
|
123
|
+
leaf.addOption(new Option(`--${leafFlag.flag}-file <path>`, `Read --${leafFlag.flag} from a file, or - for stdin.`));
|
|
124
|
+
}
|
|
125
|
+
if (fields.length && fields.every((field) => field.kind === 'boolean')) {
|
|
126
|
+
leaf.addOption(new Option(`--no-${leafFlag.flag}`, `Send it as false.`));
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
addBodyOptions(leaf, {
|
|
131
|
+
body: forms.find((form) => form.body)?.body ?? null,
|
|
132
|
+
multipart: forms.find((form) => form.multipart)?.multipart ?? null,
|
|
133
|
+
attachments: forms.find((form) => form.attachments)?.attachments ?? false,
|
|
134
|
+
});
|
|
135
|
+
leaf.addHelpText('after', () => '\nForms:\n' +
|
|
136
|
+
visible.map((form) => ` ${formUsage(form, shape)}\n ${form.summary}`).join('\n'));
|
|
137
|
+
leaf.action(async (...args) => {
|
|
138
|
+
const options = args[args.length - 2];
|
|
139
|
+
const operands = args.slice(0, args.length - 2);
|
|
140
|
+
const first = operands[0];
|
|
141
|
+
const positionals = (shape.scope ? operands.slice(1) : operands);
|
|
142
|
+
const given = {};
|
|
143
|
+
for (const leafFlag of shape.flags) {
|
|
144
|
+
const value = options[optionKey(leafFlag.flag)] ?? options[optionKey(`${leafFlag.flag}-file`)];
|
|
145
|
+
if (value !== undefined)
|
|
146
|
+
given[leafFlag.flag] = value;
|
|
147
|
+
}
|
|
148
|
+
let form;
|
|
84
149
|
try {
|
|
85
|
-
|
|
150
|
+
checkFileFlags(options, shape.flags
|
|
151
|
+
.filter((leafFlag) => [...leafFlag.forms.values()].some((field) => field.file))
|
|
152
|
+
.map((leafFlag) => leafFlag.flag));
|
|
153
|
+
form = selectForm(forms, { first, flags: given }, reachable);
|
|
86
154
|
}
|
|
87
155
|
catch (error) {
|
|
88
156
|
if (error instanceof UsageError)
|
|
89
157
|
leaf.error(error.message);
|
|
90
158
|
throw error;
|
|
91
159
|
}
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
160
|
+
const fields = {};
|
|
161
|
+
try {
|
|
162
|
+
for (const leafFlag of shape.flags) {
|
|
163
|
+
const field = leafFlag.forms.get(form);
|
|
164
|
+
if (!field || field.pathParam)
|
|
165
|
+
continue;
|
|
166
|
+
const raw = options[optionKey(leafFlag.flag)];
|
|
167
|
+
fields[field.name] =
|
|
168
|
+
raw === undefined
|
|
169
|
+
? fileValue(field, options)
|
|
170
|
+
: leafFlag.uniform
|
|
171
|
+
? raw
|
|
172
|
+
: parseForForm(field, raw);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
if (error instanceof UsageError || error instanceof InvalidArgumentError) {
|
|
177
|
+
leaf.error(error.message);
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
await run(leaf, runtime, form, {
|
|
182
|
+
pathParams: pathParamsFor(form, shape, first, positionals, given),
|
|
183
|
+
fields,
|
|
184
|
+
wholeBody: readWholeBody({
|
|
185
|
+
body: options.body,
|
|
186
|
+
bodyFile: options.bodyFile,
|
|
187
|
+
}),
|
|
188
|
+
attachments: options.attach ?? [],
|
|
95
189
|
});
|
|
96
|
-
const outcome = await execute(client, request);
|
|
97
|
-
runtime.output(outcome);
|
|
98
190
|
});
|
|
99
191
|
return leaf;
|
|
100
192
|
}
|
|
193
|
+
/** Build, send and print; a usage error is commander's, so it prints as one. */
|
|
194
|
+
async function run(leaf, runtime, operation, input) {
|
|
195
|
+
let request;
|
|
196
|
+
try {
|
|
197
|
+
request = buildRequest(operation, input);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
if (error instanceof UsageError)
|
|
201
|
+
leaf.error(error.message);
|
|
202
|
+
throw error;
|
|
203
|
+
}
|
|
204
|
+
const client = runtime.client({
|
|
205
|
+
anonymous: operation.anonymous,
|
|
206
|
+
answerTimeoutMs: operation.answerTimeoutMs,
|
|
207
|
+
});
|
|
208
|
+
const outcome = await execute(client, request);
|
|
209
|
+
runtime.output(outcome);
|
|
210
|
+
}
|
|
211
|
+
/** `(personal only)`, `(workspace only)`, `(--provider claude_code, codex)`; empty for all. */
|
|
212
|
+
function whoTakes(leafFlag, forms) {
|
|
213
|
+
const takers = forms.filter((form) => leafFlag.forms.has(form) || form.variant?.when?.flag === leafFlag.flag);
|
|
214
|
+
if (takers.length === forms.length)
|
|
215
|
+
return '';
|
|
216
|
+
const scopes = [...new Set(takers.map(scopeOf))];
|
|
217
|
+
const allOfScope = scopes.every((scope) => forms.filter((form) => scopeOf(form) === scope).every((form) => takers.includes(form)));
|
|
218
|
+
if (allOfScope)
|
|
219
|
+
return `(${scopes.join(' and ')} only)`;
|
|
220
|
+
const selected = takers.filter((form) => form.variant?.when);
|
|
221
|
+
if (selected.length === takers.length) {
|
|
222
|
+
const flag = selected[0].variant.when.flag;
|
|
223
|
+
return `(--${flag} ${selected.map((form) => form.variant.when.equals).join(', ')})`;
|
|
224
|
+
}
|
|
225
|
+
return `(${takers.map((form) => formLabel(form).replace(/^the | form$/g, '')).join(', ')})`;
|
|
226
|
+
}
|
|
227
|
+
function appendNote(description, note) {
|
|
228
|
+
return [description, note].filter(Boolean).join(' ');
|
|
229
|
+
}
|
|
230
|
+
/** A union flag the forms disagree on arrives as text, parsed by the chosen form's rule. */
|
|
231
|
+
function parseForForm(field, raw) {
|
|
232
|
+
if (typeof raw !== 'string')
|
|
233
|
+
return raw;
|
|
234
|
+
if (field.choices && !field.choices.includes(raw)) {
|
|
235
|
+
throw new UsageError(`--${field.flag} must be one of ${field.choices.join(', ')}.`);
|
|
236
|
+
}
|
|
237
|
+
if (field.kind === 'number' || field.kind === 'integer')
|
|
238
|
+
return numberParser(field)(raw);
|
|
239
|
+
if (field.kind === 'json')
|
|
240
|
+
return jsonParser(raw);
|
|
241
|
+
if (field.kind === 'boolean')
|
|
242
|
+
return raw === 'true';
|
|
243
|
+
return field.repeated ? [raw] : raw;
|
|
244
|
+
}
|
|
245
|
+
/** The value of a renamed flag, by the rule its field had: one JSON list, or the values given. */
|
|
246
|
+
function formerValueOf(field, raw) {
|
|
247
|
+
if (Array.isArray(raw))
|
|
248
|
+
return raw.flatMap((value) => formerValueOf(field, value));
|
|
249
|
+
if (typeof raw !== 'string')
|
|
250
|
+
return raw;
|
|
251
|
+
if (!field.repeated)
|
|
252
|
+
return field.kind === 'json' ? jsonParser(raw) : raw;
|
|
253
|
+
try {
|
|
254
|
+
const parsed = JSON.parse(raw);
|
|
255
|
+
return Array.isArray(parsed) ? parsed : [raw];
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return [raw];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function addFieldOptions(leaf, field, description) {
|
|
262
|
+
leaf.addOption(optionFor({ ...field, description }));
|
|
263
|
+
if (field.file) {
|
|
264
|
+
leaf.addOption(new Option(`--${field.flag}-file <path>`, `Read ${field.name} from a file, or - for stdin.`));
|
|
265
|
+
}
|
|
266
|
+
// Both spellings, so a field whose meaningful value is false (members
|
|
267
|
+
// --no-include-invitations) can be said; neither given leaves it unsent.
|
|
268
|
+
if (field.kind === 'boolean') {
|
|
269
|
+
leaf.addOption(new Option(`--no-${field.flag}`, `Send ${field.name} as false.`));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function addBodyOptions(leaf, operation) {
|
|
273
|
+
const takesBody = operation.body !== null || operation.multipart !== null;
|
|
274
|
+
if (takesBody) {
|
|
275
|
+
leaf.option('--body <json>', 'The whole request body as JSON; overrides field flags.');
|
|
276
|
+
leaf.option('--body-file <path>', 'Read the whole request body from a file, or - for stdin.');
|
|
277
|
+
}
|
|
278
|
+
if (operation.attachments) {
|
|
279
|
+
leaf.option('--attach <path>', 'Attach a file; repeat for several. Sends the request as multipart.', collect, []);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
101
282
|
/** A group created here is hidden when asked; one that already exists keeps what it is. */
|
|
102
283
|
export function groupFor(root, path, { hidden = false } = {}) {
|
|
103
284
|
let current = root;
|
|
@@ -108,6 +289,10 @@ export function groupFor(root, path, { hidden = false } = {}) {
|
|
|
108
289
|
}
|
|
109
290
|
return current;
|
|
110
291
|
}
|
|
292
|
+
/** A hand-written command's leaf at its listed path, its groups made as `groupFor` makes them. */
|
|
293
|
+
export function leafAt(root, command) {
|
|
294
|
+
return groupFor(root, command.slice(0, -1)).command(command[command.length - 1]);
|
|
295
|
+
}
|
|
111
296
|
function optionFor(field) {
|
|
112
297
|
const description = field.description ?? '';
|
|
113
298
|
if (field.repeated)
|
|
@@ -160,6 +345,48 @@ function numberParser(field) {
|
|
|
160
345
|
return value;
|
|
161
346
|
};
|
|
162
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* A value given twice is ambiguous: `--x` and `--x-file` together, or stdin (`-`) named by two
|
|
350
|
+
* file flags, which only one of them could read.
|
|
351
|
+
*/
|
|
352
|
+
function checkFileFlags(options, fileFlags) {
|
|
353
|
+
for (const flag of fileFlags) {
|
|
354
|
+
if (options[optionKey(flag)] !== undefined &&
|
|
355
|
+
options[optionKey(`${flag}-file`)] !== undefined) {
|
|
356
|
+
throw new UsageError(`--${flag} and --${flag}-file are both given; give one.`);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const stdin = [...fileFlags.map((flag) => `${flag}-file`), 'body-file'].filter((flag) => options[optionKey(flag)] === '-');
|
|
360
|
+
if (stdin.length > 1) {
|
|
361
|
+
throw new UsageError(`${stdin.map((flag) => `--${flag}`).join(' and ')} both read stdin (-); only one can.`);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* A field's value from `--<flag>-file`: the file's text, parsed as JSON for a nested field.
|
|
366
|
+
* Read at the call, so a large checklist or result never rides one shell argument.
|
|
367
|
+
*/
|
|
368
|
+
function fileValue(field, options) {
|
|
369
|
+
const path = field.file ? options[optionKey(`${field.flag}-file`)] : undefined;
|
|
370
|
+
if (typeof path !== 'string')
|
|
371
|
+
return undefined;
|
|
372
|
+
const text = readFieldFile(path);
|
|
373
|
+
if (field.kind !== 'json')
|
|
374
|
+
return text;
|
|
375
|
+
try {
|
|
376
|
+
return JSON.parse(text);
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
throw new UsageError(`--${field.flag}-file ${path} is not JSON.`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
function readFieldFile(path) {
|
|
383
|
+
try {
|
|
384
|
+
return path === '-' ? readFileSync(0, 'utf8') : readFileSync(path, 'utf8');
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
throw new UsageError(`Could not read ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
163
390
|
function jsonParser(raw) {
|
|
164
391
|
try {
|
|
165
392
|
return JSON.parse(raw);
|
|
@@ -169,21 +396,7 @@ function jsonParser(raw) {
|
|
|
169
396
|
}
|
|
170
397
|
}
|
|
171
398
|
function collect(value, previous) {
|
|
172
|
-
return [...previous, value];
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* One option per flag. The generator gives the same wire name on the JSON and
|
|
176
|
-
* the form branch one flag, and two wire names never one flag; this keys on
|
|
177
|
-
* the flag because that is what commander refuses to register twice.
|
|
178
|
-
*/
|
|
179
|
-
function dedupe(fields) {
|
|
180
|
-
const seen = new Set();
|
|
181
|
-
return fields.filter((field) => {
|
|
182
|
-
if (seen.has(field.flag))
|
|
183
|
-
return false;
|
|
184
|
-
seen.add(field.flag);
|
|
185
|
-
return true;
|
|
186
|
-
});
|
|
399
|
+
return [...(previous ?? []), value];
|
|
187
400
|
}
|
|
188
401
|
/** commander stores `--exclude-archived` as `excludeArchived`. */
|
|
189
402
|
export function optionKey(flag) {
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { FORMER_COMMANDS } from './aliases.js';
|
|
2
|
+
import { attachLeaf } from './attach.js';
|
|
3
|
+
import { PERSONAL, scopeOf } from './variants.js';
|
|
4
|
+
/** Groups that forward to a live child, so a listing of what runs can leave them out. */
|
|
5
|
+
const FORWARDERS = new WeakSet();
|
|
6
|
+
export function isForwarder(command) {
|
|
7
|
+
return FORWARDERS.has(command);
|
|
8
|
+
}
|
|
9
|
+
/** `METHOD path`, the key an alias names an operation by. */
|
|
10
|
+
export function operationKey(operation) {
|
|
11
|
+
return `${operation.method.toUpperCase()} ${operation.path}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Attaches every former name whose target this credential reaches: a hidden leaf where the
|
|
15
|
+
* old path is free, a forwarder where it is now a live group. Runs after every live command,
|
|
16
|
+
* so a forwarder finds its target.
|
|
17
|
+
*/
|
|
18
|
+
export function attachFormerCommands(root, operations, runtime, formerCommands = FORMER_COMMANDS) {
|
|
19
|
+
const byKey = new Map(operations.map((operation) => [operationKey(operation), operation]));
|
|
20
|
+
for (const former of formerCommands) {
|
|
21
|
+
const path = former.from.split(' ');
|
|
22
|
+
const existing = find(root, path);
|
|
23
|
+
if (former.operation) {
|
|
24
|
+
const operation = byKey.get(former.operation);
|
|
25
|
+
if (!operation)
|
|
26
|
+
continue;
|
|
27
|
+
if (existing) {
|
|
28
|
+
const target = find(root, operation.command);
|
|
29
|
+
if (!target)
|
|
30
|
+
continue;
|
|
31
|
+
const { prefix, suffix } = formArguments(operation);
|
|
32
|
+
forward(existing, target, prefix, suffix);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
attachLeaf(root, path, operation, runtime, {
|
|
36
|
+
hidden: true,
|
|
37
|
+
...(former.fixed ? { fixed: former.fixed } : {}),
|
|
38
|
+
...(former.formerFlags ? { formerFlags: former.formerFlags } : {}),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
else if (former.handWritten) {
|
|
43
|
+
const target = find(root, former.handWritten.split(' '));
|
|
44
|
+
if (!target)
|
|
45
|
+
continue;
|
|
46
|
+
forward(existing ?? hiddenLeaf(root, path), target, [], []);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/** What reaches a form on its live command: `personal` first, a selector last. */
|
|
51
|
+
function formArguments(operation) {
|
|
52
|
+
return {
|
|
53
|
+
prefix: scopeOf(operation) === 'personal' ? [PERSONAL] : [],
|
|
54
|
+
suffix: operation.variant?.when
|
|
55
|
+
? [`--${operation.variant.when.flag}`, operation.variant.when.equals]
|
|
56
|
+
: [],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The old leaf's arguments, re-parsed by the live command. No options of its own, since
|
|
61
|
+
* commander reads an ancestor's options anywhere on the line and would take a child's flag.
|
|
62
|
+
*/
|
|
63
|
+
function forward(command, target, prefix, suffix) {
|
|
64
|
+
FORWARDERS.add(command);
|
|
65
|
+
command
|
|
66
|
+
.allowUnknownOption()
|
|
67
|
+
.allowExcessArguments()
|
|
68
|
+
.action(async (...args) => {
|
|
69
|
+
const self = args[args.length - 1];
|
|
70
|
+
await target.parseAsync([...prefix, ...self.args, ...suffix], { from: 'user' });
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function hiddenLeaf(root, path) {
|
|
74
|
+
let current = root;
|
|
75
|
+
for (const [index, segment] of path.entries()) {
|
|
76
|
+
const found = current.commands.find((command) => command.name() === segment);
|
|
77
|
+
current = found ?? current.command(segment, { hidden: true });
|
|
78
|
+
if (!found && index < path.length - 1)
|
|
79
|
+
current.description('');
|
|
80
|
+
}
|
|
81
|
+
return current;
|
|
82
|
+
}
|
|
83
|
+
function find(root, path) {
|
|
84
|
+
let current = root;
|
|
85
|
+
for (const segment of path) {
|
|
86
|
+
current = current?.commands.find((command) => command.name() === segment);
|
|
87
|
+
}
|
|
88
|
+
return current;
|
|
89
|
+
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Following one job's `/ws/jobs` stream to its end: the socket, the resume
|
|
3
3
|
* cursor, the close codes and the status fallback, with everything that
|
|
4
4
|
* touches the process or the network handed in, so each path is testable
|
|
5
|
-
* without either. `kosuke sessions watch` is its one caller.
|
|
5
|
+
* without either. `kosuke sessions jobs watch` is its one caller.
|
|
6
6
|
*/
|
|
7
7
|
export const JOB_TYPES = ['chat', 'deploy'];
|
|
8
8
|
export const WATCH_EXIT = {
|