@agentshouse/kit 0.1.0-alpha.17 → 0.1.0-alpha.19
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 +59 -10
- package/bin/connect-linux.sh +14 -4
- package/bootstrap.json +3 -3
- package/package.json +2 -1
- package/src/bridge.js +1 -1
- package/src/contract.js +6 -2
- package/src/house-main.js +65 -8
- package/src/house.js +50 -37
- package/src/local-files.js +3 -11
- package/src/mcp.js +13 -0
- package/src/sync-library.js +7 -11
- package/src/sync.js +1 -1
- package/src/worker.js +64 -6
- package/src/working-copy.js +516 -47
package/src/worker.js
CHANGED
|
@@ -10,15 +10,16 @@ import {
|
|
|
10
10
|
} from "./agents.js";
|
|
11
11
|
import { readBindings, removeBinding, writeBinding } from "./binding.js";
|
|
12
12
|
import { readContinuation, readContinuationRuns, writeContinuation, removeContinuation } from "./continuation.js";
|
|
13
|
-
import { openBridge } from "./bridge.js";
|
|
13
|
+
import { bridgedFrame, openBridge } from "./bridge.js";
|
|
14
14
|
import { assistantBlocks } from "./blocks.js";
|
|
15
15
|
import { retryConversationFiles } from "./conversation-originals.js";
|
|
16
16
|
import { openAssistantDrafts } from "./draft.js";
|
|
17
17
|
import { localRequest, reconcileInbound } from "./inbound.js";
|
|
18
18
|
import { localFiles } from "./local-files.js";
|
|
19
|
+
import { answerText, answerYaml } from "./mcp.js";
|
|
19
20
|
import { inheritedEnvironment } from "./command.js";
|
|
20
21
|
import { watchKitWork } from "./kit-work-stream.js";
|
|
21
|
-
import { applyWorkingCopies, workingCopyPaths } from "./working-copy.js";
|
|
22
|
+
import { applyWorkingCopies, ownerCaller, pushWorkingCopy, workingCopyPaths } from "./working-copy.js";
|
|
22
23
|
import { readConfiguration } from "./configuration.js";
|
|
23
24
|
import { launchBase, readyLaunchDirectory } from "./directory.js";
|
|
24
25
|
import {
|
|
@@ -32,8 +33,9 @@ import {
|
|
|
32
33
|
WORKER_HEARTBEAT_MS,
|
|
33
34
|
WORKER_INHERITED_ENVIRONMENT,
|
|
34
35
|
WORKER_SUPERVISION_POLL_MS,
|
|
36
|
+
WORKING_COPY_PUSH_METHOD,
|
|
35
37
|
} from "./contract.js";
|
|
36
|
-
import { EpochReportRequired, houseFailed, KitRefusal } from "./refusal.js";
|
|
38
|
+
import { EpochReportRequired, formatCommandError, houseFailed, KitRefusal } from "./refusal.js";
|
|
37
39
|
import {
|
|
38
40
|
acceptAssistantText,
|
|
39
41
|
acquireCommands,
|
|
@@ -270,6 +272,52 @@ function endOnEpochReport(ended, act) {
|
|
|
270
272
|
};
|
|
271
273
|
}
|
|
272
274
|
|
|
275
|
+
function refusedWith(text) {
|
|
276
|
+
const conflicts = answerYaml(text.slice(text.indexOf("\n") + 1))?.conflicts;
|
|
277
|
+
const current = Array.isArray(conflicts)
|
|
278
|
+
? conflicts.map(({ path, state, revision }) =>
|
|
279
|
+
state === "absent" ? { path, revision: null, content: null } : { path, revision },
|
|
280
|
+
)
|
|
281
|
+
: null;
|
|
282
|
+
return { refused: { code: text.split(":")[0].trim(), text, current } };
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function acceptedWith(text) {
|
|
286
|
+
const written = answerYaml(text).results.map(({ path, op, revision }) =>
|
|
287
|
+
op === "remove" ? { path, revision: null, content: null } : { path, revision },
|
|
288
|
+
);
|
|
289
|
+
return { refused: null, written };
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function sessionPush(context, bound, authority, frame, signal) {
|
|
293
|
+
const edit = async (body, sent) => {
|
|
294
|
+
const answer = await callHouseMcp(
|
|
295
|
+
context.session,
|
|
296
|
+
await sessionAuthority(context.session, bound.session, authority, sent),
|
|
297
|
+
bridgedFrame(
|
|
298
|
+
{ jsonrpc: "2.0", id: 1, method: "tools/call", params: { name: "edit", arguments: { changes: body.changes } } },
|
|
299
|
+
body.operation_id,
|
|
300
|
+
),
|
|
301
|
+
sent,
|
|
302
|
+
);
|
|
303
|
+
if (answer.error !== undefined) return refusedWith(answer.error.message ?? "kit_house_refused");
|
|
304
|
+
const text = answerText(answer.result);
|
|
305
|
+
return answer.result?.isError === true ? refusedWith(text) : acceptedWith(text);
|
|
306
|
+
};
|
|
307
|
+
let outcome;
|
|
308
|
+
try {
|
|
309
|
+
outcome = await pushWorkingCopy(context, frame.params, { binding: { session: bound.session }, submit: edit }, signal);
|
|
310
|
+
} catch (refusal) {
|
|
311
|
+
if (!(refusal instanceof KitRefusal)) throw refusal;
|
|
312
|
+
outcome = { refused: true, text: refusal.message };
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
jsonrpc: "2.0",
|
|
316
|
+
id: frame.id,
|
|
317
|
+
result: { content: [{ type: "text", text: outcome.text }], ...(outcome.refused ? { isError: true } : {}) },
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
|
|
273
321
|
async function openRunBridge(context, bound, authority, start) {
|
|
274
322
|
const ended = new AbortController();
|
|
275
323
|
const handed = (act) => endOnEpochReport(ended, act);
|
|
@@ -291,8 +339,9 @@ async function openRunBridge(context, bound, authority, start) {
|
|
|
291
339
|
),
|
|
292
340
|
secret: (interaction, ceremony) => awaitSecretInput(context.session, interaction, ceremony),
|
|
293
341
|
settle: handed((interaction, outcome) => settleInteraction(context, interaction, outcome)),
|
|
294
|
-
forward: handed((frame, signal) =>
|
|
295
|
-
|
|
342
|
+
forward: handed((frame, signal) => frame.method === WORKING_COPY_PUSH_METHOD
|
|
343
|
+
? sessionPush(context, bound, authority, frame, signal)
|
|
344
|
+
: localFiles(async (sent) =>
|
|
296
345
|
callHouseMcp(
|
|
297
346
|
context.session,
|
|
298
347
|
await sessionAuthority(context.session, bound.session, authority, signal),
|
|
@@ -960,7 +1009,16 @@ export async function runResident(options, dependencies = {}) {
|
|
|
960
1009
|
const wake = residentWake();
|
|
961
1010
|
const update = residentUpdate(context, wake);
|
|
962
1011
|
context.update = update;
|
|
963
|
-
const served = await serveResident(
|
|
1012
|
+
const served = await serveResident(
|
|
1013
|
+
session,
|
|
1014
|
+
context.directory,
|
|
1015
|
+
options.signal,
|
|
1016
|
+
(serving) => update.request(serving),
|
|
1017
|
+
(request, signal) =>
|
|
1018
|
+
pushWorkingCopy({ directory: context.directory, session }, request, ownerCaller(session), signal).catch(
|
|
1019
|
+
(error) => ({ refused: true, text: formatCommandError(error) }),
|
|
1020
|
+
),
|
|
1021
|
+
);
|
|
964
1022
|
const serve = async (signal) => {
|
|
965
1023
|
context.busy = true;
|
|
966
1024
|
const watcher = new AbortController();
|