@oriro/orirocli 0.1.11 → 0.3.1
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/ATTRIBUTION.md +53 -53
- package/LICENSE +21 -21
- package/README.md +10 -9
- package/dist/cli.js +1866 -190
- package/package.json +65 -64
- package/skills/1password/SKILL.md +118 -118
- package/skills/1password/references/cli-examples.md +29 -29
- package/skills/1password/references/get-started.md +21 -21
- package/skills/21stdev/SKILL.md +64 -64
- package/skills/algorithmic-art/LICENSE +21 -21
- package/skills/algorithmic-art/SKILL.md +446 -446
- package/skills/algorithmic-art/templates/generator_template.js +223 -223
- package/skills/algorithmic-art/templates/viewer.html +598 -598
- package/skills/apple-notes/SKILL.md +81 -81
- package/skills/apple-reminders/SKILL.md +122 -122
- package/skills/bear-notes/SKILL.md +111 -111
- package/skills/blogwatcher/SKILL.md +73 -73
- package/skills/blucli/SKILL.md +51 -51
- package/skills/brand-guidelines/LICENSE +21 -21
- package/skills/brand-guidelines/SKILL.md +76 -76
- package/skills/business/biz-analysis/LICENSE +21 -21
- package/skills/business/biz-analysis/SKILL.md +103 -103
- package/skills/business/biz-corporate-strategy/LICENSE +21 -21
- package/skills/business/biz-corporate-strategy/SKILL.md +76 -76
- package/skills/business/biz-customer-success/LICENSE +21 -21
- package/skills/business/biz-customer-success/SKILL.md +55 -55
- package/skills/business/biz-entrepreneurship/LICENSE +21 -21
- package/skills/business/biz-entrepreneurship/SKILL.md +72 -72
- package/skills/business/biz-hr/LICENSE +21 -21
- package/skills/business/biz-hr/SKILL.md +67 -67
- package/skills/business/biz-international/LICENSE +21 -21
- package/skills/business/biz-international/SKILL.md +51 -51
- package/skills/business/biz-leadership/LICENSE +21 -21
- package/skills/business/biz-leadership/SKILL.md +106 -106
- package/skills/business/biz-marketing-strategy/LICENSE +21 -21
- package/skills/business/biz-marketing-strategy/SKILL.md +119 -119
- package/skills/business/biz-negotiation/LICENSE +21 -21
- package/skills/business/biz-negotiation/SKILL.md +152 -152
- package/skills/business/biz-operations/LICENSE +21 -21
- package/skills/business/biz-operations/SKILL.md +74 -74
- package/skills/business/biz-project/LICENSE +21 -21
- package/skills/business/biz-project/SKILL.md +203 -203
- package/skills/business/biz-risk/LICENSE +21 -21
- package/skills/business/biz-risk/SKILL.md +85 -85
- package/skills/business/biz-sales/LICENSE +21 -21
- package/skills/business/biz-sales/SKILL.md +92 -92
- package/skills/business/biz-startup-ops/LICENSE +21 -21
- package/skills/business/biz-startup-ops/SKILL.md +70 -70
- package/skills/business/biz-strategy/LICENSE +21 -21
- package/skills/business/biz-strategy/SKILL.md +233 -233
- package/skills/business/biz-supply-chain-advanced/LICENSE +21 -21
- package/skills/business/biz-supply-chain-advanced/SKILL.md +68 -68
- package/skills/business/fin-chartered-exams/LICENSE +21 -21
- package/skills/business/fin-chartered-exams/SKILL.md +69 -69
- package/skills/camsnap/SKILL.md +49 -49
- package/skills/canvas/SKILL.md +82 -82
- package/skills/canvas-design/LICENSE +21 -21
- package/skills/canvas-design/SKILL.md +140 -140
- package/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -94
- package/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -93
- package/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -93
- package/skills/coding-agent/SKILL.md +146 -146
- package/skills/communication/comm-business-writing/LICENSE +21 -21
- package/skills/communication/comm-business-writing/SKILL.md +67 -67
- package/skills/communication/comm-cross-cultural/LICENSE +21 -21
- package/skills/communication/comm-cross-cultural/SKILL.md +88 -88
- package/skills/communication/comm-journalism/LICENSE +21 -21
- package/skills/communication/comm-journalism/SKILL.md +81 -81
- package/skills/communication/comm-linguistics/LICENSE +21 -21
- package/skills/communication/comm-linguistics/SKILL.md +82 -82
- package/skills/communication/comm-negotiation/LICENSE +21 -21
- package/skills/communication/comm-negotiation/SKILL.md +120 -120
- package/skills/communication/comm-presentations/LICENSE +21 -21
- package/skills/communication/comm-presentations/SKILL.md +93 -93
- package/skills/communication/comm-public-speaking/LICENSE +21 -21
- package/skills/communication/comm-public-speaking/SKILL.md +68 -68
- package/skills/communication/comm-writing/LICENSE +21 -21
- package/skills/communication/comm-writing/SKILL.md +69 -69
- package/skills/craft/ai-engineering/LICENSE +21 -21
- package/skills/craft/ai-engineering/SKILL.md +828 -828
- package/skills/craft/app-builder-guide/LICENSE +21 -21
- package/skills/craft/app-builder-guide/SKILL.md +332 -332
- package/skills/craft/become-an-ai-engineer-26/CONTRIBUTING.md +46 -46
- package/skills/craft/become-an-ai-engineer-26/LICENSE +21 -21
- package/skills/craft/become-an-ai-engineer-26/README.md +270 -270
- package/skills/craft/become-an-ai-engineer-26/SKILL.md +667 -667
- package/skills/craft/become-an-ai-engineer-26/community/BUILDS.md +13 -13
- package/skills/craft/become-an-ai-engineer-26/community/DISCUSSIONS.md +8 -8
- package/skills/craft/become-an-ai-engineer-26/phases/phase-0-mental-models/README.md +14 -14
- package/skills/craft/become-an-ai-engineer-26/phases/phase-0-mental-models/project/TEMPLATE.md +33 -33
- package/skills/craft/become-an-ai-engineer-26/phases/phase-1-first-agent/README.md +25 -25
- package/skills/craft/become-an-ai-engineer-26/phases/phase-1-first-agent/code/raw_loop.py +126 -126
- package/skills/craft/become-an-ai-engineer-26/phases/phase-2-architecture/README.md +17 -17
- package/skills/craft/become-an-ai-engineer-26/phases/phase-3-harness/README.md +17 -17
- package/skills/craft/become-an-ai-engineer-26/phases/phase-4-evals/README.md +21 -21
- package/skills/craft/become-an-ai-engineer-26/phases/phase-4-evals/code/.github/workflows/eval.yml +40 -40
- package/skills/craft/become-an-ai-engineer-26/phases/phase-5-production/README.md +16 -16
- package/skills/craft/become-an-ai-engineer-26/projects/1-mobile-app-slm/README.md +11 -11
- package/skills/craft/become-an-ai-engineer-26/projects/2-self-improving-coder/README.md +11 -11
- package/skills/craft/become-an-ai-engineer-26/projects/3-video-editor-agent/README.md +11 -11
- package/skills/craft/become-an-ai-engineer-26/projects/4-personal-life-os/README.md +12 -12
- package/skills/craft/become-an-ai-engineer-26/projects/5-enterprise-workflow/README.md +12 -12
- package/skills/craft/become-an-ai-engineer-26/references/benchmark-numbers.md +41 -41
- package/skills/craft/become-an-ai-engineer-26/references/mhc-stable-training.md +73 -73
- package/skills/craft/become-an-ai-engineer-26/references/stack-decisions.md +37 -37
- package/skills/craft/become-an-ai-engineer-26/references/yarn-context-extension.md +123 -123
- package/skills/craft/codex-result-handling/LICENSE +21 -21
- package/skills/craft/codex-result-handling/SKILL.md +26 -26
- package/skills/craft/debug-and-build-methodology/LICENSE +21 -21
- package/skills/craft/debug-and-build-methodology/SKILL.md +432 -432
- package/skills/craft/design/LICENSE +21 -21
- package/skills/craft/design/SKILL.md +274 -274
- package/skills/craft/dev/LICENSE +21 -21
- package/skills/craft/dev/SKILL.md +12 -12
- package/skills/craft/dev/release.md +85 -85
- package/skills/craft/dev/roll.md +50 -50
- package/skills/craft/doc-coauthoring/LICENSE +21 -21
- package/skills/craft/doc-coauthoring/SKILL.md +397 -397
- package/skills/craft/focus/LICENSE +21 -21
- package/skills/craft/focus/SKILL.md +432 -432
- package/skills/craft/focus/UPSTREAM_README.md +233 -233
- package/skills/craft/gh/LICENSE +21 -21
- package/skills/craft/gh/SKILL.md +84 -84
- package/skills/craft/gh-skill/LICENSE +21 -21
- package/skills/craft/gh-skill/SKILL.md +121 -121
- package/skills/craft/godmode/LICENSE +21 -21
- package/skills/craft/godmode/SKILL.md +87 -87
- package/skills/craft/godmode/references/android-launch.md +680 -680
- package/skills/craft/godmode/references/data-gcp.md +1038 -1038
- package/skills/craft/godmode/references/expo-eas.md +816 -816
- package/skills/craft/godmode/references/ios-launch.md +734 -734
- package/skills/craft/google-ai-latest/LICENSE +21 -21
- package/skills/craft/google-ai-latest/SKILL.md +682 -682
- package/skills/craft/gpt-5-4-prompting/LICENSE +21 -21
- package/skills/craft/gpt-5-4-prompting/SKILL.md +63 -63
- package/skills/craft/gpt-5-4-prompting/references/codex-prompt-antipatterns.md +101 -101
- package/skills/craft/gpt-5-4-prompting/references/codex-prompt-recipes.md +150 -150
- package/skills/craft/gpt-5-4-prompting/references/prompt-blocks.md +172 -172
- package/skills/craft/grill-me/LICENSE +21 -21
- package/skills/craft/grill-me/SKILL.md +13 -13
- package/skills/craft/idea-to-deploy/LICENSE +21 -21
- package/skills/craft/idea-to-deploy/SKILL.md +292 -292
- package/skills/craft/idea-to-deploy/references/auth-playbook.md +195 -195
- package/skills/craft/idea-to-deploy/references/gcp-deployment.md +268 -268
- package/skills/craft/idea-to-deploy/references/stack-selection.md +117 -117
- package/skills/craft/image-generation-engineer/LICENSE +21 -21
- package/skills/craft/image-generation-engineer/SKILL.md +183 -183
- package/skills/craft/image-generation-engineer/references/architectures.md +260 -260
- package/skills/craft/image-generation-engineer/references/foundations.md +107 -107
- package/skills/craft/image-generation-engineer/references/inference-and-serving.md +253 -253
- package/skills/craft/image-generation-engineer/references/training.md +149 -149
- package/skills/craft/marketing/LICENSE +21 -21
- package/skills/craft/marketing/SKILL.md +1954 -1954
- package/skills/craft/master-architect/LICENSE +21 -21
- package/skills/craft/master-architect/SKILL.md +361 -361
- package/skills/craft/master-architect/references/ai-ml.md +317 -317
- package/skills/craft/master-architect/references/architecture.md +268 -268
- package/skills/craft/master-architect/references/auth-playbook.md +195 -195
- package/skills/craft/master-architect/references/cloud.md +323 -323
- package/skills/craft/master-architect/references/cyber.md +839 -839
- package/skills/craft/master-architect/references/data-eng.md +366 -366
- package/skills/craft/master-architect/references/devops.md +550 -550
- package/skills/craft/master-architect/references/gcp-deployment.md +268 -268
- package/skills/craft/master-architect/references/languages.md +748 -748
- package/skills/craft/master-architect/references/legacy.md +240 -240
- package/skills/craft/master-architect/references/mobile.md +447 -447
- package/skills/craft/master-architect/references/patterns.md +451 -451
- package/skills/craft/master-architect/references/saas-patterns.md +379 -379
- package/skills/craft/master-architect/references/sdlc.md +349 -349
- package/skills/craft/master-architect/references/stack-selection.md +117 -117
- package/skills/craft/oriro-ui-2026/LICENSE +21 -21
- package/skills/craft/oriro-ui-2026/SKILL.md +329 -329
- package/skills/craft/playwright-cli/LICENSE +21 -21
- package/skills/craft/playwright-cli/SKILL.md +393 -393
- package/skills/craft/playwright-cli/references/element-attributes.md +23 -23
- package/skills/craft/playwright-cli/references/playwright-tests.md +39 -39
- package/skills/craft/playwright-cli/references/request-mocking.md +87 -87
- package/skills/craft/playwright-cli/references/running-code.md +240 -240
- package/skills/craft/playwright-cli/references/session-management.md +226 -226
- package/skills/craft/playwright-cli/references/spec-driven-testing.md +312 -312
- package/skills/craft/playwright-cli/references/storage-state.md +275 -275
- package/skills/craft/playwright-cli/references/test-generation.md +134 -134
- package/skills/craft/playwright-cli/references/tracing.md +142 -142
- package/skills/craft/playwright-cli/references/video-recording.md +150 -150
- package/skills/craft/remotion-best-practices/LICENSE +21 -21
- package/skills/craft/remotion-best-practices/SKILL.md +345 -345
- package/skills/craft/remotion-best-practices/rules/3d.md +86 -86
- package/skills/craft/remotion-best-practices/rules/assets/charts-bar-chart.tsx +165 -165
- package/skills/craft/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +89 -89
- package/skills/craft/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +101 -101
- package/skills/craft/remotion-best-practices/rules/audio-visualization.md +195 -195
- package/skills/craft/remotion-best-practices/rules/audio.md +167 -167
- package/skills/craft/remotion-best-practices/rules/calculate-metadata.md +118 -118
- package/skills/craft/remotion-best-practices/rules/compositions.md +132 -132
- package/skills/craft/remotion-best-practices/rules/display-captions.md +176 -176
- package/skills/craft/remotion-best-practices/rules/ffmpeg.md +34 -34
- package/skills/craft/remotion-best-practices/rules/get-audio-duration.md +58 -58
- package/skills/craft/remotion-best-practices/rules/get-video-dimensions.md +68 -68
- package/skills/craft/remotion-best-practices/rules/get-video-duration.md +60 -60
- package/skills/craft/remotion-best-practices/rules/gifs.md +135 -135
- package/skills/craft/remotion-best-practices/rules/google-fonts.md +72 -72
- package/skills/craft/remotion-best-practices/rules/html-in-canvas.md +122 -122
- package/skills/craft/remotion-best-practices/rules/images.md +67 -67
- package/skills/craft/remotion-best-practices/rules/import-srt-captions.md +69 -69
- package/skills/craft/remotion-best-practices/rules/light-leaks.md +73 -73
- package/skills/craft/remotion-best-practices/rules/local-fonts.md +65 -65
- package/skills/craft/remotion-best-practices/rules/lottie.md +67 -67
- package/skills/craft/remotion-best-practices/rules/maplibre.md +441 -441
- package/skills/craft/remotion-best-practices/rules/measuring-dom-nodes.md +34 -34
- package/skills/craft/remotion-best-practices/rules/measuring-text.md +140 -140
- package/skills/craft/remotion-best-practices/rules/parameters.md +109 -109
- package/skills/craft/remotion-best-practices/rules/sequencing.md +144 -144
- package/skills/craft/remotion-best-practices/rules/sfx.md +30 -30
- package/skills/craft/remotion-best-practices/rules/silence-detection.md +73 -73
- package/skills/craft/remotion-best-practices/rules/subtitles.md +36 -36
- package/skills/craft/remotion-best-practices/rules/tailwind.md +11 -11
- package/skills/craft/remotion-best-practices/rules/text-animations.md +20 -20
- package/skills/craft/remotion-best-practices/rules/timing.md +130 -130
- package/skills/craft/remotion-best-practices/rules/transcribe-captions.md +70 -70
- package/skills/craft/remotion-best-practices/rules/transitions.md +193 -193
- package/skills/craft/remotion-best-practices/rules/transparent-videos.md +102 -102
- package/skills/craft/remotion-best-practices/rules/trimming.md +51 -51
- package/skills/craft/remotion-best-practices/rules/videos.md +169 -169
- package/skills/craft/remotion-best-practices/rules/voiceover.md +94 -94
- package/skills/craft/supabase-postgres-best-practices/CHANGELOG.md +25 -25
- package/skills/craft/supabase-postgres-best-practices/LICENSE +21 -21
- package/skills/craft/supabase-postgres-best-practices/SKILL.md +69 -69
- package/skills/craft/supabase-postgres-best-practices/references/_contributing.md +166 -166
- package/skills/craft/supabase-postgres-best-practices/references/_sections.md +47 -47
- package/skills/craft/supabase-postgres-best-practices/references/_template.md +34 -34
- package/skills/craft/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -55
- package/skills/craft/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -49
- package/skills/craft/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -46
- package/skills/craft/supabase-postgres-best-practices/references/conn-limits.md +44 -44
- package/skills/craft/supabase-postgres-best-practices/references/conn-pooling.md +41 -41
- package/skills/craft/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -46
- package/skills/craft/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -54
- package/skills/craft/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -53
- package/skills/craft/supabase-postgres-best-practices/references/data-pagination.md +50 -50
- package/skills/craft/supabase-postgres-best-practices/references/data-upsert.md +50 -50
- package/skills/craft/supabase-postgres-best-practices/references/lock-advisory.md +56 -56
- package/skills/craft/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -68
- package/skills/craft/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -50
- package/skills/craft/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -54
- package/skills/craft/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -45
- package/skills/craft/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -55
- package/skills/craft/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -55
- package/skills/craft/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -44
- package/skills/craft/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -40
- package/skills/craft/supabase-postgres-best-practices/references/query-index-types.md +48 -48
- package/skills/craft/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -43
- package/skills/craft/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -45
- package/skills/craft/supabase-postgres-best-practices/references/schema-constraints.md +80 -80
- package/skills/craft/supabase-postgres-best-practices/references/schema-data-types.md +46 -46
- package/skills/craft/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -59
- package/skills/craft/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -55
- package/skills/craft/supabase-postgres-best-practices/references/schema-partitioning.md +55 -55
- package/skills/craft/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -61
- package/skills/craft/supabase-postgres-best-practices/references/security-privileges.md +54 -54
- package/skills/craft/supabase-postgres-best-practices/references/security-rls-basics.md +50 -50
- package/skills/craft/supabase-postgres-best-practices/references/security-rls-performance.md +63 -63
- package/skills/craft/uipm-banner-design/LICENSE +21 -21
- package/skills/craft/uipm-banner-design/SKILL.md +201 -201
- package/skills/craft/uipm-banner-design/references/banner-sizes-and-styles.md +129 -129
- package/skills/craft/uipm-brand/LICENSE +21 -21
- package/skills/craft/uipm-brand/SKILL.md +104 -104
- package/skills/craft/uipm-brand/references/approval-checklist.md +184 -184
- package/skills/craft/uipm-brand/references/asset-organization.md +167 -167
- package/skills/craft/uipm-brand/references/brand-guideline-template.md +161 -161
- package/skills/craft/uipm-brand/references/color-palette-management.md +203 -203
- package/skills/craft/uipm-brand/references/consistency-checklist.md +105 -105
- package/skills/craft/uipm-brand/references/logo-usage-rules.md +204 -204
- package/skills/craft/uipm-brand/references/messaging-framework.md +91 -91
- package/skills/craft/uipm-brand/references/typography-specifications.md +265 -265
- package/skills/craft/uipm-brand/references/update.md +128 -128
- package/skills/craft/uipm-brand/references/visual-identity.md +109 -109
- package/skills/craft/uipm-brand/references/voice-framework.md +99 -99
- package/skills/craft/uipm-brand/scripts/extract-colors.cjs +333 -333
- package/skills/craft/uipm-brand/scripts/inject-brand-context.cjs +324 -324
- package/skills/craft/uipm-brand/scripts/sync-brand-to-tokens.cjs +269 -269
- package/skills/craft/uipm-brand/scripts/validate-asset.cjs +361 -361
- package/skills/craft/uipm-brand/templates/brand-guidelines-starter.md +280 -280
- package/skills/craft/uipm-design/LICENSE +21 -21
- package/skills/craft/uipm-design/SKILL.md +305 -305
- package/skills/craft/uipm-design/data/cip/deliverables.csv +50 -50
- package/skills/craft/uipm-design/data/cip/industries.csv +20 -20
- package/skills/craft/uipm-design/data/cip/mockup-contexts.csv +20 -20
- package/skills/craft/uipm-design/data/cip/styles.csv +20 -20
- package/skills/craft/uipm-design/data/icon/styles.csv +16 -16
- package/skills/craft/uipm-design/data/logo/colors.csv +56 -56
- package/skills/craft/uipm-design/data/logo/industries.csv +56 -56
- package/skills/craft/uipm-design/data/logo/styles.csv +56 -56
- package/skills/craft/uipm-design/references/banner-sizes-and-styles.md +129 -129
- package/skills/craft/uipm-design/references/cip-deliverable-guide.md +111 -111
- package/skills/craft/uipm-design/references/cip-design.md +121 -121
- package/skills/craft/uipm-design/references/cip-prompt-engineering.md +94 -94
- package/skills/craft/uipm-design/references/cip-style-guide.md +76 -76
- package/skills/craft/uipm-design/references/design-routing.md +226 -226
- package/skills/craft/uipm-design/references/icon-design.md +122 -122
- package/skills/craft/uipm-design/references/logo-color-psychology.md +113 -113
- package/skills/craft/uipm-design/references/logo-design.md +92 -92
- package/skills/craft/uipm-design/references/logo-prompt-engineering.md +176 -176
- package/skills/craft/uipm-design/references/logo-style-guide.md +129 -129
- package/skills/craft/uipm-design/references/slides-copywriting-formulas.md +92 -92
- package/skills/craft/uipm-design/references/slides-create.md +5 -5
- package/skills/craft/uipm-design/references/slides-html-template.md +374 -374
- package/skills/craft/uipm-design/references/slides-layout-patterns.md +155 -155
- package/skills/craft/uipm-design/references/slides-strategies.md +97 -97
- package/skills/craft/uipm-design/references/slides.md +42 -42
- package/skills/craft/uipm-design/references/social-photos-design.md +353 -353
- package/skills/craft/uipm-design/scripts/cip/core.py +215 -215
- package/skills/craft/uipm-design/scripts/cip/generate.py +484 -484
- package/skills/craft/uipm-design/scripts/cip/render-html.py +424 -424
- package/skills/craft/uipm-design/scripts/cip/search.py +127 -127
- package/skills/craft/uipm-design/scripts/icon/generate.py +487 -487
- package/skills/craft/uipm-design/scripts/logo/core.py +175 -175
- package/skills/craft/uipm-design/scripts/logo/generate.py +362 -362
- package/skills/craft/uipm-design/scripts/logo/search.py +114 -114
- package/skills/craft/uipm-design-system/LICENSE +21 -21
- package/skills/craft/uipm-design-system/SKILL.md +255 -255
- package/skills/craft/uipm-design-system/data/slide-backgrounds.csv +11 -11
- package/skills/craft/uipm-design-system/data/slide-charts.csv +26 -26
- package/skills/craft/uipm-design-system/data/slide-color-logic.csv +14 -14
- package/skills/craft/uipm-design-system/data/slide-copy.csv +26 -26
- package/skills/craft/uipm-design-system/data/slide-layout-logic.csv +16 -16
- package/skills/craft/uipm-design-system/data/slide-layouts.csv +26 -26
- package/skills/craft/uipm-design-system/data/slide-strategies.csv +16 -16
- package/skills/craft/uipm-design-system/data/slide-typography.csv +15 -15
- package/skills/craft/uipm-design-system/references/component-specs.md +236 -236
- package/skills/craft/uipm-design-system/references/component-tokens.md +214 -214
- package/skills/craft/uipm-design-system/references/primitive-tokens.md +199 -199
- package/skills/craft/uipm-design-system/references/semantic-tokens.md +215 -215
- package/skills/craft/uipm-design-system/references/states-and-variants.md +243 -243
- package/skills/craft/uipm-design-system/references/tailwind-integration.md +257 -257
- package/skills/craft/uipm-design-system/references/token-architecture.md +226 -226
- package/skills/craft/uipm-design-system/scripts/embed-tokens.cjs +97 -97
- package/skills/craft/uipm-design-system/scripts/fetch-background.py +317 -317
- package/skills/craft/uipm-design-system/scripts/generate-slide.py +753 -753
- package/skills/craft/uipm-design-system/scripts/generate-tokens.cjs +213 -213
- package/skills/craft/uipm-design-system/scripts/html-token-validator.py +327 -327
- package/skills/craft/uipm-design-system/scripts/search-slides.py +218 -218
- package/skills/craft/uipm-design-system/scripts/slide-token-validator.py +35 -35
- package/skills/craft/uipm-design-system/scripts/slide_search_core.py +453 -453
- package/skills/craft/uipm-design-system/scripts/validate-tokens.cjs +254 -254
- package/skills/craft/uipm-design-system/templates/design-tokens-starter.json +143 -143
- package/skills/craft/uipm-slides/LICENSE +21 -21
- package/skills/craft/uipm-slides/SKILL.md +45 -45
- package/skills/craft/uipm-slides/references/copywriting-formulas.md +92 -92
- package/skills/craft/uipm-slides/references/create.md +5 -5
- package/skills/craft/uipm-slides/references/html-template.md +374 -374
- package/skills/craft/uipm-slides/references/layout-patterns.md +155 -155
- package/skills/craft/uipm-slides/references/slide-strategies.md +97 -97
- package/skills/craft/uipm-ui-ux-pro-max/LICENSE +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/SKILL.md +678 -678
- package/skills/craft/uipm-ui-ux-pro-max/data/_sync_all.py +414 -414
- package/skills/craft/uipm-ui-ux-pro-max/data/app-interface.csv +30 -30
- package/skills/craft/uipm-ui-ux-pro-max/data/charts.csv +26 -26
- package/skills/craft/uipm-ui-ux-pro-max/data/colors.csv +161 -161
- package/skills/craft/uipm-ui-ux-pro-max/data/design.csv +1775 -1775
- package/skills/craft/uipm-ui-ux-pro-max/data/draft.csv +1778 -1778
- package/skills/craft/uipm-ui-ux-pro-max/data/google-fonts.csv +1924 -1924
- package/skills/craft/uipm-ui-ux-pro-max/data/icons.csv +105 -105
- package/skills/craft/uipm-ui-ux-pro-max/data/landing.csv +35 -35
- package/skills/craft/uipm-ui-ux-pro-max/data/products.csv +162 -162
- package/skills/craft/uipm-ui-ux-pro-max/data/react-performance.csv +45 -45
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/angular.csv +51 -51
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/astro.csv +54 -54
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/flutter.csv +53 -53
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/laravel.csv +51 -51
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/react-native.csv +52 -52
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/react.csv +54 -54
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/svelte.csv +54 -54
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/threejs.csv +54 -54
- package/skills/craft/uipm-ui-ux-pro-max/data/stacks/vue.csv +50 -50
- package/skills/craft/uipm-ui-ux-pro-max/data/styles.csv +85 -85
- package/skills/craft/uipm-ui-ux-pro-max/data/typography.csv +74 -74
- package/skills/craft/uipm-ui-ux-pro-max/data/ui-reasoning.csv +162 -162
- package/skills/craft/uipm-ui-ux-pro-max/data/ux-guidelines.csv +99 -99
- package/skills/craft/uipm-ui-ux-pro-max/scripts/core.py +262 -262
- package/skills/craft/uipm-ui-ux-pro-max/scripts/design_system.py +1148 -1148
- package/skills/craft/uipm-ui-ux-pro-max/scripts/search.py +114 -114
- package/skills/craft/uipm-ui-ux-pro-max/templates/base/quick-reference.md +297 -297
- package/skills/craft/uipm-ui-ux-pro-max/templates/base/skill-content.md +375 -375
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/agent.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/augment.json +18 -18
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/claude.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/codebuddy.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/codex.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/continue.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/copilot.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/cursor.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/droid.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/gemini.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/kilocode.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/kiro.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/opencode.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/qoder.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/roocode.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/trae.json +21 -21
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/warp.json +18 -18
- package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/windsurf.json +21 -21
- package/skills/craft/vercel-optimize/AGENTS.md +48 -48
- package/skills/craft/vercel-optimize/CONTRIBUTING.md +41 -41
- package/skills/craft/vercel-optimize/LICENSE +21 -21
- package/skills/craft/vercel-optimize/README.md +91 -91
- package/skills/craft/vercel-optimize/SKILL.md +325 -325
- package/skills/craft/vercel-optimize/lib/auth-route.mjs +23 -23
- package/skills/craft/vercel-optimize/lib/budget-summary.mjs +208 -208
- package/skills/craft/vercel-optimize/lib/citations.mjs +147 -147
- package/skills/craft/vercel-optimize/lib/cost-coverage.mjs +162 -162
- package/skills/craft/vercel-optimize/lib/dedup-recs.mjs +340 -340
- package/skills/craft/vercel-optimize/lib/deep-dive.mjs +371 -371
- package/skills/craft/vercel-optimize/lib/display-labels.mjs +219 -219
- package/skills/craft/vercel-optimize/lib/extract-claims.mjs +640 -640
- package/skills/craft/vercel-optimize/lib/framework-support.mjs +69 -69
- package/skills/craft/vercel-optimize/lib/gates/build-minutes-fanout.mjs +73 -73
- package/skills/craft/vercel-optimize/lib/gates/cold-start.mjs +72 -72
- package/skills/craft/vercel-optimize/lib/gates/contract.mjs +82 -82
- package/skills/craft/vercel-optimize/lib/gates/cwv-poor.mjs +95 -95
- package/skills/craft/vercel-optimize/lib/gates/external-api-slow.mjs +60 -60
- package/skills/craft/vercel-optimize/lib/gates/hard-gates.mjs +70 -70
- package/skills/craft/vercel-optimize/lib/gates/index.mjs +45 -45
- package/skills/craft/vercel-optimize/lib/gates/isr-overrevalidation.mjs +62 -62
- package/skills/craft/vercel-optimize/lib/gates/middleware-heavy.mjs +53 -53
- package/skills/craft/vercel-optimize/lib/gates/observability-events-attribution.mjs +58 -58
- package/skills/craft/vercel-optimize/lib/gates/platform-bot-protection.mjs +123 -123
- package/skills/craft/vercel-optimize/lib/gates/platform-fluid-compute.mjs +94 -94
- package/skills/craft/vercel-optimize/lib/gates/region-misconfig.mjs +71 -71
- package/skills/craft/vercel-optimize/lib/gates/route-errors.mjs +95 -95
- package/skills/craft/vercel-optimize/lib/gates/scanner-driven.mjs +150 -150
- package/skills/craft/vercel-optimize/lib/gates/select-candidates.mjs +137 -137
- package/skills/craft/vercel-optimize/lib/gates/slow-route.mjs +97 -97
- package/skills/craft/vercel-optimize/lib/gates/types.d.ts +38 -38
- package/skills/craft/vercel-optimize/lib/gates/uncached-route.mjs +103 -103
- package/skills/craft/vercel-optimize/lib/gates/usage-spike-triage.mjs +122 -122
- package/skills/craft/vercel-optimize/lib/grade-recommendation.mjs +170 -170
- package/skills/craft/vercel-optimize/lib/impact-label.mjs +128 -128
- package/skills/craft/vercel-optimize/lib/impact-magnitude.mjs +66 -66
- package/skills/craft/vercel-optimize/lib/investigation-brief.mjs +751 -751
- package/skills/craft/vercel-optimize/lib/observation-safety.mjs +217 -217
- package/skills/craft/vercel-optimize/lib/project-facts.mjs +101 -101
- package/skills/craft/vercel-optimize/lib/queries.mjs +333 -333
- package/skills/craft/vercel-optimize/lib/reconcile-candidates.mjs +388 -388
- package/skills/craft/vercel-optimize/lib/render-report.mjs +1065 -1065
- package/skills/craft/vercel-optimize/lib/repo-root.mjs +97 -97
- package/skills/craft/vercel-optimize/lib/route-normalize.mjs +224 -224
- package/skills/craft/vercel-optimize/lib/sanitizers/bot-protection-certainty.mjs +56 -56
- package/skills/craft/vercel-optimize/lib/sanitizers/cache-tag-invalidation-certainty.mjs +33 -33
- package/skills/craft/vercel-optimize/lib/sanitizers/count-correct.mjs +53 -53
- package/skills/craft/vercel-optimize/lib/sanitizers/function-duration-invocations.mjs +32 -32
- package/skills/craft/vercel-optimize/lib/sanitizers/index.mjs +87 -87
- package/skills/craft/vercel-optimize/lib/sanitizers/middleware-conflict.mjs +37 -37
- package/skills/craft/vercel-optimize/lib/sanitizers/missing-citation.mjs +16 -16
- package/skills/craft/vercel-optimize/lib/sanitizers/pre-release.mjs +75 -75
- package/skills/craft/vercel-optimize/lib/sanitizers/rate-limit.mjs +73 -73
- package/skills/craft/vercel-optimize/lib/sanitizers/rendering-mode-mislabel.mjs +42 -42
- package/skills/craft/vercel-optimize/lib/sanitizers/undeclared-dep.mjs +110 -110
- package/skills/craft/vercel-optimize/lib/sanitizers/vercel-directive-strip.mjs +37 -37
- package/skills/craft/vercel-optimize/lib/sanitizers/window-units.mjs +26 -26
- package/skills/craft/vercel-optimize/lib/scanners/cache-components-suspense-dedupe.mjs +114 -114
- package/skills/craft/vercel-optimize/lib/scanners/edge-heavy-import.mjs +102 -102
- package/skills/craft/vercel-optimize/lib/scanners/force-dynamic.mjs +39 -39
- package/skills/craft/vercel-optimize/lib/scanners/headers-in-page.mjs +43 -43
- package/skills/craft/vercel-optimize/lib/scanners/index.mjs +35 -35
- package/skills/craft/vercel-optimize/lib/scanners/large-static-asset.mjs +93 -93
- package/skills/craft/vercel-optimize/lib/scanners/max-age-without-s-maxage.mjs +47 -47
- package/skills/craft/vercel-optimize/lib/scanners/middleware-broad-matcher.mjs +53 -53
- package/skills/craft/vercel-optimize/lib/scanners/missing-cache-headers.mjs +97 -97
- package/skills/craft/vercel-optimize/lib/scanners/prisma-include-tree.mjs +39 -39
- package/skills/craft/vercel-optimize/lib/scanners/region-pin-in-config.mjs +89 -89
- package/skills/craft/vercel-optimize/lib/scanners/source-maps-production.mjs +33 -33
- package/skills/craft/vercel-optimize/lib/scanners/sveltekit-prerender-missing.mjs +47 -47
- package/skills/craft/vercel-optimize/lib/scanners/turbo-force-bypass.mjs +136 -136
- package/skills/craft/vercel-optimize/lib/scanners/unoptimized-image.mjs +127 -127
- package/skills/craft/vercel-optimize/lib/scanners/use-cache-date-stamp.mjs +112 -112
- package/skills/craft/vercel-optimize/lib/support-topics.mjs +365 -365
- package/skills/craft/vercel-optimize/lib/throttle.mjs +280 -280
- package/skills/craft/vercel-optimize/lib/util.mjs +17 -17
- package/skills/craft/vercel-optimize/lib/vercel.mjs +855 -855
- package/skills/craft/vercel-optimize/lib/verify-claim.mjs +1843 -1843
- package/skills/craft/vercel-optimize/lib/workspace-resolver.mjs +552 -552
- package/skills/craft/vercel-optimize/metadata.json +14 -14
- package/skills/craft/vercel-optimize/references/candidates.md +176 -176
- package/skills/craft/vercel-optimize/references/data-collection.md +224 -224
- package/skills/craft/vercel-optimize/references/docs-library.json +683 -683
- package/skills/craft/vercel-optimize/references/doctrine.md +108 -108
- package/skills/craft/vercel-optimize/references/observability-plus.md +109 -109
- package/skills/craft/vercel-optimize/references/playbooks/README.md +57 -57
- package/skills/craft/vercel-optimize/references/playbooks/ai-application.md +32 -32
- package/skills/craft/vercel-optimize/references/playbooks/api-service.md +30 -30
- package/skills/craft/vercel-optimize/references/playbooks/content-site.md +30 -30
- package/skills/craft/vercel-optimize/references/playbooks/ecommerce.md +30 -30
- package/skills/craft/vercel-optimize/references/playbooks/marketing.md +30 -30
- package/skills/craft/vercel-optimize/references/playbooks/saas.md +31 -31
- package/skills/craft/vercel-optimize/references/playbooks/sveltekit.md +75 -75
- package/skills/craft/vercel-optimize/references/recommendations.md +214 -214
- package/skills/craft/vercel-optimize/references/scanner-patterns.md +266 -266
- package/skills/craft/vercel-optimize/references/scoring.md +208 -208
- package/skills/craft/vercel-optimize/references/support-topics/README.md +50 -50
- package/skills/craft/vercel-optimize/references/support-topics/astro-edge-middleware-scope.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/astro-output-mode-and-isr.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/auth-preserving-parallelization.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/bot-protection-product-guardrails.md +32 -32
- package/skills/craft/vercel-optimize/references/support-topics/build-minutes-monorepo-fanout.md +32 -32
- package/skills/craft/vercel-optimize/references/support-topics/cache-components-static-shell-boundaries.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/cache-components-suspense-dedupe-pitfall.md +32 -32
- package/skills/craft/vercel-optimize/references/support-topics/cdn-cache-auth-safety.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/cold-start-initialization-bundle.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/core-web-vitals-client-bottlenecks.md +33 -33
- package/skills/craft/vercel-optimize/references/support-topics/database-egress-pooling-region.md +32 -32
- package/skills/craft/vercel-optimize/references/support-topics/dynamic-rendering-traps.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/external-api-critical-path-platform.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/external-api-critical-path.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/fast-data-transfer-payloads.md +26 -26
- package/skills/craft/vercel-optimize/references/support-topics/fluid-compute-caveats.md +26 -26
- package/skills/craft/vercel-optimize/references/support-topics/function-duration-io-and-after.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/function-invocation-reduction.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/function-region-misconfiguration-ttfb.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/image-optimization-cost-control.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/isr-revalidation-static-generation.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/middleware-proxy-edge-cost.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/next-fetch-revalidate-floor.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/next-font-cls-self-hosting.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/next-heavy-ui-lazy-load-boundaries.md +28 -28
- package/skills/craft/vercel-optimize/references/support-topics/next-image-lcp-preload-sizes.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/next-route-handler-get-cache-defaults.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/next-script-third-party-strategy.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/nextjs-version-cache-semantics.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/not-found-catchall-request-waste.md +33 -33
- package/skills/craft/vercel-optimize/references/support-topics/nuxt-route-rules-cache-isr.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/observability-events-cost-attribution.md +27 -27
- package/skills/craft/vercel-optimize/references/support-topics/post-response-work-waituntil.md +26 -26
- package/skills/craft/vercel-optimize/references/support-topics/route-error-durable-offload.md +33 -33
- package/skills/craft/vercel-optimize/references/support-topics/route-error-runtime-limits.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/runtime-cache-reusable-data.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/sveltekit-isr-prerender-safety.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/sveltekit-split-cold-start-tradeoff.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/usage-spike-triage.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/use-cache-date-stamp-isr-write-amplifier.md +31 -31
- package/skills/craft/vercel-optimize/references/support-topics/use-cache-remote-shared-origin-data.md +30 -30
- package/skills/craft/vercel-optimize/references/support-topics/workflow-resumable-stream-routes.md +32 -32
- package/skills/craft/vercel-optimize/references/verification.md +102 -102
- package/skills/craft/vercel-optimize/references/voice.md +76 -76
- package/skills/craft/vercel-optimize/scripts/budget-summary.mjs +58 -58
- package/skills/craft/vercel-optimize/scripts/build-docs.mjs +76 -76
- package/skills/craft/vercel-optimize/scripts/check-citations.mjs +91 -91
- package/skills/craft/vercel-optimize/scripts/check-docs-fresh.mjs +100 -100
- package/skills/craft/vercel-optimize/scripts/collect-signals.mjs +638 -638
- package/skills/craft/vercel-optimize/scripts/collect-sub-agent-outputs.mjs +306 -306
- package/skills/craft/vercel-optimize/scripts/deep-dive.mjs +358 -358
- package/skills/craft/vercel-optimize/scripts/gate-investigations.mjs +178 -178
- package/skills/craft/vercel-optimize/scripts/merge-signals.mjs +203 -203
- package/skills/craft/vercel-optimize/scripts/prepare-investigation-brief.mjs +249 -249
- package/skills/craft/vercel-optimize/scripts/reconcile-candidates.mjs +69 -69
- package/skills/craft/vercel-optimize/scripts/render-report.mjs +462 -462
- package/skills/craft/vercel-optimize/scripts/scan-codebase.mjs +361 -361
- package/skills/craft/vercel-optimize/scripts/verify-and-regen.mjs +379 -379
- package/skills/craft/vercel-optimize/scripts/verify-finding.mjs +21 -21
- package/skills/craft/web-design-guidelines/LICENSE +21 -21
- package/skills/craft/web-design-guidelines/SKILL.md +43 -43
- package/skills/craft/zero-to-live/LICENSE +21 -21
- package/skills/craft/zero-to-live/SKILL.md +422 -422
- package/skills/creative/creative-3d-modeling/LICENSE +21 -21
- package/skills/creative/creative-3d-modeling/SKILL.md +70 -70
- package/skills/creative/creative-architecture/LICENSE +21 -21
- package/skills/creative/creative-architecture/SKILL.md +94 -94
- package/skills/creative/creative-design-principles/LICENSE +21 -21
- package/skills/creative/creative-design-principles/SKILL.md +95 -95
- package/skills/creative/creative-fashion-advanced/LICENSE +21 -21
- package/skills/creative/creative-fashion-advanced/SKILL.md +68 -68
- package/skills/creative/creative-fashion-design/LICENSE +21 -21
- package/skills/creative/creative-fashion-design/SKILL.md +66 -66
- package/skills/creative/creative-game-design/LICENSE +21 -21
- package/skills/creative/creative-game-design/SKILL.md +77 -77
- package/skills/creative/creative-industrial-design/LICENSE +21 -21
- package/skills/creative/creative-industrial-design/SKILL.md +57 -57
- package/skills/creative/creative-interior-design/LICENSE +21 -21
- package/skills/creative/creative-interior-design/SKILL.md +59 -59
- package/skills/creative/creative-music-theory/LICENSE +21 -21
- package/skills/creative/creative-music-theory/SKILL.md +98 -98
- package/skills/creative/creative-photography/LICENSE +21 -21
- package/skills/creative/creative-photography/SKILL.md +87 -87
- package/skills/creative/creative-textile-science/LICENSE +21 -21
- package/skills/creative/creative-textile-science/SKILL.md +67 -67
- package/skills/creative/creative-ux/LICENSE +21 -21
- package/skills/creative/creative-ux/SKILL.md +81 -81
- package/skills/creative/creative-video/LICENSE +21 -21
- package/skills/creative/creative-video/SKILL.md +84 -84
- package/skills/creative/creative-writing-craft/LICENSE +21 -21
- package/skills/creative/creative-writing-craft/SKILL.md +91 -91
- package/skills/diagram-maker/SKILL.md +56 -56
- package/skills/diagram-maker/references/excalidraw-patterns.md +85 -85
- package/skills/diagram-maker/references/svg-template.md +112 -112
- package/skills/discord/SKILL.md +140 -140
- package/skills/education/edu-adult-learning/LICENSE +21 -21
- package/skills/education/edu-adult-learning/SKILL.md +81 -81
- package/skills/education/edu-africa-multilingual/LICENSE +21 -21
- package/skills/education/edu-africa-multilingual/SKILL.md +55 -55
- package/skills/education/edu-arabic/LICENSE +21 -21
- package/skills/education/edu-arabic/SKILL.md +60 -60
- package/skills/education/edu-australia-nz/LICENSE +21 -21
- package/skills/education/edu-australia-nz/SKILL.md +48 -48
- package/skills/education/edu-china-mandarin/LICENSE +21 -21
- package/skills/education/edu-china-mandarin/SKILL.md +58 -58
- package/skills/education/edu-critical-thinking/LICENSE +21 -21
- package/skills/education/edu-critical-thinking/SKILL.md +86 -86
- package/skills/education/edu-curriculum/LICENSE +21 -21
- package/skills/education/edu-curriculum/SKILL.md +87 -87
- package/skills/education/edu-ed-tech/LICENSE +21 -21
- package/skills/education/edu-ed-tech/SKILL.md +73 -73
- package/skills/education/edu-france/LICENSE +21 -21
- package/skills/education/edu-france/SKILL.md +42 -42
- package/skills/education/edu-germany/LICENSE +21 -21
- package/skills/education/edu-germany/SKILL.md +46 -46
- package/skills/education/edu-india-competitive/LICENSE +21 -21
- package/skills/education/edu-india-competitive/SKILL.md +159 -159
- package/skills/education/edu-india-east/LICENSE +21 -21
- package/skills/education/edu-india-east/SKILL.md +60 -60
- package/skills/education/edu-india-hindi/LICENSE +21 -21
- package/skills/education/edu-india-hindi/SKILL.md +107 -107
- package/skills/education/edu-india-south/LICENSE +21 -21
- package/skills/education/edu-india-south/SKILL.md +64 -64
- package/skills/education/edu-india-west/LICENSE +21 -21
- package/skills/education/edu-india-west/SKILL.md +68 -68
- package/skills/education/edu-indonesia-malay/LICENSE +21 -21
- package/skills/education/edu-indonesia-malay/SKILL.md +57 -57
- package/skills/education/edu-international-ib/LICENSE +21 -21
- package/skills/education/edu-international-ib/SKILL.md +61 -61
- package/skills/education/edu-japan/LICENSE +21 -21
- package/skills/education/edu-japan/SKILL.md +48 -48
- package/skills/education/edu-korea/LICENSE +21 -21
- package/skills/education/edu-korea/SKILL.md +48 -48
- package/skills/education/edu-learning-science/LICENSE +21 -21
- package/skills/education/edu-learning-science/SKILL.md +76 -76
- package/skills/education/edu-portuguese-brazil/LICENSE +21 -21
- package/skills/education/edu-portuguese-brazil/SKILL.md +51 -51
- package/skills/education/edu-russia/LICENSE +21 -21
- package/skills/education/edu-russia/SKILL.md +50 -50
- package/skills/education/edu-spain-latam/LICENSE +21 -21
- package/skills/education/edu-spain-latam/SKILL.md +55 -55
- package/skills/education/edu-special/LICENSE +21 -21
- package/skills/education/edu-special/SKILL.md +76 -76
- package/skills/education/edu-thailand/LICENSE +21 -21
- package/skills/education/edu-thailand/SKILL.md +55 -55
- package/skills/education/edu-turkey/LICENSE +21 -21
- package/skills/education/edu-turkey/SKILL.md +58 -58
- package/skills/education/edu-uk-gcse-alevel/LICENSE +21 -21
- package/skills/education/edu-uk-gcse-alevel/SKILL.md +51 -51
- package/skills/education/edu-usa-graduate/LICENSE +21 -21
- package/skills/education/edu-usa-graduate/SKILL.md +57 -57
- package/skills/education/edu-usa-sat-act/LICENSE +21 -21
- package/skills/education/edu-usa-sat-act/SKILL.md +55 -55
- package/skills/education/edu-vietnam/LICENSE +21 -21
- package/skills/education/edu-vietnam/SKILL.md +53 -53
- package/skills/eightctl/SKILL.md +54 -54
- package/skills/engineering/eng-aerospace/LICENSE +21 -21
- package/skills/engineering/eng-aerospace/SKILL.md +117 -117
- package/skills/engineering/eng-chemical/LICENSE +21 -21
- package/skills/engineering/eng-chemical/SKILL.md +63 -63
- package/skills/engineering/eng-civil/LICENSE +21 -21
- package/skills/engineering/eng-civil/SKILL.md +223 -223
- package/skills/engineering/eng-control-systems/LICENSE +21 -21
- package/skills/engineering/eng-control-systems/SKILL.md +158 -158
- package/skills/engineering/eng-cryogenics/LICENSE +21 -21
- package/skills/engineering/eng-cryogenics/SKILL.md +151 -151
- package/skills/engineering/eng-electrical/LICENSE +21 -21
- package/skills/engineering/eng-electrical/SKILL.md +70 -70
- package/skills/engineering/eng-electronics-embedded/LICENSE +21 -21
- package/skills/engineering/eng-electronics-embedded/SKILL.md +89 -89
- package/skills/engineering/eng-environmental/LICENSE +21 -21
- package/skills/engineering/eng-environmental/SKILL.md +66 -66
- package/skills/engineering/eng-manufacturing/LICENSE +21 -21
- package/skills/engineering/eng-manufacturing/SKILL.md +78 -78
- package/skills/engineering/eng-mechanical/LICENSE +21 -21
- package/skills/engineering/eng-mechanical/SKILL.md +66 -66
- package/skills/engineering/eng-project/LICENSE +21 -21
- package/skills/engineering/eng-project/SKILL.md +72 -72
- package/skills/engineering/eng-propulsion/LICENSE +21 -21
- package/skills/engineering/eng-propulsion/SKILL.md +133 -133
- package/skills/engineering/eng-robotics/LICENSE +21 -21
- package/skills/engineering/eng-robotics/SKILL.md +92 -92
- package/skills/engineering/eng-systems/LICENSE +21 -21
- package/skills/engineering/eng-systems/SKILL.md +81 -81
- package/skills/environment/env-biodiversity/LICENSE +21 -21
- package/skills/environment/env-biodiversity/SKILL.md +66 -66
- package/skills/environment/env-circular-economy/LICENSE +21 -21
- package/skills/environment/env-circular-economy/SKILL.md +71 -71
- package/skills/environment/env-climate-action/LICENSE +21 -21
- package/skills/environment/env-climate-action/SKILL.md +55 -55
- package/skills/environment/env-energy/LICENSE +21 -21
- package/skills/environment/env-energy/SKILL.md +83 -83
- package/skills/environment/env-sustainability-biz/LICENSE +21 -21
- package/skills/environment/env-sustainability-biz/SKILL.md +65 -65
- package/skills/environment/env-water/LICENSE +21 -21
- package/skills/environment/env-water/SKILL.md +67 -67
- package/skills/finance/finance-accounting/LICENSE +21 -21
- package/skills/finance/finance-accounting/SKILL.md +239 -239
- package/skills/finance/finance-banking/LICENSE +21 -21
- package/skills/finance/finance-banking/SKILL.md +54 -54
- package/skills/finance/finance-corporate/LICENSE +21 -21
- package/skills/finance/finance-corporate/SKILL.md +105 -105
- package/skills/finance/finance-crypto/LICENSE +21 -21
- package/skills/finance/finance-crypto/SKILL.md +94 -94
- package/skills/finance/finance-debt-management/LICENSE +21 -21
- package/skills/finance/finance-debt-management/SKILL.md +87 -87
- package/skills/finance/finance-insurance/LICENSE +21 -21
- package/skills/finance/finance-insurance/SKILL.md +91 -91
- package/skills/finance/finance-investing/LICENSE +21 -21
- package/skills/finance/finance-investing/SKILL.md +269 -269
- package/skills/finance/finance-options-derivatives/LICENSE +21 -21
- package/skills/finance/finance-options-derivatives/SKILL.md +68 -68
- package/skills/finance/finance-personal/LICENSE +21 -21
- package/skills/finance/finance-personal/SKILL.md +268 -268
- package/skills/finance/finance-real-estate/LICENSE +21 -21
- package/skills/finance/finance-real-estate/SKILL.md +110 -110
- package/skills/finance/finance-startup/LICENSE +21 -21
- package/skills/finance/finance-startup/SKILL.md +253 -253
- package/skills/finance/finance-tax-planning/LICENSE +21 -21
- package/skills/finance/finance-tax-planning/SKILL.md +89 -89
- package/skills/finance/finance-trading/LICENSE +21 -21
- package/skills/finance/finance-trading/SKILL.md +112 -112
- package/skills/gemini/SKILL.md +51 -51
- package/skills/gh-issues/SKILL.md +216 -216
- package/skills/gifgrep/SKILL.md +89 -89
- package/skills/github/SKILL.md +87 -87
- package/skills/gog/SKILL.md +120 -120
- package/skills/goplaces/SKILL.md +56 -56
- package/skills/health/health-aging/LICENSE +21 -21
- package/skills/health/health-aging/SKILL.md +82 -82
- package/skills/health/health-chronic/LICENSE +21 -21
- package/skills/health/health-chronic/SKILL.md +202 -202
- package/skills/health/health-dental/LICENSE +21 -21
- package/skills/health/health-dental/SKILL.md +41 -41
- package/skills/health/health-eye-care/LICENSE +21 -21
- package/skills/health/health-eye-care/SKILL.md +56 -56
- package/skills/health/health-first-aid/LICENSE +21 -21
- package/skills/health/health-first-aid/SKILL.md +201 -201
- package/skills/health/health-fitness/LICENSE +21 -21
- package/skills/health/health-fitness/SKILL.md +111 -111
- package/skills/health/health-general/LICENSE +21 -21
- package/skills/health/health-general/SKILL.md +277 -277
- package/skills/health/health-mens/LICENSE +21 -21
- package/skills/health/health-mens/SKILL.md +53 -53
- package/skills/health/health-mental/LICENSE +21 -21
- package/skills/health/health-mental/SKILL.md +221 -221
- package/skills/health/health-naturopathy-ayurveda/LICENSE +21 -21
- package/skills/health/health-naturopathy-ayurveda/SKILL.md +60 -60
- package/skills/health/health-nutrition/LICENSE +21 -21
- package/skills/health/health-nutrition/SKILL.md +262 -262
- package/skills/health/health-pediatric/LICENSE +21 -21
- package/skills/health/health-pediatric/SKILL.md +94 -94
- package/skills/health/health-pharmacology/LICENSE +21 -21
- package/skills/health/health-pharmacology/SKILL.md +87 -87
- package/skills/health/health-pregnancy/LICENSE +21 -21
- package/skills/health/health-pregnancy/SKILL.md +71 -71
- package/skills/health/health-skin/LICENSE +21 -21
- package/skills/health/health-skin/SKILL.md +71 -71
- package/skills/health/health-sleep/LICENSE +21 -21
- package/skills/health/health-sleep/SKILL.md +81 -81
- package/skills/health/health-womens/LICENSE +21 -21
- package/skills/health/health-womens/SKILL.md +72 -72
- package/skills/health/health-yoga-wellness/LICENSE +21 -21
- package/skills/health/health-yoga-wellness/SKILL.md +58 -58
- package/skills/healthcare-systems/health-sys-global/LICENSE +21 -21
- package/skills/healthcare-systems/health-sys-global/SKILL.md +69 -69
- package/skills/healthcare-systems/health-sys-management/LICENSE +21 -21
- package/skills/healthcare-systems/health-sys-management/SKILL.md +71 -71
- package/skills/healthcare-systems/health-sys-navigation/LICENSE +21 -21
- package/skills/healthcare-systems/health-sys-navigation/SKILL.md +60 -60
- package/skills/healthcare-systems/health-sys-public/LICENSE +21 -21
- package/skills/healthcare-systems/health-sys-public/SKILL.md +71 -71
- package/skills/healthcheck/SKILL.md +109 -109
- package/skills/himalaya/SKILL.md +84 -84
- package/skills/himalaya/references/configuration.md +184 -184
- package/skills/himalaya/references/message-composition.md +199 -199
- package/skills/humanities/humanities-history-world/LICENSE +21 -21
- package/skills/humanities/humanities-history-world/SKILL.md +59 -59
- package/skills/humanities/humanities-indian-classical/LICENSE +21 -21
- package/skills/humanities/humanities-indian-classical/SKILL.md +104 -104
- package/skills/humanities/humanities-philosophy/LICENSE +21 -21
- package/skills/humanities/humanities-philosophy/SKILL.md +105 -105
- package/skills/humanities/humanities-world-religions/LICENSE +21 -21
- package/skills/humanities/humanities-world-religions/SKILL.md +67 -67
- package/skills/impeccable/SKILL.md +185 -185
- package/skills/imsg/SKILL.md +126 -126
- package/skills/industry/industry-construction/LICENSE +21 -21
- package/skills/industry/industry-construction/SKILL.md +81 -81
- package/skills/industry/industry-education-sector/LICENSE +21 -21
- package/skills/industry/industry-education-sector/SKILL.md +49 -49
- package/skills/industry/industry-fashion/LICENSE +21 -21
- package/skills/industry/industry-fashion/SKILL.md +82 -82
- package/skills/industry/industry-food/LICENSE +21 -21
- package/skills/industry/industry-food/SKILL.md +79 -79
- package/skills/industry/industry-government/LICENSE +21 -21
- package/skills/industry/industry-government/SKILL.md +80 -80
- package/skills/industry/industry-hospitality/LICENSE +21 -21
- package/skills/industry/industry-hospitality/SKILL.md +73 -73
- package/skills/industry/industry-insurance-sector/LICENSE +21 -21
- package/skills/industry/industry-insurance-sector/SKILL.md +57 -57
- package/skills/industry/industry-logistics/LICENSE +21 -21
- package/skills/industry/industry-logistics/SKILL.md +80 -80
- package/skills/industry/industry-media/LICENSE +21 -21
- package/skills/industry/industry-media/SKILL.md +66 -66
- package/skills/industry/industry-nonprofit/LICENSE +21 -21
- package/skills/industry/industry-nonprofit/SKILL.md +77 -77
- package/skills/industry/industry-pharma/LICENSE +21 -21
- package/skills/industry/industry-pharma/SKILL.md +69 -69
- package/skills/industry/industry-real-estate/LICENSE +21 -21
- package/skills/industry/industry-real-estate/SKILL.md +61 -61
- package/skills/industry/industry-sports/LICENSE +21 -21
- package/skills/industry/industry-sports/SKILL.md +71 -71
- package/skills/industry/industry-tech-startup/LICENSE +21 -21
- package/skills/industry/industry-tech-startup/SKILL.md +82 -82
- package/skills/internal-comms/LICENSE +21 -21
- package/skills/internal-comms/SKILL.md +38 -38
- package/skills/internal-comms/examples/3p-updates.md +49 -49
- package/skills/internal-comms/examples/company-newsletter.md +76 -76
- package/skills/internal-comms/examples/faq-answers.md +35 -35
- package/skills/internal-comms/examples/general-comms.md +19 -19
- package/skills/legal/legal-business/LICENSE +21 -21
- package/skills/legal/legal-business/SKILL.md +227 -227
- package/skills/legal/legal-consumer/LICENSE +21 -21
- package/skills/legal/legal-consumer/SKILL.md +155 -155
- package/skills/legal/legal-contracts/LICENSE +21 -21
- package/skills/legal/legal-contracts/SKILL.md +268 -268
- package/skills/legal/legal-corporate-governance/LICENSE +21 -21
- package/skills/legal/legal-corporate-governance/SKILL.md +53 -53
- package/skills/legal/legal-employment/LICENSE +21 -21
- package/skills/legal/legal-employment/SKILL.md +291 -291
- package/skills/legal/legal-immigration/LICENSE +21 -21
- package/skills/legal/legal-immigration/SKILL.md +146 -146
- package/skills/legal/legal-international/LICENSE +21 -21
- package/skills/legal/legal-international/SKILL.md +51 -51
- package/skills/legal/legal-ip/LICENSE +21 -21
- package/skills/legal/legal-ip/SKILL.md +264 -264
- package/skills/legal/legal-privacy/LICENSE +21 -21
- package/skills/legal/legal-privacy/SKILL.md +161 -161
- package/skills/legal/legal-real-estate/LICENSE +21 -21
- package/skills/legal/legal-real-estate/SKILL.md +142 -142
- package/skills/legal/legal-startup/LICENSE +21 -21
- package/skills/legal/legal-startup/SKILL.md +182 -182
- package/skills/legal/legal-tax/LICENSE +21 -21
- package/skills/legal/legal-tax/SKILL.md +156 -156
- package/skills/mcp-builder/LICENSE +21 -21
- package/skills/mcp-builder/SKILL.md +257 -257
- package/skills/mcp-builder/reference/evaluation.md +630 -630
- package/skills/mcp-builder/reference/mcp_best_practices.md +269 -269
- package/skills/mcp-builder/reference/node_mcp_server.md +980 -980
- package/skills/mcp-builder/reference/python_mcp_server.md +737 -737
- package/skills/mcp-builder/scripts/connections.py +151 -151
- package/skills/mcp-builder/scripts/evaluation.py +373 -373
- package/skills/mcp-builder/scripts/example_evaluation.xml +22 -22
- package/skills/mcp-builder/scripts/requirements.txt +2 -2
- package/skills/mcporter/SKILL.md +65 -65
- package/skills/meme-maker/SKILL.md +46 -46
- package/skills/meme-maker/references/templates.json +358 -358
- package/skills/meme-maker/scripts/meme.mjs +398 -398
- package/skills/mental-health/mental-health-cbt/LICENSE +21 -21
- package/skills/mental-health/mental-health-cbt/SKILL.md +254 -254
- package/skills/mental-health/psych-addiction/LICENSE +21 -21
- package/skills/mental-health/psych-addiction/SKILL.md +79 -79
- package/skills/mental-health/psych-behavioral-econ/LICENSE +21 -21
- package/skills/mental-health/psych-behavioral-econ/SKILL.md +84 -84
- package/skills/mental-health/psych-child/LICENSE +21 -21
- package/skills/mental-health/psych-child/SKILL.md +84 -84
- package/skills/mental-health/psych-grief/LICENSE +21 -21
- package/skills/mental-health/psych-grief/SKILL.md +85 -85
- package/skills/mental-health/psych-mindfulness/LICENSE +21 -21
- package/skills/mental-health/psych-mindfulness/SKILL.md +71 -71
- package/skills/mental-health/psych-org/LICENSE +21 -21
- package/skills/mental-health/psych-org/SKILL.md +115 -115
- package/skills/mental-health/psych-positive/LICENSE +21 -21
- package/skills/mental-health/psych-positive/SKILL.md +86 -86
- package/skills/mental-health/psych-relationships/LICENSE +21 -21
- package/skills/mental-health/psych-relationships/SKILL.md +100 -100
- package/skills/mental-health/psych-trauma/LICENSE +21 -21
- package/skills/mental-health/psych-trauma/SKILL.md +109 -109
- package/skills/model-usage/SKILL.md +75 -75
- package/skills/model-usage/references/codexbar-cli.md +33 -33
- package/skills/model-usage/scripts/model_usage.py +319 -319
- package/skills/model-usage/scripts/test_model_usage.py +40 -40
- package/skills/nano-pdf/SKILL.md +42 -42
- package/skills/node-connect/SKILL.md +147 -147
- package/skills/node-inspect-debugger/SKILL.md +88 -88
- package/skills/notion/SKILL.md +154 -154
- package/skills/obsidian/SKILL.md +123 -123
- package/skills/openai-whisper/SKILL.md +42 -42
- package/skills/openai-whisper-api/SKILL.md +75 -75
- package/skills/openai-whisper-api/scripts/transcribe.sh +154 -154
- package/skills/openhue/SKILL.md +116 -116
- package/skills/oracle/SKILL.md +130 -130
- package/skills/ordercli/SKILL.md +82 -82
- package/skills/peekaboo/SKILL.md +217 -217
- package/skills/pyproject.toml +10 -10
- package/skills/python-debugpy/SKILL.md +76 -76
- package/skills/sag/SKILL.md +91 -91
- package/skills/science/sci-astronomy/LICENSE +21 -21
- package/skills/science/sci-astronomy/SKILL.md +80 -80
- package/skills/science/sci-biology/LICENSE +21 -21
- package/skills/science/sci-biology/SKILL.md +74 -74
- package/skills/science/sci-chemistry/LICENSE +21 -21
- package/skills/science/sci-chemistry/SKILL.md +89 -89
- package/skills/science/sci-climate/LICENSE +21 -21
- package/skills/science/sci-climate/SKILL.md +72 -72
- package/skills/science/sci-data-analysis/LICENSE +21 -21
- package/skills/science/sci-data-analysis/SKILL.md +87 -87
- package/skills/science/sci-environmental-science/LICENSE +21 -21
- package/skills/science/sci-environmental-science/SKILL.md +69 -69
- package/skills/science/sci-geology/LICENSE +21 -21
- package/skills/science/sci-geology/SKILL.md +56 -56
- package/skills/science/sci-method/LICENSE +21 -21
- package/skills/science/sci-method/SKILL.md +77 -77
- package/skills/science/sci-neuroscience/LICENSE +21 -21
- package/skills/science/sci-neuroscience/SKILL.md +79 -79
- package/skills/science/sci-physics/LICENSE +21 -21
- package/skills/science/sci-physics/SKILL.md +78 -78
- package/skills/science/sci-research-methods/LICENSE +21 -21
- package/skills/science/sci-research-methods/SKILL.md +83 -83
- package/skills/science/sci-statistics/LICENSE +21 -21
- package/skills/science/sci-statistics/SKILL.md +249 -249
- package/skills/session-logs/SKILL.md +155 -155
- package/skills/sherpa-onnx-tts/SKILL.md +113 -113
- package/skills/skill-creator/SKILL.md +81 -81
- package/skills/skill-creator/license.txt +202 -202
- package/skills/skill-creator/scripts/init_skill.py +378 -378
- package/skills/skill-creator/scripts/package_skill.py +144 -144
- package/skills/skill-creator/scripts/quick_validate.py +169 -169
- package/skills/skill-creator/scripts/test_init_skill.py +51 -51
- package/skills/skill-creator/scripts/test_package_skill.py +199 -199
- package/skills/skill-creator/scripts/test_quick_validate.py +116 -116
- package/skills/slack/SKILL.md +82 -82
- package/skills/slack-gif-creator/LICENSE +21 -21
- package/skills/slack-gif-creator/SKILL.md +293 -293
- package/skills/slack-gif-creator/requirements.txt +3 -3
- package/skills/social-sciences/social-anthropology/LICENSE +21 -21
- package/skills/social-sciences/social-anthropology/SKILL.md +62 -62
- package/skills/social-sciences/social-economics/LICENSE +21 -21
- package/skills/social-sciences/social-economics/SKILL.md +88 -88
- package/skills/social-sciences/social-geography/LICENSE +21 -21
- package/skills/social-sciences/social-geography/SKILL.md +61 -61
- package/skills/social-sciences/social-international-dev/LICENSE +21 -21
- package/skills/social-sciences/social-international-dev/SKILL.md +76 -76
- package/skills/social-sciences/social-political-science/LICENSE +21 -21
- package/skills/social-sciences/social-political-science/SKILL.md +70 -70
- package/skills/social-sciences/social-public-policy/LICENSE +21 -21
- package/skills/social-sciences/social-public-policy/SKILL.md +73 -73
- package/skills/social-sciences/social-sociology/LICENSE +21 -21
- package/skills/social-sciences/social-sociology/SKILL.md +78 -78
- package/skills/songsee/SKILL.md +53 -53
- package/skills/sonoscli/SKILL.md +69 -69
- package/skills/spike/SKILL.md +55 -55
- package/skills/spotify-player/SKILL.md +68 -68
- package/skills/summarize/SKILL.md +90 -90
- package/skills/taskflow/SKILL.md +153 -153
- package/skills/taskflow/examples/inbox-triage.lobster +33 -33
- package/skills/taskflow/examples/pr-intake.lobster +32 -32
- package/skills/taskflow-inbox-triage/SKILL.md +123 -123
- package/skills/technical/ai-ethics/LICENSE +21 -21
- package/skills/technical/ai-ethics/SKILL.md +92 -92
- package/skills/technical/ai-product-builder/LICENSE +21 -21
- package/skills/technical/ai-product-builder/SKILL.md +180 -180
- package/skills/technical/analytics-setup/LICENSE +21 -21
- package/skills/technical/analytics-setup/SKILL.md +125 -125
- package/skills/technical/api-builder/LICENSE +21 -21
- package/skills/technical/api-builder/SKILL.md +202 -202
- package/skills/technical/architecture-decisions/LICENSE +21 -21
- package/skills/technical/architecture-decisions/SKILL.md +120 -120
- package/skills/technical/auth-security/LICENSE +21 -21
- package/skills/technical/auth-security/SKILL.md +209 -209
- package/skills/technical/blockchain-web3/LICENSE +21 -21
- package/skills/technical/blockchain-web3/SKILL.md +84 -84
- package/skills/technical/cloud-architecture/LICENSE +21 -21
- package/skills/technical/cloud-architecture/SKILL.md +85 -85
- package/skills/technical/content-platform/LICENSE +21 -21
- package/skills/technical/content-platform/SKILL.md +134 -134
- package/skills/technical/cybersecurity-advanced/LICENSE +21 -21
- package/skills/technical/cybersecurity-advanced/SKILL.md +99 -99
- package/skills/technical/data-engineering/LICENSE +21 -21
- package/skills/technical/data-engineering/SKILL.md +117 -117
- package/skills/technical/database-design/LICENSE +21 -21
- package/skills/technical/database-design/SKILL.md +185 -185
- package/skills/technical/devops-cicd/LICENSE +21 -21
- package/skills/technical/devops-cicd/SKILL.md +181 -181
- package/skills/technical/ecommerce-builder/LICENSE +21 -21
- package/skills/technical/ecommerce-builder/SKILL.md +123 -123
- package/skills/technical/email-marketing/LICENSE +21 -21
- package/skills/technical/email-marketing/SKILL.md +128 -128
- package/skills/technical/fintech-builder/LICENSE +21 -21
- package/skills/technical/fintech-builder/SKILL.md +141 -141
- package/skills/technical/full-stack-web/LICENSE +21 -21
- package/skills/technical/full-stack-web/SKILL.md +173 -173
- package/skills/technical/gdpr-basics/LICENSE +21 -21
- package/skills/technical/gdpr-basics/SKILL.md +145 -145
- package/skills/technical/launch-playbook/LICENSE +21 -21
- package/skills/technical/launch-playbook/SKILL.md +95 -95
- package/skills/technical/marketing-copy/LICENSE +21 -21
- package/skills/technical/marketing-copy/SKILL.md +126 -126
- package/skills/technical/marketplace-builder/LICENSE +21 -21
- package/skills/technical/marketplace-builder/SKILL.md +105 -105
- package/skills/technical/mobile-pwa/LICENSE +21 -21
- package/skills/technical/mobile-pwa/SKILL.md +191 -191
- package/skills/technical/no-code-tools/LICENSE +21 -21
- package/skills/technical/no-code-tools/SKILL.md +80 -80
- package/skills/technical/open-source/LICENSE +21 -21
- package/skills/technical/open-source/SKILL.md +71 -71
- package/skills/technical/performance-optimization/LICENSE +21 -21
- package/skills/technical/performance-optimization/SKILL.md +155 -155
- package/skills/technical/pricing-design/LICENSE +21 -21
- package/skills/technical/pricing-design/SKILL.md +87 -87
- package/skills/technical/product-management/LICENSE +21 -21
- package/skills/technical/product-management/SKILL.md +94 -94
- package/skills/technical/saas-builder/LICENSE +21 -21
- package/skills/technical/saas-builder/SKILL.md +138 -138
- package/skills/technical/scope-estimation/LICENSE +21 -21
- package/skills/technical/scope-estimation/SKILL.md +99 -99
- package/skills/technical/secrets-management/LICENSE +21 -21
- package/skills/technical/secrets-management/SKILL.md +135 -135
- package/skills/technical/seo-technical/LICENSE +21 -21
- package/skills/technical/seo-technical/SKILL.md +136 -136
- package/skills/technical/technical-writing/LICENSE +21 -21
- package/skills/technical/technical-writing/SKILL.md +149 -149
- package/skills/technical/ux-research-tools/LICENSE +21 -21
- package/skills/technical/ux-research-tools/SKILL.md +54 -54
- package/skills/theme-factory/LICENSE +21 -21
- package/skills/theme-factory/SKILL.md +65 -65
- package/skills/theme-factory/themes/arctic-frost.md +19 -19
- package/skills/theme-factory/themes/botanical-garden.md +19 -19
- package/skills/theme-factory/themes/desert-rose.md +19 -19
- package/skills/theme-factory/themes/forest-canopy.md +19 -19
- package/skills/theme-factory/themes/golden-hour.md +19 -19
- package/skills/theme-factory/themes/midnight-galaxy.md +19 -19
- package/skills/theme-factory/themes/modern-minimalist.md +19 -19
- package/skills/theme-factory/themes/ocean-depths.md +19 -19
- package/skills/theme-factory/themes/sunset-boulevard.md +19 -19
- package/skills/theme-factory/themes/tech-innovation.md +19 -19
- package/skills/things-mac/SKILL.md +90 -90
- package/skills/tmux/SKILL.md +95 -95
- package/skills/tmux/scripts/find-sessions.sh +112 -112
- package/skills/tmux/scripts/wait-for-text.sh +83 -83
- package/skills/trades/trades-agriculture/LICENSE +21 -21
- package/skills/trades/trades-agriculture/SKILL.md +80 -80
- package/skills/trades/trades-automotive/LICENSE +21 -21
- package/skills/trades/trades-automotive/SKILL.md +84 -84
- package/skills/trades/trades-carpentry/LICENSE +21 -21
- package/skills/trades/trades-carpentry/SKILL.md +71 -71
- package/skills/trades/trades-cooking-pro/LICENSE +21 -21
- package/skills/trades/trades-cooking-pro/SKILL.md +90 -90
- package/skills/trades/trades-electrical/LICENSE +21 -21
- package/skills/trades/trades-electrical/SKILL.md +146 -146
- package/skills/trades/trades-hvac/LICENSE +21 -21
- package/skills/trades/trades-hvac/SKILL.md +80 -80
- package/skills/trades/trades-landscaping/LICENSE +21 -21
- package/skills/trades/trades-landscaping/SKILL.md +60 -60
- package/skills/trades/trades-metalworking/LICENSE +21 -21
- package/skills/trades/trades-metalworking/SKILL.md +64 -64
- package/skills/trades/trades-painting/LICENSE +21 -21
- package/skills/trades/trades-painting/SKILL.md +70 -70
- package/skills/trades/trades-plumbing/LICENSE +21 -21
- package/skills/trades/trades-plumbing/SKILL.md +160 -160
- package/skills/trades/trades-welding/LICENSE +21 -21
- package/skills/trades/trades-welding/SKILL.md +82 -82
- package/skills/trello/SKILL.md +112 -112
- package/skills/uipm-ui-styling/SKILL.md +328 -328
- package/skills/video-frames/SKILL.md +50 -50
- package/skills/video-frames/scripts/frame.sh +81 -81
- package/skills/voice-call/SKILL.md +49 -49
- package/skills/wacli/SKILL.md +76 -76
- package/skills/weather/SKILL.md +91 -91
- package/skills/web-artifacts-builder/LICENSE +21 -21
- package/skills/web-artifacts-builder/SKILL.md +82 -82
- package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +53 -53
- package/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -322
- package/skills/xurl/SKILL.md +124 -124
- package/skills/graphify/SKILL.md +0 -619
- package/skills/graphify/__init__.py +0 -28
- package/skills/graphify/__main__.py +0 -4582
- package/skills/graphify/affected.py +0 -154
- package/skills/graphify/always_on/agents-md.md +0 -12
- package/skills/graphify/always_on/antigravity-rules.md +0 -14
- package/skills/graphify/always_on/claude-md.md +0 -9
- package/skills/graphify/always_on/gemini-md.md +0 -9
- package/skills/graphify/always_on/kiro-steering.md +0 -5
- package/skills/graphify/always_on/vscode-instructions.md +0 -17
- package/skills/graphify/analyze.py +0 -724
- package/skills/graphify/benchmark.py +0 -155
- package/skills/graphify/build.py +0 -487
- package/skills/graphify/cache.py +0 -417
- package/skills/graphify/callflow_html.py +0 -2020
- package/skills/graphify/cluster.py +0 -272
- package/skills/graphify/command-kilo.md +0 -15
- package/skills/graphify/dedup.py +0 -429
- package/skills/graphify/detect.py +0 -1379
- package/skills/graphify/diagnostics.py +0 -390
- package/skills/graphify/export.py +0 -1408
- package/skills/graphify/extract.py +0 -11570
- package/skills/graphify/global_graph.py +0 -159
- package/skills/graphify/google_workspace.py +0 -223
- package/skills/graphify/hooks.py +0 -457
- package/skills/graphify/ingest.py +0 -331
- package/skills/graphify/llm.py +0 -1896
- package/skills/graphify/manifest.py +0 -4
- package/skills/graphify/mcp_ingest.py +0 -392
- package/skills/graphify/multigraph_compat.py +0 -212
- package/skills/graphify/pg_introspect.py +0 -142
- package/skills/graphify/prs.py +0 -748
- package/skills/graphify/querylog.py +0 -70
- package/skills/graphify/report.py +0 -218
- package/skills/graphify/scip_ingest.py +0 -363
- package/skills/graphify/security.py +0 -336
- package/skills/graphify/semantic_cleanup.py +0 -319
- package/skills/graphify/serve.py +0 -1309
- package/skills/graphify/skill-aider.md +0 -1246
- package/skills/graphify/skill-amp.md +0 -613
- package/skills/graphify/skill-claw.md +0 -616
- package/skills/graphify/skill-codex.md +0 -613
- package/skills/graphify/skill-copilot.md +0 -616
- package/skills/graphify/skill-devin.md +0 -1372
- package/skills/graphify/skill-droid.md +0 -613
- package/skills/graphify/skill-kilo.md +0 -625
- package/skills/graphify/skill-kiro.md +0 -615
- package/skills/graphify/skill-opencode.md +0 -608
- package/skills/graphify/skill-pi.md +0 -615
- package/skills/graphify/skill-trae.md +0 -614
- package/skills/graphify/skill-vscode.md +0 -612
- package/skills/graphify/skill-windows.md +0 -651
- package/skills/graphify/skills/amp/references/add-watch.md +0 -56
- package/skills/graphify/skills/amp/references/exports.md +0 -71
- package/skills/graphify/skills/amp/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/amp/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/amp/references/hooks.md +0 -33
- package/skills/graphify/skills/amp/references/query.md +0 -249
- package/skills/graphify/skills/amp/references/transcribe.md +0 -48
- package/skills/graphify/skills/amp/references/update.md +0 -179
- package/skills/graphify/skills/claude/references/add-watch.md +0 -56
- package/skills/graphify/skills/claude/references/exports.md +0 -71
- package/skills/graphify/skills/claude/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/claude/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/claude/references/hooks.md +0 -33
- package/skills/graphify/skills/claude/references/query.md +0 -103
- package/skills/graphify/skills/claude/references/transcribe.md +0 -48
- package/skills/graphify/skills/claude/references/update.md +0 -179
- package/skills/graphify/skills/claw/references/add-watch.md +0 -56
- package/skills/graphify/skills/claw/references/exports.md +0 -71
- package/skills/graphify/skills/claw/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/claw/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/claw/references/hooks.md +0 -33
- package/skills/graphify/skills/claw/references/query.md +0 -249
- package/skills/graphify/skills/claw/references/transcribe.md +0 -48
- package/skills/graphify/skills/claw/references/update.md +0 -179
- package/skills/graphify/skills/codex/references/add-watch.md +0 -56
- package/skills/graphify/skills/codex/references/exports.md +0 -71
- package/skills/graphify/skills/codex/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/codex/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/codex/references/hooks.md +0 -33
- package/skills/graphify/skills/codex/references/query.md +0 -249
- package/skills/graphify/skills/codex/references/transcribe.md +0 -48
- package/skills/graphify/skills/codex/references/update.md +0 -179
- package/skills/graphify/skills/copilot/references/add-watch.md +0 -56
- package/skills/graphify/skills/copilot/references/exports.md +0 -71
- package/skills/graphify/skills/copilot/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/copilot/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/copilot/references/hooks.md +0 -33
- package/skills/graphify/skills/copilot/references/query.md +0 -249
- package/skills/graphify/skills/copilot/references/transcribe.md +0 -48
- package/skills/graphify/skills/copilot/references/update.md +0 -179
- package/skills/graphify/skills/droid/references/add-watch.md +0 -56
- package/skills/graphify/skills/droid/references/exports.md +0 -71
- package/skills/graphify/skills/droid/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/droid/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/droid/references/hooks.md +0 -33
- package/skills/graphify/skills/droid/references/query.md +0 -249
- package/skills/graphify/skills/droid/references/transcribe.md +0 -48
- package/skills/graphify/skills/droid/references/update.md +0 -179
- package/skills/graphify/skills/kilo/references/add-watch.md +0 -56
- package/skills/graphify/skills/kilo/references/exports.md +0 -71
- package/skills/graphify/skills/kilo/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/kilo/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/kilo/references/hooks.md +0 -33
- package/skills/graphify/skills/kilo/references/query.md +0 -249
- package/skills/graphify/skills/kilo/references/transcribe.md +0 -48
- package/skills/graphify/skills/kilo/references/update.md +0 -179
- package/skills/graphify/skills/kiro/references/add-watch.md +0 -56
- package/skills/graphify/skills/kiro/references/exports.md +0 -71
- package/skills/graphify/skills/kiro/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/kiro/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/kiro/references/hooks.md +0 -33
- package/skills/graphify/skills/kiro/references/query.md +0 -249
- package/skills/graphify/skills/kiro/references/transcribe.md +0 -48
- package/skills/graphify/skills/kiro/references/update.md +0 -179
- package/skills/graphify/skills/opencode/references/add-watch.md +0 -56
- package/skills/graphify/skills/opencode/references/exports.md +0 -71
- package/skills/graphify/skills/opencode/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/opencode/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/opencode/references/hooks.md +0 -33
- package/skills/graphify/skills/opencode/references/query.md +0 -249
- package/skills/graphify/skills/opencode/references/transcribe.md +0 -48
- package/skills/graphify/skills/opencode/references/update.md +0 -179
- package/skills/graphify/skills/pi/references/add-watch.md +0 -56
- package/skills/graphify/skills/pi/references/exports.md +0 -71
- package/skills/graphify/skills/pi/references/extraction-spec.md +0 -29
- package/skills/graphify/skills/pi/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/pi/references/hooks.md +0 -33
- package/skills/graphify/skills/pi/references/query.md +0 -249
- package/skills/graphify/skills/pi/references/transcribe.md +0 -48
- package/skills/graphify/skills/pi/references/update.md +0 -179
- package/skills/graphify/skills/trae/references/add-watch.md +0 -56
- package/skills/graphify/skills/trae/references/exports.md +0 -71
- package/skills/graphify/skills/trae/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/trae/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/trae/references/hooks.md +0 -35
- package/skills/graphify/skills/trae/references/query.md +0 -249
- package/skills/graphify/skills/trae/references/transcribe.md +0 -48
- package/skills/graphify/skills/trae/references/update.md +0 -179
- package/skills/graphify/skills/vscode/references/add-watch.md +0 -56
- package/skills/graphify/skills/vscode/references/exports.md +0 -71
- package/skills/graphify/skills/vscode/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/vscode/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/vscode/references/hooks.md +0 -33
- package/skills/graphify/skills/vscode/references/query.md +0 -249
- package/skills/graphify/skills/vscode/references/transcribe.md +0 -48
- package/skills/graphify/skills/vscode/references/update.md +0 -179
- package/skills/graphify/skills/windows/references/add-watch.md +0 -56
- package/skills/graphify/skills/windows/references/exports.md +0 -71
- package/skills/graphify/skills/windows/references/extraction-spec.md +0 -68
- package/skills/graphify/skills/windows/references/github-and-merge.md +0 -46
- package/skills/graphify/skills/windows/references/hooks.md +0 -33
- package/skills/graphify/skills/windows/references/query.md +0 -249
- package/skills/graphify/skills/windows/references/transcribe.md +0 -48
- package/skills/graphify/skills/windows/references/update.md +0 -179
- package/skills/graphify/symbol_resolution.py +0 -538
- package/skills/graphify/transcribe.py +0 -184
- package/skills/graphify/tree_html.py +0 -582
- package/skills/graphify/validate.py +0 -72
- package/skills/graphify/watch.py +0 -898
- package/skills/graphify/wiki.py +0 -282
package/dist/cli.js
CHANGED
|
@@ -1250,37 +1250,37 @@ function registerVoiceSynth(fn) {
|
|
|
1250
1250
|
function registerVoiceListen(fn) {
|
|
1251
1251
|
listener = fn;
|
|
1252
1252
|
}
|
|
1253
|
-
function audioPlayers(
|
|
1254
|
-
if (process.platform === "darwin") return [{ cmd: "afplay", args: [
|
|
1253
|
+
function audioPlayers(file6) {
|
|
1254
|
+
if (process.platform === "darwin") return [{ cmd: "afplay", args: [file6] }];
|
|
1255
1255
|
if (process.platform === "win32")
|
|
1256
1256
|
return [
|
|
1257
|
-
{ cmd: "powershell", args: ["-NoProfile", "-c", `(New-Object Media.SoundPlayer '${
|
|
1257
|
+
{ cmd: "powershell", args: ["-NoProfile", "-c", `(New-Object Media.SoundPlayer '${file6}').PlaySync()`] }
|
|
1258
1258
|
];
|
|
1259
1259
|
return [
|
|
1260
|
-
{ cmd: "aplay", args: ["-q",
|
|
1261
|
-
{ cmd: "ffplay", args: ["-nodisp", "-autoexit", "-loglevel", "quiet",
|
|
1262
|
-
{ cmd: "paplay", args: [
|
|
1260
|
+
{ cmd: "aplay", args: ["-q", file6] },
|
|
1261
|
+
{ cmd: "ffplay", args: ["-nodisp", "-autoexit", "-loglevel", "quiet", file6] },
|
|
1262
|
+
{ cmd: "paplay", args: [file6] }
|
|
1263
1263
|
];
|
|
1264
1264
|
}
|
|
1265
1265
|
function playWav(wav) {
|
|
1266
|
-
const
|
|
1267
|
-
writeFileSync5(
|
|
1268
|
-
const players = audioPlayers(
|
|
1266
|
+
const file6 = join7(tmpdir(), `oriro-avatar-${process.pid}-${wav.length}.wav`);
|
|
1267
|
+
writeFileSync5(file6, wav);
|
|
1268
|
+
const players = audioPlayers(file6);
|
|
1269
1269
|
return new Promise((resolve3) => {
|
|
1270
1270
|
const tryPlayer = (i) => {
|
|
1271
1271
|
if (i >= players.length) {
|
|
1272
|
-
rmSync(
|
|
1272
|
+
rmSync(file6, { force: true });
|
|
1273
1273
|
return resolve3(false);
|
|
1274
1274
|
}
|
|
1275
1275
|
const p = players[i];
|
|
1276
1276
|
if (!p) {
|
|
1277
|
-
rmSync(
|
|
1277
|
+
rmSync(file6, { force: true });
|
|
1278
1278
|
return resolve3(false);
|
|
1279
1279
|
}
|
|
1280
1280
|
const child = spawn(p.cmd, p.args, { stdio: "ignore" });
|
|
1281
1281
|
child.on("error", () => tryPlayer(i + 1));
|
|
1282
1282
|
child.on("close", (code) => {
|
|
1283
|
-
rmSync(
|
|
1283
|
+
rmSync(file6, { force: true });
|
|
1284
1284
|
resolve3(code === 0);
|
|
1285
1285
|
});
|
|
1286
1286
|
};
|
|
@@ -1317,9 +1317,9 @@ import { existsSync, readFileSync as readFileSync6, rmSync as rmSync2 } from "fs
|
|
|
1317
1317
|
function tmpWav() {
|
|
1318
1318
|
return join8(tmpdir2(), `oriro-tts-${process.pid}-${Date.now()}-${Math.floor(performance.now())}.wav`);
|
|
1319
1319
|
}
|
|
1320
|
-
function readAndClean(
|
|
1321
|
-
const buf = readFileSync6(
|
|
1322
|
-
rmSync2(
|
|
1320
|
+
function readAndClean(file6) {
|
|
1321
|
+
const buf = readFileSync6(file6);
|
|
1322
|
+
rmSync2(file6, { force: true });
|
|
1323
1323
|
return new Uint8Array(buf);
|
|
1324
1324
|
}
|
|
1325
1325
|
function winSapi(text, lang) {
|
|
@@ -1755,13 +1755,6 @@ var ROUTER_CATALOG = [
|
|
|
1755
1755
|
freeModels: ["mistralai/Mistral-Small-Instruct"],
|
|
1756
1756
|
obtainUrl: "https://berget.ai"
|
|
1757
1757
|
}),
|
|
1758
|
-
C4({
|
|
1759
|
-
id: "huggingface",
|
|
1760
|
-
displayName: "Hugging Face",
|
|
1761
|
-
baseUrl: "https://router.huggingface.co/v1",
|
|
1762
|
-
freeModels: ["meta-llama/Llama-3.2-3B-Instruct"],
|
|
1763
|
-
obtainUrl: "https://huggingface.co/settings/tokens"
|
|
1764
|
-
}),
|
|
1765
1758
|
C4({
|
|
1766
1759
|
id: "replicate",
|
|
1767
1760
|
displayName: "Replicate",
|
|
@@ -1857,10 +1850,35 @@ var ROUTER_CATALOG = [
|
|
|
1857
1850
|
obtainUrl: "https://platform.moonshot.ai",
|
|
1858
1851
|
tier: "paid"
|
|
1859
1852
|
}),
|
|
1860
|
-
// ── ORIRO models —
|
|
1861
|
-
|
|
1862
|
-
|
|
1853
|
+
// ── ORIRO's OWN models — LIVE, keyless, first-class racers (2026-07-04) ──
|
|
1854
|
+
// Served through the same-origin oriro.ai worker proxy, which injects the serve key server-side
|
|
1855
|
+
// so the CLI stays keyless (no bearer ever touches the client) — the endpoints answer at
|
|
1856
|
+
// baseUrl + "/chat/completions" (race-{gauss,avila}.ts alias). ORIRO-Avila is V2.4 today
|
|
1857
|
+
// (AVILA_SERVE_URL set); ORIRO-Gauss races on the live serve and auto-upgrades to V2.4 the
|
|
1858
|
+
// moment GAUSS_SERVE_URL is flipped — no CLI change needed. Both are true GPU endpoints, so
|
|
1859
|
+
// they only race when the user opts them into the pool (`oriro routers add oriro-gauss`).
|
|
1860
|
+
C4({
|
|
1861
|
+
id: "oriro-gauss",
|
|
1862
|
+
displayName: "ORIRO-Gauss",
|
|
1863
|
+
baseUrl: "https://oriro.ai/api/race/gauss",
|
|
1864
|
+
freeModels: ["gauss"],
|
|
1865
|
+
obtainUrl: "https://oriro.ai",
|
|
1866
|
+
keyless: true,
|
|
1867
|
+
verified: true
|
|
1868
|
+
}),
|
|
1869
|
+
C4({
|
|
1870
|
+
id: "oriro-avila",
|
|
1871
|
+
displayName: "ORIRO-Avila",
|
|
1872
|
+
baseUrl: "https://oriro.ai/api/race/avila",
|
|
1873
|
+
freeModels: ["avila"],
|
|
1874
|
+
obtainUrl: "https://oriro.ai",
|
|
1875
|
+
keyless: true,
|
|
1876
|
+
verified: true
|
|
1877
|
+
})
|
|
1863
1878
|
];
|
|
1879
|
+
function selectableRouters() {
|
|
1880
|
+
return ROUTER_CATALOG.filter((r) => !r.comingSoon);
|
|
1881
|
+
}
|
|
1864
1882
|
function routerById(id) {
|
|
1865
1883
|
return ROUTER_CATALOG.find((r) => r.id === id);
|
|
1866
1884
|
}
|
|
@@ -3371,7 +3389,7 @@ import {
|
|
|
3371
3389
|
} from "@earendil-works/pi-coding-agent";
|
|
3372
3390
|
|
|
3373
3391
|
// src/routers/mux-provider.ts
|
|
3374
|
-
import { streamSimple as
|
|
3392
|
+
import { streamSimple as piStreamSimple2, createAssistantMessageEventStream } from "@earendil-works/pi-ai";
|
|
3375
3393
|
import { register as registerOpenAICompletions } from "@earendil-works/pi-ai/openai-completions";
|
|
3376
3394
|
|
|
3377
3395
|
// src/routers/mux.ts
|
|
@@ -3579,8 +3597,8 @@ function artifactsDir() {
|
|
|
3579
3597
|
// src/scribe/digest.ts
|
|
3580
3598
|
var DIGEST_CAP = 8192;
|
|
3581
3599
|
var TIMELINE_DAY_CAP = 400;
|
|
3582
|
-
function read(
|
|
3583
|
-
return existsSync8(
|
|
3600
|
+
function read(file6) {
|
|
3601
|
+
return existsSync8(file6) ? readFileSync12(file6, "utf8") : "";
|
|
3584
3602
|
}
|
|
3585
3603
|
function updateDigest(summary, context) {
|
|
3586
3604
|
mkdirSync10(scribeDir(), { recursive: true });
|
|
@@ -4118,7 +4136,54 @@ function attachScribe(session) {
|
|
|
4118
4136
|
});
|
|
4119
4137
|
}
|
|
4120
4138
|
|
|
4121
|
-
// src/
|
|
4139
|
+
// src/context/project-md.ts
|
|
4140
|
+
import { existsSync as existsSync13, readFileSync as readFileSync18, statSync as statSync2 } from "fs";
|
|
4141
|
+
import { join as join21, dirname as dirname3, parse } from "path";
|
|
4142
|
+
var NAMES = ["AGENTS.md", "CLAUDE.md", ".oriro/ORIRO.md"];
|
|
4143
|
+
var MAX_BYTES = 32 * 1024;
|
|
4144
|
+
var MAX_LEVELS = 24;
|
|
4145
|
+
function isRoot(dir) {
|
|
4146
|
+
return existsSync13(join21(dir, ".git")) || existsSync13(join21(dir, ".oriro"));
|
|
4147
|
+
}
|
|
4148
|
+
function discoverProjectInstructions(cwd) {
|
|
4149
|
+
const chain = [];
|
|
4150
|
+
let dir = cwd;
|
|
4151
|
+
const rootOfDrive = parse(cwd).root;
|
|
4152
|
+
for (let i = 0; i < MAX_LEVELS; i++) {
|
|
4153
|
+
for (const name of NAMES) {
|
|
4154
|
+
const p = join21(dir, name);
|
|
4155
|
+
try {
|
|
4156
|
+
if (existsSync13(p) && statSync2(p).isFile()) {
|
|
4157
|
+
let text = readFileSync18(p, "utf8");
|
|
4158
|
+
if (text.length > MAX_BYTES) text = text.slice(0, MAX_BYTES) + "\n\u2026(truncated)";
|
|
4159
|
+
text = text.trim();
|
|
4160
|
+
if (text) chain.push({ path: p, text });
|
|
4161
|
+
break;
|
|
4162
|
+
}
|
|
4163
|
+
} catch {
|
|
4164
|
+
}
|
|
4165
|
+
}
|
|
4166
|
+
if (isRoot(dir)) break;
|
|
4167
|
+
const parent = dirname3(dir);
|
|
4168
|
+
if (parent === dir || dir === rootOfDrive) break;
|
|
4169
|
+
dir = parent;
|
|
4170
|
+
}
|
|
4171
|
+
return chain.reverse();
|
|
4172
|
+
}
|
|
4173
|
+
function buildProjectContext(cwd = process.cwd()) {
|
|
4174
|
+
let found;
|
|
4175
|
+
try {
|
|
4176
|
+
found = discoverProjectInstructions(cwd);
|
|
4177
|
+
} catch {
|
|
4178
|
+
return "";
|
|
4179
|
+
}
|
|
4180
|
+
if (!found.length) return "";
|
|
4181
|
+
const blocks = found.map((f) => `# Project instructions \u2014 ${f.path}
|
|
4182
|
+
${f.text}`);
|
|
4183
|
+
return "The user's project ships these instructions. Treat them as authoritative for work in this repository; when two files conflict, the one listed LAST (nearest the working directory) wins.\n\n" + blocks.join("\n\n");
|
|
4184
|
+
}
|
|
4185
|
+
|
|
4186
|
+
// src/routers/mux-helpers.ts
|
|
4122
4187
|
var MUX_PROVIDER = "oriro-mux";
|
|
4123
4188
|
var MUX_MODEL = "oriro-free";
|
|
4124
4189
|
function errToCallError(msg) {
|
|
@@ -4138,6 +4203,145 @@ function buildErrorMessage(message) {
|
|
|
4138
4203
|
errorMessage: message
|
|
4139
4204
|
};
|
|
4140
4205
|
}
|
|
4206
|
+
|
|
4207
|
+
// src/routers/race.ts
|
|
4208
|
+
import { streamSimple as piStreamSimple } from "@earendil-works/pi-ai";
|
|
4209
|
+
|
|
4210
|
+
// src/routers/race-status.ts
|
|
4211
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
4212
|
+
var current = { phase: "idle", racers: [], winner: null };
|
|
4213
|
+
function emitRaceStatus(s) {
|
|
4214
|
+
current = s;
|
|
4215
|
+
for (const l of listeners) {
|
|
4216
|
+
try {
|
|
4217
|
+
l(s);
|
|
4218
|
+
} catch {
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
}
|
|
4222
|
+
function onRaceStatus(l) {
|
|
4223
|
+
listeners.add(l);
|
|
4224
|
+
try {
|
|
4225
|
+
l(current);
|
|
4226
|
+
} catch {
|
|
4227
|
+
}
|
|
4228
|
+
return () => {
|
|
4229
|
+
listeners.delete(l);
|
|
4230
|
+
};
|
|
4231
|
+
}
|
|
4232
|
+
function getRaceStatus() {
|
|
4233
|
+
return current;
|
|
4234
|
+
}
|
|
4235
|
+
|
|
4236
|
+
// src/routers/race.ts
|
|
4237
|
+
var DEFAULT_RACE_WIDTH = 3;
|
|
4238
|
+
var realStreamFactory = (router, context, options, signal) => piStreamSimple(routerModel(router), context, {
|
|
4239
|
+
...options ?? {},
|
|
4240
|
+
apiKey: router.apiKey,
|
|
4241
|
+
signal
|
|
4242
|
+
});
|
|
4243
|
+
async function raceMux(out, mux, byId, context, options, opts = {}) {
|
|
4244
|
+
const width = opts.width ?? DEFAULT_RACE_WIDTH;
|
|
4245
|
+
const streamFactory = opts.streamFactory ?? realStreamFactory;
|
|
4246
|
+
const push = (ev) => out.push(ev);
|
|
4247
|
+
const ranked = mux.ranked().filter((id) => byId.has(id));
|
|
4248
|
+
if (ranked.length === 0) {
|
|
4249
|
+
const msg = buildErrorMessage("All selected routers are unavailable. Add a BYOK key, select more free routers, or retry shortly.");
|
|
4250
|
+
push({ type: "error", reason: "error", error: msg });
|
|
4251
|
+
out.end(msg);
|
|
4252
|
+
emitRaceStatus({ phase: "failed", racers: [], winner: null });
|
|
4253
|
+
return;
|
|
4254
|
+
}
|
|
4255
|
+
const racers = ranked.slice(0, Math.max(1, Math.min(width, ranked.length)));
|
|
4256
|
+
emitRaceStatus({ phase: "racing", racers, winner: null });
|
|
4257
|
+
const controllers = /* @__PURE__ */ new Map();
|
|
4258
|
+
for (const id of racers) controllers.set(id, new AbortController());
|
|
4259
|
+
const abortLosers = (keep) => {
|
|
4260
|
+
for (const [id, c] of controllers) if (id !== keep) {
|
|
4261
|
+
try {
|
|
4262
|
+
c.abort();
|
|
4263
|
+
} catch {
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
};
|
|
4267
|
+
let winner = null;
|
|
4268
|
+
let settled2 = false;
|
|
4269
|
+
let lastError;
|
|
4270
|
+
let remaining = racers.length;
|
|
4271
|
+
return await new Promise((resolve3) => {
|
|
4272
|
+
const failAll = () => {
|
|
4273
|
+
if (settled2) return;
|
|
4274
|
+
settled2 = true;
|
|
4275
|
+
const msg = lastError ?? buildErrorMessage("All racers failed this request.");
|
|
4276
|
+
push({ type: "error", reason: "error", error: msg });
|
|
4277
|
+
out.end(msg);
|
|
4278
|
+
emitRaceStatus({ phase: "failed", racers, winner: null });
|
|
4279
|
+
resolve3();
|
|
4280
|
+
};
|
|
4281
|
+
for (const id of racers) {
|
|
4282
|
+
const router = byId.get(id);
|
|
4283
|
+
const ctrl = controllers.get(id);
|
|
4284
|
+
const t0 = Date.now();
|
|
4285
|
+
void (async () => {
|
|
4286
|
+
let iAmWinner = false;
|
|
4287
|
+
let lastPartial;
|
|
4288
|
+
try {
|
|
4289
|
+
for await (const ev of streamFactory(router, context, options, ctrl.signal)) {
|
|
4290
|
+
if (settled2 && !iAmWinner) return;
|
|
4291
|
+
if (ev.type === "error") {
|
|
4292
|
+
mux.recordFailure(id, ev.error ? errToCallError(ev.error) : {});
|
|
4293
|
+
if (iAmWinner && !settled2) {
|
|
4294
|
+
settled2 = true;
|
|
4295
|
+
push(ev);
|
|
4296
|
+
out.end(ev.error);
|
|
4297
|
+
resolve3();
|
|
4298
|
+
return;
|
|
4299
|
+
}
|
|
4300
|
+
lastError = ev.error ?? lastError;
|
|
4301
|
+
return;
|
|
4302
|
+
}
|
|
4303
|
+
if (!iAmWinner) {
|
|
4304
|
+
if (winner !== null || settled2) return;
|
|
4305
|
+
winner = id;
|
|
4306
|
+
iAmWinner = true;
|
|
4307
|
+
mux.recordSuccess(id, Date.now() - t0);
|
|
4308
|
+
emitRaceStatus({ phase: "won", racers, winner: id });
|
|
4309
|
+
abortLosers(id);
|
|
4310
|
+
}
|
|
4311
|
+
if (ev.type === "done") {
|
|
4312
|
+
if (!settled2) {
|
|
4313
|
+
settled2 = true;
|
|
4314
|
+
const clean = sanitizeMessageToolCalls(scrubMessageIdentity(ev.message));
|
|
4315
|
+
push({ type: "done", reason: ev.reason, message: clean });
|
|
4316
|
+
out.end(clean);
|
|
4317
|
+
resolve3();
|
|
4318
|
+
}
|
|
4319
|
+
return;
|
|
4320
|
+
}
|
|
4321
|
+
lastPartial = ev.partial ?? lastPartial;
|
|
4322
|
+
push(sanitizeEventToolCalls(ev));
|
|
4323
|
+
}
|
|
4324
|
+
if (iAmWinner && !settled2) {
|
|
4325
|
+
settled2 = true;
|
|
4326
|
+
out.end(lastPartial ? sanitizeMessageToolCalls(scrubMessageIdentity(lastPartial)) : void 0);
|
|
4327
|
+
resolve3();
|
|
4328
|
+
} else if (!iAmWinner) {
|
|
4329
|
+
mux.recordFailure(id, {});
|
|
4330
|
+
}
|
|
4331
|
+
} catch (e) {
|
|
4332
|
+
if (e?.name === "AbortError") return;
|
|
4333
|
+
mux.recordFailure(id, e);
|
|
4334
|
+
if (!iAmWinner) lastError ??= buildErrorMessage(e instanceof Error ? e.message : String(e));
|
|
4335
|
+
} finally {
|
|
4336
|
+
remaining -= 1;
|
|
4337
|
+
if (remaining === 0 && !settled2) failAll();
|
|
4338
|
+
}
|
|
4339
|
+
})();
|
|
4340
|
+
}
|
|
4341
|
+
});
|
|
4342
|
+
}
|
|
4343
|
+
|
|
4344
|
+
// src/routers/mux-provider.ts
|
|
4141
4345
|
async function driveMux(out, mux, byId, context, options) {
|
|
4142
4346
|
let lastError;
|
|
4143
4347
|
for (const id of mux.ranked()) {
|
|
@@ -4147,7 +4351,7 @@ async function driveMux(out, mux, byId, context, options) {
|
|
|
4147
4351
|
let committed = false;
|
|
4148
4352
|
let lastPartial;
|
|
4149
4353
|
try {
|
|
4150
|
-
const inner =
|
|
4354
|
+
const inner = piStreamSimple2(routerModel(router), context, {
|
|
4151
4355
|
...options ?? {},
|
|
4152
4356
|
apiKey: router.apiKey
|
|
4153
4357
|
});
|
|
@@ -4196,13 +4400,16 @@ async function driveMux(out, mux, byId, context, options) {
|
|
|
4196
4400
|
}
|
|
4197
4401
|
function registerOriroMux(registry, opts = {}) {
|
|
4198
4402
|
registerOpenAICompletions();
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4403
|
+
function resolveNow() {
|
|
4404
|
+
const pooled = resolvePool();
|
|
4405
|
+
const routers = opts.routers ?? (pooled.length > 0 ? pooled : KEYLESS_FLOOR);
|
|
4406
|
+
const byId = new Map(routers.map((r) => [r.id, r]));
|
|
4407
|
+
const mux = new RouterMux(routers.map((r) => r.id));
|
|
4408
|
+
try {
|
|
4409
|
+
mux.load(loadMuxState(oriroDir()));
|
|
4410
|
+
} catch {
|
|
4411
|
+
}
|
|
4412
|
+
return { routers, byId, mux };
|
|
4206
4413
|
}
|
|
4207
4414
|
registry.registerProvider(MUX_PROVIDER, {
|
|
4208
4415
|
name: "ORIRO Free (keyless Mux)",
|
|
@@ -4226,12 +4433,16 @@ function registerOriroMux(registry, opts = {}) {
|
|
|
4226
4433
|
],
|
|
4227
4434
|
streamSimple: (_model, context, options) => {
|
|
4228
4435
|
const out = createAssistantMessageEventStream();
|
|
4436
|
+
const { routers, byId, mux } = resolveNow();
|
|
4229
4437
|
const ctx = applyIdentity(context);
|
|
4438
|
+
const project = buildProjectContext();
|
|
4230
4439
|
const memory = buildScribeContext();
|
|
4231
|
-
const
|
|
4440
|
+
const extra = [project, memory].filter(Boolean).join("\n\n");
|
|
4441
|
+
const withMemory = extra ? { ...ctx, systemPrompt: `${ctx.systemPrompt}
|
|
4232
4442
|
|
|
4233
|
-
${
|
|
4234
|
-
|
|
4443
|
+
${extra}` } : ctx;
|
|
4444
|
+
const drive = routers.length > 1 ? raceMux(out, mux, byId, withMemory, options) : driveMux(out, mux, byId, withMemory, options);
|
|
4445
|
+
void drive.finally(() => {
|
|
4235
4446
|
try {
|
|
4236
4447
|
saveMuxState(oriroDir(), mux.snapshot());
|
|
4237
4448
|
} catch {
|
|
@@ -4554,7 +4765,7 @@ async function comparePages(opts) {
|
|
|
4554
4765
|
|
|
4555
4766
|
// src/head/run.ts
|
|
4556
4767
|
import { writeFile } from "fs/promises";
|
|
4557
|
-
import { join as
|
|
4768
|
+
import { join as join22 } from "path";
|
|
4558
4769
|
|
|
4559
4770
|
// src/head/inspection-html.ts
|
|
4560
4771
|
var PRIORITY_COLOR = {
|
|
@@ -5056,7 +5267,7 @@ async function runInspect(target, competitors, opts = {}) {
|
|
|
5056
5267
|
const report = await comparePages({ targetUrl: target, competitorUrls: competitors.length ? competitors : [target] });
|
|
5057
5268
|
const files = [];
|
|
5058
5269
|
if (opts.html) {
|
|
5059
|
-
const path =
|
|
5270
|
+
const path = join22(opts.outDir ?? process.cwd(), `oriro-head-${hostSlug(target)}-inspect.html`);
|
|
5060
5271
|
await writeFile(path, buildInspectionHtml(report), "utf8");
|
|
5061
5272
|
files.push(path);
|
|
5062
5273
|
}
|
|
@@ -5072,7 +5283,7 @@ function parseHeadTargets(text, selfOrigin) {
|
|
|
5072
5283
|
async function runUrlToCode(url, opts = {}) {
|
|
5073
5284
|
try {
|
|
5074
5285
|
const res = await urlToCode(url, headModels(), { goal: opts.goal, stack: opts.stack });
|
|
5075
|
-
const codePath =
|
|
5286
|
+
const codePath = join22(opts.outDir ?? process.cwd(), `oriro-head-${hostSlug(url)}${extForStack(opts.stack)}`);
|
|
5076
5287
|
await writeFile(codePath, res.code, "utf8");
|
|
5077
5288
|
return { summary: `Reverse-engineered ${url} into clean code (${res.code.length} chars) \u2192 ${codePath}`, files: [codePath] };
|
|
5078
5289
|
} catch (e) {
|
|
@@ -5082,7 +5293,7 @@ async function runUrlToCode(url, opts = {}) {
|
|
|
5082
5293
|
async function runUrlToSpec(url, opts = {}) {
|
|
5083
5294
|
try {
|
|
5084
5295
|
const res = await urlToSpec(url, headModels(), { goal: opts.goal });
|
|
5085
|
-
const specPath =
|
|
5296
|
+
const specPath = join22(opts.outDir ?? process.cwd(), `oriro-head-${hostSlug(url)}.spec.yaml`);
|
|
5086
5297
|
await writeFile(specPath, res.spec, "utf8");
|
|
5087
5298
|
return { summary: `Reverse-engineered ${url} into a YAML build spec \u2192 ${specPath}`, files: [specPath] };
|
|
5088
5299
|
} catch (e) {
|
|
@@ -5094,7 +5305,7 @@ async function runCapture(urls, opts = {}) {
|
|
|
5094
5305
|
const { captureScreens: captureScreens2, buildScreenshotFlowHtml: buildScreenshotFlowHtml2 } = await Promise.resolve().then(() => (init_screenshot_flow(), screenshot_flow_exports));
|
|
5095
5306
|
const caps = await captureScreens2(urls, { video: opts.video });
|
|
5096
5307
|
const html = buildScreenshotFlowHtml2([{ name: "Captured screens", captures: caps }]);
|
|
5097
|
-
const flowPath =
|
|
5308
|
+
const flowPath = join22(opts.outDir ?? process.cwd(), "oriro-head-flow.html");
|
|
5098
5309
|
await writeFile(flowPath, html, "utf8");
|
|
5099
5310
|
const ok2 = caps.filter((c) => c.ok).length;
|
|
5100
5311
|
return { summary: `Captured ${ok2}/${caps.length} full-page screenshots \u2192 ${flowPath}`, files: [flowPath] };
|
|
@@ -5115,7 +5326,7 @@ async function runVideoToCode(videoPath, opts = {}) {
|
|
|
5115
5326
|
{ videoPath, frames, mimeType: mime, goal: opts.goal, stack: opts.stack },
|
|
5116
5327
|
headVideoModels()
|
|
5117
5328
|
);
|
|
5118
|
-
const codePath =
|
|
5329
|
+
const codePath = join22(opts.outDir ?? process.cwd(), `oriro-head-video${extForStack(opts.stack)}`);
|
|
5119
5330
|
await writeFile(codePath, res.code, "utf8");
|
|
5120
5331
|
return { summary: `Watched ${videoPath} \u2192 built code (${res.code.length} chars) \u2192 ${codePath}
|
|
5121
5332
|
(experimental on the free floor \u2014 add a vision-capable router for pixel-faithful results.)`, files: [codePath] };
|
|
@@ -5293,21 +5504,428 @@ function registerOrchestrator(pi) {
|
|
|
5293
5504
|
});
|
|
5294
5505
|
}
|
|
5295
5506
|
|
|
5507
|
+
// src/agents/pi-tool.ts
|
|
5508
|
+
import { Type as Type4 } from "typebox";
|
|
5509
|
+
|
|
5510
|
+
// src/agents/store.ts
|
|
5511
|
+
import { mkdirSync as mkdirSync15, readFileSync as readFileSync19, writeFileSync as writeFileSync16, readdirSync as readdirSync2, rmSync as rmSync3, existsSync as existsSync14 } from "fs";
|
|
5512
|
+
import { join as join23 } from "path";
|
|
5513
|
+
var SLUG = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
5514
|
+
function isValidAgentName(name) {
|
|
5515
|
+
return SLUG.test(name);
|
|
5516
|
+
}
|
|
5517
|
+
function agentsDir() {
|
|
5518
|
+
return join23(oriroDir(), "agents");
|
|
5519
|
+
}
|
|
5520
|
+
function agentFile(name) {
|
|
5521
|
+
return join23(agentsDir(), `${name}.json`);
|
|
5522
|
+
}
|
|
5523
|
+
function stateFile() {
|
|
5524
|
+
return join23(agentsDir(), ".state.json");
|
|
5525
|
+
}
|
|
5526
|
+
function listAgents() {
|
|
5527
|
+
const dir = agentsDir();
|
|
5528
|
+
if (!existsSync14(dir)) return [];
|
|
5529
|
+
const out = [];
|
|
5530
|
+
for (const f of readdirSync2(dir)) {
|
|
5531
|
+
if (!f.endsWith(".json") || f.startsWith(".")) continue;
|
|
5532
|
+
try {
|
|
5533
|
+
const def = JSON.parse(readFileSync19(join23(dir, f), "utf8"));
|
|
5534
|
+
if (def && typeof def.name === "string" && typeof def.task === "string") out.push(def);
|
|
5535
|
+
} catch {
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5538
|
+
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
5539
|
+
}
|
|
5540
|
+
function loadAgent(name) {
|
|
5541
|
+
try {
|
|
5542
|
+
return JSON.parse(readFileSync19(agentFile(name), "utf8"));
|
|
5543
|
+
} catch {
|
|
5544
|
+
return void 0;
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5547
|
+
function saveAgent(def) {
|
|
5548
|
+
if (!isValidAgentName(def.name)) {
|
|
5549
|
+
throw new Error(`invalid agent name '${def.name}' \u2014 use lowercase letters, digits and hyphens`);
|
|
5550
|
+
}
|
|
5551
|
+
mkdirSync15(agentsDir(), { recursive: true });
|
|
5552
|
+
writeFileSync16(agentFile(def.name), JSON.stringify(def, null, 2), "utf8");
|
|
5553
|
+
}
|
|
5554
|
+
function removeAgent(name) {
|
|
5555
|
+
const file6 = agentFile(name);
|
|
5556
|
+
if (!existsSync14(file6)) return false;
|
|
5557
|
+
rmSync3(file6, { force: true });
|
|
5558
|
+
const state = loadState();
|
|
5559
|
+
if (state[name]) {
|
|
5560
|
+
delete state[name];
|
|
5561
|
+
saveState(state);
|
|
5562
|
+
}
|
|
5563
|
+
return true;
|
|
5564
|
+
}
|
|
5565
|
+
function loadState() {
|
|
5566
|
+
try {
|
|
5567
|
+
return JSON.parse(readFileSync19(stateFile(), "utf8"));
|
|
5568
|
+
} catch {
|
|
5569
|
+
return {};
|
|
5570
|
+
}
|
|
5571
|
+
}
|
|
5572
|
+
function saveState(state) {
|
|
5573
|
+
mkdirSync15(agentsDir(), { recursive: true });
|
|
5574
|
+
writeFileSync16(stateFile(), JSON.stringify(state, null, 2), "utf8");
|
|
5575
|
+
}
|
|
5576
|
+
function markRun(name, ok2, at) {
|
|
5577
|
+
const state = loadState();
|
|
5578
|
+
state[name] = { lastRunAt: at, lastOk: ok2 };
|
|
5579
|
+
saveState(state);
|
|
5580
|
+
}
|
|
5581
|
+
function parseScheduleMs(spec) {
|
|
5582
|
+
if (!spec) return void 0;
|
|
5583
|
+
const s = spec.trim().toLowerCase();
|
|
5584
|
+
if (s === "hourly") return 36e5;
|
|
5585
|
+
if (s === "daily") return 864e5;
|
|
5586
|
+
const m = /^(\d+)\s*(m|h|d)$/.exec(s);
|
|
5587
|
+
if (!m) return void 0;
|
|
5588
|
+
const n = Number(m[1]);
|
|
5589
|
+
if (n <= 0) return void 0;
|
|
5590
|
+
const mult = m[2] === "m" ? 6e4 : m[2] === "h" ? 36e5 : 864e5;
|
|
5591
|
+
return n * mult;
|
|
5592
|
+
}
|
|
5593
|
+
function isDue(def, state, now) {
|
|
5594
|
+
const ms = parseScheduleMs(def.schedule);
|
|
5595
|
+
if (ms === void 0) return false;
|
|
5596
|
+
const last = state[def.name]?.lastRunAt ?? 0;
|
|
5597
|
+
return now - last >= ms;
|
|
5598
|
+
}
|
|
5599
|
+
|
|
5600
|
+
// src/agents/run.ts
|
|
5601
|
+
var DEFAULT_TIMEOUT_MS = 3e5;
|
|
5602
|
+
function runTimeoutMs() {
|
|
5603
|
+
const v = Number(process.env.ORIRO_AGENT_TIMEOUT_MS);
|
|
5604
|
+
return Number.isFinite(v) && v > 0 ? v : DEFAULT_TIMEOUT_MS;
|
|
5605
|
+
}
|
|
5606
|
+
function resolveBoundRouter(id) {
|
|
5607
|
+
return registeredRouters().find((r) => r.id === id);
|
|
5608
|
+
}
|
|
5609
|
+
async function runAgent2(def, opts = {}) {
|
|
5610
|
+
const bound = def.router ? resolveBoundRouter(def.router) : void 0;
|
|
5611
|
+
const routers = bound ? [bound] : void 0;
|
|
5612
|
+
const cwd = opts.cwd ?? def.cwd ?? process.cwd();
|
|
5613
|
+
let session;
|
|
5614
|
+
try {
|
|
5615
|
+
({ session } = await assembleOriroSession({ cwd, ...routers ? { routers } : {} }));
|
|
5616
|
+
} catch (e) {
|
|
5617
|
+
return { ok: false, output: e instanceof Error ? e.message : String(e) };
|
|
5618
|
+
}
|
|
5619
|
+
let out = "";
|
|
5620
|
+
const unsub = session.subscribe(
|
|
5621
|
+
(e) => {
|
|
5622
|
+
if (e.type === "message_update" && e.assistantMessageEvent?.type === "text_delta") {
|
|
5623
|
+
out += e.assistantMessageEvent.delta ?? "";
|
|
5624
|
+
}
|
|
5625
|
+
}
|
|
5626
|
+
);
|
|
5627
|
+
const prompt = opts.input ? `${def.task}
|
|
5628
|
+
|
|
5629
|
+
Input:
|
|
5630
|
+
${opts.input}` : def.task;
|
|
5631
|
+
const prevDepth = process.env.ORIRO_AGENT_DEPTH;
|
|
5632
|
+
process.env.ORIRO_AGENT_DEPTH = String((Number(prevDepth) || 0) + 1);
|
|
5633
|
+
let timer;
|
|
5634
|
+
try {
|
|
5635
|
+
const timedOut = await Promise.race([
|
|
5636
|
+
session.prompt(prompt).then(() => false),
|
|
5637
|
+
new Promise((res) => {
|
|
5638
|
+
timer = setTimeout(() => res(true), runTimeoutMs());
|
|
5639
|
+
})
|
|
5640
|
+
]);
|
|
5641
|
+
if (timedOut) {
|
|
5642
|
+
const partial = scrubOutput(out).trim();
|
|
5643
|
+
return { ok: false, output: partial || `agent timed out after ${Math.round(runTimeoutMs() / 1e3)}s` };
|
|
5644
|
+
}
|
|
5645
|
+
} catch (e) {
|
|
5646
|
+
return { ok: false, output: e instanceof Error ? e.message : String(e) };
|
|
5647
|
+
} finally {
|
|
5648
|
+
if (timer) clearTimeout(timer);
|
|
5649
|
+
unsub();
|
|
5650
|
+
try {
|
|
5651
|
+
session.dispose();
|
|
5652
|
+
} catch {
|
|
5653
|
+
}
|
|
5654
|
+
if (prevDepth === void 0) delete process.env.ORIRO_AGENT_DEPTH;
|
|
5655
|
+
else process.env.ORIRO_AGENT_DEPTH = prevDepth;
|
|
5656
|
+
}
|
|
5657
|
+
const cleaned = scrubOutput(out).trim();
|
|
5658
|
+
return { ok: cleaned.length > 0, output: cleaned };
|
|
5659
|
+
}
|
|
5660
|
+
|
|
5661
|
+
// src/agents/pi-tool.ts
|
|
5662
|
+
function registerAgentRunner(pi) {
|
|
5663
|
+
pi.registerTool({
|
|
5664
|
+
name: "run_saved_agent",
|
|
5665
|
+
label: "ORIRO Agent",
|
|
5666
|
+
description: "Run one of the user's SAVED automation agents by name (list them first if unsure). Each agent is a stored workflow that runs on its own router with full tools behind Guardian. Optionally pass `input` to feed the agent. Use this when the user asks to run/trigger a named agent.",
|
|
5667
|
+
parameters: Type4.Object({
|
|
5668
|
+
name: Type4.String({ description: "the saved agent's name" }),
|
|
5669
|
+
input: Type4.Optional(Type4.String({ description: "optional input to pass to the agent" }))
|
|
5670
|
+
}),
|
|
5671
|
+
async execute(_id, params) {
|
|
5672
|
+
if (process.env.ORIRO_AGENT_DEPTH) {
|
|
5673
|
+
return { content: [{ type: "text", text: "Nested agent runs are disabled." }], details: { ok: false } };
|
|
5674
|
+
}
|
|
5675
|
+
const def = loadAgent(params.name);
|
|
5676
|
+
if (!def) {
|
|
5677
|
+
const names = listAgents().map((a) => a.name);
|
|
5678
|
+
const hint = names.length ? ` Saved agents: ${names.join(", ")}.` : " No agents saved yet.";
|
|
5679
|
+
return { content: [{ type: "text", text: `No agent named '${params.name}'.${hint}` }], details: { ok: false } };
|
|
5680
|
+
}
|
|
5681
|
+
const result = await runAgent2(def, params.input ? { input: params.input } : {});
|
|
5682
|
+
markRun(def.name, result.ok, Date.now());
|
|
5683
|
+
const status = result.ok ? "\u2713" : "\u2717";
|
|
5684
|
+
return {
|
|
5685
|
+
content: [{ type: "text", text: `[${def.name}] ${status}
|
|
5686
|
+
${result.output.slice(0, 4e3)}` }],
|
|
5687
|
+
details: { ok: result.ok }
|
|
5688
|
+
};
|
|
5689
|
+
}
|
|
5690
|
+
});
|
|
5691
|
+
}
|
|
5692
|
+
|
|
5693
|
+
// src/connectors/mcp-client.ts
|
|
5694
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5695
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
5696
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
5697
|
+
var DISALLOWED_ENV = /* @__PURE__ */ new Set([
|
|
5698
|
+
"PATH",
|
|
5699
|
+
"LD_PRELOAD",
|
|
5700
|
+
"LD_LIBRARY_PATH",
|
|
5701
|
+
"DYLD_INSERT_LIBRARIES",
|
|
5702
|
+
"DYLD_LIBRARY_PATH",
|
|
5703
|
+
"NODE_OPTIONS",
|
|
5704
|
+
"PYTHONPATH",
|
|
5705
|
+
"PYTHONSTARTUP",
|
|
5706
|
+
"PERL5LIB",
|
|
5707
|
+
"RUBYOPT",
|
|
5708
|
+
"GEM_PATH",
|
|
5709
|
+
"APPINIT_DLLS",
|
|
5710
|
+
"COR_PROFILER",
|
|
5711
|
+
"BASH_ENV",
|
|
5712
|
+
"ENV",
|
|
5713
|
+
"IFS"
|
|
5714
|
+
]);
|
|
5715
|
+
var HANDSHAKE_TIMEOUT_MS = 8e3;
|
|
5716
|
+
var CALL_TIMEOUT_MS = 3e4;
|
|
5717
|
+
function sanitizeName(name) {
|
|
5718
|
+
return (name || "").toLowerCase().replace(/[^a-z0-9_-]+/g, "_").replace(/^_+|_+$/g, "").slice(0, 64) || "x";
|
|
5719
|
+
}
|
|
5720
|
+
function assertSafeUrl(raw, allowLocal = false) {
|
|
5721
|
+
const u = new URL(raw);
|
|
5722
|
+
if (u.protocol !== "https:" && u.protocol !== "http:") throw new Error(`unsupported scheme: ${u.protocol}`);
|
|
5723
|
+
const host = u.hostname.toLowerCase();
|
|
5724
|
+
const isLoopback = host === "localhost" || host === "127.0.0.1" || host === "::1" || host.endsWith(".localhost");
|
|
5725
|
+
const isPrivate = /^10\./.test(host) || /^192\.168\./.test(host) || /^172\.(1[6-9]|2\d|3[01])\./.test(host) || /^169\.254\./.test(host) || /^fe80:/i.test(host) || /^f[cd][0-9a-f]{2}:/i.test(host) || host === "169.254.169.254" || host === "metadata.google.internal";
|
|
5726
|
+
if ((isLoopback || isPrivate) && !allowLocal) {
|
|
5727
|
+
throw new Error(`blocked SSRF target ${host} (use --allow-local for loopback/LAN MCP servers)`);
|
|
5728
|
+
}
|
|
5729
|
+
if (u.protocol === "http:" && !isLoopback && !allowLocal) throw new Error(`refusing plaintext http to ${host} \u2014 use https`);
|
|
5730
|
+
return u;
|
|
5731
|
+
}
|
|
5732
|
+
function safeEnv(env) {
|
|
5733
|
+
const out = {};
|
|
5734
|
+
for (const [k, v] of Object.entries(env ?? {})) {
|
|
5735
|
+
if (DISALLOWED_ENV.has(k.toUpperCase())) continue;
|
|
5736
|
+
out[k] = v;
|
|
5737
|
+
}
|
|
5738
|
+
return out;
|
|
5739
|
+
}
|
|
5740
|
+
async function connectServer(name, config, opts = {}) {
|
|
5741
|
+
const client = new Client({ name: "oriro-cli", version: "0.1.0" }, { capabilities: {} });
|
|
5742
|
+
let transport;
|
|
5743
|
+
let stderr = "";
|
|
5744
|
+
if (config.type === "stdio") {
|
|
5745
|
+
const t = new StdioClientTransport({
|
|
5746
|
+
command: config.command,
|
|
5747
|
+
args: config.args ?? [],
|
|
5748
|
+
env: safeEnv(config.env),
|
|
5749
|
+
stderr: "pipe"
|
|
5750
|
+
});
|
|
5751
|
+
t.stderr?.on("data", (b) => {
|
|
5752
|
+
stderr += b.toString();
|
|
5753
|
+
});
|
|
5754
|
+
transport = t;
|
|
5755
|
+
} else {
|
|
5756
|
+
const url = assertSafeUrl(config.url, opts.allowLocal);
|
|
5757
|
+
transport = new StreamableHTTPClientTransport(url, {
|
|
5758
|
+
requestInit: { headers: { "User-Agent": "oriro-cli/0.1.0", ...config.headers ?? {} } }
|
|
5759
|
+
});
|
|
5760
|
+
}
|
|
5761
|
+
const timeoutMs = opts.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;
|
|
5762
|
+
let timer;
|
|
5763
|
+
try {
|
|
5764
|
+
await Promise.race([
|
|
5765
|
+
client.connect(transport),
|
|
5766
|
+
new Promise((_, rej) => {
|
|
5767
|
+
timer = setTimeout(() => rej(new Error("handshake timed out")), timeoutMs);
|
|
5768
|
+
})
|
|
5769
|
+
]);
|
|
5770
|
+
} catch (e) {
|
|
5771
|
+
const detail = stderr.trim() ? `
|
|
5772
|
+
server stderr:
|
|
5773
|
+
${stderr.trim().slice(0, 800)}` : "";
|
|
5774
|
+
try {
|
|
5775
|
+
await transport.close();
|
|
5776
|
+
} catch {
|
|
5777
|
+
}
|
|
5778
|
+
throw new Error(`MCP connect failed (${name}): ${e instanceof Error ? e.message : String(e)}${detail}`);
|
|
5779
|
+
} finally {
|
|
5780
|
+
if (timer) clearTimeout(timer);
|
|
5781
|
+
}
|
|
5782
|
+
return {
|
|
5783
|
+
name,
|
|
5784
|
+
client,
|
|
5785
|
+
dispose: async () => {
|
|
5786
|
+
try {
|
|
5787
|
+
await client.close();
|
|
5788
|
+
} catch {
|
|
5789
|
+
}
|
|
5790
|
+
}
|
|
5791
|
+
};
|
|
5792
|
+
}
|
|
5793
|
+
async function listAllTools(client) {
|
|
5794
|
+
const tools = [];
|
|
5795
|
+
let cursor;
|
|
5796
|
+
do {
|
|
5797
|
+
const res = await client.listTools(cursor ? { cursor } : void 0, { timeout: CALL_TIMEOUT_MS });
|
|
5798
|
+
for (const t of res.tools) tools.push({ name: t.name, description: t.description, inputSchema: t.inputSchema });
|
|
5799
|
+
cursor = res.nextCursor;
|
|
5800
|
+
} while (cursor);
|
|
5801
|
+
return tools;
|
|
5802
|
+
}
|
|
5803
|
+
|
|
5804
|
+
// src/connectors/register.ts
|
|
5805
|
+
import { Type as Type5 } from "typebox";
|
|
5806
|
+
function registerToolList(pi, serverName, client, tools, seen = /* @__PURE__ */ new Set()) {
|
|
5807
|
+
const server = sanitizeName(serverName);
|
|
5808
|
+
const registered = [];
|
|
5809
|
+
for (const t of tools) {
|
|
5810
|
+
const publicName = `mcp__${server}__${sanitizeName(t.name)}`;
|
|
5811
|
+
if (seen.has(publicName)) continue;
|
|
5812
|
+
seen.add(publicName);
|
|
5813
|
+
const realName = t.name;
|
|
5814
|
+
pi.registerTool({
|
|
5815
|
+
name: publicName,
|
|
5816
|
+
label: `MCP: ${serverName}`,
|
|
5817
|
+
description: (t.description ?? `${t.name} (via ${serverName})`).slice(0, 1024),
|
|
5818
|
+
parameters: Type5.Object({}, { additionalProperties: true }),
|
|
5819
|
+
async execute(_id, params) {
|
|
5820
|
+
const details = { server: serverName, tool: realName };
|
|
5821
|
+
try {
|
|
5822
|
+
const res = await client.callTool(
|
|
5823
|
+
{ name: realName, arguments: params ?? {} },
|
|
5824
|
+
void 0,
|
|
5825
|
+
{ timeout: CALL_TIMEOUT_MS }
|
|
5826
|
+
);
|
|
5827
|
+
const text = (res.content ?? []).filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("\n");
|
|
5828
|
+
if (res.isError) {
|
|
5829
|
+
details.isError = true;
|
|
5830
|
+
return { content: [{ type: "text", text: `MCP tool error: ${text || "(no detail)"}` }], details };
|
|
5831
|
+
}
|
|
5832
|
+
return { content: [{ type: "text", text: text || "(no text content)" }], details };
|
|
5833
|
+
} catch (e) {
|
|
5834
|
+
details.isError = true;
|
|
5835
|
+
return { content: [{ type: "text", text: `MCP call failed: ${e instanceof Error ? e.message : String(e)}` }], details };
|
|
5836
|
+
}
|
|
5837
|
+
}
|
|
5838
|
+
});
|
|
5839
|
+
registered.push(publicName);
|
|
5840
|
+
}
|
|
5841
|
+
return registered;
|
|
5842
|
+
}
|
|
5843
|
+
|
|
5844
|
+
// src/connectors/custom.ts
|
|
5845
|
+
import { readFileSync as readFileSync20, writeFileSync as writeFileSync17 } from "fs";
|
|
5846
|
+
import { join as join24 } from "path";
|
|
5847
|
+
function file3() {
|
|
5848
|
+
return join24(oriroDir(), "mcp-custom.json");
|
|
5849
|
+
}
|
|
5850
|
+
function readCustomServers() {
|
|
5851
|
+
try {
|
|
5852
|
+
const v = JSON.parse(readFileSync20(file3(), "utf8"));
|
|
5853
|
+
return Array.isArray(v) ? v : [];
|
|
5854
|
+
} catch {
|
|
5855
|
+
return [];
|
|
5856
|
+
}
|
|
5857
|
+
}
|
|
5858
|
+
function saveCustomServer(server) {
|
|
5859
|
+
const rest = readCustomServers().filter((s) => s.name.toLowerCase() !== server.name.toLowerCase());
|
|
5860
|
+
writeFileSync17(join24(ensureOriroDir(), "mcp-custom.json"), JSON.stringify([...rest, server], null, 2), "utf8");
|
|
5861
|
+
}
|
|
5862
|
+
function removeCustomServer(name) {
|
|
5863
|
+
const before = readCustomServers();
|
|
5864
|
+
const after = before.filter((s) => s.name.toLowerCase() !== name.toLowerCase());
|
|
5865
|
+
if (after.length === before.length) return false;
|
|
5866
|
+
writeFileSync17(join24(ensureOriroDir(), "mcp-custom.json"), JSON.stringify(after, null, 2), "utf8");
|
|
5867
|
+
return true;
|
|
5868
|
+
}
|
|
5869
|
+
function trustedServerNames() {
|
|
5870
|
+
return readCustomServers().filter((s) => s.trusted).map((s) => s.name);
|
|
5871
|
+
}
|
|
5872
|
+
function isServerTrusted(name) {
|
|
5873
|
+
return trustedServerNames().some((n) => n.toLowerCase() === name.toLowerCase());
|
|
5874
|
+
}
|
|
5875
|
+
|
|
5876
|
+
// src/connectors/session-connect.ts
|
|
5877
|
+
var CONNECT_TIMEOUT_MS = 8e3;
|
|
5878
|
+
async function prepareConnectors() {
|
|
5879
|
+
const targets = [];
|
|
5880
|
+
for (const c of addedConnectors()) {
|
|
5881
|
+
if (c.mcpUrl) targets.push({ name: c.slug, config: { type: "http", url: c.mcpUrl } });
|
|
5882
|
+
}
|
|
5883
|
+
for (const s of readCustomServers()) {
|
|
5884
|
+
if (s.trusted) targets.push({ name: s.name, config: s.config, allowLocal: true });
|
|
5885
|
+
}
|
|
5886
|
+
const out = [];
|
|
5887
|
+
for (const t of targets) {
|
|
5888
|
+
try {
|
|
5889
|
+
const conn = await connectServer(t.name, t.config, {
|
|
5890
|
+
timeoutMs: CONNECT_TIMEOUT_MS,
|
|
5891
|
+
...t.allowLocal ? { allowLocal: true } : {}
|
|
5892
|
+
});
|
|
5893
|
+
const tools = await listAllTools(conn.client);
|
|
5894
|
+
out.push({ name: t.name, client: conn.client, tools });
|
|
5895
|
+
} catch {
|
|
5896
|
+
}
|
|
5897
|
+
}
|
|
5898
|
+
return out;
|
|
5899
|
+
}
|
|
5900
|
+
function registerPreparedConnectors(pi, prepared) {
|
|
5901
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5902
|
+
for (const p of prepared) registerToolList(pi, p.name, p.client, p.tools, seen);
|
|
5903
|
+
}
|
|
5904
|
+
|
|
5296
5905
|
// src/onboarding/assemble.ts
|
|
5297
5906
|
async function assembleOriroSession(opts = {}) {
|
|
5298
5907
|
const cwd = opts.cwd ?? process.cwd();
|
|
5299
5908
|
const authStorage = AuthStorage2.inMemory();
|
|
5300
5909
|
const modelRegistry = ModelRegistry2.inMemory(authStorage);
|
|
5301
5910
|
const settingsManager = SettingsManager.create(cwd);
|
|
5302
|
-
const model = registerOriroMux(modelRegistry);
|
|
5911
|
+
const model = registerOriroMux(modelRegistry, opts.routers ? { routers: opts.routers } : {});
|
|
5303
5912
|
if (!model) throw new Error("ORIRO keyless model unavailable");
|
|
5913
|
+
const preparedConnectors = await prepareConnectors();
|
|
5304
5914
|
const resourceLoader = new DefaultResourceLoader({
|
|
5305
5915
|
cwd,
|
|
5306
5916
|
agentDir: getAgentDir(),
|
|
5307
5917
|
settingsManager,
|
|
5308
5918
|
additionalSkillPaths: skillRoots(),
|
|
5309
5919
|
// bundled library + the user's own ~/.oriro/skills
|
|
5310
|
-
extensionFactories: [
|
|
5920
|
+
extensionFactories: [
|
|
5921
|
+
registerGuardian,
|
|
5922
|
+
registerHead,
|
|
5923
|
+
registerScribe,
|
|
5924
|
+
registerOrchestrator,
|
|
5925
|
+
registerAgentRunner,
|
|
5926
|
+
(pi) => registerPreparedConnectors(pi, preparedConnectors)
|
|
5927
|
+
// MCP connectors → agent tools
|
|
5928
|
+
]
|
|
5311
5929
|
});
|
|
5312
5930
|
await resourceLoader.reload();
|
|
5313
5931
|
const { session, extensionsResult } = await createAgentSession2({
|
|
@@ -5496,14 +6114,14 @@ var MODE_META = {
|
|
|
5496
6114
|
auto: { label: "Auto", indicator: "\u23F5\u23F5" },
|
|
5497
6115
|
plan: { label: "Plan", indicator: "\u25A2" }
|
|
5498
6116
|
};
|
|
5499
|
-
var
|
|
6117
|
+
var current2 = "manual";
|
|
5500
6118
|
function getMode() {
|
|
5501
|
-
return
|
|
6119
|
+
return current2;
|
|
5502
6120
|
}
|
|
5503
6121
|
function cycleMode() {
|
|
5504
|
-
const i = MODES.indexOf(
|
|
5505
|
-
|
|
5506
|
-
return
|
|
6122
|
+
const i = MODES.indexOf(current2);
|
|
6123
|
+
current2 = MODES[(i + 1) % MODES.length];
|
|
6124
|
+
return current2;
|
|
5507
6125
|
}
|
|
5508
6126
|
var thinking = false;
|
|
5509
6127
|
function getThinking() {
|
|
@@ -5516,7 +6134,7 @@ function toggleThinking() {
|
|
|
5516
6134
|
var THINKING_PRIMER = "Think step by step and plan your approach before acting. Reason carefully and check your work.";
|
|
5517
6135
|
|
|
5518
6136
|
// src/repl-ui/verify-actions.ts
|
|
5519
|
-
import { existsSync as
|
|
6137
|
+
import { existsSync as existsSync15 } from "fs";
|
|
5520
6138
|
import { isAbsolute, resolve } from "path";
|
|
5521
6139
|
var CLAIM = /\b(?:have|has)\s+been\s+created\b|\b(?:created|wrote|written|saved|generated)\b(?![ \t]*(?:by you|it yourself))/i;
|
|
5522
6140
|
var SUGGESTION = /\byou\s+(?:can|could|should|may)\s+(?:create|add|save|make|put)\b/i;
|
|
@@ -5529,7 +6147,7 @@ function phantomFileWarning(reply, cwd = process.cwd()) {
|
|
|
5529
6147
|
if (!p) continue;
|
|
5530
6148
|
if (/^https?:|node_modules|<[^>]+>|your-|example\./i.test(p)) continue;
|
|
5531
6149
|
const abs = isAbsolute(p) ? p : resolve(cwd, p.replace(/^[.][\\/]/, ""));
|
|
5532
|
-
if (!
|
|
6150
|
+
if (!existsSync15(abs)) missing.add(p);
|
|
5533
6151
|
}
|
|
5534
6152
|
if (missing.size === 0) return "";
|
|
5535
6153
|
if (SUGGESTION.test(reply) && !/\b(?:have|has)\s+been\s+created\b/i.test(reply)) return "";
|
|
@@ -5539,30 +6157,236 @@ function phantomFileWarning(reply, cwd = process.cwd()) {
|
|
|
5539
6157
|
\u26A0 ORIRO said it ${plural ? "created files" : "created a file"} (${list}), but ${plural ? "they're" : "it's"} not on disk \u2014 the free router may have described the write without actually running it. Retry, or add your own key with \`oriro routers\` for reliable coding.`;
|
|
5540
6158
|
}
|
|
5541
6159
|
|
|
5542
|
-
// src/repl-ui/
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5550
|
-
|
|
6160
|
+
// src/repl-ui/slash-routers.ts
|
|
6161
|
+
function isRouterSlash(cmd) {
|
|
6162
|
+
return /^\/(routers?|model)(\s|$)/i.test(cmd.trim());
|
|
6163
|
+
}
|
|
6164
|
+
function poolLine() {
|
|
6165
|
+
const pool = resolvePool();
|
|
6166
|
+
return pool.length ? `${dim("racing now:")} ${accent(pool.map((p) => p.id).join(", "))}` : dim("racing now: (empty) \u2192 keyless floor");
|
|
6167
|
+
}
|
|
6168
|
+
function catalogLines(head) {
|
|
6169
|
+
const lines = [];
|
|
6170
|
+
lines.push(
|
|
6171
|
+
head === "/model" ? dim(" ORIRO models & free routers \u2014 they race, best answer wins:") : dim(" Router catalog \u2014 they race, best answer wins:")
|
|
6172
|
+
);
|
|
6173
|
+
for (const r of selectableRouters()) {
|
|
6174
|
+
const tier = r.keyless ? fgHex(PALETTE.success, "keyless") : dim(r.tier);
|
|
6175
|
+
lines.push(` ${accent(r.id.padEnd(20))} ${r.displayName.padEnd(22)} ${tier}`);
|
|
6176
|
+
}
|
|
6177
|
+
lines.push(` ${poolLine()}`);
|
|
6178
|
+
lines.push(dim(" add: /routers add <id> \xB7 rotate: /routers use <id> [<id>\u2026]"));
|
|
6179
|
+
return lines;
|
|
6180
|
+
}
|
|
6181
|
+
async function handleRouterSlash(raw) {
|
|
6182
|
+
const parts = raw.trim().split(/\s+/);
|
|
6183
|
+
const head = (parts[0] ?? "").toLowerCase();
|
|
6184
|
+
const sub = (parts[1] ?? "").toLowerCase();
|
|
6185
|
+
try {
|
|
6186
|
+
if (sub === "add") {
|
|
6187
|
+
const id = parts[2];
|
|
6188
|
+
if (!id) return [dim(" usage: /routers add <id> (e.g. /routers add oriro-gauss)")];
|
|
6189
|
+
const entry = routerById(id);
|
|
6190
|
+
if (!entry) return [dim(` unknown router '${id}' \u2014 try /routers list`)];
|
|
6191
|
+
const res = await addRouter(entry, {});
|
|
6192
|
+
if (res.ok) {
|
|
6193
|
+
return [
|
|
6194
|
+
` ${fgHex(PALETTE.success, "\u2713")} added ${accent(id)} (${res.validation.latencyMs}ms, model ${res.validation.model}) \u2192 ${fgHex(PALETTE.success, "now racing")}`,
|
|
6195
|
+
` ${poolLine()}`
|
|
6196
|
+
];
|
|
6197
|
+
}
|
|
6198
|
+
return [dim(` \u2717 could not add ${id}: ${res.validation.error ?? "validation failed"}`)];
|
|
6199
|
+
}
|
|
6200
|
+
const rotate = sub === "use" ? parts.slice(2) : head === "/model" && parts[1] && sub !== "list" ? parts.slice(1) : null;
|
|
6201
|
+
if (rotate) {
|
|
6202
|
+
if (!rotate.length) return [dim(" usage: /routers use <id> [<id>\u2026]")];
|
|
6203
|
+
const { applied, unknown } = useRouters(rotate);
|
|
6204
|
+
const out = [];
|
|
6205
|
+
if (applied.length) out.push(` ${fgHex(PALETTE.success, "\u2713")} now racing: ${accent(applied.join(", "))}`);
|
|
6206
|
+
if (unknown.length) out.push(dim(` not registered yet (add first): ${unknown.join(", ")}`));
|
|
6207
|
+
return out.length ? out : [dim(" nothing applied \u2014 add a router first: /routers add <id>")];
|
|
6208
|
+
}
|
|
6209
|
+
return catalogLines(head);
|
|
6210
|
+
} catch (e) {
|
|
6211
|
+
return [dim(` router command failed: ${e instanceof Error ? e.message : String(e)}`)];
|
|
5551
6212
|
}
|
|
5552
|
-
};
|
|
5553
|
-
function footerText() {
|
|
5554
|
-
const cur = getMode();
|
|
5555
|
-
const bar = MODES.map((m) => {
|
|
5556
|
-
const meta = MODE_META[m];
|
|
5557
|
-
const s = `${meta.indicator} ${meta.label}`;
|
|
5558
|
-
return m === cur ? accent(s) : dim(s);
|
|
5559
|
-
}).join(dim(" \xB7 "));
|
|
5560
|
-
const think = getThinking() ? accent("\u{1F9E0} Thinking") : dim("\u{1F9E0} Thinking");
|
|
5561
|
-
return `${bar} ${think} ${dim("Shift+Tab posture \xB7 Alt+Shift+T thinking \xB7 /exit")}`;
|
|
5562
6213
|
}
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
6214
|
+
|
|
6215
|
+
// src/repl-ui/repl-state.ts
|
|
6216
|
+
var turns = 0;
|
|
6217
|
+
var trace = false;
|
|
6218
|
+
function bumpTurns() {
|
|
6219
|
+
turns += 1;
|
|
6220
|
+
}
|
|
6221
|
+
function getTurns() {
|
|
6222
|
+
return turns;
|
|
6223
|
+
}
|
|
6224
|
+
function getTrace() {
|
|
6225
|
+
return trace;
|
|
6226
|
+
}
|
|
6227
|
+
function toggleTrace() {
|
|
6228
|
+
trace = !trace;
|
|
6229
|
+
return trace;
|
|
6230
|
+
}
|
|
6231
|
+
|
|
6232
|
+
// src/repl-ui/slash-usage.ts
|
|
6233
|
+
function isUsageSlash(cmd) {
|
|
6234
|
+
return /^\/usage(\s|$)/i.test(cmd.trim());
|
|
6235
|
+
}
|
|
6236
|
+
function handleUsage() {
|
|
6237
|
+
const pool = resolvePool();
|
|
6238
|
+
const health = new Map(loadMuxState(oriroDir()).map((s) => [s.id, s]));
|
|
6239
|
+
const race = getRaceStatus();
|
|
6240
|
+
const lines = [];
|
|
6241
|
+
lines.push(dim(` turns this session: ${accent(String(getTurns()))} \xB7 thinking-trace: ${getTrace() ? fgHex(PALETTE.success, "on") : dim("off")}`));
|
|
6242
|
+
lines.push(dim(" racing pool (learned latency \xB7 health):"));
|
|
6243
|
+
if (!pool.length) {
|
|
6244
|
+
lines.push(dim(" (empty) \u2192 the keyless floor"));
|
|
6245
|
+
} else {
|
|
6246
|
+
const now = Date.now();
|
|
6247
|
+
for (const r of pool) {
|
|
6248
|
+
const s = health.get(r.id);
|
|
6249
|
+
const lat = s && Number.isFinite(s.latencyMs) ? `${Math.round(s.latencyMs)}ms` : "untried";
|
|
6250
|
+
const state = !s ? dim("new") : !s.healthy ? fgHex(PALETTE.error, "unhealthy") : s.cooldownUntil > now ? fgHex(PALETTE.error, "cooling") : fgHex(PALETTE.success, "healthy");
|
|
6251
|
+
lines.push(` ${accent(r.id.padEnd(20))} ${dim(lat.padEnd(9))} ${state}`);
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
if (race.winner && race.racers.length > 1) {
|
|
6255
|
+
lines.push(dim(` last race: ${race.racers.join(" \xB7 ")} \u2192 won: `) + accent(race.winner));
|
|
6256
|
+
}
|
|
6257
|
+
return lines;
|
|
6258
|
+
}
|
|
6259
|
+
|
|
6260
|
+
// src/repl-ui/slash-artifacts.ts
|
|
6261
|
+
import { existsSync as existsSync16, writeFileSync as writeFileSync18 } from "fs";
|
|
6262
|
+
|
|
6263
|
+
// src/repl-ui/artifacts.ts
|
|
6264
|
+
var LANG_EXT = {
|
|
6265
|
+
python: "py",
|
|
6266
|
+
py: "py",
|
|
6267
|
+
javascript: "js",
|
|
6268
|
+
js: "js",
|
|
6269
|
+
typescript: "ts",
|
|
6270
|
+
ts: "ts",
|
|
6271
|
+
tsx: "tsx",
|
|
6272
|
+
jsx: "jsx",
|
|
6273
|
+
html: "html",
|
|
6274
|
+
css: "css",
|
|
6275
|
+
json: "json",
|
|
6276
|
+
yaml: "yaml",
|
|
6277
|
+
yml: "yml",
|
|
6278
|
+
bash: "sh",
|
|
6279
|
+
sh: "sh",
|
|
6280
|
+
shell: "sh",
|
|
6281
|
+
sql: "sql",
|
|
6282
|
+
go: "go",
|
|
6283
|
+
rust: "rs",
|
|
6284
|
+
rs: "rs",
|
|
6285
|
+
java: "java",
|
|
6286
|
+
c: "c",
|
|
6287
|
+
cpp: "cpp",
|
|
6288
|
+
"c++": "cpp",
|
|
6289
|
+
ruby: "rb",
|
|
6290
|
+
rb: "rb",
|
|
6291
|
+
php: "php",
|
|
6292
|
+
markdown: "md",
|
|
6293
|
+
md: "md",
|
|
6294
|
+
svg: "svg"
|
|
6295
|
+
};
|
|
6296
|
+
function extFor(lang) {
|
|
6297
|
+
return LANG_EXT[lang.toLowerCase()] ?? "txt";
|
|
6298
|
+
}
|
|
6299
|
+
function extractArtifacts(text) {
|
|
6300
|
+
const out = [];
|
|
6301
|
+
if (!text) return out;
|
|
6302
|
+
const fence = /```([\w+#.-]*)\n([\s\S]*?)```/g;
|
|
6303
|
+
let m;
|
|
6304
|
+
while ((m = fence.exec(text)) !== null) {
|
|
6305
|
+
const lang = (m[1] ?? "").trim();
|
|
6306
|
+
const content = (m[2] ?? "").replace(/\n$/, "");
|
|
6307
|
+
if (!content.trim()) continue;
|
|
6308
|
+
const isSvg = lang.toLowerCase() === "svg" || /^\s*<svg[\s>]/.test(content);
|
|
6309
|
+
out.push({
|
|
6310
|
+
kind: isSvg ? "svg" : "code",
|
|
6311
|
+
lang: lang || (isSvg ? "svg" : ""),
|
|
6312
|
+
content,
|
|
6313
|
+
suggestedName: `artifact-${out.length + 1}.${isSvg ? "svg" : extFor(lang)}`
|
|
6314
|
+
});
|
|
6315
|
+
}
|
|
6316
|
+
const svg = /<svg[\s>][\s\S]*?<\/svg>/gi;
|
|
6317
|
+
while ((m = svg.exec(text)) !== null) {
|
|
6318
|
+
const content = m[0];
|
|
6319
|
+
if (out.some((a) => a.content.includes(content))) continue;
|
|
6320
|
+
out.push({ kind: "svg", lang: "svg", content, suggestedName: `artifact-${out.length + 1}.svg` });
|
|
6321
|
+
}
|
|
6322
|
+
return out;
|
|
6323
|
+
}
|
|
6324
|
+
var current3 = [];
|
|
6325
|
+
function setArtifacts(a) {
|
|
6326
|
+
current3 = a;
|
|
6327
|
+
}
|
|
6328
|
+
function getArtifacts() {
|
|
6329
|
+
return current3;
|
|
6330
|
+
}
|
|
6331
|
+
|
|
6332
|
+
// src/repl-ui/slash-artifacts.ts
|
|
6333
|
+
function isArtifactSlash(cmd) {
|
|
6334
|
+
return /^\/(review|artifacts?|save)(\s|$)/i.test(cmd.trim());
|
|
6335
|
+
}
|
|
6336
|
+
function handleArtifactSlash(raw) {
|
|
6337
|
+
const parts = raw.trim().split(/\s+/);
|
|
6338
|
+
const head = (parts[0] ?? "").toLowerCase();
|
|
6339
|
+
const arts = getArtifacts();
|
|
6340
|
+
if (head === "/save") {
|
|
6341
|
+
const idx = parseInt(parts[1] ?? "", 10);
|
|
6342
|
+
if (!Number.isInteger(idx) || idx < 1 || idx > arts.length) {
|
|
6343
|
+
return [dim(" usage: /save <n> [path] \u2014 run /review to see the artifacts")];
|
|
6344
|
+
}
|
|
6345
|
+
const art = arts[idx - 1];
|
|
6346
|
+
if (!art) return [dim(" no such artifact")];
|
|
6347
|
+
const dest = parts[2] || art.suggestedName;
|
|
6348
|
+
if (existsSync16(dest)) return [dim(` \u2717 ${dest} already exists \u2014 give a different path: /save ${idx} <path>`)];
|
|
6349
|
+
try {
|
|
6350
|
+
writeFileSync18(dest, art.content, "utf8");
|
|
6351
|
+
} catch (e) {
|
|
6352
|
+
return [dim(` \u2717 could not write ${dest}: ${e instanceof Error ? e.message : String(e)}`)];
|
|
6353
|
+
}
|
|
6354
|
+
return [` ${fgHex(PALETTE.success, "\u2713")} saved artifact ${accent(String(idx))} \u2192 ${accent(dest)} ${dim(`(${art.content.length} bytes)`)}`];
|
|
6355
|
+
}
|
|
6356
|
+
if (!arts.length) return [dim(" no artifacts in the last reply \u2014 ask for code or an SVG, then /review")];
|
|
6357
|
+
const lines = [dim(" Artifacts from the last reply \u2014 save one with /save <n> [path]:")];
|
|
6358
|
+
arts.forEach((a, i) => {
|
|
6359
|
+
const nlines = a.content.split("\n").length;
|
|
6360
|
+
const preview = (a.content.split("\n")[0] ?? "").slice(0, 48).replace(/\s+/g, " ");
|
|
6361
|
+
lines.push(` ${accent(String(i + 1))}. ${a.kind}${a.lang ? `/${a.lang}` : ""} \xB7 ${nlines} lines \xB7 \u2192 ${dim(a.suggestedName)} ${dim(preview)}`);
|
|
6362
|
+
});
|
|
6363
|
+
return lines;
|
|
6364
|
+
}
|
|
6365
|
+
|
|
6366
|
+
// src/repl-ui/tui-repl.ts
|
|
6367
|
+
var editorTheme = {
|
|
6368
|
+
borderColor: (s) => dim(s),
|
|
6369
|
+
selectList: {
|
|
6370
|
+
selectedPrefix: (s) => accent(s),
|
|
6371
|
+
selectedText: (s) => accent(s),
|
|
6372
|
+
description: (s) => dim(s),
|
|
6373
|
+
scrollInfo: (s) => dim(s),
|
|
6374
|
+
noMatch: (s) => dim(s)
|
|
6375
|
+
}
|
|
6376
|
+
};
|
|
6377
|
+
function footerText() {
|
|
6378
|
+
const cur = getMode();
|
|
6379
|
+
const bar = MODES.map((m) => {
|
|
6380
|
+
const meta = MODE_META[m];
|
|
6381
|
+
const s = `${meta.indicator} ${meta.label}`;
|
|
6382
|
+
return m === cur ? accent(s) : dim(s);
|
|
6383
|
+
}).join(dim(" \xB7 "));
|
|
6384
|
+
const think = getThinking() ? accent("\u{1F9E0} Thinking") : dim("\u{1F9E0} Thinking");
|
|
6385
|
+
return `${bar} ${think} ${dim("Shift+Tab posture \xB7 Alt+Shift+T thinking \xB7 /exit")}`;
|
|
6386
|
+
}
|
|
6387
|
+
async function runTuiRepl(session) {
|
|
6388
|
+
const isEnglish3 = getTerminalLanguage().code.toLowerCase().startsWith("en");
|
|
6389
|
+
const term = new ProcessTerminal();
|
|
5566
6390
|
const tui = new TUI(term, true);
|
|
5567
6391
|
const chat = new Container();
|
|
5568
6392
|
const editor = new Editor(tui, editorTheme, { paddingX: 1 });
|
|
@@ -5618,7 +6442,13 @@ async function runTuiRepl(session) {
|
|
|
5618
6442
|
const slash = text.toLowerCase();
|
|
5619
6443
|
if (slash === "/exit" || slash === "/quit") return cleanup();
|
|
5620
6444
|
if (slash === "/help" || slash === "/?") {
|
|
5621
|
-
|
|
6445
|
+
const help = [
|
|
6446
|
+
" Just type to chat \u2014 ORIRO writes and runs code for you (keyless, free).",
|
|
6447
|
+
` ${accent("/routers")} pool add\xB7rotate ${accent("/model")} <id\u2026> switch ${accent("/usage")} health ${accent("/trace")} tool+router activity`,
|
|
6448
|
+
` ${accent("/review")} artifacts from the last reply ${accent("/save")} <n> [path] ${accent("/skills")} ${accent("/connectors")} ${accent("/voice")}`,
|
|
6449
|
+
` ${dim("Shift+Tab")} posture ${dim("Alt+Shift+T")} thinking ${accent("/help")} ${accent("/exit")}`
|
|
6450
|
+
].join("\n");
|
|
6451
|
+
chat.addChild(new Text(help, 0, 0));
|
|
5622
6452
|
editor.setText("");
|
|
5623
6453
|
tui.requestRender();
|
|
5624
6454
|
return;
|
|
@@ -5635,6 +6465,37 @@ async function runTuiRepl(session) {
|
|
|
5635
6465
|
tui.requestRender();
|
|
5636
6466
|
return;
|
|
5637
6467
|
}
|
|
6468
|
+
if (isRouterSlash(slash)) {
|
|
6469
|
+
editor.setText("");
|
|
6470
|
+
const pending = new Text(dim(" \u2026"), 0, 0);
|
|
6471
|
+
chat.addChild(pending);
|
|
6472
|
+
tui.requestRender();
|
|
6473
|
+
void (async () => {
|
|
6474
|
+
const lines = await handleRouterSlash(text);
|
|
6475
|
+
pending.setText(lines.join("\n"));
|
|
6476
|
+
tui.requestRender();
|
|
6477
|
+
})();
|
|
6478
|
+
return;
|
|
6479
|
+
}
|
|
6480
|
+
if (isUsageSlash(slash)) {
|
|
6481
|
+
chat.addChild(new Text(handleUsage().join("\n"), 0, 0));
|
|
6482
|
+
editor.setText("");
|
|
6483
|
+
tui.requestRender();
|
|
6484
|
+
return;
|
|
6485
|
+
}
|
|
6486
|
+
if (slash === "/trace") {
|
|
6487
|
+
const on = toggleTrace();
|
|
6488
|
+
chat.addChild(new Text(dim(` trace ${on ? "ON \u2014 showing tool + router activity" : "off"}`), 0, 0));
|
|
6489
|
+
editor.setText("");
|
|
6490
|
+
tui.requestRender();
|
|
6491
|
+
return;
|
|
6492
|
+
}
|
|
6493
|
+
if (isArtifactSlash(slash)) {
|
|
6494
|
+
chat.addChild(new Text(handleArtifactSlash(text).join("\n"), 0, 0));
|
|
6495
|
+
editor.setText("");
|
|
6496
|
+
tui.requestRender();
|
|
6497
|
+
return;
|
|
6498
|
+
}
|
|
5638
6499
|
if (slash === "/voice") {
|
|
5639
6500
|
editor.setText("");
|
|
5640
6501
|
const status = new Text(dim(" \u{1F399} listening\u2026 (needs ffmpeg + the transformers voice peer)"), 0, 0);
|
|
@@ -5655,10 +6516,23 @@ async function runTuiRepl(session) {
|
|
|
5655
6516
|
editor.addToHistory(text);
|
|
5656
6517
|
editor.setText("");
|
|
5657
6518
|
chat.addChild(new Text(`${accent("\u203A")} ${text}`, 0, 1));
|
|
6519
|
+
const raceLine = new Text("", 0, 0);
|
|
6520
|
+
chat.addChild(raceLine);
|
|
5658
6521
|
const streaming = new Text(dim("\u2026"), 0, 0);
|
|
5659
6522
|
chat.addChild(streaming);
|
|
6523
|
+
const unsubRace = onRaceStatus((s) => {
|
|
6524
|
+
if (s.phase === "racing" && s.racers.length > 1) {
|
|
6525
|
+
raceLine.setText(dim(` \u23F1 racing: ${s.racers.join(" \xB7 ")}`));
|
|
6526
|
+
} else if (s.phase === "won" && s.winner && s.racers.length > 1) {
|
|
6527
|
+
raceLine.setText(dim(` \u23F1 ${s.racers.join(" \xB7 ")} \u2192 won: `) + accent(s.winner));
|
|
6528
|
+
} else {
|
|
6529
|
+
raceLine.setText("");
|
|
6530
|
+
}
|
|
6531
|
+
tui.requestRender();
|
|
6532
|
+
});
|
|
5660
6533
|
tui.requestRender();
|
|
5661
6534
|
busy = true;
|
|
6535
|
+
bumpTurns();
|
|
5662
6536
|
void (async () => {
|
|
5663
6537
|
let english = await translateIncoming(text);
|
|
5664
6538
|
if (getThinking()) english = `${THINKING_PRIMER}
|
|
@@ -5674,6 +6548,9 @@ ${english}`;
|
|
|
5674
6548
|
streaming.setText(out);
|
|
5675
6549
|
tui.requestRender();
|
|
5676
6550
|
}
|
|
6551
|
+
} else if (getTrace() && (e.type === "tool_start" || e.type === "tool_end" || e.type === "toolcall_start")) {
|
|
6552
|
+
chat.addChild(new Text(dim(` \u2699 ${e.type.replace("_", " ")}${e.toolName ? `: ${e.toolName}` : ""}`), 0, 0));
|
|
6553
|
+
tui.requestRender();
|
|
5677
6554
|
}
|
|
5678
6555
|
}
|
|
5679
6556
|
);
|
|
@@ -5684,13 +6561,19 @@ ${english}`;
|
|
|
5684
6561
|
tui.requestRender();
|
|
5685
6562
|
busy = false;
|
|
5686
6563
|
unsub();
|
|
6564
|
+
unsubRace();
|
|
5687
6565
|
return;
|
|
5688
6566
|
}
|
|
5689
6567
|
unsub();
|
|
6568
|
+
unsubRace();
|
|
5690
6569
|
const cleaned = scrubOutput(out);
|
|
5691
6570
|
const finalText = isEnglish3 ? cleaned.trim() : await translateOutgoing(cleaned.trim());
|
|
5692
6571
|
const warn = phantomFileWarning(finalText);
|
|
5693
|
-
|
|
6572
|
+
const arts = extractArtifacts(finalText);
|
|
6573
|
+
setArtifacts(arts);
|
|
6574
|
+
const hint = arts.length ? dim(`
|
|
6575
|
+
\u2398 ${arts.length} artifact${arts.length === 1 ? "" : "s"} \u2014 /review to save`) : "";
|
|
6576
|
+
streaming.setText((finalText || dim("(no response)")) + (warn ? dim(warn) : "") + hint);
|
|
5694
6577
|
tui.requestRender();
|
|
5695
6578
|
busy = false;
|
|
5696
6579
|
})();
|
|
@@ -5704,8 +6587,8 @@ ${english}`;
|
|
|
5704
6587
|
// src/voice/mic.ts
|
|
5705
6588
|
import { spawn as spawn3 } from "child_process";
|
|
5706
6589
|
import { tmpdir as tmpdir3 } from "os";
|
|
5707
|
-
import { join as
|
|
5708
|
-
import { existsSync as
|
|
6590
|
+
import { join as join25 } from "path";
|
|
6591
|
+
import { existsSync as existsSync17, statSync as statSync3 } from "fs";
|
|
5709
6592
|
function recorders(outFile, seconds) {
|
|
5710
6593
|
const dur = String(seconds);
|
|
5711
6594
|
if (process.platform === "darwin") {
|
|
@@ -5726,12 +6609,12 @@ function recorders(outFile, seconds) {
|
|
|
5726
6609
|
];
|
|
5727
6610
|
}
|
|
5728
6611
|
async function recordMic(seconds = 6) {
|
|
5729
|
-
const outFile =
|
|
6612
|
+
const outFile = join25(tmpdir3(), `oriro-voice-${process.pid}-${seconds}.wav`);
|
|
5730
6613
|
for (const r of recorders(outFile, seconds)) {
|
|
5731
6614
|
const okFile = await new Promise((resolve3) => {
|
|
5732
6615
|
const child = spawn3(r.cmd, r.args, { stdio: "ignore" });
|
|
5733
6616
|
child.on("error", () => resolve3(false));
|
|
5734
|
-
child.on("close", (code) => resolve3(code === 0 &&
|
|
6617
|
+
child.on("close", (code) => resolve3(code === 0 && existsSync17(outFile) && statSync3(outFile).size > 44));
|
|
5735
6618
|
});
|
|
5736
6619
|
if (okFile) return outFile;
|
|
5737
6620
|
}
|
|
@@ -5795,9 +6678,13 @@ function replHelp() {
|
|
|
5795
6678
|
${accent("ORIRO terminal \u2014 help")}
|
|
5796
6679
|
${dim("Just type to chat; ORIRO writes and runs code for you (keyless, free).")}
|
|
5797
6680
|
|
|
5798
|
-
${
|
|
5799
|
-
${dim("
|
|
5800
|
-
${dim("
|
|
6681
|
+
${dim("Models & routers")} ${accent("/routers")} list\xB7add\xB7rotate the racing pool ${accent("/model")} <id\u2026> switch
|
|
6682
|
+
${dim("This session")} ${accent("/usage")} pool health & turns ${accent("/trace")} show tool + router activity
|
|
6683
|
+
${dim("Artifacts")} ${accent("/review")} code/SVG from the last reply ${accent("/save")} <n> [path] write one
|
|
6684
|
+
${dim("Capabilities")} ${accent("/skills")} ${accent("/connectors")} ${accent("/voice")} speak a turn
|
|
6685
|
+
${dim("General")} ${accent("/help")} this ${accent("/exit")} / ${accent("/quit")} leave ${dim("(Ctrl-D / Ctrl-C also exit)")}
|
|
6686
|
+
|
|
6687
|
+
${dim("Full command list outside the chat:")} ${accent("oriro --help")}
|
|
5801
6688
|
|
|
5802
6689
|
`;
|
|
5803
6690
|
}
|
|
@@ -5856,6 +6743,24 @@ async function runReadlineRepl(session) {
|
|
|
5856
6743
|
`);
|
|
5857
6744
|
continue;
|
|
5858
6745
|
}
|
|
6746
|
+
if (isRouterSlash(slash)) {
|
|
6747
|
+
stdout7.write((await handleRouterSlash(line)).join("\n") + "\n");
|
|
6748
|
+
continue;
|
|
6749
|
+
}
|
|
6750
|
+
if (isUsageSlash(slash)) {
|
|
6751
|
+
stdout7.write(handleUsage().join("\n") + "\n");
|
|
6752
|
+
continue;
|
|
6753
|
+
}
|
|
6754
|
+
if (slash === "/trace") {
|
|
6755
|
+
stdout7.write(` ${dim(`trace ${toggleTrace() ? "ON" : "off"}`)}
|
|
6756
|
+
`);
|
|
6757
|
+
continue;
|
|
6758
|
+
}
|
|
6759
|
+
if (isArtifactSlash(slash)) {
|
|
6760
|
+
stdout7.write(handleArtifactSlash(line).join("\n") + "\n");
|
|
6761
|
+
continue;
|
|
6762
|
+
}
|
|
6763
|
+
bumpTurns();
|
|
5859
6764
|
const english = await translateIncoming(line);
|
|
5860
6765
|
noteUserInput(line);
|
|
5861
6766
|
let out = "";
|
|
@@ -5873,8 +6778,12 @@ async function runReadlineRepl(session) {
|
|
|
5873
6778
|
}
|
|
5874
6779
|
const cleaned = scrubOutput(out);
|
|
5875
6780
|
const shown = isEnglish3 ? cleaned.trim() : await translateOutgoing(cleaned.trim());
|
|
6781
|
+
const arts = extractArtifacts(shown);
|
|
6782
|
+
setArtifacts(arts);
|
|
6783
|
+
const hint = arts.length ? ` ${dim(`\u2398 ${arts.length} artifact${arts.length === 1 ? "" : "s"} \u2014 /review to save`)}
|
|
6784
|
+
` : "";
|
|
5876
6785
|
stdout7.write(`${shown}${phantomFileWarning(shown)}
|
|
5877
|
-
|
|
6786
|
+
${hint}
|
|
5878
6787
|
`);
|
|
5879
6788
|
}
|
|
5880
6789
|
} finally {
|
|
@@ -5887,7 +6796,54 @@ async function runReadlineRepl(session) {
|
|
|
5887
6796
|
}
|
|
5888
6797
|
}
|
|
5889
6798
|
|
|
6799
|
+
// src/headless.ts
|
|
6800
|
+
function isOutputFormatMode(s) {
|
|
6801
|
+
return s === "text" || s === "json" || s === "stream-json";
|
|
6802
|
+
}
|
|
6803
|
+
async function runHeadless(prompt, format) {
|
|
6804
|
+
if (!prompt.trim()) {
|
|
6805
|
+
process.stderr.write('error: empty prompt \u2014 pass text after -p, e.g. oriro -p "summarise this repo"\n');
|
|
6806
|
+
process.exitCode = 1;
|
|
6807
|
+
return;
|
|
6808
|
+
}
|
|
6809
|
+
const { session } = await assembleOriroSession({});
|
|
6810
|
+
let text = "";
|
|
6811
|
+
const unsub = session.subscribe(
|
|
6812
|
+
(e) => {
|
|
6813
|
+
if (e.type === "message_update" && e.assistantMessageEvent?.type === "text_delta") {
|
|
6814
|
+
const d = e.assistantMessageEvent.delta ?? "";
|
|
6815
|
+
text += d;
|
|
6816
|
+
if (format === "stream-json" && d) process.stdout.write(JSON.stringify({ type: "text_delta", delta: d }) + "\n");
|
|
6817
|
+
}
|
|
6818
|
+
}
|
|
6819
|
+
);
|
|
6820
|
+
let error = "";
|
|
6821
|
+
try {
|
|
6822
|
+
await session.prompt(prompt);
|
|
6823
|
+
} catch (e) {
|
|
6824
|
+
error = e instanceof Error ? e.message : String(e);
|
|
6825
|
+
}
|
|
6826
|
+
unsub();
|
|
6827
|
+
const response = scrubOutput(text).trim();
|
|
6828
|
+
const ok2 = !error && response.length > 0;
|
|
6829
|
+
if (format === "json") {
|
|
6830
|
+
process.stdout.write(JSON.stringify({ ok: ok2, response, ...error ? { error } : {} }) + "\n");
|
|
6831
|
+
} else if (format === "stream-json") {
|
|
6832
|
+
process.stdout.write(JSON.stringify({ type: "done", ok: ok2, response, ...error ? { error } : {} }) + "\n");
|
|
6833
|
+
} else {
|
|
6834
|
+
process.stdout.write((response || (error ? `error: ${error}` : "(no response)")) + "\n");
|
|
6835
|
+
}
|
|
6836
|
+
process.exitCode = ok2 ? 0 : 1;
|
|
6837
|
+
try {
|
|
6838
|
+
session.dispose();
|
|
6839
|
+
} catch {
|
|
6840
|
+
}
|
|
6841
|
+
setTimeout(() => process.exit(ok2 ? 0 : 1), 400).unref();
|
|
6842
|
+
}
|
|
6843
|
+
|
|
5890
6844
|
// src/commands/ui.ts
|
|
6845
|
+
import { createInterface as createInterface7 } from "readline/promises";
|
|
6846
|
+
import { stdin as stdin7, stdout as stdout8 } from "process";
|
|
5891
6847
|
var ok = (s) => {
|
|
5892
6848
|
process.stdout.write(`${fgHex(PALETTE.success, "\u2713")} ${s}
|
|
5893
6849
|
`);
|
|
@@ -5912,11 +6868,159 @@ function die(msg) {
|
|
|
5912
6868
|
process.exitCode = 1;
|
|
5913
6869
|
throw new DieError(msg);
|
|
5914
6870
|
}
|
|
6871
|
+
async function confirmDestructive(what, opts = {}) {
|
|
6872
|
+
if (opts.force) return true;
|
|
6873
|
+
if (!stdin7.isTTY || !stdout8.isTTY) {
|
|
6874
|
+
die(`refusing to ${what} without confirmation \u2014 re-run with --force in a non-interactive shell`);
|
|
6875
|
+
}
|
|
6876
|
+
const rl = createInterface7({ input: stdin7, output: stdout8 });
|
|
6877
|
+
try {
|
|
6878
|
+
const ans = (await rl.question(`${fgHex(PALETTE.error, "?")} ${what} \u2014 this cannot be undone. Proceed? [y/N] `)).trim().toLowerCase();
|
|
6879
|
+
return ans === "y" || ans === "yes";
|
|
6880
|
+
} finally {
|
|
6881
|
+
rl.close();
|
|
6882
|
+
}
|
|
6883
|
+
}
|
|
6884
|
+
|
|
6885
|
+
// src/config/store.ts
|
|
6886
|
+
import { readFileSync as readFileSync21, writeFileSync as writeFileSync19, mkdirSync as mkdirSync16 } from "fs";
|
|
6887
|
+
import { join as join26 } from "path";
|
|
6888
|
+
var KEYS = {
|
|
6889
|
+
output: {
|
|
6890
|
+
desc: "default output format for list commands: text | json | csv",
|
|
6891
|
+
validate: (v) => ["text", "json", "csv"].includes(v) ? null : "must be text | json | csv"
|
|
6892
|
+
},
|
|
6893
|
+
lang: { desc: "preferred UI language code (e.g. en, hi, es) \u2014 overrides terminal detection" },
|
|
6894
|
+
thinking: {
|
|
6895
|
+
desc: "default REPL thinking mode: on | off",
|
|
6896
|
+
validate: (v) => ["on", "off"].includes(v) ? null : "must be on | off"
|
|
6897
|
+
}
|
|
6898
|
+
};
|
|
6899
|
+
function configKeys() {
|
|
6900
|
+
return Object.keys(KEYS).map((key) => ({ key, desc: KEYS[key].desc }));
|
|
6901
|
+
}
|
|
6902
|
+
function isConfigKey(k) {
|
|
6903
|
+
return k in KEYS;
|
|
6904
|
+
}
|
|
6905
|
+
function validateConfig(key, value) {
|
|
6906
|
+
return KEYS[key].validate?.(value) ?? null;
|
|
6907
|
+
}
|
|
6908
|
+
function file4() {
|
|
6909
|
+
return join26(oriroDir(), "config.json");
|
|
6910
|
+
}
|
|
6911
|
+
var cache = null;
|
|
6912
|
+
function readAll() {
|
|
6913
|
+
if (cache) return cache;
|
|
6914
|
+
try {
|
|
6915
|
+
const v = JSON.parse(readFileSync21(file4(), "utf8"));
|
|
6916
|
+
cache = v && typeof v === "object" ? v : {};
|
|
6917
|
+
} catch {
|
|
6918
|
+
cache = {};
|
|
6919
|
+
}
|
|
6920
|
+
return cache;
|
|
6921
|
+
}
|
|
6922
|
+
function configGet(key) {
|
|
6923
|
+
return readAll()[key];
|
|
6924
|
+
}
|
|
6925
|
+
function configAll() {
|
|
6926
|
+
return { ...readAll() };
|
|
6927
|
+
}
|
|
6928
|
+
function configSet(key, value) {
|
|
6929
|
+
const all = { ...readAll(), [key]: value };
|
|
6930
|
+
mkdirSync16(oriroDir(), { recursive: true });
|
|
6931
|
+
writeFileSync19(file4(), JSON.stringify(all, null, 2), "utf8");
|
|
6932
|
+
cache = all;
|
|
6933
|
+
}
|
|
6934
|
+
function configUnset(key) {
|
|
6935
|
+
const all = readAll();
|
|
6936
|
+
if (!(key in all)) return false;
|
|
6937
|
+
const rest = { ...all };
|
|
6938
|
+
delete rest[key];
|
|
6939
|
+
writeFileSync19(file4(), JSON.stringify(rest, null, 2), "utf8");
|
|
6940
|
+
cache = rest;
|
|
6941
|
+
return true;
|
|
6942
|
+
}
|
|
6943
|
+
|
|
6944
|
+
// src/commands/output.ts
|
|
6945
|
+
function parseFormat(o) {
|
|
6946
|
+
const f = (o ?? configGet("output") ?? "text").toLowerCase();
|
|
6947
|
+
if (f === "json" || f === "csv" || f === "text") return f;
|
|
6948
|
+
throw new Error(`invalid --output '${o}'. Use: text | json | csv`);
|
|
6949
|
+
}
|
|
6950
|
+
function applyQuery(rows, query) {
|
|
6951
|
+
if (!query) return rows;
|
|
6952
|
+
const [filterPart, selectField] = query.split(":", 2);
|
|
6953
|
+
let out = rows;
|
|
6954
|
+
const fp = filterPart ?? "";
|
|
6955
|
+
if (fp.includes("=")) {
|
|
6956
|
+
const [field2, value] = fp.split("=", 2);
|
|
6957
|
+
out = rows.filter((r) => String(r[field2] ?? "") === value);
|
|
6958
|
+
} else if (fp && !selectField) {
|
|
6959
|
+
return rows.map((r) => r[fp]);
|
|
6960
|
+
}
|
|
6961
|
+
if (selectField) return out.map((r) => r[selectField]);
|
|
6962
|
+
return out;
|
|
6963
|
+
}
|
|
6964
|
+
function csvCell(v) {
|
|
6965
|
+
const s = v === null || v === void 0 ? "" : String(v);
|
|
6966
|
+
return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
|
|
6967
|
+
}
|
|
6968
|
+
function renderList2(rows, opts = {}) {
|
|
6969
|
+
const fmt = parseFormat(opts.output);
|
|
6970
|
+
const queried = applyQuery(rows, opts.query);
|
|
6971
|
+
if (fmt === "json") return JSON.stringify(queried, null, 2);
|
|
6972
|
+
if (!Array.isArray(queried) || queried.length === 0) return "";
|
|
6973
|
+
const first = queried[0];
|
|
6974
|
+
const scalar = typeof first !== "object" || first === null;
|
|
6975
|
+
if (scalar) return queried.map((v) => fmt === "csv" ? csvCell(v) : String(v)).join("\n");
|
|
6976
|
+
const objs = queried;
|
|
6977
|
+
const cols = opts.columns ?? [...new Set(objs.flatMap((r) => Object.keys(r)))];
|
|
6978
|
+
if (fmt === "csv") {
|
|
6979
|
+
return [cols.map(csvCell).join(","), ...objs.map((r) => cols.map((c) => csvCell(r[c])).join(","))].join("\n");
|
|
6980
|
+
}
|
|
6981
|
+
const widths = cols.map((c) => Math.max(c.length, ...objs.map((r) => String(r[c] ?? "").length)));
|
|
6982
|
+
const line = (cells) => cells.map((s, i) => s.padEnd(widths[i] ?? 0)).join(" ").trimEnd();
|
|
6983
|
+
return [line(cols), ...objs.map((r) => line(cols.map((c) => String(r[c] ?? ""))))].join("\n");
|
|
6984
|
+
}
|
|
6985
|
+
function isMachineOutput(opts) {
|
|
6986
|
+
return parseFormat(opts.output) !== "text";
|
|
6987
|
+
}
|
|
6988
|
+
function outputError(opts) {
|
|
6989
|
+
const f = (opts.output ?? configGet("output") ?? "text").toLowerCase();
|
|
6990
|
+
return f === "json" || f === "csv" || f === "text" ? null : `invalid --output '${opts.output}' \u2014 use text | json | csv`;
|
|
6991
|
+
}
|
|
5915
6992
|
|
|
5916
6993
|
// src/commands/routers.ts
|
|
5917
6994
|
function registerRoutersCommand(program2) {
|
|
5918
6995
|
const routers = program2.command("routers").description("manage the free-router pool the model runs on");
|
|
5919
|
-
routers.command("list").description("list the router catalog and the active pool").action(() => {
|
|
6996
|
+
routers.command("list").description("list the router catalog and the active pool").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action((opts) => {
|
|
6997
|
+
const oerr = outputError(opts);
|
|
6998
|
+
if (oerr) die(oerr);
|
|
6999
|
+
const pool = new Set(resolvePool().map((p) => p.id));
|
|
7000
|
+
if (isMachineOutput(opts) || opts.query) {
|
|
7001
|
+
const catalogRows = ROUTER_CATALOG.filter((r) => !r.comingSoon).map((r) => ({
|
|
7002
|
+
id: r.id,
|
|
7003
|
+
name: r.displayName,
|
|
7004
|
+
tier: r.keyless ? "keyless" : r.tier,
|
|
7005
|
+
keyless: Boolean(r.keyless),
|
|
7006
|
+
source: "catalog",
|
|
7007
|
+
active: pool.has(r.id)
|
|
7008
|
+
}));
|
|
7009
|
+
const customRows = registeredRouters().filter((r) => !ROUTER_CATALOG.some((c) => c.id === r.id)).map((r) => ({
|
|
7010
|
+
id: r.id,
|
|
7011
|
+
name: r.name,
|
|
7012
|
+
tier: r.apiKey && r.apiKey !== KEYLESS_SENTINEL ? "byok" : "keyless",
|
|
7013
|
+
keyless: !r.apiKey || r.apiKey === KEYLESS_SENTINEL,
|
|
7014
|
+
source: "custom",
|
|
7015
|
+
active: pool.has(r.id)
|
|
7016
|
+
}));
|
|
7017
|
+
process.stdout.write(renderList2([...catalogRows, ...customRows], {
|
|
7018
|
+
output: opts.output,
|
|
7019
|
+
query: opts.query,
|
|
7020
|
+
columns: ["id", "name", "tier", "keyless", "active", "source"]
|
|
7021
|
+
}) + "\n");
|
|
7022
|
+
return;
|
|
7023
|
+
}
|
|
5920
7024
|
heading("Routers");
|
|
5921
7025
|
for (const r of ROUTER_CATALOG) {
|
|
5922
7026
|
if (r.comingSoon) {
|
|
@@ -5939,8 +7043,7 @@ function registerRoutersCommand(program2) {
|
|
|
5939
7043
|
`);
|
|
5940
7044
|
}
|
|
5941
7045
|
}
|
|
5942
|
-
|
|
5943
|
-
info(pool.length ? `active pool: ${pool.map((p) => p.id).join(", ")}` : "active pool: empty \u2192 using the keyless floor");
|
|
7046
|
+
info(pool.size ? `active pool: ${[...pool].join(", ")}` : "active pool: empty \u2192 using the keyless floor");
|
|
5944
7047
|
});
|
|
5945
7048
|
routers.command("add <name>").description("live-validate a router and add it to the pool \u2014 a catalog name, OR any custom endpoint via --url").option("-k, --key <key>", "API key (BYOK) \u2014 omit for a keyless free router").option("-m, --model <id>", "model id to run (REQUIRED for a custom --url router)").option("--url <baseUrl>", "add ANY custom free/BYOK router by its OpenAI-compatible base URL (the part BEFORE /chat/completions)").option("--api <api>", "custom router API: 'openai' (default) or 'google'", "openai").action(async (name, opts) => {
|
|
5946
7049
|
let entry;
|
|
@@ -5976,10 +7079,10 @@ function registerRoutersCommand(program2) {
|
|
|
5976
7079
|
}
|
|
5977
7080
|
|
|
5978
7081
|
// src/commands/scribe.ts
|
|
5979
|
-
import { readFileSync as
|
|
7082
|
+
import { readFileSync as readFileSync23 } from "fs";
|
|
5980
7083
|
|
|
5981
7084
|
// src/scribe/transcript.ts
|
|
5982
|
-
import { existsSync as
|
|
7085
|
+
import { existsSync as existsSync19, readFileSync as readFileSync22 } from "fs";
|
|
5983
7086
|
function parseHookStdin(raw) {
|
|
5984
7087
|
try {
|
|
5985
7088
|
const j = JSON.parse(raw);
|
|
@@ -6012,8 +7115,8 @@ function isHumanUser(e) {
|
|
|
6012
7115
|
}
|
|
6013
7116
|
var FILE_KEYS = ["file_path", "path", "notebook_path", "filePath"];
|
|
6014
7117
|
function lastTurnFromTranscript(path) {
|
|
6015
|
-
if (!
|
|
6016
|
-
const raw =
|
|
7118
|
+
if (!existsSync19(path)) return null;
|
|
7119
|
+
const raw = readFileSync22(path, "utf8");
|
|
6017
7120
|
const entries = [];
|
|
6018
7121
|
for (const line of raw.split("\n")) {
|
|
6019
7122
|
if (!line.trim()) continue;
|
|
@@ -6074,7 +7177,7 @@ function lastTurnFromTranscript(path) {
|
|
|
6074
7177
|
// src/commands/scribe.ts
|
|
6075
7178
|
function readStdin() {
|
|
6076
7179
|
try {
|
|
6077
|
-
return
|
|
7180
|
+
return readFileSync23(0, "utf8");
|
|
6078
7181
|
} catch {
|
|
6079
7182
|
return "";
|
|
6080
7183
|
}
|
|
@@ -6187,40 +7290,8 @@ function registerScribeCommand(program2) {
|
|
|
6187
7290
|
}
|
|
6188
7291
|
|
|
6189
7292
|
// src/commands/connectors.ts
|
|
6190
|
-
import { createInterface as
|
|
6191
|
-
import { stdin as
|
|
6192
|
-
|
|
6193
|
-
// src/connectors/custom.ts
|
|
6194
|
-
import { readFileSync as readFileSync20, writeFileSync as writeFileSync16 } from "fs";
|
|
6195
|
-
import { join as join23 } from "path";
|
|
6196
|
-
function file3() {
|
|
6197
|
-
return join23(oriroDir(), "mcp-custom.json");
|
|
6198
|
-
}
|
|
6199
|
-
function readCustomServers() {
|
|
6200
|
-
try {
|
|
6201
|
-
const v = JSON.parse(readFileSync20(file3(), "utf8"));
|
|
6202
|
-
return Array.isArray(v) ? v : [];
|
|
6203
|
-
} catch {
|
|
6204
|
-
return [];
|
|
6205
|
-
}
|
|
6206
|
-
}
|
|
6207
|
-
function saveCustomServer(server) {
|
|
6208
|
-
const rest = readCustomServers().filter((s) => s.name.toLowerCase() !== server.name.toLowerCase());
|
|
6209
|
-
writeFileSync16(join23(ensureOriroDir(), "mcp-custom.json"), JSON.stringify([...rest, server], null, 2), "utf8");
|
|
6210
|
-
}
|
|
6211
|
-
function removeCustomServer(name) {
|
|
6212
|
-
const before = readCustomServers();
|
|
6213
|
-
const after = before.filter((s) => s.name.toLowerCase() !== name.toLowerCase());
|
|
6214
|
-
if (after.length === before.length) return false;
|
|
6215
|
-
writeFileSync16(join23(ensureOriroDir(), "mcp-custom.json"), JSON.stringify(after, null, 2), "utf8");
|
|
6216
|
-
return true;
|
|
6217
|
-
}
|
|
6218
|
-
function trustedServerNames() {
|
|
6219
|
-
return readCustomServers().filter((s) => s.trusted).map((s) => s.name);
|
|
6220
|
-
}
|
|
6221
|
-
function isServerTrusted(name) {
|
|
6222
|
-
return trustedServerNames().some((n) => n.toLowerCase() === name.toLowerCase());
|
|
6223
|
-
}
|
|
7293
|
+
import { createInterface as createInterface8 } from "readline/promises";
|
|
7294
|
+
import { stdin as stdin8, stdout as stdout9 } from "process";
|
|
6224
7295
|
|
|
6225
7296
|
// src/connectors/setup.ts
|
|
6226
7297
|
function buildServerConfig(i) {
|
|
@@ -6251,39 +7322,41 @@ function parsePairs(s) {
|
|
|
6251
7322
|
return out;
|
|
6252
7323
|
}
|
|
6253
7324
|
|
|
6254
|
-
// src/connectors/mcp-client.ts
|
|
6255
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
6256
|
-
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
6257
|
-
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
6258
|
-
function assertSafeUrl(raw, allowLocal = false) {
|
|
6259
|
-
const u = new URL(raw);
|
|
6260
|
-
if (u.protocol !== "https:" && u.protocol !== "http:") throw new Error(`unsupported scheme: ${u.protocol}`);
|
|
6261
|
-
const host = u.hostname.toLowerCase();
|
|
6262
|
-
const isLoopback = host === "localhost" || host === "127.0.0.1" || host === "::1" || host.endsWith(".localhost");
|
|
6263
|
-
const isPrivate = /^10\./.test(host) || /^192\.168\./.test(host) || /^172\.(1[6-9]|2\d|3[01])\./.test(host) || /^169\.254\./.test(host) || /^fe80:/i.test(host) || /^f[cd][0-9a-f]{2}:/i.test(host) || host === "169.254.169.254" || host === "metadata.google.internal";
|
|
6264
|
-
if ((isLoopback || isPrivate) && !allowLocal) {
|
|
6265
|
-
throw new Error(`blocked SSRF target ${host} (use --allow-local for loopback/LAN MCP servers)`);
|
|
6266
|
-
}
|
|
6267
|
-
if (u.protocol === "http:" && !isLoopback && !allowLocal) throw new Error(`refusing plaintext http to ${host} \u2014 use https`);
|
|
6268
|
-
return u;
|
|
6269
|
-
}
|
|
6270
|
-
|
|
6271
7325
|
// src/commands/connectors.ts
|
|
6272
7326
|
function registerConnectorsCommand(program2) {
|
|
6273
7327
|
const connectors = program2.command("connectors").description("MCP connectors \u2014 add external tools/services (inert until used)");
|
|
6274
|
-
connectors.command("list [category]").description("list the connector catalog (optionally filtered by category)").action((category) => {
|
|
7328
|
+
connectors.command("list [category]").description("list the connector catalog (optionally filtered by category)").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action((category, opts) => {
|
|
7329
|
+
const oerr = outputError(opts);
|
|
7330
|
+
if (oerr) die(oerr);
|
|
6275
7331
|
if (category && !connectorCategories().includes(category)) {
|
|
6276
7332
|
die(`unknown category '${category}' \u2014 categories: ${connectorCategories().join(", ")}`);
|
|
6277
7333
|
}
|
|
6278
7334
|
const entries = listConnectors(category);
|
|
6279
7335
|
const added = new Set(addedConnectors().map((c) => c.slug));
|
|
7336
|
+
if (isMachineOutput(opts) || opts.query) {
|
|
7337
|
+
const rows = entries.map((c) => ({
|
|
7338
|
+
slug: c.slug,
|
|
7339
|
+
name: c.name,
|
|
7340
|
+
category: c.category,
|
|
7341
|
+
addable: Boolean(c.mcpUrl),
|
|
7342
|
+
added: added.has(c.slug)
|
|
7343
|
+
}));
|
|
7344
|
+
process.stdout.write(renderList2(rows, {
|
|
7345
|
+
output: opts.output,
|
|
7346
|
+
query: opts.query,
|
|
7347
|
+
columns: ["slug", "name", "category", "addable", "added"]
|
|
7348
|
+
}) + "\n");
|
|
7349
|
+
return;
|
|
7350
|
+
}
|
|
6280
7351
|
heading(category ? `Connectors \xB7 ${category}` : "Connectors");
|
|
6281
7352
|
let addable = 0;
|
|
7353
|
+
const NAME_W = 34;
|
|
6282
7354
|
for (const c of entries) {
|
|
6283
7355
|
const canAdd = !!c.mcpUrl;
|
|
6284
7356
|
if (canAdd) addable++;
|
|
6285
7357
|
const mark = !canAdd ? dim("\xB7") : added.has(c.slug) ? accent("\u25CF") : dim("\u25CB");
|
|
6286
|
-
const
|
|
7358
|
+
const label = (canAdd ? c.name : `${c.name} (coming soon)`).padEnd(NAME_W);
|
|
7359
|
+
const name = canAdd ? label : dim(label);
|
|
6287
7360
|
process.stdout.write(` ${mark} ${(canAdd ? accent : dim)(c.slug.padEnd(20))} ${name} ${dim(c.category)}
|
|
6288
7361
|
`);
|
|
6289
7362
|
}
|
|
@@ -6298,12 +7371,20 @@ function registerConnectorsCommand(program2) {
|
|
|
6298
7371
|
if (!res.ok) die(res.error ?? `could not add '${slug}'`);
|
|
6299
7372
|
ok(`added ${accent(slug)} \u2014 recorded locally`);
|
|
6300
7373
|
});
|
|
6301
|
-
connectors.command("remove <slug>").description("remove a connector").action((slug) => {
|
|
7374
|
+
connectors.command("remove <slug>").description("remove a connector").option("-f, --force", "skip the confirmation prompt").action(async (slug, opts) => {
|
|
7375
|
+
if (!isConnectorAdded(slug)) {
|
|
7376
|
+
info(`'${slug}' is not in your added list \u2014 nothing to remove`);
|
|
7377
|
+
return;
|
|
7378
|
+
}
|
|
7379
|
+
if (!await confirmDestructive(`remove connector '${slug}'`, opts)) {
|
|
7380
|
+
info("cancelled");
|
|
7381
|
+
return;
|
|
7382
|
+
}
|
|
6302
7383
|
if (removeConnector(slug)) ok(`removed ${accent(slug)}`);
|
|
6303
7384
|
else info(`'${slug}' is not in your added list \u2014 nothing to remove`);
|
|
6304
7385
|
});
|
|
6305
7386
|
connectors.command("setup").description("guided setup of a CUSTOM MCP server \u2014 Guardian-vetted, no JSON").option("--name <name>", "a short name for the server").option("--command <cmd>", "stdio launch command, e.g. 'npx -y @scope/mcp'").option("--args <args>", "space-separated args for --command").option("--env <pairs>", "comma-separated KEY=VAL env vars").option("--url <url>", "http(s) MCP endpoint (instead of --command)").option("--header <pairs>", "comma-separated KEY=VAL headers (with --url)").option("--allow-local", "permit loopback/LAN URL targets").option("-y, --yes", "trust and save when Guardian says 'ask'").action(async (opts) => {
|
|
6306
|
-
const interactive = !!
|
|
7387
|
+
const interactive = !!stdin8.isTTY && !!stdout9.isTTY;
|
|
6307
7388
|
let { name, command, url } = opts;
|
|
6308
7389
|
let argsStr = opts.args;
|
|
6309
7390
|
let envStr = opts.env;
|
|
@@ -6322,7 +7403,7 @@ function registerConnectorsCommand(program2) {
|
|
|
6322
7403
|
);
|
|
6323
7404
|
return;
|
|
6324
7405
|
}
|
|
6325
|
-
const rl =
|
|
7406
|
+
const rl = createInterface8({ input: stdin8, output: stdout9 });
|
|
6326
7407
|
try {
|
|
6327
7408
|
name = name || (await rl.question("Server name: ")).trim();
|
|
6328
7409
|
if (!command && !url) {
|
|
@@ -6364,7 +7445,7 @@ function registerConnectorsCommand(program2) {
|
|
|
6364
7445
|
if (opts.yes) {
|
|
6365
7446
|
trusted = true;
|
|
6366
7447
|
} else if (interactive) {
|
|
6367
|
-
const rl =
|
|
7448
|
+
const rl = createInterface8({ input: stdin8, output: stdout9 });
|
|
6368
7449
|
try {
|
|
6369
7450
|
const ans = (await rl.question(`Trust and save "${name}"? [y/N] `)).trim().toLowerCase();
|
|
6370
7451
|
trusted = ans === "y" || ans === "yes";
|
|
@@ -6406,14 +7487,14 @@ function registerConnectorsCommand(program2) {
|
|
|
6406
7487
|
}
|
|
6407
7488
|
|
|
6408
7489
|
// src/channels/config.ts
|
|
6409
|
-
import { readFileSync as
|
|
6410
|
-
import { join as
|
|
6411
|
-
function
|
|
6412
|
-
return
|
|
7490
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync20 } from "fs";
|
|
7491
|
+
import { join as join27 } from "path";
|
|
7492
|
+
function file5() {
|
|
7493
|
+
return join27(oriroDir(), "channels.json");
|
|
6413
7494
|
}
|
|
6414
7495
|
function readChannels() {
|
|
6415
7496
|
try {
|
|
6416
|
-
const v = JSON.parse(
|
|
7497
|
+
const v = JSON.parse(readFileSync24(file5(), "utf8"));
|
|
6417
7498
|
return Array.isArray(v) ? v : [];
|
|
6418
7499
|
} catch {
|
|
6419
7500
|
return [];
|
|
@@ -6422,10 +7503,10 @@ function readChannels() {
|
|
|
6422
7503
|
function saveChannel(cfg) {
|
|
6423
7504
|
const all = readChannels().filter((c) => c.kind !== cfg.kind);
|
|
6424
7505
|
all.push(cfg);
|
|
6425
|
-
|
|
7506
|
+
writeFileSync20(join27(ensureOriroDir(), "channels.json"), JSON.stringify(all, null, 2), "utf8");
|
|
6426
7507
|
}
|
|
6427
7508
|
function removeChannel(kind) {
|
|
6428
|
-
|
|
7509
|
+
writeFileSync20(join27(ensureOriroDir(), "channels.json"), JSON.stringify(readChannels().filter((c) => c.kind !== kind), null, 2), "utf8");
|
|
6429
7510
|
}
|
|
6430
7511
|
|
|
6431
7512
|
// src/channels/telegram.ts
|
|
@@ -6542,9 +7623,9 @@ async function startDiscord(token) {
|
|
|
6542
7623
|
}
|
|
6543
7624
|
|
|
6544
7625
|
// src/channels/whatsapp.ts
|
|
6545
|
-
import { join as
|
|
7626
|
+
import { join as join28 } from "path";
|
|
6546
7627
|
function whatsappAuthDir() {
|
|
6547
|
-
return
|
|
7628
|
+
return join28(oriroDir(), "whatsapp-auth");
|
|
6548
7629
|
}
|
|
6549
7630
|
async function startWhatsApp() {
|
|
6550
7631
|
let baileys;
|
|
@@ -6662,12 +7743,26 @@ function registerChannelsCommand(program2) {
|
|
|
6662
7743
|
}
|
|
6663
7744
|
|
|
6664
7745
|
// src/commands/skills.ts
|
|
6665
|
-
import { existsSync as
|
|
6666
|
-
import { resolve as resolve2, join as
|
|
7746
|
+
import { existsSync as existsSync20, statSync as statSync4, mkdirSync as mkdirSync17, cpSync, rmSync as rmSync4 } from "fs";
|
|
7747
|
+
import { resolve as resolve2, join as join29, basename, dirname as dirname4 } from "path";
|
|
6667
7748
|
function registerSkillsCommand(program2) {
|
|
6668
7749
|
const skills = program2.command("skills").description("the ORIRO skill library \u2014 bundled + your own");
|
|
6669
|
-
skills.command("list").description("show CORE / TAIL skill counts (use --all to list names)").option("-a, --all", "list every skill name").action(async (opts) => {
|
|
7750
|
+
skills.command("list").description("show CORE / TAIL skill counts (use --all to list names)").option("-a, --all", "list every skill name").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action(async (opts) => {
|
|
7751
|
+
const oerr = outputError(opts);
|
|
7752
|
+
if (oerr) die(oerr);
|
|
6670
7753
|
const s = await loadOriroSkills();
|
|
7754
|
+
if (isMachineOutput(opts) || opts.query) {
|
|
7755
|
+
const rows = s.all.map((sk) => ({
|
|
7756
|
+
name: sk.name,
|
|
7757
|
+
tier: sk.disableModelInvocation ? "TAIL" : "CORE"
|
|
7758
|
+
}));
|
|
7759
|
+
process.stdout.write(renderList2(rows, {
|
|
7760
|
+
output: opts.output,
|
|
7761
|
+
query: opts.query,
|
|
7762
|
+
columns: ["name", "tier"]
|
|
7763
|
+
}) + "\n");
|
|
7764
|
+
return;
|
|
7765
|
+
}
|
|
6671
7766
|
heading("Skills");
|
|
6672
7767
|
info(`${accent(String(s.all.length))} loaded \xB7 ${accent(String(s.core.length))} CORE (model-visible) \xB7 ${accent(String(s.tail.length))} TAIL (/name-only)`);
|
|
6673
7768
|
if (opts.all) {
|
|
@@ -6681,38 +7776,42 @@ function registerSkillsCommand(program2) {
|
|
|
6681
7776
|
});
|
|
6682
7777
|
skills.command("add <path>").description("add your own skill \u2014 a folder containing SKILL.md, or a SKILL.md file").action((p) => {
|
|
6683
7778
|
const src = resolve2(p);
|
|
6684
|
-
if (!
|
|
7779
|
+
if (!existsSync20(src)) die(`not found: ${src}`);
|
|
6685
7780
|
const dest = userSkillsDir();
|
|
6686
|
-
|
|
6687
|
-
const st =
|
|
7781
|
+
mkdirSync17(dest, { recursive: true });
|
|
7782
|
+
const st = statSync4(src);
|
|
6688
7783
|
if (st.isDirectory()) {
|
|
6689
|
-
if (!
|
|
7784
|
+
if (!existsSync20(join29(src, "SKILL.md"))) die(`no SKILL.md in ${src} \u2014 a skill folder must contain SKILL.md`);
|
|
6690
7785
|
const name = basename(src);
|
|
6691
|
-
cpSync(src,
|
|
6692
|
-
ok(`added skill ${accent(name)} \u2192 ${
|
|
7786
|
+
cpSync(src, join29(dest, name), { recursive: true });
|
|
7787
|
+
ok(`added skill ${accent(name)} \u2192 ${join29(dest, name)}`);
|
|
6693
7788
|
} else if (basename(src).toLowerCase() === "skill.md") {
|
|
6694
|
-
const name = basename(
|
|
6695
|
-
|
|
6696
|
-
cpSync(src,
|
|
6697
|
-
ok(`added skill ${accent(name)} \u2192 ${
|
|
7789
|
+
const name = basename(dirname4(src)) || "custom-skill";
|
|
7790
|
+
mkdirSync17(join29(dest, name), { recursive: true });
|
|
7791
|
+
cpSync(src, join29(dest, name, "SKILL.md"));
|
|
7792
|
+
ok(`added skill ${accent(name)} \u2192 ${join29(dest, name)}`);
|
|
6698
7793
|
} else {
|
|
6699
7794
|
die("expected a folder containing SKILL.md, or a SKILL.md file");
|
|
6700
7795
|
}
|
|
6701
7796
|
info("It loads on next launch \u2014 and is available in chat via /skill.");
|
|
6702
7797
|
});
|
|
6703
|
-
skills.command("remove <name>").description("remove a skill you added").action((name) => {
|
|
6704
|
-
const target =
|
|
6705
|
-
if (!
|
|
7798
|
+
skills.command("remove <name>").description("remove a skill you added").option("-f, --force", "skip the confirmation prompt").action(async (name, opts) => {
|
|
7799
|
+
const target = join29(userSkillsDir(), name);
|
|
7800
|
+
if (!existsSync20(target)) {
|
|
6706
7801
|
info(`'${name}' is not a user-added skill \u2014 nothing to remove`);
|
|
6707
7802
|
return;
|
|
6708
7803
|
}
|
|
6709
|
-
|
|
7804
|
+
if (!await confirmDestructive(`remove skill '${name}'`, opts)) {
|
|
7805
|
+
info("cancelled");
|
|
7806
|
+
return;
|
|
7807
|
+
}
|
|
7808
|
+
rmSync4(target, { recursive: true, force: true });
|
|
6710
7809
|
ok(`removed ${accent(name)}`);
|
|
6711
7810
|
});
|
|
6712
7811
|
}
|
|
6713
7812
|
|
|
6714
7813
|
// src/commands/language.ts
|
|
6715
|
-
import { stdin as
|
|
7814
|
+
import { stdin as stdin9 } from "process";
|
|
6716
7815
|
function resolveLanguage(input) {
|
|
6717
7816
|
return languageByCode(input) ?? LANGUAGES.find((l) => l.name.toLowerCase() === input.trim().toLowerCase());
|
|
6718
7817
|
}
|
|
@@ -6734,7 +7833,7 @@ function registerLanguageCommand(program2) {
|
|
|
6734
7833
|
ok(`${accent(lang.name)} is now your terminal language.`);
|
|
6735
7834
|
return;
|
|
6736
7835
|
}
|
|
6737
|
-
if (
|
|
7836
|
+
if (stdin9.isTTY) {
|
|
6738
7837
|
const lang = await selectLanguageInteractive();
|
|
6739
7838
|
setTerminalLanguage(lang);
|
|
6740
7839
|
ok(`${accent(lang.name)} is now your terminal language.`);
|
|
@@ -6747,7 +7846,7 @@ function registerLanguageCommand(program2) {
|
|
|
6747
7846
|
}
|
|
6748
7847
|
|
|
6749
7848
|
// src/commands/avatar.ts
|
|
6750
|
-
import { stdin as
|
|
7849
|
+
import { stdin as stdin10 } from "process";
|
|
6751
7850
|
function registerAvatarCommand(program2) {
|
|
6752
7851
|
program2.command("avatar").description("show or change your terminal avatar").argument("[slug]", "set directly to this avatar slug").option("-l, --list", "list every avatar by category").action(async (slug, opts) => {
|
|
6753
7852
|
if (opts.list) {
|
|
@@ -6765,7 +7864,7 @@ function registerAvatarCommand(program2) {
|
|
|
6765
7864
|
ok(`${accent(avatar.slug)} is now your terminal face.`);
|
|
6766
7865
|
return;
|
|
6767
7866
|
}
|
|
6768
|
-
if (
|
|
7867
|
+
if (stdin10.isTTY) {
|
|
6769
7868
|
const chosen = await selectAvatarInteractive();
|
|
6770
7869
|
if (!chosen) {
|
|
6771
7870
|
info("no change.");
|
|
@@ -6843,12 +7942,12 @@ function registerHeadCommand(program2) {
|
|
|
6843
7942
|
}
|
|
6844
7943
|
|
|
6845
7944
|
// src/commands/voice.ts
|
|
6846
|
-
import { stdin as
|
|
7945
|
+
import { stdin as stdin11, stdout as stdout10 } from "process";
|
|
6847
7946
|
function registerVoiceCommand(program2) {
|
|
6848
|
-
program2.command("voice").description("speech-to-text \u2014 transcribe an audio file or the mic (on-device Whisper, experimental)").argument("[file]", "audio file to transcribe (omit to record from the mic on a real terminal)").option("--translate", "translate speech to English (Whisper translate task)").option("--seconds <n>", "mic recording length in seconds", "6").action(async (
|
|
6849
|
-
const interactive = !!
|
|
7947
|
+
program2.command("voice").description("speech-to-text \u2014 transcribe an audio file or the mic (on-device Whisper, experimental)").argument("[file]", "audio file to transcribe (omit to record from the mic on a real terminal)").option("--translate", "translate speech to English (Whisper translate task)").option("--seconds <n>", "mic recording length in seconds", "6").action(async (file6, opts) => {
|
|
7948
|
+
const interactive = !!stdin11.isTTY && !!stdout10.isTTY;
|
|
6850
7949
|
heading("ORIRO voice \u{1F399}");
|
|
6851
|
-
let audio =
|
|
7950
|
+
let audio = file6;
|
|
6852
7951
|
if (!audio) {
|
|
6853
7952
|
if (!interactive) {
|
|
6854
7953
|
info("On-device speech-to-text (experimental \u2014 needs ffmpeg + the transformers voice peer).");
|
|
@@ -6880,19 +7979,590 @@ function registerVoiceCommand(program2) {
|
|
|
6880
7979
|
});
|
|
6881
7980
|
}
|
|
6882
7981
|
|
|
7982
|
+
// src/agents/catalog.ts
|
|
7983
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
7984
|
+
function parseAgentDef(raw, now) {
|
|
7985
|
+
if (!raw || typeof raw !== "object") return { ok: false, error: "not a JSON object" };
|
|
7986
|
+
const o = raw;
|
|
7987
|
+
const name = typeof o.name === "string" ? o.name.trim().toLowerCase() : "";
|
|
7988
|
+
if (!name) return { ok: false, error: "missing 'name'" };
|
|
7989
|
+
if (!isValidAgentName(name)) return { ok: false, error: `invalid name '${name}' (lowercase, digits, hyphens)` };
|
|
7990
|
+
const task = typeof o.task === "string" ? o.task.trim() : "";
|
|
7991
|
+
if (!task) return { ok: false, error: "missing 'task'" };
|
|
7992
|
+
const def = {
|
|
7993
|
+
name,
|
|
7994
|
+
task,
|
|
7995
|
+
...typeof o.description === "string" ? { description: o.description } : {},
|
|
7996
|
+
...typeof o.router === "string" ? { router: o.router } : {},
|
|
7997
|
+
...typeof o.cwd === "string" ? { cwd: o.cwd } : {},
|
|
7998
|
+
...typeof o.schedule === "string" ? { schedule: o.schedule } : {},
|
|
7999
|
+
createdAt: now,
|
|
8000
|
+
updatedAt: now
|
|
8001
|
+
};
|
|
8002
|
+
return { ok: true, def };
|
|
8003
|
+
}
|
|
8004
|
+
async function fetchAgentSource(pathOrUrl) {
|
|
8005
|
+
if (/^https?:\/\//i.test(pathOrUrl)) {
|
|
8006
|
+
const res = await fetch(pathOrUrl);
|
|
8007
|
+
if (!res.ok) throw new Error(`fetch failed: HTTP ${res.status}`);
|
|
8008
|
+
return await res.json();
|
|
8009
|
+
}
|
|
8010
|
+
return JSON.parse(readFileSync25(pathOrUrl, "utf8"));
|
|
8011
|
+
}
|
|
8012
|
+
async function addAgentFromSource(pathOrUrl, now) {
|
|
8013
|
+
let raw;
|
|
8014
|
+
try {
|
|
8015
|
+
raw = await fetchAgentSource(pathOrUrl);
|
|
8016
|
+
} catch (e) {
|
|
8017
|
+
return { ok: false, error: e instanceof Error ? e.message : String(e) };
|
|
8018
|
+
}
|
|
8019
|
+
const parsed = parseAgentDef(raw, now);
|
|
8020
|
+
if (!parsed.ok) return { ok: false, error: parsed.error };
|
|
8021
|
+
const overwrote = Boolean(loadAgent(parsed.def.name));
|
|
8022
|
+
saveAgent(parsed.def);
|
|
8023
|
+
return { ok: true, name: parsed.def.name, overwrote };
|
|
8024
|
+
}
|
|
8025
|
+
|
|
8026
|
+
// src/commands/schedule.ts
|
|
8027
|
+
import { spawnSync } from "child_process";
|
|
8028
|
+
import { platform } from "process";
|
|
8029
|
+
var TASK_NAME = "ORIRO_Agents_Tick";
|
|
8030
|
+
function intervalMinutes(spec) {
|
|
8031
|
+
const m = /^(\d+)(m|h)$/.exec(spec.trim());
|
|
8032
|
+
if (!m) return null;
|
|
8033
|
+
const n = parseInt(m[1], 10);
|
|
8034
|
+
if (n <= 0) return null;
|
|
8035
|
+
return m[2] === "h" ? n * 60 : n;
|
|
8036
|
+
}
|
|
8037
|
+
function tickInvocation() {
|
|
8038
|
+
return { node: process.execPath, bin: process.argv[1] ?? "oriro" };
|
|
8039
|
+
}
|
|
8040
|
+
function buildCron(mins, remove) {
|
|
8041
|
+
const { node, bin } = tickInvocation();
|
|
8042
|
+
if (platform === "win32") {
|
|
8043
|
+
if (remove) return { cmd: `schtasks /Delete /TN ${TASK_NAME} /F`, note: "Windows Task Scheduler" };
|
|
8044
|
+
const sc = mins % 60 === 0 ? `/SC HOURLY /MO ${mins / 60}` : `/SC MINUTE /MO ${mins}`;
|
|
8045
|
+
return {
|
|
8046
|
+
cmd: `schtasks /Create /TN ${TASK_NAME} /TR "\\"${node}\\" \\"${bin}\\" agents tick" ${sc} /F`,
|
|
8047
|
+
note: "Windows Task Scheduler"
|
|
8048
|
+
};
|
|
8049
|
+
}
|
|
8050
|
+
const line = `*/${mins} * * * * "${node}" "${bin}" agents tick # ${TASK_NAME}`;
|
|
8051
|
+
if (remove) {
|
|
8052
|
+
return { cmd: `crontab -l 2>/dev/null | grep -v '# ${TASK_NAME}' | crontab -`, note: "crontab" };
|
|
8053
|
+
}
|
|
8054
|
+
return {
|
|
8055
|
+
cmd: `( crontab -l 2>/dev/null | grep -v '# ${TASK_NAME}'; echo '${line}' ) | crontab -`,
|
|
8056
|
+
note: "crontab"
|
|
8057
|
+
};
|
|
8058
|
+
}
|
|
8059
|
+
function runShell(cmd) {
|
|
8060
|
+
const r = platform === "win32" ? spawnSync("cmd", ["/c", cmd], { encoding: "utf8" }) : spawnSync("sh", ["-c", cmd], { encoding: "utf8" });
|
|
8061
|
+
if (r.status !== 0) {
|
|
8062
|
+
info(dim((r.stderr || r.stdout || "").trim().slice(0, 300)));
|
|
8063
|
+
return false;
|
|
8064
|
+
}
|
|
8065
|
+
return true;
|
|
8066
|
+
}
|
|
8067
|
+
function registerAgentsCron(agents) {
|
|
8068
|
+
agents.command("cron").description("install an OS scheduler that runs `agents tick` on an interval (fires scheduled agents)").option("--every <spec>", "interval: Nm | Nh", "5m").option("--remove", "remove the scheduler entry instead of installing it").option("--apply", "actually apply the change (default: just print the command to run)").action((opts) => {
|
|
8069
|
+
const mins = intervalMinutes(opts.every);
|
|
8070
|
+
if (!opts.remove && mins === null) die(`invalid --every '${opts.every}' \u2014 use Nm or Nh (e.g. 5m, 2h)`);
|
|
8071
|
+
const { cmd, note } = buildCron(mins ?? 5, Boolean(opts.remove));
|
|
8072
|
+
heading(opts.remove ? "Remove scheduled agents" : "Schedule agents");
|
|
8073
|
+
info(`${note}: runs ${accent("oriro agents tick")} ${opts.remove ? "" : `every ${accent(opts.every)}`}`);
|
|
8074
|
+
if (!opts.apply) {
|
|
8075
|
+
process.stdout.write(`
|
|
8076
|
+
${cmd}
|
|
8077
|
+
|
|
8078
|
+
`);
|
|
8079
|
+
info(dim("printed only \u2014 re-run with --apply to make this change, or run the command yourself"));
|
|
8080
|
+
return;
|
|
8081
|
+
}
|
|
8082
|
+
if (runShell(cmd)) ok(opts.remove ? "scheduler entry removed" : `scheduled \u2014 agents tick will run every ${opts.every}`);
|
|
8083
|
+
else die("could not apply the schedule (see the message above) \u2014 you can run the printed command manually");
|
|
8084
|
+
});
|
|
8085
|
+
}
|
|
8086
|
+
|
|
8087
|
+
// src/commands/agents.ts
|
|
8088
|
+
function nowIso() {
|
|
8089
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
8090
|
+
}
|
|
8091
|
+
function printAgent(a) {
|
|
8092
|
+
const brain = a.router ? accent(a.router) : dim("active pool");
|
|
8093
|
+
const sched = a.schedule ? accent(a.schedule) : dim("manual");
|
|
8094
|
+
process.stdout.write(` ${accent(a.name.padEnd(22))} brain:${brain} schedule:${sched}
|
|
8095
|
+
`);
|
|
8096
|
+
if (a.description) process.stdout.write(` ${dim(a.description)}
|
|
8097
|
+
`);
|
|
8098
|
+
}
|
|
8099
|
+
async function runAndReport(def, opts = {}) {
|
|
8100
|
+
info(`running ${accent(def.name)} ${dim(`(brain: ${def.router ?? "active pool"})`)}\u2026`);
|
|
8101
|
+
const res = await runAgent2(def, opts);
|
|
8102
|
+
markRun(def.name, res.ok, Date.now());
|
|
8103
|
+
if (res.output) process.stdout.write(`
|
|
8104
|
+
${res.output}
|
|
8105
|
+
|
|
8106
|
+
`);
|
|
8107
|
+
if (res.ok) ok(`${def.name} done`);
|
|
8108
|
+
else info(`${def.name} produced no output${res.output ? "" : " (router unavailable?)"}`);
|
|
8109
|
+
return res.ok;
|
|
8110
|
+
}
|
|
8111
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
8112
|
+
function registerAgentsCommand(program2) {
|
|
8113
|
+
const agents = program2.command("agents").description("your workflow-automation agents \u2014 run on a router, full tools behind Guardian").action(() => {
|
|
8114
|
+
heading("Agents");
|
|
8115
|
+
const all = listAgents();
|
|
8116
|
+
info(`${accent(String(all.length))} saved \xB7 an agent = a saved workflow that runs on a router (its brain)`);
|
|
8117
|
+
info(`make one: ${accent('oriro agents make <name> --task "\u2026" [--router <id>] [--schedule 1h]')}`);
|
|
8118
|
+
info(`then: ${accent("oriro agents run <name>")} ${dim("\xB7 or")} ${accent("oriro agents tick")} ${dim("for scheduled ones")}`);
|
|
8119
|
+
});
|
|
8120
|
+
agents.command("list").description("list your saved agents").option("-o, --output <fmt>", "output format: text (default) | json | csv").option("-q, --query <expr>", "filter/select: 'field', 'field=value', or 'field=value:selectField'").action((opts) => {
|
|
8121
|
+
const oerr = outputError(opts);
|
|
8122
|
+
if (oerr) die(oerr);
|
|
8123
|
+
const all = listAgents();
|
|
8124
|
+
const state = loadState();
|
|
8125
|
+
if (isMachineOutput(opts) || opts.query) {
|
|
8126
|
+
const rows = all.map((a) => ({
|
|
8127
|
+
name: a.name,
|
|
8128
|
+
brain: a.router ?? "pool",
|
|
8129
|
+
schedule: a.schedule ?? "manual",
|
|
8130
|
+
description: a.description ?? "",
|
|
8131
|
+
lastRun: state[a.name]?.lastRunAt ? new Date(state[a.name].lastRunAt).toISOString() : "",
|
|
8132
|
+
lastOk: state[a.name]?.lastOk ?? null
|
|
8133
|
+
}));
|
|
8134
|
+
process.stdout.write(renderList2(rows, {
|
|
8135
|
+
output: opts.output,
|
|
8136
|
+
query: opts.query,
|
|
8137
|
+
columns: ["name", "brain", "schedule", "lastRun", "lastOk"]
|
|
8138
|
+
}) + "\n");
|
|
8139
|
+
return;
|
|
8140
|
+
}
|
|
8141
|
+
heading("Agents");
|
|
8142
|
+
if (!all.length) {
|
|
8143
|
+
info(`no agents yet \u2014 make one: ${accent('oriro agents make my-agent --task "\u2026"')}`);
|
|
8144
|
+
return;
|
|
8145
|
+
}
|
|
8146
|
+
for (const a of all) {
|
|
8147
|
+
printAgent(a);
|
|
8148
|
+
const last = state[a.name]?.lastRunAt;
|
|
8149
|
+
if (last) process.stdout.write(` ${dim(`last run: ${new Date(last).toISOString()}${state[a.name]?.lastOk === false ? " (failed)" : ""}`)}
|
|
8150
|
+
`);
|
|
8151
|
+
}
|
|
8152
|
+
});
|
|
8153
|
+
agents.command("make <name>").description("create or update an agent").requiredOption("-t, --task <text>", "the workflow / instructions the agent carries out").option("-d, --desc <text>", "a short description").option("-r, --router <id>", "bind a router as the brain (default: your active pool)").option("-s, --schedule <spec>", "automation cadence: Nm | Nh | Nd | hourly | daily").option("-c, --cwd <path>", "working directory for the automation").action((name, opts) => {
|
|
8154
|
+
if (!isValidAgentName(name)) die(`invalid agent name '${name}' \u2014 use lowercase letters, digits and hyphens`);
|
|
8155
|
+
if (opts.schedule && parseScheduleMs(opts.schedule) === void 0) {
|
|
8156
|
+
die(`invalid --schedule '${opts.schedule}' \u2014 use Nm, Nh, Nd, hourly or daily`);
|
|
8157
|
+
}
|
|
8158
|
+
if (opts.router && !registeredRouters().some((r) => r.id === opts.router)) {
|
|
8159
|
+
info(`note: router '${opts.router}' isn't added yet \u2014 add it with \`oriro routers add ${opts.router}\` or it falls back to your active pool`);
|
|
8160
|
+
}
|
|
8161
|
+
const existing = loadAgent(name);
|
|
8162
|
+
const now = nowIso();
|
|
8163
|
+
const def = {
|
|
8164
|
+
name,
|
|
8165
|
+
task: opts.task,
|
|
8166
|
+
...opts.desc ? { description: opts.desc } : {},
|
|
8167
|
+
...opts.router ? { router: opts.router } : {},
|
|
8168
|
+
...opts.schedule ? { schedule: opts.schedule } : {},
|
|
8169
|
+
...opts.cwd ? { cwd: opts.cwd } : {},
|
|
8170
|
+
createdAt: existing?.createdAt ?? now,
|
|
8171
|
+
updatedAt: now
|
|
8172
|
+
};
|
|
8173
|
+
saveAgent(def);
|
|
8174
|
+
ok(`${existing ? "updated" : "created"} agent ${accent(name)}`);
|
|
8175
|
+
if (def.schedule) info(`scheduled ${accent(def.schedule)} \u2014 run \`oriro agents tick\` (or \`daemon\`) to fire it when due`);
|
|
8176
|
+
else info(`run it: ${accent(`oriro agents run ${name}`)}`);
|
|
8177
|
+
});
|
|
8178
|
+
agents.command("show <name>").description("print an agent's definition").action((name) => {
|
|
8179
|
+
const def = loadAgent(name);
|
|
8180
|
+
if (!def) die(`no agent named '${name}' \u2014 run \`oriro agents list\``);
|
|
8181
|
+
process.stdout.write(`${JSON.stringify(def, null, 2)}
|
|
8182
|
+
`);
|
|
8183
|
+
});
|
|
8184
|
+
agents.command("run <name>").description("run an agent now (comes alive on its router, full tools behind Guardian)").option("-c, --cwd <path>", "working directory for this run").option("-i, --input <text>", "input to pass to the agent").action(async (name, opts) => {
|
|
8185
|
+
const def = loadAgent(name);
|
|
8186
|
+
if (!def) die(`no agent named '${name}' \u2014 run \`oriro agents list\``);
|
|
8187
|
+
await runAndReport(def, { ...opts.cwd ? { cwd: opts.cwd } : {}, ...opts.input ? { input: opts.input } : {} });
|
|
8188
|
+
});
|
|
8189
|
+
agents.command("add <path-or-url>").description("import a shared/community agent from a JSON file or URL").action(async (src) => {
|
|
8190
|
+
const res = await addAgentFromSource(src, nowIso());
|
|
8191
|
+
if (!res.ok) die(`could not add agent: ${res.error}`);
|
|
8192
|
+
ok(`${res.overwrote ? "updated" : "added"} agent ${accent(res.name ?? "")} ${dim("\u2192 ~/.oriro/agents")}`);
|
|
8193
|
+
info(`run it: ${accent(`oriro agents run ${res.name}`)}`);
|
|
8194
|
+
});
|
|
8195
|
+
agents.command("remove <name>").description("delete an agent").option("-f, --force", "skip the confirmation prompt").action(async (name, opts) => {
|
|
8196
|
+
if (!loadAgent(name)) {
|
|
8197
|
+
info(`'${name}' is not a saved agent \u2014 nothing to remove`);
|
|
8198
|
+
return;
|
|
8199
|
+
}
|
|
8200
|
+
if (!await confirmDestructive(`remove agent '${name}'`, opts)) {
|
|
8201
|
+
info("cancelled");
|
|
8202
|
+
return;
|
|
8203
|
+
}
|
|
8204
|
+
if (!removeAgent(name)) {
|
|
8205
|
+
info(`'${name}' is not a saved agent \u2014 nothing to remove`);
|
|
8206
|
+
return;
|
|
8207
|
+
}
|
|
8208
|
+
ok(`removed ${accent(name)}`);
|
|
8209
|
+
});
|
|
8210
|
+
registerAgentsCron(agents);
|
|
8211
|
+
agents.command("tick").description("run every DUE scheduled agent once, then exit (wire to OS cron / Task Scheduler)").action(async () => {
|
|
8212
|
+
const state = loadState();
|
|
8213
|
+
const now = Date.now();
|
|
8214
|
+
const due = listAgents().filter((a) => isDue(a, state, now));
|
|
8215
|
+
heading("Agents \xB7 tick");
|
|
8216
|
+
if (!due.length) {
|
|
8217
|
+
info("0 agents due");
|
|
8218
|
+
return;
|
|
8219
|
+
}
|
|
8220
|
+
info(`${accent(String(due.length))} due: ${due.map((d) => d.name).join(", ")}`);
|
|
8221
|
+
for (const def of due) await runAndReport(def);
|
|
8222
|
+
});
|
|
8223
|
+
agents.command("daemon").description("stay resident and run scheduled agents as they come due (Ctrl-C to stop)").option("-i, --interval <seconds>", "how often to check for due agents", "60").action(async (opts) => {
|
|
8224
|
+
const everyMs = Math.max(5, Number(opts.interval) || 60) * 1e3;
|
|
8225
|
+
heading("Agents \xB7 daemon");
|
|
8226
|
+
info(`checking every ${accent(`${everyMs / 1e3}s`)} \u2014 Ctrl-C to stop`);
|
|
8227
|
+
let stop = false;
|
|
8228
|
+
process.on("SIGINT", () => {
|
|
8229
|
+
stop = true;
|
|
8230
|
+
info("\nstopping\u2026");
|
|
8231
|
+
});
|
|
8232
|
+
while (!stop) {
|
|
8233
|
+
const state = loadState();
|
|
8234
|
+
const now = Date.now();
|
|
8235
|
+
const due = listAgents().filter((a) => isDue(a, state, now));
|
|
8236
|
+
for (const def of due) {
|
|
8237
|
+
if (stop) break;
|
|
8238
|
+
await runAndReport(def);
|
|
8239
|
+
}
|
|
8240
|
+
for (let waited = 0; waited < everyMs && !stop; waited += 500) await sleep(500);
|
|
8241
|
+
}
|
|
8242
|
+
});
|
|
8243
|
+
}
|
|
8244
|
+
|
|
8245
|
+
// src/commands/completion.ts
|
|
8246
|
+
function extractTree(program2) {
|
|
8247
|
+
const nodes = [];
|
|
8248
|
+
for (const c of program2.commands) {
|
|
8249
|
+
const name = c.name();
|
|
8250
|
+
if (name === "completion") continue;
|
|
8251
|
+
nodes.push({
|
|
8252
|
+
name,
|
|
8253
|
+
subs: c.commands.map((s) => s.name()),
|
|
8254
|
+
opts: c.options.map((o) => o.long).filter((l) => Boolean(l))
|
|
8255
|
+
});
|
|
8256
|
+
}
|
|
8257
|
+
return nodes;
|
|
8258
|
+
}
|
|
8259
|
+
var SHELLS = ["bash", "zsh", "fish", "pwsh"];
|
|
8260
|
+
function topNames(tree) {
|
|
8261
|
+
return [...tree.map((n) => n.name), "completion", "help"].join(" ");
|
|
8262
|
+
}
|
|
8263
|
+
function genBash(tree) {
|
|
8264
|
+
const cases = tree.map((n) => ` ${n.name}) COMPREPLY=( $(compgen -W "${n.subs.join(" ")} ${n.opts.join(" ")}" -- "$cur") );;`).join("\n");
|
|
8265
|
+
return `# ORIRO bash completion. Install: oriro completion bash > /etc/bash_completion.d/oriro
|
|
8266
|
+
# or (per-user): oriro completion bash >> ~/.bashrc
|
|
8267
|
+
_oriro_complete() {
|
|
8268
|
+
local cur prev cword
|
|
8269
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
8270
|
+
cword=$COMP_CWORD
|
|
8271
|
+
if [ "$cword" -eq 1 ]; then
|
|
8272
|
+
COMPREPLY=( $(compgen -W "${topNames(tree)}" -- "$cur") )
|
|
8273
|
+
return
|
|
8274
|
+
fi
|
|
8275
|
+
case "\${COMP_WORDS[1]}" in
|
|
8276
|
+
${cases}
|
|
8277
|
+
*) COMPREPLY=();;
|
|
8278
|
+
esac
|
|
8279
|
+
}
|
|
8280
|
+
complete -F _oriro_complete oriro
|
|
8281
|
+
`;
|
|
8282
|
+
}
|
|
8283
|
+
function genZsh(tree) {
|
|
8284
|
+
const cases = tree.map((n) => ` ${n.name}) compadd ${n.subs.join(" ")} ${n.opts.join(" ")} ;;`).join("\n");
|
|
8285
|
+
return `#compdef oriro
|
|
8286
|
+
# ORIRO zsh completion. Install: oriro completion zsh > "\${fpath[1]}/_oriro" (then restart the shell)
|
|
8287
|
+
_oriro() {
|
|
8288
|
+
local -a words; words=("\${(@)words}")
|
|
8289
|
+
if (( CURRENT == 2 )); then
|
|
8290
|
+
compadd ${topNames(tree)}
|
|
8291
|
+
return
|
|
8292
|
+
fi
|
|
8293
|
+
case "\${words[2]}" in
|
|
8294
|
+
${cases}
|
|
8295
|
+
esac
|
|
8296
|
+
}
|
|
8297
|
+
_oriro "$@"
|
|
8298
|
+
`;
|
|
8299
|
+
}
|
|
8300
|
+
function genFish(tree) {
|
|
8301
|
+
const lines = [
|
|
8302
|
+
"# ORIRO fish completion. Install: oriro completion fish > ~/.config/fish/completions/oriro.fish",
|
|
8303
|
+
`complete -c oriro -f -n __fish_use_subcommand -a "${topNames(tree)}"`
|
|
8304
|
+
];
|
|
8305
|
+
for (const n of tree) {
|
|
8306
|
+
if (n.subs.length) {
|
|
8307
|
+
lines.push(`complete -c oriro -f -n "__fish_seen_subcommand_from ${n.name}" -a "${n.subs.join(" ")}"`);
|
|
8308
|
+
}
|
|
8309
|
+
}
|
|
8310
|
+
return lines.join("\n") + "\n";
|
|
8311
|
+
}
|
|
8312
|
+
function genPwsh(tree) {
|
|
8313
|
+
const cases = tree.map((n) => ` '${n.name}' { @(${[...n.subs, ...n.opts].map((s) => `'${s}'`).join(", ")}) }`).join("\n");
|
|
8314
|
+
const top = [...tree.map((n) => n.name), "completion", "help"].map((s) => `'${s}'`).join(", ");
|
|
8315
|
+
return `# ORIRO PowerShell completion. Install: oriro completion pwsh >> $PROFILE (then restart pwsh)
|
|
8316
|
+
Register-ArgumentCompleter -Native -CommandName oriro -ScriptBlock {
|
|
8317
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
8318
|
+
$tokens = $commandAst.CommandElements | ForEach-Object { $_.ToString() }
|
|
8319
|
+
$candidates = if ($tokens.Count -le 2) {
|
|
8320
|
+
@(${top})
|
|
8321
|
+
} else {
|
|
8322
|
+
switch ($tokens[1]) {
|
|
8323
|
+
${cases}
|
|
8324
|
+
default { @() }
|
|
8325
|
+
}
|
|
8326
|
+
}
|
|
8327
|
+
$candidates | Where-Object { $_ -like "$wordToComplete*" } |
|
|
8328
|
+
ForEach-Object { [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_) }
|
|
8329
|
+
}
|
|
8330
|
+
`;
|
|
8331
|
+
}
|
|
8332
|
+
var GENERATORS = {
|
|
8333
|
+
bash: genBash,
|
|
8334
|
+
zsh: genZsh,
|
|
8335
|
+
fish: genFish,
|
|
8336
|
+
pwsh: genPwsh
|
|
8337
|
+
};
|
|
8338
|
+
function registerCompletionCommand(program2) {
|
|
8339
|
+
program2.command("completion <shell>").description("print a shell tab-completion script (bash | zsh | fish | pwsh)").action((shell) => {
|
|
8340
|
+
const s = shell.toLowerCase();
|
|
8341
|
+
if (!SHELLS.includes(s)) {
|
|
8342
|
+
die(`unsupported shell '${shell}'. Use one of: ${SHELLS.join(", ")}`);
|
|
8343
|
+
return;
|
|
8344
|
+
}
|
|
8345
|
+
process.stdout.write(GENERATORS[s](extractTree(program2)));
|
|
8346
|
+
});
|
|
8347
|
+
}
|
|
8348
|
+
|
|
8349
|
+
// src/commands/config.ts
|
|
8350
|
+
function registerConfigCommand(program2) {
|
|
8351
|
+
const config = program2.command("config").description("your durable CLI settings (defaults in ~/.oriro/config.json)");
|
|
8352
|
+
config.command("list").description("show every setting, its value, and what it does").action(() => {
|
|
8353
|
+
const all = configAll();
|
|
8354
|
+
heading("Config");
|
|
8355
|
+
for (const { key, desc } of configKeys()) {
|
|
8356
|
+
const val = all[key];
|
|
8357
|
+
process.stdout.write(` ${accent(key.padEnd(10))} ${val !== void 0 ? accent(val) : dim("(default)")} ${dim(desc)}
|
|
8358
|
+
`);
|
|
8359
|
+
}
|
|
8360
|
+
info(`set: ${accent("oriro config set <key> <value>")} \xB7 clear: ${accent("oriro config unset <key>")}`);
|
|
8361
|
+
});
|
|
8362
|
+
config.command("get <key>").description("print one setting's value").action((key) => {
|
|
8363
|
+
if (!isConfigKey(key)) die(`unknown key '${key}' \u2014 run \`oriro config list\``);
|
|
8364
|
+
const val = configGet(key);
|
|
8365
|
+
if (val === void 0) {
|
|
8366
|
+
info(`${key} is unset (using the built-in default)`);
|
|
8367
|
+
return;
|
|
8368
|
+
}
|
|
8369
|
+
process.stdout.write(`${val}
|
|
8370
|
+
`);
|
|
8371
|
+
});
|
|
8372
|
+
config.command("set <key> <value>").description("set a setting (validated)").action((key, value) => {
|
|
8373
|
+
if (!isConfigKey(key)) die(`unknown key '${key}' \u2014 run \`oriro config list\``);
|
|
8374
|
+
const err = validateConfig(key, value);
|
|
8375
|
+
if (err) die(`invalid value for '${key}': ${err}`);
|
|
8376
|
+
configSet(key, value);
|
|
8377
|
+
ok(`${accent(key)} = ${accent(value)}`);
|
|
8378
|
+
});
|
|
8379
|
+
config.command("unset <key>").description("clear a setting back to its built-in default").action((key) => {
|
|
8380
|
+
if (!isConfigKey(key)) die(`unknown key '${key}' \u2014 run \`oriro config list\``);
|
|
8381
|
+
if (configUnset(key)) ok(`cleared ${accent(key)}`);
|
|
8382
|
+
else info(`${key} was already at its default`);
|
|
8383
|
+
});
|
|
8384
|
+
}
|
|
8385
|
+
|
|
8386
|
+
// src/commands/setup.ts
|
|
8387
|
+
import { rmSync as rmSync5 } from "fs";
|
|
8388
|
+
import { join as join30 } from "path";
|
|
8389
|
+
import { stdin as stdin12, stdout as stdout11 } from "process";
|
|
8390
|
+
var MARKERS = [
|
|
8391
|
+
"language.json",
|
|
8392
|
+
"avatar.json",
|
|
8393
|
+
"skills-onboarded.json",
|
|
8394
|
+
"connectors-onboarded.json",
|
|
8395
|
+
"models-onboarded.json",
|
|
8396
|
+
join30("routers", "onboarded.json")
|
|
8397
|
+
];
|
|
8398
|
+
function registerSetupCommand(program2) {
|
|
8399
|
+
program2.command("setup").description("run the guided setup wizard (language \xB7 routers \xB7 connectors \xB7 skills \xB7 avatar)").option("--reset", "clear your settled choices and re-ask every step").action(async (opts) => {
|
|
8400
|
+
if (opts.reset) {
|
|
8401
|
+
for (const m of MARKERS) {
|
|
8402
|
+
try {
|
|
8403
|
+
rmSync5(join30(oriroDir(), m), { force: true });
|
|
8404
|
+
} catch {
|
|
8405
|
+
}
|
|
8406
|
+
}
|
|
8407
|
+
ok("reset \u2014 every step will be asked again");
|
|
8408
|
+
}
|
|
8409
|
+
if (!stdin12.isTTY || !stdout11.isTTY) {
|
|
8410
|
+
heading("ORIRO setup");
|
|
8411
|
+
info(`ORIRO is ${accent("keyless")} \u2014 no login, no API keys. Run ${accent("oriro setup")} in a real terminal for the guided wizard.`);
|
|
8412
|
+
info(dim("or configure directly: oriro language <code> \xB7 oriro routers add <id> \xB7 oriro connectors add <slug> \xB7 oriro config set <k> <v>"));
|
|
8413
|
+
return;
|
|
8414
|
+
}
|
|
8415
|
+
await runOnboarding();
|
|
8416
|
+
});
|
|
8417
|
+
}
|
|
8418
|
+
|
|
8419
|
+
// src/commands/import.ts
|
|
8420
|
+
import { existsSync as existsSync21, readFileSync as readFileSync26, readdirSync as readdirSync3, statSync as statSync5, cpSync as cpSync2, mkdirSync as mkdirSync18 } from "fs";
|
|
8421
|
+
import { join as join31, basename as basename2 } from "path";
|
|
8422
|
+
function registerImportCommand(program2) {
|
|
8423
|
+
const imp = program2.command("import").description("migrate from another CLI (MCP servers, skills)");
|
|
8424
|
+
imp.command("mcp <file>").description("import MCP servers from a Claude-compatible mcp.json (Guardian-vetted)").action((file6) => {
|
|
8425
|
+
if (!existsSync21(file6)) die(`no such file: ${file6}`);
|
|
8426
|
+
let servers;
|
|
8427
|
+
try {
|
|
8428
|
+
const j = JSON.parse(readFileSync26(file6, "utf8"));
|
|
8429
|
+
servers = j.mcpServers ?? j.servers ?? {};
|
|
8430
|
+
} catch (e) {
|
|
8431
|
+
die(`could not parse ${file6}: ${e instanceof Error ? e.message : String(e)}`);
|
|
8432
|
+
return;
|
|
8433
|
+
}
|
|
8434
|
+
const names = Object.keys(servers);
|
|
8435
|
+
if (!names.length) die(`no "mcpServers" found in ${file6}`);
|
|
8436
|
+
heading(`Import MCP \xB7 ${names.length} server${names.length === 1 ? "" : "s"}`);
|
|
8437
|
+
let imported = 0, blocked2 = 0;
|
|
8438
|
+
for (const name of names) {
|
|
8439
|
+
const s = servers[name];
|
|
8440
|
+
const input = {
|
|
8441
|
+
name,
|
|
8442
|
+
...s.command ? { command: s.command } : {},
|
|
8443
|
+
...s.args ? { args: s.args } : {},
|
|
8444
|
+
...s.env ? { env: s.env } : {},
|
|
8445
|
+
...s.url ? { url: s.url } : {},
|
|
8446
|
+
...s.headers ? { headers: s.headers } : {}
|
|
8447
|
+
};
|
|
8448
|
+
if (s.url) {
|
|
8449
|
+
try {
|
|
8450
|
+
assertSafeUrl(s.url);
|
|
8451
|
+
} catch (e) {
|
|
8452
|
+
process.stdout.write(` ${fgHex(PALETTE.error, "\u2717")} ${name} ${dim(`blocked: ${e instanceof Error ? e.message : String(e)}`)}
|
|
8453
|
+
`);
|
|
8454
|
+
blocked2++;
|
|
8455
|
+
continue;
|
|
8456
|
+
}
|
|
8457
|
+
}
|
|
8458
|
+
const outcome = vetServer(input);
|
|
8459
|
+
if (outcome.decision === "block") {
|
|
8460
|
+
process.stdout.write(` ${fgHex(PALETTE.error, "\u2717")} ${name} ${dim(`blocked: ${outcome.reason}`)}
|
|
8461
|
+
`);
|
|
8462
|
+
blocked2++;
|
|
8463
|
+
continue;
|
|
8464
|
+
}
|
|
8465
|
+
saveCustomServer({ name, config: buildServerConfig(input), trusted: outcome.decision === "allow" });
|
|
8466
|
+
const mark = outcome.decision === "allow" ? fgHex(PALETTE.success, "\u2713 trusted") : dim("\u25CB needs trust");
|
|
8467
|
+
process.stdout.write(` ${mark} ${accent(name)}
|
|
8468
|
+
`);
|
|
8469
|
+
imported++;
|
|
8470
|
+
}
|
|
8471
|
+
info(`${imported} imported \xB7 ${blocked2} blocked${imported ? ` \u2014 they connect in-session; see \`oriro connectors custom\`` : ""}`);
|
|
8472
|
+
});
|
|
8473
|
+
imp.command("skills <dir>").description("import SKILL.md skill folders from another CLI's skills directory").action((dir) => {
|
|
8474
|
+
if (!existsSync21(dir) || !statSync5(dir).isDirectory()) die(`no such directory: ${dir}`);
|
|
8475
|
+
const dest = userSkillsDir();
|
|
8476
|
+
mkdirSync18(dest, { recursive: true });
|
|
8477
|
+
heading("Import skills");
|
|
8478
|
+
const sources = existsSync21(join31(dir, "SKILL.md")) ? [dir] : readdirSync3(dir).map((e) => join31(dir, e)).filter((p) => statSync5(p).isDirectory() && existsSync21(join31(p, "SKILL.md")));
|
|
8479
|
+
let n = 0;
|
|
8480
|
+
for (const src of sources) {
|
|
8481
|
+
cpSync2(src, join31(dest, basename2(src)), { recursive: true });
|
|
8482
|
+
process.stdout.write(` ${fgHex(PALETTE.success, "\u2713")} ${accent(basename2(src))}
|
|
8483
|
+
`);
|
|
8484
|
+
n++;
|
|
8485
|
+
}
|
|
8486
|
+
if (n === 0) info(dim(`no SKILL.md skill folder found at or inside ${dir}`));
|
|
8487
|
+
else ok(`imported ${n} skill${n === 1 ? "" : "s"} \u2192 ${dim(dest)}`);
|
|
8488
|
+
});
|
|
8489
|
+
}
|
|
8490
|
+
|
|
8491
|
+
// src/commands/help-on-error.ts
|
|
8492
|
+
function lev(a, b) {
|
|
8493
|
+
const m = a.length, n = b.length;
|
|
8494
|
+
if (!m) return n;
|
|
8495
|
+
if (!n) return m;
|
|
8496
|
+
let prev = Array.from({ length: n + 1 }, (_, i) => i);
|
|
8497
|
+
let curr = new Array(n + 1);
|
|
8498
|
+
for (let i = 1; i <= m; i++) {
|
|
8499
|
+
curr[0] = i;
|
|
8500
|
+
for (let j = 1; j <= n; j++) {
|
|
8501
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
8502
|
+
curr[j] = Math.min((curr[j - 1] ?? 0) + 1, (prev[j] ?? 0) + 1, (prev[j - 1] ?? 0) + cost);
|
|
8503
|
+
}
|
|
8504
|
+
[prev, curr] = [curr, prev];
|
|
8505
|
+
}
|
|
8506
|
+
return prev[n] ?? n;
|
|
8507
|
+
}
|
|
8508
|
+
function didYouMean(input, candidates) {
|
|
8509
|
+
let best;
|
|
8510
|
+
let bestD = Infinity;
|
|
8511
|
+
for (const c of candidates) {
|
|
8512
|
+
const d = lev(input.toLowerCase(), c.toLowerCase());
|
|
8513
|
+
if (d < bestD) {
|
|
8514
|
+
bestD = d;
|
|
8515
|
+
best = c;
|
|
8516
|
+
}
|
|
8517
|
+
}
|
|
8518
|
+
return best !== void 0 && bestD <= Math.max(2, Math.floor(input.length * 0.4)) ? best : void 0;
|
|
8519
|
+
}
|
|
8520
|
+
function fullPath(cmd) {
|
|
8521
|
+
const parts = [];
|
|
8522
|
+
let c = cmd;
|
|
8523
|
+
while (c && c.name() !== "oriro") {
|
|
8524
|
+
parts.unshift(c.name());
|
|
8525
|
+
c = c.parent;
|
|
8526
|
+
}
|
|
8527
|
+
return parts.length ? `oriro ${parts.join(" ")}` : "oriro <command>";
|
|
8528
|
+
}
|
|
8529
|
+
function enableHelpOnError(program2) {
|
|
8530
|
+
const apply = (cmd) => {
|
|
8531
|
+
cmd.showHelpAfterError(`
|
|
8532
|
+
(run: ${fullPath(cmd)} --help for usage)`);
|
|
8533
|
+
cmd.showSuggestionAfterError(true);
|
|
8534
|
+
for (const sub of cmd.commands) apply(sub);
|
|
8535
|
+
};
|
|
8536
|
+
apply(program2);
|
|
8537
|
+
}
|
|
8538
|
+
|
|
6883
8539
|
// src/cli.ts
|
|
6884
8540
|
var version = createRequire(import.meta.url)("../package.json").version;
|
|
6885
8541
|
var program = new Command();
|
|
6886
|
-
program.name("oriro").description("ORIRO \u2014 a free, on-device-friendly terminal AI agent.").version(version, "-v, --version").action(async (
|
|
8542
|
+
program.name("oriro").description("ORIRO \u2014 a free, on-device-friendly terminal AI agent.").version(version, "-v, --version").option("-p, --print <prompt>", "headless one-shot: run a single prompt, print the answer, exit (CI-friendly)").option("--output-format <fmt>", "with --print: text | json | stream-json", "text").action(async (options, command) => {
|
|
8543
|
+
if (options.print !== void 0) {
|
|
8544
|
+
const fmt = options.outputFormat ?? "text";
|
|
8545
|
+
if (!isOutputFormatMode(fmt)) {
|
|
8546
|
+
process.stderr.write(`error: --output-format must be text | json | stream-json
|
|
8547
|
+
`);
|
|
8548
|
+
process.exitCode = 1;
|
|
8549
|
+
return;
|
|
8550
|
+
}
|
|
8551
|
+
await runHeadless(options.print, fmt);
|
|
8552
|
+
return;
|
|
8553
|
+
}
|
|
6887
8554
|
if (command.args.length > 0) {
|
|
6888
|
-
const arg = command.args[0];
|
|
8555
|
+
const arg = command.args[0] ?? "";
|
|
6889
8556
|
if (arg === "help") {
|
|
6890
8557
|
command.outputHelp();
|
|
6891
8558
|
return;
|
|
6892
8559
|
}
|
|
6893
|
-
|
|
6894
|
-
|
|
8560
|
+
const names = command.commands.map((c) => c.name());
|
|
8561
|
+
const guess = didYouMean(arg, names);
|
|
8562
|
+
process.stderr.write(`error: unknown command '${arg}'${guess ? ` \u2014 did you mean '${guess}'?` : ""}
|
|
8563
|
+
|
|
6895
8564
|
`);
|
|
8565
|
+
command.outputHelp();
|
|
6896
8566
|
process.exitCode = 1;
|
|
6897
8567
|
return;
|
|
6898
8568
|
}
|
|
@@ -6907,6 +8577,12 @@ registerLanguageCommand(program);
|
|
|
6907
8577
|
registerAvatarCommand(program);
|
|
6908
8578
|
registerHeadCommand(program);
|
|
6909
8579
|
registerVoiceCommand(program);
|
|
8580
|
+
registerAgentsCommand(program);
|
|
8581
|
+
registerConfigCommand(program);
|
|
8582
|
+
registerSetupCommand(program);
|
|
8583
|
+
registerImportCommand(program);
|
|
8584
|
+
registerCompletionCommand(program);
|
|
8585
|
+
enableHelpOnError(program);
|
|
6910
8586
|
program.parseAsync().catch((e) => {
|
|
6911
8587
|
if (e instanceof DieError) return;
|
|
6912
8588
|
process.stderr.write(`
|