@paigy/harness 0.3.34 → 0.3.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +949 -444
- package/dist/main.js +876 -376
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -5285,7 +5285,7 @@ var require_util = __commonJS({
|
|
|
5285
5285
|
}
|
|
5286
5286
|
return controller.desiredSize > 0;
|
|
5287
5287
|
},
|
|
5288
|
-
async cancel(
|
|
5288
|
+
async cancel(reason3) {
|
|
5289
5289
|
await iterator.return();
|
|
5290
5290
|
},
|
|
5291
5291
|
type: "bytes"
|
|
@@ -5613,12 +5613,12 @@ var require_diagnostics = __commonJS({
|
|
|
5613
5613
|
websocketDebuglog("connection opened %s%s", address, port ? `:${port}` : "");
|
|
5614
5614
|
});
|
|
5615
5615
|
diagnosticsChannel.channel("undici:websocket:close").subscribe((evt) => {
|
|
5616
|
-
const { websocket, code, reason } = evt;
|
|
5616
|
+
const { websocket, code, reason: reason3 } = evt;
|
|
5617
5617
|
websocketDebuglog(
|
|
5618
5618
|
"closed connection to %s - %s %s",
|
|
5619
5619
|
websocket.url,
|
|
5620
5620
|
code,
|
|
5621
|
-
|
|
5621
|
+
reason3
|
|
5622
5622
|
);
|
|
5623
5623
|
});
|
|
5624
5624
|
diagnosticsChannel.channel("undici:websocket:socket_error").subscribe((err) => {
|
|
@@ -7480,25 +7480,25 @@ var require_data_url = __commonJS({
|
|
|
7480
7480
|
function isHTTPWhiteSpace(char) {
|
|
7481
7481
|
return char === 13 || char === 10 || char === 9 || char === 32;
|
|
7482
7482
|
}
|
|
7483
|
-
function removeHTTPWhitespace(
|
|
7484
|
-
return removeChars(
|
|
7483
|
+
function removeHTTPWhitespace(str5, leading = true, trailing = true) {
|
|
7484
|
+
return removeChars(str5, leading, trailing, isHTTPWhiteSpace);
|
|
7485
7485
|
}
|
|
7486
7486
|
function isASCIIWhitespace(char) {
|
|
7487
7487
|
return char === 13 || char === 10 || char === 9 || char === 12 || char === 32;
|
|
7488
7488
|
}
|
|
7489
|
-
function removeASCIIWhitespace(
|
|
7490
|
-
return removeChars(
|
|
7489
|
+
function removeASCIIWhitespace(str5, leading = true, trailing = true) {
|
|
7490
|
+
return removeChars(str5, leading, trailing, isASCIIWhitespace);
|
|
7491
7491
|
}
|
|
7492
|
-
function removeChars(
|
|
7492
|
+
function removeChars(str5, leading, trailing, predicate) {
|
|
7493
7493
|
let lead = 0;
|
|
7494
|
-
let trail =
|
|
7494
|
+
let trail = str5.length - 1;
|
|
7495
7495
|
if (leading) {
|
|
7496
|
-
while (lead <
|
|
7496
|
+
while (lead < str5.length && predicate(str5.charCodeAt(lead))) lead++;
|
|
7497
7497
|
}
|
|
7498
7498
|
if (trailing) {
|
|
7499
|
-
while (trail > 0 && predicate(
|
|
7499
|
+
while (trail > 0 && predicate(str5.charCodeAt(trail))) trail--;
|
|
7500
7500
|
}
|
|
7501
|
-
return lead === 0 && trail ===
|
|
7501
|
+
return lead === 0 && trail === str5.length - 1 ? str5 : str5.slice(lead, trail + 1);
|
|
7502
7502
|
}
|
|
7503
7503
|
function isomorphicDecode(input) {
|
|
7504
7504
|
const length = input.length;
|
|
@@ -9417,7 +9417,7 @@ var require_body = __commonJS({
|
|
|
9417
9417
|
const boundary = `----formdata-undici-0${`${random(1e11)}`.padStart(11, "0")}`;
|
|
9418
9418
|
const prefix = `--${boundary}\r
|
|
9419
9419
|
Content-Disposition: form-data`;
|
|
9420
|
-
const escape = (
|
|
9420
|
+
const escape = (str5) => str5.replace(/\n/g, "%0A").replace(/\r/g, "%0D").replace(/"/g, "%22");
|
|
9421
9421
|
const normalizeLinefeeds = (value) => value.replace(/\r?\n|\r/g, "\r\n");
|
|
9422
9422
|
const blobParts = [];
|
|
9423
9423
|
const rn = new Uint8Array([13, 10]);
|
|
@@ -9505,7 +9505,7 @@ Content-Type: ${value.type || "application/octet-stream"}\r
|
|
|
9505
9505
|
}
|
|
9506
9506
|
return controller.desiredSize > 0;
|
|
9507
9507
|
},
|
|
9508
|
-
async cancel(
|
|
9508
|
+
async cancel(reason3) {
|
|
9509
9509
|
await iterator.return();
|
|
9510
9510
|
},
|
|
9511
9511
|
type: "bytes"
|
|
@@ -9985,7 +9985,7 @@ var require_client_h1 = __commonJS({
|
|
|
9985
9985
|
util2.destroy(this.socket, new HeadersOverflowError());
|
|
9986
9986
|
}
|
|
9987
9987
|
}
|
|
9988
|
-
onUpgrade(
|
|
9988
|
+
onUpgrade(head2) {
|
|
9989
9989
|
const { upgrade, client, socket, headers, statusCode } = this;
|
|
9990
9990
|
assert(upgrade);
|
|
9991
9991
|
assert(client[kSocket] === socket);
|
|
@@ -10000,7 +10000,7 @@ var require_client_h1 = __commonJS({
|
|
|
10000
10000
|
this.shouldKeepAlive = null;
|
|
10001
10001
|
this.headers = [];
|
|
10002
10002
|
this.headersSize = 0;
|
|
10003
|
-
socket.unshift(
|
|
10003
|
+
socket.unshift(head2);
|
|
10004
10004
|
socket[kParser].destroy();
|
|
10005
10005
|
socket[kParser] = null;
|
|
10006
10006
|
socket[kClient] = null;
|
|
@@ -12993,12 +12993,12 @@ var require_retry_handler = __commonJS({
|
|
|
12993
12993
|
this.end = null;
|
|
12994
12994
|
this.etag = null;
|
|
12995
12995
|
this.resume = null;
|
|
12996
|
-
this.handler.onConnect((
|
|
12996
|
+
this.handler.onConnect((reason3) => {
|
|
12997
12997
|
this.aborted = true;
|
|
12998
12998
|
if (this.abort) {
|
|
12999
|
-
this.abort(
|
|
12999
|
+
this.abort(reason3);
|
|
13000
13000
|
} else {
|
|
13001
|
-
this.reason =
|
|
13001
|
+
this.reason = reason3;
|
|
13002
13002
|
}
|
|
13003
13003
|
});
|
|
13004
13004
|
}
|
|
@@ -15383,9 +15383,9 @@ var require_dump = __commonJS({
|
|
|
15383
15383
|
this.#abort = abort;
|
|
15384
15384
|
this.#handler.onConnect(this.#customAbort.bind(this));
|
|
15385
15385
|
}
|
|
15386
|
-
#customAbort(
|
|
15386
|
+
#customAbort(reason3) {
|
|
15387
15387
|
this.#aborted = true;
|
|
15388
|
-
this.#reason =
|
|
15388
|
+
this.#reason = reason3;
|
|
15389
15389
|
}
|
|
15390
15390
|
// TODO: will require adjustment after new hooks are out
|
|
15391
15391
|
onHeaders(statusCode, rawHeaders, resume, statusMessage) {
|
|
@@ -16412,13 +16412,13 @@ var require_response = __commonJS({
|
|
|
16412
16412
|
urlList: init?.urlList ? [...init.urlList] : []
|
|
16413
16413
|
};
|
|
16414
16414
|
}
|
|
16415
|
-
function makeNetworkError(
|
|
16416
|
-
const isError = isErrorLike(
|
|
16415
|
+
function makeNetworkError(reason3) {
|
|
16416
|
+
const isError = isErrorLike(reason3);
|
|
16417
16417
|
return makeResponse({
|
|
16418
16418
|
type: "error",
|
|
16419
16419
|
status: 0,
|
|
16420
|
-
error: isError ?
|
|
16421
|
-
aborted:
|
|
16420
|
+
error: isError ? reason3 : new Error(reason3 ? String(reason3) : reason3),
|
|
16421
|
+
aborted: reason3 && reason3.name === "AbortError"
|
|
16422
16422
|
});
|
|
16423
16423
|
}
|
|
16424
16424
|
function isNetworkError(response) {
|
|
@@ -17400,13 +17400,13 @@ var require_fetch = __commonJS({
|
|
|
17400
17400
|
this.dump = false;
|
|
17401
17401
|
this.state = "ongoing";
|
|
17402
17402
|
}
|
|
17403
|
-
terminate(
|
|
17403
|
+
terminate(reason3) {
|
|
17404
17404
|
if (this.state !== "ongoing") {
|
|
17405
17405
|
return;
|
|
17406
17406
|
}
|
|
17407
17407
|
this.state = "terminated";
|
|
17408
|
-
this.connection?.destroy(
|
|
17409
|
-
this.emit("terminated",
|
|
17408
|
+
this.connection?.destroy(reason3);
|
|
17409
|
+
this.emit("terminated", reason3);
|
|
17410
17410
|
}
|
|
17411
17411
|
// https://fetch.spec.whatwg.org/#fetch-controller-abort
|
|
17412
17412
|
abort(error) {
|
|
@@ -17685,7 +17685,7 @@ var require_fetch = __commonJS({
|
|
|
17685
17685
|
fetchParams.controller.dump = true;
|
|
17686
17686
|
}
|
|
17687
17687
|
if (request.integrity) {
|
|
17688
|
-
const processBodyError = (
|
|
17688
|
+
const processBodyError = (reason3) => fetchFinale(fetchParams, makeNetworkError(reason3));
|
|
17689
17689
|
if (request.responseTainting === "opaque" || response.body == null) {
|
|
17690
17690
|
processBodyError(response.error);
|
|
17691
17691
|
return;
|
|
@@ -18163,9 +18163,9 @@ var require_fetch = __commonJS({
|
|
|
18163
18163
|
const pullAlgorithm = async () => {
|
|
18164
18164
|
await fetchParams.controller.resume();
|
|
18165
18165
|
};
|
|
18166
|
-
const cancelAlgorithm = (
|
|
18166
|
+
const cancelAlgorithm = (reason3) => {
|
|
18167
18167
|
if (!isCancelled(fetchParams)) {
|
|
18168
|
-
fetchParams.controller.abort(
|
|
18168
|
+
fetchParams.controller.abort(reason3);
|
|
18169
18169
|
}
|
|
18170
18170
|
};
|
|
18171
18171
|
const stream = new ReadableStream(
|
|
@@ -18176,8 +18176,8 @@ var require_fetch = __commonJS({
|
|
|
18176
18176
|
async pull(controller) {
|
|
18177
18177
|
await pullAlgorithm(controller);
|
|
18178
18178
|
},
|
|
18179
|
-
async cancel(
|
|
18180
|
-
await cancelAlgorithm(
|
|
18179
|
+
async cancel(reason3) {
|
|
18180
|
+
await cancelAlgorithm(reason3);
|
|
18181
18181
|
},
|
|
18182
18182
|
type: "bytes"
|
|
18183
18183
|
}
|
|
@@ -18226,7 +18226,7 @@ var require_fetch = __commonJS({
|
|
|
18226
18226
|
}
|
|
18227
18227
|
}
|
|
18228
18228
|
};
|
|
18229
|
-
function onAborted(
|
|
18229
|
+
function onAborted(reason3) {
|
|
18230
18230
|
if (isAborted2(fetchParams)) {
|
|
18231
18231
|
response.aborted = true;
|
|
18232
18232
|
if (isReadable(stream)) {
|
|
@@ -18237,7 +18237,7 @@ var require_fetch = __commonJS({
|
|
|
18237
18237
|
} else {
|
|
18238
18238
|
if (isReadable(stream)) {
|
|
18239
18239
|
fetchParams.controller.controller.error(new TypeError("terminated", {
|
|
18240
|
-
cause: isErrorLike(
|
|
18240
|
+
cause: isErrorLike(reason3) ? reason3 : void 0
|
|
18241
18241
|
}));
|
|
18242
18242
|
}
|
|
18243
18243
|
}
|
|
@@ -20265,9 +20265,9 @@ var require_cookies = __commonJS({
|
|
|
20265
20265
|
webidl.argumentLengthCheck(arguments, 2, "setCookie");
|
|
20266
20266
|
webidl.brandCheck(headers, Headers, { strict: false });
|
|
20267
20267
|
cookie = webidl.converters.Cookie(cookie);
|
|
20268
|
-
const
|
|
20269
|
-
if (
|
|
20270
|
-
headers.append("Set-Cookie",
|
|
20268
|
+
const str5 = stringify(cookie);
|
|
20269
|
+
if (str5) {
|
|
20270
|
+
headers.append("Set-Cookie", str5);
|
|
20271
20271
|
}
|
|
20272
20272
|
}
|
|
20273
20273
|
webidl.converters.DeleteCookieAttributes = webidl.dictionaryConverter([
|
|
@@ -20778,16 +20778,16 @@ var require_util7 = __commonJS({
|
|
|
20778
20778
|
}
|
|
20779
20779
|
return code >= 3e3 && code <= 4999;
|
|
20780
20780
|
}
|
|
20781
|
-
function failWebsocketConnection(ws,
|
|
20781
|
+
function failWebsocketConnection(ws, reason3) {
|
|
20782
20782
|
const { [kController]: controller, [kResponse]: response } = ws;
|
|
20783
20783
|
controller.abort();
|
|
20784
20784
|
if (response?.socket && !response.socket.destroyed) {
|
|
20785
20785
|
response.socket.destroy();
|
|
20786
20786
|
}
|
|
20787
|
-
if (
|
|
20787
|
+
if (reason3) {
|
|
20788
20788
|
fireEvent("error", ws, (type, init) => new ErrorEvent(type, init), {
|
|
20789
|
-
error: new Error(
|
|
20790
|
-
message:
|
|
20789
|
+
error: new Error(reason3),
|
|
20790
|
+
message: reason3
|
|
20791
20791
|
});
|
|
20792
20792
|
}
|
|
20793
20793
|
}
|
|
@@ -21045,7 +21045,7 @@ var require_connection = __commonJS({
|
|
|
21045
21045
|
});
|
|
21046
21046
|
return controller;
|
|
21047
21047
|
}
|
|
21048
|
-
function closeWebSocketConnection(ws, code,
|
|
21048
|
+
function closeWebSocketConnection(ws, code, reason3, reasonByteLength) {
|
|
21049
21049
|
if (isClosing(ws) || isClosed(ws)) {
|
|
21050
21050
|
} else if (!isEstablished(ws)) {
|
|
21051
21051
|
failWebsocketConnection(ws, "Connection was closed before it was established.");
|
|
@@ -21053,13 +21053,13 @@ var require_connection = __commonJS({
|
|
|
21053
21053
|
} else if (ws[kSentClose] === sentCloseFrameState.NOT_SENT) {
|
|
21054
21054
|
ws[kSentClose] = sentCloseFrameState.PROCESSING;
|
|
21055
21055
|
const frame3 = new WebsocketFrameSend();
|
|
21056
|
-
if (code !== void 0 &&
|
|
21056
|
+
if (code !== void 0 && reason3 === void 0) {
|
|
21057
21057
|
frame3.frameData = Buffer.allocUnsafe(2);
|
|
21058
21058
|
frame3.frameData.writeUInt16BE(code, 0);
|
|
21059
|
-
} else if (code !== void 0 &&
|
|
21059
|
+
} else if (code !== void 0 && reason3 !== void 0) {
|
|
21060
21060
|
frame3.frameData = Buffer.allocUnsafe(2 + reasonByteLength);
|
|
21061
21061
|
frame3.frameData.writeUInt16BE(code, 0);
|
|
21062
|
-
frame3.frameData.write(
|
|
21062
|
+
frame3.frameData.write(reason3, 2, "utf-8");
|
|
21063
21063
|
} else {
|
|
21064
21064
|
frame3.frameData = emptyBuffer;
|
|
21065
21065
|
}
|
|
@@ -21084,11 +21084,11 @@ var require_connection = __commonJS({
|
|
|
21084
21084
|
response.socket.off("error", onSocketError);
|
|
21085
21085
|
const wasClean = ws[kSentClose] === sentCloseFrameState.SENT && ws[kReceivedClose];
|
|
21086
21086
|
let code = 1005;
|
|
21087
|
-
let
|
|
21087
|
+
let reason3 = "";
|
|
21088
21088
|
const result = ws[kByteParser].closingInfo;
|
|
21089
21089
|
if (result && !result.error) {
|
|
21090
21090
|
code = result.code ?? 1005;
|
|
21091
|
-
|
|
21091
|
+
reason3 = result.reason;
|
|
21092
21092
|
} else if (!ws[kReceivedClose]) {
|
|
21093
21093
|
code = 1006;
|
|
21094
21094
|
}
|
|
@@ -21096,13 +21096,13 @@ var require_connection = __commonJS({
|
|
|
21096
21096
|
fireEvent("close", ws, (type, init) => new CloseEvent(type, init), {
|
|
21097
21097
|
wasClean,
|
|
21098
21098
|
code,
|
|
21099
|
-
reason
|
|
21099
|
+
reason: reason3
|
|
21100
21100
|
});
|
|
21101
21101
|
if (channels.close.hasSubscribers) {
|
|
21102
21102
|
channels.close.publish({
|
|
21103
21103
|
websocket: ws,
|
|
21104
21104
|
code,
|
|
21105
|
-
reason
|
|
21105
|
+
reason: reason3
|
|
21106
21106
|
});
|
|
21107
21107
|
}
|
|
21108
21108
|
}
|
|
@@ -21225,9 +21225,9 @@ var require_receiver = __commonJS({
|
|
|
21225
21225
|
var { closeWebSocketConnection } = require_connection();
|
|
21226
21226
|
var { PerMessageDeflate } = require_permessage_deflate();
|
|
21227
21227
|
var { MessageSizeExceededError } = require_errors();
|
|
21228
|
-
function failWebsocketConnectionWithCode(ws, code,
|
|
21229
|
-
closeWebSocketConnection(ws, code,
|
|
21230
|
-
failWebsocketConnection(ws,
|
|
21228
|
+
function failWebsocketConnectionWithCode(ws, code, reason3) {
|
|
21229
|
+
closeWebSocketConnection(ws, code, reason3, Buffer.byteLength(reason3));
|
|
21230
|
+
failWebsocketConnection(ws, reason3);
|
|
21231
21231
|
}
|
|
21232
21232
|
var ByteParser = class extends Writable {
|
|
21233
21233
|
#buffers = [];
|
|
@@ -21497,16 +21497,16 @@ var require_receiver = __commonJS({
|
|
|
21497
21497
|
if (code !== void 0 && !isValidStatusCode(code)) {
|
|
21498
21498
|
return { code: 1002, reason: "Invalid status code", error: true };
|
|
21499
21499
|
}
|
|
21500
|
-
let
|
|
21501
|
-
if (
|
|
21502
|
-
|
|
21500
|
+
let reason3 = data.subarray(2);
|
|
21501
|
+
if (reason3[0] === 239 && reason3[1] === 187 && reason3[2] === 191) {
|
|
21502
|
+
reason3 = reason3.subarray(3);
|
|
21503
21503
|
}
|
|
21504
21504
|
try {
|
|
21505
|
-
|
|
21505
|
+
reason3 = utf8Decode(reason3);
|
|
21506
21506
|
} catch {
|
|
21507
21507
|
return { code: 1007, reason: "Invalid UTF-8", error: true };
|
|
21508
21508
|
}
|
|
21509
|
-
return { code, reason, error: false };
|
|
21509
|
+
return { code, reason: reason3, error: false };
|
|
21510
21510
|
}
|
|
21511
21511
|
/**
|
|
21512
21512
|
* Parses control frames.
|
|
@@ -21521,9 +21521,9 @@ var require_receiver = __commonJS({
|
|
|
21521
21521
|
}
|
|
21522
21522
|
this.#info.closeInfo = this.parseCloseBody(body);
|
|
21523
21523
|
if (this.#info.closeInfo.error) {
|
|
21524
|
-
const { code, reason } = this.#info.closeInfo;
|
|
21525
|
-
closeWebSocketConnection(this.ws, code,
|
|
21526
|
-
failWebsocketConnection(this.ws,
|
|
21524
|
+
const { code, reason: reason3 } = this.#info.closeInfo;
|
|
21525
|
+
closeWebSocketConnection(this.ws, code, reason3, reason3.length);
|
|
21526
|
+
failWebsocketConnection(this.ws, reason3);
|
|
21527
21527
|
return false;
|
|
21528
21528
|
}
|
|
21529
21529
|
if (this.ws[kSentClose] !== sentCloseFrameState.SENT) {
|
|
@@ -21760,14 +21760,14 @@ var require_websocket = __commonJS({
|
|
|
21760
21760
|
* @param {number|undefined} code
|
|
21761
21761
|
* @param {string|undefined} reason
|
|
21762
21762
|
*/
|
|
21763
|
-
close(code = void 0,
|
|
21763
|
+
close(code = void 0, reason3 = void 0) {
|
|
21764
21764
|
webidl.brandCheck(this, _WebSocket);
|
|
21765
21765
|
const prefix = "WebSocket.close";
|
|
21766
21766
|
if (code !== void 0) {
|
|
21767
21767
|
code = webidl.converters["unsigned short"](code, prefix, "code", { clamp: true });
|
|
21768
21768
|
}
|
|
21769
|
-
if (
|
|
21770
|
-
|
|
21769
|
+
if (reason3 !== void 0) {
|
|
21770
|
+
reason3 = webidl.converters.USVString(reason3, prefix, "reason");
|
|
21771
21771
|
}
|
|
21772
21772
|
if (code !== void 0) {
|
|
21773
21773
|
if (code !== 1e3 && (code < 3e3 || code > 4999)) {
|
|
@@ -21775,8 +21775,8 @@ var require_websocket = __commonJS({
|
|
|
21775
21775
|
}
|
|
21776
21776
|
}
|
|
21777
21777
|
let reasonByteLength = 0;
|
|
21778
|
-
if (
|
|
21779
|
-
reasonByteLength = Buffer.byteLength(
|
|
21778
|
+
if (reason3 !== void 0) {
|
|
21779
|
+
reasonByteLength = Buffer.byteLength(reason3);
|
|
21780
21780
|
if (reasonByteLength > 123) {
|
|
21781
21781
|
throw new DOMException(
|
|
21782
21782
|
`Reason must be less than 123 bytes; received ${reasonByteLength}`,
|
|
@@ -21784,7 +21784,7 @@ var require_websocket = __commonJS({
|
|
|
21784
21784
|
);
|
|
21785
21785
|
}
|
|
21786
21786
|
}
|
|
21787
|
-
closeWebSocketConnection(this, code,
|
|
21787
|
+
closeWebSocketConnection(this, code, reason3, reasonByteLength);
|
|
21788
21788
|
}
|
|
21789
21789
|
/**
|
|
21790
21790
|
* @see https://websockets.spec.whatwg.org/#dom-websocket-send
|
|
@@ -22749,13 +22749,11 @@ import { createHash, randomUUID } from "crypto";
|
|
|
22749
22749
|
import { readFileSync } from "fs";
|
|
22750
22750
|
import { homedir as homedir2 } from "os";
|
|
22751
22751
|
import { join as join2 } from "path";
|
|
22752
|
-
import { randomUUID as randomUUID3 } from "crypto";
|
|
22753
|
-
import { setTimeout as sleep2 } from "timers/promises";
|
|
22754
22752
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
22753
|
+
import { setTimeout as sleep2 } from "timers/promises";
|
|
22755
22754
|
import { closeSync, existsSync as existsSync2, mkdirSync, openSync, readFileSync as readFileSync2, rmSync, statSync, writeFileSync } from "fs";
|
|
22756
22755
|
import { homedir as homedir22 } from "os";
|
|
22757
22756
|
import { join as join22 } from "path";
|
|
22758
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
22759
22757
|
async function proxy() {
|
|
22760
22758
|
if (!PROXY_ENV.some((k) => process.env[k])) return void 0;
|
|
22761
22759
|
return agent ??= new (await Promise.resolve().then(() => __toESM(require_undici(), 1))).EnvHttpProxyAgent();
|
|
@@ -23690,6 +23688,54 @@ function mcpInputSchema(s) {
|
|
|
23690
23688
|
delete schema.$schema;
|
|
23691
23689
|
return draft2020(schema);
|
|
23692
23690
|
}
|
|
23691
|
+
function capRefusals(text, units22, field) {
|
|
23692
|
+
const out = [];
|
|
23693
|
+
const name = field === "text" ? "answer" : field;
|
|
23694
|
+
if (text.length > ASK_MAX) out.push({
|
|
23695
|
+
refusal: "ask_too_long",
|
|
23696
|
+
length: text.length,
|
|
23697
|
+
cap: ASK_MAX,
|
|
23698
|
+
path: field === "text" ? ["answer", "text"] : [field],
|
|
23699
|
+
message: `ask_too_long: the ${name} is ${text.length} characters; the cap is ${ASK_MAX}. Keep the one point in the ${name} and move the context into units.`
|
|
23700
|
+
});
|
|
23701
|
+
const all = units22 ?? [];
|
|
23702
|
+
if (all.length > UNITS_MAX) out.push({
|
|
23703
|
+
refusal: "too_many_units",
|
|
23704
|
+
length: all.length,
|
|
23705
|
+
cap: UNITS_MAX,
|
|
23706
|
+
path: ["units"],
|
|
23707
|
+
message: `too_many_units: ${all.length} units; the cap is ${UNITS_MAX}. Keep only the context this ${name} needs.`
|
|
23708
|
+
});
|
|
23709
|
+
all.forEach((unit, index) => {
|
|
23710
|
+
if (unit.title.length > UNIT_TITLE_MAX) out.push({
|
|
23711
|
+
refusal: "unit_title_too_long",
|
|
23712
|
+
index,
|
|
23713
|
+
length: unit.title.length,
|
|
23714
|
+
cap: UNIT_TITLE_MAX,
|
|
23715
|
+
path: ["units", index, "title"],
|
|
23716
|
+
message: `unit_title_too_long: units[${index}]'s title is ${unit.title.length} characters; the cap is ${UNIT_TITLE_MAX}.`
|
|
23717
|
+
});
|
|
23718
|
+
if (unit.body.length > UNIT_BODY_MAX) out.push({
|
|
23719
|
+
refusal: "unit_body_too_long",
|
|
23720
|
+
index,
|
|
23721
|
+
length: unit.body.length,
|
|
23722
|
+
cap: UNIT_BODY_MAX,
|
|
23723
|
+
path: ["units", index, "body"],
|
|
23724
|
+
message: `unit_body_too_long: units[${index}]'s body is ${unit.body.length} characters; the cap is ${UNIT_BODY_MAX}. Cut it into two units.`
|
|
23725
|
+
});
|
|
23726
|
+
});
|
|
23727
|
+
return out;
|
|
23728
|
+
}
|
|
23729
|
+
function refuseOverCaps(text, units22, field, ctx) {
|
|
23730
|
+
for (const { path, message, ...params } of capRefusals(text, units22, field)) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message, params });
|
|
23731
|
+
}
|
|
23732
|
+
function entryUnit(entry) {
|
|
23733
|
+
if (entry.kind !== "contribution" || !entry.aboutId) return null;
|
|
23734
|
+
const plain = entry.content && "plain" in entry.content ? entry.content.plain : null;
|
|
23735
|
+
if (!plain || typeof plain !== "object") return null;
|
|
23736
|
+
const { title, text } = plain;
|
|
23737
|
+
return typeof title === "string" && typeof text === "string" ? { title, body: text } : null;
|
|
23738
|
+
}
|
|
23693
23739
|
function sessionSlot(sessionId2) {
|
|
23694
23740
|
const id22 = sessionId2 ?? sessionId();
|
|
23695
23741
|
return `session:${id22.slice(0, 8)}`;
|
|
@@ -23805,39 +23851,26 @@ function overrideToken(secret) {
|
|
|
23805
23851
|
async function fail(what, res) {
|
|
23806
23852
|
throw new ApiError(what, res.status, await res.text());
|
|
23807
23853
|
}
|
|
23808
|
-
async function
|
|
23854
|
+
async function manageGoals(input, opts = {}) {
|
|
23809
23855
|
const token = authToken(opts.token) ?? "";
|
|
23810
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals`, {
|
|
23856
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/manage`, {
|
|
23811
23857
|
method: "POST",
|
|
23812
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${token}
|
|
23858
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
23813
23859
|
body: JSON.stringify(input)
|
|
23814
23860
|
}));
|
|
23815
|
-
if (!res.ok) await fail("
|
|
23816
|
-
return await res.json();
|
|
23817
|
-
}
|
|
23818
|
-
async function claimGoal(goalId, opts = {}) {
|
|
23819
|
-
const token = authToken(opts.token) ?? "";
|
|
23820
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify(goalId ? { goalId } : {}) }));
|
|
23821
|
-
if (!res.ok) await fail("claim_goal", res);
|
|
23861
|
+
if (!res.ok) await fail("manage_goals", res);
|
|
23822
23862
|
return await res.json();
|
|
23823
23863
|
}
|
|
23824
|
-
async function getGoal(goalId, opts = {},
|
|
23864
|
+
async function getGoal(goalId, opts = {}, read3 = {}) {
|
|
23825
23865
|
const token = authToken(opts.token) ?? "";
|
|
23826
|
-
const query = [
|
|
23866
|
+
const query = [read3.history ? "history=1" : "", read3.diagnose ? "diagnose=1" : ""].filter(Boolean).join("&");
|
|
23827
23867
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}${query ? `?${query}` : ""}`, {
|
|
23828
23868
|
method: "GET",
|
|
23829
|
-
headers: { authorization: `Bearer ${token}
|
|
23869
|
+
headers: { authorization: `Bearer ${token}` }
|
|
23830
23870
|
}));
|
|
23831
23871
|
if (!res.ok) await fail("get_goal", res);
|
|
23832
23872
|
return await res.json();
|
|
23833
23873
|
}
|
|
23834
|
-
async function updateGoal(goalId, input, opts = {}) {
|
|
23835
|
-
const token = authToken(opts.token) ?? "";
|
|
23836
|
-
const operationId = input.operationId ?? randomUUID2();
|
|
23837
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}`, "x-paigy-model": "goal-entry-v1" }, body: JSON.stringify({ ...input, operationId }) }));
|
|
23838
|
-
if (!res.ok) await fail("update_goal", res);
|
|
23839
|
-
return await res.json();
|
|
23840
|
-
}
|
|
23841
23874
|
async function hatch(name, voice = null, opts = {}) {
|
|
23842
23875
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/hatch`, {
|
|
23843
23876
|
method: "POST",
|
|
@@ -23926,7 +23959,7 @@ async function listNotes(opts = {}) {
|
|
|
23926
23959
|
}
|
|
23927
23960
|
async function listConnections(opts = {}) {
|
|
23928
23961
|
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
|
|
23929
|
-
headers: { authorization: `Bearer ${authToken(opts.token)}
|
|
23962
|
+
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
23930
23963
|
}));
|
|
23931
23964
|
if (!res.ok) throw new Error(`list_connections failed: ${res.status} ${await res.text()}`);
|
|
23932
23965
|
return await res.json();
|
|
@@ -23949,118 +23982,96 @@ async function acceptTriage(proposalId, body, opts = {}) {
|
|
|
23949
23982
|
if (!res.ok) throw new Error(`accept_triage failed: ${res.status} ${await res.text()}`);
|
|
23950
23983
|
return await res.json();
|
|
23951
23984
|
}
|
|
23952
|
-
function
|
|
23953
|
-
const
|
|
23954
|
-
|
|
23955
|
-
|
|
23956
|
-
|
|
23957
|
-
if (
|
|
23958
|
-
|
|
23959
|
-
if (!owner || !name) return null;
|
|
23960
|
-
return `${owner}/${name}`.toLowerCase();
|
|
23961
|
-
}
|
|
23962
|
-
function currentRepo(cwd = process.cwd()) {
|
|
23963
|
-
if (asked !== void 0) return asked;
|
|
23964
|
-
try {
|
|
23965
|
-
const url = execFileSync2("git", ["remote", "get-url", "origin"], {
|
|
23966
|
-
cwd,
|
|
23967
|
-
encoding: "utf8",
|
|
23968
|
-
timeout: 2e3,
|
|
23969
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
23970
|
-
});
|
|
23971
|
-
asked = repoFromRemote(url);
|
|
23972
|
-
} catch {
|
|
23973
|
-
asked = null;
|
|
23974
|
-
}
|
|
23975
|
-
return asked;
|
|
23985
|
+
async function readDelivery(deliveryId, opts = {}) {
|
|
23986
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, {
|
|
23987
|
+
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}` },
|
|
23988
|
+
signal: opts.signal
|
|
23989
|
+
}));
|
|
23990
|
+
if (!res.ok) await fail("read_delivery", res);
|
|
23991
|
+
return await res.json();
|
|
23976
23992
|
}
|
|
23977
23993
|
async function contact(input, opts = {}) {
|
|
23978
23994
|
const parsed = ContactSchema.parse(input);
|
|
23995
|
+
if (!sendsAnything(parsed)) throw new Error("contact with nothing to send receives: call receiveContact");
|
|
23979
23996
|
opts.signal?.throwIfAborted();
|
|
23980
23997
|
const send22 = opts.reach ?? reach;
|
|
23981
|
-
const
|
|
23982
|
-
|
|
23983
|
-
|
|
23984
|
-
|
|
23985
|
-
|
|
23986
|
-
|
|
23987
|
-
|
|
23988
|
-
|
|
23989
|
-
|
|
23990
|
-
|
|
23991
|
-
|
|
23992
|
-
|
|
23993
|
-
|
|
23994
|
-
|
|
23995
|
-
|
|
23996
|
-
|
|
23997
|
-
|
|
23998
|
-
|
|
23999
|
-
|
|
24000
|
-
|
|
24001
|
-
|
|
24002
|
-
|
|
24003
|
-
|
|
24004
|
-
|
|
24005
|
-
|
|
24006
|
-
|
|
24007
|
-
|
|
24008
|
-
|
|
24009
|
-
|
|
24010
|
-
|
|
24011
|
-
})
|
|
24012
|
-
}));
|
|
24013
|
-
if (!res.ok) await fail("batch contact", res);
|
|
24014
|
-
const receipt = await res.json();
|
|
24015
|
-
deliveries = receipt.deliveries ?? [];
|
|
24016
|
-
if (parsed.channel === "call" && receipt.channel && receipt.channel !== "call") demoted = DEMOTED;
|
|
24017
|
-
recorded = receipt.recorded ?? [];
|
|
24018
|
-
if (deliveries.length === 0 && recorded.length) return { sent: false, recorded, message: NOT_SENT };
|
|
24019
|
-
if (deliveries.length === 0) throw new Error("Goal contact returned no Delivery identities");
|
|
24020
|
-
deliveryId = deliveries[0]?.deliveryId ?? "";
|
|
24021
|
-
if (!deliveryId) throw new Error("Goal contact returned no valid Delivery identity");
|
|
24022
|
-
}
|
|
24023
|
-
const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id: id22, deliveryId: deliveryId2, goalId }) => ({ ...id22 ? { id: id22 } : {}, deliveryId: deliveryId2, goalId }));
|
|
24024
|
-
const joinedCard = deliveries[0]?.joinedCard === true;
|
|
24025
|
-
const joinedCall = deliveries[0]?.joinedCall === true;
|
|
24026
|
-
const read = async (signal2) => {
|
|
24027
|
-
const res = await ensureAuthed(await send22(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
24028
|
-
if (!res.ok) await fail("read_delivery", res);
|
|
24029
|
-
const one = await res.json();
|
|
23998
|
+
const acknowledged = parsed.ackEventIds?.length ? await acknowledge(parsed.ackEventIds, opts) : void 0;
|
|
23999
|
+
const questions = parsed.questions?.map((q) => ({ ...q, questionId: q.questionId ?? randomUUID2() }));
|
|
24000
|
+
const res = await ensureAuthed(await send22(`${BACKEND_URL}/api/goals/contact`, {
|
|
24001
|
+
method: "POST",
|
|
24002
|
+
signal: opts.signal,
|
|
24003
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}` },
|
|
24004
|
+
body: JSON.stringify({
|
|
24005
|
+
operationId: opts.operationId ?? randomUUID2(),
|
|
24006
|
+
...parsed.updates ? { updates: parsed.updates } : {},
|
|
24007
|
+
...questions ? { questions } : {},
|
|
24008
|
+
...parsed.answers ? { answers: parsed.answers } : {},
|
|
24009
|
+
...parsed.withdrawQuestionIds ? { withdrawQuestionIds: parsed.withdrawQuestionIds } : {},
|
|
24010
|
+
...parsed.questionDependencies ? { questionDependencies: parsed.questionDependencies } : {}
|
|
24011
|
+
})
|
|
24012
|
+
}));
|
|
24013
|
+
if (!res.ok) await fail("contact", res);
|
|
24014
|
+
const receipt = await res.json();
|
|
24015
|
+
const results = receipt.results ?? [];
|
|
24016
|
+
const ok = receipt.ok ?? results.every((r) => r.status !== "failed");
|
|
24017
|
+
const deliveries = receipt.deliveries ?? [];
|
|
24018
|
+
const recorded = results.filter((r) => r.status === "recorded" && r.goalId).map((r) => ({ goalId: r.goalId }));
|
|
24019
|
+
const askedCall = [...parsed.updates ?? [], ...questions ?? []].some((m) => m.userExplicitlyRequested === "call") || !!questions?.some((q) => q.workItBlocks?.length);
|
|
24020
|
+
const demoted = askedCall && receipt.channel && receipt.channel !== "call" ? DEMOTED : void 0;
|
|
24021
|
+
const acked = acknowledged ? { acknowledged } : {};
|
|
24022
|
+
if (!deliveries.length) {
|
|
24023
|
+
return { sent: false, ok, results, ...recorded.length ? { recorded } : {}, message: recorded.length ? NOT_SENT : APPLIED, waitOutcome: "not_waited", ...acked };
|
|
24024
|
+
}
|
|
24025
|
+
const lead = deliveries.find((d) => d.kind === "question") ?? deliveries[0];
|
|
24026
|
+
const read3 = async (signal2) => {
|
|
24027
|
+
const one = await readDelivery(lead.deliveryId, { ...opts, signal: signal2 });
|
|
24030
24028
|
return {
|
|
24031
24029
|
...one,
|
|
24032
|
-
|
|
24030
|
+
ok,
|
|
24031
|
+
results,
|
|
24032
|
+
...deliveries.length > 1 ? { deliveries: deliveries.map(({ deliveryId, goalId, kind, questionId }) => ({ deliveryId, goalId, kind, ...questionId ? { questionId } : {} })) } : {},
|
|
24033
24033
|
...recorded.length ? { recorded, notSent: NOT_SENT } : {},
|
|
24034
|
-
...joinedCard ? { joinedCard: true } : {},
|
|
24035
|
-
|
|
24036
|
-
...
|
|
24034
|
+
...lead.joinedCard ? { joinedCard: true } : {},
|
|
24035
|
+
// IT WENT ONTO A CALL ALREADY HAPPENING (owner, 2026-09-28): the view words it as that call.
|
|
24036
|
+
...lead.joinedCall ? { joinedCall: true } : {},
|
|
24037
|
+
...demoted ? { demoted } : {},
|
|
24038
|
+
...acked
|
|
24037
24039
|
};
|
|
24038
24040
|
};
|
|
24039
|
-
const settled = (d) => d.
|
|
24040
|
-
if (opts.waits === false) return
|
|
24041
|
+
const settled = (d) => d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution" && !entryUnit(e));
|
|
24042
|
+
if (parsed.wait !== true || opts.waits === false) return { ...await read3(opts.signal), waitOutcome: "not_waited" };
|
|
24041
24043
|
const window = AbortSignal.timeout(AWAIT_WINDOW_MS);
|
|
24042
24044
|
const signal = opts.signal ? AbortSignal.any([opts.signal, window]) : window;
|
|
24043
24045
|
let latest;
|
|
24044
24046
|
try {
|
|
24045
24047
|
while (true) {
|
|
24046
24048
|
signal.throwIfAborted();
|
|
24047
|
-
latest = await
|
|
24048
|
-
if (settled(latest)) return latest;
|
|
24049
|
+
latest = await read3(signal);
|
|
24050
|
+
if (settled(latest)) return { ...latest, waitOutcome: "available" };
|
|
24049
24051
|
await sleep2(5e3, void 0, { signal });
|
|
24050
24052
|
}
|
|
24051
24053
|
} catch (error) {
|
|
24052
24054
|
opts.signal?.throwIfAborted();
|
|
24053
|
-
if (window.aborted && latest) return latest;
|
|
24055
|
+
if (window.aborted && latest) return { ...latest, waitOutcome: "expired" };
|
|
24054
24056
|
throw error;
|
|
24055
24057
|
}
|
|
24056
24058
|
}
|
|
24057
|
-
async function
|
|
24059
|
+
async function receive(opts = {}) {
|
|
24058
24060
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries`, {
|
|
24059
|
-
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}
|
|
24061
|
+
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}` }
|
|
24060
24062
|
}));
|
|
24061
|
-
if (!res.ok) await fail("
|
|
24063
|
+
if (!res.ok) await fail("receive", res);
|
|
24062
24064
|
return await res.json();
|
|
24063
24065
|
}
|
|
24066
|
+
async function acknowledge(eventIds, opts = {}) {
|
|
24067
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries/ack`, {
|
|
24068
|
+
method: "POST",
|
|
24069
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}` },
|
|
24070
|
+
body: JSON.stringify({ eventIds })
|
|
24071
|
+
}));
|
|
24072
|
+
if (!res.ok) await fail("acknowledge", res);
|
|
24073
|
+
return (await res.json()).results ?? [];
|
|
24074
|
+
}
|
|
24064
24075
|
function frame(line, topic, event, payload) {
|
|
24065
24076
|
const ref = String(++line.ref);
|
|
24066
24077
|
try {
|
|
@@ -24222,9 +24233,9 @@ async function subscribeWake(onNudge, opts = {}) {
|
|
|
24222
24233
|
};
|
|
24223
24234
|
}
|
|
24224
24235
|
function withCodexEnv(text) {
|
|
24225
|
-
const
|
|
24226
|
-
if (!
|
|
24227
|
-
const start =
|
|
24236
|
+
const head2 = /^\[mcp_servers\.paigy\][ \t]*(?:#[^\n]*)?\r?\n/m.exec(text);
|
|
24237
|
+
if (!head2) return null;
|
|
24238
|
+
const start = head2.index + head2[0].length;
|
|
24228
24239
|
const next = /^\[/m.exec(text.slice(start));
|
|
24229
24240
|
const end = next ? start + next.index : text.length;
|
|
24230
24241
|
const block2 = text.slice(start, end);
|
|
@@ -24243,7 +24254,7 @@ ${block2}`;
|
|
|
24243
24254
|
}
|
|
24244
24255
|
return text.slice(0, start) + updated + text.slice(end);
|
|
24245
24256
|
}
|
|
24246
|
-
var import_undici, require2, CODEX_ENV, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, CLIENT, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OptionSchema, OptionInputSchema, NIGHT,
|
|
24257
|
+
var import_undici, require2, CODEX_ENV, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, CLIENT, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OptionSchema, OptionInputSchema, NIGHT, ASK_MAX, UNITS_MAX, UNIT_TITLE_MAX, UNIT_BODY_MAX, UnitInputSchema, questionHandle, NodeRef, BlockedAction, reason, actionFits, ACTION_FITS, userExplicitlyRequested, units, UpdateInputSchema, questionFields, refineQuestion, QuestionInputSchema, QuestionWireSchema, AnswerInputSchema, QuestionDependencySchema, sendFields, ContactSchema, sendsAnything, ContactWireSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema, UpdateGoalSchema, changedGoal, goalTitle, goalOutcome, CreateChange, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange, read, GoalChangeSchema, editNames, ManageGoalsSchema, ManageGoalsToolSchema, MANAGE_GOALS_DESCRIPTION, GetGoalSchema, GET_GOAL_DESCRIPTION, SearchToolSchema, SEARCH_DESCRIPTION, CheckActivitySchema, FEEDBACK_TEXT_MAX, SendFeedbackSchema, SEND_FEEDBACK_DESCRIPTION, AGENT_TOOLS, AGENT_TOOL_NAMES, id, key, participant, SourceSchema, ResultRefSchema, NodeRefSchema, DependencySchema, goalState, existingGoalChanges, BrainGoalChangeSchema, option, QuestionChangeSchema, lessonScope, LessonChangeSchema, BrainNextSchema, messageBase, BrainMessageSchema, BrainSearchSchema, BrainResultSchema, str, strs, CompactResultSchema, COMPACT_RESULT_JSON_SCHEMA, str2, strs2, TalkerReplySchema, TALKER_REPLY_JSON_SCHEMA, str3, strs3, FilerReplySchema, FILER_REPLY_JSON_SCHEMA, LIVE_MS, WORKING_MS, ContextSchema, ParticipantSchema, TransformSchema, VisualSchema, NotifyLevelSchema, SelectShapeSchema, ReceiptEventSchema, AttentionSchema, NotifyRequestFields, NotifyRequestSchema, NotifyStatusSchema, AgentStateSchema, TurnSchema, UserAnswerSchema, IntentSchema, RideAlongSchema, AwaitItemSchema, VoiceKeySchema, AgendaTurnSchema, CLAIM_STALE_MS, InboxItemSchema, APNS_TOKEN_RE, PushTokenSchema, MissedCallSchema, clock, QUIET, BrokerTuningSchema, UserSettingsSchema, HistoryWorkSchema, HistoryEntrySchema, HistoryPageSchema, ACTIVITY_LINES, ACTIVITY_LINE_MAX, AgentActivitySchema, ConnectionSummarySchema, LedgerItemSchema, AgentLedgerSchema, ReassignResultSchema, LessonStateSchema, LessonViewSchema, QueueQuestionSchema, QueueReplySchema, QueueItemSchema, QueueDeltaSchema, COLD_AFTER_MS, NoteSourceSchema, NoteStatusSchema, NoteRepeatSchema, DecisionSchema, NoteSchema, TriageItemSchema, TriageAssignmentSchema, TriageStatusSchema, SubmitTriageSchema, TriageProposalSchema, AcceptTriageSchema, AcceptTriageResultSchema, DeliveryModeSchema, WAKE_EVENT, wakeChannel, RegisterDeliverySchema, OAuthStartSchema, DeliveryConfigSchema, HostDecisionSchema, WakeNudgeSchema, PairingStatusSchema, DeviceCodeSchema, DeviceInfoSchema, DeviceTokenSchema, SupportRequestSchema, NotificationFeedbackKindSchema, SlimOptionSchema, QuestionRowSchema, WorkStateSchema, WorkRowSchema, ComputerRowSchema, AgentRowSchema, SnapshotSchema, CallRecapSchema, TOKEN_PATH, KEY_PATH, sleep, UnpairedError, RevokedError, ApiError, tokenOverride, authToken, AWAIT_WINDOW_MS, NOT_SENT, APPLIED, DEMOTED, HEARTBEAT_MS, RETRY_MS, JOIN, JOIN_TIMEOUT_MS, lines;
|
|
24247
24258
|
var init_dist = __esm({
|
|
24248
24259
|
"../../packages/sdk/dist/index.js"() {
|
|
24249
24260
|
"use strict";
|
|
@@ -24255,6 +24266,8 @@ var init_dist = __esm({
|
|
|
24255
24266
|
init_v3();
|
|
24256
24267
|
init_zod();
|
|
24257
24268
|
init_zod();
|
|
24269
|
+
init_zod();
|
|
24270
|
+
init_zod();
|
|
24258
24271
|
import_undici = __toESM(require_undici(), 1);
|
|
24259
24272
|
require2 = __sdkCreateRequire(import.meta.url);
|
|
24260
24273
|
CODEX_ENV = ["CODEX_THREAD_ID", "CODEX_SESSION_ID", "CODEX_HOME", "PAIGY_TOKEN", "PAIGY_SESSION_ID", "PAIGY_HARNESS", "PAIGY_INSTANCE_ID", "PAIGY_ON_WAKE"];
|
|
@@ -24643,43 +24656,137 @@ var init_dist = __esm({
|
|
|
24643
24656
|
// .describe() flows into the MCP contact JSON schema (zodToJsonSchema), so
|
|
24644
24657
|
// the constraints below are what an agent reads when deciding to use these.
|
|
24645
24658
|
html: external_exports.string().max(16384).describe(
|
|
24646
|
-
"Optional sandboxed HTML/CSS preview for a visual 'pick one' (shown in the option card). Untrusted-sandboxed: NO JavaScript, NO external network or images \u2014 inline CSS and data: URIs only; <=16KB. Rendered edge-to-edge in a responsive card that is 200pt tall (about 320pt wide on a phone, with the next option peeking beside it); make your HTML fit that viewport. Use for layout/CSS mockups, tables, diffs. For a hosted image use
|
|
24659
|
+
"Optional sandboxed HTML/CSS preview for a visual 'pick one' (shown in the option card). Untrusted-sandboxed: NO JavaScript, NO external network or images \u2014 inline CSS and data: URIs only; <=16KB. Rendered edge-to-edge in a responsive card that is 200pt tall (about 320pt wide on a phone, with the next option peeking beside it); make your HTML fit that viewport. Use for layout/CSS mockups, tables, diffs. For a hosted image use the image URL instead."
|
|
24647
24660
|
).optional(),
|
|
24648
24661
|
image: external_exports.string().url().describe(
|
|
24649
|
-
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use
|
|
24662
|
+
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use the HTML preview instead."
|
|
24650
24663
|
).optional()
|
|
24651
24664
|
});
|
|
24652
|
-
OptionInputSchema =
|
|
24653
|
-
|
|
24665
|
+
OptionInputSchema = external_exports.object({
|
|
24666
|
+
id: external_exports.string().trim().min(1).max(64).regex(/^[A-Za-z0-9_.:-]+$/).optional().describe(
|
|
24667
|
+
`Optional: this option's own id, which answers name it by (selectedOptionIds). Give every option one, or none: without them the options are numbered "1", "2", \u2026 in order.`
|
|
24668
|
+
),
|
|
24669
|
+
label: external_exports.string().trim().min(1).max(1e3),
|
|
24670
|
+
hint: OptionSchema.shape.hint,
|
|
24671
|
+
htmlPreview: OptionSchema.shape.html,
|
|
24672
|
+
imgUrl: OptionSchema.shape.image
|
|
24654
24673
|
}).strict();
|
|
24655
24674
|
NIGHT = { from: 23, to: 7 };
|
|
24656
|
-
|
|
24657
|
-
|
|
24658
|
-
|
|
24659
|
-
|
|
24660
|
-
|
|
24661
|
-
|
|
24675
|
+
ASK_MAX = 250;
|
|
24676
|
+
UNITS_MAX = 12;
|
|
24677
|
+
UNIT_TITLE_MAX = 50;
|
|
24678
|
+
UNIT_BODY_MAX = 200;
|
|
24679
|
+
UnitInputSchema = external_exports.object({
|
|
24680
|
+
title: external_exports.string().trim().min(1).describe(`What this unit is about, at most ${UNIT_TITLE_MAX} characters. The app lists the titles; the person taps one to read its body.`),
|
|
24681
|
+
body: external_exports.string().trim().min(1).describe(`The unit itself, at most ${UNIT_BODY_MAX} characters.`)
|
|
24682
|
+
}).strict();
|
|
24683
|
+
questionHandle = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
24684
|
+
NodeRef = external_exports.object({
|
|
24685
|
+
type: external_exports.enum(["goal", "question"]),
|
|
24686
|
+
id: external_exports.string().uuid()
|
|
24687
|
+
}).strict().describe("A Goal or a Question, by its id.");
|
|
24688
|
+
BlockedAction = external_exports.enum(["start", "complete", "answer"]).describe("What waits: starting or completing a Goal, or answering a Question.");
|
|
24689
|
+
reason = external_exports.string().trim().min(1).max(500).describe("Why, as an explanation, never as policy.");
|
|
24690
|
+
actionFits = (b) => b.blocked.type === "goal" === (b.action !== "answer");
|
|
24691
|
+
ACTION_FITS = "a goal is blocked from start or complete; a question from answer";
|
|
24692
|
+
userExplicitlyRequested = external_exports.enum(["any", "call"]).optional().describe(
|
|
24693
|
+
`Only what the person said about THIS message, in so many words: "any" when they asked you to send it to them ("send it to my phone", "message me the result"), "call" when they asked to be called about it. It is then delivered (a call rings for the whole contact, and carries everything waiting on them); omitted, an update is only recorded as the Goal's progress unless the person needs it. Never set it to make a message louder.`
|
|
24694
|
+
);
|
|
24695
|
+
units = external_exports.array(UnitInputSchema).optional().describe(
|
|
24696
|
+
`The context this message needs, as up to ${UNITS_MAX} units in reading order, each {title, body}: a title of at most ${UNIT_TITLE_MAX} characters and a body of at most ${UNIT_BODY_MAX}. One idea per unit. Leave it out when the main text says it all.`
|
|
24697
|
+
);
|
|
24698
|
+
UpdateInputSchema = external_exports.object({
|
|
24699
|
+
message: external_exports.string().trim().min(1).describe(`The one point, at most ${ASK_MAX} characters; the context goes in units.`),
|
|
24700
|
+
goalIds: external_exports.array(external_exports.string().uuid()).min(1).max(10).describe("The Goals it is about, each one that exists: the one it is mainly about first."),
|
|
24701
|
+
units,
|
|
24702
|
+
userExplicitlyRequested
|
|
24703
|
+
}).strict().superRefine((u, ctx) => refuseOverCaps(u.message, u.units, "message", ctx));
|
|
24704
|
+
questionFields = {
|
|
24705
|
+
question: external_exports.string().trim().min(1).describe(
|
|
24706
|
+
`ONE question, in at most ${ASK_MAX} characters, and only what is needed to answer it; the context goes in units. Several questions are several objects, one each: an answer settles the one question it was given, so a person who answers the part of a bundled question that interested them settles nothing and is asked again. Separate questions cost nothing: ANY contact for a person already on a call JOINS that call, so several arrive as one call.`
|
|
24662
24707
|
),
|
|
24663
|
-
|
|
24708
|
+
goalId: external_exports.string().uuid().describe("The Goal the question is about, which must exist (create it with manage_goals first). Its answer comes back there."),
|
|
24709
|
+
units,
|
|
24710
|
+
options: external_exports.array(OptionInputSchema).min(1).max(6).optional().describe("The choices, when you have them. Each label stands on its own."),
|
|
24664
24711
|
// HOW THE OPTIONS ARE ANSWERED, SAID BY THE AGENT (owner, 2026-10-02: "one and many makes sense";
|
|
24665
|
-
// brain_prompts.md §1: structured agent questions need no model).
|
|
24666
|
-
|
|
24667
|
-
|
|
24668
|
-
|
|
24669
|
-
|
|
24712
|
+
// brain_prompts.md §1: structured agent questions need no model). The app draws all three.
|
|
24713
|
+
pickMode: external_exports.enum(["one", "many", "rank"]).optional().describe(
|
|
24714
|
+
'How the options are answered: "one" (the default) a pick, for alternatives; "many" a checklist, for independent options they may want several of; "rank" an order of all of them. Only with options.'
|
|
24715
|
+
),
|
|
24716
|
+
// WHAT THE QUESTION HOLDS UP (brain_prompts.md §2.1): replaces `waiting: 'hard'`. A question that
|
|
24717
|
+
// blocks work asks for a call (the person's settings and ring cooldowns still decide).
|
|
24718
|
+
workItBlocks: external_exports.array(external_exports.object({ blocked: NodeRef, action: BlockedAction, reason: reason.optional() }).strict().refine(actionFits, ACTION_FITS)).min(1).max(10).optional().describe(
|
|
24719
|
+
"The work that cannot go on until this is answered: a Goal's start or completion, or another Question's answer. Only for work truly blocked; it asks for a call. Leave it out for a question you can keep working around."
|
|
24720
|
+
),
|
|
24721
|
+
userExplicitlyRequested
|
|
24722
|
+
};
|
|
24723
|
+
refineQuestion = (q, ctx) => {
|
|
24724
|
+
refuseOverCaps(q.question, q.units, "question", ctx);
|
|
24725
|
+
if (q.pickMode && !q.options) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["pickMode"], message: "pickMode comes only with options" });
|
|
24726
|
+
const ids = (q.options ?? []).map((o) => o.id);
|
|
24727
|
+
if (ids.some((id22) => id22) && (ids.some((id22) => !id22) || new Set(ids).size !== ids.length)) {
|
|
24728
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["options"], message: "give every option a distinct id, or none" });
|
|
24729
|
+
}
|
|
24730
|
+
};
|
|
24731
|
+
QuestionInputSchema = external_exports.object({
|
|
24732
|
+
questionId: external_exports.string().uuid().optional().describe("Optional: your own stable id for this question (a UUID), so a resend is the same question. Minted for you when omitted; the result returns it."),
|
|
24733
|
+
...questionFields
|
|
24734
|
+
}).strict().superRefine(refineQuestion);
|
|
24735
|
+
QuestionWireSchema = external_exports.object({ questionId: external_exports.string().uuid(), ...questionFields }).strict().superRefine(refineQuestion);
|
|
24736
|
+
AnswerInputSchema = external_exports.object({
|
|
24737
|
+
questionId: questionHandle.describe("The Question you answer: its id as the event or the conversation shows it (8 characters or whole)."),
|
|
24738
|
+
answer: external_exports.object({
|
|
24739
|
+
text: external_exports.string().trim().min(1).describe(`Your answer in your own words, at most ${ASK_MAX} characters; the context goes in units.`),
|
|
24740
|
+
selectedOptionIds: external_exports.array(external_exports.string().trim().min(1)).min(1).max(6).optional().describe("The ids of the options you choose, when the Question offered options (in order, for a ranking).")
|
|
24741
|
+
}).strict(),
|
|
24742
|
+
units
|
|
24743
|
+
}).strict().superRefine((a, ctx) => refuseOverCaps(a.answer.text, a.units, "text", ctx));
|
|
24744
|
+
QuestionDependencySchema = external_exports.object({
|
|
24745
|
+
questionId: questionHandle.describe("A Question you asked."),
|
|
24746
|
+
change: external_exports.enum(["add", "remove"]),
|
|
24747
|
+
blocked: NodeRef,
|
|
24748
|
+
action: BlockedAction,
|
|
24749
|
+
reason: reason.optional()
|
|
24750
|
+
}).strict().refine(actionFits, ACTION_FITS);
|
|
24751
|
+
sendFields = {
|
|
24752
|
+
updates: external_exports.array(UpdateInputSchema).min(1).max(20).optional().describe(
|
|
24753
|
+
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress and nobody is notified."
|
|
24754
|
+
),
|
|
24755
|
+
answers: external_exports.array(AnswerInputSchema).min(1).max(20).optional().describe("Answers to Questions addressed to you."),
|
|
24756
|
+
withdrawQuestionIds: external_exports.array(questionHandle).min(1).max(10).optional().describe(
|
|
24757
|
+
"Questions you asked that no longer need an answer: you acted on them yourself, they no longer matter, or you asked wrongly. Each is cancelled, not answered: its card closes and nothing rings for it."
|
|
24670
24758
|
),
|
|
24671
|
-
|
|
24672
|
-
"
|
|
24759
|
+
questionDependencies: external_exports.array(QuestionDependencySchema).min(1).max(20).optional().describe(
|
|
24760
|
+
"Add or remove what a Question you asked holds up, after asking it."
|
|
24761
|
+
)
|
|
24762
|
+
};
|
|
24763
|
+
ContactSchema = external_exports.object({
|
|
24764
|
+
...sendFields,
|
|
24765
|
+
questions: external_exports.array(QuestionInputSchema).min(1).max(20).optional().describe("Questions for the person, one per object."),
|
|
24766
|
+
/** RECEIVING (2I, I2; brain_prompts.md §2.2): the events this agent handled. */
|
|
24767
|
+
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
24768
|
+
"The exact eventIds of the events you have handled: an acknowledgment (ACK). Reading alone acknowledges nothing, so an event comes back until you acknowledge it; after that the next batch can come. Each recipient acknowledges separately, for itself only. A Question you owe is answered (answers), never acknowledged away."
|
|
24769
|
+
),
|
|
24770
|
+
wait: external_exports.boolean().optional().describe(
|
|
24771
|
+
"Only controls when this returns. Sending: false (the default) returns at once; true waits up to about 45 seconds for a response to what you sent. Sending nothing: true (the default) waits up to about 45 seconds for anything addressed to you; false returns what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived; wait again without sending again), or `not_waited`."
|
|
24673
24772
|
)
|
|
24674
24773
|
}).strict();
|
|
24675
|
-
|
|
24676
|
-
|
|
24677
|
-
|
|
24678
|
-
|
|
24679
|
-
|
|
24680
|
-
|
|
24774
|
+
sendsAnything = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
24775
|
+
ContactWireSchema = external_exports.object({
|
|
24776
|
+
operationId: external_exports.string().uuid(),
|
|
24777
|
+
...sendFields,
|
|
24778
|
+
questions: external_exports.array(QuestionWireSchema).min(1).max(20).optional()
|
|
24779
|
+
}).strict().refine(sendsAnything, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
24681
24780
|
CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
24682
|
-
CONTACT_DESCRIPTION =
|
|
24781
|
+
CONTACT_DESCRIPTION = `Send to and receive from the person: updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read \`results\`, where a failed item names why while the rest still apply.
|
|
24782
|
+
|
|
24783
|
+
QUESTIONS: one question per object; several questions are several objects in one contact, so each can be answered on its own. Each is sent exactly as written, with no reading in between: a bundled question arrives as one card. Give options when you have them. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'). pickMode:'one' (the default) makes a pick, for alternatives; 'many' a checklist, for independent options they may want several of; 'rank' an ordering. The person can always answer in their own words, so never add an 'Other' option. workItBlocks names the work a question holds up, only when you are truly blocked: it asks for a call. Answers land on the question's Goal: collect them by receiving (below) or with get_goal.
|
|
24784
|
+
|
|
24785
|
+
CUT A LONG MESSAGE BEFORE YOU SEND IT: a question, an update's message or an answer is the one point, in at most ${ASK_MAX} characters; everything else it needs goes in 'units', up to ${UNITS_MAX} {title, body} in reading order, one idea each, every title at most ${UNIT_TITLE_MAX} characters and every body at most ${UNIT_BODY_MAX}. The person sees the main text and the titles, and opens a unit to read its body. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.
|
|
24786
|
+
|
|
24787
|
+
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified. So when the work is finished, mark the Goal done first (manage_goals), then send one update saying what is done and anything they need to do or check. On a Goal whose report card is still open, an update that reaches them is added to that card, with no new push. If the person is already on a call, anything that reaches them joins that call, with no ring.
|
|
24788
|
+
|
|
24789
|
+
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with get_goal); \`instruction\`, a request or note sent to you. \`hasMore\` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (\`assigned\`; your first write to it starts it) and your work gone quiet (\`stalled\`).`;
|
|
24683
24790
|
CreateGoalSchema = external_exports.object({
|
|
24684
24791
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
24685
24792
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -24699,10 +24806,6 @@ var init_dist = __esm({
|
|
|
24699
24806
|
* repo name. Delegated work inherits this from its parent Goal when omitted. */
|
|
24700
24807
|
repo: external_exports.string().trim().min(1).max(200).optional()
|
|
24701
24808
|
});
|
|
24702
|
-
CreateGoalToolSchema = CreateGoalSchema.extend({
|
|
24703
|
-
idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
24704
|
-
}).strict();
|
|
24705
|
-
CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
|
|
24706
24809
|
UpdateGoalSchema = external_exports.object({
|
|
24707
24810
|
revision: external_exports.number().int().positive(),
|
|
24708
24811
|
changes: external_exports.object({
|
|
@@ -24717,17 +24820,64 @@ var init_dist = __esm({
|
|
|
24717
24820
|
state: external_exports.enum(["active", "done", "cancelled"]).optional(),
|
|
24718
24821
|
progress: external_exports.string().trim().min(1).max(1e4).optional(),
|
|
24719
24822
|
reviewed: external_exports.literal(true).optional(),
|
|
24720
|
-
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
24721
|
-
/** WITHDRAW YOUR OWN QUESTION (#2777, owner 2026-09-30). The question's id as every read shows it
|
|
24722
|
-
* (the conversation's `id`, eight characters, or the whole request Entry id), on THIS Goal, asked
|
|
24723
|
-
* by you and still open. It is cancelled, not answered: its cards close and nothing rings for it. */
|
|
24724
|
-
withdraw: external_exports.array(external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/)).min(1).max(10).optional()
|
|
24823
|
+
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
24725
24824
|
}).strict().refine((v) => Object.keys(v).length > 0),
|
|
24726
24825
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
24727
24826
|
operationId: external_exports.string().uuid().optional()
|
|
24728
24827
|
}).strict();
|
|
24729
|
-
|
|
24730
|
-
|
|
24828
|
+
changedGoal = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
24829
|
+
goalTitle = external_exports.string().trim().min(1).max(80).describe("The Goal's short display name: one to five words, how a person refers to it out loud.");
|
|
24830
|
+
goalOutcome = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
|
|
24831
|
+
CreateChange = external_exports.object({
|
|
24832
|
+
kind: external_exports.literal("create"),
|
|
24833
|
+
title: goalTitle,
|
|
24834
|
+
outcome: goalOutcome,
|
|
24835
|
+
ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as check_activity shows it) or the person's. Omitted: you."),
|
|
24836
|
+
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
24837
|
+
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
24838
|
+
}).strict();
|
|
24839
|
+
EditChange = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal, title: goalTitle.optional(), outcome: goalOutcome.optional() }).strict();
|
|
24840
|
+
StateChange = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal, state: external_exports.enum(["open", "completed", "canceled"]).describe(
|
|
24841
|
+
"completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
|
|
24842
|
+
) }).strict();
|
|
24843
|
+
AssignChange = external_exports.object({ kind: external_exports.literal("assign"), goalId: changedGoal, ownerId: external_exports.string().trim().min(1).describe("The new owner's participant.") }).strict();
|
|
24844
|
+
DeferChange = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
24845
|
+
"Postpone it until this instant: it waits until then, and its owner is woken when it passes (a promise to follow up later). null takes the postponement back."
|
|
24846
|
+
) }).strict();
|
|
24847
|
+
MoveChange = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
24848
|
+
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
24849
|
+
) }).strict();
|
|
24850
|
+
DependencyChange = external_exports.object({
|
|
24851
|
+
kind: external_exports.literal("dependency"),
|
|
24852
|
+
change: external_exports.enum(["add", "remove"]),
|
|
24853
|
+
goalId: changedGoal,
|
|
24854
|
+
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
24855
|
+
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
24856
|
+
reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
|
|
24857
|
+
}).strict();
|
|
24858
|
+
read = { revision: external_exports.number().int().positive().optional() };
|
|
24859
|
+
GoalChangeSchema = external_exports.discriminatedUnion("kind", [
|
|
24860
|
+
CreateChange,
|
|
24861
|
+
EditChange.extend(read),
|
|
24862
|
+
StateChange.extend(read),
|
|
24863
|
+
AssignChange.extend(read),
|
|
24864
|
+
DeferChange.extend(read),
|
|
24865
|
+
MoveChange.extend(read),
|
|
24866
|
+
DependencyChange
|
|
24867
|
+
]);
|
|
24868
|
+
editNames = (changes, ctx) => changes.forEach((c, i) => {
|
|
24869
|
+
if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
|
|
24870
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
|
|
24871
|
+
}
|
|
24872
|
+
});
|
|
24873
|
+
ManageGoalsSchema = external_exports.object({
|
|
24874
|
+
requestId: external_exports.string().uuid().optional(),
|
|
24875
|
+
changes: external_exports.array(GoalChangeSchema).min(1).max(50)
|
|
24876
|
+
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
24877
|
+
ManageGoalsToolSchema = external_exports.object({
|
|
24878
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
24879
|
+
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
24880
|
+
MANAGE_GOALS_DESCRIPTION = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls; edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goal) and reconsider. You may change any Goal of your person; a change puts you on it. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
24731
24881
|
GetGoalSchema = external_exports.object({
|
|
24732
24882
|
goalId: external_exports.string().uuid(),
|
|
24733
24883
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
@@ -24738,19 +24888,29 @@ var init_dist = __esm({
|
|
|
24738
24888
|
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
24739
24889
|
diagnose: external_exports.boolean().optional()
|
|
24740
24890
|
}).strict();
|
|
24741
|
-
GET_GOAL_DESCRIPTION = "Read one Goal
|
|
24742
|
-
|
|
24743
|
-
|
|
24744
|
-
|
|
24745
|
-
|
|
24891
|
+
GET_GOAL_DESCRIPTION = "Read one Goal (a read never puts you on it), including others (the ten most recent other contributors, with names, latest entry headlines and times): its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Every Goal of your person is readable, whichever of their agents owns it; another account's Goals are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
|
|
24892
|
+
SearchToolSchema = external_exports.object({
|
|
24893
|
+
query: external_exports.string().trim().min(1).max(500),
|
|
24894
|
+
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
24895
|
+
goalId: external_exports.string().uuid().optional(),
|
|
24896
|
+
limit: external_exports.number().int().min(1).max(20).optional()
|
|
24897
|
+
}).strict();
|
|
24898
|
+
SEARCH_DESCRIPTION = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and Answers (found by their Question or by the words that gave them). query is words to look for; records sharing more of its words rank first, and exact names work. types narrows it to entry, goal and/or answer (default: all three). goalId searches under one Goal: its Entries, its Questions' Answers, and it and its immediate children. limit is matches per type, 1 to 20 (default 8). Read-only. Each match carries its whole saved words, its ID and its links (an Answer carries its Question, the choice made and the Entries that support it); `omitted` counts what matched but was left out, so narrow the words or add a goalId to see it. Nothing found is not proof that nothing exists; a refused search says why. Sealed (encrypted) content is never searched or returned.";
|
|
24899
|
+
CheckActivitySchema = external_exports.object({}).strict();
|
|
24900
|
+
FEEDBACK_TEXT_MAX = 5e4;
|
|
24901
|
+
SendFeedbackSchema = external_exports.object({
|
|
24902
|
+
text: external_exports.string().trim().min(1).max(FEEDBACK_TEXT_MAX).describe(`The report, in markdown: what happened, what was expected, how to reproduce it, versions, evidence. At most ${FEEDBACK_TEXT_MAX} characters.`),
|
|
24903
|
+
title: external_exports.string().trim().min(1).max(200).optional().describe("One line naming it."),
|
|
24904
|
+
kind: external_exports.enum(["bug", "idea", "other"]).default("other").describe("bug: something Paigy does wrong. idea: something it should do. other: anything else.")
|
|
24905
|
+
}).strict();
|
|
24906
|
+
SEND_FEEDBACK_DESCRIPTION = "Send feedback about Paigy itself (a bug report, an idea) straight to the Paigy team. Send it only when the person asked you to, or agreed when you offered: it goes to Paigy, never to the person, and nobody answers it here. Not for your work or a question for the person: use contact for those. Returns whether it was stored.";
|
|
24746
24907
|
AGENT_TOOLS = [
|
|
24747
|
-
{ name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(CheckRepliesSchema) },
|
|
24748
24908
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
24749
|
-
{ name: "
|
|
24750
|
-
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(CreateGoalToolSchema) },
|
|
24751
|
-
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(ClaimGoalSchema) },
|
|
24909
|
+
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(ManageGoalsToolSchema) },
|
|
24752
24910
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(GetGoalSchema) },
|
|
24753
|
-
{ name: "
|
|
24911
|
+
{ name: "search", description: SEARCH_DESCRIPTION, inputSchema: mcpInputSchema(SearchToolSchema) },
|
|
24912
|
+
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(CheckActivitySchema) },
|
|
24913
|
+
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION, inputSchema: mcpInputSchema(SendFeedbackSchema) }
|
|
24754
24914
|
];
|
|
24755
24915
|
AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
24756
24916
|
id = external_exports.string().uuid();
|
|
@@ -24781,17 +24941,6 @@ var init_dist = __esm({
|
|
|
24781
24941
|
reason: external_exports.string().max(500).optional()
|
|
24782
24942
|
}).strict()
|
|
24783
24943
|
];
|
|
24784
|
-
GoalChangeSchema = external_exports.union([
|
|
24785
|
-
external_exports.object({
|
|
24786
|
-
kind: external_exports.literal("create"),
|
|
24787
|
-
title: external_exports.string().min(1).max(120),
|
|
24788
|
-
outcome: external_exports.string().min(1),
|
|
24789
|
-
ownerId: participant,
|
|
24790
|
-
parentGoalId: id.optional(),
|
|
24791
|
-
sourceEntryIds: external_exports.array(id)
|
|
24792
|
-
}).strict(),
|
|
24793
|
-
...existingGoalChanges
|
|
24794
|
-
]);
|
|
24795
24944
|
BrainGoalChangeSchema = external_exports.union([
|
|
24796
24945
|
// newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
|
|
24797
24946
|
external_exports.object({
|
|
@@ -24900,13 +25049,76 @@ var init_dist = __esm({
|
|
|
24900
25049
|
COMPACT_RESULT_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
24901
25050
|
zodToJsonSchema(CompactResultSchema, { $refStrategy: "none" })
|
|
24902
25051
|
);
|
|
25052
|
+
str2 = external_exports.string();
|
|
25053
|
+
strs2 = external_exports.array(external_exports.string());
|
|
25054
|
+
TalkerReplySchema = external_exports.object({
|
|
25055
|
+
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
25056
|
+
* or an agent's handle; `about` names handles; `blocks` is the item a question to an agent must be
|
|
25057
|
+
* answered before ("" for none). */
|
|
25058
|
+
messages: external_exports.array(external_exports.object({ key: str2, to: str2, text: str2, about: strs2, blocks: str2 }).strict()),
|
|
25059
|
+
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
25060
|
+
then: external_exports.enum(["listen", "hold", "end"]),
|
|
25061
|
+
/** Items the person's words settle: the item's handle, the chosen option IDs, the line handles. */
|
|
25062
|
+
answers: external_exports.array(external_exports.object({ item: str2, options: strs2, lines: strs2 }).strict()),
|
|
25063
|
+
/** The line handles that hold a new instruction from the person. */
|
|
25064
|
+
instruction: strs2,
|
|
25065
|
+
/** The line handles that ask for new work, a change to existing work, or a standing rule: the filer
|
|
25066
|
+
* reads only these (3e). */
|
|
25067
|
+
file: strs2,
|
|
25068
|
+
/** Evidence to fetch for a second round: a search, an item's full text, or an agent by name. */
|
|
25069
|
+
need: external_exports.object({ kind: external_exports.enum(["search", "item", "agent", ""]), text: str2 }).strict(),
|
|
25070
|
+
/** The handle of the item to explain ("" for none). */
|
|
25071
|
+
explain: str2
|
|
25072
|
+
}).strict();
|
|
25073
|
+
TALKER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
25074
|
+
zodToJsonSchema(TalkerReplySchema, { $refStrategy: "none" })
|
|
25075
|
+
);
|
|
25076
|
+
str3 = external_exports.string();
|
|
25077
|
+
strs3 = external_exports.array(external_exports.string());
|
|
25078
|
+
FilerReplySchema = external_exports.object({
|
|
25079
|
+
/** Which Goals each new line goes on: a line's handle and Goal handles (or keys of new Goals). */
|
|
25080
|
+
filed: external_exports.array(external_exports.object({ line: str3, goals: strs3 }).strict()),
|
|
25081
|
+
goals: external_exports.array(external_exports.object({
|
|
25082
|
+
op: external_exports.enum(["create", "edit", "complete", "cancel", "reopen", "assign", "defer", "move", "block", "unblock"]),
|
|
25083
|
+
key: str3,
|
|
25084
|
+
goal: str3,
|
|
25085
|
+
title: str3,
|
|
25086
|
+
outcome: str3,
|
|
25087
|
+
owner: str3,
|
|
25088
|
+
under: str3,
|
|
25089
|
+
until: str3,
|
|
25090
|
+
on: str3,
|
|
25091
|
+
gate: external_exports.enum(["start", "complete", "answer", ""]),
|
|
25092
|
+
why: str3
|
|
25093
|
+
}).strict()),
|
|
25094
|
+
questions: external_exports.array(external_exports.object({
|
|
25095
|
+
op: external_exports.enum(["create", "edit", "assign", "withdraw"]),
|
|
25096
|
+
key: str3,
|
|
25097
|
+
question: str3,
|
|
25098
|
+
text: str3,
|
|
25099
|
+
to: str3,
|
|
25100
|
+
goal: str3,
|
|
25101
|
+
options: external_exports.array(external_exports.object({ id: str3, label: str3 }).strict()),
|
|
25102
|
+
pick: external_exports.enum(["one", "many", "rank", "words", ""]),
|
|
25103
|
+
blocks: str3
|
|
25104
|
+
}).strict()),
|
|
25105
|
+
lessons: external_exports.array(external_exports.object({ op: external_exports.enum(["remember", "revise", "withdraw"]), lesson: str3, text: str3, scope: str3 }).strict()),
|
|
25106
|
+
/** Line handles whose words comment on Paigy itself. */
|
|
25107
|
+
feedback: strs3
|
|
25108
|
+
}).strict();
|
|
25109
|
+
FILER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
25110
|
+
zodToJsonSchema(FilerReplySchema, { $refStrategy: "none" })
|
|
25111
|
+
);
|
|
24903
25112
|
LIVE_MS = 3 * 6e4;
|
|
24904
25113
|
WORKING_MS = 60 * 6e4;
|
|
24905
25114
|
ContextSchema = external_exports.object({
|
|
24906
25115
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
24907
25116
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
24908
25117
|
"Semantic chunks of detail (each a standalone, non-empty piece). The user can select chunks to ask you to expand. MAY BE EMPTY: a claim whose whole content is its heading \u2014 a single sentence \u2014 has no body, and saying so beats repeating the heading underneath itself. That repeat is what `min(1)` used to force, at 2x the storage, with every reader subtracting it back out at render time."
|
|
24909
|
-
)
|
|
25118
|
+
),
|
|
25119
|
+
/** THE ASK'S UNITS (3c): its context as titled units, in order. The app lists the titles and opens
|
|
25120
|
+
* a body on a tap. Absent on an ask sent without units, which renders as before. */
|
|
25121
|
+
units: external_exports.array(external_exports.object({ title: external_exports.string(), body: external_exports.string() })).optional()
|
|
24910
25122
|
});
|
|
24911
25123
|
ParticipantSchema = external_exports.object({
|
|
24912
25124
|
kind: external_exports.enum(["human", "agent"]),
|
|
@@ -24981,7 +25193,7 @@ var init_dist = __esm({
|
|
|
24981
25193
|
* ABSENT on the E2EE path, where the sealed `envelope` below carries it. The
|
|
24982
25194
|
* superRefine at the bottom enforces exactly one of the two. */
|
|
24983
25195
|
context: ContextSchema.optional(),
|
|
24984
|
-
options: external_exports.array(
|
|
25196
|
+
options: external_exports.array(OptionSchema.omit({ id: true }).extend({ label: external_exports.string().trim().min(1).max(1e3) }).strict()).min(OPTIONS_MIN).max(OPTIONS_MAX).optional().describe(
|
|
24985
25197
|
"The choices, in order \u2014 required when select is 'one'/'many'/'rank', omitted otherwise. Ids are assigned automatically by position ('1', '2', \u2026); the user's answer references them as optionId(s)."
|
|
24986
25198
|
),
|
|
24987
25199
|
points: external_exports.array(external_exports.string().min(1)).optional().describe(
|
|
@@ -25175,7 +25387,7 @@ var init_dist = __esm({
|
|
|
25175
25387
|
/** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
|
|
25176
25388
|
* post-feedback revision, #633) — the user will never answer this id. Stop
|
|
25177
25389
|
* awaiting it; the live ask is the thread's newest turn (await that one, or
|
|
25178
|
-
* re-orient via
|
|
25390
|
+
* re-orient via contact({})). */
|
|
25179
25391
|
external_exports.object({
|
|
25180
25392
|
type: external_exports.literal("superseded"),
|
|
25181
25393
|
parentId: external_exports.string(),
|
|
@@ -25742,8 +25954,8 @@ var init_dist = __esm({
|
|
|
25742
25954
|
repo: external_exports.string().nullable().optional(),
|
|
25743
25955
|
createdAt: external_exports.string(),
|
|
25744
25956
|
updatedAt: external_exports.string().nullable().default(null),
|
|
25745
|
-
/** When its owner last SAID something about it (`
|
|
25746
|
-
*
|
|
25957
|
+
/** When its owner last SAID something about it (the newest `progress` Entry: a contact update kept
|
|
25958
|
+
* as progress). `updatedAt` moves for reasons nobody chose — a
|
|
25747
25959
|
* state recomputed, a review flag — so it cannot tell work in hand from work gone quiet. */
|
|
25748
25960
|
lastProgressAt: external_exports.string().nullable().optional(),
|
|
25749
25961
|
/** THE GOAL'S NEWEST WORD, FROM EITHER SIDE (owner, 2026-09-27): the newest Entry on it, of any
|
|
@@ -25901,11 +26113,11 @@ var init_dist = __esm({
|
|
|
25901
26113
|
/** The agent's token id: the row's `recipient`. */
|
|
25902
26114
|
agent: external_exports.string().uuid(),
|
|
25903
26115
|
decision: external_exports.enum(["stood_back", "took_over"]),
|
|
25904
|
-
/** The work it was about: the Goal
|
|
26116
|
+
/** The work it was about: the Goal waiting on that agent next (`claimable` on its `contact({})` read). */
|
|
25905
26117
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
25906
26118
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
25907
26119
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
25908
|
-
/** When that work last moved (`claimable.since` on `
|
|
26120
|
+
/** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
|
|
25909
26121
|
since: external_exports.string().datetime().nullable().optional(),
|
|
25910
26122
|
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
25911
26123
|
said: external_exports.string().max(300).optional()
|
|
@@ -26140,8 +26352,9 @@ var init_dist = __esm({
|
|
|
26140
26352
|
tokenOverride = null;
|
|
26141
26353
|
authToken = (explicit) => explicit ?? tokenOverride ?? readToken();
|
|
26142
26354
|
AWAIT_WINDOW_MS = 45e3;
|
|
26143
|
-
NOT_SENT =
|
|
26144
|
-
|
|
26355
|
+
NOT_SENT = `Recorded as the Goal's progress, not sent: nobody was notified. The person is told only a question, an answer to one they asked you, and what you say once the Goal is done. To close the work, mark the Goal done first, then send the one update saying what is done and anything they need to do or check. If the person asked you, in so many words, to send them this, send it again with userExplicitlyRequested: "any" on that update.`;
|
|
26356
|
+
APPLIED = "Applied; nothing was sent to the person.";
|
|
26357
|
+
DEMOTED = "Delivered as a card, not a call: the person's settings do not allow a call right now (silent, quiet hours, or a mode). It has reached them; do not send it again.";
|
|
26145
26358
|
HEARTBEAT_MS = 25e3;
|
|
26146
26359
|
RETRY_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
26147
26360
|
JOIN = { config: { broadcast: { self: false } } };
|
|
@@ -27044,14 +27257,14 @@ var require_regex = __commonJS({
|
|
|
27044
27257
|
var TEST_KANJI = new RegExp("^" + kanji + "$");
|
|
27045
27258
|
var TEST_NUMERIC = new RegExp("^" + numeric + "$");
|
|
27046
27259
|
var TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$");
|
|
27047
|
-
exports.testKanji = function testKanji(
|
|
27048
|
-
return TEST_KANJI.test(
|
|
27260
|
+
exports.testKanji = function testKanji(str5) {
|
|
27261
|
+
return TEST_KANJI.test(str5);
|
|
27049
27262
|
};
|
|
27050
|
-
exports.testNumeric = function testNumeric(
|
|
27051
|
-
return TEST_NUMERIC.test(
|
|
27263
|
+
exports.testNumeric = function testNumeric(str5) {
|
|
27264
|
+
return TEST_NUMERIC.test(str5);
|
|
27052
27265
|
};
|
|
27053
|
-
exports.testAlphanumeric = function testAlphanumeric(
|
|
27054
|
-
return TEST_ALPHANUMERIC.test(
|
|
27266
|
+
exports.testAlphanumeric = function testAlphanumeric(str5) {
|
|
27267
|
+
return TEST_ALPHANUMERIC.test(str5);
|
|
27055
27268
|
};
|
|
27056
27269
|
}
|
|
27057
27270
|
});
|
|
@@ -27553,13 +27766,13 @@ var require_segments = __commonJS({
|
|
|
27553
27766
|
var Regex = require_regex();
|
|
27554
27767
|
var Utils = require_utils2();
|
|
27555
27768
|
var dijkstra = require_dijkstra();
|
|
27556
|
-
function getStringByteLength(
|
|
27557
|
-
return unescape(encodeURIComponent(
|
|
27769
|
+
function getStringByteLength(str5) {
|
|
27770
|
+
return unescape(encodeURIComponent(str5)).length;
|
|
27558
27771
|
}
|
|
27559
|
-
function getSegments(regex, mode,
|
|
27772
|
+
function getSegments(regex, mode, str5) {
|
|
27560
27773
|
const segments = [];
|
|
27561
27774
|
let result;
|
|
27562
|
-
while ((result = regex.exec(
|
|
27775
|
+
while ((result = regex.exec(str5)) !== null) {
|
|
27563
27776
|
segments.push({
|
|
27564
27777
|
data: result[0],
|
|
27565
27778
|
index: result.index,
|
|
@@ -28073,27 +28286,27 @@ var require_chunkstream = __commonJS({
|
|
|
28073
28286
|
this._buffers = null;
|
|
28074
28287
|
this.emit("close");
|
|
28075
28288
|
};
|
|
28076
|
-
ChunkStream.prototype._processReadAllowingLess = function(
|
|
28289
|
+
ChunkStream.prototype._processReadAllowingLess = function(read3) {
|
|
28077
28290
|
this._reads.shift();
|
|
28078
28291
|
let smallerBuf = this._buffers[0];
|
|
28079
|
-
if (smallerBuf.length >
|
|
28080
|
-
this._buffered -=
|
|
28081
|
-
this._buffers[0] = smallerBuf.slice(
|
|
28082
|
-
|
|
28292
|
+
if (smallerBuf.length > read3.length) {
|
|
28293
|
+
this._buffered -= read3.length;
|
|
28294
|
+
this._buffers[0] = smallerBuf.slice(read3.length);
|
|
28295
|
+
read3.func.call(this, smallerBuf.slice(0, read3.length));
|
|
28083
28296
|
} else {
|
|
28084
28297
|
this._buffered -= smallerBuf.length;
|
|
28085
28298
|
this._buffers.shift();
|
|
28086
|
-
|
|
28299
|
+
read3.func.call(this, smallerBuf);
|
|
28087
28300
|
}
|
|
28088
28301
|
};
|
|
28089
|
-
ChunkStream.prototype._processRead = function(
|
|
28302
|
+
ChunkStream.prototype._processRead = function(read3) {
|
|
28090
28303
|
this._reads.shift();
|
|
28091
28304
|
let pos = 0;
|
|
28092
28305
|
let count = 0;
|
|
28093
|
-
let data = Buffer.alloc(
|
|
28094
|
-
while (pos <
|
|
28306
|
+
let data = Buffer.alloc(read3.length);
|
|
28307
|
+
while (pos < read3.length) {
|
|
28095
28308
|
let buf = this._buffers[count++];
|
|
28096
|
-
let len = Math.min(buf.length,
|
|
28309
|
+
let len = Math.min(buf.length, read3.length - pos);
|
|
28097
28310
|
buf.copy(data, pos, 0, len);
|
|
28098
28311
|
pos += len;
|
|
28099
28312
|
if (len !== buf.length) {
|
|
@@ -28103,17 +28316,17 @@ var require_chunkstream = __commonJS({
|
|
|
28103
28316
|
if (count > 0) {
|
|
28104
28317
|
this._buffers.splice(0, count);
|
|
28105
28318
|
}
|
|
28106
|
-
this._buffered -=
|
|
28107
|
-
|
|
28319
|
+
this._buffered -= read3.length;
|
|
28320
|
+
read3.func.call(this, data);
|
|
28108
28321
|
};
|
|
28109
28322
|
ChunkStream.prototype._process = function() {
|
|
28110
28323
|
try {
|
|
28111
28324
|
while (this._buffered > 0 && this._reads && this._reads.length > 0) {
|
|
28112
|
-
let
|
|
28113
|
-
if (
|
|
28114
|
-
this._processReadAllowingLess(
|
|
28115
|
-
} else if (this._buffered >=
|
|
28116
|
-
this._processRead(
|
|
28325
|
+
let read3 = this._reads[0];
|
|
28326
|
+
if (read3.allowLess) {
|
|
28327
|
+
this._processReadAllowingLess(read3);
|
|
28328
|
+
} else if (this._buffered >= read3.length) {
|
|
28329
|
+
this._processRead(read3);
|
|
28117
28330
|
} else {
|
|
28118
28331
|
break;
|
|
28119
28332
|
}
|
|
@@ -29738,12 +29951,12 @@ var require_sync_reader = __commonJS({
|
|
|
29738
29951
|
};
|
|
29739
29952
|
SyncReader.prototype.process = function() {
|
|
29740
29953
|
while (this._reads.length > 0 && this._buffer.length) {
|
|
29741
|
-
let
|
|
29742
|
-
if (this._buffer.length && (this._buffer.length >=
|
|
29954
|
+
let read3 = this._reads[0];
|
|
29955
|
+
if (this._buffer.length && (this._buffer.length >= read3.length || read3.allowLess)) {
|
|
29743
29956
|
this._reads.shift();
|
|
29744
29957
|
let buf = this._buffer;
|
|
29745
|
-
this._buffer = buf.slice(
|
|
29746
|
-
|
|
29958
|
+
this._buffer = buf.slice(read3.length);
|
|
29959
|
+
read3.func.call(this, buf.slice(0, read3.length));
|
|
29747
29960
|
} else {
|
|
29748
29961
|
break;
|
|
29749
29962
|
}
|
|
@@ -30393,13 +30606,13 @@ var require_svg_tag = __commonJS({
|
|
|
30393
30606
|
var Utils = require_utils3();
|
|
30394
30607
|
function getColorAttrib(color, attrib) {
|
|
30395
30608
|
const alpha = color.a / 255;
|
|
30396
|
-
const
|
|
30397
|
-
return alpha < 1 ?
|
|
30609
|
+
const str5 = attrib + '="' + color.hex + '"';
|
|
30610
|
+
return alpha < 1 ? str5 + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str5;
|
|
30398
30611
|
}
|
|
30399
30612
|
function svgCmd(cmd, x, y) {
|
|
30400
|
-
let
|
|
30401
|
-
if (typeof y !== "undefined")
|
|
30402
|
-
return
|
|
30613
|
+
let str5 = cmd + x;
|
|
30614
|
+
if (typeof y !== "undefined") str5 += " " + y;
|
|
30615
|
+
return str5;
|
|
30403
30616
|
}
|
|
30404
30617
|
function qrToPath(data, size, margin) {
|
|
30405
30618
|
let path = "";
|
|
@@ -30931,9 +31144,9 @@ async function available(deps = {}) {
|
|
|
30931
31144
|
});
|
|
30932
31145
|
return [ollama, ...harnesses];
|
|
30933
31146
|
}
|
|
30934
|
-
function refusal(options,
|
|
31147
|
+
function refusal(options, asked) {
|
|
30935
31148
|
const lines2 = [
|
|
30936
|
-
|
|
31149
|
+
asked ? `Can't judge with --via ${asked}: ${options.find((o) => o.provider === asked)?.hint ?? "it isn't available on this machine"}` : "No local judge available \u2014 triage refuses rather than sending your queue to a cloud model.",
|
|
30937
31150
|
"",
|
|
30938
31151
|
"Triage runs the model where your queue already lives (#1106). Your options:"
|
|
30939
31152
|
];
|
|
@@ -30944,10 +31157,10 @@ function refusal(options, asked2) {
|
|
|
30944
31157
|
lines2.push("", "Then re-run: paigy-harness triage [--via ollama|claude|codex|agy]");
|
|
30945
31158
|
return lines2.join("\n");
|
|
30946
31159
|
}
|
|
30947
|
-
async function judgeFor(
|
|
31160
|
+
async function judgeFor(asked, deps = {}) {
|
|
30948
31161
|
const options = await available(deps);
|
|
30949
|
-
const chosen =
|
|
30950
|
-
if (!chosen?.ready) return { error: refusal(options,
|
|
31162
|
+
const chosen = asked ? options.find((o) => o.provider === asked) : options.find((o) => o.ready);
|
|
31163
|
+
if (!chosen?.ready) return { error: refusal(options, asked) };
|
|
30951
31164
|
if (chosen.provider === "ollama") {
|
|
30952
31165
|
const model = chosen.model;
|
|
30953
31166
|
return {
|
|
@@ -30968,9 +31181,9 @@ async function judgeFor(asked2, deps = {}) {
|
|
|
30968
31181
|
};
|
|
30969
31182
|
}
|
|
30970
31183
|
const runner = RUNNERS[chosen.provider];
|
|
30971
|
-
if (!runner) return { error: refusal(options,
|
|
31184
|
+
if (!runner) return { error: refusal(options, asked) };
|
|
30972
31185
|
const bin = which(runner.cli);
|
|
30973
|
-
if (!bin) return { error: refusal(options,
|
|
31186
|
+
if (!bin) return { error: refusal(options, asked) };
|
|
30974
31187
|
return {
|
|
30975
31188
|
provider: chosen.provider,
|
|
30976
31189
|
model: null,
|
|
@@ -31404,7 +31617,7 @@ function onEnter(input, onLine) {
|
|
|
31404
31617
|
// src/cli.ts
|
|
31405
31618
|
init_dist();
|
|
31406
31619
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
31407
|
-
import { randomUUID as
|
|
31620
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
31408
31621
|
import { hostname } from "os";
|
|
31409
31622
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
31410
31623
|
import { execFile as execFile2, execSync } from "child_process";
|
|
@@ -31413,7 +31626,7 @@ import { join as join11 } from "path";
|
|
|
31413
31626
|
|
|
31414
31627
|
// src/run.ts
|
|
31415
31628
|
init_dist();
|
|
31416
|
-
import { randomUUID as
|
|
31629
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
31417
31630
|
|
|
31418
31631
|
// src/harness/session.ts
|
|
31419
31632
|
init_dist();
|
|
@@ -31701,7 +31914,7 @@ init_catalog();
|
|
|
31701
31914
|
import { mkdirSync as mkdirSync2, readdirSync, renameSync, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
31702
31915
|
import { join as join4 } from "path";
|
|
31703
31916
|
import { homedir as homedir3 } from "os";
|
|
31704
|
-
import { randomUUID as
|
|
31917
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
31705
31918
|
var MIDTURN_HOOK = `d="$PAIGY_INBOX"; [ -n "$d" ] || { cat >/dev/null; exit 0; }; set -- "$d"/*.note; [ -e "$1" ] || { cat >/dev/null; exit 0; }; grep '"agent_id"' >/dev/null && exit 0; mkdir -p "$d/taken"; o=""; for f in "$@"; do n=\${f##*/}; mv "$f" "$d/taken/$n" 2>/dev/null || continue; touch "$d/taken/$n"; o="$o\${o:+\\n\\n}$(cat "$d/taken/$n")"; done; [ -n "$o" ] || exit 0; printf '{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"%s"}}' "$o"`;
|
|
31706
31919
|
var missing = (error) => error.code === "ENOENT";
|
|
31707
31920
|
function openInbox(dir) {
|
|
@@ -31761,7 +31974,7 @@ function inboxFor(root = INBOX_ROOT) {
|
|
|
31761
31974
|
} catch (error) {
|
|
31762
31975
|
if (!missing(error)) throw error;
|
|
31763
31976
|
}
|
|
31764
|
-
return openInbox(join4(root, `${process.pid}-${
|
|
31977
|
+
return openInbox(join4(root, `${process.pid}-${randomUUID3().slice(0, 8)}`));
|
|
31765
31978
|
}
|
|
31766
31979
|
|
|
31767
31980
|
// src/harness/session.ts
|
|
@@ -33194,6 +33407,8 @@ var zodToJsonSchema2 = (schema, options) => {
|
|
|
33194
33407
|
// ../../packages/schema/dist/index.js
|
|
33195
33408
|
init_zod();
|
|
33196
33409
|
init_zod();
|
|
33410
|
+
init_zod();
|
|
33411
|
+
init_zod();
|
|
33197
33412
|
var OPTIONS_MIN2 = 2;
|
|
33198
33413
|
var OPTIONS_MAX2 = 6;
|
|
33199
33414
|
var OptionSchema2 = external_exports.object({
|
|
@@ -33203,14 +33418,20 @@ var OptionSchema2 = external_exports.object({
|
|
|
33203
33418
|
// .describe() flows into the MCP contact JSON schema (zodToJsonSchema), so
|
|
33204
33419
|
// the constraints below are what an agent reads when deciding to use these.
|
|
33205
33420
|
html: external_exports.string().max(16384).describe(
|
|
33206
|
-
"Optional sandboxed HTML/CSS preview for a visual 'pick one' (shown in the option card). Untrusted-sandboxed: NO JavaScript, NO external network or images \u2014 inline CSS and data: URIs only; <=16KB. Rendered edge-to-edge in a responsive card that is 200pt tall (about 320pt wide on a phone, with the next option peeking beside it); make your HTML fit that viewport. Use for layout/CSS mockups, tables, diffs. For a hosted image use
|
|
33421
|
+
"Optional sandboxed HTML/CSS preview for a visual 'pick one' (shown in the option card). Untrusted-sandboxed: NO JavaScript, NO external network or images \u2014 inline CSS and data: URIs only; <=16KB. Rendered edge-to-edge in a responsive card that is 200pt tall (about 320pt wide on a phone, with the next option peeking beside it); make your HTML fit that viewport. Use for layout/CSS mockups, tables, diffs. For a hosted image use the image URL instead."
|
|
33207
33422
|
).optional(),
|
|
33208
33423
|
image: external_exports.string().url().describe(
|
|
33209
|
-
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use
|
|
33424
|
+
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use the HTML preview instead."
|
|
33210
33425
|
).optional()
|
|
33211
33426
|
});
|
|
33212
|
-
var OptionInputSchema2 =
|
|
33213
|
-
|
|
33427
|
+
var OptionInputSchema2 = external_exports.object({
|
|
33428
|
+
id: external_exports.string().trim().min(1).max(64).regex(/^[A-Za-z0-9_.:-]+$/).optional().describe(
|
|
33429
|
+
`Optional: this option's own id, which answers name it by (selectedOptionIds). Give every option one, or none: without them the options are numbered "1", "2", \u2026 in order.`
|
|
33430
|
+
),
|
|
33431
|
+
label: external_exports.string().trim().min(1).max(1e3),
|
|
33432
|
+
hint: OptionSchema2.shape.hint,
|
|
33433
|
+
htmlPreview: OptionSchema2.shape.html,
|
|
33434
|
+
imgUrl: OptionSchema2.shape.image
|
|
33214
33435
|
}).strict();
|
|
33215
33436
|
var NIGHT2 = { from: 23, to: 7 };
|
|
33216
33437
|
function draft20202(node) {
|
|
@@ -33242,33 +33463,162 @@ function mcpInputSchema2(s) {
|
|
|
33242
33463
|
delete schema.$schema;
|
|
33243
33464
|
return draft20202(schema);
|
|
33244
33465
|
}
|
|
33245
|
-
var
|
|
33246
|
-
|
|
33247
|
-
|
|
33248
|
-
|
|
33249
|
-
|
|
33250
|
-
|
|
33466
|
+
var ASK_MAX2 = 250;
|
|
33467
|
+
var UNITS_MAX2 = 12;
|
|
33468
|
+
var UNIT_TITLE_MAX2 = 50;
|
|
33469
|
+
var UNIT_BODY_MAX2 = 200;
|
|
33470
|
+
var UnitInputSchema2 = external_exports.object({
|
|
33471
|
+
title: external_exports.string().trim().min(1).describe(`What this unit is about, at most ${UNIT_TITLE_MAX2} characters. The app lists the titles; the person taps one to read its body.`),
|
|
33472
|
+
body: external_exports.string().trim().min(1).describe(`The unit itself, at most ${UNIT_BODY_MAX2} characters.`)
|
|
33473
|
+
}).strict();
|
|
33474
|
+
function capRefusals2(text, units22, field) {
|
|
33475
|
+
const out = [];
|
|
33476
|
+
const name = field === "text" ? "answer" : field;
|
|
33477
|
+
if (text.length > ASK_MAX2) out.push({
|
|
33478
|
+
refusal: "ask_too_long",
|
|
33479
|
+
length: text.length,
|
|
33480
|
+
cap: ASK_MAX2,
|
|
33481
|
+
path: field === "text" ? ["answer", "text"] : [field],
|
|
33482
|
+
message: `ask_too_long: the ${name} is ${text.length} characters; the cap is ${ASK_MAX2}. Keep the one point in the ${name} and move the context into units.`
|
|
33483
|
+
});
|
|
33484
|
+
const all = units22 ?? [];
|
|
33485
|
+
if (all.length > UNITS_MAX2) out.push({
|
|
33486
|
+
refusal: "too_many_units",
|
|
33487
|
+
length: all.length,
|
|
33488
|
+
cap: UNITS_MAX2,
|
|
33489
|
+
path: ["units"],
|
|
33490
|
+
message: `too_many_units: ${all.length} units; the cap is ${UNITS_MAX2}. Keep only the context this ${name} needs.`
|
|
33491
|
+
});
|
|
33492
|
+
all.forEach((unit, index) => {
|
|
33493
|
+
if (unit.title.length > UNIT_TITLE_MAX2) out.push({
|
|
33494
|
+
refusal: "unit_title_too_long",
|
|
33495
|
+
index,
|
|
33496
|
+
length: unit.title.length,
|
|
33497
|
+
cap: UNIT_TITLE_MAX2,
|
|
33498
|
+
path: ["units", index, "title"],
|
|
33499
|
+
message: `unit_title_too_long: units[${index}]'s title is ${unit.title.length} characters; the cap is ${UNIT_TITLE_MAX2}.`
|
|
33500
|
+
});
|
|
33501
|
+
if (unit.body.length > UNIT_BODY_MAX2) out.push({
|
|
33502
|
+
refusal: "unit_body_too_long",
|
|
33503
|
+
index,
|
|
33504
|
+
length: unit.body.length,
|
|
33505
|
+
cap: UNIT_BODY_MAX2,
|
|
33506
|
+
path: ["units", index, "body"],
|
|
33507
|
+
message: `unit_body_too_long: units[${index}]'s body is ${unit.body.length} characters; the cap is ${UNIT_BODY_MAX2}. Cut it into two units.`
|
|
33508
|
+
});
|
|
33509
|
+
});
|
|
33510
|
+
return out;
|
|
33511
|
+
}
|
|
33512
|
+
function refuseOverCaps2(text, units22, field, ctx) {
|
|
33513
|
+
for (const { path, message, ...params } of capRefusals2(text, units22, field)) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message, params });
|
|
33514
|
+
}
|
|
33515
|
+
var questionHandle2 = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
33516
|
+
var NodeRef2 = external_exports.object({
|
|
33517
|
+
type: external_exports.enum(["goal", "question"]),
|
|
33518
|
+
id: external_exports.string().uuid()
|
|
33519
|
+
}).strict().describe("A Goal or a Question, by its id.");
|
|
33520
|
+
var BlockedAction2 = external_exports.enum(["start", "complete", "answer"]).describe("What waits: starting or completing a Goal, or answering a Question.");
|
|
33521
|
+
var reason2 = external_exports.string().trim().min(1).max(500).describe("Why, as an explanation, never as policy.");
|
|
33522
|
+
var actionFits2 = (b) => b.blocked.type === "goal" === (b.action !== "answer");
|
|
33523
|
+
var ACTION_FITS2 = "a goal is blocked from start or complete; a question from answer";
|
|
33524
|
+
var userExplicitlyRequested2 = external_exports.enum(["any", "call"]).optional().describe(
|
|
33525
|
+
`Only what the person said about THIS message, in so many words: "any" when they asked you to send it to them ("send it to my phone", "message me the result"), "call" when they asked to be called about it. It is then delivered (a call rings for the whole contact, and carries everything waiting on them); omitted, an update is only recorded as the Goal's progress unless the person needs it. Never set it to make a message louder.`
|
|
33526
|
+
);
|
|
33527
|
+
var units2 = external_exports.array(UnitInputSchema2).optional().describe(
|
|
33528
|
+
`The context this message needs, as up to ${UNITS_MAX2} units in reading order, each {title, body}: a title of at most ${UNIT_TITLE_MAX2} characters and a body of at most ${UNIT_BODY_MAX2}. One idea per unit. Leave it out when the main text says it all.`
|
|
33529
|
+
);
|
|
33530
|
+
var UpdateInputSchema2 = external_exports.object({
|
|
33531
|
+
message: external_exports.string().trim().min(1).describe(`The one point, at most ${ASK_MAX2} characters; the context goes in units.`),
|
|
33532
|
+
goalIds: external_exports.array(external_exports.string().uuid()).min(1).max(10).describe("The Goals it is about, each one that exists: the one it is mainly about first."),
|
|
33533
|
+
units: units2,
|
|
33534
|
+
userExplicitlyRequested: userExplicitlyRequested2
|
|
33535
|
+
}).strict().superRefine((u, ctx) => refuseOverCaps2(u.message, u.units, "message", ctx));
|
|
33536
|
+
var questionFields2 = {
|
|
33537
|
+
question: external_exports.string().trim().min(1).describe(
|
|
33538
|
+
`ONE question, in at most ${ASK_MAX2} characters, and only what is needed to answer it; the context goes in units. Several questions are several objects, one each: an answer settles the one question it was given, so a person who answers the part of a bundled question that interested them settles nothing and is asked again. Separate questions cost nothing: ANY contact for a person already on a call JOINS that call, so several arrive as one call.`
|
|
33251
33539
|
),
|
|
33252
|
-
|
|
33540
|
+
goalId: external_exports.string().uuid().describe("The Goal the question is about, which must exist (create it with manage_goals first). Its answer comes back there."),
|
|
33541
|
+
units: units2,
|
|
33542
|
+
options: external_exports.array(OptionInputSchema2).min(1).max(6).optional().describe("The choices, when you have them. Each label stands on its own."),
|
|
33253
33543
|
// HOW THE OPTIONS ARE ANSWERED, SAID BY THE AGENT (owner, 2026-10-02: "one and many makes sense";
|
|
33254
|
-
// brain_prompts.md §1: structured agent questions need no model).
|
|
33255
|
-
|
|
33256
|
-
|
|
33257
|
-
select: external_exports.enum(["one", "many"]).optional().describe(
|
|
33258
|
-
'How the options are answered: "many" makes a checklist (they may want several, e.g. independent fixes), "one" (the default) a pick (choosing one rules out the others). Send "many" whenever more than one option could be wanted at once. The person can always answer in their own words as well. Ignored without options.'
|
|
33544
|
+
// brain_prompts.md §1: structured agent questions need no model). The app draws all three.
|
|
33545
|
+
pickMode: external_exports.enum(["one", "many", "rank"]).optional().describe(
|
|
33546
|
+
'How the options are answered: "one" (the default) a pick, for alternatives; "many" a checklist, for independent options they may want several of; "rank" an order of all of them. Only with options.'
|
|
33259
33547
|
),
|
|
33260
|
-
|
|
33261
|
-
|
|
33548
|
+
// WHAT THE QUESTION HOLDS UP (brain_prompts.md §2.1): replaces `waiting: 'hard'`. A question that
|
|
33549
|
+
// blocks work asks for a call (the person's settings and ring cooldowns still decide).
|
|
33550
|
+
workItBlocks: external_exports.array(external_exports.object({ blocked: NodeRef2, action: BlockedAction2, reason: reason2.optional() }).strict().refine(actionFits2, ACTION_FITS2)).min(1).max(10).optional().describe(
|
|
33551
|
+
"The work that cannot go on until this is answered: a Goal's start or completion, or another Question's answer. Only for work truly blocked; it asks for a call. Leave it out for a question you can keep working around."
|
|
33552
|
+
),
|
|
33553
|
+
userExplicitlyRequested: userExplicitlyRequested2
|
|
33554
|
+
};
|
|
33555
|
+
var refineQuestion2 = (q, ctx) => {
|
|
33556
|
+
refuseOverCaps2(q.question, q.units, "question", ctx);
|
|
33557
|
+
if (q.pickMode && !q.options) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["pickMode"], message: "pickMode comes only with options" });
|
|
33558
|
+
const ids = (q.options ?? []).map((o) => o.id);
|
|
33559
|
+
if (ids.some((id22) => id22) && (ids.some((id22) => !id22) || new Set(ids).size !== ids.length)) {
|
|
33560
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["options"], message: "give every option a distinct id, or none" });
|
|
33561
|
+
}
|
|
33562
|
+
};
|
|
33563
|
+
var QuestionInputSchema2 = external_exports.object({
|
|
33564
|
+
questionId: external_exports.string().uuid().optional().describe("Optional: your own stable id for this question (a UUID), so a resend is the same question. Minted for you when omitted; the result returns it."),
|
|
33565
|
+
...questionFields2
|
|
33566
|
+
}).strict().superRefine(refineQuestion2);
|
|
33567
|
+
var QuestionWireSchema2 = external_exports.object({ questionId: external_exports.string().uuid(), ...questionFields2 }).strict().superRefine(refineQuestion2);
|
|
33568
|
+
var AnswerInputSchema2 = external_exports.object({
|
|
33569
|
+
questionId: questionHandle2.describe("The Question you answer: its id as the event or the conversation shows it (8 characters or whole)."),
|
|
33570
|
+
answer: external_exports.object({
|
|
33571
|
+
text: external_exports.string().trim().min(1).describe(`Your answer in your own words, at most ${ASK_MAX2} characters; the context goes in units.`),
|
|
33572
|
+
selectedOptionIds: external_exports.array(external_exports.string().trim().min(1)).min(1).max(6).optional().describe("The ids of the options you choose, when the Question offered options (in order, for a ranking).")
|
|
33573
|
+
}).strict(),
|
|
33574
|
+
units: units2
|
|
33575
|
+
}).strict().superRefine((a, ctx) => refuseOverCaps2(a.answer.text, a.units, "text", ctx));
|
|
33576
|
+
var QuestionDependencySchema2 = external_exports.object({
|
|
33577
|
+
questionId: questionHandle2.describe("A Question you asked."),
|
|
33578
|
+
change: external_exports.enum(["add", "remove"]),
|
|
33579
|
+
blocked: NodeRef2,
|
|
33580
|
+
action: BlockedAction2,
|
|
33581
|
+
reason: reason2.optional()
|
|
33582
|
+
}).strict().refine(actionFits2, ACTION_FITS2);
|
|
33583
|
+
var sendFields2 = {
|
|
33584
|
+
updates: external_exports.array(UpdateInputSchema2).min(1).max(20).optional().describe(
|
|
33585
|
+
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress and nobody is notified."
|
|
33586
|
+
),
|
|
33587
|
+
answers: external_exports.array(AnswerInputSchema2).min(1).max(20).optional().describe("Answers to Questions addressed to you."),
|
|
33588
|
+
withdrawQuestionIds: external_exports.array(questionHandle2).min(1).max(10).optional().describe(
|
|
33589
|
+
"Questions you asked that no longer need an answer: you acted on them yourself, they no longer matter, or you asked wrongly. Each is cancelled, not answered: its card closes and nothing rings for it."
|
|
33590
|
+
),
|
|
33591
|
+
questionDependencies: external_exports.array(QuestionDependencySchema2).min(1).max(20).optional().describe(
|
|
33592
|
+
"Add or remove what a Question you asked holds up, after asking it."
|
|
33593
|
+
)
|
|
33594
|
+
};
|
|
33595
|
+
var ContactSchema2 = external_exports.object({
|
|
33596
|
+
...sendFields2,
|
|
33597
|
+
questions: external_exports.array(QuestionInputSchema2).min(1).max(20).optional().describe("Questions for the person, one per object."),
|
|
33598
|
+
/** RECEIVING (2I, I2; brain_prompts.md §2.2): the events this agent handled. */
|
|
33599
|
+
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
33600
|
+
"The exact eventIds of the events you have handled: an acknowledgment (ACK). Reading alone acknowledges nothing, so an event comes back until you acknowledge it; after that the next batch can come. Each recipient acknowledges separately, for itself only. A Question you owe is answered (answers), never acknowledged away."
|
|
33601
|
+
),
|
|
33602
|
+
wait: external_exports.boolean().optional().describe(
|
|
33603
|
+
"Only controls when this returns. Sending: false (the default) returns at once; true waits up to about 45 seconds for a response to what you sent. Sending nothing: true (the default) waits up to about 45 seconds for anything addressed to you; false returns what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived; wait again without sending again), or `not_waited`."
|
|
33262
33604
|
)
|
|
33263
33605
|
}).strict();
|
|
33264
|
-
var
|
|
33265
|
-
|
|
33266
|
-
|
|
33267
|
-
|
|
33268
|
-
|
|
33269
|
-
|
|
33606
|
+
var sendsAnything2 = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
33607
|
+
var ContactWireSchema2 = external_exports.object({
|
|
33608
|
+
operationId: external_exports.string().uuid(),
|
|
33609
|
+
...sendFields2,
|
|
33610
|
+
questions: external_exports.array(QuestionWireSchema2).min(1).max(20).optional()
|
|
33611
|
+
}).strict().refine(sendsAnything2, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
33270
33612
|
var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
|
|
33271
|
-
var CONTACT_DESCRIPTION2 =
|
|
33613
|
+
var CONTACT_DESCRIPTION2 = `Send to and receive from the person: updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read \`results\`, where a failed item names why while the rest still apply.
|
|
33614
|
+
|
|
33615
|
+
QUESTIONS: one question per object; several questions are several objects in one contact, so each can be answered on its own. Each is sent exactly as written, with no reading in between: a bundled question arrives as one card. Give options when you have them. Each option's label must stand on its own \u2014 the person may see only the labels \u2014 so never a label that points into your text ('All three', 'Option 2', '1 and 3 only'). pickMode:'one' (the default) makes a pick, for alternatives; 'many' a checklist, for independent options they may want several of; 'rank' an ordering. The person can always answer in their own words, so never add an 'Other' option. workItBlocks names the work a question holds up, only when you are truly blocked: it asks for a call. Answers land on the question's Goal: collect them by receiving (below) or with get_goal.
|
|
33616
|
+
|
|
33617
|
+
CUT A LONG MESSAGE BEFORE YOU SEND IT: a question, an update's message or an answer is the one point, in at most ${ASK_MAX2} characters; everything else it needs goes in 'units', up to ${UNITS_MAX2} {title, body} in reading order, one idea each, every title at most ${UNIT_TITLE_MAX2} characters and every body at most ${UNIT_BODY_MAX2}. The person sees the main text and the titles, and opens a unit to read its body. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.
|
|
33618
|
+
|
|
33619
|
+
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified. So when the work is finished, mark the Goal done first (manage_goals), then send one update saying what is done and anything they need to do or check. On a Goal whose report card is still open, an update that reaches them is added to that card, with no new push. If the person is already on a call, anything that reaches them joins that call, with no ring.
|
|
33620
|
+
|
|
33621
|
+
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with get_goal); \`instruction\`, a request or note sent to you. \`hasMore\` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (\`assigned\`; your first write to it starts it) and your work gone quiet (\`stalled\`).`;
|
|
33272
33622
|
var CreateGoalSchema2 = external_exports.object({
|
|
33273
33623
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
33274
33624
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -33288,10 +33638,6 @@ var CreateGoalSchema2 = external_exports.object({
|
|
|
33288
33638
|
* repo name. Delegated work inherits this from its parent Goal when omitted. */
|
|
33289
33639
|
repo: external_exports.string().trim().min(1).max(200).optional()
|
|
33290
33640
|
});
|
|
33291
|
-
var CreateGoalToolSchema2 = CreateGoalSchema2.extend({
|
|
33292
|
-
idempotencyKey: CreateGoalSchema2.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
33293
|
-
}).strict();
|
|
33294
|
-
var CREATE_GOAL_DESCRIPTION2 = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
|
|
33295
33641
|
var UpdateGoalSchema2 = external_exports.object({
|
|
33296
33642
|
revision: external_exports.number().int().positive(),
|
|
33297
33643
|
changes: external_exports.object({
|
|
@@ -33306,17 +33652,64 @@ var UpdateGoalSchema2 = external_exports.object({
|
|
|
33306
33652
|
state: external_exports.enum(["active", "done", "cancelled"]).optional(),
|
|
33307
33653
|
progress: external_exports.string().trim().min(1).max(1e4).optional(),
|
|
33308
33654
|
reviewed: external_exports.literal(true).optional(),
|
|
33309
|
-
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
33310
|
-
/** WITHDRAW YOUR OWN QUESTION (#2777, owner 2026-09-30). The question's id as every read shows it
|
|
33311
|
-
* (the conversation's `id`, eight characters, or the whole request Entry id), on THIS Goal, asked
|
|
33312
|
-
* by you and still open. It is cancelled, not answered: its cards close and nothing rings for it. */
|
|
33313
|
-
withdraw: external_exports.array(external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/)).min(1).max(10).optional()
|
|
33655
|
+
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
33314
33656
|
}).strict().refine((v) => Object.keys(v).length > 0),
|
|
33315
33657
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
33316
33658
|
operationId: external_exports.string().uuid().optional()
|
|
33317
33659
|
}).strict();
|
|
33318
|
-
var
|
|
33319
|
-
var
|
|
33660
|
+
var changedGoal2 = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
33661
|
+
var goalTitle2 = external_exports.string().trim().min(1).max(80).describe("The Goal's short display name: one to five words, how a person refers to it out loud.");
|
|
33662
|
+
var goalOutcome2 = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
|
|
33663
|
+
var CreateChange2 = external_exports.object({
|
|
33664
|
+
kind: external_exports.literal("create"),
|
|
33665
|
+
title: goalTitle2,
|
|
33666
|
+
outcome: goalOutcome2,
|
|
33667
|
+
ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as check_activity shows it) or the person's. Omitted: you."),
|
|
33668
|
+
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
33669
|
+
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
33670
|
+
}).strict();
|
|
33671
|
+
var EditChange2 = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal2, title: goalTitle2.optional(), outcome: goalOutcome2.optional() }).strict();
|
|
33672
|
+
var StateChange2 = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal2, state: external_exports.enum(["open", "completed", "canceled"]).describe(
|
|
33673
|
+
"completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
|
|
33674
|
+
) }).strict();
|
|
33675
|
+
var AssignChange2 = external_exports.object({ kind: external_exports.literal("assign"), goalId: changedGoal2, ownerId: external_exports.string().trim().min(1).describe("The new owner's participant.") }).strict();
|
|
33676
|
+
var DeferChange2 = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal2, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
33677
|
+
"Postpone it until this instant: it waits until then, and its owner is woken when it passes (a promise to follow up later). null takes the postponement back."
|
|
33678
|
+
) }).strict();
|
|
33679
|
+
var MoveChange2 = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal2, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
33680
|
+
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
33681
|
+
) }).strict();
|
|
33682
|
+
var DependencyChange2 = external_exports.object({
|
|
33683
|
+
kind: external_exports.literal("dependency"),
|
|
33684
|
+
change: external_exports.enum(["add", "remove"]),
|
|
33685
|
+
goalId: changedGoal2,
|
|
33686
|
+
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
33687
|
+
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
33688
|
+
reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
|
|
33689
|
+
}).strict();
|
|
33690
|
+
var read2 = { revision: external_exports.number().int().positive().optional() };
|
|
33691
|
+
var GoalChangeSchema2 = external_exports.discriminatedUnion("kind", [
|
|
33692
|
+
CreateChange2,
|
|
33693
|
+
EditChange2.extend(read2),
|
|
33694
|
+
StateChange2.extend(read2),
|
|
33695
|
+
AssignChange2.extend(read2),
|
|
33696
|
+
DeferChange2.extend(read2),
|
|
33697
|
+
MoveChange2.extend(read2),
|
|
33698
|
+
DependencyChange2
|
|
33699
|
+
]);
|
|
33700
|
+
var editNames2 = (changes, ctx) => changes.forEach((c, i) => {
|
|
33701
|
+
if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
|
|
33702
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
|
|
33703
|
+
}
|
|
33704
|
+
});
|
|
33705
|
+
var ManageGoalsSchema2 = external_exports.object({
|
|
33706
|
+
requestId: external_exports.string().uuid().optional(),
|
|
33707
|
+
changes: external_exports.array(GoalChangeSchema2).min(1).max(50)
|
|
33708
|
+
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
33709
|
+
var ManageGoalsToolSchema2 = external_exports.object({
|
|
33710
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange2, EditChange2, StateChange2, AssignChange2, DeferChange2, MoveChange2, DependencyChange2])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
33711
|
+
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
33712
|
+
var MANAGE_GOALS_DESCRIPTION2 = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls; edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goal) and reconsider. You may change any Goal of your person; a change puts you on it. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
33320
33713
|
var GetGoalSchema2 = external_exports.object({
|
|
33321
33714
|
goalId: external_exports.string().uuid(),
|
|
33322
33715
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
@@ -33327,19 +33720,29 @@ var GetGoalSchema2 = external_exports.object({
|
|
|
33327
33720
|
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
33328
33721
|
diagnose: external_exports.boolean().optional()
|
|
33329
33722
|
}).strict();
|
|
33330
|
-
var GET_GOAL_DESCRIPTION2 = "Read one Goal
|
|
33331
|
-
var
|
|
33332
|
-
|
|
33333
|
-
|
|
33334
|
-
|
|
33723
|
+
var GET_GOAL_DESCRIPTION2 = "Read one Goal (a read never puts you on it), including others (the ten most recent other contributors, with names, latest entry headlines and times): its outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words \u2014 NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted \u2014 history: true reads every entry in full. Every Goal of your person is readable, whichever of their agents owns it; another account's Goals are not disclosed.\n\ndiagnose: true is for when a read has CONFUSED you \u2014 not for the working loop. It adds `diagnosis`, which asks every reader that already answers a question about your work and NAMES the reader behind every value, so you never guess which of two places to look: what state your work is really in (the stored `goals.state` beside the derived `goal_execution_state`, which can differ); whether anything is armed to ring and when (`ladder_candidates`, with the ladder's own last decision); whether a wake fired for you and what it did (durable `wake.*` events, beside when your process was last heard from); and what has reached you (`list_waiting` \u2014 review flags, unstarted work, open questions, the person's newest words). Read `diagnosis.disagreements` FIRST: each one is two readers giving different values for the same fact, with both values and both sources, and it never chooses between them \u2014 that is yours to do, from the Goal's own history. `diagnosis.looked` names every reader asked, including any that could not answer, so an empty answer is never confused with a broken one.";
|
|
33724
|
+
var SearchToolSchema2 = external_exports.object({
|
|
33725
|
+
query: external_exports.string().trim().min(1).max(500),
|
|
33726
|
+
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
33727
|
+
goalId: external_exports.string().uuid().optional(),
|
|
33728
|
+
limit: external_exports.number().int().min(1).max(20).optional()
|
|
33729
|
+
}).strict();
|
|
33730
|
+
var SEARCH_DESCRIPTION2 = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and Answers (found by their Question or by the words that gave them). query is words to look for; records sharing more of its words rank first, and exact names work. types narrows it to entry, goal and/or answer (default: all three). goalId searches under one Goal: its Entries, its Questions' Answers, and it and its immediate children. limit is matches per type, 1 to 20 (default 8). Read-only. Each match carries its whole saved words, its ID and its links (an Answer carries its Question, the choice made and the Entries that support it); `omitted` counts what matched but was left out, so narrow the words or add a goalId to see it. Nothing found is not proof that nothing exists; a refused search says why. Sealed (encrypted) content is never searched or returned.";
|
|
33731
|
+
var CheckActivitySchema2 = external_exports.object({}).strict();
|
|
33732
|
+
var FEEDBACK_TEXT_MAX2 = 5e4;
|
|
33733
|
+
var SendFeedbackSchema2 = external_exports.object({
|
|
33734
|
+
text: external_exports.string().trim().min(1).max(FEEDBACK_TEXT_MAX2).describe(`The report, in markdown: what happened, what was expected, how to reproduce it, versions, evidence. At most ${FEEDBACK_TEXT_MAX2} characters.`),
|
|
33735
|
+
title: external_exports.string().trim().min(1).max(200).optional().describe("One line naming it."),
|
|
33736
|
+
kind: external_exports.enum(["bug", "idea", "other"]).default("other").describe("bug: something Paigy does wrong. idea: something it should do. other: anything else.")
|
|
33737
|
+
}).strict();
|
|
33738
|
+
var SEND_FEEDBACK_DESCRIPTION2 = "Send feedback about Paigy itself (a bug report, an idea) straight to the Paigy team. Send it only when the person asked you to, or agreed when you offered: it goes to Paigy, never to the person, and nobody answers it here. Not for your work or a question for the person: use contact for those. Returns whether it was stored.";
|
|
33335
33739
|
var AGENT_TOOLS2 = [
|
|
33336
|
-
{ name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema2(CheckRepliesSchema2) },
|
|
33337
33740
|
{ name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
|
|
33338
|
-
{ name: "
|
|
33339
|
-
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(CreateGoalToolSchema2) },
|
|
33340
|
-
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(ClaimGoalSchema2) },
|
|
33741
|
+
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(ManageGoalsToolSchema2) },
|
|
33341
33742
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(GetGoalSchema2) },
|
|
33342
|
-
{ name: "
|
|
33743
|
+
{ name: "search", description: SEARCH_DESCRIPTION2, inputSchema: mcpInputSchema2(SearchToolSchema2) },
|
|
33744
|
+
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema2(CheckActivitySchema2) },
|
|
33745
|
+
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION2, inputSchema: mcpInputSchema2(SendFeedbackSchema2) }
|
|
33343
33746
|
];
|
|
33344
33747
|
var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
|
|
33345
33748
|
var id2 = external_exports.string().uuid();
|
|
@@ -33370,17 +33773,6 @@ var existingGoalChanges2 = [
|
|
|
33370
33773
|
reason: external_exports.string().max(500).optional()
|
|
33371
33774
|
}).strict()
|
|
33372
33775
|
];
|
|
33373
|
-
var GoalChangeSchema2 = external_exports.union([
|
|
33374
|
-
external_exports.object({
|
|
33375
|
-
kind: external_exports.literal("create"),
|
|
33376
|
-
title: external_exports.string().min(1).max(120),
|
|
33377
|
-
outcome: external_exports.string().min(1),
|
|
33378
|
-
ownerId: participant2,
|
|
33379
|
-
parentGoalId: id2.optional(),
|
|
33380
|
-
sourceEntryIds: external_exports.array(id2)
|
|
33381
|
-
}).strict(),
|
|
33382
|
-
...existingGoalChanges2
|
|
33383
|
-
]);
|
|
33384
33776
|
var BrainGoalChangeSchema2 = external_exports.union([
|
|
33385
33777
|
// newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
|
|
33386
33778
|
external_exports.object({
|
|
@@ -33462,33 +33854,93 @@ var BrainResultSchema2 = external_exports.object({
|
|
|
33462
33854
|
next: BrainNextSchema2,
|
|
33463
33855
|
search: BrainSearchSchema2.optional()
|
|
33464
33856
|
}).strict();
|
|
33465
|
-
var
|
|
33466
|
-
var
|
|
33857
|
+
var str4 = external_exports.string();
|
|
33858
|
+
var strs4 = external_exports.array(external_exports.string());
|
|
33467
33859
|
var CompactResultSchema2 = external_exports.object({
|
|
33468
|
-
next: external_exports.object({ say:
|
|
33469
|
-
messages: external_exports.array(external_exports.object({ key:
|
|
33470
|
-
entries: external_exports.array(external_exports.object({ key:
|
|
33471
|
-
answers: external_exports.array(external_exports.object({ question:
|
|
33860
|
+
next: external_exports.object({ say: strs4, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs4, reason: str4, instructions: strs4 }).strict(),
|
|
33861
|
+
messages: external_exports.array(external_exports.object({ key: str4, to: str4, text: str4, about: strs4, entries: strs4, owed: strs4, inviteToCall: external_exports.boolean() }).strict()),
|
|
33862
|
+
entries: external_exports.array(external_exports.object({ key: str4, from: str4, on: strs4 }).strict()),
|
|
33863
|
+
answers: external_exports.array(external_exports.object({ question: str4, entries: strs4, summary: str4, picked: strs4 }).strict()),
|
|
33472
33864
|
changes: external_exports.array(external_exports.object({
|
|
33473
|
-
key:
|
|
33865
|
+
key: str4,
|
|
33474
33866
|
what: external_exports.enum(["goal", "question", "lesson"]),
|
|
33475
33867
|
op: external_exports.enum(["create", "edit", "assign", "open", "complete", "cancel", "defer", "move", "block", "unblock", "withdraw", "remember", "revise"]),
|
|
33476
|
-
id:
|
|
33477
|
-
text:
|
|
33478
|
-
title:
|
|
33479
|
-
who:
|
|
33480
|
-
under:
|
|
33868
|
+
id: str4,
|
|
33869
|
+
text: str4,
|
|
33870
|
+
title: str4,
|
|
33871
|
+
who: str4,
|
|
33872
|
+
under: str4,
|
|
33481
33873
|
gate: external_exports.enum(["start", "complete", "answer", "none"]),
|
|
33482
|
-
options: external_exports.array(external_exports.object({ id:
|
|
33874
|
+
options: external_exports.array(external_exports.object({ id: str4, label: str4 }).strict()),
|
|
33483
33875
|
pick: external_exports.enum(["one", "many", "rank", "words"]),
|
|
33484
|
-
entries:
|
|
33876
|
+
entries: strs4
|
|
33485
33877
|
}).strict()),
|
|
33486
|
-
feedback: external_exports.array(
|
|
33487
|
-
search: external_exports.object({ query:
|
|
33878
|
+
feedback: external_exports.array(strs4),
|
|
33879
|
+
search: external_exports.object({ query: str4, within: strs4, goal: str4 }).strict()
|
|
33488
33880
|
}).strict();
|
|
33489
33881
|
var COMPACT_RESULT_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
33490
33882
|
zodToJsonSchema2(CompactResultSchema2, { $refStrategy: "none" })
|
|
33491
33883
|
);
|
|
33884
|
+
var str22 = external_exports.string();
|
|
33885
|
+
var strs22 = external_exports.array(external_exports.string());
|
|
33886
|
+
var TalkerReplySchema2 = external_exports.object({
|
|
33887
|
+
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
33888
|
+
* or an agent's handle; `about` names handles; `blocks` is the item a question to an agent must be
|
|
33889
|
+
* answered before ("" for none). */
|
|
33890
|
+
messages: external_exports.array(external_exports.object({ key: str22, to: str22, text: str22, about: strs22, blocks: str22 }).strict()),
|
|
33891
|
+
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
33892
|
+
then: external_exports.enum(["listen", "hold", "end"]),
|
|
33893
|
+
/** Items the person's words settle: the item's handle, the chosen option IDs, the line handles. */
|
|
33894
|
+
answers: external_exports.array(external_exports.object({ item: str22, options: strs22, lines: strs22 }).strict()),
|
|
33895
|
+
/** The line handles that hold a new instruction from the person. */
|
|
33896
|
+
instruction: strs22,
|
|
33897
|
+
/** The line handles that ask for new work, a change to existing work, or a standing rule: the filer
|
|
33898
|
+
* reads only these (3e). */
|
|
33899
|
+
file: strs22,
|
|
33900
|
+
/** Evidence to fetch for a second round: a search, an item's full text, or an agent by name. */
|
|
33901
|
+
need: external_exports.object({ kind: external_exports.enum(["search", "item", "agent", ""]), text: str22 }).strict(),
|
|
33902
|
+
/** The handle of the item to explain ("" for none). */
|
|
33903
|
+
explain: str22
|
|
33904
|
+
}).strict();
|
|
33905
|
+
var TALKER_REPLY_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
33906
|
+
zodToJsonSchema2(TalkerReplySchema2, { $refStrategy: "none" })
|
|
33907
|
+
);
|
|
33908
|
+
var str32 = external_exports.string();
|
|
33909
|
+
var strs32 = external_exports.array(external_exports.string());
|
|
33910
|
+
var FilerReplySchema2 = external_exports.object({
|
|
33911
|
+
/** Which Goals each new line goes on: a line's handle and Goal handles (or keys of new Goals). */
|
|
33912
|
+
filed: external_exports.array(external_exports.object({ line: str32, goals: strs32 }).strict()),
|
|
33913
|
+
goals: external_exports.array(external_exports.object({
|
|
33914
|
+
op: external_exports.enum(["create", "edit", "complete", "cancel", "reopen", "assign", "defer", "move", "block", "unblock"]),
|
|
33915
|
+
key: str32,
|
|
33916
|
+
goal: str32,
|
|
33917
|
+
title: str32,
|
|
33918
|
+
outcome: str32,
|
|
33919
|
+
owner: str32,
|
|
33920
|
+
under: str32,
|
|
33921
|
+
until: str32,
|
|
33922
|
+
on: str32,
|
|
33923
|
+
gate: external_exports.enum(["start", "complete", "answer", ""]),
|
|
33924
|
+
why: str32
|
|
33925
|
+
}).strict()),
|
|
33926
|
+
questions: external_exports.array(external_exports.object({
|
|
33927
|
+
op: external_exports.enum(["create", "edit", "assign", "withdraw"]),
|
|
33928
|
+
key: str32,
|
|
33929
|
+
question: str32,
|
|
33930
|
+
text: str32,
|
|
33931
|
+
to: str32,
|
|
33932
|
+
goal: str32,
|
|
33933
|
+
options: external_exports.array(external_exports.object({ id: str32, label: str32 }).strict()),
|
|
33934
|
+
pick: external_exports.enum(["one", "many", "rank", "words", ""]),
|
|
33935
|
+
blocks: str32
|
|
33936
|
+
}).strict()),
|
|
33937
|
+
lessons: external_exports.array(external_exports.object({ op: external_exports.enum(["remember", "revise", "withdraw"]), lesson: str32, text: str32, scope: str32 }).strict()),
|
|
33938
|
+
/** Line handles whose words comment on Paigy itself. */
|
|
33939
|
+
feedback: strs32
|
|
33940
|
+
}).strict();
|
|
33941
|
+
var FILER_REPLY_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
33942
|
+
zodToJsonSchema2(FilerReplySchema2, { $refStrategy: "none" })
|
|
33943
|
+
);
|
|
33492
33944
|
function entryWords(entry) {
|
|
33493
33945
|
const content = entry.content;
|
|
33494
33946
|
if (content && "sealed" in content) return "";
|
|
@@ -33512,7 +33964,10 @@ var ContextSchema2 = external_exports.object({
|
|
|
33512
33964
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
33513
33965
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
33514
33966
|
"Semantic chunks of detail (each a standalone, non-empty piece). The user can select chunks to ask you to expand. MAY BE EMPTY: a claim whose whole content is its heading \u2014 a single sentence \u2014 has no body, and saying so beats repeating the heading underneath itself. That repeat is what `min(1)` used to force, at 2x the storage, with every reader subtracting it back out at render time."
|
|
33515
|
-
)
|
|
33967
|
+
),
|
|
33968
|
+
/** THE ASK'S UNITS (3c): its context as titled units, in order. The app lists the titles and opens
|
|
33969
|
+
* a body on a tap. Absent on an ask sent without units, which renders as before. */
|
|
33970
|
+
units: external_exports.array(external_exports.object({ title: external_exports.string(), body: external_exports.string() })).optional()
|
|
33516
33971
|
});
|
|
33517
33972
|
var ParticipantSchema2 = external_exports.object({
|
|
33518
33973
|
kind: external_exports.enum(["human", "agent"]),
|
|
@@ -33587,7 +34042,7 @@ var NotifyRequestFields2 = external_exports.object({
|
|
|
33587
34042
|
* ABSENT on the E2EE path, where the sealed `envelope` below carries it. The
|
|
33588
34043
|
* superRefine at the bottom enforces exactly one of the two. */
|
|
33589
34044
|
context: ContextSchema2.optional(),
|
|
33590
|
-
options: external_exports.array(
|
|
34045
|
+
options: external_exports.array(OptionSchema2.omit({ id: true }).extend({ label: external_exports.string().trim().min(1).max(1e3) }).strict()).min(OPTIONS_MIN2).max(OPTIONS_MAX2).optional().describe(
|
|
33591
34046
|
"The choices, in order \u2014 required when select is 'one'/'many'/'rank', omitted otherwise. Ids are assigned automatically by position ('1', '2', \u2026); the user's answer references them as optionId(s)."
|
|
33592
34047
|
),
|
|
33593
34048
|
points: external_exports.array(external_exports.string().min(1)).optional().describe(
|
|
@@ -33781,7 +34236,7 @@ var AwaitItemSchema2 = external_exports.discriminatedUnion("type", [
|
|
|
33781
34236
|
/** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
|
|
33782
34237
|
* post-feedback revision, #633) — the user will never answer this id. Stop
|
|
33783
34238
|
* awaiting it; the live ask is the thread's newest turn (await that one, or
|
|
33784
|
-
* re-orient via
|
|
34239
|
+
* re-orient via contact({})). */
|
|
33785
34240
|
external_exports.object({
|
|
33786
34241
|
type: external_exports.literal("superseded"),
|
|
33787
34242
|
parentId: external_exports.string(),
|
|
@@ -34348,8 +34803,8 @@ var QueueItemSchema2 = external_exports.object({
|
|
|
34348
34803
|
repo: external_exports.string().nullable().optional(),
|
|
34349
34804
|
createdAt: external_exports.string(),
|
|
34350
34805
|
updatedAt: external_exports.string().nullable().default(null),
|
|
34351
|
-
/** When its owner last SAID something about it (`
|
|
34352
|
-
*
|
|
34806
|
+
/** When its owner last SAID something about it (the newest `progress` Entry: a contact update kept
|
|
34807
|
+
* as progress). `updatedAt` moves for reasons nobody chose — a
|
|
34353
34808
|
* state recomputed, a review flag — so it cannot tell work in hand from work gone quiet. */
|
|
34354
34809
|
lastProgressAt: external_exports.string().nullable().optional(),
|
|
34355
34810
|
/** THE GOAL'S NEWEST WORD, FROM EITHER SIDE (owner, 2026-09-27): the newest Entry on it, of any
|
|
@@ -34505,11 +34960,11 @@ var HostDecisionSchema2 = external_exports.object({
|
|
|
34505
34960
|
/** The agent's token id: the row's `recipient`. */
|
|
34506
34961
|
agent: external_exports.string().uuid(),
|
|
34507
34962
|
decision: external_exports.enum(["stood_back", "took_over"]),
|
|
34508
|
-
/** The work it was about: the Goal
|
|
34963
|
+
/** The work it was about: the Goal waiting on that agent next (`claimable` on its `contact({})` read). */
|
|
34509
34964
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
34510
34965
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
34511
34966
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
34512
|
-
/** When that work last moved (`claimable.since` on `
|
|
34967
|
+
/** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
|
|
34513
34968
|
since: external_exports.string().datetime().nullable().optional(),
|
|
34514
34969
|
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
34515
34970
|
said: external_exports.string().max(300).optional()
|
|
@@ -34734,6 +35189,32 @@ function sameTail(a, b) {
|
|
|
34734
35189
|
// src/paigy/bridge.ts
|
|
34735
35190
|
init_dist();
|
|
34736
35191
|
|
|
35192
|
+
// src/paigy/cut.ts
|
|
35193
|
+
function cut(text, title = "Details") {
|
|
35194
|
+
const all = text.trim();
|
|
35195
|
+
if (all.length <= ASK_MAX2) return { main: all };
|
|
35196
|
+
const main2 = head(all, ASK_MAX2);
|
|
35197
|
+
const units3 = [];
|
|
35198
|
+
let rest = all.slice(main2.length).trim();
|
|
35199
|
+
while (rest && units3.length < UNITS_MAX2) {
|
|
35200
|
+
const last = units3.length === UNITS_MAX2 - 1;
|
|
35201
|
+
const body = last && rest.length > UNIT_BODY_MAX2 ? `${head(rest, UNIT_BODY_MAX2 - 1).trimEnd()}\u2026` : head(rest, UNIT_BODY_MAX2);
|
|
35202
|
+
units3.push({ title: units3.length ? `${title} (${units3.length + 1})` : title, body: body.trim() });
|
|
35203
|
+
rest = last ? "" : rest.slice(body.length).trim();
|
|
35204
|
+
}
|
|
35205
|
+
return { main: main2.trim(), units: units3 };
|
|
35206
|
+
}
|
|
35207
|
+
function head(text, max) {
|
|
35208
|
+
if (text.length <= max) return text;
|
|
35209
|
+
const window = text.slice(0, max + 1);
|
|
35210
|
+
for (const boundary of [/\n\s*\n/g, /[.!?](\s)/g, /\s/g]) {
|
|
35211
|
+
let at = -1;
|
|
35212
|
+
for (const m of window.matchAll(boundary)) if (m.index > max / 3 && m.index < max) at = m.index + (boundary.source.startsWith("[") ? 1 : 0);
|
|
35213
|
+
if (at > 0) return text.slice(0, at);
|
|
35214
|
+
}
|
|
35215
|
+
return text.slice(0, max);
|
|
35216
|
+
}
|
|
35217
|
+
|
|
34737
35218
|
// src/paigy/limit.ts
|
|
34738
35219
|
var LIMIT_PREFIXES = [
|
|
34739
35220
|
"You've hit your",
|
|
@@ -34862,13 +35343,27 @@ var LIMITS = episodes();
|
|
|
34862
35343
|
// src/paigy/bridge.ts
|
|
34863
35344
|
function railFor(opts) {
|
|
34864
35345
|
return {
|
|
34865
|
-
|
|
35346
|
+
next: async () => {
|
|
35347
|
+
const waiting = await receive(opts);
|
|
35348
|
+
const goalId = waiting.claimable?.goalId ?? waiting.review?.[0]?.goalId;
|
|
35349
|
+
return goalId ? getGoal(goalId, opts) : { state: "idle", message: "" };
|
|
35350
|
+
},
|
|
34866
35351
|
read: (goalId) => getGoal(goalId, opts),
|
|
34867
|
-
|
|
34868
|
-
|
|
35352
|
+
complete: async (goalId, revision) => {
|
|
35353
|
+
const done = await manageGoals({ changes: [{ kind: "state", goalId, state: "completed", ...revision !== void 0 ? { revision } : {} }] }, opts);
|
|
35354
|
+
const result = done.results[0];
|
|
35355
|
+
if (result?.status !== "applied") throw new Error(`manage_goals failed: ${result?.error ?? "no result"}`);
|
|
35356
|
+
},
|
|
35357
|
+
ack: (eventIds) => acknowledge(eventIds, opts),
|
|
35358
|
+
// One read and back: the pump owns the waiting, so no wait is held here.
|
|
34869
35359
|
contact: (input) => contact(input, { ...opts, waits: false }),
|
|
34870
|
-
create: (input) =>
|
|
34871
|
-
|
|
35360
|
+
create: async (input) => {
|
|
35361
|
+
const made = await manageGoals({ changes: [{ kind: "create", ...input }] }, opts);
|
|
35362
|
+
const goal = made.goals.find((g) => g.goalId === made.results[0]?.goalId);
|
|
35363
|
+
if (!goal) throw new Error(`manage_goals create failed: ${made.results[0]?.error ?? "no goal"}`);
|
|
35364
|
+
return { goalId: goal.goalId, revision: goal.revision };
|
|
35365
|
+
},
|
|
35366
|
+
waiting: () => receive(opts)
|
|
34872
35367
|
};
|
|
34873
35368
|
}
|
|
34874
35369
|
function cancelAsks(state) {
|
|
@@ -34889,13 +35384,18 @@ function decisionFrom(result) {
|
|
|
34889
35384
|
}
|
|
34890
35385
|
async function ask(state, rail, input) {
|
|
34891
35386
|
if (!state.goal) return null;
|
|
35387
|
+
const { main: main2, units: units3 } = cut(input.ask);
|
|
34892
35388
|
try {
|
|
34893
35389
|
const sent = await rail.contact({
|
|
34894
|
-
|
|
34895
|
-
|
|
34896
|
-
|
|
35390
|
+
questions: [{
|
|
35391
|
+
question: main2,
|
|
35392
|
+
...units3 ? { units: units3 } : {},
|
|
35393
|
+
goalId: state.goal.id,
|
|
35394
|
+
options: input.options,
|
|
35395
|
+
workItBlocks: [{ blocked: { type: "goal", id: state.goal.id }, action: "complete", reason: "The agent cannot go on without this approval." }]
|
|
35396
|
+
}]
|
|
34897
35397
|
});
|
|
34898
|
-
if ("
|
|
35398
|
+
if ("sent" in sent) return null;
|
|
34899
35399
|
const entryId = sent.requestEntryIds[0];
|
|
34900
35400
|
if (!entryId) return null;
|
|
34901
35401
|
(state.seen ??= /* @__PURE__ */ new Set()).add(entryId);
|
|
@@ -34913,57 +35413,54 @@ async function askPermission(event, state, rail) {
|
|
|
34913
35413
|
]
|
|
34914
35414
|
}));
|
|
34915
35415
|
}
|
|
34916
|
-
async function finish(
|
|
35416
|
+
async function finish(state, rail, opts) {
|
|
34917
35417
|
const goal = state.goal;
|
|
34918
35418
|
if (!goal) return;
|
|
34919
|
-
const progress = result?.trim().slice(0, 1e4) || void 0;
|
|
34920
|
-
let revision = goal.revision;
|
|
34921
35419
|
try {
|
|
34922
35420
|
const held = await rail.read(goal.id);
|
|
34923
|
-
revision = held.revision ?? revision;
|
|
34924
35421
|
const owed = state.noted?.some((b) => b.goals.includes(goal.id));
|
|
34925
35422
|
if (held.state === "done" || held.state === "cancelled") {
|
|
34926
35423
|
if (!owed) state.goal = void 0;
|
|
34927
35424
|
return;
|
|
34928
35425
|
}
|
|
34929
35426
|
if (!held.openDecisionNeedIds?.length && !owed) {
|
|
34930
|
-
await rail.
|
|
35427
|
+
await rail.complete(goal.id, held.revision ?? goal.revision);
|
|
34931
35428
|
state.goal = void 0;
|
|
34932
|
-
return;
|
|
34933
35429
|
}
|
|
34934
35430
|
} catch (error) {
|
|
34935
35431
|
opts?.log?.(`\u26A0 the Goal did not close, still holding it: ${error.message}`);
|
|
34936
35432
|
}
|
|
34937
|
-
if (!progress) return;
|
|
34938
|
-
try {
|
|
34939
|
-
await rail.update(goal.id, { revision, changes: { progress }, reason: "The agent's turn ended; its Goal is not closed yet." });
|
|
34940
|
-
} catch (error) {
|
|
34941
|
-
opts?.log?.(`\u26A0 could not keep the turn as progress: ${error.message}`);
|
|
34942
|
-
}
|
|
34943
35433
|
}
|
|
34944
35434
|
async function cannotWork(report, state, rail, opts) {
|
|
34945
35435
|
state.resting = true;
|
|
34946
|
-
const
|
|
35436
|
+
const { main: main2, units: units3 } = cut(report);
|
|
35437
|
+
const say = (goalId) => rail.contact({ updates: [{ message: main2, ...units3 ? { units: units3 } : {}, goalIds: [goalId] }] });
|
|
35438
|
+
const own = async () => (await rail.create({ title: "Agent cannot work", outcome: main2 })).goalId;
|
|
34947
35439
|
try {
|
|
34948
35440
|
if (!state.goal) {
|
|
34949
|
-
const
|
|
34950
|
-
if (
|
|
35441
|
+
const next = await rail.next().catch(() => void 0);
|
|
35442
|
+
if (next?.goalId && next.revision !== void 0) state.goal = { id: next.goalId, revision: next.revision };
|
|
34951
35443
|
}
|
|
34952
35444
|
if (!state.goal) {
|
|
34953
|
-
await say();
|
|
35445
|
+
await say(await own());
|
|
34954
35446
|
return;
|
|
34955
35447
|
}
|
|
34956
35448
|
try {
|
|
34957
35449
|
await say(state.goal.id);
|
|
34958
35450
|
} catch (error) {
|
|
34959
|
-
if (!/
|
|
34960
|
-
opts?.log?.(`\u26A0 the held Goal ${state.goal.id.slice(0, 8)}
|
|
34961
|
-
await say();
|
|
35451
|
+
if (!/goal_not_found/.test(error.message)) throw error;
|
|
35452
|
+
opts?.log?.(`\u26A0 the held Goal ${state.goal.id.slice(0, 8)} is gone (goal_not_found) \u2014 saying it on a Goal of its own`);
|
|
35453
|
+
await say(await own());
|
|
34962
35454
|
}
|
|
34963
35455
|
} catch (error) {
|
|
34964
35456
|
opts?.log?.(`\u26A0 could not say the agent cannot work: ${error.message}`);
|
|
34965
35457
|
}
|
|
34966
35458
|
}
|
|
35459
|
+
async function callForResume(text, state, rail) {
|
|
35460
|
+
const { main: main2, units: units3 } = cut(text);
|
|
35461
|
+
const goalId = state.goal?.id ?? (await rail.create({ title: "Usage limit reset", outcome: main2 })).goalId;
|
|
35462
|
+
return rail.contact({ updates: [{ message: main2, ...units3 ? { units: units3 } : {}, goalIds: [goalId], userExplicitlyRequested: "call" }] });
|
|
35463
|
+
}
|
|
34967
35464
|
function conversationFull(result) {
|
|
34968
35465
|
return /prompt is too long/i.test(result ?? "");
|
|
34969
35466
|
}
|
|
@@ -34990,15 +35487,14 @@ async function afterTurn(event, state, rail, opts) {
|
|
|
34990
35487
|
${event.result?.trim() || "No result reported."}`, state, rail, opts);
|
|
34991
35488
|
return void 0;
|
|
34992
35489
|
}
|
|
34993
|
-
await finish(
|
|
35490
|
+
await finish(state, rail, opts);
|
|
34994
35491
|
state.typed = void 0;
|
|
34995
35492
|
state.resting = true;
|
|
34996
35493
|
return void 0;
|
|
34997
35494
|
}
|
|
34998
35495
|
|
|
34999
35496
|
// src/paigy/conversation.ts
|
|
35000
|
-
|
|
35001
|
-
var HARNESS_INSTRUCTION = "You are running as an unattended background harness agent; your user reaches you through Paigy and is not at this terminal. Nothing wakes you after your turn ends but the person, so wait on CI or a deploy inside the turn. The person never sees your turn's final message: it is kept as progress on this Goal. Anything the person needs \u2014 a question, a result, a blocker \u2014 you send through Paigy's contact tool, once; the harness sends nothing on your behalf. What the person says later arrives with the Goal it was said on named in front of it; answer them on that Goal (its id as the contact's parentId).";
|
|
35497
|
+
var HARNESS_INSTRUCTION = "You are running as an unattended background harness agent; your user reaches you through Paigy and is not at this terminal. Nothing wakes you after your turn ends but the person, so wait on CI or a deploy inside the turn. The person never sees your turn's final message, and it is not kept: report where the work stands with a contact update on this Goal (one the person does not need yet is kept as its progress). Anything the person needs \u2014 a question, a result, a blocker \u2014 you send through Paigy's contact tool, once; the harness sends nothing on your behalf. What the person says later arrives with the Goal it was said on named in front of it; answer them on that Goal (its id as the contact's goalId).";
|
|
35002
35498
|
var SAFETY_MS = 6e4;
|
|
35003
35499
|
var ASK_BEAT_MS = 5e3;
|
|
35004
35500
|
function beat() {
|
|
@@ -35098,43 +35594,48 @@ async function gather(state, rail, held) {
|
|
|
35098
35594
|
if (!looks.has(goalId)) looks.set(goalId, { via, ...title ? { title } : {}, ...since !== void 0 ? { since } : {} });
|
|
35099
35595
|
};
|
|
35100
35596
|
const waiting = await rail.waiting().catch(() => null);
|
|
35101
|
-
const listed = /* @__PURE__ */ new
|
|
35597
|
+
const listed = /* @__PURE__ */ new Map();
|
|
35598
|
+
const list = (goalId, eventId) => {
|
|
35599
|
+
const ids = listed.get(goalId) ?? [];
|
|
35600
|
+
if (eventId && !ids.includes(eventId)) ids.push(eventId);
|
|
35601
|
+
listed.set(goalId, ids);
|
|
35602
|
+
};
|
|
35102
35603
|
const announced = state.announced ??= /* @__PURE__ */ new Set();
|
|
35103
35604
|
if (waiting) {
|
|
35104
35605
|
for (const id3 of announced) if (!(waiting.assigned ?? []).some((g) => g.goalId === id3)) announced.delete(id3);
|
|
35105
35606
|
}
|
|
35106
35607
|
for (const g of waiting?.assigned ?? []) if (g.goalId !== state.goal.id && !announced.has(g.goalId)) look2(g.goalId, "assigned", g.title);
|
|
35107
35608
|
for (const g of waiting?.review ?? []) {
|
|
35108
|
-
|
|
35609
|
+
list(g.goalId, g.eventId);
|
|
35109
35610
|
look2(g.goalId, "waiting work", g.title);
|
|
35110
35611
|
}
|
|
35111
35612
|
for (const d of waiting?.deliveries ?? []) for (const id3 of d.goalIds) {
|
|
35112
|
-
|
|
35613
|
+
list(id3, d.deliveryId);
|
|
35113
35614
|
look2(id3, "waiting work");
|
|
35114
35615
|
}
|
|
35115
35616
|
const moved = movedBelow(held, state);
|
|
35116
35617
|
for (const { goal, since } of moved) look2(goal.goalId, "subtree", goal.title, since);
|
|
35117
35618
|
const heard = [];
|
|
35118
|
-
const
|
|
35619
|
+
const read3 = /* @__PURE__ */ new Set();
|
|
35119
35620
|
for (const [goalId, { since, ...found }] of looks) {
|
|
35120
35621
|
let brief = found.brief;
|
|
35121
35622
|
if (!brief) {
|
|
35122
35623
|
try {
|
|
35123
35624
|
brief = await rail.read(goalId);
|
|
35124
35625
|
} catch (error) {
|
|
35125
|
-
if (error.status === 404)
|
|
35626
|
+
if (error.status === 404) read3.add(goalId);
|
|
35126
35627
|
continue;
|
|
35127
35628
|
}
|
|
35128
35629
|
}
|
|
35129
|
-
|
|
35630
|
+
read3.add(goalId);
|
|
35130
35631
|
const fresh = !brief.reviewSince && (found.via === "waiting work" || found.via === "assigned") ? sinceTheWork(brief) : { after: -1 };
|
|
35131
35632
|
if (found.via === "assigned") announced.add(goalId);
|
|
35132
35633
|
heard.push({ goalId, ...found, brief, words: unheard(brief, state, brief.reviewSince ? null : since ?? null, fresh.after, brief.reviewSince), ...fresh.note ? { note: fresh.note } : {} });
|
|
35133
35634
|
}
|
|
35134
|
-
for (const { goal, since } of moved) if (
|
|
35635
|
+
for (const { goal, since } of moved) if (read3.has(goal.goalId)) state.below.goals.set(goal.goalId, { since, at: goal.updatedAt ?? null });
|
|
35135
35636
|
return { heard, listed };
|
|
35136
35637
|
}
|
|
35137
|
-
var GIVEN = "This Goal was given to you, and nobody has started it. Carry on with what you're doing unless it changes that;
|
|
35638
|
+
var GIVEN = "This Goal was given to you, and nobody has started it. Carry on with what you're doing unless it changes that; your first write to it (a contact update naming it) starts it when you take it up.";
|
|
35138
35639
|
var says = (h) => h.words.length > 0 || h.via === "assigned";
|
|
35139
35640
|
function whatItIs(h) {
|
|
35140
35641
|
const outcome2 = h.brief.outcome?.trim() ?? "";
|
|
@@ -35164,7 +35665,10 @@ async function hear(session, state, rail, held, opts) {
|
|
|
35164
35665
|
if (opts?.tally) opts.tally.announced += goals.length;
|
|
35165
35666
|
}
|
|
35166
35667
|
}
|
|
35167
|
-
for (const h of heard)
|
|
35668
|
+
for (const h of heard) {
|
|
35669
|
+
const events = listed.get(h.goalId);
|
|
35670
|
+
if (events) await acknowledge2(h.goalId, h.brief, events, state, rail, log);
|
|
35671
|
+
}
|
|
35168
35672
|
}
|
|
35169
35673
|
var NOTED = "New from the person while you work. Carry on unless it changes what you're doing: it comes back to you as your next turn when this one ends.";
|
|
35170
35674
|
var SEEN_MID_TURN = "While you worked, the person said this, and you saw it mid-task. Act on it now, unless you already have.";
|
|
@@ -35210,15 +35714,16 @@ function settle(session, state, inbox, log) {
|
|
|
35210
35714
|
send2(session, state, [...seen.length ? [SEEN_MID_TURN, ...seen.map((b) => b.words)] : [], ...unseen.map((b) => b.words)].join("\n\n"));
|
|
35211
35715
|
log?.(`\u25B8 typed the person's words from ${short([...new Set(batches.flatMap((b) => b.goals))])} (noted mid-turn: ${seen.length} seen by the hook, ${unseen.length} not)`);
|
|
35212
35716
|
}
|
|
35213
|
-
async function
|
|
35717
|
+
async function acknowledge2(goalId, brief, events, state, rail, log) {
|
|
35718
|
+
const ids = [.../* @__PURE__ */ new Set([...brief.reviewEventId ? [brief.reviewEventId] : [], ...events])];
|
|
35719
|
+
if (!ids.length) return;
|
|
35214
35720
|
const acked = state.acked ??= /* @__PURE__ */ new Map();
|
|
35215
|
-
|
|
35216
|
-
acked.
|
|
35721
|
+
const key3 = ids.join(",");
|
|
35722
|
+
if (acked.get(goalId) === key3) return;
|
|
35723
|
+
acked.set(goalId, key3);
|
|
35217
35724
|
try {
|
|
35218
|
-
|
|
35219
|
-
|
|
35220
|
-
acked.set(goalId, done.revision);
|
|
35221
|
-
if (state.goal?.id === goalId && done.revision !== void 0) state.goal.revision = done.revision;
|
|
35725
|
+
const refused = (await rail.ack(ids)).filter((a) => a.refused);
|
|
35726
|
+
if (refused.length) log?.(`\u26A0 could not acknowledge ${goalId.slice(0, 8)}: ${refused.map((a) => `${a.eventId.slice(0, 8)} ${a.refused}`).join(", ")} \u2014 its words are typed in; it stays listed until acknowledged`);
|
|
35222
35727
|
} catch (error) {
|
|
35223
35728
|
log?.(`\u26A0 could not acknowledge ${goalId.slice(0, 8)}: ${error.message} \u2014 its words are typed in; it stays listed until acknowledged`);
|
|
35224
35729
|
}
|
|
@@ -35244,13 +35749,13 @@ async function look(session, state, rail, opts) {
|
|
|
35244
35749
|
if (state.resting && state.noted?.length && !state.asks?.size) return settle(session, state, opts?.inbox, opts?.log);
|
|
35245
35750
|
if (!state.goal) {
|
|
35246
35751
|
if (!state.resting) return;
|
|
35247
|
-
let brief2 = await rail.
|
|
35752
|
+
let brief2 = await rail.next();
|
|
35248
35753
|
if (!brief2.goalId || brief2.revision === void 0) {
|
|
35249
35754
|
if (opts?.initialPrompt?.trim()) {
|
|
35250
35755
|
const prompt = opts.initialPrompt.trim();
|
|
35251
35756
|
opts.initialPrompt = void 0;
|
|
35252
|
-
const admitted = await rail.create({
|
|
35253
|
-
brief2 = await rail.
|
|
35757
|
+
const admitted = await rail.create({ title: prompt.split(/\s+/).slice(0, 5).join(" ").slice(0, 80), outcome: prompt });
|
|
35758
|
+
brief2 = await rail.next();
|
|
35254
35759
|
if (!brief2.goalId || brief2.revision === void 0) {
|
|
35255
35760
|
state.goal = { id: admitted.goalId, revision: admitted.revision };
|
|
35256
35761
|
send2(session, state, [HARNESS_INSTRUCTION, named(admitted.goalId, void 0, { outcome: prompt }), prompt].join("\n\n"));
|
|
@@ -35272,7 +35777,7 @@ async function look(session, state, rail, opts) {
|
|
|
35272
35777
|
const earlier = left ? `(${left} earlier entries on this Goal are left out or shortened; get_goal with history: true reads them in full.)` : "";
|
|
35273
35778
|
const fullText = [outcome2, earlier, ...said].filter(Boolean).join("\n\n");
|
|
35274
35779
|
send2(session, state, [HARNESS_INSTRUCTION, named(brief2.goalId, void 0, brief2), fullText].filter(Boolean).join("\n\n"));
|
|
35275
|
-
if (ended(brief2.state)) await
|
|
35780
|
+
if (ended(brief2.state)) await acknowledge2(brief2.goalId, brief2, [], state, rail, opts?.log);
|
|
35276
35781
|
return;
|
|
35277
35782
|
}
|
|
35278
35783
|
const brief = await rail.read(state.goal.id);
|
|
@@ -35340,9 +35845,9 @@ async function pump(session, state, rail, opts) {
|
|
|
35340
35845
|
}
|
|
35341
35846
|
if (!await opts.onIdle()) return;
|
|
35342
35847
|
if (now() - since >= BEAT_REPORT_MS) {
|
|
35343
|
-
const
|
|
35344
|
-
if (
|
|
35345
|
-
opts.log?.(`\u25B9 beats: ${
|
|
35848
|
+
const read3 = counts.wake + counts.rest + counts.safety;
|
|
35849
|
+
if (read3 || counts.skipped || tally.noted || tally.seen || tally.announced) {
|
|
35850
|
+
opts.log?.(`\u25B9 beats: ${read3} read (${counts.wake} wake, ${counts.rest} rest, ${counts.safety} safety), ${counts.skipped} wake mid-turn skipped, ${tally.noted} noted mid-turn, ${tally.seen} seen by the hook, ${tally.announced} assigned announced${tally.paused ? `, ${tally.paused} held by the usage limit` : ""}`);
|
|
35346
35851
|
}
|
|
35347
35852
|
counts.wake = counts.rest = counts.safety = counts.skipped = tally.noted = tally.seen = tally.announced = tally.paused = 0;
|
|
35348
35853
|
since = now();
|
|
@@ -35360,7 +35865,7 @@ function runHarness(opts) {
|
|
|
35360
35865
|
const clock4 = beat();
|
|
35361
35866
|
let session = null;
|
|
35362
35867
|
const speaksAs = opts.session ?? opts.resume ?? sessionId();
|
|
35363
|
-
const instance =
|
|
35868
|
+
const instance = randomUUID4();
|
|
35364
35869
|
const rail = railFor({ token: opts.token, reach: reachAs(speaksAs, instance) });
|
|
35365
35870
|
let inbox;
|
|
35366
35871
|
if (opts.harness === "claude") {
|
|
@@ -35374,7 +35879,7 @@ function runHarness(opts) {
|
|
|
35374
35879
|
function runningAgain() {
|
|
35375
35880
|
state.carriedOn = false;
|
|
35376
35881
|
opts.log("\u25B6 running again after the limit");
|
|
35377
|
-
LIMITS.running(name, (text) =>
|
|
35882
|
+
LIMITS.running(name, (text) => callForResume(text, state, rail), opts.log);
|
|
35378
35883
|
}
|
|
35379
35884
|
async function handle(event) {
|
|
35380
35885
|
if (event.kind === "error") {
|
|
@@ -35556,7 +36061,7 @@ function listRepos(deps) {
|
|
|
35556
36061
|
|
|
35557
36062
|
// src/holder.ts
|
|
35558
36063
|
init_dist();
|
|
35559
|
-
import { execFileSync as
|
|
36064
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
35560
36065
|
import { readFileSync as readFileSync5, readdirSync as readdirSync3 } from "fs";
|
|
35561
36066
|
import { homedir as homedir7 } from "os";
|
|
35562
36067
|
import { join as join7 } from "path";
|
|
@@ -35571,7 +36076,7 @@ function isAlive(pid) {
|
|
|
35571
36076
|
function psStart(pid, zone) {
|
|
35572
36077
|
try {
|
|
35573
36078
|
const env = zone === "UTC" ? { ...process.env, TZ: "UTC", LC_ALL: "C" } : { ...process.env, LC_ALL: "C" };
|
|
35574
|
-
return
|
|
36079
|
+
return execFileSync2("ps", ["-o", "lstart=", "-p", String(pid)], { env, encoding: "utf8", timeout: 2e3 }).trim() || null;
|
|
35575
36080
|
} catch {
|
|
35576
36081
|
return null;
|
|
35577
36082
|
}
|
|
@@ -35599,7 +36104,7 @@ function proven(pid, procStart, deps) {
|
|
|
35599
36104
|
function localHolderPids(deps = {}) {
|
|
35600
36105
|
const dir = deps.dir ?? join7(process.env.CLAUDE_CONFIG_DIR?.trim() || join7(homedir7(), ".claude"), "sessions");
|
|
35601
36106
|
const list = deps.list ?? ((d) => readdirSync3(d));
|
|
35602
|
-
const
|
|
36107
|
+
const read3 = deps.read ?? ((f) => readFileSync5(f, "utf8"));
|
|
35603
36108
|
const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
|
|
35604
36109
|
const held = /* @__PURE__ */ new Map();
|
|
35605
36110
|
let files;
|
|
@@ -35612,7 +36117,7 @@ function localHolderPids(deps = {}) {
|
|
|
35612
36117
|
if (!/^\d+\.json$/.test(file)) continue;
|
|
35613
36118
|
let row;
|
|
35614
36119
|
try {
|
|
35615
|
-
row = JSON.parse(
|
|
36120
|
+
row = JSON.parse(read3(join7(dir, file)));
|
|
35616
36121
|
} catch {
|
|
35617
36122
|
continue;
|
|
35618
36123
|
}
|
|
@@ -35626,7 +36131,7 @@ function localHolderPids(deps = {}) {
|
|
|
35626
36131
|
}
|
|
35627
36132
|
function psParent(pid) {
|
|
35628
36133
|
try {
|
|
35629
|
-
const out =
|
|
36134
|
+
const out = execFileSync2("ps", ["-o", "ppid=", "-p", String(pid)], { encoding: "utf8", timeout: 2e3 }).trim();
|
|
35630
36135
|
const n = Number(out);
|
|
35631
36136
|
return Number.isInteger(n) && n > 0 ? n : null;
|
|
35632
36137
|
} catch {
|
|
@@ -35644,7 +36149,7 @@ function descendsFrom(pid, ancestor, parent = psParent) {
|
|
|
35644
36149
|
function localHolders(deps = {}) {
|
|
35645
36150
|
const dir = deps.dir ?? join7(process.env.CLAUDE_CONFIG_DIR?.trim() || join7(homedir7(), ".claude"), "sessions");
|
|
35646
36151
|
const list = deps.list ?? ((d) => readdirSync3(d));
|
|
35647
|
-
const
|
|
36152
|
+
const read3 = deps.read ?? ((f) => readFileSync5(f, "utf8"));
|
|
35648
36153
|
const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
|
|
35649
36154
|
const held = /* @__PURE__ */ new Map();
|
|
35650
36155
|
let files;
|
|
@@ -35657,7 +36162,7 @@ function localHolders(deps = {}) {
|
|
|
35657
36162
|
if (!/^\d+\.json$/.test(file)) continue;
|
|
35658
36163
|
let row;
|
|
35659
36164
|
try {
|
|
35660
|
-
row = JSON.parse(
|
|
36165
|
+
row = JSON.parse(read3(join7(dir, file)));
|
|
35661
36166
|
} catch {
|
|
35662
36167
|
continue;
|
|
35663
36168
|
}
|
|
@@ -35750,7 +36255,7 @@ function ownerSession(slot, deps = {}) {
|
|
|
35750
36255
|
const prefix = m[1];
|
|
35751
36256
|
const root = deps.projectsDir ?? join8(homedir8(), ".claude", "projects");
|
|
35752
36257
|
const list = deps.list ?? ((dir) => readdirSync4(dir));
|
|
35753
|
-
const
|
|
36258
|
+
const head2 = deps.head ?? readHead;
|
|
35754
36259
|
let folders;
|
|
35755
36260
|
try {
|
|
35756
36261
|
folders = list(root);
|
|
@@ -35768,7 +36273,7 @@ function ownerSession(slot, deps = {}) {
|
|
|
35768
36273
|
if (!file) continue;
|
|
35769
36274
|
let text;
|
|
35770
36275
|
try {
|
|
35771
|
-
text =
|
|
36276
|
+
text = head2(join8(root, folder, file));
|
|
35772
36277
|
} catch {
|
|
35773
36278
|
continue;
|
|
35774
36279
|
}
|
|
@@ -35891,7 +36396,7 @@ async function waitingWork(token, session) {
|
|
|
35891
36396
|
if (quiet !== void 0 && Date.now() < quiet) return { skip: BOUND_SKIP };
|
|
35892
36397
|
let found;
|
|
35893
36398
|
try {
|
|
35894
|
-
found = await
|
|
36399
|
+
found = await receive({ token, ...session ? { reach: reachAs(session) } : {} });
|
|
35895
36400
|
} catch (error) {
|
|
35896
36401
|
if (error instanceof RevokedError) return { skip: "was revoked: its credential is gone for good", revoked: true };
|
|
35897
36402
|
if (error instanceof ApiError && error.body?.error === "identity_session_mismatch") {
|
|
@@ -36130,7 +36635,7 @@ function startHost(opts) {
|
|
|
36130
36635
|
skip(`has a full conversation (${resumes.slice(0, 8)}) \u2014 not resuming it; its Goals go to the dead-agent handoff`);
|
|
36131
36636
|
return;
|
|
36132
36637
|
}
|
|
36133
|
-
const
|
|
36638
|
+
const read3 = async () => {
|
|
36134
36639
|
const got = await waitingWork(token, identity.sessionId ?? owner?.sessionId);
|
|
36135
36640
|
if (!("skip" in got)) return got;
|
|
36136
36641
|
if (got.revoked) {
|
|
@@ -36142,7 +36647,7 @@ function startHost(opts) {
|
|
|
36142
36647
|
return null;
|
|
36143
36648
|
};
|
|
36144
36649
|
if (decided.why === "presence") {
|
|
36145
|
-
found = await
|
|
36650
|
+
found = await read3() ?? void 0;
|
|
36146
36651
|
if (!found) return;
|
|
36147
36652
|
const since = found.since;
|
|
36148
36653
|
decided = wakeAction(false, Date.now(), seenByServer, { ...here, ...since ? { movedAt: Date.parse(since) } : {} });
|
|
@@ -36168,7 +36673,7 @@ function startHost(opts) {
|
|
|
36168
36673
|
skip("has no granted folder to wake in");
|
|
36169
36674
|
return;
|
|
36170
36675
|
}
|
|
36171
|
-
found ??= await
|
|
36676
|
+
found ??= await read3() ?? void 0;
|
|
36172
36677
|
if (!found) return;
|
|
36173
36678
|
if (runs.has(key3)) {
|
|
36174
36679
|
skip("was started by the wake that read it first");
|
|
@@ -36304,7 +36809,7 @@ function startHost(opts) {
|
|
|
36304
36809
|
return {
|
|
36305
36810
|
name,
|
|
36306
36811
|
// The slot key rides along so the window's agent page can speak AS this agent —
|
|
36307
|
-
// its pending reads (`
|
|
36812
|
+
// its pending reads (`receive`, the same pure read the sweep does) need the
|
|
36308
36813
|
// slot's own token, and the display name is not a key.
|
|
36309
36814
|
slot,
|
|
36310
36815
|
tokenId: id3.tokenId,
|
|
@@ -36710,7 +37215,7 @@ async function main() {
|
|
|
36710
37215
|
let launched;
|
|
36711
37216
|
if (parsed.launch) {
|
|
36712
37217
|
overrideToken(readSlot("Desktop") || null);
|
|
36713
|
-
const session =
|
|
37218
|
+
const session = randomUUID5();
|
|
36714
37219
|
const minted = await hatch(parsed.launch, parsed.voice ?? null, {
|
|
36715
37220
|
reach: reachAs(session),
|
|
36716
37221
|
brief: parsed.prompt,
|