@agentshouse/kit 0.1.0-alpha.34 → 0.1.0-alpha.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,7 +12,7 @@ The Skill set Kit installs is Matt Pocock's
12
12
  On Linux `amd64` or `arm64`, run the published, versioned bootstrap once:
13
13
 
14
14
  ```sh
15
- bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.34/connect-linux.sh)
15
+ bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.35/connect-linux.sh)
16
16
  ```
17
17
 
18
18
  The bootstrap first establishes Docker Engine from what it observes on the
@@ -889,9 +889,10 @@ the same for every adapter kind: the line
889
889
  `The agents.house house CLI is available: run house --help.`, the base
890
890
  instructions of the Execution attempt plan House acquired, and the current text
891
891
  of the owner's How-we-work document `/private/library/how-we-work.md`, which the
892
- launcher reads with the `shell` tool over the Session's own bridge, following
893
- House's cursor to the whole text. An absent document, one the Session's ceiling
894
- cannot read, and empty base instructions add nothing. Any other failed read
892
+ launcher reads with the `shell` tool over the Session's own bridge, running
893
+ the continuation each cut reply's `output_cut` line prints until a reply comes
894
+ back uncut. A document that is absent, or that the Session's ceiling cannot
895
+ read, at the first read adds nothing, and so do empty base instructions. Any other failed read
895
896
  refuses the attempt as `kit_how_we_work_unreadable` with the bridge's cause
896
897
  before a prompt is sent. A session reloaded with `session/load` already holds
897
898
  the block and gets none. It forwards only adapter-classified User-visible assistant
@@ -2188,6 +2189,17 @@ and that a pending submission House answers `operation_expired` is pulled first,
2188
2189
  then sent again under a new identifier only if it never landed. Evidence is
2189
2190
  written to `tmp/delivery-evidence/sync-pair.json`.
2190
2191
 
2192
+ The How-we-work reader has its own paired proof:
2193
+
2194
+ ```sh
2195
+ HOUSE_CORE_ROOT=<core checkout> HOUSE_AUTH_ROOT=<auth checkout> \
2196
+ KIT_PAIR_SPECS=/kit/test/pair/how-we-work.vitest.ts bash test/pair/run.sh
2197
+ ```
2198
+
2199
+ It writes a document longer than two of House's cut shell replies and proves
2200
+ the installed reader returns its whole text by running each printed
2201
+ continuation. Evidence is written to `tmp/delivery-evidence/how-we-work-pair.json`.
2202
+
2191
2203
  The retained-original consumers have their own paired proofs:
2192
2204
 
