eve-hub 0.16.44 → 0.16.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve-hub",
3
- "version": "0.16.44",
3
+ "version": "0.16.45",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Bot-side code shared by every hub agent: registry tools, the roster hook, the eve channel, the host sandbox and browser, and model helpers.",
6
6
  "type": "module",
@@ -1,5 +1,5 @@
1
1
  - **A delivery** is tagged sections in a fixed order; an empty one is left out.
2
- - New session: `<thread_catchup>`, the thread's summary, latest status post and latest 20 posts.
2
+ - New session: `<thread_catchup>`, the thread's summary, latest status post and latest 20 posts. A `<timeline>` beside the summary and `<latest_status>` lists the thread's open notes, newest first, one `<entry kind="..." from="..." age="...">` line each; read it for the thread's structure and for which of problem, findings, decisions, options and outcome are still missing.
3
3
  - Later turns: `<new_posts>`, everything posted since your last turn, mentions or not.
4
4
  - `<thread_changes>`: the phase, PR, sha or summary moved.
5
5
  - `<team_status>`: who is active, with the human's handle and aliases.
@@ -18,3 +18,6 @@
18
18
  - **Phase**
19
19
  - When the thread's phase changes (planning, working, reviewing, done), add a status post: at most 8 plain words, no @-mention.
20
20
  - The brief, question or handoff is its own post, without `status`: the app draws a status post as a grey phase row, and the hub refuses one that carries more.
21
+ - **Notes**
22
+ - Coordinator writes `problem` and `goal` when the human opens a thread; `decision`, `cleared` or `question`, with `about`, when the human answers or corrects something; and a `summary` (2 to 3 plain sentences: the goal, where it stands, what is next) after each human decision and each merge report.
23
+ - Planner writes a `finding` on a brief. Reviewer writes an `adjustment` on fix-first and an `outcome` on ship. Builder writes an `outcome` on a merge and on real-path checks, and an `adjustment` when CI or a check changes the plan.
@@ -34,6 +34,22 @@ export declare const trackerRow: z.ZodObject<{
34
34
  waitsOn: z.ZodOptional<z.ZodString>;
35
35
  ref: z.ZodString;
36
36
  }, z.core.$strip>;
37
+ export declare const noteInput: z.ZodObject<{
38
+ kind: z.ZodEnum<{
39
+ adjustment: "adjustment";
40
+ cleared: "cleared";
41
+ decision: "decision";
42
+ finding: "finding";
43
+ goal: "goal";
44
+ outcome: "outcome";
45
+ problem: "problem";
46
+ question: "question";
47
+ summary: "summary";
48
+ }>;
49
+ text: z.ZodString;
50
+ key: z.ZodOptional<z.ZodBoolean>;
51
+ about: z.ZodOptional<z.ZodString>;
52
+ }, z.core.$strip>;
37
53
  /** An artifact's link: the one given (a sandbox path uploaded), else the post's first link, else its PR. */
38
54
  export declare function artifactUrl(given: string | undefined, text: string, pr: string | undefined, open: (path: string) => Promise<string>): Promise<string>;
