@pixelbyte-software/pixcode 1.33.3 → 1.33.4

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.
@@ -1,92 +1,92 @@
1
- // OpenCode Response Handler — `opencode run --format json` parser.
2
- //
3
- // The JSON format streams one event per line (NDJSON). Event shapes follow
4
- // the OpenAPI contract exposed by `opencode serve`. We treat the stream
5
- // permissively: lines that don't parse as JSON are passed through as plain
6
- // text deltas (covers OpenCode's pre-stream banner output and any debug
7
- // noise the CLI emits to stdout).
8
- import { sessionsService } from './modules/providers/services/sessions.service.js';
9
-
10
- class OpencodeResponseHandler {
11
- constructor(ws, options = {}) {
12
- this.ws = ws;
13
- this.buffer = '';
14
- this.onContentFragment = options.onContentFragment || null;
15
- this.onInit = options.onInit || null;
16
- this.onToolUse = options.onToolUse || null;
17
- this.onToolResult = options.onToolResult || null;
18
- }
19
-
20
- processData(data) {
21
- this.buffer += data;
22
-
23
- const lines = this.buffer.split('\n');
24
- this.buffer = lines.pop() || '';
25
-
26
- for (const line of lines) {
27
- const trimmed = line.trim();
28
- if (!trimmed) continue;
29
- try {
30
- const event = JSON.parse(trimmed);
31
- this.handleEvent(event);
32
- } catch {
33
- // Non-JSON line — surface as plain text delta so the user sees CLI
34
- // banners / status messages instead of swallowing them silently.
35
- if (this.onContentFragment) this.onContentFragment(trimmed + '\n');
36
- }
37
- }
38
- }
39
-
40
- handleEvent(event) {
41
- const sid = typeof this.ws.getSessionId === 'function' ? this.ws.getSessionId() : null;
42
-
43
- if (event.type === 'init' || event.type === 'session.start') {
44
- if (this.onInit) this.onInit(event);
45
- return;
46
- }
47
-
48
- // OpenCode emits both `message` events and `part` events that compose
49
- // a single assistant turn. We handle whichever shape lands.
50
- if (event.type === 'message' && event.role === 'assistant') {
51
- const content = event.content || event.text || '';
52
- if (this.onContentFragment && content) this.onContentFragment(content);
53
- } else if (event.type === 'part' && event.part_type === 'text') {
54
- const content = event.text || event.content || '';
55
- if (this.onContentFragment && content) this.onContentFragment(content);
56
- } else if (event.type === 'tool_use' || event.type === 'tool-use' || event.type === 'tool.start') {
57
- if (this.onToolUse) this.onToolUse({
58
- tool_id: event.tool_id || event.id,
59
- tool_name: event.tool_name || event.name,
60
- parameters: event.parameters || event.input || {},
61
- });
62
- } else if (event.type === 'tool_result' || event.type === 'tool-result' || event.type === 'tool.end') {
63
- if (this.onToolResult) this.onToolResult({
64
- tool_id: event.tool_id || event.id,
65
- output: event.output ?? event.result ?? '',
66
- status: event.status || (event.isError ? 'error' : 'ok'),
67
- });
68
- }
69
-
70
- const normalized = sessionsService.normalizeMessage('opencode', event, sid);
71
- for (const msg of normalized) {
72
- this.ws.send(msg);
73
- }
74
- }
75
-
76
- forceFlush() {
77
- if (this.buffer.trim()) {
78
- try {
79
- const event = JSON.parse(this.buffer);
80
- this.handleEvent(event);
81
- } catch {
82
- if (this.onContentFragment) this.onContentFragment(this.buffer);
83
- }
84
- }
85
- }
86
-
87
- destroy() {
88
- this.buffer = '';
89
- }
90
- }
91
-
92
- export default OpencodeResponseHandler;
1
+ // OpenCode Response Handler — `opencode run --format json` parser.
2
+ //
3
+ // The JSON format streams one event per line (NDJSON). Event shapes follow
4
+ // the OpenAPI contract exposed by `opencode serve`. We treat the stream
5
+ // permissively: lines that don't parse as JSON are passed through as plain
6
+ // text deltas (covers OpenCode's pre-stream banner output and any debug
7
+ // noise the CLI emits to stdout).
8
+ import { sessionsService } from './modules/providers/services/sessions.service.js';
9
+
10
+ class OpencodeResponseHandler {
11
+ constructor(ws, options = {}) {
12
+ this.ws = ws;
13
+ this.buffer = '';
14
+ this.onContentFragment = options.onContentFragment || null;
15
+ this.onInit = options.onInit || null;
16
+ this.onToolUse = options.onToolUse || null;
17
+ this.onToolResult = options.onToolResult || null;
18
+ }
19
+
20
+ processData(data) {
21
+ this.buffer += data;
22
+
23
+ const lines = this.buffer.split('\n');
24
+ this.buffer = lines.pop() || '';
25
+
26
+ for (const line of lines) {
27
+ const trimmed = line.trim();
28
+ if (!trimmed) continue;
29
+ try {
30
+ const event = JSON.parse(trimmed);
31
+ this.handleEvent(event);
32
+ } catch {
33
+ // Non-JSON line — surface as plain text delta so the user sees CLI
34
+ // banners / status messages instead of swallowing them silently.
35
+ if (this.onContentFragment) this.onContentFragment(trimmed + '\n');
36
+ }
37
+ }
38
+ }
39
+
40
+ handleEvent(event) {
41
+ const sid = typeof this.ws.getSessionId === 'function' ? this.ws.getSessionId() : null;
42
+
43
+ if (event.type === 'init' || event.type === 'session.start') {
44
+ if (this.onInit) this.onInit(event);
45
+ return;
46
+ }
47
+
48
+ // OpenCode emits both `message` events and `part` events that compose
49
+ // a single assistant turn. We handle whichever shape lands.
50
+ if (event.type === 'message' && event.role === 'assistant') {
51
+ const content = event.content || event.text || '';
52
+ if (this.onContentFragment && content) this.onContentFragment(content);
53
+ } else if (event.type === 'part' && event.part_type === 'text') {
54
+ const content = event.text || event.content || '';
55
+ if (this.onContentFragment && content) this.onContentFragment(content);
56
+ } else if (event.type === 'tool_use' || event.type === 'tool-use' || event.type === 'tool.start') {
57
+ if (this.onToolUse) this.onToolUse({
58
+ tool_id: event.tool_id || event.id,
59
+ tool_name: event.tool_name || event.name,
60
+ parameters: event.parameters || event.input || {},
61
+ });
62
+ } else if (event.type === 'tool_result' || event.type === 'tool-result' || event.type === 'tool.end') {
63
+ if (this.onToolResult) this.onToolResult({
64
+ tool_id: event.tool_id || event.id,
65
+ output: event.output ?? event.result ?? '',
66
+ status: event.status || (event.isError ? 'error' : 'ok'),
67
+ });
68
+ }
69
+
70
+ const normalized = sessionsService.normalizeMessage('opencode', event, sid);
71
+ for (const msg of normalized) {
72
+ this.ws.send(msg);
73
+ }
74
+ }
75
+
76
+ forceFlush() {
77
+ if (this.buffer.trim()) {
78
+ try {
79
+ const event = JSON.parse(this.buffer);
80
+ this.handleEvent(event);
81
+ } catch {
82
+ if (this.onContentFragment) this.onContentFragment(this.buffer);
83
+ }
84
+ }
85
+ }
86
+
87
+ destroy() {
88
+ this.buffer = '';
89
+ }
90
+ }
91
+
92
+ export default OpencodeResponseHandler;