@paigy/harness 0.3.42 → 0.3.45
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 +109 -102
- package/dist/main.js +109 -102
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -23446,8 +23446,8 @@ var ZodIssueCode = util.arrayToEnum([
|
|
|
23446
23446
|
"not_finite"
|
|
23447
23447
|
]);
|
|
23448
23448
|
var quotelessJson = (obj) => {
|
|
23449
|
-
const
|
|
23450
|
-
return
|
|
23449
|
+
const json = JSON.stringify(obj, null, 2);
|
|
23450
|
+
return json.replace(/"([^"]+)":/g, "$1:");
|
|
23451
23451
|
};
|
|
23452
23452
|
var ZodError = class _ZodError extends Error {
|
|
23453
23453
|
get errors() {
|
|
@@ -27373,6 +27373,24 @@ function parentOf(pid) {
|
|
|
27373
27373
|
return void 0;
|
|
27374
27374
|
}
|
|
27375
27375
|
}
|
|
27376
|
+
var CODEX_PARENT = /(^|\/)\.codex\/|CodexCLI\.app|(^|[\/\s])codex(\s|$)/;
|
|
27377
|
+
var codexParent;
|
|
27378
|
+
function underCodex() {
|
|
27379
|
+
if (codexParent !== void 0) return codexParent;
|
|
27380
|
+
codexParent = false;
|
|
27381
|
+
if (process.platform === "win32") return codexParent;
|
|
27382
|
+
for (const pid of ancestors()) {
|
|
27383
|
+
try {
|
|
27384
|
+
const command = execFileSync("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: 1e3 });
|
|
27385
|
+
if (CODEX_PARENT.test(command)) {
|
|
27386
|
+
codexParent = true;
|
|
27387
|
+
break;
|
|
27388
|
+
}
|
|
27389
|
+
} catch {
|
|
27390
|
+
}
|
|
27391
|
+
}
|
|
27392
|
+
return codexParent;
|
|
27393
|
+
}
|
|
27376
27394
|
var lineage;
|
|
27377
27395
|
function ancestors() {
|
|
27378
27396
|
if (lineage) return lineage;
|
|
@@ -27430,7 +27448,8 @@ function parseSessionRecord(text) {
|
|
|
27430
27448
|
return void 0;
|
|
27431
27449
|
}
|
|
27432
27450
|
function sessionId() {
|
|
27433
|
-
return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ??
|
|
27451
|
+
return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ?? // A Codex thread that was handed no id is its own agent, not the folder's (`underCodex`).
|
|
27452
|
+
(underCodex() ? INSTANCE_ID : WORKSPACE_ID);
|
|
27434
27453
|
}
|
|
27435
27454
|
async function reach(url, init) {
|
|
27436
27455
|
return send(url, init, sessionId());
|
|
@@ -29160,11 +29179,17 @@ var messageBase = {
|
|
|
29160
29179
|
obligationIds: external_exports.array(id)
|
|
29161
29180
|
};
|
|
29162
29181
|
var BrainMessageSchema = external_exports.union([
|
|
29163
|
-
|
|
29182
|
+
// A MESSAGE TO THE PERSON KEEPS ITS SENTENCES (turns.md): the talker writes them one by one, and each is
|
|
29183
|
+
// its own unit of speech (`<cycle>:<key>:<n>`). `text` is the same words joined, for every reader of a
|
|
29184
|
+
// message's words. Absent on results written before sentences.
|
|
29185
|
+
external_exports.object({ ...messageBase, to: external_exports.object({ kind: external_exports.literal("user") }).strict(), sentences: external_exports.array(external_exports.string().min(1)).min(1).optional() }).strict(),
|
|
29164
29186
|
external_exports.object({
|
|
29165
29187
|
...messageBase,
|
|
29166
29188
|
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
29167
|
-
call: external_exports.object({ callId: id, listen: external_exports.literal(true) }).strict().optional()
|
|
29189
|
+
call: external_exports.object({ callId: id, listen: external_exports.literal(true) }).strict().optional(),
|
|
29190
|
+
// THE PERSON ASKED TO BE CALLED BACK ONCE THIS AGENT'S WORK IS DONE (turns.md, step 0): the agent owes
|
|
29191
|
+
// the call, and its next contact about it rings them (`public.callbacks`).
|
|
29192
|
+
callback: external_exports.literal(true).optional()
|
|
29168
29193
|
}).strict()
|
|
29169
29194
|
]);
|
|
29170
29195
|
var BrainSearchSchema = external_exports.object({
|
|
@@ -29219,9 +29244,12 @@ var str2 = external_exports.string();
|
|
|
29219
29244
|
var strs2 = external_exports.array(external_exports.string());
|
|
29220
29245
|
var TalkerReplySchema = external_exports.object({
|
|
29221
29246
|
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
29222
|
-
* or an agent's handle; `
|
|
29223
|
-
*
|
|
29224
|
-
|
|
29247
|
+
* or an agent's handle; `sentences` is what a message to the person says, one short sentence each
|
|
29248
|
+
* ([] to an agent); `text` is what a message to an agent says ("" to the person); `about` names
|
|
29249
|
+
* handles; `blocks` is the item a question to an agent must be answered before ("" for none);
|
|
29250
|
+
* `callback` is true on a message to the agent doing work the person asked to be called back about
|
|
29251
|
+
* once it is done (false otherwise): that agent then owes the call (turns.md, step 0). */
|
|
29252
|
+
messages: external_exports.array(external_exports.object({ key: str2, to: str2, sentences: strs2, text: str2, about: strs2, blocks: str2, callback: external_exports.boolean() }).strict()),
|
|
29225
29253
|
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
29226
29254
|
then: external_exports.enum(["listen", "hold", "end"]),
|
|
29227
29255
|
/** The person's replies to items (replies, owner 2026-10-07): the item's handle, the chosen option
|
|
@@ -29345,42 +29373,6 @@ var LIVE_MS = 3 * 6e4;
|
|
|
29345
29373
|
var WORKING_MS = 60 * 6e4;
|
|
29346
29374
|
var WORKING_TIER_MS = 2 * 60 * 6e4;
|
|
29347
29375
|
var RECENT_TIER_MS = 24 * 60 * 6e4;
|
|
29348
|
-
var json = external_exports.lazy(() => external_exports.union([
|
|
29349
|
-
external_exports.string(),
|
|
29350
|
-
external_exports.number().finite(),
|
|
29351
|
-
external_exports.boolean(),
|
|
29352
|
-
external_exports.null(),
|
|
29353
|
-
external_exports.array(json),
|
|
29354
|
-
external_exports.record(json)
|
|
29355
|
-
]));
|
|
29356
|
-
var clock = external_exports.number().int().nonnegative().safe();
|
|
29357
|
-
var HeardEventSchema = external_exports.object({
|
|
29358
|
-
eventId: external_exports.string().uuid(),
|
|
29359
|
-
source: external_exports.enum(["phone", "bot"]),
|
|
29360
|
-
sequence: clock,
|
|
29361
|
-
kind: external_exports.string().min(1),
|
|
29362
|
-
phoneAtMs: clock.optional(),
|
|
29363
|
-
botAtMs: clock.optional(),
|
|
29364
|
-
payload: external_exports.record(json)
|
|
29365
|
-
}).strict();
|
|
29366
|
-
var HeardCursorSchema = HeardEventSchema.pick({ source: true, sequence: true, eventId: true });
|
|
29367
|
-
var HeardPageSchema = external_exports.object({
|
|
29368
|
-
events: external_exports.array(HeardEventSchema).max(200),
|
|
29369
|
-
next: HeardCursorSchema.nullable()
|
|
29370
|
-
}).strict();
|
|
29371
|
-
var MAX_EVENTS = 50;
|
|
29372
|
-
var MAX_BYTES = 8e4;
|
|
29373
|
-
var batchBytes = (events) => {
|
|
29374
|
-
let bytes = 0;
|
|
29375
|
-
for (const char of JSON.stringify({ events })) {
|
|
29376
|
-
const point = char.codePointAt(0);
|
|
29377
|
-
bytes += point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
|
|
29378
|
-
}
|
|
29379
|
-
return bytes;
|
|
29380
|
-
};
|
|
29381
|
-
var HeardBatchSchema = external_exports.object({
|
|
29382
|
-
events: external_exports.array(HeardEventSchema).min(1).max(MAX_EVENTS)
|
|
29383
|
-
}).strict().refine((value) => batchBytes(value.events) <= MAX_BYTES, "heard_batch_too_large");
|
|
29384
29376
|
var ContextSchema = external_exports.object({
|
|
29385
29377
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
29386
29378
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
@@ -29705,6 +29697,10 @@ var AgendaTurnSchema = external_exports.object({
|
|
|
29705
29697
|
/** The spoken sentences of the turn, in order. No count: how long a turn is is the brain's call
|
|
29706
29698
|
* (owner, 2026-09-25), and a count here refused whole plans. */
|
|
29707
29699
|
info: external_exports.array(external_exports.string().min(1)).default([]),
|
|
29700
|
+
/** THE ID OF EACH SENTENCE, when the plan names them (turns.md): a talker message's sentences are its
|
|
29701
|
+
* `info`, one piece each, and `units[i]` is the id the bot's line receipt carries for `info[i]`
|
|
29702
|
+
* (`<cycle>:<key>:<n>`), so what was heard is known per sentence. Absent on every other turn. */
|
|
29703
|
+
units: external_exports.array(external_exports.string().min(1)).optional(),
|
|
29708
29704
|
question: external_exports.string().min(1).nullable(),
|
|
29709
29705
|
/** True on the one turn carrying the agent's own declared question. */
|
|
29710
29706
|
asks: external_exports.boolean().optional(),
|
|
@@ -29941,8 +29937,8 @@ var MissedCallSchema = external_exports.enum([
|
|
|
29941
29937
|
"inbox",
|
|
29942
29938
|
"dismiss"
|
|
29943
29939
|
]);
|
|
29944
|
-
var
|
|
29945
|
-
var QUIET = ` Nothing rings from ${
|
|
29940
|
+
var clock = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
29941
|
+
var QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} your time; the count waits for morning.`;
|
|
29946
29942
|
var BrokerTuningSchema = external_exports.object({
|
|
29947
29943
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
29948
29944
|
ackVerbosity: external_exports.enum(["normal", "none"]).optional(),
|
|
@@ -30279,6 +30275,13 @@ var QueueItemSchema = external_exports.object({
|
|
|
30279
30275
|
* can see (`replies`, `questions[].answeredAt`) miss a spontaneous note entirely — a `request`
|
|
30280
30276
|
* Entry with no `about_id` is in neither. */
|
|
30281
30277
|
lastPersonAt: external_exports.string().nullable().optional(),
|
|
30278
|
+
/** EACH SIDE'S NEWEST WORD IN THE LAST DAY (owner, 2026-10-13, the Work tab's order): the person's
|
|
30279
|
+
* (`yours`) and the agents' (`theirs`), each null when that side wrote nothing on it in 24 hours.
|
|
30280
|
+
* `latest` holds one Entry, so whichever side wrote first is hidden there; Work orders a Goal by
|
|
30281
|
+
* these two and draws the side it was placed by under its title. Optional, so hand-built queues
|
|
30282
|
+
* and a door older than 20261013045542 need not spell them. */
|
|
30283
|
+
yours: GoalLatestSchema.nullable().optional(),
|
|
30284
|
+
theirs: GoalLatestSchema.nullable().optional(),
|
|
30282
30285
|
/** WHAT THIS ROW IS, IN TWELVE CHARACTERS (#2928) — the hash of every other field on it, stamped
|
|
30283
30286
|
* by the one projection that builds the row (`apps/api/src/goal/queue.ts`). It is how the
|
|
30284
30287
|
* incremental read knows a row has not moved: the phone echoes back the revs it holds
|
|
@@ -30552,10 +30555,20 @@ var CallRecapSchema = external_exports.object({
|
|
|
30552
30555
|
title: external_exports.string(),
|
|
30553
30556
|
owner: external_exports.string(),
|
|
30554
30557
|
state: external_exports.string(),
|
|
30558
|
+
/** Presented Entry content and its author, separately from the current Goal owner. */
|
|
30559
|
+
items: external_exports.array(external_exports.object({ entryId: external_exports.string(), author: external_exports.string(), text: external_exports.string(), summary: external_exports.string().nullable() })).optional(),
|
|
30555
30560
|
/** Whether the call put it to the person. An item it carried and never said has no row on the
|
|
30556
30561
|
* review (owner, 2026-10-08: "why do we get the third one when it didn't happen in the call?"). */
|
|
30557
30562
|
presented: external_exports.boolean(),
|
|
30558
|
-
|
|
30563
|
+
/** Whether THIS call created it — the third way a call touches work, beside carrying a request
|
|
30564
|
+
* there and filing words there (owner, 2026-10-08, Goal `5b4b1a0a`: "Show the new work, keep my
|
|
30565
|
+
* words under it"). Created work is never carried, so it is never `presented`; without this the
|
|
30566
|
+
* row is dropped by the "only what happened on the call" filter. False on a database before
|
|
30567
|
+
* 20261013080133. */
|
|
30568
|
+
created: external_exports.boolean(),
|
|
30569
|
+
/** `request` is the Entry that asked it — what a line's `about` names when the line answered or put
|
|
30570
|
+
* it off. Optional: an older API sent none. */
|
|
30571
|
+
questions: external_exports.array(external_exports.object({ id: external_exports.string().uuid(), state: external_exports.string(), title: external_exports.string(), request: external_exports.string().optional() })),
|
|
30559
30572
|
/** `words` is always what they SAID, verbatim — the record, never replaced. `summary` is what
|
|
30560
30573
|
* the line says in ten words (owner, 2026-10-07): the filer's, or the talker's for the answer it
|
|
30561
30574
|
* gave, so the row scans like a chosen option and their own words stay under it. Absent when
|
|
@@ -33451,11 +33464,17 @@ var messageBase2 = {
|
|
|
33451
33464
|
obligationIds: external_exports.array(id2)
|
|
33452
33465
|
};
|
|
33453
33466
|
var BrainMessageSchema2 = external_exports.union([
|
|
33454
|
-
|
|
33467
|
+
// A MESSAGE TO THE PERSON KEEPS ITS SENTENCES (turns.md): the talker writes them one by one, and each is
|
|
33468
|
+
// its own unit of speech (`<cycle>:<key>:<n>`). `text` is the same words joined, for every reader of a
|
|
33469
|
+
// message's words. Absent on results written before sentences.
|
|
33470
|
+
external_exports.object({ ...messageBase2, to: external_exports.object({ kind: external_exports.literal("user") }).strict(), sentences: external_exports.array(external_exports.string().min(1)).min(1).optional() }).strict(),
|
|
33455
33471
|
external_exports.object({
|
|
33456
33472
|
...messageBase2,
|
|
33457
33473
|
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
33458
|
-
call: external_exports.object({ callId: id2, listen: external_exports.literal(true) }).strict().optional()
|
|
33474
|
+
call: external_exports.object({ callId: id2, listen: external_exports.literal(true) }).strict().optional(),
|
|
33475
|
+
// THE PERSON ASKED TO BE CALLED BACK ONCE THIS AGENT'S WORK IS DONE (turns.md, step 0): the agent owes
|
|
33476
|
+
// the call, and its next contact about it rings them (`public.callbacks`).
|
|
33477
|
+
callback: external_exports.literal(true).optional()
|
|
33459
33478
|
}).strict()
|
|
33460
33479
|
]);
|
|
33461
33480
|
var BrainSearchSchema2 = external_exports.object({
|
|
@@ -33510,9 +33529,12 @@ var str22 = external_exports.string();
|
|
|
33510
33529
|
var strs22 = external_exports.array(external_exports.string());
|
|
33511
33530
|
var TalkerReplySchema2 = external_exports.object({
|
|
33512
33531
|
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
33513
|
-
* or an agent's handle; `
|
|
33514
|
-
*
|
|
33515
|
-
|
|
33532
|
+
* or an agent's handle; `sentences` is what a message to the person says, one short sentence each
|
|
33533
|
+
* ([] to an agent); `text` is what a message to an agent says ("" to the person); `about` names
|
|
33534
|
+
* handles; `blocks` is the item a question to an agent must be answered before ("" for none);
|
|
33535
|
+
* `callback` is true on a message to the agent doing work the person asked to be called back about
|
|
33536
|
+
* once it is done (false otherwise): that agent then owes the call (turns.md, step 0). */
|
|
33537
|
+
messages: external_exports.array(external_exports.object({ key: str22, to: str22, sentences: strs22, text: str22, about: strs22, blocks: str22, callback: external_exports.boolean() }).strict()),
|
|
33516
33538
|
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
33517
33539
|
then: external_exports.enum(["listen", "hold", "end"]),
|
|
33518
33540
|
/** The person's replies to items (replies, owner 2026-10-07): the item's handle, the chosen option
|
|
@@ -33647,42 +33669,6 @@ var WORKING_MS2 = 60 * 6e4;
|
|
|
33647
33669
|
var isWorking = (c, now) => !!c.lastWorkedAt && now - Date.parse(c.lastWorkedAt) < WORKING_MS2;
|
|
33648
33670
|
var WORKING_TIER_MS2 = 2 * 60 * 6e4;
|
|
33649
33671
|
var RECENT_TIER_MS2 = 24 * 60 * 6e4;
|
|
33650
|
-
var json2 = external_exports.lazy(() => external_exports.union([
|
|
33651
|
-
external_exports.string(),
|
|
33652
|
-
external_exports.number().finite(),
|
|
33653
|
-
external_exports.boolean(),
|
|
33654
|
-
external_exports.null(),
|
|
33655
|
-
external_exports.array(json2),
|
|
33656
|
-
external_exports.record(json2)
|
|
33657
|
-
]));
|
|
33658
|
-
var clock3 = external_exports.number().int().nonnegative().safe();
|
|
33659
|
-
var HeardEventSchema2 = external_exports.object({
|
|
33660
|
-
eventId: external_exports.string().uuid(),
|
|
33661
|
-
source: external_exports.enum(["phone", "bot"]),
|
|
33662
|
-
sequence: clock3,
|
|
33663
|
-
kind: external_exports.string().min(1),
|
|
33664
|
-
phoneAtMs: clock3.optional(),
|
|
33665
|
-
botAtMs: clock3.optional(),
|
|
33666
|
-
payload: external_exports.record(json2)
|
|
33667
|
-
}).strict();
|
|
33668
|
-
var HeardCursorSchema2 = HeardEventSchema2.pick({ source: true, sequence: true, eventId: true });
|
|
33669
|
-
var HeardPageSchema2 = external_exports.object({
|
|
33670
|
-
events: external_exports.array(HeardEventSchema2).max(200),
|
|
33671
|
-
next: HeardCursorSchema2.nullable()
|
|
33672
|
-
}).strict();
|
|
33673
|
-
var MAX_EVENTS2 = 50;
|
|
33674
|
-
var MAX_BYTES2 = 8e4;
|
|
33675
|
-
var batchBytes2 = (events) => {
|
|
33676
|
-
let bytes = 0;
|
|
33677
|
-
for (const char of JSON.stringify({ events })) {
|
|
33678
|
-
const point = char.codePointAt(0);
|
|
33679
|
-
bytes += point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
|
|
33680
|
-
}
|
|
33681
|
-
return bytes;
|
|
33682
|
-
};
|
|
33683
|
-
var HeardBatchSchema2 = external_exports.object({
|
|
33684
|
-
events: external_exports.array(HeardEventSchema2).min(1).max(MAX_EVENTS2)
|
|
33685
|
-
}).strict().refine((value) => batchBytes2(value.events) <= MAX_BYTES2, "heard_batch_too_large");
|
|
33686
33672
|
var ContextSchema2 = external_exports.object({
|
|
33687
33673
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
33688
33674
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
@@ -34007,6 +33993,10 @@ var AgendaTurnSchema2 = external_exports.object({
|
|
|
34007
33993
|
/** The spoken sentences of the turn, in order. No count: how long a turn is is the brain's call
|
|
34008
33994
|
* (owner, 2026-09-25), and a count here refused whole plans. */
|
|
34009
33995
|
info: external_exports.array(external_exports.string().min(1)).default([]),
|
|
33996
|
+
/** THE ID OF EACH SENTENCE, when the plan names them (turns.md): a talker message's sentences are its
|
|
33997
|
+
* `info`, one piece each, and `units[i]` is the id the bot's line receipt carries for `info[i]`
|
|
33998
|
+
* (`<cycle>:<key>:<n>`), so what was heard is known per sentence. Absent on every other turn. */
|
|
33999
|
+
units: external_exports.array(external_exports.string().min(1)).optional(),
|
|
34010
34000
|
question: external_exports.string().min(1).nullable(),
|
|
34011
34001
|
/** True on the one turn carrying the agent's own declared question. */
|
|
34012
34002
|
asks: external_exports.boolean().optional(),
|
|
@@ -34243,8 +34233,8 @@ var MissedCallSchema2 = external_exports.enum([
|
|
|
34243
34233
|
"inbox",
|
|
34244
34234
|
"dismiss"
|
|
34245
34235
|
]);
|
|
34246
|
-
var
|
|
34247
|
-
var QUIET2 = ` Nothing rings from ${
|
|
34236
|
+
var clock2 = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
34237
|
+
var QUIET2 = ` Nothing rings from ${clock2(NIGHT2.from)} to ${clock2(NIGHT2.to)} your time; the count waits for morning.`;
|
|
34248
34238
|
var BrokerTuningSchema2 = external_exports.object({
|
|
34249
34239
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
34250
34240
|
ackVerbosity: external_exports.enum(["normal", "none"]).optional(),
|
|
@@ -34581,6 +34571,13 @@ var QueueItemSchema2 = external_exports.object({
|
|
|
34581
34571
|
* can see (`replies`, `questions[].answeredAt`) miss a spontaneous note entirely — a `request`
|
|
34582
34572
|
* Entry with no `about_id` is in neither. */
|
|
34583
34573
|
lastPersonAt: external_exports.string().nullable().optional(),
|
|
34574
|
+
/** EACH SIDE'S NEWEST WORD IN THE LAST DAY (owner, 2026-10-13, the Work tab's order): the person's
|
|
34575
|
+
* (`yours`) and the agents' (`theirs`), each null when that side wrote nothing on it in 24 hours.
|
|
34576
|
+
* `latest` holds one Entry, so whichever side wrote first is hidden there; Work orders a Goal by
|
|
34577
|
+
* these two and draws the side it was placed by under its title. Optional, so hand-built queues
|
|
34578
|
+
* and a door older than 20261013045542 need not spell them. */
|
|
34579
|
+
yours: GoalLatestSchema2.nullable().optional(),
|
|
34580
|
+
theirs: GoalLatestSchema2.nullable().optional(),
|
|
34584
34581
|
/** WHAT THIS ROW IS, IN TWELVE CHARACTERS (#2928) — the hash of every other field on it, stamped
|
|
34585
34582
|
* by the one projection that builds the row (`apps/api/src/goal/queue.ts`). It is how the
|
|
34586
34583
|
* incremental read knows a row has not moved: the phone echoes back the revs it holds
|
|
@@ -34852,10 +34849,20 @@ var CallRecapSchema2 = external_exports.object({
|
|
|
34852
34849
|
title: external_exports.string(),
|
|
34853
34850
|
owner: external_exports.string(),
|
|
34854
34851
|
state: external_exports.string(),
|
|
34852
|
+
/** Presented Entry content and its author, separately from the current Goal owner. */
|
|
34853
|
+
items: external_exports.array(external_exports.object({ entryId: external_exports.string(), author: external_exports.string(), text: external_exports.string(), summary: external_exports.string().nullable() })).optional(),
|
|
34855
34854
|
/** Whether the call put it to the person. An item it carried and never said has no row on the
|
|
34856
34855
|
* review (owner, 2026-10-08: "why do we get the third one when it didn't happen in the call?"). */
|
|
34857
34856
|
presented: external_exports.boolean(),
|
|
34858
|
-
|
|
34857
|
+
/** Whether THIS call created it — the third way a call touches work, beside carrying a request
|
|
34858
|
+
* there and filing words there (owner, 2026-10-08, Goal `5b4b1a0a`: "Show the new work, keep my
|
|
34859
|
+
* words under it"). Created work is never carried, so it is never `presented`; without this the
|
|
34860
|
+
* row is dropped by the "only what happened on the call" filter. False on a database before
|
|
34861
|
+
* 20261013080133. */
|
|
34862
|
+
created: external_exports.boolean(),
|
|
34863
|
+
/** `request` is the Entry that asked it — what a line's `about` names when the line answered or put
|
|
34864
|
+
* it off. Optional: an older API sent none. */
|
|
34865
|
+
questions: external_exports.array(external_exports.object({ id: external_exports.string().uuid(), state: external_exports.string(), title: external_exports.string(), request: external_exports.string().optional() })),
|
|
34859
34866
|
/** `words` is always what they SAID, verbatim — the record, never replaced. `summary` is what
|
|
34860
34867
|
* the line says in ten words (owner, 2026-10-07): the filer's, or the talker's for the answer it
|
|
34861
34868
|
* gave, so the row scans like a chosen option and their own words stay under it. Absent when
|
|
@@ -34962,9 +34969,9 @@ function limitIn(text, now) {
|
|
|
34962
34969
|
if (!line) return null;
|
|
34963
34970
|
const reset = resetOf(line, now);
|
|
34964
34971
|
if (reset !== null && reset > now && reset - now <= FARTHEST_MS) {
|
|
34965
|
-
return { until: reset + MARGIN_MS, resets: /resets\s+(?:at\s+)?(.+?)\s*(?:\(|$)/i.exec(line)?.[1]?.trim() ??
|
|
34972
|
+
return { until: reset + MARGIN_MS, resets: /resets\s+(?:at\s+)?(.+?)\s*(?:\(|$)/i.exec(line)?.[1]?.trim() ?? clock3(reset) };
|
|
34966
34973
|
}
|
|
34967
|
-
return { until: now + RETRY_MS2, resets:
|
|
34974
|
+
return { until: now + RETRY_MS2, resets: clock3(now + RETRY_MS2) };
|
|
34968
34975
|
}
|
|
34969
34976
|
function resetOf(line, now) {
|
|
34970
34977
|
const m = /resets\s+(?:at\s+)?(?:([a-z]{3})[a-z]*\s+(\d{1,2}),?\s+(?:at\s+)?)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)\b(?:\s*\(([^)]+)\))?/i.exec(line);
|
|
@@ -35008,7 +35015,7 @@ function wallToEpoch(year, month, day, hour, minute, zone) {
|
|
|
35008
35015
|
const first = wall - offset(wall);
|
|
35009
35016
|
return wall - offset(first);
|
|
35010
35017
|
}
|
|
35011
|
-
function
|
|
35018
|
+
function clock3(t) {
|
|
35012
35019
|
return new Date(t).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }).replace(/\s?([AP])M$/i, (_, x) => `${x.toLowerCase()}m`);
|
|
35013
35020
|
}
|
|
35014
35021
|
var pausedLine = (limit) => `Paused by the usage limit until ${limit.resets}`;
|
|
@@ -35052,7 +35059,7 @@ function episodes(opts = {}) {
|
|
|
35052
35059
|
episode.called = true;
|
|
35053
35060
|
const rest = episode.paused.filter((n) => !episode.running.includes(n));
|
|
35054
35061
|
const text = [
|
|
35055
|
-
`Claude's usage limit paused ${names(episode.paused)} from ${
|
|
35062
|
+
`Claude's usage limit paused ${names(episode.paused)} from ${clock3(episode.since)}.`,
|
|
35056
35063
|
rest.length ? `It has reset: ${names(episode.running)} ${episode.running.length > 1 ? "are" : "is"} running again, and ${names(rest)} ${rest.length > 1 ? "haven't" : "hasn't"} started again yet.` : `It has reset, and ${episode.paused.length > 1 ? "they have all" : "it has"} carried on.`
|
|
35057
35064
|
].join(" ");
|
|
35058
35065
|
void call(text).then(
|
|
@@ -35617,7 +35624,7 @@ async function send2(session, state, text) {
|
|
|
35617
35624
|
}
|
|
35618
35625
|
}
|
|
35619
35626
|
async function pump(session, state, rail, opts) {
|
|
35620
|
-
const
|
|
35627
|
+
const clock4 = opts.beat ?? beat();
|
|
35621
35628
|
const now = opts.now ?? Date.now;
|
|
35622
35629
|
const counts = { wake: 0, rest: 0, safety: 0, skipped: 0 };
|
|
35623
35630
|
const tally = { noted: 0, seen: 0, announced: 0 };
|
|
@@ -35649,7 +35656,7 @@ async function pump(session, state, rail, opts) {
|
|
|
35649
35656
|
counts.wake = counts.rest = counts.safety = counts.skipped = tally.noted = tally.seen = tally.announced = tally.paused = 0;
|
|
35650
35657
|
since = now();
|
|
35651
35658
|
}
|
|
35652
|
-
cause = await
|
|
35659
|
+
cause = await clock4.next(state.asks?.size ? ASK_BEAT_MS : state.paused ? Math.max(1e3, Math.min(SAFETY_MS, state.paused.until - now())) : SAFETY_MS);
|
|
35653
35660
|
if (!await opts.onIdle()) return;
|
|
35654
35661
|
}
|
|
35655
35662
|
}
|
|
@@ -35659,7 +35666,7 @@ function runHarness(opts) {
|
|
|
35659
35666
|
let running = true;
|
|
35660
35667
|
let tail = [];
|
|
35661
35668
|
const state = { resting: true };
|
|
35662
|
-
const
|
|
35669
|
+
const clock4 = beat();
|
|
35663
35670
|
let session = null;
|
|
35664
35671
|
const speaksAs = opts.session ?? opts.resume ?? sessionId();
|
|
35665
35672
|
const instance = randomUUID4();
|
|
@@ -35720,7 +35727,7 @@ ${event.message}`, state, rail, { log: opts.log });
|
|
|
35720
35727
|
stop2();
|
|
35721
35728
|
return;
|
|
35722
35729
|
} else if (carried) runningAgain();
|
|
35723
|
-
|
|
35730
|
+
clock4.nudge("rest");
|
|
35724
35731
|
}
|
|
35725
35732
|
}
|
|
35726
35733
|
session = startSession({
|
|
@@ -35739,13 +35746,13 @@ ${event.message}`, state, rail, { log: opts.log });
|
|
|
35739
35746
|
},
|
|
35740
35747
|
onEvent: (event) => void handle(event).catch((err) => opts.log(`\u26A0 ${err.message}`))
|
|
35741
35748
|
});
|
|
35742
|
-
void pump(session, state, rail, { onIdle: () => running, beat:
|
|
35749
|
+
void pump(session, state, rail, { onIdle: () => running, beat: clock4, initialPrompt: opts.prompt, log: opts.log, ...inbox ? { inbox } : {} }).catch(
|
|
35743
35750
|
(e) => opts.log(`\u26A0 conversation loop stopped: ${e.message}`)
|
|
35744
35751
|
);
|
|
35745
35752
|
opts.log(`\u25B6 started ${opts.harness} in ${opts.cwd} (${opts.mode} mode)`);
|
|
35746
35753
|
function stop2() {
|
|
35747
35754
|
running = false;
|
|
35748
|
-
|
|
35755
|
+
clock4.nudge("wake");
|
|
35749
35756
|
tail = [];
|
|
35750
35757
|
cancelAsks(state);
|
|
35751
35758
|
session?.stop();
|
|
@@ -35757,7 +35764,7 @@ ${event.message}`, state, rail, { log: opts.log });
|
|
|
35757
35764
|
working: () => running && state.resting !== true,
|
|
35758
35765
|
// Paused by a usage limit, the activity line says so: the quiet place the pause is shown.
|
|
35759
35766
|
tail: () => state.paused ? [pausedLine(state.paused)] : [...tail],
|
|
35760
|
-
nudge: () =>
|
|
35767
|
+
nudge: () => clock4.nudge("wake"),
|
|
35761
35768
|
stop: stop2
|
|
35762
35769
|
};
|
|
35763
35770
|
}
|
package/dist/main.js
CHANGED
|
@@ -4858,8 +4858,8 @@ var ZodIssueCode = util.arrayToEnum([
|
|
|
4858
4858
|
"not_finite"
|
|
4859
4859
|
]);
|
|
4860
4860
|
var quotelessJson = (obj) => {
|
|
4861
|
-
const
|
|
4862
|
-
return
|
|
4861
|
+
const json = JSON.stringify(obj, null, 2);
|
|
4862
|
+
return json.replace(/"([^"]+)":/g, "$1:");
|
|
4863
4863
|
};
|
|
4864
4864
|
var ZodError = class _ZodError extends Error {
|
|
4865
4865
|
get errors() {
|
|
@@ -8669,6 +8669,24 @@ function parentOf(pid) {
|
|
|
8669
8669
|
return void 0;
|
|
8670
8670
|
}
|
|
8671
8671
|
}
|
|
8672
|
+
var CODEX_PARENT = /(^|\/)\.codex\/|CodexCLI\.app|(^|[\/\s])codex(\s|$)/;
|
|
8673
|
+
var codexParent;
|
|
8674
|
+
function underCodex() {
|
|
8675
|
+
if (codexParent !== void 0) return codexParent;
|
|
8676
|
+
codexParent = false;
|
|
8677
|
+
if (process.platform === "win32") return codexParent;
|
|
8678
|
+
for (const pid of ancestors()) {
|
|
8679
|
+
try {
|
|
8680
|
+
const command = execFileSync("ps", ["-o", "command=", "-p", String(pid)], { encoding: "utf8", timeout: 1e3 });
|
|
8681
|
+
if (CODEX_PARENT.test(command)) {
|
|
8682
|
+
codexParent = true;
|
|
8683
|
+
break;
|
|
8684
|
+
}
|
|
8685
|
+
} catch {
|
|
8686
|
+
}
|
|
8687
|
+
}
|
|
8688
|
+
return codexParent;
|
|
8689
|
+
}
|
|
8672
8690
|
var lineage;
|
|
8673
8691
|
function ancestors() {
|
|
8674
8692
|
if (lineage) return lineage;
|
|
@@ -8726,7 +8744,8 @@ function parseSessionRecord(text) {
|
|
|
8726
8744
|
return void 0;
|
|
8727
8745
|
}
|
|
8728
8746
|
function sessionId() {
|
|
8729
|
-
return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ??
|
|
8747
|
+
return envSession("PAIGY_SESSION_ID") ?? claudeConversation() ?? envSession("CLAUDE_CODE_SESSION_ID") ?? envSession("CODEX_THREAD_ID") ?? envSession("CODEX_SESSION_ID") ?? // A Codex thread that was handed no id is its own agent, not the folder's (`underCodex`).
|
|
8748
|
+
(underCodex() ? INSTANCE_ID : WORKSPACE_ID);
|
|
8730
8749
|
}
|
|
8731
8750
|
async function reach(url, init) {
|
|
8732
8751
|
return send(url, init, sessionId());
|
|
@@ -10453,11 +10472,17 @@ var messageBase = {
|
|
|
10453
10472
|
obligationIds: external_exports.array(id)
|
|
10454
10473
|
};
|
|
10455
10474
|
var BrainMessageSchema = external_exports.union([
|
|
10456
|
-
|
|
10475
|
+
// A MESSAGE TO THE PERSON KEEPS ITS SENTENCES (turns.md): the talker writes them one by one, and each is
|
|
10476
|
+
// its own unit of speech (`<cycle>:<key>:<n>`). `text` is the same words joined, for every reader of a
|
|
10477
|
+
// message's words. Absent on results written before sentences.
|
|
10478
|
+
external_exports.object({ ...messageBase, to: external_exports.object({ kind: external_exports.literal("user") }).strict(), sentences: external_exports.array(external_exports.string().min(1)).min(1).optional() }).strict(),
|
|
10457
10479
|
external_exports.object({
|
|
10458
10480
|
...messageBase,
|
|
10459
10481
|
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
10460
|
-
call: external_exports.object({ callId: id, listen: external_exports.literal(true) }).strict().optional()
|
|
10482
|
+
call: external_exports.object({ callId: id, listen: external_exports.literal(true) }).strict().optional(),
|
|
10483
|
+
// THE PERSON ASKED TO BE CALLED BACK ONCE THIS AGENT'S WORK IS DONE (turns.md, step 0): the agent owes
|
|
10484
|
+
// the call, and its next contact about it rings them (`public.callbacks`).
|
|
10485
|
+
callback: external_exports.literal(true).optional()
|
|
10461
10486
|
}).strict()
|
|
10462
10487
|
]);
|
|
10463
10488
|
var BrainSearchSchema = external_exports.object({
|
|
@@ -10512,9 +10537,12 @@ var str2 = external_exports.string();
|
|
|
10512
10537
|
var strs2 = external_exports.array(external_exports.string());
|
|
10513
10538
|
var TalkerReplySchema = external_exports.object({
|
|
10514
10539
|
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
10515
|
-
* or an agent's handle; `
|
|
10516
|
-
*
|
|
10517
|
-
|
|
10540
|
+
* or an agent's handle; `sentences` is what a message to the person says, one short sentence each
|
|
10541
|
+
* ([] to an agent); `text` is what a message to an agent says ("" to the person); `about` names
|
|
10542
|
+
* handles; `blocks` is the item a question to an agent must be answered before ("" for none);
|
|
10543
|
+
* `callback` is true on a message to the agent doing work the person asked to be called back about
|
|
10544
|
+
* once it is done (false otherwise): that agent then owes the call (turns.md, step 0). */
|
|
10545
|
+
messages: external_exports.array(external_exports.object({ key: str2, to: str2, sentences: strs2, text: str2, about: strs2, blocks: str2, callback: external_exports.boolean() }).strict()),
|
|
10518
10546
|
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
10519
10547
|
then: external_exports.enum(["listen", "hold", "end"]),
|
|
10520
10548
|
/** The person's replies to items (replies, owner 2026-10-07): the item's handle, the chosen option
|
|
@@ -10638,42 +10666,6 @@ var LIVE_MS = 3 * 6e4;
|
|
|
10638
10666
|
var WORKING_MS = 60 * 6e4;
|
|
10639
10667
|
var WORKING_TIER_MS = 2 * 60 * 6e4;
|
|
10640
10668
|
var RECENT_TIER_MS = 24 * 60 * 6e4;
|
|
10641
|
-
var json = external_exports.lazy(() => external_exports.union([
|
|
10642
|
-
external_exports.string(),
|
|
10643
|
-
external_exports.number().finite(),
|
|
10644
|
-
external_exports.boolean(),
|
|
10645
|
-
external_exports.null(),
|
|
10646
|
-
external_exports.array(json),
|
|
10647
|
-
external_exports.record(json)
|
|
10648
|
-
]));
|
|
10649
|
-
var clock = external_exports.number().int().nonnegative().safe();
|
|
10650
|
-
var HeardEventSchema = external_exports.object({
|
|
10651
|
-
eventId: external_exports.string().uuid(),
|
|
10652
|
-
source: external_exports.enum(["phone", "bot"]),
|
|
10653
|
-
sequence: clock,
|
|
10654
|
-
kind: external_exports.string().min(1),
|
|
10655
|
-
phoneAtMs: clock.optional(),
|
|
10656
|
-
botAtMs: clock.optional(),
|
|
10657
|
-
payload: external_exports.record(json)
|
|
10658
|
-
}).strict();
|
|
10659
|
-
var HeardCursorSchema = HeardEventSchema.pick({ source: true, sequence: true, eventId: true });
|
|
10660
|
-
var HeardPageSchema = external_exports.object({
|
|
10661
|
-
events: external_exports.array(HeardEventSchema).max(200),
|
|
10662
|
-
next: HeardCursorSchema.nullable()
|
|
10663
|
-
}).strict();
|
|
10664
|
-
var MAX_EVENTS = 50;
|
|
10665
|
-
var MAX_BYTES = 8e4;
|
|
10666
|
-
var batchBytes = (events) => {
|
|
10667
|
-
let bytes = 0;
|
|
10668
|
-
for (const char of JSON.stringify({ events })) {
|
|
10669
|
-
const point = char.codePointAt(0);
|
|
10670
|
-
bytes += point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
|
|
10671
|
-
}
|
|
10672
|
-
return bytes;
|
|
10673
|
-
};
|
|
10674
|
-
var HeardBatchSchema = external_exports.object({
|
|
10675
|
-
events: external_exports.array(HeardEventSchema).min(1).max(MAX_EVENTS)
|
|
10676
|
-
}).strict().refine((value) => batchBytes(value.events) <= MAX_BYTES, "heard_batch_too_large");
|
|
10677
10669
|
var ContextSchema = external_exports.object({
|
|
10678
10670
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
10679
10671
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
@@ -10998,6 +10990,10 @@ var AgendaTurnSchema = external_exports.object({
|
|
|
10998
10990
|
/** The spoken sentences of the turn, in order. No count: how long a turn is is the brain's call
|
|
10999
10991
|
* (owner, 2026-09-25), and a count here refused whole plans. */
|
|
11000
10992
|
info: external_exports.array(external_exports.string().min(1)).default([]),
|
|
10993
|
+
/** THE ID OF EACH SENTENCE, when the plan names them (turns.md): a talker message's sentences are its
|
|
10994
|
+
* `info`, one piece each, and `units[i]` is the id the bot's line receipt carries for `info[i]`
|
|
10995
|
+
* (`<cycle>:<key>:<n>`), so what was heard is known per sentence. Absent on every other turn. */
|
|
10996
|
+
units: external_exports.array(external_exports.string().min(1)).optional(),
|
|
11001
10997
|
question: external_exports.string().min(1).nullable(),
|
|
11002
10998
|
/** True on the one turn carrying the agent's own declared question. */
|
|
11003
10999
|
asks: external_exports.boolean().optional(),
|
|
@@ -11234,8 +11230,8 @@ var MissedCallSchema = external_exports.enum([
|
|
|
11234
11230
|
"inbox",
|
|
11235
11231
|
"dismiss"
|
|
11236
11232
|
]);
|
|
11237
|
-
var
|
|
11238
|
-
var QUIET = ` Nothing rings from ${
|
|
11233
|
+
var clock = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
11234
|
+
var QUIET = ` Nothing rings from ${clock(NIGHT.from)} to ${clock(NIGHT.to)} your time; the count waits for morning.`;
|
|
11239
11235
|
var BrokerTuningSchema = external_exports.object({
|
|
11240
11236
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
11241
11237
|
ackVerbosity: external_exports.enum(["normal", "none"]).optional(),
|
|
@@ -11572,6 +11568,13 @@ var QueueItemSchema = external_exports.object({
|
|
|
11572
11568
|
* can see (`replies`, `questions[].answeredAt`) miss a spontaneous note entirely — a `request`
|
|
11573
11569
|
* Entry with no `about_id` is in neither. */
|
|
11574
11570
|
lastPersonAt: external_exports.string().nullable().optional(),
|
|
11571
|
+
/** EACH SIDE'S NEWEST WORD IN THE LAST DAY (owner, 2026-10-13, the Work tab's order): the person's
|
|
11572
|
+
* (`yours`) and the agents' (`theirs`), each null when that side wrote nothing on it in 24 hours.
|
|
11573
|
+
* `latest` holds one Entry, so whichever side wrote first is hidden there; Work orders a Goal by
|
|
11574
|
+
* these two and draws the side it was placed by under its title. Optional, so hand-built queues
|
|
11575
|
+
* and a door older than 20261013045542 need not spell them. */
|
|
11576
|
+
yours: GoalLatestSchema.nullable().optional(),
|
|
11577
|
+
theirs: GoalLatestSchema.nullable().optional(),
|
|
11575
11578
|
/** WHAT THIS ROW IS, IN TWELVE CHARACTERS (#2928) — the hash of every other field on it, stamped
|
|
11576
11579
|
* by the one projection that builds the row (`apps/api/src/goal/queue.ts`). It is how the
|
|
11577
11580
|
* incremental read knows a row has not moved: the phone echoes back the revs it holds
|
|
@@ -11845,10 +11848,20 @@ var CallRecapSchema = external_exports.object({
|
|
|
11845
11848
|
title: external_exports.string(),
|
|
11846
11849
|
owner: external_exports.string(),
|
|
11847
11850
|
state: external_exports.string(),
|
|
11851
|
+
/** Presented Entry content and its author, separately from the current Goal owner. */
|
|
11852
|
+
items: external_exports.array(external_exports.object({ entryId: external_exports.string(), author: external_exports.string(), text: external_exports.string(), summary: external_exports.string().nullable() })).optional(),
|
|
11848
11853
|
/** Whether the call put it to the person. An item it carried and never said has no row on the
|
|
11849
11854
|
* review (owner, 2026-10-08: "why do we get the third one when it didn't happen in the call?"). */
|
|
11850
11855
|
presented: external_exports.boolean(),
|
|
11851
|
-
|
|
11856
|
+
/** Whether THIS call created it — the third way a call touches work, beside carrying a request
|
|
11857
|
+
* there and filing words there (owner, 2026-10-08, Goal `5b4b1a0a`: "Show the new work, keep my
|
|
11858
|
+
* words under it"). Created work is never carried, so it is never `presented`; without this the
|
|
11859
|
+
* row is dropped by the "only what happened on the call" filter. False on a database before
|
|
11860
|
+
* 20261013080133. */
|
|
11861
|
+
created: external_exports.boolean(),
|
|
11862
|
+
/** `request` is the Entry that asked it — what a line's `about` names when the line answered or put
|
|
11863
|
+
* it off. Optional: an older API sent none. */
|
|
11864
|
+
questions: external_exports.array(external_exports.object({ id: external_exports.string().uuid(), state: external_exports.string(), title: external_exports.string(), request: external_exports.string().optional() })),
|
|
11852
11865
|
/** `words` is always what they SAID, verbatim — the record, never replaced. `summary` is what
|
|
11853
11866
|
* the line says in ten words (owner, 2026-10-07): the filer's, or the talker's for the answer it
|
|
11854
11867
|
* gave, so the row scans like a chosen option and their own words stay under it. Absent when
|
|
@@ -14262,11 +14275,17 @@ var messageBase2 = {
|
|
|
14262
14275
|
obligationIds: external_exports.array(id2)
|
|
14263
14276
|
};
|
|
14264
14277
|
var BrainMessageSchema2 = external_exports.union([
|
|
14265
|
-
|
|
14278
|
+
// A MESSAGE TO THE PERSON KEEPS ITS SENTENCES (turns.md): the talker writes them one by one, and each is
|
|
14279
|
+
// its own unit of speech (`<cycle>:<key>:<n>`). `text` is the same words joined, for every reader of a
|
|
14280
|
+
// message's words. Absent on results written before sentences.
|
|
14281
|
+
external_exports.object({ ...messageBase2, to: external_exports.object({ kind: external_exports.literal("user") }).strict(), sentences: external_exports.array(external_exports.string().min(1)).min(1).optional() }).strict(),
|
|
14266
14282
|
external_exports.object({
|
|
14267
14283
|
...messageBase2,
|
|
14268
14284
|
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
14269
|
-
call: external_exports.object({ callId: id2, listen: external_exports.literal(true) }).strict().optional()
|
|
14285
|
+
call: external_exports.object({ callId: id2, listen: external_exports.literal(true) }).strict().optional(),
|
|
14286
|
+
// THE PERSON ASKED TO BE CALLED BACK ONCE THIS AGENT'S WORK IS DONE (turns.md, step 0): the agent owes
|
|
14287
|
+
// the call, and its next contact about it rings them (`public.callbacks`).
|
|
14288
|
+
callback: external_exports.literal(true).optional()
|
|
14270
14289
|
}).strict()
|
|
14271
14290
|
]);
|
|
14272
14291
|
var BrainSearchSchema2 = external_exports.object({
|
|
@@ -14321,9 +14340,12 @@ var str22 = external_exports.string();
|
|
|
14321
14340
|
var strs22 = external_exports.array(external_exports.string());
|
|
14322
14341
|
var TalkerReplySchema2 = external_exports.object({
|
|
14323
14342
|
/** What to say and send, messages to the person first: spoken in the order written. `to` is "user"
|
|
14324
|
-
* or an agent's handle; `
|
|
14325
|
-
*
|
|
14326
|
-
|
|
14343
|
+
* or an agent's handle; `sentences` is what a message to the person says, one short sentence each
|
|
14344
|
+
* ([] to an agent); `text` is what a message to an agent says ("" to the person); `about` names
|
|
14345
|
+
* handles; `blocks` is the item a question to an agent must be answered before ("" for none);
|
|
14346
|
+
* `callback` is true on a message to the agent doing work the person asked to be called back about
|
|
14347
|
+
* once it is done (false otherwise): that agent then owes the call (turns.md, step 0). */
|
|
14348
|
+
messages: external_exports.array(external_exports.object({ key: str22, to: str22, sentences: strs22, text: str22, about: strs22, blocks: str22, callback: external_exports.boolean() }).strict()),
|
|
14327
14349
|
/** What the call does next: listen, hold (the person asked for a moment) or end (they asked to). */
|
|
14328
14350
|
then: external_exports.enum(["listen", "hold", "end"]),
|
|
14329
14351
|
/** The person's replies to items (replies, owner 2026-10-07): the item's handle, the chosen option
|
|
@@ -14458,42 +14480,6 @@ var WORKING_MS2 = 60 * 6e4;
|
|
|
14458
14480
|
var isWorking = (c, now) => !!c.lastWorkedAt && now - Date.parse(c.lastWorkedAt) < WORKING_MS2;
|
|
14459
14481
|
var WORKING_TIER_MS2 = 2 * 60 * 6e4;
|
|
14460
14482
|
var RECENT_TIER_MS2 = 24 * 60 * 6e4;
|
|
14461
|
-
var json2 = external_exports.lazy(() => external_exports.union([
|
|
14462
|
-
external_exports.string(),
|
|
14463
|
-
external_exports.number().finite(),
|
|
14464
|
-
external_exports.boolean(),
|
|
14465
|
-
external_exports.null(),
|
|
14466
|
-
external_exports.array(json2),
|
|
14467
|
-
external_exports.record(json2)
|
|
14468
|
-
]));
|
|
14469
|
-
var clock3 = external_exports.number().int().nonnegative().safe();
|
|
14470
|
-
var HeardEventSchema2 = external_exports.object({
|
|
14471
|
-
eventId: external_exports.string().uuid(),
|
|
14472
|
-
source: external_exports.enum(["phone", "bot"]),
|
|
14473
|
-
sequence: clock3,
|
|
14474
|
-
kind: external_exports.string().min(1),
|
|
14475
|
-
phoneAtMs: clock3.optional(),
|
|
14476
|
-
botAtMs: clock3.optional(),
|
|
14477
|
-
payload: external_exports.record(json2)
|
|
14478
|
-
}).strict();
|
|
14479
|
-
var HeardCursorSchema2 = HeardEventSchema2.pick({ source: true, sequence: true, eventId: true });
|
|
14480
|
-
var HeardPageSchema2 = external_exports.object({
|
|
14481
|
-
events: external_exports.array(HeardEventSchema2).max(200),
|
|
14482
|
-
next: HeardCursorSchema2.nullable()
|
|
14483
|
-
}).strict();
|
|
14484
|
-
var MAX_EVENTS2 = 50;
|
|
14485
|
-
var MAX_BYTES2 = 8e4;
|
|
14486
|
-
var batchBytes2 = (events) => {
|
|
14487
|
-
let bytes = 0;
|
|
14488
|
-
for (const char of JSON.stringify({ events })) {
|
|
14489
|
-
const point = char.codePointAt(0);
|
|
14490
|
-
bytes += point < 128 ? 1 : point < 2048 ? 2 : point < 65536 ? 3 : 4;
|
|
14491
|
-
}
|
|
14492
|
-
return bytes;
|
|
14493
|
-
};
|
|
14494
|
-
var HeardBatchSchema2 = external_exports.object({
|
|
14495
|
-
events: external_exports.array(HeardEventSchema2).min(1).max(MAX_EVENTS2)
|
|
14496
|
-
}).strict().refine((value) => batchBytes2(value.events) <= MAX_BYTES2, "heard_batch_too_large");
|
|
14497
14483
|
var ContextSchema2 = external_exports.object({
|
|
14498
14484
|
title: external_exports.string().min(1).describe("One-line headline of what you need (required, non-empty)."),
|
|
14499
14485
|
description: external_exports.array(external_exports.string().min(1)).describe(
|
|
@@ -14818,6 +14804,10 @@ var AgendaTurnSchema2 = external_exports.object({
|
|
|
14818
14804
|
/** The spoken sentences of the turn, in order. No count: how long a turn is is the brain's call
|
|
14819
14805
|
* (owner, 2026-09-25), and a count here refused whole plans. */
|
|
14820
14806
|
info: external_exports.array(external_exports.string().min(1)).default([]),
|
|
14807
|
+
/** THE ID OF EACH SENTENCE, when the plan names them (turns.md): a talker message's sentences are its
|
|
14808
|
+
* `info`, one piece each, and `units[i]` is the id the bot's line receipt carries for `info[i]`
|
|
14809
|
+
* (`<cycle>:<key>:<n>`), so what was heard is known per sentence. Absent on every other turn. */
|
|
14810
|
+
units: external_exports.array(external_exports.string().min(1)).optional(),
|
|
14821
14811
|
question: external_exports.string().min(1).nullable(),
|
|
14822
14812
|
/** True on the one turn carrying the agent's own declared question. */
|
|
14823
14813
|
asks: external_exports.boolean().optional(),
|
|
@@ -15054,8 +15044,8 @@ var MissedCallSchema2 = external_exports.enum([
|
|
|
15054
15044
|
"inbox",
|
|
15055
15045
|
"dismiss"
|
|
15056
15046
|
]);
|
|
15057
|
-
var
|
|
15058
|
-
var QUIET2 = ` Nothing rings from ${
|
|
15047
|
+
var clock2 = (h) => h === 0 ? "midnight" : h === 12 ? "noon" : h < 12 ? `${h} am` : `${h - 12} pm`;
|
|
15048
|
+
var QUIET2 = ` Nothing rings from ${clock2(NIGHT2.from)} to ${clock2(NIGHT2.to)} your time; the count waits for morning.`;
|
|
15059
15049
|
var BrokerTuningSchema2 = external_exports.object({
|
|
15060
15050
|
/** 'none' = skip the spoken ack after a mapped answer (power users find it slow). */
|
|
15061
15051
|
ackVerbosity: external_exports.enum(["normal", "none"]).optional(),
|
|
@@ -15392,6 +15382,13 @@ var QueueItemSchema2 = external_exports.object({
|
|
|
15392
15382
|
* can see (`replies`, `questions[].answeredAt`) miss a spontaneous note entirely — a `request`
|
|
15393
15383
|
* Entry with no `about_id` is in neither. */
|
|
15394
15384
|
lastPersonAt: external_exports.string().nullable().optional(),
|
|
15385
|
+
/** EACH SIDE'S NEWEST WORD IN THE LAST DAY (owner, 2026-10-13, the Work tab's order): the person's
|
|
15386
|
+
* (`yours`) and the agents' (`theirs`), each null when that side wrote nothing on it in 24 hours.
|
|
15387
|
+
* `latest` holds one Entry, so whichever side wrote first is hidden there; Work orders a Goal by
|
|
15388
|
+
* these two and draws the side it was placed by under its title. Optional, so hand-built queues
|
|
15389
|
+
* and a door older than 20261013045542 need not spell them. */
|
|
15390
|
+
yours: GoalLatestSchema2.nullable().optional(),
|
|
15391
|
+
theirs: GoalLatestSchema2.nullable().optional(),
|
|
15395
15392
|
/** WHAT THIS ROW IS, IN TWELVE CHARACTERS (#2928) — the hash of every other field on it, stamped
|
|
15396
15393
|
* by the one projection that builds the row (`apps/api/src/goal/queue.ts`). It is how the
|
|
15397
15394
|
* incremental read knows a row has not moved: the phone echoes back the revs it holds
|
|
@@ -15663,10 +15660,20 @@ var CallRecapSchema2 = external_exports.object({
|
|
|
15663
15660
|
title: external_exports.string(),
|
|
15664
15661
|
owner: external_exports.string(),
|
|
15665
15662
|
state: external_exports.string(),
|
|
15663
|
+
/** Presented Entry content and its author, separately from the current Goal owner. */
|
|
15664
|
+
items: external_exports.array(external_exports.object({ entryId: external_exports.string(), author: external_exports.string(), text: external_exports.string(), summary: external_exports.string().nullable() })).optional(),
|
|
15666
15665
|
/** Whether the call put it to the person. An item it carried and never said has no row on the
|
|
15667
15666
|
* review (owner, 2026-10-08: "why do we get the third one when it didn't happen in the call?"). */
|
|
15668
15667
|
presented: external_exports.boolean(),
|
|
15669
|
-
|
|
15668
|
+
/** Whether THIS call created it — the third way a call touches work, beside carrying a request
|
|
15669
|
+
* there and filing words there (owner, 2026-10-08, Goal `5b4b1a0a`: "Show the new work, keep my
|
|
15670
|
+
* words under it"). Created work is never carried, so it is never `presented`; without this the
|
|
15671
|
+
* row is dropped by the "only what happened on the call" filter. False on a database before
|
|
15672
|
+
* 20261013080133. */
|
|
15673
|
+
created: external_exports.boolean(),
|
|
15674
|
+
/** `request` is the Entry that asked it — what a line's `about` names when the line answered or put
|
|
15675
|
+
* it off. Optional: an older API sent none. */
|
|
15676
|
+
questions: external_exports.array(external_exports.object({ id: external_exports.string().uuid(), state: external_exports.string(), title: external_exports.string(), request: external_exports.string().optional() })),
|
|
15670
15677
|
/** `words` is always what they SAID, verbatim — the record, never replaced. `summary` is what
|
|
15671
15678
|
* the line says in ten words (owner, 2026-10-07): the filer's, or the talker's for the answer it
|
|
15672
15679
|
* gave, so the row scans like a chosen option and their own words stay under it. Absent when
|
|
@@ -16632,9 +16639,9 @@ function limitIn(text, now) {
|
|
|
16632
16639
|
if (!line) return null;
|
|
16633
16640
|
const reset = resetOf(line, now);
|
|
16634
16641
|
if (reset !== null && reset > now && reset - now <= FARTHEST_MS) {
|
|
16635
|
-
return { until: reset + MARGIN_MS, resets: /resets\s+(?:at\s+)?(.+?)\s*(?:\(|$)/i.exec(line)?.[1]?.trim() ??
|
|
16642
|
+
return { until: reset + MARGIN_MS, resets: /resets\s+(?:at\s+)?(.+?)\s*(?:\(|$)/i.exec(line)?.[1]?.trim() ?? clock3(reset) };
|
|
16636
16643
|
}
|
|
16637
|
-
return { until: now + RETRY_MS2, resets:
|
|
16644
|
+
return { until: now + RETRY_MS2, resets: clock3(now + RETRY_MS2) };
|
|
16638
16645
|
}
|
|
16639
16646
|
function resetOf(line, now) {
|
|
16640
16647
|
const m = /resets\s+(?:at\s+)?(?:([a-z]{3})[a-z]*\s+(\d{1,2}),?\s+(?:at\s+)?)?(\d{1,2})(?::(\d{2}))?\s*(am|pm)\b(?:\s*\(([^)]+)\))?/i.exec(line);
|
|
@@ -16678,7 +16685,7 @@ function wallToEpoch(year, month, day, hour, minute, zone) {
|
|
|
16678
16685
|
const first = wall - offset(wall);
|
|
16679
16686
|
return wall - offset(first);
|
|
16680
16687
|
}
|
|
16681
|
-
function
|
|
16688
|
+
function clock3(t) {
|
|
16682
16689
|
return new Date(t).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit" }).replace(/\s?([AP])M$/i, (_, x) => `${x.toLowerCase()}m`);
|
|
16683
16690
|
}
|
|
16684
16691
|
var pausedLine = (limit) => `Paused by the usage limit until ${limit.resets}`;
|
|
@@ -16722,7 +16729,7 @@ function episodes(opts = {}) {
|
|
|
16722
16729
|
episode.called = true;
|
|
16723
16730
|
const rest = episode.paused.filter((n) => !episode.running.includes(n));
|
|
16724
16731
|
const text = [
|
|
16725
|
-
`Claude's usage limit paused ${names(episode.paused)} from ${
|
|
16732
|
+
`Claude's usage limit paused ${names(episode.paused)} from ${clock3(episode.since)}.`,
|
|
16726
16733
|
rest.length ? `It has reset: ${names(episode.running)} ${episode.running.length > 1 ? "are" : "is"} running again, and ${names(rest)} ${rest.length > 1 ? "haven't" : "hasn't"} started again yet.` : `It has reset, and ${episode.paused.length > 1 ? "they have all" : "it has"} carried on.`
|
|
16727
16734
|
].join(" ");
|
|
16728
16735
|
void call(text).then(
|
|
@@ -17287,7 +17294,7 @@ async function send2(session, state, text) {
|
|
|
17287
17294
|
}
|
|
17288
17295
|
}
|
|
17289
17296
|
async function pump(session, state, rail, opts) {
|
|
17290
|
-
const
|
|
17297
|
+
const clock4 = opts.beat ?? beat();
|
|
17291
17298
|
const now = opts.now ?? Date.now;
|
|
17292
17299
|
const counts = { wake: 0, rest: 0, safety: 0, skipped: 0 };
|
|
17293
17300
|
const tally = { noted: 0, seen: 0, announced: 0 };
|
|
@@ -17319,7 +17326,7 @@ async function pump(session, state, rail, opts) {
|
|
|
17319
17326
|
counts.wake = counts.rest = counts.safety = counts.skipped = tally.noted = tally.seen = tally.announced = tally.paused = 0;
|
|
17320
17327
|
since = now();
|
|
17321
17328
|
}
|
|
17322
|
-
cause = await
|
|
17329
|
+
cause = await clock4.next(state.asks?.size ? ASK_BEAT_MS : state.paused ? Math.max(1e3, Math.min(SAFETY_MS, state.paused.until - now())) : SAFETY_MS);
|
|
17323
17330
|
if (!await opts.onIdle()) return;
|
|
17324
17331
|
}
|
|
17325
17332
|
}
|
|
@@ -17329,7 +17336,7 @@ function runHarness(opts) {
|
|
|
17329
17336
|
let running = true;
|
|
17330
17337
|
let tail = [];
|
|
17331
17338
|
const state = { resting: true };
|
|
17332
|
-
const
|
|
17339
|
+
const clock4 = beat();
|
|
17333
17340
|
let session = null;
|
|
17334
17341
|
const speaksAs = opts.session ?? opts.resume ?? sessionId();
|
|
17335
17342
|
const instance = randomUUID4();
|
|
@@ -17390,7 +17397,7 @@ ${event.message}`, state, rail, { log: opts.log });
|
|
|
17390
17397
|
stop2();
|
|
17391
17398
|
return;
|
|
17392
17399
|
} else if (carried) runningAgain();
|
|
17393
|
-
|
|
17400
|
+
clock4.nudge("rest");
|
|
17394
17401
|
}
|
|
17395
17402
|
}
|
|
17396
17403
|
session = startSession({
|
|
@@ -17409,13 +17416,13 @@ ${event.message}`, state, rail, { log: opts.log });
|
|
|
17409
17416
|
},
|
|
17410
17417
|
onEvent: (event) => void handle(event).catch((err) => opts.log(`\u26A0 ${err.message}`))
|
|
17411
17418
|
});
|
|
17412
|
-
void pump(session, state, rail, { onIdle: () => running, beat:
|
|
17419
|
+
void pump(session, state, rail, { onIdle: () => running, beat: clock4, initialPrompt: opts.prompt, log: opts.log, ...inbox ? { inbox } : {} }).catch(
|
|
17413
17420
|
(e) => opts.log(`\u26A0 conversation loop stopped: ${e.message}`)
|
|
17414
17421
|
);
|
|
17415
17422
|
opts.log(`\u25B6 started ${opts.harness} in ${opts.cwd} (${opts.mode} mode)`);
|
|
17416
17423
|
function stop2() {
|
|
17417
17424
|
running = false;
|
|
17418
|
-
|
|
17425
|
+
clock4.nudge("wake");
|
|
17419
17426
|
tail = [];
|
|
17420
17427
|
cancelAsks(state);
|
|
17421
17428
|
session?.stop();
|
|
@@ -17427,7 +17434,7 @@ ${event.message}`, state, rail, { log: opts.log });
|
|
|
17427
17434
|
working: () => running && state.resting !== true,
|
|
17428
17435
|
// Paused by a usage limit, the activity line says so: the quiet place the pause is shown.
|
|
17429
17436
|
tail: () => state.paused ? [pausedLine(state.paused)] : [...tail],
|
|
17430
|
-
nudge: () =>
|
|
17437
|
+
nudge: () => clock4.nudge("wake"),
|
|
17431
17438
|
stop: stop2
|
|
17432
17439
|
};
|
|
17433
17440
|
}
|