@agentshouse/kit 0.2.1-c3fc787e93f0e → 0.2.1-c441d29eb63f4

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 (123) hide show
  1. package/README.md +30 -29
  2. package/dist/acp.js +36 -16
  3. package/dist/agents.js +87 -19
  4. package/dist/api.js +5 -5
  5. package/dist/app-git.js +10 -26
  6. package/dist/bootstrap.json +4 -4
  7. package/dist/bridge.js +3 -6
  8. package/dist/calls.js +63 -0
  9. package/dist/chatgpt.js +7 -1
  10. package/dist/clis.js +17 -4
  11. package/dist/connection.js +126 -0
  12. package/dist/conversations.js +399 -153
  13. package/dist/copies.js +77 -50
  14. package/dist/end.js +9 -4
  15. package/dist/events.js +6 -2
  16. package/dist/files.js +123 -37
  17. package/dist/git.js +3 -4
  18. package/dist/home.js +31 -13
  19. package/dist/house-cli.js +286 -0
  20. package/dist/house-main.js +7 -262
  21. package/dist/instructions.js +6 -10
  22. package/dist/kit-cli.js +68 -0
  23. package/dist/kit-main.js +8 -67
  24. package/dist/login.js +34 -11
  25. package/dist/logout.js +0 -2
  26. package/dist/mcp.js +4 -2
  27. package/dist/placement.js +9 -18
  28. package/dist/resident.js +88 -37
  29. package/dist/scope.js +3 -0
  30. package/dist/service.js +23 -1
  31. package/dist/sign-in.js +19 -37
  32. package/dist/skills.js +12 -34
  33. package/dist/transcription.js +53 -22
  34. package/dist/translate.js +2 -8
  35. package/dist/update.js +42 -45
  36. package/dist/web-wizard.js +100 -0
  37. package/dist/wire.js +19 -3
  38. package/dist/work.js +3 -5
  39. package/package.json +7 -6
  40. package/dist/stream.js +0 -77
  41. package/how-we-work.md +0 -23
  42. package/skills/ask-matt/LICENSE +0 -21
  43. package/skills/ask-matt/PHASE-BOUNDARIES.md +0 -55
  44. package/skills/ask-matt/SKILL.md +0 -91
  45. package/skills/ask-matt/agents/openai.yaml +0 -4
  46. package/skills/code-review/LICENSE +0 -21
  47. package/skills/code-review/SKILL.md +0 -89
  48. package/skills/code-review/agents/openai.yaml +0 -3
  49. package/skills/codebase-design/DEEPENING.md +0 -37
  50. package/skills/codebase-design/DESIGN-IT-TWICE.md +0 -44
  51. package/skills/codebase-design/LICENSE +0 -21
  52. package/skills/codebase-design/SKILL.md +0 -116
  53. package/skills/codebase-design/agents/openai.yaml +0 -3
  54. package/skills/diagnosing-bugs/LICENSE +0 -21
  55. package/skills/diagnosing-bugs/SKILL.md +0 -140
  56. package/skills/diagnosing-bugs/agents/openai.yaml +0 -3
  57. package/skills/diagnosing-bugs/scripts/hitl-loop.template.sh +0 -44
  58. package/skills/domain-modeling/ADR-FORMAT.md +0 -47
  59. package/skills/domain-modeling/CONTEXT-FORMAT.md +0 -60
  60. package/skills/domain-modeling/LICENSE +0 -21
  61. package/skills/domain-modeling/SKILL.md +0 -76
  62. package/skills/domain-modeling/agents/openai.yaml +0 -3
  63. package/skills/grill-me/LICENSE +0 -21
  64. package/skills/grill-me/SKILL.md +0 -8
  65. package/skills/grill-me/agents/openai.yaml +0 -4
  66. package/skills/grill-with-docs/LICENSE +0 -21
  67. package/skills/grill-with-docs/SKILL.md +0 -8
  68. package/skills/grill-with-docs/agents/openai.yaml +0 -4
  69. package/skills/grilling/LICENSE +0 -21
  70. package/skills/grilling/SKILL.md +0 -30
  71. package/skills/grilling/agents/openai.yaml +0 -3
  72. package/skills/handoff/LICENSE +0 -21
  73. package/skills/handoff/SKILL.md +0 -17
  74. package/skills/handoff/agents/openai.yaml +0 -4
  75. package/skills/implement/LICENSE +0 -21
  76. package/skills/implement/SKILL.md +0 -16
  77. package/skills/implement/agents/openai.yaml +0 -4
  78. package/skills/improve-codebase-architecture/HTML-REPORT.md +0 -123
  79. package/skills/improve-codebase-architecture/LICENSE +0 -21
  80. package/skills/improve-codebase-architecture/SKILL.md +0 -72
  81. package/skills/improve-codebase-architecture/agents/openai.yaml +0 -4
  82. package/skills/prototype/LICENSE +0 -21
  83. package/skills/prototype/LOGIC.md +0 -67
  84. package/skills/prototype/SKILL.md +0 -28
  85. package/skills/prototype/UI.md +0 -112
  86. package/skills/prototype/agents/openai.yaml +0 -3
  87. package/skills/research/LICENSE +0 -21
  88. package/skills/research/SKILL.md +0 -14
  89. package/skills/research/agents/openai.yaml +0 -3
  90. package/skills/resolving-merge-conflicts/LICENSE +0 -21
  91. package/skills/resolving-merge-conflicts/SKILL.md +0 -16
  92. package/skills/resolving-merge-conflicts/agents/openai.yaml +0 -3
  93. package/skills/tdd/LICENSE +0 -21
  94. package/skills/tdd/SKILL.md +0 -40
  95. package/skills/tdd/agents/openai.yaml +0 -3
  96. package/skills/tdd/mocking.md +0 -59
  97. package/skills/tdd/tests.md +0 -77
  98. package/skills/teach/GLOSSARY-FORMAT.md +0 -35
  99. package/skills/teach/LEARNING-RECORD-FORMAT.md +0 -46
  100. package/skills/teach/LICENSE +0 -21
  101. package/skills/teach/MISSION-FORMAT.md +0 -31
  102. package/skills/teach/RESOURCES-FORMAT.md +0 -32
  103. package/skills/teach/SKILL.md +0 -141
  104. package/skills/teach/agents/openai.yaml +0 -4
  105. package/skills/to-questionnaire/LICENSE +0 -21
  106. package/skills/to-questionnaire/SKILL.md +0 -55
  107. package/skills/to-questionnaire/agents/openai.yaml +0 -4
  108. package/skills/to-spec/LICENSE +0 -21
  109. package/skills/to-spec/SKILL.md +0 -76
  110. package/skills/to-spec/agents/openai.yaml +0 -4
  111. package/skills/to-tickets/LICENSE +0 -21
  112. package/skills/to-tickets/SKILL.md +0 -106
  113. package/skills/to-tickets/agents/openai.yaml +0 -4
  114. package/skills/wait-what/LICENSE +0 -21
  115. package/skills/wait-what/SKILL.md +0 -8
  116. package/skills/wait-what/agents/openai.yaml +0 -4
  117. package/skills/wayfinder/LICENSE +0 -21
  118. package/skills/wayfinder/SKILL.md +0 -129
  119. package/skills/wayfinder/agents/openai.yaml +0 -4
  120. package/skills/writing-for-agents/LICENSE +0 -21
  121. package/skills/writing-for-agents/SKILL-MECHANICS.md +0 -22
  122. package/skills/writing-for-agents/SKILL.md +0 -83
  123. package/skills/writing-for-agents/agents/openai.yaml +0 -3
