@agentshouse/kit 0.2.1-alpha.11 → 0.2.1-alpha.12

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
@@ -1,21 +1,64 @@
1
1
  import { client } from '@agentclientprotocol/sdk';
2
2
  import { readFile } from 'node:fs/promises';
3
- import { startAdapter } from './acp.js';
3
+ import { killTree, startAdapter } from './acp.js';
4
4
  import { CLIS, KIT_VERSION, cliCommand, install, run } from './clis.js';
5
5
  import { kitHome } from './home.js';
6
- async function signedIn(kind) {
7
- const probe = CLIS[kind].signedIn;
8
- if ('command' in probe) {
9
- return (await run(cliCommand(kind), probe.command, 30_000)).status === 0;
6
+ const SIGNED_OUT = { signed_in: false, models: [] };
7
+ function select(options, category) {
8
+ const option = options.find((candidate) => candidate.category === category);
9
+ return option?.type === 'select' ? option : undefined;
10
+ }
11
+ function values(options) {
12
+ return options.flatMap((entry) => ('group' in entry ? entry.options : [entry])).map((entry) => entry.value);
13
+ }
14
+ function causeOf(error) {
15
+ return error instanceof Error ? error.message : String(error);
16
+ }
17
+ async function models(kind, adapter, known) {
18
+ const agent = adapter.connection.agent;
19
+ const opened = await agent.request('session/new', { cwd: kitHome(), mcpServers: [] });
20
+ let options = opened.configOptions ?? [];
21
+ const model = select(options, 'model');
22
+ if (model === undefined)
23
+ return [];
24
+ const offered = [];
25
+ for (const value of values(model.options)) {
26
+ if (select(options, 'model')?.currentValue !== value) {
27
+ try {
28
+ options = (await agent.request('session/set_config_option', { sessionId: opened.sessionId, configId: model.id, value })).configOptions;
29
+ }
30
+ catch (error) {
31
+ process.stderr.write(`kit: ${kind} refused its model ${value}: ${causeOf(error)}\n`);
32
+ offered.push({ model: value, efforts: known.find((entry) => entry.model === value)?.efforts ?? [] });
33
+ continue;
34
+ }
35
+ }
36
+ const effort = select(options, 'thought_level');
37
+ offered.push({ model: value, efforts: effort === undefined ? [] : values(effort.options) });
10
38
  }
39
+ return offered;
40
+ }
41
+ async function offer(kind, known) {
42
+ const probe = CLIS[kind].signedIn;
43
+ if ('command' in probe && (await run(cliCommand(kind), probe.command, 30_000)).status !== 0)
44
+ return SIGNED_OUT;
45
+ let adapter;
11
46
  try {
12
- const adapter = await startAdapter(kind, kitHome(), client({ name: '@agentshouse/kit' }));
13
- adapter.child.kill('SIGKILL');
14
- const method = adapter.initialized._meta?.[probe.initializeMeta];
15
- return typeof method === 'string' && method.length > 0;
47
+ adapter = await startAdapter(kind, kitHome(), client({ name: '@agentshouse/kit' }));
48
+ if ('initializeMeta' in probe) {
49
+ const method = adapter.initialized._meta?.[probe.initializeMeta];
50
+ if (typeof method !== 'string' || method.length === 0)
51
+ return SIGNED_OUT;
52
+ }
53
+ return { signed_in: true, models: await models(kind, adapter, known.models) };
54
+ }
55
+ catch (error) {
56
+ process.stderr.write(`kit: ${kind} did not offer its models: ${causeOf(error)}\n`);
57
+ return adapter === undefined && 'initializeMeta' in probe ? known : { signed_in: true, models: known.models };
16
58
  }
17
- catch {
18
- return false;
59
+ finally {
60
+ if (adapter !== undefined)
61
+ killTree(adapter.child);
19
62
  }
20
63
  }
21
64
  async function sshHostKey() {
@@ -31,9 +74,12 @@ export class Agents {
31
74
  house;
32
75
  reading = Promise.resolve();
33
76
  installing = Promise.resolve();
34
- releases = new Map();
77
+ installs = new Map();
78
+ offers = new Map();
35
79
  reporting = null;
36
80
  again = false;
81
+ sending = Promise.resolve();
82
+ sent = null;
37
83
  constructor(house) {
38
84
  this.house = house;
39
85
  }
@@ -62,24 +108,36 @@ export class Agents {
62
108
  this.again = true;
63
109
  return Promise.all([installing, this.reporting]).then(() => undefined);
64
110
  }
65
- async report() {
111
+ report() {
112
+ const sending = this.sending.catch(() => undefined).then(() => this.send());
113
+ this.sending = sending;
114
+ return sending;
115
+ }
116
+ async send() {
66
117
  const agents = [];
67
- for (const [kind, release] of this.releases) {
68
- agents.push({ kind, release, signed_in: release !== null && (await signedIn(kind)) });
118
+ for (const [kind, installed] of this.installs) {
119
+ const offered = installed.release === null ? SIGNED_OUT : await offer(kind, this.offers.get(kind) ?? SIGNED_OUT);
120
+ this.offers.set(kind, offered);
121
+ agents.push({ kind, ...installed, ...offered });
69
122
  }
70
123
  const hostKey = await sshHostKey();
71
- await this.house.deliver('/kit/agents/report', {
124
+ const body = {
72
125
  os: await operatingSystem(),
73
126
  kit_version: KIT_VERSION,
74
127
  agents,
75
128
  ...(hostKey === null ? {} : { ssh_host_key: hostKey }),
76
- });
129
+ };
130
+ const state = JSON.stringify(body);
131
+ if (state === this.sent)
132
+ return;
133
+ await this.house.deliver('/kit/agents/report', body);
134
+ this.sent = state;
77
135
  }
78
136
  async install(kinds) {
79
- const releases = new Map();
137
+ const installs = new Map();
80
138
  for (const kind of kinds)
81
- releases.set(kind, await install(kind));
82
- this.releases = releases;
139
+ installs.set(kind, await install(kind));
140
+ this.installs = installs;
83
141
  }
84
142
  async reports() {
85
143
  try {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "version": "0.2.1-alpha.11",
3
+ "version": "0.2.1-alpha.12",
4
4
  "hosts": {
5
5
  "linux": {
6
- "command": "bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.11/connect-linux.sh)",
6
+ "command": "bash <(curl -fsSL https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.12/connect-linux.sh)",
7
7
  "asset": {
8
8
  "name": "connect-linux.sh",
9
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.11/connect-linux.sh"
9
+ "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.12/connect-linux.sh"
10
10
  },
11
11
  "workspace": {
12
12
  "argument": "--workspace",
@@ -14,10 +14,10 @@
14
14
  }
15
15
  },
16
16
  "windows": {
17
- "command": "& ([scriptblock]::Create((irm https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.11/connect-windows.ps1)))",
17
+ "command": "& ([scriptblock]::Create((irm https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.12/connect-windows.ps1)))",
18
18
  "asset": {
19
19
  "name": "connect-windows.ps1",
20
- "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.11/connect-windows.ps1"
20
+ "url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-alpha.12/connect-windows.ps1"
21
21
  },
22
22
  "workspace": {
23
23
  "argument": "--workspace",
package/dist/clis.js CHANGED
@@ -115,11 +115,12 @@ export function run(command, args, timeoutMs) {
115
115
  export async function install(kind) {
116
116
  const release = pinned(kind);
117
117
  if ((await installedRelease(kind)) === release)
118
- return release;
118
+ return { release, failure: null };
119
119
  const ran = await run('npm', ['install', '--prefix', prefix(kind), '--no-save', '--no-audit', '--no-fund', `${CLIS[kind].package}@${release}`], 15 * 60_000);
120
120
  if (ran.status !== 0) {
121
- process.stderr.write(`kit: ${kind} did not install: ${ran.output.trim()}\n`);
122
- return null;
121
+ const failure = ran.output.trim() || `npm exited with ${ran.status ?? 'a signal'}`;
122
+ process.stderr.write(`kit: ${kind} did not install: ${failure}\n`);
123
+ return { release: null, failure };
123
124
  }
124
- return installedRelease(kind);
125
+ return { release: await installedRelease(kind), failure: null };
125
126
  }
package/dist/resident.js CHANGED
@@ -14,6 +14,7 @@ import { SignIns } from './sign-in.js';
14
14
  import { placeSkillSet } from './skills.js';
15
15
  import { holdStream } from './stream.js';
16
16
  import { Updates } from './update.js';
17
+ const AGENTS_REREAD_MS = 60 * 60_000;
17
18
  function report(error) {
18
19
  process.stderr.write(`kit: ${error instanceof Error ? error.message : String(error)}\n`);
19
20
  }
@@ -93,6 +94,7 @@ export async function resident() {
93
94
  await house.deliver('/kit/restarted', {}).catch(report);
94
95
  await updates.resumed().catch(report);
95
96
  logged(agents.refresh());
97
+ setInterval(() => logged(agents.refresh()), AGENTS_REREAD_MS);
96
98
  stream = holdStream({
97
99
  opened: () => {
98
100
  conversations.opened();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/kit",
3
- "version": "0.2.1-alpha.11",
3
+ "version": "0.2.1-alpha.12",
4
4
  "description": "House Kit connects an Environment to agents.house.",
5
5
  "license": "MIT",
6
6
  "repository": {