39
55
  declare const _default: import("eve/tools").ToolDefinition<{
@@ -69,6 +85,12 @@ declare const _default: import("eve/tools").ToolDefinition<{
69
85
  waitsOn?: string | undefined;
70
86
  ref?: string | undefined;
71
87
  } | undefined;
88
+ note?: {
89
+ kind: "adjustment" | "cleared" | "decision" | "finding" | "goal" | "outcome" | "problem" | "question" | "summary";
90
+ text: string;
91
+ key?: boolean | undefined;
92
+ about?: string | undefined;
93
+ } | undefined;
72
94
  }, {
73
95
  messageId: string;
74
96
  threadId: string;
@@ -108,6 +130,12 @@ declare const _default: import("eve/tools").ToolDefinition<{
108
130
  waitsOn?: string | undefined;
109
131
  ref?: string | undefined;
110
132
  } | undefined;
133
+ note?: {
134
+ kind: "adjustment" | "cleared" | "decision" | "finding" | "goal" | "outcome" | "problem" | "question" | "summary";
135
+ text: string;
136
+ key?: boolean | undefined;
137
+ about?: string | undefined;
138
+ } | undefined;
111
139
  }, ctx: import("eve/tools").ToolContext): Promise<{
112
140
  messageId: string;
113
141
  threadId: string;
@@ -142,6 +142,13 @@ export const trackerRow = z.object({
142
142
  waitsOn: z.string().optional().describe("Who or what it is blocked on, e.g. 'rconti' or 'an eve maintainer'."),
143
143
  ref: z.string().describe("What the row opens; every row needs one: a post as thr_ID#msg_ID (a hash, never a slash), a PR or issue as owner/repo#N or its github.com URL, or an https URL."),
144
144
  });
145
+ // The hub checks the note again (packages/wire/src/state.ts); this is what the model reads.
146
+ export const noteInput = z.object({
147
+ kind: z.enum(["problem", "goal", "finding", "decision", "question", "cleared", "adjustment", "outcome", "summary"]).describe("What the note records: problem (the problem and its prior context), goal, finding (what research found), decision, question, cleared (a misconception corrected), adjustment (the plan changed, and why), outcome (how it worked out), summary (2 to 3 plain sentences: the goal, where it stands, what is next)."),
148
+ text: z.string().min(1).max(200).describe("One sentence, 1 to 200 characters, plain words, no glyph separators. It stands alone: it names the thing and never says 'it', 'this' or 'the fix' for something in an earlier entry, because the newest entry is shown above the ones that led to it."),
149
+ key: z.boolean().optional().describe("true keeps this entry open in the Artifacts pane; the others fold into 'N more steps'. Problem, goal and decision are always open. Set it when the human would lose the story if this entry were folded."),
150
+ about: z.string().optional().describe("A `thr_ID#msg_ID` ref (a hash, never a slash), for a note that records someone else's post, e.g. the human's decision; the entry then opens that post."),
151
+ });
145
152
  /** An artifact's link: the one given (a sandbox path uploaded), else the post's first link, else its PR. */
146
153
  export async function artifactUrl(given, text, pr, open) {
147
154
  if (given)
@@ -190,11 +197,15 @@ export default defineTool({
190
197
  .extend({ ref: z.string().optional().describe("What the row opens. Default: this post.") })
191
198
  .optional()
192
199
  .describe("The thread's tracker row this post marks, written with the post: e.g. on a status post handing a PR to review, {id: 'review', title: 'Review the fix', state: 'started', owner: 'reviewer'}. The hub merges it by id, so the same id on a later post moves the same row, and stamps the time and your name when its state, owner or wait changes. Optional."),
200
+ note: noteInput.optional().describe("One entry in the thread's timeline of notes, the Artifacts pane's list, newest first: {kind, text, key?, about?}. A post that has a `verdict`, `status: \"done\"`, or an artifact of kind `plan` carries a `note`."),
193
201
  }),
194
- async execute({ threadId, agent, text, images, policy, status, metadata, verdict, decisions, tested, artifact, step }, ctx) {
202
+ async execute({ threadId, agent, text, images, policy, status, metadata, verdict, decisions, tested, artifact, step, note }, ctx) {
195
203
  const bad = textError(text);
196
204
  if (bad)
197
205
  throw new Error(bad);
206
+ const noteVoice = note && voiceError(note.text);
207
+ if (noteVoice)
208
+ throw new Error(`note.text: ${noteVoice}`);
198
209
  const voice = voiceError(text);
199
210
  if (voice && !(await mentionsBot(text)))
200
211
  throw new Error(voice);
@@ -207,7 +218,7 @@ export default defineTool({
207
218
  const res = await registryFetch(`/api/threads/${encodeURIComponent(target)}/messages`, {
208
219
  method: "POST",
209
220
  headers: { "content-type": "application/json" },
210
- body: JSON.stringify({ text: posted, sessionId: ctx.session.id, ...(attachments.length ? { attachments: attachments.map(({ id, name }) => ({ id, name })) } : {}), ...(policy ? { policy } : {}), ...(status ? { status } : {}), ...(metadata ? { metadata } : {}), ...(verdict ? { verdict } : {}), ...(decisions ? { decisions } : {}), ...(tested ? { tested } : {}), ...(tagged ? { artifact: tagged } : {}), ...(step ? { step } : {}) }),
221
+ body: JSON.stringify({ text: posted, sessionId: ctx.session.id, ...(attachments.length ? { attachments: attachments.map(({ id, name }) => ({ id, name })) } : {}), ...(policy ? { policy } : {}), ...(status ? { status } : {}), ...(metadata ? { metadata } : {}), ...(verdict ? { verdict } : {}), ...(decisions ? { decisions } : {}), ...(tested ? { tested } : {}), ...(tagged ? { artifact: tagged } : {}), ...(step ? { step } : {}), ...(note ? { note } : {}) }),
211
222
  });
212
223
  if (!res.ok)
213
224
  throw new Error(`post_message failed: ${res.status} ${await res.text()}`);