package/dist/chatgpt.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { parseArgs } from 'node:util';
2
+ import { placeAppGit } from './app-git.js';
2
3
  import { kitHome, readOwnAgent, writeOwnAgent } from './home.js';
3
4
  import { accepted, DEFAULT_HOUSE } from './login.js';
4
5
  const KEY_SOURCE = 'New key for a script on Connections';
@@ -17,10 +18,15 @@ export async function chatgpt(argv) {
17
18
  }
18
19
  if (values.key === undefined)
19
20
  throw new Error(`pass --key with a key from ${KEY_SOURCE}`);
20
- const house = values.house ?? (await readOwnAgent())?.house ?? DEFAULT_HOUSE;
21
+ const before = await readOwnAgent();
22
+ const house = values.house ?? before?.house ?? DEFAULT_HOUSE;
21
23
  if (!(await accepted(house, values.key)))
22
24
  throw new Error(`${house} does not accept this key; pass one from ${KEY_SOURCE}`);
23
25
  const relay = process.env.HOUSE_KIT_RELAY || undefined;
24
26
  await writeOwnAgent({ house, ...(relay === undefined ? {} : { relay }), credential: values.key });
27
+ await placeAppGit(await readOwnAgent()).catch((error) => process.stderr.write(`kit: ${error.message}\n`));
28
+ if (before !== null && before.credential !== values.key) {
29
+ process.stdout.write('This replaced the key this Kit home held; give each session its own HOUSE_KIT_HOME to keep its own key.\n');
30
+ }
25
31
  process.stdout.write(`house now calls ${house} as you, with the key kept in ${kitHome()}.\n`);
26
32
  }
