@paigy/harness 0.3.33 → 0.3.35
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 +275 -196
- package/dist/main.js +273 -194
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1930,27 +1930,27 @@ var require_chunkstream = __commonJS({
|
|
|
1930
1930
|
this._buffers = null;
|
|
1931
1931
|
this.emit("close");
|
|
1932
1932
|
};
|
|
1933
|
-
ChunkStream.prototype._processReadAllowingLess = function(
|
|
1933
|
+
ChunkStream.prototype._processReadAllowingLess = function(read3) {
|
|
1934
1934
|
this._reads.shift();
|
|
1935
1935
|
let smallerBuf = this._buffers[0];
|
|
1936
|
-
if (smallerBuf.length >
|
|
1937
|
-
this._buffered -=
|
|
1938
|
-
this._buffers[0] = smallerBuf.slice(
|
|
1939
|
-
|
|
1936
|
+
if (smallerBuf.length > read3.length) {
|
|
1937
|
+
this._buffered -= read3.length;
|
|
1938
|
+
this._buffers[0] = smallerBuf.slice(read3.length);
|
|
1939
|
+
read3.func.call(this, smallerBuf.slice(0, read3.length));
|
|
1940
1940
|
} else {
|
|
1941
1941
|
this._buffered -= smallerBuf.length;
|
|
1942
1942
|
this._buffers.shift();
|
|
1943
|
-
|
|
1943
|
+
read3.func.call(this, smallerBuf);
|
|
1944
1944
|
}
|
|
1945
1945
|
};
|
|
1946
|
-
ChunkStream.prototype._processRead = function(
|
|
1946
|
+
ChunkStream.prototype._processRead = function(read3) {
|
|
1947
1947
|
this._reads.shift();
|
|
1948
1948
|
let pos = 0;
|
|
1949
1949
|
let count = 0;
|
|
1950
|
-
let data = Buffer.alloc(
|
|
1951
|
-
while (pos <
|
|
1950
|
+
let data = Buffer.alloc(read3.length);
|
|
1951
|
+
while (pos < read3.length) {
|
|
1952
1952
|
let buf = this._buffers[count++];
|
|
1953
|
-
let len = Math.min(buf.length,
|
|
1953
|
+
let len = Math.min(buf.length, read3.length - pos);
|
|
1954
1954
|
buf.copy(data, pos, 0, len);
|
|
1955
1955
|
pos += len;
|
|
1956
1956
|
if (len !== buf.length) {
|
|
@@ -1960,17 +1960,17 @@ var require_chunkstream = __commonJS({
|
|
|
1960
1960
|
if (count > 0) {
|
|
1961
1961
|
this._buffers.splice(0, count);
|
|
1962
1962
|
}
|
|
1963
|
-
this._buffered -=
|
|
1964
|
-
|
|
1963
|
+
this._buffered -= read3.length;
|
|
1964
|
+
read3.func.call(this, data);
|
|
1965
1965
|
};
|
|
1966
1966
|
ChunkStream.prototype._process = function() {
|
|
1967
1967
|
try {
|
|
1968
1968
|
while (this._buffered > 0 && this._reads && this._reads.length > 0) {
|
|
1969
|
-
let
|
|
1970
|
-
if (
|
|
1971
|
-
this._processReadAllowingLess(
|
|
1972
|
-
} else if (this._buffered >=
|
|
1973
|
-
this._processRead(
|
|
1969
|
+
let read3 = this._reads[0];
|
|
1970
|
+
if (read3.allowLess) {
|
|
1971
|
+
this._processReadAllowingLess(read3);
|
|
1972
|
+
} else if (this._buffered >= read3.length) {
|
|
1973
|
+
this._processRead(read3);
|
|
1974
1974
|
} else {
|
|
1975
1975
|
break;
|
|
1976
1976
|
}
|
|
@@ -3595,12 +3595,12 @@ var require_sync_reader = __commonJS({
|
|
|
3595
3595
|
};
|
|
3596
3596
|
SyncReader.prototype.process = function() {
|
|
3597
3597
|
while (this._reads.length > 0 && this._buffer.length) {
|
|
3598
|
-
let
|
|
3599
|
-
if (this._buffer.length && (this._buffer.length >=
|
|
3598
|
+
let read3 = this._reads[0];
|
|
3599
|
+
if (this._buffer.length && (this._buffer.length >= read3.length || read3.allowLess)) {
|
|
3600
3600
|
this._reads.shift();
|
|
3601
3601
|
let buf = this._buffer;
|
|
3602
|
-
this._buffer = buf.slice(
|
|
3603
|
-
|
|
3602
|
+
this._buffer = buf.slice(read3.length);
|
|
3603
|
+
read3.func.call(this, buf.slice(0, read3.length));
|
|
3604
3604
|
} else {
|
|
3605
3605
|
break;
|
|
3606
3606
|
}
|
|
@@ -9987,7 +9987,7 @@ var AskInputSchema = external_exports.object({
|
|
|
9987
9987
|
'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.'
|
|
9988
9988
|
),
|
|
9989
9989
|
answers: external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
|
|
9990
|
-
"Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them.
|
|
9990
|
+
"Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them. parentId is optional here: the question's own Goal is used. The reply is sent to them as it is; to also ask something new, send that as its own ask."
|
|
9991
9991
|
)
|
|
9992
9992
|
}).strict();
|
|
9993
9993
|
var StartContactSchema = external_exports.object({
|
|
@@ -9995,9 +9995,17 @@ var StartContactSchema = external_exports.object({
|
|
|
9995
9995
|
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."),
|
|
9996
9996
|
channel: external_exports.enum(["notification", "call"]).default("notification")
|
|
9997
9997
|
}).strict();
|
|
9998
|
-
var
|
|
9998
|
+
var ReceiveContactSchema = external_exports.object({
|
|
9999
|
+
wait: external_exports.boolean().optional().describe(
|
|
10000
|
+
"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)."
|
|
10001
|
+
),
|
|
10002
|
+
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
10003
|
+
"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 (an ask with `answers`), never acknowledged away: that id is refused until it is answered."
|
|
10004
|
+
)
|
|
10005
|
+
}).strict();
|
|
10006
|
+
var ContactSchema = external_exports.union([StartContactSchema, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict(), ReceiveContactSchema]);
|
|
9999
10007
|
var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
10000
|
-
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none starts a new Goal of yours. Notification returns immediately; collect
|
|
10008
|
+
var CONTACT_DESCRIPTION = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none starts a new Goal of yours. Notification returns immediately; collect answers by receiving (below). On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. One question per 'ask'; several questions are several objects in 'asks'. Each ask is sent exactly as written, with no reading in between: a bundled ask arrives as one card, so separate questions are separate asks. An ask with no options that is not blocking is a report, never a claim on them, so no answer is owed and none should be awaited. A report reaches the person only when it answers something they asked you, or once the Goal is done; any other report is recorded as the Goal's progress and nobody is notified. So when the work is finished, mark the Goal done first, then send one message saying what is done and anything they need to do or check. On a Goal whose report card is still open, a report that does reach them is added to that card, with no new push. Send options (or waiting:'hard') when you actually need an answer. 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'). select:'many' makes the card a checklist, for independent options they may want several of; select:'one' (the default) a pick, for alternatives. The person can always answer in their own words, so never add an 'Other' option. If the person is already on a call, a contact that reaches them joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.\n\nRECEIVING: contact with no asks sends nothing and returns `events`, a limited batch of what is addressed to you (not a history page): `question`, a Question you owe (answer it with an ask whose `answers` is 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`; claim_goal starts it) and your work gone quiet (`stalled`).";
|
|
10001
10009
|
var CreateGoalSchema = external_exports.object({
|
|
10002
10010
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
10003
10011
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -10017,10 +10025,6 @@ var CreateGoalSchema = external_exports.object({
|
|
|
10017
10025
|
* repo name. Delegated work inherits this from its parent Goal when omitted. */
|
|
10018
10026
|
repo: external_exports.string().trim().min(1).max(200).optional()
|
|
10019
10027
|
});
|
|
10020
|
-
var CreateGoalToolSchema = CreateGoalSchema.extend({
|
|
10021
|
-
idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
10022
|
-
}).strict();
|
|
10023
|
-
var CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
|
|
10024
10028
|
var UpdateGoalSchema = external_exports.object({
|
|
10025
10029
|
revision: external_exports.number().int().positive(),
|
|
10026
10030
|
changes: external_exports.object({
|
|
@@ -10044,7 +10048,65 @@ var UpdateGoalSchema = external_exports.object({
|
|
|
10044
10048
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
10045
10049
|
operationId: external_exports.string().uuid().optional()
|
|
10046
10050
|
}).strict();
|
|
10047
|
-
var UpdateGoalToolSchema =
|
|
10051
|
+
var UpdateGoalToolSchema = external_exports.object({
|
|
10052
|
+
goalId: external_exports.string().uuid(),
|
|
10053
|
+
revision: UpdateGoalSchema.shape.revision,
|
|
10054
|
+
changes: UpdateGoalSchema.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
|
|
10055
|
+
reason: UpdateGoalSchema.shape.reason
|
|
10056
|
+
}).strict();
|
|
10057
|
+
var changedGoal = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
10058
|
+
var 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.");
|
|
10059
|
+
var goalOutcome = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
|
|
10060
|
+
var CreateChange = external_exports.object({
|
|
10061
|
+
kind: external_exports.literal("create"),
|
|
10062
|
+
title: goalTitle,
|
|
10063
|
+
outcome: goalOutcome,
|
|
10064
|
+
ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as who_is_working shows it) or the person's. Omitted: you."),
|
|
10065
|
+
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
10066
|
+
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
10067
|
+
}).strict();
|
|
10068
|
+
var EditChange = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal, title: goalTitle.optional(), outcome: goalOutcome.optional() }).strict();
|
|
10069
|
+
var StateChange = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal, state: external_exports.enum(["open", "completed", "canceled"]).describe(
|
|
10070
|
+
"completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
|
|
10071
|
+
) }).strict();
|
|
10072
|
+
var 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();
|
|
10073
|
+
var DeferChange = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
10074
|
+
"Postpone it until this instant (its owner is woken then), or null to take the postponement back."
|
|
10075
|
+
) }).strict();
|
|
10076
|
+
var MoveChange = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
10077
|
+
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
10078
|
+
) }).strict();
|
|
10079
|
+
var DependencyChange = external_exports.object({
|
|
10080
|
+
kind: external_exports.literal("dependency"),
|
|
10081
|
+
change: external_exports.enum(["add", "remove"]),
|
|
10082
|
+
goalId: changedGoal,
|
|
10083
|
+
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
10084
|
+
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
10085
|
+
reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
|
|
10086
|
+
}).strict();
|
|
10087
|
+
var read = { revision: external_exports.number().int().positive().optional() };
|
|
10088
|
+
var GoalChangeSchema = external_exports.discriminatedUnion("kind", [
|
|
10089
|
+
CreateChange,
|
|
10090
|
+
EditChange.extend(read),
|
|
10091
|
+
StateChange.extend(read),
|
|
10092
|
+
AssignChange.extend(read),
|
|
10093
|
+
DeferChange.extend(read),
|
|
10094
|
+
MoveChange.extend(read),
|
|
10095
|
+
DependencyChange
|
|
10096
|
+
]);
|
|
10097
|
+
var editNames = (changes, ctx) => changes.forEach((c, i) => {
|
|
10098
|
+
if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
|
|
10099
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
|
|
10100
|
+
}
|
|
10101
|
+
});
|
|
10102
|
+
var ManageGoalsSchema = external_exports.object({
|
|
10103
|
+
requestId: external_exports.string().uuid().optional(),
|
|
10104
|
+
changes: external_exports.array(GoalChangeSchema).min(1).max(50)
|
|
10105
|
+
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
10106
|
+
var ManageGoalsToolSchema = external_exports.object({
|
|
10107
|
+
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.")
|
|
10108
|
+
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
10109
|
+
var 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_joined, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls; edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until, or null); 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 a Goal you own or have written on. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
10048
10110
|
var ClaimGoalSchema = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
10049
10111
|
var GetGoalSchema = external_exports.object({
|
|
10050
10112
|
goalId: external_exports.string().uuid(),
|
|
@@ -10057,27 +10119,30 @@ var GetGoalSchema = external_exports.object({
|
|
|
10057
10119
|
diagnose: external_exports.boolean().optional()
|
|
10058
10120
|
}).strict();
|
|
10059
10121
|
var GET_GOAL_DESCRIPTION = "Read one Goal without claiming 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.";
|
|
10060
|
-
var UPDATE_GOAL_DESCRIPTION =
|
|
10061
|
-
var 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
|
|
10062
|
-
var
|
|
10063
|
-
|
|
10122
|
+
var 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.";
|
|
10123
|
+
var 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).";
|
|
10124
|
+
var SearchToolSchema = external_exports.object({
|
|
10125
|
+
query: external_exports.string().trim().min(1).max(500),
|
|
10126
|
+
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
10127
|
+
goalId: external_exports.string().uuid().optional(),
|
|
10128
|
+
limit: external_exports.number().int().min(1).max(20).optional()
|
|
10129
|
+
}).strict();
|
|
10130
|
+
var SEARCH_DESCRIPTION = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and Answers (found by their Question or by the words that gave them). query is words to look for; records sharing more of its words rank first, and exact names work. types narrows it to entry, goal and/or answer (default: all three). goalId searches under one Goal: its Entries, its Questions' Answers, and it and its immediate children. limit is matches per type, 1 to 20 (default 8). Read-only. Each match carries its whole saved words, its ID and its links (an Answer carries its Question, the choice made and the Entries that support it); `omitted` counts what matched but was left out, so narrow the words or add a goalId to see it. Nothing found is not proof that nothing exists; a refused search says why. Sealed (encrypted) content is never searched or returned.";
|
|
10131
|
+
var WhoIsWorkingSchema = external_exports.object({}).strict();
|
|
10064
10132
|
var AGENT_TOOLS = [
|
|
10065
|
-
{ 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(
|
|
10133
|
+
{ 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) },
|
|
10066
10134
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
10067
|
-
{ name: "
|
|
10068
|
-
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(CreateGoalToolSchema) },
|
|
10135
|
+
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(ManageGoalsToolSchema) },
|
|
10069
10136
|
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(ClaimGoalSchema) },
|
|
10070
10137
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(GetGoalSchema) },
|
|
10071
|
-
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) }
|
|
10138
|
+
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) },
|
|
10139
|
+
{ name: "search", description: SEARCH_DESCRIPTION, inputSchema: mcpInputSchema(SearchToolSchema) }
|
|
10072
10140
|
];
|
|
10073
10141
|
var AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
10074
10142
|
var id = external_exports.string().uuid();
|
|
10075
10143
|
var key = external_exports.string().min(1).max(40);
|
|
10076
10144
|
var participant = external_exports.string().regex(/^(human|agent):.+$/, "a participant ID such as agent:<uuid>");
|
|
10077
|
-
var SourceSchema = external_exports.object({
|
|
10078
|
-
entryId: id,
|
|
10079
|
-
span: external_exports.object({ start: external_exports.number().int().min(0), end: external_exports.number().int().min(1) }).strict().refine((s) => s.end > s.start, "a span ends after it starts").optional()
|
|
10080
|
-
}).strict();
|
|
10145
|
+
var SourceSchema = external_exports.object({ entryId: id }).strict();
|
|
10081
10146
|
var ResultRefSchema = external_exports.union([external_exports.object({ id }).strict(), external_exports.object({ local: key }).strict()]);
|
|
10082
10147
|
var NodeRefSchema = external_exports.object({ type: external_exports.enum(["goal", "question"]), id }).strict();
|
|
10083
10148
|
var DependencySchema = external_exports.object({
|
|
@@ -10102,17 +10167,6 @@ var existingGoalChanges = [
|
|
|
10102
10167
|
reason: external_exports.string().max(500).optional()
|
|
10103
10168
|
}).strict()
|
|
10104
10169
|
];
|
|
10105
|
-
var GoalChangeSchema = external_exports.union([
|
|
10106
|
-
external_exports.object({
|
|
10107
|
-
kind: external_exports.literal("create"),
|
|
10108
|
-
title: external_exports.string().min(1).max(120),
|
|
10109
|
-
outcome: external_exports.string().min(1),
|
|
10110
|
-
ownerId: participant,
|
|
10111
|
-
parentGoalId: id.optional(),
|
|
10112
|
-
sourceEntryIds: external_exports.array(id)
|
|
10113
|
-
}).strict(),
|
|
10114
|
-
...existingGoalChanges
|
|
10115
|
-
]);
|
|
10116
10170
|
var BrainGoalChangeSchema = external_exports.union([
|
|
10117
10171
|
// newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
|
|
10118
10172
|
external_exports.object({
|
|
@@ -10169,7 +10223,7 @@ var BrainMessageSchema = external_exports.union([
|
|
|
10169
10223
|
external_exports.object({ ...messageBase, to: external_exports.object({ kind: external_exports.literal("user") }).strict() }).strict(),
|
|
10170
10224
|
external_exports.object({
|
|
10171
10225
|
...messageBase,
|
|
10172
|
-
to: external_exports.object({ kind: external_exports.literal("
|
|
10226
|
+
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
10173
10227
|
call: external_exports.object({ callId: id, listen: external_exports.literal(true) }).strict().optional()
|
|
10174
10228
|
}).strict()
|
|
10175
10229
|
]);
|
|
@@ -10199,7 +10253,7 @@ var strs = external_exports.array(external_exports.string());
|
|
|
10199
10253
|
var CompactResultSchema = external_exports.object({
|
|
10200
10254
|
next: external_exports.object({ say: strs, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs, reason: str, instructions: strs }).strict(),
|
|
10201
10255
|
messages: external_exports.array(external_exports.object({ key: str, to: str, text: str, about: strs, entries: strs, owed: strs, inviteToCall: external_exports.boolean() }).strict()),
|
|
10202
|
-
entries: external_exports.array(external_exports.object({ key: str, from: str,
|
|
10256
|
+
entries: external_exports.array(external_exports.object({ key: str, from: str, on: strs }).strict()),
|
|
10203
10257
|
answers: external_exports.array(external_exports.object({ question: str, entries: strs, summary: str, picked: strs }).strict()),
|
|
10204
10258
|
changes: external_exports.array(external_exports.object({
|
|
10205
10259
|
key: str,
|
|
@@ -10496,7 +10550,7 @@ var AwaitItemSchema = external_exports.discriminatedUnion("type", [
|
|
|
10496
10550
|
/** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
|
|
10497
10551
|
* post-feedback revision, #633) — the user will never answer this id. Stop
|
|
10498
10552
|
* awaiting it; the live ask is the thread's newest turn (await that one, or
|
|
10499
|
-
* re-orient via
|
|
10553
|
+
* re-orient via contact({})). */
|
|
10500
10554
|
external_exports.object({
|
|
10501
10555
|
type: external_exports.literal("superseded"),
|
|
10502
10556
|
parentId: external_exports.string(),
|
|
@@ -10947,39 +11001,22 @@ var ReassignResultSchema = external_exports.object({
|
|
|
10947
11001
|
moved: external_exports.object({ asks: external_exports.number(), answered: external_exports.number(), requests: external_exports.number(), goals: external_exports.number(), callbacks: external_exports.number() }),
|
|
10948
11002
|
parentId: external_exports.string().nullable()
|
|
10949
11003
|
});
|
|
10950
|
-
var
|
|
10951
|
-
var
|
|
11004
|
+
var LessonStateSchema = external_exports.enum(["active", "proposed", "retired"]);
|
|
11005
|
+
var LessonViewSchema = external_exports.object({
|
|
10952
11006
|
id: external_exports.string(),
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
/** The
|
|
10956
|
-
|
|
10957
|
-
|
|
10958
|
-
|
|
10959
|
-
rationale: external_exports.string().nullable(),
|
|
10960
|
-
/** Where the ruling lives: a repo/workspace, or 'global'. */
|
|
10961
|
-
scope: external_exports.string(),
|
|
10962
|
-
ring: MoveRingSchema,
|
|
10963
|
-
/** True = the user pinned it with `always` (travel granted by hand, not by evidence). */
|
|
11007
|
+
text: external_exports.string(),
|
|
11008
|
+
state: LessonStateSchema,
|
|
11009
|
+
/** The Goal it is scoped to; null = the whole account. */
|
|
11010
|
+
scopeGoalId: external_exports.string().nullable(),
|
|
11011
|
+
goalTitle: external_exports.string().nullable(),
|
|
11012
|
+
version: external_exports.number(),
|
|
10964
11013
|
pinned: external_exports.boolean(),
|
|
10965
|
-
/**
|
|
10966
|
-
|
|
10967
|
-
|
|
10968
|
-
|
|
10969
|
-
|
|
10970
|
-
|
|
10971
|
-
lastUsedAt: external_exports.string().nullable(),
|
|
10972
|
-
/** How many asks it has answered. Instrumentation — deliberately NOT an input to the
|
|
10973
|
-
* evidence curve: firing says the question keeps arising, not that the ruling is right. */
|
|
10974
|
-
usedCount: external_exports.number(),
|
|
10975
|
-
/** Ledger: outcomes that said it held up. Saturating — the tenth is worth almost nothing. */
|
|
10976
|
-
confirms: external_exports.number(),
|
|
10977
|
-
/** Ledger: contradictions, in signal units (a full override = 1, weaker signals less).
|
|
10978
|
-
* Linear and priced above the entire confirmation budget, so any full counter wins. */
|
|
10979
|
-
counters: external_exports.number(),
|
|
10980
|
-
/** The agent that asked the question this move came from, when known. Null for a move
|
|
10981
|
-
* distilled from a clarify ruling (those carry no agent) or one whose source rows are gone. */
|
|
10982
|
-
learnedFrom: external_exports.object({ id: external_exports.string(), name: external_exports.string() }).nullable()
|
|
11014
|
+
/** When the person last wrote its text themselves. */
|
|
11015
|
+
editedAt: external_exports.string().nullable(),
|
|
11016
|
+
createdAt: external_exports.string(),
|
|
11017
|
+
updatedAt: external_exports.string(),
|
|
11018
|
+
/** The Entries it came from, oldest first; `words` is null when an Entry has none to show (sealed). */
|
|
11019
|
+
sources: external_exports.array(external_exports.object({ entryId: external_exports.string(), words: external_exports.string().nullable(), at: external_exports.string() }))
|
|
10983
11020
|
});
|
|
10984
11021
|
var QueueQuestionSchema = external_exports.object({
|
|
10985
11022
|
/** The decision need's id — what an answer is accepted against. */
|
|
@@ -11243,7 +11280,7 @@ var HostDecisionSchema = external_exports.object({
|
|
|
11243
11280
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
11244
11281
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
11245
11282
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
11246
|
-
/** When that work last moved (`claimable.since` on `
|
|
11283
|
+
/** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
|
|
11247
11284
|
since: external_exports.string().datetime().nullable().optional(),
|
|
11248
11285
|
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
11249
11286
|
said: external_exports.string().max(300).optional()
|
|
@@ -11586,28 +11623,28 @@ var authToken = (explicit) => explicit ?? tokenOverride ?? readToken();
|
|
|
11586
11623
|
async function fail(what, res) {
|
|
11587
11624
|
throw new ApiError(what, res.status, await res.text());
|
|
11588
11625
|
}
|
|
11589
|
-
async function
|
|
11626
|
+
async function manageGoals(input, opts = {}) {
|
|
11590
11627
|
const token = authToken(opts.token) ?? "";
|
|
11591
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals`, {
|
|
11628
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/manage`, {
|
|
11592
11629
|
method: "POST",
|
|
11593
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${token}
|
|
11630
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
11594
11631
|
body: JSON.stringify(input)
|
|
11595
11632
|
}));
|
|
11596
|
-
if (!res.ok) await fail("
|
|
11633
|
+
if (!res.ok) await fail("manage_goals", res);
|
|
11597
11634
|
return await res.json();
|
|
11598
11635
|
}
|
|
11599
11636
|
async function claimGoal(goalId, opts = {}) {
|
|
11600
11637
|
const token = authToken(opts.token) ?? "";
|
|
11601
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}
|
|
11638
|
+
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 } : {}) }));
|
|
11602
11639
|
if (!res.ok) await fail("claim_goal", res);
|
|
11603
11640
|
return await res.json();
|
|
11604
11641
|
}
|
|
11605
|
-
async function getGoal(goalId, opts = {},
|
|
11642
|
+
async function getGoal(goalId, opts = {}, read3 = {}) {
|
|
11606
11643
|
const token = authToken(opts.token) ?? "";
|
|
11607
|
-
const query = [
|
|
11644
|
+
const query = [read3.history ? "history=1" : "", read3.diagnose ? "diagnose=1" : ""].filter(Boolean).join("&");
|
|
11608
11645
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}${query ? `?${query}` : ""}`, {
|
|
11609
11646
|
method: "GET",
|
|
11610
|
-
headers: { authorization: `Bearer ${token}
|
|
11647
|
+
headers: { authorization: `Bearer ${token}` }
|
|
11611
11648
|
}));
|
|
11612
11649
|
if (!res.ok) await fail("get_goal", res);
|
|
11613
11650
|
return await res.json();
|
|
@@ -11615,7 +11652,7 @@ async function getGoal(goalId, opts = {}, read = {}) {
|
|
|
11615
11652
|
async function updateGoal(goalId, input, opts = {}) {
|
|
11616
11653
|
const token = authToken(opts.token) ?? "";
|
|
11617
11654
|
const operationId = input.operationId ?? randomUUID2();
|
|
11618
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}
|
|
11655
|
+
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 }) }));
|
|
11619
11656
|
if (!res.ok) await fail("update_goal", res);
|
|
11620
11657
|
return await res.json();
|
|
11621
11658
|
}
|
|
@@ -11694,7 +11731,7 @@ async function listNotes(opts = {}) {
|
|
|
11694
11731
|
}
|
|
11695
11732
|
async function listConnections(opts = {}) {
|
|
11696
11733
|
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
|
|
11697
|
-
headers: { authorization: `Bearer ${authToken(opts.token)}
|
|
11734
|
+
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
11698
11735
|
}));
|
|
11699
11736
|
if (!res.ok) throw new Error(`list_connections failed: ${res.status} ${await res.text()}`);
|
|
11700
11737
|
return await res.json();
|
|
@@ -11758,13 +11795,14 @@ function currentRepo(cwd = process.cwd()) {
|
|
|
11758
11795
|
}
|
|
11759
11796
|
return asked;
|
|
11760
11797
|
}
|
|
11761
|
-
var NOT_SENT = "Recorded as progress, not sent: nobody was notified.
|
|
11798
|
+
var 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 message saying what is done and anything they need to do or check.";
|
|
11762
11799
|
var 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, with or without a Goal.";
|
|
11763
11800
|
async function contact(input, opts = {}) {
|
|
11764
11801
|
const parsed = ContactSchema.parse(input);
|
|
11802
|
+
if (!("asks" in parsed) && !("deliveryId" in parsed)) throw new Error("contact with nothing to send receives: call receiveContact");
|
|
11765
11803
|
opts.signal?.throwIfAborted();
|
|
11766
11804
|
const send22 = opts.reach ?? reach;
|
|
11767
|
-
const headers = { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}
|
|
11805
|
+
const headers = { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}` };
|
|
11768
11806
|
let deliveryId;
|
|
11769
11807
|
let deliveries = [];
|
|
11770
11808
|
let recorded = [];
|
|
@@ -11809,7 +11847,7 @@ async function contact(input, opts = {}) {
|
|
|
11809
11847
|
const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id: id22, deliveryId: deliveryId2, goalId }) => ({ ...id22 ? { id: id22 } : {}, deliveryId: deliveryId2, goalId }));
|
|
11810
11848
|
const joinedCard = deliveries[0]?.joinedCard === true;
|
|
11811
11849
|
const joinedCall = deliveries[0]?.joinedCall === true;
|
|
11812
|
-
const
|
|
11850
|
+
const read3 = async (signal2) => {
|
|
11813
11851
|
const res = await ensureAuthed(await send22(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
11814
11852
|
if (!res.ok) await fail("read_delivery", res);
|
|
11815
11853
|
const one = await res.json();
|
|
@@ -11823,14 +11861,14 @@ async function contact(input, opts = {}) {
|
|
|
11823
11861
|
};
|
|
11824
11862
|
};
|
|
11825
11863
|
const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
|
|
11826
|
-
if (opts.waits === false) return
|
|
11864
|
+
if (opts.waits === false) return read3(opts.signal);
|
|
11827
11865
|
const window = AbortSignal.timeout(AWAIT_WINDOW_MS);
|
|
11828
11866
|
const signal = opts.signal ? AbortSignal.any([opts.signal, window]) : window;
|
|
11829
11867
|
let latest;
|
|
11830
11868
|
try {
|
|
11831
11869
|
while (true) {
|
|
11832
11870
|
signal.throwIfAborted();
|
|
11833
|
-
latest = await
|
|
11871
|
+
latest = await read3(signal);
|
|
11834
11872
|
if (settled(latest)) return latest;
|
|
11835
11873
|
await sleep2(5e3, void 0, { signal });
|
|
11836
11874
|
}
|
|
@@ -11840,11 +11878,11 @@ async function contact(input, opts = {}) {
|
|
|
11840
11878
|
throw error;
|
|
11841
11879
|
}
|
|
11842
11880
|
}
|
|
11843
|
-
async function
|
|
11881
|
+
async function receive(opts = {}) {
|
|
11844
11882
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries`, {
|
|
11845
|
-
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}
|
|
11883
|
+
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}` }
|
|
11846
11884
|
}));
|
|
11847
|
-
if (!res.ok) await fail("
|
|
11885
|
+
if (!res.ok) await fail("receive", res);
|
|
11848
11886
|
return await res.json();
|
|
11849
11887
|
}
|
|
11850
11888
|
var HEARTBEAT_MS = 25e3;
|
|
@@ -12794,7 +12832,7 @@ function proven(pid, procStart, deps) {
|
|
|
12794
12832
|
function localHolderPids(deps = {}) {
|
|
12795
12833
|
const dir = deps.dir ?? join6(process.env.CLAUDE_CONFIG_DIR?.trim() || join6(homedir6(), ".claude"), "sessions");
|
|
12796
12834
|
const list = deps.list ?? ((d) => readdirSync2(d));
|
|
12797
|
-
const
|
|
12835
|
+
const read3 = deps.read ?? ((f) => readFileSync4(f, "utf8"));
|
|
12798
12836
|
const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
|
|
12799
12837
|
const held = /* @__PURE__ */ new Map();
|
|
12800
12838
|
let files;
|
|
@@ -12807,7 +12845,7 @@ function localHolderPids(deps = {}) {
|
|
|
12807
12845
|
if (!/^\d+\.json$/.test(file)) continue;
|
|
12808
12846
|
let row;
|
|
12809
12847
|
try {
|
|
12810
|
-
row = JSON.parse(
|
|
12848
|
+
row = JSON.parse(read3(join6(dir, file)));
|
|
12811
12849
|
} catch {
|
|
12812
12850
|
continue;
|
|
12813
12851
|
}
|
|
@@ -12839,7 +12877,7 @@ function descendsFrom(pid, ancestor, parent = psParent) {
|
|
|
12839
12877
|
function localHolders(deps = {}) {
|
|
12840
12878
|
const dir = deps.dir ?? join6(process.env.CLAUDE_CONFIG_DIR?.trim() || join6(homedir6(), ".claude"), "sessions");
|
|
12841
12879
|
const list = deps.list ?? ((d) => readdirSync2(d));
|
|
12842
|
-
const
|
|
12880
|
+
const read3 = deps.read ?? ((f) => readFileSync4(f, "utf8"));
|
|
12843
12881
|
const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
|
|
12844
12882
|
const held = /* @__PURE__ */ new Map();
|
|
12845
12883
|
let files;
|
|
@@ -12852,7 +12890,7 @@ function localHolders(deps = {}) {
|
|
|
12852
12890
|
if (!/^\d+\.json$/.test(file)) continue;
|
|
12853
12891
|
let row;
|
|
12854
12892
|
try {
|
|
12855
|
-
row = JSON.parse(
|
|
12893
|
+
row = JSON.parse(read3(join6(dir, file)));
|
|
12856
12894
|
} catch {
|
|
12857
12895
|
continue;
|
|
12858
12896
|
}
|
|
@@ -14329,7 +14367,7 @@ var AskInputSchema2 = external_exports.object({
|
|
|
14329
14367
|
'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.'
|
|
14330
14368
|
),
|
|
14331
14369
|
answers: external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
|
|
14332
|
-
"Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them.
|
|
14370
|
+
"Your reply answers a question the person asked you: the id the conversation shows for it (8 characters or whole). Their question closes with this reply as its answer, and any decision of yours it was holding back goes back to them. parentId is optional here: the question's own Goal is used. The reply is sent to them as it is; to also ask something new, send that as its own ask."
|
|
14333
14371
|
)
|
|
14334
14372
|
}).strict();
|
|
14335
14373
|
var StartContactSchema2 = external_exports.object({
|
|
@@ -14337,9 +14375,17 @@ var StartContactSchema2 = external_exports.object({
|
|
|
14337
14375
|
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."),
|
|
14338
14376
|
channel: external_exports.enum(["notification", "call"]).default("notification")
|
|
14339
14377
|
}).strict();
|
|
14340
|
-
var
|
|
14378
|
+
var ReceiveContactSchema2 = external_exports.object({
|
|
14379
|
+
wait: external_exports.boolean().optional().describe(
|
|
14380
|
+
"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)."
|
|
14381
|
+
),
|
|
14382
|
+
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
14383
|
+
"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 (an ask with `answers`), never acknowledged away: that id is refused until it is answered."
|
|
14384
|
+
)
|
|
14385
|
+
}).strict();
|
|
14386
|
+
var ContactSchema2 = external_exports.union([StartContactSchema2, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict(), ReceiveContactSchema2]);
|
|
14341
14387
|
var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
|
|
14342
|
-
var CONTACT_DESCRIPTION2 = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none starts a new Goal of yours. Notification returns immediately; collect
|
|
14388
|
+
var CONTACT_DESCRIPTION2 = "Contact the user with one or more asks/questions. Pass an array of asks (each with 'ask', optional 'options', 'select', 'id', 'parentId', 'repo'), plus channel:'notification'|'call', and waiting:'none'|'hard'. An ask that names a Goal (parentId) goes onto that Goal; one that names none starts a new Goal of yours. Notification returns immediately; collect answers by receiving (below). On stdio, a Call holds one cancellable ~45s window; continue with ONLY {deliveryId}. One question per 'ask'; several questions are several objects in 'asks'. Each ask is sent exactly as written, with no reading in between: a bundled ask arrives as one card, so separate questions are separate asks. An ask with no options that is not blocking is a report, never a claim on them, so no answer is owed and none should be awaited. A report reaches the person only when it answers something they asked you, or once the Goal is done; any other report is recorded as the Goal's progress and nobody is notified. So when the work is finished, mark the Goal done first, then send one message saying what is done and anything they need to do or check. On a Goal whose report card is still open, a report that does reach them is added to that card, with no new push. Send options (or waiting:'hard') when you actually need an answer. 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'). select:'many' makes the card a checklist, for independent options they may want several of; select:'one' (the default) a pick, for alternatives. The person can always answer in their own words, so never add an 'Other' option. If the person is already on a call, a contact that reaches them joins that call automatically \u2014 whatever channel you asked for, with no ring \u2014 and the Delivery it returns IS that call: reread it with contact({deliveryId}) to see everything answered on it so far, and contact again while it is live to add information or a further question to the same call.\n\nRECEIVING: contact with no asks sends nothing and returns `events`, a limited batch of what is addressed to you (not a history page): `question`, a Question you owe (answer it with an ask whose `answers` is 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`; claim_goal starts it) and your work gone quiet (`stalled`).";
|
|
14343
14389
|
var CreateGoalSchema2 = external_exports.object({
|
|
14344
14390
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
14345
14391
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -14359,10 +14405,6 @@ var CreateGoalSchema2 = external_exports.object({
|
|
|
14359
14405
|
* repo name. Delegated work inherits this from its parent Goal when omitted. */
|
|
14360
14406
|
repo: external_exports.string().trim().min(1).max(200).optional()
|
|
14361
14407
|
});
|
|
14362
|
-
var CreateGoalToolSchema2 = CreateGoalSchema2.extend({
|
|
14363
|
-
idempotencyKey: CreateGoalSchema2.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
14364
|
-
}).strict();
|
|
14365
|
-
var CREATE_GOAL_DESCRIPTION2 = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
|
|
14366
14408
|
var UpdateGoalSchema2 = external_exports.object({
|
|
14367
14409
|
revision: external_exports.number().int().positive(),
|
|
14368
14410
|
changes: external_exports.object({
|
|
@@ -14386,7 +14428,65 @@ var UpdateGoalSchema2 = external_exports.object({
|
|
|
14386
14428
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
14387
14429
|
operationId: external_exports.string().uuid().optional()
|
|
14388
14430
|
}).strict();
|
|
14389
|
-
var UpdateGoalToolSchema2 =
|
|
14431
|
+
var UpdateGoalToolSchema2 = external_exports.object({
|
|
14432
|
+
goalId: external_exports.string().uuid(),
|
|
14433
|
+
revision: UpdateGoalSchema2.shape.revision,
|
|
14434
|
+
changes: UpdateGoalSchema2.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
|
|
14435
|
+
reason: UpdateGoalSchema2.shape.reason
|
|
14436
|
+
}).strict();
|
|
14437
|
+
var changedGoal2 = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
14438
|
+
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.");
|
|
14439
|
+
var goalOutcome2 = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
|
|
14440
|
+
var CreateChange2 = external_exports.object({
|
|
14441
|
+
kind: external_exports.literal("create"),
|
|
14442
|
+
title: goalTitle2,
|
|
14443
|
+
outcome: goalOutcome2,
|
|
14444
|
+
ownerId: external_exports.string().trim().min(1).optional().describe("Who owns the work: an agent's participant (as who_is_working shows it) or the person's. Omitted: you."),
|
|
14445
|
+
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
14446
|
+
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
14447
|
+
}).strict();
|
|
14448
|
+
var EditChange2 = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal2, title: goalTitle2.optional(), outcome: goalOutcome2.optional() }).strict();
|
|
14449
|
+
var StateChange2 = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal2, state: external_exports.enum(["open", "completed", "canceled"]).describe(
|
|
14450
|
+
"completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
|
|
14451
|
+
) }).strict();
|
|
14452
|
+
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();
|
|
14453
|
+
var DeferChange2 = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal2, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
14454
|
+
"Postpone it until this instant (its owner is woken then), or null to take the postponement back."
|
|
14455
|
+
) }).strict();
|
|
14456
|
+
var MoveChange2 = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal2, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
14457
|
+
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
14458
|
+
) }).strict();
|
|
14459
|
+
var DependencyChange2 = external_exports.object({
|
|
14460
|
+
kind: external_exports.literal("dependency"),
|
|
14461
|
+
change: external_exports.enum(["add", "remove"]),
|
|
14462
|
+
goalId: changedGoal2,
|
|
14463
|
+
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
14464
|
+
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
14465
|
+
reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
|
|
14466
|
+
}).strict();
|
|
14467
|
+
var read2 = { revision: external_exports.number().int().positive().optional() };
|
|
14468
|
+
var GoalChangeSchema2 = external_exports.discriminatedUnion("kind", [
|
|
14469
|
+
CreateChange2,
|
|
14470
|
+
EditChange2.extend(read2),
|
|
14471
|
+
StateChange2.extend(read2),
|
|
14472
|
+
AssignChange2.extend(read2),
|
|
14473
|
+
DeferChange2.extend(read2),
|
|
14474
|
+
MoveChange2.extend(read2),
|
|
14475
|
+
DependencyChange2
|
|
14476
|
+
]);
|
|
14477
|
+
var editNames2 = (changes, ctx) => changes.forEach((c, i) => {
|
|
14478
|
+
if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
|
|
14479
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
|
|
14480
|
+
}
|
|
14481
|
+
});
|
|
14482
|
+
var ManageGoalsSchema2 = external_exports.object({
|
|
14483
|
+
requestId: external_exports.string().uuid().optional(),
|
|
14484
|
+
changes: external_exports.array(GoalChangeSchema2).min(1).max(50)
|
|
14485
|
+
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
14486
|
+
var ManageGoalsToolSchema2 = external_exports.object({
|
|
14487
|
+
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.")
|
|
14488
|
+
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
14489
|
+
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_joined, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls; edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until, or null); 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 a Goal you own or have written on. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
14390
14490
|
var ClaimGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
14391
14491
|
var GetGoalSchema2 = external_exports.object({
|
|
14392
14492
|
goalId: external_exports.string().uuid(),
|
|
@@ -14399,27 +14499,30 @@ var GetGoalSchema2 = external_exports.object({
|
|
|
14399
14499
|
diagnose: external_exports.boolean().optional()
|
|
14400
14500
|
}).strict();
|
|
14401
14501
|
var GET_GOAL_DESCRIPTION2 = "Read one Goal without claiming 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.";
|
|
14402
|
-
var UPDATE_GOAL_DESCRIPTION2 =
|
|
14403
|
-
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
|
|
14404
|
-
var
|
|
14405
|
-
|
|
14502
|
+
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.";
|
|
14503
|
+
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).";
|
|
14504
|
+
var SearchToolSchema2 = external_exports.object({
|
|
14505
|
+
query: external_exports.string().trim().min(1).max(500),
|
|
14506
|
+
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
14507
|
+
goalId: external_exports.string().uuid().optional(),
|
|
14508
|
+
limit: external_exports.number().int().min(1).max(20).optional()
|
|
14509
|
+
}).strict();
|
|
14510
|
+
var SEARCH_DESCRIPTION2 = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and Answers (found by their Question or by the words that gave them). query is words to look for; records sharing more of its words rank first, and exact names work. types narrows it to entry, goal and/or answer (default: all three). goalId searches under one Goal: its Entries, its Questions' Answers, and it and its immediate children. limit is matches per type, 1 to 20 (default 8). Read-only. Each match carries its whole saved words, its ID and its links (an Answer carries its Question, the choice made and the Entries that support it); `omitted` counts what matched but was left out, so narrow the words or add a goalId to see it. Nothing found is not proof that nothing exists; a refused search says why. Sealed (encrypted) content is never searched or returned.";
|
|
14511
|
+
var WhoIsWorkingSchema2 = external_exports.object({}).strict();
|
|
14406
14512
|
var AGENT_TOOLS2 = [
|
|
14407
|
-
{ 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(
|
|
14513
|
+
{ 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) },
|
|
14408
14514
|
{ name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
|
|
14409
|
-
{ name: "
|
|
14410
|
-
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(CreateGoalToolSchema2) },
|
|
14515
|
+
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(ManageGoalsToolSchema2) },
|
|
14411
14516
|
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(ClaimGoalSchema2) },
|
|
14412
14517
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(GetGoalSchema2) },
|
|
14413
|
-
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(UpdateGoalToolSchema2) }
|
|
14518
|
+
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(UpdateGoalToolSchema2) },
|
|
14519
|
+
{ name: "search", description: SEARCH_DESCRIPTION2, inputSchema: mcpInputSchema2(SearchToolSchema2) }
|
|
14414
14520
|
];
|
|
14415
14521
|
var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
|
|
14416
14522
|
var id2 = external_exports.string().uuid();
|
|
14417
14523
|
var key2 = external_exports.string().min(1).max(40);
|
|
14418
14524
|
var participant2 = external_exports.string().regex(/^(human|agent):.+$/, "a participant ID such as agent:<uuid>");
|
|
14419
|
-
var SourceSchema2 = external_exports.object({
|
|
14420
|
-
entryId: id2,
|
|
14421
|
-
span: external_exports.object({ start: external_exports.number().int().min(0), end: external_exports.number().int().min(1) }).strict().refine((s) => s.end > s.start, "a span ends after it starts").optional()
|
|
14422
|
-
}).strict();
|
|
14525
|
+
var SourceSchema2 = external_exports.object({ entryId: id2 }).strict();
|
|
14423
14526
|
var ResultRefSchema2 = external_exports.union([external_exports.object({ id: id2 }).strict(), external_exports.object({ local: key2 }).strict()]);
|
|
14424
14527
|
var NodeRefSchema2 = external_exports.object({ type: external_exports.enum(["goal", "question"]), id: id2 }).strict();
|
|
14425
14528
|
var DependencySchema2 = external_exports.object({
|
|
@@ -14444,17 +14547,6 @@ var existingGoalChanges2 = [
|
|
|
14444
14547
|
reason: external_exports.string().max(500).optional()
|
|
14445
14548
|
}).strict()
|
|
14446
14549
|
];
|
|
14447
|
-
var GoalChangeSchema2 = external_exports.union([
|
|
14448
|
-
external_exports.object({
|
|
14449
|
-
kind: external_exports.literal("create"),
|
|
14450
|
-
title: external_exports.string().min(1).max(120),
|
|
14451
|
-
outcome: external_exports.string().min(1),
|
|
14452
|
-
ownerId: participant2,
|
|
14453
|
-
parentGoalId: id2.optional(),
|
|
14454
|
-
sourceEntryIds: external_exports.array(id2)
|
|
14455
|
-
}).strict(),
|
|
14456
|
-
...existingGoalChanges2
|
|
14457
|
-
]);
|
|
14458
14550
|
var BrainGoalChangeSchema2 = external_exports.union([
|
|
14459
14551
|
// newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
|
|
14460
14552
|
external_exports.object({
|
|
@@ -14511,7 +14603,7 @@ var BrainMessageSchema2 = external_exports.union([
|
|
|
14511
14603
|
external_exports.object({ ...messageBase2, to: external_exports.object({ kind: external_exports.literal("user") }).strict() }).strict(),
|
|
14512
14604
|
external_exports.object({
|
|
14513
14605
|
...messageBase2,
|
|
14514
|
-
to: external_exports.object({ kind: external_exports.literal("
|
|
14606
|
+
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
14515
14607
|
call: external_exports.object({ callId: id2, listen: external_exports.literal(true) }).strict().optional()
|
|
14516
14608
|
}).strict()
|
|
14517
14609
|
]);
|
|
@@ -14541,7 +14633,7 @@ var strs2 = external_exports.array(external_exports.string());
|
|
|
14541
14633
|
var CompactResultSchema2 = external_exports.object({
|
|
14542
14634
|
next: external_exports.object({ say: strs2, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs2, reason: str2, instructions: strs2 }).strict(),
|
|
14543
14635
|
messages: external_exports.array(external_exports.object({ key: str2, to: str2, text: str2, about: strs2, entries: strs2, owed: strs2, inviteToCall: external_exports.boolean() }).strict()),
|
|
14544
|
-
entries: external_exports.array(external_exports.object({ key: str2, from: str2,
|
|
14636
|
+
entries: external_exports.array(external_exports.object({ key: str2, from: str2, on: strs2 }).strict()),
|
|
14545
14637
|
answers: external_exports.array(external_exports.object({ question: str2, entries: strs2, summary: str2, picked: strs2 }).strict()),
|
|
14546
14638
|
changes: external_exports.array(external_exports.object({
|
|
14547
14639
|
key: str2,
|
|
@@ -14855,7 +14947,7 @@ var AwaitItemSchema2 = external_exports.discriminatedUnion("type", [
|
|
|
14855
14947
|
/** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
|
|
14856
14948
|
* post-feedback revision, #633) — the user will never answer this id. Stop
|
|
14857
14949
|
* awaiting it; the live ask is the thread's newest turn (await that one, or
|
|
14858
|
-
* re-orient via
|
|
14950
|
+
* re-orient via contact({})). */
|
|
14859
14951
|
external_exports.object({
|
|
14860
14952
|
type: external_exports.literal("superseded"),
|
|
14861
14953
|
parentId: external_exports.string(),
|
|
@@ -15306,39 +15398,22 @@ var ReassignResultSchema2 = external_exports.object({
|
|
|
15306
15398
|
moved: external_exports.object({ asks: external_exports.number(), answered: external_exports.number(), requests: external_exports.number(), goals: external_exports.number(), callbacks: external_exports.number() }),
|
|
15307
15399
|
parentId: external_exports.string().nullable()
|
|
15308
15400
|
});
|
|
15309
|
-
var
|
|
15310
|
-
var
|
|
15401
|
+
var LessonStateSchema2 = external_exports.enum(["active", "proposed", "retired"]);
|
|
15402
|
+
var LessonViewSchema2 = external_exports.object({
|
|
15311
15403
|
id: external_exports.string(),
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
/** The
|
|
15315
|
-
|
|
15316
|
-
|
|
15317
|
-
|
|
15318
|
-
rationale: external_exports.string().nullable(),
|
|
15319
|
-
/** Where the ruling lives: a repo/workspace, or 'global'. */
|
|
15320
|
-
scope: external_exports.string(),
|
|
15321
|
-
ring: MoveRingSchema2,
|
|
15322
|
-
/** True = the user pinned it with `always` (travel granted by hand, not by evidence). */
|
|
15404
|
+
text: external_exports.string(),
|
|
15405
|
+
state: LessonStateSchema2,
|
|
15406
|
+
/** The Goal it is scoped to; null = the whole account. */
|
|
15407
|
+
scopeGoalId: external_exports.string().nullable(),
|
|
15408
|
+
goalTitle: external_exports.string().nullable(),
|
|
15409
|
+
version: external_exports.number(),
|
|
15323
15410
|
pinned: external_exports.boolean(),
|
|
15324
|
-
/**
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
|
|
15329
|
-
|
|
15330
|
-
lastUsedAt: external_exports.string().nullable(),
|
|
15331
|
-
/** How many asks it has answered. Instrumentation — deliberately NOT an input to the
|
|
15332
|
-
* evidence curve: firing says the question keeps arising, not that the ruling is right. */
|
|
15333
|
-
usedCount: external_exports.number(),
|
|
15334
|
-
/** Ledger: outcomes that said it held up. Saturating — the tenth is worth almost nothing. */
|
|
15335
|
-
confirms: external_exports.number(),
|
|
15336
|
-
/** Ledger: contradictions, in signal units (a full override = 1, weaker signals less).
|
|
15337
|
-
* Linear and priced above the entire confirmation budget, so any full counter wins. */
|
|
15338
|
-
counters: external_exports.number(),
|
|
15339
|
-
/** The agent that asked the question this move came from, when known. Null for a move
|
|
15340
|
-
* distilled from a clarify ruling (those carry no agent) or one whose source rows are gone. */
|
|
15341
|
-
learnedFrom: external_exports.object({ id: external_exports.string(), name: external_exports.string() }).nullable()
|
|
15411
|
+
/** When the person last wrote its text themselves. */
|
|
15412
|
+
editedAt: external_exports.string().nullable(),
|
|
15413
|
+
createdAt: external_exports.string(),
|
|
15414
|
+
updatedAt: external_exports.string(),
|
|
15415
|
+
/** The Entries it came from, oldest first; `words` is null when an Entry has none to show (sealed). */
|
|
15416
|
+
sources: external_exports.array(external_exports.object({ entryId: external_exports.string(), words: external_exports.string().nullable(), at: external_exports.string() }))
|
|
15342
15417
|
});
|
|
15343
15418
|
var QueueQuestionSchema2 = external_exports.object({
|
|
15344
15419
|
/** The decision need's id — what an answer is accepted against. */
|
|
@@ -15600,7 +15675,7 @@ var HostDecisionSchema2 = external_exports.object({
|
|
|
15600
15675
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
15601
15676
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
15602
15677
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
15603
|
-
/** When that work last moved (`claimable.since` on `
|
|
15678
|
+
/** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
|
|
15604
15679
|
since: external_exports.string().datetime().nullable().optional(),
|
|
15605
15680
|
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
15606
15681
|
said: external_exports.string().max(300).optional()
|
|
@@ -15823,7 +15898,7 @@ function sameTail(a, b) {
|
|
|
15823
15898
|
}
|
|
15824
15899
|
|
|
15825
15900
|
// src/run.ts
|
|
15826
|
-
import { randomUUID as
|
|
15901
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
15827
15902
|
|
|
15828
15903
|
// src/harness/session.ts
|
|
15829
15904
|
import { spawn } from "child_process";
|
|
@@ -16434,8 +16509,13 @@ function railFor(opts) {
|
|
|
16434
16509
|
update: (goalId, input) => updateGoal(goalId, input, opts),
|
|
16435
16510
|
// One read and back: the pump owns the waiting, so a Call must not hold a window here.
|
|
16436
16511
|
contact: (input) => contact(input, { ...opts, waits: false }),
|
|
16437
|
-
create: (input) =>
|
|
16438
|
-
|
|
16512
|
+
create: async (input) => {
|
|
16513
|
+
const made = await manageGoals({ changes: [{ kind: "create", ...input }] }, opts);
|
|
16514
|
+
const goal = made.goals.find((g) => g.goalId === made.results[0]?.goalId);
|
|
16515
|
+
if (!goal) throw new Error(`manage_goals create failed: ${made.results[0]?.error ?? "no goal"}`);
|
|
16516
|
+
return { goalId: goal.goalId, revision: goal.revision };
|
|
16517
|
+
},
|
|
16518
|
+
waiting: () => receive(opts)
|
|
16439
16519
|
};
|
|
16440
16520
|
}
|
|
16441
16521
|
function cancelAsks(state) {
|
|
@@ -16564,7 +16644,6 @@ ${event.result?.trim() || "No result reported."}`, state, rail, opts);
|
|
|
16564
16644
|
}
|
|
16565
16645
|
|
|
16566
16646
|
// src/paigy/conversation.ts
|
|
16567
|
-
import { randomUUID as randomUUID5 } from "crypto";
|
|
16568
16647
|
var HARNESS_INSTRUCTION = "You are running as an unattended background harness agent; your user reaches you through Paigy and is not at this terminal. Nothing wakes you after your turn ends but the person, so wait on CI or a deploy inside the turn. The person never sees your turn's final message: it is kept as progress on this Goal. Anything the person needs \u2014 a question, a result, a blocker \u2014 you send through Paigy's contact tool, once; the harness sends nothing on your behalf. What the person says later arrives with the Goal it was said on named in front of it; answer them on that Goal (its id as the contact's parentId).";
|
|
16569
16648
|
var SAFETY_MS = 6e4;
|
|
16570
16649
|
var ASK_BEAT_MS = 5e3;
|
|
@@ -16682,23 +16761,23 @@ async function gather(state, rail, held) {
|
|
|
16682
16761
|
const moved = movedBelow(held, state);
|
|
16683
16762
|
for (const { goal, since } of moved) look2(goal.goalId, "subtree", goal.title, since);
|
|
16684
16763
|
const heard = [];
|
|
16685
|
-
const
|
|
16764
|
+
const read3 = /* @__PURE__ */ new Set();
|
|
16686
16765
|
for (const [goalId, { since, ...found }] of looks) {
|
|
16687
16766
|
let brief = found.brief;
|
|
16688
16767
|
if (!brief) {
|
|
16689
16768
|
try {
|
|
16690
16769
|
brief = await rail.read(goalId);
|
|
16691
16770
|
} catch (error) {
|
|
16692
|
-
if (error.status === 404)
|
|
16771
|
+
if (error.status === 404) read3.add(goalId);
|
|
16693
16772
|
continue;
|
|
16694
16773
|
}
|
|
16695
16774
|
}
|
|
16696
|
-
|
|
16775
|
+
read3.add(goalId);
|
|
16697
16776
|
const fresh = !brief.reviewSince && (found.via === "waiting work" || found.via === "assigned") ? sinceTheWork(brief) : { after: -1 };
|
|
16698
16777
|
if (found.via === "assigned") announced.add(goalId);
|
|
16699
16778
|
heard.push({ goalId, ...found, brief, words: unheard(brief, state, brief.reviewSince ? null : since ?? null, fresh.after, brief.reviewSince), ...fresh.note ? { note: fresh.note } : {} });
|
|
16700
16779
|
}
|
|
16701
|
-
for (const { goal, since } of moved) if (
|
|
16780
|
+
for (const { goal, since } of moved) if (read3.has(goal.goalId)) state.below.goals.set(goal.goalId, { since, at: goal.updatedAt ?? null });
|
|
16702
16781
|
return { heard, listed };
|
|
16703
16782
|
}
|
|
16704
16783
|
var GIVEN = "This Goal was given to you, and nobody has started it. Carry on with what you're doing unless it changes that; claim_goal with its id when you take it up.";
|
|
@@ -16816,7 +16895,7 @@ async function look(session, state, rail, opts) {
|
|
|
16816
16895
|
if (opts?.initialPrompt?.trim()) {
|
|
16817
16896
|
const prompt = opts.initialPrompt.trim();
|
|
16818
16897
|
opts.initialPrompt = void 0;
|
|
16819
|
-
const admitted = await rail.create({
|
|
16898
|
+
const admitted = await rail.create({ title: prompt.split(/\s+/).slice(0, 5).join(" ").slice(0, 80), outcome: prompt });
|
|
16820
16899
|
brief2 = await rail.claim();
|
|
16821
16900
|
if (!brief2.goalId || brief2.revision === void 0) {
|
|
16822
16901
|
state.goal = { id: admitted.goalId, revision: admitted.revision };
|
|
@@ -16907,9 +16986,9 @@ async function pump(session, state, rail, opts) {
|
|
|
16907
16986
|
}
|
|
16908
16987
|
if (!await opts.onIdle()) return;
|
|
16909
16988
|
if (now() - since >= BEAT_REPORT_MS) {
|
|
16910
|
-
const
|
|
16911
|
-
if (
|
|
16912
|
-
opts.log?.(`\u25B9 beats: ${
|
|
16989
|
+
const read3 = counts.wake + counts.rest + counts.safety;
|
|
16990
|
+
if (read3 || counts.skipped || tally.noted || tally.seen || tally.announced) {
|
|
16991
|
+
opts.log?.(`\u25B9 beats: ${read3} read (${counts.wake} wake, ${counts.rest} rest, ${counts.safety} safety), ${counts.skipped} wake mid-turn skipped, ${tally.noted} noted mid-turn, ${tally.seen} seen by the hook, ${tally.announced} assigned announced${tally.paused ? `, ${tally.paused} held by the usage limit` : ""}`);
|
|
16913
16992
|
}
|
|
16914
16993
|
counts.wake = counts.rest = counts.safety = counts.skipped = tally.noted = tally.seen = tally.announced = tally.paused = 0;
|
|
16915
16994
|
since = now();
|
|
@@ -16927,7 +17006,7 @@ function runHarness(opts) {
|
|
|
16927
17006
|
const clock4 = beat();
|
|
16928
17007
|
let session = null;
|
|
16929
17008
|
const speaksAs = opts.session ?? opts.resume ?? sessionId();
|
|
16930
|
-
const instance =
|
|
17009
|
+
const instance = randomUUID5();
|
|
16931
17010
|
const rail = railFor({ token: opts.token, reach: reachAs(speaksAs, instance) });
|
|
16932
17011
|
let inbox;
|
|
16933
17012
|
if (opts.harness === "claude") {
|
|
@@ -17154,7 +17233,7 @@ async function waitingWork(token, session) {
|
|
|
17154
17233
|
if (quiet !== void 0 && Date.now() < quiet) return { skip: BOUND_SKIP };
|
|
17155
17234
|
let found;
|
|
17156
17235
|
try {
|
|
17157
|
-
found = await
|
|
17236
|
+
found = await receive({ token, ...session ? { reach: reachAs(session) } : {} });
|
|
17158
17237
|
} catch (error) {
|
|
17159
17238
|
if (error instanceof RevokedError) return { skip: "was revoked: its credential is gone for good", revoked: true };
|
|
17160
17239
|
if (error instanceof ApiError && error.body?.error === "identity_session_mismatch") {
|
|
@@ -17393,7 +17472,7 @@ function startHost(opts) {
|
|
|
17393
17472
|
skip(`has a full conversation (${resumes.slice(0, 8)}) \u2014 not resuming it; its Goals go to the dead-agent handoff`);
|
|
17394
17473
|
return;
|
|
17395
17474
|
}
|
|
17396
|
-
const
|
|
17475
|
+
const read3 = async () => {
|
|
17397
17476
|
const got = await waitingWork(token, identity.sessionId ?? owner?.sessionId);
|
|
17398
17477
|
if (!("skip" in got)) return got;
|
|
17399
17478
|
if (got.revoked) {
|
|
@@ -17405,7 +17484,7 @@ function startHost(opts) {
|
|
|
17405
17484
|
return null;
|
|
17406
17485
|
};
|
|
17407
17486
|
if (decided.why === "presence") {
|
|
17408
|
-
found = await
|
|
17487
|
+
found = await read3() ?? void 0;
|
|
17409
17488
|
if (!found) return;
|
|
17410
17489
|
const since = found.since;
|
|
17411
17490
|
decided = wakeAction(false, Date.now(), seenByServer, { ...here2, ...since ? { movedAt: Date.parse(since) } : {} });
|
|
@@ -17431,7 +17510,7 @@ function startHost(opts) {
|
|
|
17431
17510
|
skip("has no granted folder to wake in");
|
|
17432
17511
|
return;
|
|
17433
17512
|
}
|
|
17434
|
-
found ??= await
|
|
17513
|
+
found ??= await read3() ?? void 0;
|
|
17435
17514
|
if (!found) return;
|
|
17436
17515
|
if (runs.has(key3)) {
|
|
17437
17516
|
skip("was started by the wake that read it first");
|
|
@@ -17567,7 +17646,7 @@ function startHost(opts) {
|
|
|
17567
17646
|
return {
|
|
17568
17647
|
name,
|
|
17569
17648
|
// The slot key rides along so the window's agent page can speak AS this agent —
|
|
17570
|
-
// its pending reads (`
|
|
17649
|
+
// its pending reads (`receive`, the same pure read the sweep does) need the
|
|
17571
17650
|
// slot's own token, and the display name is not a key.
|
|
17572
17651
|
slot,
|
|
17573
17652
|
tokenId: id3.tokenId,
|
|
@@ -17686,7 +17765,7 @@ ipcMain.handle("paigy:agent", async (_e, name) => {
|
|
|
17686
17765
|
const entry = (host?.roster() ?? readHostState()?.roster ?? []).find((a) => a.name === name);
|
|
17687
17766
|
if (!entry) return null;
|
|
17688
17767
|
const token = entry.slot ? readToken(entry.slot) : "";
|
|
17689
|
-
const open = token ? await
|
|
17768
|
+
const open = token ? await receive({ token }).then((r) => r.deliveries).catch(() => null) : null;
|
|
17690
17769
|
return {
|
|
17691
17770
|
...entry,
|
|
17692
17771
|
pending: open ? {
|