@paigy/harness 0.3.35 → 0.3.37
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 +923 -409
- package/dist/main.js +845 -340
- 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)}`;
|
|
@@ -23815,12 +23861,6 @@ async function manageGoals(input, opts = {}) {
|
|
|
23815
23861
|
if (!res.ok) await fail("manage_goals", res);
|
|
23816
23862
|
return await res.json();
|
|
23817
23863
|
}
|
|
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}` }, body: JSON.stringify(goalId ? { goalId } : {}) }));
|
|
23821
|
-
if (!res.ok) await fail("claim_goal", res);
|
|
23822
|
-
return await res.json();
|
|
23823
|
-
}
|
|
23824
23864
|
async function getGoal(goalId, opts = {}, read3 = {}) {
|
|
23825
23865
|
const token = authToken(opts.token) ?? "";
|
|
23826
23866
|
const query = [read3.history ? "history=1" : "", read3.diagnose ? "diagnose=1" : ""].filter(Boolean).join("&");
|
|
@@ -23831,13 +23871,6 @@ async function getGoal(goalId, opts = {}, read3 = {}) {
|
|
|
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}` }, 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",
|
|
@@ -23949,96 +23982,64 @@ 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);
|
|
23979
|
-
if (!(
|
|
23995
|
+
if (!sendsAnything(parsed)) throw new Error("contact with nothing to send receives: call receiveContact");
|
|
23980
23996
|
opts.signal?.throwIfAborted();
|
|
23981
23997
|
const send22 = opts.reach ?? reach;
|
|
23982
|
-
const
|
|
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
|
-
waiting: parsed.waiting,
|
|
24011
|
-
channel: parsed.channel === "call" ? "call" : "message"
|
|
24012
|
-
})
|
|
24013
|
-
}));
|
|
24014
|
-
if (!res.ok) await fail("batch contact", res);
|
|
24015
|
-
const receipt = await res.json();
|
|
24016
|
-
deliveries = receipt.deliveries ?? [];
|
|
24017
|
-
if (parsed.channel === "call" && receipt.channel && receipt.channel !== "call") demoted = DEMOTED;
|
|
24018
|
-
recorded = receipt.recorded ?? [];
|
|
24019
|
-
if (deliveries.length === 0 && recorded.length) return { sent: false, recorded, message: NOT_SENT };
|
|
24020
|
-
if (deliveries.length === 0) throw new Error("Goal contact returned no Delivery identities");
|
|
24021
|
-
deliveryId = deliveries[0]?.deliveryId ?? "";
|
|
24022
|
-
if (!deliveryId) throw new Error("Goal contact returned no valid Delivery identity");
|
|
24023
|
-
}
|
|
24024
|
-
const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id: id22, deliveryId: deliveryId2, goalId }) => ({ ...id22 ? { id: id22 } : {}, deliveryId: deliveryId2, goalId }));
|
|
24025
|
-
const joinedCard = deliveries[0]?.joinedCard === true;
|
|
24026
|
-
const joinedCall = deliveries[0]?.joinedCall === true;
|
|
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];
|
|
24027
24026
|
const read3 = async (signal2) => {
|
|
24028
|
-
const
|
|
24029
|
-
if (!res.ok) await fail("read_delivery", res);
|
|
24030
|
-
const one = await res.json();
|
|
24027
|
+
const one = await readDelivery(lead.deliveryId, { ...opts, signal: signal2 });
|
|
24031
24028
|
return {
|
|
24032
24029
|
...one,
|
|
24033
|
-
|
|
24030
|
+
ok,
|
|
24031
|
+
results,
|
|
24032
|
+
...deliveries.length > 1 ? { deliveries: deliveries.map(({ deliveryId, goalId, kind, questionId }) => ({ deliveryId, goalId, kind, ...questionId ? { questionId } : {} })) } : {},
|
|
24034
24033
|
...recorded.length ? { recorded, notSent: NOT_SENT } : {},
|
|
24035
|
-
...joinedCard ? { joinedCard: true } : {},
|
|
24036
|
-
|
|
24037
|
-
...
|
|
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
|
|
24038
24039
|
};
|
|
24039
24040
|
};
|
|
24040
|
-
const settled = (d) => d.
|
|
24041
|
-
if (opts.waits === false) return read3(opts.signal);
|
|
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" };
|
|
24042
24043
|
const window = AbortSignal.timeout(AWAIT_WINDOW_MS);
|
|
24043
24044
|
const signal = opts.signal ? AbortSignal.any([opts.signal, window]) : window;
|
|
24044
24045
|
let latest;
|
|
@@ -24046,12 +24047,12 @@ async function contact(input, opts = {}) {
|
|
|
24046
24047
|
while (true) {
|
|
24047
24048
|
signal.throwIfAborted();
|
|
24048
24049
|
latest = await read3(signal);
|
|
24049
|
-
if (settled(latest)) return latest;
|
|
24050
|
+
if (settled(latest)) return { ...latest, waitOutcome: "available" };
|
|
24050
24051
|
await sleep2(5e3, void 0, { signal });
|
|
24051
24052
|
}
|
|
24052
24053
|
} catch (error) {
|
|
24053
24054
|
opts.signal?.throwIfAborted();
|
|
24054
|
-
if (window.aborted && latest) return latest;
|
|
24055
|
+
if (window.aborted && latest) return { ...latest, waitOutcome: "expired" };
|
|
24055
24056
|
throw error;
|
|
24056
24057
|
}
|
|
24057
24058
|
}
|
|
@@ -24062,6 +24063,15 @@ async function receive(opts = {}) {
|
|
|
24062
24063
|
if (!res.ok) await fail("receive", res);
|
|
24063
24064
|
return await res.json();
|
|
24064
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
|
+
}
|
|
24065
24075
|
function frame(line, topic, event, payload) {
|
|
24066
24076
|
const ref = String(++line.ref);
|
|
24067
24077
|
try {
|
|
@@ -24223,9 +24233,9 @@ async function subscribeWake(onNudge, opts = {}) {
|
|
|
24223
24233
|
};
|
|
24224
24234
|
}
|
|
24225
24235
|
function withCodexEnv(text) {
|
|
24226
|
-
const
|
|
24227
|
-
if (!
|
|
24228
|
-
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;
|
|
24229
24239
|
const next = /^\[/m.exec(text.slice(start));
|
|
24230
24240
|
const end = next ? start + next.index : text.length;
|
|
24231
24241
|
const block2 = text.slice(start, end);
|
|
@@ -24244,7 +24254,7 @@ ${block2}`;
|
|
|
24244
24254
|
}
|
|
24245
24255
|
return text.slice(0, start) + updated + text.slice(end);
|
|
24246
24256
|
}
|
|
24247
|
-
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, OPTION_LABEL_MAX, OPTION_HINT_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, GOAL_OUTCOME_MAX, 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, ExplainerReplySchema, EXPLAINER_REPLY_JSON_SCHEMA, DISTILLER_DEFECTS, DistillerReplySchema, DISTILLER_REPLY_JSON_SCHEMA, TIDY_AUDIENCES, TidyReplySchema, TIDY_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;
|
|
24248
24258
|
var init_dist = __esm({
|
|
24249
24259
|
"../../packages/sdk/dist/index.js"() {
|
|
24250
24260
|
"use strict";
|
|
@@ -24256,6 +24266,10 @@ var init_dist = __esm({
|
|
|
24256
24266
|
init_v3();
|
|
24257
24267
|
init_zod();
|
|
24258
24268
|
init_zod();
|
|
24269
|
+
init_zod();
|
|
24270
|
+
init_zod();
|
|
24271
|
+
init_zod();
|
|
24272
|
+
init_zod();
|
|
24259
24273
|
import_undici = __toESM(require_undici(), 1);
|
|
24260
24274
|
require2 = __sdkCreateRequire(import.meta.url);
|
|
24261
24275
|
CODEX_ENV = ["CODEX_THREAD_ID", "CODEX_SESSION_ID", "CODEX_HOME", "PAIGY_TOKEN", "PAIGY_SESSION_ID", "PAIGY_HARNESS", "PAIGY_INSTANCE_ID", "PAIGY_ON_WAKE"];
|
|
@@ -24637,58 +24651,148 @@ var init_dist = __esm({
|
|
|
24637
24651
|
};
|
|
24638
24652
|
OPTIONS_MIN = 2;
|
|
24639
24653
|
OPTIONS_MAX = 6;
|
|
24654
|
+
OPTION_LABEL_MAX = 50;
|
|
24655
|
+
OPTION_HINT_MAX = 200;
|
|
24640
24656
|
OptionSchema = external_exports.object({
|
|
24641
24657
|
id: external_exports.string(),
|
|
24642
24658
|
label: external_exports.string(),
|
|
24643
|
-
hint: external_exports.string().max(500).describe(
|
|
24659
|
+
hint: external_exports.string().max(500).describe(`Optional: what choosing it does, at most ${OPTION_HINT_MAX} characters (e.g. 'Reruns test suite', 'Merges to main').`).optional(),
|
|
24644
24660
|
// .describe() flows into the MCP contact JSON schema (zodToJsonSchema), so
|
|
24645
24661
|
// the constraints below are what an agent reads when deciding to use these.
|
|
24646
24662
|
html: external_exports.string().max(16384).describe(
|
|
24647
|
-
"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
|
|
24663
|
+
"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."
|
|
24648
24664
|
).optional(),
|
|
24649
24665
|
image: external_exports.string().url().describe(
|
|
24650
|
-
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use
|
|
24666
|
+
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use the HTML preview instead."
|
|
24651
24667
|
).optional()
|
|
24652
24668
|
});
|
|
24653
|
-
OptionInputSchema =
|
|
24654
|
-
|
|
24669
|
+
OptionInputSchema = external_exports.object({
|
|
24670
|
+
id: external_exports.string().trim().min(1).max(64).regex(/^[A-Za-z0-9_.:-]+$/).optional().describe(
|
|
24671
|
+
`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.`
|
|
24672
|
+
),
|
|
24673
|
+
// SHORT CHOICES (owner, 2026-10-07: "options label should be maybe max 50 characters and the hint 200"):
|
|
24674
|
+
// a label is one choice the person reads, or hears on a call; a hint says its consequence in a line.
|
|
24675
|
+
label: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX, `option_label_too_long: an option's label is at most ${OPTION_LABEL_MAX} characters; say the choice, and put its consequence in the hint.`).describe(`The choice, at most ${OPTION_LABEL_MAX} characters, standing on its own.`),
|
|
24676
|
+
hint: external_exports.string().max(OPTION_HINT_MAX, `option_hint_too_long: an option's hint is at most ${OPTION_HINT_MAX} characters.`).describe(`Optional: what choosing it does, at most ${OPTION_HINT_MAX} characters (e.g. 'Reruns test suite', 'Merges to main').`).optional(),
|
|
24677
|
+
htmlPreview: OptionSchema.shape.html,
|
|
24678
|
+
imgUrl: OptionSchema.shape.image
|
|
24655
24679
|
}).strict();
|
|
24656
24680
|
NIGHT = { from: 23, to: 7 };
|
|
24657
|
-
|
|
24658
|
-
|
|
24659
|
-
|
|
24660
|
-
|
|
24661
|
-
|
|
24662
|
-
|
|
24681
|
+
ASK_MAX = 250;
|
|
24682
|
+
UNITS_MAX = 12;
|
|
24683
|
+
UNIT_TITLE_MAX = 50;
|
|
24684
|
+
UNIT_BODY_MAX = 200;
|
|
24685
|
+
UnitInputSchema = external_exports.object({
|
|
24686
|
+
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.`),
|
|
24687
|
+
body: external_exports.string().trim().min(1).describe(`The unit itself, at most ${UNIT_BODY_MAX} characters.`)
|
|
24688
|
+
}).strict();
|
|
24689
|
+
questionHandle = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
24690
|
+
NodeRef = external_exports.object({
|
|
24691
|
+
type: external_exports.enum(["goal", "question"]),
|
|
24692
|
+
id: external_exports.string().uuid()
|
|
24693
|
+
}).strict().describe("A Goal or a Question, by its id.");
|
|
24694
|
+
BlockedAction = external_exports.enum(["start", "complete", "answer"]).describe("What waits: starting or completing a Goal, or answering a Question.");
|
|
24695
|
+
reason = external_exports.string().trim().min(1).max(500).describe("Why, as an explanation, never as policy.");
|
|
24696
|
+
actionFits = (b) => b.blocked.type === "goal" === (b.action !== "answer");
|
|
24697
|
+
ACTION_FITS = "a goal is blocked from start or complete; a question from answer";
|
|
24698
|
+
userExplicitlyRequested = external_exports.enum(["any", "call"]).optional().describe(
|
|
24699
|
+
`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.`
|
|
24700
|
+
);
|
|
24701
|
+
units = external_exports.array(UnitInputSchema).optional().describe(
|
|
24702
|
+
`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.`
|
|
24703
|
+
);
|
|
24704
|
+
UpdateInputSchema = external_exports.object({
|
|
24705
|
+
message: external_exports.string().trim().min(1).describe(`The one point, at most ${ASK_MAX} characters; the context goes in units.`),
|
|
24706
|
+
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."),
|
|
24707
|
+
units,
|
|
24708
|
+
userExplicitlyRequested
|
|
24709
|
+
}).strict().superRefine((u, ctx) => refuseOverCaps(u.message, u.units, "message", ctx));
|
|
24710
|
+
questionFields = {
|
|
24711
|
+
question: external_exports.string().trim().min(1).describe(
|
|
24712
|
+
`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.`
|
|
24663
24713
|
),
|
|
24664
|
-
|
|
24714
|
+
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."),
|
|
24715
|
+
units,
|
|
24716
|
+
options: external_exports.array(OptionInputSchema).min(1).max(6).optional().describe("The choices, when you have them. Each label stands on its own, at most 50 characters; a hint, at most 200."),
|
|
24665
24717
|
// HOW THE OPTIONS ARE ANSWERED, SAID BY THE AGENT (owner, 2026-10-02: "one and many makes sense";
|
|
24666
|
-
// brain_prompts.md §1: structured agent questions need no model).
|
|
24667
|
-
|
|
24668
|
-
|
|
24669
|
-
select: external_exports.enum(["one", "many"]).optional().describe(
|
|
24670
|
-
'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.'
|
|
24718
|
+
// brain_prompts.md §1: structured agent questions need no model). The app draws all three.
|
|
24719
|
+
pickMode: external_exports.enum(["one", "many", "rank"]).optional().describe(
|
|
24720
|
+
'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.'
|
|
24671
24721
|
),
|
|
24672
|
-
|
|
24673
|
-
|
|
24674
|
-
)
|
|
24675
|
-
|
|
24676
|
-
StartContactSchema = external_exports.object({
|
|
24677
|
-
asks: external_exports.array(AskInputSchema).min(1).describe("The questions to pose, one per object. An ask with a parentId is filed on that Goal as it is; an ask naming no Goal starts a new Goal of yours."),
|
|
24678
|
-
waiting: external_exports.enum(["none", "hard"]).default("none").describe("hard requests a call even when channel is notification; user permissions and ring cooldowns still apply."),
|
|
24679
|
-
channel: external_exports.enum(["notification", "call"]).default("notification")
|
|
24680
|
-
}).strict();
|
|
24681
|
-
ReceiveContactSchema = external_exports.object({
|
|
24682
|
-
wait: external_exports.boolean().optional().describe(
|
|
24683
|
-
"Only controls when this returns. true (the default when you send and acknowledge nothing): wait up to about 45 seconds for incoming communication addressed to you, and return as soon as some is available. false: return 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 in the window; wait again without sending again), or `not_waited` (a hosted connection never holds a wait)."
|
|
24722
|
+
// WHAT THE QUESTION HOLDS UP (brain_prompts.md §2.1): replaces `waiting: 'hard'`. A question that
|
|
24723
|
+
// blocks work asks for a call (the person's settings and ring cooldowns still decide).
|
|
24724
|
+
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(
|
|
24725
|
+
"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."
|
|
24684
24726
|
),
|
|
24727
|
+
userExplicitlyRequested
|
|
24728
|
+
};
|
|
24729
|
+
refineQuestion = (q, ctx) => {
|
|
24730
|
+
refuseOverCaps(q.question, q.units, "question", ctx);
|
|
24731
|
+
if (q.pickMode && !q.options) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["pickMode"], message: "pickMode comes only with options" });
|
|
24732
|
+
const ids = (q.options ?? []).map((o) => o.id);
|
|
24733
|
+
if (ids.some((id22) => id22) && (ids.some((id22) => !id22) || new Set(ids).size !== ids.length)) {
|
|
24734
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["options"], message: "give every option a distinct id, or none" });
|
|
24735
|
+
}
|
|
24736
|
+
};
|
|
24737
|
+
QuestionInputSchema = external_exports.object({
|
|
24738
|
+
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."),
|
|
24739
|
+
...questionFields
|
|
24740
|
+
}).strict().superRefine(refineQuestion);
|
|
24741
|
+
QuestionWireSchema = external_exports.object({ questionId: external_exports.string().uuid(), ...questionFields }).strict().superRefine(refineQuestion);
|
|
24742
|
+
AnswerInputSchema = external_exports.object({
|
|
24743
|
+
questionId: questionHandle.describe("The Question you answer: its id as the event or the conversation shows it (8 characters or whole)."),
|
|
24744
|
+
answer: external_exports.object({
|
|
24745
|
+
text: external_exports.string().trim().min(1).describe(`Your answer in your own words, at most ${ASK_MAX} characters; the context goes in units.`),
|
|
24746
|
+
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).")
|
|
24747
|
+
}).strict(),
|
|
24748
|
+
units
|
|
24749
|
+
}).strict().superRefine((a, ctx) => refuseOverCaps(a.answer.text, a.units, "text", ctx));
|
|
24750
|
+
QuestionDependencySchema = external_exports.object({
|
|
24751
|
+
questionId: questionHandle.describe("A Question you asked."),
|
|
24752
|
+
change: external_exports.enum(["add", "remove"]),
|
|
24753
|
+
blocked: NodeRef,
|
|
24754
|
+
action: BlockedAction,
|
|
24755
|
+
reason: reason.optional()
|
|
24756
|
+
}).strict().refine(actionFits, ACTION_FITS);
|
|
24757
|
+
sendFields = {
|
|
24758
|
+
updates: external_exports.array(UpdateInputSchema).min(1).max(20).optional().describe(
|
|
24759
|
+
"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."
|
|
24760
|
+
),
|
|
24761
|
+
answers: external_exports.array(AnswerInputSchema).min(1).max(20).optional().describe("Answers to Questions addressed to you."),
|
|
24762
|
+
withdrawQuestionIds: external_exports.array(questionHandle).min(1).max(10).optional().describe(
|
|
24763
|
+
"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."
|
|
24764
|
+
),
|
|
24765
|
+
questionDependencies: external_exports.array(QuestionDependencySchema).min(1).max(20).optional().describe(
|
|
24766
|
+
"Add or remove what a Question you asked holds up, after asking it."
|
|
24767
|
+
)
|
|
24768
|
+
};
|
|
24769
|
+
ContactSchema = external_exports.object({
|
|
24770
|
+
...sendFields,
|
|
24771
|
+
questions: external_exports.array(QuestionInputSchema).min(1).max(20).optional().describe("Questions for the person, one per object."),
|
|
24772
|
+
/** RECEIVING (2I, I2; brain_prompts.md §2.2): the events this agent handled. */
|
|
24685
24773
|
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
24686
|
-
"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 (
|
|
24774
|
+
"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."
|
|
24775
|
+
),
|
|
24776
|
+
wait: external_exports.boolean().optional().describe(
|
|
24777
|
+
"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`."
|
|
24687
24778
|
)
|
|
24688
24779
|
}).strict();
|
|
24689
|
-
|
|
24780
|
+
sendsAnything = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
24781
|
+
ContactWireSchema = external_exports.object({
|
|
24782
|
+
operationId: external_exports.string().uuid(),
|
|
24783
|
+
...sendFields,
|
|
24784
|
+
questions: external_exports.array(QuestionWireSchema).min(1).max(20).optional()
|
|
24785
|
+
}).strict().refine(sendsAnything, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
24690
24786
|
CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
24691
|
-
CONTACT_DESCRIPTION =
|
|
24787
|
+
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.
|
|
24788
|
+
|
|
24789
|
+
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.
|
|
24790
|
+
|
|
24791
|
+
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.
|
|
24792
|
+
|
|
24793
|
+
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.
|
|
24794
|
+
|
|
24795
|
+
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\`).`;
|
|
24692
24796
|
CreateGoalSchema = external_exports.object({
|
|
24693
24797
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
24694
24798
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -24722,29 +24826,20 @@ var init_dist = __esm({
|
|
|
24722
24826
|
state: external_exports.enum(["active", "done", "cancelled"]).optional(),
|
|
24723
24827
|
progress: external_exports.string().trim().min(1).max(1e4).optional(),
|
|
24724
24828
|
reviewed: external_exports.literal(true).optional(),
|
|
24725
|
-
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
24726
|
-
/** WITHDRAW YOUR OWN QUESTION (#2777, owner 2026-09-30). The question's id as every read shows it
|
|
24727
|
-
* (the conversation's `id`, eight characters, or the whole request Entry id), on THIS Goal, asked
|
|
24728
|
-
* by you and still open. It is cancelled, not answered: its cards close and nothing rings for it. */
|
|
24729
|
-
withdraw: external_exports.array(external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/)).min(1).max(10).optional()
|
|
24829
|
+
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
24730
24830
|
}).strict().refine((v) => Object.keys(v).length > 0),
|
|
24731
24831
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
24732
24832
|
operationId: external_exports.string().uuid().optional()
|
|
24733
24833
|
}).strict();
|
|
24734
|
-
UpdateGoalToolSchema = external_exports.object({
|
|
24735
|
-
goalId: external_exports.string().uuid(),
|
|
24736
|
-
revision: UpdateGoalSchema.shape.revision,
|
|
24737
|
-
changes: UpdateGoalSchema.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
|
|
24738
|
-
reason: UpdateGoalSchema.shape.reason
|
|
24739
|
-
}).strict();
|
|
24740
24834
|
changedGoal = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
24741
24835
|
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.");
|
|
24742
|
-
|
|
24836
|
+
GOAL_OUTCOME_MAX = 500;
|
|
24837
|
+
goalOutcome = external_exports.string().trim().min(1).max(GOAL_OUTCOME_MAX, `outcome_too_long: a Goal's outcome is one paragraph, at most ${GOAL_OUTCOME_MAX} characters; split the rest into child Goals (create with parentGoalId).`).describe(`The desired result, one paragraph of at most ${GOAL_OUTCOME_MAX} characters. More than that is more work: create child Goals under it (parentGoalId). There is no third description field.`);
|
|
24743
24838
|
CreateChange = external_exports.object({
|
|
24744
24839
|
kind: external_exports.literal("create"),
|
|
24745
24840
|
title: goalTitle,
|
|
24746
24841
|
outcome: goalOutcome,
|
|
24747
|
-
ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as
|
|
24842
|
+
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."),
|
|
24748
24843
|
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
24749
24844
|
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
24750
24845
|
}).strict();
|
|
@@ -24754,7 +24849,7 @@ var init_dist = __esm({
|
|
|
24754
24849
|
) }).strict();
|
|
24755
24850
|
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();
|
|
24756
24851
|
DeferChange = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
24757
|
-
"Postpone it until this instant
|
|
24852
|
+
"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."
|
|
24758
24853
|
) }).strict();
|
|
24759
24854
|
MoveChange = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
24760
24855
|
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
@@ -24765,7 +24860,7 @@ var init_dist = __esm({
|
|
|
24765
24860
|
goalId: changedGoal,
|
|
24766
24861
|
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
24767
24862
|
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
24768
|
-
reason: external_exports.string().trim().min(1).max(
|
|
24863
|
+
reason: external_exports.string().trim().min(1).max(250).optional().describe("Why, at most 250 characters, as an explanation, never as policy.")
|
|
24769
24864
|
}).strict();
|
|
24770
24865
|
read = { revision: external_exports.number().int().positive().optional() };
|
|
24771
24866
|
GoalChangeSchema = external_exports.discriminatedUnion("kind", [
|
|
@@ -24789,8 +24884,7 @@ var init_dist = __esm({
|
|
|
24789
24884
|
ManageGoalsToolSchema = external_exports.object({
|
|
24790
24885
|
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.")
|
|
24791
24886
|
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
24792
|
-
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,
|
|
24793
|
-
ClaimGoalSchema = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
24887
|
+
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 (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); 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.";
|
|
24794
24888
|
GetGoalSchema = external_exports.object({
|
|
24795
24889
|
goalId: external_exports.string().uuid(),
|
|
24796
24890
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
@@ -24801,25 +24895,29 @@ var init_dist = __esm({
|
|
|
24801
24895
|
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
24802
24896
|
diagnose: external_exports.boolean().optional()
|
|
24803
24897
|
}).strict();
|
|
24804
|
-
GET_GOAL_DESCRIPTION = "Read one Goal
|
|
24805
|
-
UPDATE_GOAL_DESCRIPTION = "Report work on a Goal you are on, at an exact revision: progress, review acknowledgement, when to wake for it, and withdrawing a question of yours. What the Goal is (its title, outcome, state, owner, parent, dependencies) changes with manage_goals. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). Stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. progress says where the work stands. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision (contact({ackEventIds}) does the same for an `update` event). dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. Returns the Goal as get_goal reads it, at its new revision.";
|
|
24806
|
-
CLAIM_GOAL_DESCRIPTION = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change it; use manage_goals (assign) when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
|
|
24898
|
+
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.";
|
|
24807
24899
|
SearchToolSchema = external_exports.object({
|
|
24808
24900
|
query: external_exports.string().trim().min(1).max(500),
|
|
24809
24901
|
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
24810
24902
|
goalId: external_exports.string().uuid().optional(),
|
|
24811
24903
|
limit: external_exports.number().int().min(1).max(20).optional()
|
|
24812
24904
|
}).strict();
|
|
24813
|
-
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
|
|
24814
|
-
|
|
24905
|
+
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 replies -- the person's answers, acknowledgements and deferrals (type answer; found by their summary, by the question or report they reply to, 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, the replies to its items, 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 (a reply carries its kind -- answered, acknowledged or deferred -- whether it is closed (a deferral is not), its summary in under ten words, its question or report, 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.";
|
|
24906
|
+
CheckActivitySchema = external_exports.object({}).strict();
|
|
24907
|
+
FEEDBACK_TEXT_MAX = 5e4;
|
|
24908
|
+
SendFeedbackSchema = external_exports.object({
|
|
24909
|
+
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.`),
|
|
24910
|
+
title: external_exports.string().trim().min(1).max(200).optional().describe("One line naming it."),
|
|
24911
|
+
kind: external_exports.enum(["bug", "idea", "other"]).default("other").describe("bug: something Paigy does wrong. idea: something it should do. other: anything else.")
|
|
24912
|
+
}).strict();
|
|
24913
|
+
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.";
|
|
24815
24914
|
AGENT_TOOLS = [
|
|
24816
|
-
{ 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(WhoIsWorkingSchema) },
|
|
24817
24915
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
24818
24916
|
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(ManageGoalsToolSchema) },
|
|
24819
|
-
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(ClaimGoalSchema) },
|
|
24820
24917
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(GetGoalSchema) },
|
|
24821
|
-
{ name: "
|
|
24822
|
-
{ name: "
|
|
24918
|
+
{ name: "search", description: SEARCH_DESCRIPTION, inputSchema: mcpInputSchema(SearchToolSchema) },
|
|
24919
|
+
{ 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) },
|
|
24920
|
+
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION, inputSchema: mcpInputSchema(SendFeedbackSchema) }
|
|
24823
24921
|
];
|
|
24824
24922
|
AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
24825
24923
|
id = external_exports.string().uuid();
|
|
@@ -24867,6 +24965,7 @@ var init_dist = __esm({
|
|
|
24867
24965
|
external_exports.object({
|
|
24868
24966
|
kind: external_exports.literal("create"),
|
|
24869
24967
|
text: external_exports.string().min(1),
|
|
24968
|
+
summary: external_exports.string().optional(),
|
|
24870
24969
|
answererId: participant,
|
|
24871
24970
|
goal: ResultRefSchema.optional(),
|
|
24872
24971
|
blocks: external_exports.array(external_exports.object({ question: ResultRefSchema }).strict()),
|
|
@@ -24917,12 +25016,12 @@ var init_dist = __esm({
|
|
|
24917
25016
|
}).strict();
|
|
24918
25017
|
BrainResultSchema = external_exports.object({
|
|
24919
25018
|
messages: external_exports.array(BrainMessageSchema),
|
|
24920
|
-
entries: external_exports.array(external_exports.object({ key, sources: external_exports.array(SourceSchema).min(1), goals: external_exports.array(ResultRefSchema) }).strict()),
|
|
25019
|
+
entries: external_exports.array(external_exports.object({ key, sources: external_exports.array(SourceSchema).min(1), goals: external_exports.array(ResultRefSchema), summary: external_exports.string().optional() }).strict()),
|
|
24921
25020
|
questions: external_exports.array(external_exports.object({ key, entryKeys: external_exports.array(key), change: QuestionChangeSchema }).strict()),
|
|
24922
25021
|
answers: external_exports.array(external_exports.object({
|
|
24923
25022
|
question: ResultRefSchema,
|
|
24924
25023
|
entryKeys: external_exports.array(key).min(1),
|
|
24925
|
-
summary: external_exports.string()
|
|
25024
|
+
summary: external_exports.string(),
|
|
24926
25025
|
selectedOptionIds: external_exports.array(external_exports.string().min(1)).optional()
|
|
24927
25026
|
}).strict()),
|
|
24928
25027
|
goals: external_exports.array(external_exports.object({ key, entryKeys: external_exports.array(key), change: BrainGoalChangeSchema }).strict()),
|
|
@@ -24958,13 +25057,133 @@ var init_dist = __esm({
|
|
|
24958
25057
|
COMPACT_RESULT_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
24959
25058
|
zodToJsonSchema(CompactResultSchema, { $refStrategy: "none" })
|
|
24960
25059
|
);
|
|
25060
|
+
str2 = external_exports.string();
|
|
25061
|
+
strs2 = external_exports.array(external_exports.string());
|
|
25062
|
+
TalkerReplySchema = external_exports.object({
|
|
25063
|
+
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
25064
|
+
* or an agent's handle; `about` names handles; `blocks` is the item a question to an agent must be
|
|
25065
|
+
* answered before ("" for none). */
|
|
25066
|
+
messages: external_exports.array(external_exports.object({ key: str2, to: str2, text: str2, about: strs2, blocks: str2 }).strict()),
|
|
25067
|
+
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
25068
|
+
then: external_exports.enum(["listen", "hold", "end"]),
|
|
25069
|
+
/** The person's replies to items (replies, owner 2026-10-07): the item's handle, the chosen option
|
|
25070
|
+
* IDs, the line handles, how they replied in under ten words (keeping any condition), and `defer`:
|
|
25071
|
+
* "" when their words settle the item, else what a reply that puts it off waits for -- "call" (the
|
|
25072
|
+
* end of this call), a question's handle (that question's answer) or an ISO time. */
|
|
25073
|
+
replies: external_exports.array(external_exports.object({ item: str2, options: strs2, lines: strs2, summary: str2, defer: str2 }).strict()),
|
|
25074
|
+
/** The line handles that tell the talker how to run this call; they last until it ends and reach no agent. */
|
|
25075
|
+
instruction: strs2,
|
|
25076
|
+
/** The line handles the filer acts on, and the only ones it reads (3e): new work, a change to existing
|
|
25077
|
+
* work, feedback on Paigy, anything said to an agent, and any rule meant to outlast the call. */
|
|
25078
|
+
file: strs2,
|
|
25079
|
+
/** Evidence to fetch for a second round: a search, an item's full text, or an agent by name. */
|
|
25080
|
+
need: external_exports.object({ kind: external_exports.enum(["search", "item", "agent", ""]), text: str2 }).strict(),
|
|
25081
|
+
/** The handle of the item to explain ("" for none). */
|
|
25082
|
+
explain: str2
|
|
25083
|
+
}).strict();
|
|
25084
|
+
TALKER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
25085
|
+
zodToJsonSchema(TalkerReplySchema, { $refStrategy: "none" })
|
|
25086
|
+
);
|
|
25087
|
+
str3 = external_exports.string();
|
|
25088
|
+
strs3 = external_exports.array(external_exports.string());
|
|
25089
|
+
FilerReplySchema = external_exports.object({
|
|
25090
|
+
/** Which Goals each new line goes on: a line's handle, Goal handles (or keys of new Goals), and what
|
|
25091
|
+
* the line says in at most ten words. */
|
|
25092
|
+
filed: external_exports.array(external_exports.object({ line: str3, goals: strs3, summary: str3 }).strict()),
|
|
25093
|
+
goals: external_exports.array(external_exports.object({
|
|
25094
|
+
op: external_exports.enum(["create", "edit", "complete", "cancel", "reopen", "assign", "defer", "move", "block", "unblock"]),
|
|
25095
|
+
key: str3,
|
|
25096
|
+
goal: str3,
|
|
25097
|
+
title: str3,
|
|
25098
|
+
outcome: str3,
|
|
25099
|
+
owner: str3,
|
|
25100
|
+
under: str3,
|
|
25101
|
+
until: str3,
|
|
25102
|
+
on: str3,
|
|
25103
|
+
gate: external_exports.enum(["start", "complete", "answer", ""]),
|
|
25104
|
+
why: str3
|
|
25105
|
+
}).strict()),
|
|
25106
|
+
questions: external_exports.array(external_exports.object({
|
|
25107
|
+
op: external_exports.enum(["create", "edit", "assign", "withdraw"]),
|
|
25108
|
+
key: str3,
|
|
25109
|
+
question: str3,
|
|
25110
|
+
text: str3,
|
|
25111
|
+
summary: str3,
|
|
25112
|
+
to: str3,
|
|
25113
|
+
goal: str3,
|
|
25114
|
+
options: external_exports.array(external_exports.object({ id: str3, label: str3 }).strict()),
|
|
25115
|
+
pick: external_exports.enum(["one", "many", "rank", "words", ""]),
|
|
25116
|
+
blocks: str3
|
|
25117
|
+
}).strict()),
|
|
25118
|
+
lessons: external_exports.array(external_exports.object({ op: external_exports.enum(["remember", "revise", "withdraw"]), lesson: str3, text: str3, scope: str3 }).strict()),
|
|
25119
|
+
/** Line handles whose words comment on Paigy itself. */
|
|
25120
|
+
feedback: strs3
|
|
25121
|
+
}).strict();
|
|
25122
|
+
FILER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
25123
|
+
zodToJsonSchema(FilerReplySchema, { $refStrategy: "none" })
|
|
25124
|
+
);
|
|
25125
|
+
ExplainerReplySchema = external_exports.object({
|
|
25126
|
+
/** The explanation, as sentences, spoken in order. */
|
|
25127
|
+
say: external_exports.array(external_exports.string()),
|
|
25128
|
+
/** Questions to an agent about gaps in what it read: the agent's handle and the question. */
|
|
25129
|
+
followUps: external_exports.array(external_exports.object({ to: external_exports.string(), text: external_exports.string() }).strict())
|
|
25130
|
+
}).strict();
|
|
25131
|
+
EXPLAINER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
25132
|
+
zodToJsonSchema(ExplainerReplySchema, { $refStrategy: "none" })
|
|
25133
|
+
);
|
|
25134
|
+
DISTILLER_DEFECTS = [
|
|
25135
|
+
"reasked",
|
|
25136
|
+
// a question put to the person again after they answered it
|
|
25137
|
+
"unsupported",
|
|
25138
|
+
// a fact stated that nothing in the input supports
|
|
25139
|
+
"unsaid",
|
|
25140
|
+
// an agent's answer arrived during the call and was never said
|
|
25141
|
+
"skipped",
|
|
25142
|
+
// an agenda item never put to the person
|
|
25143
|
+
"unsaved",
|
|
25144
|
+
// something the person answered or asked for did not save, was refused or dropped
|
|
25145
|
+
"ignored",
|
|
25146
|
+
// the person asked or said something and was never answered (the critic's ignored_a_question)
|
|
25147
|
+
"promised"
|
|
25148
|
+
// said it did or would do something, and nothing shows it done (the critic's broken_promise)
|
|
25149
|
+
];
|
|
25150
|
+
DistillerReplySchema = external_exports.object({
|
|
25151
|
+
defects: external_exports.array(external_exports.object({
|
|
25152
|
+
kind: external_exports.enum(DISTILLER_DEFECTS),
|
|
25153
|
+
/** The handles of the lines it shows in. */
|
|
25154
|
+
lines: external_exports.array(external_exports.string()),
|
|
25155
|
+
/** The handle of the record it concerns, or "". */
|
|
25156
|
+
about: external_exports.string(),
|
|
25157
|
+
/** One plain sentence, in words, never handles: it is what the feedback row keeps. */
|
|
25158
|
+
why: external_exports.string()
|
|
25159
|
+
}).strict())
|
|
25160
|
+
}).strict();
|
|
25161
|
+
DISTILLER_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
25162
|
+
zodToJsonSchema(DistillerReplySchema, { $refStrategy: "none" })
|
|
25163
|
+
);
|
|
25164
|
+
TIDY_AUDIENCES = ["talker", "filer", "agents"];
|
|
25165
|
+
TidyReplySchema = external_exports.object({
|
|
25166
|
+
lessons: external_exports.array(external_exports.object({
|
|
25167
|
+
lesson: external_exports.string(),
|
|
25168
|
+
op: external_exports.enum(["keep", "revise", "withdraw"]),
|
|
25169
|
+
text: external_exports.string(),
|
|
25170
|
+
for: external_exports.enum([...TIDY_AUDIENCES, ""]),
|
|
25171
|
+
into: external_exports.string()
|
|
25172
|
+
}).strict())
|
|
25173
|
+
}).strict();
|
|
25174
|
+
TIDY_REPLY_JSON_SCHEMA = (({ $schema: _, ...rest }) => rest)(
|
|
25175
|
+
zodToJsonSchema(TidyReplySchema, { $refStrategy: "none" })
|
|
25176
|
+
);
|
|
24961
25177
|
LIVE_MS = 3 * 6e4;
|
|
24962
25178
|
WORKING_MS = 60 * 6e4;
|
|
24963
25179
|
ContextSchema = external_exports.object({
|
|
24964
25180
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
24965
25181
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
24966
25182
|
"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."
|
|
24967
|
-
)
|
|
25183
|
+
),
|
|
25184
|
+
/** THE ASK'S UNITS (3c): its context as titled units, in order. The app lists the titles and opens
|
|
25185
|
+
* a body on a tap. Absent on an ask sent without units, which renders as before. */
|
|
25186
|
+
units: external_exports.array(external_exports.object({ title: external_exports.string(), body: external_exports.string() })).optional()
|
|
24968
25187
|
});
|
|
24969
25188
|
ParticipantSchema = external_exports.object({
|
|
24970
25189
|
kind: external_exports.enum(["human", "agent"]),
|
|
@@ -25039,7 +25258,7 @@ var init_dist = __esm({
|
|
|
25039
25258
|
* ABSENT on the E2EE path, where the sealed `envelope` below carries it. The
|
|
25040
25259
|
* superRefine at the bottom enforces exactly one of the two. */
|
|
25041
25260
|
context: ContextSchema.optional(),
|
|
25042
|
-
options: external_exports.array(
|
|
25261
|
+
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(
|
|
25043
25262
|
"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)."
|
|
25044
25263
|
),
|
|
25045
25264
|
points: external_exports.array(external_exports.string().min(1)).optional().describe(
|
|
@@ -25637,7 +25856,7 @@ var init_dist = __esm({
|
|
|
25637
25856
|
* desktop app while open. Null = never seen; stale = offline. */
|
|
25638
25857
|
lastSeenAt: external_exports.string().datetime().nullable().optional(),
|
|
25639
25858
|
/** WORKING, NOT JUST CONNECTED (owner, 2026-09-30): the last time the agent itself acted on one of
|
|
25640
|
-
* its Goals —
|
|
25859
|
+
* its Goals — wrote on one or recorded an operation (`tokens.last_worked_at`). Within
|
|
25641
25860
|
* `WORKING_MS` it is working; otherwise it is connected but idle. Null = not seen working yet. */
|
|
25642
25861
|
lastWorkedAt: external_exports.string().datetime().nullable().optional(),
|
|
25643
25862
|
/** The oldest of its Goals that is `ready` for it — work handed to it that nobody has started.
|
|
@@ -25800,8 +26019,8 @@ var init_dist = __esm({
|
|
|
25800
26019
|
repo: external_exports.string().nullable().optional(),
|
|
25801
26020
|
createdAt: external_exports.string(),
|
|
25802
26021
|
updatedAt: external_exports.string().nullable().default(null),
|
|
25803
|
-
/** When its owner last SAID something about it (`
|
|
25804
|
-
*
|
|
26022
|
+
/** When its owner last SAID something about it (the newest `progress` Entry: a contact update kept
|
|
26023
|
+
* as progress). `updatedAt` moves for reasons nobody chose — a
|
|
25805
26024
|
* state recomputed, a review flag — so it cannot tell work in hand from work gone quiet. */
|
|
25806
26025
|
lastProgressAt: external_exports.string().nullable().optional(),
|
|
25807
26026
|
/** THE GOAL'S NEWEST WORD, FROM EITHER SIDE (owner, 2026-09-27): the newest Entry on it, of any
|
|
@@ -25835,7 +26054,7 @@ var init_dist = __esm({
|
|
|
25835
26054
|
*
|
|
25836
26055
|
* IT IS THE PAYLOAD'S OWN HASH, NEVER A STAMP ON THE WORK. Nothing here reasons about which
|
|
25837
26056
|
* writes change which field — the comparison is over the bytes the phone is holding, so a fact
|
|
25838
|
-
* the row shows that no `updated_at` moves for (
|
|
26057
|
+
* the row shows that no `updated_at` moves for (`active` lapsing, a dependency's state, a
|
|
25839
26058
|
* sibling appearing in `childGoalIds`) cannot go unnoticed. Optional because a hand-built
|
|
25840
26059
|
* queue (a fixture, the demo) spells none, and a row with no rev is simply always re-sent. */
|
|
25841
26060
|
rev: external_exports.string().optional()
|
|
@@ -25959,7 +26178,7 @@ var init_dist = __esm({
|
|
|
25959
26178
|
/** The agent's token id: the row's `recipient`. */
|
|
25960
26179
|
agent: external_exports.string().uuid(),
|
|
25961
26180
|
decision: external_exports.enum(["stood_back", "took_over"]),
|
|
25962
|
-
/** The work it was about: the Goal
|
|
26181
|
+
/** The work it was about: the Goal waiting on that agent next (`claimable` on its `contact({})` read). */
|
|
25963
26182
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
25964
26183
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
25965
26184
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
@@ -26152,14 +26371,13 @@ var init_dist = __esm({
|
|
|
26152
26371
|
owner: external_exports.string(),
|
|
26153
26372
|
state: external_exports.string(),
|
|
26154
26373
|
questions: external_exports.array(external_exports.object({ id: external_exports.string().uuid(), state: external_exports.string(), title: external_exports.string() })),
|
|
26155
|
-
/** `words` is always what they SAID, verbatim — the record, never replaced. `
|
|
26156
|
-
*
|
|
26157
|
-
*
|
|
26158
|
-
*
|
|
26159
|
-
* anything that is not an answer. */
|
|
26374
|
+
/** `words` is always what they SAID, verbatim — the record, never replaced. `summary` is what
|
|
26375
|
+
* the line says in ten words (owner, 2026-10-07): the filer's, or the talker's for the answer it
|
|
26376
|
+
* gave, so the row scans like a chosen option and their own words stay under it. Absent when
|
|
26377
|
+
* neither wrote one. */
|
|
26160
26378
|
/** `about` is the request the line answered (its question), null for words that answered none —
|
|
26161
26379
|
* the key the screen groups on, so one question is one row however many times it was answered. */
|
|
26162
|
-
lines: external_exports.array(external_exports.object({ entryId: external_exports.string().uuid(), words: external_exports.string(),
|
|
26380
|
+
lines: external_exports.array(external_exports.object({ entryId: external_exports.string().uuid(), words: external_exports.string(), summary: external_exports.string().optional(), about: external_exports.string().nullable().optional() }))
|
|
26163
26381
|
})),
|
|
26164
26382
|
unfiled: external_exports.array(external_exports.object({ lineId: external_exports.string().uuid(), words: external_exports.string(), atMs: external_exports.number() })),
|
|
26165
26383
|
more: external_exports.object({ lines: external_exports.number(), entries: external_exports.number(), topics: external_exports.number() })
|
|
@@ -26198,8 +26416,9 @@ var init_dist = __esm({
|
|
|
26198
26416
|
tokenOverride = null;
|
|
26199
26417
|
authToken = (explicit) => explicit ?? tokenOverride ?? readToken();
|
|
26200
26418
|
AWAIT_WINDOW_MS = 45e3;
|
|
26201
|
-
NOT_SENT =
|
|
26202
|
-
|
|
26419
|
+
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.`;
|
|
26420
|
+
APPLIED = "Applied; nothing was sent to the person.";
|
|
26421
|
+
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.";
|
|
26203
26422
|
HEARTBEAT_MS = 25e3;
|
|
26204
26423
|
RETRY_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
26205
26424
|
JOIN = { config: { broadcast: { self: false } } };
|
|
@@ -27102,14 +27321,14 @@ var require_regex = __commonJS({
|
|
|
27102
27321
|
var TEST_KANJI = new RegExp("^" + kanji + "$");
|
|
27103
27322
|
var TEST_NUMERIC = new RegExp("^" + numeric + "$");
|
|
27104
27323
|
var TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$");
|
|
27105
|
-
exports.testKanji = function testKanji(
|
|
27106
|
-
return TEST_KANJI.test(
|
|
27324
|
+
exports.testKanji = function testKanji(str5) {
|
|
27325
|
+
return TEST_KANJI.test(str5);
|
|
27107
27326
|
};
|
|
27108
|
-
exports.testNumeric = function testNumeric(
|
|
27109
|
-
return TEST_NUMERIC.test(
|
|
27327
|
+
exports.testNumeric = function testNumeric(str5) {
|
|
27328
|
+
return TEST_NUMERIC.test(str5);
|
|
27110
27329
|
};
|
|
27111
|
-
exports.testAlphanumeric = function testAlphanumeric(
|
|
27112
|
-
return TEST_ALPHANUMERIC.test(
|
|
27330
|
+
exports.testAlphanumeric = function testAlphanumeric(str5) {
|
|
27331
|
+
return TEST_ALPHANUMERIC.test(str5);
|
|
27113
27332
|
};
|
|
27114
27333
|
}
|
|
27115
27334
|
});
|
|
@@ -27611,13 +27830,13 @@ var require_segments = __commonJS({
|
|
|
27611
27830
|
var Regex = require_regex();
|
|
27612
27831
|
var Utils = require_utils2();
|
|
27613
27832
|
var dijkstra = require_dijkstra();
|
|
27614
|
-
function getStringByteLength(
|
|
27615
|
-
return unescape(encodeURIComponent(
|
|
27833
|
+
function getStringByteLength(str5) {
|
|
27834
|
+
return unescape(encodeURIComponent(str5)).length;
|
|
27616
27835
|
}
|
|
27617
|
-
function getSegments(regex, mode,
|
|
27836
|
+
function getSegments(regex, mode, str5) {
|
|
27618
27837
|
const segments = [];
|
|
27619
27838
|
let result;
|
|
27620
|
-
while ((result = regex.exec(
|
|
27839
|
+
while ((result = regex.exec(str5)) !== null) {
|
|
27621
27840
|
segments.push({
|
|
27622
27841
|
data: result[0],
|
|
27623
27842
|
index: result.index,
|
|
@@ -30451,13 +30670,13 @@ var require_svg_tag = __commonJS({
|
|
|
30451
30670
|
var Utils = require_utils3();
|
|
30452
30671
|
function getColorAttrib(color, attrib) {
|
|
30453
30672
|
const alpha = color.a / 255;
|
|
30454
|
-
const
|
|
30455
|
-
return alpha < 1 ?
|
|
30673
|
+
const str5 = attrib + '="' + color.hex + '"';
|
|
30674
|
+
return alpha < 1 ? str5 + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str5;
|
|
30456
30675
|
}
|
|
30457
30676
|
function svgCmd(cmd, x, y) {
|
|
30458
|
-
let
|
|
30459
|
-
if (typeof y !== "undefined")
|
|
30460
|
-
return
|
|
30677
|
+
let str5 = cmd + x;
|
|
30678
|
+
if (typeof y !== "undefined") str5 += " " + y;
|
|
30679
|
+
return str5;
|
|
30461
30680
|
}
|
|
30462
30681
|
function qrToPath(data, size, margin) {
|
|
30463
30682
|
let path = "";
|
|
@@ -30989,9 +31208,9 @@ async function available(deps = {}) {
|
|
|
30989
31208
|
});
|
|
30990
31209
|
return [ollama, ...harnesses];
|
|
30991
31210
|
}
|
|
30992
|
-
function refusal(options,
|
|
31211
|
+
function refusal(options, asked) {
|
|
30993
31212
|
const lines2 = [
|
|
30994
|
-
|
|
31213
|
+
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.",
|
|
30995
31214
|
"",
|
|
30996
31215
|
"Triage runs the model where your queue already lives (#1106). Your options:"
|
|
30997
31216
|
];
|
|
@@ -31002,10 +31221,10 @@ function refusal(options, asked2) {
|
|
|
31002
31221
|
lines2.push("", "Then re-run: paigy-harness triage [--via ollama|claude|codex|agy]");
|
|
31003
31222
|
return lines2.join("\n");
|
|
31004
31223
|
}
|
|
31005
|
-
async function judgeFor(
|
|
31224
|
+
async function judgeFor(asked, deps = {}) {
|
|
31006
31225
|
const options = await available(deps);
|
|
31007
|
-
const chosen =
|
|
31008
|
-
if (!chosen?.ready) return { error: refusal(options,
|
|
31226
|
+
const chosen = asked ? options.find((o) => o.provider === asked) : options.find((o) => o.ready);
|
|
31227
|
+
if (!chosen?.ready) return { error: refusal(options, asked) };
|
|
31009
31228
|
if (chosen.provider === "ollama") {
|
|
31010
31229
|
const model = chosen.model;
|
|
31011
31230
|
return {
|
|
@@ -31026,9 +31245,9 @@ async function judgeFor(asked2, deps = {}) {
|
|
|
31026
31245
|
};
|
|
31027
31246
|
}
|
|
31028
31247
|
const runner = RUNNERS[chosen.provider];
|
|
31029
|
-
if (!runner) return { error: refusal(options,
|
|
31248
|
+
if (!runner) return { error: refusal(options, asked) };
|
|
31030
31249
|
const bin = which(runner.cli);
|
|
31031
|
-
if (!bin) return { error: refusal(options,
|
|
31250
|
+
if (!bin) return { error: refusal(options, asked) };
|
|
31032
31251
|
return {
|
|
31033
31252
|
provider: chosen.provider,
|
|
31034
31253
|
model: null,
|
|
@@ -31462,7 +31681,7 @@ function onEnter(input, onLine) {
|
|
|
31462
31681
|
// src/cli.ts
|
|
31463
31682
|
init_dist();
|
|
31464
31683
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
31465
|
-
import { randomUUID as
|
|
31684
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
31466
31685
|
import { hostname } from "os";
|
|
31467
31686
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
31468
31687
|
import { execFile as execFile2, execSync } from "child_process";
|
|
@@ -31471,7 +31690,7 @@ import { join as join11 } from "path";
|
|
|
31471
31690
|
|
|
31472
31691
|
// src/run.ts
|
|
31473
31692
|
init_dist();
|
|
31474
|
-
import { randomUUID as
|
|
31693
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
31475
31694
|
|
|
31476
31695
|
// src/harness/session.ts
|
|
31477
31696
|
init_dist();
|
|
@@ -31759,7 +31978,7 @@ init_catalog();
|
|
|
31759
31978
|
import { mkdirSync as mkdirSync2, readdirSync, renameSync, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
31760
31979
|
import { join as join4 } from "path";
|
|
31761
31980
|
import { homedir as homedir3 } from "os";
|
|
31762
|
-
import { randomUUID as
|
|
31981
|
+
import { randomUUID as randomUUID3 } from "crypto";
|
|
31763
31982
|
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"`;
|
|
31764
31983
|
var missing = (error) => error.code === "ENOENT";
|
|
31765
31984
|
function openInbox(dir) {
|
|
@@ -31819,7 +32038,7 @@ function inboxFor(root = INBOX_ROOT) {
|
|
|
31819
32038
|
} catch (error) {
|
|
31820
32039
|
if (!missing(error)) throw error;
|
|
31821
32040
|
}
|
|
31822
|
-
return openInbox(join4(root, `${process.pid}-${
|
|
32041
|
+
return openInbox(join4(root, `${process.pid}-${randomUUID3().slice(0, 8)}`));
|
|
31823
32042
|
}
|
|
31824
32043
|
|
|
31825
32044
|
// src/harness/session.ts
|
|
@@ -33252,23 +33471,37 @@ var zodToJsonSchema2 = (schema, options) => {
|
|
|
33252
33471
|
// ../../packages/schema/dist/index.js
|
|
33253
33472
|
init_zod();
|
|
33254
33473
|
init_zod();
|
|
33474
|
+
init_zod();
|
|
33475
|
+
init_zod();
|
|
33476
|
+
init_zod();
|
|
33477
|
+
init_zod();
|
|
33255
33478
|
var OPTIONS_MIN2 = 2;
|
|
33256
33479
|
var OPTIONS_MAX2 = 6;
|
|
33480
|
+
var OPTION_LABEL_MAX2 = 50;
|
|
33481
|
+
var OPTION_HINT_MAX2 = 200;
|
|
33257
33482
|
var OptionSchema2 = external_exports.object({
|
|
33258
33483
|
id: external_exports.string(),
|
|
33259
33484
|
label: external_exports.string(),
|
|
33260
|
-
hint: external_exports.string().max(500).describe(
|
|
33485
|
+
hint: external_exports.string().max(500).describe(`Optional: what choosing it does, at most ${OPTION_HINT_MAX2} characters (e.g. 'Reruns test suite', 'Merges to main').`).optional(),
|
|
33261
33486
|
// .describe() flows into the MCP contact JSON schema (zodToJsonSchema), so
|
|
33262
33487
|
// the constraints below are what an agent reads when deciding to use these.
|
|
33263
33488
|
html: external_exports.string().max(16384).describe(
|
|
33264
|
-
"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
|
|
33489
|
+
"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."
|
|
33265
33490
|
).optional(),
|
|
33266
33491
|
image: external_exports.string().url().describe(
|
|
33267
|
-
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use
|
|
33492
|
+
"Optional image URL rendered as the option's preview (plain image, not sandboxed). For agent-generated HTML/CSS mockups, use the HTML preview instead."
|
|
33268
33493
|
).optional()
|
|
33269
33494
|
});
|
|
33270
|
-
var OptionInputSchema2 =
|
|
33271
|
-
|
|
33495
|
+
var OptionInputSchema2 = external_exports.object({
|
|
33496
|
+
id: external_exports.string().trim().min(1).max(64).regex(/^[A-Za-z0-9_.:-]+$/).optional().describe(
|
|
33497
|
+
`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.`
|
|
33498
|
+
),
|
|
33499
|
+
// SHORT CHOICES (owner, 2026-10-07: "options label should be maybe max 50 characters and the hint 200"):
|
|
33500
|
+
// a label is one choice the person reads, or hears on a call; a hint says its consequence in a line.
|
|
33501
|
+
label: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX2, `option_label_too_long: an option's label is at most ${OPTION_LABEL_MAX2} characters; say the choice, and put its consequence in the hint.`).describe(`The choice, at most ${OPTION_LABEL_MAX2} characters, standing on its own.`),
|
|
33502
|
+
hint: external_exports.string().max(OPTION_HINT_MAX2, `option_hint_too_long: an option's hint is at most ${OPTION_HINT_MAX2} characters.`).describe(`Optional: what choosing it does, at most ${OPTION_HINT_MAX2} characters (e.g. 'Reruns test suite', 'Merges to main').`).optional(),
|
|
33503
|
+
htmlPreview: OptionSchema2.shape.html,
|
|
33504
|
+
imgUrl: OptionSchema2.shape.image
|
|
33272
33505
|
}).strict();
|
|
33273
33506
|
var NIGHT2 = { from: 23, to: 7 };
|
|
33274
33507
|
function draft20202(node) {
|
|
@@ -33300,41 +33533,162 @@ function mcpInputSchema2(s) {
|
|
|
33300
33533
|
delete schema.$schema;
|
|
33301
33534
|
return draft20202(schema);
|
|
33302
33535
|
}
|
|
33303
|
-
var
|
|
33304
|
-
|
|
33305
|
-
|
|
33306
|
-
|
|
33307
|
-
|
|
33308
|
-
|
|
33536
|
+
var ASK_MAX2 = 250;
|
|
33537
|
+
var UNITS_MAX2 = 12;
|
|
33538
|
+
var UNIT_TITLE_MAX2 = 50;
|
|
33539
|
+
var UNIT_BODY_MAX2 = 200;
|
|
33540
|
+
var UnitInputSchema2 = external_exports.object({
|
|
33541
|
+
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.`),
|
|
33542
|
+
body: external_exports.string().trim().min(1).describe(`The unit itself, at most ${UNIT_BODY_MAX2} characters.`)
|
|
33543
|
+
}).strict();
|
|
33544
|
+
function capRefusals2(text, units22, field) {
|
|
33545
|
+
const out = [];
|
|
33546
|
+
const name = field === "text" ? "answer" : field;
|
|
33547
|
+
if (text.length > ASK_MAX2) out.push({
|
|
33548
|
+
refusal: "ask_too_long",
|
|
33549
|
+
length: text.length,
|
|
33550
|
+
cap: ASK_MAX2,
|
|
33551
|
+
path: field === "text" ? ["answer", "text"] : [field],
|
|
33552
|
+
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.`
|
|
33553
|
+
});
|
|
33554
|
+
const all = units22 ?? [];
|
|
33555
|
+
if (all.length > UNITS_MAX2) out.push({
|
|
33556
|
+
refusal: "too_many_units",
|
|
33557
|
+
length: all.length,
|
|
33558
|
+
cap: UNITS_MAX2,
|
|
33559
|
+
path: ["units"],
|
|
33560
|
+
message: `too_many_units: ${all.length} units; the cap is ${UNITS_MAX2}. Keep only the context this ${name} needs.`
|
|
33561
|
+
});
|
|
33562
|
+
all.forEach((unit, index) => {
|
|
33563
|
+
if (unit.title.length > UNIT_TITLE_MAX2) out.push({
|
|
33564
|
+
refusal: "unit_title_too_long",
|
|
33565
|
+
index,
|
|
33566
|
+
length: unit.title.length,
|
|
33567
|
+
cap: UNIT_TITLE_MAX2,
|
|
33568
|
+
path: ["units", index, "title"],
|
|
33569
|
+
message: `unit_title_too_long: units[${index}]'s title is ${unit.title.length} characters; the cap is ${UNIT_TITLE_MAX2}.`
|
|
33570
|
+
});
|
|
33571
|
+
if (unit.body.length > UNIT_BODY_MAX2) out.push({
|
|
33572
|
+
refusal: "unit_body_too_long",
|
|
33573
|
+
index,
|
|
33574
|
+
length: unit.body.length,
|
|
33575
|
+
cap: UNIT_BODY_MAX2,
|
|
33576
|
+
path: ["units", index, "body"],
|
|
33577
|
+
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.`
|
|
33578
|
+
});
|
|
33579
|
+
});
|
|
33580
|
+
return out;
|
|
33581
|
+
}
|
|
33582
|
+
function refuseOverCaps2(text, units22, field, ctx) {
|
|
33583
|
+
for (const { path, message, ...params } of capRefusals2(text, units22, field)) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message, params });
|
|
33584
|
+
}
|
|
33585
|
+
var questionHandle2 = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
33586
|
+
var NodeRef2 = external_exports.object({
|
|
33587
|
+
type: external_exports.enum(["goal", "question"]),
|
|
33588
|
+
id: external_exports.string().uuid()
|
|
33589
|
+
}).strict().describe("A Goal or a Question, by its id.");
|
|
33590
|
+
var BlockedAction2 = external_exports.enum(["start", "complete", "answer"]).describe("What waits: starting or completing a Goal, or answering a Question.");
|
|
33591
|
+
var reason2 = external_exports.string().trim().min(1).max(500).describe("Why, as an explanation, never as policy.");
|
|
33592
|
+
var actionFits2 = (b) => b.blocked.type === "goal" === (b.action !== "answer");
|
|
33593
|
+
var ACTION_FITS2 = "a goal is blocked from start or complete; a question from answer";
|
|
33594
|
+
var userExplicitlyRequested2 = external_exports.enum(["any", "call"]).optional().describe(
|
|
33595
|
+
`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.`
|
|
33596
|
+
);
|
|
33597
|
+
var units2 = external_exports.array(UnitInputSchema2).optional().describe(
|
|
33598
|
+
`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.`
|
|
33599
|
+
);
|
|
33600
|
+
var UpdateInputSchema2 = external_exports.object({
|
|
33601
|
+
message: external_exports.string().trim().min(1).describe(`The one point, at most ${ASK_MAX2} characters; the context goes in units.`),
|
|
33602
|
+
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."),
|
|
33603
|
+
units: units2,
|
|
33604
|
+
userExplicitlyRequested: userExplicitlyRequested2
|
|
33605
|
+
}).strict().superRefine((u, ctx) => refuseOverCaps2(u.message, u.units, "message", ctx));
|
|
33606
|
+
var questionFields2 = {
|
|
33607
|
+
question: external_exports.string().trim().min(1).describe(
|
|
33608
|
+
`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.`
|
|
33309
33609
|
),
|
|
33310
|
-
|
|
33610
|
+
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."),
|
|
33611
|
+
units: units2,
|
|
33612
|
+
options: external_exports.array(OptionInputSchema2).min(1).max(6).optional().describe("The choices, when you have them. Each label stands on its own, at most 50 characters; a hint, at most 200."),
|
|
33311
33613
|
// HOW THE OPTIONS ARE ANSWERED, SAID BY THE AGENT (owner, 2026-10-02: "one and many makes sense";
|
|
33312
|
-
// brain_prompts.md §1: structured agent questions need no model).
|
|
33313
|
-
|
|
33314
|
-
|
|
33315
|
-
select: external_exports.enum(["one", "many"]).optional().describe(
|
|
33316
|
-
'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.'
|
|
33614
|
+
// brain_prompts.md §1: structured agent questions need no model). The app draws all three.
|
|
33615
|
+
pickMode: external_exports.enum(["one", "many", "rank"]).optional().describe(
|
|
33616
|
+
'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.'
|
|
33317
33617
|
),
|
|
33318
|
-
|
|
33319
|
-
|
|
33320
|
-
)
|
|
33321
|
-
|
|
33322
|
-
|
|
33323
|
-
|
|
33324
|
-
|
|
33325
|
-
|
|
33326
|
-
|
|
33327
|
-
|
|
33328
|
-
|
|
33329
|
-
|
|
33618
|
+
// WHAT THE QUESTION HOLDS UP (brain_prompts.md §2.1): replaces `waiting: 'hard'`. A question that
|
|
33619
|
+
// blocks work asks for a call (the person's settings and ring cooldowns still decide).
|
|
33620
|
+
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(
|
|
33621
|
+
"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."
|
|
33622
|
+
),
|
|
33623
|
+
userExplicitlyRequested: userExplicitlyRequested2
|
|
33624
|
+
};
|
|
33625
|
+
var refineQuestion2 = (q, ctx) => {
|
|
33626
|
+
refuseOverCaps2(q.question, q.units, "question", ctx);
|
|
33627
|
+
if (q.pickMode && !q.options) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["pickMode"], message: "pickMode comes only with options" });
|
|
33628
|
+
const ids = (q.options ?? []).map((o) => o.id);
|
|
33629
|
+
if (ids.some((id22) => id22) && (ids.some((id22) => !id22) || new Set(ids).size !== ids.length)) {
|
|
33630
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["options"], message: "give every option a distinct id, or none" });
|
|
33631
|
+
}
|
|
33632
|
+
};
|
|
33633
|
+
var QuestionInputSchema2 = external_exports.object({
|
|
33634
|
+
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."),
|
|
33635
|
+
...questionFields2
|
|
33636
|
+
}).strict().superRefine(refineQuestion2);
|
|
33637
|
+
var QuestionWireSchema2 = external_exports.object({ questionId: external_exports.string().uuid(), ...questionFields2 }).strict().superRefine(refineQuestion2);
|
|
33638
|
+
var AnswerInputSchema2 = external_exports.object({
|
|
33639
|
+
questionId: questionHandle2.describe("The Question you answer: its id as the event or the conversation shows it (8 characters or whole)."),
|
|
33640
|
+
answer: external_exports.object({
|
|
33641
|
+
text: external_exports.string().trim().min(1).describe(`Your answer in your own words, at most ${ASK_MAX2} characters; the context goes in units.`),
|
|
33642
|
+
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).")
|
|
33643
|
+
}).strict(),
|
|
33644
|
+
units: units2
|
|
33645
|
+
}).strict().superRefine((a, ctx) => refuseOverCaps2(a.answer.text, a.units, "text", ctx));
|
|
33646
|
+
var QuestionDependencySchema2 = external_exports.object({
|
|
33647
|
+
questionId: questionHandle2.describe("A Question you asked."),
|
|
33648
|
+
change: external_exports.enum(["add", "remove"]),
|
|
33649
|
+
blocked: NodeRef2,
|
|
33650
|
+
action: BlockedAction2,
|
|
33651
|
+
reason: reason2.optional()
|
|
33652
|
+
}).strict().refine(actionFits2, ACTION_FITS2);
|
|
33653
|
+
var sendFields2 = {
|
|
33654
|
+
updates: external_exports.array(UpdateInputSchema2).min(1).max(20).optional().describe(
|
|
33655
|
+
"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."
|
|
33330
33656
|
),
|
|
33657
|
+
answers: external_exports.array(AnswerInputSchema2).min(1).max(20).optional().describe("Answers to Questions addressed to you."),
|
|
33658
|
+
withdrawQuestionIds: external_exports.array(questionHandle2).min(1).max(10).optional().describe(
|
|
33659
|
+
"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."
|
|
33660
|
+
),
|
|
33661
|
+
questionDependencies: external_exports.array(QuestionDependencySchema2).min(1).max(20).optional().describe(
|
|
33662
|
+
"Add or remove what a Question you asked holds up, after asking it."
|
|
33663
|
+
)
|
|
33664
|
+
};
|
|
33665
|
+
var ContactSchema2 = external_exports.object({
|
|
33666
|
+
...sendFields2,
|
|
33667
|
+
questions: external_exports.array(QuestionInputSchema2).min(1).max(20).optional().describe("Questions for the person, one per object."),
|
|
33668
|
+
/** RECEIVING (2I, I2; brain_prompts.md §2.2): the events this agent handled. */
|
|
33331
33669
|
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
33332
|
-
"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 (
|
|
33670
|
+
"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."
|
|
33671
|
+
),
|
|
33672
|
+
wait: external_exports.boolean().optional().describe(
|
|
33673
|
+
"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`."
|
|
33333
33674
|
)
|
|
33334
33675
|
}).strict();
|
|
33335
|
-
var
|
|
33676
|
+
var sendsAnything2 = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
33677
|
+
var ContactWireSchema2 = external_exports.object({
|
|
33678
|
+
operationId: external_exports.string().uuid(),
|
|
33679
|
+
...sendFields2,
|
|
33680
|
+
questions: external_exports.array(QuestionWireSchema2).min(1).max(20).optional()
|
|
33681
|
+
}).strict().refine(sendsAnything2, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
33336
33682
|
var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
|
|
33337
|
-
var CONTACT_DESCRIPTION2 =
|
|
33683
|
+
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.
|
|
33684
|
+
|
|
33685
|
+
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.
|
|
33686
|
+
|
|
33687
|
+
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.
|
|
33688
|
+
|
|
33689
|
+
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.
|
|
33690
|
+
|
|
33691
|
+
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\`).`;
|
|
33338
33692
|
var CreateGoalSchema2 = external_exports.object({
|
|
33339
33693
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
33340
33694
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -33368,29 +33722,20 @@ var UpdateGoalSchema2 = external_exports.object({
|
|
|
33368
33722
|
state: external_exports.enum(["active", "done", "cancelled"]).optional(),
|
|
33369
33723
|
progress: external_exports.string().trim().min(1).max(1e4).optional(),
|
|
33370
33724
|
reviewed: external_exports.literal(true).optional(),
|
|
33371
|
-
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
33372
|
-
/** WITHDRAW YOUR OWN QUESTION (#2777, owner 2026-09-30). The question's id as every read shows it
|
|
33373
|
-
* (the conversation's `id`, eight characters, or the whole request Entry id), on THIS Goal, asked
|
|
33374
|
-
* by you and still open. It is cancelled, not answered: its cards close and nothing rings for it. */
|
|
33375
|
-
withdraw: external_exports.array(external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/)).min(1).max(10).optional()
|
|
33725
|
+
dueAt: external_exports.string().datetime({ offset: true }).nullable().optional()
|
|
33376
33726
|
}).strict().refine((v) => Object.keys(v).length > 0),
|
|
33377
33727
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
33378
33728
|
operationId: external_exports.string().uuid().optional()
|
|
33379
33729
|
}).strict();
|
|
33380
|
-
var UpdateGoalToolSchema2 = external_exports.object({
|
|
33381
|
-
goalId: external_exports.string().uuid(),
|
|
33382
|
-
revision: UpdateGoalSchema2.shape.revision,
|
|
33383
|
-
changes: UpdateGoalSchema2.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
|
|
33384
|
-
reason: UpdateGoalSchema2.shape.reason
|
|
33385
|
-
}).strict();
|
|
33386
33730
|
var changedGoal2 = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
33387
33731
|
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.");
|
|
33388
|
-
var
|
|
33732
|
+
var GOAL_OUTCOME_MAX2 = 500;
|
|
33733
|
+
var goalOutcome2 = external_exports.string().trim().min(1).max(GOAL_OUTCOME_MAX2, `outcome_too_long: a Goal's outcome is one paragraph, at most ${GOAL_OUTCOME_MAX2} characters; split the rest into child Goals (create with parentGoalId).`).describe(`The desired result, one paragraph of at most ${GOAL_OUTCOME_MAX2} characters. More than that is more work: create child Goals under it (parentGoalId). There is no third description field.`);
|
|
33389
33734
|
var CreateChange2 = external_exports.object({
|
|
33390
33735
|
kind: external_exports.literal("create"),
|
|
33391
33736
|
title: goalTitle2,
|
|
33392
33737
|
outcome: goalOutcome2,
|
|
33393
|
-
ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as
|
|
33738
|
+
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."),
|
|
33394
33739
|
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
33395
33740
|
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
33396
33741
|
}).strict();
|
|
@@ -33400,7 +33745,7 @@ var StateChange2 = external_exports.object({ kind: external_exports.literal("sta
|
|
|
33400
33745
|
) }).strict();
|
|
33401
33746
|
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();
|
|
33402
33747
|
var DeferChange2 = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal2, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
33403
|
-
"Postpone it until this instant
|
|
33748
|
+
"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."
|
|
33404
33749
|
) }).strict();
|
|
33405
33750
|
var MoveChange2 = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal2, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
33406
33751
|
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
@@ -33411,7 +33756,7 @@ var DependencyChange2 = external_exports.object({
|
|
|
33411
33756
|
goalId: changedGoal2,
|
|
33412
33757
|
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
33413
33758
|
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
33414
|
-
reason: external_exports.string().trim().min(1).max(
|
|
33759
|
+
reason: external_exports.string().trim().min(1).max(250).optional().describe("Why, at most 250 characters, as an explanation, never as policy.")
|
|
33415
33760
|
}).strict();
|
|
33416
33761
|
var read2 = { revision: external_exports.number().int().positive().optional() };
|
|
33417
33762
|
var GoalChangeSchema2 = external_exports.discriminatedUnion("kind", [
|
|
@@ -33435,8 +33780,7 @@ var ManageGoalsSchema2 = external_exports.object({
|
|
|
33435
33780
|
var ManageGoalsToolSchema2 = external_exports.object({
|
|
33436
33781
|
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.")
|
|
33437
33782
|
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
33438
|
-
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,
|
|
33439
|
-
var ClaimGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
33783
|
+
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 (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); 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.";
|
|
33440
33784
|
var GetGoalSchema2 = external_exports.object({
|
|
33441
33785
|
goalId: external_exports.string().uuid(),
|
|
33442
33786
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
@@ -33447,25 +33791,29 @@ var GetGoalSchema2 = external_exports.object({
|
|
|
33447
33791
|
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
33448
33792
|
diagnose: external_exports.boolean().optional()
|
|
33449
33793
|
}).strict();
|
|
33450
|
-
var GET_GOAL_DESCRIPTION2 = "Read one Goal
|
|
33451
|
-
var UPDATE_GOAL_DESCRIPTION2 = "Report work on a Goal you are on, at an exact revision: progress, review acknowledgement, when to wake for it, and withdrawing a question of yours. What the Goal is (its title, outcome, state, owner, parent, dependencies) changes with manage_goals. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). Stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. progress says where the work stands. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision (contact({ackEventIds}) does the same for an `update` event). dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. Returns the Goal as get_goal reads it, at its new revision.";
|
|
33452
|
-
var CLAIM_GOAL_DESCRIPTION2 = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change it; use manage_goals (assign) when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
|
|
33794
|
+
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.";
|
|
33453
33795
|
var SearchToolSchema2 = external_exports.object({
|
|
33454
33796
|
query: external_exports.string().trim().min(1).max(500),
|
|
33455
33797
|
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
33456
33798
|
goalId: external_exports.string().uuid().optional(),
|
|
33457
33799
|
limit: external_exports.number().int().min(1).max(20).optional()
|
|
33458
33800
|
}).strict();
|
|
33459
|
-
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
|
|
33460
|
-
var
|
|
33801
|
+
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 replies -- the person's answers, acknowledgements and deferrals (type answer; found by their summary, by the question or report they reply to, 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, the replies to its items, 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 (a reply carries its kind -- answered, acknowledged or deferred -- whether it is closed (a deferral is not), its summary in under ten words, its question or report, 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.";
|
|
33802
|
+
var CheckActivitySchema2 = external_exports.object({}).strict();
|
|
33803
|
+
var FEEDBACK_TEXT_MAX2 = 5e4;
|
|
33804
|
+
var SendFeedbackSchema2 = external_exports.object({
|
|
33805
|
+
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.`),
|
|
33806
|
+
title: external_exports.string().trim().min(1).max(200).optional().describe("One line naming it."),
|
|
33807
|
+
kind: external_exports.enum(["bug", "idea", "other"]).default("other").describe("bug: something Paigy does wrong. idea: something it should do. other: anything else.")
|
|
33808
|
+
}).strict();
|
|
33809
|
+
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.";
|
|
33461
33810
|
var AGENT_TOOLS2 = [
|
|
33462
|
-
{ 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(WhoIsWorkingSchema2) },
|
|
33463
33811
|
{ name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
|
|
33464
33812
|
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(ManageGoalsToolSchema2) },
|
|
33465
|
-
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(ClaimGoalSchema2) },
|
|
33466
33813
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(GetGoalSchema2) },
|
|
33467
|
-
{ name: "
|
|
33468
|
-
{ name: "
|
|
33814
|
+
{ name: "search", description: SEARCH_DESCRIPTION2, inputSchema: mcpInputSchema2(SearchToolSchema2) },
|
|
33815
|
+
{ 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) },
|
|
33816
|
+
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION2, inputSchema: mcpInputSchema2(SendFeedbackSchema2) }
|
|
33469
33817
|
];
|
|
33470
33818
|
var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
|
|
33471
33819
|
var id2 = external_exports.string().uuid();
|
|
@@ -33513,6 +33861,7 @@ var QuestionChangeSchema2 = external_exports.union([
|
|
|
33513
33861
|
external_exports.object({
|
|
33514
33862
|
kind: external_exports.literal("create"),
|
|
33515
33863
|
text: external_exports.string().min(1),
|
|
33864
|
+
summary: external_exports.string().optional(),
|
|
33516
33865
|
answererId: participant2,
|
|
33517
33866
|
goal: ResultRefSchema2.optional(),
|
|
33518
33867
|
blocks: external_exports.array(external_exports.object({ question: ResultRefSchema2 }).strict()),
|
|
@@ -33563,12 +33912,12 @@ var BrainSearchSchema2 = external_exports.object({
|
|
|
33563
33912
|
}).strict();
|
|
33564
33913
|
var BrainResultSchema2 = external_exports.object({
|
|
33565
33914
|
messages: external_exports.array(BrainMessageSchema2),
|
|
33566
|
-
entries: external_exports.array(external_exports.object({ key: key2, sources: external_exports.array(SourceSchema2).min(1), goals: external_exports.array(ResultRefSchema2) }).strict()),
|
|
33915
|
+
entries: external_exports.array(external_exports.object({ key: key2, sources: external_exports.array(SourceSchema2).min(1), goals: external_exports.array(ResultRefSchema2), summary: external_exports.string().optional() }).strict()),
|
|
33567
33916
|
questions: external_exports.array(external_exports.object({ key: key2, entryKeys: external_exports.array(key2), change: QuestionChangeSchema2 }).strict()),
|
|
33568
33917
|
answers: external_exports.array(external_exports.object({
|
|
33569
33918
|
question: ResultRefSchema2,
|
|
33570
33919
|
entryKeys: external_exports.array(key2).min(1),
|
|
33571
|
-
summary: external_exports.string()
|
|
33920
|
+
summary: external_exports.string(),
|
|
33572
33921
|
selectedOptionIds: external_exports.array(external_exports.string().min(1)).optional()
|
|
33573
33922
|
}).strict()),
|
|
33574
33923
|
goals: external_exports.array(external_exports.object({ key: key2, entryKeys: external_exports.array(key2), change: BrainGoalChangeSchema2 }).strict()),
|
|
@@ -33577,33 +33926,150 @@ var BrainResultSchema2 = external_exports.object({
|
|
|
33577
33926
|
next: BrainNextSchema2,
|
|
33578
33927
|
search: BrainSearchSchema2.optional()
|
|
33579
33928
|
}).strict();
|
|
33580
|
-
var
|
|
33581
|
-
var
|
|
33929
|
+
var str4 = external_exports.string();
|
|
33930
|
+
var strs4 = external_exports.array(external_exports.string());
|
|
33582
33931
|
var CompactResultSchema2 = external_exports.object({
|
|
33583
|
-
next: external_exports.object({ say:
|
|
33584
|
-
messages: external_exports.array(external_exports.object({ key:
|
|
33585
|
-
entries: external_exports.array(external_exports.object({ key:
|
|
33586
|
-
answers: external_exports.array(external_exports.object({ question:
|
|
33932
|
+
next: external_exports.object({ say: strs4, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs4, reason: str4, instructions: strs4 }).strict(),
|
|
33933
|
+
messages: external_exports.array(external_exports.object({ key: str4, to: str4, text: str4, about: strs4, entries: strs4, owed: strs4, inviteToCall: external_exports.boolean() }).strict()),
|
|
33934
|
+
entries: external_exports.array(external_exports.object({ key: str4, from: str4, on: strs4 }).strict()),
|
|
33935
|
+
answers: external_exports.array(external_exports.object({ question: str4, entries: strs4, summary: str4, picked: strs4 }).strict()),
|
|
33587
33936
|
changes: external_exports.array(external_exports.object({
|
|
33588
|
-
key:
|
|
33937
|
+
key: str4,
|
|
33589
33938
|
what: external_exports.enum(["goal", "question", "lesson"]),
|
|
33590
33939
|
op: external_exports.enum(["create", "edit", "assign", "open", "complete", "cancel", "defer", "move", "block", "unblock", "withdraw", "remember", "revise"]),
|
|
33591
|
-
id:
|
|
33592
|
-
text:
|
|
33593
|
-
title:
|
|
33594
|
-
who:
|
|
33595
|
-
under:
|
|
33940
|
+
id: str4,
|
|
33941
|
+
text: str4,
|
|
33942
|
+
title: str4,
|
|
33943
|
+
who: str4,
|
|
33944
|
+
under: str4,
|
|
33596
33945
|
gate: external_exports.enum(["start", "complete", "answer", "none"]),
|
|
33597
|
-
options: external_exports.array(external_exports.object({ id:
|
|
33946
|
+
options: external_exports.array(external_exports.object({ id: str4, label: str4 }).strict()),
|
|
33598
33947
|
pick: external_exports.enum(["one", "many", "rank", "words"]),
|
|
33599
|
-
entries:
|
|
33948
|
+
entries: strs4
|
|
33600
33949
|
}).strict()),
|
|
33601
|
-
feedback: external_exports.array(
|
|
33602
|
-
search: external_exports.object({ query:
|
|
33950
|
+
feedback: external_exports.array(strs4),
|
|
33951
|
+
search: external_exports.object({ query: str4, within: strs4, goal: str4 }).strict()
|
|
33603
33952
|
}).strict();
|
|
33604
33953
|
var COMPACT_RESULT_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
33605
33954
|
zodToJsonSchema2(CompactResultSchema2, { $refStrategy: "none" })
|
|
33606
33955
|
);
|
|
33956
|
+
var str22 = external_exports.string();
|
|
33957
|
+
var strs22 = external_exports.array(external_exports.string());
|
|
33958
|
+
var TalkerReplySchema2 = external_exports.object({
|
|
33959
|
+
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
33960
|
+
* or an agent's handle; `about` names handles; `blocks` is the item a question to an agent must be
|
|
33961
|
+
* answered before ("" for none). */
|
|
33962
|
+
messages: external_exports.array(external_exports.object({ key: str22, to: str22, text: str22, about: strs22, blocks: str22 }).strict()),
|
|
33963
|
+
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
33964
|
+
then: external_exports.enum(["listen", "hold", "end"]),
|
|
33965
|
+
/** The person's replies to items (replies, owner 2026-10-07): the item's handle, the chosen option
|
|
33966
|
+
* IDs, the line handles, how they replied in under ten words (keeping any condition), and `defer`:
|
|
33967
|
+
* "" when their words settle the item, else what a reply that puts it off waits for -- "call" (the
|
|
33968
|
+
* end of this call), a question's handle (that question's answer) or an ISO time. */
|
|
33969
|
+
replies: external_exports.array(external_exports.object({ item: str22, options: strs22, lines: strs22, summary: str22, defer: str22 }).strict()),
|
|
33970
|
+
/** The line handles that tell the talker how to run this call; they last until it ends and reach no agent. */
|
|
33971
|
+
instruction: strs22,
|
|
33972
|
+
/** The line handles the filer acts on, and the only ones it reads (3e): new work, a change to existing
|
|
33973
|
+
* work, feedback on Paigy, anything said to an agent, and any rule meant to outlast the call. */
|
|
33974
|
+
file: strs22,
|
|
33975
|
+
/** Evidence to fetch for a second round: a search, an item's full text, or an agent by name. */
|
|
33976
|
+
need: external_exports.object({ kind: external_exports.enum(["search", "item", "agent", ""]), text: str22 }).strict(),
|
|
33977
|
+
/** The handle of the item to explain ("" for none). */
|
|
33978
|
+
explain: str22
|
|
33979
|
+
}).strict();
|
|
33980
|
+
var TALKER_REPLY_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
33981
|
+
zodToJsonSchema2(TalkerReplySchema2, { $refStrategy: "none" })
|
|
33982
|
+
);
|
|
33983
|
+
var str32 = external_exports.string();
|
|
33984
|
+
var strs32 = external_exports.array(external_exports.string());
|
|
33985
|
+
var FilerReplySchema2 = external_exports.object({
|
|
33986
|
+
/** Which Goals each new line goes on: a line's handle, Goal handles (or keys of new Goals), and what
|
|
33987
|
+
* the line says in at most ten words. */
|
|
33988
|
+
filed: external_exports.array(external_exports.object({ line: str32, goals: strs32, summary: str32 }).strict()),
|
|
33989
|
+
goals: external_exports.array(external_exports.object({
|
|
33990
|
+
op: external_exports.enum(["create", "edit", "complete", "cancel", "reopen", "assign", "defer", "move", "block", "unblock"]),
|
|
33991
|
+
key: str32,
|
|
33992
|
+
goal: str32,
|
|
33993
|
+
title: str32,
|
|
33994
|
+
outcome: str32,
|
|
33995
|
+
owner: str32,
|
|
33996
|
+
under: str32,
|
|
33997
|
+
until: str32,
|
|
33998
|
+
on: str32,
|
|
33999
|
+
gate: external_exports.enum(["start", "complete", "answer", ""]),
|
|
34000
|
+
why: str32
|
|
34001
|
+
}).strict()),
|
|
34002
|
+
questions: external_exports.array(external_exports.object({
|
|
34003
|
+
op: external_exports.enum(["create", "edit", "assign", "withdraw"]),
|
|
34004
|
+
key: str32,
|
|
34005
|
+
question: str32,
|
|
34006
|
+
text: str32,
|
|
34007
|
+
summary: str32,
|
|
34008
|
+
to: str32,
|
|
34009
|
+
goal: str32,
|
|
34010
|
+
options: external_exports.array(external_exports.object({ id: str32, label: str32 }).strict()),
|
|
34011
|
+
pick: external_exports.enum(["one", "many", "rank", "words", ""]),
|
|
34012
|
+
blocks: str32
|
|
34013
|
+
}).strict()),
|
|
34014
|
+
lessons: external_exports.array(external_exports.object({ op: external_exports.enum(["remember", "revise", "withdraw"]), lesson: str32, text: str32, scope: str32 }).strict()),
|
|
34015
|
+
/** Line handles whose words comment on Paigy itself. */
|
|
34016
|
+
feedback: strs32
|
|
34017
|
+
}).strict();
|
|
34018
|
+
var FILER_REPLY_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
34019
|
+
zodToJsonSchema2(FilerReplySchema2, { $refStrategy: "none" })
|
|
34020
|
+
);
|
|
34021
|
+
var ExplainerReplySchema2 = external_exports.object({
|
|
34022
|
+
/** The explanation, as sentences, spoken in order. */
|
|
34023
|
+
say: external_exports.array(external_exports.string()),
|
|
34024
|
+
/** Questions to an agent about gaps in what it read: the agent's handle and the question. */
|
|
34025
|
+
followUps: external_exports.array(external_exports.object({ to: external_exports.string(), text: external_exports.string() }).strict())
|
|
34026
|
+
}).strict();
|
|
34027
|
+
var EXPLAINER_REPLY_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
34028
|
+
zodToJsonSchema2(ExplainerReplySchema2, { $refStrategy: "none" })
|
|
34029
|
+
);
|
|
34030
|
+
var DISTILLER_DEFECTS2 = [
|
|
34031
|
+
"reasked",
|
|
34032
|
+
// a question put to the person again after they answered it
|
|
34033
|
+
"unsupported",
|
|
34034
|
+
// a fact stated that nothing in the input supports
|
|
34035
|
+
"unsaid",
|
|
34036
|
+
// an agent's answer arrived during the call and was never said
|
|
34037
|
+
"skipped",
|
|
34038
|
+
// an agenda item never put to the person
|
|
34039
|
+
"unsaved",
|
|
34040
|
+
// something the person answered or asked for did not save, was refused or dropped
|
|
34041
|
+
"ignored",
|
|
34042
|
+
// the person asked or said something and was never answered (the critic's ignored_a_question)
|
|
34043
|
+
"promised"
|
|
34044
|
+
// said it did or would do something, and nothing shows it done (the critic's broken_promise)
|
|
34045
|
+
];
|
|
34046
|
+
var DistillerReplySchema2 = external_exports.object({
|
|
34047
|
+
defects: external_exports.array(external_exports.object({
|
|
34048
|
+
kind: external_exports.enum(DISTILLER_DEFECTS2),
|
|
34049
|
+
/** The handles of the lines it shows in. */
|
|
34050
|
+
lines: external_exports.array(external_exports.string()),
|
|
34051
|
+
/** The handle of the record it concerns, or "". */
|
|
34052
|
+
about: external_exports.string(),
|
|
34053
|
+
/** One plain sentence, in words, never handles: it is what the feedback row keeps. */
|
|
34054
|
+
why: external_exports.string()
|
|
34055
|
+
}).strict())
|
|
34056
|
+
}).strict();
|
|
34057
|
+
var DISTILLER_REPLY_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
34058
|
+
zodToJsonSchema2(DistillerReplySchema2, { $refStrategy: "none" })
|
|
34059
|
+
);
|
|
34060
|
+
var TIDY_AUDIENCES2 = ["talker", "filer", "agents"];
|
|
34061
|
+
var TidyReplySchema2 = external_exports.object({
|
|
34062
|
+
lessons: external_exports.array(external_exports.object({
|
|
34063
|
+
lesson: external_exports.string(),
|
|
34064
|
+
op: external_exports.enum(["keep", "revise", "withdraw"]),
|
|
34065
|
+
text: external_exports.string(),
|
|
34066
|
+
for: external_exports.enum([...TIDY_AUDIENCES2, ""]),
|
|
34067
|
+
into: external_exports.string()
|
|
34068
|
+
}).strict())
|
|
34069
|
+
}).strict();
|
|
34070
|
+
var TIDY_REPLY_JSON_SCHEMA2 = (({ $schema: _, ...rest }) => rest)(
|
|
34071
|
+
zodToJsonSchema2(TidyReplySchema2, { $refStrategy: "none" })
|
|
34072
|
+
);
|
|
33607
34073
|
function entryWords(entry) {
|
|
33608
34074
|
const content = entry.content;
|
|
33609
34075
|
if (content && "sealed" in content) return "";
|
|
@@ -33627,7 +34093,10 @@ var ContextSchema2 = external_exports.object({
|
|
|
33627
34093
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
33628
34094
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
33629
34095
|
"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."
|
|
33630
|
-
)
|
|
34096
|
+
),
|
|
34097
|
+
/** THE ASK'S UNITS (3c): its context as titled units, in order. The app lists the titles and opens
|
|
34098
|
+
* a body on a tap. Absent on an ask sent without units, which renders as before. */
|
|
34099
|
+
units: external_exports.array(external_exports.object({ title: external_exports.string(), body: external_exports.string() })).optional()
|
|
33631
34100
|
});
|
|
33632
34101
|
var ParticipantSchema2 = external_exports.object({
|
|
33633
34102
|
kind: external_exports.enum(["human", "agent"]),
|
|
@@ -33702,7 +34171,7 @@ var NotifyRequestFields2 = external_exports.object({
|
|
|
33702
34171
|
* ABSENT on the E2EE path, where the sealed `envelope` below carries it. The
|
|
33703
34172
|
* superRefine at the bottom enforces exactly one of the two. */
|
|
33704
34173
|
context: ContextSchema2.optional(),
|
|
33705
|
-
options: external_exports.array(
|
|
34174
|
+
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(
|
|
33706
34175
|
"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)."
|
|
33707
34176
|
),
|
|
33708
34177
|
points: external_exports.array(external_exports.string().min(1)).optional().describe(
|
|
@@ -34300,7 +34769,7 @@ var ConnectionSummarySchema2 = external_exports.object({
|
|
|
34300
34769
|
* desktop app while open. Null = never seen; stale = offline. */
|
|
34301
34770
|
lastSeenAt: external_exports.string().datetime().nullable().optional(),
|
|
34302
34771
|
/** WORKING, NOT JUST CONNECTED (owner, 2026-09-30): the last time the agent itself acted on one of
|
|
34303
|
-
* its Goals —
|
|
34772
|
+
* its Goals — wrote on one or recorded an operation (`tokens.last_worked_at`). Within
|
|
34304
34773
|
* `WORKING_MS` it is working; otherwise it is connected but idle. Null = not seen working yet. */
|
|
34305
34774
|
lastWorkedAt: external_exports.string().datetime().nullable().optional(),
|
|
34306
34775
|
/** The oldest of its Goals that is `ready` for it — work handed to it that nobody has started.
|
|
@@ -34463,8 +34932,8 @@ var QueueItemSchema2 = external_exports.object({
|
|
|
34463
34932
|
repo: external_exports.string().nullable().optional(),
|
|
34464
34933
|
createdAt: external_exports.string(),
|
|
34465
34934
|
updatedAt: external_exports.string().nullable().default(null),
|
|
34466
|
-
/** When its owner last SAID something about it (`
|
|
34467
|
-
*
|
|
34935
|
+
/** When its owner last SAID something about it (the newest `progress` Entry: a contact update kept
|
|
34936
|
+
* as progress). `updatedAt` moves for reasons nobody chose — a
|
|
34468
34937
|
* state recomputed, a review flag — so it cannot tell work in hand from work gone quiet. */
|
|
34469
34938
|
lastProgressAt: external_exports.string().nullable().optional(),
|
|
34470
34939
|
/** THE GOAL'S NEWEST WORD, FROM EITHER SIDE (owner, 2026-09-27): the newest Entry on it, of any
|
|
@@ -34498,7 +34967,7 @@ var QueueItemSchema2 = external_exports.object({
|
|
|
34498
34967
|
*
|
|
34499
34968
|
* IT IS THE PAYLOAD'S OWN HASH, NEVER A STAMP ON THE WORK. Nothing here reasons about which
|
|
34500
34969
|
* writes change which field — the comparison is over the bytes the phone is holding, so a fact
|
|
34501
|
-
* the row shows that no `updated_at` moves for (
|
|
34970
|
+
* the row shows that no `updated_at` moves for (`active` lapsing, a dependency's state, a
|
|
34502
34971
|
* sibling appearing in `childGoalIds`) cannot go unnoticed. Optional because a hand-built
|
|
34503
34972
|
* queue (a fixture, the demo) spells none, and a row with no rev is simply always re-sent. */
|
|
34504
34973
|
rev: external_exports.string().optional()
|
|
@@ -34620,7 +35089,7 @@ var HostDecisionSchema2 = external_exports.object({
|
|
|
34620
35089
|
/** The agent's token id: the row's `recipient`. */
|
|
34621
35090
|
agent: external_exports.string().uuid(),
|
|
34622
35091
|
decision: external_exports.enum(["stood_back", "took_over"]),
|
|
34623
|
-
/** The work it was about: the Goal
|
|
35092
|
+
/** The work it was about: the Goal waiting on that agent next (`claimable` on its `contact({})` read). */
|
|
34624
35093
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
34625
35094
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
34626
35095
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
@@ -34813,14 +35282,13 @@ var CallRecapSchema2 = external_exports.object({
|
|
|
34813
35282
|
owner: external_exports.string(),
|
|
34814
35283
|
state: external_exports.string(),
|
|
34815
35284
|
questions: external_exports.array(external_exports.object({ id: external_exports.string().uuid(), state: external_exports.string(), title: external_exports.string() })),
|
|
34816
|
-
/** `words` is always what they SAID, verbatim — the record, never replaced. `
|
|
34817
|
-
*
|
|
34818
|
-
*
|
|
34819
|
-
*
|
|
34820
|
-
* anything that is not an answer. */
|
|
35285
|
+
/** `words` is always what they SAID, verbatim — the record, never replaced. `summary` is what
|
|
35286
|
+
* the line says in ten words (owner, 2026-10-07): the filer's, or the talker's for the answer it
|
|
35287
|
+
* gave, so the row scans like a chosen option and their own words stay under it. Absent when
|
|
35288
|
+
* neither wrote one. */
|
|
34821
35289
|
/** `about` is the request the line answered (its question), null for words that answered none —
|
|
34822
35290
|
* the key the screen groups on, so one question is one row however many times it was answered. */
|
|
34823
|
-
lines: external_exports.array(external_exports.object({ entryId: external_exports.string().uuid(), words: external_exports.string(),
|
|
35291
|
+
lines: external_exports.array(external_exports.object({ entryId: external_exports.string().uuid(), words: external_exports.string(), summary: external_exports.string().optional(), about: external_exports.string().nullable().optional() }))
|
|
34824
35292
|
})),
|
|
34825
35293
|
unfiled: external_exports.array(external_exports.object({ lineId: external_exports.string().uuid(), words: external_exports.string(), atMs: external_exports.number() })),
|
|
34826
35294
|
more: external_exports.object({ lines: external_exports.number(), entries: external_exports.number(), topics: external_exports.number() })
|
|
@@ -34849,6 +35317,32 @@ function sameTail(a, b) {
|
|
|
34849
35317
|
// src/paigy/bridge.ts
|
|
34850
35318
|
init_dist();
|
|
34851
35319
|
|
|
35320
|
+
// src/paigy/cut.ts
|
|
35321
|
+
function cut(text, title = "Details") {
|
|
35322
|
+
const all = text.trim();
|
|
35323
|
+
if (all.length <= ASK_MAX2) return { main: all };
|
|
35324
|
+
const main2 = head(all, ASK_MAX2);
|
|
35325
|
+
const units3 = [];
|
|
35326
|
+
let rest = all.slice(main2.length).trim();
|
|
35327
|
+
while (rest && units3.length < UNITS_MAX2) {
|
|
35328
|
+
const last = units3.length === UNITS_MAX2 - 1;
|
|
35329
|
+
const body = last && rest.length > UNIT_BODY_MAX2 ? `${head(rest, UNIT_BODY_MAX2 - 1).trimEnd()}\u2026` : head(rest, UNIT_BODY_MAX2);
|
|
35330
|
+
units3.push({ title: units3.length ? `${title} (${units3.length + 1})` : title, body: body.trim() });
|
|
35331
|
+
rest = last ? "" : rest.slice(body.length).trim();
|
|
35332
|
+
}
|
|
35333
|
+
return { main: main2.trim(), units: units3 };
|
|
35334
|
+
}
|
|
35335
|
+
function head(text, max) {
|
|
35336
|
+
if (text.length <= max) return text;
|
|
35337
|
+
const window = text.slice(0, max + 1);
|
|
35338
|
+
for (const boundary of [/\n\s*\n/g, /[.!?](\s)/g, /\s/g]) {
|
|
35339
|
+
let at = -1;
|
|
35340
|
+
for (const m of window.matchAll(boundary)) if (m.index > max / 3 && m.index < max) at = m.index + (boundary.source.startsWith("[") ? 1 : 0);
|
|
35341
|
+
if (at > 0) return text.slice(0, at);
|
|
35342
|
+
}
|
|
35343
|
+
return text.slice(0, max);
|
|
35344
|
+
}
|
|
35345
|
+
|
|
34852
35346
|
// src/paigy/limit.ts
|
|
34853
35347
|
var LIMIT_PREFIXES = [
|
|
34854
35348
|
"You've hit your",
|
|
@@ -34977,10 +35471,19 @@ var LIMITS = episodes();
|
|
|
34977
35471
|
// src/paigy/bridge.ts
|
|
34978
35472
|
function railFor(opts) {
|
|
34979
35473
|
return {
|
|
34980
|
-
|
|
35474
|
+
next: async () => {
|
|
35475
|
+
const waiting = await receive(opts);
|
|
35476
|
+
const goalId = waiting.claimable?.goalId ?? waiting.review?.[0]?.goalId;
|
|
35477
|
+
return goalId ? getGoal(goalId, opts) : { state: "idle", message: "" };
|
|
35478
|
+
},
|
|
34981
35479
|
read: (goalId) => getGoal(goalId, opts),
|
|
34982
|
-
|
|
34983
|
-
|
|
35480
|
+
complete: async (goalId, revision) => {
|
|
35481
|
+
const done = await manageGoals({ changes: [{ kind: "state", goalId, state: "completed", ...revision !== void 0 ? { revision } : {} }] }, opts);
|
|
35482
|
+
const result = done.results[0];
|
|
35483
|
+
if (result?.status !== "applied") throw new Error(`manage_goals failed: ${result?.error ?? "no result"}`);
|
|
35484
|
+
},
|
|
35485
|
+
ack: (eventIds) => acknowledge(eventIds, opts),
|
|
35486
|
+
// One read and back: the pump owns the waiting, so no wait is held here.
|
|
34984
35487
|
contact: (input) => contact(input, { ...opts, waits: false }),
|
|
34985
35488
|
create: async (input) => {
|
|
34986
35489
|
const made = await manageGoals({ changes: [{ kind: "create", ...input }] }, opts);
|
|
@@ -35009,13 +35512,18 @@ function decisionFrom(result) {
|
|
|
35009
35512
|
}
|
|
35010
35513
|
async function ask(state, rail, input) {
|
|
35011
35514
|
if (!state.goal) return null;
|
|
35515
|
+
const { main: main2, units: units3 } = cut(input.ask);
|
|
35012
35516
|
try {
|
|
35013
35517
|
const sent = await rail.contact({
|
|
35014
|
-
|
|
35015
|
-
|
|
35016
|
-
|
|
35518
|
+
questions: [{
|
|
35519
|
+
question: main2,
|
|
35520
|
+
...units3 ? { units: units3 } : {},
|
|
35521
|
+
goalId: state.goal.id,
|
|
35522
|
+
options: input.options,
|
|
35523
|
+
workItBlocks: [{ blocked: { type: "goal", id: state.goal.id }, action: "complete", reason: "The agent cannot go on without this approval." }]
|
|
35524
|
+
}]
|
|
35017
35525
|
});
|
|
35018
|
-
if ("
|
|
35526
|
+
if ("sent" in sent) return null;
|
|
35019
35527
|
const entryId = sent.requestEntryIds[0];
|
|
35020
35528
|
if (!entryId) return null;
|
|
35021
35529
|
(state.seen ??= /* @__PURE__ */ new Set()).add(entryId);
|
|
@@ -35033,57 +35541,54 @@ async function askPermission(event, state, rail) {
|
|
|
35033
35541
|
]
|
|
35034
35542
|
}));
|
|
35035
35543
|
}
|
|
35036
|
-
async function finish(
|
|
35544
|
+
async function finish(state, rail, opts) {
|
|
35037
35545
|
const goal = state.goal;
|
|
35038
35546
|
if (!goal) return;
|
|
35039
|
-
const progress = result?.trim().slice(0, 1e4) || void 0;
|
|
35040
|
-
let revision = goal.revision;
|
|
35041
35547
|
try {
|
|
35042
35548
|
const held = await rail.read(goal.id);
|
|
35043
|
-
revision = held.revision ?? revision;
|
|
35044
35549
|
const owed = state.noted?.some((b) => b.goals.includes(goal.id));
|
|
35045
35550
|
if (held.state === "done" || held.state === "cancelled") {
|
|
35046
35551
|
if (!owed) state.goal = void 0;
|
|
35047
35552
|
return;
|
|
35048
35553
|
}
|
|
35049
35554
|
if (!held.openDecisionNeedIds?.length && !owed) {
|
|
35050
|
-
await rail.
|
|
35555
|
+
await rail.complete(goal.id, held.revision ?? goal.revision);
|
|
35051
35556
|
state.goal = void 0;
|
|
35052
|
-
return;
|
|
35053
35557
|
}
|
|
35054
35558
|
} catch (error) {
|
|
35055
35559
|
opts?.log?.(`\u26A0 the Goal did not close, still holding it: ${error.message}`);
|
|
35056
35560
|
}
|
|
35057
|
-
if (!progress) return;
|
|
35058
|
-
try {
|
|
35059
|
-
await rail.update(goal.id, { revision, changes: { progress }, reason: "The agent's turn ended; its Goal is not closed yet." });
|
|
35060
|
-
} catch (error) {
|
|
35061
|
-
opts?.log?.(`\u26A0 could not keep the turn as progress: ${error.message}`);
|
|
35062
|
-
}
|
|
35063
35561
|
}
|
|
35064
35562
|
async function cannotWork(report, state, rail, opts) {
|
|
35065
35563
|
state.resting = true;
|
|
35066
|
-
const
|
|
35564
|
+
const { main: main2, units: units3 } = cut(report);
|
|
35565
|
+
const say = (goalId) => rail.contact({ updates: [{ message: main2, ...units3 ? { units: units3 } : {}, goalIds: [goalId] }] });
|
|
35566
|
+
const own = async () => (await rail.create({ title: "Agent cannot work", outcome: main2 })).goalId;
|
|
35067
35567
|
try {
|
|
35068
35568
|
if (!state.goal) {
|
|
35069
|
-
const
|
|
35070
|
-
if (
|
|
35569
|
+
const next = await rail.next().catch(() => void 0);
|
|
35570
|
+
if (next?.goalId && next.revision !== void 0) state.goal = { id: next.goalId, revision: next.revision };
|
|
35071
35571
|
}
|
|
35072
35572
|
if (!state.goal) {
|
|
35073
|
-
await say();
|
|
35573
|
+
await say(await own());
|
|
35074
35574
|
return;
|
|
35075
35575
|
}
|
|
35076
35576
|
try {
|
|
35077
35577
|
await say(state.goal.id);
|
|
35078
35578
|
} catch (error) {
|
|
35079
|
-
if (!/
|
|
35080
|
-
opts?.log?.(`\u26A0 the held Goal ${state.goal.id.slice(0, 8)}
|
|
35081
|
-
await say();
|
|
35579
|
+
if (!/goal_not_found/.test(error.message)) throw error;
|
|
35580
|
+
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`);
|
|
35581
|
+
await say(await own());
|
|
35082
35582
|
}
|
|
35083
35583
|
} catch (error) {
|
|
35084
35584
|
opts?.log?.(`\u26A0 could not say the agent cannot work: ${error.message}`);
|
|
35085
35585
|
}
|
|
35086
35586
|
}
|
|
35587
|
+
async function callForResume(text, state, rail) {
|
|
35588
|
+
const { main: main2, units: units3 } = cut(text);
|
|
35589
|
+
const goalId = state.goal?.id ?? (await rail.create({ title: "Usage limit reset", outcome: main2 })).goalId;
|
|
35590
|
+
return rail.contact({ updates: [{ message: main2, ...units3 ? { units: units3 } : {}, goalIds: [goalId], userExplicitlyRequested: "call" }] });
|
|
35591
|
+
}
|
|
35087
35592
|
function conversationFull(result) {
|
|
35088
35593
|
return /prompt is too long/i.test(result ?? "");
|
|
35089
35594
|
}
|
|
@@ -35110,14 +35615,14 @@ async function afterTurn(event, state, rail, opts) {
|
|
|
35110
35615
|
${event.result?.trim() || "No result reported."}`, state, rail, opts);
|
|
35111
35616
|
return void 0;
|
|
35112
35617
|
}
|
|
35113
|
-
await finish(
|
|
35618
|
+
await finish(state, rail, opts);
|
|
35114
35619
|
state.typed = void 0;
|
|
35115
35620
|
state.resting = true;
|
|
35116
35621
|
return void 0;
|
|
35117
35622
|
}
|
|
35118
35623
|
|
|
35119
35624
|
// src/paigy/conversation.ts
|
|
35120
|
-
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
|
|
35625
|
+
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).";
|
|
35121
35626
|
var SAFETY_MS = 6e4;
|
|
35122
35627
|
var ASK_BEAT_MS = 5e3;
|
|
35123
35628
|
function beat() {
|
|
@@ -35217,18 +35722,23 @@ async function gather(state, rail, held) {
|
|
|
35217
35722
|
if (!looks.has(goalId)) looks.set(goalId, { via, ...title ? { title } : {}, ...since !== void 0 ? { since } : {} });
|
|
35218
35723
|
};
|
|
35219
35724
|
const waiting = await rail.waiting().catch(() => null);
|
|
35220
|
-
const listed = /* @__PURE__ */ new
|
|
35725
|
+
const listed = /* @__PURE__ */ new Map();
|
|
35726
|
+
const list = (goalId, eventId) => {
|
|
35727
|
+
const ids = listed.get(goalId) ?? [];
|
|
35728
|
+
if (eventId && !ids.includes(eventId)) ids.push(eventId);
|
|
35729
|
+
listed.set(goalId, ids);
|
|
35730
|
+
};
|
|
35221
35731
|
const announced = state.announced ??= /* @__PURE__ */ new Set();
|
|
35222
35732
|
if (waiting) {
|
|
35223
35733
|
for (const id3 of announced) if (!(waiting.assigned ?? []).some((g) => g.goalId === id3)) announced.delete(id3);
|
|
35224
35734
|
}
|
|
35225
35735
|
for (const g of waiting?.assigned ?? []) if (g.goalId !== state.goal.id && !announced.has(g.goalId)) look2(g.goalId, "assigned", g.title);
|
|
35226
35736
|
for (const g of waiting?.review ?? []) {
|
|
35227
|
-
|
|
35737
|
+
list(g.goalId, g.eventId);
|
|
35228
35738
|
look2(g.goalId, "waiting work", g.title);
|
|
35229
35739
|
}
|
|
35230
35740
|
for (const d of waiting?.deliveries ?? []) for (const id3 of d.goalIds) {
|
|
35231
|
-
|
|
35741
|
+
list(id3, d.deliveryId);
|
|
35232
35742
|
look2(id3, "waiting work");
|
|
35233
35743
|
}
|
|
35234
35744
|
const moved = movedBelow(held, state);
|
|
@@ -35253,7 +35763,7 @@ async function gather(state, rail, held) {
|
|
|
35253
35763
|
for (const { goal, since } of moved) if (read3.has(goal.goalId)) state.below.goals.set(goal.goalId, { since, at: goal.updatedAt ?? null });
|
|
35254
35764
|
return { heard, listed };
|
|
35255
35765
|
}
|
|
35256
|
-
var GIVEN = "This Goal was given to you, and nobody has started it. Carry on with what you're doing unless it changes that;
|
|
35766
|
+
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.";
|
|
35257
35767
|
var says = (h) => h.words.length > 0 || h.via === "assigned";
|
|
35258
35768
|
function whatItIs(h) {
|
|
35259
35769
|
const outcome2 = h.brief.outcome?.trim() ?? "";
|
|
@@ -35283,7 +35793,10 @@ async function hear(session, state, rail, held, opts) {
|
|
|
35283
35793
|
if (opts?.tally) opts.tally.announced += goals.length;
|
|
35284
35794
|
}
|
|
35285
35795
|
}
|
|
35286
|
-
for (const h of heard)
|
|
35796
|
+
for (const h of heard) {
|
|
35797
|
+
const events = listed.get(h.goalId);
|
|
35798
|
+
if (events) await acknowledge2(h.goalId, h.brief, events, state, rail, log);
|
|
35799
|
+
}
|
|
35287
35800
|
}
|
|
35288
35801
|
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.";
|
|
35289
35802
|
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.";
|
|
@@ -35329,15 +35842,16 @@ function settle(session, state, inbox, log) {
|
|
|
35329
35842
|
send2(session, state, [...seen.length ? [SEEN_MID_TURN, ...seen.map((b) => b.words)] : [], ...unseen.map((b) => b.words)].join("\n\n"));
|
|
35330
35843
|
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)`);
|
|
35331
35844
|
}
|
|
35332
|
-
async function
|
|
35845
|
+
async function acknowledge2(goalId, brief, events, state, rail, log) {
|
|
35846
|
+
const ids = [.../* @__PURE__ */ new Set([...brief.reviewEventId ? [brief.reviewEventId] : [], ...events])];
|
|
35847
|
+
if (!ids.length) return;
|
|
35333
35848
|
const acked = state.acked ??= /* @__PURE__ */ new Map();
|
|
35334
|
-
|
|
35335
|
-
acked.
|
|
35849
|
+
const key3 = ids.join(",");
|
|
35850
|
+
if (acked.get(goalId) === key3) return;
|
|
35851
|
+
acked.set(goalId, key3);
|
|
35336
35852
|
try {
|
|
35337
|
-
|
|
35338
|
-
|
|
35339
|
-
acked.set(goalId, done.revision);
|
|
35340
|
-
if (state.goal?.id === goalId && done.revision !== void 0) state.goal.revision = done.revision;
|
|
35853
|
+
const refused = (await rail.ack(ids)).filter((a) => a.refused);
|
|
35854
|
+
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`);
|
|
35341
35855
|
} catch (error) {
|
|
35342
35856
|
log?.(`\u26A0 could not acknowledge ${goalId.slice(0, 8)}: ${error.message} \u2014 its words are typed in; it stays listed until acknowledged`);
|
|
35343
35857
|
}
|
|
@@ -35363,13 +35877,13 @@ async function look(session, state, rail, opts) {
|
|
|
35363
35877
|
if (state.resting && state.noted?.length && !state.asks?.size) return settle(session, state, opts?.inbox, opts?.log);
|
|
35364
35878
|
if (!state.goal) {
|
|
35365
35879
|
if (!state.resting) return;
|
|
35366
|
-
let brief2 = await rail.
|
|
35880
|
+
let brief2 = await rail.next();
|
|
35367
35881
|
if (!brief2.goalId || brief2.revision === void 0) {
|
|
35368
35882
|
if (opts?.initialPrompt?.trim()) {
|
|
35369
35883
|
const prompt = opts.initialPrompt.trim();
|
|
35370
35884
|
opts.initialPrompt = void 0;
|
|
35371
35885
|
const admitted = await rail.create({ title: prompt.split(/\s+/).slice(0, 5).join(" ").slice(0, 80), outcome: prompt });
|
|
35372
|
-
brief2 = await rail.
|
|
35886
|
+
brief2 = await rail.next();
|
|
35373
35887
|
if (!brief2.goalId || brief2.revision === void 0) {
|
|
35374
35888
|
state.goal = { id: admitted.goalId, revision: admitted.revision };
|
|
35375
35889
|
send2(session, state, [HARNESS_INSTRUCTION, named(admitted.goalId, void 0, { outcome: prompt }), prompt].join("\n\n"));
|
|
@@ -35391,7 +35905,7 @@ async function look(session, state, rail, opts) {
|
|
|
35391
35905
|
const earlier = left ? `(${left} earlier entries on this Goal are left out or shortened; get_goal with history: true reads them in full.)` : "";
|
|
35392
35906
|
const fullText = [outcome2, earlier, ...said].filter(Boolean).join("\n\n");
|
|
35393
35907
|
send2(session, state, [HARNESS_INSTRUCTION, named(brief2.goalId, void 0, brief2), fullText].filter(Boolean).join("\n\n"));
|
|
35394
|
-
if (ended(brief2.state)) await
|
|
35908
|
+
if (ended(brief2.state)) await acknowledge2(brief2.goalId, brief2, [], state, rail, opts?.log);
|
|
35395
35909
|
return;
|
|
35396
35910
|
}
|
|
35397
35911
|
const brief = await rail.read(state.goal.id);
|
|
@@ -35479,7 +35993,7 @@ function runHarness(opts) {
|
|
|
35479
35993
|
const clock4 = beat();
|
|
35480
35994
|
let session = null;
|
|
35481
35995
|
const speaksAs = opts.session ?? opts.resume ?? sessionId();
|
|
35482
|
-
const instance =
|
|
35996
|
+
const instance = randomUUID4();
|
|
35483
35997
|
const rail = railFor({ token: opts.token, reach: reachAs(speaksAs, instance) });
|
|
35484
35998
|
let inbox;
|
|
35485
35999
|
if (opts.harness === "claude") {
|
|
@@ -35493,7 +36007,7 @@ function runHarness(opts) {
|
|
|
35493
36007
|
function runningAgain() {
|
|
35494
36008
|
state.carriedOn = false;
|
|
35495
36009
|
opts.log("\u25B6 running again after the limit");
|
|
35496
|
-
LIMITS.running(name, (text) =>
|
|
36010
|
+
LIMITS.running(name, (text) => callForResume(text, state, rail), opts.log);
|
|
35497
36011
|
}
|
|
35498
36012
|
async function handle(event) {
|
|
35499
36013
|
if (event.kind === "error") {
|
|
@@ -35675,7 +36189,7 @@ function listRepos(deps) {
|
|
|
35675
36189
|
|
|
35676
36190
|
// src/holder.ts
|
|
35677
36191
|
init_dist();
|
|
35678
|
-
import { execFileSync as
|
|
36192
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
35679
36193
|
import { readFileSync as readFileSync5, readdirSync as readdirSync3 } from "fs";
|
|
35680
36194
|
import { homedir as homedir7 } from "os";
|
|
35681
36195
|
import { join as join7 } from "path";
|
|
@@ -35690,7 +36204,7 @@ function isAlive(pid) {
|
|
|
35690
36204
|
function psStart(pid, zone) {
|
|
35691
36205
|
try {
|
|
35692
36206
|
const env = zone === "UTC" ? { ...process.env, TZ: "UTC", LC_ALL: "C" } : { ...process.env, LC_ALL: "C" };
|
|
35693
|
-
return
|
|
36207
|
+
return execFileSync2("ps", ["-o", "lstart=", "-p", String(pid)], { env, encoding: "utf8", timeout: 2e3 }).trim() || null;
|
|
35694
36208
|
} catch {
|
|
35695
36209
|
return null;
|
|
35696
36210
|
}
|
|
@@ -35745,7 +36259,7 @@ function localHolderPids(deps = {}) {
|
|
|
35745
36259
|
}
|
|
35746
36260
|
function psParent(pid) {
|
|
35747
36261
|
try {
|
|
35748
|
-
const out =
|
|
36262
|
+
const out = execFileSync2("ps", ["-o", "ppid=", "-p", String(pid)], { encoding: "utf8", timeout: 2e3 }).trim();
|
|
35749
36263
|
const n = Number(out);
|
|
35750
36264
|
return Number.isInteger(n) && n > 0 ? n : null;
|
|
35751
36265
|
} catch {
|
|
@@ -35869,7 +36383,7 @@ function ownerSession(slot, deps = {}) {
|
|
|
35869
36383
|
const prefix = m[1];
|
|
35870
36384
|
const root = deps.projectsDir ?? join8(homedir8(), ".claude", "projects");
|
|
35871
36385
|
const list = deps.list ?? ((dir) => readdirSync4(dir));
|
|
35872
|
-
const
|
|
36386
|
+
const head2 = deps.head ?? readHead;
|
|
35873
36387
|
let folders;
|
|
35874
36388
|
try {
|
|
35875
36389
|
folders = list(root);
|
|
@@ -35887,7 +36401,7 @@ function ownerSession(slot, deps = {}) {
|
|
|
35887
36401
|
if (!file) continue;
|
|
35888
36402
|
let text;
|
|
35889
36403
|
try {
|
|
35890
|
-
text =
|
|
36404
|
+
text = head2(join8(root, folder, file));
|
|
35891
36405
|
} catch {
|
|
35892
36406
|
continue;
|
|
35893
36407
|
}
|
|
@@ -36829,7 +37343,7 @@ async function main() {
|
|
|
36829
37343
|
let launched;
|
|
36830
37344
|
if (parsed.launch) {
|
|
36831
37345
|
overrideToken(readSlot("Desktop") || null);
|
|
36832
|
-
const session =
|
|
37346
|
+
const session = randomUUID5();
|
|
36833
37347
|
const minted = await hatch(parsed.launch, parsed.voice ?? null, {
|
|
36834
37348
|
reach: reachAs(session),
|
|
36835
37349
|
brief: parsed.prompt,
|