package/dist/clis.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { spawn } from 'node:child_process';
2
+ import { randomUUID } from 'node:crypto';
2
3
  import { constants, readFileSync } from 'node:fs';
3
4
  import { access, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
4
5
  import { homedir, userInfo } from 'node:os';
@@ -54,11 +55,14 @@ export async function allowHouseInCodex(path) {
54
55
  houses.push(house);
55
56
  }
56
57
  await mkdir(rules, { recursive: true });
57
- const temporary = `${file}.${process.pid}`;
58
+ const temporary = `${file}.${randomUUID()}`;
58
59
  await writeFile(temporary, houseRule(houses));
59
60
  await rename(temporary, file);
60
61
  }
61
62
  async function nothing() { }
63
+ function answered(error) {
64
+ return typeof error === 'object' && error !== null ? error : {};
65
+ }
62
66
  function bridgeInClaudeSandbox(bridge) {
63
67
  return process.platform === 'darwin' ? { allowUnixSockets: [bridge] } : { allowAllUnixSockets: true };
64
68
  }
@@ -76,6 +80,10 @@ export const CLIS = {
76
80
  args: [],
77
81
  fullAccess: 'agent-full-access',
78
82
  sessionMeta: () => ({}),
83
+ unknownSession: (error) => {
84
+ const { code, data } = answered(error);
85
+ return code === -32603 && typeof data?.details === 'string' && data.details.startsWith('no rollout found');
86
+ },
79
87
  renames: true,
80
88
  allowHouse: allowHouseInCodex,
81
89
  signedIn: { command: ['login', 'status'] },
@@ -105,6 +113,7 @@ export const CLIS = {
105
113
  emitRawSDKMessages: RAW_SUBTYPES.map((subtype) => ({ type: 'system', subtype })),
106
114
  },
107
115
  }),
116
+ unknownSession: (error) => answered(error).code === -32002,
108
117
  renames: false,
109
118
  allowHouse: nothing,
110
119
  signedIn: { command: ['auth', 'status'] },
@@ -119,6 +128,7 @@ export const CLIS = {
119
128
  args: ['--sandbox', 'off', 'agent', '--always-approve', '--no-leader', 'stdio'],
120
129
  fullAccess: null,
121
130
  sessionMeta: () => ({}),
131
+ unknownSession: (error) => answered(error).data?.code === 'FS_NOT_FOUND',
122
132
  renames: false,
123
133
  allowHouse: nothing,
124
134
  signedIn: { initializeMeta: 'defaultAuthMethodId' },
@@ -127,7 +137,7 @@ export const CLIS = {
127
137
  },
128
138
  };
129
139
  const KIT_PACKAGE = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
130
- export const KIT_VERSION = KIT_PACKAGE.version;
140
+ export const KIT_RELEASE = KIT_PACKAGE.version;
131
141
  const PROXY = /^https?_proxy$/i;
132
142
  const VERSION = /\d+\.\d+\.\d+(?:-[0-9A-Za-z.]+)?/;
133
143
  // An install still running after fifteen minutes is ended and reported as failed, so a hung download cannot hold its CLI's report.
@@ -215,10 +225,13 @@ const USER_BIN = 'case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) PATH="$PATH:$H
215
225
  function inLoginShell(script, argument = '', signal) {
216
226
  return run(loginShell(), ['-l', '-i', '-c', `exec /bin/sh -c '${USER_BIN}; ${script}' sh ${argument}`], READ_MS, true, signal);
217
227
  }
