@agentshouse/kit 0.2.1-ca0e1517cce79 → 0.2.1-ca1f38641026d
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/README.md +6 -6
- package/dist/acp.js +57 -6
- package/dist/agents.js +12 -21
- package/dist/authority-main.js +2 -2
- package/dist/building.js +46 -0
- package/dist/calls.js +11 -3
- package/dist/clis-main.js +2 -2
- package/dist/clis.js +37 -13
- package/dist/connection.js +19 -29
- package/dist/conversations.js +140 -40
- package/dist/end.js +8 -2
- package/dist/events.js +29 -8
- package/dist/git.js +2 -2
- package/dist/house-cli.js +3 -4
- package/dist/instructions.js +4 -4
- package/dist/kit-cli.js +2 -2
- package/dist/login.js +3 -1
- package/dist/mcp.js +2 -0
- package/dist/relay.js +21 -0
- package/dist/resident.js +17 -12
- package/dist/scripts.js +255 -0
- package/dist/sign-in.js +3 -2
- package/dist/silence.js +28 -0
- package/dist/skills.js +38 -12
- package/dist/transcription.js +32 -23
- package/dist/update.js +51 -8
- package/package.json +11 -12
- package/dist/bootstrap.json +0 -24
- package/dist/web-wizard.js +0 -100
package/dist/update.js
CHANGED
|
@@ -6,6 +6,13 @@ import { join } from 'node:path';
|
|
|
6
6
|
import { run } from './clis.js';
|
|
7
7
|
import { kitHome, workspaceRoot } from './home.js';
|
|
8
8
|
import { service, throughSudo } from './placement.js';
|
|
9
|
+
import { relayed } from './relay.js';
|
|
10
|
+
const BOOTSTRAP_BYTES = 1_000_000;
|
|
11
|
+
// A bootstrap is at most a million bytes, so two minutes carry it over ten kilobytes a second and no stalled host holds the update queue.
|
|
12
|
+
const BOOTSTRAP_MS = 120_000;
|
|
13
|
+
// A bootstrap's downloads and CLI updates take minutes, so one still running after an hour has hung and is ended before it keeps the Kit offline.
|
|
14
|
+
const RERUN_MS = 60 * 60_000;
|
|
15
|
+
const TIMED_OUT = '124';
|
|
9
16
|
function directory() {
|
|
10
17
|
return join(kitHome(), 'update');
|
|
11
18
|
}
|
|
@@ -31,7 +38,7 @@ function placement() {
|
|
|
31
38
|
return service() === 'user' ? ['--workspace', workspaceRoot()] : ['--linux'];
|
|
32
39
|
}
|
|
33
40
|
function record() {
|
|
34
|
-
return `outcome=$1; shift; bash "$0" "$@"; printf %s "$?" > "$outcome"; ${[...elevated(), 'systemctl', ...manager(), 'start', 'house-kit.service'].join(' ')}`;
|
|
41
|
+
return `outcome=$1; shift; timeout ${RERUN_MS / 1000} bash "$0" "$@"; printf %s "$?" > "$outcome"; ${[...elevated(), 'systemctl', ...manager(), 'start', 'house-kit.service'].join(' ')}`;
|
|
35
42
|
}
|
|
36
43
|
async function pendingCall() {
|
|
37
44
|
try {
|
|
@@ -45,6 +52,8 @@ async function recorded() {
|
|
|
45
52
|
const status = await readFile(outcome(), 'utf8').catch(() => null);
|
|
46
53
|
if (status === null)
|
|
47
54
|
return null;
|
|
55
|
+
if (status.trim() === TIMED_OUT)
|
|
56
|
+
return { refused: `the Kit bootstrap did not finish within ${RERUN_MS / 1000} seconds` };
|
|
48
57
|
return status.trim() === '0' ? {} : { refused: `the Kit bootstrap exited with ${status.trim()}` };
|
|
49
58
|
}
|
|
50
59
|
async function forget(callId) {
|
|
@@ -66,6 +75,17 @@ async function finished(callId) {
|
|
|
66
75
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
67
76
|
}
|
|
68
77
|
}
|
|
78
|
+
async function bounded(body, most) {
|
|
79
|
+
const chunks = [];
|
|
80
|
+
let bytes = 0;
|
|
81
|
+
for await (const chunk of body ?? []) {
|
|
82
|
+
bytes += chunk.length;
|
|
83
|
+
if (bytes > most)
|
|
84
|
+
return null;
|
|
85
|
+
chunks.push(chunk);
|
|
86
|
+
}
|
|
87
|
+
return Buffer.concat(chunks, bytes);
|
|
88
|
+
}
|
|
69
89
|
function rerun(script, callId, flags) {
|
|
70
90
|
return new Promise((resolve) => {
|
|
71
91
|
const [command, ...args] = [
|
|
@@ -94,9 +114,12 @@ function rerun(script, callId, flags) {
|
|
|
94
114
|
}
|
|
95
115
|
export class KitUpdate {
|
|
96
116
|
calls;
|
|
117
|
+
changed;
|
|
118
|
+
waiting = new Map();
|
|
97
119
|
queue = Promise.resolve();
|
|
98
|
-
constructor(calls) {
|
|
120
|
+
constructor(calls, changed) {
|
|
99
121
|
this.calls = calls;
|
|
122
|
+
this.changed = changed;
|
|
100
123
|
}
|
|
101
124
|
async resumed() {
|
|
102
125
|
const callId = await pendingCall();
|
|
@@ -104,8 +127,17 @@ export class KitUpdate {
|
|
|
104
127
|
return;
|
|
105
128
|
await this.enqueue(callId, () => finished(callId));
|
|
106
129
|
}
|
|
107
|
-
|
|
108
|
-
|
|
130
|
+
hold(call) {
|
|
131
|
+
this.waiting.set(call.input_id, call);
|
|
132
|
+
this.changed();
|
|
133
|
+
}
|
|
134
|
+
held() {
|
|
135
|
+
return this.waiting.size > 0;
|
|
136
|
+
}
|
|
137
|
+
apply(resume) {
|
|
138
|
+
const held = [...this.waiting.values()];
|
|
139
|
+
this.waiting.clear();
|
|
140
|
+
void Promise.all(held.map((call) => this.enqueue(call.input_id, () => this.carry(call)))).then(resume);
|
|
109
141
|
}
|
|
110
142
|
enqueue(callId, work) {
|
|
111
143
|
const before = this.queue;
|
|
@@ -119,10 +151,21 @@ export class KitUpdate {
|
|
|
119
151
|
async carry(call) {
|
|
120
152
|
if ((await pendingCall()) === call.input_id)
|
|
121
153
|
return finished(call.input_id);
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
154
|
+
const deadline = AbortSignal.timeout(BOOTSTRAP_MS);
|
|
155
|
+
let script;
|
|
156
|
+
try {
|
|
157
|
+
const answer = await fetch(relayed(call.bootstrap), { signal: deadline });
|
|
158
|
+
if (!answer.ok)
|
|
159
|
+
return { refused: `the Kit bootstrap could not be downloaded: ${answer.status}` };
|
|
160
|
+
script = await bounded(answer.body, BOOTSTRAP_BYTES);
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
if (!deadline.aborted)
|
|
164
|
+
throw error;
|
|
165
|
+
return { refused: `the Kit bootstrap did not arrive within ${BOOTSTRAP_MS / 1000} seconds` };
|
|
166
|
+
}
|
|
167
|
+
if (script === null)
|
|
168
|
+
return { refused: `the Kit bootstrap is larger than ${BOOTSTRAP_BYTES} bytes` };
|
|
126
169
|
if (createHash('sha256').update(script).digest('hex') !== call.sha256) {
|
|
127
170
|
return { refused: 'the Kit bootstrap does not match its sha256' };
|
|
128
171
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentshouse/kit",
|
|
3
|
-
"version": "0.2.1-
|
|
3
|
+
"version": "0.2.1-ca1f38641026d",
|
|
4
4
|
"description": "Kit connects an Environment to agents.house.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -12,28 +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
16
|
"dist"
|
|
20
17
|
],
|
|
21
18
|
"scripts": {
|
|
22
|
-
"
|
|
19
|
+
"bootstrap-manifest": "node scripts/bootstrap-manifest.mjs",
|
|
20
|
+
"build": "tsc -p tsconfig.build.json",
|
|
23
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",
|
|
24
22
|
"follow-skills": "node scripts/follow-skills.mjs",
|
|
23
|
+
"release-files": "node scripts/release-files.mjs",
|
|
25
24
|
"test": "tsc -p tsconfig.json && vitest run"
|
|
26
25
|
},
|
|
27
26
|
"dependencies": {
|
|
28
|
-
"@agentclientprotocol/sdk": "
|
|
29
|
-
"@agentshouse/mdmodel": "0.1.0-
|
|
30
|
-
"@agentshouse/skills": "0.1.0-
|
|
27
|
+
"@agentclientprotocol/sdk": "2.0.1",
|
|
28
|
+
"@agentshouse/mdmodel": "0.1.0-c4f4d37bc9d6a",
|
|
29
|
+
"@agentshouse/skills": "0.1.0-c1884c2b56810",
|
|
31
30
|
"@lydell/node-pty": "1.2.0-beta.15",
|
|
32
31
|
"yaml": "2.9.1"
|
|
33
32
|
},
|
|
34
33
|
"peerDependencies": {
|
|
35
|
-
"@agentclientprotocol/claude-agent-acp": "0.
|
|
36
|
-
"@agentclientprotocol/codex-acp": "2.
|
|
34
|
+
"@agentclientprotocol/claude-agent-acp": "0.94.0",
|
|
35
|
+
"@agentclientprotocol/codex-acp": "2.2.2"
|
|
37
36
|
},
|
|
38
37
|
"peerDependenciesMeta": {
|
|
39
38
|
"@agentclientprotocol/claude-agent-acp": {
|
|
@@ -44,10 +43,10 @@
|
|
|
44
43
|
}
|
|
45
44
|
},
|
|
46
45
|
"devDependencies": {
|
|
47
|
-
"@types/node": "24.
|
|
46
|
+
"@types/node": "24.19.2",
|
|
48
47
|
"@types/ws": "8.18.2",
|
|
49
48
|
"typescript": "7.0.2",
|
|
50
|
-
"vitest": "5.0.
|
|
49
|
+
"vitest": "5.0.5",
|
|
51
50
|
"ws": "8.22.0"
|
|
52
51
|
},
|
|
53
52
|
"packageManager": "npm@11.19.1",
|
package/dist/bootstrap.json
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"schemaVersion": 2,
|
|
3
|
-
"version": "0.2.1-ca0e1517cce79",
|
|
4
|
-
"hosts": {
|
|
5
|
-
"macos": {
|
|
6
|
-
"asset": {
|
|
7
|
-
"name": "connect-linux.sh",
|
|
8
|
-
"url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-ca0e1517cce79/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-ca0e1517cce79/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-ca0e1517cce79/connect-windows.ps1"
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
package/dist/web-wizard.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { loginPath, onLoginPath, withoutProxy } from './clis.js';
|
|
2
|
-
import { killTree } from './scope.js';
|
|
3
|
-
const TERMINAL = 'xterm-256color';
|
|
4
|
-
const SIGNALLED = 128;
|
|
5
|
-
const NO_BASH = "bash is not on the login shell's PATH";
|
|
6
|
-
const LOST = { refused: 'the Kit lost its connection to House' };
|
|
7
|
-
function causeOf(error) {
|
|
8
|
-
return error instanceof Error ? error.message : String(error);
|
|
9
|
-
}
|
|
10
|
-
function failed(cause) {
|
|
11
|
-
process.stderr.write(`kit: a Web Wizard could not start: ${cause}\n`);
|
|
12
|
-
return { refused: `the script could not start: ${cause}` };
|
|
13
|
-
}
|
|
14
|
-
export class WebWizards {
|
|
15
|
-
calls;
|
|
16
|
-
send;
|
|
17
|
-
runs = new Map();
|
|
18
|
-
constructor(calls, send) {
|
|
19
|
-
this.calls = calls;
|
|
20
|
-
this.send = send;
|
|
21
|
-
}
|
|
22
|
-
start(call) {
|
|
23
|
-
void this.calls.carry(call.input_id, () => this.run(call));
|
|
24
|
-
}
|
|
25
|
-
notified(notification) {
|
|
26
|
-
const run = this.runs.get(String(notification.wizard));
|
|
27
|
-
if (run === undefined)
|
|
28
|
-
return;
|
|
29
|
-
if (notification.type === 'wizard_input')
|
|
30
|
-
this.typed(run, String(notification.data));
|
|
31
|
-
if (notification.type === 'wizard_size')
|
|
32
|
-
this.resized(run, { cols: Number(notification.cols), rows: Number(notification.rows) });
|
|
33
|
-
if (notification.type === 'wizard_end')
|
|
34
|
-
this.end(run, {});
|
|
35
|
-
}
|
|
36
|
-
disconnected() {
|
|
37
|
-
for (const run of this.runs.values())
|
|
38
|
-
this.end(run, LOST);
|
|
39
|
-
}
|
|
40
|
-
async run(call) {
|
|
41
|
-
const run = { terminal: null, size: null, typed: [], ended: null, sized: Promise.withResolvers() };
|
|
42
|
-
this.runs.set(call.input_id, run);
|
|
43
|
-
try {
|
|
44
|
-
return { result: await this.ran(call.input_id, call.script, run) };
|
|
45
|
-
}
|
|
46
|
-
finally {
|
|
47
|
-
this.runs.delete(call.input_id);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
async ran(wizard, script, run) {
|
|
51
|
-
let terminal;
|
|
52
|
-
try {
|
|
53
|
-
const { spawn } = await import('@lydell/node-pty');
|
|
54
|
-
const shell = await onLoginPath('bash');
|
|
55
|
-
if (shell === null)
|
|
56
|
-
return failed(NO_BASH);
|
|
57
|
-
const path = await loginPath();
|
|
58
|
-
await run.sized.promise;
|
|
59
|
-
if (run.ended !== null)
|
|
60
|
-
return run.ended;
|
|
61
|
-
terminal = spawn(shell, ['-c', script], {
|
|
62
|
-
name: TERMINAL,
|
|
63
|
-
...run.size,
|
|
64
|
-
cwd: process.cwd(),
|
|
65
|
-
env: { ...withoutProxy(), PATH: path },
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
catch (error) {
|
|
69
|
-
return failed(causeOf(error));
|
|
70
|
-
}
|
|
71
|
-
run.terminal = terminal;
|
|
72
|
-
terminal.onData((data) => this.send({ type: 'wizard_output', wizard, data }));
|
|
73
|
-
for (const data of run.typed.splice(0))
|
|
74
|
-
terminal.write(data);
|
|
75
|
-
const exited = await new Promise((resolve) => terminal.onExit(resolve));
|
|
76
|
-
return run.ended ?? { exit_code: exited.signal ? SIGNALLED + exited.signal : exited.exitCode };
|
|
77
|
-
}
|
|
78
|
-
typed(run, data) {
|
|
79
|
-
if (run.terminal === null)
|
|
80
|
-
run.typed.push(data);
|
|
81
|
-
else
|
|
82
|
-
run.terminal.write(data);
|
|
83
|
-
}
|
|
84
|
-
resized(run, size) {
|
|
85
|
-
run.size = size;
|
|
86
|
-
run.sized.resolve();
|
|
87
|
-
try {
|
|
88
|
-
run.terminal?.resize(size.cols, size.rows);
|
|
89
|
-
}
|
|
90
|
-
catch { }
|
|
91
|
-
}
|
|
92
|
-
end(run, result) {
|
|
93
|
-
if (run.ended !== null)
|
|
94
|
-
return;
|
|
95
|
-
run.ended = result;
|
|
96
|
-
run.sized.resolve();
|
|
97
|
-
if (run.terminal !== null)
|
|
98
|
-
killTree(run.terminal);
|
|
99
|
-
}
|
|
100
|
-
}
|