@agentshouse/kit 0.2.1-cb6679d048e60 → 0.2.1-cca9e1f43de44
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 +8 -9
- package/dist/acp.js +26 -13
- package/dist/agents.js +79 -38
- package/dist/api.js +32 -3
- package/dist/app-git.js +64 -0
- package/dist/bootstrap.json +4 -4
- package/dist/bridge.js +35 -40
- package/dist/clis.js +55 -64
- package/dist/conversations.js +282 -231
- package/dist/copies.js +29 -36
- package/dist/end.js +8 -0
- package/dist/events.js +587 -0
- package/dist/files.js +16 -1
- package/dist/house-main.js +28 -10
- package/dist/instructions.js +2 -2
- package/dist/kit-main.js +3 -0
- package/dist/login.js +4 -0
- package/dist/logout.js +3 -0
- package/dist/mcp.js +2 -1
- package/dist/parts.js +64 -0
- package/dist/refusals.js +12 -0
- package/dist/relay.js +10 -0
- package/dist/resident.js +3 -3
- package/dist/secret-input.js +4 -1
- package/dist/shell.js +3 -0
- package/dist/sign-in.js +33 -8
- package/dist/skills.js +1 -1
- package/dist/stream.js +31 -5
- package/dist/transcription.js +54 -6
- package/dist/update.js +2 -0
- package/package.json +1 -1
- package/dist/blocks.js +0 -51
package/dist/clis.js
CHANGED
|
@@ -1,34 +1,15 @@
|
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
return params.update._meta?.codex?.threadStatus?.type;
|
|
12
|
-
}
|
|
13
|
-
function asyncTask({ method, params }) {
|
|
14
|
-
const update = params?.update;
|
|
15
|
-
if (method !== 'session/update' || update?.asyncTaskId === undefined)
|
|
16
|
-
return null;
|
|
17
|
-
if (update.sessionUpdate === 'async_task_spawned')
|
|
18
|
-
return { id: update.asyncTaskId, running: true };
|
|
19
|
-
if (update.sessionUpdate === 'async_task_state_update' && !RUNNING_JOB.has(update.state ?? '')) {
|
|
20
|
-
return { id: update.asyncTaskId, running: false };
|
|
21
|
-
}
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
24
|
-
function airPhase({ _meta }) {
|
|
25
|
-
const phase = _meta?.jetbrains?.air?.phase;
|
|
26
|
-
if (phase === 'commentary')
|
|
27
|
-
return 'note';
|
|
28
|
-
if (phase === 'final_answer')
|
|
29
|
-
return 'answer';
|
|
30
|
-
return null;
|
|
7
|
+
async function allowHouseInCodex() {
|
|
8
|
+
const rules = join(process.env.CODEX_HOME || join(homedir(), '.codex'), 'rules');
|
|
9
|
+
await mkdir(rules, { recursive: true });
|
|
10
|
+
await writeFile(join(rules, 'house.rules'), 'prefix_rule(pattern = ["house"], decision = "allow")\n');
|
|
31
11
|
}
|
|
12
|
+
async function nothing() { }
|
|
32
13
|
export const CLIS = {
|
|
33
14
|
'codex-acp': {
|
|
34
15
|
bin: 'codex',
|
|
@@ -36,13 +17,12 @@ export const CLIS = {
|
|
|
36
17
|
install: 'curl -fsSL https://chatgpt.com/codex/install.sh | sh',
|
|
37
18
|
adapter: { package: '@agentclientprotocol/codex-acp', bin: 'codex-acp', executable: 'CODEX_PATH', env: {} },
|
|
38
19
|
args: [],
|
|
20
|
+
fullAccess: 'agent-full-access',
|
|
21
|
+
sessionMeta: {},
|
|
22
|
+
allowHouse: allowHouseInCodex,
|
|
39
23
|
signedIn: { command: ['login', 'status'] },
|
|
40
24
|
login: { args: ['login', '--device-auth'], code: 'show' },
|
|
41
|
-
|
|
42
|
-
turnStarted: (notice) => threadStatus(notice) === 'active',
|
|
43
|
-
turnEnded: (notice) => threadStatus(notice) === 'idle',
|
|
44
|
-
job: asyncTask,
|
|
45
|
-
phase: airPhase,
|
|
25
|
+
air: ['asyncTasks', 'nativeSubagentSessions'],
|
|
46
26
|
},
|
|
47
27
|
'claude-agent-acp': {
|
|
48
28
|
bin: 'claude',
|
|
@@ -52,45 +32,42 @@ export const CLIS = {
|
|
|
52
32
|
package: '@agentclientprotocol/claude-agent-acp',
|
|
53
33
|
bin: 'claude-agent-acp',
|
|
54
34
|
executable: 'CLAUDE_CODE_EXECUTABLE',
|
|
55
|
-
env: { CLAUDE_CODE_ENTRYPOINT: 'claude-agent-acp' },
|
|
35
|
+
env: { CLAUDE_CODE_ENTRYPOINT: 'claude-agent-acp', IS_SANDBOX: '1' },
|
|
56
36
|
},
|
|
57
37
|
args: [],
|
|
38
|
+
fullAccess: 'bypassPermissions',
|
|
39
|
+
sessionMeta: {
|
|
40
|
+
claudeCode: {
|
|
41
|
+
options: { allowedTools: ['Bash(house:*)'] },
|
|
42
|
+
emitRawSDKMessages: ['background_tasks_changed', 'session_state_changed', 'task_started', 'task_notification'].map((subtype) => ({ type: 'system', subtype })),
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
allowHouse: nothing,
|
|
58
46
|
signedIn: { command: ['auth', 'status'] },
|
|
59
47
|
login: { args: ['auth', 'login', '--claudeai'], code: 'collect', rejected: 'Invalid code' },
|
|
60
|
-
|
|
61
|
-
turnStarted: () => false,
|
|
62
|
-
turnEnded: ({ method, params }) => method === 'session/update' &&
|
|
63
|
-
params?.update?.sessionUpdate === 'usage_update' &&
|
|
64
|
-
params.update._meta?.['_claude/origin'] !== undefined,
|
|
65
|
-
job: asyncTask,
|
|
66
|
-
phase: () => null,
|
|
48
|
+
air: ['asyncTasks', 'sessionFailure'],
|
|
67
49
|
},
|
|
68
50
|
'grok-build': {
|
|
69
51
|
bin: 'grok',
|
|
70
52
|
minimum: '1.0.46',
|
|
71
53
|
install: 'curl -fsSL https://x.ai/cli/install.sh | bash',
|
|
72
54
|
adapter: null,
|
|
73
|
-
args: ['agent', '--no-leader', 'stdio'],
|
|
55
|
+
args: ['agent', '--always-approve', '--no-leader', 'stdio'],
|
|
56
|
+
fullAccess: null,
|
|
57
|
+
sessionMeta: {},
|
|
58
|
+
allowHouse: nothing,
|
|
74
59
|
signedIn: { initializeMeta: 'defaultAuthMethodId' },
|
|
75
60
|
login: { args: ['login', '--device-auth'], code: 'show' },
|
|
76
|
-
|
|
77
|
-
turnStarted: ({ method, params }) => method === '_x.ai/queue/changed' && params?.runningPromptId !== undefined,
|
|
78
|
-
turnEnded: ({ method, params }) => method === '_x.ai/session_notification' && params?.update?.sessionUpdate === 'turn_completed',
|
|
79
|
-
job: ({ method, params }) => {
|
|
80
|
-
if (method === '_x.ai/task_backgrounded')
|
|
81
|
-
return { id: params.update.task_id, running: true };
|
|
82
|
-
if (method === '_x.ai/task_completed')
|
|
83
|
-
return { id: params.update.task_snapshot.task_id, running: false };
|
|
84
|
-
return null;
|
|
85
|
-
},
|
|
86
|
-
phase: () => null,
|
|
61
|
+
air: ['asyncTasks'],
|
|
87
62
|
},
|
|
88
63
|
};
|
|
89
64
|
const KIT_PACKAGE = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
90
65
|
export const KIT_VERSION = KIT_PACKAGE.version;
|
|
91
66
|
const PROXY = /^https?_proxy$/i;
|
|
92
67
|
const VERSION = /\d+\.\d+\.\d+(?:-[0-9A-Za-z.]+)?/;
|
|
68
|
+
// An install still running after fifteen minutes is ended and reported as failed, so a hung download cannot hold its CLI's report.
|
|
93
69
|
const INSTALL_MS = 15 * 60_000;
|
|
70
|
+
// A login shell or a version read is ended after half a minute, so a profile that waits for input cannot stall the report.
|
|
94
71
|
const READ_MS = 30_000;
|
|
95
72
|
const CAUSE_CHARACTERS = 4000;
|
|
96
73
|
function prefix(kind) {
|
|
@@ -118,8 +95,22 @@ export function run(command, args, timeoutMs, detached = false, signal) {
|
|
|
118
95
|
timeout: timeoutMs,
|
|
119
96
|
env: withoutProxy(),
|
|
120
97
|
detached,
|
|
121
|
-
signal,
|
|
98
|
+
signal: detached ? undefined : signal,
|
|
122
99
|
});
|
|
100
|
+
const stop = () => {
|
|
101
|
+
try {
|
|
102
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
103
|
+
}
|
|
104
|
+
catch { }
|
|
105
|
+
};
|
|
106
|
+
if (detached && signal?.aborted)
|
|
107
|
+
stop();
|
|
108
|
+
if (detached)
|
|
109
|
+
signal?.addEventListener('abort', stop, { once: true });
|
|
110
|
+
const ended = (ran) => {
|
|
111
|
+
signal?.removeEventListener('abort', stop);
|
|
112
|
+
resolve(ran);
|
|
113
|
+
};
|
|
123
114
|
let stdout = '';
|
|
124
115
|
let output = '';
|
|
125
116
|
child.stdout.setEncoding('utf8').on('data', (chunk) => {
|
|
@@ -129,25 +120,25 @@ export function run(command, args, timeoutMs, detached = false, signal) {
|
|
|
129
120
|
child.stderr.setEncoding('utf8').on('data', (chunk) => {
|
|
130
121
|
output += chunk;
|
|
131
122
|
});
|
|
132
|
-
child.on('error', (error) =>
|
|
133
|
-
child.on('close', (status) =>
|
|
123
|
+
child.on('error', (error) => ended({ status: null, stdout, output: error.message }));
|
|
124
|
+
child.on('close', (status) => ended({ status, stdout, output }));
|
|
134
125
|
});
|
|
135
126
|
}
|
|
136
127
|
export function failureOf(ran, program) {
|
|
137
128
|
return ran.output.trim().slice(-CAUSE_CHARACTERS) || `${program} exited with ${ran.status ?? 'a signal'}`;
|
|
138
129
|
}
|
|
139
|
-
export async function installAdapter(kind) {
|
|
130
|
+
export async function installAdapter(kind, signal) {
|
|
140
131
|
const adapter = CLIS[kind].adapter;
|
|
141
132
|
if (adapter === null)
|
|
142
133
|
return null;
|
|
143
134
|
const release = KIT_PACKAGE.peerDependencies[adapter.package];
|
|
144
135
|
if ((await installedAdapter(kind)) === release)
|
|
145
136
|
return null;
|
|
146
|
-
const ran = await run('npm', ['install', '--prefix', prefix(kind), '--no-save', '--no-audit', '--no-fund', '--omit=optional', `${adapter.package}@${release}`], INSTALL_MS);
|
|
137
|
+
const ran = await run('npm', ['install', '--prefix', prefix(kind), '--no-save', '--no-audit', '--no-fund', '--omit=optional', `${adapter.package}@${release}`], INSTALL_MS, true, signal);
|
|
147
138
|
return ran.status === 0 ? null : failureOf(ran, 'npm');
|
|
148
139
|
}
|
|
149
|
-
export async function installCli(kind) {
|
|
150
|
-
const ran = await run('bash', ['-o', 'pipefail', '-c', CLIS[kind].install], INSTALL_MS, true);
|
|
140
|
+
export async function installCli(kind, signal) {
|
|
141
|
+
const ran = await run('bash', ['-o', 'pipefail', '-c', CLIS[kind].install], INSTALL_MS, true, signal);
|
|
151
142
|
return ran.status === 0 ? null : failureOf(ran, 'the install');
|
|
152
143
|
}
|
|
153
144
|
function loginShell() {
|
|
@@ -156,11 +147,11 @@ function loginShell() {
|
|
|
156
147
|
const FOUND = 'house-kit-cli ';
|
|
157
148
|
const LOOKUP = `found=$(command -v "$1") || exit 0; case $found in /*) ;; *) found=$(pwd -P)/$found ;; esac; printf "${FOUND}%s\\n" "$found"`;
|
|
158
149
|
const USER_BIN = 'case ":$PATH:" in *":$HOME/.local/bin:"*) ;; *) PATH="$PATH:$HOME/.local/bin" ;; esac; export PATH';
|
|
159
|
-
function inLoginShell(script, argument = '') {
|
|
160
|
-
return run(loginShell(), ['-l', '-i', '-c', `exec /bin/sh -c '${USER_BIN}; ${script}' sh ${argument}`], READ_MS, true);
|
|
150
|
+
function inLoginShell(script, argument = '', signal) {
|
|
151
|
+
return run(loginShell(), ['-l', '-i', '-c', `exec /bin/sh -c '${USER_BIN}; ${script}' sh ${argument}`], READ_MS, true, signal);
|
|
161
152
|
}
|
|
162
|
-
export async function locate(kind) {
|
|
163
|
-
const ran = await inLoginShell(LOOKUP, CLIS[kind].bin);
|
|
153
|
+
export async function locate(kind, signal) {
|
|
154
|
+
const ran = await inLoginShell(LOOKUP, CLIS[kind].bin, signal);
|
|
164
155
|
return ran.stdout.split('\n').findLast((line) => line.startsWith(FOUND))?.slice(FOUND.length) ?? null;
|
|
165
156
|
}
|
|
166
157
|
export async function loginPath() {
|
|
@@ -168,8 +159,8 @@ export async function loginPath() {
|
|
|
168
159
|
const ran = await inLoginShell(`printf "${marker}%s\\n" "$PATH"`);
|
|
169
160
|
return ran.stdout.split('\n').findLast((line) => line.startsWith(marker)).slice(marker.length);
|
|
170
161
|
}
|
|
171
|
-
export async function versionOf(path) {
|
|
172
|
-
return VERSION.exec((await run(path, ['--version'], READ_MS)).stdout)?.[0] ?? null;
|
|
162
|
+
export async function versionOf(path, signal) {
|
|
163
|
+
return VERSION.exec((await run(path, ['--version'], READ_MS, false, signal)).stdout)?.[0] ?? null;
|
|
173
164
|
}
|
|
174
165
|
function numbers(version) {
|
|
175
166
|
return version.split(/[.-]/, 3).map(Number);
|