@volter/supercode-orchestrator 0.5.209 → 0.5.210
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/bin/orchestrator.mjs +1 -1
- package/board/event-stream.mjs +38 -4
- package/package.json +4 -3
package/bin/orchestrator.mjs
CHANGED
|
@@ -34,7 +34,7 @@ if (process.argv[2] === 'workflow') {
|
|
|
34
34
|
catch(error) {noteCommandError(error);process.stderr.write(`supercode workflow: ${error.message??error}\n${error?.errcode!=null&&error.stack?`${error.stack}\n`:''}`);code=1;}
|
|
35
35
|
// the board documents' git work this command queued (a ztrack board's commit and push) is finished before it exits
|
|
36
36
|
try{const{settleDocuments}=await import('../board/git-document.mjs');await settleDocuments();}catch{/* nothing queued */}
|
|
37
|
-
await Promise.all([process.stdout,process.stderr].map(stream=>new Promise(done=>stream.write('',done))));
|
|
37
|
+
await Promise.all([process.stdout,process.stderr].map(stream=>new Promise(done=>stream.destroyed?done():stream.write('',done))));
|
|
38
38
|
process.exit(code);
|
|
39
39
|
} else if (process.argv[2] === 'connect') {
|
|
40
40
|
const {parseArgs}=await import('node:util');
|
package/board/event-stream.mjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { watch, existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
|
|
4
4
|
import { dirname, basename, join, resolve } from 'node:path';
|
|
5
5
|
import { createHash } from 'node:crypto';
|
|
6
|
+
import { once } from 'node:events';
|
|
6
7
|
import { listBoards, openBoard, backingPaths } from './store.mjs';
|
|
7
8
|
|
|
8
9
|
const identity = root => createHash('sha256').update(realpathSync(root)).digest('hex');
|
|
@@ -117,14 +118,47 @@ export async function* followBoardPublications({root,after,signal}) {
|
|
|
117
118
|
|
|
118
119
|
export async function streamBoardPublications(options) {
|
|
119
120
|
if(options.once&&options.after)throw new Error('--once requires a fresh snapshot; omit --after');
|
|
121
|
+
const parent=process.ppid, reader=Number(process.env.SUPERCODE_WORKFLOW_READER_PID??parent);
|
|
122
|
+
if(!Number.isSafeInteger(reader)||reader<1||reader>2147483647)throw new Error('Invalid SUPERCODE_WORKFLOW_READER_PID');
|
|
120
123
|
const abort=new AbortController();const stop=()=>abort.abort();
|
|
124
|
+
let outputError=null;
|
|
125
|
+
const failed=error=>{outputError=error;stop();};
|
|
121
126
|
process.once('SIGINT',stop);process.once('SIGTERM',stop);
|
|
127
|
+
process.stdout.on('error',failed);process.stdout.once('close',stop);
|
|
128
|
+
// Quiet streams never meet EPIPE. The connector names the real reader across native/npm/home hand-offs; direct
|
|
129
|
+
// callers use their parent. Unix also detects reparenting (including death before this command finished starting).
|
|
130
|
+
// On Windows ppid does not change, but probing the named reader still detects its exit.
|
|
131
|
+
const checkReader=()=>{
|
|
132
|
+
if(process.platform!=='win32'&&(parent===1||process.ppid!==parent)){stop();return;}
|
|
133
|
+
try{process.kill(reader,0);}catch(error){if(error.code==='ESRCH')stop();}
|
|
134
|
+
};
|
|
135
|
+
const lifetime=setInterval(checkReader,1000);lifetime.unref();checkReader();
|
|
136
|
+
const write=async frame=>{
|
|
137
|
+
if(abort.signal.aborted)return;
|
|
138
|
+
try{
|
|
139
|
+
if(!process.stdout.write(`${JSON.stringify(frame)}\n`))await once(process.stdout,'drain',{signal:abort.signal});
|
|
140
|
+
}catch(error){
|
|
141
|
+
if(error.name==='AbortError'&&abort.signal.aborted)return;
|
|
142
|
+
if(error.code==='EPIPE'){stop();return;}
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
let code=0;
|
|
122
147
|
try {
|
|
123
148
|
for await(const frame of followBoardPublications({...options,signal:abort.signal})){
|
|
124
|
-
if(
|
|
149
|
+
if(abort.signal.aborted)break;
|
|
150
|
+
await write(frame);
|
|
151
|
+
if(abort.signal.aborted)break;
|
|
125
152
|
if(options.once&&frame.type==='snapshot_end')break;
|
|
126
153
|
}
|
|
127
|
-
}catch(error){if(error.code==='resync_required'){
|
|
128
|
-
finally{
|
|
129
|
-
|
|
154
|
+
}catch(error){if(error.code==='resync_required'){await write({type:'resync_required',reason:error.message});code=1;}else throw error;}
|
|
155
|
+
finally{
|
|
156
|
+
clearInterval(lifetime);process.removeListener('SIGINT',stop);process.removeListener('SIGTERM',stop);
|
|
157
|
+
// No final flush can drain into a dead or stalled reader. Returning the iterator above closes its board and
|
|
158
|
+
// watchers first; discard pending bytes on cancellation so the public entry can finish too.
|
|
159
|
+
if(abort.signal.aborted)process.stdout.destroy();
|
|
160
|
+
process.stdout.removeListener('error',failed);process.stdout.removeListener('close',stop);
|
|
161
|
+
}
|
|
162
|
+
if(outputError&&outputError.code!=='EPIPE')throw outputError;
|
|
163
|
+
return code;
|
|
130
164
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.210",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
|
|
6
6
|
"exports": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"check-types": "node scripts/generate-types.mjs --check"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@volter/supercode-teams": "^0.3.
|
|
35
|
+
"@volter/supercode-teams": "^0.3.346",
|
|
36
36
|
"@volter/supercode-terminal": "^0.3.10",
|
|
37
37
|
"@volter/supercode-harness-sdk": "^0.3.104",
|
|
38
38
|
"@volter/teams": "0.2.98",
|
|
@@ -61,5 +61,6 @@
|
|
|
61
61
|
"board",
|
|
62
62
|
"apply",
|
|
63
63
|
"README.md"
|
|
64
|
-
]
|
|
64
|
+
],
|
|
65
|
+
"gitHead": "b2585dc5c6b40d48be96fd3c4148f2c53d7a7ef2"
|
|
65
66
|
}
|