@agentshouse/kit 0.2.1-cb6679d048e60 → 0.2.1-cb997daca91ed

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.
Files changed (135) hide show
  1. package/README.md +42 -41
  2. package/dist/acp.js +50 -106
  3. package/dist/agents.js +180 -51
  4. package/dist/api.js +36 -3
  5. package/dist/app-git.js +48 -0
  6. package/dist/authority-main.js +2 -2
  7. package/dist/bridge.js +40 -59
  8. package/dist/building.js +46 -0
  9. package/dist/calls.js +63 -0
  10. package/dist/chatgpt.js +32 -0
  11. package/dist/clis-main.js +2 -2
  12. package/dist/clis.js +171 -76
  13. package/dist/codex-main.js +58 -0
  14. package/dist/connection.js +143 -0
  15. package/dist/conversations.js +625 -323
  16. package/dist/copies.js +205 -150
  17. package/dist/end.js +27 -0
  18. package/dist/enrol-main.js +7 -1
  19. package/dist/events.js +525 -0
  20. package/dist/files.js +140 -17
  21. package/dist/git.js +13 -11
  22. package/dist/home.js +96 -7
  23. package/dist/house-cli.js +299 -0
  24. package/dist/house-main.js +7 -159
  25. package/dist/instructions.js +8 -10
  26. package/dist/kit-cli.js +68 -0
  27. package/dist/kit-main.js +8 -19
  28. package/dist/login.js +117 -104
  29. package/dist/logout.js +14 -13
  30. package/dist/mcp.js +6 -3
  31. package/dist/parts.js +82 -0
  32. package/dist/placement.js +39 -0
  33. package/dist/refusals.js +12 -0
  34. package/dist/relay.js +41 -0
  35. package/dist/resident.js +116 -51
  36. package/dist/scope.js +206 -0
  37. package/dist/secret-input.js +4 -1
  38. package/dist/service-main.js +9 -0
  39. package/dist/service.js +55 -0
  40. package/dist/shell.js +3 -0
  41. package/dist/sign-in.js +40 -32
  42. package/dist/skills.js +49 -35
  43. package/dist/transcription.js +129 -41
  44. package/dist/translate.js +2 -8
  45. package/dist/update.js +112 -53
  46. package/dist/web-wizard.js +101 -0
  47. package/dist/wire.js +22 -0
  48. package/dist/work.js +346 -0
  49. package/package.json +20 -20
  50. package/dist/blocks.js +0 -51
  51. package/dist/bootstrap.json +0 -24
  52. package/dist/stream.js +0 -46
  53. package/how-we-work.md +0 -23
  54. package/skills/ask-matt/LICENSE +0 -21
  55. package/skills/ask-matt/PHASE-BOUNDARIES.md +0 -55
  56. package/skills/ask-matt/SKILL.md +0 -91
  57. package/skills/ask-matt/agents/openai.yaml +0 -4
  58. package/skills/code-review/LICENSE +0 -21
  59. package/skills/code-review/SKILL.md +0 -89
  60. package/skills/code-review/agents/openai.yaml +0 -3
  61. package/skills/codebase-design/DEEPENING.md +0 -37
  62. package/skills/codebase-design/DESIGN-IT-TWICE.md +0 -44
  63. package/skills/codebase-design/LICENSE +0 -21
  64. package/skills/codebase-design/SKILL.md +0 -116
  65. package/skills/codebase-design/agents/openai.yaml +0 -3
  66. package/skills/diagnosing-bugs/LICENSE +0 -21
  67. package/skills/diagnosing-bugs/SKILL.md +0 -140
  68. package/skills/diagnosing-bugs/agents/openai.yaml +0 -3
  69. package/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -44
  70. package/skills/domain-modeling/ADR-FORMAT.md +0 -47
  71. package/skills/domain-modeling/CONTEXT-FORMAT.md +0 -60
  72. package/skills/domain-modeling/LICENSE +0 -21
  73. package/skills/domain-modeling/SKILL.md +0 -76
  74. package/skills/domain-modeling/agents/openai.yaml +0 -3
  75. package/skills/grill-me/LICENSE +0 -21
  76. package/skills/grill-me/SKILL.md +0 -8
  77. package/skills/grill-me/agents/openai.yaml +0 -4
  78. package/skills/grill-with-docs/LICENSE +0 -21
  79. package/skills/grill-with-docs/SKILL.md +0 -8
  80. package/skills/grill-with-docs/agents/openai.yaml +0 -4
  81. package/skills/grilling/LICENSE +0 -21
  82. package/skills/grilling/SKILL.md +0 -30
  83. package/skills/grilling/agents/openai.yaml +0 -3
  84. package/skills/handoff/LICENSE +0 -21
  85. package/skills/handoff/SKILL.md +0 -17
  86. package/skills/handoff/agents/openai.yaml +0 -4
  87. package/skills/implement/LICENSE +0 -21
  88. package/skills/implement/SKILL.md +0 -16
  89. package/skills/implement/agents/openai.yaml +0 -4
  90. package/skills/improve-codebase-architecture/HTML-REPORT.md +0 -123
  91. package/skills/improve-codebase-architecture/LICENSE +0 -21
  92. package/skills/improve-codebase-architecture/SKILL.md +0 -72
  93. package/skills/improve-codebase-architecture/agents/openai.yaml +0 -4
  94. package/skills/prototype/LICENSE +0 -21
  95. package/skills/prototype/LOGIC.md +0 -67
  96. package/skills/prototype/SKILL.md +0 -28
  97. package/skills/prototype/UI.md +0 -112
  98. package/skills/prototype/agents/openai.yaml +0 -3
  99. package/skills/research/LICENSE +0 -21
  100. package/skills/research/SKILL.md +0 -14
  101. package/skills/research/agents/openai.yaml +0 -3
  102. package/skills/resolving-merge-conflicts/LICENSE +0 -21
  103. package/skills/resolving-merge-conflicts/SKILL.md +0 -16
  104. package/skills/resolving-merge-conflicts/agents/openai.yaml +0 -3
  105. package/skills/tdd/LICENSE +0 -21
  106. package/skills/tdd/SKILL.md +0 -40
  107. package/skills/tdd/agents/openai.yaml +0 -3
  108. package/skills/tdd/mocking.md +0 -59
  109. package/skills/tdd/tests.md +0 -77
  110. package/skills/teach/GLOSSARY-FORMAT.md +0 -35
  111. package/skills/teach/LEARNING-RECORD-FORMAT.md +0 -46
  112. package/skills/teach/LICENSE +0 -21
  113. package/skills/teach/MISSION-FORMAT.md +0 -31
  114. package/skills/teach/RESOURCES-FORMAT.md +0 -32
  115. package/skills/teach/SKILL.md +0 -141
  116. package/skills/teach/agents/openai.yaml +0 -4
  117. package/skills/to-questionnaire/LICENSE +0 -21
  118. package/skills/to-questionnaire/SKILL.md +0 -55
  119. package/skills/to-questionnaire/agents/openai.yaml +0 -4
  120. package/skills/to-spec/LICENSE +0 -21
  121. package/skills/to-spec/SKILL.md +0 -76
  122. package/skills/to-spec/agents/openai.yaml +0 -4
  123. package/skills/to-tickets/LICENSE +0 -21
  124. package/skills/to-tickets/SKILL.md +0 -106
  125. package/skills/to-tickets/agents/openai.yaml +0 -4
  126. package/skills/wait-what/LICENSE +0 -21
  127. package/skills/wait-what/SKILL.md +0 -8
  128. package/skills/wait-what/agents/openai.yaml +0 -4
  129. package/skills/wayfinder/LICENSE +0 -21
  130. package/skills/wayfinder/SKILL.md +0 -129
  131. package/skills/wayfinder/agents/openai.yaml +0 -4
  132. package/skills/writing-for-agents/LICENSE +0 -21
  133. package/skills/writing-for-agents/SKILL-MECHANICS.md +0 -22
  134. package/skills/writing-for-agents/SKILL.md +0 -83
  135. package/skills/writing-for-agents/agents/openai.yaml +0 -3
