@jini-ai/cli 0.4.0 → 0.4.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/CHANGELOG.md +6 -0
- package/dist/run-command.js +17 -35
- package/package.json +19 -6
package/CHANGELOG.md
CHANGED
package/dist/run-command.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* line per event on stdout, stop at a terminal `'end'` event — a clean
|
|
20
20
|
* pattern that had no route to call until now).
|
|
21
21
|
*/
|
|
22
|
+
import { decodeSseFrames } from '@jini-ai/core/primitives';
|
|
22
23
|
import { parseFlags, positionalArgs } from './flags.js';
|
|
23
24
|
import { exitWithStructuredError, structuredHttpFailure } from './errors.js';
|
|
24
25
|
import { getJsonFromDaemon, postJsonToDaemon } from './http.js';
|
|
@@ -140,47 +141,28 @@ export async function runCancelCommand({ args, resolveBaseUrl: resolveBaseUrlPor
|
|
|
140
141
|
const result = await postJsonToDaemon({ base: baseUrl, route: `/api/runs/${encodeURIComponent(runId)}/cancel`, body }, transportOptions(deps));
|
|
141
142
|
printJsonResult(deps, result);
|
|
142
143
|
}
|
|
143
|
-
/** Cap on total buffered-but-not-yet-frame-terminated SSE
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
let id;
|
|
147
|
-
let eventName;
|
|
148
|
-
const dataLines = [];
|
|
149
|
-
for (const line of rawFrame.split('\n')) {
|
|
150
|
-
if (line.startsWith('id: '))
|
|
151
|
-
id = line.slice(4);
|
|
152
|
-
else if (line.startsWith('event: '))
|
|
153
|
-
eventName = line.slice(7);
|
|
154
|
-
else if (line.startsWith('data: '))
|
|
155
|
-
dataLines.push(line.slice(6));
|
|
156
|
-
}
|
|
157
|
-
if (dataLines.length === 0)
|
|
158
|
-
return null;
|
|
159
|
-
return { ...(id !== undefined ? { id } : {}), ...(eventName !== undefined ? { event: eventName } : {}), data: dataLines.join('\n') };
|
|
160
|
-
}
|
|
161
|
-
/** Reads `body` as an SSE byte stream and yields one {@link SseFrame} per blank-line-terminated frame. */
|
|
144
|
+
/** Cap on total buffered-but-not-yet-frame-terminated SSE text — a daemon that never sends a blank-line frame terminator must not grow this without bound (retains the historical 10 MiB-sized text cap; TextDecoder output is measured in UTF-16 units). */
|
|
145
|
+
const MAX_SSE_BUFFER_CHARS = 10 * 1024 * 1024;
|
|
146
|
+
/** Reads complete records; this adapter releases the lock without canceling the host's body. */
|
|
162
147
|
async function* readSseFrames(body) {
|
|
163
148
|
const reader = body.getReader();
|
|
164
|
-
|
|
165
|
-
let buffer = '';
|
|
166
|
-
try {
|
|
149
|
+
async function* chunks() {
|
|
167
150
|
for (;;) {
|
|
168
151
|
const { done, value } = await reader.read();
|
|
169
152
|
if (done)
|
|
170
|
-
|
|
153
|
+
return;
|
|
171
154
|
if (value !== undefined)
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
155
|
+
yield value;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
for await (const frame of decodeSseFrames({ source: chunks() }, {
|
|
160
|
+
flushFinalFrame: false, maxBufferChars: MAX_SSE_BUFFER_CHARS,
|
|
161
|
+
})) {
|
|
162
|
+
if (frame.dataLines.length === 0)
|
|
163
|
+
continue;
|
|
164
|
+
yield { ...(frame.id !== undefined ? { id: frame.id } : {}),
|
|
165
|
+
...(frame.event !== null ? { event: frame.event } : {}), data: frame.data };
|
|
184
166
|
}
|
|
185
167
|
}
|
|
186
168
|
finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jini-ai/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "CLI transport shell for driving a Jini daemon over HTTP: flag parsing, daemon-URL resolution, local daemon discovery, and a pluggable command registry.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -52,13 +52,26 @@
|
|
|
52
52
|
"access": "public",
|
|
53
53
|
"registry": "https://registry.npmjs.org"
|
|
54
54
|
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"commander": "^15.0.0",
|
|
57
|
+
"@jini-ai/core": "0.4.2",
|
|
58
|
+
"@jini-ai/sidecar": "0.4.1",
|
|
59
|
+
"@jini-ai/platform": "0.5.2"
|
|
60
|
+
},
|
|
55
61
|
"dependencies": {
|
|
56
|
-
"@jini-ai/core": "0.4.
|
|
57
|
-
"@jini-ai/platform": "0.5.0",
|
|
58
|
-
"@jini-ai/sidecar": "0.4.0"
|
|
62
|
+
"@jini-ai/core": "^0.4.2"
|
|
59
63
|
},
|
|
60
|
-
"
|
|
61
|
-
"
|
|
64
|
+
"peerDependencies": {
|
|
65
|
+
"@jini-ai/platform": "^0.5.1",
|
|
66
|
+
"@jini-ai/sidecar": "^0.4.0"
|
|
67
|
+
},
|
|
68
|
+
"peerDependenciesMeta": {
|
|
69
|
+
"@jini-ai/platform": {
|
|
70
|
+
"optional": true
|
|
71
|
+
},
|
|
72
|
+
"@jini-ai/sidecar": {
|
|
73
|
+
"optional": true
|
|
74
|
+
}
|
|
62
75
|
},
|
|
63
76
|
"scripts": {
|
|
64
77
|
"build": "tsc -p tsconfig.json && chmod +x dist/main.js",
|