@agentshouse/kit 0.1.0-alpha.3 → 0.1.0-alpha.31

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 (142) hide show
  1. package/README.md +722 -263
  2. package/bin/connect-linux.sh +200 -25
  3. package/bin/kit.js +179 -157
  4. package/bootstrap.json +17 -0
  5. package/package.json +7 -2
  6. package/src/adapter-mcp.js +76 -12
  7. package/src/agents.js +63 -8
  8. package/src/binding.js +52 -0
  9. package/src/blocks.js +2 -26
  10. package/src/bridge.js +28 -14
  11. package/src/bytes.js +19 -8
  12. package/src/configuration.js +13 -209
  13. package/src/connector-login.js +3 -84
  14. package/src/contract.js +36 -11
  15. package/src/delivery.js +4 -7
  16. package/src/directory.js +6 -26
  17. package/src/draft.js +4 -82
  18. package/src/git-main.js +138 -0
  19. package/src/git.js +62 -0
  20. package/src/google/calendar.js +39 -45
  21. package/src/google/drive.js +61 -186
  22. package/src/google/entries.js +346 -0
  23. package/src/google/gateway.js +3 -6
  24. package/src/google/gmail.js +33 -23
  25. package/src/google/oauth.js +106 -66
  26. package/src/google/source.js +21 -23
  27. package/src/host.js +6 -2
  28. package/src/house-main.js +65 -8
  29. package/src/house.js +446 -127
  30. package/src/how-we-work.md +25 -0
  31. package/src/inbound.js +2 -18
  32. package/src/kit-work-stream.js +118 -0
  33. package/src/launcher.js +46 -10
  34. package/src/local-files.js +3 -11
  35. package/src/login.js +23 -11
  36. package/src/mcp.js +18 -0
  37. package/src/mount.js +13 -21
  38. package/src/original.js +4 -4
  39. package/src/pacing.js +41 -0
  40. package/src/plan.js +37 -45
  41. package/src/repository.js +3 -61
  42. package/src/session-bin/git +2 -0
  43. package/src/setup.js +14 -15
  44. package/src/skill-set/ask-matt/PHASE-BOUNDARIES.md +55 -0
  45. package/src/skill-set/ask-matt/SKILL.md +91 -0
  46. package/src/skill-set/ask-matt/agents/openai.yaml +4 -0
  47. package/src/skill-set/code-review/LICENSE +21 -0
  48. package/src/skill-set/code-review/SKILL.md +89 -0
  49. package/src/skill-set/code-review/agents/openai.yaml +3 -0
  50. package/src/skill-set/codebase-design/DEEPENING.md +37 -0
  51. package/src/skill-set/codebase-design/DESIGN-IT-TWICE.md +44 -0
  52. package/src/skill-set/codebase-design/LICENSE +21 -0
  53. package/src/skill-set/codebase-design/SKILL.md +116 -0
  54. package/src/skill-set/codebase-design/agents/openai.yaml +3 -0
  55. package/src/skill-set/diagnosing-bugs/LICENSE +21 -0
  56. package/src/skill-set/diagnosing-bugs/SKILL.md +140 -0
  57. package/src/skill-set/diagnosing-bugs/agents/openai.yaml +3 -0
  58. package/src/skill-set/diagnosing-bugs/scripts/hitl-loop.template.sh +44 -0
  59. package/src/skill-set/domain-modeling/ADR-FORMAT.md +47 -0
  60. package/src/skill-set/domain-modeling/CONTEXT-FORMAT.md +60 -0
  61. package/src/skill-set/domain-modeling/LICENSE +21 -0
  62. package/src/skill-set/domain-modeling/SKILL.md +76 -0
  63. package/src/skill-set/domain-modeling/agents/openai.yaml +3 -0
  64. package/src/skill-set/grill-me/LICENSE +21 -0
  65. package/src/skill-set/grill-me/SKILL.md +8 -0
  66. package/src/skill-set/grill-me/agents/openai.yaml +4 -0
  67. package/src/skill-set/grill-with-docs/LICENSE +21 -0
  68. package/src/skill-set/grill-with-docs/SKILL.md +8 -0
  69. package/src/skill-set/grill-with-docs/agents/openai.yaml +4 -0
  70. package/src/skill-set/grilling/LICENSE +21 -0
  71. package/src/{starter-set → skill-set}/grilling/SKILL.md +1 -1
  72. package/src/skill-set/handoff/LICENSE +21 -0
  73. package/src/skill-set/handoff/SKILL.md +17 -0
  74. package/src/skill-set/handoff/agents/openai.yaml +4 -0
  75. package/src/skill-set/implement/LICENSE +21 -0
  76. package/src/skill-set/implement/SKILL.md +16 -0
  77. package/src/skill-set/implement/agents/openai.yaml +4 -0
  78. package/src/skill-set/improve-codebase-architecture/HTML-REPORT.md +123 -0
  79. package/src/skill-set/improve-codebase-architecture/LICENSE +21 -0
  80. package/src/skill-set/improve-codebase-architecture/SKILL.md +72 -0
  81. package/src/skill-set/improve-codebase-architecture/agents/openai.yaml +4 -0
  82. package/src/skill-set/prototype/LICENSE +21 -0
  83. package/src/skill-set/prototype/LOGIC.md +67 -0
  84. package/src/skill-set/prototype/SKILL.md +28 -0
  85. package/src/skill-set/prototype/UI.md +112 -0
  86. package/src/skill-set/prototype/agents/openai.yaml +3 -0
  87. package/src/skill-set/research/LICENSE +21 -0
  88. package/src/skill-set/research/SKILL.md +14 -0
  89. package/src/skill-set/research/agents/openai.yaml +3 -0
  90. package/src/skill-set/resolving-merge-conflicts/LICENSE +21 -0
  91. package/src/skill-set/resolving-merge-conflicts/SKILL.md +16 -0
  92. package/src/skill-set/resolving-merge-conflicts/agents/openai.yaml +3 -0
  93. package/src/skill-set/tdd/LICENSE +21 -0
  94. package/src/skill-set/tdd/SKILL.md +40 -0
  95. package/src/skill-set/tdd/agents/openai.yaml +3 -0
  96. package/src/skill-set/tdd/mocking.md +59 -0
  97. package/src/skill-set/tdd/tests.md +77 -0
  98. package/src/skill-set/teach/GLOSSARY-FORMAT.md +35 -0
  99. package/src/skill-set/teach/LEARNING-RECORD-FORMAT.md +46 -0
  100. package/src/skill-set/teach/LICENSE +21 -0
  101. package/src/skill-set/teach/MISSION-FORMAT.md +31 -0
  102. package/src/skill-set/teach/RESOURCES-FORMAT.md +32 -0
  103. package/src/skill-set/teach/SKILL.md +141 -0
  104. package/src/skill-set/teach/agents/openai.yaml +4 -0
  105. package/src/skill-set/to-questionnaire/LICENSE +21 -0
  106. package/src/skill-set/to-questionnaire/SKILL.md +55 -0
  107. package/src/skill-set/to-questionnaire/agents/openai.yaml +4 -0
  108. package/src/skill-set/to-spec/LICENSE +21 -0
  109. package/src/skill-set/to-spec/SKILL.md +76 -0
  110. package/src/skill-set/to-spec/agents/openai.yaml +4 -0
  111. package/src/skill-set/to-tickets/LICENSE +21 -0
  112. package/src/skill-set/to-tickets/SKILL.md +106 -0
  113. package/src/skill-set/to-tickets/agents/openai.yaml +4 -0
  114. package/src/skill-set/wait-what/LICENSE +21 -0
  115. package/src/skill-set/wait-what/SKILL.md +8 -0
  116. package/src/skill-set/wait-what/agents/openai.yaml +4 -0
  117. package/src/skill-set/wayfinder/LICENSE +21 -0
  118. package/src/skill-set/wayfinder/SKILL.md +129 -0
  119. package/src/skill-set/wayfinder/agents/openai.yaml +4 -0
  120. package/src/skill-set/writing-for-agents/LICENSE +21 -0
  121. package/src/skill-set/writing-for-agents/SKILL-MECHANICS.md +22 -0
  122. package/src/skill-set/writing-for-agents/SKILL.md +83 -0
  123. package/src/skill-set/writing-for-agents/agents/openai.yaml +3 -0
  124. package/src/skill-set.js +85 -0
  125. package/src/source.js +93 -54
  126. package/src/state.js +19 -1
  127. package/src/sync-library.js +7 -11
  128. package/src/sync-state.js +16 -3
  129. package/src/sync.js +129 -41
  130. package/src/tasks.js +75 -0
  131. package/src/telegram-view.js +214 -0
  132. package/src/telegram.js +161 -66
  133. package/src/turn-frames.js +69 -0
  134. package/src/worker.js +685 -184
  135. package/src/working-copy.js +1221 -0
  136. package/src/workspace.js +40 -32
  137. package/src/google/declared.js +0 -146
  138. package/src/google/id.js +0 -1
  139. package/src/instance/google.js +0 -1
  140. package/src/starter-set.js +0 -17
  141. /package/src/{starter-set/grilling → skill-set/ask-matt}/LICENSE +0 -0
  142. /package/src/{starter-set → skill-set}/grilling/agents/openai.yaml +0 -0