2193
2205
  ```sh
package/bootstrap.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.1.0-alpha.34",
3
+ "version": "0.1.0-alpha.35",
4
4
  "hosts": {
5
5
  "linux": {
6
- "command": "bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.34/connect-linux.sh)",
6
+ "command": "bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.35/connect-linux.sh)",
7
7
  "asset": {
8
8
  "name": "connect-linux.sh",
9
- "url": "https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.34/connect-linux.sh"
9
+ "url": "https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.35/connect-linux.sh"
10
10
  },
11
11
  "workspace": {
12
12
  "argument": "--workspace",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/kit",
3
- "version": "0.1.0-alpha.34",
3
+ "version": "0.1.0-alpha.35",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,54 +38,70 @@ export async function commandHouseInstructions(bridge) {
38
38
  return frame.result.instructions;
39
39
  }
40
40
 
41
+ const CUT_NOTICE = "shell: output_cut ";
42
+ const CONTINUATION = "; continue with: ";
43
+ const BYTE_CONTINUATION = /\| tail -c \+[1-9][0-9]*$/u;
44
+
41
45
  function shellAnswer(text) {
42
46
  const lines = text.split("\n");
43
47
  if (!lines[0].startsWith(`protocol: render=${SHELL_RENDER} `)) return null;
44
48
  const exit = Number(lines[2].slice("exit: ".length));
49
+ const truncation = lines[3].slice("truncation: ".length);
45
50
  let at = lines[5]?.startsWith("authority: ") ? 6 : 5;
46
- if (exit === 0) return { exit, stderr: [], stdout: lines.slice(at).join("\n"), cursor: null };
51
+ if (exit === 0 && truncation === "none") {
52
+ return { exit, truncation, stderr: [], stdout: lines.slice(at).join("\n"), continuation: null };
53
+ }
47
54
  const stderr = [];
48
- while (lines[at]?.startsWith("stderr: ")) stderr.push(lines[at++].slice("stderr: ".length));
49
- const stdout = lines.slice(at);
50
- const cursor = stdout.at(-1)?.startsWith("cursor: ") ? stdout.pop().slice("cursor: ".length) : null;
51
- return { exit, stderr, stdout: stdout.join("\n"), cursor };
55
+ let continuation = null;
56
+ while (continuation === null && lines[at]?.startsWith("stderr: ")) {
57
+ const line = lines[at++].slice("stderr: ".length);
58
+ stderr.push(line);
59
+ const separator = line.indexOf(CONTINUATION);
60
+ if (line.startsWith(CUT_NOTICE) && separator !== -1) {
61
+ continuation = line.slice(separator + CONTINUATION.length);
62
+ }
63
+ }
64
+ return { exit, truncation, stderr, stdout: lines.slice(at).join("\n"), continuation };
52
65
  }
53
66
 
54
- async function howWeWorkPage(bridge, cursor) {
67
+ async function howWeWorkReply(bridge, command, first) {
55
68
  const frame = await bridgeCall(bridge, {
56
69
  method: "tools/call",
57
- params: {
58
- name: "shell",
59
- arguments: { command: `cat ${HOW_WE_WORK_PATH}`, ...(cursor === null ? {} : { cursor }) },
60
- },
70
+ params: { name: "shell", arguments: { command } },
61
71
  });
62
72
  if (frame.error !== undefined) {
63
73
  throw new KitRefusal("kit_how_we_work_unreadable", frame.error.message ?? null);
64
74
  }
65
75
  const text = answerText(frame.result);
66
76
  if (frame.result?.isError === true) {
67
- if (text.split(":")[0] === "room_not_found") return null;
77
+ if (first && text.split(":")[0] === "room_not_found") return null;
68
78
  throw new KitRefusal("kit_how_we_work_unreadable", text);
69
79
  }
70
- const page = shellAnswer(text);
71
- if (page === null) throw new KitRefusal("kit_how_we_work_unreadable", text);
72
- if (page.cursor === null && page.exit !== 0) {
73
- if (page.stderr.length === 1 && page.stderr[0].split(" ")[1] === "path_not_found") return null;
74
- throw new KitRefusal("kit_how_we_work_unreadable", page.stderr.join("\n"));
80
+ const reply = shellAnswer(text);
81
+ if (reply === null) throw new KitRefusal("kit_how_we_work_unreadable", text);
82
+ if (reply.exit !== 0) {
83
+ if (first && reply.stderr.length === 1 && reply.stderr[0].split(" ")[1] === "path_not_found") return null;
84
+ throw new KitRefusal("kit_how_we_work_unreadable", reply.stderr.join("\n"));
85
+ }
86
+ if (reply.truncation !== "none" && reply.continuation === null) {
87
+ throw new KitRefusal("kit_how_we_work_unreadable", reply.stderr.join("\n"));
75
88
  }
76
- return page;
89
+ return reply;
77
90
  }
78
91
 
79
92
  export async function commandHouseHowWeWork(bridge) {
80
- const pages = [];
81
- let cursor = null;
82
- do {
83
- const page = await howWeWorkPage(bridge, cursor);
84
- if (page === null) return "";
85
- pages.push(page.stdout);
86
- cursor = page.cursor;
87
- } while (cursor !== null);
88
- return pages.join("\n");
93
+ let document = "";
94
+ let command = `cat ${HOW_WE_WORK_PATH}`;
95
+ let first = true;
96
+ while (command !== null) {
97
+ const reply = await howWeWorkReply(bridge, command, first);
98
+ if (reply === null) return "";
99
+ document += reply.stdout;
100
+ command = reply.continuation;
101
+ if (command !== null && !BYTE_CONTINUATION.test(command)) document += "\n";
102
+ first = false;
103
+ }
104
+ return document;
89
105
  }
90
106
 
91
107
  export async function commandHouseCreateHowWeWork(bridge) {