fengming 0.3.10 → 0.3.12
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/dist/build-info.json +2 -2
- package/dist/canvas-host/a2ui/.bundle.hash +1 -1
- package/dist/cli/run-main.js +3 -3
- package/dist/cli-startup-metadata.json +8 -8
- package/dist/{command-registry-DMB-HKIk.js → command-registry-BHIBvpgR.js} +2 -2
- package/dist/{command-registry-C5ooX6PF.js → command-registry-BT5icv-c.js} +2 -2
- package/dist/{command-registry-core-B2w_XWvn.js → command-registry-core-C-a3GaYV.js} +2 -2
- package/dist/{completion-cli-Bf4mEw2W.js → completion-cli-BUfFF31m.js} +2 -2
- package/dist/control-ui/assets/{activity-D-mnRThU.js → activity-DF1iC1pF.js} +2 -2
- package/dist/control-ui/assets/{agents-U_KSP5I_.js → agents-CDGNJA8n.js} +2 -2
- package/dist/control-ui/assets/{channels-ohK9_G1O.js → channels-CAPFdCrE.js} +2 -2
- package/dist/control-ui/assets/{cron-6ZCzfU29.js → cron-DUUdUzzu.js} +2 -2
- package/dist/control-ui/assets/{debug-CSsDLg_s.js → debug-BwfVXGKK.js} +2 -2
- package/dist/control-ui/assets/{index-jUDczxhd.js → index-JWV4rMUy.js} +4 -4
- package/dist/control-ui/assets/{instances-782ZoDT4.js → instances-BqAPpn0Y.js} +2 -2
- package/dist/control-ui/assets/{nodes-BMX16BKM.js → nodes-gya-0PkG.js} +2 -2
- package/dist/control-ui/assets/{sessions-jLGSApYa.js → sessions-BdttyTpI.js} +2 -2
- package/dist/control-ui/assets/{skills-DweBwUhs.js → skills-D_rtwBjc.js} +2 -2
- package/dist/control-ui/assets/{workboard-BsU-FXIo.js → workboard-CIGDGkWB.js} +2 -2
- package/dist/control-ui/index.html +1 -1
- package/dist/control-ui/sw.js +1 -1
- package/dist/crestodian/crestodian.js +1 -1
- package/dist/crestodian/rescue-message.js +1 -1
- package/dist/{crestodian-C0x7JjF-.js → crestodian-CAxGCgHM.js} +3 -3
- package/dist/{dialogue-No0NvYX7.js → dialogue-CHuN9qet.js} +1 -1
- package/dist/gateway/protocol/index.d.ts +1 -1
- package/dist/{index-AZzJCgph.d.ts → index-DbpfOFUf.d.ts} +1 -1
- package/dist/{operations-Z85LFqsT.js → operations-Mvnrndji.js} +1 -1
- package/dist/plugin-sdk/.boundary-entry-shims.stamp +1 -1
- package/dist/plugin-sdk/{agent-harness-runtime-CgQiThzm.d.ts → agent-harness-runtime-Bkrjji63.d.ts} +2 -2
- package/dist/plugin-sdk/agent-harness-runtime.d.ts +4 -4
- package/dist/plugin-sdk/agent-harness-task-runtime.d.ts +1 -1
- package/dist/plugin-sdk/agent-harness.d.ts +4 -4
- package/dist/plugin-sdk/agent-runtime.d.ts +1 -1
- package/dist/plugin-sdk/{bundled-channel-config-schema-Dfn3b8sF.d.ts → bundled-channel-config-schema-ZTBQez8k.d.ts} +9 -9
- package/dist/plugin-sdk/bundled-channel-config-schema.d.ts +1 -1
- package/dist/plugin-sdk/channel-config-schema-legacy.d.ts +1 -1
- package/dist/plugin-sdk/channel-core.d.ts +2 -2
- package/dist/plugin-sdk/channel-entry-contract.d.ts +1 -1
- package/dist/plugin-sdk/{channel-pairing-CX6ncj1r.d.ts → channel-pairing-CzsPAHgH.d.ts} +1 -1
- package/dist/plugin-sdk/channel-pairing.d.ts +1 -1
- package/dist/plugin-sdk/channel-plugin-common.d.ts +2 -2
- package/dist/plugin-sdk/cli-backend.d.ts +1 -1
- package/dist/plugin-sdk/compat.d.ts +4 -4
- package/dist/plugin-sdk/{config-schema-DuJUjn6k.d.ts → config-schema-N64y7n8C.d.ts} +1 -1
- package/dist/plugin-sdk/config-schema.d.ts +4 -4
- package/dist/plugin-sdk/{core-CPtu2Ftl.d.ts → core-BWZB2hNB.d.ts} +1 -1
- package/dist/plugin-sdk/core.d.ts +7 -7
- package/dist/plugin-sdk/{delegate-uk6vAMkc.d.ts → delegate-o5xckIuc.d.ts} +1 -1
- package/dist/plugin-sdk/discord.d.ts +3 -3
- package/dist/plugin-sdk/{fengming-runtime-Dt2ZEVYX.d.ts → fengming-runtime-abXAXyq2.d.ts} +1 -1
- package/dist/plugin-sdk/gateway-runtime.d.ts +1 -1
- package/dist/plugin-sdk/{host-compat-CM0h9ODw.d.ts → host-compat-D2Ky8seZ.d.ts} +1 -1
- package/dist/plugin-sdk/{http-registry-BniL_epL.d.ts → http-registry-oxJbX3E-.d.ts} +2 -2
- package/dist/plugin-sdk/image-generation-core.d.ts +4 -4
- package/dist/plugin-sdk/image-generation-runtime.d.ts +3 -3
- package/dist/plugin-sdk/index.d.ts +4 -4
- package/dist/plugin-sdk/lmstudio.d.ts +1 -1
- package/dist/plugin-sdk/{loader-aELh60PE.d.ts → loader-CgJhYjxT.d.ts} +3 -3
- package/dist/plugin-sdk/{logger-BpB3--7Z.d.ts → logger-CyDIBtoX.d.ts} +1 -1
- package/dist/plugin-sdk/logging-core.d.ts +3 -3
- package/dist/plugin-sdk/memory-core-host-engine-embeddings.d.ts +2 -2
- package/dist/plugin-sdk/memory-core-host-engine-foundation.d.ts +3 -3
- package/dist/plugin-sdk/{memory-core-host-engine-storage-DYPjOQCg.d.ts → memory-core-host-engine-storage-DfW7ZqD0.d.ts} +1 -1
- package/dist/plugin-sdk/memory-core-host-engine-storage.d.ts +1 -1
- package/dist/plugin-sdk/memory-core-host-runtime-cli.d.ts +1 -1
- package/dist/plugin-sdk/memory-core-host-runtime-core.d.ts +3 -3
- package/dist/plugin-sdk/memory-core.d.ts +3 -3
- package/dist/plugin-sdk/memory-host-core.d.ts +3 -3
- package/dist/plugin-sdk/migration-runtime.d.ts +1 -1
- package/dist/plugin-sdk/migration.d.ts +1 -1
- package/dist/plugin-sdk/music-generation-core.d.ts +2 -2
- package/dist/plugin-sdk/{plugin-entry-DO9kQeTr.d.ts → plugin-entry-C9xM-ZA9.d.ts} +1 -1
- package/dist/plugin-sdk/plugin-entry.d.ts +3 -3
- package/dist/plugin-sdk/plugin-runtime.d.ts +3 -3
- package/dist/plugin-sdk/{provider-api-key-auth-DvIiojS6.d.ts → provider-api-key-auth-DOmYPTC2.d.ts} +1 -1
- package/dist/plugin-sdk/provider-auth-api-key.d.ts +4 -4
- package/dist/plugin-sdk/{provider-auth-helpers-CYkWZ0vq.d.ts → provider-auth-helpers-pqDNrZTd.d.ts} +1 -1
- package/dist/plugin-sdk/{provider-auth-input-DUV6ZTw4.d.ts → provider-auth-input-Ckt-cU4H.d.ts} +1 -1
- package/dist/plugin-sdk/provider-auth-result.d.ts +1 -1
- package/dist/plugin-sdk/provider-auth-runtime.d.ts +1 -1
- package/dist/plugin-sdk/provider-auth.d.ts +5 -5
- package/dist/plugin-sdk/provider-catalog-runtime.d.ts +2 -2
- package/dist/plugin-sdk/{provider-catalog-shared-Cm3SyFfL.d.ts → provider-catalog-shared-QvOT8Wz1.d.ts} +1 -1
- package/dist/plugin-sdk/provider-catalog-shared.d.ts +2 -2
- package/dist/plugin-sdk/provider-entry.d.ts +3 -3
- package/dist/plugin-sdk/{provider-model-shared-D5rgn7Gb.d.ts → provider-model-shared-Bnc8IMx5.d.ts} +1 -1
- package/dist/plugin-sdk/provider-model-shared.d.ts +2 -2
- package/dist/plugin-sdk/{provider-registry-DxdZT9UN.d.ts → provider-registry-Ba1nNfhA.d.ts} +1 -1
- package/dist/plugin-sdk/{provider-registry-DiKX35tc.d.ts → provider-registry-CqB5bSAD.d.ts} +1 -1
- package/dist/plugin-sdk/{provider-registry-D0vmhPWL.d.ts → provider-registry-CxdVib8g.d.ts} +1 -1
- package/dist/plugin-sdk/{provider-self-hosted-setup-BPx7JMDC.d.ts → provider-self-hosted-setup-eMoeVPnF.d.ts} +1 -1
- package/dist/plugin-sdk/provider-setup.d.ts +2 -2
- package/dist/plugin-sdk/{provider-stream-DcC2vn_N.d.ts → provider-stream-CGaLae9n.d.ts} +1 -1
- package/dist/plugin-sdk/provider-stream-family.d.ts +2 -2
- package/dist/plugin-sdk/{provider-stream-shared-ByDv3QKm.d.ts → provider-stream-shared-u5mt-8_i.d.ts} +1 -1
- package/dist/plugin-sdk/provider-stream-shared.d.ts +1 -1
- package/dist/plugin-sdk/provider-stream.d.ts +2 -2
- package/dist/plugin-sdk/provider-tools.d.ts +1 -1
- package/dist/plugin-sdk/provider-web-fetch-contract.d.ts +1 -1
- package/dist/plugin-sdk/provider-web-fetch.d.ts +1 -1
- package/dist/plugin-sdk/provider-web-search-config-contract.d.ts +2 -2
- package/dist/plugin-sdk/{provider-web-search-contract-fields-CY4v8kS-.d.ts → provider-web-search-contract-fields-BiWOSs_d.d.ts} +1 -1
- package/dist/plugin-sdk/provider-web-search-contract.d.ts +2 -2
- package/dist/plugin-sdk/provider-web-search.d.ts +1 -1
- package/dist/plugin-sdk/realtime-transcription.d.ts +1 -1
- package/dist/plugin-sdk/realtime-voice.d.ts +1 -1
- package/dist/plugin-sdk/{redact-identifier-CVwkabcI.d.ts → redact-identifier-CVqsKaEK.d.ts} +1 -1
- package/dist/plugin-sdk/{registry-CzaGoAKH.d.ts → registry-Gq9OFlb3.d.ts} +2 -2
- package/dist/plugin-sdk/{registry-types-DN1yiH3F.d.ts → registry-types-DyBkef1H.d.ts} +2 -2
- package/dist/plugin-sdk/reply-runtime.d.ts +1 -1
- package/dist/plugin-sdk/runtime-env.d.ts +3 -3
- package/dist/plugin-sdk/runtime-store.d.ts +1 -1
- package/dist/plugin-sdk/runtime.d.ts +3 -3
- package/dist/plugin-sdk/self-hosted-provider-setup.d.ts +2 -2
- package/dist/plugin-sdk/simple-completion-runtime.d.ts +1 -1
- package/dist/plugin-sdk/speech-core.d.ts +2 -2
- package/dist/plugin-sdk/speech.d.ts +2 -2
- package/dist/plugin-sdk/{subsystem-n4Y4vCcQ.d.ts → subsystem-Boo2DQIV.d.ts} +1 -1
- package/dist/plugin-sdk/text-runtime.d.ts +2 -2
- package/dist/plugin-sdk/tool-plugin.d.ts +2 -2
- package/dist/plugin-sdk/{types-BI8R-vGd.d.ts → types-DGF1KeaJ.d.ts} +2 -2
- package/dist/plugin-sdk/{types-CsqNt0j8.d.ts → types-DpaN54PS.d.ts} +1 -1
- package/dist/plugin-sdk/{unhandled-rejections-D9eBl3hT.d.ts → unhandled-rejections-Bez6JG0y.d.ts} +2 -2
- package/dist/plugin-sdk/video-generation-core.d.ts +3 -3
- package/dist/plugin-sdk/video-generation-runtime.d.ts +3 -3
- package/dist/plugin-sdk/webhook-ingress.d.ts +1 -1
- package/dist/plugin-sdk/webhook-targets.d.ts +1 -1
- package/dist/{program-D19g2jaa.js → program-BaCHjV-F.js} +1 -1
- package/dist/{register.crestodian-BhIukKDA.js → register.crestodian-DMJEPMf3.js} +1 -1
- package/dist/register.subclis-B0BgjwyK.js +3 -0
- package/dist/{register.subclis-DVk0HU4k.js → register.subclis-BuoWG93n.js} +2 -2
- package/dist/{register.subclis-core-BK7nVvl6.js → register.subclis-core-BGBFrWE3.js} +2 -2
- package/dist/{standalone-CHrieUsw.js → standalone-CV2Ud6F7.js} +1 -1
- package/dist/tui-Bvt7hhwe.js +3 -0
- package/dist/tui-CFSmzhsm.js +2 -0
- package/dist/{tui-backend-_Pn3Byj-.js → tui-backend-Bm_t5G7x.js} +4 -4
- package/dist/{tui-cli-CAiC39zd.js → tui-cli-9Ny23hmo.js} +1 -1
- package/dist/tui-ink-run-CuExfFLV.js +2 -0
- package/dist/{tui-ink-run-ChXEGj1h.js → tui-ink-run-qNL49iQn.js} +17 -1
- package/package.json +6 -410
- package/CHANGELOG.md +0 -42
- package/THIRD_PARTY_NOTICES.md +0 -37
- package/dist/register.subclis-Bsvdh8RI.js +0 -3
- package/dist/tui-C733Qov0.js +0 -2
- package/dist/tui-DqbscVN5.js +0 -3
- package/dist/tui-ink-run-D4mSfLHj.js +0 -2
- package/docs/.i18n/README.md +0 -81
- package/docs/.i18n/ar-navigation.json +0 -18
- package/docs/.i18n/de-navigation.json +0 -18
- package/docs/.i18n/es-navigation.json +0 -18
- package/docs/.i18n/fr-navigation.json +0 -18
- package/docs/.i18n/glossary.ar.json +0 -78
- package/docs/.i18n/glossary.de.json +0 -78
- package/docs/.i18n/glossary.es.json +0 -78
- package/docs/.i18n/glossary.fa.json +0 -78
- package/docs/.i18n/glossary.fr.json +0 -78
- package/docs/.i18n/glossary.id.json +0 -78
- package/docs/.i18n/glossary.it.json +0 -78
- package/docs/.i18n/glossary.ja-JP.json +0 -98
- package/docs/.i18n/glossary.ko.json +0 -78
- package/docs/.i18n/glossary.nl.json +0 -78
- package/docs/.i18n/glossary.pl.json +0 -78
- package/docs/.i18n/glossary.pt-BR.json +0 -78
- package/docs/.i18n/glossary.th.json +0 -78
- package/docs/.i18n/glossary.tr.json +0 -78
- package/docs/.i18n/glossary.uk.json +0 -78
- package/docs/.i18n/glossary.vi.json +0 -78
- package/docs/.i18n/glossary.zh-CN.json +0 -1122
- package/docs/.i18n/glossary.zh-TW.json +0 -78
- package/docs/.i18n/id-navigation.json +0 -18
- package/docs/.i18n/it-navigation.json +0 -18
- package/docs/.i18n/ja-navigation.json +0 -18
- package/docs/.i18n/ko-navigation.json +0 -18
- package/docs/.i18n/pl-navigation.json +0 -18
- package/docs/.i18n/pt-BR-navigation.json +0 -18
- package/docs/.i18n/tr-navigation.json +0 -18
- package/docs/.i18n/translation-workflow.md +0 -111
- package/docs/.i18n/zh-Hans-navigation.json +0 -552
- package/docs/AGENTS.md +0 -36
- package/docs/CLAUDE.md +0 -1
- package/docs/agent-runtime-architecture.md +0 -48
- package/docs/announcements/bluebubbles-imessage.md +0 -79
- package/docs/auth-credential-semantics.md +0 -124
- package/docs/automation/auth-monitoring.md +0 -11
- package/docs/automation/clawflow.md +0 -12
- package/docs/automation/cron-jobs.md +0 -534
- package/docs/automation/cron-vs-heartbeat.md +0 -11
- package/docs/automation/gmail-pubsub.md +0 -11
- package/docs/automation/hooks.md +0 -387
- package/docs/automation/index.md +0 -135
- package/docs/automation/poll.md +0 -12
- package/docs/automation/standing-orders.md +0 -250
- package/docs/automation/taskflow.md +0 -155
- package/docs/automation/tasks.md +0 -374
- package/docs/automation/troubleshooting.md +0 -12
- package/docs/automation/webhook.md +0 -12
- package/docs/brave-search.md +0 -11
- package/docs/channels/access-groups.md +0 -201
- package/docs/channels/ambient-room-events.md +0 -214
- package/docs/channels/bot-loop-protection.md +0 -131
- package/docs/channels/broadcast-groups.md +0 -472
- package/docs/channels/channel-routing.md +0 -162
- package/docs/channels/clickclack.md +0 -138
- package/docs/channels/discord.md +0 -1758
- package/docs/channels/feishu.md +0 -650
- package/docs/channels/googlechat.md +0 -284
- package/docs/channels/group-messages.md +0 -95
- package/docs/channels/groups.md +0 -524
- package/docs/channels/imessage-from-bluebubbles.md +0 -259
- package/docs/channels/imessage.md +0 -839
- package/docs/channels/index.md +0 -64
- package/docs/channels/irc.md +0 -253
- package/docs/channels/line.md +0 -243
- package/docs/channels/location.md +0 -71
- package/docs/channels/matrix-migration.md +0 -370
- package/docs/channels/matrix-presentation.md +0 -77
- package/docs/channels/matrix-push-rules.md +0 -150
- package/docs/channels/matrix.md +0 -921
- package/docs/channels/mattermost.md +0 -542
- package/docs/channels/msteams.md +0 -1096
- package/docs/channels/nextcloud-talk.md +0 -176
- package/docs/channels/nostr.md +0 -253
- package/docs/channels/pairing.md +0 -214
- package/docs/channels/qqbot.md +0 -314
- package/docs/channels/signal.md +0 -417
- package/docs/channels/slack.md +0 -1623
- package/docs/channels/synology-chat.md +0 -187
- package/docs/channels/telegram.md +0 -1124
- package/docs/channels/tlon.md +0 -296
- package/docs/channels/troubleshooting.md +0 -162
- package/docs/channels/twitch.md +0 -431
- package/docs/channels/wechat.md +0 -171
- package/docs/channels/whatsapp.md +0 -796
- package/docs/channels/yuanbao.md +0 -416
- package/docs/channels/zalo.md +0 -253
- package/docs/channels/zalouser.md +0 -217
- package/docs/ci.md +0 -657
- package/docs/clawhub/publishing.md +0 -96
- package/docs/cli/acp.md +0 -370
- package/docs/cli/agent.md +0 -109
- package/docs/cli/agents.md +0 -253
- package/docs/cli/approvals.md +0 -190
- package/docs/cli/backup.md +0 -98
- package/docs/cli/browser.md +0 -307
- package/docs/cli/channels.md +0 -154
- package/docs/cli/clawbot.md +0 -25
- package/docs/cli/commitments.md +0 -90
- package/docs/cli/completion.md +0 -39
- package/docs/cli/config.md +0 -504
- package/docs/cli/configure.md +0 -77
- package/docs/cli/crestodian.md +0 -337
- package/docs/cli/cron.md +0 -304
- package/docs/cli/daemon.md +0 -67
- package/docs/cli/dashboard.md +0 -33
- package/docs/cli/devices.md +0 -240
- package/docs/cli/directory.md +0 -68
- package/docs/cli/dns.md +0 -53
- package/docs/cli/docs.md +0 -63
- package/docs/cli/doctor.md +0 -241
- package/docs/cli/flows.md +0 -52
- package/docs/cli/gateway.md +0 -572
- package/docs/cli/health.md +0 -43
- package/docs/cli/hooks.md +0 -345
- package/docs/cli/index.md +0 -400
- package/docs/cli/infer.md +0 -364
- package/docs/cli/logs.md +0 -68
- package/docs/cli/mcp.md +0 -529
- package/docs/cli/memory.md +0 -183
- package/docs/cli/message.md +0 -317
- package/docs/cli/migrate.md +0 -334
- package/docs/cli/models.md +0 -239
- package/docs/cli/node.md +0 -177
- package/docs/cli/nodes.md +0 -76
- package/docs/cli/onboard.md +0 -250
- package/docs/cli/pairing.md +0 -77
- package/docs/cli/path.md +0 -511
- package/docs/cli/plugins.md +0 -459
- package/docs/cli/policy.md +0 -886
- package/docs/cli/proxy.md +0 -89
- package/docs/cli/qr.md +0 -56
- package/docs/cli/reset.md +0 -39
- package/docs/cli/sandbox.md +0 -208
- package/docs/cli/secrets.md +0 -202
- package/docs/cli/security.md +0 -136
- package/docs/cli/sessions.md +0 -164
- package/docs/cli/setup.md +0 -59
- package/docs/cli/skills.md +0 -122
- package/docs/cli/status.md +0 -45
- package/docs/cli/system.md +0 -89
- package/docs/cli/tasks.md +0 -111
- package/docs/cli/transcripts.md +0 -151
- package/docs/cli/tui.md +0 -91
- package/docs/cli/uninstall.md +0 -44
- package/docs/cli/update.md +0 -243
- package/docs/cli/voicecall.md +0 -204
- package/docs/cli/webhooks.md +0 -117
- package/docs/cli/wiki.md +0 -256
- package/docs/concepts/active-memory.md +0 -856
- package/docs/concepts/agent-loop.md +0 -185
- package/docs/concepts/agent-runtimes.md +0 -276
- package/docs/concepts/agent-workspace.md +0 -230
- package/docs/concepts/agent.md +0 -140
- package/docs/concepts/architecture.md +0 -154
- package/docs/concepts/channel-docking.md +0 -145
- package/docs/concepts/commitments.md +0 -150
- package/docs/concepts/compaction.md +0 -203
- package/docs/concepts/context-engine.md +0 -347
- package/docs/concepts/context.md +0 -199
- package/docs/concepts/delegate-architecture.md +0 -319
- package/docs/concepts/dreaming.md +0 -264
- package/docs/concepts/experimental-features.md +0 -109
- package/docs/concepts/features.md +0 -91
- package/docs/concepts/fengming-sdk.md +0 -323
- package/docs/concepts/mantis-slack-desktop-runbook.md +0 -231
- package/docs/concepts/mantis.md +0 -744
- package/docs/concepts/markdown-formatting.md +0 -139
- package/docs/concepts/memory-builtin.md +0 -148
- package/docs/concepts/memory-honcho.md +0 -144
- package/docs/concepts/memory-qmd.md +0 -271
- package/docs/concepts/memory-search.md +0 -167
- package/docs/concepts/memory.md +0 -299
- package/docs/concepts/message-lifecycle-refactor.md +0 -1126
- package/docs/concepts/messages.md +0 -214
- package/docs/concepts/model-failover.md +0 -384
- package/docs/concepts/model-providers.md +0 -719
- package/docs/concepts/models.md +0 -371
- package/docs/concepts/multi-agent.md +0 -625
- package/docs/concepts/oauth.md +0 -198
- package/docs/concepts/parallel-specialist-lanes.md +0 -127
- package/docs/concepts/personal-agent-benchmark-pack.md +0 -74
- package/docs/concepts/presence.md +0 -117
- package/docs/concepts/progress-drafts.md +0 -406
- package/docs/concepts/qa-e2e-automation.md +0 -947
- package/docs/concepts/qa-matrix.md +0 -139
- package/docs/concepts/queue-steering.md +0 -90
- package/docs/concepts/queue.md +0 -136
- package/docs/concepts/retry.md +0 -86
- package/docs/concepts/session-pruning.md +0 -104
- package/docs/concepts/session-tool.md +0 -188
- package/docs/concepts/session.md +0 -164
- package/docs/concepts/soul.md +0 -116
- package/docs/concepts/streaming.md +0 -257
- package/docs/concepts/system-prompt.md +0 -328
- package/docs/concepts/timezone.md +0 -47
- package/docs/concepts/typebox.md +0 -309
- package/docs/concepts/typing-indicators.md +0 -88
- package/docs/concepts/usage-tracking.md +0 -66
- package/docs/date-time.md +0 -126
- package/docs/debug/node-issue.md +0 -90
- package/docs/diagnostics/flags.md +0 -182
- package/docs/docs.json +0 -1862
- package/docs/fengming-agent-runtime.md +0 -82
- package/docs/gateway/authentication.md +0 -256
- package/docs/gateway/background-process.md +0 -147
- package/docs/gateway/bonjour.md +0 -303
- package/docs/gateway/bridge-protocol.md +0 -97
- package/docs/gateway/cli-backends.md +0 -439
- package/docs/gateway/config-agents.md +0 -1525
- package/docs/gateway/config-channels.md +0 -945
- package/docs/gateway/config-tools.md +0 -774
- package/docs/gateway/configuration-examples.md +0 -704
- package/docs/gateway/configuration-reference.md +0 -1391
- package/docs/gateway/configuration.md +0 -739
- package/docs/gateway/diagnostics.md +0 -213
- package/docs/gateway/discovery.md +0 -154
- package/docs/gateway/doctor.md +0 -575
- package/docs/gateway/gateway-lock.md +0 -37
- package/docs/gateway/health.md +0 -73
- package/docs/gateway/heartbeat.md +0 -498
- package/docs/gateway/index.md +0 -383
- package/docs/gateway/local-model-services.md +0 -205
- package/docs/gateway/local-models.md +0 -355
- package/docs/gateway/logging.md +0 -149
- package/docs/gateway/multiple-gateways.md +0 -178
- package/docs/gateway/network-model.md +0 -15
- package/docs/gateway/openai-http-api.md +0 -378
- package/docs/gateway/openresponses-http-api.md +0 -347
- package/docs/gateway/openshell.md +0 -316
- package/docs/gateway/opentelemetry.md +0 -433
- package/docs/gateway/operator-scopes.md +0 -119
- package/docs/gateway/pairing.md +0 -207
- package/docs/gateway/prometheus.md +0 -249
- package/docs/gateway/protocol.md +0 -826
- package/docs/gateway/remote-gateway-readme.md +0 -169
- package/docs/gateway/remote.md +0 -280
- package/docs/gateway/sandbox-vs-tool-policy-vs-elevated.md +0 -148
- package/docs/gateway/sandboxing.md +0 -546
- package/docs/gateway/secrets-plan-contract.md +0 -159
- package/docs/gateway/secrets.md +0 -805
- package/docs/gateway/security/audit-checks.md +0 -127
- package/docs/gateway/security/exposure-runbook.md +0 -212
- package/docs/gateway/security/index.md +0 -1343
- package/docs/gateway/security/secure-file-operations.md +0 -76
- package/docs/gateway/security/shrinkwrap.md +0 -111
- package/docs/gateway/tailscale.md +0 -156
- package/docs/gateway/tools-invoke-http-api.md +0 -169
- package/docs/gateway/troubleshooting.md +0 -877
- package/docs/gateway/trusted-proxy-auth.md +0 -483
- package/docs/help/debugging.md +0 -341
- package/docs/help/environment.md +0 -233
- package/docs/help/faq-first-run.md +0 -870
- package/docs/help/faq-models.md +0 -556
- package/docs/help/faq.md +0 -2041
- package/docs/help/index.md +0 -39
- package/docs/help/scripts.md +0 -56
- package/docs/help/testing-live.md +0 -587
- package/docs/help/testing-updates-plugins.md +0 -299
- package/docs/help/testing.md +0 -977
- package/docs/help/troubleshooting.md +0 -449
- package/docs/index.md +0 -196
- package/docs/install/ansible.md +0 -233
- package/docs/install/azure.md +0 -315
- package/docs/install/bun.md +0 -59
- package/docs/install/clawdock.md +0 -112
- package/docs/install/development-channels.md +0 -148
- package/docs/install/digitalocean.md +0 -174
- package/docs/install/docker-vm-runtime.md +0 -154
- package/docs/install/docker.md +0 -564
- package/docs/install/exe-dev.md +0 -201
- package/docs/install/fly.md +0 -524
- package/docs/install/gcp.md +0 -418
- package/docs/install/hetzner.md +0 -285
- package/docs/install/hostinger.md +0 -98
- package/docs/install/index.md +0 -232
- package/docs/install/installer.md +0 -447
- package/docs/install/kubernetes.md +0 -196
- package/docs/install/macos-vm.md +0 -281
- package/docs/install/migrating-claude.md +0 -165
- package/docs/install/migrating-hermes.md +0 -178
- package/docs/install/migrating.md +0 -137
- package/docs/install/nix.md +0 -112
- package/docs/install/node.md +0 -142
- package/docs/install/northflank.mdx +0 -44
- package/docs/install/oracle.md +0 -218
- package/docs/install/podman.md +0 -216
- package/docs/install/railway.mdx +0 -92
- package/docs/install/raspberry-pi.md +0 -234
- package/docs/install/render.mdx +0 -167
- package/docs/install/uninstall.md +0 -131
- package/docs/install/updating.md +0 -284
- package/docs/install/upstash.md +0 -96
- package/docs/logging.md +0 -320
- package/docs/nav-tabs-underline.js +0 -100
- package/docs/network.md +0 -72
- package/docs/nodes/audio.md +0 -216
- package/docs/nodes/camera.md +0 -166
- package/docs/nodes/images.md +0 -77
- package/docs/nodes/index.md +0 -439
- package/docs/nodes/location-command.md +0 -102
- package/docs/nodes/media-understanding.md +0 -495
- package/docs/nodes/talk.md +0 -160
- package/docs/nodes/troubleshooting.md +0 -123
- package/docs/nodes/voicewake.md +0 -93
- package/docs/perplexity.md +0 -11
- package/docs/plan/codex-context-engine-harness.md +0 -624
- package/docs/plan/ui-channels.md +0 -284
- package/docs/platforms/digitalocean.md +0 -12
- package/docs/platforms/easyrunner.md +0 -109
- package/docs/platforms/index.md +0 -51
- package/docs/platforms/linux.md +0 -141
- package/docs/platforms/mac/bundled-gateway.md +0 -79
- package/docs/platforms/mac/canvas.md +0 -128
- package/docs/platforms/mac/child-process.md +0 -72
- package/docs/platforms/mac/dev-setup.md +0 -112
- package/docs/platforms/mac/health.md +0 -39
- package/docs/platforms/mac/icon.md +0 -36
- package/docs/platforms/mac/logging.md +0 -62
- package/docs/platforms/mac/menu-bar.md +0 -93
- package/docs/platforms/mac/peekaboo.md +0 -96
- package/docs/platforms/mac/permissions.md +0 -73
- package/docs/platforms/mac/remote.md +0 -123
- package/docs/platforms/mac/signing.md +0 -52
- package/docs/platforms/mac/skills.md +0 -43
- package/docs/platforms/mac/voice-overlay.md +0 -66
- package/docs/platforms/mac/voicewake.md +0 -73
- package/docs/platforms/mac/webchat.md +0 -54
- package/docs/platforms/mac/xpc.md +0 -66
- package/docs/platforms/oracle.md +0 -12
- package/docs/platforms/raspberry-pi.md +0 -13
- package/docs/platforms/windows.md +0 -286
- package/docs/plugins/adding-capabilities.md +0 -146
- package/docs/plugins/admin-http-rpc.md +0 -216
- package/docs/plugins/agent-tools.md +0 -13
- package/docs/plugins/architecture-internals.md +0 -1196
- package/docs/plugins/architecture.md +0 -483
- package/docs/plugins/building-extensions.md +0 -13
- package/docs/plugins/building-plugins.md +0 -335
- package/docs/plugins/bundles.md +0 -310
- package/docs/plugins/cli-backend-plugins.md +0 -310
- package/docs/plugins/codex-computer-use.md +0 -297
- package/docs/plugins/codex-harness-reference.md +0 -470
- package/docs/plugins/codex-harness-runtime.md +0 -268
- package/docs/plugins/codex-harness.md +0 -780
- package/docs/plugins/codex-native-plugins.md +0 -276
- package/docs/plugins/community.md +0 -77
- package/docs/plugins/compatibility.md +0 -167
- package/docs/plugins/copilot.md +0 -356
- package/docs/plugins/dependency-resolution.md +0 -176
- package/docs/plugins/google-meet.md +0 -1737
- package/docs/plugins/hooks.md +0 -484
- package/docs/plugins/install-overrides.md +0 -80
- package/docs/plugins/manage-plugins.md +0 -210
- package/docs/plugins/manifest.md +0 -1457
- package/docs/plugins/memory-lancedb.md +0 -385
- package/docs/plugins/memory-wiki.md +0 -529
- package/docs/plugins/message-presentation.md +0 -473
- package/docs/plugins/oc-path.md +0 -166
- package/docs/plugins/plugin-inventory.md +0 -189
- package/docs/plugins/plugin-permission-requests.md +0 -193
- package/docs/plugins/reference/acpx.md +0 -23
- package/docs/plugins/reference/admin-http-rpc.md +0 -23
- package/docs/plugins/reference/alibaba.md +0 -23
- package/docs/plugins/reference/amazon-bedrock-mantle.md +0 -23
- package/docs/plugins/reference/amazon-bedrock.md +0 -23
- package/docs/plugins/reference/anthropic-vertex.md +0 -19
- package/docs/plugins/reference/anthropic.md +0 -23
- package/docs/plugins/reference/arcee.md +0 -23
- package/docs/plugins/reference/azure-speech.md +0 -23
- package/docs/plugins/reference/bonjour.md +0 -19
- package/docs/plugins/reference/brave.md +0 -23
- package/docs/plugins/reference/browser.md +0 -23
- package/docs/plugins/reference/byteplus.md +0 -19
- package/docs/plugins/reference/canvas.md +0 -19
- package/docs/plugins/reference/cerebras.md +0 -23
- package/docs/plugins/reference/chutes.md +0 -23
- package/docs/plugins/reference/clickclack.md +0 -23
- package/docs/plugins/reference/cloudflare-ai-gateway.md +0 -23
- package/docs/plugins/reference/codex-supervisor.md +0 -27
- package/docs/plugins/reference/codex.md +0 -23
- package/docs/plugins/reference/comfy.md +0 -23
- package/docs/plugins/reference/copilot-proxy.md +0 -19
- package/docs/plugins/reference/copilot.md +0 -23
- package/docs/plugins/reference/deepgram.md +0 -23
- package/docs/plugins/reference/deepinfra.md +0 -23
- package/docs/plugins/reference/deepseek.md +0 -23
- package/docs/plugins/reference/diagnostics-otel.md +0 -19
- package/docs/plugins/reference/diagnostics-prometheus.md +0 -19
- package/docs/plugins/reference/diffs-language-pack.md +0 -19
- package/docs/plugins/reference/diffs.md +0 -19
- package/docs/plugins/reference/discord.md +0 -23
- package/docs/plugins/reference/document-extract.md +0 -23
- package/docs/plugins/reference/duckduckgo.md +0 -23
- package/docs/plugins/reference/elevenlabs.md +0 -23
- package/docs/plugins/reference/exa.md +0 -23
- package/docs/plugins/reference/fal.md +0 -23
- package/docs/plugins/reference/feishu.md +0 -23
- package/docs/plugins/reference/file-transfer.md +0 -19
- package/docs/plugins/reference/firecrawl.md +0 -23
- package/docs/plugins/reference/fireworks.md +0 -23
- package/docs/plugins/reference/github-copilot.md +0 -23
- package/docs/plugins/reference/gmi.md +0 -23
- package/docs/plugins/reference/google-meet.md +0 -23
- package/docs/plugins/reference/google.md +0 -23
- package/docs/plugins/reference/googlechat.md +0 -23
- package/docs/plugins/reference/gradium.md +0 -23
- package/docs/plugins/reference/groq.md +0 -23
- package/docs/plugins/reference/huggingface.md +0 -23
- package/docs/plugins/reference/imessage.md +0 -23
- package/docs/plugins/reference/inworld.md +0 -23
- package/docs/plugins/reference/irc.md +0 -23
- package/docs/plugins/reference/kilocode.md +0 -23
- package/docs/plugins/reference/kimi.md +0 -23
- package/docs/plugins/reference/line.md +0 -23
- package/docs/plugins/reference/litellm.md +0 -23
- package/docs/plugins/reference/llm-task.md +0 -19
- package/docs/plugins/reference/lmstudio.md +0 -23
- package/docs/plugins/reference/lobster.md +0 -19
- package/docs/plugins/reference/matrix.md +0 -23
- package/docs/plugins/reference/mattermost.md +0 -23
- package/docs/plugins/reference/memory-core.md +0 -19
- package/docs/plugins/reference/memory-lancedb.md +0 -23
- package/docs/plugins/reference/memory-wiki.md +0 -23
- package/docs/plugins/reference/microsoft-foundry.md +0 -19
- package/docs/plugins/reference/microsoft.md +0 -19
- package/docs/plugins/reference/migrate-claude.md +0 -19
- package/docs/plugins/reference/migrate-hermes.md +0 -19
- package/docs/plugins/reference/minimax.md +0 -23
- package/docs/plugins/reference/mistral.md +0 -23
- package/docs/plugins/reference/moonshot.md +0 -23
- package/docs/plugins/reference/msteams.md +0 -23
- package/docs/plugins/reference/nextcloud-talk.md +0 -23
- package/docs/plugins/reference/nostr.md +0 -23
- package/docs/plugins/reference/novita.md +0 -23
- package/docs/plugins/reference/nvidia.md +0 -23
- package/docs/plugins/reference/oc-path.md +0 -23
- package/docs/plugins/reference/ollama.md +0 -23
- package/docs/plugins/reference/open-prose.md +0 -19
- package/docs/plugins/reference/openai.md +0 -23
- package/docs/plugins/reference/opencode-go.md +0 -23
- package/docs/plugins/reference/opencode.md +0 -23
- package/docs/plugins/reference/openrouter.md +0 -23
- package/docs/plugins/reference/openshell.md +0 -19
- package/docs/plugins/reference/perplexity.md +0 -23
- package/docs/plugins/reference/pixverse.md +0 -23
- package/docs/plugins/reference/policy.md +0 -72
- package/docs/plugins/reference/qa-channel.md +0 -23
- package/docs/plugins/reference/qa-lab.md +0 -19
- package/docs/plugins/reference/qa-matrix.md +0 -19
- package/docs/plugins/reference/qianfan.md +0 -23
- package/docs/plugins/reference/qqbot.md +0 -23
- package/docs/plugins/reference/qwen.md +0 -23
- package/docs/plugins/reference/runway.md +0 -23
- package/docs/plugins/reference/searxng.md +0 -19
- package/docs/plugins/reference/senseaudio.md +0 -23
- package/docs/plugins/reference/sglang.md +0 -23
- package/docs/plugins/reference/signal.md +0 -23
- package/docs/plugins/reference/skill-workshop.md +0 -23
- package/docs/plugins/reference/slack.md +0 -23
- package/docs/plugins/reference/stepfun.md +0 -23
- package/docs/plugins/reference/synology-chat.md +0 -23
- package/docs/plugins/reference/synthetic.md +0 -23
- package/docs/plugins/reference/tavily.md +0 -23
- package/docs/plugins/reference/telegram.md +0 -23
- package/docs/plugins/reference/tencent.md +0 -23
- package/docs/plugins/reference/tlon.md +0 -23
- package/docs/plugins/reference/together.md +0 -23
- package/docs/plugins/reference/tokenjuice.md +0 -23
- package/docs/plugins/reference/tts-local-cli.md +0 -19
- package/docs/plugins/reference/twitch.md +0 -23
- package/docs/plugins/reference/venice.md +0 -23
- package/docs/plugins/reference/vercel-ai-gateway.md +0 -23
- package/docs/plugins/reference/vllm.md +0 -23
- package/docs/plugins/reference/voice-call.md +0 -23
- package/docs/plugins/reference/volcengine.md +0 -23
- package/docs/plugins/reference/voyage.md +0 -19
- package/docs/plugins/reference/vydra.md +0 -23
- package/docs/plugins/reference/web-readability.md +0 -19
- package/docs/plugins/reference/webhooks.md +0 -23
- package/docs/plugins/reference/whatsapp.md +0 -23
- package/docs/plugins/reference/workboard.md +0 -23
- package/docs/plugins/reference/xai.md +0 -23
- package/docs/plugins/reference/xiaomi.md +0 -23
- package/docs/plugins/reference/zai.md +0 -23
- package/docs/plugins/reference/zalo.md +0 -23
- package/docs/plugins/reference/zalouser.md +0 -24
- package/docs/plugins/reference.md +0 -145
- package/docs/plugins/sdk-agent-harness.md +0 -338
- package/docs/plugins/sdk-channel-inbound.md +0 -70
- package/docs/plugins/sdk-channel-ingress.md +0 -137
- package/docs/plugins/sdk-channel-message.md +0 -18
- package/docs/plugins/sdk-channel-outbound.md +0 -113
- package/docs/plugins/sdk-channel-plugins.md +0 -765
- package/docs/plugins/sdk-channel-turn.md +0 -9
- package/docs/plugins/sdk-entrypoints.md +0 -344
- package/docs/plugins/sdk-migration.md +0 -979
- package/docs/plugins/sdk-overview.md +0 -511
- package/docs/plugins/sdk-provider-plugins.md +0 -846
- package/docs/plugins/sdk-runtime.md +0 -676
- package/docs/plugins/sdk-setup.md +0 -550
- package/docs/plugins/sdk-subpaths.md +0 -391
- package/docs/plugins/sdk-testing.md +0 -403
- package/docs/plugins/skill-workshop.md +0 -713
- package/docs/plugins/tool-plugins.md +0 -411
- package/docs/plugins/voice-call.md +0 -942
- package/docs/plugins/webhooks.md +0 -192
- package/docs/plugins/workboard.md +0 -252
- package/docs/plugins/zalouser.md +0 -86
- package/docs/prose.md +0 -137
- package/docs/providers/alibaba.md +0 -158
- package/docs/providers/anthropic.md +0 -381
- package/docs/providers/arcee.md +0 -144
- package/docs/providers/azure-speech.md +0 -119
- package/docs/providers/bedrock-mantle.md +0 -211
- package/docs/providers/bedrock.md +0 -414
- package/docs/providers/cerebras.md +0 -130
- package/docs/providers/chutes.md +0 -153
- package/docs/providers/claude-max-api-proxy.md +0 -191
- package/docs/providers/cloudflare-ai-gateway.md +0 -119
- package/docs/providers/comfy.md +0 -362
- package/docs/providers/deepgram.md +0 -184
- package/docs/providers/deepinfra.md +0 -92
- package/docs/providers/deepseek.md +0 -146
- package/docs/providers/ds4.md +0 -309
- package/docs/providers/elevenlabs.md +0 -130
- package/docs/providers/fal.md +0 -240
- package/docs/providers/fireworks.md +0 -144
- package/docs/providers/github-copilot.md +0 -257
- package/docs/providers/gmi.md +0 -92
- package/docs/providers/google.md +0 -472
- package/docs/providers/gradium.md +0 -123
- package/docs/providers/groq.md +0 -171
- package/docs/providers/huggingface.md +0 -235
- package/docs/providers/index.md +0 -105
- package/docs/providers/inferrs.md +0 -272
- package/docs/providers/inworld.md +0 -120
- package/docs/providers/kilocode.md +0 -135
- package/docs/providers/litellm.md +0 -234
- package/docs/providers/lmstudio.md +0 -224
- package/docs/providers/minimax.md +0 -505
- package/docs/providers/mistral.md +0 -235
- package/docs/providers/models.md +0 -64
- package/docs/providers/moonshot.md +0 -413
- package/docs/providers/novita.md +0 -92
- package/docs/providers/nvidia.md +0 -158
- package/docs/providers/ollama-cloud.md +0 -115
- package/docs/providers/ollama.md +0 -1225
- package/docs/providers/openai.md +0 -1093
- package/docs/providers/opencode-go.md +0 -123
- package/docs/providers/opencode.md +0 -149
- package/docs/providers/openrouter.md +0 -349
- package/docs/providers/perplexity-provider.md +0 -123
- package/docs/providers/pixverse.md +0 -165
- package/docs/providers/qianfan.md +0 -132
- package/docs/providers/qwen-oauth.md +0 -115
- package/docs/providers/qwen.md +0 -364
- package/docs/providers/runway.md +0 -103
- package/docs/providers/senseaudio.md +0 -68
- package/docs/providers/sglang.md +0 -161
- package/docs/providers/stepfun.md +0 -229
- package/docs/providers/synthetic.md +0 -154
- package/docs/providers/tencent.md +0 -130
- package/docs/providers/together.md +0 -140
- package/docs/providers/venice.md +0 -312
- package/docs/providers/vercel-ai-gateway.md +0 -128
- package/docs/providers/vllm.md +0 -407
- package/docs/providers/volcengine.md +0 -199
- package/docs/providers/vydra.md +0 -180
- package/docs/providers/xai.md +0 -571
- package/docs/providers/xiaomi.md +0 -262
- package/docs/providers/zai.md +0 -224
- package/docs/refactor/access.md +0 -9
- package/docs/refactor/acp.md +0 -298
- package/docs/refactor/canvas.md +0 -131
- package/docs/refactor/database-first.md +0 -2256
- package/docs/refactor/ingress-core.md +0 -341
- package/docs/reference/AGENTS.default.md +0 -131
- package/docs/reference/RELEASING.md +0 -799
- package/docs/reference/api-usage-costs.md +0 -208
- package/docs/reference/application-modernization-plan.md +0 -208
- package/docs/reference/code-mode.md +0 -773
- package/docs/reference/credits.md +0 -33
- package/docs/reference/device-models.md +0 -50
- package/docs/reference/fengming-sdk-api-design.md +0 -390
- package/docs/reference/full-release-validation.md +0 -202
- package/docs/reference/memory-config.md +0 -604
- package/docs/reference/prompt-caching.md +0 -358
- package/docs/reference/release-performance-sweep.md +0 -360
- package/docs/reference/rich-output-protocol.md +0 -101
- package/docs/reference/rpc.md +0 -43
- package/docs/reference/secret-placeholder-conventions.md +0 -33
- package/docs/reference/secretref-credential-surface.md +0 -159
- package/docs/reference/secretref-user-supplied-credentials-matrix.json +0 -663
- package/docs/reference/session-management-compaction.md +0 -474
- package/docs/reference/templates/AGENTS.dev.md +0 -90
- package/docs/reference/templates/AGENTS.md +0 -227
- package/docs/reference/templates/BOOT.md +0 -16
- package/docs/reference/templates/BOOTSTRAP.md +0 -66
- package/docs/reference/templates/CLAUDE.md +0 -1
- package/docs/reference/templates/HEARTBEAT.md +0 -24
- package/docs/reference/templates/IDENTITY.dev.md +0 -52
- package/docs/reference/templates/IDENTITY.md +0 -34
- package/docs/reference/templates/SOUL.dev.md +0 -82
- package/docs/reference/templates/SOUL.md +0 -49
- package/docs/reference/templates/TOOLS.dev.md +0 -29
- package/docs/reference/templates/TOOLS.md +0 -51
- package/docs/reference/templates/USER.dev.md +0 -23
- package/docs/reference/templates/USER.md +0 -28
- package/docs/reference/test.md +0 -247
- package/docs/reference/token-use.md +0 -246
- package/docs/reference/transcript-hygiene.md +0 -214
- package/docs/reference/wizard.md +0 -252
- package/docs/security/CONTRIBUTING-THREAT-MODEL.md +0 -101
- package/docs/security/THREAT-MODEL-ATLAS.md +0 -611
- package/docs/security/formal-verification.md +0 -170
- package/docs/security/incident-response.md +0 -59
- package/docs/security/network-proxy.md +0 -268
- package/docs/snippets/plugin-publish/minimal-fengming.plugin.json +0 -12
- package/docs/snippets/plugin-publish/minimal-package.json +0 -16
- package/docs/specs/claw-supervisor.md +0 -247
- package/docs/start/bootstrapping.md +0 -49
- package/docs/start/docs-directory.md +0 -69
- package/docs/start/fengming.md +0 -252
- package/docs/start/getting-started.md +0 -152
- package/docs/start/hubs.md +0 -201
- package/docs/start/lore.md +0 -223
- package/docs/start/onboarding-overview.md +0 -72
- package/docs/start/onboarding.md +0 -98
- package/docs/start/quickstart.md +0 -25
- package/docs/start/setup.md +0 -178
- package/docs/start/showcase.md +0 -363
- package/docs/start/wizard-cli-automation.md +0 -232
- package/docs/start/wizard-cli-reference.md +0 -331
- package/docs/start/wizard.md +0 -141
- package/docs/style.css +0 -137
- package/docs/superpowers/specs/2026-04-22-tweakcn-custom-theme-import-design.md +0 -316
- package/docs/tools/acp-agents-setup.md +0 -351
- package/docs/tools/acp-agents.md +0 -854
- package/docs/tools/agent-send.md +0 -130
- package/docs/tools/apply-patch.md +0 -64
- package/docs/tools/brave-search.md +0 -139
- package/docs/tools/browser-control.md +0 -391
- package/docs/tools/browser-linux-troubleshooting.md +0 -173
- package/docs/tools/browser-login.md +0 -77
- package/docs/tools/browser-wsl2-windows-remote-cdp-troubleshooting.md +0 -219
- package/docs/tools/browser.md +0 -810
- package/docs/tools/btw.md +0 -159
- package/docs/tools/capability-cookbook.md +0 -12
- package/docs/tools/clawhub.md +0 -5
- package/docs/tools/code-execution.md +0 -173
- package/docs/tools/creating-skills.md +0 -158
- package/docs/tools/diffs.md +0 -525
- package/docs/tools/duckduckgo-search.md +0 -109
- package/docs/tools/elevated.md +0 -128
- package/docs/tools/exa-search.md +0 -152
- package/docs/tools/exec-approvals-advanced.md +0 -444
- package/docs/tools/exec-approvals.md +0 -494
- package/docs/tools/exec.md +0 -285
- package/docs/tools/firecrawl.md +0 -155
- package/docs/tools/gemini-search.md +0 -114
- package/docs/tools/goal.md +0 -217
- package/docs/tools/grok-search.md +0 -129
- package/docs/tools/image-generation.md +0 -493
- package/docs/tools/index.md +0 -178
- package/docs/tools/kimi-search.md +0 -105
- package/docs/tools/llm-task.md +0 -137
- package/docs/tools/lobster.md +0 -365
- package/docs/tools/loop-detection.md +0 -154
- package/docs/tools/media-overview.md +0 -160
- package/docs/tools/minimax-search.md +0 -102
- package/docs/tools/multi-agent-sandbox-tools.md +0 -409
- package/docs/tools/music-generation.md +0 -372
- package/docs/tools/ollama-search.md +0 -153
- package/docs/tools/pdf.md +0 -213
- package/docs/tools/perplexity-search.md +0 -220
- package/docs/tools/plugin.md +0 -363
- package/docs/tools/reactions.md +0 -100
- package/docs/tools/searxng-search.md +0 -141
- package/docs/tools/skills-config.md +0 -195
- package/docs/tools/skills.md +0 -569
- package/docs/tools/slash-commands.md +0 -487
- package/docs/tools/steer.md +0 -77
- package/docs/tools/subagents.md +0 -651
- package/docs/tools/tavily.md +0 -162
- package/docs/tools/thinking.md +0 -142
- package/docs/tools/tokenjuice.md +0 -84
- package/docs/tools/tool-search.md +0 -269
- package/docs/tools/trajectory.md +0 -229
- package/docs/tools/tts.md +0 -1009
- package/docs/tools/video-generation.md +0 -555
- package/docs/tools/web-fetch.md +0 -210
- package/docs/tools/web.md +0 -461
- package/docs/tts.md +0 -11
- package/docs/vps.md +0 -139
- package/docs/web/control-ui.md +0 -512
- package/docs/web/dashboard.md +0 -107
- package/docs/web/index.md +0 -133
- package/docs/web/tui.md +0 -250
- package/docs/web/webchat.md +0 -102
- package/npm-shrinkwrap.json +0 -12861
- package/patches/.gitkeep +0 -0
- package/patches/@agentclientprotocol__claude-agent-acp@0.37.0.patch +0 -41
- package/pnpm-workspace.yaml +0 -120
- package/scripts/crabbox-wrapper.mjs +0 -2004
- package/scripts/lib/official-external-channel-catalog.json +0 -560
- package/scripts/lib/official-external-plugin-catalog.json +0 -264
- package/scripts/lib/official-external-provider-catalog.json +0 -158
- package/scripts/lib/package-dist-imports.mjs +0 -171
- package/scripts/npm-runner.mjs +0 -91
- package/scripts/postinstall-bundled-plugins.mjs +0 -978
- package/scripts/preinstall-package-manager-warning.mjs +0 -64
- package/scripts/prepare-git-hooks.mjs +0 -72
- package/scripts/windows-cmd-helpers.mjs +0 -22
- package/skills/batch/SKILL.md +0 -118
- package/skills/code-review/SKILL.md +0 -107
- package/skills/debug/SKILL.md +0 -83
- package/skills/loop/SKILL.md +0 -118
- package/skills/run/SKILL.md +0 -79
- package/skills/run-skill-generator/SKILL.md +0 -179
- package/skills/verify/SKILL.md +0 -103
- package/src/agents/templates/HEARTBEAT.md +0 -3
|
@@ -1,2004 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
3
|
-
import {
|
|
4
|
-
accessSync,
|
|
5
|
-
chmodSync,
|
|
6
|
-
constants,
|
|
7
|
-
cpSync,
|
|
8
|
-
mkdirSync,
|
|
9
|
-
mkdtempSync,
|
|
10
|
-
readFileSync,
|
|
11
|
-
readdirSync,
|
|
12
|
-
rmSync,
|
|
13
|
-
statSync,
|
|
14
|
-
writeFileSync,
|
|
15
|
-
} from "node:fs";
|
|
16
|
-
import { tmpdir } from "node:os";
|
|
17
|
-
import { delimiter, dirname, extname, isAbsolute, relative, resolve } from "node:path";
|
|
18
|
-
import { fileURLToPath } from "node:url";
|
|
19
|
-
import { resolvePathEnvKey } from "./windows-cmd-helpers.mjs";
|
|
20
|
-
|
|
21
|
-
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
|
|
22
|
-
const ignoreRepoBinary = process.env.FENGMING_CRABBOX_WRAPPER_IGNORE_REPO_BINARY === "1";
|
|
23
|
-
const repoLocal = ignoreRepoBinary ? null : resolveCrabboxBinary(process.env, process.platform);
|
|
24
|
-
const pathLocal = resolvePathBinary("crabbox", process.env, process.platform);
|
|
25
|
-
const binary =
|
|
26
|
-
repoLocal ??
|
|
27
|
-
pathLocal ??
|
|
28
|
-
resolveGitCommonCrabboxBinary(process.env, process.platform) ??
|
|
29
|
-
"crabbox";
|
|
30
|
-
const args = process.argv.slice(2);
|
|
31
|
-
|
|
32
|
-
if (args[0] === "--") {
|
|
33
|
-
args.shift();
|
|
34
|
-
}
|
|
35
|
-
const userArgStart = args[0] === "actions" && args[1] === "hydrate" ? 2 : 1;
|
|
36
|
-
if (args[userArgStart] === "--") {
|
|
37
|
-
args.splice(userArgStart, 1);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function commandCandidates(command, platform) {
|
|
41
|
-
if (platform !== "win32") {
|
|
42
|
-
return [command];
|
|
43
|
-
}
|
|
44
|
-
if (extname(command)) {
|
|
45
|
-
return [command];
|
|
46
|
-
}
|
|
47
|
-
return [`${command}.exe`, `${command}.cmd`, `${command}.bat`, `${command}.com`, command];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function resolveCrabboxBinary(env, platform) {
|
|
51
|
-
const base = resolve(repoRoot, "../crabbox/bin/crabbox");
|
|
52
|
-
for (const candidate of commandCandidates(base, platform)) {
|
|
53
|
-
if (isExecutableFile(candidate, platform)) {
|
|
54
|
-
return candidate;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function resolvePathBinary(command, env, platform) {
|
|
61
|
-
const pathValue = env[resolvePathEnvKey(env)] ?? "";
|
|
62
|
-
for (const dir of pathValue.split(delimiter).filter(Boolean)) {
|
|
63
|
-
for (const candidate of commandCandidates(command, platform)) {
|
|
64
|
-
const fullPath = resolve(dir, candidate);
|
|
65
|
-
if (isExecutableFile(fullPath, platform)) {
|
|
66
|
-
return fullPath;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function resolveGitCommonCrabboxBinary(env, platform) {
|
|
74
|
-
const gitBinary = resolvePathBinary("git", env, platform) ?? "git";
|
|
75
|
-
const invocation = spawnInvocation(gitBinary, ["rev-parse", "--git-common-dir"], env, platform);
|
|
76
|
-
const result = spawnSync(invocation.command, invocation.args, {
|
|
77
|
-
cwd: repoRoot,
|
|
78
|
-
encoding: "utf8",
|
|
79
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
80
|
-
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
|
81
|
-
});
|
|
82
|
-
if ((result.status ?? 1) !== 0) {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
const gitCommonDir = result.stdout.trim();
|
|
86
|
-
if (!gitCommonDir) {
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
const absoluteGitCommonDir = isAbsolute(gitCommonDir)
|
|
90
|
-
? gitCommonDir
|
|
91
|
-
: resolve(repoRoot, gitCommonDir);
|
|
92
|
-
const base = resolve(absoluteGitCommonDir, "../..", "crabbox/bin/crabbox");
|
|
93
|
-
for (const candidate of commandCandidates(base, platform)) {
|
|
94
|
-
if (isExecutableFile(candidate, platform)) {
|
|
95
|
-
return candidate;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function isExecutableFile(path, platform) {
|
|
102
|
-
try {
|
|
103
|
-
if (!statSync(path).isFile()) {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
if (platform !== "win32") {
|
|
107
|
-
accessSync(path, constants.X_OK);
|
|
108
|
-
}
|
|
109
|
-
return true;
|
|
110
|
-
} catch {
|
|
111
|
-
return false;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function spawnInvocation(command, commandArgs, env, platform) {
|
|
116
|
-
const extension = extname(command).toLowerCase();
|
|
117
|
-
if (platform === "win32" && (extension === ".cmd" || extension === ".bat")) {
|
|
118
|
-
return {
|
|
119
|
-
command: env.ComSpec ?? "cmd.exe",
|
|
120
|
-
args: ["/d", "/s", "/c", buildBatchCommandLine(command, commandArgs)],
|
|
121
|
-
windowsVerbatimArguments: true,
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
return { command, args: commandArgs };
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const cmdMetaCharactersRe = /([()\][%!^"`<>&|;, *?])/g;
|
|
128
|
-
const jsRuntimeEntrypoints = new Set(["pnpm", "npm", "npx", "corepack", "node", "yarn", "bun"]);
|
|
129
|
-
const awsMacosCorepackEntrypoints = new Set(["pnpm", "yarn", "corepack"]);
|
|
130
|
-
const shellControlCommandPrefixes = new Set([
|
|
131
|
-
"if",
|
|
132
|
-
"while",
|
|
133
|
-
"until",
|
|
134
|
-
"then",
|
|
135
|
-
"do",
|
|
136
|
-
"else",
|
|
137
|
-
"elif",
|
|
138
|
-
"!",
|
|
139
|
-
]);
|
|
140
|
-
const shellCommandExecutionPrefixes = new Set(["exec"]);
|
|
141
|
-
const shellInlineCommandInterpreters = new Set(["bash", "dash", "ksh", "sh", "zsh"]);
|
|
142
|
-
const shellInlineCommandOptionsWithNextValue = new Set([
|
|
143
|
-
"+O",
|
|
144
|
-
"+o",
|
|
145
|
-
"-O",
|
|
146
|
-
"-o",
|
|
147
|
-
"--init-file",
|
|
148
|
-
"--rcfile",
|
|
149
|
-
]);
|
|
150
|
-
|
|
151
|
-
function escapeBatchCommand(command) {
|
|
152
|
-
return `${command}`.replace(cmdMetaCharactersRe, "^$1");
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function escapeBatchArgument(arg) {
|
|
156
|
-
let escaped = `${arg}`;
|
|
157
|
-
escaped = escaped.replace(/(?=(\\+?)?)\1"/g, '$1$1\\"');
|
|
158
|
-
escaped = escaped.replace(/(?=(\\+?)?)\1$/, "$1$1");
|
|
159
|
-
escaped = `"${escaped}"`;
|
|
160
|
-
escaped = escaped.replace(cmdMetaCharactersRe, "^$1");
|
|
161
|
-
return escaped.replace(cmdMetaCharactersRe, "^$1");
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function buildBatchCommandLine(command, commandArgs) {
|
|
165
|
-
const escapedCommand = escapeBatchCommand(command);
|
|
166
|
-
const escapedArgs = commandArgs.map(escapeBatchArgument);
|
|
167
|
-
return `"${[escapedCommand, ...escapedArgs].join(" ")}"`;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function checkedOutput(command, commandArgs) {
|
|
171
|
-
const invocation = spawnInvocation(command, commandArgs, process.env, process.platform);
|
|
172
|
-
const result = spawnSync(invocation.command, invocation.args, {
|
|
173
|
-
cwd: repoRoot,
|
|
174
|
-
encoding: "utf8",
|
|
175
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
176
|
-
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
|
177
|
-
});
|
|
178
|
-
return {
|
|
179
|
-
status: result.status ?? 1,
|
|
180
|
-
text: `${result.stdout ?? ""}${result.stderr ?? ""}`.trim(),
|
|
181
|
-
stdout: (result.stdout ?? "").trim(),
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function gitOutput(commandArgs) {
|
|
186
|
-
const gitBinary = resolvePathBinary("git", process.env, process.platform) ?? "git";
|
|
187
|
-
const invocation = spawnInvocation(gitBinary, commandArgs, process.env, process.platform);
|
|
188
|
-
const result = spawnSync(invocation.command, invocation.args, {
|
|
189
|
-
cwd: repoRoot,
|
|
190
|
-
encoding: "utf8",
|
|
191
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
192
|
-
windowsVerbatimArguments: invocation.windowsVerbatimArguments,
|
|
193
|
-
});
|
|
194
|
-
return {
|
|
195
|
-
status: result.status ?? 1,
|
|
196
|
-
text: `${result.stdout ?? ""}${result.stderr ?? ""}`.trim(),
|
|
197
|
-
stdout: (result.stdout ?? "").trim(),
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function envProvider() {
|
|
202
|
-
const envProvider = process.env.CRABBOX_PROVIDER?.trim();
|
|
203
|
-
if (envProvider) {
|
|
204
|
-
return envProvider;
|
|
205
|
-
}
|
|
206
|
-
return "";
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function configProvider() {
|
|
210
|
-
try {
|
|
211
|
-
const config = readFileSync(resolve(repoRoot, ".crabbox.yaml"), "utf8");
|
|
212
|
-
const match = config.match(/^provider:\s*([^\s#]+)/m);
|
|
213
|
-
return match?.[1] ?? "aws";
|
|
214
|
-
} catch {
|
|
215
|
-
return "aws";
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function configuredProvider() {
|
|
220
|
-
return envProvider() || configProvider();
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const runValueOptions = new Set([
|
|
224
|
-
"allow-env",
|
|
225
|
-
"artifact-glob",
|
|
226
|
-
"azure-location",
|
|
227
|
-
"azure-os-disk",
|
|
228
|
-
"azure-resource-group",
|
|
229
|
-
"azure-subnet",
|
|
230
|
-
"azure-vnet",
|
|
231
|
-
"blacksmith-job",
|
|
232
|
-
"blacksmith-org",
|
|
233
|
-
"blacksmith-ref",
|
|
234
|
-
"blacksmith-workflow",
|
|
235
|
-
"capture-stderr",
|
|
236
|
-
"capture-stdout",
|
|
237
|
-
"class",
|
|
238
|
-
"cloudflare-url",
|
|
239
|
-
"cloudflare-workdir",
|
|
240
|
-
"daytona-api-url",
|
|
241
|
-
"daytona-snapshot",
|
|
242
|
-
"daytona-ssh-access-minutes",
|
|
243
|
-
"daytona-ssh-gateway-host",
|
|
244
|
-
"daytona-target",
|
|
245
|
-
"daytona-user",
|
|
246
|
-
"daytona-work-root",
|
|
247
|
-
"download",
|
|
248
|
-
"env-from-profile",
|
|
249
|
-
"env-helper",
|
|
250
|
-
"e2b-api-url",
|
|
251
|
-
"e2b-domain",
|
|
252
|
-
"e2b-template",
|
|
253
|
-
"e2b-user",
|
|
254
|
-
"e2b-workdir",
|
|
255
|
-
"fresh-pr",
|
|
256
|
-
"id",
|
|
257
|
-
"idle-timeout",
|
|
258
|
-
"islo-base-url",
|
|
259
|
-
"islo-disk-gb",
|
|
260
|
-
"islo-gateway-profile",
|
|
261
|
-
"islo-image",
|
|
262
|
-
"islo-memory-mb",
|
|
263
|
-
"islo-snapshot-name",
|
|
264
|
-
"islo-vcpus",
|
|
265
|
-
"islo-workdir",
|
|
266
|
-
"junit",
|
|
267
|
-
"label",
|
|
268
|
-
"market",
|
|
269
|
-
"modal-app",
|
|
270
|
-
"modal-image",
|
|
271
|
-
"modal-python",
|
|
272
|
-
"modal-workdir",
|
|
273
|
-
"namespace-auto-stop-idle-timeout",
|
|
274
|
-
"namespace-image",
|
|
275
|
-
"namespace-repository",
|
|
276
|
-
"namespace-site",
|
|
277
|
-
"namespace-size",
|
|
278
|
-
"namespace-volume-size-gb",
|
|
279
|
-
"namespace-work-root",
|
|
280
|
-
"network",
|
|
281
|
-
"preflight-tools",
|
|
282
|
-
"profile",
|
|
283
|
-
"proof-template",
|
|
284
|
-
"provider",
|
|
285
|
-
"proxmox-api-url",
|
|
286
|
-
"proxmox-bridge",
|
|
287
|
-
"proxmox-node",
|
|
288
|
-
"proxmox-pool",
|
|
289
|
-
"proxmox-storage",
|
|
290
|
-
"proxmox-template-id",
|
|
291
|
-
"proxmox-user",
|
|
292
|
-
"proxmox-work-root",
|
|
293
|
-
"script",
|
|
294
|
-
"scenario",
|
|
295
|
-
"semaphore-host",
|
|
296
|
-
"semaphore-idle-timeout",
|
|
297
|
-
"semaphore-machine",
|
|
298
|
-
"semaphore-os-image",
|
|
299
|
-
"semaphore-project",
|
|
300
|
-
"sprites-api-url",
|
|
301
|
-
"sprites-work-root",
|
|
302
|
-
"static-host",
|
|
303
|
-
"static-port",
|
|
304
|
-
"static-user",
|
|
305
|
-
"static-work-root",
|
|
306
|
-
"stop-after",
|
|
307
|
-
"tailscale-auth-key-env",
|
|
308
|
-
"tailscale-exit-node",
|
|
309
|
-
"tailscale-hostname-template",
|
|
310
|
-
"tailscale-tags",
|
|
311
|
-
"target",
|
|
312
|
-
"tensorlake-api-url",
|
|
313
|
-
"tensorlake-cli",
|
|
314
|
-
"tensorlake-cpus",
|
|
315
|
-
"tensorlake-disk-mb",
|
|
316
|
-
"tensorlake-image",
|
|
317
|
-
"tensorlake-memory-mb",
|
|
318
|
-
"tensorlake-namespace",
|
|
319
|
-
"tensorlake-organization-id",
|
|
320
|
-
"tensorlake-project-id",
|
|
321
|
-
"tensorlake-snapshot",
|
|
322
|
-
"tensorlake-timeout-secs",
|
|
323
|
-
"tensorlake-workdir",
|
|
324
|
-
"ttl",
|
|
325
|
-
"type",
|
|
326
|
-
"emit-proof",
|
|
327
|
-
"preset",
|
|
328
|
-
"preset-var",
|
|
329
|
-
"windows-mode",
|
|
330
|
-
]);
|
|
331
|
-
|
|
332
|
-
let runValueOptionsFromHelp;
|
|
333
|
-
|
|
334
|
-
function parseRunValueOptionsFromHelp(text) {
|
|
335
|
-
const names = new Set();
|
|
336
|
-
for (const line of text.split(/\r?\n/u)) {
|
|
337
|
-
const match = line.match(
|
|
338
|
-
/^\s+-{1,2}([a-z0-9][a-z0-9-]*)\s+(?:string|duration|int|float|value)\b/u,
|
|
339
|
-
);
|
|
340
|
-
if (match) {
|
|
341
|
-
names.add(match[1]);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
return names;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function currentRunValueOptions() {
|
|
348
|
-
if (!runValueOptionsFromHelp) {
|
|
349
|
-
runValueOptionsFromHelp = new Set([
|
|
350
|
-
...runValueOptions,
|
|
351
|
-
...parseRunValueOptionsFromHelp(help.text),
|
|
352
|
-
]);
|
|
353
|
-
}
|
|
354
|
-
return runValueOptionsFromHelp;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
function runOptionName(arg) {
|
|
358
|
-
return arg.replace(/^-+/u, "").split("=", 1)[0];
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function runCommandBounds(commandArgs) {
|
|
362
|
-
if (commandArgs[0] !== "run") {
|
|
363
|
-
return { start: -1, optionEnd: commandArgs.length };
|
|
364
|
-
}
|
|
365
|
-
for (let index = 1; index < commandArgs.length; index += 1) {
|
|
366
|
-
const arg = commandArgs[index];
|
|
367
|
-
if (arg === "--") {
|
|
368
|
-
return { start: index + 1, optionEnd: index };
|
|
369
|
-
}
|
|
370
|
-
if (!arg.startsWith("-")) {
|
|
371
|
-
return { start: index, optionEnd: index };
|
|
372
|
-
}
|
|
373
|
-
if (!arg.includes("=") && currentRunValueOptions().has(runOptionName(arg))) {
|
|
374
|
-
index += 1;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return { start: -1, optionEnd: commandArgs.length };
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
function crabboxOptionArgs(commandArgs) {
|
|
381
|
-
const bounds = runCommandBounds(commandArgs);
|
|
382
|
-
if (commandArgs[0] === "run") {
|
|
383
|
-
return commandArgs.slice(0, bounds.optionEnd);
|
|
384
|
-
}
|
|
385
|
-
const delimiter = commandArgs.indexOf("--");
|
|
386
|
-
return delimiter >= 0 ? commandArgs.slice(0, delimiter) : commandArgs;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
function commandProvider(commandArgs) {
|
|
390
|
-
commandArgs = crabboxOptionArgs(commandArgs);
|
|
391
|
-
for (let index = 0; index < commandArgs.length; index += 1) {
|
|
392
|
-
const arg = commandArgs[index];
|
|
393
|
-
if (arg === "--provider" || arg === "-provider") {
|
|
394
|
-
return commandArgs[index + 1] ?? "";
|
|
395
|
-
}
|
|
396
|
-
if (arg.startsWith("--provider=") || arg.startsWith("-provider=")) {
|
|
397
|
-
return arg.slice(arg.indexOf("=") + 1);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
return "";
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
function selectedProvider(commandArgs, advertisedProviders = []) {
|
|
404
|
-
const explicitProvider = commandProvider(commandArgs);
|
|
405
|
-
if (explicitProvider) {
|
|
406
|
-
return explicitProvider;
|
|
407
|
-
}
|
|
408
|
-
if (shouldPreferAzureForWindows(commandArgs, advertisedProviders)) {
|
|
409
|
-
return "azure";
|
|
410
|
-
}
|
|
411
|
-
return configuredProvider();
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
function shouldRequireBrokeredAws(commandArgs, providerName) {
|
|
415
|
-
if (process.env.FENGMING_CRABBOX_ALLOW_DIRECT_AWS === "1") {
|
|
416
|
-
return false;
|
|
417
|
-
}
|
|
418
|
-
const canonicalProvider = providerAliases.get(providerName) ?? providerName;
|
|
419
|
-
if (canonicalProvider !== "aws") {
|
|
420
|
-
return false;
|
|
421
|
-
}
|
|
422
|
-
if (commandArgs[0] === "run" || commandArgs[0] === "warmup") {
|
|
423
|
-
return true;
|
|
424
|
-
}
|
|
425
|
-
return commandArgs[0] === "actions" && commandArgs[1] === "hydrate";
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
function brokerAuthConfigured() {
|
|
429
|
-
const config = checkedOutput(binary, ["config", "show", "--json"]);
|
|
430
|
-
if (config.status !== 0) {
|
|
431
|
-
return false;
|
|
432
|
-
}
|
|
433
|
-
let parsed;
|
|
434
|
-
try {
|
|
435
|
-
parsed = JSON.parse(config.stdout || config.text);
|
|
436
|
-
} catch {
|
|
437
|
-
return false;
|
|
438
|
-
}
|
|
439
|
-
return Boolean(parsed?.coordinator && parsed?.brokerAuth === "configured");
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
function enforceBrokeredAws(commandArgs, providerName) {
|
|
443
|
-
if (!shouldRequireBrokeredAws(commandArgs, providerName) || brokerAuthConfigured()) {
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
console.error(
|
|
447
|
-
[
|
|
448
|
-
"[crabbox] provider=aws requires a configured Crabbox broker for FengMing proof.",
|
|
449
|
-
"[crabbox] run `crabbox login --url https://crabbox.fengming.ai --provider aws`, then retry.",
|
|
450
|
-
"[crabbox] for intentional direct AWS provider debugging, set FENGMING_CRABBOX_ALLOW_DIRECT_AWS=1.",
|
|
451
|
-
].join("\n"),
|
|
452
|
-
);
|
|
453
|
-
process.exit(2);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
function optionValue(commandArgs, name) {
|
|
457
|
-
commandArgs = crabboxOptionArgs(commandArgs);
|
|
458
|
-
for (let index = 0; index < commandArgs.length; index += 1) {
|
|
459
|
-
const arg = commandArgs[index];
|
|
460
|
-
if (arg === name || arg === name.replace(/^--/u, "-")) {
|
|
461
|
-
return commandArgs[index + 1] ?? "";
|
|
462
|
-
}
|
|
463
|
-
if (arg.startsWith(`${name}=`) || arg.startsWith(`${name.replace(/^--/u, "-")}=`)) {
|
|
464
|
-
return arg.slice(arg.indexOf("=") + 1);
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
return "";
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
function hasOption(commandArgs, name) {
|
|
471
|
-
commandArgs = crabboxOptionArgs(commandArgs);
|
|
472
|
-
const shortName = name.replace(/^--/u, "-");
|
|
473
|
-
for (const arg of commandArgs) {
|
|
474
|
-
if (
|
|
475
|
-
arg === name ||
|
|
476
|
-
arg === shortName ||
|
|
477
|
-
arg.startsWith(`${name}=`) ||
|
|
478
|
-
arg.startsWith(`${shortName}=`)
|
|
479
|
-
) {
|
|
480
|
-
return true;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
return false;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
function commandOptionEnd(commandArgs) {
|
|
487
|
-
if (commandArgs[0] === "run") {
|
|
488
|
-
return runCommandBounds(commandArgs).optionEnd;
|
|
489
|
-
}
|
|
490
|
-
const delimiter = commandArgs.indexOf("--");
|
|
491
|
-
return delimiter >= 0 ? delimiter : commandArgs.length;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
function shouldPreferAzureForWindows(commandArgs, advertisedProviders = []) {
|
|
495
|
-
return (
|
|
496
|
-
["run", "warmup"].includes(commandArgs[0]) &&
|
|
497
|
-
isWindowsRemoteTarget(commandArgs) &&
|
|
498
|
-
!commandProvider(commandArgs) &&
|
|
499
|
-
!envProvider() &&
|
|
500
|
-
!hasOption(commandArgs, "--id") &&
|
|
501
|
-
advertisedProviders.includes("azure")
|
|
502
|
-
);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
function ensureAzureWindowsProvider(commandArgs, providerName, advertisedProviders = []) {
|
|
506
|
-
if (providerName !== "azure" || !shouldPreferAzureForWindows(commandArgs, advertisedProviders)) {
|
|
507
|
-
return commandArgs;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
const optionEnd = commandOptionEnd(commandArgs);
|
|
511
|
-
const normalizedArgs = [...commandArgs];
|
|
512
|
-
normalizedArgs.splice(optionEnd, 0, "--provider", "azure");
|
|
513
|
-
return normalizedArgs;
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
function ensureAwsMacOnDemandMarket(commandArgs, providerName) {
|
|
517
|
-
if (
|
|
518
|
-
!["run", "warmup"].includes(commandArgs[0]) ||
|
|
519
|
-
providerName !== "aws" ||
|
|
520
|
-
optionValue(commandArgs, "--target") !== "macos" ||
|
|
521
|
-
hasOption(commandArgs, "--market") ||
|
|
522
|
-
hasOption(commandArgs, "--id")
|
|
523
|
-
) {
|
|
524
|
-
return commandArgs;
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
const optionEnd = commandOptionEnd(commandArgs);
|
|
528
|
-
const normalizedArgs = [...commandArgs];
|
|
529
|
-
normalizedArgs.splice(optionEnd, 0, "--market", "on-demand");
|
|
530
|
-
return normalizedArgs;
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
const localPathRunOptions = new Set([
|
|
534
|
-
"capture-stderr",
|
|
535
|
-
"capture-stdout",
|
|
536
|
-
"emit-proof",
|
|
537
|
-
"env-from-profile",
|
|
538
|
-
"script",
|
|
539
|
-
]);
|
|
540
|
-
|
|
541
|
-
function repoRelativePath(value) {
|
|
542
|
-
if (!value || value === "-" || isAbsolute(value)) {
|
|
543
|
-
return value;
|
|
544
|
-
}
|
|
545
|
-
return resolve(repoRoot, value);
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
function repoRelativeDownload(value) {
|
|
549
|
-
const split = value.indexOf("=");
|
|
550
|
-
if (split < 0) {
|
|
551
|
-
return value;
|
|
552
|
-
}
|
|
553
|
-
const remote = value.slice(0, split + 1);
|
|
554
|
-
const local = value.slice(split + 1);
|
|
555
|
-
return `${remote}${repoRelativePath(local)}`;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
function absolutizeLocalRunPaths(commandArgs) {
|
|
559
|
-
if (commandArgs[0] !== "run") {
|
|
560
|
-
return commandArgs;
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
const normalizedArgs = [...commandArgs];
|
|
564
|
-
const { optionEnd } = runCommandBounds(normalizedArgs);
|
|
565
|
-
for (let index = 1; index < optionEnd; index += 1) {
|
|
566
|
-
const arg = normalizedArgs[index];
|
|
567
|
-
if (!arg.startsWith("-")) {
|
|
568
|
-
continue;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
const optionName = runOptionName(arg);
|
|
572
|
-
const absolutize = optionName === "download" ? repoRelativeDownload : repoRelativePath;
|
|
573
|
-
if (localPathRunOptions.has(optionName) || optionName === "download") {
|
|
574
|
-
const equals = arg.indexOf("=");
|
|
575
|
-
if (equals >= 0) {
|
|
576
|
-
normalizedArgs[index] = `${arg.slice(0, equals + 1)}${absolutize(arg.slice(equals + 1))}`;
|
|
577
|
-
} else if (index + 1 < optionEnd) {
|
|
578
|
-
normalizedArgs[index + 1] = absolutize(normalizedArgs[index + 1]);
|
|
579
|
-
index += 1;
|
|
580
|
-
}
|
|
581
|
-
continue;
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
if (!arg.includes("=") && currentRunValueOptions().has(optionName)) {
|
|
585
|
-
index += 1;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
return normalizedArgs;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
function pathExists(path) {
|
|
592
|
-
try {
|
|
593
|
-
statSync(path);
|
|
594
|
-
return true;
|
|
595
|
-
} catch {
|
|
596
|
-
return false;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
function preserveTemporaryCrabboxRuns() {
|
|
601
|
-
if (childCwd === repoRoot) {
|
|
602
|
-
return;
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
const sourceRuns = resolve(childCwd, ".crabbox", "runs");
|
|
606
|
-
if (!pathExists(sourceRuns)) {
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
const targetRuns = resolve(repoRoot, ".crabbox", "runs");
|
|
611
|
-
mkdirSync(targetRuns, { recursive: true });
|
|
612
|
-
let preserved = 0;
|
|
613
|
-
for (const entry of readdirSync(sourceRuns)) {
|
|
614
|
-
cpSync(resolve(sourceRuns, entry), resolve(targetRuns, entry), {
|
|
615
|
-
recursive: true,
|
|
616
|
-
force: true,
|
|
617
|
-
});
|
|
618
|
-
preserved += 1;
|
|
619
|
-
}
|
|
620
|
-
if (preserved > 0) {
|
|
621
|
-
console.error(
|
|
622
|
-
`[crabbox] preserved ${preserved} temporary run artifact ${preserved === 1 ? "directory" : "directories"} under ${relative(repoRoot, targetRuns)}`,
|
|
623
|
-
);
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
function shellQuote(value) {
|
|
628
|
-
const text = `${value}`;
|
|
629
|
-
if (text === "") {
|
|
630
|
-
return "''";
|
|
631
|
-
}
|
|
632
|
-
if (/^[A-Za-z0-9_./:=@%+-]+$/u.test(text)) {
|
|
633
|
-
return text;
|
|
634
|
-
}
|
|
635
|
-
return `'${text.replaceAll("'", "'\\''")}'`;
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
function shellJoin(commandArgs) {
|
|
639
|
-
return commandArgs.map(shellQuote).join(" ");
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
function isLocalContainerProvider(providerName) {
|
|
643
|
-
return ["local-container", "docker", "container", "local-docker"].includes(providerName);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
function runCommandArgs(commandArgs) {
|
|
647
|
-
const { start } = runCommandBounds(commandArgs);
|
|
648
|
-
return start >= 0 ? commandArgs.slice(start) : [];
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
function normalizedCommandWords(commandArgs) {
|
|
652
|
-
const words = commandArgs.length === 1 ? commandArgs[0].split(/\s+/u) : [...commandArgs];
|
|
653
|
-
while (/^[A-Za-z_][A-Za-z0-9_]*=/.test(words[0] ?? "")) {
|
|
654
|
-
words.shift();
|
|
655
|
-
}
|
|
656
|
-
return words.map((word) => word.replace(/^['"]|['";|&()]+$/g, ""));
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
function commandRuntimeEntrypoint(commandArgs) {
|
|
660
|
-
if (commandArgs.length === 1) {
|
|
661
|
-
for (const candidateWords of shellCommandWordCandidates(commandArgs[0])) {
|
|
662
|
-
const shellRuntime = commandWordsRuntimeEntrypoint(candidateWords);
|
|
663
|
-
if (shellRuntime) {
|
|
664
|
-
return shellRuntime;
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
return "";
|
|
668
|
-
}
|
|
669
|
-
const words = normalizedCommandWords(commandArgs);
|
|
670
|
-
const directRuntime = commandWordsRuntimeEntrypoint(words);
|
|
671
|
-
if (directRuntime) {
|
|
672
|
-
return directRuntime;
|
|
673
|
-
}
|
|
674
|
-
return "";
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
function commandWordsRuntimeEntrypoint(words) {
|
|
678
|
-
words = normalizeExecutableWords(words);
|
|
679
|
-
const first = (words[0] ?? "").split("/").pop();
|
|
680
|
-
if (jsRuntimeEntrypoints.has(first)) {
|
|
681
|
-
return first;
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
const inlineCommand = shellInlineCommand(words);
|
|
685
|
-
if (!inlineCommand) {
|
|
686
|
-
return "";
|
|
687
|
-
}
|
|
688
|
-
for (const candidateWords of shellCommandWordCandidates(inlineCommand)) {
|
|
689
|
-
const shellRuntime = commandWordsRuntimeEntrypoint(candidateWords);
|
|
690
|
-
if (shellRuntime) {
|
|
691
|
-
return shellRuntime;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
return "";
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
function commandNeedsAwsMacosPackageManager(commandArgs) {
|
|
698
|
-
if (isChangedGateCommand(commandArgs)) {
|
|
699
|
-
return true;
|
|
700
|
-
}
|
|
701
|
-
if (commandArgs.length === 1) {
|
|
702
|
-
return shellCommandWordCandidates(commandArgs[0]).some(commandWordsNeedAwsMacosPackageManager);
|
|
703
|
-
}
|
|
704
|
-
return commandWordsNeedAwsMacosPackageManager(normalizedCommandWords(commandArgs));
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
function commandWordsNeedAwsMacosPackageManager(words) {
|
|
708
|
-
words = normalizeExecutableWords(words);
|
|
709
|
-
const first = (words[0] ?? "").split("/").pop();
|
|
710
|
-
if (awsMacosCorepackEntrypoints.has(first)) {
|
|
711
|
-
return true;
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
const inlineCommand = shellInlineCommand(words);
|
|
715
|
-
if (!inlineCommand) {
|
|
716
|
-
return false;
|
|
717
|
-
}
|
|
718
|
-
return shellCommandWordCandidates(inlineCommand).some(commandWordsNeedAwsMacosPackageManager);
|
|
719
|
-
}
|
|
720
|
-
|
|
721
|
-
function isChangedGateCommand(commandArgs) {
|
|
722
|
-
if (commandArgs.length === 1) {
|
|
723
|
-
return shellCommandWordCandidates(commandArgs[0]).some(isChangedGateCommandWords);
|
|
724
|
-
}
|
|
725
|
-
const words = normalizedCommandWords(commandArgs);
|
|
726
|
-
return isChangedGateCommandWords(words);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
function isChangedGateCommandWords(words) {
|
|
730
|
-
words = normalizeExecutableWords(words);
|
|
731
|
-
if (isChangedGateWords(words)) {
|
|
732
|
-
return true;
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
const inlineCommand = shellInlineCommand(words);
|
|
736
|
-
return inlineCommand
|
|
737
|
-
? shellCommandWordCandidates(inlineCommand).some(isChangedGateCommandWords)
|
|
738
|
-
: false;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
function isChangedGateWords(words) {
|
|
742
|
-
words = normalizeExecutableWords(words);
|
|
743
|
-
if (words[0] === "corepack") {
|
|
744
|
-
words.shift();
|
|
745
|
-
}
|
|
746
|
-
return (
|
|
747
|
-
(words[0] === "pnpm" && words[1] === "check:changed") ||
|
|
748
|
-
(words[0] === "pnpm" && words[1] === "run" && words[2] === "check:changed") ||
|
|
749
|
-
(words[0] === "node" && (words[1] ?? "").endsWith("scripts/check-changed.mjs"))
|
|
750
|
-
);
|
|
751
|
-
}
|
|
752
|
-
|
|
753
|
-
function shellInlineCommand(words) {
|
|
754
|
-
const command = shellWordBasename(words[0]);
|
|
755
|
-
if (!shellInlineCommandInterpreters.has(command)) {
|
|
756
|
-
return "";
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
for (let index = 1; index < words.length; index += 1) {
|
|
760
|
-
const word = words[index];
|
|
761
|
-
if (word === "--") {
|
|
762
|
-
return "";
|
|
763
|
-
}
|
|
764
|
-
if (!word.startsWith("-") && !word.startsWith("+")) {
|
|
765
|
-
return "";
|
|
766
|
-
}
|
|
767
|
-
if (word === "-c" || /^-[^-]*c/u.test(word)) {
|
|
768
|
-
return words[index + 1] ?? "";
|
|
769
|
-
}
|
|
770
|
-
if (shellInlineCommandOptionConsumesNextValue(word)) {
|
|
771
|
-
index += 1;
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
return "";
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
function shellInlineCommandOptionConsumesNextValue(word) {
|
|
778
|
-
return shellInlineCommandOptionsWithNextValue.has(word) || /^[+-][^-+]*[oO]$/u.test(word);
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
function shellCommandWordCandidates(command) {
|
|
782
|
-
return shellCommandSegments(stripHeredocBodies(command.replace(/\\\r?\n/gu, " ")));
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
function pushShellCandidate(candidates, segment) {
|
|
786
|
-
const words = normalizedShellSegmentWords(segment);
|
|
787
|
-
if (words.length > 0) {
|
|
788
|
-
candidates.push(words);
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
function normalizedShellSegmentWords(segment) {
|
|
793
|
-
const trimmed = segment.trim().replace(/^[({]\s*/u, "");
|
|
794
|
-
if (!trimmed || trimmed.startsWith("#")) {
|
|
795
|
-
return [];
|
|
796
|
-
}
|
|
797
|
-
const words = normalizedCommandWords(splitShellWords(trimmed));
|
|
798
|
-
while (shellControlCommandPrefixes.has(words[0])) {
|
|
799
|
-
words.shift();
|
|
800
|
-
}
|
|
801
|
-
const normalizedWords = normalizedCommandWords(words);
|
|
802
|
-
return normalizedCommandWords(stripShellExecutionPrefixes(normalizedWords));
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
function normalizeExecutableWords(words) {
|
|
806
|
-
return normalizedCommandWords(stripShellExecutionPrefixes(words));
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
function stripShellExecutionPrefixes(words) {
|
|
810
|
-
words = [...words];
|
|
811
|
-
for (;;) {
|
|
812
|
-
const first = shellWordBasename(words[0]);
|
|
813
|
-
if (shellCommandExecutionPrefixes.has(first)) {
|
|
814
|
-
words.shift();
|
|
815
|
-
continue;
|
|
816
|
-
}
|
|
817
|
-
if (first === "command") {
|
|
818
|
-
words.shift();
|
|
819
|
-
if (!stripCommandBuiltinOptions(words)) {
|
|
820
|
-
return words;
|
|
821
|
-
}
|
|
822
|
-
continue;
|
|
823
|
-
}
|
|
824
|
-
if (first === "env") {
|
|
825
|
-
if (!stripEnvCommandOptions(words, { canShimIgnoreEnvironment: false })) {
|
|
826
|
-
return words;
|
|
827
|
-
}
|
|
828
|
-
continue;
|
|
829
|
-
}
|
|
830
|
-
if (first === "time") {
|
|
831
|
-
words.shift();
|
|
832
|
-
stripTimeOptions(words);
|
|
833
|
-
continue;
|
|
834
|
-
}
|
|
835
|
-
if (first === "timeout") {
|
|
836
|
-
stripTimeoutOptions(words);
|
|
837
|
-
continue;
|
|
838
|
-
}
|
|
839
|
-
return words;
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
function stripEnvCommandOptions(words, { canShimIgnoreEnvironment = true } = {}) {
|
|
844
|
-
const originalWords = [...words];
|
|
845
|
-
const envCommand = words.shift() ?? "";
|
|
846
|
-
let ignoresEnvironment = false;
|
|
847
|
-
for (;;) {
|
|
848
|
-
const word = words[0] ?? "";
|
|
849
|
-
if (!word) {
|
|
850
|
-
words.splice(0, words.length, ...originalWords);
|
|
851
|
-
return false;
|
|
852
|
-
}
|
|
853
|
-
if (word === "--") {
|
|
854
|
-
words.shift();
|
|
855
|
-
return true;
|
|
856
|
-
}
|
|
857
|
-
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(word)) {
|
|
858
|
-
words.shift();
|
|
859
|
-
continue;
|
|
860
|
-
}
|
|
861
|
-
if (word === "-S" || word === "--split-string") {
|
|
862
|
-
if (ignoresEnvironment) {
|
|
863
|
-
words.splice(0, words.length, ...originalWords);
|
|
864
|
-
return false;
|
|
865
|
-
}
|
|
866
|
-
words.shift();
|
|
867
|
-
const split = splitShellWords(words.shift() ?? "");
|
|
868
|
-
words.unshift(...split);
|
|
869
|
-
return words.length > 0;
|
|
870
|
-
}
|
|
871
|
-
if (word.startsWith("-S") && word !== "-S") {
|
|
872
|
-
if (ignoresEnvironment) {
|
|
873
|
-
words.splice(0, words.length, ...originalWords);
|
|
874
|
-
return false;
|
|
875
|
-
}
|
|
876
|
-
words.shift();
|
|
877
|
-
words.unshift(...splitShellWords(word.slice(2)));
|
|
878
|
-
return words.length > 0;
|
|
879
|
-
}
|
|
880
|
-
if (word.startsWith("--split-string=")) {
|
|
881
|
-
if (ignoresEnvironment) {
|
|
882
|
-
words.splice(0, words.length, ...originalWords);
|
|
883
|
-
return false;
|
|
884
|
-
}
|
|
885
|
-
words.shift();
|
|
886
|
-
words.unshift(...splitShellWords(word.slice("--split-string=".length)));
|
|
887
|
-
return words.length > 0;
|
|
888
|
-
}
|
|
889
|
-
if (word === "-i" || word === "--ignore-environment") {
|
|
890
|
-
if (!canShimIgnoreEnvironment || envCommand.includes("/")) {
|
|
891
|
-
words.splice(0, words.length, ...originalWords);
|
|
892
|
-
return false;
|
|
893
|
-
}
|
|
894
|
-
ignoresEnvironment = true;
|
|
895
|
-
words.shift();
|
|
896
|
-
continue;
|
|
897
|
-
}
|
|
898
|
-
if (word === "-u" || word === "--unset" || word === "-C" || word === "--chdir") {
|
|
899
|
-
words.shift();
|
|
900
|
-
if (words[0]) {
|
|
901
|
-
words.shift();
|
|
902
|
-
}
|
|
903
|
-
continue;
|
|
904
|
-
}
|
|
905
|
-
if (word.startsWith("--unset=") || word.startsWith("--chdir=")) {
|
|
906
|
-
words.shift();
|
|
907
|
-
continue;
|
|
908
|
-
}
|
|
909
|
-
if (word.startsWith("-") && word !== "-") {
|
|
910
|
-
if (word.includes("i")) {
|
|
911
|
-
if (!canShimIgnoreEnvironment || envCommand.includes("/")) {
|
|
912
|
-
words.splice(0, words.length, ...originalWords);
|
|
913
|
-
return false;
|
|
914
|
-
}
|
|
915
|
-
ignoresEnvironment = true;
|
|
916
|
-
}
|
|
917
|
-
words.shift();
|
|
918
|
-
continue;
|
|
919
|
-
}
|
|
920
|
-
if (ignoresEnvironment && (!canShimIgnoreEnvironment || envCommand.includes("/"))) {
|
|
921
|
-
words.splice(0, words.length, ...originalWords);
|
|
922
|
-
return false;
|
|
923
|
-
}
|
|
924
|
-
return true;
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
function shellWordBasename(word) {
|
|
929
|
-
return (word ?? "").split("/").pop() ?? "";
|
|
930
|
-
}
|
|
931
|
-
|
|
932
|
-
function stripCommandBuiltinOptions(words) {
|
|
933
|
-
for (;;) {
|
|
934
|
-
if (words[0] === "--") {
|
|
935
|
-
words.shift();
|
|
936
|
-
return true;
|
|
937
|
-
}
|
|
938
|
-
if (words[0] === "-p") {
|
|
939
|
-
words.shift();
|
|
940
|
-
continue;
|
|
941
|
-
}
|
|
942
|
-
return words[0] !== "-v" && words[0] !== "-V";
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
function stripTimeOptions(words) {
|
|
947
|
-
while ((words[0] ?? "").startsWith("-")) {
|
|
948
|
-
if (words[0] === "--") {
|
|
949
|
-
words.shift();
|
|
950
|
-
return;
|
|
951
|
-
}
|
|
952
|
-
words.shift();
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
function stripTimeoutOptions(words) {
|
|
957
|
-
words.shift();
|
|
958
|
-
for (;;) {
|
|
959
|
-
const word = words[0] ?? "";
|
|
960
|
-
if (!word) {
|
|
961
|
-
return;
|
|
962
|
-
}
|
|
963
|
-
if (word === "--") {
|
|
964
|
-
words.shift();
|
|
965
|
-
break;
|
|
966
|
-
}
|
|
967
|
-
if (word === "-k" || word === "--kill-after" || word === "-s" || word === "--signal") {
|
|
968
|
-
words.shift();
|
|
969
|
-
if (words[0]) {
|
|
970
|
-
words.shift();
|
|
971
|
-
}
|
|
972
|
-
continue;
|
|
973
|
-
}
|
|
974
|
-
if (word.startsWith("--kill-after=") || word.startsWith("--signal=")) {
|
|
975
|
-
words.shift();
|
|
976
|
-
continue;
|
|
977
|
-
}
|
|
978
|
-
if (word.startsWith("-") && word !== "-") {
|
|
979
|
-
words.shift();
|
|
980
|
-
continue;
|
|
981
|
-
}
|
|
982
|
-
break;
|
|
983
|
-
}
|
|
984
|
-
if (words[0]) {
|
|
985
|
-
words.shift();
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
function splitShellWords(value) {
|
|
990
|
-
const words = [];
|
|
991
|
-
let word = "";
|
|
992
|
-
let quote = "";
|
|
993
|
-
let escaped = false;
|
|
994
|
-
for (const char of value) {
|
|
995
|
-
if (escaped) {
|
|
996
|
-
word += char;
|
|
997
|
-
escaped = false;
|
|
998
|
-
continue;
|
|
999
|
-
}
|
|
1000
|
-
if (char === "\\" && quote !== "'") {
|
|
1001
|
-
escaped = true;
|
|
1002
|
-
continue;
|
|
1003
|
-
}
|
|
1004
|
-
if (quote) {
|
|
1005
|
-
if (char === quote) {
|
|
1006
|
-
quote = "";
|
|
1007
|
-
} else {
|
|
1008
|
-
word += char;
|
|
1009
|
-
}
|
|
1010
|
-
continue;
|
|
1011
|
-
}
|
|
1012
|
-
if (char === "'" || char === '"') {
|
|
1013
|
-
quote = char;
|
|
1014
|
-
continue;
|
|
1015
|
-
}
|
|
1016
|
-
if (/\s/u.test(char)) {
|
|
1017
|
-
if (word) {
|
|
1018
|
-
words.push(word);
|
|
1019
|
-
word = "";
|
|
1020
|
-
}
|
|
1021
|
-
continue;
|
|
1022
|
-
}
|
|
1023
|
-
word += char;
|
|
1024
|
-
}
|
|
1025
|
-
if (word) {
|
|
1026
|
-
words.push(word);
|
|
1027
|
-
}
|
|
1028
|
-
return words;
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
function stripHeredocBodies(command) {
|
|
1032
|
-
const lines = command.split("\n");
|
|
1033
|
-
const kept = [];
|
|
1034
|
-
const pendingDelimiters = [];
|
|
1035
|
-
for (const line of lines) {
|
|
1036
|
-
if (pendingDelimiters.length > 0) {
|
|
1037
|
-
const current = pendingDelimiters[0];
|
|
1038
|
-
const candidate = current.stripTabs ? line.replace(/^\t+/u, "") : line;
|
|
1039
|
-
if (candidate === current.delimiter) {
|
|
1040
|
-
pendingDelimiters.shift();
|
|
1041
|
-
} else if (current.expand) {
|
|
1042
|
-
kept.push(...extractCommandSubstitutionBodies(line));
|
|
1043
|
-
}
|
|
1044
|
-
continue;
|
|
1045
|
-
}
|
|
1046
|
-
kept.push(line);
|
|
1047
|
-
pendingDelimiters.push(...lineHeredocDelimiters(line));
|
|
1048
|
-
}
|
|
1049
|
-
return kept.join("\n");
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
function lineHeredocDelimiters(line) {
|
|
1053
|
-
const delimiters = [];
|
|
1054
|
-
let quote = "";
|
|
1055
|
-
let escaped = false;
|
|
1056
|
-
for (let index = 0; index < line.length; index += 1) {
|
|
1057
|
-
const char = line[index];
|
|
1058
|
-
const next = line[index + 1] ?? "";
|
|
1059
|
-
if (escaped) {
|
|
1060
|
-
escaped = false;
|
|
1061
|
-
continue;
|
|
1062
|
-
}
|
|
1063
|
-
if (char === "\\" && quote !== "'") {
|
|
1064
|
-
escaped = true;
|
|
1065
|
-
continue;
|
|
1066
|
-
}
|
|
1067
|
-
if (quote) {
|
|
1068
|
-
if (char === quote) {
|
|
1069
|
-
quote = "";
|
|
1070
|
-
}
|
|
1071
|
-
continue;
|
|
1072
|
-
}
|
|
1073
|
-
if (char === "'" || char === '"') {
|
|
1074
|
-
quote = char;
|
|
1075
|
-
continue;
|
|
1076
|
-
}
|
|
1077
|
-
if (char !== "<" || next !== "<" || line[index + 2] === "<") {
|
|
1078
|
-
continue;
|
|
1079
|
-
}
|
|
1080
|
-
let delimiterStart = index + 2;
|
|
1081
|
-
const stripTabs = line[delimiterStart] === "-";
|
|
1082
|
-
if (stripTabs) {
|
|
1083
|
-
delimiterStart += 1;
|
|
1084
|
-
}
|
|
1085
|
-
while (/\s/u.test(line[delimiterStart] ?? "")) {
|
|
1086
|
-
delimiterStart += 1;
|
|
1087
|
-
}
|
|
1088
|
-
const parsed = readHeredocDelimiter(line, delimiterStart);
|
|
1089
|
-
if (parsed.delimiter) {
|
|
1090
|
-
delimiters.push({ delimiter: parsed.delimiter, stripTabs, expand: !parsed.quoted });
|
|
1091
|
-
index = parsed.endIndex;
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
return delimiters;
|
|
1095
|
-
}
|
|
1096
|
-
|
|
1097
|
-
function readHeredocDelimiter(line, startIndex) {
|
|
1098
|
-
let delimiter = "";
|
|
1099
|
-
let quote = "";
|
|
1100
|
-
let escaped = false;
|
|
1101
|
-
let quoted = false;
|
|
1102
|
-
let index = startIndex;
|
|
1103
|
-
for (; index < line.length; index += 1) {
|
|
1104
|
-
const char = line[index];
|
|
1105
|
-
if (escaped) {
|
|
1106
|
-
delimiter += char;
|
|
1107
|
-
escaped = false;
|
|
1108
|
-
continue;
|
|
1109
|
-
}
|
|
1110
|
-
if (char === "\\" && quote !== "'") {
|
|
1111
|
-
quoted = true;
|
|
1112
|
-
escaped = true;
|
|
1113
|
-
continue;
|
|
1114
|
-
}
|
|
1115
|
-
if (quote) {
|
|
1116
|
-
if (char === quote) {
|
|
1117
|
-
quote = "";
|
|
1118
|
-
} else {
|
|
1119
|
-
delimiter += char;
|
|
1120
|
-
}
|
|
1121
|
-
continue;
|
|
1122
|
-
}
|
|
1123
|
-
if (char === "'" || char === '"') {
|
|
1124
|
-
quoted = true;
|
|
1125
|
-
quote = char;
|
|
1126
|
-
continue;
|
|
1127
|
-
}
|
|
1128
|
-
if (/\s/u.test(char) || /[;&|()<>]/u.test(char)) {
|
|
1129
|
-
break;
|
|
1130
|
-
}
|
|
1131
|
-
delimiter += char;
|
|
1132
|
-
}
|
|
1133
|
-
return { delimiter, endIndex: Math.max(startIndex, index), quoted };
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
|
-
function extractCommandSubstitutionBodies(line) {
|
|
1137
|
-
const substitutions = [];
|
|
1138
|
-
let escaped = false;
|
|
1139
|
-
for (let index = 0; index < line.length; index += 1) {
|
|
1140
|
-
const char = line[index];
|
|
1141
|
-
const next = line[index + 1] ?? "";
|
|
1142
|
-
if (escaped) {
|
|
1143
|
-
escaped = false;
|
|
1144
|
-
continue;
|
|
1145
|
-
}
|
|
1146
|
-
if (char === "\\") {
|
|
1147
|
-
escaped = true;
|
|
1148
|
-
continue;
|
|
1149
|
-
}
|
|
1150
|
-
if (char === "$" && next === "(" && line[index + 2] !== "(") {
|
|
1151
|
-
const substitution = readCommandSubstitution(line, index + 2);
|
|
1152
|
-
substitutions.push(substitution.content);
|
|
1153
|
-
index = substitution.endIndex;
|
|
1154
|
-
}
|
|
1155
|
-
}
|
|
1156
|
-
return substitutions;
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
function shellCommandSegments(command) {
|
|
1160
|
-
const segments = [];
|
|
1161
|
-
let segment = "";
|
|
1162
|
-
let quote = "";
|
|
1163
|
-
let escaped = false;
|
|
1164
|
-
let inCase = false;
|
|
1165
|
-
let readingCasePattern = false;
|
|
1166
|
-
for (let index = 0; index < command.length; index += 1) {
|
|
1167
|
-
const char = command[index];
|
|
1168
|
-
const next = command[index + 1] ?? "";
|
|
1169
|
-
if (escaped) {
|
|
1170
|
-
segment += char;
|
|
1171
|
-
escaped = false;
|
|
1172
|
-
continue;
|
|
1173
|
-
}
|
|
1174
|
-
if (char === "\\" && quote !== "'") {
|
|
1175
|
-
segment += char;
|
|
1176
|
-
escaped = true;
|
|
1177
|
-
continue;
|
|
1178
|
-
}
|
|
1179
|
-
if (quote) {
|
|
1180
|
-
if (quote === '"' && char === "$" && next === "(" && command[index + 2] !== "(") {
|
|
1181
|
-
const substitution = readCommandSubstitution(command, index + 2);
|
|
1182
|
-
segments.push(...shellCommandWordCandidates(substitution.content));
|
|
1183
|
-
index = substitution.endIndex;
|
|
1184
|
-
segment += "$()";
|
|
1185
|
-
continue;
|
|
1186
|
-
}
|
|
1187
|
-
if (char === quote) {
|
|
1188
|
-
quote = "";
|
|
1189
|
-
}
|
|
1190
|
-
segment += char;
|
|
1191
|
-
continue;
|
|
1192
|
-
}
|
|
1193
|
-
if (char === "'" || char === '"') {
|
|
1194
|
-
quote = char;
|
|
1195
|
-
segment += char;
|
|
1196
|
-
continue;
|
|
1197
|
-
}
|
|
1198
|
-
if (char === "#" && (segment.trim() === "" || /\s$/u.test(segment))) {
|
|
1199
|
-
index = skipUntilNewline(command, index);
|
|
1200
|
-
pushShellCandidate(segments, segment);
|
|
1201
|
-
segment = "";
|
|
1202
|
-
continue;
|
|
1203
|
-
}
|
|
1204
|
-
if (char === "$" && next === "(" && command[index + 2] !== "(") {
|
|
1205
|
-
const substitution = readCommandSubstitution(command, index + 2);
|
|
1206
|
-
segments.push(...shellCommandWordCandidates(substitution.content));
|
|
1207
|
-
index = substitution.endIndex;
|
|
1208
|
-
segment += "$()";
|
|
1209
|
-
continue;
|
|
1210
|
-
}
|
|
1211
|
-
if (segment.trim() === "" && startsShellReservedWord(command, index, "case")) {
|
|
1212
|
-
pushShellCandidate(segments, segment);
|
|
1213
|
-
segment = "";
|
|
1214
|
-
inCase = true;
|
|
1215
|
-
readingCasePattern = true;
|
|
1216
|
-
index += "case".length - 1;
|
|
1217
|
-
continue;
|
|
1218
|
-
}
|
|
1219
|
-
if (inCase && segment.trim() === "" && startsShellReservedWord(command, index, "esac")) {
|
|
1220
|
-
pushShellCandidate(segments, segment);
|
|
1221
|
-
segment = "";
|
|
1222
|
-
inCase = false;
|
|
1223
|
-
readingCasePattern = false;
|
|
1224
|
-
index += "esac".length - 1;
|
|
1225
|
-
continue;
|
|
1226
|
-
}
|
|
1227
|
-
if (inCase && readingCasePattern) {
|
|
1228
|
-
if (char === ")") {
|
|
1229
|
-
segment = "";
|
|
1230
|
-
readingCasePattern = false;
|
|
1231
|
-
continue;
|
|
1232
|
-
}
|
|
1233
|
-
segment += char;
|
|
1234
|
-
continue;
|
|
1235
|
-
}
|
|
1236
|
-
if (inCase && char === ";" && next === ";") {
|
|
1237
|
-
pushShellCandidate(segments, segment);
|
|
1238
|
-
segment = "";
|
|
1239
|
-
readingCasePattern = true;
|
|
1240
|
-
index += 1;
|
|
1241
|
-
continue;
|
|
1242
|
-
}
|
|
1243
|
-
if (char === "\n" || char === ";" || char === ")") {
|
|
1244
|
-
pushShellCandidate(segments, segment);
|
|
1245
|
-
segment = "";
|
|
1246
|
-
continue;
|
|
1247
|
-
}
|
|
1248
|
-
if ((char === "&" && next === "&") || (char === "|" && next === "|")) {
|
|
1249
|
-
pushShellCandidate(segments, segment);
|
|
1250
|
-
segment = "";
|
|
1251
|
-
index += 1;
|
|
1252
|
-
continue;
|
|
1253
|
-
}
|
|
1254
|
-
if (char === "&" && next !== ">" && command[index - 1] !== ">") {
|
|
1255
|
-
pushShellCandidate(segments, segment);
|
|
1256
|
-
segment = "";
|
|
1257
|
-
continue;
|
|
1258
|
-
}
|
|
1259
|
-
if (char === "|") {
|
|
1260
|
-
pushShellCandidate(segments, segment);
|
|
1261
|
-
segment = "";
|
|
1262
|
-
if (next === "&") {
|
|
1263
|
-
index += 1;
|
|
1264
|
-
}
|
|
1265
|
-
continue;
|
|
1266
|
-
}
|
|
1267
|
-
segment += char;
|
|
1268
|
-
}
|
|
1269
|
-
pushShellCandidate(segments, segment);
|
|
1270
|
-
return segments;
|
|
1271
|
-
}
|
|
1272
|
-
|
|
1273
|
-
function readCommandSubstitution(command, startIndex) {
|
|
1274
|
-
let depth = 1;
|
|
1275
|
-
let quote = "";
|
|
1276
|
-
let escaped = false;
|
|
1277
|
-
let inCase = false;
|
|
1278
|
-
let readingCasePattern = false;
|
|
1279
|
-
let content = "";
|
|
1280
|
-
for (let index = startIndex; index < command.length; index += 1) {
|
|
1281
|
-
const char = command[index];
|
|
1282
|
-
const next = command[index + 1] ?? "";
|
|
1283
|
-
if (escaped) {
|
|
1284
|
-
content += char;
|
|
1285
|
-
escaped = false;
|
|
1286
|
-
continue;
|
|
1287
|
-
}
|
|
1288
|
-
if (char === "\\" && quote !== "'") {
|
|
1289
|
-
content += char;
|
|
1290
|
-
escaped = true;
|
|
1291
|
-
continue;
|
|
1292
|
-
}
|
|
1293
|
-
if (quote) {
|
|
1294
|
-
if (char === quote) {
|
|
1295
|
-
quote = "";
|
|
1296
|
-
}
|
|
1297
|
-
content += char;
|
|
1298
|
-
continue;
|
|
1299
|
-
}
|
|
1300
|
-
if (char === "'" || char === '"') {
|
|
1301
|
-
quote = char;
|
|
1302
|
-
content += char;
|
|
1303
|
-
continue;
|
|
1304
|
-
}
|
|
1305
|
-
if (!inCase && startsShellToken(command, index, "case")) {
|
|
1306
|
-
inCase = true;
|
|
1307
|
-
readingCasePattern = true;
|
|
1308
|
-
} else if (inCase && startsShellToken(command, index, "esac")) {
|
|
1309
|
-
inCase = false;
|
|
1310
|
-
readingCasePattern = false;
|
|
1311
|
-
}
|
|
1312
|
-
if (char === "$" && next === "(") {
|
|
1313
|
-
depth += 1;
|
|
1314
|
-
content += "$(";
|
|
1315
|
-
index += 1;
|
|
1316
|
-
continue;
|
|
1317
|
-
}
|
|
1318
|
-
if (char === "(") {
|
|
1319
|
-
depth += 1;
|
|
1320
|
-
content += char;
|
|
1321
|
-
continue;
|
|
1322
|
-
}
|
|
1323
|
-
if (inCase && char === ";" && next === ";") {
|
|
1324
|
-
readingCasePattern = true;
|
|
1325
|
-
content += ";;";
|
|
1326
|
-
index += 1;
|
|
1327
|
-
continue;
|
|
1328
|
-
}
|
|
1329
|
-
if (inCase && readingCasePattern && depth === 1 && char === ")") {
|
|
1330
|
-
readingCasePattern = false;
|
|
1331
|
-
content += char;
|
|
1332
|
-
continue;
|
|
1333
|
-
}
|
|
1334
|
-
if (char === ")") {
|
|
1335
|
-
depth -= 1;
|
|
1336
|
-
if (depth === 0) {
|
|
1337
|
-
return { content, endIndex: index };
|
|
1338
|
-
}
|
|
1339
|
-
}
|
|
1340
|
-
content += char;
|
|
1341
|
-
}
|
|
1342
|
-
return { content, endIndex: command.length - 1 };
|
|
1343
|
-
}
|
|
1344
|
-
|
|
1345
|
-
function startsShellReservedWord(command, index, word) {
|
|
1346
|
-
if (!command.startsWith(word, index)) {
|
|
1347
|
-
return false;
|
|
1348
|
-
}
|
|
1349
|
-
const after = command[index + word.length] ?? "";
|
|
1350
|
-
return !after || /\s|[;&|()<>]/u.test(after);
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
function startsShellToken(command, index, word) {
|
|
1354
|
-
if (!command.startsWith(word, index)) {
|
|
1355
|
-
return false;
|
|
1356
|
-
}
|
|
1357
|
-
const before = command[index - 1] ?? "";
|
|
1358
|
-
const after = command[index + word.length] ?? "";
|
|
1359
|
-
return (!before || /\s|[;&|()<>]/u.test(before)) && (!after || /\s|[;&|()<>]/u.test(after));
|
|
1360
|
-
}
|
|
1361
|
-
|
|
1362
|
-
function skipUntilNewline(command, index) {
|
|
1363
|
-
const newlineIndex = command.indexOf("\n", index);
|
|
1364
|
-
return newlineIndex < 0 ? command.length - 1 : newlineIndex;
|
|
1365
|
-
}
|
|
1366
|
-
|
|
1367
|
-
function mergeBaseForChangedGate() {
|
|
1368
|
-
const base = gitOutput(["merge-base", "origin/main", "HEAD"]);
|
|
1369
|
-
return base.status === 0 && base.stdout ? base.stdout : "origin/main";
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
function remoteGitBootstrapForChangedGate(changedGateBase) {
|
|
1373
|
-
const quotedBase = shellQuote(changedGateBase);
|
|
1374
|
-
return [
|
|
1375
|
-
"if ! git status --short >/dev/null 2>&1; then",
|
|
1376
|
-
"rm -rf .git;",
|
|
1377
|
-
"git init -q;",
|
|
1378
|
-
"git remote add origin https://github.com/fengming/fengming.git 2>/dev/null || git remote set-url origin https://github.com/fengming/fengming.git;",
|
|
1379
|
-
`git fetch -q --depth=1 origin ${quotedBase}:refs/remotes/origin/main;`,
|
|
1380
|
-
"git reset --mixed --quiet refs/remotes/origin/main;",
|
|
1381
|
-
"git add -A;",
|
|
1382
|
-
"if ! git diff --cached --quiet; then git -c user.name=FengMing -c user.email=ci@fengming.local commit -q --no-gpg-sign -m remote-changed-gate-tree; fi;",
|
|
1383
|
-
"fi",
|
|
1384
|
-
].join(" ");
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
function isWindowsRemoteTarget(commandArgs) {
|
|
1388
|
-
return (
|
|
1389
|
-
optionValue(commandArgs, "--target") === "windows" || hasOption(commandArgs, "--windows-mode")
|
|
1390
|
-
);
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
function isAwsMacosRemoteTarget(commandArgs, providerName) {
|
|
1394
|
-
return (
|
|
1395
|
-
commandArgs[0] === "run" &&
|
|
1396
|
-
providerName === "aws" &&
|
|
1397
|
-
optionValue(commandArgs, "--target") === "macos"
|
|
1398
|
-
);
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
function injectRemoteChangedGateGitBootstrap(commandArgs, changedGateBase) {
|
|
1402
|
-
if (!changedGateBase || commandArgs[0] !== "run" || isWindowsRemoteTarget(commandArgs)) {
|
|
1403
|
-
return commandArgs;
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
const { start, optionEnd } = runCommandBounds(commandArgs);
|
|
1407
|
-
if (start < 0) {
|
|
1408
|
-
return commandArgs;
|
|
1409
|
-
}
|
|
1410
|
-
|
|
1411
|
-
const normalizedArgs = [...commandArgs];
|
|
1412
|
-
const remoteCommand = normalizedArgs.slice(start);
|
|
1413
|
-
const originalShellCommand =
|
|
1414
|
-
hasOption(normalizedArgs, "--shell") && remoteCommand.length === 1
|
|
1415
|
-
? remoteCommand[0]
|
|
1416
|
-
: shellJoin(remoteCommand);
|
|
1417
|
-
const shellCommand = `${remoteGitBootstrapForChangedGate(changedGateBase)} && ${originalShellCommand}`;
|
|
1418
|
-
|
|
1419
|
-
if (!hasOption(normalizedArgs, "--shell")) {
|
|
1420
|
-
normalizedArgs.splice(optionEnd, 0, "--shell");
|
|
1421
|
-
}
|
|
1422
|
-
|
|
1423
|
-
const updatedBounds = runCommandBounds(normalizedArgs);
|
|
1424
|
-
normalizedArgs.splice(
|
|
1425
|
-
updatedBounds.start,
|
|
1426
|
-
normalizedArgs.length - updatedBounds.start,
|
|
1427
|
-
shellCommand,
|
|
1428
|
-
);
|
|
1429
|
-
return normalizedArgs;
|
|
1430
|
-
}
|
|
1431
|
-
|
|
1432
|
-
function remoteAwsMacosJsBootstrap({ packageManager = false } = {}) {
|
|
1433
|
-
const nodeVersion = process.env.FENGMING_CRABBOX_MACOS_NODE_VERSION?.trim() || "24.15.0";
|
|
1434
|
-
const bootstrap = [
|
|
1435
|
-
"fengming_crabbox_bootstrap_macos_js() {",
|
|
1436
|
-
'tool_root="${FENGMING_CRABBOX_MACOS_TOOLCHAIN_DIR:-$HOME/.fengming-crabbox-toolchain}";',
|
|
1437
|
-
`node_version=${shellQuote(nodeVersion)};`,
|
|
1438
|
-
'arch="$(uname -m)";',
|
|
1439
|
-
'case "$arch" in arm64) node_arch=arm64 ;; x86_64) node_arch=x64 ;; *) echo "unsupported macOS arch: $arch" >&2; return 2 ;; esac;',
|
|
1440
|
-
'if [ -z "${TMPDIR:-}" ]; then export TMPDIR="/tmp"; fi;',
|
|
1441
|
-
'if [ ! -d "$TMPDIR" ]; then mkdir -p "$TMPDIR" 2>/dev/null || export TMPDIR="/tmp"; fi;',
|
|
1442
|
-
'if [ ! -d "$TMPDIR" ]; then echo "usable TMPDIR not found: $TMPDIR" >&2; return 1; fi;',
|
|
1443
|
-
'node_dir="$tool_root/node-v${node_version}-darwin-${node_arch}";',
|
|
1444
|
-
'export PATH="$node_dir/bin:$PATH";',
|
|
1445
|
-
'if [ ! -x "$node_dir/bin/node" ]; then',
|
|
1446
|
-
'tmp_dir="$(mktemp -d)" || return 1;',
|
|
1447
|
-
'pkg="node-v${node_version}-darwin-${node_arch}.tar.gz";',
|
|
1448
|
-
'base_url="https://nodejs.org/dist/v${node_version}";',
|
|
1449
|
-
'mkdir -p "$tool_root" || { status=$?; rm -rf "$tmp_dir"; return "$status"; };',
|
|
1450
|
-
'curl -fsSLo "$tmp_dir/$pkg" "$base_url/$pkg" || { status=$?; rm -rf "$tmp_dir"; return "$status"; };',
|
|
1451
|
-
'curl -fsSLo "$tmp_dir/SHASUMS256.txt" "$base_url/SHASUMS256.txt" || { status=$?; rm -rf "$tmp_dir"; return "$status"; };',
|
|
1452
|
-
'(cd "$tmp_dir" && grep " $pkg$" SHASUMS256.txt | shasum -a 256 -c -) || { status=$?; rm -rf "$tmp_dir"; return "$status"; };',
|
|
1453
|
-
'rm -rf "$node_dir" || { status=$?; rm -rf "$tmp_dir"; return "$status"; };',
|
|
1454
|
-
'tar -xzf "$tmp_dir/$pkg" -C "$tool_root" || { status=$?; rm -rf "$tmp_dir"; return "$status"; };',
|
|
1455
|
-
'rm -rf "$tmp_dir";',
|
|
1456
|
-
"fi;",
|
|
1457
|
-
"node --version >&2 || return 1;",
|
|
1458
|
-
"fengming_crabbox_env() {",
|
|
1459
|
-
"fengming_env_args=();",
|
|
1460
|
-
"fengming_env_ignore=0;",
|
|
1461
|
-
"fengming_env_path_seen=0;",
|
|
1462
|
-
'while [ "$#" -gt 0 ]; do',
|
|
1463
|
-
'case "$1" in',
|
|
1464
|
-
'-i|--ignore-environment) fengming_env_ignore=1; fengming_env_args+=("$1"); shift ;;',
|
|
1465
|
-
'-S|--split-string|-S*|--split-string=*) command env "${fengming_env_args[@]}" "$@"; return ;;',
|
|
1466
|
-
'-[!-]*i*) fengming_env_ignore=1; fengming_env_args+=("$1"); shift ;;',
|
|
1467
|
-
'-u|--unset|-C|--chdir) fengming_env_args+=("$1"); shift; if [ "$#" -gt 0 ]; then fengming_env_args+=("$1"); shift; fi ;;',
|
|
1468
|
-
'--unset=*|--chdir=*) fengming_env_args+=("$1"); shift ;;',
|
|
1469
|
-
'PATH=*) if [ "$fengming_env_ignore" = "1" ]; then fengming_env_args+=("PATH=$PATH:${1#PATH=}"); else fengming_env_args+=("$1"); fi; fengming_env_path_seen=1; shift ;;',
|
|
1470
|
-
'[A-Za-z_]*=*) fengming_env_args+=("$1"); shift ;;',
|
|
1471
|
-
'--) fengming_env_args+=("--"); shift; break ;;',
|
|
1472
|
-
"*) break ;;",
|
|
1473
|
-
"esac;",
|
|
1474
|
-
"done;",
|
|
1475
|
-
'if [ "$fengming_env_ignore" = "1" ] && [ "$fengming_env_path_seen" = "0" ]; then fengming_env_args+=("PATH=$PATH"); fi;',
|
|
1476
|
-
'command env "${fengming_env_args[@]}" "$@";',
|
|
1477
|
-
"};",
|
|
1478
|
-
];
|
|
1479
|
-
if (packageManager) {
|
|
1480
|
-
bootstrap.push(
|
|
1481
|
-
'export COREPACK_HOME="${COREPACK_HOME:-$tool_root/corepack}";',
|
|
1482
|
-
'export PNPM_HOME="${PNPM_HOME:-$tool_root/pnpm-home}";',
|
|
1483
|
-
'mkdir -p "$COREPACK_HOME" "$PNPM_HOME" || return 1;',
|
|
1484
|
-
'export PATH="$PNPM_HOME:$PATH";',
|
|
1485
|
-
'corepack enable --install-directory "$PNPM_HOME" || return 1;',
|
|
1486
|
-
"pnpm --version >&2;",
|
|
1487
|
-
);
|
|
1488
|
-
}
|
|
1489
|
-
bootstrap.push("};", "fengming_crabbox_bootstrap_macos_js");
|
|
1490
|
-
return bootstrap.join(" ");
|
|
1491
|
-
}
|
|
1492
|
-
|
|
1493
|
-
function scopedAwsMacosEnvCommand(commandArgs) {
|
|
1494
|
-
if (
|
|
1495
|
-
commandArgs.length <= 1 ||
|
|
1496
|
-
shellWordBasename(commandArgs[0]) !== "env" ||
|
|
1497
|
-
commandArgs[0].includes("/")
|
|
1498
|
-
) {
|
|
1499
|
-
return null;
|
|
1500
|
-
}
|
|
1501
|
-
|
|
1502
|
-
const targetWords = [...commandArgs];
|
|
1503
|
-
if (!stripEnvCommandOptions(targetWords, { canShimIgnoreEnvironment: true })) {
|
|
1504
|
-
return null;
|
|
1505
|
-
}
|
|
1506
|
-
|
|
1507
|
-
const targetEntrypoint = shellWordBasename(targetWords[0]);
|
|
1508
|
-
if (
|
|
1509
|
-
!jsRuntimeEntrypoints.has(targetEntrypoint) &&
|
|
1510
|
-
!awsMacosCorepackEntrypoints.has(targetEntrypoint)
|
|
1511
|
-
) {
|
|
1512
|
-
return null;
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
return {
|
|
1516
|
-
runtimeEntrypoint: targetEntrypoint,
|
|
1517
|
-
packageManager: awsMacosCorepackEntrypoints.has(targetEntrypoint),
|
|
1518
|
-
shellCommand: `fengming_crabbox_env ${shellJoin(commandArgs.slice(1))}`,
|
|
1519
|
-
};
|
|
1520
|
-
}
|
|
1521
|
-
|
|
1522
|
-
function injectRemoteAwsMacosJsBootstrap(commandArgs, providerName) {
|
|
1523
|
-
const runArgs = runCommandArgs(commandArgs);
|
|
1524
|
-
const directScopedEnvCommand = hasOption(commandArgs, "--shell")
|
|
1525
|
-
? null
|
|
1526
|
-
: scopedAwsMacosEnvCommand(runArgs);
|
|
1527
|
-
const runtimeEntrypoint =
|
|
1528
|
-
directScopedEnvCommand?.runtimeEntrypoint || commandRuntimeEntrypoint(runArgs);
|
|
1529
|
-
if (!isAwsMacosRemoteTarget(commandArgs, providerName) || !runtimeEntrypoint) {
|
|
1530
|
-
return commandArgs;
|
|
1531
|
-
}
|
|
1532
|
-
|
|
1533
|
-
const { start, optionEnd } = runCommandBounds(commandArgs);
|
|
1534
|
-
if (start < 0) {
|
|
1535
|
-
return commandArgs;
|
|
1536
|
-
}
|
|
1537
|
-
|
|
1538
|
-
const normalizedArgs = [...commandArgs];
|
|
1539
|
-
const remoteCommand = normalizedArgs.slice(start);
|
|
1540
|
-
const originalShellCommand =
|
|
1541
|
-
directScopedEnvCommand?.shellCommand ??
|
|
1542
|
-
(hasOption(normalizedArgs, "--shell") && remoteCommand.length === 1
|
|
1543
|
-
? remoteCommand[0]
|
|
1544
|
-
: shellJoin(remoteCommand));
|
|
1545
|
-
const shellCommand = `${remoteAwsMacosJsBootstrap({
|
|
1546
|
-
packageManager:
|
|
1547
|
-
directScopedEnvCommand?.packageManager || commandNeedsAwsMacosPackageManager(runArgs),
|
|
1548
|
-
})} && { ${originalShellCommand}\n}`;
|
|
1549
|
-
|
|
1550
|
-
if (!hasOption(normalizedArgs, "--shell")) {
|
|
1551
|
-
normalizedArgs.splice(optionEnd, 0, "--shell");
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
const updatedBounds = runCommandBounds(normalizedArgs);
|
|
1555
|
-
normalizedArgs.splice(
|
|
1556
|
-
updatedBounds.start,
|
|
1557
|
-
normalizedArgs.length - updatedBounds.start,
|
|
1558
|
-
shellCommand,
|
|
1559
|
-
);
|
|
1560
|
-
return normalizedArgs;
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
|
-
function hasRunOption(commandArgs, name) {
|
|
1564
|
-
if (commandArgs[0] !== "run") {
|
|
1565
|
-
return false;
|
|
1566
|
-
}
|
|
1567
|
-
const { optionEnd } = runCommandBounds(commandArgs);
|
|
1568
|
-
const normalizedName = name.replace(/^-+/u, "");
|
|
1569
|
-
for (let index = 1; index < optionEnd; index += 1) {
|
|
1570
|
-
const arg = commandArgs[index];
|
|
1571
|
-
if (arg.startsWith("-") && runOptionName(arg) === normalizedName) {
|
|
1572
|
-
return true;
|
|
1573
|
-
}
|
|
1574
|
-
if (!arg.includes("=") && currentRunValueOptions().has(runOptionName(arg))) {
|
|
1575
|
-
index += 1;
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
return false;
|
|
1579
|
-
}
|
|
1580
|
-
|
|
1581
|
-
function replaceRunFlagWithScript(commandArgs, flagName, scriptPath) {
|
|
1582
|
-
const { optionEnd } = runCommandBounds(commandArgs);
|
|
1583
|
-
const normalizedName = flagName.replace(/^-+/u, "");
|
|
1584
|
-
const normalizedArgs = [...commandArgs];
|
|
1585
|
-
for (let index = 1; index < optionEnd; index += 1) {
|
|
1586
|
-
const arg = normalizedArgs[index];
|
|
1587
|
-
if (arg.startsWith("-") && runOptionName(arg) === normalizedName) {
|
|
1588
|
-
normalizedArgs.splice(index, 1, "--script", scriptPath);
|
|
1589
|
-
return normalizedArgs;
|
|
1590
|
-
}
|
|
1591
|
-
if (!arg.includes("=") && currentRunValueOptions().has(runOptionName(arg))) {
|
|
1592
|
-
index += 1;
|
|
1593
|
-
}
|
|
1594
|
-
}
|
|
1595
|
-
return normalizedArgs;
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
function prepareAwsMacosScriptStdinBootstrap(commandArgs, providerName) {
|
|
1599
|
-
if (
|
|
1600
|
-
!isAwsMacosRemoteTarget(commandArgs, providerName) ||
|
|
1601
|
-
!hasRunOption(commandArgs, "--script-stdin")
|
|
1602
|
-
) {
|
|
1603
|
-
return { args: commandArgs, cleanup: () => {}, prepared: false };
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
const scriptRoot = mkdtempSync(resolve(tmpdir(), "fengming-crabbox-macos-script-"));
|
|
1607
|
-
const scriptPath = resolve(scriptRoot, "script.sh");
|
|
1608
|
-
const script = readFileSync(0, "utf8");
|
|
1609
|
-
writeFileSync(scriptPath, createAwsMacosScriptStdinWrapper(script), "utf8");
|
|
1610
|
-
chmodSync(scriptPath, 0o700);
|
|
1611
|
-
return {
|
|
1612
|
-
args: replaceRunFlagWithScript(commandArgs, "--script-stdin", scriptPath),
|
|
1613
|
-
cleanup: () => rmSync(scriptRoot, { recursive: true, force: true }),
|
|
1614
|
-
prepared: true,
|
|
1615
|
-
};
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
|
-
function createAwsMacosScriptStdinWrapper(script) {
|
|
1619
|
-
const packageManager = scriptNeedsAwsMacosPackageManager(script);
|
|
1620
|
-
if (!script.startsWith("#!")) {
|
|
1621
|
-
return `${remoteAwsMacosJsBootstrap({ packageManager })} || exit $?\n${script}`;
|
|
1622
|
-
}
|
|
1623
|
-
const delimiter = uniqueHereDocDelimiter(script);
|
|
1624
|
-
return [
|
|
1625
|
-
`${remoteAwsMacosJsBootstrap({ packageManager })} || exit $?`,
|
|
1626
|
-
'tmp_script="$(mktemp "${TMPDIR:-/tmp}/fengming-crabbox-script.XXXXXX")" || exit $?',
|
|
1627
|
-
'cleanup_fengming_crabbox_script() { rm -f "$tmp_script"; }',
|
|
1628
|
-
"trap cleanup_fengming_crabbox_script EXIT",
|
|
1629
|
-
`cat >"$tmp_script" <<'${delimiter}'`,
|
|
1630
|
-
script.endsWith("\n") ? script.slice(0, -1) : script,
|
|
1631
|
-
delimiter,
|
|
1632
|
-
'chmod 700 "$tmp_script" || exit $?',
|
|
1633
|
-
'"$tmp_script" "$@"',
|
|
1634
|
-
"",
|
|
1635
|
-
].join("\n");
|
|
1636
|
-
}
|
|
1637
|
-
|
|
1638
|
-
function scriptNeedsAwsMacosPackageManager(script) {
|
|
1639
|
-
const firstLine = script.match(/^[^\r\n]*/u)?.[0] ?? "";
|
|
1640
|
-
if (firstLine.startsWith("#!")) {
|
|
1641
|
-
let words = firstLine.slice(2).trim().split(/\s+/u).filter(Boolean);
|
|
1642
|
-
if ((words[0] ?? "").split("/").pop() === "env") {
|
|
1643
|
-
words = words.slice(1);
|
|
1644
|
-
while ((words[0] ?? "").startsWith("-")) {
|
|
1645
|
-
words = words.slice(1);
|
|
1646
|
-
}
|
|
1647
|
-
}
|
|
1648
|
-
if (commandWordsNeedAwsMacosPackageManager(words)) {
|
|
1649
|
-
return true;
|
|
1650
|
-
}
|
|
1651
|
-
}
|
|
1652
|
-
return commandNeedsAwsMacosPackageManager([script]);
|
|
1653
|
-
}
|
|
1654
|
-
|
|
1655
|
-
function uniqueHereDocDelimiter(script) {
|
|
1656
|
-
let index = 0;
|
|
1657
|
-
for (;;) {
|
|
1658
|
-
const delimiter = `FENGMING_CRABBOX_SCRIPT_${index}`;
|
|
1659
|
-
if (!new RegExp(`^${delimiter}$`, "mu").test(script)) {
|
|
1660
|
-
return delimiter;
|
|
1661
|
-
}
|
|
1662
|
-
index += 1;
|
|
1663
|
-
}
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
function isSparseCheckout() {
|
|
1667
|
-
const config = gitOutput(["config", "--bool", "core.sparseCheckout"]);
|
|
1668
|
-
if (config.status === 0 && config.stdout === "true") {
|
|
1669
|
-
return true;
|
|
1670
|
-
}
|
|
1671
|
-
const patterns = gitOutput(["sparse-checkout", "list"]);
|
|
1672
|
-
return patterns.status === 0 && patterns.stdout.length > 0;
|
|
1673
|
-
}
|
|
1674
|
-
|
|
1675
|
-
function isWorktreeClean() {
|
|
1676
|
-
return gitOutput(["status", "--porcelain=v1"]).stdout === "";
|
|
1677
|
-
}
|
|
1678
|
-
|
|
1679
|
-
function shouldUseFullCheckoutForCleanSparseRemoteSync(commandArgs, providerName) {
|
|
1680
|
-
if (commandArgs[0] !== "run") {
|
|
1681
|
-
return false;
|
|
1682
|
-
}
|
|
1683
|
-
if (hasOption(commandArgs, "--no-sync")) {
|
|
1684
|
-
return false;
|
|
1685
|
-
}
|
|
1686
|
-
|
|
1687
|
-
return isSparseCheckout() && isWorktreeClean();
|
|
1688
|
-
}
|
|
1689
|
-
|
|
1690
|
-
function prepareFullCheckoutForSync(options = {}) {
|
|
1691
|
-
const dir = mkdtempSync(resolve(tmpdir(), "fengming-crabbox-sync-"));
|
|
1692
|
-
let active = false;
|
|
1693
|
-
const add = gitOutput(["worktree", "add", "--detach", dir, "HEAD"]);
|
|
1694
|
-
if (add.status !== 0) {
|
|
1695
|
-
rmSync(dir, { recursive: true, force: true });
|
|
1696
|
-
throw new Error(`git worktree add failed: ${add.text}`);
|
|
1697
|
-
}
|
|
1698
|
-
active = true;
|
|
1699
|
-
|
|
1700
|
-
const disableSparse = gitOutput(["-C", dir, "sparse-checkout", "disable"]);
|
|
1701
|
-
if (disableSparse.status !== 0) {
|
|
1702
|
-
cleanupFullCheckout(dir, active);
|
|
1703
|
-
throw new Error(`git sparse-checkout disable failed: ${disableSparse.text}`);
|
|
1704
|
-
}
|
|
1705
|
-
|
|
1706
|
-
if (options.changedGateBase) {
|
|
1707
|
-
const reset = gitOutput(["-C", dir, "reset", "--mixed", "--quiet", options.changedGateBase]);
|
|
1708
|
-
if (reset.status !== 0) {
|
|
1709
|
-
cleanupFullCheckout(dir, active);
|
|
1710
|
-
throw new Error(`git reset for changed-gate sync failed: ${reset.text}`);
|
|
1711
|
-
}
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
return {
|
|
1715
|
-
dir,
|
|
1716
|
-
changedGateBase: options.changedGateBase ?? "",
|
|
1717
|
-
cleanup() {
|
|
1718
|
-
cleanupFullCheckout(dir, active);
|
|
1719
|
-
active = false;
|
|
1720
|
-
},
|
|
1721
|
-
};
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1724
|
-
function cleanupFullCheckout(dir, active) {
|
|
1725
|
-
if (active) {
|
|
1726
|
-
const remove = gitOutput(["worktree", "remove", "--force", dir]);
|
|
1727
|
-
if (remove.status === 0) {
|
|
1728
|
-
return;
|
|
1729
|
-
}
|
|
1730
|
-
console.error(`[crabbox] warning: git worktree remove failed for ${dir}: ${remove.text}`);
|
|
1731
|
-
}
|
|
1732
|
-
rmSync(dir, { recursive: true, force: true });
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
|
-
const version = checkedOutput(binary, ["--version"]);
|
|
1736
|
-
const help = checkedOutput(binary, ["run", "--help"]);
|
|
1737
|
-
const providerAliases = new Map([
|
|
1738
|
-
["blacksmith", "blacksmith-testbox"],
|
|
1739
|
-
["cf", "cloudflare"],
|
|
1740
|
-
["container", "local-container"],
|
|
1741
|
-
["docker", "local-container"],
|
|
1742
|
-
["exe", "exe-dev"],
|
|
1743
|
-
["exedev", "exe-dev"],
|
|
1744
|
-
["google", "gcp"],
|
|
1745
|
-
["google-cloud", "gcp"],
|
|
1746
|
-
["local-docker", "local-container"],
|
|
1747
|
-
["namespace", "namespace-devbox"],
|
|
1748
|
-
["namespace-devboxes", "namespace-devbox"],
|
|
1749
|
-
["rail", "railway"],
|
|
1750
|
-
["railwayapp", "railway"],
|
|
1751
|
-
["run-pod", "runpod"],
|
|
1752
|
-
["runpodio", "runpod"],
|
|
1753
|
-
["sem", "semaphore"],
|
|
1754
|
-
["static", "ssh"],
|
|
1755
|
-
["static-ssh", "ssh"],
|
|
1756
|
-
["tensorlake-sbx", "tensorlake"],
|
|
1757
|
-
["tl", "tensorlake"],
|
|
1758
|
-
]);
|
|
1759
|
-
// Crabbox providerHelpAll can omit Tensorlake even when the binary accepts it.
|
|
1760
|
-
const providerHelpOmissions = new Set(["tensorlake"]);
|
|
1761
|
-
|
|
1762
|
-
function addProviderNames(names, text) {
|
|
1763
|
-
for (const name of text
|
|
1764
|
-
.replace(/\s+\(default\b.*$/u, "")
|
|
1765
|
-
.split(/\s*(?:,|\||\bor\b)\s*/u)
|
|
1766
|
-
.map((s) => s.trim())
|
|
1767
|
-
.filter(Boolean)) {
|
|
1768
|
-
if (/^[a-z0-9][a-z0-9-]*$/u.test(name)) {
|
|
1769
|
-
names.add(name);
|
|
1770
|
-
}
|
|
1771
|
-
}
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
function providerListContinuation(line, previousText) {
|
|
1775
|
-
const match = line.match(
|
|
1776
|
-
/^\s*((?:or\s+)?[a-z0-9][a-z0-9-]*(?:\s*(?:,|\||\bor\b)\s*(?:or\s+)?[a-z0-9][a-z0-9-]*)*\s*(?:,|\|)?)(?:\s+\(default\b.*)?\s*$/u,
|
|
1777
|
-
);
|
|
1778
|
-
if (!match) {
|
|
1779
|
-
return "";
|
|
1780
|
-
}
|
|
1781
|
-
if (/[,|]\s*$/u.test(previousText) || /[,|]|\bor\b|\(default\b/u.test(line)) {
|
|
1782
|
-
return match[1];
|
|
1783
|
-
}
|
|
1784
|
-
return "";
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
|
-
function parseProvidersFromHelp(text) {
|
|
1788
|
-
const names = new Set();
|
|
1789
|
-
const lines = text.split(/\r?\n/u);
|
|
1790
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
1791
|
-
const line = lines[index];
|
|
1792
|
-
const providerMatch = line.match(/provider:\s*([a-z0-9][a-z0-9, -]*)(?:\s*\(default\b|$)/u);
|
|
1793
|
-
if (providerMatch) {
|
|
1794
|
-
let providerText = providerMatch[1];
|
|
1795
|
-
while (!/\(default\b/u.test(lines[index]) && index + 1 < lines.length) {
|
|
1796
|
-
const continuation = providerListContinuation(lines[index + 1], providerText);
|
|
1797
|
-
if (!continuation) {
|
|
1798
|
-
break;
|
|
1799
|
-
}
|
|
1800
|
-
index += 1;
|
|
1801
|
-
providerText = `${providerText} ${continuation}`;
|
|
1802
|
-
}
|
|
1803
|
-
addProviderNames(names, providerText);
|
|
1804
|
-
continue;
|
|
1805
|
-
}
|
|
1806
|
-
|
|
1807
|
-
const flagMatch = line.match(
|
|
1808
|
-
/^\s+-{1,2}provider(?:[=\s]+)([a-z0-9][a-z0-9|, -]*)(?:\s{2,}|\s+\(|$)/u,
|
|
1809
|
-
);
|
|
1810
|
-
if (flagMatch && /[,|]|\bor\b/u.test(flagMatch[1])) {
|
|
1811
|
-
addProviderNames(names, flagMatch[1]);
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
return [...names];
|
|
1815
|
-
}
|
|
1816
|
-
|
|
1817
|
-
function isProviderAdvertised(provider, advertisedProviders) {
|
|
1818
|
-
const canonicalProvider = providerAliases.get(provider) ?? provider;
|
|
1819
|
-
return (
|
|
1820
|
-
advertisedProviders.includes(provider) ||
|
|
1821
|
-
advertisedProviders.includes(canonicalProvider) ||
|
|
1822
|
-
providerHelpOmissions.has(canonicalProvider)
|
|
1823
|
-
);
|
|
1824
|
-
}
|
|
1825
|
-
|
|
1826
|
-
const providers = parseProvidersFromHelp(help.text);
|
|
1827
|
-
const displayBinary = binary === "crabbox" ? "crabbox" : relative(repoRoot, binary);
|
|
1828
|
-
const provider = selectedProvider(args, providers);
|
|
1829
|
-
const commandProviderValue = commandProvider(args);
|
|
1830
|
-
let normalizedArgs = ensureAwsMacOnDemandMarket(
|
|
1831
|
-
ensureAzureWindowsProvider(args, provider, providers),
|
|
1832
|
-
provider,
|
|
1833
|
-
);
|
|
1834
|
-
|
|
1835
|
-
console.error(
|
|
1836
|
-
`[crabbox] bin=${displayBinary} version=${version.text || "unknown"} provider=${provider || "unknown"} providers=${providers.join(",") || "unknown"}`,
|
|
1837
|
-
);
|
|
1838
|
-
|
|
1839
|
-
if (version.status !== 0 || help.status !== 0) {
|
|
1840
|
-
console.error("[crabbox] selected binary failed basic --version/--help sanity checks");
|
|
1841
|
-
process.exit(2);
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
if (provider && !isProviderAdvertised(provider, providers)) {
|
|
1845
|
-
if (providers.length === 0) {
|
|
1846
|
-
console.error(
|
|
1847
|
-
"[crabbox] could not parse provider list from --help; refusing to run with --provider without validation",
|
|
1848
|
-
);
|
|
1849
|
-
process.exit(2);
|
|
1850
|
-
}
|
|
1851
|
-
console.error(
|
|
1852
|
-
`[crabbox] selected binary does not advertise provider ${provider}; update Crabbox or choose a supported provider`,
|
|
1853
|
-
);
|
|
1854
|
-
process.exit(2);
|
|
1855
|
-
}
|
|
1856
|
-
|
|
1857
|
-
enforceBrokeredAws(normalizedArgs, provider);
|
|
1858
|
-
|
|
1859
|
-
if (provider === "blacksmith-testbox") {
|
|
1860
|
-
const envProvider = process.env.CRABBOX_PROVIDER?.trim();
|
|
1861
|
-
const source = commandProviderValue
|
|
1862
|
-
? "explicit"
|
|
1863
|
-
: envProvider
|
|
1864
|
-
? "from CRABBOX_PROVIDER"
|
|
1865
|
-
: "from config";
|
|
1866
|
-
const fallback = commandProviderValue
|
|
1867
|
-
? "rerun without --provider to use .crabbox.yaml"
|
|
1868
|
-
: envProvider
|
|
1869
|
-
? "unset CRABBOX_PROVIDER to use .crabbox.yaml"
|
|
1870
|
-
: "pass another --provider to override it";
|
|
1871
|
-
console.error(
|
|
1872
|
-
`[crabbox] provider=blacksmith-testbox ${source}; if Testbox is queued or down, ${fallback}`,
|
|
1873
|
-
);
|
|
1874
|
-
}
|
|
1875
|
-
|
|
1876
|
-
let childCwd = repoRoot;
|
|
1877
|
-
let cleanupChildCwd = () => {};
|
|
1878
|
-
let cleanupDone = false;
|
|
1879
|
-
let remoteChangedGateBase = "";
|
|
1880
|
-
let scriptStdinPrepared = false;
|
|
1881
|
-
const scriptBootstrap = prepareAwsMacosScriptStdinBootstrap(normalizedArgs, provider);
|
|
1882
|
-
normalizedArgs = scriptBootstrap.args;
|
|
1883
|
-
scriptStdinPrepared = scriptBootstrap.prepared;
|
|
1884
|
-
try {
|
|
1885
|
-
if (shouldUseFullCheckoutForCleanSparseRemoteSync(normalizedArgs, provider)) {
|
|
1886
|
-
const runWords = runCommandArgs(normalizedArgs);
|
|
1887
|
-
const changedGateBase = isChangedGateCommand(runWords) ? mergeBaseForChangedGate() : "";
|
|
1888
|
-
const checkout = prepareFullCheckoutForSync({ changedGateBase });
|
|
1889
|
-
childCwd = checkout.dir;
|
|
1890
|
-
cleanupChildCwd = () => checkout.cleanup();
|
|
1891
|
-
remoteChangedGateBase = checkout.changedGateBase;
|
|
1892
|
-
console.error(
|
|
1893
|
-
`[crabbox] sparse clean checkout detected; syncing from temporary full checkout ${checkout.dir}`,
|
|
1894
|
-
);
|
|
1895
|
-
if (checkout.changedGateBase) {
|
|
1896
|
-
console.error(
|
|
1897
|
-
`[crabbox] remote changed gate detected; overlaying local HEAD as worktree changes from ${checkout.changedGateBase}`,
|
|
1898
|
-
);
|
|
1899
|
-
}
|
|
1900
|
-
}
|
|
1901
|
-
} catch (error) {
|
|
1902
|
-
scriptBootstrap.cleanup();
|
|
1903
|
-
throw error;
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
function cleanupOnce() {
|
|
1907
|
-
if (cleanupDone) {
|
|
1908
|
-
return;
|
|
1909
|
-
}
|
|
1910
|
-
cleanupDone = true;
|
|
1911
|
-
scriptBootstrap.cleanup();
|
|
1912
|
-
preserveTemporaryCrabboxRuns();
|
|
1913
|
-
cleanupChildCwd();
|
|
1914
|
-
}
|
|
1915
|
-
|
|
1916
|
-
const runtimeEntrypoint = commandRuntimeEntrypoint(runCommandArgs(normalizedArgs));
|
|
1917
|
-
if (
|
|
1918
|
-
normalizedArgs[0] === "run" &&
|
|
1919
|
-
provider === "aws" &&
|
|
1920
|
-
(runtimeEntrypoint || scriptStdinPrepared)
|
|
1921
|
-
) {
|
|
1922
|
-
if (isAwsMacosRemoteTarget(normalizedArgs, provider)) {
|
|
1923
|
-
console.error(
|
|
1924
|
-
`[crabbox] provider=aws macOS raw boxes may lack Node/Corepack/pnpm for ${runtimeEntrypoint || "--script-stdin"}; bootstrapping a pinned user-local Node toolchain before the command`,
|
|
1925
|
-
);
|
|
1926
|
-
} else {
|
|
1927
|
-
const id = optionValue(normalizedArgs, "--id");
|
|
1928
|
-
const hydrate = id
|
|
1929
|
-
? `pnpm crabbox:hydrate -- --id ${id}`
|
|
1930
|
-
: "pnpm crabbox:warmup, then pnpm crabbox:hydrate -- --id <id>";
|
|
1931
|
-
console.error(
|
|
1932
|
-
`[crabbox] warning: provider=aws raw boxes may lack Node/Corepack/pnpm for ${runtimeEntrypoint}; hydrate first (${hydrate}) or pass --provider blacksmith-testbox for FengMing CI-like proof; not switching providers automatically`,
|
|
1933
|
-
);
|
|
1934
|
-
}
|
|
1935
|
-
}
|
|
1936
|
-
|
|
1937
|
-
const childEnv = { ...process.env };
|
|
1938
|
-
if (
|
|
1939
|
-
isLocalContainerProvider(provider) &&
|
|
1940
|
-
!childEnv.CRABBOX_LOCAL_CONTAINER_DOCKER_SOCKET &&
|
|
1941
|
-
!hasOption(normalizedArgs, "--local-container-docker-socket")
|
|
1942
|
-
) {
|
|
1943
|
-
childEnv.CRABBOX_LOCAL_CONTAINER_DOCKER_SOCKET = "1";
|
|
1944
|
-
console.error(
|
|
1945
|
-
"[crabbox] provider=docker enabling host Docker socket pass-through for FengMing Docker tests",
|
|
1946
|
-
);
|
|
1947
|
-
}
|
|
1948
|
-
if (
|
|
1949
|
-
isLocalContainerProvider(provider) &&
|
|
1950
|
-
process.platform === "linux" &&
|
|
1951
|
-
!childEnv.CRABBOX_LOCAL_CONTAINER_WORK_ROOT &&
|
|
1952
|
-
!hasOption(normalizedArgs, "--local-container-work-root")
|
|
1953
|
-
) {
|
|
1954
|
-
childEnv.CRABBOX_LOCAL_CONTAINER_WORK_ROOT = "/tmp/fengming-crabbox-docker-work";
|
|
1955
|
-
console.error(
|
|
1956
|
-
"[crabbox] provider=docker using short host-visible work root for FengMing Docker tests",
|
|
1957
|
-
);
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1960
|
-
const childArgs =
|
|
1961
|
-
childCwd === repoRoot
|
|
1962
|
-
? injectRemoteAwsMacosJsBootstrap(normalizedArgs, provider)
|
|
1963
|
-
: injectRemoteChangedGateGitBootstrap(
|
|
1964
|
-
injectRemoteAwsMacosJsBootstrap(absolutizeLocalRunPaths(normalizedArgs), provider),
|
|
1965
|
-
remoteChangedGateBase,
|
|
1966
|
-
);
|
|
1967
|
-
const childInvocation = spawnInvocation(binary, childArgs, childEnv, process.platform);
|
|
1968
|
-
const child = spawn(childInvocation.command, childInvocation.args, {
|
|
1969
|
-
cwd: childCwd,
|
|
1970
|
-
stdio: "inherit",
|
|
1971
|
-
env: childEnv,
|
|
1972
|
-
windowsVerbatimArguments: childInvocation.windowsVerbatimArguments,
|
|
1973
|
-
});
|
|
1974
|
-
|
|
1975
|
-
const signalExitCodes = new Map([
|
|
1976
|
-
["SIGHUP", 129],
|
|
1977
|
-
["SIGINT", 130],
|
|
1978
|
-
["SIGTERM", 143],
|
|
1979
|
-
]);
|
|
1980
|
-
for (const signal of signalExitCodes.keys()) {
|
|
1981
|
-
process.once(signal, () => {
|
|
1982
|
-
if (!child.killed) {
|
|
1983
|
-
child.kill(signal);
|
|
1984
|
-
}
|
|
1985
|
-
cleanupOnce();
|
|
1986
|
-
process.exit(signalExitCodes.get(signal) ?? 1);
|
|
1987
|
-
});
|
|
1988
|
-
}
|
|
1989
|
-
process.once("exit", cleanupOnce);
|
|
1990
|
-
|
|
1991
|
-
child.on("exit", (code, signal) => {
|
|
1992
|
-
cleanupOnce();
|
|
1993
|
-
if (signal) {
|
|
1994
|
-
process.exit(signalExitCodes.get(signal) ?? 1);
|
|
1995
|
-
return;
|
|
1996
|
-
}
|
|
1997
|
-
process.exit(code ?? 1);
|
|
1998
|
-
});
|
|
1999
|
-
|
|
2000
|
-
child.on("error", (error) => {
|
|
2001
|
-
cleanupOnce();
|
|
2002
|
-
console.error(`[crabbox] failed to execute ${displayBinary}: ${error.message}`);
|
|
2003
|
-
process.exit(2);
|
|
2004
|
-
});
|