package/bin/kit.js CHANGED
@@ -2,15 +2,15 @@
2
2
  import { readFile } from "node:fs/promises";
3
3
  import { homedir } from "node:os";
4
4
  import { join, resolve } from "node:path";
5
- import { connectHouse, storedEnvironment, storedHouse } from "../src/login.js";
5
+ import { connectHouse, loginHouse, storedEnvironment, storedHouse } from "../src/login.js";
6
6
  import { apply } from "../src/apply.js";
7
7
  import { captureSource, resetSource, retrySourceOriginals, sourceStatus } from "../src/source.js";
8
+ import { accountEntries, accountStatus, captureAccount } from "../src/google/entries.js";
8
9
  import { setupEnvironment } from "../src/setup.js";
9
10
  import { signInConnector } from "../src/connector-login.js";
10
11
  import { attachSession } from "../src/attach.js";
11
12
  import { runResident, runWorkers } from "../src/worker.js";
12
- import { openSession, releaseControl } from "../src/house.js";
13
- import { GOOGLE_OAUTH_CLIENT } from "../src/instance/google.js";
13
+ import { openSession, releaseControl, requestDrain } from "../src/house.js";
14
14
  import { reportHost } from "../src/host.js";
15
15
  import { signInAgent, updateAgents } from "../src/agents.js";
16
16
  import { serveWorkspaces } from "../src/workspace.js";
@@ -32,44 +32,44 @@ const USAGE =
32
32
  "usage: kit <login|resident|credential|setup|apply|agents|source|repository|worker|sync|migrate|attachment|host|workspace|telegram> ...";
33
33
  const LOGIN_USAGE =
34
34
  "usage: kit login [--house <url>] [--environment <uuid>] [--manual|--host-browser]";
