codeply-cli 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/THIRD_PARTY_NOTICES.md +65 -63
- package/bin/codeply.js +1 -1
- package/lib/agent.mjs +133 -24
- package/lib/ai.js +268 -9
- package/lib/ai.mjs +6 -6
- package/lib/apply-patch.js +217 -217
- package/lib/arity-table.json +138 -138
- package/lib/arity.js +70 -70
- package/lib/auth.mjs +6 -6
- package/lib/bots.js +82 -17
- package/lib/chatgpt.js +282 -0
- package/lib/cloud-browser.mjs +143 -143
- package/lib/cloud.mjs +1186 -1144
- package/lib/commands.js +103 -103
- package/lib/config.js +83 -3
- package/lib/design-library/assemble-artifact.mjs +21 -21
- package/lib/design-library/cleanup.mjs +45 -45
- package/lib/design-library/index.json +22379 -22379
- package/lib/design-library/make-table-data.mjs +39 -39
- package/lib/diagnostics.js +192 -192
- package/lib/edit-engine.js +364 -364
- package/lib/github-agent.mjs +311 -311
- package/lib/history.js +75 -75
- package/lib/mail-watch.js +504 -0
- package/lib/mcp.js +258 -258
- package/lib/model-sync.js +114 -0
- package/lib/native-tools.mjs +16 -1
- package/lib/oauth-connectors.js +146 -24
- package/lib/permissions.js +109 -109
- package/lib/plugins.js +353 -353
- package/lib/publish.js +916 -0
- package/lib/reach.js +67 -0
- package/lib/server.mjs +457 -457
- package/lib/session-db.js +220 -220
- package/lib/share.js +168 -168
- package/lib/skills.js +2 -0
- package/lib/snapshot.js +146 -146
- package/lib/telemetry.js +102 -0
- package/lib/terminal-hints.js +154 -154
- package/lib/tools.mjs +316 -14
- package/lib/typecheck-worker.js +147 -147
- package/lib/web-tools.js +209 -158
- package/package.json +49 -49
- package/skills/SOURCE.md +58 -58
- package/skills/accessibility/SKILL.md +147 -147
- package/skills/agent-architecture-audit/SKILL.md +257 -257
- package/skills/agent-eval/SKILL.md +147 -147
- package/skills/agent-harness-construction/SKILL.md +74 -74
- package/skills/agent-introspection-debugging/SKILL.md +154 -154
- package/skills/agent-payment-x402/SKILL.md +225 -225
- package/skills/agent-self-evaluation/SKILL.md +182 -182
- package/skills/agent-self-evaluation/references/evaluation-criteria.md +71 -71
- package/skills/agent-self-evaluation/references/hook-integration.md +64 -64
- package/skills/agent-sort/SKILL.md +216 -216
- package/skills/agentic-engineering/SKILL.md +64 -64
- package/skills/agentic-os/SKILL.md +388 -388
- package/skills/ai-first-engineering/SKILL.md +52 -52
- package/skills/ai-regression-testing/SKILL.md +386 -386
- package/skills/android-clean-architecture/SKILL.md +340 -340
- package/skills/angular-developer/SKILL.md +155 -155
- package/skills/angular-developer/references/angular-animations.md +160 -160
- package/skills/angular-developer/references/angular-aria.md +410 -410
- package/skills/angular-developer/references/cli.md +86 -86
- package/skills/angular-developer/references/component-harnesses.md +59 -59
- package/skills/angular-developer/references/component-styling.md +91 -91
- package/skills/angular-developer/references/components.md +117 -117
- package/skills/angular-developer/references/creating-services.md +97 -97
- package/skills/angular-developer/references/data-resolvers.md +69 -69
- package/skills/angular-developer/references/define-routes.md +67 -67
- package/skills/angular-developer/references/defining-providers.md +72 -72
- package/skills/angular-developer/references/di-fundamentals.md +120 -120
- package/skills/angular-developer/references/e2e-testing.md +56 -56
- package/skills/angular-developer/references/effects.md +83 -83
- package/skills/angular-developer/references/hierarchical-injectors.md +43 -43
- package/skills/angular-developer/references/host-elements.md +80 -80
- package/skills/angular-developer/references/injection-context.md +63 -63
- package/skills/angular-developer/references/inputs.md +101 -101
- package/skills/angular-developer/references/linked-signal.md +59 -59
- package/skills/angular-developer/references/loading-strategies.md +61 -61
- package/skills/angular-developer/references/mcp.md +108 -108
- package/skills/angular-developer/references/navigate-to-routes.md +69 -69
- package/skills/angular-developer/references/outputs.md +86 -86
- package/skills/angular-developer/references/reactive-forms.md +122 -122
- package/skills/angular-developer/references/rendering-strategies.md +44 -44
- package/skills/angular-developer/references/resource.md +77 -77
- package/skills/angular-developer/references/route-animations.md +56 -56
- package/skills/angular-developer/references/route-guards.md +52 -52
- package/skills/angular-developer/references/router-lifecycle.md +45 -45
- package/skills/angular-developer/references/router-testing.md +87 -87
- package/skills/angular-developer/references/show-routes-with-outlets.md +68 -68
- package/skills/angular-developer/references/signal-forms.md +795 -795
- package/skills/angular-developer/references/signals-overview.md +94 -94
- package/skills/angular-developer/references/tailwind-css.md +69 -69
- package/skills/angular-developer/references/template-driven-forms.md +114 -114
- package/skills/angular-developer/references/testing-fundamentals.md +65 -65
- package/skills/api-connector-builder/SKILL.md +121 -121
- package/skills/api-design/SKILL.md +524 -524
- package/skills/architecture-decision-records/SKILL.md +180 -180
- package/skills/article-writing/SKILL.md +80 -80
- package/skills/automation-audit-ops/SKILL.md +143 -143
- package/skills/autonomous-agent-harness/SKILL.md +274 -274
- package/skills/autonomous-loops/SKILL.md +611 -611
- package/skills/backend-patterns/SKILL.md +562 -562
- package/skills/benchmark/SKILL.md +95 -95
- package/skills/benchmark-methodology/SKILL.md +191 -191
- package/skills/benchmark-optimization-loop/SKILL.md +71 -71
- package/skills/blender-motion-state-inspection/SKILL.md +165 -165
- package/skills/blueprint/SKILL.md +106 -106
- package/skills/brand-discovery/SKILL.md +145 -145
- package/skills/brand-discovery/references/10_purpose-why.md +40 -40
- package/skills/brand-discovery/references/20_positioning.md +44 -44
- package/skills/brand-discovery/references/30_audience-niche.md +52 -52
- package/skills/brand-discovery/references/40_personality-archetype.md +57 -57
- package/skills/brand-discovery/references/50_voice-tone.md +59 -59
- package/skills/brand-discovery/references/60_narrative-story.md +50 -50
- package/skills/brand-discovery/references/70_founder-tension.md +49 -49
- package/skills/brand-discovery/references/90_SYNTHESIS.md +133 -133
- package/skills/brand-voice/SKILL.md +98 -98
- package/skills/brand-voice/references/voice-profile-schema.md +55 -55
- package/skills/browser-qa/SKILL.md +105 -105
- package/skills/bun-runtime/SKILL.md +85 -85
- package/skills/canary-watch/SKILL.md +108 -108
- package/skills/carrier-relationship-management/SKILL.md +212 -212
- package/skills/cisco-ios-patterns/SKILL.md +164 -164
- package/skills/ck/SKILL.md +148 -148
- package/skills/claude-devfleet/SKILL.md +112 -112
- package/skills/click-path-audit/SKILL.md +245 -245
- package/skills/clickhouse-io/SKILL.md +445 -445
- package/skills/code-tour/SKILL.md +254 -254
- package/skills/codebase-onboarding/SKILL.md +234 -234
- package/skills/codehealth-mcp/SKILL.md +167 -167
- package/skills/coding-standards/SKILL.md +551 -551
- package/skills/competitive-platform-analysis/SKILL.md +214 -214
- package/skills/competitive-report-structure/SKILL.md +162 -162
- package/skills/compose-multiplatform-patterns/SKILL.md +300 -300
- package/skills/config-gc/SKILL.md +120 -120
- package/skills/configure-ecc/SKILL.md +385 -385
- package/skills/connections-optimizer/SKILL.md +190 -190
- package/skills/content-engine/SKILL.md +132 -132
- package/skills/content-hash-cache-pattern/SKILL.md +162 -162
- package/skills/context-budget/SKILL.md +136 -136
- package/skills/continuous-agent-loop/SKILL.md +46 -46
- package/skills/continuous-learning/SKILL.md +132 -132
- package/skills/continuous-learning-v2/SKILL.md +361 -361
- package/skills/contract-first/SKILL.md +287 -287
- package/skills/cost-aware-llm-pipeline/SKILL.md +184 -184
- package/skills/cost-tracking/SKILL.md +97 -97
- package/skills/council/SKILL.md +204 -204
- package/skills/cpp-coding-standards/SKILL.md +724 -724
- package/skills/cpp-testing/SKILL.md +325 -325
- package/skills/crosspost/SKILL.md +112 -112
- package/skills/csharp-testing/SKILL.md +322 -322
- package/skills/customer-billing-ops/SKILL.md +141 -141
- package/skills/customs-trade-compliance/SKILL.md +263 -263
- package/skills/dart-flutter-patterns/SKILL.md +564 -564
- package/skills/dashboard-builder/SKILL.md +109 -109
- package/skills/data-scraper-agent/SKILL.md +765 -765
- package/skills/data-throughput-accelerator/SKILL.md +74 -74
- package/skills/database-migrations/SKILL.md +430 -430
- package/skills/deep-research/SKILL.md +160 -160
- package/skills/defi-amm-security/SKILL.md +167 -167
- package/skills/delivery-gate/SKILL.md +126 -126
- package/skills/deployment-patterns/SKILL.md +428 -428
- package/skills/design-system/SKILL.md +83 -83
- package/skills/django-celery/SKILL.md +458 -458
- package/skills/django-patterns/SKILL.md +735 -735
- package/skills/django-security/SKILL.md +644 -644
- package/skills/django-tdd/SKILL.md +730 -730
- package/skills/django-verification/SKILL.md +470 -470
- package/skills/dmux-workflows/SKILL.md +192 -192
- package/skills/docker-patterns/SKILL.md +365 -365
- package/skills/documentation-lookup/SKILL.md +91 -91
- package/skills/dotnet-patterns/SKILL.md +322 -322
- package/skills/dynamic-workflow-mode/SKILL.md +124 -124
- package/skills/e2e-testing/SKILL.md +327 -327
- package/skills/ecc-guide/SKILL.md +190 -190
- package/skills/ecc-recipes/SKILL.md +149 -149
- package/skills/ecc-tools-cost-audit/SKILL.md +161 -161
- package/skills/email-ops/SKILL.md +122 -122
- package/skills/energy-procurement/SKILL.md +228 -228
- package/skills/enterprise-agent-ops/SKILL.md +51 -51
- package/skills/error-handling/SKILL.md +377 -377
- package/skills/eval-harness/SKILL.md +271 -271
- package/skills/evm-token-decimals/SKILL.md +131 -131
- package/skills/exa-search/SKILL.md +108 -108
- package/skills/fal-ai-media/SKILL.md +289 -289
- package/skills/fastapi-patterns/SKILL.md +514 -514
- package/skills/finance-billing-ops/SKILL.md +128 -128
- package/skills/flox-environments/SKILL.md +497 -497
- package/skills/flutter-dart-code-review/SKILL.md +436 -436
- package/skills/foundation-models-on-device/SKILL.md +243 -243
- package/skills/frontend-a11y/SKILL.md +446 -446
- package/skills/frontend-design-direction/SKILL.md +93 -93
- package/skills/frontend-patterns/SKILL.md +657 -657
- package/skills/frontend-slides/SKILL.md +185 -185
- package/skills/fsharp-testing/SKILL.md +281 -281
- package/skills/gan-style-harness/SKILL.md +279 -279
- package/skills/gateguard/SKILL.md +133 -133
- package/skills/generating-python-installer/SKILL.md +820 -820
- package/skills/git-workflow/SKILL.md +716 -716
- package/skills/github-ops/SKILL.md +145 -145
- package/skills/golang-patterns/SKILL.md +676 -676
- package/skills/golang-testing/SKILL.md +721 -721
- package/skills/google-workspace-ops/SKILL.md +96 -96
- package/skills/growth-log/SKILL.md +128 -128
- package/skills/healthcare-cdss-patterns/SKILL.md +246 -246
- package/skills/healthcare-emr-patterns/SKILL.md +160 -160
- package/skills/healthcare-eval-harness/SKILL.md +208 -208
- package/skills/healthcare-phi-compliance/SKILL.md +146 -146
- package/skills/hermes-imports/SKILL.md +89 -89
- package/skills/hexagonal-architecture/SKILL.md +277 -277
- package/skills/hipaa-compliance/SKILL.md +79 -79
- package/skills/homelab-network-readiness/SKILL.md +170 -170
- package/skills/homelab-network-setup/SKILL.md +130 -130
- package/skills/homelab-pihole-dns/SKILL.md +275 -275
- package/skills/homelab-vlan-segmentation/SKILL.md +312 -312
- package/skills/homelab-wireguard-vpn/SKILL.md +306 -306
- package/skills/hookify-rules/SKILL.md +128 -128
- package/skills/inherit-legacy-style/SKILL.md +157 -157
- package/skills/intent-driven-development/SKILL.md +360 -360
- package/skills/inventory-demand-planning/SKILL.md +247 -247
- package/skills/investor-materials/SKILL.md +97 -97
- package/skills/investor-outreach/SKILL.md +92 -92
- package/skills/ios-icon-gen/SKILL.md +158 -158
- package/skills/iterative-retrieval/SKILL.md +212 -212
- package/skills/ito-basket-compare/SKILL.md +64 -64
- package/skills/ito-compute/SKILL.md +129 -129
- package/skills/ito-data-atlas-agent/SKILL.md +64 -64
- package/skills/ito-market-intelligence/SKILL.md +61 -61
- package/skills/ito-trade-planner/SKILL.md +68 -68
- package/skills/java-coding-standards/SKILL.md +384 -384
- package/skills/jira-integration/SKILL.md +303 -303
- package/skills/jpa-patterns/SKILL.md +152 -152
- package/skills/knowledge-ops/SKILL.md +155 -155
- package/skills/kotlin-coroutines-flows/SKILL.md +285 -285
- package/skills/kotlin-exposed-patterns/SKILL.md +720 -720
- package/skills/kotlin-ktor-patterns/SKILL.md +690 -690
- package/skills/kotlin-patterns/SKILL.md +712 -712
- package/skills/kotlin-testing/SKILL.md +825 -825
- package/skills/kubernetes-patterns/SKILL.md +756 -756
- package/skills/laravel-patterns/SKILL.md +416 -416
- package/skills/laravel-plugin-discovery/SKILL.md +230 -230
- package/skills/laravel-security/SKILL.md +948 -948
- package/skills/laravel-tdd/SKILL.md +675 -675
- package/skills/laravel-verification/SKILL.md +180 -180
- package/skills/latency-critical-systems/SKILL.md +75 -75
- package/skills/lead-intelligence/SKILL.md +322 -322
- package/skills/liquid-glass-design/SKILL.md +279 -279
- package/skills/llm-trading-agent-security/SKILL.md +147 -147
- package/skills/logistics-exception-management/SKILL.md +222 -222
- package/skills/loop-design-check/SKILL.md +143 -143
- package/skills/mailtrap-email-integration/SKILL.md +77 -77
- package/skills/make-interfaces-feel-better/SKILL.md +152 -152
- package/skills/manim-video/SKILL.md +90 -90
- package/skills/market-research/SKILL.md +76 -76
- package/skills/marketing-campaign/SKILL.md +114 -114
- package/skills/mcp-server-patterns/SKILL.md +70 -70
- package/skills/messages-ops/SKILL.md +105 -105
- package/skills/ml-adoption-playbook/SKILL.md +57 -57
- package/skills/mle-workflow/SKILL.md +348 -348
- package/skills/motion-advanced/SKILL.md +596 -596
- package/skills/motion-foundations/SKILL.md +299 -299
- package/skills/motion-patterns/SKILL.md +434 -434
- package/skills/motion-ui/SKILL.md +576 -576
- package/skills/mysql-patterns/SKILL.md +413 -413
- package/skills/nanoclaw-repl/SKILL.md +34 -34
- package/skills/nestjs-patterns/SKILL.md +231 -231
- package/skills/netmiko-ssh-automation/SKILL.md +174 -174
- package/skills/network-bgp-diagnostics/SKILL.md +168 -168
- package/skills/network-config-validation/SKILL.md +211 -211
- package/skills/network-interface-health/SKILL.md +153 -153
- package/skills/nextjs-turbopack/SKILL.md +58 -58
- package/skills/nodejs-keccak256/SKILL.md +103 -103
- package/skills/nutrient-document-processing/SKILL.md +168 -168
- package/skills/nuxt4-patterns/SKILL.md +101 -101
- package/skills/openclaw-persona-forge/SKILL.md +289 -289
- package/skills/openclaw-persona-forge/references/avatar-style.md +124 -124
- package/skills/openclaw-persona-forge/references/boundary-rules.md +53 -53
- package/skills/openclaw-persona-forge/references/error-handling.md +53 -53
- package/skills/openclaw-persona-forge/references/identity-tension.md +48 -48
- package/skills/openclaw-persona-forge/references/naming-system.md +39 -39
- package/skills/openclaw-persona-forge/references/output-template.md +166 -166
- package/skills/opensource-pipeline/SKILL.md +256 -256
- package/skills/orch-add-feature/SKILL.md +45 -45
- package/skills/orch-build-mvp/SKILL.md +49 -49
- package/skills/orch-change-feature/SKILL.md +43 -43
- package/skills/orch-fix-defect/SKILL.md +43 -43
- package/skills/orch-pipeline/SKILL.md +121 -121
- package/skills/orch-refine-code/SKILL.md +44 -44
- package/skills/parallel-execution-optimizer/SKILL.md +74 -74
- package/skills/perl-patterns/SKILL.md +505 -505
- package/skills/perl-security/SKILL.md +504 -504
- package/skills/perl-testing/SKILL.md +476 -476
- package/skills/plan-canvas/SKILL.md +153 -153
- package/skills/plan-orchestrate/SKILL.md +263 -263
- package/skills/plankton-code-quality/SKILL.md +237 -237
- package/skills/postgres-patterns/SKILL.md +148 -148
- package/skills/prediction-market-oracle-research/SKILL.md +64 -64
- package/skills/prediction-market-risk-review/SKILL.md +61 -61
- package/skills/premium-web-design/SKILL.md +154 -154
- package/skills/prisma-patterns/SKILL.md +401 -401
- package/skills/product-capability/SKILL.md +142 -142
- package/skills/product-lens/SKILL.md +93 -93
- package/skills/production-audit/SKILL.md +207 -207
- package/skills/production-scheduling/SKILL.md +238 -238
- package/skills/project-flow-ops/SKILL.md +112 -112
- package/skills/prompt-optimizer/SKILL.md +398 -398
- package/skills/publish-website/SKILL.md +76 -0
- package/skills/python-patterns/SKILL.md +751 -751
- package/skills/python-testing/SKILL.md +817 -817
- package/skills/pytorch-patterns/SKILL.md +397 -397
- package/skills/quality-nonconformance/SKILL.md +260 -260
- package/skills/quarkus-patterns/SKILL.md +723 -723
- package/skills/quarkus-security/SKILL.md +468 -468
- package/skills/quarkus-tdd/SKILL.md +812 -812
- package/skills/quarkus-verification/SKILL.md +480 -480
- package/skills/ralphinho-rfc-pipeline/SKILL.md +68 -68
- package/skills/react-native-patterns/SKILL.md +326 -326
- package/skills/react-patterns/SKILL.md +342 -342
- package/skills/react-performance/SKILL.md +575 -575
- package/skills/react-testing/SKILL.md +424 -424
- package/skills/recsys-pipeline-architect/SKILL.md +115 -115
- package/skills/recursive-decision-ledger/SKILL.md +81 -81
- package/skills/redis-patterns/SKILL.md +404 -404
- package/skills/regex-vs-llm-structured-text/SKILL.md +221 -221
- package/skills/remotion-video-creation/SKILL.md +43 -43
- package/skills/repo-scan/SKILL.md +79 -79
- package/skills/research-ops/SKILL.md +113 -113
- package/skills/returns-reverse-logistics/SKILL.md +240 -240
- package/skills/rules-distill/SKILL.md +265 -265
- package/skills/rust-patterns/SKILL.md +500 -500
- package/skills/rust-testing/SKILL.md +501 -501
- package/skills/safety-guard/SKILL.md +76 -76
- package/skills/santa-method/SKILL.md +307 -307
- package/skills/scientific-db-pubmed-database/SKILL.md +176 -176
- package/skills/scientific-db-uspto-database/SKILL.md +178 -178
- package/skills/scientific-pkg-gget/SKILL.md +167 -167
- package/skills/scientific-thinking-literature-review/SKILL.md +193 -193
- package/skills/scientific-thinking-scholar-evaluation/SKILL.md +161 -161
- package/skills/search-first/SKILL.md +183 -183
- package/skills/security-bounty-hunter/SKILL.md +100 -100
- package/skills/security-review/SKILL.md +504 -504
- package/skills/security-scan/SKILL.md +166 -166
- package/skills/seo/SKILL.md +155 -155
- package/skills/skill-comply/SKILL.md +59 -59
- package/skills/skill-scout/SKILL.md +141 -141
- package/skills/skill-stocktake/SKILL.md +195 -195
- package/skills/social-graph-ranker/SKILL.md +155 -155
- package/skills/social-publisher/SKILL.md +130 -130
- package/skills/springboot-patterns/SKILL.md +315 -315
- package/skills/springboot-security/SKILL.md +273 -273
- package/skills/springboot-tdd/SKILL.md +159 -159
- package/skills/springboot-verification/SKILL.md +232 -232
- package/skills/strategic-compact/SKILL.md +142 -142
- package/skills/swift-actor-persistence/SKILL.md +144 -144
- package/skills/swift-concurrency-6-2/SKILL.md +216 -216
- package/skills/swift-protocol-di-testing/SKILL.md +191 -191
- package/skills/swiftui-patterns/SKILL.md +259 -259
- package/skills/taste/SKILL.md +264 -264
- package/skills/taste/references/genre-taxonomy.md +87 -87
- package/skills/tdd-workflow/SKILL.md +583 -583
- package/skills/team-agent-orchestration/SKILL.md +111 -111
- package/skills/team-builder/SKILL.md +169 -169
- package/skills/terminal-ops/SKILL.md +110 -110
- package/skills/tinystruct-patterns/SKILL.md +279 -279
- package/skills/tinystruct-patterns/references/architecture.md +90 -90
- package/skills/tinystruct-patterns/references/data-handling.md +60 -60
- package/skills/tinystruct-patterns/references/database.md +99 -99
- package/skills/tinystruct-patterns/references/routing.md +64 -64
- package/skills/tinystruct-patterns/references/system-usage.md +97 -97
- package/skills/tinystruct-patterns/references/testing.md +72 -72
- package/skills/token-budget-advisor/SKILL.md +134 -134
- package/skills/ui-demo/SKILL.md +466 -466
- package/skills/ui-to-vue/SKILL.md +135 -135
- package/skills/uncloud/SKILL.md +344 -344
- package/skills/unified-memory/SKILL.md +170 -170
- package/skills/unified-notifications-ops/SKILL.md +188 -188
- package/skills/verification-loop/SKILL.md +129 -129
- package/skills/video-editing/SKILL.md +311 -311
- package/skills/videodb/SKILL.md +375 -375
- package/skills/visa-doc-translate/SKILL.md +117 -117
- package/skills/vite-patterns/SKILL.md +450 -450
- package/skills/vue-patterns/SKILL.md +471 -471
- package/skills/windows-desktop-e2e/SKILL.md +888 -888
- package/skills/workspace-surface-audit/SKILL.md +126 -126
- package/skills/x-api/SKILL.md +235 -235
package/lib/arity-table.json
CHANGED
|
@@ -1,138 +1,138 @@
|
|
|
1
|
-
{
|
|
2
|
-
"cat": 1,
|
|
3
|
-
"cd": 1,
|
|
4
|
-
"chmod": 1,
|
|
5
|
-
"chown": 1,
|
|
6
|
-
"cp": 1,
|
|
7
|
-
"echo": 1,
|
|
8
|
-
"env": 1,
|
|
9
|
-
"export": 1,
|
|
10
|
-
"grep": 1,
|
|
11
|
-
"kill": 1,
|
|
12
|
-
"killall": 1,
|
|
13
|
-
"ln": 1,
|
|
14
|
-
"ls": 1,
|
|
15
|
-
"mkdir": 1,
|
|
16
|
-
"mv": 1,
|
|
17
|
-
"ps": 1,
|
|
18
|
-
"pwd": 1,
|
|
19
|
-
"rm": 1,
|
|
20
|
-
"rmdir": 1,
|
|
21
|
-
"sleep": 1,
|
|
22
|
-
"source": 1,
|
|
23
|
-
"tail": 1,
|
|
24
|
-
"touch": 1,
|
|
25
|
-
"unset": 1,
|
|
26
|
-
"which": 1,
|
|
27
|
-
"aws": 3,
|
|
28
|
-
"az": 3,
|
|
29
|
-
"bazel": 2,
|
|
30
|
-
"brew": 2,
|
|
31
|
-
"bun": 2,
|
|
32
|
-
"bun run": 3,
|
|
33
|
-
"bun x": 3,
|
|
34
|
-
"cargo": 2,
|
|
35
|
-
"cargo add": 3,
|
|
36
|
-
"cargo run": 3,
|
|
37
|
-
"cdk": 2,
|
|
38
|
-
"cf": 2,
|
|
39
|
-
"cmake": 2,
|
|
40
|
-
"composer": 2,
|
|
41
|
-
"consul": 2,
|
|
42
|
-
"consul kv": 3,
|
|
43
|
-
"crictl": 2,
|
|
44
|
-
"deno": 2,
|
|
45
|
-
"deno task": 3,
|
|
46
|
-
"doctl": 3,
|
|
47
|
-
"docker": 2,
|
|
48
|
-
"docker builder": 3,
|
|
49
|
-
"docker compose": 3,
|
|
50
|
-
"docker container": 3,
|
|
51
|
-
"docker image": 3,
|
|
52
|
-
"docker network": 3,
|
|
53
|
-
"docker volume": 3,
|
|
54
|
-
"eksctl": 2,
|
|
55
|
-
"eksctl create": 3,
|
|
56
|
-
"firebase": 2,
|
|
57
|
-
"flyctl": 2,
|
|
58
|
-
"gcloud": 3,
|
|
59
|
-
"gh": 3,
|
|
60
|
-
"git": 2,
|
|
61
|
-
"git config": 3,
|
|
62
|
-
"git remote": 3,
|
|
63
|
-
"git stash": 3,
|
|
64
|
-
"go": 2,
|
|
65
|
-
"gradle": 2,
|
|
66
|
-
"helm": 2,
|
|
67
|
-
"heroku": 2,
|
|
68
|
-
"hugo": 2,
|
|
69
|
-
"ip": 2,
|
|
70
|
-
"ip addr": 3,
|
|
71
|
-
"ip link": 3,
|
|
72
|
-
"ip netns": 3,
|
|
73
|
-
"ip route": 3,
|
|
74
|
-
"kind": 2,
|
|
75
|
-
"kind create": 3,
|
|
76
|
-
"kubectl": 2,
|
|
77
|
-
"kubectl kustomize": 3,
|
|
78
|
-
"kubectl rollout": 3,
|
|
79
|
-
"kustomize": 2,
|
|
80
|
-
"make": 2,
|
|
81
|
-
"mc": 2,
|
|
82
|
-
"mc admin": 3,
|
|
83
|
-
"minikube": 2,
|
|
84
|
-
"mongosh": 2,
|
|
85
|
-
"mysql": 2,
|
|
86
|
-
"mvn": 2,
|
|
87
|
-
"ng": 2,
|
|
88
|
-
"npm": 2,
|
|
89
|
-
"npm exec": 3,
|
|
90
|
-
"npm init": 3,
|
|
91
|
-
"npm run": 3,
|
|
92
|
-
"npm view": 3,
|
|
93
|
-
"nvm": 2,
|
|
94
|
-
"nx": 2,
|
|
95
|
-
"openssl": 2,
|
|
96
|
-
"openssl req": 3,
|
|
97
|
-
"openssl x509": 3,
|
|
98
|
-
"pip": 2,
|
|
99
|
-
"pipenv": 2,
|
|
100
|
-
"pnpm": 2,
|
|
101
|
-
"pnpm dlx": 3,
|
|
102
|
-
"pnpm exec": 3,
|
|
103
|
-
"pnpm run": 3,
|
|
104
|
-
"poetry": 2,
|
|
105
|
-
"podman": 2,
|
|
106
|
-
"podman container": 3,
|
|
107
|
-
"podman image": 3,
|
|
108
|
-
"psql": 2,
|
|
109
|
-
"pulumi": 2,
|
|
110
|
-
"pulumi stack": 3,
|
|
111
|
-
"pyenv": 2,
|
|
112
|
-
"python": 2,
|
|
113
|
-
"rake": 2,
|
|
114
|
-
"rbenv": 2,
|
|
115
|
-
"redis-cli": 2,
|
|
116
|
-
"rustup": 2,
|
|
117
|
-
"serverless": 2,
|
|
118
|
-
"sfdx": 3,
|
|
119
|
-
"skaffold": 2,
|
|
120
|
-
"sls": 2,
|
|
121
|
-
"sst": 2,
|
|
122
|
-
"swift": 2,
|
|
123
|
-
"systemctl": 2,
|
|
124
|
-
"terraform": 2,
|
|
125
|
-
"terraform workspace": 3,
|
|
126
|
-
"tmux": 2,
|
|
127
|
-
"turbo": 2,
|
|
128
|
-
"ufw": 2,
|
|
129
|
-
"vault": 2,
|
|
130
|
-
"vault auth": 3,
|
|
131
|
-
"vault kv": 3,
|
|
132
|
-
"vercel": 2,
|
|
133
|
-
"volta": 2,
|
|
134
|
-
"wp": 2,
|
|
135
|
-
"yarn": 2,
|
|
136
|
-
"yarn dlx": 3,
|
|
137
|
-
"yarn run": 3
|
|
138
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"cat": 1,
|
|
3
|
+
"cd": 1,
|
|
4
|
+
"chmod": 1,
|
|
5
|
+
"chown": 1,
|
|
6
|
+
"cp": 1,
|
|
7
|
+
"echo": 1,
|
|
8
|
+
"env": 1,
|
|
9
|
+
"export": 1,
|
|
10
|
+
"grep": 1,
|
|
11
|
+
"kill": 1,
|
|
12
|
+
"killall": 1,
|
|
13
|
+
"ln": 1,
|
|
14
|
+
"ls": 1,
|
|
15
|
+
"mkdir": 1,
|
|
16
|
+
"mv": 1,
|
|
17
|
+
"ps": 1,
|
|
18
|
+
"pwd": 1,
|
|
19
|
+
"rm": 1,
|
|
20
|
+
"rmdir": 1,
|
|
21
|
+
"sleep": 1,
|
|
22
|
+
"source": 1,
|
|
23
|
+
"tail": 1,
|
|
24
|
+
"touch": 1,
|
|
25
|
+
"unset": 1,
|
|
26
|
+
"which": 1,
|
|
27
|
+
"aws": 3,
|
|
28
|
+
"az": 3,
|
|
29
|
+
"bazel": 2,
|
|
30
|
+
"brew": 2,
|
|
31
|
+
"bun": 2,
|
|
32
|
+
"bun run": 3,
|
|
33
|
+
"bun x": 3,
|
|
34
|
+
"cargo": 2,
|
|
35
|
+
"cargo add": 3,
|
|
36
|
+
"cargo run": 3,
|
|
37
|
+
"cdk": 2,
|
|
38
|
+
"cf": 2,
|
|
39
|
+
"cmake": 2,
|
|
40
|
+
"composer": 2,
|
|
41
|
+
"consul": 2,
|
|
42
|
+
"consul kv": 3,
|
|
43
|
+
"crictl": 2,
|
|
44
|
+
"deno": 2,
|
|
45
|
+
"deno task": 3,
|
|
46
|
+
"doctl": 3,
|
|
47
|
+
"docker": 2,
|
|
48
|
+
"docker builder": 3,
|
|
49
|
+
"docker compose": 3,
|
|
50
|
+
"docker container": 3,
|
|
51
|
+
"docker image": 3,
|
|
52
|
+
"docker network": 3,
|
|
53
|
+
"docker volume": 3,
|
|
54
|
+
"eksctl": 2,
|
|
55
|
+
"eksctl create": 3,
|
|
56
|
+
"firebase": 2,
|
|
57
|
+
"flyctl": 2,
|
|
58
|
+
"gcloud": 3,
|
|
59
|
+
"gh": 3,
|
|
60
|
+
"git": 2,
|
|
61
|
+
"git config": 3,
|
|
62
|
+
"git remote": 3,
|
|
63
|
+
"git stash": 3,
|
|
64
|
+
"go": 2,
|
|
65
|
+
"gradle": 2,
|
|
66
|
+
"helm": 2,
|
|
67
|
+
"heroku": 2,
|
|
68
|
+
"hugo": 2,
|
|
69
|
+
"ip": 2,
|
|
70
|
+
"ip addr": 3,
|
|
71
|
+
"ip link": 3,
|
|
72
|
+
"ip netns": 3,
|
|
73
|
+
"ip route": 3,
|
|
74
|
+
"kind": 2,
|
|
75
|
+
"kind create": 3,
|
|
76
|
+
"kubectl": 2,
|
|
77
|
+
"kubectl kustomize": 3,
|
|
78
|
+
"kubectl rollout": 3,
|
|
79
|
+
"kustomize": 2,
|
|
80
|
+
"make": 2,
|
|
81
|
+
"mc": 2,
|
|
82
|
+
"mc admin": 3,
|
|
83
|
+
"minikube": 2,
|
|
84
|
+
"mongosh": 2,
|
|
85
|
+
"mysql": 2,
|
|
86
|
+
"mvn": 2,
|
|
87
|
+
"ng": 2,
|
|
88
|
+
"npm": 2,
|
|
89
|
+
"npm exec": 3,
|
|
90
|
+
"npm init": 3,
|
|
91
|
+
"npm run": 3,
|
|
92
|
+
"npm view": 3,
|
|
93
|
+
"nvm": 2,
|
|
94
|
+
"nx": 2,
|
|
95
|
+
"openssl": 2,
|
|
96
|
+
"openssl req": 3,
|
|
97
|
+
"openssl x509": 3,
|
|
98
|
+
"pip": 2,
|
|
99
|
+
"pipenv": 2,
|
|
100
|
+
"pnpm": 2,
|
|
101
|
+
"pnpm dlx": 3,
|
|
102
|
+
"pnpm exec": 3,
|
|
103
|
+
"pnpm run": 3,
|
|
104
|
+
"poetry": 2,
|
|
105
|
+
"podman": 2,
|
|
106
|
+
"podman container": 3,
|
|
107
|
+
"podman image": 3,
|
|
108
|
+
"psql": 2,
|
|
109
|
+
"pulumi": 2,
|
|
110
|
+
"pulumi stack": 3,
|
|
111
|
+
"pyenv": 2,
|
|
112
|
+
"python": 2,
|
|
113
|
+
"rake": 2,
|
|
114
|
+
"rbenv": 2,
|
|
115
|
+
"redis-cli": 2,
|
|
116
|
+
"rustup": 2,
|
|
117
|
+
"serverless": 2,
|
|
118
|
+
"sfdx": 3,
|
|
119
|
+
"skaffold": 2,
|
|
120
|
+
"sls": 2,
|
|
121
|
+
"sst": 2,
|
|
122
|
+
"swift": 2,
|
|
123
|
+
"systemctl": 2,
|
|
124
|
+
"terraform": 2,
|
|
125
|
+
"terraform workspace": 3,
|
|
126
|
+
"tmux": 2,
|
|
127
|
+
"turbo": 2,
|
|
128
|
+
"ufw": 2,
|
|
129
|
+
"vault": 2,
|
|
130
|
+
"vault auth": 3,
|
|
131
|
+
"vault kv": 3,
|
|
132
|
+
"vercel": 2,
|
|
133
|
+
"volta": 2,
|
|
134
|
+
"wp": 2,
|
|
135
|
+
"yarn": 2,
|
|
136
|
+
"yarn dlx": 3,
|
|
137
|
+
"yarn run": 3
|
|
138
|
+
}
|
package/lib/arity.js
CHANGED
|
@@ -1,70 +1,70 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How many words name a shell command, so "always allow" can be scoped to
|
|
3
|
-
* `npm run dev` or `git checkout` instead of every command there is.
|
|
4
|
-
*
|
|
5
|
-
* The ARITY table and the prefix() rule are from opencode
|
|
6
|
-
* (packages/opencode/src/permission/arity.ts), MIT License,
|
|
7
|
-
* Copyright (c) 2025 opencode - https://github.com/sst/opencode
|
|
8
|
-
* Command splitting and tokenizing below are Codeply's own.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const ARITY = require('./arity-table.json');
|
|
12
|
-
|
|
13
|
-
// "Always allow node" would allow every script there is. For interpreters the
|
|
14
|
-
// script (or module) is part of the name: `node server.js`, `python app.py`.
|
|
15
|
-
const INTERPRETERS = new Set(['node', 'python', 'python3', 'py', 'deno', 'bun', 'ruby', 'php', 'perl', 'bash', 'sh', 'zsh', 'powershell', 'pwsh', 'cmd', 'tsx', 'ts-node']);
|
|
16
|
-
|
|
17
|
-
/** Longest listed prefix wins; unlisted commands are named by their first word. */
|
|
18
|
-
function prefix(tokens) {
|
|
19
|
-
if (tokens.length && INTERPRETERS.has(tokens[0]) && !ARITY[tokens.slice(0, 2).join(' ')]) return tokens.slice(0, 2);
|
|
20
|
-
for (let len = tokens.length; len > 0; len--) {
|
|
21
|
-
const arity = ARITY[tokens.slice(0, len).join(' ')];
|
|
22
|
-
if (arity !== undefined) return tokens.slice(0, arity);
|
|
23
|
-
}
|
|
24
|
-
return tokens.slice(0, 1);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/** Split a command line into its separate commands (&&, ||, ;, |, newlines). Quotes are respected. */
|
|
28
|
-
function splitCommands(line) {
|
|
29
|
-
const out = [];
|
|
30
|
-
let cur = '';
|
|
31
|
-
let quote = null;
|
|
32
|
-
for (let i = 0; i < line.length; i++) {
|
|
33
|
-
const c = line[i];
|
|
34
|
-
const n = line[i + 1];
|
|
35
|
-
if (quote) { cur += c; if (c === quote) quote = null; continue; }
|
|
36
|
-
if (c === '"' || c === "'") { quote = c; cur += c; continue; }
|
|
37
|
-
if ((c === '&' && n === '&') || (c === '|' && n === '|')) { out.push(cur); cur = ''; i++; continue; }
|
|
38
|
-
if (c === ';' || c === '|' || c === '\n' || c === '&') { out.push(cur); cur = ''; continue; }
|
|
39
|
-
cur += c;
|
|
40
|
-
}
|
|
41
|
-
out.push(cur);
|
|
42
|
-
return out.map((s) => s.trim()).filter(Boolean);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/** Words of one command, without leading VAR=value assignments or flags. */
|
|
46
|
-
function tokenize(cmd) {
|
|
47
|
-
const words = cmd.match(/"[^"]*"|'[^']*'|\S+/g) || [];
|
|
48
|
-
const clean = words.map((w) => w.replace(/^["']|["']$/g, ''));
|
|
49
|
-
let i = 0;
|
|
50
|
-
while (i < clean.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(clean[i])) i++;
|
|
51
|
-
const rest = clean.slice(i).filter((w) => !w.startsWith('-'));
|
|
52
|
-
// A path to a program is still that program: C:\tools\git.exe -> git
|
|
53
|
-
if (rest.length) rest[0] = rest[0].split(/[\\/]/).pop().replace(/\.(exe|cmd|bat|ps1)$/i, '').toLowerCase();
|
|
54
|
-
return rest;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* The permission patterns a command line needs, one per command in it:
|
|
59
|
-
* 'npm run dev && git status' -> ['npm run dev', 'git status']
|
|
60
|
-
* Subshells, backticks and redirections into files return null: too dynamic
|
|
61
|
-
* (or too destructive) to approve by name alone.
|
|
62
|
-
*/
|
|
63
|
-
function commandPatterns(line) {
|
|
64
|
-
const text = String(line || '');
|
|
65
|
-
if (/\$\(|`|>/.test(text)) return null;
|
|
66
|
-
const pats = splitCommands(text).map((c) => prefix(tokenize(c)).join(' ')).filter(Boolean);
|
|
67
|
-
return pats.length ? [...new Set(pats)] : null;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
module.exports = { commandPatterns, prefix, tokenize, splitCommands };
|
|
1
|
+
/**
|
|
2
|
+
* How many words name a shell command, so "always allow" can be scoped to
|
|
3
|
+
* `npm run dev` or `git checkout` instead of every command there is.
|
|
4
|
+
*
|
|
5
|
+
* The ARITY table and the prefix() rule are from opencode
|
|
6
|
+
* (packages/opencode/src/permission/arity.ts), MIT License,
|
|
7
|
+
* Copyright (c) 2025 opencode - https://github.com/sst/opencode
|
|
8
|
+
* Command splitting and tokenizing below are Codeply's own.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const ARITY = require('./arity-table.json');
|
|
12
|
+
|
|
13
|
+
// "Always allow node" would allow every script there is. For interpreters the
|
|
14
|
+
// script (or module) is part of the name: `node server.js`, `python app.py`.
|
|
15
|
+
const INTERPRETERS = new Set(['node', 'python', 'python3', 'py', 'deno', 'bun', 'ruby', 'php', 'perl', 'bash', 'sh', 'zsh', 'powershell', 'pwsh', 'cmd', 'tsx', 'ts-node']);
|
|
16
|
+
|
|
17
|
+
/** Longest listed prefix wins; unlisted commands are named by their first word. */
|
|
18
|
+
function prefix(tokens) {
|
|
19
|
+
if (tokens.length && INTERPRETERS.has(tokens[0]) && !ARITY[tokens.slice(0, 2).join(' ')]) return tokens.slice(0, 2);
|
|
20
|
+
for (let len = tokens.length; len > 0; len--) {
|
|
21
|
+
const arity = ARITY[tokens.slice(0, len).join(' ')];
|
|
22
|
+
if (arity !== undefined) return tokens.slice(0, arity);
|
|
23
|
+
}
|
|
24
|
+
return tokens.slice(0, 1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Split a command line into its separate commands (&&, ||, ;, |, newlines). Quotes are respected. */
|
|
28
|
+
function splitCommands(line) {
|
|
29
|
+
const out = [];
|
|
30
|
+
let cur = '';
|
|
31
|
+
let quote = null;
|
|
32
|
+
for (let i = 0; i < line.length; i++) {
|
|
33
|
+
const c = line[i];
|
|
34
|
+
const n = line[i + 1];
|
|
35
|
+
if (quote) { cur += c; if (c === quote) quote = null; continue; }
|
|
36
|
+
if (c === '"' || c === "'") { quote = c; cur += c; continue; }
|
|
37
|
+
if ((c === '&' && n === '&') || (c === '|' && n === '|')) { out.push(cur); cur = ''; i++; continue; }
|
|
38
|
+
if (c === ';' || c === '|' || c === '\n' || c === '&') { out.push(cur); cur = ''; continue; }
|
|
39
|
+
cur += c;
|
|
40
|
+
}
|
|
41
|
+
out.push(cur);
|
|
42
|
+
return out.map((s) => s.trim()).filter(Boolean);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Words of one command, without leading VAR=value assignments or flags. */
|
|
46
|
+
function tokenize(cmd) {
|
|
47
|
+
const words = cmd.match(/"[^"]*"|'[^']*'|\S+/g) || [];
|
|
48
|
+
const clean = words.map((w) => w.replace(/^["']|["']$/g, ''));
|
|
49
|
+
let i = 0;
|
|
50
|
+
while (i < clean.length && /^[A-Za-z_][A-Za-z0-9_]*=/.test(clean[i])) i++;
|
|
51
|
+
const rest = clean.slice(i).filter((w) => !w.startsWith('-'));
|
|
52
|
+
// A path to a program is still that program: C:\tools\git.exe -> git
|
|
53
|
+
if (rest.length) rest[0] = rest[0].split(/[\\/]/).pop().replace(/\.(exe|cmd|bat|ps1)$/i, '').toLowerCase();
|
|
54
|
+
return rest;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The permission patterns a command line needs, one per command in it:
|
|
59
|
+
* 'npm run dev && git status' -> ['npm run dev', 'git status']
|
|
60
|
+
* Subshells, backticks and redirections into files return null: too dynamic
|
|
61
|
+
* (or too destructive) to approve by name alone.
|
|
62
|
+
*/
|
|
63
|
+
function commandPatterns(line) {
|
|
64
|
+
const text = String(line || '');
|
|
65
|
+
if (/\$\(|`|>/.test(text)) return null;
|
|
66
|
+
const pats = splitCommands(text).map((c) => prefix(tokenize(c)).join(' ')).filter(Boolean);
|
|
67
|
+
return pats.length ? [...new Set(pats)] : null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = { commandPatterns, prefix, tokenize, splitCommands };
|
package/lib/auth.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { createRequire } from 'module';
|
|
2
|
-
const require = createRequire(import.meta.url);
|
|
3
|
-
|
|
4
|
-
const auth = require('./auth.js');
|
|
5
|
-
export default auth;
|
|
6
|
-
export const { SUPABASE_URL, SUPABASE_ANON_KEY, getClient, login, logout, getSession, getAccessToken } = auth;
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
const require = createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
const auth = require('./auth.js');
|
|
5
|
+
export default auth;
|
|
6
|
+
export const { SUPABASE_URL, SUPABASE_ANON_KEY, getClient, login, logout, getSession, getAccessToken } = auth;
|
package/lib/bots.js
CHANGED
|
@@ -58,10 +58,44 @@ const APPROVALS = {
|
|
|
58
58
|
edit_files: { label: 'Editing files', tools: ['write_file', 'edit_file', 'apply_patch', 'fetch_image'] },
|
|
59
59
|
run_commands: { label: 'Running commands', tools: ['run'] },
|
|
60
60
|
send: { label: 'Sending anything (email, Slack)', tools: ['gmail_send', 'slack_post_message'] },
|
|
61
|
-
publish: { label: 'Deploying or publishing', tools: ['vercel_deploy', 'github_create_repo', 'vercel_api'] },
|
|
62
|
-
databases: { label: 'Changing databases or cloud projects', tools: ['supabase_create_project', 'supabase_delete_project', 'supabase_api', 'supabase_sql'] },
|
|
61
|
+
publish: { label: 'Deploying or publishing', tools: ['vercel_deploy', 'github_create_repo', 'vercel_api', 'publish_deploy', 'publish_github'] },
|
|
62
|
+
databases: { label: 'Changing databases or cloud projects', tools: ['supabase_create_project', 'supabase_delete_project', 'supabase_api', 'supabase_sql', 'supabase_setup', 'supabase_schema'] },
|
|
63
|
+
calendar: { label: 'Adding to your calendar', tools: ['calendar_add'] },
|
|
63
64
|
};
|
|
64
65
|
const ALL_APPROVALS = Object.keys(APPROVALS);
|
|
66
|
+
// The categories bots were saved with before `calendar` existed. A bot saved
|
|
67
|
+
// back then never chose about the newer ones, so it asks for them (listBots).
|
|
68
|
+
const FIRST_APPROVALS = ['edit_files', 'run_commands', 'send', 'publish', 'databases'];
|
|
69
|
+
|
|
70
|
+
// Always on (mail-watch.js): the bot watches in the background, with no model
|
|
71
|
+
// calls until something important arrives. What it can watch, and how it
|
|
72
|
+
// reaches the user when it finds something.
|
|
73
|
+
const WATCH_SOURCES = { gmail: 'Gmail inbox' };
|
|
74
|
+
const REACH = {
|
|
75
|
+
message: 'Message me in Craft',
|
|
76
|
+
push: 'Notify my phone',
|
|
77
|
+
call: 'Call me when it is very important',
|
|
78
|
+
};
|
|
79
|
+
const HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
80
|
+
|
|
81
|
+
function normalizeAlwaysOn(a) {
|
|
82
|
+
a = a && typeof a === 'object' ? a : {};
|
|
83
|
+
const q = a.quiet && typeof a.quiet === 'object' ? a.quiet : {};
|
|
84
|
+
const watch = (Array.isArray(a.watch) ? a.watch : ['gmail']).filter((k) => WATCH_SOURCES[k]);
|
|
85
|
+
return {
|
|
86
|
+
on: !!a.on,
|
|
87
|
+
watch: watch.length ? [...new Set(watch)] : ['gmail'],
|
|
88
|
+
reach: REACH[a.reach] ? a.reach : 'push',
|
|
89
|
+
// Draft a reply in Gmail for important mail (one model call each). Off = just tell me.
|
|
90
|
+
draft: a.draft !== false,
|
|
91
|
+
quiet: { on: q.on !== false, from: HHMM.test(q.from) ? q.from : '22:00', to: HHMM.test(q.to) ? q.to : '07:00' },
|
|
92
|
+
// Keep watching from Codeply's server while this PC is off (stores the Gmail sign-in there, encrypted).
|
|
93
|
+
cloud: !!a.cloud,
|
|
94
|
+
// "Call me when X emails me" (watch_email): sender, call or text, once unless repeat.
|
|
95
|
+
alerts: (Array.isArray(a.alerts) ? a.alerts : []).filter((x) => x && typeof x.from === 'string' && x.from.trim())
|
|
96
|
+
.slice(-20).map((x) => ({ from: x.from.trim().toLowerCase().slice(0, 200), how: x.how === 'call' ? 'call' : 'text', note: String(x.note || '').slice(0, 200), repeat: !!x.repeat, at: Number(x.at) || Date.now() })),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
65
99
|
|
|
66
100
|
// Kept in sync with bot-avatar.js (the renderer). The engine only validates.
|
|
67
101
|
const AVATAR_KEYS = {
|
|
@@ -115,7 +149,7 @@ const TEMPLATES = [
|
|
|
115
149
|
specialty: 'Breaks a big goal into steps and gets the right teammate on each one',
|
|
116
150
|
instructions: 'Restate the objective in one line. Split it into a few small steps. Hand each step to the teammate whose domain fits, one at a time, with only the context they need. Read every result critically before moving on, redo or adjust when something is off, and finish with one merged answer that says what was done and what is left.',
|
|
117
151
|
tone: { preset: 'friendly', custom: '' },
|
|
118
|
-
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases'],
|
|
152
|
+
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases', 'calendar'],
|
|
119
153
|
avatar: { shape: 'burst9', eyes: 'pills', color: 'graphite' },
|
|
120
154
|
},
|
|
121
155
|
{
|
|
@@ -123,7 +157,7 @@ const TEMPLATES = [
|
|
|
123
157
|
specialty: 'Research: finds facts, docs and prior art, and cites where they came from',
|
|
124
158
|
instructions: 'Search the project and the web, read the primary source, and report what you found with links or file paths. Separate facts from guesses. Never change files.',
|
|
125
159
|
tone: { preset: 'professional', custom: '' }, sources: 'Official docs first, then the project itself, then reputable articles.',
|
|
126
|
-
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases'],
|
|
160
|
+
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases', 'calendar'],
|
|
127
161
|
avatar: { shape: 'drop', eyes: 'big', color: 'blue' },
|
|
128
162
|
},
|
|
129
163
|
{
|
|
@@ -131,7 +165,7 @@ const TEMPLATES = [
|
|
|
131
165
|
specialty: 'Outreach: drafts emails, posts and messages that sound like the user',
|
|
132
166
|
instructions: 'Write drafts the user can send as is: clear subject, short body, one ask. Match their voice from earlier messages. Never send anything yourself without the user saying yes.',
|
|
133
167
|
tone: { preset: 'friendly', custom: '' },
|
|
134
|
-
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases'],
|
|
168
|
+
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases', 'calendar'],
|
|
135
169
|
avatar: { shape: 'cloud', eyes: 'happy', color: 'pink', cheeks: true },
|
|
136
170
|
},
|
|
137
171
|
{
|
|
@@ -139,7 +173,7 @@ const TEMPLATES = [
|
|
|
139
173
|
specialty: 'Analysis: digs into code, data and numbers and explains what they mean',
|
|
140
174
|
instructions: 'Read the real code or data before concluding anything. Show the key numbers, the reasoning, and a clear recommendation. Say how sure you are.',
|
|
141
175
|
tone: { preset: 'direct', custom: '' },
|
|
142
|
-
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases'],
|
|
176
|
+
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases', 'calendar'],
|
|
143
177
|
avatar: { shape: 'squircle', eyes: 'ovals', color: 'teal', glasses: 'round' },
|
|
144
178
|
},
|
|
145
179
|
{
|
|
@@ -147,7 +181,7 @@ const TEMPLATES = [
|
|
|
147
181
|
specialty: 'Reporting: turns results into short, skimmable summaries and status updates',
|
|
148
182
|
instructions: 'Lead with the outcome, then 3 to 5 bullets, then next steps. Plain words, no jargon, nothing invented.',
|
|
149
183
|
tone: { preset: 'concise', custom: '' },
|
|
150
|
-
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases'],
|
|
184
|
+
approval: ['edit_files', 'run_commands', 'send', 'publish', 'databases', 'calendar'],
|
|
151
185
|
avatar: { shape: 'star', eyes: 'dots', color: 'orange', accessory: 'sprout' },
|
|
152
186
|
},
|
|
153
187
|
{
|
|
@@ -155,7 +189,7 @@ const TEMPLATES = [
|
|
|
155
189
|
specialty: 'Execution: writes and changes code, runs the checks, ships the change',
|
|
156
190
|
instructions: 'Make the smallest change that does the job, in the project\'s own style. Run the relevant check after every change and report what really happened.',
|
|
157
191
|
tone: { preset: 'concise', custom: '' },
|
|
158
|
-
approval: ['run_commands', 'send', 'publish', 'databases'],
|
|
192
|
+
approval: ['run_commands', 'send', 'publish', 'databases', 'calendar'],
|
|
159
193
|
avatar: { shape: 'burst7', eyes: 'sleepy', color: 'red', accessory: 'antenna' },
|
|
160
194
|
},
|
|
161
195
|
{
|
|
@@ -163,7 +197,7 @@ const TEMPLATES = [
|
|
|
163
197
|
specialty: 'Monitoring: checks that things still work and flags what changed or broke',
|
|
164
198
|
instructions: 'Run the checks, compare with what was expected, and report only what changed or failed, with the exact error. Suggest the next step, do not fix it yourself.',
|
|
165
199
|
tone: { preset: 'direct', custom: '' },
|
|
166
|
-
approval: ['edit_files', 'send', 'publish', 'databases'],
|
|
200
|
+
approval: ['edit_files', 'send', 'publish', 'databases', 'calendar'],
|
|
167
201
|
avatar: { shape: 'burst12', eyes: 'sparkle', color: 'purple', accessory: 'halo' },
|
|
168
202
|
},
|
|
169
203
|
];
|
|
@@ -199,9 +233,12 @@ function normalizeBot(input, existing) {
|
|
|
199
233
|
tone: { preset: TONES[tone.preset] ? tone.preset : 'friendly', custom: clip(tone.custom, 400) },
|
|
200
234
|
sources: clip(b.sources, 2000),
|
|
201
235
|
approval: Array.isArray(b.approval) ? [...new Set(b.approval.filter((k) => APPROVALS[k]))] : ALL_APPROVALS.slice(),
|
|
236
|
+
// Which categories existed when the user last chose; newer ones default to asking.
|
|
237
|
+
approvalSeen: ALL_APPROVALS.slice(),
|
|
202
238
|
avatar: normalizeAvatar(b.avatar),
|
|
203
239
|
// The voice it speaks with on calls (a Deepgram, Edge or Kokoro voice id; '' = pick one).
|
|
204
240
|
voice: typeof b.voice === 'string' && /^[\w.-]{0,80}$/.test(b.voice) ? b.voice : '',
|
|
241
|
+
alwaysOn: normalizeAlwaysOn(b.alwaysOn),
|
|
205
242
|
memory: cleanMemory(b.memory),
|
|
206
243
|
// Experience (learned on the job, see reflectOnRun): lessons, playbooks, tool tips, open threads.
|
|
207
244
|
lessons: cleanLessons(b.lessons),
|
|
@@ -235,6 +272,10 @@ function listBots() {
|
|
|
235
272
|
for (const f of files) {
|
|
236
273
|
try {
|
|
237
274
|
const raw = JSON.parse(fs.readFileSync(path.join(botsDir(), f), 'utf8'));
|
|
275
|
+
if (Array.isArray(raw.approval)) {
|
|
276
|
+
const seen = Array.isArray(raw.approvalSeen) ? raw.approvalSeen : FIRST_APPROVALS;
|
|
277
|
+
for (const k of ALL_APPROVALS) if (!seen.includes(k) && !raw.approval.includes(k)) raw.approval.push(k);
|
|
278
|
+
}
|
|
238
279
|
const bot = normalizeBot(raw, { id: f.replace(/\.json$/, ''), createdAt: raw.createdAt });
|
|
239
280
|
bot.updatedAt = Number(raw.updatedAt) || bot.updatedAt;
|
|
240
281
|
out.push(bot);
|
|
@@ -641,10 +682,29 @@ const ASK_BOT_FORMAT = `To ask a teammate, write:
|
|
|
641
682
|
<codeply:ask_bot>
|
|
642
683
|
<bot>Name</bot>
|
|
643
684
|
<task>
|
|
644
|
-
The one task, with every bit of context they need
|
|
685
|
+
The one task, with every bit of context they need. Spell out the concrete details: email addresses, names, subjects, dates, file paths. Never write "the email from earlier" or "what they told you".
|
|
645
686
|
</task>
|
|
646
687
|
</codeply:ask_bot>`;
|
|
647
688
|
|
|
689
|
+
const PHONE_RULES = `YOUR LINE TO THE USER'S PHONE
|
|
690
|
+
You can reach the user on their phone with reach_me, and watch their inbox with watch_email (it keeps watching in the background).
|
|
691
|
+
- Urgent or time critical, or they asked for a call: reach_me with how=call (the phone rings and you speak).
|
|
692
|
+
- Anything else worth their attention: how=text (a notification).
|
|
693
|
+
- "Tell me / call me when X emails me": watch_email with from=X and how=call or text. Do not say you cannot run in the background.
|
|
694
|
+
- A reminder at a time: reach_me with at set to that time.
|
|
695
|
+
- "Have Shella call me": reach_me with bot set to that bot's name, so the call comes from them.`;
|
|
696
|
+
const PHONE_FORMAT = `To reach the phone or watch for an email, write:
|
|
697
|
+
<codeply:reach_me>
|
|
698
|
+
<how>call</how>
|
|
699
|
+
<message>Your Vercel deploy just failed on main.</message>
|
|
700
|
+
<at>17:30</at>
|
|
701
|
+
<bot>(optional: the bot it comes from)</bot>
|
|
702
|
+
</codeply:reach_me>
|
|
703
|
+
<codeply:watch_email>
|
|
704
|
+
<from>someone@example.com</from>
|
|
705
|
+
<how>call</how>
|
|
706
|
+
</codeply:watch_email>`;
|
|
707
|
+
|
|
648
708
|
const VERIFY_RULES = `BEFORE YOU SAY IT IS DONE
|
|
649
709
|
- Base every claim on what your tools actually returned in this run.
|
|
650
710
|
- Check the deliverable exists (the file is written, the message is sent, the command passed) before you say so.
|
|
@@ -707,9 +767,10 @@ function buildBotPrompt(bot, o = {}) {
|
|
|
707
767
|
parts.push(`APPROVAL BOUNDARY\n${approvalLine(bot)}`);
|
|
708
768
|
const memory = (bot.memory || []).slice(-MAX_MEMORY);
|
|
709
769
|
if (memory.length) {
|
|
710
|
-
parts.push(`WHAT YOU HAVE LEARNED ABOUT THIS USER\
|
|
770
|
+
parts.push(`WHAT YOU HAVE LEARNED ABOUT THIS USER\nBackground only. The current request and the recent chat always win: never assume an old item here is what the user means now (an older email, project or task). If the request is unclear, say which one you picked, or ask.\n${memory.map((m) => `- ${m.fact}`).join('\n')}`);
|
|
711
771
|
}
|
|
712
772
|
parts.push(...experienceParts(bot, o.request));
|
|
773
|
+
if (require('./reach.js').available()) parts.push(o.native ? PHONE_RULES : `${PHONE_RULES}\n\n${PHONE_FORMAT}`);
|
|
713
774
|
parts.push(VERIFY_RULES);
|
|
714
775
|
if (o.askedBy) {
|
|
715
776
|
parts.push(`DELEGATED TASK\n${o.askedBy} asked you to do one task. You only see that task, not the rest of the conversation. Do it fully with your tools, then reply in this shape:\nSummary: <one sentence with the outcome>\n<the details: findings, what you changed, anything ${o.askedBy} must know or check>`);
|
|
@@ -728,7 +789,10 @@ function buildBotPrompt(bot, o = {}) {
|
|
|
728
789
|
function teamPrompt(team, o = {}) {
|
|
729
790
|
const roster = rosterLines(team, null);
|
|
730
791
|
if (!roster.length) return '';
|
|
731
|
-
|
|
792
|
+
const phone = require('./reach.js').available()
|
|
793
|
+
? `\n\nWhen the user asks a bot to call or text them ("tell Shella to call me"), do it yourself with reach_me and bot set to that bot's name, so it comes from that bot. ${o.native ? '' : PHONE_FORMAT}`
|
|
794
|
+
: '';
|
|
795
|
+
return `BOTS\nThe user has these bots. When they ask for one by name, or a part of the work is clearly a bot's specialty, you can hand it that part with ask_bot. Only one bot runs at a time, and you wait for its answer.\n${roster.join('\n')}${o.native ? '' : `\n\n${ASK_BOT_FORMAT}`}${phone}`;
|
|
732
796
|
}
|
|
733
797
|
|
|
734
798
|
/** Which approval category a tool falls into, or null. */
|
|
@@ -887,7 +951,7 @@ function fromDescription(json, description) {
|
|
|
887
951
|
for (const k of ['name', 'specialty', 'instructions', 'sources']) draft[k] = noDash(draft[k]);
|
|
888
952
|
draft.tone.custom = noDash(draft.tone.custom);
|
|
889
953
|
// Irreversible actions always stay behind approval, whatever the model said.
|
|
890
|
-
for (const k of ['send', 'publish', 'databases']) if (!draft.approval.includes(k)) draft.approval.push(k);
|
|
954
|
+
for (const k of ['send', 'publish', 'databases', 'calendar']) if (!draft.approval.includes(k)) draft.approval.push(k);
|
|
891
955
|
delete draft.id; delete draft.memory; delete draft.createdAt; delete draft.updatedAt;
|
|
892
956
|
delete draft.lessons; delete draft.playbooks; delete draft.toolTips; delete draft.openThreads;
|
|
893
957
|
return draft;
|
|
@@ -954,7 +1018,7 @@ async function voiceTurn({ bot, team, turns, recentChat, runAgent, route, cwd, s
|
|
|
954
1018
|
if (!userMessage) return { text: '' };
|
|
955
1019
|
const extra = recentChat ? `\n\nRECENT CHAT BEFORE THIS CALL\n${recentChat}` : '';
|
|
956
1020
|
const run = runAgent({
|
|
957
|
-
userMessage, history, mode: 'Build', cwd, signal, route, maxSteps, approve,
|
|
1021
|
+
userMessage, history, mode: 'Build', cwd, signal, route, maxSteps, approve, botId: bot.id,
|
|
958
1022
|
botPrompt: () => `${buildBotPrompt(bot, { team, request: userMessage })}\n\n${VOICE_RULES}${extra}`,
|
|
959
1023
|
});
|
|
960
1024
|
let reply = '';
|
|
@@ -981,7 +1045,8 @@ function runStep(ev) {
|
|
|
981
1045
|
|
|
982
1046
|
/** What the call screen says while a tool runs. */
|
|
983
1047
|
const CALL_STEP = {
|
|
984
|
-
gmail_search: 'Checking your email', gmail_send: 'Sending the email',
|
|
1048
|
+
gmail_search: 'Checking your email', gmail_send: 'Sending the email', gmail_draft: 'Saving a draft', drafts_list: 'Looking at your drafts',
|
|
1049
|
+
calendar_list: 'Checking your calendar', calendar_add: 'Adding it to your calendar', web_search: 'Searching the web', image_search: 'Looking for images', reach_me: 'Reaching your phone', watch_email: 'Setting an email alert', web_fetch: 'Reading a page',
|
|
985
1050
|
read_file: 'Reading a file', write_file: 'Writing a file', edit_file: 'Editing a file', apply_patch: 'Editing files', run: 'Running a command',
|
|
986
1051
|
search: 'Searching your files', list_dir: 'Looking through files', slack_post_message: 'Posting to Slack', browser_check: 'Checking the page',
|
|
987
1052
|
ask_bot: 'Asking a teammate', todo: 'Planning',
|
|
@@ -990,8 +1055,8 @@ const callStepLabel = (name) => CALL_STEP[name] || 'Working on it';
|
|
|
990
1055
|
|
|
991
1056
|
module.exports = {
|
|
992
1057
|
VOICE_RULES, VOICE_RULES_NO_TOOLS, spoken, callTurns, voiceTurn, callStepLabel,
|
|
993
|
-
MAX_MEMORY, MAX_DEPTH, ROLES, TONES, APPROVALS, AVATAR_KEYS, TEMPLATES,
|
|
994
|
-
botsDir, setBotsDir, normalizeBot, normalizeAvatar,
|
|
1058
|
+
MAX_MEMORY, MAX_DEPTH, ROLES, TONES, APPROVALS, AVATAR_KEYS, TEMPLATES, WATCH_SOURCES, REACH,
|
|
1059
|
+
botsDir, setBotsDir, normalizeBot, normalizeAvatar, normalizeAlwaysOn,
|
|
995
1060
|
listBots, getBot, findBot, createBot, createFromTemplate, updateBot, removeBot,
|
|
996
1061
|
mergeMemory, addMemory, forget, clearMemory, learnFromTurn,
|
|
997
1062
|
MAX_LESSONS, MAX_PLAYBOOKS, MAX_TOOL_TIPS, MAX_OPEN_THREADS,
|