@@ -0,0 +1,101 @@
1
+ import { loginPath, onLoginPath } from './clis.js';
2
+ import { childEnvironment } from './relay.js';
3
+ import { killTree } from './scope.js';
4
+ const TERMINAL = 'xterm-256color';
5
+ const SIGNALLED = 128;
6
+ const NO_BASH = "bash is not on the login shell's PATH";
7
+ const LOST = { refused: 'the Kit lost its connection to House' };
8
+ function causeOf(error) {
9
+ return error instanceof Error ? error.message : String(error);
10
+ }
11
+ function failed(cause) {
12
+ process.stderr.write(`kit: a Web Wizard could not start: ${cause}\n`);
13
+ return { refused: `the script could not start: ${cause}` };
14
+ }
15
+ export class WebWizards {
16
+ calls;
17
+ send;
18
+ runs = new Map();
19
+ constructor(calls, send) {
20
+ this.calls = calls;
21
+ this.send = send;
22
+ }
23
+ start(call) {
24
+ void this.calls.carry(call.input_id, () => this.run(call));
25
+ }
26
+ notified(notification) {
27
+ const run = this.runs.get(String(notification.wizard));
28
+ if (run === undefined)
29
+ return;
30
+ if (notification.type === 'wizard_input')
31
+ this.typed(run, String(notification.data));
32
+ if (notification.type === 'wizard_size')
33
+ this.resized(run, { cols: Number(notification.cols), rows: Number(notification.rows) });
34
+ if (notification.type === 'wizard_end')
35
+ this.end(run, {});
36
+ }
37
+ disconnected() {
38
+ for (const run of this.runs.values())
39
+ this.end(run, LOST);
40
+ }
41
+ async run(call) {
42
+ const run = { terminal: null, size: null, typed: [], ended: null, sized: Promise.withResolvers() };
43
+ this.runs.set(call.input_id, run);
44
+ try {
45
+ return { result: await this.ran(call.input_id, call.script, run) };
46
+ }
47
+ finally {
48
+ this.runs.delete(call.input_id);
49
+ }
50
+ }
51
+ async ran(wizard, script, run) {
52
+ let terminal;
53
+ try {
54
+ const { spawn } = await import('@lydell/node-pty');
55
+ const shell = await onLoginPath('bash');
56
+ if (shell === null)
57
+ return failed(NO_BASH);
58
+ const path = await loginPath();
59
+ await run.sized.promise;
60
+ if (run.ended !== null)
61
+ return run.ended;
62
+ terminal = spawn(shell, ['-c', script], {
63
+ name: TERMINAL,
64
+ ...run.size,
65
+ cwd: process.cwd(),
66
+ env: { ...childEnvironment(), PATH: path },
67
+ });
68
+ }
69
+ catch (error) {
70
+ return failed(causeOf(error));
71
+ }
72
+ run.terminal = terminal;
73
+ terminal.onData((data) => this.send({ type: 'wizard_output', wizard, data }));
74
+ for (const data of run.typed.splice(0))
75
+ terminal.write(data);
76
+ const exited = await new Promise((resolve) => terminal.onExit(resolve));
77
+ return run.ended ?? { exit_code: exited.signal ? SIGNALLED + exited.signal : exited.exitCode };
78
+ }
79
+ typed(run, data) {
80
+ if (run.terminal === null)
81
+ run.typed.push(data);
82
+ else
83
+ run.terminal.write(data);
84
+ }
85
+ resized(run, size) {
86
+ run.size = size;
87
+ run.sized.resolve();
88
+ try {
89
+ run.terminal?.resize(size.cols, size.rows);
90
+ }
91
+ catch { }
92
+ }
93
+ end(run, result) {
94
+ if (run.ended !== null)
95
+ return;
96
+ run.ended = result;
97
+ run.sized.resolve();
98
+ if (run.terminal !== null)
99
+ killTree(run.terminal);
100
+ }
101
+ }
package/dist/wire.js ADDED
@@ -0,0 +1,22 @@
1
+ import { newerThanHouse, updateRequired } from './end.js';
2
+ import { machine } from './placement.js';
3
+ import { refusalOf } from './refusals.js';
4
+ export const KIT_WIRE = 3;
5
+ export const KIT_WIRE_HEADER = 'x-house-kit-wire';
6
+ function newer(text) {
7
+ let body;
8
+ try {
9
+ body = JSON.parse(text);
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ return body?.error?.code === 'kit_newer_than_house' ? body.error : null;
15
+ }
16
+ export function endUnserved(text) {
17
+ if (refusalOf(text)?.code === 'kit_update_required')
18
+ updateRequired();
19
+ const refused = newer(text);
20
+ if (refused !== null)
21
+ newerThanHouse(refused.release, refused.commands[machine()]);
22
+ }
package/dist/work.js ADDED
@@ -0,0 +1,346 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { once } from 'node:events';
3
+ import { readFileSync } from 'node:fs';
4
+ import { rm } from 'node:fs/promises';
5
+ import { createServer } from 'node:net';
6
+ import { join } from 'node:path';
7
+ import { RUNNING_JOB } from './events.js';
8
+ import { kitHome, socketDirectory } from './home.js';
9
+ const ENDED_TASK = new Set(['completed', 'failed', 'killed']);
10
+ const SCHEDULING = new Set(['CronCreate', 'CronDelete', 'ScheduleWakeup']);
11
+ const QUEUE_LIST = 'house-kit-queue-';
12
+ const SYNC = 'house-kit-sync-';
13
+ const WAKEUP = /Next wakeup scheduled for (\d\d):(\d\d):(\d\d) \(in (\d+)s\)/;
14
+ const HALF_DAY = 12 * 60 * 60 * 1000;
15
+ export function codexLauncher() {
16
+ return join(kitHome(), 'launchers', 'codex');
17
+ }
18
+ export class Work {
19
+ changed;
20
+ jobs = new Set();
21
+ constructor(changed) {
22
+ this.changed = changed;
23
+ }
24
+ async open(_cli) {
25
+ return {};
26
+ }
27
+ async settled() { }
28
+ read(message) {
29
+ this.take(message);
30
+ this.changed();
31
+ }
32
+ take(message) {
33
+ const update = message.params?.update;
34
+ if (message.method !== 'session/update' || update?.asyncTaskId === undefined)
35
+ return;
36
+ if (update.sessionUpdate === 'async_task_spawned')
37
+ this.jobs.add(update.asyncTaskId);
38
+ if (update.sessionUpdate === 'async_task_state_update' && !RUNNING_JOB.has(update.state))
39
+ this.jobs.delete(update.asyncTaskId);
40
+ }
41
+ busy() {
42
+ return this.jobs.size > 0;
43
+ }
44
+ close() { }
45
+ }
46
+ class ClaudeWork extends Work {
47
+ cwd;
48
+ level = new Set();
49
+ listed = new Set();
50
+ started = new Set();
51
+ running = false;
52
+ hooks = new Set();
53
+ calls = new Map();
54
+ crons = new Map();
55
+ wakeups = [];
56
+ goal = false;
57
+ constructor(cwd, changed) {
58
+ super(changed);
59
+ this.cwd = cwd;
60
+ }
61
+ take(message) {
62
+ super.take(message);
63
+ if (message.method === '_claude/sdkMessage')
64
+ this.sdk(message.params.message);
65
+ if (message.method === 'session/update')
66
+ this.update(message.params.update);
67
+ }
68
+ busy() {
69
+ return (super.busy() ||
70
+ this.level.size > 0 ||
71
+ this.started.size > 0 ||
72
+ this.running ||
73
+ this.hooks.size > 0 ||
74
+ this.crons.size > 0 ||
75
+ this.wakeups.length > 0 ||
76
+ this.goal ||
77
+ this.durable());
78
+ }
79
+ sdk(message) {
80
+ switch (message.subtype) {
81
+ case 'background_tasks_changed':
82
+ this.level = new Set(message.tasks.map((task) => task.task_id));
83
+ for (const id of this.level) {
84
+ this.listed.add(id);
85
+ this.started.delete(id);
86
+ }
87
+ break;
88
+ case 'task_started':
89
+ if (!this.listed.has(message.task_id))
90
+ this.started.add(message.task_id);
91
+ break;
92
+ case 'task_updated':
93
+ if (ENDED_TASK.has(message.patch.status))
94
+ this.started.delete(message.task_id);
95
+ break;
96
+ case 'task_notification':
97
+ this.started.delete(message.task_id);
98
+ break;
99
+ case 'session_state_changed':
100
+ if (message.state === 'running' && !this.running)
101
+ this.wakeups = this.wakeups.filter((due) => due > Date.now());
102
+ this.running = message.state === 'running';
103
+ break;
104
+ case 'hook_started':
105
+ this.hooks.add(message.hook_id);
106
+ break;
107
+ case 'hook_response':
108
+ this.hooks.delete(message.hook_id);
109
+ break;
110
+ }
111
+ }
112
+ update(update) {
113
+ const air = update._meta?.jetbrains?.air;
114
+ if (update.sessionUpdate === 'session_info_update' && air !== undefined && 'goal' in air) {
115
+ this.goal = air.goal?.status === 'active';
116
+ }
117
+ if (update.sessionUpdate !== 'tool_call' && update.sessionUpdate !== 'tool_call_update')
118
+ return;
119
+ const tool = update._meta?.claudeCode?.toolName;
120
+ if (update.sessionUpdate === 'tool_call' && SCHEDULING.has(tool ?? ''))
121
+ this.calls.set(update.toolCallId, { tool });
122
+ const call = this.calls.get(update.toolCallId);
123
+ if (call === undefined)
124
+ return;
125
+ if (update.rawInput !== undefined)
126
+ call.input = update.rawInput;
127
+ if (update.content !== undefined)
128
+ call.content = update.content;
129
+ if (update.status === 'failed')
130
+ this.calls.delete(update.toolCallId);
131
+ if (update.status !== 'completed')
132
+ return;
133
+ this.calls.delete(update.toolCallId);
134
+ if (call.tool === 'CronCreate')
135
+ this.crons.set(update.toolCallId, JSON.stringify(call.content ?? []));
136
+ if (call.tool === 'ScheduleWakeup')
137
+ this.wakeup(call);
138
+ if (call.tool !== 'CronDelete')
139
+ return;
140
+ for (const [id, text] of this.crons)
141
+ if (text.includes(String(call.input?.id)))
142
+ this.crons.delete(id);
143
+ }
144
+ wakeup(call) {
145
+ if (call.input?.stop === true) {
146
+ this.wakeups = [];
147
+ return;
148
+ }
149
+ const time = WAKEUP.exec(JSON.stringify(call.content ?? []));
150
+ if (time === null) {
151
+ this.wakeups.push(Infinity);
152
+ return;
153
+ }
154
+ const fires = Date.now() + Number(time[4]) * 1000;
155
+ const due = new Date(fires);
156
+ due.setHours(Number(time[1]), Number(time[2]), Number(time[3]), 0);
157
+ if (due.getTime() - fires > HALF_DAY)
158
+ due.setDate(due.getDate() - 1);
159
+ if (fires - due.getTime() > HALF_DAY)
160
+ due.setDate(due.getDate() + 1);
161
+ this.wakeups.push(due.getTime());
162
+ }
163
+ durable() {
164
+ let text;
165
+ try {
166
+ text = readFileSync(join(this.cwd, '.claude', 'scheduled_tasks.json'), 'utf8');
167
+ }
168
+ catch (error) {
169
+ return error.code !== 'ENOENT';
170
+ }
171
+ try {
172
+ return JSON.parse(text).tasks?.length !== 0;
173
+ }
174
+ catch {
175
+ return true;
176
+ }
177
+ }
178
+ }
179
+ class CodexWork extends Work {
180
+ threads = new Map();
181
+ queues = new Map();
182
+ goals = new Set();
183
+ items = new Set();
184
+ hooks = new Set();
185
+ starting = new Set();
186
+ settling = [];
187
+ memories = null;
188
+ lost = false;
189
+ server = null;
190
+ path = null;
191
+ socket = null;
192
+ asked = 0;
193
+ heard = 0;
194
+ proving = -1;
195
+ proven = -1;
196
+ async open(cli) {
197
+ this.path = join(socketDirectory(), `${randomUUID()}.sock`);
198
+ this.server = createServer((socket) => this.connected(socket));
199
+ this.server.listen(this.path);
200
+ await once(this.server, 'listening');
201
+ return { CODEX_PATH: codexLauncher(), HOUSE_KIT_CODEX: cli, HOUSE_KIT_CODEX_STREAM: this.path };
202
+ }
203
+ settled() {
204
+ return new Promise((resolve) => {
205
+ this.settling.push(resolve);
206
+ this.settle();
207
+ });
208
+ }
209
+ take(message) {
210
+ super.take(message);
211
+ this.heard++;
212
+ }
213
+ busy() {
214
+ if (super.busy() ||
215
+ this.lost ||
216
+ this.memories !== false ||
217
+ [...this.threads.values()].some(Boolean) ||
218
+ this.queues.size > 0 ||
219
+ this.goals.size > 0 ||
220
+ this.items.size > 0 ||
221
+ this.hooks.size > 0) {
222
+ return true;
223
+ }
224
+ if (this.proven === this.heard)
225
+ return false;
226
+ this.prove();
227
+ return true;
228
+ }
229
+ close() {
230
+ this.server?.close();
231
+ if (this.path !== null)
232
+ void rm(this.path, { force: true });
233
+ }
234
+ connected(socket) {
235
+ this.socket = socket;
236
+ let buffer = '';
237
+ socket.on('error', () => this.lose());
238
+ socket.on('close', () => this.lose());
239
+ socket.setEncoding('utf8').on('data', (chunk) => {
240
+ buffer += chunk;
241
+ for (let index = buffer.indexOf('\n'); index >= 0; index = buffer.indexOf('\n')) {
242
+ const message = this.parsed(buffer.slice(0, index));
243
+ buffer = buffer.slice(index + 1);
244
+ if (message !== null)
245
+ this.stream(message, socket);
246
+ }
247
+ this.settle();
248
+ this.changed();
249
+ });
250
+ }
251
+ parsed(line) {
252
+ try {
253
+ return JSON.parse(line);
254
+ }
255
+ catch {
256
+ this.lost = true;
257
+ return null;
258
+ }
259
+ }
260
+ lose() {
261
+ this.lost = true;
262
+ this.changed();
263
+ }
264
+ prove() {
265
+ if (this.proving === this.heard)
266
+ return;
267
+ this.proving = this.heard;
268
+ this.socket.write(`${JSON.stringify({ jsonrpc: '2.0', id: `${SYNC}${this.heard}`, method: 'house-kit/sync' })}\n`);
269
+ }
270
+ settle() {
271
+ if (this.starting.size === 0)
272
+ for (const resolve of this.settling.splice(0))
273
+ resolve();
274
+ }
275
+ stream(message, socket) {
276
+ const params = message.params;
277
+ switch (message.method) {
278
+ case 'thread/status/changed':
279
+ this.threads.set(params.threadId, params.status.type === 'active' && params.status.activeFlags.length === 0);
280
+ break;
281
+ case 'thread/closed':
282
+ this.threads.delete(params.threadId);
283
+ break;
284
+ case 'thread/queue/changed':
285
+ this.queues.set(params.threadId, ++this.asked);
286
+ socket.write(`${JSON.stringify({ jsonrpc: '2.0', id: `${QUEUE_LIST}${this.asked}`, method: 'thread/queue/list', params: { threadId: params.threadId } })}\n`);
287
+ break;
288
+ case 'thread/goal/updated':
289
+ if (params.goal.status === 'active')
290
+ this.goals.add(params.threadId);
291
+ else
292
+ this.goals.delete(params.threadId);
293
+ break;
294
+ case 'thread/goal/cleared':
295
+ this.goals.delete(params.threadId);
296
+ break;
297
+ case 'item/started':
298
+ this.items.add(`${params.threadId} ${params.item.id}`);
299
+ break;
300
+ case 'item/completed':
301
+ this.items.delete(`${params.threadId} ${params.item.id}`);
302
+ break;
303
+ case 'hook/started':
304
+ this.hooks.add(params.run.id);
305
+ break;
306
+ case 'hook/completed':
307
+ this.hooks.delete(params.run.id);
308
+ break;
309
+ case 'mcpServer/startupStatus/updated':
310
+ if (params.status === 'starting')
311
+ this.starting.add(`${params.threadId} ${params.name}`);
312
+ else
313
+ this.starting.delete(`${params.threadId} ${params.name}`);
314
+ break;
315
+ case undefined:
316
+ this.answered(message);
317
+ }
318
+ }
319
+ answered(message) {
320
+ if (typeof message.id === 'string' && message.id.startsWith(SYNC)) {
321
+ this.proven = Number(message.id.slice(SYNC.length));
322
+ }
323
+ else if (typeof message.id === 'string' && message.id.startsWith(QUEUE_LIST)) {
324
+ const asked = Number(message.id.slice(QUEUE_LIST.length));
325
+ for (const [thread, latest] of this.queues) {
326
+ if (latest === asked && message.result?.data?.length === 0)
327
+ this.queues.delete(thread);
328
+ }
329
+ }
330
+ else if (message.result?.config?.features !== undefined) {
331
+ this.memories = message.result.config.features.memories !== false;
332
+ }
333
+ }
334
+ }
335
+ class GrokWork extends Work {
336
+ busy() {
337
+ return true;
338
+ }
339
+ }
340
+ export function workFor(kind, cwd, changed) {
341
+ if (kind === 'claude-agent-acp')
342
+ return new ClaudeWork(cwd, changed);
343
+ if (kind === 'codex-acp')
344
+ return new CodexWork(changed);
345
+ return new GrokWork(changed);
346
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agentshouse/kit",
3
- "version": "0.2.1-cb6679d048e60",
4
- "description": "House Kit connects an Environment to agents.house.",
3
+ "version": "0.2.1-cb997daca91ed",
4
+ "description": "Kit connects an Environment to agents.house.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -12,27 +12,27 @@
12
12
  "kit": "dist/kit-main.js",
13
13
  "house": "dist/house-main.js"
14
14
  },
15
- "exports": {
16
- "./bootstrap": "./dist/bootstrap.json"
17
- },
18
15
  "files": [
19
- "dist",
20
- "how-we-work.md",
21
- "skills"
16
+ "dist"
22
17
  ],
23
18
  "scripts": {
24
- "build": "tsc -p tsconfig.build.json && node scripts/bootstrap-manifest.mjs",
19
+ "bootstrap-manifest": "node scripts/bootstrap-manifest.mjs",
20
+ "build": "tsc -p tsconfig.build.json",
25
21
  "engine": "mkdir -p tmp/engine && docker run --rm -v \"$PWD:/kit\" -w /kit alpine:3.24@sha256:294b683cb724975bec92580e1e685676bd4b50bda910ddb8c51d4cabeaec77e6 sh scripts/engine.sh tmp/engine",
22
+ "follow-skills": "node scripts/follow-skills.mjs",
23
+ "release-files": "node scripts/release-files.mjs",
26
24
  "test": "tsc -p tsconfig.json && vitest run"
27
25
  },
28
26
  "dependencies": {
29
- "@agentclientprotocol/sdk": "1.7.0",
30
- "@agentshouse/mdmodel": "0.1.0-alpha.19",
27
+ "@agentclientprotocol/sdk": "2.0.1",
28
+ "@agentshouse/mdmodel": "0.1.0-c4f4d37bc9d6a",
29
+ "@agentshouse/skills": "0.1.0-c08575ab21b57",
30
+ "@lydell/node-pty": "1.2.0-beta.15",
31
31
  "yaml": "2.9.1"
32
32
  },
33
33
  "peerDependencies": {
34
- "@agentclientprotocol/claude-agent-acp": "0.85.1",
35
- "@agentclientprotocol/codex-acp": "2.1.1"
34
+ "@agentclientprotocol/claude-agent-acp": "0.94.0",
35
+ "@agentclientprotocol/codex-acp": "2.2.2"
36
36
  },
37
37
  "peerDependenciesMeta": {
38
38
  "@agentclientprotocol/claude-agent-acp": {
@@ -43,26 +43,26 @@
43
43
  }
44
44
  },
45
45
  "devDependencies": {
46
- "@types/node": "24.13.6",
46
+ "@types/node": "24.19.2",
47
47
  "@types/ws": "8.18.2",
48
48
  "typescript": "7.0.2",
49
- "vitest": "5.0.1",
49
+ "vitest": "5.0.5",
50
50
  "ws": "8.22.0"
51
51
  },
52
- "packageManager": "npm@11.19.0",
52
+ "packageManager": "npm@11.19.1",
53
53
  "engines": {
54
- "node": "24.21.0",
55
- "npm": "11.19.0"
54
+ "node": "24.22.1",
55
+ "npm": "11.19.1"
56
56
  },
57
57
  "devEngines": {
58
58
  "runtime": {
59
59
  "name": "node",
60
- "version": "24.21.0",
60
+ "version": "24.22.1",
61
61
  "onFail": "error"
62
62
  },
63
63
  "packageManager": {
64
64
  "name": "npm",
65
- "version": "11.19.0",
65
+ "version": "11.19.1",
66
66
  "onFail": "error"
67
67
  }
68
68
  }
package/dist/blocks.js DELETED
@@ -1,51 +0,0 @@
1
- const FENCE = /^\s*(`{3,}|~{3,})\s*(\S*)/;
2
- export function blocksOf(text) {
3
- const blocks = [];
4
- let paragraph = [];
5
- let fence = null;
6
- const closeParagraph = () => {
7
- const joined = paragraph.join('\n').trim();
8
- if (joined.length > 0)
9
- blocks.push({ type: 'paragraph', text: joined });
10
- paragraph = [];
11
- };
12
- const closeFence = () => {
13
- const joined = fence.lines.join('\n');
14
- if (joined.length > 0)
15
- blocks.push({ type: 'code', language: fence.language, text: joined });
16
- fence = null;
17
- };
18
- for (const line of text.split('\n')) {
19
- if (fence !== null) {
20
- if (line.trim().startsWith(fence.marker))
21
- closeFence();
22
- else
23
- fence.lines.push(line);
24
- continue;
25
- }
26
- const opening = FENCE.exec(line);
27
- if (opening !== null) {
28
- closeParagraph();
29
- fence = { marker: opening[1], language: opening[2] || null, lines: [] };
30
- }
31
- else if (line.trim().length === 0) {
32
- closeParagraph();
33
- }
34
- else {
35
- paragraph.push(line);
36
- }
37
- }
38
- if (fence !== null)
39
- closeFence();
40
- closeParagraph();
41
- return blocks;
42
- }
43
- export function firstChange(before, after) {
44
- let index = 0;
45
- while (index < before.length &&
46
- index < after.length &&
47
- JSON.stringify(before[index]) === JSON.stringify(after[index])) {
48
- index++;
49
- }
50
- return index;
51
- }
@@ -1,24 +0,0 @@
1
- {
2
- "schemaVersion": 2,
3
- "version": "0.2.1-cb6679d048e60",
4
- "hosts": {
5
- "macos": {
6
- "asset": {
7
- "name": "connect-linux.sh",
8
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-cb6679d048e60/connect-linux.sh"
9
- }
10
- },
11
- "linux": {
12
- "asset": {
13
- "name": "connect-linux.sh",
14
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-cb6679d048e60/connect-linux.sh"
15
- }
16
- },
17
- "windows": {
18
- "asset": {
19
- "name": "connect-windows.ps1",
20
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-cb6679d048e60/connect-windows.ps1"
21
- }
22
- }
23
- }
24
- }
package/dist/stream.js DELETED
@@ -1,46 +0,0 @@
1
- import { retryDelay } from './api.js';
2
- import { readEnrolment } from './home.js';
3
- const SUBPROTOCOL = 'house.kit.stream.1';
4
- function streamUrl(house) {
5
- const url = new URL('/kit/stream', house);
6
- url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
7
- return url;
8
- }
9
- export function holdStream(handlers) {
10
- let socket = null;
11
- let failures = 0;
12
- const connect = async () => {
13
- const { house, credential } = (await readEnrolment());
14
- const opening = new WebSocket(streamUrl(house), {
15
- protocols: [SUBPROTOCOL],
16
- headers: { authorization: `Bearer ${credential}` },
17
- });
18
- let opened = false;
19
- opening.onopen = () => {
20
- opened = true;
21
- failures = 0;
22
- socket = opening;
23
- handlers.opened();
24
- };
25
- opening.onmessage = (event) => {
26
- handlers.frame(JSON.parse(String(event.data)));
27
- };
28
- opening.onerror = () => undefined;
29
- opening.onclose = (event) => {
30
- if (socket === opening)
31
- socket = null;
32
- process.stderr.write(`kit: control stream closed ${event.code} ${event.reason}\n`);
33
- const delay = opened ? 1000 + Math.random() * 2000 : retryDelay(failures++);
34
- setTimeout(() => void connect(), delay);
35
- };
36
- };
37
- void connect();
38
- return {
39
- send(frame) {
40
- if (socket === null || socket.readyState !== WebSocket.OPEN)
41
- return false;
42
- socket.send(JSON.stringify(frame));
43
- return true;
44
- },
45
- };
46
- }