makaron-cli 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 +14 -2
- package/SKILL.md +14 -2
- package/bin/makaron.mjs +156 -6
- package/package.json +1 -1
- package/skills/makaron/SKILL.md +14 -2
package/README.md
CHANGED
|
@@ -141,15 +141,16 @@ For a new Agent, keep the default service flow to two response commands:
|
|
|
141
141
|
```bash
|
|
142
142
|
npx makaron-cli responses next <runId> --json
|
|
143
143
|
npx makaron-cli responses handle <messageId> --run <runId> --choice approve
|
|
144
|
+
npx makaron-cli responses deliver <artifactId> --run <runId> --channel feishu --message-id <messageId>
|
|
144
145
|
```
|
|
145
146
|
|
|
146
|
-
`responses next` emits a compact timeline, detects text-only checkpoints for creative/service work, and returns `next_commands` when the Agent must handle a Makaron message before waiting for artifacts. It exits with code `3` on an unhandled checkpoint so wrappers stop instead of silently waiting. After handling a checkpoint, run the returned `next_commands.inspect` command to continue. A non-checkpoint response returns `status: "ready"` or `status: "
|
|
147
|
+
`responses next` emits a compact timeline, detects text-only checkpoints for creative/service work, and returns `next_commands` when the Agent must handle a Makaron message before waiting for artifacts. It exits with code `3` on an unhandled checkpoint so wrappers stop instead of silently waiting. After handling a checkpoint, run the returned `next_commands.inspect` command to continue. While the run is still generating, it returns `status: "running"` and `blocking: false`. If completed image/video artifacts exist and have not been delivered, it returns `status: "has_artifacts"` and `blocking: true` with compact `undelivered_artifacts` entries containing `kind`, `status`, `url`, `fileName`, and `contentType` when available, plus `next_commands.deliver`; the Agent must send the artifact URL to the user, then record delivery with `responses deliver`. A non-checkpoint response returns `status: "ready"` or `status: "delivered"`. If a run failed, `responses next --json` prints `status: "failed"` and `blocking: true` plus `error.type`, `error.message`, `error.recoverable`, `error.detail`, and `next_command` to stdout before exiting `1`, so wrappers can parse the failure without scraping stderr. Use `--no-fail` to inspect checkpoint JSON without failing. For pure Q&A runs, use:
|
|
147
148
|
|
|
148
149
|
```bash
|
|
149
150
|
npx makaron-cli responses next <runId> --json --checkpoint-mode off
|
|
150
151
|
```
|
|
151
152
|
|
|
152
|
-
`responses handle` is the single checkpoint action command. Valid choices are `approve`, `revise`, `ask_user`, and `continue`.
|
|
153
|
+
`responses handle` is the single checkpoint action command. Valid choices are `approve`, `revise`, `ask_user`, and `continue`. `responses deliver` records that a completed artifact was actually delivered to the user, preventing repeated delivery prompts.
|
|
153
154
|
|
|
154
155
|
### Dialogue events for external Agents
|
|
155
156
|
|
|
@@ -338,9 +339,20 @@ if ! NEXT=$(npx makaron-cli responses next "$RUN_ID" --json); then
|
|
|
338
339
|
send_message "$TEXT"
|
|
339
340
|
npx makaron-cli responses handle "$MSG_ID" --run "$RUN_ID" --choice ask_user
|
|
340
341
|
exit 3
|
|
342
|
+
elif [ "$STATUS" = "failed" ]; then
|
|
343
|
+
send_message "$(echo "$NEXT" | jq -r .error.message)"
|
|
344
|
+
exit 1
|
|
341
345
|
fi
|
|
342
346
|
fi
|
|
343
347
|
|
|
348
|
+
NEXT=$(npx makaron-cli responses next "$RUN_ID" --json --no-fail)
|
|
349
|
+
if [ "$(echo "$NEXT" | jq -r .status)" = "has_artifacts" ]; then
|
|
350
|
+
ARTIFACT_ID=$(echo "$NEXT" | jq -r ".undelivered_artifacts[0].id")
|
|
351
|
+
ARTIFACT_URL=$(echo "$NEXT" | jq -r ".undelivered_artifacts[0].url")
|
|
352
|
+
DELIVERY_MESSAGE_ID=$(send_message "$ARTIFACT_URL")
|
|
353
|
+
npx makaron-cli responses deliver "$ARTIFACT_ID" --run "$RUN_ID" --channel feishu --message-id "$DELIVERY_MESSAGE_ID"
|
|
354
|
+
fi
|
|
355
|
+
|
|
344
356
|
RESULT=$(npx makaron-cli responses get "$RUN_ID" --wait --json)
|
|
345
357
|
```
|
|
346
358
|
|
package/SKILL.md
CHANGED
|
@@ -133,15 +133,16 @@ For a new Agent, keep the default service flow to two response commands:
|
|
|
133
133
|
```bash
|
|
134
134
|
npx makaron-cli responses next <runId> --json
|
|
135
135
|
npx makaron-cli responses handle <messageId> --run <runId> --choice approve
|
|
136
|
+
npx makaron-cli responses deliver <artifactId> --run <runId> --channel feishu --message-id <messageId>
|
|
136
137
|
```
|
|
137
138
|
|
|
138
|
-
`responses next` emits a compact timeline, detects text-only checkpoints for creative/service work, and returns `next_commands` when the Agent must handle a Makaron message before waiting for artifacts. It exits with code `3` on an unhandled checkpoint so wrappers stop instead of silently waiting. After handling a checkpoint, run the returned `next_commands.inspect` command to continue. A non-checkpoint response returns `status: "ready"` or `status: "
|
|
139
|
+
`responses next` emits a compact timeline, detects text-only checkpoints for creative/service work, and returns `next_commands` when the Agent must handle a Makaron message before waiting for artifacts. It exits with code `3` on an unhandled checkpoint so wrappers stop instead of silently waiting. After handling a checkpoint, run the returned `next_commands.inspect` command to continue. While the run is still generating, it returns `status: "running"` and `blocking: false`. If completed image/video artifacts exist and have not been delivered, it returns `status: "has_artifacts"` and `blocking: true` with compact `undelivered_artifacts` entries containing `kind`, `status`, `url`, `fileName`, and `contentType` when available, plus `next_commands.deliver`; the Agent must send the artifact URL to the user, then record delivery with `responses deliver`. A non-checkpoint response returns `status: "ready"` or `status: "delivered"`. If a run failed, `responses next --json` prints `status: "failed"` and `blocking: true` plus `error.type`, `error.message`, `error.recoverable`, `error.detail`, and `next_command` to stdout before exiting `1`, so wrappers can parse the failure without scraping stderr. Use `--no-fail` to inspect checkpoint JSON without failing. For pure Q&A runs, use:
|
|
139
140
|
|
|
140
141
|
```bash
|
|
141
142
|
npx makaron-cli responses next <runId> --json --checkpoint-mode off
|
|
142
143
|
```
|
|
143
144
|
|
|
144
|
-
`responses handle` is the single checkpoint action command. Valid choices are `approve`, `revise`, `ask_user`, and `continue`.
|
|
145
|
+
`responses handle` is the single checkpoint action command. Valid choices are `approve`, `revise`, `ask_user`, and `continue`. `responses deliver` records that a completed artifact was actually delivered to the user, preventing repeated delivery prompts.
|
|
145
146
|
|
|
146
147
|
### Dialogue events for external Agents
|
|
147
148
|
|
|
@@ -327,9 +328,20 @@ if ! NEXT=$(npx makaron-cli responses next "$RUN_ID" --json); then
|
|
|
327
328
|
send_message "$TEXT"
|
|
328
329
|
npx makaron-cli responses handle "$MSG_ID" --run "$RUN_ID" --choice ask_user
|
|
329
330
|
exit 3
|
|
331
|
+
elif [ "$STATUS" = "failed" ]; then
|
|
332
|
+
send_message "$(echo "$NEXT" | jq -r .error.message)"
|
|
333
|
+
exit 1
|
|
330
334
|
fi
|
|
331
335
|
fi
|
|
332
336
|
|
|
337
|
+
NEXT=$(npx makaron-cli responses next "$RUN_ID" --json --no-fail)
|
|
338
|
+
if [ "$(echo "$NEXT" | jq -r .status)" = "has_artifacts" ]; then
|
|
339
|
+
ARTIFACT_ID=$(echo "$NEXT" | jq -r ".undelivered_artifacts[0].id")
|
|
340
|
+
ARTIFACT_URL=$(echo "$NEXT" | jq -r ".undelivered_artifacts[0].url")
|
|
341
|
+
DELIVERY_MESSAGE_ID=$(send_message "$ARTIFACT_URL")
|
|
342
|
+
npx makaron-cli responses deliver "$ARTIFACT_ID" --run "$RUN_ID" --channel feishu --message-id "$DELIVERY_MESSAGE_ID"
|
|
343
|
+
fi
|
|
344
|
+
|
|
333
345
|
RESULT=$(npx makaron-cli responses get "$RUN_ID" --wait --json)
|
|
334
346
|
```
|
|
335
347
|
|
package/bin/makaron.mjs
CHANGED
|
@@ -20,6 +20,7 @@ import { execFileSync } from 'child_process';
|
|
|
20
20
|
|
|
21
21
|
const AUTH_FILE = path.join(process.env.HOME || '~', '.makaron', 'auth.json');
|
|
22
22
|
const APPROVALS_FILE = path.join(path.dirname(AUTH_FILE), 'approvals.json');
|
|
23
|
+
const DELIVERIES_FILE = path.join(path.dirname(AUTH_FILE), 'deliveries.json');
|
|
23
24
|
const DEFAULT_URL = 'https://www.makaron.app';
|
|
24
25
|
const BASE_URL = process.env.MAKARON_URL || DEFAULT_URL;
|
|
25
26
|
const APP_URL = process.env.MAKARON_APP_URL || DEFAULT_URL;
|
|
@@ -77,6 +78,20 @@ function saveApprovals(approvals) {
|
|
|
77
78
|
fs.writeFileSync(APPROVALS_FILE, JSON.stringify(approvals, null, 2));
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
function loadDeliveries() {
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(fs.readFileSync(DELIVERIES_FILE, 'utf-8'));
|
|
84
|
+
} catch {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function saveDeliveries(deliveries) {
|
|
90
|
+
const dir = path.dirname(DELIVERIES_FILE);
|
|
91
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
92
|
+
fs.writeFileSync(DELIVERIES_FILE, JSON.stringify(deliveries, null, 2));
|
|
93
|
+
}
|
|
94
|
+
|
|
80
95
|
function buildCookie(tokenJson) {
|
|
81
96
|
const url = tokenJson._supabaseUrl || SUPABASE_URL;
|
|
82
97
|
const ref = url.match(/\/\/([^.]+)\./)?.[1] || '';
|
|
@@ -498,6 +513,7 @@ function normalizeDialogueMessage(runId, projectId, ev, context = {}) {
|
|
|
498
513
|
const explicitApproval = hasExplicitApprovalRequirement(data, text);
|
|
499
514
|
const textOnlyCheckpoint = Boolean(
|
|
500
515
|
context.stoppedWithoutArtifacts
|
|
516
|
+
&& ev.type !== 'error'
|
|
501
517
|
&& !explicitApproval
|
|
502
518
|
&& !isPureStatusMessage(text, ev.type, data.status)
|
|
503
519
|
);
|
|
@@ -537,6 +553,10 @@ function normalizeDialogueArtifact(runId, projectId, item, seq) {
|
|
|
537
553
|
};
|
|
538
554
|
const url = item.url || item.imageUrl || item.videoUrl || item.audioUrl;
|
|
539
555
|
if (url) artifact.url = url;
|
|
556
|
+
const fileName = item.fileName || item.filename || item.name || (url ? url.split('/').pop()?.split('?')[0] : null);
|
|
557
|
+
const contentType = item.contentType || item.content_type || item.mimeType || item.mime_type;
|
|
558
|
+
if (fileName) artifact.fileName = fileName;
|
|
559
|
+
if (contentType) artifact.contentType = contentType;
|
|
540
560
|
if (item.error) artifact.error = item.error;
|
|
541
561
|
if (item.taskId) artifact.taskId = item.taskId;
|
|
542
562
|
if (item.snapshotId) artifact.snapshotId = item.snapshotId;
|
|
@@ -632,21 +652,84 @@ function findUnhandledApprovalMessages(events) {
|
|
|
632
652
|
return events.filter(ev => ev.type === 'message' && ev.requires_approval && !approved.has(ev.id));
|
|
633
653
|
}
|
|
634
654
|
|
|
655
|
+
function isCompletedDeliverableArtifact(artifact) {
|
|
656
|
+
return artifact?.type === 'artifact'
|
|
657
|
+
&& ['image', 'video', 'design', 'music', 'audio', 'file'].includes(artifact.kind)
|
|
658
|
+
&& artifact.status === 'completed'
|
|
659
|
+
&& Boolean(artifact.url);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
function findUndeliveredArtifacts(runId, events) {
|
|
663
|
+
const delivered = new Set(loadDeliveries().filter(item => item.runId === runId).map(item => item.artifactId || item.artifact_id));
|
|
664
|
+
return events.filter(isCompletedDeliverableArtifact).filter(artifact => !delivered.has(artifact.id));
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function buildCliCommand() {
|
|
668
|
+
return 'npx makaron-cli@latest';
|
|
669
|
+
}
|
|
670
|
+
|
|
635
671
|
function buildHandleCommand(messageId, runId, choice) {
|
|
636
|
-
return
|
|
672
|
+
return `${buildCliCommand()} responses handle ${messageId} --run ${runId} --choice ${choice}`;
|
|
637
673
|
}
|
|
638
674
|
|
|
639
675
|
function buildNextCommand(runId) {
|
|
640
|
-
return
|
|
676
|
+
return `${buildCliCommand()} responses next ${runId} --json`;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function buildDeliverCommand(artifactId, runId) {
|
|
680
|
+
return `${buildCliCommand()} responses deliver ${artifactId} --run ${runId}`;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
function buildRunError(data, events) {
|
|
684
|
+
const errorEvent = events.find(ev => ev.type === 'message' && ev.source_type === 'error') || null;
|
|
685
|
+
const resultError = data.result?.error || data.error || data.message || null;
|
|
686
|
+
if (!errorEvent && !resultError && !['failed', 'aborted'].includes(data.status)) return null;
|
|
687
|
+
const errorType = (typeof resultError === 'object' && (resultError.type || resultError.code)) || data.error_type || data.errorType || data.status || 'failed';
|
|
688
|
+
return {
|
|
689
|
+
type: errorType,
|
|
690
|
+
status: data.status || 'failed',
|
|
691
|
+
message: errorEvent?.text || (typeof resultError === 'string' ? resultError : resultError?.message) || `Makaron run ${data.status || 'failed'}`,
|
|
692
|
+
recoverable: Boolean((typeof resultError === 'object' && resultError.recoverable) || data.recoverable),
|
|
693
|
+
detail: typeof resultError === 'object' ? resultError : undefined,
|
|
694
|
+
};
|
|
641
695
|
}
|
|
642
696
|
|
|
643
|
-
function buildNextAction(runId, events) {
|
|
697
|
+
function buildNextAction(runId, events, data = {}) {
|
|
698
|
+
const runError = buildRunError(data, events);
|
|
699
|
+
if (runError) {
|
|
700
|
+
return {
|
|
701
|
+
status: 'failed',
|
|
702
|
+
blocking: true,
|
|
703
|
+
runId,
|
|
704
|
+
error: runError,
|
|
705
|
+
next_command: buildNextCommand(runId),
|
|
706
|
+
next_commands: {
|
|
707
|
+
inspect: buildNextCommand(runId),
|
|
708
|
+
},
|
|
709
|
+
events,
|
|
710
|
+
};
|
|
711
|
+
}
|
|
644
712
|
const checkpoint = findUnhandledApprovalMessages(events)[0] || null;
|
|
645
713
|
const artifacts = events.filter(ev => ev.type === 'artifact');
|
|
646
714
|
const approvals = events.filter(ev => ev.type === 'approval');
|
|
715
|
+
if (data.incomplete || ['queued', 'running', 'rendering', 'processing', 'generating', 'submitted'].includes(data.status)) {
|
|
716
|
+
return {
|
|
717
|
+
status: 'running',
|
|
718
|
+
blocking: false,
|
|
719
|
+
runId,
|
|
720
|
+
artifacts,
|
|
721
|
+
approvals,
|
|
722
|
+
next_command: buildNextCommand(runId),
|
|
723
|
+
next_commands: {
|
|
724
|
+
inspect: buildNextCommand(runId),
|
|
725
|
+
},
|
|
726
|
+
events,
|
|
727
|
+
};
|
|
728
|
+
}
|
|
647
729
|
if (checkpoint) {
|
|
648
730
|
return {
|
|
649
731
|
status: 'needs_approval',
|
|
732
|
+
blocking: true,
|
|
650
733
|
runId,
|
|
651
734
|
checkpoint,
|
|
652
735
|
next_commands: {
|
|
@@ -659,11 +742,30 @@ function buildNextAction(runId, events) {
|
|
|
659
742
|
events,
|
|
660
743
|
};
|
|
661
744
|
}
|
|
745
|
+
const undeliveredArtifacts = findUndeliveredArtifacts(runId, events);
|
|
746
|
+
if (undeliveredArtifacts.length) {
|
|
747
|
+
const first = undeliveredArtifacts[0];
|
|
748
|
+
return {
|
|
749
|
+
status: 'has_artifacts',
|
|
750
|
+
blocking: true,
|
|
751
|
+
runId,
|
|
752
|
+
artifacts,
|
|
753
|
+
undelivered_artifacts: undeliveredArtifacts,
|
|
754
|
+
approvals,
|
|
755
|
+
next_commands: {
|
|
756
|
+
deliver: buildDeliverCommand(first.id, runId),
|
|
757
|
+
inspect: buildNextCommand(runId),
|
|
758
|
+
},
|
|
759
|
+
events,
|
|
760
|
+
};
|
|
761
|
+
}
|
|
662
762
|
return {
|
|
663
|
-
status: artifacts.length ? '
|
|
763
|
+
status: artifacts.length ? 'delivered' : 'ready',
|
|
764
|
+
blocking: false,
|
|
664
765
|
runId,
|
|
665
766
|
artifacts,
|
|
666
767
|
approvals,
|
|
768
|
+
deliveries: loadDeliveries().filter(item => item.runId === runId),
|
|
667
769
|
next_commands: {
|
|
668
770
|
inspect: buildNextCommand(runId),
|
|
669
771
|
},
|
|
@@ -713,9 +815,12 @@ async function printAgentNext(baseUrl, headers, runId, opts = {}) {
|
|
|
713
815
|
const { json = false, checkpointMode = 'service', failOnCheckpoint = true } = opts;
|
|
714
816
|
const data = await fetchRun(baseUrl, headers, runId, { events: true });
|
|
715
817
|
const events = compactDialogueEvents(buildDialogueEvents(runId, { ...data, checkpointMode }));
|
|
716
|
-
const action = buildNextAction(runId, events);
|
|
818
|
+
const action = buildNextAction(runId, events, data);
|
|
717
819
|
if (json) {
|
|
718
820
|
console.log(JSON.stringify(action, null, 2));
|
|
821
|
+
} else if (action.status === 'failed') {
|
|
822
|
+
console.log(`failed: ${action.error?.message || 'Makaron run failed'}`);
|
|
823
|
+
console.log(`inspect: ${action.next_commands.inspect}`);
|
|
719
824
|
} else if (action.status === 'needs_approval') {
|
|
720
825
|
console.log(`needs_approval: ${action.checkpoint.id}`);
|
|
721
826
|
if (action.checkpoint.text) console.log(action.checkpoint.text);
|
|
@@ -725,14 +830,23 @@ async function printAgentNext(baseUrl, headers, runId, opts = {}) {
|
|
|
725
830
|
console.log(`continue: ${action.next_commands.continue}`);
|
|
726
831
|
console.log(`inspect: ${action.next_commands.inspect}`);
|
|
727
832
|
} else if (action.status === 'has_artifacts') {
|
|
728
|
-
for (const artifact of action.artifacts) {
|
|
833
|
+
for (const artifact of action.undelivered_artifacts || action.artifacts) {
|
|
729
834
|
console.log(`${artifact.kind} ${artifact.status}${artifact.url ? ` ${artifact.url}` : ''}`);
|
|
730
835
|
}
|
|
836
|
+
if (action.next_commands.deliver) console.log(`deliver: ${action.next_commands.deliver}`);
|
|
837
|
+
console.log(`inspect: ${action.next_commands.inspect}`);
|
|
838
|
+
} else if (action.status === 'running') {
|
|
839
|
+
console.log('running');
|
|
840
|
+
console.log(`inspect: ${action.next_commands.inspect}`);
|
|
841
|
+
} else if (action.status === 'delivered') {
|
|
842
|
+
console.log('delivered');
|
|
843
|
+
console.log(`inspect: ${action.next_commands.inspect}`);
|
|
731
844
|
} else {
|
|
732
845
|
console.log('ready');
|
|
733
846
|
console.log(`inspect: ${action.next_commands.inspect}`);
|
|
734
847
|
}
|
|
735
848
|
if (action.status === 'needs_approval' && failOnCheckpoint) process.exit(3);
|
|
849
|
+
if (action.status === 'failed') process.exit(1);
|
|
736
850
|
}
|
|
737
851
|
|
|
738
852
|
function recordApproval(runId, messageId, choice, note) {
|
|
@@ -752,6 +866,24 @@ function recordApproval(runId, messageId, choice, note) {
|
|
|
752
866
|
console.log(JSON.stringify(approval));
|
|
753
867
|
}
|
|
754
868
|
|
|
869
|
+
function recordDelivery(runId, artifactId, opts = {}) {
|
|
870
|
+
const deliveries = loadDeliveries();
|
|
871
|
+
const delivery = {
|
|
872
|
+
type: 'delivery',
|
|
873
|
+
id: `delivery_${Date.now()}`,
|
|
874
|
+
runId,
|
|
875
|
+
artifactId,
|
|
876
|
+
status: 'recorded',
|
|
877
|
+
createdAt: new Date().toISOString(),
|
|
878
|
+
};
|
|
879
|
+
if (opts.channel) delivery.channel = opts.channel;
|
|
880
|
+
if (opts.messageId) delivery.messageId = opts.messageId;
|
|
881
|
+
if (opts.note) delivery.note = opts.note;
|
|
882
|
+
deliveries.push(delivery);
|
|
883
|
+
saveDeliveries(deliveries);
|
|
884
|
+
console.log(JSON.stringify(delivery));
|
|
885
|
+
}
|
|
886
|
+
|
|
755
887
|
// ─── Watch (incremental event stream) ───────────────────────────────────────
|
|
756
888
|
|
|
757
889
|
async function watchRun(baseUrl, headers, runId, opts = {}) {
|
|
@@ -1419,6 +1551,22 @@ if (command === '--version' || command === '-v' || command === 'version') {
|
|
|
1419
1551
|
}
|
|
1420
1552
|
await printDialogueEvents(baseUrl, headers, runId, { interval, jsonl, follow, failOnUnapproved, compact, checkpointMode });
|
|
1421
1553
|
|
|
1554
|
+
} else if (sub === 'deliver') {
|
|
1555
|
+
const artifactId = args[2];
|
|
1556
|
+
if (!artifactId) { console.error('Usage: makaron responses deliver <artifactId> --run <runId> [--channel <name>] [--message-id <id>] [--note <text>]'); process.exit(1); }
|
|
1557
|
+
let runId = null, note = null, channel = null, messageId = null;
|
|
1558
|
+
const noteParts = [];
|
|
1559
|
+
for (let i = 3; i < args.length; i++) {
|
|
1560
|
+
if (args[i] === '--run' && args[i + 1]) runId = args[++i];
|
|
1561
|
+
else if (args[i] === '--note' && args[i + 1]) note = args[++i];
|
|
1562
|
+
else if (args[i] === '--channel' && args[i + 1]) channel = args[++i];
|
|
1563
|
+
else if (args[i] === '--message-id' && args[i + 1]) messageId = args[++i];
|
|
1564
|
+
else noteParts.push(args[i]);
|
|
1565
|
+
}
|
|
1566
|
+
if (!runId) { console.error('Usage: makaron responses deliver <artifactId> --run <runId> [--channel <name>] [--message-id <id>] [--note <text>]'); process.exit(1); }
|
|
1567
|
+
if (!note && noteParts.length) note = noteParts.join(' ');
|
|
1568
|
+
recordDelivery(runId, artifactId, { note, channel, messageId });
|
|
1569
|
+
|
|
1422
1570
|
} else if (sub === 'handle' || ['approve', 'revise', 'ask-user', 'continue'].includes(sub)) {
|
|
1423
1571
|
const messageId = args[2];
|
|
1424
1572
|
if (!messageId) {
|
|
@@ -1474,6 +1622,7 @@ if (command === '--version' || command === '-v' || command === 'version') {
|
|
|
1474
1622
|
responses get <runId> --pick <field> Extract: first_image_url, first_video_url, project_url, output
|
|
1475
1623
|
responses next <runId> --json New Agent entry: compact timeline + checkpoint guidance
|
|
1476
1624
|
responses handle <messageId> --run <runId> --choice approve|revise|ask_user|continue
|
|
1625
|
+
responses deliver <artifactId> --run <runId> Record artifact delivered to the user
|
|
1477
1626
|
responses events <runId> --jsonl Emit message/approval/artifact events for external Agents
|
|
1478
1627
|
responses timeline <runId> --jsonl Alias for responses events
|
|
1479
1628
|
responses timeline <runId> --checkpoint-mode off Disable text-only checkpoints for pure Q&A
|
|
@@ -1920,6 +2069,7 @@ Commands:
|
|
|
1920
2069
|
responses get <runId> --wait Poll until completed
|
|
1921
2070
|
responses next <runId> --json New Agent entry: compact timeline + checkpoint guidance
|
|
1922
2071
|
responses handle <messageId> --run <runId> --choice approve|revise|ask_user|continue
|
|
2072
|
+
responses deliver <artifactId> --run <runId> Record artifact delivered to the user
|
|
1923
2073
|
responses events <runId> --jsonl Emit message/approval/artifact events
|
|
1924
2074
|
responses timeline <runId> --checkpoint-mode off Disable text-only checkpoints for pure Q&A
|
|
1925
2075
|
responses list --project <id> List runs for a project
|
package/package.json
CHANGED
package/skills/makaron/SKILL.md
CHANGED
|
@@ -133,15 +133,16 @@ For a new Agent, keep the default service flow to two response commands:
|
|
|
133
133
|
```bash
|
|
134
134
|
npx makaron-cli responses next <runId> --json
|
|
135
135
|
npx makaron-cli responses handle <messageId> --run <runId> --choice approve
|
|
136
|
+
npx makaron-cli responses deliver <artifactId> --run <runId> --channel feishu --message-id <messageId>
|
|
136
137
|
```
|
|
137
138
|
|
|
138
|
-
`responses next` emits a compact timeline, detects text-only checkpoints for creative/service work, and returns `next_commands` when the Agent must handle a Makaron message before waiting for artifacts. It exits with code `3` on an unhandled checkpoint so wrappers stop instead of silently waiting. After handling a checkpoint, run the returned `next_commands.inspect` command to continue. A non-checkpoint response returns `status: "ready"` or `status: "
|
|
139
|
+
`responses next` emits a compact timeline, detects text-only checkpoints for creative/service work, and returns `next_commands` when the Agent must handle a Makaron message before waiting for artifacts. It exits with code `3` on an unhandled checkpoint so wrappers stop instead of silently waiting. After handling a checkpoint, run the returned `next_commands.inspect` command to continue. While the run is still generating, it returns `status: "running"` and `blocking: false`. If completed image/video artifacts exist and have not been delivered, it returns `status: "has_artifacts"` and `blocking: true` with compact `undelivered_artifacts` entries containing `kind`, `status`, `url`, `fileName`, and `contentType` when available, plus `next_commands.deliver`; the Agent must send the artifact URL to the user, then record delivery with `responses deliver`. A non-checkpoint response returns `status: "ready"` or `status: "delivered"`. If a run failed, `responses next --json` prints `status: "failed"` and `blocking: true` plus `error.type`, `error.message`, `error.recoverable`, `error.detail`, and `next_command` to stdout before exiting `1`, so wrappers can parse the failure without scraping stderr. Use `--no-fail` to inspect checkpoint JSON without failing. For pure Q&A runs, use:
|
|
139
140
|
|
|
140
141
|
```bash
|
|
141
142
|
npx makaron-cli responses next <runId> --json --checkpoint-mode off
|
|
142
143
|
```
|
|
143
144
|
|
|
144
|
-
`responses handle` is the single checkpoint action command. Valid choices are `approve`, `revise`, `ask_user`, and `continue`.
|
|
145
|
+
`responses handle` is the single checkpoint action command. Valid choices are `approve`, `revise`, `ask_user`, and `continue`. `responses deliver` records that a completed artifact was actually delivered to the user, preventing repeated delivery prompts.
|
|
145
146
|
|
|
146
147
|
### Dialogue events for external Agents
|
|
147
148
|
|
|
@@ -327,9 +328,20 @@ if ! NEXT=$(npx makaron-cli responses next "$RUN_ID" --json); then
|
|
|
327
328
|
send_message "$TEXT"
|
|
328
329
|
npx makaron-cli responses handle "$MSG_ID" --run "$RUN_ID" --choice ask_user
|
|
329
330
|
exit 3
|
|
331
|
+
elif [ "$STATUS" = "failed" ]; then
|
|
332
|
+
send_message "$(echo "$NEXT" | jq -r .error.message)"
|
|
333
|
+
exit 1
|
|
330
334
|
fi
|
|
331
335
|
fi
|
|
332
336
|
|
|
337
|
+
NEXT=$(npx makaron-cli responses next "$RUN_ID" --json --no-fail)
|
|
338
|
+
if [ "$(echo "$NEXT" | jq -r .status)" = "has_artifacts" ]; then
|
|
339
|
+
ARTIFACT_ID=$(echo "$NEXT" | jq -r ".undelivered_artifacts[0].id")
|
|
340
|
+
ARTIFACT_URL=$(echo "$NEXT" | jq -r ".undelivered_artifacts[0].url")
|
|
341
|
+
DELIVERY_MESSAGE_ID=$(send_message "$ARTIFACT_URL")
|
|
342
|
+
npx makaron-cli responses deliver "$ARTIFACT_ID" --run "$RUN_ID" --channel feishu --message-id "$DELIVERY_MESSAGE_ID"
|
|
343
|
+
fi
|
|
344
|
+
|
|
333
345
|
RESULT=$(npx makaron-cli responses get "$RUN_ID" --wait --json)
|
|
334
346
|
```
|
|
335
347
|
|