amsd-pipeline-workflow 0.1.5 → 0.1.6

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/driver/runtime.js CHANGED
@@ -127,6 +127,9 @@ function runLive(opts) {
127
127
  // transcripts by this id.
128
128
  const __session = { sessionId: out.session_id, modelUsage: out.modelUsage || {}, totalCostUsd: out.total_cost_usd };
129
129
  const res = typeof out.result === 'string' ? resultJson(out.result) : out.result;
130
+ // THE SESSION'S ANSWER, KEPT (the self-heal listener, tools/live-tracker.js): a stage ended by an agent error the gateway
131
+ // did not take must be visible in the run's own records — the driver logs only "failed".
132
+ try { fs.writeFileSync(path.join(opts.sessionDir, `${opts.name}.result.json`), `${JSON.stringify(res && typeof res === 'object' ? res : { status: 'failed', unreadable: String(out.result).slice(0, 2000) }, null, 2)}\n`); } catch { /* evidence only */ }
130
133
  if (!res || typeof res !== 'object') {
131
134
  return { status: 'failed', exit: 1, reason: `the ${opts.name} session's answer is not JSON: ${String(out.result).slice(0, 300)}`, __session };
132
135
  }
@@ -1,4 +1,5 @@
1
1
  'use strict';
2
+ const gateway = require('./gateway.js');
2
3
  // THE CODELINE, AGENTS WORKFLOW: plan (data) + emitted script (decisions 10, 15, 16, 25).
3
4
  //
4
5
  // The script holds the stage's ORDER — the pipeline's own: the launcher's reset (orchestrate.sh), the resume
@@ -27,7 +28,7 @@ function emit(plan) {
27
28
  // (an abort, the budget) still stops the run.
28
29
  async function agentOrNull(prompt, opts) {
29
30
  try { return await agent(prompt, opts) } catch (e) {
30
- if (!/without calling StructuredOutput/.test(String(e && e.message))) throw e
31
+ if (!${gateway.NO_ANSWER}.test(String(e && e.message))) throw e
31
32
  log(\`\${(opts && opts.label) || 'an agent'}: no StructuredOutput — taken as no answer\`)
32
33
  return null
33
34
  }
@@ -5,7 +5,13 @@
5
5
  // workflow's agentOrNull and log.
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
- const text = `\n${fs.readFileSync(path.join(__dirname, 'gateway.wf.js'), 'utf8')}`;
8
+ // AN ANSWER THE AGENT NEVER GAVE IN USABLE FORM — the Workflow tool's own errors for it: the agent ended without calling
9
+ // StructuredOutput; or it called it and its output never matched the schema (the tool's retry cap). Each is a failed call,
10
+ // as the pipeline takes it (no usable output); any other error (an abort, the budget) is not. Defined once, used by the
11
+ // gateway and by every template's agentOrNull. (LIVE-AMSD-2974-4b: the retry-cap error went unrecognised and took the
12
+ // Writer down.)
13
+ const NO_ANSWER = String.raw`/without calling StructuredOutput|StructuredOutput retry cap|does not match required schema/`;
14
+ const text = `\n${fs.readFileSync(path.join(__dirname, 'gateway.wf.js'), 'utf8')}`.split('__NO_ANSWER__').join(NO_ANSWER);
9
15
  const mailbox = `\n${fs.readFileSync(path.join(__dirname, 'mailbox.wf.js'), 'utf8')}`;
10
16
 
11
17
  /**
@@ -37,4 +43,4 @@ function messagesSetup({ defs, outDir, busDir, router, story, install, scripts }
37
43
  }
38
44
  return { router, bus: busDir, deliverySrc: require(lib).deliveryBlock.toString() };
39
45
  }
40
- module.exports = { text, textFor, messagesSetup };
46
+ module.exports = { text, textFor, messagesSetup, NO_ANSWER };
@@ -15,8 +15,10 @@ async function agentCall(prompt, opts) {
15
15
  for (; ; attempt++) {
16
16
  let a = null, why = ''
17
17
  try { a = await agent(p, { ...opts, ...(schema ? { schema } : {}), ...(model ? { model } : {}) }) } catch (e) {
18
- if (!/without calling StructuredOutput/.test(String(e && e.message))) throw e
19
- why = 'the agent ended without calling StructuredOutput — its answer was never submitted'
18
+ const msg = String(e && e.message)
19
+ if (!__NO_ANSWER__.test(msg)) throw e
20
+ why = /without calling StructuredOutput/.test(msg) ? 'the agent ended without calling StructuredOutput — its answer was never submitted'
21
+ : `the answer did not match its required format (${msg.replace(/^[\s\S]*?(StructuredOutput error: |does not match)/, '$1').slice(0, 400)}) — give the answer in exactly that format`
20
22
  }
21
23
  if (a !== null && a !== undefined) {
22
24
  if (mail.length) MAILBOX[who.agent] = []
@@ -21,7 +21,7 @@ function emit(plan) {
21
21
  // (an abort, the budget) still stops the run.
22
22
  async function agentOrNull(prompt, opts) {
23
23
  try { return await agent(prompt, opts) } catch (e) {
24
- if (!/without calling StructuredOutput/.test(String(e && e.message))) throw e
24
+ if (!${gateway.NO_ANSWER}.test(String(e && e.message))) throw e
25
25
  log(\`\${(opts && opts.label) || 'an agent'}: no StructuredOutput — taken as no answer\`)
26
26
  return null
27
27
  }
@@ -78,7 +78,7 @@ function emit(plan) {
78
78
  // (an abort, the budget) still stops the run.
79
79
  async function agentOrNull(prompt, opts) {
80
80
  try { return await agent(prompt, opts) } catch (e) {
81
- if (!/without calling StructuredOutput/.test(String(e && e.message))) throw e
81
+ if (!${gateway.NO_ANSWER}.test(String(e && e.message))) throw e
82
82
  log(\`\${(opts && opts.label) || 'an agent'}: no StructuredOutput — taken as no answer\`)
83
83
  return null
84
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "amsd-pipeline-workflow",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "The AMSD pipeline as Claude workflows. Installed by the amsd-pipeline installer: install.sh --workflows",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {