|
|
@@ -199,6 +199,65 @@ does - the branch name is just computed:
|
|
|
return { _activeBranch: 'case' + i, ['case' + i]: data };
|
|
|
```
|
|
|
|
|
|
+## Pausing for an Answer
|
|
|
+
|
|
|
+A node pauses its execution by returning a `_pause` marker, the way a branching
|
|
|
+node returns `_activeBranch`:
|
|
|
+
|
|
|
+```javascript
|
|
|
+return {
|
|
|
+ token: token,
|
|
|
+ reason: 'Approve the refund',
|
|
|
+ expiresAt: Date.now() + 86400000,
|
|
|
+ _pause: { token: token, reason: 'Approve the refund', expiresAt: expiresAt }
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+The engine stops the walk, stores the execution as `waiting` with everything
|
|
|
+computed so far, and returns. Nothing downstream runs. The marker is stripped
|
|
|
+from the stored output, so a reader sees the request rather than the mechanism.
|
|
|
+
|
|
|
+Answering it continues the run:
|
|
|
+
|
|
|
+```
|
|
|
+POST /api/v1/executions/{id}/resume
|
|
|
+{ "token": "...", "approved": true, "data": { "note": "looks fine" } }
|
|
|
+```
|
|
|
+
|
|
|
+The paused node's output becomes that payload, and the walk continues from
|
|
|
+there. Nodes that already ran are not run again. The workflow is rebuilt from
|
|
|
+the snapshot stored with the execution, not from the workflow as it stands now,
|
|
|
+because it may have been edited while the approval waited.
|
|
|
+
|
|
|
+`GET /api/v1/executions/pending` lists executions waiting for an answer. It
|
|
|
+deliberately omits the token: listing is a weaker permission than approving.
|
|
|
+
|
|
|
+Two limits are deliberate. A pause inside a Loop body cannot be resumed, because
|
|
|
+loop iteration state is not part of the stored execution, so a node must refuse
|
|
|
+to pause there rather than record something unanswerable. And a webhook cannot
|
|
|
+wait for an approval - the HTTP request is still open and its deadline is
|
|
|
+35 seconds - so a webhook-triggered workflow that pauses returns immediately
|
|
|
+with the execution id.
|
|
|
+
|
|
|
+## Answering a Webhook
|
|
|
+
|
|
|
+A webhook-triggered workflow returns the last node's output as JSON by default.
|
|
|
+To control the response, return a `_webhookResponse` marker from any node:
|
|
|
+
|
|
|
+```javascript
|
|
|
+return {
|
|
|
+ _webhookResponse: {
|
|
|
+ status: 201,
|
|
|
+ headers: { 'Content-Type': 'application/json' },
|
|
|
+ body: { id: created.id }
|
|
|
+ }
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+Any node may set it, not only the last one to run, so adding a node to the end
|
|
|
+of a workflow cannot silently change what its API returns. If several set it,
|
|
|
+the last one wins and the runner logs that it happened.
|
|
|
+
|
|
|
## Multiple Inputs
|
|
|
|
|
|
A node that joins two branches names its inputs:
|
|
|
@@ -354,6 +413,38 @@ smartbotic.storage.update('collection', 'document-id', { key: 'new-value' });
|
|
|
smartbotic.storage.delete('collection', 'document-id');
|
|
|
```
|
|
|
|
|
|
+### Filesystem
|
|
|
+
|
|
|
+```javascript
|
|
|
+// Read a file
|
|
|
+const read = smartbotic.fs.readFile('/tmp/example.txt', 'base64');
|
|
|
+// { success, data } - data is base64-encoded when the encoding argument is 'base64'
|
|
|
+
|
|
|
+// Write a file
|
|
|
+smartbotic.fs.writeFile('/tmp/example.txt', base64Data, 'base64');
|
|
|
+
|
|
|
+// Check existence
|
|
|
+const there = smartbotic.fs.exists('/tmp/example.txt');
|
|
|
+
|
|
|
+// Stat a file
|
|
|
+const info = smartbotic.fs.stat('/tmp/example.txt');
|
|
|
+// { success, size, mtime, isDirectory } - mtime is milliseconds since the epoch
|
|
|
+
|
|
|
+// Create a directory
|
|
|
+smartbotic.fs.mkdir('/tmp/example-dir');
|
|
|
+
|
|
|
+// Delete a file
|
|
|
+smartbotic.fs.unlink('/tmp/example.txt');
|
|
|
+
|
|
|
+// List a directory, one level
|
|
|
+const listing = smartbotic.fs.readdir('/var/spool/incoming');
|
|
|
+// { success: true, entries: [{ name, path, size, modifiedAt, isDirectory }] }
|
|
|
+```
|
|
|
+
|
|
|
+The `fs` API applies no path restrictions. Every call takes an arbitrary
|
|
|
+absolute path and acts on it with the runner process's own permissions, the
|
|
|
+same trust level a `code` node or `process.exec` already has.
|
|
|
+
|
|
|
### Credentials
|
|
|
|
|
|
```javascript
|