makersclaw 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/package.json +1 -1
- package/r/activity-log.json +52 -0
- package/r/agent-changes.json +51 -0
- package/r/agent-chat.json +53 -0
- package/r/agent-column.json +85 -0
- package/r/agent-dock.json +57 -0
- package/r/agent-kit.json +49 -0
- package/r/agent-marks.json +49 -0
- package/r/agent-pane.json +93 -0
- package/r/ai-action.json +56 -0
- package/r/annotate.json +3 -3
- package/r/approval-request.json +2 -2
- package/r/approval.json +54 -0
- package/r/ask-bar.json +50 -0
- package/r/audio-player.json +2 -2
- package/r/auth-form.json +2 -2
- package/r/automation-editor.json +66 -0
- package/r/automation-list.json +57 -0
- package/r/automation-model.json +118 -0
- package/r/automations-screen.json +71 -0
- package/r/board.json +2 -2
- package/r/calendar-view.json +3 -3
- package/r/cart.json +2 -2
- package/r/chart.json +2 -2
- package/r/chat-pane.json +84 -0
- package/r/chat.json +2 -2
- package/r/code-editor.json +2 -2
- package/r/comment-box.json +3 -3
- package/r/connect-card.json +51 -0
- package/r/contact-section.json +2 -2
- package/r/core.json +13 -7
- package/r/cost.json +51 -0
- package/r/csv-import.json +3 -3
- package/r/data-picker.json +60 -0
- package/r/data-table.json +2 -2
- package/r/diagram.json +2 -2
- package/r/doc-editor.json +2 -2
- package/r/doc-page.json +3 -3
- package/r/email-render.json +2 -2
- package/r/faq.json +2 -2
- package/r/file-upload.json +2 -2
- package/r/first-run.json +63 -0
- package/r/fix-note.json +57 -0
- package/r/flow-canvas.json +2 -2
- package/r/flow-editor.json +79 -0
- package/r/footer.json +2 -2
- package/r/gantt.json +3 -3
- package/r/job-panel.json +2 -2
- package/r/json-editor.json +3 -3
- package/r/library-shelf.json +56 -0
- package/r/map.json +2 -2
- package/r/margin-notes.json +67 -0
- package/r/menubar.json +2 -2
- package/r/mind-map.json +3 -3
- package/r/navigation-menu.json +2 -2
- package/r/needs-you.json +55 -0
- package/r/order-detail.json +2 -2
- package/r/org-chart.json +3 -3
- package/r/pace-bar.json +69 -0
- package/r/page-builder.json +2 -2
- package/r/payment-methods.json +2 -2
- package/r/pdf-document.json +2 -2
- package/r/pdf-viewer.json +2 -2
- package/r/product-detail.json +2 -2
- package/r/product-grid.json +3 -3
- package/r/record-form.json +2 -2
- package/r/record-grid.json +52 -0
- package/r/record-notes.json +4 -4
- package/r/registry.json +4086 -1512
- package/r/run-history.json +52 -0
- package/r/run-view.json +80 -0
- package/r/schedule-card.json +54 -0
- package/r/schedule-engine.json +79 -0
- package/r/schedule-gantt.json +83 -0
- package/r/schedule-ruler.json +64 -0
- package/r/search-dialog.json +2 -2
- package/r/settings-list.json +2 -2
- package/r/setup-checklist.json +2 -2
- package/r/share-dialog.json +2 -2
- package/r/sidebar.json +2 -2
- package/r/signature-pad.json +2 -2
- package/r/sketch-canvas.json +2 -2
- package/r/source-receipt.json +52 -0
- package/r/spreadsheet.json +3 -3
- package/r/stat-cards.json +3 -3
- package/r/step-picker.json +53 -0
- package/r/step-settings.json +72 -0
- package/r/suggestion.json +58 -0
- package/r/sum-bar.json +64 -0
- package/r/task-list.json +3 -3
- package/r/task-model.json +2 -2
- package/r/testimonials.json +2 -2
- package/r/tier-map.json +67 -0
- package/r/time-grid.json +73 -0
- package/r/time-strip.json +64 -0
- package/r/top-bar.json +66 -0
- package/r/transaction-list.json +2 -2
- package/r/trigger-picker.json +61 -0
- package/r/whiteboard.json +3 -3
- package/r/workflow-view.json +55 -0
- package/registry/blocks/activity-log/README.md +112 -0
- package/registry/blocks/activity-log/activity-log.jsx +351 -0
- package/registry/blocks/activity-log/block.json +33 -0
- package/registry/blocks/activity-log/demo.jsx +48 -0
- package/registry/blocks/activity-log/index.js +4 -0
- package/registry/blocks/agent-changes/README.md +94 -0
- package/registry/blocks/agent-changes/agent-changes.jsx +118 -0
- package/registry/blocks/agent-changes/block.json +28 -0
- package/registry/blocks/agent-changes/demo.jsx +39 -0
- package/registry/blocks/agent-changes/index.js +3 -0
- package/registry/blocks/agent-chat/README.md +145 -0
- package/registry/blocks/agent-chat/agent-chat.jsx +415 -0
- package/registry/blocks/agent-chat/block.json +30 -0
- package/registry/blocks/agent-chat/demo.jsx +165 -0
- package/registry/blocks/agent-chat/index.js +3 -0
- package/registry/blocks/agent-column/README.md +197 -0
- package/registry/blocks/agent-column/agent-column.jsx +492 -0
- package/registry/blocks/agent-column/block.json +67 -0
- package/registry/blocks/agent-column/column-picker.jsx +163 -0
- package/registry/blocks/agent-column/demo.jsx +50 -0
- package/registry/blocks/agent-column/index.js +7 -0
- package/registry/blocks/agent-column/model.js +164 -0
- package/registry/blocks/agent-column/receipt.jsx +483 -0
- package/registry/blocks/agent-column/spreadsheet-type.jsx +24 -0
- package/registry/blocks/agent-dock/README.md +210 -0
- package/registry/blocks/agent-dock/agent-dock.jsx +356 -0
- package/registry/blocks/agent-dock/block.json +47 -0
- package/registry/blocks/agent-dock/demo.jsx +153 -0
- package/registry/blocks/agent-dock/dock-model.js +118 -0
- package/registry/blocks/agent-dock/index.js +5 -0
- package/registry/blocks/agent-kit/README.md +73 -0
- package/registry/blocks/agent-kit/agent-kit.jsx +86 -0
- package/registry/blocks/agent-kit/block.json +10 -0
- package/registry/blocks/agent-kit/demo.jsx +35 -0
- package/registry/blocks/agent-kit/index.js +3 -0
- package/registry/blocks/agent-marks/README.md +80 -0
- package/registry/blocks/agent-marks/agent-marks.jsx +133 -0
- package/registry/blocks/agent-marks/block.json +27 -0
- package/registry/blocks/agent-marks/demo.jsx +49 -0
- package/registry/blocks/agent-marks/index.js +3 -0
- package/registry/blocks/agent-pane/README.md +225 -0
- package/registry/blocks/agent-pane/agent-pane.jsx +244 -0
- package/registry/blocks/agent-pane/block.json +41 -0
- package/registry/blocks/agent-pane/composer.jsx +6 -0
- package/registry/blocks/agent-pane/demo.jsx +233 -0
- package/registry/blocks/agent-pane/dock-context.js +10 -0
- package/registry/blocks/agent-pane/index.js +4 -0
- package/registry/blocks/agent-pane/prose.jsx +84 -0
- package/registry/blocks/agent-pane/questions.jsx +134 -0
- package/registry/blocks/agent-pane/transcript.jsx +268 -0
- package/registry/blocks/agent-pane/work.jsx +368 -0
- package/registry/blocks/ai-action/README.md +94 -0
- package/registry/blocks/ai-action/ai-action.jsx +188 -0
- package/registry/blocks/ai-action/block.json +34 -0
- package/registry/blocks/ai-action/demo.jsx +93 -0
- package/registry/blocks/ai-action/index.js +3 -0
- package/registry/blocks/approval/README.md +145 -0
- package/registry/blocks/approval/approval.jsx +163 -0
- package/registry/blocks/approval/block.json +31 -0
- package/registry/blocks/approval/demo.jsx +121 -0
- package/registry/blocks/approval/index.js +3 -0
- package/registry/blocks/ask-bar/README.md +105 -0
- package/registry/blocks/ask-bar/ask-bar.jsx +166 -0
- package/registry/blocks/ask-bar/block.json +26 -0
- package/registry/blocks/ask-bar/demo.jsx +78 -0
- package/registry/blocks/ask-bar/index.js +3 -0
- package/registry/blocks/automation-editor/README.md +291 -0
- package/registry/blocks/automation-editor/automation-editor.jsx +656 -0
- package/registry/blocks/automation-editor/block.json +39 -0
- package/registry/blocks/automation-editor/demo.jsx +284 -0
- package/registry/blocks/automation-editor/index.js +4 -0
- package/registry/blocks/automation-editor/run-inputs.jsx +82 -0
- package/registry/blocks/automation-list/README.md +129 -0
- package/registry/blocks/automation-list/automation-list.jsx +476 -0
- package/registry/blocks/automation-list/block.json +35 -0
- package/registry/blocks/automation-list/demo.jsx +67 -0
- package/registry/blocks/automation-list/index.js +3 -0
- package/registry/blocks/automation-model/README.md +109 -0
- package/registry/blocks/automation-model/block.json +135 -0
- package/registry/blocks/automation-model/catalog.js +256 -0
- package/registry/blocks/automation-model/check.js +161 -0
- package/registry/blocks/automation-model/demo.jsx +42 -0
- package/registry/blocks/automation-model/edit.js +262 -0
- package/registry/blocks/automation-model/fixes.js +287 -0
- package/registry/blocks/automation-model/glyph.jsx +13 -0
- package/registry/blocks/automation-model/graph.js +410 -0
- package/registry/blocks/automation-model/index.js +33 -0
- package/registry/blocks/automation-model/overlay.js +175 -0
- package/registry/blocks/automation-model/parts.jsx +94 -0
- package/registry/blocks/automation-model/schedule.js +53 -0
- package/registry/blocks/automation-model/templates.js +128 -0
- package/registry/blocks/automation-model/values.js +29 -0
- package/registry/blocks/automation-model/words.js +439 -0
- package/registry/blocks/automations-screen/README.md +207 -0
- package/registry/blocks/automations-screen/automations-screen.jsx +452 -0
- package/registry/blocks/automations-screen/block.json +47 -0
- package/registry/blocks/automations-screen/demo.jsx +364 -0
- package/registry/blocks/automations-screen/index.js +4 -0
- package/registry/blocks/automations-screen/screen-model.js +129 -0
- package/registry/blocks/chat-pane/README.md +143 -0
- package/registry/blocks/chat-pane/block.json +48 -0
- package/registry/blocks/chat-pane/chat-attach.js +166 -0
- package/registry/blocks/chat-pane/chat-composer.jsx +195 -0
- package/registry/blocks/chat-pane/chat-context.js +17 -0
- package/registry/blocks/chat-pane/chat-model.js +43 -0
- package/registry/blocks/chat-pane/chat-pane.jsx +398 -0
- package/registry/blocks/chat-pane/chats-list.jsx +52 -0
- package/registry/blocks/chat-pane/demo.jsx +103 -0
- package/registry/blocks/chat-pane/index.js +9 -0
- package/registry/blocks/connect-card/README.md +99 -0
- package/registry/blocks/connect-card/block.json +10 -0
- package/registry/blocks/connect-card/connect-card.jsx +103 -0
- package/registry/blocks/connect-card/demo.jsx +49 -0
- package/registry/blocks/connect-card/index.js +3 -0
- package/registry/blocks/cost/README.md +115 -0
- package/registry/blocks/cost/block.json +10 -0
- package/registry/blocks/cost/cost.jsx +176 -0
- package/registry/blocks/cost/demo.jsx +66 -0
- package/registry/blocks/cost/index.js +3 -0
- package/registry/blocks/data-picker/README.md +81 -0
- package/registry/blocks/data-picker/block.json +38 -0
- package/registry/blocks/data-picker/data-picker.jsx +210 -0
- package/registry/blocks/data-picker/demo.jsx +34 -0
- package/registry/blocks/data-picker/fields.js +89 -0
- package/registry/blocks/data-picker/index.js +4 -0
- package/registry/blocks/data-table/demo.jsx +1 -1
- package/registry/blocks/first-run/README.md +118 -0
- package/registry/blocks/first-run/block.json +11 -0
- package/registry/blocks/first-run/demo.jsx +88 -0
- package/registry/blocks/first-run/first-run-model.js +51 -0
- package/registry/blocks/first-run/first-run.jsx +156 -0
- package/registry/blocks/first-run/index.js +5 -0
- package/registry/blocks/first-run/probe-rules.js +26 -0
- package/registry/blocks/fix-note/README.md +79 -0
- package/registry/blocks/fix-note/block.json +35 -0
- package/registry/blocks/fix-note/demo.jsx +30 -0
- package/registry/blocks/fix-note/fix-note.jsx +235 -0
- package/registry/blocks/fix-note/index.js +3 -0
- package/registry/blocks/flow-editor/README.md +108 -0
- package/registry/blocks/flow-editor/block.json +44 -0
- package/registry/blocks/flow-editor/demo.jsx +115 -0
- package/registry/blocks/flow-editor/flow-canvas.jsx +568 -0
- package/registry/blocks/flow-editor/flow-editor.jsx +154 -0
- package/registry/blocks/flow-editor/index.js +6 -0
- package/registry/blocks/flow-editor/minimap.jsx +78 -0
- package/registry/blocks/flow-editor/outline.jsx +134 -0
- package/registry/blocks/library-shelf/README.md +117 -0
- package/registry/blocks/library-shelf/block.json +28 -0
- package/registry/blocks/library-shelf/demo.jsx +68 -0
- package/registry/blocks/library-shelf/index.js +3 -0
- package/registry/blocks/library-shelf/library-shelf.jsx +211 -0
- package/registry/blocks/library-shelf/probe-rules.js +15 -0
- package/registry/blocks/margin-notes/README.md +222 -0
- package/registry/blocks/margin-notes/block.json +10 -0
- package/registry/blocks/margin-notes/demo.jsx +144 -0
- package/registry/blocks/margin-notes/index.js +20 -0
- package/registry/blocks/margin-notes/margin-model.js +224 -0
- package/registry/blocks/margin-notes/margin-notes.jsx +465 -0
- package/registry/blocks/needs-you/README.md +177 -0
- package/registry/blocks/needs-you/block.json +34 -0
- package/registry/blocks/needs-you/demo.jsx +143 -0
- package/registry/blocks/needs-you/index.js +3 -0
- package/registry/blocks/needs-you/needs-you.jsx +441 -0
- package/registry/blocks/pace-bar/README.md +230 -0
- package/registry/blocks/pace-bar/block.json +10 -0
- package/registry/blocks/pace-bar/demo.jsx +255 -0
- package/registry/blocks/pace-bar/index.js +22 -0
- package/registry/blocks/pace-bar/pace-bar.jsx +461 -0
- package/registry/blocks/pace-bar/pace-model.js +288 -0
- package/registry/blocks/record-grid/README.md +100 -0
- package/registry/blocks/record-grid/block.json +28 -0
- package/registry/blocks/record-grid/demo.jsx +43 -0
- package/registry/blocks/record-grid/index.js +3 -0
- package/registry/blocks/record-grid/record-grid.jsx +251 -0
- package/registry/blocks/run-history/README.md +138 -0
- package/registry/blocks/run-history/block.json +10 -0
- package/registry/blocks/run-history/demo.jsx +74 -0
- package/registry/blocks/run-history/index.js +3 -0
- package/registry/blocks/run-history/run-history.jsx +218 -0
- package/registry/blocks/run-view/README.md +174 -0
- package/registry/blocks/run-view/block.json +50 -0
- package/registry/blocks/run-view/demo.jsx +286 -0
- package/registry/blocks/run-view/index.js +5 -0
- package/registry/blocks/run-view/run-controls.jsx +266 -0
- package/registry/blocks/run-view/run-view.jsx +236 -0
- package/registry/blocks/run-view/runs-list.jsx +99 -0
- package/registry/blocks/schedule-card/README.md +121 -0
- package/registry/blocks/schedule-card/block.json +10 -0
- package/registry/blocks/schedule-card/demo.jsx +82 -0
- package/registry/blocks/schedule-card/index.js +3 -0
- package/registry/blocks/schedule-card/schedule-card.jsx +136 -0
- package/registry/blocks/schedule-engine/README.md +137 -0
- package/registry/blocks/schedule-engine/block.json +10 -0
- package/registry/blocks/schedule-engine/demo.jsx +82 -0
- package/registry/blocks/schedule-engine/engine.js +769 -0
- package/registry/blocks/schedule-engine/index.js +9 -0
- package/registry/blocks/schedule-engine/ops.js +71 -0
- package/registry/blocks/schedule-engine/place.js +294 -0
- package/registry/blocks/schedule-engine/tree.js +79 -0
- package/registry/blocks/schedule-engine/waits.js +80 -0
- package/registry/blocks/schedule-gantt/README.md +159 -0
- package/registry/blocks/schedule-gantt/block.json +10 -0
- package/registry/blocks/schedule-gantt/demo.jsx +223 -0
- package/registry/blocks/schedule-gantt/gantt-model.js +219 -0
- package/registry/blocks/schedule-gantt/geometry.js +176 -0
- package/registry/blocks/schedule-gantt/index.js +26 -0
- package/registry/blocks/schedule-gantt/schedule-gantt.jsx +882 -0
- package/registry/blocks/schedule-gantt/sheet.jsx +372 -0
- package/registry/blocks/schedule-gantt/track.jsx +190 -0
- package/registry/blocks/schedule-ruler/README.md +148 -0
- package/registry/blocks/schedule-ruler/block.json +10 -0
- package/registry/blocks/schedule-ruler/demo.jsx +181 -0
- package/registry/blocks/schedule-ruler/index.js +21 -0
- package/registry/blocks/schedule-ruler/ruler-model.js +239 -0
- package/registry/blocks/schedule-ruler/schedule-ruler.jsx +548 -0
- package/registry/blocks/source-receipt/README.md +97 -0
- package/registry/blocks/source-receipt/block.json +30 -0
- package/registry/blocks/source-receipt/demo.jsx +71 -0
- package/registry/blocks/source-receipt/index.js +3 -0
- package/registry/blocks/source-receipt/source-receipt.jsx +107 -0
- package/registry/blocks/spreadsheet/spreadsheet.jsx +15 -1
- package/registry/blocks/step-picker/README.md +78 -0
- package/registry/blocks/step-picker/block.json +31 -0
- package/registry/blocks/step-picker/demo.jsx +23 -0
- package/registry/blocks/step-picker/index.js +3 -0
- package/registry/blocks/step-picker/step-picker.jsx +144 -0
- package/registry/blocks/step-settings/README.md +100 -0
- package/registry/blocks/step-settings/block.json +44 -0
- package/registry/blocks/step-settings/demo.jsx +93 -0
- package/registry/blocks/step-settings/fields.jsx +58 -0
- package/registry/blocks/step-settings/flow-settings.jsx +115 -0
- package/registry/blocks/step-settings/index.js +5 -0
- package/registry/blocks/step-settings/step-settings.jsx +290 -0
- package/registry/blocks/suggestion/README.md +171 -0
- package/registry/blocks/suggestion/block.json +40 -0
- package/registry/blocks/suggestion/demo.jsx +91 -0
- package/registry/blocks/suggestion/index.js +3 -0
- package/registry/blocks/suggestion/suggestion.jsx +436 -0
- package/registry/blocks/sum-bar/README.md +122 -0
- package/registry/blocks/sum-bar/block.json +10 -0
- package/registry/blocks/sum-bar/demo.jsx +110 -0
- package/registry/blocks/sum-bar/index.js +5 -0
- package/registry/blocks/sum-bar/sum-bar.jsx +209 -0
- package/registry/blocks/sum-bar/sum-model.js +126 -0
- package/registry/blocks/tier-map/README.md +217 -0
- package/registry/blocks/tier-map/block.json +10 -0
- package/registry/blocks/tier-map/demo.jsx +222 -0
- package/registry/blocks/tier-map/index.js +24 -0
- package/registry/blocks/tier-map/tier-map.jsx +574 -0
- package/registry/blocks/tier-map/tier-model.js +318 -0
- package/registry/blocks/time-grid/README.md +305 -0
- package/registry/blocks/time-grid/block.json +10 -0
- package/registry/blocks/time-grid/demo.jsx +279 -0
- package/registry/blocks/time-grid/grid-model.js +322 -0
- package/registry/blocks/time-grid/index.js +25 -0
- package/registry/blocks/time-grid/time-grid.jsx +1325 -0
- package/registry/blocks/time-strip/README.md +141 -0
- package/registry/blocks/time-strip/block.json +10 -0
- package/registry/blocks/time-strip/demo.jsx +129 -0
- package/registry/blocks/time-strip/index.js +19 -0
- package/registry/blocks/time-strip/strip-model.js +178 -0
- package/registry/blocks/time-strip/time-strip.jsx +260 -0
- package/registry/blocks/top-bar/README.md +149 -0
- package/registry/blocks/top-bar/block.json +35 -0
- package/registry/blocks/top-bar/demo.jsx +78 -0
- package/registry/blocks/top-bar/index.js +5 -0
- package/registry/blocks/top-bar/probe-rules.js +74 -0
- package/registry/blocks/top-bar/top-bar-model.js +152 -0
- package/registry/blocks/top-bar/top-bar.jsx +244 -0
- package/registry/blocks/trigger-picker/README.md +98 -0
- package/registry/blocks/trigger-picker/block.json +38 -0
- package/registry/blocks/trigger-picker/demo.jsx +59 -0
- package/registry/blocks/trigger-picker/index.js +3 -0
- package/registry/blocks/trigger-picker/trigger-picker.jsx +374 -0
- package/registry/blocks/workflow-view/README.md +123 -0
- package/registry/blocks/workflow-view/block.json +10 -0
- package/registry/blocks/workflow-view/demo.jsx +90 -0
- package/registry/blocks/workflow-view/index.js +3 -0
- package/registry/blocks/workflow-view/workflow-view.jsx +203 -0
- package/src/install.mjs +77 -16
- package/src/registry.mjs +3 -0
- package/templates/next/browser/lib/data.js +6 -1
- package/templates/next/files/README.md +627 -24
- package/templates/next/files/check/automation-format.ts +2103 -0
- package/templates/next/files/check/automation-package.ts +142 -0
- package/templates/next/files/check/run.mjs +968 -9
- package/templates/next/files/components/ui/field.jsx +17 -4
- package/templates/next/files/components/ui/icon.jsx +13 -0
- package/templates/next/files/components/ui/index.js +2 -1
- package/templates/next/files/components/ui/layout.jsx +77 -2
- package/templates/next/files/components/ui/notice.jsx +70 -0
- package/templates/next/files/components/ui/page.jsx +124 -0
- package/templates/next/files/components/ui/stat.jsx +22 -7
- package/templates/next/files/components/ui/toast.jsx +6 -3
- package/templates/next/files/lib/automations.js +660 -0
- package/templates/next/files/lib/claw.js +241 -5
- package/templates/next/files/lib/door.js +92 -0
- package/templates/next/files/lib/hooks.js +1627 -8
- package/templates/next/files/lib/platform.js +529 -21
- package/templates/next/template.json +13 -3
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# AutomationModel
|
|
2
|
+
|
|
3
|
+
The pure part of the automation blocks. It has no screen of its own: it is
|
|
4
|
+
what `flow-editor`, `step-picker`, `step-settings`, `data-picker`,
|
|
5
|
+
`trigger-picker`, `automation-list`, `automation-editor` and `run-view`
|
|
6
|
+
all read, so a kind of step has one name, one face and one price flag
|
|
7
|
+
everywhere, and the canvas, the outline and a run say the same thing about
|
|
8
|
+
the same definition. It is laid with the blocks that need it; you place it
|
|
9
|
+
on its own only to build a screen of your own on automations.
|
|
10
|
+
|
|
11
|
+
```jsx
|
|
12
|
+
import { KINDS, layoutAutomation, triggerWords } from "../components/blocks/automation-model"; // a Makersclaw app
|
|
13
|
+
import { KINDS, layoutAutomation, triggerWords } from "@/components/makersclaw/blocks/automation-model"; // a shadcn project
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
An automation is the platform's format 1: a trigger and an ordered list of
|
|
17
|
+
steps. A condition has `then` and `else` lists, a loop has a `steps` list,
|
|
18
|
+
no arrows, no cycles. The platform checks every definition when it is
|
|
19
|
+
saved; this block only reads and dresses one.
|
|
20
|
+
|
|
21
|
+
## What is in it
|
|
22
|
+
|
|
23
|
+
- **The catalog** — `KINDS` (each kind's `name`, `blurb`, `glyph`, `tone`
|
|
24
|
+
plain · model · agent, `group`, `paid`), `paletteGroups()`,
|
|
25
|
+
`newStep(kind, takenIds)`, `stepTitle(step)`, `stepSub(step)`,
|
|
26
|
+
`RUNNABLE` (the kinds the platform runs today; a prop on the blocks
|
|
27
|
+
overrides it), `Glyph` (a kind's face, from the kit's icons).
|
|
28
|
+
- **The layout** — `layoutAutomation(def, { triggerWords, collapsed })` →
|
|
29
|
+
`{ nodes, edges, groups, bounds }`: boxes and curved connectors, left to
|
|
30
|
+
right, a branch's two paths one above the other that meet at a join, a
|
|
31
|
+
for-each as a dashed box or one card. Every connector carries its
|
|
32
|
+
`slot`, the place in the definition a step added there would land.
|
|
33
|
+
`curveBetween(a, b)`, `readingOrder(layout)`, `slotWords(slot)`.
|
|
34
|
+
- **The edits** — pure, the old definition never touched: `addStep`,
|
|
35
|
+
`insertStep`, `removeStep`, `updateStep`, `nudgeStep`, `duplicateStep`,
|
|
36
|
+
`findStep`, `locate`, `slotAfter`, `slotAtEnd`, `availableBefore(def,
|
|
37
|
+
id, stepTitle)` (what a step may read), `keyFromName`,
|
|
38
|
+
`blankAutomation`, `canonicalJson`.
|
|
39
|
+
- **A run** — `overlayOf(layout, stepRows, runStatus)` → how each card
|
|
40
|
+
went, which connectors were walked, which way each condition took it;
|
|
41
|
+
`summarizeSteps(rows)`. In a **test run** (a dry run: it reads real data
|
|
42
|
+
and changes nothing) a step that stood in for itself has the state
|
|
43
|
+
`would` (it would have run; it did not), ranked between `done` and
|
|
44
|
+
`fixed`. Each summary also carries `would` (the step's own words, "Would
|
|
45
|
+
send with send_email.", else "Would run.") and `unchecked` (it needs
|
|
46
|
+
what a would-step would have made, so it could not be checked).
|
|
47
|
+
- **Fixes and run controls** (`fixes.js`) — `draftOfStep(fixes, stepId)`
|
|
48
|
+
(the change the agent drafted for a step), `changeLines(patch, def)` (the
|
|
49
|
+
steps it would touch and what in them, by key, never a value),
|
|
50
|
+
`controlsOf(run, rows, { stepsVisible })` (which controls a run offers
|
|
51
|
+
right now), `retryFromOf(run, rows, def, stepId)` (whether "Retry from this
|
|
52
|
+
step" shows for a step, the top-level step it starts at, and whether to
|
|
53
|
+
ask first because something already sent; its words are `RETRY_FROM`), `fixTag(fix)` (the card's two words: "The agent fixed this",
|
|
54
|
+
or for a person's own edit "You changed its data"), and the words
|
|
55
|
+
`CONTROL_DONE` and `CONTROL_REFUSED`. For a screen that shares the draft
|
|
56
|
+
with the agent: `changeLinesBetween(before, after)` (what differs between
|
|
57
|
+
two definitions, one plain line each: how it starts, the name, a step
|
|
58
|
+
added, removed or changed, the settings; never a value),
|
|
59
|
+
`latestVersionOf({ versions, draftVersion, liveVersion })`,
|
|
60
|
+
`agentDraftOf({ versions, draftVersion, liveVersion })` (the draft, when the
|
|
61
|
+
agent wrote it and it is not live yet: `{ version, note }`) and
|
|
62
|
+
`newerVersionWords(version, versions)`. A step the AGENT fixed is `fixed`;
|
|
63
|
+
a person's own edit leaves the step `done`.
|
|
64
|
+
- **The words** — `triggerWords`, `cronWords`, `clockWords(iso, tz)` (a
|
|
65
|
+
time in the automation's own zone: a 07:00 schedule says 07:00 whoever
|
|
66
|
+
looks), `agoWords`, `durationWords`, `creditsWords`, `healthOf(row)`,
|
|
67
|
+
`runStatusWords(status, dry?)` (a test says Test passed, Test failed,
|
|
68
|
+
Test stopped), `nodeStateWords`, `wouldWords(row)`, `testWords(detail)`
|
|
69
|
+
(the one line a test run leaves: "Test passed: nothing was sent or
|
|
70
|
+
changed. 3 steps would have run."), `summaryOf(rows)`,
|
|
71
|
+
`overviewOf(runs)`, `priceMap(estimate)`.
|
|
72
|
+
- **The quick check** — `checkAutomation(def)` → `[{ path, message,
|
|
73
|
+
stepId }]`: the mistakes a person makes most (a blank action, an empty
|
|
74
|
+
branch, a step the platform cannot run yet), in words and by step. It
|
|
75
|
+
never says a definition is valid; only the platform does.
|
|
76
|
+
`issuesFromProblems(def, problems)` puts the platform's own refusal
|
|
77
|
+
lines on their steps.
|
|
78
|
+
- **The shared pieces** — `Chip`, `Dot`, `SidePanel`, `PanelSection`,
|
|
79
|
+
`RunPicker`; `STARTING_POINTS`, the ready-made flows the list offers;
|
|
80
|
+
`startsFromPlatform(starts)` turns the desk's own list (`useAutomations().starts`)
|
|
81
|
+
into the same shape plus `ai` and `price: { credits, per }`, each with a
|
|
82
|
+
`build(taken)` that returns a whole definition under a free key.
|
|
83
|
+
|
|
84
|
+
## Never
|
|
85
|
+
|
|
86
|
+
- Never a status by colour alone: each comes with its word.
|
|
87
|
+
- Never a time shown in the viewer's zone for a schedule: pass the
|
|
88
|
+
automation's `tz`.
|
|
89
|
+
- Never trust `checkAutomation` over the platform: a save the platform
|
|
90
|
+
refuses is the answer.
|
|
91
|
+
|
|
92
|
+
## Example
|
|
93
|
+
|
|
94
|
+
```jsx
|
|
95
|
+
"use client";
|
|
96
|
+
import { KINDS, layoutAutomation, triggerWords } from "../components/blocks/automation-model";
|
|
97
|
+
|
|
98
|
+
// How many cards a definition draws, and what starts it, in words.
|
|
99
|
+
export default function Summary({ definition }) {
|
|
100
|
+
const layout = layoutAutomation(definition, { triggerWords: triggerWords(definition.trigger) });
|
|
101
|
+
const cards = layout.nodes.filter((n) => n.type === "step" || n.type === "card");
|
|
102
|
+
return (
|
|
103
|
+
<p>
|
|
104
|
+
{definition.name}: {cards.length} steps, {triggerWords(definition.trigger).toLowerCase()}.{" "}
|
|
105
|
+
{cards.some((n) => KINDS[n.kind]?.paid) ? "Some steps cost credits." : "All steps are free."}
|
|
106
|
+
</p>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
```
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "automation-model",
|
|
3
|
+
"title": "AutomationModel",
|
|
4
|
+
"description": "The pure part of the automation blocks, with no screen of its own: the step catalog (each kind's name, face, group and price flag, a fresh step, a step's title and quiet line), the canvas layout (an automation turned into boxes, curved connectors with a slot for every +, labelled branches that rejoin, a for-each box), the edits (insert, remove, update, nudge, duplicate, what a step may read), what a run did (each node's state, the path taken), the words (a schedule in cron and in speech, a time in the automation's zone, a cost, a health, a run's outcome), a quick check of a definition, and the starting points. Glyph draws a kind's face from the kit's icons.",
|
|
5
|
+
"useWhen": "You are building your own screen on automations (flow-editor, step-settings, automation-list and run-view all do) and need the catalog, the words or the layout without a canvas. Rarely placed on its own: it is laid with the blocks that need it.",
|
|
6
|
+
"tags": [
|
|
7
|
+
"automation",
|
|
8
|
+
"workflow",
|
|
9
|
+
"steps",
|
|
10
|
+
"trigger",
|
|
11
|
+
"schedule",
|
|
12
|
+
"cron",
|
|
13
|
+
"catalog",
|
|
14
|
+
"layout",
|
|
15
|
+
"graph",
|
|
16
|
+
"words",
|
|
17
|
+
"model",
|
|
18
|
+
"runs"
|
|
19
|
+
],
|
|
20
|
+
"exports": [
|
|
21
|
+
"ACTIVE",
|
|
22
|
+
"GLYPH_ICON",
|
|
23
|
+
"GROUP_LABELS",
|
|
24
|
+
"GROUP_ORDER",
|
|
25
|
+
"Glyph",
|
|
26
|
+
"KINDS",
|
|
27
|
+
"LABEL_W",
|
|
28
|
+
"MARGIN",
|
|
29
|
+
"RUNNABLE",
|
|
30
|
+
"STARTING_POINTS",
|
|
31
|
+
"startsFromPlatform",
|
|
32
|
+
"testWords",
|
|
33
|
+
"wouldWords",
|
|
34
|
+
"T",
|
|
35
|
+
"WEEKDAYS",
|
|
36
|
+
"addStep",
|
|
37
|
+
"agoWords",
|
|
38
|
+
"allStepIds",
|
|
39
|
+
"availableBefore",
|
|
40
|
+
"blankAutomation",
|
|
41
|
+
"canonicalJson",
|
|
42
|
+
"checkAutomation",
|
|
43
|
+
"clockWords",
|
|
44
|
+
"creditsWords",
|
|
45
|
+
"deleteWords",
|
|
46
|
+
"cronFromParts",
|
|
47
|
+
"cronWords",
|
|
48
|
+
"curveBetween",
|
|
49
|
+
"duplicateStep",
|
|
50
|
+
"durationWords",
|
|
51
|
+
"findStep",
|
|
52
|
+
"flaggedSteps",
|
|
53
|
+
"formatCreditAmount",
|
|
54
|
+
"healthOf",
|
|
55
|
+
"humanize",
|
|
56
|
+
"innerCount",
|
|
57
|
+
"insertStep",
|
|
58
|
+
"isRunnable",
|
|
59
|
+
"issuesFor",
|
|
60
|
+
"issuesFromProblems",
|
|
61
|
+
"keyFromName",
|
|
62
|
+
"latestRows",
|
|
63
|
+
"layoutAutomation",
|
|
64
|
+
"locate",
|
|
65
|
+
"newStep",
|
|
66
|
+
"nodeIndex",
|
|
67
|
+
"nodeStateWords",
|
|
68
|
+
"nudgeStep",
|
|
69
|
+
"originWords",
|
|
70
|
+
"overlayOf",
|
|
71
|
+
"overviewOf",
|
|
72
|
+
"paletteGroups",
|
|
73
|
+
"parseTime",
|
|
74
|
+
"partsFromCron",
|
|
75
|
+
"plainWords",
|
|
76
|
+
"priceMap",
|
|
77
|
+
"readingOrder",
|
|
78
|
+
"removeStep",
|
|
79
|
+
"reportLines",
|
|
80
|
+
"runLine",
|
|
81
|
+
"runStatusWords",
|
|
82
|
+
"sameSlot",
|
|
83
|
+
"slotAfter",
|
|
84
|
+
"slotAtEnd",
|
|
85
|
+
"slotWords",
|
|
86
|
+
"stepIdForPath",
|
|
87
|
+
"stepSub",
|
|
88
|
+
"stepTitle",
|
|
89
|
+
"summaryOf",
|
|
90
|
+
"summarizeSteps",
|
|
91
|
+
"textToValue",
|
|
92
|
+
"timeText",
|
|
93
|
+
"triggerTypeWords",
|
|
94
|
+
"triggerWords",
|
|
95
|
+
"uniqueStepId",
|
|
96
|
+
"updateStep",
|
|
97
|
+
"valueToText",
|
|
98
|
+
"Chip",
|
|
99
|
+
"Dot",
|
|
100
|
+
"PanelSection",
|
|
101
|
+
"SidePanel",
|
|
102
|
+
"RunPicker",
|
|
103
|
+
"CONTROL_DONE",
|
|
104
|
+
"CONTROL_REFUSED",
|
|
105
|
+
"RETRY_FROM",
|
|
106
|
+
"agentDraftOf",
|
|
107
|
+
"changeLines",
|
|
108
|
+
"changeLinesBetween",
|
|
109
|
+
"controlsOf",
|
|
110
|
+
"draftOfStep",
|
|
111
|
+
"fixTag",
|
|
112
|
+
"latestVersionOf",
|
|
113
|
+
"newerVersionWords",
|
|
114
|
+
"retryFromOf",
|
|
115
|
+
"TRIGGER_TITLES",
|
|
116
|
+
"triggerGlyph",
|
|
117
|
+
"triggerTitle"
|
|
118
|
+
],
|
|
119
|
+
"files": [
|
|
120
|
+
"index.js",
|
|
121
|
+
"catalog.js",
|
|
122
|
+
"graph.js",
|
|
123
|
+
"edit.js",
|
|
124
|
+
"overlay.js",
|
|
125
|
+
"fixes.js",
|
|
126
|
+
"words.js",
|
|
127
|
+
"schedule.js",
|
|
128
|
+
"values.js",
|
|
129
|
+
"check.js",
|
|
130
|
+
"templates.js",
|
|
131
|
+
"glyph.jsx",
|
|
132
|
+
"parts.jsx"
|
|
133
|
+
],
|
|
134
|
+
"requires": []
|
|
135
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// The step catalog: what each kind of step is called, which icon wears it,
|
|
2
|
+
// where the picker files it, and what a fresh one looks like.
|
|
3
|
+
//
|
|
4
|
+
// Pure data and small functions; no React. The canvas, the picker, the
|
|
5
|
+
// outline and the settings panel all read this one table, so a kind has
|
|
6
|
+
// one name and one face everywhere. It mirrors the platform's automation
|
|
7
|
+
// format (format 1: a trigger and an ordered list of steps; a condition
|
|
8
|
+
// has `then` and `else`, a loop has `steps`); the platform validates a
|
|
9
|
+
// definition when it is saved, this file only dresses it.
|
|
10
|
+
|
|
11
|
+
/** A kind's face: a kit Icon name per glyph (glyph.jsx draws it). */
|
|
12
|
+
export const GLYPH_ICON = {
|
|
13
|
+
"trigger-schedule": "calendar-clock",
|
|
14
|
+
"trigger-manual": "hand",
|
|
15
|
+
"trigger-event": "send",
|
|
16
|
+
"trigger-action": "zap",
|
|
17
|
+
"trigger-record": "database",
|
|
18
|
+
"trigger-webhook": "globe",
|
|
19
|
+
"trigger-automation": "workflow",
|
|
20
|
+
"trigger-connection": "plug",
|
|
21
|
+
action: "zap",
|
|
22
|
+
brain: "book-open",
|
|
23
|
+
condition: "split",
|
|
24
|
+
loop: "repeat",
|
|
25
|
+
set: "braces",
|
|
26
|
+
wait: "timer",
|
|
27
|
+
stop: "square",
|
|
28
|
+
notify: "bell",
|
|
29
|
+
tool: "plug",
|
|
30
|
+
search: "search",
|
|
31
|
+
llm: "sparkles",
|
|
32
|
+
agent: "bot",
|
|
33
|
+
zero: "dollar",
|
|
34
|
+
automation: "workflow",
|
|
35
|
+
join: "circle",
|
|
36
|
+
plus: "plus",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** How each way of starting is named on the canvas, in the outline and at
|
|
40
|
+
* the top of its panel: one short title per trigger type. */
|
|
41
|
+
export const TRIGGER_TITLES = {
|
|
42
|
+
manual: "By hand",
|
|
43
|
+
schedule: "Schedule",
|
|
44
|
+
event: "Event",
|
|
45
|
+
action: "App action",
|
|
46
|
+
record: "Record",
|
|
47
|
+
webhook: "Web address",
|
|
48
|
+
automation: "After another",
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** The glyph of a trigger type (an unknown type wears the hand's). */
|
|
52
|
+
export function triggerGlyph(type) {
|
|
53
|
+
return Object.prototype.hasOwnProperty.call(TRIGGER_TITLES, type) ? `trigger-${type}` : "trigger-manual";
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** The title of a trigger type. */
|
|
57
|
+
export function triggerTitle(type) {
|
|
58
|
+
return TRIGGER_TITLES[type] ?? "By hand";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** The picker's groups, in the order it shows them. A step's tone (plain,
|
|
62
|
+
* model, agent) says how it is dressed: an agent step is solid in the AI
|
|
63
|
+
* hue, a model call carries a "model" mark in it, the rest are plain. */
|
|
64
|
+
export const GROUP_LABELS = {
|
|
65
|
+
app: "Your apps",
|
|
66
|
+
think: "Think",
|
|
67
|
+
flow: "Flow",
|
|
68
|
+
data: "Data",
|
|
69
|
+
tell: "Tell",
|
|
70
|
+
more: "More",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const GROUP_ORDER = ["app", "think", "flow", "data", "tell", "more"];
|
|
74
|
+
|
|
75
|
+
/** The kinds the platform knows, in format 1. */
|
|
76
|
+
export const KINDS = {
|
|
77
|
+
action: { kind: "action", name: "App action", blurb: "Do something in one of your apps: add people, save a draft, close a task.", glyph: "action", tone: "plain", group: "app", paid: false },
|
|
78
|
+
"brain.read": { kind: "brain.read", name: "Read the company brain", blurb: "Look up notes and records you can read.", glyph: "brain", tone: "plain", group: "data", paid: false },
|
|
79
|
+
condition: { kind: "condition", name: "Condition", blurb: "Go one way when something is true and another way when it is not.", glyph: "condition", tone: "plain", group: "flow", paid: false },
|
|
80
|
+
loop: { kind: "loop", name: "For each", blurb: "Do the same steps for every item in a list.", glyph: "loop", tone: "plain", group: "flow", paid: false },
|
|
81
|
+
set: { kind: "set", name: "Set values", blurb: "Build or reshape a value for the steps after it.", glyph: "set", tone: "plain", group: "data", paid: false },
|
|
82
|
+
wait: { kind: "wait", name: "Wait", blurb: "Pause for a while, or until a time. Nothing runs while it waits.", glyph: "wait", tone: "plain", group: "flow", paid: false },
|
|
83
|
+
stop: { kind: "stop", name: "Stop", blurb: "End the run here with a plain message.", glyph: "stop", tone: "plain", group: "flow", paid: false },
|
|
84
|
+
notify: { kind: "notify", name: "Tell someone", blurb: "Leave a line for the owner: a note in their Needs you.", glyph: "notify", tone: "plain", group: "tell", paid: false },
|
|
85
|
+
tool: { kind: "tool", name: "Connected tool", blurb: "Use one of your connected accounts: read mail, post a message, add a row.", glyph: "tool", tone: "plain", group: "app", paid: false },
|
|
86
|
+
search: { kind: "search", name: "Search the web", blurb: "Look something up on the web.", glyph: "search", tone: "plain", group: "data", paid: true },
|
|
87
|
+
llm: { kind: "llm", name: "Ask the model", blurb: "One model call: write a line, sort a list, pull facts out of text.", glyph: "llm", tone: "model", group: "think", paid: true, mark: "model" },
|
|
88
|
+
agent: { kind: "agent", name: "Agent", blurb: "Hand a job that needs judgment to the agent, with a limit on what it may spend.", glyph: "agent", tone: "agent", group: "think", paid: true, mark: "agent" },
|
|
89
|
+
zero: { kind: "zero", name: "Buy paid data", blurb: "Pay for one call to a paid data service, up to a price you set. Plain steps, and the same call is never paid for twice.", glyph: "zero", tone: "plain", group: "data", paid: true },
|
|
90
|
+
automation: { kind: "automation", name: "Another automation", blurb: "Run another automation and use what it makes.", glyph: "automation", tone: "plain", group: "more", paid: false },
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
/** The kinds the engine runs today. Anything else can be drawn and is
|
|
94
|
+
* saved only once the engine knows it (the platform refuses it until
|
|
95
|
+
* then). A platform that runs more says so in `runnable` (a prop). */
|
|
96
|
+
export const RUNNABLE = new Set(["action", "brain.read", "condition", "loop", "set", "wait", "stop", "notify", "tool", "search", "llm", "agent", "zero"]);
|
|
97
|
+
|
|
98
|
+
export const isRunnable = (kind, runnable = RUNNABLE) => runnable.has(kind);
|
|
99
|
+
|
|
100
|
+
const PALETTE_ORDER = ["action", "tool", "llm", "agent", "condition", "loop", "wait", "stop", "set", "brain.read", "search", "zero", "notify", "automation"];
|
|
101
|
+
|
|
102
|
+
/** Palette order: the groups, and in each group the kinds in a fixed order. */
|
|
103
|
+
export function paletteGroups() {
|
|
104
|
+
return GROUP_ORDER.map((group) => ({
|
|
105
|
+
group,
|
|
106
|
+
label: GROUP_LABELS[group],
|
|
107
|
+
kinds: PALETTE_ORDER.map((k) => KINDS[k]).filter((k) => k.group === group),
|
|
108
|
+
})).filter((g) => g.kinds.length > 0);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* ---- a fresh step ------------------------------------------------------ */
|
|
112
|
+
|
|
113
|
+
/** `brain.read` becomes `brain_read`: a step id's own alphabet. */
|
|
114
|
+
const idBase = (kind) => kind.replace(/[^a-z0-9]+/g, "_");
|
|
115
|
+
|
|
116
|
+
/** A step id no other step uses: `wait`, `wait_2`, `wait_3` … */
|
|
117
|
+
export function uniqueStepId(kind, taken) {
|
|
118
|
+
const base = idBase(kind);
|
|
119
|
+
if (!taken.has(base)) return base;
|
|
120
|
+
for (let n = 2; n < 1000; n += 1) {
|
|
121
|
+
const id = `${base}_${n}`;
|
|
122
|
+
if (!taken.has(id)) return id;
|
|
123
|
+
}
|
|
124
|
+
return `${base}_${taken.size + 1}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** A new step of a kind, with whatever default makes it read as itself.
|
|
128
|
+
* Some kinds cannot be valid until a person names something (an action,
|
|
129
|
+
* a tool): the settings panel asks for it, and the save waits. */
|
|
130
|
+
export function newStep(kind, taken) {
|
|
131
|
+
const id = uniqueStepId(kind, taken);
|
|
132
|
+
switch (kind) {
|
|
133
|
+
case "action":
|
|
134
|
+
return { id, kind, action: "", input: {} };
|
|
135
|
+
case "brain.read":
|
|
136
|
+
return { id, kind, op: "search", input: { query: "" } };
|
|
137
|
+
case "condition":
|
|
138
|
+
return { id, kind, if: "{{ true }}", then: [], else: [] };
|
|
139
|
+
case "loop":
|
|
140
|
+
return { id, kind, over: "{{ trigger.items }}", max: 100, steps: [] };
|
|
141
|
+
case "set":
|
|
142
|
+
return { id, kind, values: { value: "" } };
|
|
143
|
+
case "wait":
|
|
144
|
+
return { id, kind, for: "10m" };
|
|
145
|
+
case "stop":
|
|
146
|
+
return { id, kind, message: "Done" };
|
|
147
|
+
case "notify":
|
|
148
|
+
return { id, kind, message: "Something to look at" };
|
|
149
|
+
case "tool":
|
|
150
|
+
return { id, kind, needs: { category: "mail" }, tool: "", input: {} };
|
|
151
|
+
case "search":
|
|
152
|
+
return { id, kind, query: "", limit: 5 };
|
|
153
|
+
case "llm":
|
|
154
|
+
return { id, kind, prompt: "", tier: "fast" };
|
|
155
|
+
case "agent":
|
|
156
|
+
return { id, kind, instructions: "", cap_credits: 50 };
|
|
157
|
+
case "zero":
|
|
158
|
+
return { id, kind, capability: "", url: "https://", max_pay_usd: 0.05 };
|
|
159
|
+
case "automation":
|
|
160
|
+
return { id, kind, key: "", input: {} };
|
|
161
|
+
default:
|
|
162
|
+
return { id, kind };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* ---- words for a step on a card ---------------------------------------- */
|
|
167
|
+
|
|
168
|
+
const strip = (text) => String(text ?? "").replace(/\{\{\s*|\s*\}\}/g, "").replace(/\s+/g, " ").trim();
|
|
169
|
+
const cut = (text, n) => (text.length > n ? `${text.slice(0, n - 1).trimEnd()}…` : text);
|
|
170
|
+
|
|
171
|
+
/** `read_mail` becomes "Read mail". */
|
|
172
|
+
export function humanize(name) {
|
|
173
|
+
const s = String(name ?? "").replace(/[._-]+/g, " ").replace(/\s+/g, " ").trim();
|
|
174
|
+
return s ? s[0].toUpperCase() + s.slice(1) : "";
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** The card's title: the label the person gave it, else the kind's name
|
|
178
|
+
* with what it is about. Written in full; the card wraps it. */
|
|
179
|
+
export function stepTitle(step) {
|
|
180
|
+
if (step.label?.trim()) return step.label.trim();
|
|
181
|
+
switch (step.kind) {
|
|
182
|
+
case "action":
|
|
183
|
+
return step.action ? humanize(step.action) : "Pick an action";
|
|
184
|
+
case "tool":
|
|
185
|
+
return step.tool ? humanize(step.tool) : "Pick a tool";
|
|
186
|
+
case "condition":
|
|
187
|
+
return "Check a condition";
|
|
188
|
+
case "loop":
|
|
189
|
+
return "For each item";
|
|
190
|
+
case "brain.read":
|
|
191
|
+
return step.op === "get" ? "Read one record" : step.op === "list" ? "List records" : "Search the company brain";
|
|
192
|
+
case "set":
|
|
193
|
+
return "Set values";
|
|
194
|
+
case "wait":
|
|
195
|
+
return step.until ? "Wait until a time" : `Wait ${step.for ?? ""}`.trim();
|
|
196
|
+
case "stop":
|
|
197
|
+
return step.as === "failed" ? "Stop as failed" : "Stop";
|
|
198
|
+
case "notify":
|
|
199
|
+
return "Tell the owner";
|
|
200
|
+
case "search":
|
|
201
|
+
return "Search the web";
|
|
202
|
+
case "llm":
|
|
203
|
+
return "Ask the model";
|
|
204
|
+
case "agent":
|
|
205
|
+
return "Agent step";
|
|
206
|
+
case "zero":
|
|
207
|
+
return "Buy paid data";
|
|
208
|
+
case "automation":
|
|
209
|
+
return step.key ? `Run ${humanize(step.key)}` : "Run another automation";
|
|
210
|
+
default:
|
|
211
|
+
return humanize(step.kind);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** "api.example.com · up to $0.05": where it goes and the most it may pay. */
|
|
216
|
+
function zeroSub(step) {
|
|
217
|
+
const host = /^https:\/\/([^\s/{]+)/i.exec(String(step.url ?? "").trim())?.[1] ?? "";
|
|
218
|
+
const price = Number.isFinite(step.max_pay_usd) && step.max_pay_usd > 0 ? `up to $${Number(step.max_pay_usd).toString()}` : "";
|
|
219
|
+
return [host || "Needs an address", price].filter(Boolean).join(" · ");
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** The one quiet line under the title: "verb: object". */
|
|
223
|
+
export function stepSub(step) {
|
|
224
|
+
switch (step.kind) {
|
|
225
|
+
case "action":
|
|
226
|
+
return step.app ? `in ${humanize(step.app)}` : "App action";
|
|
227
|
+
case "tool":
|
|
228
|
+
return step.needs?.category ? `Using ${step.needs.category}` : "Connected tool";
|
|
229
|
+
case "condition":
|
|
230
|
+
return cut(strip(step.if), 52);
|
|
231
|
+
case "loop":
|
|
232
|
+
return cut(`over ${strip(step.over)}${step.max ? `, up to ${step.max}` : ""}`, 52);
|
|
233
|
+
case "brain.read":
|
|
234
|
+
return Object.keys(step.input ?? {}).length ? `with ${Object.keys(step.input).slice(0, 3).join(", ")}` : "Company brain";
|
|
235
|
+
case "set":
|
|
236
|
+
return `Sets ${Object.keys(step.values ?? {}).slice(0, 3).join(", ") || "values"}`;
|
|
237
|
+
case "wait":
|
|
238
|
+
return step.until ? cut(strip(step.until), 52) : "Nothing runs meanwhile";
|
|
239
|
+
case "stop":
|
|
240
|
+
return cut(strip(step.message), 52);
|
|
241
|
+
case "notify":
|
|
242
|
+
return cut(strip(step.message), 52);
|
|
243
|
+
case "search":
|
|
244
|
+
return cut(strip(step.query) || "Web search", 52);
|
|
245
|
+
case "llm":
|
|
246
|
+
return step.tier === "smart" ? "Careful model" : "Quick model";
|
|
247
|
+
case "agent":
|
|
248
|
+
return cut(strip(step.instructions) || "Needs instructions", 52);
|
|
249
|
+
case "zero":
|
|
250
|
+
return cut(zeroSub(step), 52);
|
|
251
|
+
case "automation":
|
|
252
|
+
return "Another automation";
|
|
253
|
+
default:
|
|
254
|
+
return "";
|
|
255
|
+
}
|
|
256
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// What is wrong with a definition, before the platform is asked.
|
|
2
|
+
//
|
|
3
|
+
// The platform validates every definition when it is saved (one validator,
|
|
4
|
+
// whatever wrote the definition); a refusal comes back with `problems`,
|
|
5
|
+
// one line each, and the builder shows those too. This file is the quick
|
|
6
|
+
// check a screen makes on every edit, so a card can wear a red mark and
|
|
7
|
+
// the Save button can say why it waits: the mistakes a person makes most,
|
|
8
|
+
// in the words a person uses. It never says a definition is valid; only
|
|
9
|
+
// the platform does.
|
|
10
|
+
|
|
11
|
+
import { KINDS, RUNNABLE } from "./catalog";
|
|
12
|
+
import { stepIdForPath } from "./edit";
|
|
13
|
+
|
|
14
|
+
/** Words for the paths a person never sees spelled out. */
|
|
15
|
+
function plainPath(path) {
|
|
16
|
+
if (!path) return "";
|
|
17
|
+
if (path.startsWith("trigger")) return "The trigger";
|
|
18
|
+
if (path.startsWith("settings")) return "The settings";
|
|
19
|
+
if (path.startsWith("inputs")) return "A question";
|
|
20
|
+
if (path.startsWith("name")) return "The name";
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** The platform's own wording for the mistakes a person makes most, in the
|
|
25
|
+
* words a person uses. Anything not listed passes through as written. */
|
|
26
|
+
export function plainWords(message) {
|
|
27
|
+
if (/^a condition needs steps in then, else or both/.test(message)) return "Add a step to the Yes or the No path, with the + on it.";
|
|
28
|
+
if (/^a loop has steps/.test(message)) return "Add a step inside the box, with the + on it.";
|
|
29
|
+
if (/^steps is a list with at least one step/.test(message)) return "Add a first step to save it.";
|
|
30
|
+
const unavailable = /^([a-z.]+) steps are not available yet/.exec(message);
|
|
31
|
+
if (unavailable) {
|
|
32
|
+
const info = KINDS[unavailable[1]];
|
|
33
|
+
return `${info?.name ?? unavailable[1]} steps cannot run yet. You can draw one, and save it once they can.`;
|
|
34
|
+
}
|
|
35
|
+
return message;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const blank = (v) => typeof v !== "string" || v.trim() === "";
|
|
39
|
+
|
|
40
|
+
/** The most one Zero step may pay for a call, in USD: the platform's own ceiling
|
|
41
|
+
* (claw shared/src/automation.ts ZERO_STEP_MAX_PAY_USD; keep the two equal). */
|
|
42
|
+
const ZERO_MAX_PAY_USD = 2;
|
|
43
|
+
|
|
44
|
+
/** One step's own problems: [{ path, message }]. */
|
|
45
|
+
function stepProblems(step, path, runnable) {
|
|
46
|
+
const out = [];
|
|
47
|
+
const bad = (field, message) => out.push({ path: `${path}.${field}`, message });
|
|
48
|
+
if (!KINDS[step.kind]) {
|
|
49
|
+
out.push({ path, message: `${step.kind} is not a kind of step this editor knows.` });
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
if (!runnable.has(step.kind)) out.push({ path, message: `${step.kind} steps are not available yet.` });
|
|
53
|
+
switch (step.kind) {
|
|
54
|
+
case "action":
|
|
55
|
+
if (blank(step.action)) bad("action", "Pick the action to run.");
|
|
56
|
+
break;
|
|
57
|
+
case "tool":
|
|
58
|
+
if (blank(step.tool)) bad("tool", "Pick the tool to use.");
|
|
59
|
+
if (blank(step.needs?.category)) bad("needs", "Say what kind of account it uses.");
|
|
60
|
+
break;
|
|
61
|
+
case "condition":
|
|
62
|
+
if (blank(step.if)) bad("if", "Say when it goes the Yes way.");
|
|
63
|
+
if ((step.then ?? []).length + (step.else ?? []).length === 0) out.push({ path, message: "a condition needs steps in then, else or both." });
|
|
64
|
+
break;
|
|
65
|
+
case "loop":
|
|
66
|
+
if (blank(step.over)) bad("over", "Say which list to go through.");
|
|
67
|
+
if ((step.steps ?? []).length === 0) out.push({ path, message: "a loop has steps to repeat." });
|
|
68
|
+
break;
|
|
69
|
+
case "llm":
|
|
70
|
+
if (blank(step.prompt)) bad("prompt", "Say what to ask the model.");
|
|
71
|
+
break;
|
|
72
|
+
case "agent":
|
|
73
|
+
if (blank(step.instructions)) bad("instructions", "Tell the agent what to do.");
|
|
74
|
+
break;
|
|
75
|
+
case "search":
|
|
76
|
+
if (blank(step.query)) bad("query", "Say what to search for.");
|
|
77
|
+
break;
|
|
78
|
+
case "zero":
|
|
79
|
+
// A paid call needs the service, its address and a price it may not pass.
|
|
80
|
+
if (blank(step.capability)) bad("capability", "Say which paid service it uses.");
|
|
81
|
+
if (blank(step.url) || (!/^https:\/\/[^\s/]+/i.test(step.url.trim()) && !step.url.trimStart().startsWith("{{"))) bad("url", "Give the service's address, starting with https://.");
|
|
82
|
+
if (!(typeof step.max_pay_usd === "number" && Number.isFinite(step.max_pay_usd) && step.max_pay_usd > 0 && step.max_pay_usd <= ZERO_MAX_PAY_USD)) bad("max_pay_usd", `Set the most one call may cost: more than $0, and at most $${ZERO_MAX_PAY_USD}.`);
|
|
83
|
+
break;
|
|
84
|
+
case "stop":
|
|
85
|
+
case "notify":
|
|
86
|
+
if (blank(step.message)) bad("message", "Write the message.");
|
|
87
|
+
break;
|
|
88
|
+
case "wait":
|
|
89
|
+
if (blank(step.for) && blank(step.until)) bad("for", "Say how long to wait, or until when.");
|
|
90
|
+
break;
|
|
91
|
+
case "automation":
|
|
92
|
+
if (blank(step.key)) bad("key", "Say which automation to run.");
|
|
93
|
+
break;
|
|
94
|
+
default:
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/** Every step's problems, depth first, with the path the platform would
|
|
101
|
+
* name (`steps[2].then[0].input`). */
|
|
102
|
+
function walk(list, base, runnable, seen, out) {
|
|
103
|
+
list.forEach((step, i) => {
|
|
104
|
+
const path = `${base}[${i}]`;
|
|
105
|
+
if (seen.has(step.id)) out.push({ path, message: `the step id ${step.id} is used twice.` });
|
|
106
|
+
seen.add(step.id);
|
|
107
|
+
out.push(...stepProblems(step, path, runnable));
|
|
108
|
+
if (step.kind === "condition") {
|
|
109
|
+
walk(step.then ?? [], `${path}.then`, runnable, seen, out);
|
|
110
|
+
walk(step.else ?? [], `${path}.else`, runnable, seen, out);
|
|
111
|
+
} else if (step.kind === "loop") walk(step.steps ?? [], `${path}.steps`, runnable, seen, out);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* checkAutomation(def, { runnable })
|
|
117
|
+
* → [{ path, message, stepId }]
|
|
118
|
+
* `message` is for a person; `stepId` is the step it is about (null for
|
|
119
|
+
* the flow or its trigger). An empty canvas is not an error, only not
|
|
120
|
+
* finished, but it cannot be saved: the first problem says so.
|
|
121
|
+
*/
|
|
122
|
+
export function checkAutomation(def, { runnable = RUNNABLE } = {}) {
|
|
123
|
+
const raw = [];
|
|
124
|
+
if (blank(def.name)) raw.push({ path: "name", message: "Give it a name." });
|
|
125
|
+
const trigger = def.trigger ?? {};
|
|
126
|
+
if (trigger.type === "schedule" && String(trigger.cron ?? "").trim().split(/\s+/).length !== 5) {
|
|
127
|
+
raw.push({ path: "trigger.cron", message: "Use five fields: minute, hour, day, month, weekday." });
|
|
128
|
+
}
|
|
129
|
+
if (trigger.type === "event" && blank(trigger.topic)) raw.push({ path: "trigger.topic", message: "Say which event starts it." });
|
|
130
|
+
if (trigger.type === "action" && blank(trigger.action)) raw.push({ path: "trigger.action", message: "Pick the action it waits for." });
|
|
131
|
+
if (trigger.type === "automation" && blank(trigger.key)) raw.push({ path: "trigger.key", message: "Pick the automation it follows." });
|
|
132
|
+
if ((def.steps ?? []).length === 0) raw.push({ path: "steps", message: "steps is a list with at least one step." });
|
|
133
|
+
walk(def.steps ?? [], "steps", runnable, new Set(), raw);
|
|
134
|
+
return raw.map((p) => {
|
|
135
|
+
const said = plainWords(p.message);
|
|
136
|
+
const stepId = stepIdForPath(def, p.path);
|
|
137
|
+
// A blank canvas is not a mistake, only not finished.
|
|
138
|
+
const who = p.path === "steps" ? "" : stepId ? `“${stepId}”` : plainPath(p.path);
|
|
139
|
+
return { path: p.path, message: who ? `${who}: ${said}` : said, stepId };
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Turn the platform's refusal lines (`problems`) into the same shape. */
|
|
144
|
+
export function issuesFromProblems(def, problems) {
|
|
145
|
+
return (problems ?? []).map((line) => {
|
|
146
|
+
const m = /^([\w[\].]+):\s*(.*)$/.exec(line);
|
|
147
|
+
const path = m ? m[1] : "";
|
|
148
|
+
const stepId = path ? stepIdForPath(def, path) : null;
|
|
149
|
+
return { path, message: plainWords(m ? m[2] : line), stepId };
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** The steps with something wrong, for the red marks. */
|
|
154
|
+
export function flaggedSteps(issues) {
|
|
155
|
+
return new Set(issues.map((i) => i.stepId).filter(Boolean));
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** The lines to show in one step's own panel. */
|
|
159
|
+
export function issuesFor(issues, stepId) {
|
|
160
|
+
return issues.filter((i) => i.stepId === stepId).map((i) => i.message.replace(/^“[^”]*”: /, ""));
|
|
161
|
+
}
|