@agentshouse/kit 0.1.0-alpha.28 → 0.1.0-alpha.29
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 +88 -42
- package/bootstrap.json +3 -3
- package/package.json +1 -1
- package/src/binding.js +11 -0
- package/src/blocks.js +2 -26
- package/src/bridge.js +23 -13
- package/src/contract.js +3 -7
- package/src/draft.js +4 -82
- package/src/house.js +63 -47
- package/src/kit-work-stream.js +9 -1
- package/src/launcher.js +21 -6
- package/src/pacing.js +41 -0
- package/src/plan.js +37 -45
- package/src/telegram-view.js +214 -0
- package/src/telegram.js +124 -53
- package/src/turn-frames.js +69 -0
- package/src/worker.js +45 -37
package/src/worker.js
CHANGED
|
@@ -15,13 +15,13 @@ import { bridgedFrame, openBridge } from "./bridge.js";
|
|
|
15
15
|
import { transferBytes } from "./bytes.js";
|
|
16
16
|
import { assistantBlocks } from "./blocks.js";
|
|
17
17
|
import { retryConversationFiles } from "./conversation-originals.js";
|
|
18
|
-
import { openAssistantDrafts } from "./draft.js";
|
|
19
18
|
import { localRequest, reconcileInbound } from "./inbound.js";
|
|
20
19
|
import { localFiles } from "./local-files.js";
|
|
21
20
|
import { answerText, answerYaml, editRefusal } from "./mcp.js";
|
|
22
21
|
import { inheritedEnvironment } from "./command.js";
|
|
23
22
|
import { sourceEntries } from "./google/entries.js";
|
|
24
23
|
import { watchKitWork } from "./kit-work-stream.js";
|
|
24
|
+
import { finalPlan } from "./plan.js";
|
|
25
25
|
import { coalescedTask, residentWake } from "./tasks.js";
|
|
26
26
|
import {
|
|
27
27
|
applyWorkingCopies,
|
|
@@ -56,7 +56,6 @@ import {
|
|
|
56
56
|
acquireOneRun,
|
|
57
57
|
acquireOneResumption,
|
|
58
58
|
admitInteraction,
|
|
59
|
-
admitPlanSnapshot,
|
|
60
59
|
awaitSecretInput,
|
|
61
60
|
rejectResumption,
|
|
62
61
|
callHouseMcp,
|
|
@@ -78,7 +77,6 @@ import {
|
|
|
78
77
|
reportSessions,
|
|
79
78
|
serveResident,
|
|
80
79
|
sessionAuthority,
|
|
81
|
-
streamAssistantDraft,
|
|
82
80
|
updateDrain,
|
|
83
81
|
} from "./house.js";
|
|
84
82
|
import { operationId } from "./operation.js";
|
|
@@ -87,6 +85,7 @@ import { readSettlements, removeSettlement, writeSettlement } from "./settlement
|
|
|
87
85
|
import { howWeWorkOwed, noteHowWeWork, reconcileSkillSet } from "./skill-set.js";
|
|
88
86
|
import { writeText } from "./state.js";
|
|
89
87
|
import { failedReport, terminalReport } from "./terminal.js";
|
|
88
|
+
import { kitStreamWriter, turnFrames } from "./turn-frames.js";
|
|
90
89
|
import {
|
|
91
90
|
createSession,
|
|
92
91
|
destroySession,
|
|
@@ -102,7 +101,7 @@ const PASS_REACHES = ["commands", "runs"];
|
|
|
102
101
|
|
|
103
102
|
async function dispatchSeal(context, bound) {
|
|
104
103
|
try {
|
|
105
|
-
await acceptAssistantText(context.session, bound.session, bound.sealed);
|
|
104
|
+
await acceptAssistantText(context.session, bound.session, bound.sealed, bound.plan);
|
|
106
105
|
bound.stopped.textAccepted = true;
|
|
107
106
|
} catch (refusal) {
|
|
108
107
|
if (!(refusal instanceof KitRefusal)) throw refusal;
|
|
@@ -217,7 +216,7 @@ async function completeOwnerStop(context, bound, requestedAt) {
|
|
|
217
216
|
const destroyed = await destroySession(context.runtime, bound.tmux);
|
|
218
217
|
let failure = null;
|
|
219
218
|
try {
|
|
220
|
-
await observeSessionStop(context.session, bound.session);
|
|
219
|
+
await observeSessionStop(context.session, bound.session, false, bound.plan);
|
|
221
220
|
} catch (refusal) {
|
|
222
221
|
if (undecided(context, refusal)) return { destroyed, confirmed: false, failure: null };
|
|
223
222
|
if (!(refusal instanceof KitRefusal)) throw refusal;
|
|
@@ -230,7 +229,7 @@ async function completeOwnerStop(context, bound, requestedAt) {
|
|
|
230
229
|
|
|
231
230
|
async function settleReported(context, bound) {
|
|
232
231
|
try {
|
|
233
|
-
await reportRunOutcome(context.session, bound.run, bound.reported);
|
|
232
|
+
await reportRunOutcome(context.session, bound.run, bound.reported, bound.plan);
|
|
234
233
|
return { settled: true, failure: null };
|
|
235
234
|
} catch (refusal) {
|
|
236
235
|
if (undecided(context, refusal)) return { settled: false, failure: null };
|
|
@@ -359,25 +358,23 @@ async function sessionPush(context, bound, authority, frame, signal) {
|
|
|
359
358
|
async function openRunBridge(context, bound, authority, start) {
|
|
360
359
|
const ended = new AbortController();
|
|
361
360
|
const handed = (act) => endOnEpochReport(ended, act);
|
|
362
|
-
const
|
|
363
|
-
send: handed((blocks) => streamAssistantDraft(context.session, bound.session, blocks)),
|
|
364
|
-
});
|
|
361
|
+
const frames = turnFrames(context.stream);
|
|
365
362
|
const bridge = await openBridge({
|
|
366
363
|
socket: bound.socket,
|
|
367
364
|
nonce: bound.nonce,
|
|
368
365
|
signal: AbortSignal.any([context.signal, ended.signal]),
|
|
369
366
|
mutates: mutatingCall(await toolMutations(context.session, context.signal)),
|
|
370
367
|
alive: () => sessionPresent(context.runtime, bound.tmux),
|
|
371
|
-
draft: (
|
|
368
|
+
draft: (view) => frames.draft(view),
|
|
369
|
+
plan: (snapshot) => frames.plan(snapshot),
|
|
372
370
|
start,
|
|
373
371
|
question: handed((batch) => admitInteraction(context.session, bound.session, batch)),
|
|
374
|
-
plan: handed((snapshot) => admitPlanSnapshot(context.session, bound.session, snapshot)),
|
|
375
372
|
howWeWork: () =>
|
|
376
373
|
noteHowWeWork(context.directory).catch((error) =>
|
|
377
374
|
reported(`How-we-work note unwritable (${error.code ?? "unknown"})`),
|
|
378
375
|
),
|
|
379
|
-
interrupt: handed((interrupt, outcome) =>
|
|
380
|
-
reportInterruptOutcome(context.session, interrupt, outcome),
|
|
376
|
+
interrupt: handed((interrupt, outcome, plan) =>
|
|
377
|
+
reportInterruptOutcome(context.session, interrupt, outcome, finalPlan(plan)),
|
|
381
378
|
),
|
|
382
379
|
secret: (interaction, ceremony) => awaitSecretInput(context.session, interaction, ceremony),
|
|
383
380
|
settle: handed((interaction, outcome) => settleInteraction(context, interaction, outcome)),
|
|
@@ -393,11 +390,11 @@ async function openRunBridge(context, bound, authority, start) {
|
|
|
393
390
|
signal,
|
|
394
391
|
), context.session.dependencies, signal)(frame)),
|
|
395
392
|
});
|
|
396
|
-
return { bridge,
|
|
393
|
+
return { bridge, frames, ended };
|
|
397
394
|
}
|
|
398
395
|
|
|
399
396
|
async function superviseBound(context, bound, opened, start) {
|
|
400
|
-
const { bridge,
|
|
397
|
+
const { bridge, ended } = opened;
|
|
401
398
|
const spawn = { committed: false };
|
|
402
399
|
let unsupervised = null;
|
|
403
400
|
let destroyed = false;
|
|
@@ -411,24 +408,20 @@ async function superviseBound(context, bound, opened, start) {
|
|
|
411
408
|
unsupervised = { code: refusal.code, detail: refusal.message };
|
|
412
409
|
} finally {
|
|
413
410
|
try {
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
await settleInteraction(context, interaction, "expired");
|
|
419
|
-
}
|
|
420
|
-
} finally {
|
|
421
|
-
bridge.stopRecovery();
|
|
422
|
-
if (owner === null) {
|
|
423
|
-
try {
|
|
424
|
-
destroyed = await grantExitGrace(context.runtime, bound.tmux);
|
|
425
|
-
} finally {
|
|
426
|
-
await bridge.close();
|
|
427
|
-
}
|
|
428
|
-
}
|
|
411
|
+
retryFiles(context);
|
|
412
|
+
await settleFiles(context);
|
|
413
|
+
for (const interaction of bridge.unsettledInteractions()) {
|
|
414
|
+
await settleInteraction(context, interaction, "expired");
|
|
429
415
|
}
|
|
430
416
|
} finally {
|
|
431
|
-
|
|
417
|
+
bridge.stopRecovery();
|
|
418
|
+
if (owner === null) {
|
|
419
|
+
try {
|
|
420
|
+
destroyed = await grantExitGrace(context.runtime, bound.tmux);
|
|
421
|
+
} finally {
|
|
422
|
+
await bridge.close();
|
|
423
|
+
}
|
|
424
|
+
}
|
|
432
425
|
}
|
|
433
426
|
}
|
|
434
427
|
ended.signal.throwIfAborted();
|
|
@@ -444,6 +437,7 @@ async function superviseBound(context, bound, opened, start) {
|
|
|
444
437
|
destroyed,
|
|
445
438
|
stopped: null,
|
|
446
439
|
};
|
|
440
|
+
bound.plan = finalPlan(bridge.plan());
|
|
447
441
|
if (owner !== null) {
|
|
448
442
|
const finished = await completeOwnerStop(context, bound, owner.requestedAt);
|
|
449
443
|
return {
|
|
@@ -495,12 +489,12 @@ async function settleStopped(context, bound) {
|
|
|
495
489
|
}
|
|
496
490
|
let failure = stopped.failure;
|
|
497
491
|
try {
|
|
498
|
-
await observeSessionStop(context.session, bound.session, stopped.textAccepted);
|
|
492
|
+
await observeSessionStop(context.session, bound.session, stopped.textAccepted, bound.plan);
|
|
499
493
|
} catch (refusal) {
|
|
500
494
|
if (undecided(context, refusal)) return unresolved(null);
|
|
501
495
|
if (!(refusal instanceof KitRefusal) || refusal.code !== "conversation_final_text_pending") throw refusal;
|
|
502
496
|
failure ??= { code: refusal.code, detail: refusal.message };
|
|
503
|
-
await observeSessionStop(context.session, bound.session);
|
|
497
|
+
await observeSessionStop(context.session, bound.session, false, bound.plan);
|
|
504
498
|
}
|
|
505
499
|
const report = stoppedReport(bound);
|
|
506
500
|
if (report !== null) await removeContinuation(context.directory, bound.run);
|
|
@@ -560,6 +554,7 @@ async function prepareAssignment(context, assignment, resumed) {
|
|
|
560
554
|
ownerStop: null,
|
|
561
555
|
sealed: null,
|
|
562
556
|
reported: null,
|
|
557
|
+
plan: null,
|
|
563
558
|
};
|
|
564
559
|
const authority = { token: assignment.session.token, expiresAt: assignment.session.expiresAt };
|
|
565
560
|
const start = {
|
|
@@ -642,7 +637,7 @@ async function superviseAssignment(context, assignment, resumed = false) {
|
|
|
642
637
|
},
|
|
643
638
|
command: context.launcher,
|
|
644
639
|
});
|
|
645
|
-
await observeSessionStart(context.session, bound.session);
|
|
640
|
+
opened.frames.identify(await observeSessionStart(context.session, bound.session));
|
|
646
641
|
});
|
|
647
642
|
}
|
|
648
643
|
|
|
@@ -661,7 +656,7 @@ async function superviseRestored(context, binding, authority) {
|
|
|
661
656
|
const opened = await openRunBridge(context, binding, authority);
|
|
662
657
|
return superviseBound(context, binding, opened, async (spawn) => {
|
|
663
658
|
spawn.committed = true;
|
|
664
|
-
await observeSessionStart(context.session, binding.session);
|
|
659
|
+
opened.frames.identify(await observeSessionStart(context.session, binding.session));
|
|
665
660
|
});
|
|
666
661
|
}
|
|
667
662
|
|
|
@@ -848,6 +843,7 @@ async function workerContext(options, dependencies, resident = false) {
|
|
|
848
843
|
home: dependencies.home ?? homedir(),
|
|
849
844
|
files: { originals: [], failures: [] },
|
|
850
845
|
commands: residentWake(),
|
|
846
|
+
stream: kitStreamWriter(),
|
|
851
847
|
epochReport: null,
|
|
852
848
|
agentRefresh: Promise.resolve(),
|
|
853
849
|
configurationPath: options.configuration,
|
|
@@ -920,7 +916,12 @@ export async function runWorkers(options, dependencies = {}) {
|
|
|
920
916
|
const watching = (dependencies.watchKitWork ?? watchKitWork)(
|
|
921
917
|
session,
|
|
922
918
|
AbortSignal.any([signal, watcher.signal]),
|
|
923
|
-
{
|
|
919
|
+
{
|
|
920
|
+
available: commanded,
|
|
921
|
+
changed: () => {},
|
|
922
|
+
opened: context.stream.opened,
|
|
923
|
+
closed: context.stream.closed,
|
|
924
|
+
},
|
|
924
925
|
dependencies,
|
|
925
926
|
).catch((error) => reported(`control stream ended: ${error?.code ?? error?.message ?? error}`));
|
|
926
927
|
try {
|
|
@@ -1036,6 +1037,7 @@ export async function runResident(options, dependencies = {}) {
|
|
|
1036
1037
|
),
|
|
1037
1038
|
(source) =>
|
|
1038
1039
|
sources === null ? Promise.reject(new KitRefusal("kit_resident_unavailable")) : sources.capture(source),
|
|
1040
|
+
context.stream,
|
|
1039
1041
|
);
|
|
1040
1042
|
const serve = async (signal) => {
|
|
1041
1043
|
context.busy = true;
|
|
@@ -1160,7 +1162,13 @@ export async function runResident(options, dependencies = {}) {
|
|
|
1160
1162
|
const watching = (dependencies.watchKitWork ?? watchKitWork)(
|
|
1161
1163
|
context.session,
|
|
1162
1164
|
AbortSignal.any([signal, watcher.signal]),
|
|
1163
|
-
{
|
|
1165
|
+
{
|
|
1166
|
+
available,
|
|
1167
|
+
changed,
|
|
1168
|
+
opened: context.stream.opened,
|
|
1169
|
+
closed: context.stream.closed,
|
|
1170
|
+
viewed: (frame) => served.forward(frame),
|
|
1171
|
+
},
|
|
1164
1172
|
dependencies,
|
|
1165
1173
|
).catch(fail);
|
|
1166
1174
|
try {
|