@paigy/harness 0.3.39 → 0.3.40
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 +160 -121
- package/dist/main.js +156 -121
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -23696,35 +23696,6 @@ function parseDef(def, refs, forceResolution = false) {
|
|
|
23696
23696
|
newItem.jsonSchema = jsonSchema;
|
|
23697
23697
|
return jsonSchema;
|
|
23698
23698
|
}
|
|
23699
|
-
function draft2020(node) {
|
|
23700
|
-
if (Array.isArray(node)) return node.map(draft2020);
|
|
23701
|
-
if (node && typeof node === "object") {
|
|
23702
|
-
const o = node;
|
|
23703
|
-
if (Array.isArray(o.items)) {
|
|
23704
|
-
o.prefixItems = o.items;
|
|
23705
|
-
if ("additionalItems" in o) {
|
|
23706
|
-
o.items = o.additionalItems;
|
|
23707
|
-
delete o.additionalItems;
|
|
23708
|
-
} else delete o.items;
|
|
23709
|
-
}
|
|
23710
|
-
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
23711
|
-
if (typeof o[excl] === "boolean") {
|
|
23712
|
-
if (o[excl] === true && typeof o[lim] === "number") {
|
|
23713
|
-
o[excl] = o[lim];
|
|
23714
|
-
delete o[lim];
|
|
23715
|
-
} else delete o[excl];
|
|
23716
|
-
}
|
|
23717
|
-
}
|
|
23718
|
-
for (const k of Object.keys(o)) o[k] = draft2020(o[k]);
|
|
23719
|
-
return o;
|
|
23720
|
-
}
|
|
23721
|
-
return node;
|
|
23722
|
-
}
|
|
23723
|
-
function mcpInputSchema(s) {
|
|
23724
|
-
const schema = zodToJsonSchema(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
23725
|
-
delete schema.$schema;
|
|
23726
|
-
return draft2020(schema);
|
|
23727
|
-
}
|
|
23728
23699
|
function capRefusals(text, units22, field) {
|
|
23729
23700
|
const out = [];
|
|
23730
23701
|
const name = field === "text" ? "answer" : field;
|
|
@@ -23766,6 +23737,35 @@ function capRefusals(text, units22, field) {
|
|
|
23766
23737
|
function refuseOverCaps(text, units22, field, ctx) {
|
|
23767
23738
|
for (const { path, message, ...params } of capRefusals(text, units22, field)) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message, params });
|
|
23768
23739
|
}
|
|
23740
|
+
function draft2020(node) {
|
|
23741
|
+
if (Array.isArray(node)) return node.map(draft2020);
|
|
23742
|
+
if (node && typeof node === "object") {
|
|
23743
|
+
const o = node;
|
|
23744
|
+
if (Array.isArray(o.items)) {
|
|
23745
|
+
o.prefixItems = o.items;
|
|
23746
|
+
if ("additionalItems" in o) {
|
|
23747
|
+
o.items = o.additionalItems;
|
|
23748
|
+
delete o.additionalItems;
|
|
23749
|
+
} else delete o.items;
|
|
23750
|
+
}
|
|
23751
|
+
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
23752
|
+
if (typeof o[excl] === "boolean") {
|
|
23753
|
+
if (o[excl] === true && typeof o[lim] === "number") {
|
|
23754
|
+
o[excl] = o[lim];
|
|
23755
|
+
delete o[lim];
|
|
23756
|
+
} else delete o[excl];
|
|
23757
|
+
}
|
|
23758
|
+
}
|
|
23759
|
+
for (const k of Object.keys(o)) o[k] = draft2020(o[k]);
|
|
23760
|
+
return o;
|
|
23761
|
+
}
|
|
23762
|
+
return node;
|
|
23763
|
+
}
|
|
23764
|
+
function mcpInputSchema(s) {
|
|
23765
|
+
const schema = zodToJsonSchema(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
23766
|
+
delete schema.$schema;
|
|
23767
|
+
return draft2020(schema);
|
|
23768
|
+
}
|
|
23769
23769
|
function entryUnit(entry) {
|
|
23770
23770
|
if (entry.kind !== "contribution" || !entry.aboutId) return null;
|
|
23771
23771
|
const plain = entry.content && "plain" in entry.content ? entry.content.plain : null;
|
|
@@ -23898,15 +23898,15 @@ async function manageGoals(input, opts = {}) {
|
|
|
23898
23898
|
if (!res.ok) await fail("manage_goals", res);
|
|
23899
23899
|
return await res.json();
|
|
23900
23900
|
}
|
|
23901
|
-
async function
|
|
23901
|
+
async function getGoals(goalIds, opts = {}, read3 = {}) {
|
|
23902
23902
|
const token = authToken(opts.token) ?? "";
|
|
23903
|
-
const
|
|
23904
|
-
|
|
23905
|
-
|
|
23906
|
-
|
|
23903
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/read`, {
|
|
23904
|
+
method: "POST",
|
|
23905
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
23906
|
+
body: JSON.stringify({ goalIds, ...read3 })
|
|
23907
23907
|
}));
|
|
23908
|
-
if (!res.ok) await fail("
|
|
23909
|
-
return await res.json();
|
|
23908
|
+
if (!res.ok) await fail("get_goals", res);
|
|
23909
|
+
return (await res.json()).goals;
|
|
23910
23910
|
}
|
|
23911
23911
|
async function hatch(name, voice = null, opts = {}) {
|
|
23912
23912
|
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/hatch`, {
|
|
@@ -24045,6 +24045,7 @@ async function contact(input, opts = {}) {
|
|
|
24045
24045
|
body: JSON.stringify({
|
|
24046
24046
|
operationId: opts.operationId ?? randomUUID2(),
|
|
24047
24047
|
...parsed.updates ? { updates: parsed.updates } : {},
|
|
24048
|
+
...parsed.completions ? { completions: parsed.completions } : {},
|
|
24048
24049
|
...questions ? { questions } : {},
|
|
24049
24050
|
...parsed.answers ? { answers: parsed.answers } : {},
|
|
24050
24051
|
...parsed.withdrawQuestionIds ? { withdrawQuestionIds: parsed.withdrawQuestionIds } : {},
|
|
@@ -24295,13 +24296,15 @@ ${block2}`;
|
|
|
24295
24296
|
}
|
|
24296
24297
|
return text.slice(0, start) + updated + text.slice(end);
|
|
24297
24298
|
}
|
|
24298
|
-
var import_undici, require2, CODEX_ENV, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, CLIENT, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OPTION_LABEL_MAX, OPTION_HINT_MAX, OptionSchema, OptionInputSchema, NIGHT,
|
|
24299
|
+
var import_undici, require2, CODEX_ENV, BACKEND_URL, NETWORK_MSG, PROXY_ENV, agent, INSTANCE_ID, WORKSPACE_ID, envSession, lineage, CLIENT, ignoreOverride, defaultOptions, getDefaultOptions, getRefs, getRelativePath, parseCatchDef, integerDateParser, isJsonSchema7AllOfType, emojiRegex2, zodPatterns, ALPHA_NUMERIC, primitiveMappings, asAnyOf, parseOptionalDef, parsePipelineDef, parseReadonlyDef, selectParser, get$ref, addMeta, zodToJsonSchema, OPTIONS_MIN, OPTIONS_MAX, OPTION_LABEL_MAX, OPTION_HINT_MAX, OptionSchema, OptionInputSchema, NIGHT, ASK_MAX, UNITS_MAX, UNIT_TITLE_MAX, UNIT_BODY_MAX, UnitInputSchema, COMPLETION_MESSAGE_MAX, CompletionSchema, CompleteChangeSchema, ASKING_RULES, questionHandle, NodeRef, BlockedAction, reason, actionFits, ACTION_FITS, userExplicitlyRequested, units, UpdateInputSchema, questionFields, refineQuestion, QuestionInputSchema, QuestionWireSchema, AnswerInputSchema, QuestionDependencySchema, sendFields, ContactSchema, sendsAnything, ContactWireSchema, CONTACT_SCHEMA, CONTACT_DESCRIPTION, CreateGoalSchema, UpdateGoalSchema, changedGoal, goalTitle, GOAL_OUTCOME_MAX, goalOutcome, CreateChange, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange, read, GoalChangeSchema, editNames, ManageGoalsSchema, ManageGoalsToolSchema, MANAGE_GOALS_DESCRIPTION, GetGoalsSchema, GetDeliverySchema, GET_DELIVERY_DESCRIPTION, GET_GOALS_DESCRIPTION, SearchToolSchema, SEARCH_DESCRIPTION, ConfigureIdentitySchema, CONFIGURE_IDENTITY_DESCRIPTION, CheckActivitySchema, FEEDBACK_TEXT_MAX, SendFeedbackSchema, SEND_FEEDBACK_DESCRIPTION, AGENT_TOOLS, AGENT_TOOL_NAMES, id, key, participant, SourceSchema, ResultRefSchema, NodeRefSchema, DependencySchema, goalState, existingGoalChanges, BrainGoalChangeSchema, option, QuestionChangeSchema, lessonScope, LessonChangeSchema, BrainNextSchema, messageBase, BrainMessageSchema, BrainSearchSchema, BrainResultSchema, str, strs, CompactResultSchema, COMPACT_RESULT_JSON_SCHEMA, str2, strs2, TalkerReplySchema, TALKER_REPLY_JSON_SCHEMA, str3, strs3, FilerReplySchema, FILER_REPLY_JSON_SCHEMA, ExplainerReplySchema, EXPLAINER_REPLY_JSON_SCHEMA, DISTILLER_DEFECTS, DistillerReplySchema, DISTILLER_REPLY_JSON_SCHEMA, TIDY_AUDIENCES, TidyReplySchema, TIDY_REPLY_JSON_SCHEMA, LIVE_MS, WORKING_MS, WORKING_TIER_MS, RECENT_TIER_MS, json, clock, HeardEventSchema, HeardCursorSchema, HeardPageSchema, MAX_EVENTS, MAX_BYTES, batchBytes, HeardBatchSchema, 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, clock2, QUIET, BrokerTuningSchema, UserSettingsSchema, HistoryWorkSchema, HistoryEntrySchema, HistoryPageSchema, ACTIVITY_LINES, ACTIVITY_LINE_MAX, AgentActivitySchema, ConnectionSummarySchema, LedgerItemSchema, AgentLedgerSchema, ReassignResultSchema, LessonStateSchema, LessonViewSchema, QueueQuestionSchema, QueueReplySchema, QueueItemSchema, QueueDeltaSchema, COLD_AFTER_MS, NoteSourceSchema, NoteStatusSchema, NoteRepeatSchema, DecisionSchema, NoteSchema, TriageItemSchema, TriageAssignmentSchema, TriageStatusSchema, SubmitTriageSchema, TriageProposalSchema, AcceptTriageSchema, AcceptTriageResultSchema, DeliveryModeSchema, WAKE_EVENT, wakeChannel, RegisterDeliverySchema, OAuthStartSchema, DeliveryConfigSchema, HostDecisionSchema, WakeNudgeSchema, PairingStatusSchema, DeviceCodeSchema, DeviceInfoSchema, DeviceTokenSchema, SupportRequestSchema, NotificationFeedbackKindSchema, SlimOptionSchema, QuestionRowSchema, WorkStateSchema, WorkRowSchema, ComputerRowSchema, AgentRowSchema, SnapshotSchema, CallRecapSchema, TOKEN_PATH, KEY_PATH, sleep, UnpairedError, RevokedError, ApiError, tokenOverride, authToken, AWAIT_WINDOW_MS, NOT_SENT, APPLIED, DEMOTED, HEARTBEAT_MS, RETRY_MS, JOIN, JOIN_TIMEOUT_MS, lines;
|
|
24299
24300
|
var init_dist = __esm({
|
|
24300
24301
|
"../../packages/sdk/dist/index.js"() {
|
|
24301
24302
|
"use strict";
|
|
24302
24303
|
init_zod();
|
|
24303
24304
|
init_zod();
|
|
24304
24305
|
init_zod();
|
|
24306
|
+
init_zod();
|
|
24307
|
+
init_zod();
|
|
24305
24308
|
init_v3();
|
|
24306
24309
|
init_v3();
|
|
24307
24310
|
init_v3();
|
|
@@ -24720,24 +24723,39 @@ var init_dist = __esm({
|
|
|
24720
24723
|
imgUrl: OptionSchema.shape.image
|
|
24721
24724
|
}).strict();
|
|
24722
24725
|
NIGHT = { from: 23, to: 7 };
|
|
24726
|
+
ASK_MAX = 250;
|
|
24727
|
+
UNITS_MAX = 12;
|
|
24728
|
+
UNIT_TITLE_MAX = 50;
|
|
24729
|
+
UNIT_BODY_MAX = 200;
|
|
24730
|
+
UnitInputSchema = external_exports.object({
|
|
24731
|
+
title: external_exports.string().trim().min(1).describe(`What this unit is about, at most ${UNIT_TITLE_MAX} characters. The app lists the titles; the person taps one to read its body.`),
|
|
24732
|
+
body: external_exports.string().trim().min(1).describe(`The unit itself, at most ${UNIT_BODY_MAX} characters.`)
|
|
24733
|
+
}).strict();
|
|
24734
|
+
COMPLETION_MESSAGE_MAX = 50;
|
|
24735
|
+
CompletionSchema = external_exports.object({
|
|
24736
|
+
goalId: external_exports.string().uuid().describe("The existing Goal to complete."),
|
|
24737
|
+
message: external_exports.string().trim().min(1).max(COMPLETION_MESSAGE_MAX, "completion_message_too_long: at most 50 characters; put detail in units.").describe("Completion headline, at most 50 characters."),
|
|
24738
|
+
units: external_exports.array(UnitInputSchema.extend({
|
|
24739
|
+
title: external_exports.string().trim().min(1).max(UNIT_TITLE_MAX),
|
|
24740
|
+
body: external_exports.string().trim().min(1).max(UNIT_BODY_MAX)
|
|
24741
|
+
})).max(UNITS_MAX).optional().describe("Suggest initial state, changes, current state with verification and limits, and next steps / leftover work with its owner when useful. One idea per unit; omit unnecessary sections."),
|
|
24742
|
+
reply: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX).describe("One acknowledgement in the person's voice, at most 50 characters. Acknowledgement alone requests no follow-up and does not claim they tested the work."),
|
|
24743
|
+
options: external_exports.array(external_exports.object({
|
|
24744
|
+
label: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX),
|
|
24745
|
+
hint: external_exports.string().trim().min(1).max(OPTION_HINT_MAX)
|
|
24746
|
+
}).strict()).max(5).optional().describe("Optional next steps the person may initiate: label (50 characters) and consequence in hint (200). Selecting one acknowledges the report and requests that step from its author; it never reopens this Goal.")
|
|
24747
|
+
}).strict();
|
|
24748
|
+
CompleteChangeSchema = CompletionSchema.extend({ kind: external_exports.literal("complete") });
|
|
24723
24749
|
ASKING_RULES = `HOW TO ASK:
|
|
24724
24750
|
1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
24725
24751
|
2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
|
|
24726
24752
|
3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
|
|
24727
|
-
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`
|
|
24753
|
+
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`get_goals\` on that wake.
|
|
24728
24754
|
5. One question, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open. Take back one that no longer matters with \`withdrawQuestionIds\`.
|
|
24729
24755
|
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
24730
24756
|
7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
|
|
24731
24757
|
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
|
|
24732
24758
|
9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
|
|
24733
|
-
ASK_MAX = 250;
|
|
24734
|
-
UNITS_MAX = 12;
|
|
24735
|
-
UNIT_TITLE_MAX = 50;
|
|
24736
|
-
UNIT_BODY_MAX = 200;
|
|
24737
|
-
UnitInputSchema = external_exports.object({
|
|
24738
|
-
title: external_exports.string().trim().min(1).describe(`What this unit is about, at most ${UNIT_TITLE_MAX} characters. The app lists the titles; the person taps one to read its body.`),
|
|
24739
|
-
body: external_exports.string().trim().min(1).describe(`The unit itself, at most ${UNIT_BODY_MAX} characters.`)
|
|
24740
|
-
}).strict();
|
|
24741
24759
|
questionHandle = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
24742
24760
|
NodeRef = external_exports.object({
|
|
24743
24761
|
type: external_exports.enum(["goal", "question"]),
|
|
@@ -24848,6 +24866,7 @@ var init_dist = __esm({
|
|
|
24848
24866
|
reason: reason.optional()
|
|
24849
24867
|
}).strict().refine(actionFits, ACTION_FITS);
|
|
24850
24868
|
sendFields = {
|
|
24869
|
+
completions: external_exports.array(CompletionSchema).min(1).max(20).optional().describe("Close existing Goals and deliver their completion reports atomically. Ordinary updates never close work."),
|
|
24851
24870
|
updates: external_exports.array(UpdateInputSchema).min(1).max(20).optional().describe(
|
|
24852
24871
|
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress and nobody is notified."
|
|
24853
24872
|
),
|
|
@@ -24870,20 +24889,22 @@ var init_dist = __esm({
|
|
|
24870
24889
|
"Only controls when this returns. Sending: false (the default) returns at once; true waits up to about 45 seconds for a response to what you sent. Sending nothing: true (the default) waits up to about 45 seconds for anything addressed to you; false returns what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived; wait again without sending again), or `not_waited`."
|
|
24871
24890
|
)
|
|
24872
24891
|
}).strict();
|
|
24873
|
-
sendsAnything = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
24892
|
+
sendsAnything = (c) => !!(c.completions?.length || c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
24874
24893
|
ContactWireSchema = external_exports.object({
|
|
24875
24894
|
operationId: external_exports.string().uuid(),
|
|
24876
24895
|
...sendFields,
|
|
24877
24896
|
questions: external_exports.array(QuestionWireSchema).min(1).max(20).optional()
|
|
24878
24897
|
}).strict().refine(sendsAnything, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
24879
24898
|
CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
24880
|
-
CONTACT_DESCRIPTION = "Send to and receive from the person: updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES + `
|
|
24899
|
+
CONTACT_DESCRIPTION = "Send to and receive from the person: completions, updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES + `
|
|
24881
24900
|
|
|
24882
24901
|
CUT A LONG MESSAGE BEFORE YOU SEND IT: a question, an update's message or an answer is the one point, in at most ${ASK_MAX} characters; everything else it needs goes in 'units', up to ${UNITS_MAX} {title, body} in reading order, one idea each, every title at most ${UNIT_TITLE_MAX} characters and every body at most ${UNIT_BODY_MAX}. The person sees the main text and the titles, and opens a unit to read its body. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.
|
|
24883
24902
|
|
|
24884
|
-
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified.
|
|
24903
|
+
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified. Ordinary updates never close a Goal. On a Goal whose report card is still open, an update that reaches them is added to that card, with no new push. If the person is already on a call, anything that reaches them joins that call, with no ring.
|
|
24904
|
+
|
|
24905
|
+
COMPLETIONS close and report in one operation: completions:[{goalId,message,units?,reply,options?}]. The same contract works in manage_goals changes with kind:complete. message is at most 50 characters; use units when useful for initial state, changes, current state (verification and limits), and next steps / leftover work with its owner. reply is one acknowledgement in the person's voice. Optional options:[{label,hint}] suggest next steps: a tap acknowledges the report and requests that step from its author. It never reopens the completed Goal; follow-up work needs a new Goal. Closure and the report commit together or neither does. Required children and dependencies must already be finished. No Reviewer rejudges your completion; say only what your evidence supports.
|
|
24885
24906
|
|
|
24886
|
-
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with
|
|
24907
|
+
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with get_goals); \`instruction\`, a request or note sent to you. \`hasMore\` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (\`assigned\`; your first write to it starts it) and your work gone quiet (\`stalled\`).`;
|
|
24887
24908
|
CreateGoalSchema = external_exports.object({
|
|
24888
24909
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
24889
24910
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -24956,6 +24977,7 @@ RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of w
|
|
|
24956
24977
|
read = { revision: external_exports.number().int().positive().optional() };
|
|
24957
24978
|
GoalChangeSchema = external_exports.discriminatedUnion("kind", [
|
|
24958
24979
|
CreateChange,
|
|
24980
|
+
CompleteChangeSchema.extend(read),
|
|
24959
24981
|
EditChange.extend(read),
|
|
24960
24982
|
StateChange.extend(read),
|
|
24961
24983
|
AssignChange.extend(read),
|
|
@@ -24973,24 +24995,20 @@ RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of w
|
|
|
24973
24995
|
changes: external_exports.array(GoalChangeSchema).min(1).max(50)
|
|
24974
24996
|
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
24975
24997
|
ManageGoalsToolSchema = external_exports.object({
|
|
24976
|
-
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.")
|
|
24998
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange, CompleteChangeSchema, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
24977
24999
|
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
24978
|
-
MANAGE_GOALS_DESCRIPTION = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (
|
|
24979
|
-
|
|
24980
|
-
|
|
25000
|
+
MANAGE_GOALS_DESCRIPTION = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: complete (goalId, message capped at 50 characters, units, reply, optional next-step options {label, hint}) closes and reports atomically, exactly as contact.completions; create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goals) and reconsider. You may change any Goal of your person; a change puts you on it. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
25001
|
+
GetGoalsSchema = external_exports.object({
|
|
25002
|
+
goalIds: external_exports.array(external_exports.string().uuid()).min(1).max(10).describe("The Goals to read, in order; one to ten IDs."),
|
|
24981
25003
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
24982
25004
|
* newest entry, and counts what it left out (`apps/api/src/goal/collapse.ts`). */
|
|
24983
|
-
history: external_exports.boolean().optional()
|
|
24984
|
-
/** WHEN A READ HAS CONFUSED YOU. Adds `diagnosis`: every reader that already answers a question
|
|
24985
|
-
* about this work, each answer attributed to the reader that gave it, and every disagreement
|
|
24986
|
-
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
24987
|
-
diagnose: external_exports.boolean().optional()
|
|
25005
|
+
history: external_exports.boolean().optional()
|
|
24988
25006
|
}).strict();
|
|
24989
25007
|
GetDeliverySchema = external_exports.object({
|
|
24990
25008
|
deliveryId: external_exports.string().uuid().describe("The Delivery id returned by contact or receive.")
|
|
24991
25009
|
}).strict();
|
|
24992
25010
|
GET_DELIVERY_DESCRIPTION = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
24993
|
-
|
|
25011
|
+
GET_GOALS_DESCRIPTION = "Read one to ten Goals by goalIds, returned in the same order under goals (a read never puts you on them). history applies to every requested Goal. A refused read fails the call with its original refusal; no partial result is presented as complete. Each Goal includes its ten most recent other contributors (names, latest entry headlines and times), 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.";
|
|
24994
25012
|
SearchToolSchema = external_exports.object({
|
|
24995
25013
|
query: external_exports.string().trim().min(1).max(500),
|
|
24996
25014
|
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
@@ -25013,9 +25031,9 @@ RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of w
|
|
|
25013
25031
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
25014
25032
|
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(ManageGoalsToolSchema) },
|
|
25015
25033
|
{ name: "get_delivery", description: GET_DELIVERY_DESCRIPTION, inputSchema: mcpInputSchema(GetDeliverySchema) },
|
|
25016
|
-
{ name: "
|
|
25034
|
+
{ name: "get_goals", description: GET_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(GetGoalsSchema) },
|
|
25017
25035
|
{ name: "search", description: SEARCH_DESCRIPTION, inputSchema: mcpInputSchema(SearchToolSchema) },
|
|
25018
|
-
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use
|
|
25036
|
+
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goals to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(CheckActivitySchema) },
|
|
25019
25037
|
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION, inputSchema: mcpInputSchema(SendFeedbackSchema) }
|
|
25020
25038
|
];
|
|
25021
25039
|
AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
@@ -26523,6 +26541,8 @@ RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of w
|
|
|
26523
26541
|
status: external_exports.string(),
|
|
26524
26542
|
startedAt: external_exports.string(),
|
|
26525
26543
|
durationMs: external_exports.number().nullable(),
|
|
26544
|
+
/** Bot-clock pickup offset; absent before the timestamp release, null before its report lands. */
|
|
26545
|
+
pickupMs: external_exports.number().nullable().optional(),
|
|
26526
26546
|
agents: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string().nullable() }))
|
|
26527
26547
|
}),
|
|
26528
26548
|
topics: external_exports.array(external_exports.object({
|
|
@@ -26605,7 +26625,7 @@ RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of w
|
|
|
26605
26625
|
tokenOverride = null;
|
|
26606
26626
|
authToken = (explicit) => explicit ?? tokenOverride ?? readToken();
|
|
26607
26627
|
AWAIT_WINDOW_MS = 45e3;
|
|
26608
|
-
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,
|
|
26628
|
+
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, send contact.completions or manage_goals kind:complete with the shared completion report, closing and reporting together. If the person asked you, in so many words, to send them this, send it again with userExplicitlyRequested: "any" on that update.`;
|
|
26609
26629
|
APPLIED = "Applied; nothing was sent to the person.";
|
|
26610
26630
|
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.";
|
|
26611
26631
|
HEARTBEAT_MS = 25e3;
|
|
@@ -32372,6 +32392,8 @@ function startSession(opts) {
|
|
|
32372
32392
|
init_zod();
|
|
32373
32393
|
init_zod();
|
|
32374
32394
|
init_zod();
|
|
32395
|
+
init_zod();
|
|
32396
|
+
init_zod();
|
|
32375
32397
|
|
|
32376
32398
|
// ../../node_modules/.pnpm/zod-to-json-schema@3.25.2_zod@3.25.76/node_modules/zod-to-json-schema/dist/esm/Options.js
|
|
32377
32399
|
var ignoreOverride2 = /* @__PURE__ */ Symbol("Let zodToJsonSchema decide on which parser to use");
|
|
@@ -33701,45 +33723,6 @@ var OptionInputSchema2 = external_exports.object({
|
|
|
33701
33723
|
imgUrl: OptionSchema2.shape.image
|
|
33702
33724
|
}).strict();
|
|
33703
33725
|
var NIGHT2 = { from: 23, to: 7 };
|
|
33704
|
-
var ASKING_RULES2 = `HOW TO ASK:
|
|
33705
|
-
1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
33706
|
-
2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
|
|
33707
|
-
3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
|
|
33708
|
-
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`get_goal\` on that wake.
|
|
33709
|
-
5. One question, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open. Take back one that no longer matters with \`withdrawQuestionIds\`.
|
|
33710
|
-
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
33711
|
-
7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
|
|
33712
|
-
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
|
|
33713
|
-
9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
|
|
33714
|
-
function draft20202(node) {
|
|
33715
|
-
if (Array.isArray(node)) return node.map(draft20202);
|
|
33716
|
-
if (node && typeof node === "object") {
|
|
33717
|
-
const o = node;
|
|
33718
|
-
if (Array.isArray(o.items)) {
|
|
33719
|
-
o.prefixItems = o.items;
|
|
33720
|
-
if ("additionalItems" in o) {
|
|
33721
|
-
o.items = o.additionalItems;
|
|
33722
|
-
delete o.additionalItems;
|
|
33723
|
-
} else delete o.items;
|
|
33724
|
-
}
|
|
33725
|
-
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
33726
|
-
if (typeof o[excl] === "boolean") {
|
|
33727
|
-
if (o[excl] === true && typeof o[lim] === "number") {
|
|
33728
|
-
o[excl] = o[lim];
|
|
33729
|
-
delete o[lim];
|
|
33730
|
-
} else delete o[excl];
|
|
33731
|
-
}
|
|
33732
|
-
}
|
|
33733
|
-
for (const k of Object.keys(o)) o[k] = draft20202(o[k]);
|
|
33734
|
-
return o;
|
|
33735
|
-
}
|
|
33736
|
-
return node;
|
|
33737
|
-
}
|
|
33738
|
-
function mcpInputSchema2(s) {
|
|
33739
|
-
const schema = zodToJsonSchema2(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
33740
|
-
delete schema.$schema;
|
|
33741
|
-
return draft20202(schema);
|
|
33742
|
-
}
|
|
33743
33726
|
var ASK_MAX2 = 250;
|
|
33744
33727
|
var UNITS_MAX2 = 12;
|
|
33745
33728
|
var UNIT_TITLE_MAX2 = 50;
|
|
@@ -33789,6 +33772,60 @@ function capRefusals2(text, units22, field) {
|
|
|
33789
33772
|
function refuseOverCaps2(text, units22, field, ctx) {
|
|
33790
33773
|
for (const { path, message, ...params } of capRefusals2(text, units22, field)) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message, params });
|
|
33791
33774
|
}
|
|
33775
|
+
var COMPLETION_MESSAGE_MAX2 = 50;
|
|
33776
|
+
var CompletionSchema2 = external_exports.object({
|
|
33777
|
+
goalId: external_exports.string().uuid().describe("The existing Goal to complete."),
|
|
33778
|
+
message: external_exports.string().trim().min(1).max(COMPLETION_MESSAGE_MAX2, "completion_message_too_long: at most 50 characters; put detail in units.").describe("Completion headline, at most 50 characters."),
|
|
33779
|
+
units: external_exports.array(UnitInputSchema2.extend({
|
|
33780
|
+
title: external_exports.string().trim().min(1).max(UNIT_TITLE_MAX2),
|
|
33781
|
+
body: external_exports.string().trim().min(1).max(UNIT_BODY_MAX2)
|
|
33782
|
+
})).max(UNITS_MAX2).optional().describe("Suggest initial state, changes, current state with verification and limits, and next steps / leftover work with its owner when useful. One idea per unit; omit unnecessary sections."),
|
|
33783
|
+
reply: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX2).describe("One acknowledgement in the person's voice, at most 50 characters. Acknowledgement alone requests no follow-up and does not claim they tested the work."),
|
|
33784
|
+
options: external_exports.array(external_exports.object({
|
|
33785
|
+
label: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX2),
|
|
33786
|
+
hint: external_exports.string().trim().min(1).max(OPTION_HINT_MAX2)
|
|
33787
|
+
}).strict()).max(5).optional().describe("Optional next steps the person may initiate: label (50 characters) and consequence in hint (200). Selecting one acknowledges the report and requests that step from its author; it never reopens this Goal.")
|
|
33788
|
+
}).strict();
|
|
33789
|
+
var CompleteChangeSchema2 = CompletionSchema2.extend({ kind: external_exports.literal("complete") });
|
|
33790
|
+
var ASKING_RULES2 = `HOW TO ASK:
|
|
33791
|
+
1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
33792
|
+
2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
|
|
33793
|
+
3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
|
|
33794
|
+
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`get_goals\` on that wake.
|
|
33795
|
+
5. One question, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open. Take back one that no longer matters with \`withdrawQuestionIds\`.
|
|
33796
|
+
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
33797
|
+
7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
|
|
33798
|
+
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
|
|
33799
|
+
9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
|
|
33800
|
+
function draft20202(node) {
|
|
33801
|
+
if (Array.isArray(node)) return node.map(draft20202);
|
|
33802
|
+
if (node && typeof node === "object") {
|
|
33803
|
+
const o = node;
|
|
33804
|
+
if (Array.isArray(o.items)) {
|
|
33805
|
+
o.prefixItems = o.items;
|
|
33806
|
+
if ("additionalItems" in o) {
|
|
33807
|
+
o.items = o.additionalItems;
|
|
33808
|
+
delete o.additionalItems;
|
|
33809
|
+
} else delete o.items;
|
|
33810
|
+
}
|
|
33811
|
+
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
33812
|
+
if (typeof o[excl] === "boolean") {
|
|
33813
|
+
if (o[excl] === true && typeof o[lim] === "number") {
|
|
33814
|
+
o[excl] = o[lim];
|
|
33815
|
+
delete o[lim];
|
|
33816
|
+
} else delete o[excl];
|
|
33817
|
+
}
|
|
33818
|
+
}
|
|
33819
|
+
for (const k of Object.keys(o)) o[k] = draft20202(o[k]);
|
|
33820
|
+
return o;
|
|
33821
|
+
}
|
|
33822
|
+
return node;
|
|
33823
|
+
}
|
|
33824
|
+
function mcpInputSchema2(s) {
|
|
33825
|
+
const schema = zodToJsonSchema2(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
33826
|
+
delete schema.$schema;
|
|
33827
|
+
return draft20202(schema);
|
|
33828
|
+
}
|
|
33792
33829
|
var questionHandle2 = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
33793
33830
|
var NodeRef2 = external_exports.object({
|
|
33794
33831
|
type: external_exports.enum(["goal", "question"]),
|
|
@@ -33899,6 +33936,7 @@ var QuestionDependencySchema2 = external_exports.object({
|
|
|
33899
33936
|
reason: reason2.optional()
|
|
33900
33937
|
}).strict().refine(actionFits2, ACTION_FITS2);
|
|
33901
33938
|
var sendFields2 = {
|
|
33939
|
+
completions: external_exports.array(CompletionSchema2).min(1).max(20).optional().describe("Close existing Goals and deliver their completion reports atomically. Ordinary updates never close work."),
|
|
33902
33940
|
updates: external_exports.array(UpdateInputSchema2).min(1).max(20).optional().describe(
|
|
33903
33941
|
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress and nobody is notified."
|
|
33904
33942
|
),
|
|
@@ -33921,20 +33959,22 @@ var ContactSchema2 = external_exports.object({
|
|
|
33921
33959
|
"Only controls when this returns. Sending: false (the default) returns at once; true waits up to about 45 seconds for a response to what you sent. Sending nothing: true (the default) waits up to about 45 seconds for anything addressed to you; false returns what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived; wait again without sending again), or `not_waited`."
|
|
33922
33960
|
)
|
|
33923
33961
|
}).strict();
|
|
33924
|
-
var sendsAnything2 = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
33962
|
+
var sendsAnything2 = (c) => !!(c.completions?.length || c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
33925
33963
|
var ContactWireSchema2 = external_exports.object({
|
|
33926
33964
|
operationId: external_exports.string().uuid(),
|
|
33927
33965
|
...sendFields2,
|
|
33928
33966
|
questions: external_exports.array(QuestionWireSchema2).min(1).max(20).optional()
|
|
33929
33967
|
}).strict().refine(sendsAnything2, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
33930
33968
|
var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
|
|
33931
|
-
var CONTACT_DESCRIPTION2 = "Send to and receive from the person: updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES2 + `
|
|
33969
|
+
var CONTACT_DESCRIPTION2 = "Send to and receive from the person: completions, updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES2 + `
|
|
33932
33970
|
|
|
33933
33971
|
CUT A LONG MESSAGE BEFORE YOU SEND IT: a question, an update's message or an answer is the one point, in at most ${ASK_MAX2} characters; everything else it needs goes in 'units', up to ${UNITS_MAX2} {title, body} in reading order, one idea each, every title at most ${UNIT_TITLE_MAX2} characters and every body at most ${UNIT_BODY_MAX2}. The person sees the main text and the titles, and opens a unit to read its body. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.
|
|
33934
33972
|
|
|
33935
|
-
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified.
|
|
33973
|
+
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified. Ordinary updates never close a Goal. On a Goal whose report card is still open, an update that reaches them is added to that card, with no new push. If the person is already on a call, anything that reaches them joins that call, with no ring.
|
|
33974
|
+
|
|
33975
|
+
COMPLETIONS close and report in one operation: completions:[{goalId,message,units?,reply,options?}]. The same contract works in manage_goals changes with kind:complete. message is at most 50 characters; use units when useful for initial state, changes, current state (verification and limits), and next steps / leftover work with its owner. reply is one acknowledgement in the person's voice. Optional options:[{label,hint}] suggest next steps: a tap acknowledges the report and requests that step from its author. It never reopens the completed Goal; follow-up work needs a new Goal. Closure and the report commit together or neither does. Required children and dependencies must already be finished. No Reviewer rejudges your completion; say only what your evidence supports.
|
|
33936
33976
|
|
|
33937
|
-
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with
|
|
33977
|
+
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with get_goals); \`instruction\`, a request or note sent to you. \`hasMore\` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (\`assigned\`; your first write to it starts it) and your work gone quiet (\`stalled\`).`;
|
|
33938
33978
|
var CreateGoalSchema2 = external_exports.object({
|
|
33939
33979
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
33940
33980
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -34007,6 +34047,7 @@ var DependencyChange2 = external_exports.object({
|
|
|
34007
34047
|
var read2 = { revision: external_exports.number().int().positive().optional() };
|
|
34008
34048
|
var GoalChangeSchema2 = external_exports.discriminatedUnion("kind", [
|
|
34009
34049
|
CreateChange2,
|
|
34050
|
+
CompleteChangeSchema2.extend(read2),
|
|
34010
34051
|
EditChange2.extend(read2),
|
|
34011
34052
|
StateChange2.extend(read2),
|
|
34012
34053
|
AssignChange2.extend(read2),
|
|
@@ -34024,24 +34065,20 @@ var ManageGoalsSchema2 = external_exports.object({
|
|
|
34024
34065
|
changes: external_exports.array(GoalChangeSchema2).min(1).max(50)
|
|
34025
34066
|
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
34026
34067
|
var ManageGoalsToolSchema2 = external_exports.object({
|
|
34027
|
-
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.")
|
|
34068
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange2, CompleteChangeSchema2, EditChange2, StateChange2, AssignChange2, DeferChange2, MoveChange2, DependencyChange2])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
34028
34069
|
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
34029
|
-
var MANAGE_GOALS_DESCRIPTION2 = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (
|
|
34030
|
-
var
|
|
34031
|
-
|
|
34070
|
+
var MANAGE_GOALS_DESCRIPTION2 = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: complete (goalId, message capped at 50 characters, units, reply, optional next-step options {label, hint}) closes and reports atomically, exactly as contact.completions; create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goals) and reconsider. You may change any Goal of your person; a change puts you on it. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
34071
|
+
var GetGoalsSchema2 = external_exports.object({
|
|
34072
|
+
goalIds: external_exports.array(external_exports.string().uuid()).min(1).max(10).describe("The Goals to read, in order; one to ten IDs."),
|
|
34032
34073
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
34033
34074
|
* newest entry, and counts what it left out (`apps/api/src/goal/collapse.ts`). */
|
|
34034
|
-
history: external_exports.boolean().optional()
|
|
34035
|
-
/** WHEN A READ HAS CONFUSED YOU. Adds `diagnosis`: every reader that already answers a question
|
|
34036
|
-
* about this work, each answer attributed to the reader that gave it, and every disagreement
|
|
34037
|
-
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
34038
|
-
diagnose: external_exports.boolean().optional()
|
|
34075
|
+
history: external_exports.boolean().optional()
|
|
34039
34076
|
}).strict();
|
|
34040
34077
|
var GetDeliverySchema2 = external_exports.object({
|
|
34041
34078
|
deliveryId: external_exports.string().uuid().describe("The Delivery id returned by contact or receive.")
|
|
34042
34079
|
}).strict();
|
|
34043
34080
|
var GET_DELIVERY_DESCRIPTION2 = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
34044
|
-
var
|
|
34081
|
+
var GET_GOALS_DESCRIPTION2 = "Read one to ten Goals by goalIds, returned in the same order under goals (a read never puts you on them). history applies to every requested Goal. A refused read fails the call with its original refusal; no partial result is presented as complete. Each Goal includes its ten most recent other contributors (names, latest entry headlines and times), 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.";
|
|
34045
34082
|
var SearchToolSchema2 = external_exports.object({
|
|
34046
34083
|
query: external_exports.string().trim().min(1).max(500),
|
|
34047
34084
|
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
@@ -34064,9 +34101,9 @@ var AGENT_TOOLS2 = [
|
|
|
34064
34101
|
{ name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
|
|
34065
34102
|
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(ManageGoalsToolSchema2) },
|
|
34066
34103
|
{ name: "get_delivery", description: GET_DELIVERY_DESCRIPTION2, inputSchema: mcpInputSchema2(GetDeliverySchema2) },
|
|
34067
|
-
{ name: "
|
|
34104
|
+
{ name: "get_goals", description: GET_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(GetGoalsSchema2) },
|
|
34068
34105
|
{ name: "search", description: SEARCH_DESCRIPTION2, inputSchema: mcpInputSchema2(SearchToolSchema2) },
|
|
34069
|
-
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use
|
|
34106
|
+
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goals to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema2(CheckActivitySchema2) },
|
|
34070
34107
|
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION2, inputSchema: mcpInputSchema2(SendFeedbackSchema2) }
|
|
34071
34108
|
];
|
|
34072
34109
|
var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
|
|
@@ -35590,6 +35627,8 @@ var CallRecapSchema2 = external_exports.object({
|
|
|
35590
35627
|
status: external_exports.string(),
|
|
35591
35628
|
startedAt: external_exports.string(),
|
|
35592
35629
|
durationMs: external_exports.number().nullable(),
|
|
35630
|
+
/** Bot-clock pickup offset; absent before the timestamp release, null before its report lands. */
|
|
35631
|
+
pickupMs: external_exports.number().nullable().optional(),
|
|
35593
35632
|
agents: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string().nullable() }))
|
|
35594
35633
|
}),
|
|
35595
35634
|
topics: external_exports.array(external_exports.object({
|
|
@@ -35819,9 +35858,9 @@ function railFor(opts) {
|
|
|
35819
35858
|
next: async () => {
|
|
35820
35859
|
const waiting = await receive(opts);
|
|
35821
35860
|
const goalId = waiting.claimable?.goalId ?? waiting.review?.[0]?.goalId;
|
|
35822
|
-
return goalId ?
|
|
35861
|
+
return goalId ? getGoals([goalId], opts).then(([goal]) => goal) : { state: "idle", message: "" };
|
|
35823
35862
|
},
|
|
35824
|
-
read: (goalId) =>
|
|
35863
|
+
read: (goalId) => getGoals([goalId], opts).then(([goal]) => goal),
|
|
35825
35864
|
complete: async (goalId, revision) => {
|
|
35826
35865
|
const done = await manageGoals({ changes: [{ kind: "state", goalId, state: "completed", ...revision !== void 0 ? { revision } : {} }] }, opts);
|
|
35827
35866
|
const result = done.results[0];
|
|
@@ -36247,7 +36286,7 @@ async function look(session, state, rail, opts) {
|
|
|
36247
36286
|
const outcome2 = brief2.outcome?.trim() ?? "";
|
|
36248
36287
|
const said = (pendingWords ?? (brief2.entries ?? []).map((e) => entryWords(e).trim())).filter((w) => w && w.toLowerCase() !== outcome2.toLowerCase());
|
|
36249
36288
|
const left = brief2.earlier ? brief2.earlier.omitted + brief2.earlier.shortened : 0;
|
|
36250
|
-
const earlier = left ? `(${left} earlier entries on this Goal are left out or shortened;
|
|
36289
|
+
const earlier = left ? `(${left} earlier entries on this Goal are left out or shortened; get_goals with history: true reads them in full.)` : "";
|
|
36251
36290
|
const fullText = [outcome2, earlier, ...said].filter(Boolean).join("\n\n");
|
|
36252
36291
|
send2(session, state, [HARNESS_INSTRUCTION, named(brief2.goalId, void 0, brief2), fullText].filter(Boolean).join("\n\n"));
|
|
36253
36292
|
if (ended(brief2.state)) await acknowledge2(brief2.goalId, brief2, [], state, rail, opts?.log);
|
package/dist/main.js
CHANGED
|
@@ -9987,45 +9987,6 @@ var OptionInputSchema = external_exports.object({
|
|
|
9987
9987
|
imgUrl: OptionSchema.shape.image
|
|
9988
9988
|
}).strict();
|
|
9989
9989
|
var NIGHT = { from: 23, to: 7 };
|
|
9990
|
-
var ASKING_RULES = `HOW TO ASK:
|
|
9991
|
-
1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
9992
|
-
2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
|
|
9993
|
-
3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
|
|
9994
|
-
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`get_goal\` on that wake.
|
|
9995
|
-
5. One question, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open. Take back one that no longer matters with \`withdrawQuestionIds\`.
|
|
9996
|
-
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
9997
|
-
7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
|
|
9998
|
-
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
|
|
9999
|
-
9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
|
|
10000
|
-
function draft2020(node) {
|
|
10001
|
-
if (Array.isArray(node)) return node.map(draft2020);
|
|
10002
|
-
if (node && typeof node === "object") {
|
|
10003
|
-
const o = node;
|
|
10004
|
-
if (Array.isArray(o.items)) {
|
|
10005
|
-
o.prefixItems = o.items;
|
|
10006
|
-
if ("additionalItems" in o) {
|
|
10007
|
-
o.items = o.additionalItems;
|
|
10008
|
-
delete o.additionalItems;
|
|
10009
|
-
} else delete o.items;
|
|
10010
|
-
}
|
|
10011
|
-
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
10012
|
-
if (typeof o[excl] === "boolean") {
|
|
10013
|
-
if (o[excl] === true && typeof o[lim] === "number") {
|
|
10014
|
-
o[excl] = o[lim];
|
|
10015
|
-
delete o[lim];
|
|
10016
|
-
} else delete o[excl];
|
|
10017
|
-
}
|
|
10018
|
-
}
|
|
10019
|
-
for (const k of Object.keys(o)) o[k] = draft2020(o[k]);
|
|
10020
|
-
return o;
|
|
10021
|
-
}
|
|
10022
|
-
return node;
|
|
10023
|
-
}
|
|
10024
|
-
function mcpInputSchema(s) {
|
|
10025
|
-
const schema = zodToJsonSchema(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
10026
|
-
delete schema.$schema;
|
|
10027
|
-
return draft2020(schema);
|
|
10028
|
-
}
|
|
10029
9990
|
var ASK_MAX = 250;
|
|
10030
9991
|
var UNITS_MAX = 12;
|
|
10031
9992
|
var UNIT_TITLE_MAX = 50;
|
|
@@ -10075,6 +10036,60 @@ function capRefusals(text, units22, field) {
|
|
|
10075
10036
|
function refuseOverCaps(text, units22, field, ctx) {
|
|
10076
10037
|
for (const { path, message, ...params } of capRefusals(text, units22, field)) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message, params });
|
|
10077
10038
|
}
|
|
10039
|
+
var COMPLETION_MESSAGE_MAX = 50;
|
|
10040
|
+
var CompletionSchema = external_exports.object({
|
|
10041
|
+
goalId: external_exports.string().uuid().describe("The existing Goal to complete."),
|
|
10042
|
+
message: external_exports.string().trim().min(1).max(COMPLETION_MESSAGE_MAX, "completion_message_too_long: at most 50 characters; put detail in units.").describe("Completion headline, at most 50 characters."),
|
|
10043
|
+
units: external_exports.array(UnitInputSchema.extend({
|
|
10044
|
+
title: external_exports.string().trim().min(1).max(UNIT_TITLE_MAX),
|
|
10045
|
+
body: external_exports.string().trim().min(1).max(UNIT_BODY_MAX)
|
|
10046
|
+
})).max(UNITS_MAX).optional().describe("Suggest initial state, changes, current state with verification and limits, and next steps / leftover work with its owner when useful. One idea per unit; omit unnecessary sections."),
|
|
10047
|
+
reply: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX).describe("One acknowledgement in the person's voice, at most 50 characters. Acknowledgement alone requests no follow-up and does not claim they tested the work."),
|
|
10048
|
+
options: external_exports.array(external_exports.object({
|
|
10049
|
+
label: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX),
|
|
10050
|
+
hint: external_exports.string().trim().min(1).max(OPTION_HINT_MAX)
|
|
10051
|
+
}).strict()).max(5).optional().describe("Optional next steps the person may initiate: label (50 characters) and consequence in hint (200). Selecting one acknowledges the report and requests that step from its author; it never reopens this Goal.")
|
|
10052
|
+
}).strict();
|
|
10053
|
+
var CompleteChangeSchema = CompletionSchema.extend({ kind: external_exports.literal("complete") });
|
|
10054
|
+
var ASKING_RULES = `HOW TO ASK:
|
|
10055
|
+
1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
10056
|
+
2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
|
|
10057
|
+
3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
|
|
10058
|
+
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`get_goals\` on that wake.
|
|
10059
|
+
5. One question, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open. Take back one that no longer matters with \`withdrawQuestionIds\`.
|
|
10060
|
+
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
10061
|
+
7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
|
|
10062
|
+
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
|
|
10063
|
+
9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
|
|
10064
|
+
function draft2020(node) {
|
|
10065
|
+
if (Array.isArray(node)) return node.map(draft2020);
|
|
10066
|
+
if (node && typeof node === "object") {
|
|
10067
|
+
const o = node;
|
|
10068
|
+
if (Array.isArray(o.items)) {
|
|
10069
|
+
o.prefixItems = o.items;
|
|
10070
|
+
if ("additionalItems" in o) {
|
|
10071
|
+
o.items = o.additionalItems;
|
|
10072
|
+
delete o.additionalItems;
|
|
10073
|
+
} else delete o.items;
|
|
10074
|
+
}
|
|
10075
|
+
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
10076
|
+
if (typeof o[excl] === "boolean") {
|
|
10077
|
+
if (o[excl] === true && typeof o[lim] === "number") {
|
|
10078
|
+
o[excl] = o[lim];
|
|
10079
|
+
delete o[lim];
|
|
10080
|
+
} else delete o[excl];
|
|
10081
|
+
}
|
|
10082
|
+
}
|
|
10083
|
+
for (const k of Object.keys(o)) o[k] = draft2020(o[k]);
|
|
10084
|
+
return o;
|
|
10085
|
+
}
|
|
10086
|
+
return node;
|
|
10087
|
+
}
|
|
10088
|
+
function mcpInputSchema(s) {
|
|
10089
|
+
const schema = zodToJsonSchema(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
10090
|
+
delete schema.$schema;
|
|
10091
|
+
return draft2020(schema);
|
|
10092
|
+
}
|
|
10078
10093
|
var questionHandle = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
10079
10094
|
var NodeRef = external_exports.object({
|
|
10080
10095
|
type: external_exports.enum(["goal", "question"]),
|
|
@@ -10185,6 +10200,7 @@ var QuestionDependencySchema = external_exports.object({
|
|
|
10185
10200
|
reason: reason.optional()
|
|
10186
10201
|
}).strict().refine(actionFits, ACTION_FITS);
|
|
10187
10202
|
var sendFields = {
|
|
10203
|
+
completions: external_exports.array(CompletionSchema).min(1).max(20).optional().describe("Close existing Goals and deliver their completion reports atomically. Ordinary updates never close work."),
|
|
10188
10204
|
updates: external_exports.array(UpdateInputSchema).min(1).max(20).optional().describe(
|
|
10189
10205
|
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress and nobody is notified."
|
|
10190
10206
|
),
|
|
@@ -10207,20 +10223,22 @@ var ContactSchema = external_exports.object({
|
|
|
10207
10223
|
"Only controls when this returns. Sending: false (the default) returns at once; true waits up to about 45 seconds for a response to what you sent. Sending nothing: true (the default) waits up to about 45 seconds for anything addressed to you; false returns what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived; wait again without sending again), or `not_waited`."
|
|
10208
10224
|
)
|
|
10209
10225
|
}).strict();
|
|
10210
|
-
var sendsAnything = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
10226
|
+
var sendsAnything = (c) => !!(c.completions?.length || c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
10211
10227
|
var ContactWireSchema = external_exports.object({
|
|
10212
10228
|
operationId: external_exports.string().uuid(),
|
|
10213
10229
|
...sendFields,
|
|
10214
10230
|
questions: external_exports.array(QuestionWireSchema).min(1).max(20).optional()
|
|
10215
10231
|
}).strict().refine(sendsAnything, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
10216
10232
|
var CONTACT_SCHEMA = { type: "object", ...mcpInputSchema(ContactSchema) };
|
|
10217
|
-
var CONTACT_DESCRIPTION = "Send to and receive from the person: updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES + `
|
|
10233
|
+
var CONTACT_DESCRIPTION = "Send to and receive from the person: completions, updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES + `
|
|
10218
10234
|
|
|
10219
10235
|
CUT A LONG MESSAGE BEFORE YOU SEND IT: a question, an update's message or an answer is the one point, in at most ${ASK_MAX} characters; everything else it needs goes in 'units', up to ${UNITS_MAX} {title, body} in reading order, one idea each, every title at most ${UNIT_TITLE_MAX} characters and every body at most ${UNIT_BODY_MAX}. The person sees the main text and the titles, and opens a unit to read its body. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.
|
|
10220
10236
|
|
|
10221
|
-
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified.
|
|
10237
|
+
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified. Ordinary updates never close a Goal. On a Goal whose report card is still open, an update that reaches them is added to that card, with no new push. If the person is already on a call, anything that reaches them joins that call, with no ring.
|
|
10238
|
+
|
|
10239
|
+
COMPLETIONS close and report in one operation: completions:[{goalId,message,units?,reply,options?}]. The same contract works in manage_goals changes with kind:complete. message is at most 50 characters; use units when useful for initial state, changes, current state (verification and limits), and next steps / leftover work with its owner. reply is one acknowledgement in the person's voice. Optional options:[{label,hint}] suggest next steps: a tap acknowledges the report and requests that step from its author. It never reopens the completed Goal; follow-up work needs a new Goal. Closure and the report commit together or neither does. Required children and dependencies must already be finished. No Reviewer rejudges your completion; say only what your evidence supports.
|
|
10222
10240
|
|
|
10223
|
-
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with
|
|
10241
|
+
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with get_goals); \`instruction\`, a request or note sent to you. \`hasMore\` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (\`assigned\`; your first write to it starts it) and your work gone quiet (\`stalled\`).`;
|
|
10224
10242
|
var CreateGoalSchema = external_exports.object({
|
|
10225
10243
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
10226
10244
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -10293,6 +10311,7 @@ var DependencyChange = external_exports.object({
|
|
|
10293
10311
|
var read = { revision: external_exports.number().int().positive().optional() };
|
|
10294
10312
|
var GoalChangeSchema = external_exports.discriminatedUnion("kind", [
|
|
10295
10313
|
CreateChange,
|
|
10314
|
+
CompleteChangeSchema.extend(read),
|
|
10296
10315
|
EditChange.extend(read),
|
|
10297
10316
|
StateChange.extend(read),
|
|
10298
10317
|
AssignChange.extend(read),
|
|
@@ -10310,24 +10329,20 @@ var ManageGoalsSchema = external_exports.object({
|
|
|
10310
10329
|
changes: external_exports.array(GoalChangeSchema).min(1).max(50)
|
|
10311
10330
|
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
10312
10331
|
var ManageGoalsToolSchema = external_exports.object({
|
|
10313
|
-
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.")
|
|
10332
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange, CompleteChangeSchema, EditChange, StateChange, AssignChange, DeferChange, MoveChange, DependencyChange])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
10314
10333
|
}).strict().superRefine((v, ctx) => editNames(v.changes, ctx));
|
|
10315
|
-
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_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (
|
|
10316
|
-
var
|
|
10317
|
-
|
|
10334
|
+
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_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: complete (goalId, message capped at 50 characters, units, reply, optional next-step options {label, hint}) closes and reports atomically, exactly as contact.completions; create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goals) and reconsider. You may change any Goal of your person; a change puts you on it. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
10335
|
+
var GetGoalsSchema = external_exports.object({
|
|
10336
|
+
goalIds: external_exports.array(external_exports.string().uuid()).min(1).max(10).describe("The Goals to read, in order; one to ten IDs."),
|
|
10318
10337
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
10319
10338
|
* newest entry, and counts what it left out (`apps/api/src/goal/collapse.ts`). */
|
|
10320
|
-
history: external_exports.boolean().optional()
|
|
10321
|
-
/** WHEN A READ HAS CONFUSED YOU. Adds `diagnosis`: every reader that already answers a question
|
|
10322
|
-
* about this work, each answer attributed to the reader that gave it, and every disagreement
|
|
10323
|
-
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
10324
|
-
diagnose: external_exports.boolean().optional()
|
|
10339
|
+
history: external_exports.boolean().optional()
|
|
10325
10340
|
}).strict();
|
|
10326
10341
|
var GetDeliverySchema = external_exports.object({
|
|
10327
10342
|
deliveryId: external_exports.string().uuid().describe("The Delivery id returned by contact or receive.")
|
|
10328
10343
|
}).strict();
|
|
10329
10344
|
var GET_DELIVERY_DESCRIPTION = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
10330
|
-
var
|
|
10345
|
+
var GET_GOALS_DESCRIPTION = "Read one to ten Goals by goalIds, returned in the same order under goals (a read never puts you on them). history applies to every requested Goal. A refused read fails the call with its original refusal; no partial result is presented as complete. Each Goal includes its ten most recent other contributors (names, latest entry headlines and times), 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.";
|
|
10331
10346
|
var SearchToolSchema = external_exports.object({
|
|
10332
10347
|
query: external_exports.string().trim().min(1).max(500),
|
|
10333
10348
|
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
@@ -10350,9 +10365,9 @@ var AGENT_TOOLS = [
|
|
|
10350
10365
|
{ name: "contact", description: CONTACT_DESCRIPTION, inputSchema: CONTACT_SCHEMA },
|
|
10351
10366
|
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(ManageGoalsToolSchema) },
|
|
10352
10367
|
{ name: "get_delivery", description: GET_DELIVERY_DESCRIPTION, inputSchema: mcpInputSchema(GetDeliverySchema) },
|
|
10353
|
-
{ name: "
|
|
10368
|
+
{ name: "get_goals", description: GET_GOALS_DESCRIPTION, inputSchema: mcpInputSchema(GetGoalsSchema) },
|
|
10354
10369
|
{ name: "search", description: SEARCH_DESCRIPTION, inputSchema: mcpInputSchema(SearchToolSchema) },
|
|
10355
|
-
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use
|
|
10370
|
+
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goals to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema(CheckActivitySchema) },
|
|
10356
10371
|
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION, inputSchema: mcpInputSchema(SendFeedbackSchema) }
|
|
10357
10372
|
];
|
|
10358
10373
|
var AGENT_TOOL_NAMES = AGENT_TOOLS.map((t) => t.name);
|
|
@@ -11867,6 +11882,8 @@ var CallRecapSchema = external_exports.object({
|
|
|
11867
11882
|
status: external_exports.string(),
|
|
11868
11883
|
startedAt: external_exports.string(),
|
|
11869
11884
|
durationMs: external_exports.number().nullable(),
|
|
11885
|
+
/** Bot-clock pickup offset; absent before the timestamp release, null before its report lands. */
|
|
11886
|
+
pickupMs: external_exports.number().nullable().optional(),
|
|
11870
11887
|
agents: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string().nullable() }))
|
|
11871
11888
|
}),
|
|
11872
11889
|
topics: external_exports.array(external_exports.object({
|
|
@@ -12067,15 +12084,15 @@ async function manageGoals(input, opts = {}) {
|
|
|
12067
12084
|
if (!res.ok) await fail("manage_goals", res);
|
|
12068
12085
|
return await res.json();
|
|
12069
12086
|
}
|
|
12070
|
-
async function
|
|
12087
|
+
async function getGoals(goalIds, opts = {}, read3 = {}) {
|
|
12071
12088
|
const token = authToken(opts.token) ?? "";
|
|
12072
|
-
const
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12089
|
+
const res = await ensureAuthed(await (opts.reach ?? reach)(`${BACKEND_URL}/api/goals/read`, {
|
|
12090
|
+
method: "POST",
|
|
12091
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${token}` },
|
|
12092
|
+
body: JSON.stringify({ goalIds, ...read3 })
|
|
12076
12093
|
}));
|
|
12077
|
-
if (!res.ok) await fail("
|
|
12078
|
-
return await res.json();
|
|
12094
|
+
if (!res.ok) await fail("get_goals", res);
|
|
12095
|
+
return (await res.json()).goals;
|
|
12079
12096
|
}
|
|
12080
12097
|
var AWAIT_WINDOW_MS = 45e3;
|
|
12081
12098
|
async function whoAmI(opts = {}) {
|
|
@@ -12194,7 +12211,7 @@ async function dismissTriage(proposalId, opts = {}) {
|
|
|
12194
12211
|
if (!res.ok) throw new Error(`dismiss_triage failed: ${res.status} ${await res.text()}`);
|
|
12195
12212
|
return await res.json();
|
|
12196
12213
|
}
|
|
12197
|
-
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,
|
|
12214
|
+
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, send contact.completions or manage_goals kind:complete with the shared completion report, closing and reporting together. If the person asked you, in so many words, to send them this, send it again with userExplicitlyRequested: "any" on that update.`;
|
|
12198
12215
|
var APPLIED = "Applied; nothing was sent to the person.";
|
|
12199
12216
|
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.";
|
|
12200
12217
|
async function readDelivery(deliveryId, opts = {}) {
|
|
@@ -12219,6 +12236,7 @@ async function contact(input, opts = {}) {
|
|
|
12219
12236
|
body: JSON.stringify({
|
|
12220
12237
|
operationId: opts.operationId ?? randomUUID2(),
|
|
12221
12238
|
...parsed.updates ? { updates: parsed.updates } : {},
|
|
12239
|
+
...parsed.completions ? { completions: parsed.completions } : {},
|
|
12222
12240
|
...questions ? { questions } : {},
|
|
12223
12241
|
...parsed.answers ? { answers: parsed.answers } : {},
|
|
12224
12242
|
...parsed.withdrawQuestionIds ? { withdrawQuestionIds: parsed.withdrawQuestionIds } : {},
|
|
@@ -13861,45 +13879,6 @@ var OptionInputSchema2 = external_exports.object({
|
|
|
13861
13879
|
imgUrl: OptionSchema2.shape.image
|
|
13862
13880
|
}).strict();
|
|
13863
13881
|
var NIGHT2 = { from: 23, to: 7 };
|
|
13864
|
-
var ASKING_RULES2 = `HOW TO ASK:
|
|
13865
|
-
1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
13866
|
-
2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
|
|
13867
|
-
3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
|
|
13868
|
-
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`get_goal\` on that wake.
|
|
13869
|
-
5. One question, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open. Take back one that no longer matters with \`withdrawQuestionIds\`.
|
|
13870
|
-
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
13871
|
-
7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
|
|
13872
|
-
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
|
|
13873
|
-
9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
|
|
13874
|
-
function draft20202(node) {
|
|
13875
|
-
if (Array.isArray(node)) return node.map(draft20202);
|
|
13876
|
-
if (node && typeof node === "object") {
|
|
13877
|
-
const o = node;
|
|
13878
|
-
if (Array.isArray(o.items)) {
|
|
13879
|
-
o.prefixItems = o.items;
|
|
13880
|
-
if ("additionalItems" in o) {
|
|
13881
|
-
o.items = o.additionalItems;
|
|
13882
|
-
delete o.additionalItems;
|
|
13883
|
-
} else delete o.items;
|
|
13884
|
-
}
|
|
13885
|
-
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
13886
|
-
if (typeof o[excl] === "boolean") {
|
|
13887
|
-
if (o[excl] === true && typeof o[lim] === "number") {
|
|
13888
|
-
o[excl] = o[lim];
|
|
13889
|
-
delete o[lim];
|
|
13890
|
-
} else delete o[excl];
|
|
13891
|
-
}
|
|
13892
|
-
}
|
|
13893
|
-
for (const k of Object.keys(o)) o[k] = draft20202(o[k]);
|
|
13894
|
-
return o;
|
|
13895
|
-
}
|
|
13896
|
-
return node;
|
|
13897
|
-
}
|
|
13898
|
-
function mcpInputSchema2(s) {
|
|
13899
|
-
const schema = zodToJsonSchema2(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
13900
|
-
delete schema.$schema;
|
|
13901
|
-
return draft20202(schema);
|
|
13902
|
-
}
|
|
13903
13882
|
var ASK_MAX2 = 250;
|
|
13904
13883
|
var UNITS_MAX2 = 12;
|
|
13905
13884
|
var UNIT_TITLE_MAX2 = 50;
|
|
@@ -13949,6 +13928,60 @@ function capRefusals2(text, units22, field) {
|
|
|
13949
13928
|
function refuseOverCaps2(text, units22, field, ctx) {
|
|
13950
13929
|
for (const { path, message, ...params } of capRefusals2(text, units22, field)) ctx.addIssue({ code: external_exports.ZodIssueCode.custom, path, message, params });
|
|
13951
13930
|
}
|
|
13931
|
+
var COMPLETION_MESSAGE_MAX2 = 50;
|
|
13932
|
+
var CompletionSchema2 = external_exports.object({
|
|
13933
|
+
goalId: external_exports.string().uuid().describe("The existing Goal to complete."),
|
|
13934
|
+
message: external_exports.string().trim().min(1).max(COMPLETION_MESSAGE_MAX2, "completion_message_too_long: at most 50 characters; put detail in units.").describe("Completion headline, at most 50 characters."),
|
|
13935
|
+
units: external_exports.array(UnitInputSchema2.extend({
|
|
13936
|
+
title: external_exports.string().trim().min(1).max(UNIT_TITLE_MAX2),
|
|
13937
|
+
body: external_exports.string().trim().min(1).max(UNIT_BODY_MAX2)
|
|
13938
|
+
})).max(UNITS_MAX2).optional().describe("Suggest initial state, changes, current state with verification and limits, and next steps / leftover work with its owner when useful. One idea per unit; omit unnecessary sections."),
|
|
13939
|
+
reply: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX2).describe("One acknowledgement in the person's voice, at most 50 characters. Acknowledgement alone requests no follow-up and does not claim they tested the work."),
|
|
13940
|
+
options: external_exports.array(external_exports.object({
|
|
13941
|
+
label: external_exports.string().trim().min(1).max(OPTION_LABEL_MAX2),
|
|
13942
|
+
hint: external_exports.string().trim().min(1).max(OPTION_HINT_MAX2)
|
|
13943
|
+
}).strict()).max(5).optional().describe("Optional next steps the person may initiate: label (50 characters) and consequence in hint (200). Selecting one acknowledges the report and requests that step from its author; it never reopens this Goal.")
|
|
13944
|
+
}).strict();
|
|
13945
|
+
var CompleteChangeSchema2 = CompletionSchema2.extend({ kind: external_exports.literal("complete") });
|
|
13946
|
+
var ASKING_RULES2 = `HOW TO ASK:
|
|
13947
|
+
1. Write one question per object. Five questions are five objects in \`questions\`, in one contact, so each can be answered on its own; one question with five parts settles nothing until all five are answered.
|
|
13948
|
+
2. Name the Goal you are working on as the question's \`goalId\`: the question goes onto that Goal and its answer comes back there. It must exist: create it with manage_goals first.
|
|
13949
|
+
3. \`workItBlocks\` only for work you are truly blocked on (it asks for a call); leave it out for a question you can keep working around.
|
|
13950
|
+
4. Never hold the process open with while-loops. A wait that comes back \`expired\` is not a finished conversation: wait again with contact({wait:true}) only while you have nothing else to do. While a Call you placed is open, keep receiving window after window until it ends, even when a window is empty: the person may give follow-ups or instructions. With no open Call, STOP WAITING when a window comes back with nothing new \u2014 the question stays open, and its answer reaches you on the Goal. Otherwise, yield only with a working listener or scheduled wakeup, and collect answers with \`contact({wait:false})\` or \`get_goals\` on that wake.
|
|
13951
|
+
5. One question, one row. Never restate a question that is still waiting inside a new contact: keep waiting on the original, or the answer lands on one copy and the other stays open. Take back one that no longer matters with \`withdrawQuestionIds\`.
|
|
13952
|
+
6. Read the Goal's conversation before asking. Never ask again what was answered or already shipped \u2014 and tell its states apart: \`answered\` carries the choice in \`answer\`, while \`replied\` means they said something and chose none of your options, so that question is still yours to settle and their words are the line beside it.
|
|
13953
|
+
7. A question carries its options when you have them; a free-text question may omit them. Each option\u2019s label must stand on its own and name its choice in full -- never \`All three\` or \`Option 2\`. \`pickMode: "many"\` makes the card a checklist (options they may want several of); \`"one"\`, the default, a pick (one rules out the others); \`"rank"\` an ordering. Each question is sent exactly as written, with no reading in between. They can always answer in their own words, so never add an 'Other' option.
|
|
13954
|
+
8. A diagnosis says when, why and how it happens, then proposes one fix. Never options first.
|
|
13955
|
+
9. GIVE A REPORT ITS REPLY: an update takes \`reply\` too, one line the person can tap instead of typing, written in THEIR voice for THAT report ("Sounds good, I'll test later") \u2014 the same care you give a question's options. What they tap is what you read back, which tells you whether they verified your work or only received it. One line, because a report has one way to close, and it may not change what happens next: a reply that would is a question. Requested delivery and completed-Goal reports require a reply (reply_required); ordinary progress may omit it.`;
|
|
13956
|
+
function draft20202(node) {
|
|
13957
|
+
if (Array.isArray(node)) return node.map(draft20202);
|
|
13958
|
+
if (node && typeof node === "object") {
|
|
13959
|
+
const o = node;
|
|
13960
|
+
if (Array.isArray(o.items)) {
|
|
13961
|
+
o.prefixItems = o.items;
|
|
13962
|
+
if ("additionalItems" in o) {
|
|
13963
|
+
o.items = o.additionalItems;
|
|
13964
|
+
delete o.additionalItems;
|
|
13965
|
+
} else delete o.items;
|
|
13966
|
+
}
|
|
13967
|
+
for (const [excl, lim] of [["exclusiveMinimum", "minimum"], ["exclusiveMaximum", "maximum"]]) {
|
|
13968
|
+
if (typeof o[excl] === "boolean") {
|
|
13969
|
+
if (o[excl] === true && typeof o[lim] === "number") {
|
|
13970
|
+
o[excl] = o[lim];
|
|
13971
|
+
delete o[lim];
|
|
13972
|
+
} else delete o[excl];
|
|
13973
|
+
}
|
|
13974
|
+
}
|
|
13975
|
+
for (const k of Object.keys(o)) o[k] = draft20202(o[k]);
|
|
13976
|
+
return o;
|
|
13977
|
+
}
|
|
13978
|
+
return node;
|
|
13979
|
+
}
|
|
13980
|
+
function mcpInputSchema2(s) {
|
|
13981
|
+
const schema = zodToJsonSchema2(s, { target: "jsonSchema2019-09", $refStrategy: "none" });
|
|
13982
|
+
delete schema.$schema;
|
|
13983
|
+
return draft20202(schema);
|
|
13984
|
+
}
|
|
13952
13985
|
var questionHandle2 = external_exports.string().trim().regex(/^[0-9a-fA-F-]{8,36}$/, "a question id, whole or its first eight characters");
|
|
13953
13986
|
var NodeRef2 = external_exports.object({
|
|
13954
13987
|
type: external_exports.enum(["goal", "question"]),
|
|
@@ -14059,6 +14092,7 @@ var QuestionDependencySchema2 = external_exports.object({
|
|
|
14059
14092
|
reason: reason2.optional()
|
|
14060
14093
|
}).strict().refine(actionFits2, ACTION_FITS2);
|
|
14061
14094
|
var sendFields2 = {
|
|
14095
|
+
completions: external_exports.array(CompletionSchema2).min(1).max(20).optional().describe("Close existing Goals and deliver their completion reports atomically. Ordinary updates never close work."),
|
|
14062
14096
|
updates: external_exports.array(UpdateInputSchema2).min(1).max(20).optional().describe(
|
|
14063
14097
|
"News: progress, findings, a result. An update asks nothing. It reaches the person only when they asked for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; otherwise it is recorded as the Goal's progress and nobody is notified."
|
|
14064
14098
|
),
|
|
@@ -14081,20 +14115,22 @@ var ContactSchema2 = external_exports.object({
|
|
|
14081
14115
|
"Only controls when this returns. Sending: false (the default) returns at once; true waits up to about 45 seconds for a response to what you sent. Sending nothing: true (the default) waits up to about 45 seconds for anything addressed to you; false returns what is waiting now. It does not mean work is blocked, set urgency, or ask for a call. `waitOutcome` says which happened: `available`, `expired` (nothing arrived; wait again without sending again), or `not_waited`."
|
|
14082
14116
|
)
|
|
14083
14117
|
}).strict();
|
|
14084
|
-
var sendsAnything2 = (c) => !!(c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
14118
|
+
var sendsAnything2 = (c) => !!(c.completions?.length || c.updates?.length || c.questions?.length || c.answers?.length || c.withdrawQuestionIds?.length || c.questionDependencies?.length);
|
|
14085
14119
|
var ContactWireSchema2 = external_exports.object({
|
|
14086
14120
|
operationId: external_exports.string().uuid(),
|
|
14087
14121
|
...sendFields2,
|
|
14088
14122
|
questions: external_exports.array(QuestionWireSchema2).min(1).max(20).optional()
|
|
14089
14123
|
}).strict().refine(sendsAnything2, "a contact sends at least one update, question, answer, withdrawal or question dependency");
|
|
14090
14124
|
var CONTACT_SCHEMA2 = { type: "object", ...mcpInputSchema2(ContactSchema2) };
|
|
14091
|
-
var CONTACT_DESCRIPTION2 = "Send to and receive from the person: updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES2 + `
|
|
14125
|
+
var CONTACT_DESCRIPTION2 = "Send to and receive from the person: completions, updates, questions, answers to questions addressed to you, withdrawals of your own questions, and what a question holds up. Every Goal you name must already exist: create it with manage_goals first; an unknown Goal is refused and nothing is sent. Every item applies on its own: read `results`, where a failed item names why while the rest still apply.\n\n" + ASKING_RULES2 + `
|
|
14092
14126
|
|
|
14093
14127
|
CUT A LONG MESSAGE BEFORE YOU SEND IT: a question, an update's message or an answer is the one point, in at most ${ASK_MAX2} characters; everything else it needs goes in 'units', up to ${UNITS_MAX2} {title, body} in reading order, one idea each, every title at most ${UNIT_TITLE_MAX2} characters and every body at most ${UNIT_BODY_MAX2}. The person sees the main text and the titles, and opens a unit to read its body. Over a cap is refused by name (ask_too_long, too_many_units, unit_title_too_long, unit_body_too_long) and nothing is sent.
|
|
14094
14128
|
|
|
14095
|
-
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified.
|
|
14129
|
+
UPDATES ask nothing, so no answer is owed and none should be awaited. An update reaches the person only when they asked you for it (userExplicitlyRequested), when it answers something they said, or once its Goal is done; any other is recorded as the Goal's progress and nobody is notified. Ordinary updates never close a Goal. On a Goal whose report card is still open, an update that reaches them is added to that card, with no new push. If the person is already on a call, anything that reaches them joins that call, with no ring.
|
|
14130
|
+
|
|
14131
|
+
COMPLETIONS close and report in one operation: completions:[{goalId,message,units?,reply,options?}]. The same contract works in manage_goals changes with kind:complete. message is at most 50 characters; use units when useful for initial state, changes, current state (verification and limits), and next steps / leftover work with its owner. reply is one acknowledgement in the person's voice. Optional options:[{label,hint}] suggest next steps: a tap acknowledges the report and requests that step from its author. It never reopens the completed Goal; follow-up work needs a new Goal. Closure and the report commit together or neither does. Required children and dependencies must already be finished. No Reviewer rejudges your completion; say only what your evidence supports.
|
|
14096
14132
|
|
|
14097
|
-
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with
|
|
14133
|
+
RECEIVING: a contact that sends nothing returns \`events\`, a limited batch of what is addressed to you (not a history page): \`question\`, a Question you owe (answer it in answers, with its questionId); \`update\`, something new on one of your Goals (a reply, an answer: read it with get_goals); \`instruction\`, a request or note sent to you. \`hasMore\` says more are waiting. Reading acknowledges nothing: once you have handled events, confirm their eventIds with contact({ackEventIds}), and the next batch can come. contact({}) waits up to about 45 seconds for something to arrive; contact({wait:false}) returns at once. It also lists work given to you that nobody has started (\`assigned\`; your first write to it starts it) and your work gone quiet (\`stalled\`).`;
|
|
14098
14134
|
var CreateGoalSchema2 = external_exports.object({
|
|
14099
14135
|
outcome: external_exports.string().trim().min(1).max(1e4),
|
|
14100
14136
|
/** The work's NAME (#2115) — one to five words, how a person refers to it out loud ("the night
|
|
@@ -14167,6 +14203,7 @@ var DependencyChange2 = external_exports.object({
|
|
|
14167
14203
|
var read2 = { revision: external_exports.number().int().positive().optional() };
|
|
14168
14204
|
var GoalChangeSchema2 = external_exports.discriminatedUnion("kind", [
|
|
14169
14205
|
CreateChange2,
|
|
14206
|
+
CompleteChangeSchema2.extend(read2),
|
|
14170
14207
|
EditChange2.extend(read2),
|
|
14171
14208
|
StateChange2.extend(read2),
|
|
14172
14209
|
AssignChange2.extend(read2),
|
|
@@ -14184,24 +14221,20 @@ var ManageGoalsSchema2 = external_exports.object({
|
|
|
14184
14221
|
changes: external_exports.array(GoalChangeSchema2).min(1).max(50)
|
|
14185
14222
|
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
14186
14223
|
var ManageGoalsToolSchema2 = external_exports.object({
|
|
14187
|
-
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.")
|
|
14224
|
+
changes: external_exports.array(external_exports.discriminatedUnion("kind", [CreateChange2, CompleteChangeSchema2, EditChange2, StateChange2, AssignChange2, DeferChange2, MoveChange2, DependencyChange2])).min(1).max(50).describe("The changes, applied in order, each on its own.")
|
|
14188
14225
|
}).strict().superRefine((v, ctx) => editNames2(v.changes, ctx));
|
|
14189
|
-
var MANAGE_GOALS_DESCRIPTION2 = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (
|
|
14190
|
-
var
|
|
14191
|
-
|
|
14226
|
+
var MANAGE_GOALS_DESCRIPTION2 = "Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: complete (goalId, message capped at 50 characters, units, reply, optional next-step options {label, hint}) closes and reports atomically, exactly as contact.completions; create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goals) and reconsider. You may change any Goal of your person; a change puts you on it. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.";
|
|
14227
|
+
var GetGoalsSchema2 = external_exports.object({
|
|
14228
|
+
goalIds: external_exports.array(external_exports.string().uuid()).min(1).max(10).describe("The Goals to read, in order; one to ten IDs."),
|
|
14192
14229
|
/** Every entry in full. Without it the read carries the person's words, open questions and your
|
|
14193
14230
|
* newest entry, and counts what it left out (`apps/api/src/goal/collapse.ts`). */
|
|
14194
|
-
history: external_exports.boolean().optional()
|
|
14195
|
-
/** WHEN A READ HAS CONFUSED YOU. Adds `diagnosis`: every reader that already answers a question
|
|
14196
|
-
* about this work, each answer attributed to the reader that gave it, and every disagreement
|
|
14197
|
-
* between two of them named. Off by default; `docs/model/goal/diagnose-design.md`. */
|
|
14198
|
-
diagnose: external_exports.boolean().optional()
|
|
14231
|
+
history: external_exports.boolean().optional()
|
|
14199
14232
|
}).strict();
|
|
14200
14233
|
var GetDeliverySchema2 = external_exports.object({
|
|
14201
14234
|
deliveryId: external_exports.string().uuid().describe("The Delivery id returned by contact or receive.")
|
|
14202
14235
|
}).strict();
|
|
14203
14236
|
var GET_DELIVERY_DESCRIPTION2 = "Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.";
|
|
14204
|
-
var
|
|
14237
|
+
var GET_GOALS_DESCRIPTION2 = "Read one to ten Goals by goalIds, returned in the same order under goals (a read never puts you on them). history applies to every requested Goal. A refused read fails the call with its original refusal; no partial result is presented as complete. Each Goal includes its ten most recent other contributors (names, latest entry headlines and times), 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.";
|
|
14205
14238
|
var SearchToolSchema2 = external_exports.object({
|
|
14206
14239
|
query: external_exports.string().trim().min(1).max(500),
|
|
14207
14240
|
types: external_exports.array(external_exports.enum(["entry", "goal", "answer"])).min(1).optional(),
|
|
@@ -14224,9 +14257,9 @@ var AGENT_TOOLS2 = [
|
|
|
14224
14257
|
{ name: "contact", description: CONTACT_DESCRIPTION2, inputSchema: CONTACT_SCHEMA2 },
|
|
14225
14258
|
{ name: "manage_goals", description: MANAGE_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(ManageGoalsToolSchema2) },
|
|
14226
14259
|
{ name: "get_delivery", description: GET_DELIVERY_DESCRIPTION2, inputSchema: mcpInputSchema2(GetDeliverySchema2) },
|
|
14227
|
-
{ name: "
|
|
14260
|
+
{ name: "get_goals", description: GET_GOALS_DESCRIPTION2, inputSchema: mcpInputSchema2(GetGoalsSchema2) },
|
|
14228
14261
|
{ name: "search", description: SEARCH_DESCRIPTION2, inputSchema: mcpInputSchema2(SearchToolSchema2) },
|
|
14229
|
-
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use
|
|
14262
|
+
{ name: "check_activity", description: "Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goals to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.", inputSchema: mcpInputSchema2(CheckActivitySchema2) },
|
|
14230
14263
|
{ name: "send_feedback", description: SEND_FEEDBACK_DESCRIPTION2, inputSchema: mcpInputSchema2(SendFeedbackSchema2) }
|
|
14231
14264
|
];
|
|
14232
14265
|
var AGENT_TOOL_NAMES2 = AGENT_TOOLS2.map((t) => t.name);
|
|
@@ -15750,6 +15783,8 @@ var CallRecapSchema2 = external_exports.object({
|
|
|
15750
15783
|
status: external_exports.string(),
|
|
15751
15784
|
startedAt: external_exports.string(),
|
|
15752
15785
|
durationMs: external_exports.number().nullable(),
|
|
15786
|
+
/** Bot-clock pickup offset; absent before the timestamp release, null before its report lands. */
|
|
15787
|
+
pickupMs: external_exports.number().nullable().optional(),
|
|
15753
15788
|
agents: external_exports.array(external_exports.object({ id: external_exports.string(), name: external_exports.string().nullable() }))
|
|
15754
15789
|
}),
|
|
15755
15790
|
topics: external_exports.array(external_exports.object({
|
|
@@ -17336,9 +17371,9 @@ function railFor(opts) {
|
|
|
17336
17371
|
next: async () => {
|
|
17337
17372
|
const waiting = await receive(opts);
|
|
17338
17373
|
const goalId = waiting.claimable?.goalId ?? waiting.review?.[0]?.goalId;
|
|
17339
|
-
return goalId ?
|
|
17374
|
+
return goalId ? getGoals([goalId], opts).then(([goal]) => goal) : { state: "idle", message: "" };
|
|
17340
17375
|
},
|
|
17341
|
-
read: (goalId) =>
|
|
17376
|
+
read: (goalId) => getGoals([goalId], opts).then(([goal]) => goal),
|
|
17342
17377
|
complete: async (goalId, revision) => {
|
|
17343
17378
|
const done = await manageGoals({ changes: [{ kind: "state", goalId, state: "completed", ...revision !== void 0 ? { revision } : {} }] }, opts);
|
|
17344
17379
|
const result = done.results[0];
|
|
@@ -17764,7 +17799,7 @@ async function look(session, state, rail, opts) {
|
|
|
17764
17799
|
const outcome2 = brief2.outcome?.trim() ?? "";
|
|
17765
17800
|
const said = (pendingWords ?? (brief2.entries ?? []).map((e) => entryWords(e).trim())).filter((w) => w && w.toLowerCase() !== outcome2.toLowerCase());
|
|
17766
17801
|
const left = brief2.earlier ? brief2.earlier.omitted + brief2.earlier.shortened : 0;
|
|
17767
|
-
const earlier = left ? `(${left} earlier entries on this Goal are left out or shortened;
|
|
17802
|
+
const earlier = left ? `(${left} earlier entries on this Goal are left out or shortened; get_goals with history: true reads them in full.)` : "";
|
|
17768
17803
|
const fullText = [outcome2, earlier, ...said].filter(Boolean).join("\n\n");
|
|
17769
17804
|
send2(session, state, [HARNESS_INSTRUCTION, named(brief2.goalId, void 0, brief2), fullText].filter(Boolean).join("\n\n"));
|
|
17770
17805
|
if (ended(brief2.state)) await acknowledge2(brief2.goalId, brief2, [], state, rail, opts?.log);
|