@agentshouse/kit 0.2.1-c7f53ff9eaf98 → 0.2.1-c84a4fccf2835
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/bootstrap.json +4 -4
- package/dist/bridge.js +1 -1
- package/dist/conversations.js +31 -33
- package/dist/files.js +1 -1
- package/dist/inputs.js +37 -0
- package/dist/resident.js +7 -5
- package/dist/sign-in.js +5 -23
- package/dist/update.js +20 -23
- package/package.json +1 -1
package/dist/bootstrap.json
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
|
-
"version": "0.2.1-
|
|
3
|
+
"version": "0.2.1-c84a4fccf2835",
|
|
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-
|
|
8
|
+
"url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-c84a4fccf2835/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-
|
|
14
|
+
"url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-c84a4fccf2835/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-
|
|
20
|
+
"url": "https://github.com/agentshouse/kit/releases/download/v0.2.1-c84a4fccf2835/connect-windows.ps1"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
}
|
package/dist/bridge.js
CHANGED
|
@@ -81,7 +81,7 @@ function editAnswer(forwarded) {
|
|
|
81
81
|
export async function openBridge(house, copies, conversationId, signal) {
|
|
82
82
|
const path = [join(kitHome(), 'shim'), dirname(process.execPath), await loginPath()].join(delimiter);
|
|
83
83
|
const origin = (await readEnrolment()).house;
|
|
84
|
-
const { credential } = await house.post(`/kit/conversations/${conversationId}/credential`, {}, signal);
|
|
84
|
+
const { credential } = await retrying(() => house.post(`/kit/conversations/${conversationId}/credential`, {}, signal), signal);
|
|
85
85
|
const closed = new AbortController();
|
|
86
86
|
const sent = (message, operation) => callHouse(origin, credential, message, operation, closed.signal);
|
|
87
87
|
const send = async (message, operation) => {
|
package/dist/conversations.js
CHANGED
|
@@ -4,6 +4,7 @@ import { mkdir } from 'node:fs/promises';
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { unlessAborted } from './abort.js';
|
|
6
6
|
import { startAdapter } from './acp.js';
|
|
7
|
+
import { finalRefusal } from './api.js';
|
|
7
8
|
import { openBridge } from './bridge.js';
|
|
8
9
|
import { CLIS } from './clis.js';
|
|
9
10
|
import { answeredFailure, readerFor } from './events.js';
|
|
@@ -11,6 +12,7 @@ import { placeFiles, uploadBytes } from './files.js';
|
|
|
11
12
|
import { agentBase } from './home.js';
|
|
12
13
|
import { instructions } from './instructions.js';
|
|
13
14
|
import { Parts } from './parts.js';
|
|
15
|
+
import { refusalOf } from './refusals.js';
|
|
14
16
|
import { killMarked, Scope } from './scope.js';
|
|
15
17
|
import { holdSecretInput } from './secret-input.js';
|
|
16
18
|
import { createHowWeWork } from './skills.js';
|
|
@@ -19,7 +21,13 @@ import { workFor } from './work.js';
|
|
|
19
21
|
const SIGNED_OUT = RequestError.authRequired().code;
|
|
20
22
|
const KILLED = 'the conversation was killed';
|
|
21
23
|
const REFUSED = 'the CLI refused the prompt';
|
|
22
|
-
const NO_CONNECTION = "the
|
|
24
|
+
const NO_CONNECTION = "the Agent's computer could not open this conversation; try again";
|
|
25
|
+
const GONE = 'House no longer holds this conversation; start a new one';
|
|
26
|
+
const RETIRED = "this conversation's Agent is retired, so it cannot start";
|
|
27
|
+
const ENDED = {
|
|
28
|
+
conversation_not_found: GONE,
|
|
29
|
+
conversation_historical: RETIRED,
|
|
30
|
+
};
|
|
23
31
|
const NO_START = "the Agent's CLI did not start";
|
|
24
32
|
const NO_SESSION = "the Agent's CLI did not open a session";
|
|
25
33
|
const NO_RESUME = "the Agent's CLI could not resume this conversation";
|
|
@@ -31,9 +39,12 @@ async function step(reason, work) {
|
|
|
31
39
|
return await work;
|
|
32
40
|
}
|
|
33
41
|
catch (error) {
|
|
34
|
-
throw new NotStarted(reason, { cause: error });
|
|
42
|
+
throw new NotStarted(typeof reason === 'string' ? reason : reason(error), { cause: error });
|
|
35
43
|
}
|
|
36
44
|
}
|
|
45
|
+
function unbridged(error) {
|
|
46
|
+
return (finalRefusal(error) ? ENDED[refusalOf(error.text)?.code ?? ''] : undefined) ?? NO_CONNECTION;
|
|
47
|
+
}
|
|
37
48
|
const EXIT_PLAN_MODE = {
|
|
38
49
|
parse(value) {
|
|
39
50
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
@@ -119,9 +130,7 @@ function asksSecret(request) {
|
|
|
119
130
|
export class Conversations {
|
|
120
131
|
kit;
|
|
121
132
|
conversations = new Map();
|
|
122
|
-
acks = new Map();
|
|
123
133
|
questions = new Map();
|
|
124
|
-
carrying = 0;
|
|
125
134
|
reporting = 0;
|
|
126
135
|
watched = false;
|
|
127
136
|
constructor(kit) {
|
|
@@ -130,37 +139,26 @@ export class Conversations {
|
|
|
130
139
|
setInterval(() => this.look(), 2_000);
|
|
131
140
|
}
|
|
132
141
|
input(input) {
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
conversation.queue = handled.catch(() => undefined);
|
|
150
|
-
const work = handled.then(({ ack }) => ack);
|
|
151
|
-
this.acks.set(input.input_id, work);
|
|
152
|
-
return work;
|
|
153
|
-
})();
|
|
154
|
-
carried
|
|
155
|
-
.then((body) => this.kit.house.deliver(`/kit/inputs/${input.input_id}/ack`, body))
|
|
156
|
-
.catch(logged)
|
|
157
|
-
.finally(() => {
|
|
158
|
-
this.carrying--;
|
|
159
|
-
this.kit.changed();
|
|
142
|
+
void this.kit.inputs.carry(input.input_id, () => {
|
|
143
|
+
const conversation = this.conversation(input.conversation_id);
|
|
144
|
+
if (input.kind === 'kill') {
|
|
145
|
+
conversation.kills++;
|
|
146
|
+
conversation.killed.abort(new Error(KILLED));
|
|
147
|
+
for (const waiting of conversation.waiting.splice(0))
|
|
148
|
+
waiting.settle({ refused: KILLED });
|
|
149
|
+
this.halt(conversation);
|
|
150
|
+
}
|
|
151
|
+
if (input.kind === 'interrupt') {
|
|
152
|
+
conversation.interrupts++;
|
|
153
|
+
conversation.interrupted.abort();
|
|
154
|
+
}
|
|
155
|
+
const handled = conversation.queue.then(() => this.carry(conversation, input));
|
|
156
|
+
conversation.queue = handled.catch(() => undefined);
|
|
157
|
+
return handled.then(async ({ ack }) => ({ ack: await ack }));
|
|
160
158
|
});
|
|
161
159
|
}
|
|
162
160
|
idle() {
|
|
163
|
-
if (this.
|
|
161
|
+
if (this.reporting > 0)
|
|
164
162
|
return false;
|
|
165
163
|
for (const conversation of this.conversations.values()) {
|
|
166
164
|
const turn = conversation.turn;
|
|
@@ -395,7 +393,7 @@ export class Conversations {
|
|
|
395
393
|
.onRequest('elicitation/create', ({ params, signal }) => this.ask(conversation, 'elicitation/create', params, asksSecret(params), signal))
|
|
396
394
|
.onRequest('_x.ai/exit_plan_mode', EXIT_PLAN_MODE, ({ params, signal }) => this.ask(conversation, '_x.ai/exit_plan_mode', params, false, signal));
|
|
397
395
|
const cli = await unlessAborted(this.kit.agents.cli(route.kind), conversation.killed.signal);
|
|
398
|
-
const bridge = await step(
|
|
396
|
+
const bridge = await step(unbridged, openBridge(this.kit.house, this.kit.copies, conversation.id, conversation.killed.signal));
|
|
399
397
|
if (conversation.kills > 0) {
|
|
400
398
|
bridge.close();
|
|
401
399
|
throw new Error(KILLED);
|
package/dist/files.js
CHANGED
|
@@ -11,7 +11,7 @@ export function verified(bytes, sha256, name) {
|
|
|
11
11
|
export async function placeFiles(house, directory, files, signal) {
|
|
12
12
|
const paths = [];
|
|
13
13
|
for (const file of files) {
|
|
14
|
-
const original = await house.post('/kit/conversation/originals/get', { version: file.version, download: true }, signal);
|
|
14
|
+
const original = await retrying(() => house.post('/kit/conversation/originals/get', { version: file.version, download: true }, signal), signal);
|
|
15
15
|
const answer = await fetch(relayed(original.download.url), { signal });
|
|
16
16
|
if (!answer.ok)
|
|
17
17
|
throw new Error(`${file.name} did not download: ${answer.status}`);
|
package/dist/inputs.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
function logged(error) {
|
|
2
|
+
process.stderr.write(`kit: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
3
|
+
}
|
|
4
|
+
export class Inputs {
|
|
5
|
+
house;
|
|
6
|
+
changed;
|
|
7
|
+
carried = new Map();
|
|
8
|
+
open = 0;
|
|
9
|
+
constructor(house, changed) {
|
|
10
|
+
this.house = house;
|
|
11
|
+
this.changed = changed;
|
|
12
|
+
}
|
|
13
|
+
idle() {
|
|
14
|
+
return this.open === 0;
|
|
15
|
+
}
|
|
16
|
+
carry(inputId, work) {
|
|
17
|
+
const known = this.carried.get(inputId);
|
|
18
|
+
const carried = known ?? work();
|
|
19
|
+
if (known === undefined) {
|
|
20
|
+
this.carried.set(inputId, carried);
|
|
21
|
+
carried.catch(() => this.carried.delete(inputId));
|
|
22
|
+
}
|
|
23
|
+
this.open++;
|
|
24
|
+
this.changed();
|
|
25
|
+
return carried
|
|
26
|
+
.then(async ({ ack, acknowledged }) => {
|
|
27
|
+
await this.house.deliver(`/kit/inputs/${inputId}/ack`, ack);
|
|
28
|
+
if (known === undefined)
|
|
29
|
+
await acknowledged?.();
|
|
30
|
+
})
|
|
31
|
+
.catch(logged)
|
|
32
|
+
.finally(() => {
|
|
33
|
+
this.open--;
|
|
34
|
+
this.changed();
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
package/dist/resident.js
CHANGED
|
@@ -12,6 +12,7 @@ import { CONVERSATION_INPUTS, Conversations } from './conversations.js';
|
|
|
12
12
|
import { LocalCopies } from './copies.js';
|
|
13
13
|
import { restart } from './end.js';
|
|
14
14
|
import { agentBase, enrolled, forgetRestart, kitHome, ownerLock, ownerSocket, restartAsked } from './home.js';
|
|
15
|
+
import { Inputs } from './inputs.js';
|
|
15
16
|
import { killDescendants } from './scope.js';
|
|
16
17
|
import { quoted } from './shell.js';
|
|
17
18
|
import { SignIns } from './sign-in.js';
|
|
@@ -133,7 +134,7 @@ export async function resident() {
|
|
|
133
134
|
const agents = new Agents(house, () => changed());
|
|
134
135
|
let stream = null;
|
|
135
136
|
let reported = false;
|
|
136
|
-
const idle = () =>
|
|
137
|
+
const idle = () => inputs.idle() && conversations.idle() && agents.idle();
|
|
137
138
|
const changed = () => {
|
|
138
139
|
if (!idle()) {
|
|
139
140
|
reported = false;
|
|
@@ -146,15 +147,17 @@ export async function resident() {
|
|
|
146
147
|
logged(house.deliver('/kit/idle', {}, idle));
|
|
147
148
|
}
|
|
148
149
|
};
|
|
150
|
+
const inputs = new Inputs(house, changed);
|
|
149
151
|
const conversations = new Conversations({
|
|
150
152
|
house,
|
|
151
153
|
agents,
|
|
152
154
|
copies,
|
|
155
|
+
inputs,
|
|
153
156
|
send: (frame) => stream?.send(frame) ?? false,
|
|
154
157
|
changed,
|
|
155
158
|
});
|
|
156
|
-
const signIns = new SignIns(house, agents,
|
|
157
|
-
const updates = new Updates(
|
|
159
|
+
const signIns = new SignIns(house, agents, inputs);
|
|
160
|
+
const updates = new Updates(inputs);
|
|
158
161
|
for (const signal of ['SIGTERM', 'SIGINT']) {
|
|
159
162
|
process.once(signal, () => {
|
|
160
163
|
killDescendants();
|
|
@@ -178,7 +181,6 @@ export async function resident() {
|
|
|
178
181
|
if (arrived.type === 'work_available' && arrived.subject === 'agents')
|
|
179
182
|
logged(agents.refresh());
|
|
180
183
|
if (arrived.type === 'input') {
|
|
181
|
-
reported = false;
|
|
182
184
|
if (arrived.kind === 'sign_in')
|
|
183
185
|
signIns.start(arrived);
|
|
184
186
|
else if (arrived.kind === 'update')
|
|
@@ -187,7 +189,7 @@ export async function resident() {
|
|
|
187
189
|
conversations.input(arrived);
|
|
188
190
|
else {
|
|
189
191
|
const refused = { refused: `This Kit does not know ${arrived.kind}; update the Kit` };
|
|
190
|
-
|
|
192
|
+
void inputs.carry(String(arrived.input_id), async () => ({ ack: refused }));
|
|
191
193
|
}
|
|
192
194
|
}
|
|
193
195
|
},
|
package/dist/sign-in.js
CHANGED
|
@@ -9,36 +9,20 @@ const CODE = /^[A-Z0-9]+-[A-Z0-9]+$/;
|
|
|
9
9
|
function causeOf(error) {
|
|
10
10
|
return error instanceof Error ? error.message : String(error);
|
|
11
11
|
}
|
|
12
|
-
function logged(error) {
|
|
13
|
-
process.stderr.write(`kit: ${causeOf(error)}\n`);
|
|
14
|
-
}
|
|
15
12
|
function endOf(signal) {
|
|
16
13
|
return new Promise((resolve) => signal.addEventListener('abort', () => resolve(true), { once: true }));
|
|
17
14
|
}
|
|
18
15
|
export class SignIns {
|
|
19
16
|
house;
|
|
20
17
|
agents;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
constructor(house, agents, changed) {
|
|
18
|
+
inputs;
|
|
19
|
+
constructor(house, agents, inputs) {
|
|
24
20
|
this.house = house;
|
|
25
21
|
this.agents = agents;
|
|
26
|
-
this.
|
|
27
|
-
}
|
|
28
|
-
idle() {
|
|
29
|
-
return this.running.size === 0;
|
|
22
|
+
this.inputs = inputs;
|
|
30
23
|
}
|
|
31
24
|
start(input) {
|
|
32
|
-
|
|
33
|
-
return;
|
|
34
|
-
this.running.add(input.input_id);
|
|
35
|
-
this.changed();
|
|
36
|
-
this.signIn(input)
|
|
37
|
-
.catch(logged)
|
|
38
|
-
.finally(() => {
|
|
39
|
-
this.running.delete(input.input_id);
|
|
40
|
-
this.changed();
|
|
41
|
-
});
|
|
25
|
+
void this.inputs.carry(input.input_id, () => this.signIn(input));
|
|
42
26
|
}
|
|
43
27
|
async signIn(input) {
|
|
44
28
|
const ending = new AbortController();
|
|
@@ -48,9 +32,7 @@ export class SignIns {
|
|
|
48
32
|
clearTimeout(timer);
|
|
49
33
|
if (ended)
|
|
50
34
|
process.stderr.write(`kit: the ${input.cli} sign-in reached the end House set for it\n`);
|
|
51
|
-
|
|
52
|
-
if (!ended)
|
|
53
|
-
await this.agents.reread(input.cli);
|
|
35
|
+
return ended ? { ack: {} } : { ack: {}, acknowledged: () => this.agents.reread(input.cli) };
|
|
54
36
|
}
|
|
55
37
|
async signedIn(input, signal) {
|
|
56
38
|
await this.login(input, signal);
|
package/dist/update.js
CHANGED
|
@@ -6,9 +6,6 @@ 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
|
-
function logged(error) {
|
|
10
|
-
process.stderr.write(`kit: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
11
|
-
}
|
|
12
9
|
function directory() {
|
|
13
10
|
return join(kitHome(), 'update');
|
|
14
11
|
}
|
|
@@ -50,6 +47,12 @@ async function recorded() {
|
|
|
50
47
|
return null;
|
|
51
48
|
return status.trim() === '0' ? {} : { refused: `the Kit bootstrap exited with ${status.trim()}` };
|
|
52
49
|
}
|
|
50
|
+
async function forget(inputId) {
|
|
51
|
+
if ((await pendingInput()) !== inputId)
|
|
52
|
+
return;
|
|
53
|
+
await rm(pending(), { force: true });
|
|
54
|
+
await rm(outcome(), { force: true });
|
|
55
|
+
}
|
|
53
56
|
async function finished(inputId) {
|
|
54
57
|
for (;;) {
|
|
55
58
|
const ack = await recorded();
|
|
@@ -90,27 +93,28 @@ function rerun(script, inputId, flags) {
|
|
|
90
93
|
});
|
|
91
94
|
}
|
|
92
95
|
export class Updates {
|
|
93
|
-
|
|
94
|
-
held = new Set();
|
|
96
|
+
inputs;
|
|
95
97
|
queue = Promise.resolve();
|
|
96
|
-
constructor(
|
|
97
|
-
this.
|
|
98
|
+
constructor(inputs) {
|
|
99
|
+
this.inputs = inputs;
|
|
98
100
|
}
|
|
99
101
|
async resumed() {
|
|
100
102
|
const inputId = await pendingInput();
|
|
101
103
|
if (inputId === null)
|
|
102
104
|
return;
|
|
103
|
-
await this.
|
|
105
|
+
await this.enqueue(inputId, () => finished(inputId));
|
|
104
106
|
}
|
|
105
107
|
start(input) {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
108
|
+
void this.enqueue(input.input_id, () => this.carry(input));
|
|
109
|
+
}
|
|
110
|
+
enqueue(inputId, work) {
|
|
111
|
+
const before = this.queue;
|
|
112
|
+
const carried = this.inputs.carry(inputId, async () => {
|
|
113
|
+
await before;
|
|
114
|
+
return { ack: await work(), acknowledged: () => forget(inputId) };
|
|
115
|
+
});
|
|
116
|
+
this.queue = before.then(() => carried);
|
|
117
|
+
return carried;
|
|
114
118
|
}
|
|
115
119
|
async carry(input) {
|
|
116
120
|
if ((await pendingInput()) === input.input_id)
|
|
@@ -131,11 +135,4 @@ export class Updates {
|
|
|
131
135
|
refused: 'the Kit bootstrap did not finish',
|
|
132
136
|
};
|
|
133
137
|
}
|
|
134
|
-
async acknowledge(inputId, ack) {
|
|
135
|
-
await this.house.deliver(`/kit/inputs/${inputId}/ack`, ack);
|
|
136
|
-
if ((await pendingInput()) !== inputId)
|
|
137
|
-
return;
|
|
138
|
-
await rm(pending(), { force: true });
|
|
139
|
-
await rm(outcome(), { force: true });
|
|
140
|
-
}
|
|
141
138
|
}
|