218
- export async function locate(kind, signal) {
219
- const ran = await inLoginShell(LOOKUP, CLIS[kind].bin, signal);
228
+ export async function onLoginPath(program, signal) {
229
+ const ran = await inLoginShell(LOOKUP, program, signal);
220
230
  return ran.stdout.split('\n').findLast((line) => line.startsWith(FOUND))?.slice(FOUND.length) ?? null;
221
231
  }
232
+ export function locate(kind, signal) {
233
+ return onLoginPath(CLIS[kind].bin, signal);
234
+ }
222
235
  export async function loginPath() {
223
236
  const marker = 'house-kit-path ';
224
237
  const ran = await inLoginShell(`printf "${marker}%s\\n" "$PATH"`);
@@ -0,0 +1,126 @@
1
+ import { subscribe } from 'node:diagnostics_channel';
2
+ import { HouseRefusal, retryDelay } from './api.js';
3
+ import { end, REPLACED, signInAgain } from './end.js';
4
+ import { readEnrolment } from './home.js';
5
+ import { relayed } from './relay.js';
6
+ import { endUnserved, KIT_WIRE } from './wire.js';
7
+ const PATH = '/kit/stream';
8
+ const SUBPROTOCOL = `house.kit.stream.${KIT_WIRE}`;
9
+ const REFUSAL_HEADER = 'x-house-refusal';
10
+ // House beats each Kit connection every thirty seconds, so two silent beats mean this Kit process cannot hear House.
11
+ export const CONNECTION_SILENCE_MS = 60_000;
12
+ const SYSTEM_CONNECTION_CLOCK = {
13
+ later: (delay, callback) => setTimeout(callback, delay),
14
+ clear: (timer) => clearTimeout(timer),
15
+ };
16
+ export class ConnectionSilence {
17
+ timer = null;
18
+ silent;
19
+ clock;
20
+ interval;
21
+ constructor(silent, clock = SYSTEM_CONNECTION_CLOCK, interval = CONNECTION_SILENCE_MS) {
22
+ this.silent = silent;
23
+ this.clock = clock;
24
+ this.interval = interval;
25
+ }
26
+ heard() {
27
+ this.stop();
28
+ this.timer = this.clock.later(this.interval, () => {
29
+ this.timer = null;
30
+ this.silent();
31
+ });
32
+ }
33
+ stop() {
34
+ if (this.timer === null)
35
+ return;
36
+ this.clock.clear(this.timer);
37
+ this.timer = null;
38
+ }
39
+ }
40
+ function connectionUrl(house) {
41
+ const url = new URL(PATH, house);
42
+ url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';
43
+ return url;
44
+ }
45
+ function header(headers, name) {
46
+ for (let index = 0; index < headers.length; index += 2) {
47
+ if (headers[index].toString('latin1').toLowerCase() === name)
48
+ return headers[index + 1].toString('latin1');
49
+ }
50
+ return '';
51
+ }
52
+ let refused = null;
53
+ subscribe('undici:request:headers', (message) => {
54
+ const { request, response } = message;
55
+ if (!request.path.endsWith(PATH))
56
+ return;
57
+ refused = new HouseRefusal(PATH, response.statusCode, header(response.headers, REFUSAL_HEADER) || response.statusText);
58
+ });
59
+ export function holdConnection(handlers) {
60
+ let connection = null;
61
+ let failures = 0;
62
+ const connect = async () => {
63
+ const { house, credential } = (await readEnrolment());
64
+ refused = null;
65
+ const opening = new WebSocket(relayed(connectionUrl(house)), {
66
+ protocols: [SUBPROTOCOL],
67
+ headers: { authorization: `Bearer ${credential}` },
68
+ });
69
+ let opened = false;
70
+ let silence = null;
71
+ const closed = (event) => {
72
+ silence?.stop();
73
+ silence = null;
74
+ if (connection === opening)
75
+ connection = null;
76
+ handlers.closed();
77
+ process.stderr.write(`kit: connection closed ${event.code} ${event.reason}\n`);
78
+ if (event.reason === 'replaced')
79
+ end(REPLACED);
80
+ if (event.reason === 'credential_rejected' || refused?.status === 401) {
81
+ void signInAgain(credential);
82
+ return;
83
+ }
84
+ if (refused !== null)
85
+ endUnserved(refused.text);
86
+ if (!opened && refused !== null)
87
+ process.stderr.write(`kit: ${refused.message}\n`);
88
+ // A closed connection reopens in one to three seconds, spread so Kit processes one restart closed return apart; an opening House refused or left unanswered backs off on the jittered curve, retryable or not, since a resident outlives a House deploy.
89
+ setTimeout(() => void connect(), opened ? 1000 + Math.random() * 2000 : retryDelay(failures++));
90
+ };
91
+ opening.onopen = () => {
92
+ opened = true;
93
+ failures = 0;
94
+ connection = opening;
95
+ silence = new ConnectionSilence(() => {
96
+ if (connection !== opening)
97
+ return;
98
+ connection = null;
99
+ opening.onclose = null;
100
+ opening.close();
101
+ closed(new CloseEvent('close', { code: 1006, reason: 'heartbeat_missed' }));
102
+ });
103
+ silence.heard();
104
+ handlers.opened();
105
+ };
106
+ opening.onmessage = (event) => {
107
+ silence?.heard();
108
+ const arrived = JSON.parse(String(event.data));
109
+ if (arrived.type === 'input')
110
+ handlers.call(arrived);
111
+ else if (arrived.type !== 'beat')
112
+ handlers.notification(arrived);
113
+ };
114
+ opening.onerror = () => undefined;
115
+ opening.onclose = closed;
116
+ };
117
+ void connect();
118
+ return {
119
+ send(notification) {
120
+ if (connection === null || connection.readyState !== WebSocket.OPEN)
121
+ return false;
122
+ connection.send(JSON.stringify(notification));
123
+ return true;
124
+ },
125
+ };
126
+ }