35
- const HOST_USAGE = "usage: kit host report [--house <url>] [--config <path>]";
35
+ const HOST_USAGE = "usage: kit host report [--config <path>]";
36
36
  const AGENTS_USAGE =
37
- "usage: kit agents update [--house <url>] [--config <path>] | kit agents sign-in <kind> [--house <url>] [--config <path>]";
38
- const WORKSPACE_USAGE = "usage: kit workspace host [--house <url>] [--config <path>] [--passes <count>]";
37
+ "usage: kit agents update [--config <path>] | kit agents sign-in <kind> [--config <path>]";
38
+ const WORKSPACE_USAGE = "usage: kit workspace host [--config <path>] [--passes <count>]";
39
39
  const SOURCE_USAGE =
40
- "usage: kit source <capture|reset|retry-files> <instance> [service] [--house <url>] [--config <path>]\n" +
41
- " kit source status <instance> [service] [--config <path>]\n" +
40
+ "usage: kit source <capture|status> <account|instance> [service] [--config <path>]\n" +
41
+ " kit source <reset|retry-files> <instance> [service] [--config <path>]\n" +
42
42
  " kit source sign-in <instance> [--config <path>]";
43
- const SETUP_USAGE = "usage: kit setup [--house <url>] [--config <path>]";
43
+ const SETUP_USAGE = "usage: kit setup [--config <path>]";
44
44
  const REPOSITORY_USAGE =
45
- "usage: kit repository capture <checkout> --room <room> --source-handle <handle> [--house <url>]";
45
+ "usage: kit repository capture <checkout> --room <room> --source-handle <handle>";
46
46
  const WORKER_USAGE =
47
- "usage: kit worker run [--house <url>] [--config <path>] | kit worker attach [<session>]";
47
+ "usage: kit worker run [--config <path>] | kit worker attach [<session>]";
48
48
  const SYNC_USAGE =
49
49
  "usage: kit sync <bootstrap|pull|rebootstrap|submit> ...";
50
50
  const SYNC_BOOTSTRAP_USAGE =
51
- "usage: kit sync bootstrap <directory> [--house <url>] --prefix <path> [--prefix <path> ...]";
52
- const SYNC_PULL_USAGE = "usage: kit sync pull <directory> [--house <url>]";
53
- const SYNC_REBOOTSTRAP_USAGE = "usage: kit sync rebootstrap <directory> [--house <url>]";
51
+ "usage: kit sync bootstrap <directory> --prefix <path> [--prefix <path> ...]";
52
+ const SYNC_PULL_USAGE = "usage: kit sync pull <directory>";
53
+ const SYNC_REBOOTSTRAP_USAGE = "usage: kit sync rebootstrap <directory>";
54
54
  const SYNC_SUBMIT_USAGE =
55
- "usage: kit sync submit <directory> [--house <url>] [--changes <path>]";
55
+ "usage: kit sync submit <directory> [--changes <path>]";
56
56
  const MIGRATE_USAGE = "usage: kit migrate <emit|mount|unmount|run> ...";
57
57
  const MIGRATE_EMIT_USAGE =
58
58
  "usage: kit migrate emit <migrator> --package <directory> [--config <path>]";
59
59
  const MIGRATE_MOUNT_USAGE =
60
- "usage: kit migrate mount <package> [--house <url>] --subtree <path>";
60
+ "usage: kit migrate mount <package> --subtree <path>";
61
61
  const MIGRATE_UNMOUNT_USAGE =
62
- "usage: kit migrate unmount <subtree> [--house <url>] [--confirm <subtree>]";
62
+ "usage: kit migrate unmount <subtree> [--confirm <subtree>]";
63
63
  const MIGRATE_RUN_USAGE =
64
- "usage: kit migrate run <migrator> [--house <url>] --subtree <path> --package <directory> [--config <path>]";
64
+ "usage: kit migrate run <migrator> --subtree <path> --package <directory> [--config <path>]";
65
65
  const ATTACHMENT_USAGE = "usage: kit attachment <upload|get> ...";
66
66
  const ATTACHMENT_UPLOAD_USAGE =
67
- "usage: kit attachment upload <file> [--house <url>] (--room <ref> | --private) [--name <name>] [--media-type <type>]";
67
+ "usage: kit attachment upload <file> (--room <ref> | --private) [--name <name>] [--media-type <type>]";
68
68
  const ATTACHMENT_GET_USAGE =
69
- "usage: kit attachment get [--house <url>] --attachment <at_ref> (--room <ref> | --private) [--output <path>]";
69
+ "usage: kit attachment get --attachment <at_ref> (--room <ref> | --private) [--output <path>]";
70
70
  const TELEGRAM_USAGE =
71
- "usage: kit telegram <connect|disconnect> [--house <url>]\n" +
72
- " kit telegram serve [--house <url>] [--passes <count>]";
71
+ "usage: kit telegram <connect|disconnect>\n" +
72
+ " kit telegram serve [--passes <count>]";
73
73
 
