@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/cli.js
CHANGED
|
@@ -23805,28 +23805,28 @@ function overrideToken(secret) {
|
|
|
23805
23805
|
async function fail(what, res) {
|
|
23806
23806
|
throw new ApiError(what, res.status, await res.text());
|
|
23807
23807
|
}
|
|
23808
|
-
async function
|
|
23808
|
+
async function manageGoals(input, opts = {}) {
|
|
23809
23809
|
const token = authToken(opts.token) ?? "";
|
|
23810
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals`, {
|
|
23810
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/manage`, {
|
|
23811
23811
|
method: "POST",
|
|
23812
|
-
headers: { "content-type": "application/json", authorization: `Bearer ${token}
|
|
23812
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
23813
23813
|
body: JSON.stringify(input)
|
|
23814
23814
|
}));
|
|
23815
|
-
if (!res.ok) await fail("
|
|
23815
|
+
if (!res.ok) await fail("manage_goals", res);
|
|
23816
23816
|
return await res.json();
|
|
23817
23817
|
}
|
|
23818
23818
|
async function claimGoal(goalId, opts = {}) {
|
|
23819
23819
|
const token = authToken(opts.token) ?? "";
|
|
23820
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}
|
|
23820
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/claim`, { method: "POST", headers: { "content-type": "application/json", authorization: `Bearer ${token}` }, body: JSON.stringify(goalId ? { goalId } : {}) }));
|
|
23821
23821
|
if (!res.ok) await fail("claim_goal", res);
|
|
23822
23822
|
return await res.json();
|
|
23823
23823
|
}
|
|
23824
|
-
async function getGoal(goalId, opts = {},
|
|
23824
|
+
async function getGoal(goalId, opts = {}, read3 = {}) {
|
|
23825
23825
|
const token = authToken(opts.token) ?? "";
|
|
23826
|
-
const query = [
|
|
23826
|
+
const query = [read3.history ? "history=1" : "", read3.diagnose ? "diagnose=1" : ""].filter(Boolean).join("&");
|
|
23827
23827
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}${query ? `?${query}` : ""}`, {
|
|
23828
23828
|
method: "GET",
|
|
23829
|
-
headers: { authorization: `Bearer ${token}
|
|
23829
|
+
headers: { authorization: `Bearer ${token}` }
|
|
23830
23830
|
}));
|
|
23831
23831
|
if (!res.ok) await fail("get_goal", res);
|
|
23832
23832
|
return await res.json();
|
|
@@ -23834,7 +23834,7 @@ async function getGoal(goalId, opts = {}, read = {}) {
|
|
|
23834
23834
|
async function updateGoal(goalId, input, opts = {}) {
|
|
23835
23835
|
const token = authToken(opts.token) ?? "";
|
|
23836
23836
|
const operationId = input.operationId ?? randomUUID2();
|
|
23837
|
-
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}
|
|
23837
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/${encodeURIComponent(goalId)}`, { method: "PATCH", headers: { "content-type": "application/json", authorization: `Bearer ${token}` }, body: JSON.stringify({ ...input, operationId }) }));
|
|
23838
23838
|
if (!res.ok) await fail("update_goal", res);
|
|
23839
23839
|
return await res.json();
|
|
23840
23840
|
}
|
|
@@ -23926,7 +23926,7 @@ async function listNotes(opts = {}) {
|
|
|
23926
23926
|
}
|
|
23927
23927
|
async function listConnections(opts = {}) {
|
|
23928
23928
|
const res = await ensureAuthed(await reach(`${BACKEND_URL}/api/tokens`, {
|
|
23929
|
-
headers: { authorization: `Bearer ${authToken(opts.token)}
|
|
23929
|
+
headers: { authorization: `Bearer ${authToken(opts.token)}` }
|
|
23930
23930
|
}));
|
|
23931
23931
|
if (!res.ok) throw new Error(`list_connections failed: ${res.status} ${await res.text()}`);
|
|
23932
23932
|
return await res.json();
|
|
@@ -23976,9 +23976,10 @@ function currentRepo(cwd = process.cwd()) {
|
|
|
23976
23976
|
}
|
|
23977
23977
|
async function contact(input, opts = {}) {
|
|
23978
23978
|
const parsed = ContactSchema.parse(input);
|
|
23979
|
+
if (!("asks" in parsed) && !("deliveryId" in parsed)) throw new Error("contact with nothing to send receives: call receiveContact");
|
|
23979
23980
|
opts.signal?.throwIfAborted();
|
|
23980
23981
|
const send22 = opts.reach ?? reach;
|
|
23981
|
-
const headers = { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}
|
|
23982
|
+
const headers = { "content-type": "application/json", authorization: `Bearer ${authToken(opts.token) ?? ""}` };
|
|
23982
23983
|
let deliveryId;
|
|
23983
23984
|
let deliveries = [];
|
|
23984
23985
|
let recorded = [];
|
|
@@ -24023,7 +24024,7 @@ async function contact(input, opts = {}) {
|
|
|
24023
24024
|
const all = deliveries.filter((d) => !!d.deliveryId && !!d.goalId).map(({ id: id22, deliveryId: deliveryId2, goalId }) => ({ ...id22 ? { id: id22 } : {}, deliveryId: deliveryId2, goalId }));
|
|
24024
24025
|
const joinedCard = deliveries[0]?.joinedCard === true;
|
|
24025
24026
|
const joinedCall = deliveries[0]?.joinedCall === true;
|
|
24026
|
-
const
|
|
24027
|
+
const read3 = async (signal2) => {
|
|
24027
24028
|
const res = await ensureAuthed(await send22(`${BACKEND_URL}/api/deliveries/${encodeURIComponent(deliveryId)}`, { headers, signal: signal2 }));
|
|
24028
24029
|
if (!res.ok) await fail("read_delivery", res);
|
|
24029
24030
|
const one = await res.json();
|
|
@@ -24037,14 +24038,14 @@ async function contact(input, opts = {}) {
|
|
|
24037
24038
|
};
|
|
24038
24039
|
};
|
|
24039
24040
|
const settled = (d) => d.kind === "notification" || d.state === "closed" || d.answers.length > 0 || d.entries.some((e) => e.kind === "contribution");
|
|
24040
|
-
if (opts.waits === false) return
|
|
24041
|
+
if (opts.waits === false) return read3(opts.signal);
|
|
24041
24042
|
const window = AbortSignal.timeout(AWAIT_WINDOW_MS);
|
|
24042
24043
|
const signal = opts.signal ? AbortSignal.any([opts.signal, window]) : window;
|
|
24043
24044
|
let latest;
|
|
24044
24045
|
try {
|
|
24045
24046
|
while (true) {
|
|
24046
24047
|
signal.throwIfAborted();
|
|
24047
|
-
latest = await
|
|
24048
|
+
latest = await read3(signal);
|
|
24048
24049
|
if (settled(latest)) return latest;
|
|
24049
24050
|
await sleep2(5e3, void 0, { signal });
|
|
24050
24051
|
}
|
|
@@ -24054,11 +24055,11 @@ async function contact(input, opts = {}) {
|
|
|
24054
24055
|
throw error;
|
|
24055
24056
|
}
|
|
24056
24057
|
}
|
|
24057
|
-
async function
|
|
24058
|
+
async function receive(opts = {}) {
|
|
24058
24059
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/deliveries`, {
|
|
24059
|
-
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}
|
|
24060
|
+
headers: { authorization: `Bearer ${authToken(opts.token) ?? ""}` }
|
|
24060
24061
|
}));
|
|
24061
|
-
if (!res.ok) await fail("
|
|
24062
|
+
if (!res.ok) await fail("receive", res);
|
|
24062
24063
|
return await res.json();
|
|
24063
24064
|
}
|
|
24064
24065
|
function frame(line, topic, event, payload) {
|
|
@@ -24243,7 +24244,7 @@ ${block2}`;
|
|
|
24243
24244
|
}
|
|
24244
24245
|
return text.slice(0, start) + updated + text.slice(end);
|
|
24245
24246
|
}
|
|
24246
|
-
var import_undici, require2, CODEX_ENV, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, CLIENT, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OptionSchema, OptionInputSchema, NIGHT, AskInputSchema, StartContactSchema, ContactSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema,
|
|
24247
|
+
var import_undici, require2, CODEX_ENV, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, CLIENT, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OptionSchema, OptionInputSchema, NIGHT, AskInputSchema, StartContactSchema, ReceiveContactSchema, ContactSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema, UpdateGoalSchema, UpdateGoalToolSchema, changedGoal, goalTitle, goalOutcome, CreateChange, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange, read, GoalChangeSchema, editNames, ManageGoalsSchema, ManageGoalsToolSchema, MANAGE_GOALS_DESCRIPTION, ClaimGoalSchema, GetGoalSchema, GET_GOAL_DESCRIPTION, UPDATE_GOAL_DESCRIPTION, CLAIM_GOAL_DESCRIPTION, SearchToolSchema, SEARCH_DESCRIPTION, WhoIsWorkingSchema, AGENT_TOOLS, AGENT_TOOL_NAMES, id, key, participant, SourceSchema, ResultRefSchema, NodeRefSchema, DependencySchema, goalState, existingGoalChanges, BrainGoalChangeSchema, option, QuestionChangeSchema, lessonScope, LessonChangeSchema, BrainNextSchema, messageBase, BrainMessageSchema, BrainSearchSchema, BrainResultSchema, str, strs, CompactResultSchema, COMPACT_RESULT_JSON_SCHEMA, LIVE_MS, WORKING_MS, ContextSchema, ParticipantSchema, TransformSchema, VisualSchema, NotifyLevelSchema, SelectShapeSchema, ReceiptEventSchema, AttentionSchema, NotifyRequestFields, NotifyRequestSchema, NotifyStatusSchema, AgentStateSchema, TurnSchema, UserAnswerSchema, IntentSchema, RideAlongSchema, AwaitItemSchema, VoiceKeySchema, AgendaTurnSchema, CLAIM_STALE_MS, InboxItemSchema, APNS_TOKEN_RE, PushTokenSchema, MissedCallSchema, clock, QUIET, BrokerTuningSchema, UserSettingsSchema, HistoryWorkSchema, HistoryEntrySchema, HistoryPageSchema, ACTIVITY_LINES, ACTIVITY_LINE_MAX, AgentActivitySchema, ConnectionSummarySchema, LedgerItemSchema, AgentLedgerSchema, ReassignResultSchema, LessonStateSchema, LessonViewSchema, QueueQuestionSchema, QueueReplySchema, QueueItemSchema, QueueDeltaSchema, COLD_AFTER_MS, NoteSourceSchema, NoteStatusSchema, NoteRepeatSchema, DecisionSchema, NoteSchema, TriageItemSchema, TriageAssignmentSchema, TriageStatusSchema, SubmitTriageSchema, TriageProposalSchema, AcceptTriageSchema, AcceptTriageResultSchema, DeliveryModeSchema, WAKE_EVENT, wakeChannel, RegisterDeliverySchema, OAuthStartSchema, DeliveryConfigSchema, HostDecisionSchema, WakeNudgeSchema, PairingStatusSchema, DeviceCodeSchema, DeviceInfoSchema, DeviceTokenSchema, SupportRequestSchema, NotificationFeedbackKindSchema, SlimOptionSchema, QuestionRowSchema, WorkStateSchema, WorkRowSchema, ComputerRowSchema, AgentRowSchema, SnapshotSchema, CallRecapSchema, TOKEN_PATH, KEY_PATH, sleep, UnpairedError, RevokedError, ApiError, tokenOverride, authToken, AWAIT_WINDOW_MS, asked, NOT_SENT, DEMOTED, HEARTBEAT_MS, RETRY_MS, JOIN, JOIN_TIMEOUT_MS, lines;
|
|
24247
24248
|
var init_dist = __esm({
|
|
24248
24249
|
"../../packages/sdk/dist/index.js"() {
|
|
24249
24250
|
"use strict";
|
|
@@ -24669,7 +24670,7 @@ var init_dist = __esm({
|
|
|
24669
24670
|
'How the options are answered: "many" makes a checklist (they may want several, e.g. independent fixes), "one" (the default) a pick (choosing one rules out the others). Send "many" whenever more than one option could be wanted at once. The person can always answer in their own words as well. Ignored without options.'
|
|
24670
24671
|
),
|
|
24671
24672
|
answers: external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
|
|
24672
|
-
"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.
|
|
24673
|
+
"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."
|
|
24673
24674
|
)
|
|
24674
24675
|
}).strict();
|
|
24675
24676
|
StartContactSchema = external_exports.object({
|
|
@@ -24677,9 +24678,17 @@ var init_dist = __esm({
|
|
|
24677
24678
|
waiting: external_exports.enum(["none", "hard"]).default("none").describe("hard requests a call even when channel is notification; user permissions and ring cooldowns still apply."),
|
|
24678
24679
|
channel: external_exports.enum(["notification", "call"]).default("notification")
|
|
24679
24680
|
}).strict();
|
|
24680
|
-
|
|
24681
|
+
ReceiveContactSchema = external_exports.object({
|
|
24682
|
+
wait: external_exports.boolean().optional().describe(
|
|
24683
|
+
"Only controls when this returns. true (the default when you send and acknowledge nothing): wait up to about 45 seconds for incoming communication addressed to you, and return as soon as some is available. false: return what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived in the window; wait again without sending again), or `not_waited` (a hosted connection never holds a wait)."
|
|
24684
|
+
),
|
|
24685
|
+
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
24686
|
+
"The exact eventIds of the events you have handled: an acknowledgment (ACK). Reading alone acknowledges nothing, so an event comes back until you acknowledge it; after that the next batch can come. Each recipient acknowledges separately, for itself only. A Question you owe is answered (an ask with `answers`), never acknowledged away: that id is refused until it is answered."
|
|
24687
|
+
)
|
|
24688
|
+
}).strict();
|
|
24689
|
+
ContactSchema = external_exports.union([StartContactSchema, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict(), ReceiveContactSchema]);
|
|
24681
24690
|
CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
24682
|
-
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
|
|
24691
|
+
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`).";
|
|
24683
24692
|
CreateGoalSchema = external_exports.object({
|
|
24684
24693
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
24685
24694
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -24699,10 +24708,6 @@ var init_dist = __esm({
|
|
|
24699
24708
|
* repo name. Delegated work inherits this from its parent Goal when omitted. */
|
|
24700
24709
|
repo: external_exports.string().trim().min(1).max(200).optional()
|
|
24701
24710
|
});
|
|
24702
|
-
CreateGoalToolSchema = CreateGoalSchema.extend({
|
|
24703
|
-
idempotencyKey: CreateGoalSchema.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
24704
|
-
}).strict();
|
|
24705
|
-
CREATE_GOAL_DESCRIPTION = 'Create a durable Goal for an outcome. Without parentGoalId it is placed against your open Goals: if one already IS this work, that Goal comes back (existing: true) and nothing new is created \u2014 continue it; if the work belongs under one, it is created there (parentGoalId in the receipt); otherwise it is a root. Pass parentGoalId yourself to put it under a specific Goal. Pass repo to anchor the work to a specific repository ("owner/repo" or repo name); delegated children inherit it. Pass title to name it in one to five words, as a person would refer to it out loud ("the night rings") \u2014 it heads every list and is spoken on a call; without one the brain writes it. Admission only: claim it before doing work, then update it as it advances. Returns an admission receipt with goalId, current state, revision, ownerParticipant, and the next step; no Goal content or execution lease.';
|
|
24706
24711
|
UpdateGoalSchema = external_exports.object({
|
|
24707
24712
|
revision: external_exports.number().int().positive(),
|
|
24708
24713
|
changes: external_exports.object({
|
|
@@ -24726,7 +24731,65 @@ var init_dist = __esm({
|
|
|
24726
24731
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
24727
24732
|
operationId: external_exports.string().uuid().optional()
|
|
24728
24733
|
}).strict();
|
|
24729
|
-
UpdateGoalToolSchema =
|
|
24734
|
+
UpdateGoalToolSchema = external_exports.object({
|
|
24735
|
+
goalId: external_exports.string().uuid(),
|
|
24736
|
+
revision: UpdateGoalSchema.shape.revision,
|
|
24737
|
+
changes: UpdateGoalSchema.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
|
|
24738
|
+
reason: UpdateGoalSchema.shape.reason
|
|
24739
|
+
}).strict();
|
|
24740
|
+
changedGoal = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
24741
|
+
goalTitle = external_exports.string().trim().min(1).max(80).describe("The Goal's short display name: one to five words, how a person refers to it out loud.");
|
|
24742
|
+
goalOutcome = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
|
|
24743
|
+
CreateChange = external_exports.object({
|
|
24744
|
+
kind: external_exports.literal("create"),
|
|
24745
|
+
title: goalTitle,
|
|
24746
|
+
outcome: goalOutcome,
|
|
24747
|
+
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."),
|
|
24748
|
+
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
24749
|
+
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
24750
|
+
}).strict();
|
|
24751
|
+
EditChange = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal, title: goalTitle.optional(), outcome: goalOutcome.optional() }).strict();
|
|
24752
|
+
StateChange = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal, state: external_exports.enum(["open", "completed", "canceled"]).describe(
|
|
24753
|
+
"completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
|
|
24754
|
+
) }).strict();
|
|
24755
|
+
AssignChange = external_exports.object({ kind: external_exports.literal("assign"), goalId: changedGoal, ownerId: external_exports.string().trim().min(1).describe("The new owner's participant.") }).strict();
|
|
24756
|
+
DeferChange = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
24757
|
+
"Postpone it until this instant (its owner is woken then), or null to take the postponement back."
|
|
24758
|
+
) }).strict();
|
|
24759
|
+
MoveChange = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
24760
|
+
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
24761
|
+
) }).strict();
|
|
24762
|
+
DependencyChange = external_exports.object({
|
|
24763
|
+
kind: external_exports.literal("dependency"),
|
|
24764
|
+
change: external_exports.enum(["add", "remove"]),
|
|
24765
|
+
goalId: changedGoal,
|
|
24766
|
+
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
24767
|
+
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
24768
|
+
reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
|
|
24769
|
+
}).strict();
|
|
24770
|
+
read = { revision: external_exports.number().int().positive().optional() };
|
|
24771
|
+
GoalChangeSchema = external_exports.discriminatedUnion("kind", [
|
|
24772
|
+
CreateChange,
|
|
24773
|
+
EditChange.extend(read),
|
|
24774
|
+
StateChange.extend(read),
|
|
24775
|
+
AssignChange.extend(read),
|
|
24776
|
+
DeferChange.extend(read),
|
|
24777
|
+
MoveChange.extend(read),
|
|
24778
|
+
DependencyChange
|
|
24779
|
+
]);
|
|
24780
|
+
editNames = (changes, ctx) => changes.forEach((c, i) => {
|
|
24781
|
+
if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
|
|
24782
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
|
|
24783
|
+
}
|
|
24784
|
+
});
|
|
24785
|
+
ManageGoalsSchema = external_exports.object({
|
|
24786
|
+
requestId: external_exports.string().uuid().optional(),
|
|
24787
|
+
changes: external_exports.array(GoalChangeSchema).min(1).max(50)
|
|
24788
|
+
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
24789
|
+
ManageGoalsToolSchema = external_exports.object({
|
|
24790
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
24791
|
+
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
24792
|
+
MANAGE_GOALS_DESCRIPTION = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, 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.";
|
|
24730
24793
|
ClaimGoalSchema = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
24731
24794
|
GetGoalSchema = external_exports.object({
|
|
24732
24795
|
goalId: external_exports.string().uuid(),
|
|
@@ -24739,27 +24802,30 @@ var init_dist = __esm({
|
|
|
24739
24802
|
diagnose: external_exports.boolean().optional()
|
|
24740
24803
|
}).strict();
|
|
24741
24804
|
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.";
|
|
24742
|
-
UPDATE_GOAL_DESCRIPTION =
|
|
24743
|
-
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
|
|
24744
|
-
|
|
24745
|
-
|
|
24805
|
+
UPDATE_GOAL_DESCRIPTION = "Report work on a Goal you are on, at an exact revision: progress, review acknowledgement, when to wake for it, and withdrawing a question of yours. What the Goal is (its title, outcome, state, owner, parent, dependencies) changes with manage_goals. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). Stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. progress says where the work stands. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision (contact({ackEventIds}) does the same for an `update` event). dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. Returns the Goal as get_goal reads it, at its new revision.";
|
|
24806
|
+
CLAIM_GOAL_DESCRIPTION = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change it; use manage_goals (assign) when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
|
|
24807
|
+
SearchToolSchema = external_exports.object({
|
|
24808
|
+
query: external_exports.string().trim().min(1).max(500),
|
|
24809
|
+
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
24810
|
+
goalId: external_exports.string().uuid().optional(),
|
|
24811
|
+
limit: external_exports.number().int().min(1).max(20).optional()
|
|
24812
|
+
}).strict();
|
|
24813
|
+
SEARCH_DESCRIPTION = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and 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.";
|
|
24814
|
+
WhoIsWorkingSchema = external_exports.object({}).strict();
|
|
24746
24815
|
AGENT_TOOLS = [
|
|
24747
|
-
{ name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(
|
|
24816
|
+
{ name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(WhoIsWorkingSchema) },
|
|
24748
24817
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
24749
|
-
{ name: "
|
|
24750
|
-
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(CreateGoalToolSchema) },
|
|
24818
|
+
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(ManageGoalsToolSchema) },
|
|
24751
24819
|
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(ClaimGoalSchema) },
|
|
24752
24820
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(GetGoalSchema) },
|
|
24753
|
-
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) }
|
|
24821
|
+
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION, inputSchema: mcpInputSchema(UpdateGoalToolSchema) },
|
|
24822
|
+
{ name: "search", description: SEARCH_DESCRIPTION, inputSchema: mcpInputSchema(SearchToolSchema) }
|
|
24754
24823
|
];
|
|
24755
24824
|
AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
24756
24825
|
id = external_exports.string().uuid();
|
|
24757
24826
|
key = external_exports.string().min(1).max(40);
|
|
24758
24827
|
participant = external_exports.string().regex(/^(human|agent):.+$/, "a participant ID such as agent:<uuid>");
|
|
24759
|
-
SourceSchema = external_exports.object({
|
|
24760
|
-
entryId: id,
|
|
24761
|
-
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()
|
|
24762
|
-
}).strict();
|
|
24828
|
+
SourceSchema = external_exports.object({ entryId: id }).strict();
|
|
24763
24829
|
ResultRefSchema = external_exports.union([external_exports.object({ id }).strict(), external_exports.object({ local: key }).strict()]);
|
|
24764
24830
|
NodeRefSchema = external_exports.object({ type: external_exports.enum(["goal", "question"]), id }).strict();
|
|
24765
24831
|
DependencySchema = external_exports.object({
|
|
@@ -24784,17 +24850,6 @@ var init_dist = __esm({
|
|
|
24784
24850
|
reason: external_exports.string().max(500).optional()
|
|
24785
24851
|
}).strict()
|
|
24786
24852
|
];
|
|
24787
|
-
GoalChangeSchema = external_exports.union([
|
|
24788
|
-
external_exports.object({
|
|
24789
|
-
kind: external_exports.literal("create"),
|
|
24790
|
-
title: external_exports.string().min(1).max(120),
|
|
24791
|
-
outcome: external_exports.string().min(1),
|
|
24792
|
-
ownerId: participant,
|
|
24793
|
-
parentGoalId: id.optional(),
|
|
24794
|
-
sourceEntryIds: external_exports.array(id)
|
|
24795
|
-
}).strict(),
|
|
24796
|
-
...existingGoalChanges
|
|
24797
|
-
]);
|
|
24798
24853
|
BrainGoalChangeSchema = external_exports.union([
|
|
24799
24854
|
// newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
|
|
24800
24855
|
external_exports.object({
|
|
@@ -24851,7 +24906,7 @@ var init_dist = __esm({
|
|
|
24851
24906
|
external_exports.object({ ...messageBase, to: external_exports.object({ kind: external_exports.literal("user") }).strict() }).strict(),
|
|
24852
24907
|
external_exports.object({
|
|
24853
24908
|
...messageBase,
|
|
24854
|
-
to: external_exports.object({ kind: external_exports.literal("
|
|
24909
|
+
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
24855
24910
|
call: external_exports.object({ callId: id, listen: external_exports.literal(true) }).strict().optional()
|
|
24856
24911
|
}).strict()
|
|
24857
24912
|
]);
|
|
@@ -24881,7 +24936,7 @@ var init_dist = __esm({
|
|
|
24881
24936
|
CompactResultSchema = external_exports.object({
|
|
24882
24937
|
next: external_exports.object({ say: strs, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs, reason: str, instructions: strs }).strict(),
|
|
24883
24938
|
messages: external_exports.array(external_exports.object({ key: str, to: str, text: str, about: strs, entries: strs, owed: strs, inviteToCall: external_exports.boolean() }).strict()),
|
|
24884
|
-
entries: external_exports.array(external_exports.object({ key: str, from: str,
|
|
24939
|
+
entries: external_exports.array(external_exports.object({ key: str, from: str, on: strs }).strict()),
|
|
24885
24940
|
answers: external_exports.array(external_exports.object({ question: str, entries: strs, summary: str, picked: strs }).strict()),
|
|
24886
24941
|
changes: external_exports.array(external_exports.object({
|
|
24887
24942
|
key: str,
|
|
@@ -25178,7 +25233,7 @@ var init_dist = __esm({
|
|
|
25178
25233
|
/** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
|
|
25179
25234
|
* post-feedback revision, #633) — the user will never answer this id. Stop
|
|
25180
25235
|
* awaiting it; the live ask is the thread's newest turn (await that one, or
|
|
25181
|
-
* re-orient via
|
|
25236
|
+
* re-orient via contact({})). */
|
|
25182
25237
|
external_exports.object({
|
|
25183
25238
|
type: external_exports.literal("superseded"),
|
|
25184
25239
|
parentId: external_exports.string(),
|
|
@@ -25629,39 +25684,22 @@ var init_dist = __esm({
|
|
|
25629
25684
|
moved: external_exports.object({ asks: external_exports.number(), answered: external_exports.number(), requests: external_exports.number(), goals: external_exports.number(), callbacks: external_exports.number() }),
|
|
25630
25685
|
parentId: external_exports.string().nullable()
|
|
25631
25686
|
});
|
|
25632
|
-
|
|
25633
|
-
|
|
25687
|
+
LessonStateSchema = external_exports.enum(["active", "proposed", "retired"]);
|
|
25688
|
+
LessonViewSchema = external_exports.object({
|
|
25634
25689
|
id: external_exports.string(),
|
|
25635
|
-
|
|
25636
|
-
|
|
25637
|
-
/** The
|
|
25638
|
-
|
|
25639
|
-
|
|
25640
|
-
|
|
25641
|
-
rationale: external_exports.string().nullable(),
|
|
25642
|
-
/** Where the ruling lives: a repo/workspace, or 'global'. */
|
|
25643
|
-
scope: external_exports.string(),
|
|
25644
|
-
ring: MoveRingSchema,
|
|
25645
|
-
/** True = the user pinned it with `always` (travel granted by hand, not by evidence). */
|
|
25690
|
+
text: external_exports.string(),
|
|
25691
|
+
state: LessonStateSchema,
|
|
25692
|
+
/** The Goal it is scoped to; null = the whole account. */
|
|
25693
|
+
scopeGoalId: external_exports.string().nullable(),
|
|
25694
|
+
goalTitle: external_exports.string().nullable(),
|
|
25695
|
+
version: external_exports.number(),
|
|
25646
25696
|
pinned: external_exports.boolean(),
|
|
25647
|
-
/**
|
|
25648
|
-
|
|
25649
|
-
|
|
25650
|
-
|
|
25651
|
-
|
|
25652
|
-
|
|
25653
|
-
lastUsedAt: external_exports.string().nullable(),
|
|
25654
|
-
/** How many asks it has answered. Instrumentation — deliberately NOT an input to the
|
|
25655
|
-
* evidence curve: firing says the question keeps arising, not that the ruling is right. */
|
|
25656
|
-
usedCount: external_exports.number(),
|
|
25657
|
-
/** Ledger: outcomes that said it held up. Saturating — the tenth is worth almost nothing. */
|
|
25658
|
-
confirms: external_exports.number(),
|
|
25659
|
-
/** Ledger: contradictions, in signal units (a full override = 1, weaker signals less).
|
|
25660
|
-
* Linear and priced above the entire confirmation budget, so any full counter wins. */
|
|
25661
|
-
counters: external_exports.number(),
|
|
25662
|
-
/** The agent that asked the question this move came from, when known. Null for a move
|
|
25663
|
-
* distilled from a clarify ruling (those carry no agent) or one whose source rows are gone. */
|
|
25664
|
-
learnedFrom: external_exports.object({ id: external_exports.string(), name: external_exports.string() }).nullable()
|
|
25697
|
+
/** When the person last wrote its text themselves. */
|
|
25698
|
+
editedAt: external_exports.string().nullable(),
|
|
25699
|
+
createdAt: external_exports.string(),
|
|
25700
|
+
updatedAt: external_exports.string(),
|
|
25701
|
+
/** The Entries it came from, oldest first; `words` is null when an Entry has none to show (sealed). */
|
|
25702
|
+
sources: external_exports.array(external_exports.object({ entryId: external_exports.string(), words: external_exports.string().nullable(), at: external_exports.string() }))
|
|
25665
25703
|
});
|
|
25666
25704
|
QueueQuestionSchema = external_exports.object({
|
|
25667
25705
|
/** The decision need's id — what an answer is accepted against. */
|
|
@@ -25925,7 +25963,7 @@ var init_dist = __esm({
|
|
|
25925
25963
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
25926
25964
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
25927
25965
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
25928
|
-
/** When that work last moved (`claimable.since` on `
|
|
25966
|
+
/** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
|
|
25929
25967
|
since: external_exports.string().datetime().nullable().optional(),
|
|
25930
25968
|
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
25931
25969
|
said: external_exports.string().max(300).optional()
|
|
@@ -26160,7 +26198,7 @@ var init_dist = __esm({
|
|
|
26160
26198
|
tokenOverride = null;
|
|
26161
26199
|
authToken = (explicit) => explicit ?? tokenOverride ?? readToken();
|
|
26162
26200
|
AWAIT_WINDOW_MS = 45e3;
|
|
26163
|
-
NOT_SENT = "Recorded as progress, not sent: nobody was notified.
|
|
26201
|
+
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.";
|
|
26164
26202
|
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.";
|
|
26165
26203
|
HEARTBEAT_MS = 25e3;
|
|
26166
26204
|
RETRY_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
@@ -28093,27 +28131,27 @@ var require_chunkstream = __commonJS({
|
|
|
28093
28131
|
this._buffers = null;
|
|
28094
28132
|
this.emit("close");
|
|
28095
28133
|
};
|
|
28096
|
-
ChunkStream.prototype._processReadAllowingLess = function(
|
|
28134
|
+
ChunkStream.prototype._processReadAllowingLess = function(read3) {
|
|
28097
28135
|
this._reads.shift();
|
|
28098
28136
|
let smallerBuf = this._buffers[0];
|
|
28099
|
-
if (smallerBuf.length >
|
|
28100
|
-
this._buffered -=
|
|
28101
|
-
this._buffers[0] = smallerBuf.slice(
|
|
28102
|
-
|
|
28137
|
+
if (smallerBuf.length > read3.length) {
|
|
28138
|
+
this._buffered -= read3.length;
|
|
28139
|
+
this._buffers[0] = smallerBuf.slice(read3.length);
|
|
28140
|
+
read3.func.call(this, smallerBuf.slice(0, read3.length));
|
|
28103
28141
|
} else {
|
|
28104
28142
|
this._buffered -= smallerBuf.length;
|
|
28105
28143
|
this._buffers.shift();
|
|
28106
|
-
|
|
28144
|
+
read3.func.call(this, smallerBuf);
|
|
28107
28145
|
}
|
|
28108
28146
|
};
|
|
28109
|
-
ChunkStream.prototype._processRead = function(
|
|
28147
|
+
ChunkStream.prototype._processRead = function(read3) {
|
|
28110
28148
|
this._reads.shift();
|
|
28111
28149
|
let pos = 0;
|
|
28112
28150
|
let count = 0;
|
|
28113
|
-
let data = Buffer.alloc(
|
|
28114
|
-
while (pos <
|
|
28151
|
+
let data = Buffer.alloc(read3.length);
|
|
28152
|
+
while (pos < read3.length) {
|
|
28115
28153
|
let buf = this._buffers[count++];
|
|
28116
|
-
let len = Math.min(buf.length,
|
|
28154
|
+
let len = Math.min(buf.length, read3.length - pos);
|
|
28117
28155
|
buf.copy(data, pos, 0, len);
|
|
28118
28156
|
pos += len;
|
|
28119
28157
|
if (len !== buf.length) {
|
|
@@ -28123,17 +28161,17 @@ var require_chunkstream = __commonJS({
|
|
|
28123
28161
|
if (count > 0) {
|
|
28124
28162
|
this._buffers.splice(0, count);
|
|
28125
28163
|
}
|
|
28126
|
-
this._buffered -=
|
|
28127
|
-
|
|
28164
|
+
this._buffered -= read3.length;
|
|
28165
|
+
read3.func.call(this, data);
|
|
28128
28166
|
};
|
|
28129
28167
|
ChunkStream.prototype._process = function() {
|
|
28130
28168
|
try {
|
|
28131
28169
|
while (this._buffered > 0 && this._reads && this._reads.length > 0) {
|
|
28132
|
-
let
|
|
28133
|
-
if (
|
|
28134
|
-
this._processReadAllowingLess(
|
|
28135
|
-
} else if (this._buffered >=
|
|
28136
|
-
this._processRead(
|
|
28170
|
+
let read3 = this._reads[0];
|
|
28171
|
+
if (read3.allowLess) {
|
|
28172
|
+
this._processReadAllowingLess(read3);
|
|
28173
|
+
} else if (this._buffered >= read3.length) {
|
|
28174
|
+
this._processRead(read3);
|
|
28137
28175
|
} else {
|
|
28138
28176
|
break;
|
|
28139
28177
|
}
|
|
@@ -29758,12 +29796,12 @@ var require_sync_reader = __commonJS({
|
|
|
29758
29796
|
};
|
|
29759
29797
|
SyncReader.prototype.process = function() {
|
|
29760
29798
|
while (this._reads.length > 0 && this._buffer.length) {
|
|
29761
|
-
let
|
|
29762
|
-
if (this._buffer.length && (this._buffer.length >=
|
|
29799
|
+
let read3 = this._reads[0];
|
|
29800
|
+
if (this._buffer.length && (this._buffer.length >= read3.length || read3.allowLess)) {
|
|
29763
29801
|
this._reads.shift();
|
|
29764
29802
|
let buf = this._buffer;
|
|
29765
|
-
this._buffer = buf.slice(
|
|
29766
|
-
|
|
29803
|
+
this._buffer = buf.slice(read3.length);
|
|
29804
|
+
read3.func.call(this, buf.slice(0, read3.length));
|
|
29767
29805
|
} else {
|
|
29768
29806
|
break;
|
|
29769
29807
|
}
|
|
@@ -31424,7 +31462,7 @@ function onEnter(input, onLine) {
|
|
|
31424
31462
|
// src/cli.ts
|
|
31425
31463
|
init_dist();
|
|
31426
31464
|
var import_qrcode = __toESM(require_lib(), 1);
|
|
31427
|
-
import { randomUUID as
|
|
31465
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
31428
31466
|
import { hostname } from "os";
|
|
31429
31467
|
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
31430
31468
|
import { execFile as execFile2, execSync } from "child_process";
|
|
@@ -31433,7 +31471,7 @@ import { join as join11 } from "path";
|
|
|
31433
31471
|
|
|
31434
31472
|
// src/run.ts
|
|
31435
31473
|
init_dist();
|
|
31436
|
-
import { randomUUID as
|
|
31474
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
31437
31475
|
|
|
31438
31476
|
// src/harness/session.ts
|
|
31439
31477
|
init_dist();
|
|
@@ -33278,7 +33316,7 @@ var AskInputSchema2 = external_exports.object({
|
|
|
33278
33316
|
'How the options are answered: "many" makes a checklist (they may want several, e.g. independent fixes), "one" (the default) a pick (choosing one rules out the others). Send "many" whenever more than one option could be wanted at once. The person can always answer in their own words as well. Ignored without options.'
|
|
33279
33317
|
),
|
|
33280
33318
|
answers: external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/).optional().describe(
|
|
33281
|
-
"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.
|
|
33319
|
+
"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."
|
|
33282
33320
|
)
|
|
33283
33321
|
}).strict();
|
|
33284
33322
|
var StartContactSchema2 = external_exports.object({
|
|
@@ -33286,9 +33324,17 @@ var StartContactSchema2 = external_exports.object({
|
|
|
33286
33324
|
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."),
|
|
33287
33325
|
channel: external_exports.enum(["notification", "call"]).default("notification")
|
|
33288
33326
|
}).strict();
|
|
33289
|
-
var
|
|
33327
|
+
var ReceiveContactSchema2 = external_exports.object({
|
|
33328
|
+
wait: external_exports.boolean().optional().describe(
|
|
33329
|
+
"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)."
|
|
33330
|
+
),
|
|
33331
|
+
ackEventIds: external_exports.array(external_exports.string().uuid()).min(1).max(100).optional().describe(
|
|
33332
|
+
"The exact eventIds of the events you have handled: an acknowledgment (ACK). Reading alone acknowledges nothing, so an event comes back until you acknowledge it; after that the next batch can come. Each recipient acknowledges separately, for itself only. A Question you owe is answered (an ask with `answers`), never acknowledged away: that id is refused until it is answered."
|
|
33333
|
+
)
|
|
33334
|
+
}).strict();
|
|
33335
|
+
var ContactSchema2 = external_exports.union([StartContactSchema2, external_exports.object({ deliveryId: external_exports.string().uuid() }).strict(), ReceiveContactSchema2]);
|
|
33290
33336
|
var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
|
|
33291
|
-
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
|
|
33337
|
+
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`).";
|
|
33292
33338
|
var CreateGoalSchema2 = external_exports.object({
|
|
33293
33339
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
33294
33340
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -33308,10 +33354,6 @@ var CreateGoalSchema2 = external_exports.object({
|
|
|
33308
33354
|
* repo name. Delegated work inherits this from its parent Goal when omitted. */
|
|
33309
33355
|
repo: external_exports.string().trim().min(1).max(200).optional()
|
|
33310
33356
|
});
|
|
33311
|
-
var CreateGoalToolSchema2 = CreateGoalSchema2.extend({
|
|
33312
|
-
idempotencyKey: CreateGoalSchema2.shape.idempotencyKey.optional().describe("Optional. One is minted per call; pass your own only so a retry lands on the same Goal.")
|
|
33313
|
-
}).strict();
|
|
33314
|
-
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.';
|
|
33315
33357
|
var UpdateGoalSchema2 = external_exports.object({
|
|
33316
33358
|
revision: external_exports.number().int().positive(),
|
|
33317
33359
|
changes: external_exports.object({
|
|
@@ -33335,7 +33377,65 @@ var UpdateGoalSchema2 = external_exports.object({
|
|
|
33335
33377
|
reason: external_exports.string().trim().min(1).max(2e3),
|
|
33336
33378
|
operationId: external_exports.string().uuid().optional()
|
|
33337
33379
|
}).strict();
|
|
33338
|
-
var UpdateGoalToolSchema2 =
|
|
33380
|
+
var UpdateGoalToolSchema2 = external_exports.object({
|
|
33381
|
+
goalId: external_exports.string().uuid(),
|
|
33382
|
+
revision: UpdateGoalSchema2.shape.revision,
|
|
33383
|
+
changes: UpdateGoalSchema2.shape.changes.innerType().pick({ progress: true, reviewed: true, dueAt: true, withdraw: true }).strict().refine((v) => Object.keys(v).length > 0),
|
|
33384
|
+
reason: UpdateGoalSchema2.shape.reason
|
|
33385
|
+
}).strict();
|
|
33386
|
+
var changedGoal2 = external_exports.string().uuid().describe("The Goal to change, as a read shows it.");
|
|
33387
|
+
var goalTitle2 = external_exports.string().trim().min(1).max(80).describe("The Goal's short display name: one to five words, how a person refers to it out loud.");
|
|
33388
|
+
var goalOutcome2 = external_exports.string().trim().min(1).max(1e4).describe("The full desired result. There is no third description field.");
|
|
33389
|
+
var CreateChange2 = external_exports.object({
|
|
33390
|
+
kind: external_exports.literal("create"),
|
|
33391
|
+
title: goalTitle2,
|
|
33392
|
+
outcome: goalOutcome2,
|
|
33393
|
+
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."),
|
|
33394
|
+
parentGoalId: external_exports.string().uuid().optional().describe("The Goal it belongs under. Omitted: a root."),
|
|
33395
|
+
sourceEntryIds: external_exports.array(external_exports.string().uuid()).max(20).optional().describe("The whole Entries the work came from, ones you can read.")
|
|
33396
|
+
}).strict();
|
|
33397
|
+
var EditChange2 = external_exports.object({ kind: external_exports.literal("edit"), goalId: changedGoal2, title: goalTitle2.optional(), outcome: goalOutcome2.optional() }).strict();
|
|
33398
|
+
var StateChange2 = external_exports.object({ kind: external_exports.literal("state"), goalId: changedGoal2, state: external_exports.enum(["open", "completed", "canceled"]).describe(
|
|
33399
|
+
"completed: the Goal's own work is done now (refused while required children are open); open: reopen it; canceled: it will not be done."
|
|
33400
|
+
) }).strict();
|
|
33401
|
+
var AssignChange2 = external_exports.object({ kind: external_exports.literal("assign"), goalId: changedGoal2, ownerId: external_exports.string().trim().min(1).describe("The new owner's participant.") }).strict();
|
|
33402
|
+
var DeferChange2 = external_exports.object({ kind: external_exports.literal("defer"), goalId: changedGoal2, until: external_exports.string().datetime({ offset: true }).nullable().describe(
|
|
33403
|
+
"Postpone it until this instant (its owner is woken then), or null to take the postponement back."
|
|
33404
|
+
) }).strict();
|
|
33405
|
+
var MoveChange2 = external_exports.object({ kind: external_exports.literal("move"), goalId: changedGoal2, parentGoalId: external_exports.string().uuid().nullable().describe(
|
|
33406
|
+
"Its new parent, or null for a root. Only this Goal moves; its new parent's other children stay."
|
|
33407
|
+
) }).strict();
|
|
33408
|
+
var DependencyChange2 = external_exports.object({
|
|
33409
|
+
kind: external_exports.literal("dependency"),
|
|
33410
|
+
change: external_exports.enum(["add", "remove"]),
|
|
33411
|
+
goalId: changedGoal2,
|
|
33412
|
+
dependsOnGoalId: external_exports.string().uuid().describe("The Goal it waits on."),
|
|
33413
|
+
action: external_exports.enum(["start", "complete"]).describe("What waits: starting goalId, or completing it."),
|
|
33414
|
+
reason: external_exports.string().trim().min(1).max(2e3).optional().describe("Why, as an explanation, never as policy.")
|
|
33415
|
+
}).strict();
|
|
33416
|
+
var read2 = { revision: external_exports.number().int().positive().optional() };
|
|
33417
|
+
var GoalChangeSchema2 = external_exports.discriminatedUnion("kind", [
|
|
33418
|
+
CreateChange2,
|
|
33419
|
+
EditChange2.extend(read2),
|
|
33420
|
+
StateChange2.extend(read2),
|
|
33421
|
+
AssignChange2.extend(read2),
|
|
33422
|
+
DeferChange2.extend(read2),
|
|
33423
|
+
MoveChange2.extend(read2),
|
|
33424
|
+
DependencyChange2
|
|
33425
|
+
]);
|
|
33426
|
+
var editNames2 = (changes, ctx) => changes.forEach((c, i) => {
|
|
33427
|
+
if (c.kind === "edit" && c.title === void 0 && c.outcome === void 0) {
|
|
33428
|
+
ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path: ["changes", i], message: "an edit supplies title, outcome, or both" });
|
|
33429
|
+
}
|
|
33430
|
+
});
|
|
33431
|
+
var ManageGoalsSchema2 = external_exports.object({
|
|
33432
|
+
requestId: external_exports.string().uuid().optional(),
|
|
33433
|
+
changes: external_exports.array(GoalChangeSchema2).min(1).max(50)
|
|
33434
|
+
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
33435
|
+
var ManageGoalsToolSchema2 = external_exports.object({
|
|
33436
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange2, EditChange2, StateChange2, AssignChange2, DeferChange2, MoveChange2, DependencyChange2])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
33437
|
+
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
33438
|
+
var MANAGE_GOALS_DESCRIPTION2 = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, 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.";
|
|
33339
33439
|
var ClaimGoalSchema2 = external_exports.object({ goalId: external_exports.string().uuid().optional() }).strict();
|
|
33340
33440
|
var GetGoalSchema2 = external_exports.object({
|
|
33341
33441
|
goalId: external_exports.string().uuid(),
|
|
@@ -33348,27 +33448,30 @@ var GetGoalSchema2 = external_exports.object({
|
|
|
33348
33448
|
diagnose: external_exports.boolean().optional()
|
|
33349
33449
|
}).strict();
|
|
33350
33450
|
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.";
|
|
33351
|
-
var UPDATE_GOAL_DESCRIPTION2 =
|
|
33352
|
-
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
|
|
33353
|
-
var
|
|
33354
|
-
|
|
33451
|
+
var UPDATE_GOAL_DESCRIPTION2 = "Report work on a Goal you are on, at an exact revision: progress, review acknowledgement, when to wake for it, and withdrawing a question of yours. What the Goal is (its title, outcome, state, owner, parent, dependencies) changes with manage_goals. You are on a Goal you own, or one you have written on (an update with progress, or a contact on it); any of your person's agents may write on any of their Goals, and one that never touched a Goal is refused (409 goal_not_joined). Stale revisions are rejected. A CONTACT ON THIS GOAL MOVES ITS REVISION: a question filed on a Goal is a change to it, so an update prepared before a contact and sent after it is refused as stale (409 goal_revision_conflict) \u2014 re-read the Goal, then write. progress says where the work stands. reviewed: true acknowledges new evidence and closes the Deliveries addressed to you on that Goal, never over an open decision (contact({ackEventIds}) does the same for an `update` event). dueAt (an ISO instant, or null) makes the Goal wait until then; when it passes you are woken for it \u2014 use it for a promise to follow up later. withdraw: [questionId] takes back a question YOU asked on this Goal that is still open \u2014 because you acted on it yourself, it no longer matters, or you asked it wrongly (e.g. waiting: hard when nothing was blocked): it is cancelled, not answered, its card closes and it stops ringing; the id is the one the conversation shows. Returns the Goal as get_goal reads it, at its new revision.";
|
|
33452
|
+
var CLAIM_GOAL_DESCRIPTION2 = "Claim a pending answer to your question or the oldest runnable or review-pending Goal you own. Pass goalId to join any Goal of your person; its assignment stays unchanged. Read others before overlapping another agent\u2019s work. Joining lets you contribute and change it; use manage_goals (assign) when the assignment itself should change. Returns the Goal as get_goal reads it, and marks you as on it, which never shuts another agent out: other agents of your person may write on it and change it too, and two changes at once are told apart by revision (409 goal_revision_conflict).";
|
|
33453
|
+
var SearchToolSchema2 = external_exports.object({
|
|
33454
|
+
query: external_exports.string().trim().min(1).max(500),
|
|
33455
|
+
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
33456
|
+
goalId: external_exports.string().uuid().optional(),
|
|
33457
|
+
limit: external_exports.number().int().min(1).max(20).optional()
|
|
33458
|
+
}).strict();
|
|
33459
|
+
var SEARCH_DESCRIPTION2 = "Search your person's history across all of their agents: Entries (what anyone said or wrote, typed or spoken on a call), Goals (by title and outcome) and 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.";
|
|
33460
|
+
var WhoIsWorkingSchema2 = external_exports.object({}).strict();
|
|
33355
33461
|
var AGENT_TOOLS2 = [
|
|
33356
|
-
{ 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(
|
|
33462
|
+
{ name: "who_is_working", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goal to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema2(WhoIsWorkingSchema2) },
|
|
33357
33463
|
{ name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
|
|
33358
|
-
{ name: "
|
|
33359
|
-
{ name: "create_goal", description: CREATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(CreateGoalToolSchema2) },
|
|
33464
|
+
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(ManageGoalsToolSchema2) },
|
|
33360
33465
|
{ name: "claim_goal", description: CLAIM_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(ClaimGoalSchema2) },
|
|
33361
33466
|
{ name: "get_goal", description: GET_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(GetGoalSchema2) },
|
|
33362
|
-
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(UpdateGoalToolSchema2) }
|
|
33467
|
+
{ name: "update_goal", description: UPDATE_GOAL_DESCRIPTION2, inputSchema: mcpInputSchema2(UpdateGoalToolSchema2) },
|
|
33468
|
+
{ name: "search", description: SEARCH_DESCRIPTION2, inputSchema: mcpInputSchema2(SearchToolSchema2) }
|
|
33363
33469
|
];
|
|
33364
33470
|
var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
|
|
33365
33471
|
var id2 = external_exports.string().uuid();
|
|
33366
33472
|
var key2 = external_exports.string().min(1).max(40);
|
|
33367
33473
|
var participant2 = external_exports.string().regex(/^(human|agent):.+$/, "a participant ID such as agent:<uuid>");
|
|
33368
|
-
var SourceSchema2 = external_exports.object({
|
|
33369
|
-
entryId: id2,
|
|
33370
|
-
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()
|
|
33371
|
-
}).strict();
|
|
33474
|
+
var SourceSchema2 = external_exports.object({ entryId: id2 }).strict();
|
|
33372
33475
|
var ResultRefSchema2 = external_exports.union([external_exports.object({ id: id2 }).strict(), external_exports.object({ local: key2 }).strict()]);
|
|
33373
33476
|
var NodeRefSchema2 = external_exports.object({ type: external_exports.enum(["goal", "question"]), id: id2 }).strict();
|
|
33374
33477
|
var DependencySchema2 = external_exports.object({
|
|
@@ -33393,17 +33496,6 @@ var existingGoalChanges2 = [
|
|
|
33393
33496
|
reason: external_exports.string().max(500).optional()
|
|
33394
33497
|
}).strict()
|
|
33395
33498
|
];
|
|
33396
|
-
var GoalChangeSchema2 = external_exports.union([
|
|
33397
|
-
external_exports.object({
|
|
33398
|
-
kind: external_exports.literal("create"),
|
|
33399
|
-
title: external_exports.string().min(1).max(120),
|
|
33400
|
-
outcome: external_exports.string().min(1),
|
|
33401
|
-
ownerId: participant2,
|
|
33402
|
-
parentGoalId: id2.optional(),
|
|
33403
|
-
sourceEntryIds: external_exports.array(id2)
|
|
33404
|
-
}).strict(),
|
|
33405
|
-
...existingGoalChanges2
|
|
33406
|
-
]);
|
|
33407
33499
|
var BrainGoalChangeSchema2 = external_exports.union([
|
|
33408
33500
|
// newSession: Paigy starts a session to own it (owner, 2026-10-06); until it has, the person owns it.
|
|
33409
33501
|
external_exports.object({
|
|
@@ -33460,7 +33552,7 @@ var BrainMessageSchema2 = external_exports.union([
|
|
|
33460
33552
|
external_exports.object({ ...messageBase2, to: external_exports.object({ kind: external_exports.literal("user") }).strict() }).strict(),
|
|
33461
33553
|
external_exports.object({
|
|
33462
33554
|
...messageBase2,
|
|
33463
|
-
to: external_exports.object({ kind: external_exports.literal("
|
|
33555
|
+
to: external_exports.object({ kind: external_exports.literal("agent"), agentId: external_exports.string().regex(/^agent:(?!paigy$)\S+$/) }).strict(),
|
|
33464
33556
|
call: external_exports.object({ callId: id2, listen: external_exports.literal(true) }).strict().optional()
|
|
33465
33557
|
}).strict()
|
|
33466
33558
|
]);
|
|
@@ -33490,7 +33582,7 @@ var strs2 = external_exports.array(external_exports.string());
|
|
|
33490
33582
|
var CompactResultSchema2 = external_exports.object({
|
|
33491
33583
|
next: external_exports.object({ say: strs2, then: external_exports.enum(["listen", "hold", "end", "none"]), waitFor: strs2, reason: str2, instructions: strs2 }).strict(),
|
|
33492
33584
|
messages: external_exports.array(external_exports.object({ key: str2, to: str2, text: str2, about: strs2, entries: strs2, owed: strs2, inviteToCall: external_exports.boolean() }).strict()),
|
|
33493
|
-
entries: external_exports.array(external_exports.object({ key: str2, from: str2,
|
|
33585
|
+
entries: external_exports.array(external_exports.object({ key: str2, from: str2, on: strs2 }).strict()),
|
|
33494
33586
|
answers: external_exports.array(external_exports.object({ question: str2, entries: strs2, summary: str2, picked: strs2 }).strict()),
|
|
33495
33587
|
changes: external_exports.array(external_exports.object({
|
|
33496
33588
|
key: str2,
|
|
@@ -33804,7 +33896,7 @@ var AwaitItemSchema2 = external_exports.discriminatedUnion("type", [
|
|
|
33804
33896
|
/** The awaited ask was REPLACED by a newer notification on its thread (e.g. a
|
|
33805
33897
|
* post-feedback revision, #633) — the user will never answer this id. Stop
|
|
33806
33898
|
* awaiting it; the live ask is the thread's newest turn (await that one, or
|
|
33807
|
-
* re-orient via
|
|
33899
|
+
* re-orient via contact({})). */
|
|
33808
33900
|
external_exports.object({
|
|
33809
33901
|
type: external_exports.literal("superseded"),
|
|
33810
33902
|
parentId: external_exports.string(),
|
|
@@ -34255,39 +34347,22 @@ var ReassignResultSchema2 = external_exports.object({
|
|
|
34255
34347
|
moved: external_exports.object({ asks: external_exports.number(), answered: external_exports.number(), requests: external_exports.number(), goals: external_exports.number(), callbacks: external_exports.number() }),
|
|
34256
34348
|
parentId: external_exports.string().nullable()
|
|
34257
34349
|
});
|
|
34258
|
-
var
|
|
34259
|
-
var
|
|
34350
|
+
var LessonStateSchema2 = external_exports.enum(["active", "proposed", "retired"]);
|
|
34351
|
+
var LessonViewSchema2 = external_exports.object({
|
|
34260
34352
|
id: external_exports.string(),
|
|
34261
|
-
|
|
34262
|
-
|
|
34263
|
-
/** The
|
|
34264
|
-
|
|
34265
|
-
|
|
34266
|
-
|
|
34267
|
-
rationale: external_exports.string().nullable(),
|
|
34268
|
-
/** Where the ruling lives: a repo/workspace, or 'global'. */
|
|
34269
|
-
scope: external_exports.string(),
|
|
34270
|
-
ring: MoveRingSchema2,
|
|
34271
|
-
/** True = the user pinned it with `always` (travel granted by hand, not by evidence). */
|
|
34353
|
+
text: external_exports.string(),
|
|
34354
|
+
state: LessonStateSchema2,
|
|
34355
|
+
/** The Goal it is scoped to; null = the whole account. */
|
|
34356
|
+
scopeGoalId: external_exports.string().nullable(),
|
|
34357
|
+
goalTitle: external_exports.string().nullable(),
|
|
34358
|
+
version: external_exports.number(),
|
|
34272
34359
|
pinned: external_exports.boolean(),
|
|
34273
|
-
/**
|
|
34274
|
-
|
|
34275
|
-
|
|
34276
|
-
|
|
34277
|
-
|
|
34278
|
-
|
|
34279
|
-
lastUsedAt: external_exports.string().nullable(),
|
|
34280
|
-
/** How many asks it has answered. Instrumentation — deliberately NOT an input to the
|
|
34281
|
-
* evidence curve: firing says the question keeps arising, not that the ruling is right. */
|
|
34282
|
-
usedCount: external_exports.number(),
|
|
34283
|
-
/** Ledger: outcomes that said it held up. Saturating — the tenth is worth almost nothing. */
|
|
34284
|
-
confirms: external_exports.number(),
|
|
34285
|
-
/** Ledger: contradictions, in signal units (a full override = 1, weaker signals less).
|
|
34286
|
-
* Linear and priced above the entire confirmation budget, so any full counter wins. */
|
|
34287
|
-
counters: external_exports.number(),
|
|
34288
|
-
/** The agent that asked the question this move came from, when known. Null for a move
|
|
34289
|
-
* distilled from a clarify ruling (those carry no agent) or one whose source rows are gone. */
|
|
34290
|
-
learnedFrom: external_exports.object({ id: external_exports.string(), name: external_exports.string() }).nullable()
|
|
34360
|
+
/** When the person last wrote its text themselves. */
|
|
34361
|
+
editedAt: external_exports.string().nullable(),
|
|
34362
|
+
createdAt: external_exports.string(),
|
|
34363
|
+
updatedAt: external_exports.string(),
|
|
34364
|
+
/** The Entries it came from, oldest first; `words` is null when an Entry has none to show (sealed). */
|
|
34365
|
+
sources: external_exports.array(external_exports.object({ entryId: external_exports.string(), words: external_exports.string().nullable(), at: external_exports.string() }))
|
|
34291
34366
|
});
|
|
34292
34367
|
var QueueQuestionSchema2 = external_exports.object({
|
|
34293
34368
|
/** The decision need's id — what an answer is accepted against. */
|
|
@@ -34549,7 +34624,7 @@ var HostDecisionSchema2 = external_exports.object({
|
|
|
34549
34624
|
goalId: external_exports.string().uuid().nullable().optional(),
|
|
34550
34625
|
/** When the server last heard from the agent, as the host read it: the presence it stood back for. */
|
|
34551
34626
|
seenAt: external_exports.string().datetime().nullable().optional(),
|
|
34552
|
-
/** When that work last moved (`claimable.since` on `
|
|
34627
|
+
/** When that work last moved (`claimable.since` on an agent's `contact({})` read), the fact the bound is judged on. */
|
|
34553
34628
|
since: external_exports.string().datetime().nullable().optional(),
|
|
34554
34629
|
/** What the host said, in its log's own words: why it stood back, or what the take-over did. */
|
|
34555
34630
|
said: external_exports.string().max(300).optional()
|
|
@@ -34907,8 +34982,13 @@ function railFor(opts) {
|
|
|
34907
34982
|
update: (goalId, input) => updateGoal(goalId, input, opts),
|
|
34908
34983
|
// One read and back: the pump owns the waiting, so a Call must not hold a window here.
|
|
34909
34984
|
contact: (input) => contact(input, { ...opts, waits: false }),
|
|
34910
|
-
create: (input) =>
|
|
34911
|
-
|
|
34985
|
+
create: async (input) => {
|
|
34986
|
+
const made = await manageGoals({ changes: [{ kind: "create", ...input }] }, opts);
|
|
34987
|
+
const goal = made.goals.find((g) => g.goalId === made.results[0]?.goalId);
|
|
34988
|
+
if (!goal) throw new Error(`manage_goals create failed: ${made.results[0]?.error ?? "no goal"}`);
|
|
34989
|
+
return { goalId: goal.goalId, revision: goal.revision };
|
|
34990
|
+
},
|
|
34991
|
+
waiting: () => receive(opts)
|
|
34912
34992
|
};
|
|
34913
34993
|
}
|
|
34914
34994
|
function cancelAsks(state) {
|
|
@@ -35037,7 +35117,6 @@ ${event.result?.trim() || "No result reported."}`, state, rail, opts);
|
|
|
35037
35117
|
}
|
|
35038
35118
|
|
|
35039
35119
|
// src/paigy/conversation.ts
|
|
35040
|
-
import { randomUUID as randomUUID5 } from "crypto";
|
|
35041
35120
|
var HARNESS_INSTRUCTION = "You are running as an unattended background harness agent; your user reaches you through Paigy and is not at this terminal. Nothing wakes you after your turn ends but the person, so wait on CI or a deploy inside the turn. The person never sees your turn's final message: 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).";
|
|
35042
35121
|
var SAFETY_MS = 6e4;
|
|
35043
35122
|
var ASK_BEAT_MS = 5e3;
|
|
@@ -35155,23 +35234,23 @@ async function gather(state, rail, held) {
|
|
|
35155
35234
|
const moved = movedBelow(held, state);
|
|
35156
35235
|
for (const { goal, since } of moved) look2(goal.goalId, "subtree", goal.title, since);
|
|
35157
35236
|
const heard = [];
|
|
35158
|
-
const
|
|
35237
|
+
const read3 = /* @__PURE__ */ new Set();
|
|
35159
35238
|
for (const [goalId, { since, ...found }] of looks) {
|
|
35160
35239
|
let brief = found.brief;
|
|
35161
35240
|
if (!brief) {
|
|
35162
35241
|
try {
|
|
35163
35242
|
brief = await rail.read(goalId);
|
|
35164
35243
|
} catch (error) {
|
|
35165
|
-
if (error.status === 404)
|
|
35244
|
+
if (error.status === 404) read3.add(goalId);
|
|
35166
35245
|
continue;
|
|
35167
35246
|
}
|
|
35168
35247
|
}
|
|
35169
|
-
|
|
35248
|
+
read3.add(goalId);
|
|
35170
35249
|
const fresh = !brief.reviewSince && (found.via === "waiting work" || found.via === "assigned") ? sinceTheWork(brief) : { after: -1 };
|
|
35171
35250
|
if (found.via === "assigned") announced.add(goalId);
|
|
35172
35251
|
heard.push({ goalId, ...found, brief, words: unheard(brief, state, brief.reviewSince ? null : since ?? null, fresh.after, brief.reviewSince), ...fresh.note ? { note: fresh.note } : {} });
|
|
35173
35252
|
}
|
|
35174
|
-
for (const { goal, since } of moved) if (
|
|
35253
|
+
for (const { goal, since } of moved) if (read3.has(goal.goalId)) state.below.goals.set(goal.goalId, { since, at: goal.updatedAt ?? null });
|
|
35175
35254
|
return { heard, listed };
|
|
35176
35255
|
}
|
|
35177
35256
|
var GIVEN = "This Goal was given to you, and nobody has started it. Carry on with what you're doing unless it changes that; claim_goal with its id when you take it up.";
|
|
@@ -35289,7 +35368,7 @@ async function look(session, state, rail, opts) {
|
|
|
35289
35368
|
if (opts?.initialPrompt?.trim()) {
|
|
35290
35369
|
const prompt = opts.initialPrompt.trim();
|
|
35291
35370
|
opts.initialPrompt = void 0;
|
|
35292
|
-
const admitted = await rail.create({
|
|
35371
|
+
const admitted = await rail.create({ title: prompt.split(/\s+/).slice(0, 5).join(" ").slice(0, 80), outcome: prompt });
|
|
35293
35372
|
brief2 = await rail.claim();
|
|
35294
35373
|
if (!brief2.goalId || brief2.revision === void 0) {
|
|
35295
35374
|
state.goal = { id: admitted.goalId, revision: admitted.revision };
|
|
@@ -35380,9 +35459,9 @@ async function pump(session, state, rail, opts) {
|
|
|
35380
35459
|
}
|
|
35381
35460
|
if (!await opts.onIdle()) return;
|
|
35382
35461
|
if (now() - since >= BEAT_REPORT_MS) {
|
|
35383
|
-
const
|
|
35384
|
-
if (
|
|
35385
|
-
opts.log?.(`\u25B9 beats: ${
|
|
35462
|
+
const read3 = counts.wake + counts.rest + counts.safety;
|
|
35463
|
+
if (read3 || counts.skipped || tally.noted || tally.seen || tally.announced) {
|
|
35464
|
+
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` : ""}`);
|
|
35386
35465
|
}
|
|
35387
35466
|
counts.wake = counts.rest = counts.safety = counts.skipped = tally.noted = tally.seen = tally.announced = tally.paused = 0;
|
|
35388
35467
|
since = now();
|
|
@@ -35400,7 +35479,7 @@ function runHarness(opts) {
|
|
|
35400
35479
|
const clock4 = beat();
|
|
35401
35480
|
let session = null;
|
|
35402
35481
|
const speaksAs = opts.session ?? opts.resume ?? sessionId();
|
|
35403
|
-
const instance =
|
|
35482
|
+
const instance = randomUUID5();
|
|
35404
35483
|
const rail = railFor({ token: opts.token, reach: reachAs(speaksAs, instance) });
|
|
35405
35484
|
let inbox;
|
|
35406
35485
|
if (opts.harness === "claude") {
|
|
@@ -35639,7 +35718,7 @@ function proven(pid, procStart, deps) {
|
|
|
35639
35718
|
function localHolderPids(deps = {}) {
|
|
35640
35719
|
const dir = deps.dir ?? join7(process.env.CLAUDE_CONFIG_DIR?.trim() || join7(homedir7(), ".claude"), "sessions");
|
|
35641
35720
|
const list = deps.list ?? ((d) => readdirSync3(d));
|
|
35642
|
-
const
|
|
35721
|
+
const read3 = deps.read ?? ((f) => readFileSync5(f, "utf8"));
|
|
35643
35722
|
const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
|
|
35644
35723
|
const held = /* @__PURE__ */ new Map();
|
|
35645
35724
|
let files;
|
|
@@ -35652,7 +35731,7 @@ function localHolderPids(deps = {}) {
|
|
|
35652
35731
|
if (!/^\d+\.json$/.test(file)) continue;
|
|
35653
35732
|
let row;
|
|
35654
35733
|
try {
|
|
35655
|
-
row = JSON.parse(
|
|
35734
|
+
row = JSON.parse(read3(join7(dir, file)));
|
|
35656
35735
|
} catch {
|
|
35657
35736
|
continue;
|
|
35658
35737
|
}
|
|
@@ -35684,7 +35763,7 @@ function descendsFrom(pid, ancestor, parent = psParent) {
|
|
|
35684
35763
|
function localHolders(deps = {}) {
|
|
35685
35764
|
const dir = deps.dir ?? join7(process.env.CLAUDE_CONFIG_DIR?.trim() || join7(homedir7(), ".claude"), "sessions");
|
|
35686
35765
|
const list = deps.list ?? ((d) => readdirSync3(d));
|
|
35687
|
-
const
|
|
35766
|
+
const read3 = deps.read ?? ((f) => readFileSync5(f, "utf8"));
|
|
35688
35767
|
const check = { alive: deps.alive ?? isAlive, started: deps.started ?? psStart };
|
|
35689
35768
|
const held = /* @__PURE__ */ new Map();
|
|
35690
35769
|
let files;
|
|
@@ -35697,7 +35776,7 @@ function localHolders(deps = {}) {
|
|
|
35697
35776
|
if (!/^\d+\.json$/.test(file)) continue;
|
|
35698
35777
|
let row;
|
|
35699
35778
|
try {
|
|
35700
|
-
row = JSON.parse(
|
|
35779
|
+
row = JSON.parse(read3(join7(dir, file)));
|
|
35701
35780
|
} catch {
|
|
35702
35781
|
continue;
|
|
35703
35782
|
}
|
|
@@ -35931,7 +36010,7 @@ async function waitingWork(token, session) {
|
|
|
35931
36010
|
if (quiet !== void 0 && Date.now() < quiet) return { skip: BOUND_SKIP };
|
|
35932
36011
|
let found;
|
|
35933
36012
|
try {
|
|
35934
|
-
found = await
|
|
36013
|
+
found = await receive({ token, ...session ? { reach: reachAs(session) } : {} });
|
|
35935
36014
|
} catch (error) {
|
|
35936
36015
|
if (error instanceof RevokedError) return { skip: "was revoked: its credential is gone for good", revoked: true };
|
|
35937
36016
|
if (error instanceof ApiError && error.body?.error === "identity_session_mismatch") {
|
|
@@ -36170,7 +36249,7 @@ function startHost(opts) {
|
|
|
36170
36249
|
skip(`has a full conversation (${resumes.slice(0, 8)}) \u2014 not resuming it; its Goals go to the dead-agent handoff`);
|
|
36171
36250
|
return;
|
|
36172
36251
|
}
|
|
36173
|
-
const
|
|
36252
|
+
const read3 = async () => {
|
|
36174
36253
|
const got = await waitingWork(token, identity.sessionId ?? owner?.sessionId);
|
|
36175
36254
|
if (!("skip" in got)) return got;
|
|
36176
36255
|
if (got.revoked) {
|
|
@@ -36182,7 +36261,7 @@ function startHost(opts) {
|
|
|
36182
36261
|
return null;
|
|
36183
36262
|
};
|
|
36184
36263
|
if (decided.why === "presence") {
|
|
36185
|
-
found = await
|
|
36264
|
+
found = await read3() ?? void 0;
|
|
36186
36265
|
if (!found) return;
|
|
36187
36266
|
const since = found.since;
|
|
36188
36267
|
decided = wakeAction(false, Date.now(), seenByServer, { ...here, ...since ? { movedAt: Date.parse(since) } : {} });
|
|
@@ -36208,7 +36287,7 @@ function startHost(opts) {
|
|
|
36208
36287
|
skip("has no granted folder to wake in");
|
|
36209
36288
|
return;
|
|
36210
36289
|
}
|
|
36211
|
-
found ??= await
|
|
36290
|
+
found ??= await read3() ?? void 0;
|
|
36212
36291
|
if (!found) return;
|
|
36213
36292
|
if (runs.has(key3)) {
|
|
36214
36293
|
skip("was started by the wake that read it first");
|
|
@@ -36344,7 +36423,7 @@ function startHost(opts) {
|
|
|
36344
36423
|
return {
|
|
36345
36424
|
name,
|
|
36346
36425
|
// The slot key rides along so the window's agent page can speak AS this agent —
|
|
36347
|
-
// its pending reads (`
|
|
36426
|
+
// its pending reads (`receive`, the same pure read the sweep does) need the
|
|
36348
36427
|
// slot's own token, and the display name is not a key.
|
|
36349
36428
|
slot,
|
|
36350
36429
|
tokenId: id3.tokenId,
|
|
@@ -36750,7 +36829,7 @@ async function main() {
|
|
|
36750
36829
|
let launched;
|
|
36751
36830
|
if (parsed.launch) {
|
|
36752
36831
|
overrideToken(readSlot("Desktop") || null);
|
|
36753
|
-
const session =
|
|
36832
|
+
const session = randomUUID6();
|
|
36754
36833
|
const minted = await hatch(parsed.launch, parsed.voice ?? null, {
|
|
36755
36834
|
reach: reachAs(session),
|
|
36756
36835
|
brief: parsed.prompt,
|