eve-hub 0.6.3 → 0.6.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # eve-hub
2
2
 
3
+ ## 0.6.5
4
+
5
+ ### Patch Changes
6
+
7
+ - Bots learn forms: the protocol now teaches flow, sequence, chart and ask figures.
8
+
9
+ ## 0.6.4
10
+
11
+ ### Patch Changes
12
+
13
+ - A running tool's input in the live activity keeps every field when it's long: long string values are cut before the input is stringified, so the JSON still parses.
14
+
3
15
  ## 0.6.3
4
16
 
5
17
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  // main's instructions, rendered from the kit's templates: templates/main-instructions.md,
2
- // then the shared protocol (templates/workspace-protocol.md, then the engineering
3
- // page, templates/engineering.md). One source for
2
+ // then the shared protocol (templates/workspace-protocol.md, the forms guide,
3
+ // templates/forms.md, then the engineering page, templates/engineering.md). One source for
4
4
  // `hub workspace init` (lib/agent-template.mjs) and for every workspace's main,
5
5
  // which imports it (instructions/main.ts) instead of carrying a copy, so a
6
6
  // template edit reaches each workspace on main's next build. Every other bot
@@ -12,6 +12,7 @@ import { findWorkspaceRoot } from "./workspace.mjs";
12
12
 
13
13
  const HEAD = "main-instructions.md";
14
14
  const PROTOCOL = "workspace-protocol.md";
15
+ const FORMS = "forms.md";
15
16
  const ENGINEERING = "engineering.md";
16
17
  const templatesOf = (kitDir) => join(kitDir, "templates");
17
18
 
@@ -42,5 +43,5 @@ export function engineeringPage(options) {
42
43
  // The shared protocol: every bot but main appends it after its own
43
44
  // instructions.md (agent/instructions/protocol.ts re-exports instructions/protocol.ts).
44
45
  export function workspaceProtocol(options) {
45
- return `${readFileSync(join(templatesDir(options), PROTOCOL), "utf8")}\n${engineeringPage(options)}`;
46
+ return `${readFileSync(join(templatesDir(options), PROTOCOL), "utf8")}${readFileSync(join(templatesDir(options), FORMS), "utf8")}\n${engineeringPage(options)}`;
46
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eve-hub",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
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",
@@ -0,0 +1,48 @@
1
+
2
+ ## Forms
3
+
4
+ A form is an interactive figure the app draws from a fenced block with a JSON body. Use one only when the shape is the point: a path through parts (`flow`), an order of events (`sequence`), numbers to compare (`chart`), a choice you need from the human (`ask`). Everything else is plain prose. At most one or two forms per message.
5
+
6
+ - Claim first: a sentence that says what the form shows comes before it. A chart's `title` is its claim.
7
+ - Link a word in your prose to a part with `[word](#id)`. Ids are lowercase slugs (`a-z`, `0-9`, `-`, up to 32 characters), unique in the whole message.
8
+ - Put the explanation of a part in `note` (up to 240 characters), which the human sees when they point at or step to it. Keep labels short.
9
+ - `hi: true` marks the one part that matters, at most one per form. Unknown keys are rejected.
10
+ - Send a form with `post_message`, never in your end-of-turn reply. The hub checks a posted form and rejects a bad one (400) with what's wrong: fix it and post again. Nothing checks a final reply, so a bad form there shows as raw JSON.
11
+
12
+ A request leaves the [app](#app), the [hub](#hub) routes it, and a [bot](#bot) answers. `flow`: nodes 2–12 (`role`, `group`, `ref` as file:line), edges 1–24 (`from`, `to`, `label` up to 16, `fail` for a failure path), optional `groups`. Steps follow node order.
13
+
14
+ ```flow
15
+ {"nodes": [
16
+ {"id": "app", "label": "App", "role": "on your Mac"},
17
+ {"id": "hub", "label": "Hub", "role": "threads, routing", "hi": true, "ref": "server.mjs:5323", "note": "Stores the message, then wakes the bot."},
18
+ {"id": "bot", "label": "Bot", "role": "one turn"}],
19
+ "edges": [{"from": "app", "to": "hub", "label": "send"}, {"from": "hub", "to": "bot", "label": "wake"}, {"from": "bot", "to": "hub", "label": "post"}]}
20
+ ```
21
+
22
+ The stream [drops](#drop) before the client [retries](#retry). `sequence`: actors 2–6, messages 1–16 (`from`, `to`, `label` up to 32, `fail` where it breaks, `ref` as file:line). Steps follow message order.
23
+
24
+ ```sequence
25
+ {"actors": [{"id": "hub", "label": "Hub"}, {"id": "client", "label": "Client"}],
26
+ "messages": [
27
+ {"id": "drop", "from": "hub", "to": "client", "label": "stream drops", "fail": true, "ref": "Client.swift:257"},
28
+ {"id": "retry", "from": "client", "to": "hub", "label": "reconnects", "note": "Resumes from the last event id."}]}
29
+ ```
30
+
31
+ First token is under 2 s everywhere but [Sydney](#syd). `chart`: `title` (the claim) and `points` 1–24, each with an id and `label`. `type` is one of four:
32
+ - `bar`: `value`; optional `unit`, `target`.
33
+ - `scatter`: axis titles `x`, `y`; points have numeric `x`, `y`.
34
+ - `budget`: `value` > 0; optional `total`; `spare: true` for unused room.
35
+ - `schedule`: `row` (up to 8 rows), `start` < `end`; optional `unit`.
36
+
37
+ ```chart
38
+ {"type": "bar", "title": "First token is under 2 s everywhere but Sydney", "unit": "s", "target": 2,
39
+ "points": [{"id": "sfo", "label": "San Francisco", "value": 0.9}, {"id": "syd", "label": "Sydney", "value": 2.6, "hi": true, "note": "No region near it."}]}
40
+ ```
41
+
42
+ You need a decision, so I'm asking you to pick one. `ask`: 2–5 `options`, each with `id`, `label` (up to 40) and an optional one-line `line` (up to 160). Choosing one sends its label back as the human's reply, so write labels you can act on.
43
+
44
+ ```ask
45
+ {"options": [
46
+ {"id": "heron", "label": "Heron Lodge", "line": "Lake house 90 minutes north. Rooms for all 14, $5,400."},
47
+ {"id": "pines", "label": "The Pines", "line": "In town, walkable. Sleeps 10, so 4 need a hotel."}]}
48
+ ```
package/world.mjs CHANGED
@@ -357,7 +357,11 @@ function summarize(input2) {
357
357
  if (input2 == null) return "";
358
358
  if (typeof input2 === "string") return input2.slice(0, 160);
359
359
  const value = input2.message ?? input2.command ?? input2.query ?? input2.path ?? input2.title ?? input2.url;
360
- return String(value ?? JSON.stringify(input2)).slice(0, 2e3);
360
+ if (value != null) return String(value).slice(0, 2e3);
361
+ for (let cap = 2e3; ; cap = Math.floor(cap / 2)) {
362
+ const json2 = JSON.stringify(input2, (_, v) => typeof v === "string" && v.length > cap ? v.slice(0, cap) + "\u2026" : v);
363
+ if (json2.length <= 2e3 || cap < 16) return json2;
364
+ }
361
365
  }
362
366
  function reduceChild(member, { type, data = {}, meta: meta4 }, at = Date.parse(meta4?.at ?? "") || Date.now(), onCutOff) {
363
367
  member.card ??= emptyCard();