74
74
  function declared(argv, accepted, positionals, options = {}) {
75
75
  const repeated = options.repeated ?? [];
@@ -108,21 +108,10 @@ function write(line) {
108
108
  process.stdout.write(`${line}\n`);
109
109
  }
110
110
 
111
- function builtGoogleOAuthClient() {
112
- if (GOOGLE_OAUTH_CLIENT === null) {
113
- throw new KitRefusal("google_oauth_client_unconfigured", "run npm run build");
114
- }
115
- return GOOGLE_OAUTH_CLIENT;
116
- }
117
-
118
- async function selectedHouse(values, directory) {
119
- return storedHouse(directory, false, values["--house"]);
120
- }
121
-
122
111
  async function runLogin(args, directory) {
123
112
  const { values } = declared(args, ["--house", "--manual", "--host-browser", "--environment"], 0, { flags: ["--host-browser"] });
124
113
  if (values["--manual"] && values["--host-browser"]) throw new Error(LOGIN_USAGE);
125
- const house = await storedHouse(directory, true, values["--house"]);
114
+ const house = await loginHouse(directory, values["--house"]);
126
115
  const presentation = values["--manual"] === true ? "manual" : "loopback";
127
116
  await connectHouse({
128
117
  house,
@@ -135,12 +124,12 @@ async function runLogin(args, directory) {
135
124
  }
136
125
 
137
126
  async function runCredentialCheck(args, directory) {
138
- const { values } = declared(args, ["--house"], 0, { exact: true });
127
+ declared(args, [], 0, { exact: true });
139
128
  if (await storedEnvironment(directory) === null) throw new KitRefusal("kit_environment_invalid", "no enrolled Environment id");
140
- const house = await selectedHouse(values, directory);
129
+ const house = await storedHouse(directory);
141
130
  let session;
142
131
  try {
143
- session = await openSession({ house, directory });
132
+ session = await openSession({ house, directory, acquire: true });
144
133
  } catch (error) {
145
134
  if (error instanceof KitRefusal && error.code === "environment_control_lease_active") {
146
135
  write("Stored Kit authority is accepted; its Environment already has an active control lease.");
@@ -153,8 +142,8 @@ async function runCredentialCheck(args, directory) {
153
142
  }
154
143
 
155
144
  async function runResidentCommand(args, directory) {
156
- const { values } = declared(args, ["--house", "--config"], 0, { exact: true });
157
- const house = await selectedHouse(values, directory);
145
+ const { values } = declared(args, ["--config"], 0, { exact: true });
146
+ const house = await storedHouse(directory);
158
147
  const cancellation = new AbortController();
159
148
  const stop = () => cancellation.abort();
160
149
  process.once("SIGINT", stop);
@@ -167,24 +156,37 @@ async function runResidentCommand(args, directory) {
167
156
  }
168
157
  }
169
158
 
159
+ async function runResidentDrain(args, directory) {
160
+ declared(args, [], 0, { exact: true });
161
+ const answer = await requestDrain(directory);
162
+ if (answer.ready === true) {
163
+ write("House Kit is ready for its update.");
164
+ return;
165
+ }
166
+ write(
167
+ answer.sessions.length > 0
168
+ ? `House Kit is draining for its update and waits for Agent Sessions ${answer.sessions.join(", ")}.`
169
+ : answer.serving === true
170
+ ? "House Kit is draining for its update and waits for the Kit command it serves."
171
+ : `House Kit is draining for its update; House refused its lease release (${answer.refused}).`,
172
+ );
173
+ process.exitCode = 1;
174
+ }
175
+
170
176
  async function runSetup(args, directory) {
171
- const { values } = declared(args, ["--house", "--config"], 0, { exact: true });
172
- const house = await selectedHouse(values, directory);
173
- if (!house) throw new Error(SETUP_USAGE);
177
+ const { values } = declared(args, ["--config"], 0, { exact: true });
178
+ const house = await storedHouse(directory);
174
179
  const cancellation = new AbortController();
175
180
  const cancel = () => cancellation.abort();
176
181
  process.once("SIGINT", cancel);
177
182
  let setup;
178
183
  try {
179
- setup = await setupEnvironment(
180
- {
181
- house,
182
- directory,
183
- configuration: values["--config"] ?? join(directory, "kit.json"),
184
- signal: cancellation.signal,
185
- },
186
- { googleOAuthClient: builtGoogleOAuthClient },
187
- );
184
+ setup = await setupEnvironment({
185
+ house,
186
+ directory,
187
+ configuration: values["--config"] ?? join(directory, "kit.json"),
188
+ signal: cancellation.signal,
189
+ });
188
190
  } finally {
189
191
  process.removeListener("SIGINT", cancel);
190
192
  }
@@ -223,9 +225,8 @@ async function runSourceSignIn(args, directory) {
223
225
  }
224
226
 
225
227
  async function runApply(args, directory) {
226
- const { values } = declared(args, ["--house", "--config"], 0);
227
- const house = await selectedHouse(values, directory);
228
- if (!house) throw new Error("usage: kit apply --house <url> [--config <path>]");
228
+ const { values } = declared(args, ["--config"], 0);
229
+ const house = await storedHouse(directory);
229
230
  const cancellation = new AbortController();
230
231
  const cancel = () => cancellation.abort();
231
232
  process.once("SIGINT", cancel);
@@ -252,27 +253,32 @@ async function runApply(args, directory) {
252
253
  }
253
254
 
254
255
  async function runSourceCapture(args, directory) {
255
- const { values, rest } = declared(args, ["--house", "--config"], 2);
256
- const house = await selectedHouse(values, directory);
257
- if (!house || rest.length === 0) throw new Error(SOURCE_USAGE);
256
+ const { values, rest } = declared(args, ["--config"], 2);
257
+ if (rest.length === 0) throw new Error(SOURCE_USAGE);
258
+ const house = await storedHouse(directory);
258
259
  const cancellation = new AbortController();
259
260
  process.once("SIGINT", () => cancellation.abort());
260
- const result = await captureSource(
261
- {
262
- house,
263
- directory,
264
- configuration: values["--config"] ?? join(directory, "kit.json"),
265
- instance: rest[0],
266
- service: rest[1] ?? null,
267
- signal: cancellation.signal,
268
- },
269
- { googleOAuthClient: builtGoogleOAuthClient },
270
- );
261
+ const entries = await accountEntries(directory, rest[0]);
262
+ const options = {
263
+ house,
264
+ directory,
265
+ service: rest[1] ?? null,
266
+ signal: cancellation.signal,
267
+ };
268
+ const result =
269
+ entries.length > 0
270
+ ? await captureAccount({ ...options, account: rest[0], entries })
271
+ : await captureSource({
272
+ ...options,
273
+ configuration: values["--config"] ?? join(directory, "kit.json"),
274
+ instance: rest[0],
275
+ });
271
276
  for (const delivered of result.services) {
272
277
  const category =
273
278
  delivered.health.category === null ? "" : ` (${delivered.health.category})`;
279
+ const cause = delivered.health.cause === undefined ? "" : `, cause ${delivered.health.cause}`;
274
280
  write(
275
- `Delivered ${delivered.delivered} items for ${result.instance}/${delivered.service} in ${delivered.batches} batches; health ${delivered.health.state}${category}.`,
281
+ `Delivered ${delivered.delivered} items for ${result.instance}/${delivered.service} in ${delivered.batches} batches; health ${delivered.health.state}${category}${cause}.`,
276
282
  );
277
283
  if (delivered.refused !== null) {
278
284
  write(
@@ -297,9 +303,9 @@ function writeSourceOriginals(instance, service) {
297
303
  }
298
304
 
299
305
  async function runSourceRetryFiles(args, directory) {
300
- const { values, rest } = declared(args, ["--house", "--config"], 2);
301
- const house = await selectedHouse(values, directory);
302
- if (!house || rest.length === 0) throw new Error(SOURCE_USAGE);
306
+ const { values, rest } = declared(args, ["--config"], 2);
307
+ if (rest.length === 0) throw new Error(SOURCE_USAGE);
308
+ const house = await storedHouse(directory);
303
309
  const cancellation = new AbortController();
304
310
  process.once("SIGINT", () => cancellation.abort());
305
311
  const result = await retrySourceOriginals({
@@ -321,30 +327,40 @@ async function runSourceRetryFiles(args, directory) {
321
327
  async function runSourceStatus(args, directory) {
322
328
  const { values, rest } = declared(args, ["--config"], 2);
323
329
  if (rest.length === 0) throw new Error(SOURCE_USAGE);
324
- const result = await sourceStatus({
325
- directory,
326
- configuration: values["--config"] ?? join(directory, "kit.json"),
327
- instance: rest[0],
328
- service: rest[1] ?? null,
329
- });
330
+ const entries = await accountEntries(directory, rest[0]);
331
+ const result =
332
+ entries.length > 0
333
+ ? await accountStatus({ directory, account: rest[0], entries, service: rest[1] ?? null })
334
+ : await sourceStatus({
335
+ directory,
336
+ configuration: values["--config"] ?? join(directory, "kit.json"),
337
+ instance: rest[0],
338
+ service: rest[1] ?? null,
339
+ });
330
340
  for (const reported of result.services) {
331
341
  const category = reported.health.category === null ? "" : ` (${reported.health.category})`;
342
+ const cause = reported.health.cause === undefined ? "" : `, cause ${reported.health.cause}`;
332
343
  const observed =
333
344
  reported.health.observed_at === null ? "never observed" : reported.health.observed_at;
345
+ const signedIn =
346
+ reported.signed_in === undefined ? "" : reported.signed_in ? "signed in; " : "signed out; ";
334
347
  write(
335
348
  `${result.instance}/${reported.service} -> ${reported.source_ref} in ${reported.rooms.join(", ")}: ` +
336
- `${reported.health.state}${category} at ${observed}; ` +
349
+ `${signedIn}${reported.health.state}${category}${cause} at ${observed}; ` +
337
350
  `cursor ${reported.checkpoint?.cursor ?? "none"}, ${reported.gaps.length} gaps, ` +
338
351
  `${reported.dropped.length} dropped items, ${reported.originals.length} unsaved originals.`,
339
352
  );
353
+ if (reported.enable !== null && reported.enable !== undefined) {
354
+ write(`Enable the ${reported.enable} in the Google Cloud project of ${result.instance}'s OAuth client.`);
355
+ }
340
356
  }
341
357
  if (result.services.some((reported) => reported.health.state !== "ok")) process.exitCode = 1;
342
358
  }
343
359
 
344
360
  async function runSourceReset(args, directory) {
345
- const { values, rest } = declared(args, ["--house", "--config"], 2);
346
- const house = await selectedHouse(values, directory);
347
- if (!house || rest.length === 0) throw new Error(SOURCE_USAGE);
361
+ const { values, rest } = declared(args, ["--config"], 2);
362
+ if (rest.length === 0) throw new Error(SOURCE_USAGE);
363
+ const house = await storedHouse(directory);
348
364
  const result = await resetSource({
349
365
  house,
350
366
  directory,
@@ -360,11 +376,11 @@ async function runSourceReset(args, directory) {
360
376
  }
361
377
 
362
378
  async function runRepositoryCapture(args, directory) {
363
- const { values, rest } = declared(args, ["--house", "--room", "--source-handle"], 1);
364
- const house = await selectedHouse(values, directory);
379
+ const { values, rest } = declared(args, ["--room", "--source-handle"], 1);
365
380
  const room = values["--room"];
366
381
  const sourceHandle = values["--source-handle"];
367
- if (!house || !room || !sourceHandle || rest.length !== 1) throw new Error(REPOSITORY_USAGE);
382
+ if (!room || !sourceHandle || rest.length !== 1) throw new Error(REPOSITORY_USAGE);
383
+ const house = await storedHouse(directory);
368
384
  const cancellation = new AbortController();
369
385
  const cancel = () => cancellation.abort();
370
386
  process.once("SIGINT", cancel);
@@ -412,17 +428,13 @@ function writeConversationFiles(supervised) {
412
428
  }
413
429
 
414
430
  async function runWorkerRun(args, directory) {
415
- const { values } = declared(args, ["--house", "--config"], 0);
416
- const house = await selectedHouse(values, directory);
417
- if (!house) throw new Error(WORKER_USAGE);
418
- const supervised = await runWorkers(
419
- {
420
- house,
421
- directory,
422
- configuration: values["--config"] ?? join(directory, "kit.json"),
423
- },
424
- { googleOAuthClient: builtGoogleOAuthClient },
425
- );
431
+ const { values } = declared(args, ["--config"], 0);
432
+ const house = await storedHouse(directory);
433
+ const supervised = await runWorkers({
434
+ house,
435
+ directory,
436
+ configuration: values["--config"] ?? join(directory, "kit.json"),
437
+ });
426
438
  write(`Worker runtime ready on tmux ${supervised.tmux} in namespace ${supervised.namespace}.`);
427
439
  if (supervised.epochReport !== null) {
428
440
  write(`House started a new log epoch; reported ${supervised.epochReport.length} held Runs and House settled each.`);
@@ -483,12 +495,12 @@ function syncCancellation() {
483
495
  }
484
496
 
485
497
  async function runSyncBootstrap(args, directory) {
486
- const { values, lists, rest } = declared(args, ["--house", "--prefix"], 1, {
498
+ const { lists, rest } = declared(args, ["--prefix"], 1, {
487
499
  repeated: ["--prefix"],
488
500
  exact: true,
489
501
  });
490
- const house = await selectedHouse(values, directory);
491
- if (!house || lists["--prefix"].length === 0) throw new Error(SYNC_BOOTSTRAP_USAGE);
502
+ if (lists["--prefix"].length === 0) throw new Error(SYNC_BOOTSTRAP_USAGE);
503
+ const house = await storedHouse(directory);
492
504
  const run = syncCancellation();
493
505
  try {
494
506
  const result = await bootstrap({
@@ -507,9 +519,8 @@ async function runSyncBootstrap(args, directory) {
507
519
  }
508
520
 
509
521
  async function runSyncPull(args, directory) {
510
- const { values, rest } = declared(args, ["--house"], 1, { exact: true });
511
- const house = await selectedHouse(values, directory);
512
- if (!house) throw new Error(SYNC_PULL_USAGE);
522
+ const { rest } = declared(args, [], 1, { exact: true });
523
+ const house = await storedHouse(directory);
513
524
  const run = syncCancellation();
514
525
  try {
515
526
  const result = await pull({
@@ -527,9 +538,8 @@ async function runSyncPull(args, directory) {
527
538
  }
528
539
 
529
540
  async function runSyncRebootstrap(args, directory) {
530
- const { values, rest } = declared(args, ["--house"], 1, { exact: true });
531
- const house = await selectedHouse(values, directory);
532
- if (!house) throw new Error(SYNC_REBOOTSTRAP_USAGE);
541
+ const { rest } = declared(args, [], 1, { exact: true });
542
+ const house = await storedHouse(directory);
533
543
  const run = syncCancellation();
534
544
  try {
535
545
  const result = await rebootstrap({
@@ -554,9 +564,8 @@ async function readChanges(path) {
554
564
  }
555
565
 
556
566
  async function runSyncSubmit(args, directory) {
557
- const { values, rest } = declared(args, ["--house", "--changes"], 1, { exact: true });
558
- const house = await selectedHouse(values, directory);
559
- if (!house) throw new Error(SYNC_SUBMIT_USAGE);
567
+ const { values, rest } = declared(args, ["--changes"], 1, { exact: true });
568
+ const house = await storedHouse(directory);
560
569
  const run = syncCancellation();
561
570
  try {
562
571
  const result = await submit({
@@ -629,11 +638,11 @@ async function mountEmitted(packagePath, options, run) {
629
638
  }
630
639
 
631
640
  async function runMigrateMount(args, directory) {
632
- const { values, rest } = declared(args, ["--house", "--subtree"], 1, { exact: true });
633
- const house = await selectedHouse(values, directory);
634
- if (!house || rest.length !== 1 || values["--subtree"] === undefined) {
641
+ const { values, rest } = declared(args, ["--subtree"], 1, { exact: true });
642
+ if (rest.length !== 1 || values["--subtree"] === undefined) {
635
643
  throw new Error(MIGRATE_MOUNT_USAGE);
636
644
  }
645
+ const house = await storedHouse(directory);
637
646
  const run = migrateCancellation();
638
647
  try {
639
648
  await mountEmitted(rest[0], { house, directory, subtree: values["--subtree"] }, run);
@@ -643,18 +652,17 @@ async function runMigrateMount(args, directory) {
643
652
  }
644
653
 
645
654
  async function runMigrateRun(args, directory) {
646
- const { values, rest } = declared(args, ["--house", "--subtree", "--package", "--config"], 1, {
655
+ const { values, rest } = declared(args, ["--subtree", "--package", "--config"], 1, {
647
656
  exact: true,
648
657
  });
649
- const house = await selectedHouse(values, directory);
650
658
  if (
651
- !house ||
652
659
  rest.length !== 1 ||
653
660
  values["--subtree"] === undefined ||
654
661
  values["--package"] === undefined
655
662
  ) {
656
663
  throw new Error(MIGRATE_RUN_USAGE);
657
664
  }
665
+ const house = await storedHouse(directory);
658
666
  const run = migrateCancellation();
659
667
  try {
660
668
  const emitted = await emitPackage(
@@ -671,9 +679,9 @@ async function runMigrateRun(args, directory) {
671
679
  }
672
680
 
673
681
  async function runMigrateUnmount(args, directory) {
674
- const { values, rest } = declared(args, ["--house", "--confirm"], 1, { exact: true });
675
- const house = await selectedHouse(values, directory);
676
- if (!house || rest.length !== 1) throw new Error(MIGRATE_UNMOUNT_USAGE);
682
+ const { values, rest } = declared(args, ["--confirm"], 1, { exact: true });
683
+ if (rest.length !== 1) throw new Error(MIGRATE_UNMOUNT_USAGE);
684
+ const house = await storedHouse(directory);
677
685
  const run = migrateCancellation();
678
686
  try {
679
687
  const result = await unmountSubtree({
@@ -729,12 +737,12 @@ function attachmentCancellation() {
729
737
  async function runAttachmentUpload(args, directory) {
730
738
  const { values, rest } = declared(
731
739
  args,
732
- ["--house", "--room", "--private", "--name", "--media-type"],
740
+ ["--room", "--private", "--name", "--media-type"],
733
741
  1,
734
742
  { flags: ["--private"] },
735
743
  );
736
- const house = await selectedHouse(values, directory);
737
- if (!house || rest.length !== 1) throw new Error(ATTACHMENT_UPLOAD_USAGE);
744
+ if (rest.length !== 1) throw new Error(ATTACHMENT_UPLOAD_USAGE);
745
+ const house = await storedHouse(directory);
738
746
  const run = attachmentCancellation();
739
747
  try {
740
748
  const result = await uploadAttachment({
@@ -756,13 +764,13 @@ async function runAttachmentUpload(args, directory) {
756
764
  async function runAttachmentGet(args, directory) {
757
765
  const { values } = declared(
758
766
  args,
759
- ["--house", "--attachment", "--room", "--private", "--output"],
767
+ ["--attachment", "--room", "--private", "--output"],
760
768
  0,
761
769
  { flags: ["--private"] },
762
770
  );
763
- const house = await selectedHouse(values, directory);
764
771
  const attachment = values["--attachment"];
765
- if (!house || !attachment) throw new Error(ATTACHMENT_GET_USAGE);
772
+ if (!attachment) throw new Error(ATTACHMENT_GET_USAGE);
773
+ const house = await storedHouse(directory);
766
774
  const run = attachmentCancellation();
767
775
  try {
768
776
  const result = await getAttachment({
@@ -788,9 +796,8 @@ async function runAttachment(args, directory) {
788
796
  }
789
797
 
790
798
  async function runHostReport(args, directory) {
791
- const { values } = declared(args, ["--house", "--config"], 0, { exact: true });
792
- const house = await selectedHouse(values, directory);
793
- if (!house) throw new Error(HOST_USAGE);
799
+ const { values } = declared(args, ["--config"], 0, { exact: true });
800
+ const house = await storedHouse(directory);
794
801
  const observed = await reportHost({
795
802
  house,
796
803
  directory,
@@ -802,9 +809,8 @@ async function runHostReport(args, directory) {
802
809
  }
803
810
 
804
811
  async function runAgentsUpdate(args, directory) {
805
- const { values } = declared(args, ["--house", "--config"], 0, { exact: true });
806
- const house = await selectedHouse(values, directory);
807
- if (!house) throw new Error(AGENTS_USAGE);
812
+ const { values } = declared(args, ["--config"], 0, { exact: true });
813
+ const house = await storedHouse(directory);
808
814
  const { updated } = await updateAgents({
809
815
  house,
810
816
  directory,
@@ -830,10 +836,10 @@ async function runAgentsUpdate(args, directory) {
830
836
  }
831
837
 
832
838
  async function runAgentsSignIn(args, directory) {
833
- const { values, rest } = declared(args, ["--house", "--config"], 1, { exact: true });
834
- const house = await selectedHouse(values, directory);
839
+ const { values, rest } = declared(args, ["--config"], 1, { exact: true });
835
840
  const [kind] = rest;
836
- if (!house || !kind) throw new Error(AGENTS_USAGE);
841
+ if (!kind) throw new Error(AGENTS_USAGE);
842
+ const house = await storedHouse(directory);
837
843
  const { status, reported } = await signInAgent({
838
844
  house,
839
845
  directory,
@@ -850,19 +856,29 @@ async function runAgentsSignIn(args, directory) {
850
856
  }
851
857
 
852
858
  async function runWorkspaceHost(args, directory) {
853
- const { values } = declared(args, ["--house", "--config", "--passes"], 0, { exact: true });
854
- const house = await selectedHouse(values, directory);
855
- if (!house) throw new Error(WORKSPACE_USAGE);
859
+ const { values } = declared(args, ["--config", "--passes"], 0, { exact: true });
856
860
  const passes = values["--passes"] === undefined ? undefined : Number(values["--passes"]);
857
861
  if (passes !== undefined && (!Number.isSafeInteger(passes) || passes < 1)) {
858
862
  throw new Error(WORKSPACE_USAGE);
859
863
  }
860
- const served = await serveWorkspaces({
861
- house,
862
- directory,
863
- configuration: values["--config"] ?? join(directory, "kit.json"),
864
- passes,
865
- });
864
+ const house = await storedHouse(directory);
865
+ const cancellation = new AbortController();
866
+ const cancel = () => cancellation.abort();
867
+ process.once("SIGINT", cancel);
868
+ process.once("SIGTERM", cancel);
869
+ let served;
870
+ try {
871
+ served = await serveWorkspaces({
872
+ house,
873
+ directory,
874
+ configuration: values["--config"] ?? join(directory, "kit.json"),
875
+ passes,
876
+ signal: cancellation.signal,
877
+ });
878
+ } finally {
879
+ process.removeListener("SIGINT", cancel);
880
+ process.removeListener("SIGTERM", cancel);
881
+ }
866
882
  for (const name of served.reconciled) {
867
883
  write(`Stopped ${name}; House authorizes no running workspace for it.`);
868
884
  }
@@ -877,9 +893,8 @@ async function runWorkspaceHost(args, directory) {
877
893
  }
878
894
 
879
895
  async function runTelegramConnect(args, directory) {
880
- const { values } = declared(args, ["--house"], 0, { exact: true });
881
- const house = await selectedHouse(values, directory);
882
- if (!house) throw new Error(TELEGRAM_USAGE);
896
+ declared(args, [], 0, { exact: true });
897
+ const house = await storedHouse(directory);
883
898
  const cancellation = new AbortController();
884
899
  const cancel = () => cancellation.abort();
885
900
  process.once("SIGINT", cancel);
@@ -897,9 +912,8 @@ async function runTelegramConnect(args, directory) {
897
912
  }
898
913
 
899
914
  async function runTelegramDisconnect(args, directory) {
900
- const { values } = declared(args, ["--house"], 0, { exact: true });
901
- const house = await selectedHouse(values, directory);
902
- if (!house) throw new Error(TELEGRAM_USAGE);
915
+ declared(args, [], 0, { exact: true });
916
+ const house = await storedHouse(directory);
903
917
  const cancellation = new AbortController();
904
918
  const cancel = () => cancellation.abort();
905
919
  process.once("SIGINT", cancel);
@@ -919,20 +933,25 @@ async function runTelegramDisconnect(args, directory) {
919
933
  }
920
934
 
921
935
  async function runTelegramServe(args, directory) {
922
- const { values } = declared(args, ["--house", "--passes"], 0, { exact: true });
923
- const house = await selectedHouse(values, directory);
924
- if (!house) throw new Error(TELEGRAM_USAGE);
936
+ const { values } = declared(args, ["--passes"], 0, { exact: true });
925
937
  const passes = values["--passes"] === undefined ? undefined : Number(values["--passes"]);
926
938
  if (passes !== undefined && (!Number.isSafeInteger(passes) || passes < 1)) {
927
939
  throw new Error(TELEGRAM_USAGE);
928
940
  }
941
+ const house = await storedHouse(directory);
929
942
  const cancellation = new AbortController();
930
943
  const cancel = () => cancellation.abort();
931
944
  process.once("SIGINT", cancel);
932
945
  process.once("SIGTERM", cancel);
933
946
  let served;
934
947
  try {
935
- served = await serveTelegramGateway({ house, directory, passes, signal: cancellation.signal });
948
+ served = await serveTelegramGateway({
949
+ house,
950
+ directory,
951
+ passes,
952
+ signal: cancellation.signal,
953
+ refused: (failure) => write(refusedPassLine(failure)),
954
+ });
936
955
  } finally {
937
956
  process.removeListener("SIGINT", cancel);
938
957
  process.removeListener("SIGTERM", cancel);
@@ -952,20 +971,23 @@ async function runTelegramServe(args, directory) {
952
971
  `File send ${settled.upload} settled ${settled.outcome}${settled.reason === null ? "" : ` (${settled.reason})`}.`,
953
972
  );
954
973
  }
955
- for (const failure of served.failures) {
956
- write(
957
- `The ${failure.activity} pass${failure.item === null ? "" : ` for ${failure.item}`} could not finish (${failure.code}).`,
958
- );
959
- }
974
+ for (const failure of served.failures) write(refusedPassLine(failure));
960
975
  if (served.failures.length > 0) process.exitCode = 1;
961
976
  }
962
977
 
978
+ function refusedPassLine(failure) {
979
+ return `The ${failure.activity} pass${failure.item === null ? "" : ` for ${failure.item}`} could not finish (${failure.code}).`;
980
+ }
981
+
963
982
  async function main() {
964
983
  const [command, ...args] = process.argv.slice(2);
965
984
  const directory = process.env.HOUSE_KIT_HOME ?? join(homedir(), ".house-kit");
966
985
  if (command === "login") return runLogin(args, directory);
967
986
  if (command === "credential" && args[0] === "check") return runCredentialCheck(args.slice(1), directory);
968
- if (command === "resident") return runResidentCommand(args, directory);
987
+ if (command === "resident") {
988
+ if (args[0] === "drain") return runResidentDrain(args.slice(1), directory);
989
+ return runResidentCommand(args, directory);
990
+ }
969
991
  if (command === "setup") return runSetup(args, directory);
970
992
  if (command === "apply") return runApply(args, directory);
971
993
  if (command === "worker") {
package/bootstrap.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "version": "0.1.0-alpha.31",
4
+ "hosts": {
5
+ "linux": {
6
+ "command": "bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.31/connect-linux.sh)",
7
+ "asset": {
8
+ "name": "connect-linux.sh",
9
+ "url": "https://github.com/agentshouse/kit/releases/download/v0.1.0-alpha.31/connect-linux.sh"
10
+ },
11
+ "workspace": {
12
+ "argument": "--workspace",
13
+ "quoting": "posix"
14
+ }
15
+ }
16
+ }
17
+ }