@pellux/goodvibes-sdk 0.18.28 → 0.18.30
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/dist/_internal/platform/agents/orchestrator-runner.js +1 -1
- package/dist/_internal/platform/bookmarks/manager.d.ts +1 -1
- package/dist/_internal/platform/bookmarks/manager.d.ts.map +1 -1
- package/dist/_internal/platform/channels/surface-registry.js +3 -3
- package/dist/_internal/platform/config/api-keys.d.ts +29 -0
- package/dist/_internal/platform/config/api-keys.d.ts.map +1 -0
- package/dist/_internal/platform/config/api-keys.js +153 -0
- package/dist/_internal/platform/config/index.d.ts +1 -13
- package/dist/_internal/platform/config/index.d.ts.map +1 -1
- package/dist/_internal/platform/config/index.js +1 -138
- package/dist/_internal/platform/config/schema-domain-core.d.ts +1 -0
- package/dist/_internal/platform/config/schema-domain-core.d.ts.map +1 -1
- package/dist/_internal/platform/config/schema-domain-core.js +7 -0
- package/dist/_internal/platform/config/schema-types.d.ts +3 -2
- package/dist/_internal/platform/config/schema-types.d.ts.map +1 -1
- package/dist/_internal/platform/config/tool-llm.d.ts.map +1 -1
- package/dist/_internal/platform/config/tool-llm.js +3 -0
- package/dist/_internal/platform/core/conversation-diff.d.ts +6 -2
- package/dist/_internal/platform/core/conversation-diff.d.ts.map +1 -1
- package/dist/_internal/platform/core/conversation.d.ts +13 -5
- package/dist/_internal/platform/core/conversation.d.ts.map +1 -1
- package/dist/_internal/platform/core/conversation.js +35 -1
- package/dist/_internal/platform/pairing/companion-token.d.ts +45 -0
- package/dist/_internal/platform/pairing/companion-token.d.ts.map +1 -0
- package/dist/_internal/platform/pairing/companion-token.js +74 -0
- package/dist/_internal/platform/pairing/connection-info.d.ts +10 -0
- package/dist/_internal/platform/pairing/connection-info.d.ts.map +1 -0
- package/dist/_internal/platform/pairing/connection-info.js +27 -0
- package/dist/_internal/platform/pairing/index.d.ts +6 -0
- package/dist/_internal/platform/pairing/index.d.ts.map +1 -0
- package/dist/_internal/platform/pairing/index.js +3 -0
- package/dist/_internal/platform/pairing/qr-generator.d.ts +20 -0
- package/dist/_internal/platform/pairing/qr-generator.d.ts.map +1 -0
- package/dist/_internal/platform/pairing/qr-generator.js +452 -0
- package/dist/_internal/platform/plugins/loader.d.ts +5 -1
- package/dist/_internal/platform/plugins/loader.d.ts.map +1 -1
- package/dist/_internal/platform/plugins/loader.js +7 -3
- package/dist/_internal/platform/runtime/bootstrap-hook-bridge.d.ts +10 -0
- package/dist/_internal/platform/runtime/bootstrap-hook-bridge.d.ts.map +1 -0
- package/dist/_internal/platform/runtime/bootstrap-hook-bridge.js +143 -0
- package/dist/_internal/platform/runtime/diagnostics/panels/panel-resources.d.ts +5 -5
- package/dist/_internal/platform/runtime/diagnostics/panels/panel-resources.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/diagnostics/panels/panel-resources.js +3 -3
- package/dist/_internal/platform/runtime/diagnostics/types.d.ts +26 -13
- package/dist/_internal/platform/runtime/diagnostics/types.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/diagnostics/types.js +4 -2
- package/dist/_internal/platform/runtime/mutable-runtime-state.d.ts +14 -0
- package/dist/_internal/platform/runtime/mutable-runtime-state.d.ts.map +1 -0
- package/dist/_internal/platform/runtime/mutable-runtime-state.js +1 -0
- package/dist/_internal/platform/runtime/ops/playbooks/permission-deadlock.js +2 -2
- package/dist/_internal/platform/runtime/perf/component-contracts.d.ts +114 -0
- package/dist/_internal/platform/runtime/perf/component-contracts.d.ts.map +1 -0
- package/dist/_internal/platform/runtime/perf/component-contracts.js +104 -0
- package/dist/_internal/platform/runtime/perf/component-health-monitor.d.ts +98 -0
- package/dist/_internal/platform/runtime/perf/component-health-monitor.d.ts.map +1 -0
- package/dist/_internal/platform/runtime/perf/component-health-monitor.js +248 -0
- package/dist/_internal/platform/runtime/perf/index.d.ts +6 -3
- package/dist/_internal/platform/runtime/perf/index.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/perf/index.js +4 -2
- package/dist/_internal/platform/runtime/perf/panel-contracts.d.ts +6 -90
- package/dist/_internal/platform/runtime/perf/panel-contracts.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/perf/panel-contracts.js +4 -83
- package/dist/_internal/platform/runtime/perf/panel-health-monitor.d.ts +4 -88
- package/dist/_internal/platform/runtime/perf/panel-health-monitor.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/perf/panel-health-monitor.js +4 -236
- package/dist/_internal/platform/runtime/service-queries.d.ts +3 -0
- package/dist/_internal/platform/runtime/service-queries.d.ts.map +1 -0
- package/dist/_internal/platform/runtime/service-queries.js +1 -0
- package/dist/_internal/platform/runtime/services.d.ts +2 -2
- package/dist/_internal/platform/runtime/services.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/services.js +3 -3
- package/dist/_internal/platform/runtime/session-return-context.js +1 -1
- package/dist/_internal/platform/runtime/shell-command-services.d.ts +2 -2
- package/dist/_internal/platform/runtime/shell-command-services.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/shell-command-services.js +2 -2
- package/dist/_internal/platform/runtime/shell-command-workspace.d.ts +2 -2
- package/dist/_internal/platform/runtime/shell-command-workspace.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/shell-command-workspace.js +2 -2
- package/dist/_internal/platform/runtime/store/domains/index.d.ts +2 -0
- package/dist/_internal/platform/runtime/store/domains/index.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/store/domains/index.js +1 -0
- package/dist/_internal/platform/runtime/store/selectors/index.d.ts +27 -14
- package/dist/_internal/platform/runtime/store/selectors/index.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/store/selectors/index.js +35 -25
- package/dist/_internal/platform/runtime/store/state.d.ts +3 -4
- package/dist/_internal/platform/runtime/store/state.d.ts.map +1 -1
- package/dist/_internal/platform/runtime/store/state.js +3 -4
- package/dist/_internal/platform/runtime/system-message-policy.d.ts +18 -0
- package/dist/_internal/platform/runtime/system-message-policy.d.ts.map +1 -0
- package/dist/_internal/platform/runtime/system-message-policy.js +35 -0
- package/dist/_internal/platform/utils/clipboard.d.ts +3 -2
- package/dist/_internal/platform/utils/clipboard.d.ts.map +1 -1
- package/dist/_internal/platform/utils/clipboard.js +0 -17
- package/dist/_internal/platform/utils/notify.d.ts.map +1 -1
- package/dist/_internal/platform/utils/notify.js +4 -1
- package/dist/_internal/platform/utils/terminal-width.d.ts +13 -0
- package/dist/_internal/platform/utils/terminal-width.d.ts.map +1 -1
- package/dist/_internal/platform/utils/terminal-width.js +13 -0
- package/dist/_internal/platform/version.js +1 -1
- package/package.json +1 -1
- package/dist/_internal/platform/core/history.d.ts +0 -22
- package/dist/_internal/platform/core/history.d.ts.map +0 -1
- package/dist/_internal/platform/core/history.js +0 -43
- package/dist/_internal/platform/types/grid.d.ts +0 -27
- package/dist/_internal/platform/types/grid.d.ts.map +0 -1
- package/dist/_internal/platform/types/grid.js +0 -26
- package/dist/_internal/platform/utils/splash-lines.d.ts +0 -8
- package/dist/_internal/platform/utils/splash-lines.d.ts.map +0 -1
- package/dist/_internal/platform/utils/splash-lines.js +0 -32
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
import { execSync } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Attempt to generate a QR matrix by shelling out to `qrencode`.
|
|
4
|
+
* Returns null if qrencode is not available or fails.
|
|
5
|
+
*/
|
|
6
|
+
function tryQrencode(data) {
|
|
7
|
+
try {
|
|
8
|
+
// -t ASC outputs a 2-character-per-module ASCII representation:
|
|
9
|
+
// '##' = dark module, ' ' = light module, with a surrounding quiet zone
|
|
10
|
+
// We use -t UTF8i (inverted) if available, or fall back to -t ASC.
|
|
11
|
+
// qrencode -t ASC outputs lines like: '###### ## ######'
|
|
12
|
+
// where each character is one module.
|
|
13
|
+
// We request -m 0 (no margin) and -s 1 for raw matrix output.
|
|
14
|
+
const output = execSync(`qrencode -m 0 -t ASC ${JSON.stringify(data)}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 5000 });
|
|
15
|
+
const rawLines = output.split('\n').filter((l) => l.length > 0);
|
|
16
|
+
if (rawLines.length === 0)
|
|
17
|
+
return null;
|
|
18
|
+
// qrencode ASC mode: each module is 2 characters wide ('##' dark, ' ' light)
|
|
19
|
+
const modules = rawLines.map((line) => {
|
|
20
|
+
const row = [];
|
|
21
|
+
for (let i = 0; i < line.length; i += 2) {
|
|
22
|
+
const pair = line.slice(i, i + 2);
|
|
23
|
+
row.push(pair === '##');
|
|
24
|
+
}
|
|
25
|
+
return row;
|
|
26
|
+
});
|
|
27
|
+
const size = modules[0]?.length ?? 0;
|
|
28
|
+
// Normalize all rows to the same size
|
|
29
|
+
const normalized = modules.map((row) => {
|
|
30
|
+
while (row.length < size)
|
|
31
|
+
row.push(false);
|
|
32
|
+
return row.slice(0, size);
|
|
33
|
+
});
|
|
34
|
+
return { size, modules: normalized };
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Minimal fallback QR matrix generator using a tiny Reed-Solomon QR implementation.
|
|
42
|
+
* Supports QR versions 1-9 (up to ~134 bytes, ECC level M).
|
|
43
|
+
*
|
|
44
|
+
* This is a self-contained implementation suitable for short connection strings.
|
|
45
|
+
*/
|
|
46
|
+
function generateQrMatrixMinimal(data) {
|
|
47
|
+
const bytes = new TextEncoder().encode(data);
|
|
48
|
+
const len = bytes.length;
|
|
49
|
+
// Version selection table: [version, dataCapacityBytes at ECC-M]
|
|
50
|
+
// Source: QR code spec Table 9
|
|
51
|
+
const versionTable = [
|
|
52
|
+
[1, 16], [2, 28], [3, 44], [4, 64], [5, 86],
|
|
53
|
+
[6, 108], [7, 124], [8, 154], [9, 182], [10, 216],
|
|
54
|
+
];
|
|
55
|
+
let version = 0;
|
|
56
|
+
for (const [v, cap] of versionTable) {
|
|
57
|
+
if (len <= cap) {
|
|
58
|
+
version = v;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (version === 0) {
|
|
63
|
+
throw new Error(`Data too long for minimal QR generator (${len} bytes, max 216)`);
|
|
64
|
+
}
|
|
65
|
+
// Total codewords and ECC codewords per block (ECC level M)
|
|
66
|
+
// [version]: [totalCodewords, eccCodewords, blocks]
|
|
67
|
+
const eccTable = {
|
|
68
|
+
1: [26, 10, 1], 2: [44, 16, 1], 3: [70, 26, 2],
|
|
69
|
+
4: [100, 36, 2], 5: [134, 48, 2], 6: [172, 64, 4],
|
|
70
|
+
7: [196, 72, 4], 8: [242, 88, 4], 9: [292, 110, 5],
|
|
71
|
+
10: [346, 130, 5],
|
|
72
|
+
};
|
|
73
|
+
const [totalCodewords, eccPerBlock, numBlocks] = eccTable[version];
|
|
74
|
+
const dataCodewords = totalCodewords - (eccPerBlock * numBlocks);
|
|
75
|
+
// Build data bit stream: mode (byte=0100), char count, data, terminator, padding
|
|
76
|
+
const bits = [];
|
|
77
|
+
function pushBits(value, count) {
|
|
78
|
+
for (let i = count - 1; i >= 0; i--) {
|
|
79
|
+
bits.push((value >> i) & 1);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Mode indicator: byte mode = 0100
|
|
83
|
+
pushBits(0b0100, 4);
|
|
84
|
+
// Character count indicator (version 1-9: 8 bits for byte mode)
|
|
85
|
+
pushBits(len, 8);
|
|
86
|
+
// Data bytes
|
|
87
|
+
for (const b of bytes)
|
|
88
|
+
pushBits(b, 8);
|
|
89
|
+
// Terminator (up to 4 zero bits)
|
|
90
|
+
const maxBits = dataCodewords * 8;
|
|
91
|
+
for (let i = 0; i < 4 && bits.length < maxBits; i++)
|
|
92
|
+
bits.push(0);
|
|
93
|
+
// Pad to byte boundary
|
|
94
|
+
while (bits.length % 8 !== 0)
|
|
95
|
+
bits.push(0);
|
|
96
|
+
// Pad codewords
|
|
97
|
+
const padBytes = [0xEC, 0x11];
|
|
98
|
+
let padIdx = 0;
|
|
99
|
+
while (bits.length < maxBits) {
|
|
100
|
+
pushBits(padBytes[padIdx % 2], 8);
|
|
101
|
+
padIdx++;
|
|
102
|
+
}
|
|
103
|
+
// Convert bits to bytes
|
|
104
|
+
const dataBytes = [];
|
|
105
|
+
for (let i = 0; i < bits.length; i += 8) {
|
|
106
|
+
let b = 0;
|
|
107
|
+
for (let j = 0; j < 8; j++)
|
|
108
|
+
b = (b << 1) | (bits[i + j] ?? 0);
|
|
109
|
+
dataBytes.push(b);
|
|
110
|
+
}
|
|
111
|
+
// Split into blocks and compute ECC
|
|
112
|
+
const dataPerBlock = Math.floor(dataCodewords / numBlocks);
|
|
113
|
+
const extraBlocks = dataCodewords - dataPerBlock * numBlocks;
|
|
114
|
+
const blocks = [];
|
|
115
|
+
let offset = 0;
|
|
116
|
+
for (let b = 0; b < numBlocks; b++) {
|
|
117
|
+
const blockLen = dataPerBlock + (b < extraBlocks ? 1 : 0);
|
|
118
|
+
blocks.push(dataBytes.slice(offset, offset + blockLen));
|
|
119
|
+
offset += blockLen;
|
|
120
|
+
}
|
|
121
|
+
// Reed-Solomon ECC generation
|
|
122
|
+
function gfMul(a, b) {
|
|
123
|
+
if (a === 0 || b === 0)
|
|
124
|
+
return 0;
|
|
125
|
+
const logTable = buildLogTable();
|
|
126
|
+
const expTable = buildExpTable();
|
|
127
|
+
return expTable[(logTable[a] + logTable[b]) % 255];
|
|
128
|
+
}
|
|
129
|
+
// Lazily built lookup tables (closured)
|
|
130
|
+
let _expTable = null;
|
|
131
|
+
let _logTable = null;
|
|
132
|
+
function buildExpTable() {
|
|
133
|
+
if (_expTable)
|
|
134
|
+
return _expTable;
|
|
135
|
+
_expTable = new Array(256);
|
|
136
|
+
let x = 1;
|
|
137
|
+
for (let i = 0; i < 255; i++) {
|
|
138
|
+
_expTable[i] = x;
|
|
139
|
+
x = (x << 1) ^ (x >= 128 ? 0x11d : 0);
|
|
140
|
+
}
|
|
141
|
+
_expTable[255] = _expTable[0];
|
|
142
|
+
return _expTable;
|
|
143
|
+
}
|
|
144
|
+
function buildLogTable() {
|
|
145
|
+
if (_logTable)
|
|
146
|
+
return _logTable;
|
|
147
|
+
const exp = buildExpTable();
|
|
148
|
+
_logTable = new Array(256).fill(0);
|
|
149
|
+
for (let i = 0; i < 255; i++)
|
|
150
|
+
_logTable[exp[i]] = i;
|
|
151
|
+
return _logTable;
|
|
152
|
+
}
|
|
153
|
+
function rsEcc(data, eccCount) {
|
|
154
|
+
// Generator polynomial for eccCount error correction codewords
|
|
155
|
+
const expTable = buildExpTable();
|
|
156
|
+
const logTable = buildLogTable();
|
|
157
|
+
// Build generator polynomial
|
|
158
|
+
let gen = [1];
|
|
159
|
+
for (let i = 0; i < eccCount; i++) {
|
|
160
|
+
const factor = [1, expTable[i]];
|
|
161
|
+
const newGen = new Array(gen.length + factor.length - 1).fill(0);
|
|
162
|
+
for (let j = 0; j < gen.length; j++) {
|
|
163
|
+
for (let k = 0; k < factor.length; k++) {
|
|
164
|
+
newGen[j + k] ^= gfMul(gen[j], factor[k]);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
gen = newGen;
|
|
168
|
+
}
|
|
169
|
+
// Polynomial long division
|
|
170
|
+
const msg = [...data, ...new Array(eccCount).fill(0)];
|
|
171
|
+
for (let i = 0; i < data.length; i++) {
|
|
172
|
+
const coef = msg[i];
|
|
173
|
+
if (coef !== 0) {
|
|
174
|
+
const log = logTable[coef];
|
|
175
|
+
for (let j = 0; j < gen.length; j++) {
|
|
176
|
+
msg[i + j] ^= gfMul(gen[j], expTable[(log + logTable[gen[j]]) % 255] / gen[j] | 0);
|
|
177
|
+
// Correct formula using logs:
|
|
178
|
+
if (gen[j] !== 0) {
|
|
179
|
+
msg[i + j] ^= expTable[(log + logTable[gen[j]]) % 255];
|
|
180
|
+
// undo the wrong xor above
|
|
181
|
+
msg[i + j] ^= gfMul(gen[j], expTable[(log + logTable[gen[j]]) % 255] / gen[j] | 0);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return msg.slice(data.length);
|
|
187
|
+
}
|
|
188
|
+
// Simpler, correct RS ECC implementation:
|
|
189
|
+
function rsEccCorrect(data, eccCount) {
|
|
190
|
+
const expTable = buildExpTable();
|
|
191
|
+
const logTable = buildLogTable();
|
|
192
|
+
let gen = [1];
|
|
193
|
+
for (let i = 0; i < eccCount; i++) {
|
|
194
|
+
const factor = [1, expTable[i]];
|
|
195
|
+
const newGen = new Array(gen.length + factor.length - 1).fill(0);
|
|
196
|
+
for (let j = 0; j < gen.length; j++) {
|
|
197
|
+
for (let k = 0; k < factor.length; k++) {
|
|
198
|
+
newGen[j + k] ^= gfMul(gen[j], factor[k]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
gen = newGen;
|
|
202
|
+
}
|
|
203
|
+
const msg = [...data, ...new Array(eccCount).fill(0)];
|
|
204
|
+
for (let i = 0; i < data.length; i++) {
|
|
205
|
+
const coef = msg[i];
|
|
206
|
+
if (coef !== 0) {
|
|
207
|
+
const logCoef = logTable[coef];
|
|
208
|
+
for (let j = 1; j < gen.length; j++) {
|
|
209
|
+
if (gen[j] !== 0) {
|
|
210
|
+
msg[i + j] ^= expTable[(logCoef + logTable[gen[j]]) % 255];
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return msg.slice(data.length);
|
|
216
|
+
}
|
|
217
|
+
// Interleave blocks and compute ECC
|
|
218
|
+
const eccBlocks = blocks.map((b) => rsEccCorrect(b, eccPerBlock));
|
|
219
|
+
const finalBytes = [];
|
|
220
|
+
// Interleave data blocks
|
|
221
|
+
const maxDataLen = Math.max(...blocks.map((b) => b.length));
|
|
222
|
+
for (let i = 0; i < maxDataLen; i++) {
|
|
223
|
+
for (const block of blocks) {
|
|
224
|
+
if (i < block.length)
|
|
225
|
+
finalBytes.push(block[i]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Interleave ECC blocks
|
|
229
|
+
for (let i = 0; i < eccPerBlock; i++) {
|
|
230
|
+
for (const ecc of eccBlocks) {
|
|
231
|
+
finalBytes.push(ecc[i]);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Build the QR matrix
|
|
235
|
+
const size = 21 + (version - 1) * 4;
|
|
236
|
+
const matrix = Array.from({ length: size }, () => new Array(size).fill(null));
|
|
237
|
+
function setModule(row, col, dark) {
|
|
238
|
+
if (row >= 0 && row < size && col >= 0 && col < size) {
|
|
239
|
+
matrix[row][col] = dark;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Place finder pattern
|
|
243
|
+
function placeFinderPattern(r, c) {
|
|
244
|
+
for (let dy = -1; dy <= 7; dy++) {
|
|
245
|
+
for (let dx = -1; dx <= 7; dx++) {
|
|
246
|
+
const inOuter = dy >= 0 && dy <= 6 && dx >= 0 && dx <= 6;
|
|
247
|
+
const inWhite = dy >= 1 && dy <= 5 && dx >= 1 && dx <= 5;
|
|
248
|
+
const inInner = dy >= 2 && dy <= 4 && dx >= 2 && dx <= 4;
|
|
249
|
+
if (!inOuter) {
|
|
250
|
+
setModule(r + dy, c + dx, false); // separator
|
|
251
|
+
}
|
|
252
|
+
else if (inWhite && !inInner) {
|
|
253
|
+
setModule(r + dy, c + dx, false);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
setModule(r + dy, c + dx, inInner || (dy === 0 || dy === 6 || dx === 0 || dx === 6));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
placeFinderPattern(0, 0);
|
|
262
|
+
placeFinderPattern(0, size - 7);
|
|
263
|
+
placeFinderPattern(size - 7, 0);
|
|
264
|
+
// Timing patterns
|
|
265
|
+
for (let i = 8; i < size - 8; i++) {
|
|
266
|
+
const dark = i % 2 === 0;
|
|
267
|
+
setModule(6, i, dark);
|
|
268
|
+
setModule(i, 6, dark);
|
|
269
|
+
}
|
|
270
|
+
// Alignment patterns (version >= 2)
|
|
271
|
+
const alignmentPositions = {
|
|
272
|
+
2: [6, 18], 3: [6, 22], 4: [6, 26], 5: [6, 30],
|
|
273
|
+
6: [6, 34], 7: [6, 22, 38], 8: [6, 24, 42],
|
|
274
|
+
9: [6, 28, 46], 10: [6, 28, 50],
|
|
275
|
+
};
|
|
276
|
+
const alignPos = version >= 2 ? alignmentPositions[version] ?? [] : [];
|
|
277
|
+
for (const r of alignPos) {
|
|
278
|
+
for (const c of alignPos) {
|
|
279
|
+
// Skip positions occupied by finder patterns
|
|
280
|
+
if ((r <= 8 && c <= 8) || (r <= 8 && c >= size - 8) || (r >= size - 8 && c <= 8))
|
|
281
|
+
continue;
|
|
282
|
+
for (let dy = -2; dy <= 2; dy++) {
|
|
283
|
+
for (let dx = -2; dx <= 2; dx++) {
|
|
284
|
+
const isEdge = Math.abs(dy) === 2 || Math.abs(dx) === 2;
|
|
285
|
+
const isCenter = dy === 0 && dx === 0;
|
|
286
|
+
setModule(r + dy, c + dx, isEdge || isCenter);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Dark module (always dark)
|
|
292
|
+
setModule(4 * version + 9, 8, true);
|
|
293
|
+
// Format information area — reserve (mark as false for now)
|
|
294
|
+
for (let i = 0; i < 9; i++) {
|
|
295
|
+
setModule(8, i, matrix[8]?.[i] ?? false);
|
|
296
|
+
setModule(i, 8, matrix[i]?.[8] ?? false);
|
|
297
|
+
}
|
|
298
|
+
for (let i = size - 8; i < size; i++) {
|
|
299
|
+
setModule(8, i, false);
|
|
300
|
+
setModule(i, 8, false);
|
|
301
|
+
}
|
|
302
|
+
// Place data bits (zigzag pattern)
|
|
303
|
+
const allBits = [];
|
|
304
|
+
for (const b of finalBytes) {
|
|
305
|
+
for (let i = 7; i >= 0; i--)
|
|
306
|
+
allBits.push((b >> i) & 1);
|
|
307
|
+
}
|
|
308
|
+
let bitIdx = 0;
|
|
309
|
+
let goUp = true;
|
|
310
|
+
// Right-to-left column pairs, skipping column 6 (timing)
|
|
311
|
+
for (let col = size - 1; col >= 1; col -= 2) {
|
|
312
|
+
if (col === 6)
|
|
313
|
+
col--; // skip timing column
|
|
314
|
+
const colRange = goUp
|
|
315
|
+
? Array.from({ length: size }, (_, i) => size - 1 - i)
|
|
316
|
+
: Array.from({ length: size }, (_, i) => i);
|
|
317
|
+
for (const row of colRange) {
|
|
318
|
+
for (const dc of [0, -1]) {
|
|
319
|
+
const c = col + dc;
|
|
320
|
+
if (matrix[row]?.[c] === null) {
|
|
321
|
+
const bit = allBits[bitIdx++] ?? 0;
|
|
322
|
+
matrix[row][c] = bit === 1;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
goUp = !goUp;
|
|
327
|
+
}
|
|
328
|
+
// Apply mask pattern 0 (checkerboard: (row + col) % 2 === 0)
|
|
329
|
+
// and place format information
|
|
330
|
+
const maskFn = (r, c) => (r + c) % 2 === 0;
|
|
331
|
+
for (let r = 0; r < size; r++) {
|
|
332
|
+
for (let c = 0; c < size; c++) {
|
|
333
|
+
const module = matrix[r]?.[c];
|
|
334
|
+
if (module === null) {
|
|
335
|
+
matrix[r][c] = false; // unfilled = light
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
// Only apply mask to data modules (not function patterns)
|
|
339
|
+
// We re-apply masking carefully: function patterns are already fixed
|
|
340
|
+
// Data modules that were null are now set above
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
// Apply mask to data modules (those placed via zigzag)
|
|
345
|
+
bitIdx = 0;
|
|
346
|
+
goUp = true;
|
|
347
|
+
const maskedMatrix = matrix.map((row) => row.map((m) => m ?? false));
|
|
348
|
+
// Reset data area and re-place with masking
|
|
349
|
+
{
|
|
350
|
+
const tempMatrix = matrix.map((row) => [...row]);
|
|
351
|
+
// Re-mark data positions as null
|
|
352
|
+
let bi = 0;
|
|
353
|
+
let gu = true;
|
|
354
|
+
for (let col = size - 1; col >= 1; col -= 2) {
|
|
355
|
+
if (col === 6)
|
|
356
|
+
col--;
|
|
357
|
+
const colRange = gu
|
|
358
|
+
? Array.from({ length: size }, (_, i) => size - 1 - i)
|
|
359
|
+
: Array.from({ length: size }, (_, i) => i);
|
|
360
|
+
for (const row of colRange) {
|
|
361
|
+
for (const dc of [0, -1]) {
|
|
362
|
+
const c = col + dc;
|
|
363
|
+
if (tempMatrix[row]?.[c] !== null) {
|
|
364
|
+
// was set as data, apply mask
|
|
365
|
+
const dark = (allBits[bi++] ?? 0) === 1;
|
|
366
|
+
maskedMatrix[row][c] = maskFn(row, c) ? !dark : dark;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
gu = !gu;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
// Format string for ECC level M (01), mask pattern 0 (000)
|
|
374
|
+
// Format info = 01000 XOR 101010000010010 = 110010111100101
|
|
375
|
+
// Precomputed: ECC-M + mask-0 = format bits 101000000100101 (with BCH)
|
|
376
|
+
// Using known correct value for M+mask0: 0x5647 -> bits[14..0]
|
|
377
|
+
// Actually standard value: ECC-M=1, mask=0 -> data=01_000 -> format=01000 00000000
|
|
378
|
+
// BCH(01000)=0100000000+BCH = let's use precomputed: 0x72F3 for M+mask2, etc.
|
|
379
|
+
// Correct precomputed format words (ECC-M=0b01, masks 0-7):
|
|
380
|
+
const formatWords = [
|
|
381
|
+
0x5412, 0x5125, 0x5E7C, 0x5B4B, 0x45F9, 0x40CE, 0x4F97, 0x4AA0,
|
|
382
|
+
];
|
|
383
|
+
const formatWord = formatWords[0]; // mask 0
|
|
384
|
+
const formatXor = 0b101010000010010;
|
|
385
|
+
const fmt = (formatWord ^ formatXor) & 0x7FFF;
|
|
386
|
+
const fmtBits = Array.from({ length: 15 }, (_, i) => (fmt >> (14 - i)) & 1);
|
|
387
|
+
// Place format bits around finder patterns
|
|
388
|
+
// Around top-left finder:
|
|
389
|
+
const fmtPositions1 = [
|
|
390
|
+
[8, 0], [8, 1], [8, 2], [8, 3], [8, 4], [8, 5], [8, 7], [8, 8],
|
|
391
|
+
[7, 8], [5, 8], [4, 8], [3, 8], [2, 8], [1, 8], [0, 8],
|
|
392
|
+
];
|
|
393
|
+
fmtPositions1.forEach(([r, c], i) => {
|
|
394
|
+
maskedMatrix[r][c] = fmtBits[i] === 1;
|
|
395
|
+
});
|
|
396
|
+
// Around top-right and bottom-left finders:
|
|
397
|
+
const fmtPositions2 = [
|
|
398
|
+
[8, size - 8], [8, size - 7], [8, size - 6], [8, size - 5],
|
|
399
|
+
[8, size - 4], [8, size - 3], [8, size - 2], [8, size - 1],
|
|
400
|
+
];
|
|
401
|
+
fmtPositions2.forEach(([r, c], i) => {
|
|
402
|
+
maskedMatrix[r][c] = fmtBits[i] === 1;
|
|
403
|
+
});
|
|
404
|
+
const fmtPositions3 = [
|
|
405
|
+
[size - 7, 8], [size - 6, 8], [size - 5, 8],
|
|
406
|
+
[size - 4, 8], [size - 3, 8], [size - 2, 8], [size - 1, 8],
|
|
407
|
+
];
|
|
408
|
+
fmtPositions3.forEach(([r, c], i) => {
|
|
409
|
+
maskedMatrix[r][c] = fmtBits[i + 8] === 1;
|
|
410
|
+
});
|
|
411
|
+
return { size, modules: maskedMatrix };
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Generate a QR code matrix for the given data string.
|
|
415
|
+
* Tries qrencode CLI first; falls back to minimal built-in implementation.
|
|
416
|
+
*/
|
|
417
|
+
export function generateQrMatrix(data) {
|
|
418
|
+
const fromCli = tryQrencode(data);
|
|
419
|
+
if (fromCli !== null)
|
|
420
|
+
return fromCli;
|
|
421
|
+
return generateQrMatrixMinimal(data);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Render a QR matrix to a Unicode block string suitable for terminal output.
|
|
425
|
+
* Uses half-block characters to pack 2 rows into 1 terminal row.
|
|
426
|
+
*
|
|
427
|
+
* - Full block `█` = dark top + dark bottom
|
|
428
|
+
* - Upper half `▀` = dark top + light bottom
|
|
429
|
+
* - Lower half `▄` = light top + dark bottom
|
|
430
|
+
* - Space ` ` = light top + light bottom
|
|
431
|
+
*/
|
|
432
|
+
export function renderQrToString(matrix) {
|
|
433
|
+
const { size, modules } = matrix;
|
|
434
|
+
const lines = [];
|
|
435
|
+
for (let row = 0; row < size; row += 2) {
|
|
436
|
+
let line = '';
|
|
437
|
+
for (let col = 0; col < size; col++) {
|
|
438
|
+
const top = modules[row]?.[col] ?? false;
|
|
439
|
+
const bottom = modules[row + 1]?.[col] ?? false;
|
|
440
|
+
if (top && bottom)
|
|
441
|
+
line += '\u2588'; // full block
|
|
442
|
+
else if (top && !bottom)
|
|
443
|
+
line += '\u2580'; // upper half
|
|
444
|
+
else if (!top && bottom)
|
|
445
|
+
line += '\u2584'; // lower half
|
|
446
|
+
else
|
|
447
|
+
line += ' '; // space
|
|
448
|
+
}
|
|
449
|
+
lines.push(line);
|
|
450
|
+
}
|
|
451
|
+
return lines.join('\n');
|
|
452
|
+
}
|
|
@@ -12,6 +12,10 @@ import type { WebSearchProviderRegistry } from '../web-search/index.js';
|
|
|
12
12
|
export interface PluginPathOptions {
|
|
13
13
|
readonly cwd: string;
|
|
14
14
|
readonly homeDir: string;
|
|
15
|
+
/** Additional plugin directories to search, appended after the standard directories. */
|
|
16
|
+
readonly additionalDirectories?: readonly string[];
|
|
17
|
+
/** Default entry point filename when a plugin manifest does not specify `main`. Defaults to 'index.js'. */
|
|
18
|
+
readonly entryDefault?: string;
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
17
21
|
* Plugin search directories in precedence order.
|
|
@@ -93,7 +97,7 @@ export interface PluginLoaderDeps {
|
|
|
93
97
|
* @param cacheBust - Optional timestamp suffix appended to the import URL to bypass
|
|
94
98
|
* Bun's module cache. Pass `Date.now()` on reload to force fresh execution.
|
|
95
99
|
*/
|
|
96
|
-
export declare function loadPlugin(discovered: DiscoveredPlugin, deps: PluginLoaderDeps, cacheBust?: number): Promise<LoadedPlugin | null>;
|
|
100
|
+
export declare function loadPlugin(discovered: DiscoveredPlugin, deps: PluginLoaderDeps, cacheBust?: number, entryDefault?: string): Promise<LoadedPlugin | null>;
|
|
97
101
|
/**
|
|
98
102
|
* unloadPlugin — Deactivate a plugin and run all cleanup callbacks.
|
|
99
103
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/plugins/loader.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAyB,MAAM,UAAU,CAAC;AAClE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4CAA4C,CAAC;AACxF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAGxE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/plugins/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,10 +12,14 @@ export function getUserPluginDirectory(options) {
|
|
|
12
12
|
return join(options.homeDir, '.goodvibes', PLUGIN_ROOT);
|
|
13
13
|
}
|
|
14
14
|
export function getPluginDirectories(options) {
|
|
15
|
-
|
|
15
|
+
const dirs = [
|
|
16
16
|
join(options.cwd, '.goodvibes', PLUGIN_ROOT),
|
|
17
17
|
getUserPluginDirectory(options),
|
|
18
18
|
];
|
|
19
|
+
if (options.additionalDirectories) {
|
|
20
|
+
dirs.push(...options.additionalDirectories);
|
|
21
|
+
}
|
|
22
|
+
return dirs;
|
|
19
23
|
}
|
|
20
24
|
/**
|
|
21
25
|
* discoverPlugins — Scan the configured plugin directories for valid plugin folders.
|
|
@@ -88,9 +92,9 @@ export function discoverPlugins(options) {
|
|
|
88
92
|
* @param cacheBust - Optional timestamp suffix appended to the import URL to bypass
|
|
89
93
|
* Bun's module cache. Pass `Date.now()` on reload to force fresh execution.
|
|
90
94
|
*/
|
|
91
|
-
export async function loadPlugin(discovered, deps, cacheBust) {
|
|
95
|
+
export async function loadPlugin(discovered, deps, cacheBust, entryDefault) {
|
|
92
96
|
const { manifest, pluginDir } = discovered;
|
|
93
|
-
const entryFile = manifest.main ?? 'index.js';
|
|
97
|
+
const entryFile = manifest.main ?? entryDefault ?? 'index.js';
|
|
94
98
|
const entryPath = join(pluginDir, entryFile);
|
|
95
99
|
// Path traversal guard: resolved entry must remain within pluginDir
|
|
96
100
|
const resolvedEntry = resolve(entryPath);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HookDispatcher } from '../hooks/index.js';
|
|
2
|
+
import type { MutableRuntimeState } from './mutable-runtime-state.js';
|
|
3
|
+
import type { RuntimeEventBus } from './events/index.js';
|
|
4
|
+
export interface HookBridgeRegistrationOptions {
|
|
5
|
+
readonly runtimeBus: RuntimeEventBus;
|
|
6
|
+
readonly hookDispatcher: HookDispatcher;
|
|
7
|
+
readonly runtime: MutableRuntimeState;
|
|
8
|
+
}
|
|
9
|
+
export declare function registerBootstrapHookBridge(options: HookBridgeRegistrationOptions): Array<() => void>;
|
|
10
|
+
//# sourceMappingURL=bootstrap-hook-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap-hook-bridge.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/runtime/bootstrap-hook-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAAwB,eAAe,EAAiB,MAAM,mBAAmB,CAAC;AA4B9F,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;CACvC;AAED,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,6BAA6B,GACrC,KAAK,CAAC,MAAM,IAAI,CAAC,CAoInB"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { logger } from '../utils/logger.js';
|
|
2
|
+
import { summarizeError } from '../utils/error-display.js';
|
|
3
|
+
function fireHook(options, path, phase, category, specific, payload) {
|
|
4
|
+
options.hookDispatcher.fire({
|
|
5
|
+
path,
|
|
6
|
+
phase,
|
|
7
|
+
category,
|
|
8
|
+
specific,
|
|
9
|
+
sessionId: options.runtime.sessionId,
|
|
10
|
+
timestamp: Date.now(),
|
|
11
|
+
payload,
|
|
12
|
+
}).catch((err) => logger.debug('Hook bridge fire error', { path, error: summarizeError(err) }));
|
|
13
|
+
}
|
|
14
|
+
export function registerBootstrapHookBridge(options) {
|
|
15
|
+
const fireOptions = {
|
|
16
|
+
hookDispatcher: options.hookDispatcher,
|
|
17
|
+
runtime: options.runtime,
|
|
18
|
+
};
|
|
19
|
+
const unsubs = [];
|
|
20
|
+
const { runtimeBus } = options;
|
|
21
|
+
unsubs.push(runtimeBus.on('AGENT_SPAWNING', ({ payload }) => {
|
|
22
|
+
fireHook(fireOptions, 'Lifecycle:agent:spawned', 'Lifecycle', 'agent', 'spawned', { agentId: payload.agentId, task: payload.task });
|
|
23
|
+
}));
|
|
24
|
+
unsubs.push(runtimeBus.on('AGENT_COMPLETED', ({ payload }) => {
|
|
25
|
+
fireHook(fireOptions, 'Lifecycle:agent:completed', 'Lifecycle', 'agent', 'completed', {
|
|
26
|
+
agentId: payload.agentId,
|
|
27
|
+
result: {
|
|
28
|
+
durationMs: payload.durationMs,
|
|
29
|
+
...(payload.output !== undefined ? { output: payload.output } : {}),
|
|
30
|
+
...(payload.toolCallsMade !== undefined ? { toolCallsMade: payload.toolCallsMade } : {}),
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}));
|
|
34
|
+
unsubs.push(runtimeBus.on('AGENT_FAILED', ({ payload }) => {
|
|
35
|
+
const specific = payload.error === 'Agent cancelled' || payload.error.includes('cancelled') ? 'cancelled' : 'failed';
|
|
36
|
+
fireHook(fireOptions, `Lifecycle:agent:${specific}`, 'Lifecycle', 'agent', specific, { agentId: payload.agentId, error: payload.error });
|
|
37
|
+
}));
|
|
38
|
+
unsubs.push(runtimeBus.on('WORKFLOW_CHAIN_CREATED', ({ payload }) => {
|
|
39
|
+
fireHook(fireOptions, 'Lifecycle:workflow:started', 'Lifecycle', 'workflow', 'started', { chainId: payload.chainId, task: payload.task });
|
|
40
|
+
}));
|
|
41
|
+
unsubs.push(runtimeBus.on('WORKFLOW_CHAIN_PASSED', ({ payload }) => {
|
|
42
|
+
fireHook(fireOptions, 'Lifecycle:workflow:completed', 'Lifecycle', 'workflow', 'completed', { chainId: payload.chainId });
|
|
43
|
+
}));
|
|
44
|
+
unsubs.push(runtimeBus.on('WORKFLOW_CHAIN_FAILED', ({ payload }) => {
|
|
45
|
+
fireHook(fireOptions, 'Lifecycle:workflow:failed', 'Lifecycle', 'workflow', 'failed', { chainId: payload.chainId, reason: payload.reason });
|
|
46
|
+
}));
|
|
47
|
+
unsubs.push(runtimeBus.on('WORKFLOW_REVIEW_COMPLETED', ({ payload }) => {
|
|
48
|
+
fireHook(fireOptions, 'Lifecycle:workflow:reviewed', 'Lifecycle', 'workflow', 'reviewed', {
|
|
49
|
+
chainId: payload.chainId,
|
|
50
|
+
score: payload.score,
|
|
51
|
+
passed: payload.passed,
|
|
52
|
+
});
|
|
53
|
+
}));
|
|
54
|
+
unsubs.push(runtimeBus.on('WORKFLOW_FIX_ATTEMPTED', ({ payload }) => {
|
|
55
|
+
fireHook(fireOptions, 'Lifecycle:workflow:fix-attempted', 'Lifecycle', 'workflow', 'fix-attempted', {
|
|
56
|
+
chainId: payload.chainId,
|
|
57
|
+
attempt: payload.attempt,
|
|
58
|
+
maxAttempts: payload.maxAttempts,
|
|
59
|
+
});
|
|
60
|
+
}));
|
|
61
|
+
unsubs.push(runtimeBus.on('WORKFLOW_GATE_RESULT', ({ payload }) => {
|
|
62
|
+
fireHook(fireOptions, 'Lifecycle:workflow:gate-result', 'Lifecycle', 'workflow', 'gate-result', {
|
|
63
|
+
chainId: payload.chainId,
|
|
64
|
+
gate: payload.gate,
|
|
65
|
+
passed: payload.passed,
|
|
66
|
+
});
|
|
67
|
+
}));
|
|
68
|
+
unsubs.push(runtimeBus.on('ORCHESTRATION_GRAPH_CREATED', ({ payload }) => {
|
|
69
|
+
fireHook(fireOptions, 'Lifecycle:orchestration:graph-created', 'Lifecycle', 'orchestration', 'graph-created', {
|
|
70
|
+
graphId: payload.graphId,
|
|
71
|
+
title: payload.title,
|
|
72
|
+
mode: payload.mode,
|
|
73
|
+
});
|
|
74
|
+
}));
|
|
75
|
+
unsubs.push(runtimeBus.on('ORCHESTRATION_NODE_STARTED', ({ payload }) => {
|
|
76
|
+
fireHook(fireOptions, 'Lifecycle:orchestration:node-started', 'Lifecycle', 'orchestration', 'node-started', {
|
|
77
|
+
graphId: payload.graphId,
|
|
78
|
+
nodeId: payload.nodeId,
|
|
79
|
+
...(payload.taskId !== undefined ? { taskId: payload.taskId } : {}),
|
|
80
|
+
...(payload.agentId !== undefined ? { agentId: payload.agentId } : {}),
|
|
81
|
+
});
|
|
82
|
+
}));
|
|
83
|
+
unsubs.push(runtimeBus.on('ORCHESTRATION_NODE_COMPLETED', ({ payload }) => {
|
|
84
|
+
fireHook(fireOptions, 'Lifecycle:orchestration:node-completed', 'Lifecycle', 'orchestration', 'node-completed', {
|
|
85
|
+
graphId: payload.graphId,
|
|
86
|
+
nodeId: payload.nodeId,
|
|
87
|
+
...(payload.summary !== undefined ? { summary: payload.summary } : {}),
|
|
88
|
+
});
|
|
89
|
+
}));
|
|
90
|
+
unsubs.push(runtimeBus.on('ORCHESTRATION_NODE_FAILED', ({ payload }) => {
|
|
91
|
+
fireHook(fireOptions, 'Lifecycle:orchestration:node-failed', 'Lifecycle', 'orchestration', 'node-failed', {
|
|
92
|
+
graphId: payload.graphId,
|
|
93
|
+
nodeId: payload.nodeId,
|
|
94
|
+
error: payload.error,
|
|
95
|
+
});
|
|
96
|
+
}));
|
|
97
|
+
unsubs.push(runtimeBus.on('ORCHESTRATION_RECURSION_GUARD_TRIGGERED', ({ payload }) => {
|
|
98
|
+
fireHook(fireOptions, 'Change:orchestration:recursion-guard', 'Change', 'orchestration', 'recursion-guard', {
|
|
99
|
+
graphId: payload.graphId,
|
|
100
|
+
...(payload.nodeId !== undefined ? { nodeId: payload.nodeId } : {}),
|
|
101
|
+
depth: payload.depth,
|
|
102
|
+
activeAgents: payload.activeAgents,
|
|
103
|
+
reason: payload.reason,
|
|
104
|
+
});
|
|
105
|
+
}));
|
|
106
|
+
unsubs.push(runtimeBus.on('COMMUNICATION_SENT', ({ payload }) => {
|
|
107
|
+
fireHook(fireOptions, 'Lifecycle:communication:sent', 'Lifecycle', 'communication', 'sent', {
|
|
108
|
+
messageId: payload.messageId,
|
|
109
|
+
fromId: payload.fromId,
|
|
110
|
+
toId: payload.toId,
|
|
111
|
+
scope: payload.scope,
|
|
112
|
+
kind: payload.kind,
|
|
113
|
+
...(payload.fromRole !== undefined ? { fromRole: payload.fromRole } : {}),
|
|
114
|
+
...(payload.toRole !== undefined ? { toRole: payload.toRole } : {}),
|
|
115
|
+
});
|
|
116
|
+
}));
|
|
117
|
+
unsubs.push(runtimeBus.on('COMMUNICATION_DELIVERED', ({ payload }) => {
|
|
118
|
+
fireHook(fireOptions, 'Lifecycle:communication:delivered', 'Lifecycle', 'communication', 'delivered', {
|
|
119
|
+
messageId: payload.messageId,
|
|
120
|
+
fromId: payload.fromId,
|
|
121
|
+
toId: payload.toId,
|
|
122
|
+
scope: payload.scope,
|
|
123
|
+
kind: payload.kind,
|
|
124
|
+
});
|
|
125
|
+
}));
|
|
126
|
+
unsubs.push(runtimeBus.on('COMMUNICATION_BLOCKED', ({ payload }) => {
|
|
127
|
+
fireHook(fireOptions, 'Change:communication:blocked', 'Change', 'communication', 'blocked', {
|
|
128
|
+
messageId: payload.messageId,
|
|
129
|
+
fromId: payload.fromId,
|
|
130
|
+
toId: payload.toId,
|
|
131
|
+
scope: payload.scope,
|
|
132
|
+
kind: payload.kind,
|
|
133
|
+
reason: payload.reason,
|
|
134
|
+
...(payload.fromRole !== undefined ? { fromRole: payload.fromRole } : {}),
|
|
135
|
+
...(payload.toRole !== undefined ? { toRole: payload.toRole } : {}),
|
|
136
|
+
});
|
|
137
|
+
}));
|
|
138
|
+
unsubs.push(runtimeBus.on('OPS_CONTEXT_WARNING', ({ payload: { usage, threshold } }) => {
|
|
139
|
+
const specific = usage >= threshold ? 'exceeded' : 'warning';
|
|
140
|
+
fireHook(fireOptions, `Change:budget:${specific}`, 'Change', 'budget', specific, { usage, threshold });
|
|
141
|
+
}));
|
|
142
|
+
return unsubs;
|
|
143
|
+
}
|