@schoolai/shipyard-mcp 0.1.0
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/LICENSE.md +105 -0
- package/README.md +221 -0
- package/apps/hook/README.md +273 -0
- package/apps/hook/dist/index.js +3078 -0
- package/apps/server/.env.example +20 -0
- package/apps/server/dist/chunk-7GPZDCWI.js +158 -0
- package/apps/server/dist/chunk-EBNL5ZX7.js +120 -0
- package/apps/server/dist/chunk-GSGLHRWX.js +62 -0
- package/apps/server/dist/chunk-JSBRDJBE.js +30 -0
- package/apps/server/dist/chunk-LTC26IRQ.js +2930 -0
- package/apps/server/dist/chunk-SIQIBECG.js +273 -0
- package/apps/server/dist/dist-LQBXUHLR.js +409 -0
- package/apps/server/dist/index.js +5450 -0
- package/apps/server/dist/input-request-manager-YVKAMQPF.js +9 -0
- package/apps/server/dist/server-identity-KUXYHULN.js +10 -0
- package/apps/server/dist/session-registry-DMV543RG.js +40 -0
- package/package.json +74 -0
|
@@ -0,0 +1,3078 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
|
|
28
|
+
// ../../node_modules/.pnpm/lz-string@1.5.0/node_modules/lz-string/libs/lz-string.js
|
|
29
|
+
var require_lz_string = __commonJS({
|
|
30
|
+
"../../node_modules/.pnpm/lz-string@1.5.0/node_modules/lz-string/libs/lz-string.js"(exports, module) {
|
|
31
|
+
"use strict";
|
|
32
|
+
var LZString = (function() {
|
|
33
|
+
var f = String.fromCharCode;
|
|
34
|
+
var keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
|
35
|
+
var keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$";
|
|
36
|
+
var baseReverseDic = {};
|
|
37
|
+
function getBaseValue(alphabet, character) {
|
|
38
|
+
if (!baseReverseDic[alphabet]) {
|
|
39
|
+
baseReverseDic[alphabet] = {};
|
|
40
|
+
for (var i = 0; i < alphabet.length; i++) {
|
|
41
|
+
baseReverseDic[alphabet][alphabet.charAt(i)] = i;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return baseReverseDic[alphabet][character];
|
|
45
|
+
}
|
|
46
|
+
var LZString2 = {
|
|
47
|
+
compressToBase64: function(input) {
|
|
48
|
+
if (input == null) return "";
|
|
49
|
+
var res = LZString2._compress(input, 6, function(a) {
|
|
50
|
+
return keyStrBase64.charAt(a);
|
|
51
|
+
});
|
|
52
|
+
switch (res.length % 4) {
|
|
53
|
+
// To produce valid Base64
|
|
54
|
+
default:
|
|
55
|
+
// When could this happen ?
|
|
56
|
+
case 0:
|
|
57
|
+
return res;
|
|
58
|
+
case 1:
|
|
59
|
+
return res + "===";
|
|
60
|
+
case 2:
|
|
61
|
+
return res + "==";
|
|
62
|
+
case 3:
|
|
63
|
+
return res + "=";
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
decompressFromBase64: function(input) {
|
|
67
|
+
if (input == null) return "";
|
|
68
|
+
if (input == "") return null;
|
|
69
|
+
return LZString2._decompress(input.length, 32, function(index) {
|
|
70
|
+
return getBaseValue(keyStrBase64, input.charAt(index));
|
|
71
|
+
});
|
|
72
|
+
},
|
|
73
|
+
compressToUTF16: function(input) {
|
|
74
|
+
if (input == null) return "";
|
|
75
|
+
return LZString2._compress(input, 15, function(a) {
|
|
76
|
+
return f(a + 32);
|
|
77
|
+
}) + " ";
|
|
78
|
+
},
|
|
79
|
+
decompressFromUTF16: function(compressed) {
|
|
80
|
+
if (compressed == null) return "";
|
|
81
|
+
if (compressed == "") return null;
|
|
82
|
+
return LZString2._decompress(compressed.length, 16384, function(index) {
|
|
83
|
+
return compressed.charCodeAt(index) - 32;
|
|
84
|
+
});
|
|
85
|
+
},
|
|
86
|
+
//compress into uint8array (UCS-2 big endian format)
|
|
87
|
+
compressToUint8Array: function(uncompressed) {
|
|
88
|
+
var compressed = LZString2.compress(uncompressed);
|
|
89
|
+
var buf = new Uint8Array(compressed.length * 2);
|
|
90
|
+
for (var i = 0, TotalLen = compressed.length; i < TotalLen; i++) {
|
|
91
|
+
var current_value = compressed.charCodeAt(i);
|
|
92
|
+
buf[i * 2] = current_value >>> 8;
|
|
93
|
+
buf[i * 2 + 1] = current_value % 256;
|
|
94
|
+
}
|
|
95
|
+
return buf;
|
|
96
|
+
},
|
|
97
|
+
//decompress from uint8array (UCS-2 big endian format)
|
|
98
|
+
decompressFromUint8Array: function(compressed) {
|
|
99
|
+
if (compressed === null || compressed === void 0) {
|
|
100
|
+
return LZString2.decompress(compressed);
|
|
101
|
+
} else {
|
|
102
|
+
var buf = new Array(compressed.length / 2);
|
|
103
|
+
for (var i = 0, TotalLen = buf.length; i < TotalLen; i++) {
|
|
104
|
+
buf[i] = compressed[i * 2] * 256 + compressed[i * 2 + 1];
|
|
105
|
+
}
|
|
106
|
+
var result = [];
|
|
107
|
+
buf.forEach(function(c) {
|
|
108
|
+
result.push(f(c));
|
|
109
|
+
});
|
|
110
|
+
return LZString2.decompress(result.join(""));
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
//compress into a string that is already URI encoded
|
|
114
|
+
compressToEncodedURIComponent: function(input) {
|
|
115
|
+
if (input == null) return "";
|
|
116
|
+
return LZString2._compress(input, 6, function(a) {
|
|
117
|
+
return keyStrUriSafe.charAt(a);
|
|
118
|
+
});
|
|
119
|
+
},
|
|
120
|
+
//decompress from an output of compressToEncodedURIComponent
|
|
121
|
+
decompressFromEncodedURIComponent: function(input) {
|
|
122
|
+
if (input == null) return "";
|
|
123
|
+
if (input == "") return null;
|
|
124
|
+
input = input.replace(/ /g, "+");
|
|
125
|
+
return LZString2._decompress(input.length, 32, function(index) {
|
|
126
|
+
return getBaseValue(keyStrUriSafe, input.charAt(index));
|
|
127
|
+
});
|
|
128
|
+
},
|
|
129
|
+
compress: function(uncompressed) {
|
|
130
|
+
return LZString2._compress(uncompressed, 16, function(a) {
|
|
131
|
+
return f(a);
|
|
132
|
+
});
|
|
133
|
+
},
|
|
134
|
+
_compress: function(uncompressed, bitsPerChar, getCharFromInt) {
|
|
135
|
+
if (uncompressed == null) return "";
|
|
136
|
+
var i, value, context_dictionary = {}, context_dictionaryToCreate = {}, context_c = "", context_wc = "", context_w = "", context_enlargeIn = 2, context_dictSize = 3, context_numBits = 2, context_data = [], context_data_val = 0, context_data_position = 0, ii;
|
|
137
|
+
for (ii = 0; ii < uncompressed.length; ii += 1) {
|
|
138
|
+
context_c = uncompressed.charAt(ii);
|
|
139
|
+
if (!Object.prototype.hasOwnProperty.call(context_dictionary, context_c)) {
|
|
140
|
+
context_dictionary[context_c] = context_dictSize++;
|
|
141
|
+
context_dictionaryToCreate[context_c] = true;
|
|
142
|
+
}
|
|
143
|
+
context_wc = context_w + context_c;
|
|
144
|
+
if (Object.prototype.hasOwnProperty.call(context_dictionary, context_wc)) {
|
|
145
|
+
context_w = context_wc;
|
|
146
|
+
} else {
|
|
147
|
+
if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) {
|
|
148
|
+
if (context_w.charCodeAt(0) < 256) {
|
|
149
|
+
for (i = 0; i < context_numBits; i++) {
|
|
150
|
+
context_data_val = context_data_val << 1;
|
|
151
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
152
|
+
context_data_position = 0;
|
|
153
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
154
|
+
context_data_val = 0;
|
|
155
|
+
} else {
|
|
156
|
+
context_data_position++;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
value = context_w.charCodeAt(0);
|
|
160
|
+
for (i = 0; i < 8; i++) {
|
|
161
|
+
context_data_val = context_data_val << 1 | value & 1;
|
|
162
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
163
|
+
context_data_position = 0;
|
|
164
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
165
|
+
context_data_val = 0;
|
|
166
|
+
} else {
|
|
167
|
+
context_data_position++;
|
|
168
|
+
}
|
|
169
|
+
value = value >> 1;
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
value = 1;
|
|
173
|
+
for (i = 0; i < context_numBits; i++) {
|
|
174
|
+
context_data_val = context_data_val << 1 | value;
|
|
175
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
176
|
+
context_data_position = 0;
|
|
177
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
178
|
+
context_data_val = 0;
|
|
179
|
+
} else {
|
|
180
|
+
context_data_position++;
|
|
181
|
+
}
|
|
182
|
+
value = 0;
|
|
183
|
+
}
|
|
184
|
+
value = context_w.charCodeAt(0);
|
|
185
|
+
for (i = 0; i < 16; i++) {
|
|
186
|
+
context_data_val = context_data_val << 1 | value & 1;
|
|
187
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
188
|
+
context_data_position = 0;
|
|
189
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
190
|
+
context_data_val = 0;
|
|
191
|
+
} else {
|
|
192
|
+
context_data_position++;
|
|
193
|
+
}
|
|
194
|
+
value = value >> 1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
context_enlargeIn--;
|
|
198
|
+
if (context_enlargeIn == 0) {
|
|
199
|
+
context_enlargeIn = Math.pow(2, context_numBits);
|
|
200
|
+
context_numBits++;
|
|
201
|
+
}
|
|
202
|
+
delete context_dictionaryToCreate[context_w];
|
|
203
|
+
} else {
|
|
204
|
+
value = context_dictionary[context_w];
|
|
205
|
+
for (i = 0; i < context_numBits; i++) {
|
|
206
|
+
context_data_val = context_data_val << 1 | value & 1;
|
|
207
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
208
|
+
context_data_position = 0;
|
|
209
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
210
|
+
context_data_val = 0;
|
|
211
|
+
} else {
|
|
212
|
+
context_data_position++;
|
|
213
|
+
}
|
|
214
|
+
value = value >> 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
context_enlargeIn--;
|
|
218
|
+
if (context_enlargeIn == 0) {
|
|
219
|
+
context_enlargeIn = Math.pow(2, context_numBits);
|
|
220
|
+
context_numBits++;
|
|
221
|
+
}
|
|
222
|
+
context_dictionary[context_wc] = context_dictSize++;
|
|
223
|
+
context_w = String(context_c);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (context_w !== "") {
|
|
227
|
+
if (Object.prototype.hasOwnProperty.call(context_dictionaryToCreate, context_w)) {
|
|
228
|
+
if (context_w.charCodeAt(0) < 256) {
|
|
229
|
+
for (i = 0; i < context_numBits; i++) {
|
|
230
|
+
context_data_val = context_data_val << 1;
|
|
231
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
232
|
+
context_data_position = 0;
|
|
233
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
234
|
+
context_data_val = 0;
|
|
235
|
+
} else {
|
|
236
|
+
context_data_position++;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
value = context_w.charCodeAt(0);
|
|
240
|
+
for (i = 0; i < 8; i++) {
|
|
241
|
+
context_data_val = context_data_val << 1 | value & 1;
|
|
242
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
243
|
+
context_data_position = 0;
|
|
244
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
245
|
+
context_data_val = 0;
|
|
246
|
+
} else {
|
|
247
|
+
context_data_position++;
|
|
248
|
+
}
|
|
249
|
+
value = value >> 1;
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
value = 1;
|
|
253
|
+
for (i = 0; i < context_numBits; i++) {
|
|
254
|
+
context_data_val = context_data_val << 1 | value;
|
|
255
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
256
|
+
context_data_position = 0;
|
|
257
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
258
|
+
context_data_val = 0;
|
|
259
|
+
} else {
|
|
260
|
+
context_data_position++;
|
|
261
|
+
}
|
|
262
|
+
value = 0;
|
|
263
|
+
}
|
|
264
|
+
value = context_w.charCodeAt(0);
|
|
265
|
+
for (i = 0; i < 16; i++) {
|
|
266
|
+
context_data_val = context_data_val << 1 | value & 1;
|
|
267
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
268
|
+
context_data_position = 0;
|
|
269
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
270
|
+
context_data_val = 0;
|
|
271
|
+
} else {
|
|
272
|
+
context_data_position++;
|
|
273
|
+
}
|
|
274
|
+
value = value >> 1;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
context_enlargeIn--;
|
|
278
|
+
if (context_enlargeIn == 0) {
|
|
279
|
+
context_enlargeIn = Math.pow(2, context_numBits);
|
|
280
|
+
context_numBits++;
|
|
281
|
+
}
|
|
282
|
+
delete context_dictionaryToCreate[context_w];
|
|
283
|
+
} else {
|
|
284
|
+
value = context_dictionary[context_w];
|
|
285
|
+
for (i = 0; i < context_numBits; i++) {
|
|
286
|
+
context_data_val = context_data_val << 1 | value & 1;
|
|
287
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
288
|
+
context_data_position = 0;
|
|
289
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
290
|
+
context_data_val = 0;
|
|
291
|
+
} else {
|
|
292
|
+
context_data_position++;
|
|
293
|
+
}
|
|
294
|
+
value = value >> 1;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
context_enlargeIn--;
|
|
298
|
+
if (context_enlargeIn == 0) {
|
|
299
|
+
context_enlargeIn = Math.pow(2, context_numBits);
|
|
300
|
+
context_numBits++;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
value = 2;
|
|
304
|
+
for (i = 0; i < context_numBits; i++) {
|
|
305
|
+
context_data_val = context_data_val << 1 | value & 1;
|
|
306
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
307
|
+
context_data_position = 0;
|
|
308
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
309
|
+
context_data_val = 0;
|
|
310
|
+
} else {
|
|
311
|
+
context_data_position++;
|
|
312
|
+
}
|
|
313
|
+
value = value >> 1;
|
|
314
|
+
}
|
|
315
|
+
while (true) {
|
|
316
|
+
context_data_val = context_data_val << 1;
|
|
317
|
+
if (context_data_position == bitsPerChar - 1) {
|
|
318
|
+
context_data.push(getCharFromInt(context_data_val));
|
|
319
|
+
break;
|
|
320
|
+
} else context_data_position++;
|
|
321
|
+
}
|
|
322
|
+
return context_data.join("");
|
|
323
|
+
},
|
|
324
|
+
decompress: function(compressed) {
|
|
325
|
+
if (compressed == null) return "";
|
|
326
|
+
if (compressed == "") return null;
|
|
327
|
+
return LZString2._decompress(compressed.length, 32768, function(index) {
|
|
328
|
+
return compressed.charCodeAt(index);
|
|
329
|
+
});
|
|
330
|
+
},
|
|
331
|
+
_decompress: function(length, resetValue, getNextValue) {
|
|
332
|
+
var dictionary = [], next, enlargeIn = 4, dictSize = 4, numBits = 3, entry = "", result = [], i, w, bits, resb, maxpower, power, c, data = { val: getNextValue(0), position: resetValue, index: 1 };
|
|
333
|
+
for (i = 0; i < 3; i += 1) {
|
|
334
|
+
dictionary[i] = i;
|
|
335
|
+
}
|
|
336
|
+
bits = 0;
|
|
337
|
+
maxpower = Math.pow(2, 2);
|
|
338
|
+
power = 1;
|
|
339
|
+
while (power != maxpower) {
|
|
340
|
+
resb = data.val & data.position;
|
|
341
|
+
data.position >>= 1;
|
|
342
|
+
if (data.position == 0) {
|
|
343
|
+
data.position = resetValue;
|
|
344
|
+
data.val = getNextValue(data.index++);
|
|
345
|
+
}
|
|
346
|
+
bits |= (resb > 0 ? 1 : 0) * power;
|
|
347
|
+
power <<= 1;
|
|
348
|
+
}
|
|
349
|
+
switch (next = bits) {
|
|
350
|
+
case 0:
|
|
351
|
+
bits = 0;
|
|
352
|
+
maxpower = Math.pow(2, 8);
|
|
353
|
+
power = 1;
|
|
354
|
+
while (power != maxpower) {
|
|
355
|
+
resb = data.val & data.position;
|
|
356
|
+
data.position >>= 1;
|
|
357
|
+
if (data.position == 0) {
|
|
358
|
+
data.position = resetValue;
|
|
359
|
+
data.val = getNextValue(data.index++);
|
|
360
|
+
}
|
|
361
|
+
bits |= (resb > 0 ? 1 : 0) * power;
|
|
362
|
+
power <<= 1;
|
|
363
|
+
}
|
|
364
|
+
c = f(bits);
|
|
365
|
+
break;
|
|
366
|
+
case 1:
|
|
367
|
+
bits = 0;
|
|
368
|
+
maxpower = Math.pow(2, 16);
|
|
369
|
+
power = 1;
|
|
370
|
+
while (power != maxpower) {
|
|
371
|
+
resb = data.val & data.position;
|
|
372
|
+
data.position >>= 1;
|
|
373
|
+
if (data.position == 0) {
|
|
374
|
+
data.position = resetValue;
|
|
375
|
+
data.val = getNextValue(data.index++);
|
|
376
|
+
}
|
|
377
|
+
bits |= (resb > 0 ? 1 : 0) * power;
|
|
378
|
+
power <<= 1;
|
|
379
|
+
}
|
|
380
|
+
c = f(bits);
|
|
381
|
+
break;
|
|
382
|
+
case 2:
|
|
383
|
+
return "";
|
|
384
|
+
}
|
|
385
|
+
dictionary[3] = c;
|
|
386
|
+
w = c;
|
|
387
|
+
result.push(c);
|
|
388
|
+
while (true) {
|
|
389
|
+
if (data.index > length) {
|
|
390
|
+
return "";
|
|
391
|
+
}
|
|
392
|
+
bits = 0;
|
|
393
|
+
maxpower = Math.pow(2, numBits);
|
|
394
|
+
power = 1;
|
|
395
|
+
while (power != maxpower) {
|
|
396
|
+
resb = data.val & data.position;
|
|
397
|
+
data.position >>= 1;
|
|
398
|
+
if (data.position == 0) {
|
|
399
|
+
data.position = resetValue;
|
|
400
|
+
data.val = getNextValue(data.index++);
|
|
401
|
+
}
|
|
402
|
+
bits |= (resb > 0 ? 1 : 0) * power;
|
|
403
|
+
power <<= 1;
|
|
404
|
+
}
|
|
405
|
+
switch (c = bits) {
|
|
406
|
+
case 0:
|
|
407
|
+
bits = 0;
|
|
408
|
+
maxpower = Math.pow(2, 8);
|
|
409
|
+
power = 1;
|
|
410
|
+
while (power != maxpower) {
|
|
411
|
+
resb = data.val & data.position;
|
|
412
|
+
data.position >>= 1;
|
|
413
|
+
if (data.position == 0) {
|
|
414
|
+
data.position = resetValue;
|
|
415
|
+
data.val = getNextValue(data.index++);
|
|
416
|
+
}
|
|
417
|
+
bits |= (resb > 0 ? 1 : 0) * power;
|
|
418
|
+
power <<= 1;
|
|
419
|
+
}
|
|
420
|
+
dictionary[dictSize++] = f(bits);
|
|
421
|
+
c = dictSize - 1;
|
|
422
|
+
enlargeIn--;
|
|
423
|
+
break;
|
|
424
|
+
case 1:
|
|
425
|
+
bits = 0;
|
|
426
|
+
maxpower = Math.pow(2, 16);
|
|
427
|
+
power = 1;
|
|
428
|
+
while (power != maxpower) {
|
|
429
|
+
resb = data.val & data.position;
|
|
430
|
+
data.position >>= 1;
|
|
431
|
+
if (data.position == 0) {
|
|
432
|
+
data.position = resetValue;
|
|
433
|
+
data.val = getNextValue(data.index++);
|
|
434
|
+
}
|
|
435
|
+
bits |= (resb > 0 ? 1 : 0) * power;
|
|
436
|
+
power <<= 1;
|
|
437
|
+
}
|
|
438
|
+
dictionary[dictSize++] = f(bits);
|
|
439
|
+
c = dictSize - 1;
|
|
440
|
+
enlargeIn--;
|
|
441
|
+
break;
|
|
442
|
+
case 2:
|
|
443
|
+
return result.join("");
|
|
444
|
+
}
|
|
445
|
+
if (enlargeIn == 0) {
|
|
446
|
+
enlargeIn = Math.pow(2, numBits);
|
|
447
|
+
numBits++;
|
|
448
|
+
}
|
|
449
|
+
if (dictionary[c]) {
|
|
450
|
+
entry = dictionary[c];
|
|
451
|
+
} else {
|
|
452
|
+
if (c === dictSize) {
|
|
453
|
+
entry = w + w.charAt(0);
|
|
454
|
+
} else {
|
|
455
|
+
return null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
result.push(entry);
|
|
459
|
+
dictionary[dictSize++] = w + entry.charAt(0);
|
|
460
|
+
enlargeIn--;
|
|
461
|
+
w = entry;
|
|
462
|
+
if (enlargeIn == 0) {
|
|
463
|
+
enlargeIn = Math.pow(2, numBits);
|
|
464
|
+
numBits++;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
return LZString2;
|
|
470
|
+
})();
|
|
471
|
+
if (typeof define === "function" && define.amd) {
|
|
472
|
+
define(function() {
|
|
473
|
+
return LZString;
|
|
474
|
+
});
|
|
475
|
+
} else if (typeof module !== "undefined" && module != null) {
|
|
476
|
+
module.exports = LZString;
|
|
477
|
+
} else if (typeof angular !== "undefined" && angular != null) {
|
|
478
|
+
angular.module("LZString", []).factory("LZString", function() {
|
|
479
|
+
return LZString;
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
// ../../packages/schema/dist/plan.mjs
|
|
486
|
+
import { z } from "zod";
|
|
487
|
+
import { nanoid } from "nanoid";
|
|
488
|
+
var PlanStatusValues = [
|
|
489
|
+
"draft",
|
|
490
|
+
"pending_review",
|
|
491
|
+
"changes_requested",
|
|
492
|
+
"in_progress",
|
|
493
|
+
"completed"
|
|
494
|
+
];
|
|
495
|
+
var OriginPlatformValues = [
|
|
496
|
+
"claude-code",
|
|
497
|
+
"devin",
|
|
498
|
+
"cursor",
|
|
499
|
+
"windsurf",
|
|
500
|
+
"aider",
|
|
501
|
+
"unknown"
|
|
502
|
+
];
|
|
503
|
+
var ClaudeCodeOriginMetadataSchema = z.object({
|
|
504
|
+
platform: z.literal("claude-code"),
|
|
505
|
+
sessionId: z.string(),
|
|
506
|
+
transcriptPath: z.string(),
|
|
507
|
+
cwd: z.string().optional()
|
|
508
|
+
});
|
|
509
|
+
var DevinOriginMetadataSchema = z.object({
|
|
510
|
+
platform: z.literal("devin"),
|
|
511
|
+
sessionId: z.string()
|
|
512
|
+
});
|
|
513
|
+
var CursorOriginMetadataSchema = z.object({
|
|
514
|
+
platform: z.literal("cursor"),
|
|
515
|
+
conversationId: z.string(),
|
|
516
|
+
generationId: z.string().optional()
|
|
517
|
+
});
|
|
518
|
+
var UnknownOriginMetadataSchema = z.object({ platform: z.literal("unknown") });
|
|
519
|
+
var OriginMetadataSchema = z.discriminatedUnion("platform", [
|
|
520
|
+
ClaudeCodeOriginMetadataSchema,
|
|
521
|
+
DevinOriginMetadataSchema,
|
|
522
|
+
CursorOriginMetadataSchema,
|
|
523
|
+
UnknownOriginMetadataSchema
|
|
524
|
+
]);
|
|
525
|
+
var ConversationVersionBaseSchema = z.object({
|
|
526
|
+
versionId: z.string(),
|
|
527
|
+
creator: z.string(),
|
|
528
|
+
platform: z.enum(OriginPlatformValues),
|
|
529
|
+
sessionId: z.string(),
|
|
530
|
+
messageCount: z.number(),
|
|
531
|
+
createdAt: z.number()
|
|
532
|
+
});
|
|
533
|
+
var ConversationVersionSchema = z.discriminatedUnion("handedOff", [ConversationVersionBaseSchema.extend({ handedOff: z.literal(false) }), ConversationVersionBaseSchema.extend({
|
|
534
|
+
handedOff: z.literal(true),
|
|
535
|
+
handedOffAt: z.number(),
|
|
536
|
+
handedOffTo: z.string()
|
|
537
|
+
})]);
|
|
538
|
+
var PlanEventBaseSchema = z.object({
|
|
539
|
+
id: z.string(),
|
|
540
|
+
actor: z.string(),
|
|
541
|
+
timestamp: z.number(),
|
|
542
|
+
inboxWorthy: z.boolean().optional(),
|
|
543
|
+
inboxFor: z.union([z.string(), z.array(z.string())]).optional()
|
|
544
|
+
});
|
|
545
|
+
var AgentActivityDataSchema = z.discriminatedUnion("activityType", [
|
|
546
|
+
z.object({
|
|
547
|
+
activityType: z.literal("help_request"),
|
|
548
|
+
requestId: z.string(),
|
|
549
|
+
message: z.string()
|
|
550
|
+
}),
|
|
551
|
+
z.object({
|
|
552
|
+
activityType: z.literal("help_request_resolved"),
|
|
553
|
+
requestId: z.string(),
|
|
554
|
+
resolution: z.string().optional()
|
|
555
|
+
}),
|
|
556
|
+
z.object({
|
|
557
|
+
activityType: z.literal("blocker"),
|
|
558
|
+
message: z.string(),
|
|
559
|
+
requestId: z.string()
|
|
560
|
+
}),
|
|
561
|
+
z.object({
|
|
562
|
+
activityType: z.literal("blocker_resolved"),
|
|
563
|
+
requestId: z.string(),
|
|
564
|
+
resolution: z.string().optional()
|
|
565
|
+
})
|
|
566
|
+
]);
|
|
567
|
+
var PlanEventSchema = z.discriminatedUnion("type", [
|
|
568
|
+
PlanEventBaseSchema.extend({ type: z.enum([
|
|
569
|
+
"plan_created",
|
|
570
|
+
"content_edited",
|
|
571
|
+
"plan_archived",
|
|
572
|
+
"plan_unarchived",
|
|
573
|
+
"plan_shared"
|
|
574
|
+
]) }),
|
|
575
|
+
PlanEventBaseSchema.extend({
|
|
576
|
+
type: z.literal("status_changed"),
|
|
577
|
+
data: z.object({
|
|
578
|
+
fromStatus: z.enum(PlanStatusValues),
|
|
579
|
+
toStatus: z.enum(PlanStatusValues)
|
|
580
|
+
})
|
|
581
|
+
}),
|
|
582
|
+
PlanEventBaseSchema.extend({
|
|
583
|
+
type: z.literal("artifact_uploaded"),
|
|
584
|
+
data: z.object({ artifactId: z.string() })
|
|
585
|
+
}),
|
|
586
|
+
PlanEventBaseSchema.extend({
|
|
587
|
+
type: z.literal("comment_added"),
|
|
588
|
+
data: z.object({
|
|
589
|
+
commentId: z.string().optional(),
|
|
590
|
+
prNumber: z.number().optional(),
|
|
591
|
+
mentions: z.boolean().optional()
|
|
592
|
+
}).optional()
|
|
593
|
+
}),
|
|
594
|
+
PlanEventBaseSchema.extend({
|
|
595
|
+
type: z.literal("comment_resolved"),
|
|
596
|
+
data: z.object({
|
|
597
|
+
commentId: z.string().optional(),
|
|
598
|
+
resolvedCount: z.number().optional()
|
|
599
|
+
}).optional()
|
|
600
|
+
}),
|
|
601
|
+
PlanEventBaseSchema.extend({
|
|
602
|
+
type: z.literal("deliverable_linked"),
|
|
603
|
+
data: z.object({
|
|
604
|
+
deliverableId: z.string().optional(),
|
|
605
|
+
artifactId: z.string().optional(),
|
|
606
|
+
allFulfilled: z.boolean().optional()
|
|
607
|
+
}).optional()
|
|
608
|
+
}),
|
|
609
|
+
PlanEventBaseSchema.extend({
|
|
610
|
+
type: z.literal("pr_linked"),
|
|
611
|
+
data: z.object({
|
|
612
|
+
prNumber: z.number(),
|
|
613
|
+
url: z.string().optional()
|
|
614
|
+
})
|
|
615
|
+
}),
|
|
616
|
+
PlanEventBaseSchema.extend({
|
|
617
|
+
type: z.enum(["approved", "changes_requested"]),
|
|
618
|
+
data: z.object({ comment: z.string().optional() }).optional()
|
|
619
|
+
}),
|
|
620
|
+
PlanEventBaseSchema.extend({ type: z.literal("completed") }),
|
|
621
|
+
PlanEventBaseSchema.extend({
|
|
622
|
+
type: z.literal("step_completed"),
|
|
623
|
+
data: z.object({
|
|
624
|
+
stepId: z.string(),
|
|
625
|
+
completed: z.boolean()
|
|
626
|
+
})
|
|
627
|
+
}),
|
|
628
|
+
PlanEventBaseSchema.extend({
|
|
629
|
+
type: z.literal("conversation_imported"),
|
|
630
|
+
data: z.object({
|
|
631
|
+
sourcePlatform: z.string().optional(),
|
|
632
|
+
messageCount: z.number(),
|
|
633
|
+
sourceSessionId: z.string().optional()
|
|
634
|
+
})
|
|
635
|
+
}),
|
|
636
|
+
PlanEventBaseSchema.extend({
|
|
637
|
+
type: z.literal("conversation_exported"),
|
|
638
|
+
data: z.object({ messageCount: z.number() })
|
|
639
|
+
}),
|
|
640
|
+
PlanEventBaseSchema.extend({
|
|
641
|
+
type: z.literal("conversation_handed_off"),
|
|
642
|
+
data: z.object({
|
|
643
|
+
handedOffTo: z.string(),
|
|
644
|
+
messageCount: z.number()
|
|
645
|
+
})
|
|
646
|
+
}),
|
|
647
|
+
PlanEventBaseSchema.extend({
|
|
648
|
+
type: z.literal("approval_requested"),
|
|
649
|
+
data: z.object({ requesterName: z.string().optional() }).optional()
|
|
650
|
+
}),
|
|
651
|
+
PlanEventBaseSchema.extend({
|
|
652
|
+
type: z.literal("input_request_created"),
|
|
653
|
+
data: z.object({
|
|
654
|
+
requestId: z.string(),
|
|
655
|
+
requestType: z.enum([
|
|
656
|
+
"text",
|
|
657
|
+
"multiline",
|
|
658
|
+
"choice",
|
|
659
|
+
"confirm"
|
|
660
|
+
]),
|
|
661
|
+
requestMessage: z.string()
|
|
662
|
+
})
|
|
663
|
+
}),
|
|
664
|
+
PlanEventBaseSchema.extend({
|
|
665
|
+
type: z.literal("input_request_answered"),
|
|
666
|
+
data: z.object({
|
|
667
|
+
requestId: z.string(),
|
|
668
|
+
response: z.unknown(),
|
|
669
|
+
answeredBy: z.string()
|
|
670
|
+
})
|
|
671
|
+
}),
|
|
672
|
+
PlanEventBaseSchema.extend({
|
|
673
|
+
type: z.literal("input_request_declined"),
|
|
674
|
+
data: z.object({ requestId: z.string() })
|
|
675
|
+
}),
|
|
676
|
+
PlanEventBaseSchema.extend({
|
|
677
|
+
type: z.literal("agent_activity"),
|
|
678
|
+
data: AgentActivityDataSchema
|
|
679
|
+
})
|
|
680
|
+
]);
|
|
681
|
+
var PlanMetadataBaseSchema = z.object({
|
|
682
|
+
id: z.string(),
|
|
683
|
+
title: z.string(),
|
|
684
|
+
createdAt: z.number(),
|
|
685
|
+
updatedAt: z.number(),
|
|
686
|
+
repo: z.string().optional(),
|
|
687
|
+
pr: z.number().optional(),
|
|
688
|
+
ownerId: z.string().optional(),
|
|
689
|
+
approvalRequired: z.boolean().optional(),
|
|
690
|
+
approvedUsers: z.array(z.string()).optional(),
|
|
691
|
+
rejectedUsers: z.array(z.string()).optional(),
|
|
692
|
+
sessionTokenHash: z.string().optional(),
|
|
693
|
+
archivedAt: z.number().optional(),
|
|
694
|
+
archivedBy: z.string().optional(),
|
|
695
|
+
origin: OriginMetadataSchema.optional(),
|
|
696
|
+
viewedBy: z.record(z.string(), z.number()).optional(),
|
|
697
|
+
conversationVersions: z.array(ConversationVersionSchema).optional(),
|
|
698
|
+
events: z.array(PlanEventSchema).optional(),
|
|
699
|
+
tags: z.array(z.string()).optional()
|
|
700
|
+
});
|
|
701
|
+
var PlanMetadataSchema = z.discriminatedUnion("status", [
|
|
702
|
+
PlanMetadataBaseSchema.extend({ status: z.literal("draft") }),
|
|
703
|
+
PlanMetadataBaseSchema.extend({
|
|
704
|
+
status: z.literal("pending_review"),
|
|
705
|
+
reviewRequestId: z.string()
|
|
706
|
+
}),
|
|
707
|
+
PlanMetadataBaseSchema.extend({
|
|
708
|
+
status: z.literal("changes_requested"),
|
|
709
|
+
reviewedAt: z.number(),
|
|
710
|
+
reviewedBy: z.string(),
|
|
711
|
+
reviewComment: z.string().optional()
|
|
712
|
+
}),
|
|
713
|
+
PlanMetadataBaseSchema.extend({
|
|
714
|
+
status: z.literal("in_progress"),
|
|
715
|
+
reviewedAt: z.number(),
|
|
716
|
+
reviewedBy: z.string(),
|
|
717
|
+
reviewComment: z.string().optional()
|
|
718
|
+
}),
|
|
719
|
+
PlanMetadataBaseSchema.extend({
|
|
720
|
+
status: z.literal("completed"),
|
|
721
|
+
completedAt: z.number(),
|
|
722
|
+
completedBy: z.string(),
|
|
723
|
+
snapshotUrl: z.string().optional()
|
|
724
|
+
})
|
|
725
|
+
]);
|
|
726
|
+
var BaseArtifactSchema = z.object({
|
|
727
|
+
id: z.string(),
|
|
728
|
+
type: z.enum([
|
|
729
|
+
"screenshot",
|
|
730
|
+
"video",
|
|
731
|
+
"test_results",
|
|
732
|
+
"diff"
|
|
733
|
+
]),
|
|
734
|
+
filename: z.string(),
|
|
735
|
+
description: z.string().optional(),
|
|
736
|
+
uploadedAt: z.number().optional()
|
|
737
|
+
});
|
|
738
|
+
var GitHubArtifactSchema = BaseArtifactSchema.extend({
|
|
739
|
+
storage: z.literal("github"),
|
|
740
|
+
url: z.string()
|
|
741
|
+
});
|
|
742
|
+
var LocalArtifactSchema = BaseArtifactSchema.extend({
|
|
743
|
+
storage: z.literal("local"),
|
|
744
|
+
localArtifactId: z.string()
|
|
745
|
+
});
|
|
746
|
+
var ArtifactSchema = z.discriminatedUnion("storage", [GitHubArtifactSchema, LocalArtifactSchema]);
|
|
747
|
+
var DeliverableSchema = z.object({
|
|
748
|
+
id: z.string(),
|
|
749
|
+
text: z.string(),
|
|
750
|
+
linkedArtifactId: z.string().optional(),
|
|
751
|
+
linkedAt: z.number().optional()
|
|
752
|
+
});
|
|
753
|
+
var PlanSnapshotSchema = z.object({
|
|
754
|
+
id: z.string(),
|
|
755
|
+
status: z.enum(PlanStatusValues),
|
|
756
|
+
createdBy: z.string(),
|
|
757
|
+
reason: z.string(),
|
|
758
|
+
createdAt: z.number(),
|
|
759
|
+
content: z.array(z.unknown()),
|
|
760
|
+
threadSummary: z.object({
|
|
761
|
+
total: z.number(),
|
|
762
|
+
unresolved: z.number()
|
|
763
|
+
}).optional(),
|
|
764
|
+
artifacts: z.array(ArtifactSchema).optional(),
|
|
765
|
+
deliverables: z.array(DeliverableSchema).optional()
|
|
766
|
+
});
|
|
767
|
+
var LinkedPRStatusValues = [
|
|
768
|
+
"draft",
|
|
769
|
+
"open",
|
|
770
|
+
"merged",
|
|
771
|
+
"closed"
|
|
772
|
+
];
|
|
773
|
+
var LinkedPRSchema = z.object({
|
|
774
|
+
prNumber: z.number(),
|
|
775
|
+
url: z.string(),
|
|
776
|
+
linkedAt: z.number(),
|
|
777
|
+
status: z.enum(LinkedPRStatusValues),
|
|
778
|
+
branch: z.string().optional(),
|
|
779
|
+
title: z.string().optional()
|
|
780
|
+
});
|
|
781
|
+
var PRReviewCommentSchema = z.object({
|
|
782
|
+
id: z.string(),
|
|
783
|
+
prNumber: z.number(),
|
|
784
|
+
path: z.string(),
|
|
785
|
+
line: z.number(),
|
|
786
|
+
body: z.string(),
|
|
787
|
+
author: z.string(),
|
|
788
|
+
createdAt: z.number(),
|
|
789
|
+
resolved: z.boolean().optional()
|
|
790
|
+
});
|
|
791
|
+
|
|
792
|
+
// ../../packages/schema/dist/yjs-helpers-xzZyVQl7.mjs
|
|
793
|
+
import { z as z2 } from "zod";
|
|
794
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
795
|
+
import * as Y from "yjs";
|
|
796
|
+
function assertNever(value) {
|
|
797
|
+
throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);
|
|
798
|
+
}
|
|
799
|
+
var AgentPresenceSchema = z2.object({
|
|
800
|
+
agentType: z2.string(),
|
|
801
|
+
sessionId: z2.string(),
|
|
802
|
+
connectedAt: z2.number(),
|
|
803
|
+
lastSeenAt: z2.number()
|
|
804
|
+
});
|
|
805
|
+
var ReviewCommentSchema = z2.object({
|
|
806
|
+
author: z2.string(),
|
|
807
|
+
content: z2.string(),
|
|
808
|
+
createdAt: z2.number()
|
|
809
|
+
});
|
|
810
|
+
var ReviewFeedbackSchema = z2.object({
|
|
811
|
+
threadId: z2.string(),
|
|
812
|
+
blockId: z2.string().optional(),
|
|
813
|
+
comments: z2.array(ReviewCommentSchema)
|
|
814
|
+
});
|
|
815
|
+
var CreateHookSessionRequestSchema = z2.object({
|
|
816
|
+
sessionId: z2.string(),
|
|
817
|
+
agentType: z2.string().default("claude-code"),
|
|
818
|
+
metadata: z2.record(z2.string(), z2.unknown()).optional()
|
|
819
|
+
});
|
|
820
|
+
var CreateHookSessionResponseSchema = z2.object({
|
|
821
|
+
planId: z2.string(),
|
|
822
|
+
url: z2.string()
|
|
823
|
+
});
|
|
824
|
+
var UpdatePlanContentRequestSchema = z2.object({
|
|
825
|
+
content: z2.string(),
|
|
826
|
+
filePath: z2.string().optional()
|
|
827
|
+
});
|
|
828
|
+
var UpdatePlanContentResponseSchema = z2.object({
|
|
829
|
+
success: z2.boolean(),
|
|
830
|
+
updatedAt: z2.number()
|
|
831
|
+
});
|
|
832
|
+
var GetReviewStatusResponseSchema = z2.discriminatedUnion("status", [
|
|
833
|
+
z2.object({ status: z2.literal("draft") }),
|
|
834
|
+
z2.object({
|
|
835
|
+
status: z2.literal("pending_review"),
|
|
836
|
+
reviewRequestId: z2.string()
|
|
837
|
+
}),
|
|
838
|
+
z2.object({
|
|
839
|
+
status: z2.literal("changes_requested"),
|
|
840
|
+
reviewedAt: z2.number(),
|
|
841
|
+
reviewedBy: z2.string(),
|
|
842
|
+
reviewComment: z2.string().optional(),
|
|
843
|
+
feedback: z2.array(ReviewFeedbackSchema).optional()
|
|
844
|
+
}),
|
|
845
|
+
z2.object({
|
|
846
|
+
status: z2.literal("in_progress"),
|
|
847
|
+
reviewedAt: z2.number(),
|
|
848
|
+
reviewedBy: z2.string()
|
|
849
|
+
}),
|
|
850
|
+
z2.object({
|
|
851
|
+
status: z2.literal("completed"),
|
|
852
|
+
completedAt: z2.number(),
|
|
853
|
+
completedBy: z2.string(),
|
|
854
|
+
snapshotUrl: z2.string().optional()
|
|
855
|
+
})
|
|
856
|
+
]);
|
|
857
|
+
var UpdatePresenceRequestSchema = z2.object({
|
|
858
|
+
agentType: z2.string(),
|
|
859
|
+
sessionId: z2.string()
|
|
860
|
+
});
|
|
861
|
+
var UpdatePresenceResponseSchema = z2.object({ success: z2.boolean() });
|
|
862
|
+
var HookApiErrorSchema = z2.object({ error: z2.string() });
|
|
863
|
+
var RegisterServerRequestSchema = z2.object({
|
|
864
|
+
port: z2.number().int().positive(),
|
|
865
|
+
pid: z2.number().int().positive()
|
|
866
|
+
});
|
|
867
|
+
var RegisterServerResponseSchema = z2.object({
|
|
868
|
+
success: z2.boolean(),
|
|
869
|
+
entry: z2.object({
|
|
870
|
+
port: z2.number(),
|
|
871
|
+
pid: z2.number(),
|
|
872
|
+
url: z2.string(),
|
|
873
|
+
registeredAt: z2.number()
|
|
874
|
+
})
|
|
875
|
+
});
|
|
876
|
+
var UnregisterServerRequestSchema = z2.object({ pid: z2.number().int().positive() });
|
|
877
|
+
var UnregisterServerResponseSchema = z2.object({
|
|
878
|
+
success: z2.boolean(),
|
|
879
|
+
existed: z2.boolean()
|
|
880
|
+
});
|
|
881
|
+
var CreateSubscriptionRequestSchema = z2.object({
|
|
882
|
+
subscribe: z2.array(z2.string()).optional(),
|
|
883
|
+
windowMs: z2.number().positive().optional(),
|
|
884
|
+
maxWindowMs: z2.number().positive().optional(),
|
|
885
|
+
threshold: z2.number().positive().optional()
|
|
886
|
+
});
|
|
887
|
+
var CreateSubscriptionResponseSchema = z2.object({ clientId: z2.string() });
|
|
888
|
+
var InputRequestStatusValues = [
|
|
889
|
+
"pending",
|
|
890
|
+
"answered",
|
|
891
|
+
"declined",
|
|
892
|
+
"cancelled"
|
|
893
|
+
];
|
|
894
|
+
var InputRequestBaseSchema = z2.object({
|
|
895
|
+
id: z2.string(),
|
|
896
|
+
createdAt: z2.number(),
|
|
897
|
+
message: z2.string().min(1, "Message cannot be empty"),
|
|
898
|
+
status: z2.enum(InputRequestStatusValues),
|
|
899
|
+
defaultValue: z2.string().optional(),
|
|
900
|
+
timeout: z2.number().int().min(10, "Timeout must be at least 10 seconds").max(900, "Timeout cannot exceed 15 minutes").optional(),
|
|
901
|
+
planId: z2.string().optional(),
|
|
902
|
+
response: z2.unknown().optional(),
|
|
903
|
+
answeredAt: z2.number().optional(),
|
|
904
|
+
answeredBy: z2.string().optional()
|
|
905
|
+
});
|
|
906
|
+
var TextInputSchema = InputRequestBaseSchema.extend({ type: z2.literal("text") });
|
|
907
|
+
var MultilineInputSchema = InputRequestBaseSchema.extend({ type: z2.literal("multiline") });
|
|
908
|
+
var ChoiceInputSchema = InputRequestBaseSchema.extend({
|
|
909
|
+
type: z2.literal("choice"),
|
|
910
|
+
options: z2.array(z2.string()).min(1, "Choice requests must have at least one option"),
|
|
911
|
+
multiSelect: z2.boolean().optional()
|
|
912
|
+
});
|
|
913
|
+
var ConfirmInputSchema = InputRequestBaseSchema.extend({ type: z2.literal("confirm") });
|
|
914
|
+
var InputRequestSchema = z2.discriminatedUnion("type", [
|
|
915
|
+
TextInputSchema,
|
|
916
|
+
MultilineInputSchema,
|
|
917
|
+
ChoiceInputSchema,
|
|
918
|
+
ConfirmInputSchema
|
|
919
|
+
]);
|
|
920
|
+
var YDOC_KEYS = {
|
|
921
|
+
METADATA: "metadata",
|
|
922
|
+
DOCUMENT_FRAGMENT: "document",
|
|
923
|
+
THREADS: "threads",
|
|
924
|
+
STEP_COMPLETIONS: "stepCompletions",
|
|
925
|
+
PLANS: "plans",
|
|
926
|
+
ARTIFACTS: "artifacts",
|
|
927
|
+
DELIVERABLES: "deliverables",
|
|
928
|
+
PRESENCE: "presence",
|
|
929
|
+
LINKED_PRS: "linkedPRs",
|
|
930
|
+
PR_REVIEW_COMMENTS: "prReviewComments",
|
|
931
|
+
EVENTS: "events",
|
|
932
|
+
SNAPSHOTS: "snapshots",
|
|
933
|
+
INPUT_REQUESTS: "inputRequests"
|
|
934
|
+
};
|
|
935
|
+
var CommentBodySchema = z2.union([z2.string(), z2.array(z2.unknown())]);
|
|
936
|
+
var ThreadCommentSchema = z2.object({
|
|
937
|
+
id: z2.string(),
|
|
938
|
+
userId: z2.string(),
|
|
939
|
+
body: CommentBodySchema,
|
|
940
|
+
createdAt: z2.number()
|
|
941
|
+
});
|
|
942
|
+
var ThreadSchema = z2.object({
|
|
943
|
+
id: z2.string(),
|
|
944
|
+
comments: z2.array(ThreadCommentSchema),
|
|
945
|
+
resolved: z2.boolean().optional(),
|
|
946
|
+
selectedText: z2.string().optional()
|
|
947
|
+
});
|
|
948
|
+
function extractTextFromCommentBody(body) {
|
|
949
|
+
if (typeof body === "string") return body;
|
|
950
|
+
if (!Array.isArray(body)) return "";
|
|
951
|
+
return body.map((block) => {
|
|
952
|
+
if (typeof block === "string") return block;
|
|
953
|
+
if (typeof block !== "object" || block === null) return "";
|
|
954
|
+
const blockObj = block;
|
|
955
|
+
if (Array.isArray(blockObj.content)) return blockObj.content.map((item) => {
|
|
956
|
+
if (typeof item === "string") return item;
|
|
957
|
+
if (typeof item === "object" && item !== null && "text" in item) return item.text;
|
|
958
|
+
return "";
|
|
959
|
+
}).join("");
|
|
960
|
+
return "";
|
|
961
|
+
}).join("\n");
|
|
962
|
+
}
|
|
963
|
+
function getPlanMetadata(ydoc) {
|
|
964
|
+
const result = getPlanMetadataWithValidation(ydoc);
|
|
965
|
+
return result.success ? result.data : null;
|
|
966
|
+
}
|
|
967
|
+
function getPlanMetadataWithValidation(ydoc) {
|
|
968
|
+
const data = ydoc.getMap(YDOC_KEYS.METADATA).toJSON();
|
|
969
|
+
if (!data || Object.keys(data).length === 0) return {
|
|
970
|
+
success: false,
|
|
971
|
+
error: "No metadata found in Y.Doc"
|
|
972
|
+
};
|
|
973
|
+
const result = PlanMetadataSchema.safeParse(data);
|
|
974
|
+
if (!result.success) return {
|
|
975
|
+
success: false,
|
|
976
|
+
error: `Invalid metadata: ${result.error.message}`
|
|
977
|
+
};
|
|
978
|
+
return {
|
|
979
|
+
success: true,
|
|
980
|
+
data: result.data
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// ../../packages/schema/dist/url-encoding.mjs
|
|
985
|
+
var import_lz_string = __toESM(require_lz_string(), 1);
|
|
986
|
+
|
|
987
|
+
// ../../packages/schema/dist/index.mjs
|
|
988
|
+
import { z as z3 } from "zod";
|
|
989
|
+
import * as Y2 from "yjs";
|
|
990
|
+
|
|
991
|
+
// ../../node_modules/.pnpm/@trpc+server@11.8.1_typescript@5.9.3/node_modules/@trpc/server/dist/codes-DagpWZLc.mjs
|
|
992
|
+
function mergeWithoutOverrides(obj1, ...objs) {
|
|
993
|
+
const newObj = Object.assign(emptyObject(), obj1);
|
|
994
|
+
for (const overrides of objs) for (const key in overrides) {
|
|
995
|
+
if (key in newObj && newObj[key] !== overrides[key]) throw new Error(`Duplicate key ${key}`);
|
|
996
|
+
newObj[key] = overrides[key];
|
|
997
|
+
}
|
|
998
|
+
return newObj;
|
|
999
|
+
}
|
|
1000
|
+
function isObject(value) {
|
|
1001
|
+
return !!value && !Array.isArray(value) && typeof value === "object";
|
|
1002
|
+
}
|
|
1003
|
+
function isFunction(fn) {
|
|
1004
|
+
return typeof fn === "function";
|
|
1005
|
+
}
|
|
1006
|
+
function emptyObject() {
|
|
1007
|
+
return /* @__PURE__ */ Object.create(null);
|
|
1008
|
+
}
|
|
1009
|
+
var TRPC_ERROR_CODES_BY_KEY = {
|
|
1010
|
+
PARSE_ERROR: -32700,
|
|
1011
|
+
BAD_REQUEST: -32600,
|
|
1012
|
+
INTERNAL_SERVER_ERROR: -32603,
|
|
1013
|
+
NOT_IMPLEMENTED: -32603,
|
|
1014
|
+
BAD_GATEWAY: -32603,
|
|
1015
|
+
SERVICE_UNAVAILABLE: -32603,
|
|
1016
|
+
GATEWAY_TIMEOUT: -32603,
|
|
1017
|
+
UNAUTHORIZED: -32001,
|
|
1018
|
+
PAYMENT_REQUIRED: -32002,
|
|
1019
|
+
FORBIDDEN: -32003,
|
|
1020
|
+
NOT_FOUND: -32004,
|
|
1021
|
+
METHOD_NOT_SUPPORTED: -32005,
|
|
1022
|
+
TIMEOUT: -32008,
|
|
1023
|
+
CONFLICT: -32009,
|
|
1024
|
+
PRECONDITION_FAILED: -32012,
|
|
1025
|
+
PAYLOAD_TOO_LARGE: -32013,
|
|
1026
|
+
UNSUPPORTED_MEDIA_TYPE: -32015,
|
|
1027
|
+
UNPROCESSABLE_CONTENT: -32022,
|
|
1028
|
+
PRECONDITION_REQUIRED: -32028,
|
|
1029
|
+
TOO_MANY_REQUESTS: -32029,
|
|
1030
|
+
CLIENT_CLOSED_REQUEST: -32099
|
|
1031
|
+
};
|
|
1032
|
+
var retryableRpcCodes = [
|
|
1033
|
+
TRPC_ERROR_CODES_BY_KEY.BAD_GATEWAY,
|
|
1034
|
+
TRPC_ERROR_CODES_BY_KEY.SERVICE_UNAVAILABLE,
|
|
1035
|
+
TRPC_ERROR_CODES_BY_KEY.GATEWAY_TIMEOUT,
|
|
1036
|
+
TRPC_ERROR_CODES_BY_KEY.INTERNAL_SERVER_ERROR
|
|
1037
|
+
];
|
|
1038
|
+
|
|
1039
|
+
// ../../node_modules/.pnpm/@trpc+server@11.8.1_typescript@5.9.3/node_modules/@trpc/server/dist/getErrorShape-vC8mUXJD.mjs
|
|
1040
|
+
var __create2 = Object.create;
|
|
1041
|
+
var __defProp2 = Object.defineProperty;
|
|
1042
|
+
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
1043
|
+
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
1044
|
+
var __getProtoOf2 = Object.getPrototypeOf;
|
|
1045
|
+
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
1046
|
+
var __commonJS2 = (cb, mod) => function() {
|
|
1047
|
+
return mod || (0, cb[__getOwnPropNames2(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
1048
|
+
};
|
|
1049
|
+
var __copyProps2 = (to, from, except, desc) => {
|
|
1050
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames2(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
1051
|
+
key = keys[i];
|
|
1052
|
+
if (!__hasOwnProp2.call(to, key) && key !== except) __defProp2(to, key, {
|
|
1053
|
+
get: ((k) => from[k]).bind(null, key),
|
|
1054
|
+
enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable
|
|
1055
|
+
});
|
|
1056
|
+
}
|
|
1057
|
+
return to;
|
|
1058
|
+
};
|
|
1059
|
+
var __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps2(isNodeMode || !mod || !mod.__esModule ? __defProp2(target, "default", {
|
|
1060
|
+
value: mod,
|
|
1061
|
+
enumerable: true
|
|
1062
|
+
}) : target, mod));
|
|
1063
|
+
var noop = () => {
|
|
1064
|
+
};
|
|
1065
|
+
var freezeIfAvailable = (obj) => {
|
|
1066
|
+
if (Object.freeze) Object.freeze(obj);
|
|
1067
|
+
};
|
|
1068
|
+
function createInnerProxy(callback, path, memo) {
|
|
1069
|
+
var _memo$cacheKey;
|
|
1070
|
+
const cacheKey = path.join(".");
|
|
1071
|
+
(_memo$cacheKey = memo[cacheKey]) !== null && _memo$cacheKey !== void 0 || (memo[cacheKey] = new Proxy(noop, {
|
|
1072
|
+
get(_obj, key) {
|
|
1073
|
+
if (typeof key !== "string" || key === "then") return void 0;
|
|
1074
|
+
return createInnerProxy(callback, [...path, key], memo);
|
|
1075
|
+
},
|
|
1076
|
+
apply(_1, _2, args) {
|
|
1077
|
+
const lastOfPath = path[path.length - 1];
|
|
1078
|
+
let opts = {
|
|
1079
|
+
args,
|
|
1080
|
+
path
|
|
1081
|
+
};
|
|
1082
|
+
if (lastOfPath === "call") opts = {
|
|
1083
|
+
args: args.length >= 2 ? [args[1]] : [],
|
|
1084
|
+
path: path.slice(0, -1)
|
|
1085
|
+
};
|
|
1086
|
+
else if (lastOfPath === "apply") opts = {
|
|
1087
|
+
args: args.length >= 2 ? args[1] : [],
|
|
1088
|
+
path: path.slice(0, -1)
|
|
1089
|
+
};
|
|
1090
|
+
freezeIfAvailable(opts.args);
|
|
1091
|
+
freezeIfAvailable(opts.path);
|
|
1092
|
+
return callback(opts);
|
|
1093
|
+
}
|
|
1094
|
+
}));
|
|
1095
|
+
return memo[cacheKey];
|
|
1096
|
+
}
|
|
1097
|
+
var createRecursiveProxy = (callback) => createInnerProxy(callback, [], emptyObject());
|
|
1098
|
+
var require_typeof = __commonJS2({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/typeof.js"(exports, module) {
|
|
1099
|
+
function _typeof$2(o) {
|
|
1100
|
+
"@babel/helpers - typeof";
|
|
1101
|
+
return module.exports = _typeof$2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
|
|
1102
|
+
return typeof o$1;
|
|
1103
|
+
} : function(o$1) {
|
|
1104
|
+
return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
|
|
1105
|
+
}, module.exports.__esModule = true, module.exports["default"] = module.exports, _typeof$2(o);
|
|
1106
|
+
}
|
|
1107
|
+
module.exports = _typeof$2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1108
|
+
} });
|
|
1109
|
+
var require_toPrimitive = __commonJS2({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/toPrimitive.js"(exports, module) {
|
|
1110
|
+
var _typeof$1 = require_typeof()["default"];
|
|
1111
|
+
function toPrimitive$1(t2, r) {
|
|
1112
|
+
if ("object" != _typeof$1(t2) || !t2) return t2;
|
|
1113
|
+
var e = t2[Symbol.toPrimitive];
|
|
1114
|
+
if (void 0 !== e) {
|
|
1115
|
+
var i = e.call(t2, r || "default");
|
|
1116
|
+
if ("object" != _typeof$1(i)) return i;
|
|
1117
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
1118
|
+
}
|
|
1119
|
+
return ("string" === r ? String : Number)(t2);
|
|
1120
|
+
}
|
|
1121
|
+
module.exports = toPrimitive$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1122
|
+
} });
|
|
1123
|
+
var require_toPropertyKey = __commonJS2({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/toPropertyKey.js"(exports, module) {
|
|
1124
|
+
var _typeof = require_typeof()["default"];
|
|
1125
|
+
var toPrimitive = require_toPrimitive();
|
|
1126
|
+
function toPropertyKey$1(t2) {
|
|
1127
|
+
var i = toPrimitive(t2, "string");
|
|
1128
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
1129
|
+
}
|
|
1130
|
+
module.exports = toPropertyKey$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1131
|
+
} });
|
|
1132
|
+
var require_defineProperty = __commonJS2({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/defineProperty.js"(exports, module) {
|
|
1133
|
+
var toPropertyKey = require_toPropertyKey();
|
|
1134
|
+
function _defineProperty(e, r, t2) {
|
|
1135
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
1136
|
+
value: t2,
|
|
1137
|
+
enumerable: true,
|
|
1138
|
+
configurable: true,
|
|
1139
|
+
writable: true
|
|
1140
|
+
}) : e[r] = t2, e;
|
|
1141
|
+
}
|
|
1142
|
+
module.exports = _defineProperty, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1143
|
+
} });
|
|
1144
|
+
var require_objectSpread2 = __commonJS2({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectSpread2.js"(exports, module) {
|
|
1145
|
+
var defineProperty = require_defineProperty();
|
|
1146
|
+
function ownKeys(e, r) {
|
|
1147
|
+
var t2 = Object.keys(e);
|
|
1148
|
+
if (Object.getOwnPropertySymbols) {
|
|
1149
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
1150
|
+
r && (o = o.filter(function(r$1) {
|
|
1151
|
+
return Object.getOwnPropertyDescriptor(e, r$1).enumerable;
|
|
1152
|
+
})), t2.push.apply(t2, o);
|
|
1153
|
+
}
|
|
1154
|
+
return t2;
|
|
1155
|
+
}
|
|
1156
|
+
function _objectSpread2(e) {
|
|
1157
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
1158
|
+
var t2 = null != arguments[r] ? arguments[r] : {};
|
|
1159
|
+
r % 2 ? ownKeys(Object(t2), true).forEach(function(r$1) {
|
|
1160
|
+
defineProperty(e, r$1, t2[r$1]);
|
|
1161
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t2)) : ownKeys(Object(t2)).forEach(function(r$1) {
|
|
1162
|
+
Object.defineProperty(e, r$1, Object.getOwnPropertyDescriptor(t2, r$1));
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
return e;
|
|
1166
|
+
}
|
|
1167
|
+
module.exports = _objectSpread2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1168
|
+
} });
|
|
1169
|
+
var import_objectSpread2 = __toESM2(require_objectSpread2(), 1);
|
|
1170
|
+
|
|
1171
|
+
// ../../node_modules/.pnpm/@trpc+server@11.8.1_typescript@5.9.3/node_modules/@trpc/server/dist/tracked-D4V22yc5.mjs
|
|
1172
|
+
var defaultFormatter = ({ shape }) => {
|
|
1173
|
+
return shape;
|
|
1174
|
+
};
|
|
1175
|
+
var import_defineProperty = __toESM2(require_defineProperty(), 1);
|
|
1176
|
+
var UnknownCauseError = class extends Error {
|
|
1177
|
+
};
|
|
1178
|
+
function getCauseFromUnknown(cause) {
|
|
1179
|
+
if (cause instanceof Error) return cause;
|
|
1180
|
+
const type = typeof cause;
|
|
1181
|
+
if (type === "undefined" || type === "function" || cause === null) return void 0;
|
|
1182
|
+
if (type !== "object") return new Error(String(cause));
|
|
1183
|
+
if (isObject(cause)) return Object.assign(new UnknownCauseError(), cause);
|
|
1184
|
+
return void 0;
|
|
1185
|
+
}
|
|
1186
|
+
function getTRPCErrorFromUnknown(cause) {
|
|
1187
|
+
if (cause instanceof TRPCError) return cause;
|
|
1188
|
+
if (cause instanceof Error && cause.name === "TRPCError") return cause;
|
|
1189
|
+
const trpcError = new TRPCError({
|
|
1190
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
1191
|
+
cause
|
|
1192
|
+
});
|
|
1193
|
+
if (cause instanceof Error && cause.stack) trpcError.stack = cause.stack;
|
|
1194
|
+
return trpcError;
|
|
1195
|
+
}
|
|
1196
|
+
var TRPCError = class extends Error {
|
|
1197
|
+
constructor(opts) {
|
|
1198
|
+
var _ref, _opts$message, _this$cause;
|
|
1199
|
+
const cause = getCauseFromUnknown(opts.cause);
|
|
1200
|
+
const message = (_ref = (_opts$message = opts.message) !== null && _opts$message !== void 0 ? _opts$message : cause === null || cause === void 0 ? void 0 : cause.message) !== null && _ref !== void 0 ? _ref : opts.code;
|
|
1201
|
+
super(message, { cause });
|
|
1202
|
+
(0, import_defineProperty.default)(this, "cause", void 0);
|
|
1203
|
+
(0, import_defineProperty.default)(this, "code", void 0);
|
|
1204
|
+
this.code = opts.code;
|
|
1205
|
+
this.name = "TRPCError";
|
|
1206
|
+
(_this$cause = this.cause) !== null && _this$cause !== void 0 || (this.cause = cause);
|
|
1207
|
+
}
|
|
1208
|
+
};
|
|
1209
|
+
var import_objectSpread2$1 = __toESM2(require_objectSpread2(), 1);
|
|
1210
|
+
function getDataTransformer(transformer) {
|
|
1211
|
+
if ("input" in transformer) return transformer;
|
|
1212
|
+
return {
|
|
1213
|
+
input: transformer,
|
|
1214
|
+
output: transformer
|
|
1215
|
+
};
|
|
1216
|
+
}
|
|
1217
|
+
var defaultTransformer = {
|
|
1218
|
+
input: {
|
|
1219
|
+
serialize: (obj) => obj,
|
|
1220
|
+
deserialize: (obj) => obj
|
|
1221
|
+
},
|
|
1222
|
+
output: {
|
|
1223
|
+
serialize: (obj) => obj,
|
|
1224
|
+
deserialize: (obj) => obj
|
|
1225
|
+
}
|
|
1226
|
+
};
|
|
1227
|
+
var import_objectSpread22 = __toESM2(require_objectSpread2(), 1);
|
|
1228
|
+
var lazyMarker = "lazyMarker";
|
|
1229
|
+
function once(fn) {
|
|
1230
|
+
const uncalled = /* @__PURE__ */ Symbol();
|
|
1231
|
+
let result = uncalled;
|
|
1232
|
+
return () => {
|
|
1233
|
+
if (result === uncalled) result = fn();
|
|
1234
|
+
return result;
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function isLazy(input) {
|
|
1238
|
+
return typeof input === "function" && lazyMarker in input;
|
|
1239
|
+
}
|
|
1240
|
+
function isRouter(value) {
|
|
1241
|
+
return isObject(value) && isObject(value["_def"]) && "router" in value["_def"];
|
|
1242
|
+
}
|
|
1243
|
+
var emptyRouter = {
|
|
1244
|
+
_ctx: null,
|
|
1245
|
+
_errorShape: null,
|
|
1246
|
+
_meta: null,
|
|
1247
|
+
queries: {},
|
|
1248
|
+
mutations: {},
|
|
1249
|
+
subscriptions: {},
|
|
1250
|
+
errorFormatter: defaultFormatter,
|
|
1251
|
+
transformer: defaultTransformer
|
|
1252
|
+
};
|
|
1253
|
+
var reservedWords = [
|
|
1254
|
+
"then",
|
|
1255
|
+
"call",
|
|
1256
|
+
"apply"
|
|
1257
|
+
];
|
|
1258
|
+
function createRouterFactory(config) {
|
|
1259
|
+
function createRouterInner(input) {
|
|
1260
|
+
const reservedWordsUsed = new Set(Object.keys(input).filter((v) => reservedWords.includes(v)));
|
|
1261
|
+
if (reservedWordsUsed.size > 0) throw new Error("Reserved words used in `router({})` call: " + Array.from(reservedWordsUsed).join(", "));
|
|
1262
|
+
const procedures = emptyObject();
|
|
1263
|
+
const lazy$1 = emptyObject();
|
|
1264
|
+
function createLazyLoader(opts) {
|
|
1265
|
+
return {
|
|
1266
|
+
ref: opts.ref,
|
|
1267
|
+
load: once(async () => {
|
|
1268
|
+
const router$1 = await opts.ref();
|
|
1269
|
+
const lazyPath = [...opts.path, opts.key];
|
|
1270
|
+
const lazyKey = lazyPath.join(".");
|
|
1271
|
+
opts.aggregate[opts.key] = step(router$1._def.record, lazyPath);
|
|
1272
|
+
delete lazy$1[lazyKey];
|
|
1273
|
+
for (const [nestedKey, nestedItem] of Object.entries(router$1._def.lazy)) {
|
|
1274
|
+
const nestedRouterKey = [...lazyPath, nestedKey].join(".");
|
|
1275
|
+
lazy$1[nestedRouterKey] = createLazyLoader({
|
|
1276
|
+
ref: nestedItem.ref,
|
|
1277
|
+
path: lazyPath,
|
|
1278
|
+
key: nestedKey,
|
|
1279
|
+
aggregate: opts.aggregate[opts.key]
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
})
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
function step(from, path = []) {
|
|
1286
|
+
const aggregate = emptyObject();
|
|
1287
|
+
for (const [key, item] of Object.entries(from !== null && from !== void 0 ? from : {})) {
|
|
1288
|
+
if (isLazy(item)) {
|
|
1289
|
+
lazy$1[[...path, key].join(".")] = createLazyLoader({
|
|
1290
|
+
path,
|
|
1291
|
+
ref: item,
|
|
1292
|
+
key,
|
|
1293
|
+
aggregate
|
|
1294
|
+
});
|
|
1295
|
+
continue;
|
|
1296
|
+
}
|
|
1297
|
+
if (isRouter(item)) {
|
|
1298
|
+
aggregate[key] = step(item._def.record, [...path, key]);
|
|
1299
|
+
continue;
|
|
1300
|
+
}
|
|
1301
|
+
if (!isProcedure(item)) {
|
|
1302
|
+
aggregate[key] = step(item, [...path, key]);
|
|
1303
|
+
continue;
|
|
1304
|
+
}
|
|
1305
|
+
const newPath = [...path, key].join(".");
|
|
1306
|
+
if (procedures[newPath]) throw new Error(`Duplicate key: ${newPath}`);
|
|
1307
|
+
procedures[newPath] = item;
|
|
1308
|
+
aggregate[key] = item;
|
|
1309
|
+
}
|
|
1310
|
+
return aggregate;
|
|
1311
|
+
}
|
|
1312
|
+
const record = step(input);
|
|
1313
|
+
const _def = (0, import_objectSpread22.default)((0, import_objectSpread22.default)({
|
|
1314
|
+
_config: config,
|
|
1315
|
+
router: true,
|
|
1316
|
+
procedures,
|
|
1317
|
+
lazy: lazy$1
|
|
1318
|
+
}, emptyRouter), {}, { record });
|
|
1319
|
+
const router2 = (0, import_objectSpread22.default)((0, import_objectSpread22.default)({}, record), {}, {
|
|
1320
|
+
_def,
|
|
1321
|
+
createCaller: createCallerFactory()({ _def })
|
|
1322
|
+
});
|
|
1323
|
+
return router2;
|
|
1324
|
+
}
|
|
1325
|
+
return createRouterInner;
|
|
1326
|
+
}
|
|
1327
|
+
function isProcedure(procedureOrRouter) {
|
|
1328
|
+
return typeof procedureOrRouter === "function";
|
|
1329
|
+
}
|
|
1330
|
+
async function getProcedureAtPath(router2, path) {
|
|
1331
|
+
const { _def } = router2;
|
|
1332
|
+
let procedure = _def.procedures[path];
|
|
1333
|
+
while (!procedure) {
|
|
1334
|
+
const key = Object.keys(_def.lazy).find((key$1) => path.startsWith(key$1));
|
|
1335
|
+
if (!key) return null;
|
|
1336
|
+
const lazyRouter = _def.lazy[key];
|
|
1337
|
+
await lazyRouter.load();
|
|
1338
|
+
procedure = _def.procedures[path];
|
|
1339
|
+
}
|
|
1340
|
+
return procedure;
|
|
1341
|
+
}
|
|
1342
|
+
function createCallerFactory() {
|
|
1343
|
+
return function createCallerInner(router2) {
|
|
1344
|
+
const { _def } = router2;
|
|
1345
|
+
return function createCaller(ctxOrCallback, opts) {
|
|
1346
|
+
return createRecursiveProxy(async (innerOpts) => {
|
|
1347
|
+
const { path, args } = innerOpts;
|
|
1348
|
+
const fullPath = path.join(".");
|
|
1349
|
+
if (path.length === 1 && path[0] === "_def") return _def;
|
|
1350
|
+
const procedure = await getProcedureAtPath(router2, fullPath);
|
|
1351
|
+
let ctx = void 0;
|
|
1352
|
+
try {
|
|
1353
|
+
if (!procedure) throw new TRPCError({
|
|
1354
|
+
code: "NOT_FOUND",
|
|
1355
|
+
message: `No procedure found on path "${path}"`
|
|
1356
|
+
});
|
|
1357
|
+
ctx = isFunction(ctxOrCallback) ? await Promise.resolve(ctxOrCallback()) : ctxOrCallback;
|
|
1358
|
+
return await procedure({
|
|
1359
|
+
path: fullPath,
|
|
1360
|
+
getRawInput: async () => args[0],
|
|
1361
|
+
ctx,
|
|
1362
|
+
type: procedure._def.type,
|
|
1363
|
+
signal: opts === null || opts === void 0 ? void 0 : opts.signal
|
|
1364
|
+
});
|
|
1365
|
+
} catch (cause) {
|
|
1366
|
+
var _opts$onError, _procedure$_def$type;
|
|
1367
|
+
opts === null || opts === void 0 || (_opts$onError = opts.onError) === null || _opts$onError === void 0 || _opts$onError.call(opts, {
|
|
1368
|
+
ctx,
|
|
1369
|
+
error: getTRPCErrorFromUnknown(cause),
|
|
1370
|
+
input: args[0],
|
|
1371
|
+
path: fullPath,
|
|
1372
|
+
type: (_procedure$_def$type = procedure === null || procedure === void 0 ? void 0 : procedure._def.type) !== null && _procedure$_def$type !== void 0 ? _procedure$_def$type : "unknown"
|
|
1373
|
+
});
|
|
1374
|
+
throw cause;
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
};
|
|
1378
|
+
};
|
|
1379
|
+
}
|
|
1380
|
+
function mergeRouters(...routerList) {
|
|
1381
|
+
var _routerList$, _routerList$2;
|
|
1382
|
+
const record = mergeWithoutOverrides({}, ...routerList.map((r) => r._def.record));
|
|
1383
|
+
const errorFormatter = routerList.reduce((currentErrorFormatter, nextRouter) => {
|
|
1384
|
+
if (nextRouter._def._config.errorFormatter && nextRouter._def._config.errorFormatter !== defaultFormatter) {
|
|
1385
|
+
if (currentErrorFormatter !== defaultFormatter && currentErrorFormatter !== nextRouter._def._config.errorFormatter) throw new Error("You seem to have several error formatters");
|
|
1386
|
+
return nextRouter._def._config.errorFormatter;
|
|
1387
|
+
}
|
|
1388
|
+
return currentErrorFormatter;
|
|
1389
|
+
}, defaultFormatter);
|
|
1390
|
+
const transformer = routerList.reduce((prev, current) => {
|
|
1391
|
+
if (current._def._config.transformer && current._def._config.transformer !== defaultTransformer) {
|
|
1392
|
+
if (prev !== defaultTransformer && prev !== current._def._config.transformer) throw new Error("You seem to have several transformers");
|
|
1393
|
+
return current._def._config.transformer;
|
|
1394
|
+
}
|
|
1395
|
+
return prev;
|
|
1396
|
+
}, defaultTransformer);
|
|
1397
|
+
const router2 = createRouterFactory({
|
|
1398
|
+
errorFormatter,
|
|
1399
|
+
transformer,
|
|
1400
|
+
isDev: routerList.every((r) => r._def._config.isDev),
|
|
1401
|
+
allowOutsideOfServer: routerList.every((r) => r._def._config.allowOutsideOfServer),
|
|
1402
|
+
isServer: routerList.every((r) => r._def._config.isServer),
|
|
1403
|
+
$types: (_routerList$ = routerList[0]) === null || _routerList$ === void 0 ? void 0 : _routerList$._def._config.$types,
|
|
1404
|
+
sse: (_routerList$2 = routerList[0]) === null || _routerList$2 === void 0 ? void 0 : _routerList$2._def._config.sse
|
|
1405
|
+
})(record);
|
|
1406
|
+
return router2;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
// ../../node_modules/.pnpm/@trpc+server@11.8.1_typescript@5.9.3/node_modules/@trpc/server/dist/initTRPC-T5bbc89W.mjs
|
|
1410
|
+
var import_objectSpread2$2 = __toESM2(require_objectSpread2(), 1);
|
|
1411
|
+
var middlewareMarker = "middlewareMarker";
|
|
1412
|
+
function createMiddlewareFactory() {
|
|
1413
|
+
function createMiddlewareInner(middlewares) {
|
|
1414
|
+
return {
|
|
1415
|
+
_middlewares: middlewares,
|
|
1416
|
+
unstable_pipe(middlewareBuilderOrFn) {
|
|
1417
|
+
const pipedMiddleware = "_middlewares" in middlewareBuilderOrFn ? middlewareBuilderOrFn._middlewares : [middlewareBuilderOrFn];
|
|
1418
|
+
return createMiddlewareInner([...middlewares, ...pipedMiddleware]);
|
|
1419
|
+
}
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
function createMiddleware(fn) {
|
|
1423
|
+
return createMiddlewareInner([fn]);
|
|
1424
|
+
}
|
|
1425
|
+
return createMiddleware;
|
|
1426
|
+
}
|
|
1427
|
+
function createInputMiddleware(parse) {
|
|
1428
|
+
const inputMiddleware = async function inputValidatorMiddleware(opts) {
|
|
1429
|
+
let parsedInput;
|
|
1430
|
+
const rawInput = await opts.getRawInput();
|
|
1431
|
+
try {
|
|
1432
|
+
parsedInput = await parse(rawInput);
|
|
1433
|
+
} catch (cause) {
|
|
1434
|
+
throw new TRPCError({
|
|
1435
|
+
code: "BAD_REQUEST",
|
|
1436
|
+
cause
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
const combinedInput = isObject(opts.input) && isObject(parsedInput) ? (0, import_objectSpread2$2.default)((0, import_objectSpread2$2.default)({}, opts.input), parsedInput) : parsedInput;
|
|
1440
|
+
return opts.next({ input: combinedInput });
|
|
1441
|
+
};
|
|
1442
|
+
inputMiddleware._type = "input";
|
|
1443
|
+
return inputMiddleware;
|
|
1444
|
+
}
|
|
1445
|
+
function createOutputMiddleware(parse) {
|
|
1446
|
+
const outputMiddleware = async function outputValidatorMiddleware({ next }) {
|
|
1447
|
+
const result = await next();
|
|
1448
|
+
if (!result.ok) return result;
|
|
1449
|
+
try {
|
|
1450
|
+
const data = await parse(result.data);
|
|
1451
|
+
return (0, import_objectSpread2$2.default)((0, import_objectSpread2$2.default)({}, result), {}, { data });
|
|
1452
|
+
} catch (cause) {
|
|
1453
|
+
throw new TRPCError({
|
|
1454
|
+
message: "Output validation failed",
|
|
1455
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
1456
|
+
cause
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
};
|
|
1460
|
+
outputMiddleware._type = "output";
|
|
1461
|
+
return outputMiddleware;
|
|
1462
|
+
}
|
|
1463
|
+
var import_defineProperty2 = __toESM2(require_defineProperty(), 1);
|
|
1464
|
+
var StandardSchemaV1Error = class extends Error {
|
|
1465
|
+
/**
|
|
1466
|
+
* Creates a schema error with useful information.
|
|
1467
|
+
*
|
|
1468
|
+
* @param issues The schema issues.
|
|
1469
|
+
*/
|
|
1470
|
+
constructor(issues) {
|
|
1471
|
+
var _issues$;
|
|
1472
|
+
super((_issues$ = issues[0]) === null || _issues$ === void 0 ? void 0 : _issues$.message);
|
|
1473
|
+
(0, import_defineProperty2.default)(this, "issues", void 0);
|
|
1474
|
+
this.name = "SchemaError";
|
|
1475
|
+
this.issues = issues;
|
|
1476
|
+
}
|
|
1477
|
+
};
|
|
1478
|
+
function getParseFn(procedureParser) {
|
|
1479
|
+
const parser = procedureParser;
|
|
1480
|
+
const isStandardSchema = "~standard" in parser;
|
|
1481
|
+
if (typeof parser === "function" && typeof parser.assert === "function") return parser.assert.bind(parser);
|
|
1482
|
+
if (typeof parser === "function" && !isStandardSchema) return parser;
|
|
1483
|
+
if (typeof parser.parseAsync === "function") return parser.parseAsync.bind(parser);
|
|
1484
|
+
if (typeof parser.parse === "function") return parser.parse.bind(parser);
|
|
1485
|
+
if (typeof parser.validateSync === "function") return parser.validateSync.bind(parser);
|
|
1486
|
+
if (typeof parser.create === "function") return parser.create.bind(parser);
|
|
1487
|
+
if (typeof parser.assert === "function") return (value) => {
|
|
1488
|
+
parser.assert(value);
|
|
1489
|
+
return value;
|
|
1490
|
+
};
|
|
1491
|
+
if (isStandardSchema) return async (value) => {
|
|
1492
|
+
const result = await parser["~standard"].validate(value);
|
|
1493
|
+
if (result.issues) throw new StandardSchemaV1Error(result.issues);
|
|
1494
|
+
return result.value;
|
|
1495
|
+
};
|
|
1496
|
+
throw new Error("Could not find a validator fn");
|
|
1497
|
+
}
|
|
1498
|
+
var require_objectWithoutPropertiesLoose = __commonJS2({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutPropertiesLoose.js"(exports, module) {
|
|
1499
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
1500
|
+
if (null == r) return {};
|
|
1501
|
+
var t2 = {};
|
|
1502
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
1503
|
+
if (e.includes(n)) continue;
|
|
1504
|
+
t2[n] = r[n];
|
|
1505
|
+
}
|
|
1506
|
+
return t2;
|
|
1507
|
+
}
|
|
1508
|
+
module.exports = _objectWithoutPropertiesLoose, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1509
|
+
} });
|
|
1510
|
+
var require_objectWithoutProperties = __commonJS2({ "../../node_modules/.pnpm/@oxc-project+runtime@0.72.2/node_modules/@oxc-project/runtime/src/helpers/objectWithoutProperties.js"(exports, module) {
|
|
1511
|
+
var objectWithoutPropertiesLoose = require_objectWithoutPropertiesLoose();
|
|
1512
|
+
function _objectWithoutProperties$1(e, t2) {
|
|
1513
|
+
if (null == e) return {};
|
|
1514
|
+
var o, r, i = objectWithoutPropertiesLoose(e, t2);
|
|
1515
|
+
if (Object.getOwnPropertySymbols) {
|
|
1516
|
+
var s = Object.getOwnPropertySymbols(e);
|
|
1517
|
+
for (r = 0; r < s.length; r++) o = s[r], t2.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
1518
|
+
}
|
|
1519
|
+
return i;
|
|
1520
|
+
}
|
|
1521
|
+
module.exports = _objectWithoutProperties$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
1522
|
+
} });
|
|
1523
|
+
var import_objectWithoutProperties = __toESM2(require_objectWithoutProperties(), 1);
|
|
1524
|
+
var import_objectSpread2$12 = __toESM2(require_objectSpread2(), 1);
|
|
1525
|
+
var _excluded = [
|
|
1526
|
+
"middlewares",
|
|
1527
|
+
"inputs",
|
|
1528
|
+
"meta"
|
|
1529
|
+
];
|
|
1530
|
+
function createNewBuilder(def1, def2) {
|
|
1531
|
+
const { middlewares = [], inputs, meta } = def2, rest = (0, import_objectWithoutProperties.default)(def2, _excluded);
|
|
1532
|
+
return createBuilder((0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, mergeWithoutOverrides(def1, rest)), {}, {
|
|
1533
|
+
inputs: [...def1.inputs, ...inputs !== null && inputs !== void 0 ? inputs : []],
|
|
1534
|
+
middlewares: [...def1.middlewares, ...middlewares],
|
|
1535
|
+
meta: def1.meta && meta ? (0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, def1.meta), meta) : meta !== null && meta !== void 0 ? meta : def1.meta
|
|
1536
|
+
}));
|
|
1537
|
+
}
|
|
1538
|
+
function createBuilder(initDef = {}) {
|
|
1539
|
+
const _def = (0, import_objectSpread2$12.default)({
|
|
1540
|
+
procedure: true,
|
|
1541
|
+
inputs: [],
|
|
1542
|
+
middlewares: []
|
|
1543
|
+
}, initDef);
|
|
1544
|
+
const builder = {
|
|
1545
|
+
_def,
|
|
1546
|
+
input(input) {
|
|
1547
|
+
const parser = getParseFn(input);
|
|
1548
|
+
return createNewBuilder(_def, {
|
|
1549
|
+
inputs: [input],
|
|
1550
|
+
middlewares: [createInputMiddleware(parser)]
|
|
1551
|
+
});
|
|
1552
|
+
},
|
|
1553
|
+
output(output) {
|
|
1554
|
+
const parser = getParseFn(output);
|
|
1555
|
+
return createNewBuilder(_def, {
|
|
1556
|
+
output,
|
|
1557
|
+
middlewares: [createOutputMiddleware(parser)]
|
|
1558
|
+
});
|
|
1559
|
+
},
|
|
1560
|
+
meta(meta) {
|
|
1561
|
+
return createNewBuilder(_def, { meta });
|
|
1562
|
+
},
|
|
1563
|
+
use(middlewareBuilderOrFn) {
|
|
1564
|
+
const middlewares = "_middlewares" in middlewareBuilderOrFn ? middlewareBuilderOrFn._middlewares : [middlewareBuilderOrFn];
|
|
1565
|
+
return createNewBuilder(_def, { middlewares });
|
|
1566
|
+
},
|
|
1567
|
+
unstable_concat(builder$1) {
|
|
1568
|
+
return createNewBuilder(_def, builder$1._def);
|
|
1569
|
+
},
|
|
1570
|
+
concat(builder$1) {
|
|
1571
|
+
return createNewBuilder(_def, builder$1._def);
|
|
1572
|
+
},
|
|
1573
|
+
query(resolver) {
|
|
1574
|
+
return createResolver((0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, _def), {}, { type: "query" }), resolver);
|
|
1575
|
+
},
|
|
1576
|
+
mutation(resolver) {
|
|
1577
|
+
return createResolver((0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, _def), {}, { type: "mutation" }), resolver);
|
|
1578
|
+
},
|
|
1579
|
+
subscription(resolver) {
|
|
1580
|
+
return createResolver((0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, _def), {}, { type: "subscription" }), resolver);
|
|
1581
|
+
},
|
|
1582
|
+
experimental_caller(caller) {
|
|
1583
|
+
return createNewBuilder(_def, { caller });
|
|
1584
|
+
}
|
|
1585
|
+
};
|
|
1586
|
+
return builder;
|
|
1587
|
+
}
|
|
1588
|
+
function createResolver(_defIn, resolver) {
|
|
1589
|
+
const finalBuilder = createNewBuilder(_defIn, {
|
|
1590
|
+
resolver,
|
|
1591
|
+
middlewares: [async function resolveMiddleware(opts) {
|
|
1592
|
+
const data = await resolver(opts);
|
|
1593
|
+
return {
|
|
1594
|
+
marker: middlewareMarker,
|
|
1595
|
+
ok: true,
|
|
1596
|
+
data,
|
|
1597
|
+
ctx: opts.ctx
|
|
1598
|
+
};
|
|
1599
|
+
}]
|
|
1600
|
+
});
|
|
1601
|
+
const _def = (0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, finalBuilder._def), {}, {
|
|
1602
|
+
type: _defIn.type,
|
|
1603
|
+
experimental_caller: Boolean(finalBuilder._def.caller),
|
|
1604
|
+
meta: finalBuilder._def.meta,
|
|
1605
|
+
$types: null
|
|
1606
|
+
});
|
|
1607
|
+
const invoke = createProcedureCaller(finalBuilder._def);
|
|
1608
|
+
const callerOverride = finalBuilder._def.caller;
|
|
1609
|
+
if (!callerOverride) return invoke;
|
|
1610
|
+
const callerWrapper = async (...args) => {
|
|
1611
|
+
return await callerOverride({
|
|
1612
|
+
args,
|
|
1613
|
+
invoke,
|
|
1614
|
+
_def
|
|
1615
|
+
});
|
|
1616
|
+
};
|
|
1617
|
+
callerWrapper._def = _def;
|
|
1618
|
+
return callerWrapper;
|
|
1619
|
+
}
|
|
1620
|
+
var codeblock = `
|
|
1621
|
+
This is a client-only function.
|
|
1622
|
+
If you want to call this function on the server, see https://trpc.io/docs/v11/server/server-side-calls
|
|
1623
|
+
`.trim();
|
|
1624
|
+
async function callRecursive(index, _def, opts) {
|
|
1625
|
+
try {
|
|
1626
|
+
const middleware2 = _def.middlewares[index];
|
|
1627
|
+
const result = await middleware2((0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, opts), {}, {
|
|
1628
|
+
meta: _def.meta,
|
|
1629
|
+
input: opts.input,
|
|
1630
|
+
next(_nextOpts) {
|
|
1631
|
+
var _nextOpts$getRawInput;
|
|
1632
|
+
const nextOpts = _nextOpts;
|
|
1633
|
+
return callRecursive(index + 1, _def, (0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, opts), {}, {
|
|
1634
|
+
ctx: (nextOpts === null || nextOpts === void 0 ? void 0 : nextOpts.ctx) ? (0, import_objectSpread2$12.default)((0, import_objectSpread2$12.default)({}, opts.ctx), nextOpts.ctx) : opts.ctx,
|
|
1635
|
+
input: nextOpts && "input" in nextOpts ? nextOpts.input : opts.input,
|
|
1636
|
+
getRawInput: (_nextOpts$getRawInput = nextOpts === null || nextOpts === void 0 ? void 0 : nextOpts.getRawInput) !== null && _nextOpts$getRawInput !== void 0 ? _nextOpts$getRawInput : opts.getRawInput
|
|
1637
|
+
}));
|
|
1638
|
+
}
|
|
1639
|
+
}));
|
|
1640
|
+
return result;
|
|
1641
|
+
} catch (cause) {
|
|
1642
|
+
return {
|
|
1643
|
+
ok: false,
|
|
1644
|
+
error: getTRPCErrorFromUnknown(cause),
|
|
1645
|
+
marker: middlewareMarker
|
|
1646
|
+
};
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
function createProcedureCaller(_def) {
|
|
1650
|
+
async function procedure(opts) {
|
|
1651
|
+
if (!opts || !("getRawInput" in opts)) throw new Error(codeblock);
|
|
1652
|
+
const result = await callRecursive(0, _def, opts);
|
|
1653
|
+
if (!result) throw new TRPCError({
|
|
1654
|
+
code: "INTERNAL_SERVER_ERROR",
|
|
1655
|
+
message: "No result from middlewares - did you forget to `return next()`?"
|
|
1656
|
+
});
|
|
1657
|
+
if (!result.ok) throw result.error;
|
|
1658
|
+
return result.data;
|
|
1659
|
+
}
|
|
1660
|
+
procedure._def = _def;
|
|
1661
|
+
procedure.procedure = true;
|
|
1662
|
+
procedure.meta = _def.meta;
|
|
1663
|
+
return procedure;
|
|
1664
|
+
}
|
|
1665
|
+
var _globalThis$process;
|
|
1666
|
+
var _globalThis$process2;
|
|
1667
|
+
var _globalThis$process3;
|
|
1668
|
+
var isServerDefault = typeof window === "undefined" || "Deno" in window || ((_globalThis$process = globalThis.process) === null || _globalThis$process === void 0 || (_globalThis$process = _globalThis$process.env) === null || _globalThis$process === void 0 ? void 0 : _globalThis$process["NODE_ENV"]) === "test" || !!((_globalThis$process2 = globalThis.process) === null || _globalThis$process2 === void 0 || (_globalThis$process2 = _globalThis$process2.env) === null || _globalThis$process2 === void 0 ? void 0 : _globalThis$process2["JEST_WORKER_ID"]) || !!((_globalThis$process3 = globalThis.process) === null || _globalThis$process3 === void 0 || (_globalThis$process3 = _globalThis$process3.env) === null || _globalThis$process3 === void 0 ? void 0 : _globalThis$process3["VITEST_WORKER_ID"]);
|
|
1669
|
+
var import_objectSpread23 = __toESM2(require_objectSpread2(), 1);
|
|
1670
|
+
var TRPCBuilder = class TRPCBuilder2 {
|
|
1671
|
+
/**
|
|
1672
|
+
* Add a context shape as a generic to the root object
|
|
1673
|
+
* @see https://trpc.io/docs/v11/server/context
|
|
1674
|
+
*/
|
|
1675
|
+
context() {
|
|
1676
|
+
return new TRPCBuilder2();
|
|
1677
|
+
}
|
|
1678
|
+
/**
|
|
1679
|
+
* Add a meta shape as a generic to the root object
|
|
1680
|
+
* @see https://trpc.io/docs/v11/quickstart
|
|
1681
|
+
*/
|
|
1682
|
+
meta() {
|
|
1683
|
+
return new TRPCBuilder2();
|
|
1684
|
+
}
|
|
1685
|
+
/**
|
|
1686
|
+
* Create the root object
|
|
1687
|
+
* @see https://trpc.io/docs/v11/server/routers#initialize-trpc
|
|
1688
|
+
*/
|
|
1689
|
+
create(opts) {
|
|
1690
|
+
var _opts$transformer, _opts$isDev, _globalThis$process$1, _opts$allowOutsideOfS, _opts$errorFormatter, _opts$isServer;
|
|
1691
|
+
const config = (0, import_objectSpread23.default)((0, import_objectSpread23.default)({}, opts), {}, {
|
|
1692
|
+
transformer: getDataTransformer((_opts$transformer = opts === null || opts === void 0 ? void 0 : opts.transformer) !== null && _opts$transformer !== void 0 ? _opts$transformer : defaultTransformer),
|
|
1693
|
+
isDev: (_opts$isDev = opts === null || opts === void 0 ? void 0 : opts.isDev) !== null && _opts$isDev !== void 0 ? _opts$isDev : ((_globalThis$process$1 = globalThis.process) === null || _globalThis$process$1 === void 0 ? void 0 : _globalThis$process$1.env["NODE_ENV"]) !== "production",
|
|
1694
|
+
allowOutsideOfServer: (_opts$allowOutsideOfS = opts === null || opts === void 0 ? void 0 : opts.allowOutsideOfServer) !== null && _opts$allowOutsideOfS !== void 0 ? _opts$allowOutsideOfS : false,
|
|
1695
|
+
errorFormatter: (_opts$errorFormatter = opts === null || opts === void 0 ? void 0 : opts.errorFormatter) !== null && _opts$errorFormatter !== void 0 ? _opts$errorFormatter : defaultFormatter,
|
|
1696
|
+
isServer: (_opts$isServer = opts === null || opts === void 0 ? void 0 : opts.isServer) !== null && _opts$isServer !== void 0 ? _opts$isServer : isServerDefault,
|
|
1697
|
+
$types: null
|
|
1698
|
+
});
|
|
1699
|
+
{
|
|
1700
|
+
var _opts$isServer2;
|
|
1701
|
+
const isServer = (_opts$isServer2 = opts === null || opts === void 0 ? void 0 : opts.isServer) !== null && _opts$isServer2 !== void 0 ? _opts$isServer2 : isServerDefault;
|
|
1702
|
+
if (!isServer && (opts === null || opts === void 0 ? void 0 : opts.allowOutsideOfServer) !== true) throw new Error(`You're trying to use @trpc/server in a non-server environment. This is not supported by default.`);
|
|
1703
|
+
}
|
|
1704
|
+
return {
|
|
1705
|
+
_config: config,
|
|
1706
|
+
procedure: createBuilder({ meta: opts === null || opts === void 0 ? void 0 : opts.defaultMeta }),
|
|
1707
|
+
middleware: createMiddlewareFactory(),
|
|
1708
|
+
router: createRouterFactory(config),
|
|
1709
|
+
mergeRouters,
|
|
1710
|
+
createCallerFactory: createCallerFactory()
|
|
1711
|
+
};
|
|
1712
|
+
}
|
|
1713
|
+
};
|
|
1714
|
+
var initTRPC = new TRPCBuilder();
|
|
1715
|
+
|
|
1716
|
+
// ../../packages/schema/dist/index.mjs
|
|
1717
|
+
var A2ATextPartSchema = z3.object({
|
|
1718
|
+
type: z3.literal("text"),
|
|
1719
|
+
text: z3.string()
|
|
1720
|
+
});
|
|
1721
|
+
var A2ADataPartSchema = z3.object({
|
|
1722
|
+
type: z3.literal("data"),
|
|
1723
|
+
data: z3.unknown()
|
|
1724
|
+
});
|
|
1725
|
+
var A2AFilePartSchema = z3.object({
|
|
1726
|
+
type: z3.literal("file"),
|
|
1727
|
+
uri: z3.string(),
|
|
1728
|
+
mediaType: z3.string().optional(),
|
|
1729
|
+
name: z3.string().optional()
|
|
1730
|
+
});
|
|
1731
|
+
var A2APartSchema = z3.object({ type: z3.enum([
|
|
1732
|
+
"text",
|
|
1733
|
+
"data",
|
|
1734
|
+
"file"
|
|
1735
|
+
]) }).passthrough().superRefine((val, ctx) => {
|
|
1736
|
+
if (val.type === "text") {
|
|
1737
|
+
if (typeof val.text !== "string") ctx.addIssue({
|
|
1738
|
+
code: z3.ZodIssueCode.custom,
|
|
1739
|
+
message: "text part must have a string text field"
|
|
1740
|
+
});
|
|
1741
|
+
} else if (val.type === "data") {
|
|
1742
|
+
if (!("data" in val)) ctx.addIssue({
|
|
1743
|
+
code: z3.ZodIssueCode.custom,
|
|
1744
|
+
message: "data part must have a data field"
|
|
1745
|
+
});
|
|
1746
|
+
} else if (val.type === "file") {
|
|
1747
|
+
if (typeof val.uri !== "string") ctx.addIssue({
|
|
1748
|
+
code: z3.ZodIssueCode.custom,
|
|
1749
|
+
message: "file part must have a string uri field"
|
|
1750
|
+
});
|
|
1751
|
+
}
|
|
1752
|
+
});
|
|
1753
|
+
function isValidA2APart(part) {
|
|
1754
|
+
if (!part || typeof part !== "object") return false;
|
|
1755
|
+
const p = part;
|
|
1756
|
+
const t$1 = p.type;
|
|
1757
|
+
if (t$1 === "text") return typeof p.text === "string";
|
|
1758
|
+
else if (t$1 === "data") return "data" in p;
|
|
1759
|
+
else if (t$1 === "file") return typeof p.uri === "string";
|
|
1760
|
+
return false;
|
|
1761
|
+
}
|
|
1762
|
+
function isValidA2AParts(parts) {
|
|
1763
|
+
if (!Array.isArray(parts)) return false;
|
|
1764
|
+
return parts.every(isValidA2APart);
|
|
1765
|
+
}
|
|
1766
|
+
var A2AMessageSchema = z3.object({
|
|
1767
|
+
messageId: z3.string(),
|
|
1768
|
+
role: z3.enum(["user", "agent"]),
|
|
1769
|
+
contextId: z3.string().optional(),
|
|
1770
|
+
taskId: z3.string().optional(),
|
|
1771
|
+
referenceTaskIds: z3.array(z3.string()).optional(),
|
|
1772
|
+
metadata: z3.record(z3.string(), z3.unknown()).optional(),
|
|
1773
|
+
extensions: z3.array(z3.string()).optional()
|
|
1774
|
+
}).passthrough().refine((val) => {
|
|
1775
|
+
const parts = val.parts;
|
|
1776
|
+
return isValidA2AParts(parts);
|
|
1777
|
+
}, {
|
|
1778
|
+
message: "Invalid parts array - each part must have valid type and required fields",
|
|
1779
|
+
path: ["parts"]
|
|
1780
|
+
}).transform((val) => ({
|
|
1781
|
+
...val,
|
|
1782
|
+
parts: val.parts
|
|
1783
|
+
}));
|
|
1784
|
+
var ConversationExportMetaSchema = z3.object({
|
|
1785
|
+
exportId: z3.string(),
|
|
1786
|
+
sourcePlatform: z3.string(),
|
|
1787
|
+
sourceSessionId: z3.string(),
|
|
1788
|
+
planId: z3.string(),
|
|
1789
|
+
exportedAt: z3.number(),
|
|
1790
|
+
messageCount: z3.number(),
|
|
1791
|
+
compressedBytes: z3.number(),
|
|
1792
|
+
uncompressedBytes: z3.number()
|
|
1793
|
+
});
|
|
1794
|
+
z3.object({
|
|
1795
|
+
type: z3.literal("text"),
|
|
1796
|
+
text: z3.string()
|
|
1797
|
+
});
|
|
1798
|
+
z3.object({
|
|
1799
|
+
type: z3.literal("tool_use"),
|
|
1800
|
+
id: z3.string(),
|
|
1801
|
+
name: z3.string(),
|
|
1802
|
+
input: z3.record(z3.string(), z3.unknown())
|
|
1803
|
+
});
|
|
1804
|
+
z3.object({
|
|
1805
|
+
type: z3.literal("tool_result"),
|
|
1806
|
+
tool_use_id: z3.string(),
|
|
1807
|
+
content: z3.unknown(),
|
|
1808
|
+
is_error: z3.boolean().optional()
|
|
1809
|
+
});
|
|
1810
|
+
var ClaudeCodeContentBlockSchema = z3.object({ type: z3.enum([
|
|
1811
|
+
"text",
|
|
1812
|
+
"tool_use",
|
|
1813
|
+
"tool_result"
|
|
1814
|
+
]) }).passthrough().superRefine((val, ctx) => {
|
|
1815
|
+
const typedVal = val;
|
|
1816
|
+
if (val.type === "text") {
|
|
1817
|
+
if (typeof typedVal.text !== "string") ctx.addIssue({
|
|
1818
|
+
code: z3.ZodIssueCode.custom,
|
|
1819
|
+
message: "text block must have a string text field"
|
|
1820
|
+
});
|
|
1821
|
+
} else if (val.type === "tool_use") {
|
|
1822
|
+
if (typeof typedVal.id !== "string") ctx.addIssue({
|
|
1823
|
+
code: z3.ZodIssueCode.custom,
|
|
1824
|
+
message: "tool_use block must have a string id field"
|
|
1825
|
+
});
|
|
1826
|
+
if (typeof typedVal.name !== "string") ctx.addIssue({
|
|
1827
|
+
code: z3.ZodIssueCode.custom,
|
|
1828
|
+
message: "tool_use block must have a string name field"
|
|
1829
|
+
});
|
|
1830
|
+
if (typeof typedVal.input !== "object" || typedVal.input === null) ctx.addIssue({
|
|
1831
|
+
code: z3.ZodIssueCode.custom,
|
|
1832
|
+
message: "tool_use block must have an object input field"
|
|
1833
|
+
});
|
|
1834
|
+
} else if (val.type === "tool_result") {
|
|
1835
|
+
if (typeof typedVal.tool_use_id !== "string") ctx.addIssue({
|
|
1836
|
+
code: z3.ZodIssueCode.custom,
|
|
1837
|
+
message: "tool_result block must have a string tool_use_id field"
|
|
1838
|
+
});
|
|
1839
|
+
}
|
|
1840
|
+
});
|
|
1841
|
+
var ClaudeCodeUsageSchema = z3.object({
|
|
1842
|
+
input_tokens: z3.number(),
|
|
1843
|
+
output_tokens: z3.number(),
|
|
1844
|
+
cache_creation_input_tokens: z3.number().optional(),
|
|
1845
|
+
cache_read_input_tokens: z3.number().optional()
|
|
1846
|
+
});
|
|
1847
|
+
var ClaudeCodeMessageInnerSchema = z3.object({
|
|
1848
|
+
role: z3.string(),
|
|
1849
|
+
content: z3.array(ClaudeCodeContentBlockSchema),
|
|
1850
|
+
id: z3.string().optional(),
|
|
1851
|
+
model: z3.string().optional(),
|
|
1852
|
+
usage: ClaudeCodeUsageSchema.optional()
|
|
1853
|
+
});
|
|
1854
|
+
var ClaudeCodeMessageSchema = z3.object({
|
|
1855
|
+
sessionId: z3.string(),
|
|
1856
|
+
type: z3.enum([
|
|
1857
|
+
"user",
|
|
1858
|
+
"assistant",
|
|
1859
|
+
"summary"
|
|
1860
|
+
]),
|
|
1861
|
+
message: ClaudeCodeMessageInnerSchema,
|
|
1862
|
+
uuid: z3.string(),
|
|
1863
|
+
timestamp: z3.string(),
|
|
1864
|
+
parentUuid: z3.string().optional(),
|
|
1865
|
+
costUSD: z3.number().optional(),
|
|
1866
|
+
durationMs: z3.number().optional()
|
|
1867
|
+
});
|
|
1868
|
+
var GitHubPRResponseSchema = z3.object({
|
|
1869
|
+
number: z3.number(),
|
|
1870
|
+
html_url: z3.string().url(),
|
|
1871
|
+
title: z3.string(),
|
|
1872
|
+
state: z3.enum(["open", "closed"]),
|
|
1873
|
+
draft: z3.boolean(),
|
|
1874
|
+
merged: z3.boolean(),
|
|
1875
|
+
head: z3.object({ ref: z3.string() })
|
|
1876
|
+
});
|
|
1877
|
+
var InviteTokenSchema = z3.object({
|
|
1878
|
+
id: z3.string(),
|
|
1879
|
+
tokenHash: z3.string(),
|
|
1880
|
+
planId: z3.string(),
|
|
1881
|
+
createdBy: z3.string(),
|
|
1882
|
+
createdAt: z3.number(),
|
|
1883
|
+
expiresAt: z3.number(),
|
|
1884
|
+
maxUses: z3.number().nullable(),
|
|
1885
|
+
useCount: z3.number(),
|
|
1886
|
+
revoked: z3.boolean(),
|
|
1887
|
+
label: z3.string().optional()
|
|
1888
|
+
});
|
|
1889
|
+
var InviteRedemptionSchema = z3.object({
|
|
1890
|
+
redeemedBy: z3.string(),
|
|
1891
|
+
redeemedAt: z3.number(),
|
|
1892
|
+
tokenId: z3.string()
|
|
1893
|
+
});
|
|
1894
|
+
var ConversationExportStartMetaSchema = z3.object({
|
|
1895
|
+
exportId: z3.string(),
|
|
1896
|
+
totalChunks: z3.number().int().positive(),
|
|
1897
|
+
totalBytes: z3.number().int().nonnegative(),
|
|
1898
|
+
compressedBytes: z3.number().int().nonnegative(),
|
|
1899
|
+
sourcePlatform: z3.string(),
|
|
1900
|
+
sourceSessionId: z3.string(),
|
|
1901
|
+
planId: z3.string(),
|
|
1902
|
+
exportedAt: z3.number().int().positive()
|
|
1903
|
+
});
|
|
1904
|
+
var ChunkMessageSchema = z3.object({
|
|
1905
|
+
exportId: z3.string(),
|
|
1906
|
+
chunkIndex: z3.number().int().nonnegative(),
|
|
1907
|
+
data: z3.instanceof(Uint8Array)
|
|
1908
|
+
});
|
|
1909
|
+
var ConversationExportEndSchema = z3.object({
|
|
1910
|
+
exportId: z3.string(),
|
|
1911
|
+
checksum: z3.string()
|
|
1912
|
+
});
|
|
1913
|
+
var textEncoder = new TextEncoder();
|
|
1914
|
+
var textDecoder = new TextDecoder();
|
|
1915
|
+
var PlanIndexEntrySchema = z3.discriminatedUnion("deleted", [z3.object({
|
|
1916
|
+
deleted: z3.literal(false),
|
|
1917
|
+
id: z3.string(),
|
|
1918
|
+
title: z3.string(),
|
|
1919
|
+
status: z3.enum(PlanStatusValues),
|
|
1920
|
+
createdAt: z3.number(),
|
|
1921
|
+
updatedAt: z3.number(),
|
|
1922
|
+
ownerId: z3.string(),
|
|
1923
|
+
tags: z3.array(z3.string()).optional()
|
|
1924
|
+
}), z3.object({
|
|
1925
|
+
deleted: z3.literal(true),
|
|
1926
|
+
id: z3.string(),
|
|
1927
|
+
title: z3.string(),
|
|
1928
|
+
status: z3.enum(PlanStatusValues),
|
|
1929
|
+
createdAt: z3.number(),
|
|
1930
|
+
updatedAt: z3.number(),
|
|
1931
|
+
ownerId: z3.string(),
|
|
1932
|
+
tags: z3.array(z3.string()).optional(),
|
|
1933
|
+
deletedAt: z3.number(),
|
|
1934
|
+
deletedBy: z3.string()
|
|
1935
|
+
})]);
|
|
1936
|
+
function formatThreadsForLLM(threads, options = {}) {
|
|
1937
|
+
const { includeResolved = false, selectedTextMaxLength = 100, resolveUser } = options;
|
|
1938
|
+
const unresolvedThreads = threads.filter((t$1) => !t$1.resolved);
|
|
1939
|
+
const resolvedCount = threads.length - unresolvedThreads.length;
|
|
1940
|
+
const threadsToShow = includeResolved ? threads : unresolvedThreads;
|
|
1941
|
+
if (threadsToShow.length === 0) {
|
|
1942
|
+
if (resolvedCount > 0) return `All ${resolvedCount} comment(s) have been resolved.`;
|
|
1943
|
+
return "";
|
|
1944
|
+
}
|
|
1945
|
+
let output = threadsToShow.map((thread, index) => {
|
|
1946
|
+
const location = thread.selectedText ? `On: "${truncate(thread.selectedText, selectedTextMaxLength)}"` : `Comment ${index + 1}`;
|
|
1947
|
+
const comments = thread.comments.map((c, idx) => {
|
|
1948
|
+
const text = extractTextFromCommentBody(c.body);
|
|
1949
|
+
const author = resolveUser ? resolveUser(c.userId) : c.userId.slice(0, 8);
|
|
1950
|
+
if (idx === 0) return `${author}: ${text}`;
|
|
1951
|
+
return `${author} (reply): ${text}`;
|
|
1952
|
+
}).join("\n");
|
|
1953
|
+
return `${location}${thread.resolved ? " [Resolved]" : ""}
|
|
1954
|
+
${comments}`;
|
|
1955
|
+
}).join("\n\n");
|
|
1956
|
+
if (!includeResolved && resolvedCount > 0) output += `
|
|
1957
|
+
|
|
1958
|
+
---
|
|
1959
|
+
(${resolvedCount} resolved comment(s) not shown)`;
|
|
1960
|
+
return output;
|
|
1961
|
+
}
|
|
1962
|
+
function truncate(text, maxLength) {
|
|
1963
|
+
const cleaned = text.replace(/\n/g, " ").trim();
|
|
1964
|
+
if (cleaned.length <= maxLength) return cleaned;
|
|
1965
|
+
return `${cleaned.slice(0, maxLength)}...`;
|
|
1966
|
+
}
|
|
1967
|
+
var PlanIdSchema = z3.object({ planId: z3.string().min(1) });
|
|
1968
|
+
var PlanStatusResponseSchema = z3.object({ status: z3.string() });
|
|
1969
|
+
var HasConnectionsResponseSchema = z3.object({ hasConnections: z3.boolean() });
|
|
1970
|
+
var SubscriptionClientIdSchema = z3.object({
|
|
1971
|
+
planId: z3.string().min(1),
|
|
1972
|
+
clientId: z3.string().min(1)
|
|
1973
|
+
});
|
|
1974
|
+
var ChangeTypeSchema = z3.enum([
|
|
1975
|
+
"status",
|
|
1976
|
+
"comments",
|
|
1977
|
+
"resolved",
|
|
1978
|
+
"content",
|
|
1979
|
+
"artifacts"
|
|
1980
|
+
]);
|
|
1981
|
+
var ChangeSchema = z3.object({
|
|
1982
|
+
type: ChangeTypeSchema,
|
|
1983
|
+
timestamp: z3.number(),
|
|
1984
|
+
summary: z3.string(),
|
|
1985
|
+
details: z3.record(z3.string(), z3.unknown()).optional()
|
|
1986
|
+
});
|
|
1987
|
+
var ChangesResponseSchema = z3.discriminatedUnion("ready", [z3.object({
|
|
1988
|
+
ready: z3.literal(true),
|
|
1989
|
+
changes: z3.string(),
|
|
1990
|
+
details: z3.array(ChangeSchema)
|
|
1991
|
+
}), z3.object({
|
|
1992
|
+
ready: z3.literal(false),
|
|
1993
|
+
pending: z3.number(),
|
|
1994
|
+
windowExpiresIn: z3.number()
|
|
1995
|
+
})]);
|
|
1996
|
+
var DeleteSubscriptionResponseSchema = z3.object({ success: z3.boolean() });
|
|
1997
|
+
var SetSessionTokenRequestSchema = z3.object({ sessionTokenHash: z3.string().min(1) });
|
|
1998
|
+
var GetDeliverableContextRequestSchema = z3.object({ sessionToken: z3.string().min(1) });
|
|
1999
|
+
var GetDeliverableContextResponseSchema = z3.object({ context: z3.string() });
|
|
2000
|
+
var SetSessionTokenResponseSchema = z3.object({ url: z3.string() });
|
|
2001
|
+
var ImportConversationRequestSchema = z3.object({
|
|
2002
|
+
a2aMessages: z3.array(A2AMessageSchema),
|
|
2003
|
+
meta: z3.object({
|
|
2004
|
+
planId: z3.string().optional(),
|
|
2005
|
+
sourcePlatform: z3.string().optional(),
|
|
2006
|
+
sessionId: z3.string().optional()
|
|
2007
|
+
}).optional()
|
|
2008
|
+
});
|
|
2009
|
+
var ImportConversationResponseSchema = z3.discriminatedUnion("success", [z3.object({
|
|
2010
|
+
success: z3.literal(true),
|
|
2011
|
+
sessionId: z3.string(),
|
|
2012
|
+
transcriptPath: z3.string(),
|
|
2013
|
+
messageCount: z3.number()
|
|
2014
|
+
}), z3.object({
|
|
2015
|
+
success: z3.literal(false),
|
|
2016
|
+
error: z3.string()
|
|
2017
|
+
})]);
|
|
2018
|
+
var t = initTRPC.context().create({ allowOutsideOfServer: true });
|
|
2019
|
+
var router = t.router;
|
|
2020
|
+
var publicProcedure = t.procedure;
|
|
2021
|
+
var middleware = t.middleware;
|
|
2022
|
+
var conversationRouter = router({ import: publicProcedure.input(ImportConversationRequestSchema).output(ImportConversationResponseSchema).mutation(async ({ input, ctx }) => {
|
|
2023
|
+
return ctx.conversationHandlers.importConversation(input, ctx);
|
|
2024
|
+
}) });
|
|
2025
|
+
var hookRouter = router({
|
|
2026
|
+
createSession: publicProcedure.input(CreateHookSessionRequestSchema).output(CreateHookSessionResponseSchema).mutation(async ({ input, ctx }) => {
|
|
2027
|
+
return ctx.hookHandlers.createSession(input, ctx);
|
|
2028
|
+
}),
|
|
2029
|
+
updateContent: publicProcedure.input(PlanIdSchema.merge(UpdatePlanContentRequestSchema)).output(UpdatePlanContentResponseSchema).mutation(async ({ input, ctx }) => {
|
|
2030
|
+
const { planId, ...contentInput } = input;
|
|
2031
|
+
return ctx.hookHandlers.updateContent(planId, contentInput, ctx);
|
|
2032
|
+
}),
|
|
2033
|
+
getReviewStatus: publicProcedure.input(PlanIdSchema).output(GetReviewStatusResponseSchema).query(async ({ input, ctx }) => {
|
|
2034
|
+
return ctx.hookHandlers.getReviewStatus(input.planId, ctx);
|
|
2035
|
+
}),
|
|
2036
|
+
updatePresence: publicProcedure.input(PlanIdSchema.merge(UpdatePresenceRequestSchema)).output(UpdatePresenceResponseSchema).mutation(async ({ input, ctx }) => {
|
|
2037
|
+
const { planId, ...presenceInput } = input;
|
|
2038
|
+
return ctx.hookHandlers.updatePresence(planId, presenceInput, ctx);
|
|
2039
|
+
}),
|
|
2040
|
+
setSessionToken: publicProcedure.input(PlanIdSchema.merge(SetSessionTokenRequestSchema)).output(SetSessionTokenResponseSchema).mutation(async ({ input, ctx }) => {
|
|
2041
|
+
const { planId, sessionTokenHash } = input;
|
|
2042
|
+
return ctx.hookHandlers.setSessionToken(planId, sessionTokenHash, ctx);
|
|
2043
|
+
}),
|
|
2044
|
+
waitForApproval: publicProcedure.input(z3.object({
|
|
2045
|
+
planId: z3.string(),
|
|
2046
|
+
reviewRequestId: z3.string()
|
|
2047
|
+
})).output(z3.object({
|
|
2048
|
+
approved: z3.boolean(),
|
|
2049
|
+
feedback: z3.string().optional(),
|
|
2050
|
+
deliverables: z3.array(z3.any()).optional(),
|
|
2051
|
+
reviewComment: z3.string().optional(),
|
|
2052
|
+
reviewedBy: z3.string().optional(),
|
|
2053
|
+
status: z3.string().optional()
|
|
2054
|
+
})).mutation(async ({ input, ctx }) => {
|
|
2055
|
+
const { planId, reviewRequestId } = input;
|
|
2056
|
+
return ctx.hookHandlers.waitForApproval(planId, reviewRequestId, ctx);
|
|
2057
|
+
}),
|
|
2058
|
+
getDeliverableContext: publicProcedure.input(PlanIdSchema.merge(GetDeliverableContextRequestSchema)).output(GetDeliverableContextResponseSchema).query(async ({ input, ctx }) => {
|
|
2059
|
+
const { planId, sessionToken } = input;
|
|
2060
|
+
return ctx.hookHandlers.getDeliverableContext(planId, sessionToken, ctx);
|
|
2061
|
+
}),
|
|
2062
|
+
getSessionContext: publicProcedure.input(z3.object({ sessionId: z3.string() })).output(z3.discriminatedUnion("found", [z3.object({
|
|
2063
|
+
found: z3.literal(true),
|
|
2064
|
+
planId: z3.string(),
|
|
2065
|
+
sessionToken: z3.string(),
|
|
2066
|
+
url: z3.string(),
|
|
2067
|
+
deliverables: z3.array(z3.object({
|
|
2068
|
+
id: z3.string(),
|
|
2069
|
+
text: z3.string()
|
|
2070
|
+
})),
|
|
2071
|
+
reviewComment: z3.string().optional(),
|
|
2072
|
+
reviewedBy: z3.string().optional(),
|
|
2073
|
+
reviewStatus: z3.string().optional()
|
|
2074
|
+
}), z3.object({ found: z3.literal(false) })])).query(async ({ input, ctx }) => {
|
|
2075
|
+
return ctx.hookHandlers.getSessionContext(input.sessionId, ctx);
|
|
2076
|
+
})
|
|
2077
|
+
});
|
|
2078
|
+
var planRouter = router({
|
|
2079
|
+
getStatus: publicProcedure.input(PlanIdSchema).output(PlanStatusResponseSchema).query(async ({ input, ctx }) => {
|
|
2080
|
+
const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
|
|
2081
|
+
if (!metadata) throw new TRPCError({
|
|
2082
|
+
code: "NOT_FOUND",
|
|
2083
|
+
message: "Plan not found"
|
|
2084
|
+
});
|
|
2085
|
+
return { status: metadata.status };
|
|
2086
|
+
}),
|
|
2087
|
+
hasConnections: publicProcedure.input(PlanIdSchema).output(HasConnectionsResponseSchema).query(async ({ input, ctx }) => {
|
|
2088
|
+
return { hasConnections: await ctx.getPlanStore().hasActiveConnections(input.planId) };
|
|
2089
|
+
})
|
|
2090
|
+
});
|
|
2091
|
+
var subscriptionRouter = router({
|
|
2092
|
+
create: publicProcedure.input(PlanIdSchema.merge(CreateSubscriptionRequestSchema)).output(CreateSubscriptionResponseSchema).mutation(async ({ input, ctx }) => {
|
|
2093
|
+
const { planId, subscribe, windowMs, maxWindowMs, threshold } = input;
|
|
2094
|
+
return { clientId: ctx.getPlanStore().createSubscription({
|
|
2095
|
+
planId,
|
|
2096
|
+
subscribe: subscribe || ["status"],
|
|
2097
|
+
windowMs: windowMs ?? 5e3,
|
|
2098
|
+
maxWindowMs: maxWindowMs ?? 3e4,
|
|
2099
|
+
threshold: threshold ?? 1
|
|
2100
|
+
}) };
|
|
2101
|
+
}),
|
|
2102
|
+
getChanges: publicProcedure.input(SubscriptionClientIdSchema).output(ChangesResponseSchema).query(async ({ input, ctx }) => {
|
|
2103
|
+
const { planId, clientId } = input;
|
|
2104
|
+
const result = ctx.getPlanStore().getChanges(planId, clientId);
|
|
2105
|
+
if (!result) throw new TRPCError({
|
|
2106
|
+
code: "NOT_FOUND",
|
|
2107
|
+
message: "Subscription not found"
|
|
2108
|
+
});
|
|
2109
|
+
return result;
|
|
2110
|
+
}),
|
|
2111
|
+
delete: publicProcedure.input(SubscriptionClientIdSchema).output(DeleteSubscriptionResponseSchema).mutation(async ({ input, ctx }) => {
|
|
2112
|
+
const { planId, clientId } = input;
|
|
2113
|
+
return { success: ctx.getPlanStore().deleteSubscription(planId, clientId) };
|
|
2114
|
+
})
|
|
2115
|
+
});
|
|
2116
|
+
var appRouter = router({
|
|
2117
|
+
hook: hookRouter,
|
|
2118
|
+
plan: planRouter,
|
|
2119
|
+
subscription: subscriptionRouter,
|
|
2120
|
+
conversation: conversationRouter
|
|
2121
|
+
});
|
|
2122
|
+
|
|
2123
|
+
// src/adapters/claude-code.ts
|
|
2124
|
+
import { z as z6 } from "zod";
|
|
2125
|
+
|
|
2126
|
+
// src/constants.ts
|
|
2127
|
+
var CLAUDE_TOOL_NAMES = {
|
|
2128
|
+
WRITE: "Write",
|
|
2129
|
+
EDIT: "Edit",
|
|
2130
|
+
EXIT_PLAN_MODE: "ExitPlanMode",
|
|
2131
|
+
ASK_USER_QUESTION: "AskUserQuestion"
|
|
2132
|
+
};
|
|
2133
|
+
var MCP_TOOL_NAMES = {
|
|
2134
|
+
REQUEST_USER_INPUT: "request_user_input"
|
|
2135
|
+
};
|
|
2136
|
+
var CLAUDE_PERMISSION_MODES = {
|
|
2137
|
+
PLAN: "plan",
|
|
2138
|
+
DEFAULT: "default",
|
|
2139
|
+
ACCEPT_EDITS: "acceptEdits",
|
|
2140
|
+
DONT_ASK: "dontAsk",
|
|
2141
|
+
BYPASS_PERMISSIONS: "bypassPermissions"
|
|
2142
|
+
};
|
|
2143
|
+
var CLAUDE_HOOK_EVENTS = {
|
|
2144
|
+
PRE_TOOL_USE: "PreToolUse",
|
|
2145
|
+
POST_TOOL_USE: "PostToolUse",
|
|
2146
|
+
PERMISSION_REQUEST: "PermissionRequest"
|
|
2147
|
+
};
|
|
2148
|
+
var DEFAULT_AGENT_TYPE = "claude-code";
|
|
2149
|
+
|
|
2150
|
+
// src/logger.ts
|
|
2151
|
+
import { homedir } from "os";
|
|
2152
|
+
import { join } from "path";
|
|
2153
|
+
import pino from "pino";
|
|
2154
|
+
|
|
2155
|
+
// src/config/env/server.ts
|
|
2156
|
+
import { z as z5 } from "zod";
|
|
2157
|
+
|
|
2158
|
+
// src/config/config.ts
|
|
2159
|
+
import { z as z4 } from "zod";
|
|
2160
|
+
function loadEnv(schema4) {
|
|
2161
|
+
try {
|
|
2162
|
+
return schema4.parse(process.env);
|
|
2163
|
+
} catch (error) {
|
|
2164
|
+
if (error instanceof z4.ZodError) {
|
|
2165
|
+
const testResult = schema4.safeParse(void 0);
|
|
2166
|
+
if (testResult.success) {
|
|
2167
|
+
return testResult.data;
|
|
2168
|
+
}
|
|
2169
|
+
if (!error.issues || !Array.isArray(error.issues)) {
|
|
2170
|
+
throw new Error("Environment variable validation failed (no error details available)");
|
|
2171
|
+
}
|
|
2172
|
+
const errorMessages = error.issues.map((err) => ` - ${err.path.join(".")}: ${err.message}`).join("\n");
|
|
2173
|
+
throw new Error(`Environment variable validation failed:
|
|
2174
|
+
${errorMessages}`);
|
|
2175
|
+
}
|
|
2176
|
+
throw error;
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
// src/config/env/server.ts
|
|
2181
|
+
var schema = z5.object({
|
|
2182
|
+
LOG_LEVEL: z5.enum(["debug", "info", "warn", "error"]).default("info")
|
|
2183
|
+
});
|
|
2184
|
+
var serverConfig = loadEnv(schema);
|
|
2185
|
+
|
|
2186
|
+
// src/logger.ts
|
|
2187
|
+
var LOG_FILE = join(homedir(), ".shipyard", "hook-debug.log");
|
|
2188
|
+
var logger = pino(
|
|
2189
|
+
{
|
|
2190
|
+
level: serverConfig.LOG_LEVEL,
|
|
2191
|
+
timestamp: pino.stdTimeFunctions.isoTime
|
|
2192
|
+
},
|
|
2193
|
+
pino.multistream([{ stream: pino.destination(2) }, { stream: pino.destination(LOG_FILE) }])
|
|
2194
|
+
);
|
|
2195
|
+
|
|
2196
|
+
// src/adapters/claude-code.ts
|
|
2197
|
+
var ClaudeCodeHookBaseSchema = z6.object({
|
|
2198
|
+
session_id: z6.string(),
|
|
2199
|
+
transcript_path: z6.string().optional(),
|
|
2200
|
+
cwd: z6.string().optional(),
|
|
2201
|
+
permission_mode: z6.enum([
|
|
2202
|
+
CLAUDE_PERMISSION_MODES.DEFAULT,
|
|
2203
|
+
CLAUDE_PERMISSION_MODES.PLAN,
|
|
2204
|
+
CLAUDE_PERMISSION_MODES.ACCEPT_EDITS,
|
|
2205
|
+
CLAUDE_PERMISSION_MODES.DONT_ASK,
|
|
2206
|
+
CLAUDE_PERMISSION_MODES.BYPASS_PERMISSIONS
|
|
2207
|
+
]),
|
|
2208
|
+
hook_event_name: z6.string(),
|
|
2209
|
+
tool_name: z6.string().optional(),
|
|
2210
|
+
tool_input: z6.record(z6.string(), z6.unknown()).optional()
|
|
2211
|
+
});
|
|
2212
|
+
function handlePreToolUse(input) {
|
|
2213
|
+
const toolName = input.tool_name;
|
|
2214
|
+
if (toolName === CLAUDE_TOOL_NAMES.ASK_USER_QUESTION) {
|
|
2215
|
+
logger.info(
|
|
2216
|
+
{ toolName },
|
|
2217
|
+
"Blocking AskUserQuestion - redirecting to request_user_input MCP tool"
|
|
2218
|
+
);
|
|
2219
|
+
return {
|
|
2220
|
+
type: "tool_deny",
|
|
2221
|
+
reason: `BLOCKED: Use the ${MCP_TOOL_NAMES.REQUEST_USER_INPUT} MCP tool instead for consistent browser UI. See the tool description for available parameters.`
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2224
|
+
return { type: "passthrough" };
|
|
2225
|
+
}
|
|
2226
|
+
var ExitPlanModeToolInputSchema = z6.object({
|
|
2227
|
+
plan: z6.string()
|
|
2228
|
+
});
|
|
2229
|
+
function handlePermissionRequest(input) {
|
|
2230
|
+
const sessionId = input.session_id;
|
|
2231
|
+
const toolName = input.tool_name;
|
|
2232
|
+
if (toolName === CLAUDE_TOOL_NAMES.EXIT_PLAN_MODE) {
|
|
2233
|
+
logger.info(
|
|
2234
|
+
{
|
|
2235
|
+
toolInput: input.tool_input,
|
|
2236
|
+
toolInputKeys: input.tool_input ? Object.keys(input.tool_input) : []
|
|
2237
|
+
},
|
|
2238
|
+
"ExitPlanMode tool_input received"
|
|
2239
|
+
);
|
|
2240
|
+
const parsed = ExitPlanModeToolInputSchema.safeParse(input.tool_input);
|
|
2241
|
+
if (!parsed.success) {
|
|
2242
|
+
logger.warn(
|
|
2243
|
+
{ parseError: parsed.error?.issues, toolInput: input.tool_input },
|
|
2244
|
+
"ExitPlanMode tool_input parse failed - no plan content"
|
|
2245
|
+
);
|
|
2246
|
+
return { type: "plan_exit", sessionId };
|
|
2247
|
+
}
|
|
2248
|
+
return {
|
|
2249
|
+
type: "plan_exit",
|
|
2250
|
+
sessionId,
|
|
2251
|
+
planContent: parsed.data.plan,
|
|
2252
|
+
metadata: {
|
|
2253
|
+
originSessionId: input.session_id,
|
|
2254
|
+
originTranscriptPath: input.transcript_path,
|
|
2255
|
+
originCwd: input.cwd
|
|
2256
|
+
}
|
|
2257
|
+
};
|
|
2258
|
+
}
|
|
2259
|
+
return { type: "passthrough" };
|
|
2260
|
+
}
|
|
2261
|
+
function handlePostToolUse(input) {
|
|
2262
|
+
const sessionId = input.session_id;
|
|
2263
|
+
const toolName = input.tool_name;
|
|
2264
|
+
if (toolName === CLAUDE_TOOL_NAMES.EXIT_PLAN_MODE) {
|
|
2265
|
+
return {
|
|
2266
|
+
type: "post_exit",
|
|
2267
|
+
sessionId,
|
|
2268
|
+
toolName
|
|
2269
|
+
};
|
|
2270
|
+
}
|
|
2271
|
+
return { type: "passthrough" };
|
|
2272
|
+
}
|
|
2273
|
+
var claudeCodeAdapter = {
|
|
2274
|
+
name: "claude-code",
|
|
2275
|
+
parseInput(stdin) {
|
|
2276
|
+
let input;
|
|
2277
|
+
try {
|
|
2278
|
+
const parsed = JSON.parse(stdin);
|
|
2279
|
+
input = ClaudeCodeHookBaseSchema.parse(parsed);
|
|
2280
|
+
} catch {
|
|
2281
|
+
return { type: "passthrough" };
|
|
2282
|
+
}
|
|
2283
|
+
if (input.hook_event_name === CLAUDE_HOOK_EVENTS.PRE_TOOL_USE) {
|
|
2284
|
+
return handlePreToolUse(input);
|
|
2285
|
+
}
|
|
2286
|
+
if (input.permission_mode !== CLAUDE_PERMISSION_MODES.PLAN) {
|
|
2287
|
+
return { type: "passthrough" };
|
|
2288
|
+
}
|
|
2289
|
+
if (input.hook_event_name === CLAUDE_HOOK_EVENTS.PERMISSION_REQUEST) {
|
|
2290
|
+
return handlePermissionRequest(input);
|
|
2291
|
+
}
|
|
2292
|
+
if (input.hook_event_name === CLAUDE_HOOK_EVENTS.POST_TOOL_USE) {
|
|
2293
|
+
return handlePostToolUse(input);
|
|
2294
|
+
}
|
|
2295
|
+
return { type: "passthrough" };
|
|
2296
|
+
},
|
|
2297
|
+
formatOutput(response) {
|
|
2298
|
+
if (response.hookType === "tool_deny") {
|
|
2299
|
+
return JSON.stringify({
|
|
2300
|
+
hookSpecificOutput: {
|
|
2301
|
+
hookEventName: CLAUDE_HOOK_EVENTS.PRE_TOOL_USE,
|
|
2302
|
+
permissionDecision: "deny",
|
|
2303
|
+
permissionDecisionReason: response.denyReason || "Tool call denied by hook"
|
|
2304
|
+
}
|
|
2305
|
+
});
|
|
2306
|
+
}
|
|
2307
|
+
if (response.hookType === "post_tool_use") {
|
|
2308
|
+
return JSON.stringify({
|
|
2309
|
+
hookSpecificOutput: {
|
|
2310
|
+
hookEventName: CLAUDE_HOOK_EVENTS.POST_TOOL_USE,
|
|
2311
|
+
additionalContext: response.additionalContext || ""
|
|
2312
|
+
}
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
if (response.allow) {
|
|
2316
|
+
return JSON.stringify({
|
|
2317
|
+
hookSpecificOutput: {
|
|
2318
|
+
hookEventName: CLAUDE_HOOK_EVENTS.PERMISSION_REQUEST,
|
|
2319
|
+
decision: {
|
|
2320
|
+
behavior: "allow",
|
|
2321
|
+
message: response.message
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
});
|
|
2325
|
+
}
|
|
2326
|
+
const message = response.feedback?.length ? formatFeedback(response.feedback) : response.message || "Changes requested";
|
|
2327
|
+
return JSON.stringify({
|
|
2328
|
+
hookSpecificOutput: {
|
|
2329
|
+
hookEventName: CLAUDE_HOOK_EVENTS.PERMISSION_REQUEST,
|
|
2330
|
+
decision: {
|
|
2331
|
+
behavior: "deny",
|
|
2332
|
+
message
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
});
|
|
2336
|
+
}
|
|
2337
|
+
};
|
|
2338
|
+
function formatFeedback(feedback) {
|
|
2339
|
+
if (!feedback.length) {
|
|
2340
|
+
return "Changes requested. Check the plan for reviewer comments.";
|
|
2341
|
+
}
|
|
2342
|
+
const threads = feedback.map((f) => ({
|
|
2343
|
+
id: f.threadId,
|
|
2344
|
+
comments: f.comments.map((c) => ({
|
|
2345
|
+
id: c.author,
|
|
2346
|
+
userId: c.author,
|
|
2347
|
+
body: c.content,
|
|
2348
|
+
createdAt: c.createdAt
|
|
2349
|
+
})),
|
|
2350
|
+
selectedText: f.blockId ? `Block ${f.blockId}` : void 0
|
|
2351
|
+
}));
|
|
2352
|
+
const feedbackText = formatThreadsForLLM(threads, {
|
|
2353
|
+
includeResolved: false,
|
|
2354
|
+
selectedTextMaxLength: 100
|
|
2355
|
+
});
|
|
2356
|
+
return `Changes requested:
|
|
2357
|
+
|
|
2358
|
+
${feedbackText}`;
|
|
2359
|
+
}
|
|
2360
|
+
|
|
2361
|
+
// ../../packages/shared/dist/registry-config.mjs
|
|
2362
|
+
var DEFAULT_REGISTRY_PORTS = [32191, 32192];
|
|
2363
|
+
|
|
2364
|
+
// ../../packages/shared/dist/index.mjs
|
|
2365
|
+
import { createHash, randomBytes } from "crypto";
|
|
2366
|
+
function computeHash(content) {
|
|
2367
|
+
return createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
2368
|
+
}
|
|
2369
|
+
function generateSessionToken() {
|
|
2370
|
+
return randomBytes(32).toString("base64url");
|
|
2371
|
+
}
|
|
2372
|
+
function hashSessionToken(token) {
|
|
2373
|
+
return createHash("sha256").update(token).digest("hex");
|
|
2374
|
+
}
|
|
2375
|
+
var APPROVAL_LONG_POLL_TIMEOUT_MS = 1800 * 1e3;
|
|
2376
|
+
var DEFAULT_TRPC_TIMEOUT_MS = 10 * 1e3;
|
|
2377
|
+
|
|
2378
|
+
// src/config/env/registry.ts
|
|
2379
|
+
import { homedir as homedir2 } from "os";
|
|
2380
|
+
import { join as join2 } from "path";
|
|
2381
|
+
import { z as z7 } from "zod";
|
|
2382
|
+
var schema2 = z7.object({
|
|
2383
|
+
REGISTRY_PORT: z7.string().optional().transform((val) => {
|
|
2384
|
+
if (!val) return DEFAULT_REGISTRY_PORTS;
|
|
2385
|
+
const port = Number.parseInt(val, 10);
|
|
2386
|
+
if (Number.isNaN(port)) {
|
|
2387
|
+
throw new Error(`REGISTRY_PORT must be a valid number, got: ${val}`);
|
|
2388
|
+
}
|
|
2389
|
+
return [port];
|
|
2390
|
+
}),
|
|
2391
|
+
SHIPYARD_STATE_DIR: z7.string().optional().default(() => join2(homedir2(), ".shipyard"))
|
|
2392
|
+
});
|
|
2393
|
+
var registryConfig = loadEnv(schema2);
|
|
2394
|
+
|
|
2395
|
+
// src/trpc-client.ts
|
|
2396
|
+
import { createTRPCClient, httpBatchLink } from "@trpc/client";
|
|
2397
|
+
var cachedClient = null;
|
|
2398
|
+
var cachedBaseUrl = null;
|
|
2399
|
+
function getTRPCClient(baseUrl, timeoutMs = DEFAULT_TRPC_TIMEOUT_MS) {
|
|
2400
|
+
if (timeoutMs !== DEFAULT_TRPC_TIMEOUT_MS) {
|
|
2401
|
+
return createTRPCClient({
|
|
2402
|
+
links: [
|
|
2403
|
+
httpBatchLink({
|
|
2404
|
+
url: `${baseUrl}/trpc`,
|
|
2405
|
+
fetch: (url, options) => {
|
|
2406
|
+
return fetch(url, {
|
|
2407
|
+
...options,
|
|
2408
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
2409
|
+
});
|
|
2410
|
+
}
|
|
2411
|
+
})
|
|
2412
|
+
]
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
if (cachedClient && cachedBaseUrl === baseUrl) {
|
|
2416
|
+
return cachedClient;
|
|
2417
|
+
}
|
|
2418
|
+
cachedClient = createTRPCClient({
|
|
2419
|
+
links: [
|
|
2420
|
+
httpBatchLink({
|
|
2421
|
+
url: `${baseUrl}/trpc`,
|
|
2422
|
+
fetch: (url, options) => {
|
|
2423
|
+
return fetch(url, {
|
|
2424
|
+
...options,
|
|
2425
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
})
|
|
2429
|
+
]
|
|
2430
|
+
});
|
|
2431
|
+
cachedBaseUrl = baseUrl;
|
|
2432
|
+
return cachedClient;
|
|
2433
|
+
}
|
|
2434
|
+
|
|
2435
|
+
// src/http-client.ts
|
|
2436
|
+
async function retryWithBackoff(fn, maxAttempts = 3, baseDelay = 1e3) {
|
|
2437
|
+
let lastError = null;
|
|
2438
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2439
|
+
try {
|
|
2440
|
+
return await fn();
|
|
2441
|
+
} catch (err) {
|
|
2442
|
+
lastError = err;
|
|
2443
|
+
if (attempt < maxAttempts - 1) {
|
|
2444
|
+
const delay = attempt === 0 ? 0 : baseDelay * 2 ** (attempt - 1);
|
|
2445
|
+
logger.debug(
|
|
2446
|
+
{ attempt: attempt + 1, maxAttempts, delay },
|
|
2447
|
+
"Registry health check failed, retrying..."
|
|
2448
|
+
);
|
|
2449
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
throw lastError || new Error("Retry failed");
|
|
2454
|
+
}
|
|
2455
|
+
async function getRegistryUrl() {
|
|
2456
|
+
const ports = registryConfig.REGISTRY_PORT;
|
|
2457
|
+
for (const port of ports) {
|
|
2458
|
+
try {
|
|
2459
|
+
const url = `http://localhost:${port}`;
|
|
2460
|
+
await retryWithBackoff(
|
|
2461
|
+
async () => {
|
|
2462
|
+
const res = await fetch(`${url}/registry`, {
|
|
2463
|
+
signal: AbortSignal.timeout(5e3)
|
|
2464
|
+
});
|
|
2465
|
+
if (!res.ok) {
|
|
2466
|
+
throw new Error(`Registry responded with status ${res.status}`);
|
|
2467
|
+
}
|
|
2468
|
+
},
|
|
2469
|
+
3,
|
|
2470
|
+
1e3
|
|
2471
|
+
);
|
|
2472
|
+
logger.debug({ port }, "Found registry server (with retry)");
|
|
2473
|
+
return url;
|
|
2474
|
+
} catch (err) {
|
|
2475
|
+
const error = err;
|
|
2476
|
+
logger.debug(
|
|
2477
|
+
{ port, error: error.message },
|
|
2478
|
+
"Failed to connect to registry port after retries"
|
|
2479
|
+
);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
logger.error(
|
|
2483
|
+
{
|
|
2484
|
+
ports,
|
|
2485
|
+
attemptsPerPort: 3,
|
|
2486
|
+
totalTimeout: "15s (5s per attempt * 3 attempts)"
|
|
2487
|
+
},
|
|
2488
|
+
"Registry server not reachable - check if `pnpm dev` is running"
|
|
2489
|
+
);
|
|
2490
|
+
return null;
|
|
2491
|
+
}
|
|
2492
|
+
async function createSession(request) {
|
|
2493
|
+
const baseUrl = await getRegistryUrl();
|
|
2494
|
+
if (!baseUrl) {
|
|
2495
|
+
throw new Error("Registry server not available");
|
|
2496
|
+
}
|
|
2497
|
+
const trpc = getTRPCClient(baseUrl);
|
|
2498
|
+
return trpc.hook.createSession.mutate(request);
|
|
2499
|
+
}
|
|
2500
|
+
async function updatePlanContent(planId, request) {
|
|
2501
|
+
const baseUrl = await getRegistryUrl();
|
|
2502
|
+
if (!baseUrl) {
|
|
2503
|
+
throw new Error("Registry server not available");
|
|
2504
|
+
}
|
|
2505
|
+
const trpc = getTRPCClient(baseUrl);
|
|
2506
|
+
return trpc.hook.updateContent.mutate({ planId, ...request });
|
|
2507
|
+
}
|
|
2508
|
+
async function getReviewStatus(planId) {
|
|
2509
|
+
const baseUrl = await getRegistryUrl();
|
|
2510
|
+
if (!baseUrl) {
|
|
2511
|
+
throw new Error("Registry server not available");
|
|
2512
|
+
}
|
|
2513
|
+
const trpc = getTRPCClient(baseUrl);
|
|
2514
|
+
return trpc.hook.getReviewStatus.query({ planId });
|
|
2515
|
+
}
|
|
2516
|
+
async function updatePresence(planId, request) {
|
|
2517
|
+
const baseUrl = await getRegistryUrl();
|
|
2518
|
+
if (!baseUrl) {
|
|
2519
|
+
throw new Error("Registry server not available");
|
|
2520
|
+
}
|
|
2521
|
+
const trpc = getTRPCClient(baseUrl);
|
|
2522
|
+
return trpc.hook.updatePresence.mutate({ planId, ...request });
|
|
2523
|
+
}
|
|
2524
|
+
async function setSessionToken(planId, sessionTokenHash) {
|
|
2525
|
+
const baseUrl = await getRegistryUrl();
|
|
2526
|
+
if (!baseUrl) {
|
|
2527
|
+
throw new Error("Registry server not available");
|
|
2528
|
+
}
|
|
2529
|
+
const trpc = getTRPCClient(baseUrl);
|
|
2530
|
+
return trpc.hook.setSessionToken.mutate({ planId, sessionTokenHash });
|
|
2531
|
+
}
|
|
2532
|
+
async function waitForApproval(planId, reviewRequestId) {
|
|
2533
|
+
const baseUrl = await getRegistryUrl();
|
|
2534
|
+
if (!baseUrl) {
|
|
2535
|
+
throw new Error("Registry server not available");
|
|
2536
|
+
}
|
|
2537
|
+
const trpc = getTRPCClient(baseUrl, APPROVAL_LONG_POLL_TIMEOUT_MS);
|
|
2538
|
+
return trpc.hook.waitForApproval.mutate({ planId, reviewRequestId });
|
|
2539
|
+
}
|
|
2540
|
+
async function getSessionContext(sessionId) {
|
|
2541
|
+
const baseUrl = await getRegistryUrl();
|
|
2542
|
+
if (!baseUrl) {
|
|
2543
|
+
throw new Error("Registry server not available");
|
|
2544
|
+
}
|
|
2545
|
+
const trpc = getTRPCClient(baseUrl);
|
|
2546
|
+
return trpc.hook.getSessionContext.query({ sessionId });
|
|
2547
|
+
}
|
|
2548
|
+
async function getDeliverableContext(planId, sessionToken) {
|
|
2549
|
+
const baseUrl = await getRegistryUrl();
|
|
2550
|
+
if (!baseUrl) {
|
|
2551
|
+
throw new Error("Registry server not available");
|
|
2552
|
+
}
|
|
2553
|
+
const trpc = getTRPCClient(baseUrl);
|
|
2554
|
+
return trpc.hook.getDeliverableContext.query({ planId, sessionToken });
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
// src/core/plan-manager.ts
|
|
2558
|
+
var sessionToPlan = /* @__PURE__ */ new Map();
|
|
2559
|
+
async function createPlan(options) {
|
|
2560
|
+
const { sessionId, agentType, metadata } = options;
|
|
2561
|
+
logger.info({ sessionId, agentType }, "Creating plan for session");
|
|
2562
|
+
const response = await createSession({
|
|
2563
|
+
sessionId,
|
|
2564
|
+
agentType,
|
|
2565
|
+
metadata
|
|
2566
|
+
});
|
|
2567
|
+
sessionToPlan.set(sessionId, {
|
|
2568
|
+
planId: response.planId
|
|
2569
|
+
});
|
|
2570
|
+
await updatePresence(response.planId, {
|
|
2571
|
+
agentType,
|
|
2572
|
+
sessionId
|
|
2573
|
+
});
|
|
2574
|
+
logger.info({ sessionId, planId: response.planId, url: response.url }, "Plan created by server");
|
|
2575
|
+
return response;
|
|
2576
|
+
}
|
|
2577
|
+
async function updateContent(options) {
|
|
2578
|
+
const { sessionId, filePath, content, agentType } = options;
|
|
2579
|
+
let session = sessionToPlan.get(sessionId);
|
|
2580
|
+
if (!session) {
|
|
2581
|
+
try {
|
|
2582
|
+
const serverSession = await getSessionContext(sessionId);
|
|
2583
|
+
if (serverSession.found && serverSession.planId) {
|
|
2584
|
+
logger.info(
|
|
2585
|
+
{ sessionId, planId: serverSession.planId },
|
|
2586
|
+
"Found existing session on server"
|
|
2587
|
+
);
|
|
2588
|
+
session = { planId: serverSession.planId };
|
|
2589
|
+
sessionToPlan.set(sessionId, session);
|
|
2590
|
+
}
|
|
2591
|
+
} catch (err) {
|
|
2592
|
+
logger.debug({ sessionId, err }, "Could not fetch session from server");
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
if (!session) {
|
|
2596
|
+
logger.info({ sessionId, filePath }, "First write detected, creating plan");
|
|
2597
|
+
await createPlan({
|
|
2598
|
+
sessionId,
|
|
2599
|
+
agentType: agentType ?? DEFAULT_AGENT_TYPE,
|
|
2600
|
+
metadata: { filePath }
|
|
2601
|
+
});
|
|
2602
|
+
session = sessionToPlan.get(sessionId);
|
|
2603
|
+
if (!session) {
|
|
2604
|
+
logger.error({ sessionId }, "Failed to track session after plan creation");
|
|
2605
|
+
return false;
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
const contentHash = computeHash(content);
|
|
2609
|
+
if (session.lastContentHash === contentHash) {
|
|
2610
|
+
logger.debug({ sessionId }, "Content unchanged, skipping update");
|
|
2611
|
+
return true;
|
|
2612
|
+
}
|
|
2613
|
+
logger.info({ sessionId, planId: session.planId, filePath }, "Updating plan content");
|
|
2614
|
+
await updatePlanContent(session.planId, {
|
|
2615
|
+
content,
|
|
2616
|
+
filePath
|
|
2617
|
+
});
|
|
2618
|
+
sessionToPlan.set(sessionId, {
|
|
2619
|
+
...session,
|
|
2620
|
+
filePath,
|
|
2621
|
+
lastContentHash: contentHash
|
|
2622
|
+
});
|
|
2623
|
+
if (agentType) {
|
|
2624
|
+
await updatePresence(session.planId, {
|
|
2625
|
+
agentType,
|
|
2626
|
+
sessionId
|
|
2627
|
+
});
|
|
2628
|
+
}
|
|
2629
|
+
return true;
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
// src/config/env/web.ts
|
|
2633
|
+
import { z as z8 } from "zod";
|
|
2634
|
+
var schema3 = z8.object({
|
|
2635
|
+
SHIPYARD_WEB_URL: z8.string().url().default("http://localhost:5173")
|
|
2636
|
+
});
|
|
2637
|
+
var webConfig = loadEnv(schema3);
|
|
2638
|
+
|
|
2639
|
+
// src/core/review-status.ts
|
|
2640
|
+
async function waitForReviewDecision(planId, _wsUrl) {
|
|
2641
|
+
logger.info({ planId }, "Waiting for approval via server endpoint");
|
|
2642
|
+
const result = await waitForApproval(planId, planId);
|
|
2643
|
+
logger.info({ planId, approved: result.approved }, "Received approval decision from server");
|
|
2644
|
+
return {
|
|
2645
|
+
approved: result.approved,
|
|
2646
|
+
feedback: result.feedback,
|
|
2647
|
+
deliverables: result.deliverables,
|
|
2648
|
+
reviewComment: result.reviewComment,
|
|
2649
|
+
reviewedBy: result.reviewedBy,
|
|
2650
|
+
status: result.status
|
|
2651
|
+
};
|
|
2652
|
+
}
|
|
2653
|
+
async function handleUpdatedPlanReview(sessionId, planId, planContent, _originMetadata) {
|
|
2654
|
+
logger.info(
|
|
2655
|
+
{ planId, contentLength: planContent.length },
|
|
2656
|
+
"Plan content changed, triggering re-review"
|
|
2657
|
+
);
|
|
2658
|
+
logger.info({ planId }, "Syncing updated plan content");
|
|
2659
|
+
try {
|
|
2660
|
+
await updatePlanContent(planId, {
|
|
2661
|
+
content: planContent
|
|
2662
|
+
});
|
|
2663
|
+
} catch (err) {
|
|
2664
|
+
const error = err;
|
|
2665
|
+
if (error.message?.includes("404")) {
|
|
2666
|
+
logger.warn(
|
|
2667
|
+
{ planId, sessionId },
|
|
2668
|
+
"Plan not found (404), creating new plan with updated content"
|
|
2669
|
+
);
|
|
2670
|
+
return await checkReviewStatus(sessionId, planContent, _originMetadata);
|
|
2671
|
+
}
|
|
2672
|
+
throw err;
|
|
2673
|
+
}
|
|
2674
|
+
const baseUrl = webConfig.SHIPYARD_WEB_URL;
|
|
2675
|
+
logger.info(
|
|
2676
|
+
{ planId, url: `${baseUrl}/plan/${planId}` },
|
|
2677
|
+
"Content synced, browser already open. Waiting for server approval..."
|
|
2678
|
+
);
|
|
2679
|
+
const decision = await waitForReviewDecision(planId, "");
|
|
2680
|
+
logger.info({ planId, approved: decision.approved }, "Decision received via Y.Doc");
|
|
2681
|
+
if (decision.approved) {
|
|
2682
|
+
const sessionToken = generateSessionToken();
|
|
2683
|
+
const sessionTokenHash = hashSessionToken(sessionToken);
|
|
2684
|
+
logger.info({ planId }, "Generating new session token for re-approved plan");
|
|
2685
|
+
try {
|
|
2686
|
+
const tokenResult = await setSessionToken(planId, sessionTokenHash);
|
|
2687
|
+
const url = tokenResult.url;
|
|
2688
|
+
const deliverableCount = (decision.deliverables ?? []).length;
|
|
2689
|
+
logger.info(
|
|
2690
|
+
{ planId, url, deliverableCount },
|
|
2691
|
+
"Session token set and stored by server with updated content hash"
|
|
2692
|
+
);
|
|
2693
|
+
const reviewFeedback = decision.reviewComment ? `
|
|
2694
|
+
|
|
2695
|
+
Reviewer comment: ${decision.reviewComment}` : "";
|
|
2696
|
+
return {
|
|
2697
|
+
allow: true,
|
|
2698
|
+
message: `Plan re-approved with updates! You have ${deliverableCount} deliverable${deliverableCount === 1 ? "" : "s"}. Use add_artifact(filePath, deliverableId) to upload proof-of-work.${reviewFeedback}`,
|
|
2699
|
+
planId,
|
|
2700
|
+
sessionToken,
|
|
2701
|
+
url
|
|
2702
|
+
};
|
|
2703
|
+
} catch (err) {
|
|
2704
|
+
logger.error({ err, planId }, "Failed to set session token, but plan was approved");
|
|
2705
|
+
return {
|
|
2706
|
+
allow: true,
|
|
2707
|
+
message: "Updated plan approved (session token unavailable)",
|
|
2708
|
+
planId
|
|
2709
|
+
};
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
logger.debug({ planId }, "Changes requested - server will manage state cleanup");
|
|
2713
|
+
return {
|
|
2714
|
+
allow: false,
|
|
2715
|
+
message: decision.reviewComment || "Changes requested",
|
|
2716
|
+
planId
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2719
|
+
async function checkReviewStatus(sessionId, planContent, originMetadata) {
|
|
2720
|
+
const state = await getSessionContext(sessionId);
|
|
2721
|
+
let planId;
|
|
2722
|
+
if (!state.found && planContent) {
|
|
2723
|
+
logger.info(
|
|
2724
|
+
{ sessionId, contentLength: planContent.length, hasState: !!state },
|
|
2725
|
+
"Creating plan from ExitPlanMode (blocking mode)"
|
|
2726
|
+
);
|
|
2727
|
+
const result = await createPlan({
|
|
2728
|
+
sessionId,
|
|
2729
|
+
agentType: DEFAULT_AGENT_TYPE,
|
|
2730
|
+
metadata: {
|
|
2731
|
+
source: "ExitPlanMode",
|
|
2732
|
+
...originMetadata
|
|
2733
|
+
}
|
|
2734
|
+
});
|
|
2735
|
+
planId = result.planId;
|
|
2736
|
+
logger.info({ planId }, "Syncing plan content");
|
|
2737
|
+
await updatePlanContent(planId, {
|
|
2738
|
+
content: planContent
|
|
2739
|
+
});
|
|
2740
|
+
logger.info(
|
|
2741
|
+
{ planId, url: result.url },
|
|
2742
|
+
"Plan created and synced, browser opened. Waiting for server approval..."
|
|
2743
|
+
);
|
|
2744
|
+
const decision = await waitForReviewDecision(planId, "");
|
|
2745
|
+
logger.info({ planId, approved: decision.approved }, "Decision received via Y.Doc");
|
|
2746
|
+
if (decision.approved) {
|
|
2747
|
+
const sessionToken = generateSessionToken();
|
|
2748
|
+
const sessionTokenHash = hashSessionToken(sessionToken);
|
|
2749
|
+
logger.info({ planId }, "Generating session token for approved plan");
|
|
2750
|
+
try {
|
|
2751
|
+
const tokenResult = await setSessionToken(planId, sessionTokenHash);
|
|
2752
|
+
const url = tokenResult.url;
|
|
2753
|
+
const deliverableCount = (decision.deliverables ?? []).length;
|
|
2754
|
+
logger.info(
|
|
2755
|
+
{ planId, url, deliverableCount },
|
|
2756
|
+
"Session token set and stored by server with deliverables"
|
|
2757
|
+
);
|
|
2758
|
+
const reviewFeedback = decision.reviewComment ? `
|
|
2759
|
+
|
|
2760
|
+
Reviewer comment: ${decision.reviewComment}` : "";
|
|
2761
|
+
return {
|
|
2762
|
+
allow: true,
|
|
2763
|
+
message: `Plan approved! You have ${deliverableCount} deliverable${deliverableCount === 1 ? "" : "s"}. Use add_artifact(filePath, deliverableId) to upload proof-of-work.${reviewFeedback}`,
|
|
2764
|
+
planId,
|
|
2765
|
+
sessionToken,
|
|
2766
|
+
url
|
|
2767
|
+
};
|
|
2768
|
+
} catch (err) {
|
|
2769
|
+
logger.error({ err, planId }, "Failed to set session token, approving without it");
|
|
2770
|
+
return {
|
|
2771
|
+
allow: true,
|
|
2772
|
+
message: "Plan approved, but session token unavailable. You may need to refresh the plan in the browser. Check ~/.shipyard/server-debug.log for details.",
|
|
2773
|
+
planId
|
|
2774
|
+
};
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
logger.debug({ sessionId }, "Changes requested - server will manage state cleanup");
|
|
2778
|
+
return {
|
|
2779
|
+
allow: false,
|
|
2780
|
+
message: decision.reviewComment || "Changes requested",
|
|
2781
|
+
planId
|
|
2782
|
+
};
|
|
2783
|
+
}
|
|
2784
|
+
if (!state.found) {
|
|
2785
|
+
logger.info({ sessionId }, "No session state or plan content, allowing exit");
|
|
2786
|
+
return { allow: true };
|
|
2787
|
+
}
|
|
2788
|
+
if ((!state || !state.planId) && planContent) {
|
|
2789
|
+
logger.error(
|
|
2790
|
+
{ sessionId, hasPlanContent: !!planContent, hasState: !!state, statePlanId: state?.planId },
|
|
2791
|
+
"Unreachable state: plan content exists but no session state"
|
|
2792
|
+
);
|
|
2793
|
+
return {
|
|
2794
|
+
allow: false,
|
|
2795
|
+
message: "Internal error: Plan content found but session state missing. Check ~/.shipyard/hook-debug.log and report this issue."
|
|
2796
|
+
};
|
|
2797
|
+
}
|
|
2798
|
+
if (!state.planId) {
|
|
2799
|
+
throw new Error("Unreachable: state.planId should exist at this point");
|
|
2800
|
+
}
|
|
2801
|
+
planId = state.planId;
|
|
2802
|
+
if (planContent) {
|
|
2803
|
+
logger.info({ planId }, "Plan content provided, triggering re-review");
|
|
2804
|
+
return await handleUpdatedPlanReview(sessionId, planId, planContent, originMetadata);
|
|
2805
|
+
}
|
|
2806
|
+
logger.info({ sessionId, planId }, "Checking review status");
|
|
2807
|
+
let status;
|
|
2808
|
+
try {
|
|
2809
|
+
status = await getReviewStatus(planId);
|
|
2810
|
+
} catch (err) {
|
|
2811
|
+
logger.warn({ err, planId }, "Failed to get review status, blocking exit");
|
|
2812
|
+
return {
|
|
2813
|
+
allow: false,
|
|
2814
|
+
message: "Cannot verify plan approval status. Ensure the Shipyard MCP server is running. Check ~/.shipyard/server-debug.log for details.",
|
|
2815
|
+
planId
|
|
2816
|
+
};
|
|
2817
|
+
}
|
|
2818
|
+
logger.info({ sessionId, planId, status: status.status }, "Review status retrieved");
|
|
2819
|
+
const baseUrl = webConfig.SHIPYARD_WEB_URL;
|
|
2820
|
+
switch (status.status) {
|
|
2821
|
+
case "changes_requested":
|
|
2822
|
+
return {
|
|
2823
|
+
allow: false,
|
|
2824
|
+
message: formatFeedbackMessage(status.feedback),
|
|
2825
|
+
feedback: status.feedback,
|
|
2826
|
+
planId
|
|
2827
|
+
};
|
|
2828
|
+
case "pending_review":
|
|
2829
|
+
return {
|
|
2830
|
+
allow: false,
|
|
2831
|
+
message: `Plan is pending review.
|
|
2832
|
+
|
|
2833
|
+
Open: ${baseUrl}/plan/${planId}`,
|
|
2834
|
+
planId
|
|
2835
|
+
};
|
|
2836
|
+
case "draft":
|
|
2837
|
+
return {
|
|
2838
|
+
allow: false,
|
|
2839
|
+
message: `Plan is still in draft.
|
|
2840
|
+
|
|
2841
|
+
Submit for review at: ${baseUrl}/plan/${planId}`,
|
|
2842
|
+
planId
|
|
2843
|
+
};
|
|
2844
|
+
case "in_progress":
|
|
2845
|
+
return {
|
|
2846
|
+
allow: true,
|
|
2847
|
+
message: "Plan approved. Work is in progress. Use add_artifact(filePath, deliverableId) to upload deliverable proofs.",
|
|
2848
|
+
planId
|
|
2849
|
+
};
|
|
2850
|
+
case "completed":
|
|
2851
|
+
return {
|
|
2852
|
+
allow: true,
|
|
2853
|
+
message: `Task completed by ${status.completedBy}`,
|
|
2854
|
+
planId
|
|
2855
|
+
};
|
|
2856
|
+
default: {
|
|
2857
|
+
assertNever(status);
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
function formatFeedbackMessage(feedback) {
|
|
2862
|
+
if (!feedback?.length) {
|
|
2863
|
+
return "Changes requested. Check the plan for reviewer comments.";
|
|
2864
|
+
}
|
|
2865
|
+
const lines = feedback.map((f) => {
|
|
2866
|
+
const blockInfo = f.blockId ? `Block ${f.blockId}` : "General";
|
|
2867
|
+
const comments = f.comments.map((c) => ` - ${c.author}: ${c.content}`).join("\n");
|
|
2868
|
+
return `${blockInfo}:
|
|
2869
|
+
${comments}`;
|
|
2870
|
+
});
|
|
2871
|
+
return `Changes requested:
|
|
2872
|
+
|
|
2873
|
+
${lines.join("\n\n")}`;
|
|
2874
|
+
}
|
|
2875
|
+
|
|
2876
|
+
// src/index.ts
|
|
2877
|
+
function getAdapter() {
|
|
2878
|
+
return claudeCodeAdapter;
|
|
2879
|
+
}
|
|
2880
|
+
async function handlePlanStart(event) {
|
|
2881
|
+
try {
|
|
2882
|
+
const result = await createPlan({
|
|
2883
|
+
sessionId: event.sessionId,
|
|
2884
|
+
agentType: DEFAULT_AGENT_TYPE,
|
|
2885
|
+
metadata: event.metadata
|
|
2886
|
+
});
|
|
2887
|
+
return {
|
|
2888
|
+
allow: true,
|
|
2889
|
+
message: `Plan created at ${result.url}. Write your plan, mark deliverables with {#deliverable}, then exit plan mode to await approval.`,
|
|
2890
|
+
planId: result.planId,
|
|
2891
|
+
url: result.url
|
|
2892
|
+
};
|
|
2893
|
+
} catch (err) {
|
|
2894
|
+
logger.error({ err }, "Failed to create plan");
|
|
2895
|
+
return { allow: true };
|
|
2896
|
+
}
|
|
2897
|
+
}
|
|
2898
|
+
async function handleContentUpdate(event) {
|
|
2899
|
+
try {
|
|
2900
|
+
await updateContent({
|
|
2901
|
+
sessionId: event.sessionId,
|
|
2902
|
+
filePath: event.filePath,
|
|
2903
|
+
content: event.content,
|
|
2904
|
+
agentType: DEFAULT_AGENT_TYPE
|
|
2905
|
+
});
|
|
2906
|
+
return { allow: true };
|
|
2907
|
+
} catch (err) {
|
|
2908
|
+
logger.error({ err }, "Failed to update content");
|
|
2909
|
+
throw err;
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
async function handlePlanExit(event) {
|
|
2913
|
+
try {
|
|
2914
|
+
return await checkReviewStatus(event.sessionId, event.planContent, event.metadata);
|
|
2915
|
+
} catch (err) {
|
|
2916
|
+
const error = err;
|
|
2917
|
+
logger.error(
|
|
2918
|
+
{ err: error, message: error.message, code: error.code },
|
|
2919
|
+
"Failed to check review status"
|
|
2920
|
+
);
|
|
2921
|
+
const isConnectionError = error.code === "ECONNREFUSED" || error.code === "ECONNRESET" || error.code === "ETIMEDOUT" || error.code === "ENOTFOUND" || error.message?.includes("connect") || error.message?.includes("timeout") || error.message?.includes("WebSocket") || error.message?.includes("not available");
|
|
2922
|
+
const message = isConnectionError ? "Cannot connect to Shipyard server. Ensure the Shipyard MCP server is running. Check ~/.shipyard/hook-debug.log for details." : `Review system error: ${error.message}. Check ~/.shipyard/hook-debug.log for details.`;
|
|
2923
|
+
return {
|
|
2924
|
+
allow: false,
|
|
2925
|
+
message
|
|
2926
|
+
};
|
|
2927
|
+
}
|
|
2928
|
+
}
|
|
2929
|
+
async function handlePostExit(event) {
|
|
2930
|
+
try {
|
|
2931
|
+
const sessionContext = await getSessionContext(event.sessionId);
|
|
2932
|
+
if (!sessionContext.found) {
|
|
2933
|
+
logger.debug({ sessionId: event.sessionId }, "No session found in registry");
|
|
2934
|
+
return {
|
|
2935
|
+
allow: true,
|
|
2936
|
+
hookType: "post_tool_use",
|
|
2937
|
+
additionalContext: ""
|
|
2938
|
+
};
|
|
2939
|
+
}
|
|
2940
|
+
const { planId, sessionToken, url } = sessionContext;
|
|
2941
|
+
logger.info(
|
|
2942
|
+
{ planId, sessionId: event.sessionId },
|
|
2943
|
+
"Injecting session context via PostToolUse"
|
|
2944
|
+
);
|
|
2945
|
+
const result = await getDeliverableContext(planId, sessionToken);
|
|
2946
|
+
return {
|
|
2947
|
+
allow: true,
|
|
2948
|
+
hookType: "post_tool_use",
|
|
2949
|
+
additionalContext: result.context,
|
|
2950
|
+
planId,
|
|
2951
|
+
sessionToken,
|
|
2952
|
+
url
|
|
2953
|
+
};
|
|
2954
|
+
} catch (err) {
|
|
2955
|
+
logger.error({ err, sessionId: event.sessionId }, "Failed to get session context from server");
|
|
2956
|
+
return {
|
|
2957
|
+
allow: true,
|
|
2958
|
+
hookType: "post_tool_use",
|
|
2959
|
+
additionalContext: ""
|
|
2960
|
+
};
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2963
|
+
async function processEvent(_adapter, event) {
|
|
2964
|
+
switch (event.type) {
|
|
2965
|
+
case "plan_start":
|
|
2966
|
+
return handlePlanStart(event);
|
|
2967
|
+
case "content_update":
|
|
2968
|
+
return handleContentUpdate(event);
|
|
2969
|
+
case "plan_exit":
|
|
2970
|
+
return handlePlanExit(event);
|
|
2971
|
+
case "post_exit":
|
|
2972
|
+
return handlePostExit(event);
|
|
2973
|
+
case "disconnect":
|
|
2974
|
+
return { allow: true };
|
|
2975
|
+
case "tool_deny":
|
|
2976
|
+
return {
|
|
2977
|
+
allow: false,
|
|
2978
|
+
hookType: "tool_deny",
|
|
2979
|
+
denyReason: event.reason
|
|
2980
|
+
};
|
|
2981
|
+
case "passthrough":
|
|
2982
|
+
return { allow: true };
|
|
2983
|
+
default: {
|
|
2984
|
+
const _exhaustive = event;
|
|
2985
|
+
logger.warn({ event: _exhaustive }, "Unknown event type");
|
|
2986
|
+
return { allow: true };
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
async function readStdin() {
|
|
2991
|
+
const chunks = [];
|
|
2992
|
+
for await (const chunk of process.stdin) {
|
|
2993
|
+
chunks.push(chunk);
|
|
2994
|
+
}
|
|
2995
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
2996
|
+
}
|
|
2997
|
+
function outputSessionStartContext() {
|
|
2998
|
+
const context = `[SHIPYARD] Collaborative planning with human review & proof-of-work tracking.
|
|
2999
|
+
|
|
3000
|
+
IMPORTANT: Use native plan mode (Shift+Tab) to create plans. The hook handles everything automatically.
|
|
3001
|
+
|
|
3002
|
+
## What are Deliverables?
|
|
3003
|
+
|
|
3004
|
+
Deliverables are measurable outcomes you can prove with artifacts (screenshots, videos, test results).
|
|
3005
|
+
|
|
3006
|
+
Good deliverables (provable):
|
|
3007
|
+
\`\`\`
|
|
3008
|
+
- [ ] Screenshot of working login page {#deliverable}
|
|
3009
|
+
- [ ] Video showing feature in action {#deliverable}
|
|
3010
|
+
- [ ] Test results showing all tests pass {#deliverable}
|
|
3011
|
+
\`\`\`
|
|
3012
|
+
|
|
3013
|
+
Bad deliverables (implementation details, not provable):
|
|
3014
|
+
\`\`\`
|
|
3015
|
+
- [ ] Implement getUserMedia API \u2190 This is a task, not a deliverable
|
|
3016
|
+
- [ ] Add error handling \u2190 Can't prove this with an artifact
|
|
3017
|
+
\`\`\`
|
|
3018
|
+
|
|
3019
|
+
## Workflow
|
|
3020
|
+
|
|
3021
|
+
1. Enter plan mode (Shift+Tab) \u2192 Browser opens with live plan
|
|
3022
|
+
2. Write plan with {#deliverable} markers for provable outcomes
|
|
3023
|
+
3. Exit plan mode \u2192 Hook BLOCKS until human approves
|
|
3024
|
+
4. On approval \u2192 You receive planId, sessionToken, and deliverable IDs
|
|
3025
|
+
5. Do work \u2192 Take screenshots/videos as you go
|
|
3026
|
+
6. \`add_artifact(filePath, deliverableId)\` for each deliverable
|
|
3027
|
+
7. When all deliverables fulfilled \u2192 Auto-completes with snapshot URL
|
|
3028
|
+
|
|
3029
|
+
## After Approval
|
|
3030
|
+
|
|
3031
|
+
You only need ONE tool: \`add_artifact\`
|
|
3032
|
+
|
|
3033
|
+
When the last deliverable gets an artifact, the task auto-completes and returns a snapshot URL for your PR.`;
|
|
3034
|
+
const hookOutput = {
|
|
3035
|
+
hookSpecificOutput: {
|
|
3036
|
+
hookEventName: "SessionStart",
|
|
3037
|
+
additionalContext: context
|
|
3038
|
+
}
|
|
3039
|
+
};
|
|
3040
|
+
console.log(JSON.stringify(hookOutput));
|
|
3041
|
+
}
|
|
3042
|
+
async function main() {
|
|
3043
|
+
try {
|
|
3044
|
+
if (process.argv.includes("--context")) {
|
|
3045
|
+
outputSessionStartContext();
|
|
3046
|
+
return;
|
|
3047
|
+
}
|
|
3048
|
+
const stdin = await readStdin();
|
|
3049
|
+
if (!stdin.trim()) {
|
|
3050
|
+
logger.debug("Empty stdin, passing through");
|
|
3051
|
+
console.log(JSON.stringify({ continue: true }));
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
const adapter = getAdapter();
|
|
3055
|
+
const event = adapter.parseInput(stdin);
|
|
3056
|
+
logger.debug({ event }, "Parsed event");
|
|
3057
|
+
const response = await processEvent(adapter, event);
|
|
3058
|
+
const output = adapter.formatOutput(response);
|
|
3059
|
+
logger.debug({ output }, "Sending hook response");
|
|
3060
|
+
console.log(output);
|
|
3061
|
+
process.exit(0);
|
|
3062
|
+
} catch (err) {
|
|
3063
|
+
logger.error({ err }, "Hook error, failing closed");
|
|
3064
|
+
console.log(
|
|
3065
|
+
JSON.stringify({
|
|
3066
|
+
hookSpecificOutput: {
|
|
3067
|
+
hookEventName: "PermissionRequest",
|
|
3068
|
+
decision: {
|
|
3069
|
+
behavior: "deny",
|
|
3070
|
+
message: `Hook error: ${err.message}. Check ~/.shipyard/hook-debug.log for details.`
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
3073
|
+
})
|
|
3074
|
+
);
|
|
3075
|
+
process.exit(0);
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
main();
|