@agentshouse/kit 0.2.1-cd9cbd8b6428c → 0.2.1-ce145e9aadbf6

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/dist/agents.js CHANGED
@@ -3,13 +3,16 @@ import { readFile, realpath } from 'node:fs/promises';
3
3
  import { killTree, startAdapter } from './acp.js';
4
4
  import { CLIS, KIT_VERSION, below, installAdapter, installCli, locate, run, versionOf } from './clis.js';
5
5
  import { agentBase, kitHome } from './home.js';
6
- const SIGNED_OUT = { signed_in: false, models: [] };
6
+ const SIGNED_OUT = { signed_in: false, models: [], modes: [] };
7
7
  function select(options, category) {
8
8
  const option = options.find((candidate) => candidate.category === category);
9
9
  return option?.type === 'select' ? option : undefined;
10
10
  }
11
+ function choices(options) {
12
+ return options.flatMap((entry) => ('group' in entry ? entry.options : [entry]));
13
+ }
11
14
  function values(options) {
12
- return options.flatMap((entry) => ('group' in entry ? entry.options : [entry])).map((entry) => entry.value);
15
+ return choices(options).map((entry) => entry.value);
13
16
  }
14
17
  function causeOf(error) {
15
18
  return error instanceof Error ? error.message : String(error);
@@ -21,9 +24,11 @@ async function models(kind, adapter, known) {
21
24
  const agent = adapter.connection.agent;
22
25
  const opened = await agent.request('session/new', { cwd: kitHome(), mcpServers: [] });
23
26
  let options = opened.configOptions ?? [];
27
+ const mode = select(options, 'mode');
28
+ const modes = mode === undefined ? [] : choices(mode.options).map(({ value, name }) => ({ mode: value, name }));
24
29
  const model = select(options, 'model');
25
30
  if (model === undefined)
26
- return [];
31
+ return { models: [], modes };
27
32
  const offered = [];
28
33
  for (const value of values(model.options)) {
29
34
  if (select(options, 'model')?.currentValue !== value) {
@@ -39,7 +44,13 @@ async function models(kind, adapter, known) {
39
44
  const effort = select(options, 'thought_level');
40
45
  offered.push({ model: value, efforts: effort === undefined ? [] : values(effort.options) });
41
46
  }
42
- return offered;
47
+ return { models: offered, modes };
48
+ }
49
+ async function signedIn(kind, cli, known) {
50
+ const probe = CLIS[kind].signedIn;
51
+ if ('command' in probe)
52
+ return (await run(cli, probe.command, 30_000)).status === 0;
53
+ return (await offer(kind, cli, known)).signed_in;
43
54
  }
44
55
  async function offer(kind, cli, known) {
45
56
  const probe = CLIS[kind].signedIn;
@@ -53,11 +64,15 @@ async function offer(kind, cli, known) {
53
64
  if (typeof method !== 'string' || method.length === 0)
54
65
  return SIGNED_OUT;
55
66
  }
56
- return { signed_in: true, models: await models(kind, adapter, known.models) };
67
+ return { signed_in: true, ...(await models(kind, adapter, known.models)) };
57
68
  }
58
69
  catch (error) {
59
70
  process.stderr.write(`kit: ${kind} did not offer its models: ${causeOf(error)}\n`);
60
- return { signed_in: adapter === undefined && 'initializeMeta' in probe ? known.signed_in : true, models: known.models };
71
+ return {
72
+ signed_in: adapter === undefined && 'initializeMeta' in probe ? known.signed_in : true,
73
+ models: known.models,
74
+ modes: known.modes,
75
+ };
61
76
  }
62
77
  finally {
63
78
  if (adapter !== undefined)
@@ -72,6 +87,8 @@ function reported(kind, reading) {
72
87
  failure: reading.failure,
73
88
  signed_in: reading.signed_in,
74
89
  models: reading.models,
90
+ modes: reading.modes,
91
+ full_access: CLIS[kind].fullAccess,
75
92
  };
76
93
  }
77
94
  function tooOld(kind, release) {
@@ -114,7 +131,7 @@ export class Agents {
114
131
  });
115
132
  this.reading = reading;
116
133
  return reading.then(({ agents }) => {
117
- Promise.all(agents.map((kind) => this.queue(kind, () => this.load(kind))))
134
+ Promise.all(agents.map((kind) => this.load(kind)))
118
135
  .then(() => this.report())
119
136
  .catch(logged);
120
137
  });
@@ -130,7 +147,7 @@ export class Agents {
130
147
  const known = this.readings.get(kind);
131
148
  const kept = known?.release === null || known?.minimum !== undefined ? SIGNED_OUT : (known ?? SIGNED_OUT);
132
149
  if (known?.release !== release || known.minimum !== undefined) {
133
- this.update(kind, { release, failure: null, signed_in: kept.signed_in, models: kept.models });
150
+ this.update(kind, { release, failure: null, signed_in: kept.signed_in, models: kept.models, modes: kept.modes });
134
151
  }
135
152
  const read = this.nextRead(kind);
136
153
  offer(kind, cli, kept)
@@ -147,10 +164,12 @@ export class Agents {
147
164
  return this.queue(kind, () => this.ensure(kind));
148
165
  }
149
166
  async reread(kind) {
150
- await this.queue(kind, async () => {
151
- this.nextRead(kind);
152
- this.readings.set(kind, await this.examine(kind, this.readings.get(kind) ?? SIGNED_OUT));
153
- });
167
+ await this.examine(kind, this.readings.get(kind) ?? SIGNED_OUT, offer);
168
+ await this.report();
169
+ }
170
+ async recheck(kind) {
171
+ const known = this.readings.get(kind) ?? SIGNED_OUT;
172
+ await this.examine(kind, known, async (kind, cli) => (await signedIn(kind, cli, known)) ? { ...known, signed_in: true } : SIGNED_OUT);
154
173
  await this.report();
155
174
  }
156
175
  report() {
@@ -207,18 +226,18 @@ export class Agents {
207
226
  return { release, minimum, failure: null, ...SIGNED_OUT };
208
227
  return { cli, release };
209
228
  }
210
- async examine(kind, known) {
211
- const resolved = await this.resolve(kind);
212
- if (!('cli' in resolved))
213
- return resolved;
214
- return { release: resolved.release, failure: null, ...(await offer(kind, resolved.cli, known)) };
229
+ async examine(kind, known, read) {
230
+ const current = this.nextRead(kind);
231
+ const resolved = await this.queue(kind, () => this.resolve(kind));
232
+ const reading = 'cli' in resolved ? { release: resolved.release, failure: null, ...(await read(kind, resolved.cli, known)) } : resolved;
233
+ if (this.reads.get(kind) === current)
234
+ this.readings.set(kind, reading);
215
235
  }
216
236
  async load(kind) {
217
237
  const known = this.readings.get(kind);
218
238
  if (known !== undefined && known.failure === null)
219
239
  return;
220
- this.nextRead(kind);
221
- this.readings.set(kind, await this.examine(kind, SIGNED_OUT));
240
+ await this.examine(kind, SIGNED_OUT, offer);
222
241
  }
223
242
  async send() {
224
243
  const agents = this.desired.agents.flatMap((kind) => {
@@ -1,23 +1,23 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "version": "0.2.1-cd9cbd8b6428c",
3
+ "version": "0.2.1-ce145e9aadbf6",
4
4
  "hosts": {
5
5
  "macos": {
6
6
  "asset": {
7
7
  "name": "connect-linux.sh",
8
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-cd9cbd8b6428c/connect-linux.sh"
8
+ "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-ce145e9aadbf6/connect-linux.sh"
9
9
  }
10
10
  },
11
11
  "linux": {
12
12
  "asset": {
13
13
  "name": "connect-linux.sh",
14
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-cd9cbd8b6428c/connect-linux.sh"
14
+ "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-ce145e9aadbf6/connect-linux.sh"
15
15
  }
16
16
  },
17
17
  "windows": {
18
18
  "asset": {
19
19
  "name": "connect-windows.ps1",
20
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-cd9cbd8b6428c/connect-windows.ps1"
20
+ "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-ce145e9aadbf6/connect-windows.ps1"
21
21
  }
22
22
  }
23
23
  }
package/dist/bridge.js CHANGED
@@ -23,7 +23,8 @@ export async function received(request) {
23
23
  text += chunk;
24
24
  return text;
25
25
  }
26
- function relay(request, response, target, authorization) {
26
+ function relay(request, response, house, authorization) {
27
+ const target = relayed(house);
27
28
  const send = target.protocol === 'https:' ? httpsRequest : httpRequest;
28
29
  const forwarded = send(target, {
29
30
  method: request.method,
package/dist/clis.js CHANGED
@@ -1,10 +1,16 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { readFileSync } from 'node:fs';
3
- import { readFile } from 'node:fs/promises';
4
- import { userInfo } from 'node:os';
3
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
4
+ import { homedir, userInfo } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
  import { kitHome } from './home.js';
7
7
  const RUNNING_JOB = new Set(['running', 'paused']);
8
+ async function allowHouseInCodex() {
9
+ const rules = join(process.env.CODEX_HOME || join(homedir(), '.codex'), 'rules');
10
+ await mkdir(rules, { recursive: true });
11
+ await writeFile(join(rules, 'house.rules'), 'prefix_rule(pattern = ["house"], decision = "allow")\n');
12
+ }
13
+ async function nothing() { }
8
14
  function threadStatus({ method, params }) {
9
15
  if (method !== 'session/update' || params?.update?.sessionUpdate !== 'session_info_update')
10
16
  return undefined;
@@ -36,6 +42,9 @@ export const CLIS = {
36
42
  install: 'curl -fsSL https://chatgpt.com/codex/install.sh | sh',
37
43
  adapter: { package: '@agentclientprotocol/codex-acp', bin: 'codex-acp', executable: 'CODEX_PATH', env: {} },
38
44
  args: [],
45
+ fullAccess: 'agent-full-access',
46
+ sessionMeta: {},
47
+ allowHouse: allowHouseInCodex,
39
48
  signedIn: { command: ['login', 'status'] },
40
49
  login: { args: ['login', '--device-auth'], code: 'show' },
41
50
  queues: false,
@@ -52,9 +61,12 @@ export const CLIS = {
52
61
  package: '@agentclientprotocol/claude-agent-acp',
53
62
  bin: 'claude-agent-acp',
54
63
  executable: 'CLAUDE_CODE_EXECUTABLE',
55
- env: { CLAUDE_CODE_ENTRYPOINT: 'claude-agent-acp' },
64
+ env: { CLAUDE_CODE_ENTRYPOINT: 'claude-agent-acp', IS_SANDBOX: '1' },
56
65
  },
57
66
  args: [],
67
+ fullAccess: 'bypassPermissions',
68
+ sessionMeta: { claudeCode: { options: { allowedTools: ['Bash(house:*)'] } } },
69
+ allowHouse: nothing,
58
70
  signedIn: { command: ['auth', 'status'] },
59
71
  login: { args: ['auth', 'login', '--claudeai'], code: 'collect', rejected: 'Invalid code' },
60
72
  queues: false,
@@ -70,7 +82,10 @@ export const CLIS = {
70
82
  minimum: '1.0.46',
71
83
  install: 'curl -fsSL https://x.ai/cli/install.sh | bash',
72
84
  adapter: null,
73
- args: ['agent', '--no-leader', 'stdio'],
85
+ args: ['agent', '--always-approve', '--no-leader', 'stdio'],
86
+ fullAccess: null,
87
+ sessionMeta: {},
88
+ allowHouse: nothing,
74
89
  signedIn: { initializeMeta: 'defaultAuthMethodId' },
75
90
  login: { args: ['login', '--device-auth'], code: 'show' },
76
91
  queues: true,
@@ -285,13 +285,15 @@ export class Conversations {
285
285
  conversation.opening = bridge;
286
286
  try {
287
287
  await unlessAborted(createHowWeWork(bridge), conversation.killed.signal);
288
+ await CLIS[route.kind].allowHouse();
288
289
  const adapter = await startAdapter(route.kind, cli, route.working_directory, app, (job) => this.job(conversation, job), bridge.env);
289
290
  void adapter.exited.then(() => bridge.close());
290
291
  const agent = adapter.connection.agent;
291
292
  const cwd = route.working_directory;
293
+ const _meta = CLIS[route.kind].sessionMeta;
292
294
  const opened = sessionId === null
293
- ? await agent.request('session/new', { cwd, mcpServers: [] })
294
- : { ...(await agent.request('session/resume', { sessionId, cwd, mcpServers: [] })), sessionId };
295
+ ? await agent.request('session/new', { cwd, mcpServers: [], _meta })
296
+ : { ...(await agent.request('session/resume', { sessionId, cwd, mcpServers: [], _meta })), sessionId };
295
297
  const running = {
296
298
  adapter,
297
299
  bridge,
@@ -321,6 +323,7 @@ export class Conversations {
321
323
  async launchSettings(running, route, offered) {
322
324
  let options = offered;
323
325
  const settings = [
326
+ ['mode', route.mode ?? CLIS[route.kind].fullAccess],
324
327
  ['model', route.model],
325
328
  ['thought_level', route.effort],
326
329
  ];
package/dist/copies.js CHANGED
@@ -41,11 +41,11 @@ function sidecar(path) {
41
41
  segments.splice(-1, 0, PROVENANCE);
42
42
  return segments.join('/');
43
43
  }
44
- function rootOf(copy) {
45
- return copy.private ? '/private' : `/rooms/${copy.room_handle}`;
44
+ function rootOf(handle) {
45
+ return `/rooms/${handle}`;
46
46
  }
47
47
  function relative(path) {
48
- return path.replace(/^\/private\//, '').replace(/^\/rooms\/[^/]+\//, '');
48
+ return path.replace(/^\/rooms\/[^/]+\//, '');
49
49
  }
50
50
  function declaredWritable(path, copy) {
51
51
  const deepest = (scopes) => Math.max(-1, ...scopes.filter((scope) => covers(path, scope)).map((scope) => scope.length));
@@ -177,7 +177,7 @@ export class LocalCopies {
177
177
  async load() {
178
178
  const home = join(kitHome(), 'local-copies');
179
179
  const names = (await readdir(join(home, 'rooms')).catch(() => [])).filter((name) => name.endsWith('.json'));
180
- for (const path of [...names.map((name) => join(home, 'rooms', name)), join(home, 'private.json')]) {
180
+ for (const path of names.map((name) => join(home, 'rooms', name))) {
181
181
  const text = await readFile(path, 'utf8').catch(() => null);
182
182
  if (text === null)
183
183
  continue;
@@ -189,7 +189,7 @@ export class LocalCopies {
189
189
  await this.selecting;
190
190
  return [...this.copies.values()]
191
191
  .filter((copy) => copy.active)
192
- .map((copy) => `${rootOf(copy)}: ${copy.repository}`)
192
+ .map((copy) => `${rootOf(copy.room_handle)}: ${copy.repository}`)
193
193
  .sort();
194
194
  }
195
195
  select() {
@@ -199,12 +199,7 @@ export class LocalCopies {
199
199
  }
200
200
  async reselect() {
201
201
  const { local_copy: chosen } = await this.house.post('/kit/local-copy/selection', {});
202
- const selected = [
203
- ...(chosen?.rooms ?? [])
204
- .filter((room) => room.room_handle !== null)
205
- .map((room) => ({ key: `rooms/${room.room_ref}`, private: false, handle: room.room_handle })),
206
- ...(chosen?.private === true ? [{ key: 'private', private: true, handle: null }] : []),
207
- ];
202
+ const selected = (chosen?.rooms ?? []).flatMap((room) => room.room_handle === null ? [] : [{ key: `rooms/${room.room_ref}`, handle: room.room_handle }]);
208
203
  const keys = new Set(selected.map((scope) => scope.key));
209
204
  const work = [];
210
205
  for (const key of this.copies.keys()) {
@@ -288,7 +283,7 @@ export class LocalCopies {
288
283
  }).catch(logged);
289
284
  }
290
285
  async save(copy) {
291
- const path = join(kitHome(), 'local-copies', copy.private ? 'private.json' : `${copy.key}.json`);
286
+ const path = join(kitHome(), 'local-copies', `${copy.key}.json`);
292
287
  await mkdir(dirname(path), { recursive: true, mode: 0o700 });
293
288
  const temporary = `${path}.${process.pid}`;
294
289
  await writeFile(temporary, JSON.stringify(copy), { mode: 0o600 });
@@ -296,8 +291,8 @@ export class LocalCopies {
296
291
  this.copies.set(copy.key, copy);
297
292
  return copy;
298
293
  }
299
- async read(selected) {
300
- const prefixes = [rootOf(selected)];
294
+ async read(handle) {
295
+ const prefixes = [rootOf(handle)];
301
296
  const discovery = await this.house.post('/kit/door/discover', { prefixes });
302
297
  let bundle = await this.house.post('/kit/door/bootstrap', { prefixes });
303
298
  if ('transfer' in bundle)
@@ -344,13 +339,13 @@ export class LocalCopies {
344
339
  return;
345
340
  }
346
341
  const discovery = await this.house.post('/kit/door/discover', {
347
- prefixes: [rootOf(copy)],
342
+ prefixes: [rootOf(copy.room_handle)],
348
343
  });
349
344
  const authority = discovery.authorities.find((entry) => entry.room_ref === copy.room_ref);
350
345
  if (authority === undefined)
351
346
  return;
352
347
  if (authority.managed_replication !== 'admitted') {
353
- logged(`operation_denied: ${rootOf(copy)} is not synchronized to this Environment`);
348
+ logged(`operation_denied: ${rootOf(copy.room_handle)} is not synchronized to this Environment`);
354
349
  return;
355
350
  }
356
351
  if (JSON.stringify([authority.operations.write, authority.protected_paths]) !==
@@ -361,12 +356,12 @@ export class LocalCopies {
361
356
  await this.save(await this.caughtUp(copy));
362
357
  }
363
358
  async materialize(scope) {
364
- const read = await this.read({ private: scope.private, room_handle: scope.handle });
359
+ const read = await this.read(scope.handle);
365
360
  if (read === null) {
366
- logged(`House serves nothing of ${rootOf({ private: scope.private, room_handle: scope.handle })} to copy`);
361
+ logged(`House serves nothing of ${rootOf(scope.handle)} to copy`);
367
362
  return;
368
363
  }
369
- const repository = scope.private ? join(localCopies(), 'private') : join(localCopies(), 'rooms', read.anchor);
364
+ const repository = join(localCopies(), 'rooms', read.anchor);
370
365
  if (await exists(repository)) {
371
366
  logged(`${repository} already exists and House Kit leaves it as it is`);
372
367
  return;
@@ -378,7 +373,7 @@ export class LocalCopies {
378
373
  try {
379
374
  await git(staging, ['init', '-q', '-b', BRANCH]);
380
375
  house = await importCommits(staging, [
381
- { message: `House ${rootOf({ private: scope.private, room_handle: scope.handle })}`, from: null, files: read.writable },
376
+ { message: `House ${rootOf(scope.handle)}`, from: null, files: read.writable },
382
377
  ]);
383
378
  await git(staging, ['update-ref', `refs/heads/${BRANCH}`, house]);
384
379
  await git(staging, ['reset', '-q', '--hard']);
@@ -392,7 +387,6 @@ export class LocalCopies {
392
387
  }
393
388
  await this.save({
394
389
  key: scope.key,
395
- private: scope.private,
396
390
  room_ref: read.anchor,
397
391
  room_handle: scope.handle,
398
392
  repository,
@@ -408,11 +402,11 @@ export class LocalCopies {
408
402
  });
409
403
  }
410
404
  async received(copy) {
411
- const read = await this.read(copy);
405
+ const read = await this.read(copy.room_handle);
412
406
  if (read === null)
413
407
  return copy;
414
408
  const house = await importCommits(copy.repository, [
415
- { message: `House ${rootOf(copy)} at position ${read.position}`, from: copy.house, replaces: true, files: read.writable },
409
+ { message: `House ${rootOf(copy.room_handle)} at position ${read.position}`, from: copy.house, replaces: true, files: read.writable },
416
410
  ]);
417
411
  const removed = copy.read_only.filter((path) => !read.readOnly.has(path));
418
412
  const readOnly = await readOnlyPlaced(copy.repository, copy.read_only, read.readOnly, removed);
@@ -435,7 +429,7 @@ export class LocalCopies {
435
429
  let answer;
436
430
  try {
437
431
  answer = await this.house.post('/kit/door/enumerate', {
438
- prefixes: [rootOf(copy)],
432
+ prefixes: [rootOf(copy.room_handle)],
439
433
  positions: [{ authority: copy.room_ref, position: copy.position, log_epoch: copy.log_epoch }],
440
434
  });
441
435
  }
@@ -485,7 +479,7 @@ export class LocalCopies {
485
479
  let { house, manifests } = copy;
486
480
  if (files.size > 0) {
487
481
  house = await importCommits(copy.repository, [
488
- { message: `House ${rootOf(copy)} at position ${position}`, from: copy.house, files },
482
+ { message: `House ${rootOf(copy.room_handle)} at position ${position}`, from: copy.house, files },
489
483
  ]);
490
484
  manifests = { ...manifests, [house]: { parent: copy.house, files: revisions } };
491
485
  }
@@ -516,7 +510,7 @@ export class LocalCopies {
516
510
  copy = await this.save(without(copy));
517
511
  }
518
512
  if (!copy.active) {
519
- return { refused: true, text: `${rootOf(copy)} is no longer synced to this Environment, so House takes no push from it` };
513
+ return { refused: true, text: `${rootOf(copy.room_handle)} is no longer synced to this Environment, so House takes no push from it` };
520
514
  }
521
515
  const listed = (await git(copy.repository, ['rev-list', '--topo-order', commit])).split('\n');
522
516
  const base = listed.find((ancestor) => ancestor in copy.manifests);
@@ -550,7 +544,7 @@ export class LocalCopies {
550
544
  return this.settle(submitted, caller);
551
545
  }
552
546
  async derived(copy, base, commit) {
553
- const root = rootOf(copy);
547
+ const root = rootOf(copy.room_handle);
554
548
  const before = await tree(copy.repository, base);
555
549
  const after = await tree(copy.repository, commit);
556
550
  const moved = movedPaths(copy.moves, before, after);
@@ -632,7 +626,7 @@ export class LocalCopies {
632
626
  const push = copy.push;
633
627
  const current = await this.save(await this.caughtUp(copy));
634
628
  const house = await tree(copy.repository, current.house);
635
- const root = rootOf(current);
629
+ const root = rootOf(current.room_handle);
636
630
  if (!(await this.landed(copy.repository, push.changes, house, await tree(copy.repository, push.commit)))) {
637
631
  await this.save(without(current));
638
632
  return {
@@ -688,7 +682,7 @@ export class LocalCopies {
688
682
  written = [
689
683
  ...written,
690
684
  {
691
- path: `${rootOf(copy)}/${path}`,
685
+ path: `${rootOf(copy.room_handle)}/${path}`,
692
686
  revision: entry === undefined ? null : (revisionAt(copy, copy.house, path) ?? null),
693
687
  content: entry === undefined ? null : await blobText(copy.repository, entry, path),
694
688
  },
@@ -708,7 +702,7 @@ export class LocalCopies {
708
702
  }
709
703
  const edits = new Map([...files].filter(([path, content]) => (content === null ? selected.has(path) : selected.get(path) !== blobId(content))));
710
704
  const received = [...files.keys()].filter((path) => revisionAt(copy, copy.house, path) === revisionAt(copy, push.house, path));
711
- const accepted = `House ${rootOf(copy)} with ${push.commit} accepted`;
705
+ const accepted = `House ${rootOf(copy.room_handle)} with ${push.commit} accepted`;
712
706
  const house = await importCommits(copy.repository, [
713
707
  ...(edits.size === 0 ? [] : [{ message: accepted, from: push.commit, files: edits }]),
714
708
  {
@@ -1,7 +1,7 @@
1
1
  import { HOW_WE_WORK } from './skills.js';
2
2
  const HOUSE_LINE = 'Work with House through the `house` CLI: run `house --help`.';
3
3
  const FILE_LINE = 'To give the User a file or a page, upload it with `house upload_attachment` and link it; never start a server.';
4
- const READ_LINE = 'Before working in a Room, read `/private/rooms/<handle>/AGENTS.md`.';
4
+ const READ_LINE = 'Before working in a Room, read `/rooms/private/rooms/<handle>/AGENTS.md`.';
5
5
  const COPIES_LINE = 'House Local copies; commit, then `house push`:';
6
6
  const UNREADABLE = /^(?:\S+: )?(?:path_not_found|room_not_found|operation_denied)\b/;
7
7
  const FAILED = /^exit: [1-9]\d*$/;
@@ -1,4 +1,4 @@
1
- import { retryDelay } from './api.js';
1
+ import { HouseRefusal, retryDelay } from './api.js';
2
2
  export async function holdSecretInput(house, subject, steps, waiting) {
3
3
  for (let failures = 0; waiting();) {
4
4
  try {
@@ -10,6 +10,8 @@ export async function holdSecretInput(house, subject, steps, waiting) {
10
10
  failures = 0;
11
11
  }
12
12
  catch (error) {
13
+ if (error instanceof HouseRefusal && error.status < 500)
14
+ return null;
13
15
  process.stderr.write(`kit: ${error instanceof Error ? error.message : String(error)}\n`);
14
16
  await new Promise((resolve) => setTimeout(resolve, retryDelay(failures++)));
15
17
  }
package/dist/sign-in.js CHANGED
@@ -31,8 +31,9 @@ export class SignIns {
31
31
  this.running.add(input.input_id);
32
32
  this.changed();
33
33
  this.login(input)
34
- .then(() => this.agents.reread(input.cli))
34
+ .then(() => this.agents.recheck(input.cli))
35
35
  .then(() => this.house.deliver(`/kit/inputs/${input.input_id}/ack`, {}))
36
+ .then(() => this.agents.reread(input.cli))
36
37
  .catch(logged)
37
38
  .finally(() => {
38
39
  this.running.delete(input.input_id);
package/dist/skills.js CHANGED
@@ -6,7 +6,7 @@ import { fileURLToPath } from 'node:url';
6
6
  import { KIT_VERSION } from './clis.js';
7
7
  import { kitHome, readConfiguration, readHome, writeHome } from './home.js';
8
8
  import { refusalOf } from './refusals.js';
9
- export const HOW_WE_WORK = '/private/how-we-work.md';
9
+ export const HOW_WE_WORK = '/rooms/private/how-we-work.md';
10
10
  const SKILL_SET = fileURLToPath(new URL('../skills/', import.meta.url));
11
11
  const HOW_WE_WORK_TEXT = readFileSync(new URL('../how-we-work.md', import.meta.url), 'utf8');
12
12
  const RECORD = 'skill-set.json';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/kit",
3
- "version": "0.2.1-cd9cbd8b6428c",
3
+ "version": "0.2.1-ce145e9aadbf6",
4
4
  "description": "House Kit connects an Environment to agents.house.",
5
5
  "license": "MIT",
6
6
  "repository": {