zilmate 1.8.0 → 1.8.5
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/.agents/skills/copywriting/SKILL.md +252 -0
- package/.agents/skills/copywriting/evals/evals.json +111 -0
- package/.agents/skills/copywriting/references/copy-frameworks.md +344 -0
- package/.agents/skills/copywriting/references/natural-transitions.md +272 -0
- package/.agents/skills/firecrawl-deep-research/SKILL.md +108 -0
- package/.agents/skills/shadcn/SKILL.md +267 -0
- package/.agents/skills/shadcn/agents/openai.yml +5 -0
- package/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
- package/.agents/skills/shadcn/assets/shadcn.png +0 -0
- package/.agents/skills/shadcn/cli.md +290 -0
- package/.agents/skills/shadcn/customization.md +209 -0
- package/.agents/skills/shadcn/evals/evals.json +47 -0
- package/.agents/skills/shadcn/mcp.md +105 -0
- package/.agents/skills/shadcn/registry.md +277 -0
- package/.agents/skills/shadcn/rules/base-vs-radix.md +306 -0
- package/.agents/skills/shadcn/rules/composition.md +195 -0
- package/.agents/skills/shadcn/rules/forms.md +192 -0
- package/.agents/skills/shadcn/rules/icons.md +101 -0
- package/.agents/skills/shadcn/rules/styling.md +162 -0
- package/.agents/skills/tavily-research/SKILL.md +100 -0
- package/.agents/skills/upstash/SKILL.md +48 -0
- package/.agents/skills/upstash/upstash-box-js/overview.md +243 -0
- package/.agents/skills/upstash/upstash-box-py/overview.md +275 -0
- package/.agents/skills/upstash/upstash-cli/overview.md +138 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/callbacks.md +147 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/deduplication.md +86 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/dlq.md +164 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/multi-region/summary.md +388 -0
- package/.agents/skills/upstash/upstash-qstash-js/advanced/multi-region/verify-multi-region-setup.ts +388 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/local-development.md +106 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/publishing-messages.md +144 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/queues-and-flow-control.md +148 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/schedules.md +177 -0
- package/.agents/skills/upstash/upstash-qstash-js/fundamentals/url-groups.md +127 -0
- package/.agents/skills/upstash/upstash-qstash-js/overview.md +81 -0
- package/.agents/skills/upstash/upstash-qstash-js/verification/platform-specific/nextjs.md +171 -0
- package/.agents/skills/upstash/upstash-qstash-js/verification/receiver.md +213 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/algorithms.md +84 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/features.md +117 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/methods-getting-started.md +77 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/overview.md +26 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/pricing-cost.md +146 -0
- package/.agents/skills/upstash/upstash-ratelimit-js/traffic-protection.md +77 -0
- package/.agents/skills/upstash/upstash-redis-js/advanced-features/auto-pipeline.md +49 -0
- package/.agents/skills/upstash/upstash-redis-js/advanced-features/pipeline-and-transactions.md +42 -0
- package/.agents/skills/upstash/upstash-redis-js/advanced-features/scripting.md +124 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/hashes.md +71 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/json.md +133 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/lists.md +72 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/sets.md +90 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/sorted-sets.md +126 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/streams.md +196 -0
- package/.agents/skills/upstash/upstash-redis-js/data-structures/strings.md +73 -0
- package/.agents/skills/upstash/upstash-redis-js/migrations/from-ioredis.md +163 -0
- package/.agents/skills/upstash/upstash-redis-js/migrations/from-redis-node.md +205 -0
- package/.agents/skills/upstash/upstash-redis-js/overview.md +183 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/caching.md +58 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/distributed-locks.md +130 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/leaderboard.md +134 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/rate-limiting.md +187 -0
- package/.agents/skills/upstash/upstash-redis-js/patterns/session-management.md +217 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/batching-operations.md +76 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/data-serialization.md +134 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/error-handling.md +118 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/pipeline-optimization.md +105 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/redis-replicas.md +14 -0
- package/.agents/skills/upstash/upstash-redis-js/performance/ttl-expiration.md +32 -0
- package/.agents/skills/upstash/upstash-redis-js/search/adapters.md +99 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/aggregating.md +234 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/aliases.md +76 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/index-management.md +124 -0
- package/.agents/skills/upstash/upstash-redis-js/search/commands/querying.md +315 -0
- package/.agents/skills/upstash/upstash-redis-js/search/overview.md +155 -0
- package/.agents/skills/upstash/upstash-redis-start/overview.md +71 -0
- package/.agents/skills/upstash/upstash-search-js/overview.md +48 -0
- package/.agents/skills/upstash/upstash-search-js/quick-start.md +158 -0
- package/.agents/skills/upstash/upstash-search-js/sdk-overview.md +158 -0
- package/.agents/skills/upstash/upstash-vector-js/features/filtering-and-metadata.md +82 -0
- package/.agents/skills/upstash/upstash-vector-js/features/index-structure.md +193 -0
- package/.agents/skills/upstash/upstash-vector-js/features/namespaces.md +32 -0
- package/.agents/skills/upstash/upstash-vector-js/overview.md +44 -0
- package/.agents/skills/upstash/upstash-vector-js/sdk-methods.md +210 -0
- package/.agents/skills/upstash/upstash-workflow-js/agents.md +248 -0
- package/.agents/skills/upstash/upstash-workflow-js/basics/client.md +180 -0
- package/.agents/skills/upstash/upstash-workflow-js/basics/context.md +230 -0
- package/.agents/skills/upstash/upstash-workflow-js/basics/serve.md +70 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/flow-control.md +145 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/invoke.md +97 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/retries-failures-reliability.md +239 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/wait-for-event.md +97 -0
- package/.agents/skills/upstash/upstash-workflow-js/features/webhooks.md +79 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/local-dev.md +177 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/middleware.md +166 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/migrations.md +201 -0
- package/.agents/skills/upstash/upstash-workflow-js/how-to/realtime.md +186 -0
- package/.agents/skills/upstash/upstash-workflow-js/overview.md +55 -0
- package/.agents/skills/upstash/upstash-workflow-js/rest-api.md +156 -0
- package/.agents/skills/upstash/upstash-workflow-js/troubleshooting.md +201 -0
- package/.agents/skills/upstash-box-js/SKILL.md +248 -0
- package/.agents/skills/upstash-box-py/SKILL.md +280 -0
- package/.agents/skills/upstash-cli/SKILL.md +143 -0
- package/.agents/skills/upstash-qstash-js/SKILL.md +86 -0
- package/.agents/skills/upstash-qstash-js/advanced/callbacks.md +147 -0
- package/.agents/skills/upstash-qstash-js/advanced/deduplication.md +86 -0
- package/.agents/skills/upstash-qstash-js/advanced/dlq.md +164 -0
- package/.agents/skills/upstash-qstash-js/advanced/multi-region/summary.md +388 -0
- package/.agents/skills/upstash-qstash-js/advanced/multi-region/verify-multi-region-setup.ts +388 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/local-development.md +106 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/publishing-messages.md +144 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/queues-and-flow-control.md +148 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/schedules.md +177 -0
- package/.agents/skills/upstash-qstash-js/fundamentals/url-groups.md +127 -0
- package/.agents/skills/upstash-qstash-js/verification/platform-specific/nextjs.md +171 -0
- package/.agents/skills/upstash-qstash-js/verification/receiver.md +213 -0
- package/.agents/skills/upstash-ratelimit-js/SKILL.md +31 -0
- package/.agents/skills/upstash-ratelimit-js/algorithms.md +84 -0
- package/.agents/skills/upstash-ratelimit-js/features.md +117 -0
- package/.agents/skills/upstash-ratelimit-js/methods-getting-started.md +77 -0
- package/.agents/skills/upstash-ratelimit-js/pricing-cost.md +146 -0
- package/.agents/skills/upstash-ratelimit-js/traffic-protection.md +77 -0
- package/.agents/skills/upstash-redis-js/SKILL.md +188 -0
- package/.agents/skills/upstash-redis-js/advanced-features/auto-pipeline.md +49 -0
- package/.agents/skills/upstash-redis-js/advanced-features/pipeline-and-transactions.md +42 -0
- package/.agents/skills/upstash-redis-js/advanced-features/scripting.md +124 -0
- package/.agents/skills/upstash-redis-js/data-structures/hashes.md +71 -0
- package/.agents/skills/upstash-redis-js/data-structures/json.md +133 -0
- package/.agents/skills/upstash-redis-js/data-structures/lists.md +72 -0
- package/.agents/skills/upstash-redis-js/data-structures/sets.md +90 -0
- package/.agents/skills/upstash-redis-js/data-structures/sorted-sets.md +126 -0
- package/.agents/skills/upstash-redis-js/data-structures/streams.md +196 -0
- package/.agents/skills/upstash-redis-js/data-structures/strings.md +73 -0
- package/.agents/skills/upstash-redis-js/migrations/from-ioredis.md +163 -0
- package/.agents/skills/upstash-redis-js/migrations/from-redis-node.md +205 -0
- package/.agents/skills/upstash-redis-js/patterns/caching.md +58 -0
- package/.agents/skills/upstash-redis-js/patterns/distributed-locks.md +130 -0
- package/.agents/skills/upstash-redis-js/patterns/leaderboard.md +134 -0
- package/.agents/skills/upstash-redis-js/patterns/rate-limiting.md +187 -0
- package/.agents/skills/upstash-redis-js/patterns/session-management.md +217 -0
- package/.agents/skills/upstash-redis-js/performance/batching-operations.md +76 -0
- package/.agents/skills/upstash-redis-js/performance/data-serialization.md +134 -0
- package/.agents/skills/upstash-redis-js/performance/error-handling.md +118 -0
- package/.agents/skills/upstash-redis-js/performance/pipeline-optimization.md +105 -0
- package/.agents/skills/upstash-redis-js/performance/redis-replicas.md +14 -0
- package/.agents/skills/upstash-redis-js/performance/ttl-expiration.md +32 -0
- package/.agents/skills/upstash-redis-js/search/adapters.md +99 -0
- package/.agents/skills/upstash-redis-js/search/commands/aggregating.md +234 -0
- package/.agents/skills/upstash-redis-js/search/commands/aliases.md +76 -0
- package/.agents/skills/upstash-redis-js/search/commands/index-management.md +124 -0
- package/.agents/skills/upstash-redis-js/search/commands/querying.md +315 -0
- package/.agents/skills/upstash-redis-js/search/overview.md +155 -0
- package/.agents/skills/upstash-redis-start/SKILL.md +76 -0
- package/.agents/skills/upstash-search-js/SKILL.md +53 -0
- package/.agents/skills/upstash-search-js/quick-start.md +158 -0
- package/.agents/skills/upstash-search-js/sdk-overview.md +158 -0
- package/.agents/skills/upstash-vector-js/SKILL.md +49 -0
- package/.agents/skills/upstash-vector-js/features/filtering-and-metadata.md +82 -0
- package/.agents/skills/upstash-vector-js/features/index-structure.md +193 -0
- package/.agents/skills/upstash-vector-js/features/namespaces.md +32 -0
- package/.agents/skills/upstash-vector-js/sdk-methods.md +210 -0
- package/.agents/skills/upstash-workflow-js/SKILL.md +60 -0
- package/.agents/skills/upstash-workflow-js/agents.md +248 -0
- package/.agents/skills/upstash-workflow-js/basics/client.md +180 -0
- package/.agents/skills/upstash-workflow-js/basics/context.md +230 -0
- package/.agents/skills/upstash-workflow-js/basics/serve.md +70 -0
- package/.agents/skills/upstash-workflow-js/features/flow-control.md +145 -0
- package/.agents/skills/upstash-workflow-js/features/invoke.md +97 -0
- package/.agents/skills/upstash-workflow-js/features/retries-failures-reliability.md +239 -0
- package/.agents/skills/upstash-workflow-js/features/wait-for-event.md +97 -0
- package/.agents/skills/upstash-workflow-js/features/webhooks.md +79 -0
- package/.agents/skills/upstash-workflow-js/how-to/local-dev.md +177 -0
- package/.agents/skills/upstash-workflow-js/how-to/middleware.md +166 -0
- package/.agents/skills/upstash-workflow-js/how-to/migrations.md +201 -0
- package/.agents/skills/upstash-workflow-js/how-to/realtime.md +186 -0
- package/.agents/skills/upstash-workflow-js/rest-api.md +156 -0
- package/.agents/skills/upstash-workflow-js/troubleshooting.md +201 -0
- package/dist/agents/coding.agent.d.ts +185 -42
- package/dist/agents/coding.agent.d.ts.map +1 -1
- package/dist/agents/coding.agent.js +42 -5
- package/dist/agents/coding.agent.js.map +1 -1
- package/dist/agents/manager.d.ts +216 -41
- package/dist/agents/manager.d.ts.map +1 -1
- package/dist/agents/manager.js +103 -140
- package/dist/agents/manager.js.map +1 -1
- package/dist/agents/security.agent.d.ts +3 -3
- package/dist/agents/swarm/development/lead.d.ts +3 -0
- package/dist/agents/swarm/development/lead.d.ts.map +1 -0
- package/dist/agents/swarm/development/lead.js +24 -0
- package/dist/agents/swarm/development/lead.js.map +1 -0
- package/dist/agents/swarm/main.d.ts +69 -0
- package/dist/agents/swarm/main.d.ts.map +1 -1
- package/dist/agents/swarm/main.js +65 -11
- package/dist/agents/swarm/main.js.map +1 -1
- package/dist/agents/swarm/registry.d.ts +2 -1
- package/dist/agents/swarm/registry.d.ts.map +1 -1
- package/dist/agents/swarm/registry.js +225 -95
- package/dist/agents/swarm/registry.js.map +1 -1
- package/dist/cli/composer.d.ts.map +1 -1
- package/dist/cli/composer.js +85 -30
- package/dist/cli/composer.js.map +1 -1
- package/dist/cli/confirm.d.ts +2 -2
- package/dist/cli/confirm.d.ts.map +1 -1
- package/dist/cli/confirm.js +373 -4
- package/dist/cli/confirm.js.map +1 -1
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +47 -2
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/format.d.ts +4 -0
- package/dist/cli/format.d.ts.map +1 -1
- package/dist/cli/format.js +352 -65
- package/dist/cli/format.js.map +1 -1
- package/dist/cli/interactive.d.ts.map +1 -1
- package/dist/cli/interactive.js +80 -2
- package/dist/cli/interactive.js.map +1 -1
- package/dist/cli/menu.d.ts.map +1 -1
- package/dist/cli/menu.js +93 -83
- package/dist/cli/menu.js.map +1 -1
- package/dist/cli/render.d.ts.map +1 -1
- package/dist/cli/render.js +2 -1
- package/dist/cli/render.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +262 -27
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/swarm.d.ts.map +1 -1
- package/dist/cli/swarm.js +13 -10
- package/dist/cli/swarm.js.map +1 -1
- package/dist/cli/theme.d.ts +7 -1
- package/dist/cli/theme.d.ts.map +1 -1
- package/dist/cli/theme.js +4 -16
- package/dist/cli/theme.js.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +27 -4
- package/dist/cli/update.js.map +1 -1
- package/dist/config/env.d.ts +3 -1
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +22 -2
- package/dist/config/env.js.map +1 -1
- package/dist/config/models.d.ts +1 -0
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +17 -1
- package/dist/config/models.js.map +1 -1
- package/dist/documents/pdf.d.ts.map +1 -1
- package/dist/documents/pdf.js +282 -22
- package/dist/documents/pdf.js.map +1 -1
- package/dist/documents/slides.d.ts.map +1 -1
- package/dist/documents/slides.js +160 -30
- package/dist/documents/slides.js.map +1 -1
- package/dist/index.js +73 -18
- package/dist/index.js.map +1 -1
- package/dist/memory/history.js +1 -1
- package/dist/observability/doctor.d.ts.map +1 -1
- package/dist/observability/doctor.js +3 -0
- package/dist/observability/doctor.js.map +1 -1
- package/dist/runtime/progress.d.ts +5 -1
- package/dist/runtime/progress.d.ts.map +1 -1
- package/dist/runtime/progress.js.map +1 -1
- package/dist/runtime/swarm.d.ts +1 -1
- package/dist/runtime/swarm.d.ts.map +1 -1
- package/dist/runtime/swarm.js +19 -3
- package/dist/runtime/swarm.js.map +1 -1
- package/dist/runtime/tool-utils.d.ts +2 -0
- package/dist/runtime/tool-utils.d.ts.map +1 -1
- package/dist/runtime/tool-utils.js +91 -0
- package/dist/runtime/tool-utils.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/skills/loader.d.ts.map +1 -1
- package/dist/skills/loader.js +16 -0
- package/dist/skills/loader.js.map +1 -1
- package/dist/test-call.d.ts +2 -0
- package/dist/test-call.d.ts.map +1 -0
- package/dist/test-call.js +29 -0
- package/dist/test-call.js.map +1 -0
- package/dist/test-manager-call.d.ts +2 -0
- package/dist/test-manager-call.d.ts.map +1 -0
- package/dist/test-manager-call.js +138 -0
- package/dist/test-manager-call.js.map +1 -0
- package/dist/test-manager-filtered.d.ts +2 -0
- package/dist/test-manager-filtered.d.ts.map +1 -0
- package/dist/test-manager-filtered.js +130 -0
- package/dist/test-manager-filtered.js.map +1 -0
- package/dist/test-mcp-call.d.ts +2 -0
- package/dist/test-mcp-call.d.ts.map +1 -0
- package/dist/test-mcp-call.js +103 -0
- package/dist/test-mcp-call.js.map +1 -0
- package/dist/tools/composio.tool.d.ts +1 -1
- package/dist/tools/composio.tool.d.ts.map +1 -1
- package/dist/tools/composio.tool.js +7 -16
- package/dist/tools/composio.tool.js.map +1 -1
- package/dist/tools/daytona-browser.tool.js +1 -1
- package/dist/tools/daytona-browser.tool.js.map +1 -1
- package/dist/tools/executive.tool.d.ts +40 -0
- package/dist/tools/executive.tool.d.ts.map +1 -0
- package/dist/tools/executive.tool.js +74 -0
- package/dist/tools/executive.tool.js.map +1 -0
- package/dist/tools/filesystem.tool.d.ts +183 -40
- package/dist/tools/filesystem.tool.d.ts.map +1 -1
- package/dist/tools/filesystem.tool.js +564 -111
- package/dist/tools/filesystem.tool.js.map +1 -1
- package/dist/tools/mcp.tool.d.ts +56 -0
- package/dist/tools/mcp.tool.d.ts.map +1 -0
- package/dist/tools/mcp.tool.js +285 -0
- package/dist/tools/mcp.tool.js.map +1 -0
- package/dist/tools/osint.tool.d.ts +4 -4
- package/dist/tools/pentest.tool.d.ts +2 -2
- package/dist/tools/setup-assistant.tool.d.ts +1 -1
- package/dist/tools/setup-assistant.tool.js +1 -1
- package/dist/tools/setup-assistant.tool.js.map +1 -1
- package/dist/workspace/paths.d.ts +1 -0
- package/dist/workspace/paths.d.ts.map +1 -1
- package/dist/workspace/paths.js +3 -4
- package/dist/workspace/paths.js.map +1 -1
- package/package.json +8 -4
- package/scripts/postinstall.mjs +19 -4
- package/scripts/release-github.mjs +11 -11
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# Workflow REST API Skill
|
|
2
|
+
|
|
3
|
+
This Skill provides TypeScript-focused guidance for interacting with the Upstash QStash Workflow Dead Letter Queue (DLQ) REST API. It includes practical usage examples, consolidated patterns, and key considerations for safely restarting, resuming, listing, deleting, and inspecting failed workflow runs.
|
|
4
|
+
|
|
5
|
+
The goal is to help agents construct correct TypeScript API requests, handle optional fields, and avoid common pitfalls when working with workflow recovery operations.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Core Concepts
|
|
10
|
+
|
|
11
|
+
• **DLQ Entries** represent failed workflow runs containing metadata such as payload, headers, timestamps, failure callback state, and workflow configuration.
|
|
12
|
+
• **Restart** recreates the entire workflow run from the beginning (fresh execution, no preserved state).
|
|
13
|
+
• **Resume** creates a new run continuing from the failed step (preserves successful steps).
|
|
14
|
+
• **Bulk operations** process up to 50 DLQ entries per request and may return a cursor for pagination.
|
|
15
|
+
• **Flow-Control and Retry Overrides** are passed via headers and apply only to the newly created workflow run.
|
|
16
|
+
|
|
17
|
+
Be careful: changing workflow code **before** the failed step may cause resume operations to break.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# HTTP Endpoints Overview
|
|
22
|
+
|
|
23
|
+
Below is a complete summary of the API endpoints supported by this skill.
|
|
24
|
+
|
|
25
|
+
• `GET /v2/workflows/dlq` — List DLQ entries with filtering.
|
|
26
|
+
• `GET /v2/workflows/dlq/{dlqId}` — Retrieve a single DLQ entry.
|
|
27
|
+
• `DELETE /v2/workflows/dlq/{dlqId}` — Delete a DLQ entry.
|
|
28
|
+
• `POST /v2/workflows/dlq/restart/{dlqId}` — Restart a workflow from scratch.
|
|
29
|
+
• `POST /v2/workflows/dlq/resume/{dlqId}` — Resume a workflow from point of failure.
|
|
30
|
+
• `POST /v2/workflows/dlq/restart` — Bulk restart (up to 50).
|
|
31
|
+
• `POST /v2/workflows/dlq/resume` — Bulk resume (up to 50).
|
|
32
|
+
• `POST /v2/workflows/dlq/callback/{dlqId}` — Rerun a failed failure-callback.
|
|
33
|
+
• `GET /v2/flowControl` and `/v2/flowControl/{key}` — Flow-control inspection.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# TypeScript Usage Patterns
|
|
38
|
+
|
|
39
|
+
Below is a single integrated example illustrating several endpoints, optional query parameters, header overrides, and response field handling.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import fetch from "node-fetch";
|
|
43
|
+
|
|
44
|
+
const token = process.env.QSTASH_TOKEN;
|
|
45
|
+
const base = "https://qstash.upstash.io/v2";
|
|
46
|
+
|
|
47
|
+
async function example() {
|
|
48
|
+
// 1. List DLQ items with filters
|
|
49
|
+
const list = await fetch(
|
|
50
|
+
`${base}/workflows/dlq?workflowUrl=https://my.app/workflow&fromDate=1700000000000`,
|
|
51
|
+
{
|
|
52
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
53
|
+
}
|
|
54
|
+
).then((r) => r.json());
|
|
55
|
+
|
|
56
|
+
const firstDlqId = list.messages?.[0]?.dlqId;
|
|
57
|
+
|
|
58
|
+
// 2. Restart or Resume a specific run (headers may override flow control or retries)
|
|
59
|
+
const restart = await fetch(`${base}/workflows/dlq/restart/${firstDlqId}`, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: {
|
|
62
|
+
Authorization: `Bearer ${token}`,
|
|
63
|
+
"Upstash-Flow-Control-Key": "my-key", // optional
|
|
64
|
+
"Upstash-Flow-Control-Value": "parallelism=1", // optional
|
|
65
|
+
"Upstash-Retries": "3", // optional
|
|
66
|
+
},
|
|
67
|
+
}).then((r) => r.json());
|
|
68
|
+
|
|
69
|
+
// 3. Bulk resume using filters and cursor handling
|
|
70
|
+
const bulkResume = await fetch(`${base}/workflows/dlq/resume`, {
|
|
71
|
+
method: "POST",
|
|
72
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
73
|
+
body: JSON.stringify({
|
|
74
|
+
fromDate: 1700000000000,
|
|
75
|
+
workflowUrl: "https://my.app/workflow",
|
|
76
|
+
dlqIds: [firstDlqId], // optional; filters also supported
|
|
77
|
+
}),
|
|
78
|
+
}).then((r) => r.json());
|
|
79
|
+
|
|
80
|
+
// 4. Rerun failure callback
|
|
81
|
+
const callback = await fetch(`${base}/workflows/dlq/callback/${firstDlqId}`, {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
84
|
+
}).then((r) => r.json());
|
|
85
|
+
|
|
86
|
+
// 5. Delete a DLQ entry
|
|
87
|
+
await fetch(`${base}/workflows/dlq/${firstDlqId}`, {
|
|
88
|
+
method: "DELETE",
|
|
89
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// 6. Inspect Flow-Control
|
|
93
|
+
const fc = await fetch(`${base}/flowControl/my-key`, {
|
|
94
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
95
|
+
}).then((r) => r.json());
|
|
96
|
+
|
|
97
|
+
console.log({ list, restart, bulkResume, callback, fc });
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
# Key Fields and Behaviors
|
|
104
|
+
|
|
105
|
+
## Request Query Fields
|
|
106
|
+
|
|
107
|
+
• **dlqIds: string[]** — Exact DLQ IDs for targeting specific failed runs (bulk restart/resume).
|
|
108
|
+
• **fromDate / toDate: number** — Millisecond timestamps; inclusive range filters.
|
|
109
|
+
• **workflowUrl: string** — Filters by workflow endpoint URL.
|
|
110
|
+
• **workflowRunId: string** — Can match full run ID or prefix.
|
|
111
|
+
• **workflowCreatedAt: number** — Timestamp filter for creation time.
|
|
112
|
+
• **responseStatus: number** — Filter by HTTP status of failed run.
|
|
113
|
+
• **callerIP: string** — Filter by origin IP.
|
|
114
|
+
• **failureCallbackState: string** — Filter runs whose failure callback succeeded or failed.
|
|
115
|
+
• **cursor: string** — Pagination cursor; returned by list & bulk ops.
|
|
116
|
+
• **count: number** — Limit for listing DLQ entries (default/max 100).
|
|
117
|
+
|
|
118
|
+
## Header Overrides
|
|
119
|
+
|
|
120
|
+
These apply only when creating a **new workflow run** (restart or resume).
|
|
121
|
+
|
|
122
|
+
• **Upstash-Flow-Control-Key** — Override flow-control key.
|
|
123
|
+
• **Upstash-Flow-Control-Value** — Override flow-control config (e.g., "parallelism=1").
|
|
124
|
+
• **Upstash-Retries** — Override step retry configuration.
|
|
125
|
+
|
|
126
|
+
All are optional; original values are reused if omitted.
|
|
127
|
+
|
|
128
|
+
## Response Fields
|
|
129
|
+
|
|
130
|
+
• **cursor?: string** — If returned, additional entries exist.
|
|
131
|
+
• **workflowRuns: { workflowRunId: string; workflowCreatedAt: number }[]** — Returned by bulk restart/resume.
|
|
132
|
+
• **message objects** (DLQ list/get) include:
|
|
133
|
+
|
|
134
|
+
- **workflowRunId, workflowCreatedAt, workflowUrl**
|
|
135
|
+
- **responseStatus, responseHeader, responseBody**
|
|
136
|
+
- **failureCallbackInfo.state** — Identify failed callbacks.
|
|
137
|
+
- **dlqId** — Unique DLQ entry identifier.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
# Pitfalls & Best Practices
|
|
142
|
+
|
|
143
|
+
• **Resume only works if workflow code before the failed step stays unchanged**. Any change may cause resume to fail.
|
|
144
|
+
• **Bulk operations process max 50 items**. Always check `cursor` to continue processing.
|
|
145
|
+
• **Deleting a DLQ entry is permanent**; once removed, it cannot be resumed or restarted.
|
|
146
|
+
• **Failure callback reruns are independent** and do not affect workflow execution. They only retry the failure-notification step.
|
|
147
|
+
• **Prefix matching on workflowRunId** can unintentionally match more runs than expected—use full ID for precision.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
# Recommended Patterns
|
|
152
|
+
|
|
153
|
+
• Fetch → Check cursor → Continue looping for bulk operations.
|
|
154
|
+
• Always log `failureCallbackInfo.state` to determine whether a callback rerun is required.
|
|
155
|
+
• Apply header overrides sparingly; flow-control misconfiguration may stall large batches.
|
|
156
|
+
• Prefer filtering in bulk operations instead of manually passing large dlqIds arrays.
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Workflow Troubleshooting (TypeScript)
|
|
2
|
+
|
|
3
|
+
This guide provides clear, TypeScript‑focused patterns for diagnosing and fixing common issues in Upstash Workflow. It highlights correct usage of core workflow features and shows how to avoid pitfalls that commonly occur in real applications.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Steps Inside try/catch
|
|
8
|
+
|
|
9
|
+
Workflow steps (`context.run`, `context.sleep`, `context.sleepUntil`, `context.call`) intentionally throw `WorkflowAbort` after completing. Catching this error prevents the workflow engine from progressing.
|
|
10
|
+
|
|
11
|
+
**Correct pattern:** rethrow `WorkflowAbort` or avoid `try/catch` around steps.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { WorkflowAbort } from "@upstash/workflow";
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// Any step will throw WorkflowAbort
|
|
18
|
+
const result = await context.run("step", () => "ok");
|
|
19
|
+
} catch (err) {
|
|
20
|
+
if (err instanceof WorkflowAbort) throw err; // required
|
|
21
|
+
// handle real errors
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If you _must_ handle errors, move the `try/catch` into the function passed to `context.run`.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## requestPayload Becoming Undefined
|
|
30
|
+
|
|
31
|
+
During `context.call`, the workflow endpoint is invoked multiple times internally. Before the first step executes, `context.requestPayload` may appear `undefined`.
|
|
32
|
+
|
|
33
|
+
**Fix:** capture the payload via a step:
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
export const { POST } = serve(async (context) => {
|
|
37
|
+
const payload = await context.run("get-payload", () => context.requestPayload);
|
|
38
|
+
|
|
39
|
+
// payload remains stable even during context.call
|
|
40
|
+
await context.call("my-call", {
|
|
41
|
+
url: "https://example.com",
|
|
42
|
+
body: payload,
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Header considerations:** When triggering workflows, ensure payload‑friendly headers like:
|
|
48
|
+
|
|
49
|
+
- `Content-Type: text/plain`
|
|
50
|
+
- `Content-Type: application/json`
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Signature Verification Failures
|
|
55
|
+
|
|
56
|
+
If QStash request verification fails:
|
|
57
|
+
|
|
58
|
+
- Ensure the workflow is triggered through QStash (`client.trigger` or publish)
|
|
59
|
+
- Verify `QSTASH_CURRENT_SIGNING_KEY` and `QSTASH_NEXT_SIGNING_KEY`
|
|
60
|
+
- Pass appropriate `Content-Type` headers when triggering
|
|
61
|
+
|
|
62
|
+
Error looks like:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Failed to verify that the Workflow request comes from QStash: ...
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Authorization Errors from Early Returns
|
|
71
|
+
|
|
72
|
+
If your workflow returns **before running any step**, the SDK interprets this as failed authorization:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
HTTP 400 – Failed to authenticate Workflow request.
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
To safely perform non‑deterministic checks, wrap them in a step:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
export const { POST } = serve(async (context) => {
|
|
82
|
+
const shouldExit = await context.run("check-condition", () => Math.random() > 0.5);
|
|
83
|
+
if (shouldExit) return;
|
|
84
|
+
|
|
85
|
+
// remaining workflow
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Retry Configuration
|
|
92
|
+
|
|
93
|
+
Retries come from two locations:
|
|
94
|
+
|
|
95
|
+
- Workflow start (`client.trigger`): default **3**, applies to workflow steps
|
|
96
|
+
- `context.call`: default **0**
|
|
97
|
+
- `context.invoke`: default **0**
|
|
98
|
+
|
|
99
|
+
Use these in combination to tune behavior correctly.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Verbose Mode Diagnostics
|
|
104
|
+
|
|
105
|
+
Enable verbose logging to debug rare edge cases:
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
serve(handler, { verbose: true });
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Useful warnings include:
|
|
112
|
+
|
|
113
|
+
- Localhost in workflow URL
|
|
114
|
+
- Duplicate step execution
|
|
115
|
+
- Network response anomalies
|
|
116
|
+
- Parallel `context.call` race warnings
|
|
117
|
+
|
|
118
|
+
Each of these indicates environmental or routing issues rather than workflow logic problems.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## HTTPS Protocol Issues (Proxy Environments)
|
|
123
|
+
|
|
124
|
+
If deployed behind a proxy that downgrades HTTPS → HTTP (e.g., Railway), the SDK may infer the wrong protocol.
|
|
125
|
+
|
|
126
|
+
**Fix:** explicitly set:
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
UPSTASH_WORKFLOW_URL=https://your-deployment-url
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Workflow Stuck on First Step
|
|
135
|
+
|
|
136
|
+
If the first step appears stuck:
|
|
137
|
+
|
|
138
|
+
- Check step logs in the dashboard
|
|
139
|
+
- Ensure the endpoint URL is correct and reachable
|
|
140
|
+
- Verify SDK versions
|
|
141
|
+
- If inference is failing, explicitly set `baseUrl`:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
serve(handler, { baseUrl: "https://your-url" });
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Non‑workflow Destination Error
|
|
150
|
+
|
|
151
|
+
Occurs when triggering a non‑workflow endpoint or using mismatched SDK versions.
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
detected a non-workflow destination for trigger/invoke
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Ensure:**
|
|
158
|
+
|
|
159
|
+
- The URL points to a `serve()` workflow endpoint
|
|
160
|
+
- Both caller and workflow endpoint use the latest SDK
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Vercel Preview Deployment Protection
|
|
165
|
+
|
|
166
|
+
Preview deployments block external requests unless bypassed.
|
|
167
|
+
|
|
168
|
+
**Steps:**
|
|
169
|
+
|
|
170
|
+
1. Create a bypass secret in Vercel → Deployment Protection
|
|
171
|
+
2. Add it to the QStash client + pass it when triggering
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { Client as QStash } from "@upstash/qstash";
|
|
175
|
+
import { serve } from "@upstash/workflow/nextjs";
|
|
176
|
+
|
|
177
|
+
export const { POST } = serve(
|
|
178
|
+
async (context) => {
|
|
179
|
+
// workflow logic
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
qstashClient: new QStash({
|
|
183
|
+
token: process.env.QSTASH_TOKEN!,
|
|
184
|
+
headers: {
|
|
185
|
+
"x-vercel-protection-bypass": process.env.VERCEL_AUTOMATION_BYPASS_SECRET!,
|
|
186
|
+
},
|
|
187
|
+
}),
|
|
188
|
+
}
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// Triggering
|
|
192
|
+
await client.trigger({
|
|
193
|
+
url: "https://preview.vercel.app/workflow",
|
|
194
|
+
headers: {
|
|
195
|
+
"x-vercel-protection-bypass": process.env.VERCEL_AUTOMATION_BYPASS_SECRET!,
|
|
196
|
+
},
|
|
197
|
+
body: "hello",
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Both trigger header and client header are required.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upstash-box-js
|
|
3
|
+
description: Work with the @upstash/box TypeScript/JavaScript SDK for sandboxed cloud containers with AI agents, shell, filesystem, and git. Use when building with Upstash Box, creating sandboxed environments, running AI agents in containers, or orchestrating parallel boxes.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# @upstash/box SDK
|
|
7
|
+
|
|
8
|
+
Sandboxed cloud containers with built-in AI agents, shell, filesystem, and git.
|
|
9
|
+
|
|
10
|
+
## Install & Setup
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @upstash/box
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Set `UPSTASH_BOX_API_KEY` env var or pass `apiKey` to constructors.
|
|
17
|
+
|
|
18
|
+
## Box Lifecycle
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { Box, Agent, ClaudeCode, BoxApiKey } from "@upstash/box"
|
|
22
|
+
|
|
23
|
+
// Create with agent + git + env vars
|
|
24
|
+
const box = await Box.create({
|
|
25
|
+
runtime: "node", // "node" | "python" | "golang" | "ruby" | "rust"
|
|
26
|
+
agent: {
|
|
27
|
+
harness: Agent.ClaudeCode, // Agent.Codex | Agent.OpenCode
|
|
28
|
+
model: ClaudeCode.Sonnet_4_5,
|
|
29
|
+
// apiKey options:
|
|
30
|
+
// omit → server decides which key to use
|
|
31
|
+
// BoxApiKey.UpstashKey → use Upstash-provided LLM key
|
|
32
|
+
// BoxApiKey.StoredKey → use key previously stored via Upstash Console
|
|
33
|
+
// "sk-..." → direct API key string
|
|
34
|
+
apiKey: BoxApiKey.UpstashKey,
|
|
35
|
+
},
|
|
36
|
+
git: { // all fields optional
|
|
37
|
+
token: process.env.GITHUB_TOKEN, // alternatively link your GitHub account via Upstash Console
|
|
38
|
+
userName: "Bot",
|
|
39
|
+
userEmail: "bot@example.com",
|
|
40
|
+
},
|
|
41
|
+
env: { DATABASE_URL: "..." },
|
|
42
|
+
skills: ["upstash/qstash-js"], // GitHub repos as agent skills
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// Reconnect, list, delete, pause/resume
|
|
46
|
+
const same = await Box.get(box.id)
|
|
47
|
+
const all = await Box.list()
|
|
48
|
+
await box.pause()
|
|
49
|
+
await box.resume()
|
|
50
|
+
await box.delete() // irreversible
|
|
51
|
+
const { status } = await box.getStatus()
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Agent Runs
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { z } from "zod"
|
|
58
|
+
|
|
59
|
+
// Structured output with Zod schema
|
|
60
|
+
const run = await box.agent.run({
|
|
61
|
+
prompt: "Review the code for security issues",
|
|
62
|
+
responseSchema: z.object({
|
|
63
|
+
verdict: z.enum(["approved", "changes_requested"]),
|
|
64
|
+
findings: z.array(z.object({
|
|
65
|
+
severity: z.enum(["high", "medium", "low"]),
|
|
66
|
+
file: z.string(),
|
|
67
|
+
issue: z.string(),
|
|
68
|
+
})),
|
|
69
|
+
}),
|
|
70
|
+
timeout: 120_000,
|
|
71
|
+
maxRetries: 2,
|
|
72
|
+
onToolUse: (tool) => console.log(tool.name, tool.input),
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
run.status // "running" | "completed" | "failed" | "cancelled" | "detached"
|
|
76
|
+
run.result // typed from schema
|
|
77
|
+
run.cost // { inputTokens, outputTokens, computeMs, totalUsd }
|
|
78
|
+
|
|
79
|
+
// Streaming
|
|
80
|
+
const stream = await box.agent.stream({
|
|
81
|
+
prompt: "Build a REST API",
|
|
82
|
+
})
|
|
83
|
+
for await (const chunk of stream) { console.log(chunk) }
|
|
84
|
+
|
|
85
|
+
// Fire-and-forget with webhook
|
|
86
|
+
await box.agent.run({
|
|
87
|
+
prompt: "Run tests",
|
|
88
|
+
webhook: { url: "https://example.com/hook", headers: { Authorization: "Bearer ..." } },
|
|
89
|
+
})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Run Fields
|
|
93
|
+
|
|
94
|
+
Every `run` (agent, command, or code) returns a `Run<T>`:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
const run = await box.exec.command("npm test")
|
|
98
|
+
run.id // run ID
|
|
99
|
+
run.status // "completed" | "failed" | ...
|
|
100
|
+
run.result // string output (or typed T with responseSchema)
|
|
101
|
+
run.exitCode // number | null (null for agent runs)
|
|
102
|
+
run.cost // { inputTokens, outputTokens, computeMs, totalUsd }
|
|
103
|
+
|
|
104
|
+
await run.cancel() // cancel a running run
|
|
105
|
+
const logs = await run.logs() // [{ timestamp, level, message }]
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Shell Execution
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
// Run commands
|
|
112
|
+
const run = await box.exec.command("echo hello && ls -la")
|
|
113
|
+
|
|
114
|
+
// Run code snippets — lang: "js" | "ts" | "python"
|
|
115
|
+
const run2 = await box.exec.code({ code: "console.log(1+1)", lang: "js", timeout: 10_000 })
|
|
116
|
+
|
|
117
|
+
// Streaming shell
|
|
118
|
+
const stream = await box.exec.stream("npm run build")
|
|
119
|
+
for await (const chunk of stream) {
|
|
120
|
+
// chunk: { type: "output", data } | { type: "exit", exitCode, cpuNs }
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Filesystem
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
await box.files.write({ path: "/workspace/home/app.js", content: "console.log('hi')" })
|
|
128
|
+
const content = await box.files.read("/workspace/home/app.js")
|
|
129
|
+
const entries = await box.files.list("/workspace/home") // [{ name, path, size, is_dir, mod_time }]
|
|
130
|
+
|
|
131
|
+
// Binary files — use encoding: "base64" for read and write
|
|
132
|
+
await box.files.write({ path: "/workspace/home/image.png", content: base64String, encoding: "base64" })
|
|
133
|
+
const b64 = await box.files.read("/workspace/home/image.png", { encoding: "base64" })
|
|
134
|
+
|
|
135
|
+
// Upload local files, download box files
|
|
136
|
+
await box.files.upload([{ path: "./local/file.txt", destination: "/workspace/home/file.txt" }])
|
|
137
|
+
await box.files.download({ folder: "./output" })
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## cd / Working Directory
|
|
141
|
+
|
|
142
|
+
The SDK tracks `cwd` client-side. All operations (exec, files, git, agent) run relative to it.
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
box.cwd // current working directory (starts at /workspace/home)
|
|
146
|
+
await box.cd("my-repo") // relative to current cwd
|
|
147
|
+
await box.cd("/workspace/home/other") // absolute path
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Git
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
await box.git.clone({ repo: "github.com/org/repo", branch: "main" })
|
|
154
|
+
await box.cd("repo") // cd into cloned repo
|
|
155
|
+
|
|
156
|
+
const status = await box.git.status()
|
|
157
|
+
const diff = await box.git.diff()
|
|
158
|
+
const { sha } = await box.git.commit({ message: "fix: resolve bug" })
|
|
159
|
+
await box.git.push({ branch: "feature/fix" })
|
|
160
|
+
|
|
161
|
+
await box.git.checkout({ branch: "release/v2" })
|
|
162
|
+
const pr = await box.git.createPR({ title: "Fix bug", body: "...", base: "main" })
|
|
163
|
+
// pr: { url, number, title, base }
|
|
164
|
+
|
|
165
|
+
// Arbitrary git commands
|
|
166
|
+
const { output } = await box.git.exec({ args: ["log", "--oneline", "-5"] })
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Snapshots & Fork
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
// Snapshot — checkpoint workspace state
|
|
173
|
+
const snap = await box.snapshot({ name: "after-setup" })
|
|
174
|
+
// snap: { id, name, box_id, size_bytes, status, created_at }
|
|
175
|
+
|
|
176
|
+
const restored = await Box.fromSnapshot(snap.id)
|
|
177
|
+
const snaps = await box.listSnapshots()
|
|
178
|
+
await box.deleteSnapshot(snap.id)
|
|
179
|
+
|
|
180
|
+
// Fork — clone live state into a new box
|
|
181
|
+
const forked = await box.fork()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## EphemeralBox
|
|
185
|
+
|
|
186
|
+
Lightweight, short-lived boxes (max 3 days). No agent, git, snapshot, or fork. Supports exec, files, cd, and snapshots only.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { EphemeralBox } from "@upstash/box"
|
|
190
|
+
|
|
191
|
+
const ebox = await EphemeralBox.create({
|
|
192
|
+
runtime: "python",
|
|
193
|
+
ttl: 3600, // seconds, max 259200 (3 days)
|
|
194
|
+
env: { API_KEY: "..." },
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
ebox.expiresAt // unix timestamp when auto-deleted
|
|
198
|
+
await ebox.exec.command("python -c 'print(1+1)'")
|
|
199
|
+
await ebox.exec.code({ code: "print('hi')", lang: "python" })
|
|
200
|
+
await ebox.files.write({ path: "/workspace/home/data.json", content: "{}" })
|
|
201
|
+
await ebox.cd("subdir")
|
|
202
|
+
await ebox.delete()
|
|
203
|
+
|
|
204
|
+
// Restore from snapshot
|
|
205
|
+
const ebox2 = await EphemeralBox.fromSnapshot(snap.id, { ttl: 7200 })
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Public URLs
|
|
209
|
+
|
|
210
|
+
Expose box ports as public URLs with optional auth.
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
const publicURL = await box.getPublicURL(3000)
|
|
214
|
+
// publicURL: { url: "https://{id}-3000.preview.box.upstash.com", port }
|
|
215
|
+
|
|
216
|
+
const authed = await box.getPublicURL(3000, { bearerToken: true })
|
|
217
|
+
// authed: { url, port, token }
|
|
218
|
+
|
|
219
|
+
const basic = await box.getPublicURL(3000, { basicAuth: true })
|
|
220
|
+
// basic: { url, port, username, password }
|
|
221
|
+
|
|
222
|
+
const { publicURLs } = await box.listPublicURLs()
|
|
223
|
+
await box.deletePublicURL(3000)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## MCP Servers
|
|
227
|
+
|
|
228
|
+
Attach MCP servers to the box agent.
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
const box = await Box.create({
|
|
232
|
+
agent: { harness: Agent.ClaudeCode, model: ClaudeCode.Sonnet_4_5 },
|
|
233
|
+
mcpServers: [
|
|
234
|
+
{ name: "fs", package: "@modelcontextprotocol/server-filesystem" },
|
|
235
|
+
{ name: "custom", url: "https://mcp.example.com/sse", headers: { Authorization: "..." } },
|
|
236
|
+
],
|
|
237
|
+
})
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Gotchas
|
|
241
|
+
|
|
242
|
+
- Default working directory is `/workspace/home`, not `/home` or `/`
|
|
243
|
+
- `box.cd()` is client-side tracking — it validates the path exists but doesn't change the box's shell cwd. All SDK methods use it automatically.
|
|
244
|
+
- `EphemeralBox` does NOT support `agent`, `git`, `fork`, or public URLs — use full `Box` for those
|
|
245
|
+
- `run.exitCode` is `null` for agent runs, only available for exec commands
|
|
246
|
+
- `box.delete()` is irreversible — snapshot first if you need the state
|
|
247
|
+
- Git operations require `git.token` in `BoxConfig` for private repos and PRs
|
|
248
|
+
- `Box.fromSnapshot()` creates a new box — it does not modify the original
|