@assuredloop/orca-bot-kit 0.22.0 → 0.24.1
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 +18 -2
- package/package.json +1 -1
- package/skills/obk-bot-building/SKILL.md +3 -2
- package/src/book.js +94 -3
- package/src/clear.js +554 -0
- package/src/cli.js +61 -0
- package/src/groom.js +17 -10
- package/src/health.js +4 -7
- package/src/hooks.js +67 -31
- package/src/lines.js +7 -4
- package/src/message.js +15 -1
- package/src/name.js +138 -0
- package/src/orca.js +6 -4
- package/src/record.js +5 -5
- package/src/skills.js +10 -1
- package/src/temp.js +17 -10
- package/src/up.js +49 -26
package/src/temp.js
CHANGED
|
@@ -28,7 +28,7 @@ import { mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
|
28
28
|
import path from 'node:path';
|
|
29
29
|
import { setTimeout as pause } from 'node:timers/promises';
|
|
30
30
|
|
|
31
|
-
import { readBook, updateBook } from './book.js';
|
|
31
|
+
import { readBook, takeLineTurn, TYPING_HELD, TYPING_WAIT_MS, updateBook } from './book.js';
|
|
32
32
|
import { addSession, dropSession, NAME, readBot, tempRoles } from './bot.js';
|
|
33
33
|
import { DEFAULT_APPROVAL, harnessOf, isShortPrompt, ownCli, shellWord, startPrompt, workDirOf } from './launch.js';
|
|
34
34
|
import { sessionInTab } from './message.js';
|
|
@@ -353,16 +353,23 @@ export async function trustHooks(bots, { tab, name }) {
|
|
|
353
353
|
if (handle === undefined) {
|
|
354
354
|
throw new Error(`${run} has no tab open in Orca, so there is no review of its to answer. ${nothing}`);
|
|
355
355
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
356
|
+
// The session's turn for a line (#482), for the look and the keys.
|
|
357
|
+
const turn = takeLineTurn(caller.home, name, TYPING_WAIT_MS);
|
|
358
|
+
if (turn === undefined) throw new Error(`${run}: ${TYPING_HELD}.`);
|
|
359
|
+
try {
|
|
360
|
+
const seen = screenRows(handle);
|
|
361
|
+
if (seen.rows === undefined) {
|
|
362
|
+
throw new Error(`${run}'s screen could not be read (${seen.unreadable}), so the kit cannot tell whether its hooks review is there. ${nothing}`);
|
|
363
|
+
}
|
|
364
|
+
const keys = keysToTrustAll(seen.rows);
|
|
365
|
+
if (keys === undefined) {
|
|
366
|
+
throw new Error(`${run}'s screen shows no "${HOOKS_REVIEW}" with its choices, so there is nothing for this to answer. It shows: ${shown(seen.rows)}. ${nothing}`);
|
|
367
|
+
}
|
|
368
|
+
// The return is inside the text: `--enter` would be a second key.
|
|
369
|
+
orca(['terminal', 'send', '--terminal', handle, '--text', keys]);
|
|
370
|
+
} finally {
|
|
371
|
+
turn.release();
|
|
363
372
|
}
|
|
364
|
-
// The return is inside the text: `--enter` would be a second key.
|
|
365
|
-
orca(['terminal', 'send', '--terminal', handle, '--text', keys]);
|
|
366
373
|
for (let waited = 0; ; waited += 500) {
|
|
367
374
|
const after = screenRows(handle);
|
|
368
375
|
if (after.rows !== undefined && !after.rows.some((row) => row.includes(HOOKS_REVIEW))) break;
|
package/src/up.js
CHANGED
|
@@ -8,7 +8,7 @@ import { existsSync, mkdirSync, realpathSync, writeFileSync } from 'node:fs';
|
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import { setTimeout as pause } from 'node:timers/promises';
|
|
10
10
|
|
|
11
|
-
import { forgetClaimed, forgetSession, MAILBOX_WAIT_MS, readBook, sessionIdsIn, tabIdsIn, takeMailboxTurn, updateBook, withUnclaimed } from './book.js';
|
|
11
|
+
import { forgetClaimed, forgetSession, MAILBOX_WAIT_MS, readBook, sessionIdsIn, tabIdsIn, takeLineTurn, takeMailboxTurn, TYPING_HELD, TYPING_WAIT_MS, updateBook, withUnclaimed } from './book.js';
|
|
12
12
|
import { botDir, botNames, displayName, projectName, readBot } from './bot.js';
|
|
13
13
|
import { conversationsIn, hasConversation, heldAsUserTurn, transcriptsIn } from './conversations.js';
|
|
14
14
|
import { installHook } from './hooks.js';
|
|
@@ -374,7 +374,7 @@ async function bringUpSession(bots, home, live, session, bot, title) {
|
|
|
374
374
|
// 0.157.1 (#226). So it is given one line, through the same gate as a mail
|
|
375
375
|
// notice, which the owner allowed. A fresh start's first turn is its prompt.
|
|
376
376
|
const list = harness === 'codex' && launch.resume !== undefined && tui.running === true
|
|
377
|
-
? await typeListLine(home, made.tabId)
|
|
377
|
+
? await typeListLine(home, session.name, made.tabId)
|
|
378
378
|
: undefined;
|
|
379
379
|
|
|
380
380
|
return entry(made, {
|
|
@@ -408,42 +408,65 @@ const LIST_LOOK_MS = 2000;
|
|
|
408
408
|
const LIST_ASK_MS = 500;
|
|
409
409
|
|
|
410
410
|
/**
|
|
411
|
-
* Type LIST_LINE into the tab `tabId`
|
|
412
|
-
*
|
|
413
|
-
*
|
|
414
|
-
*
|
|
411
|
+
* Type `line`, LIST_LINE unless told otherwise, into the tab `tabId` of
|
|
412
|
+
* `session` once the gate every typed line goes through lets it:
|
|
413
|
+
* `{ typed: true }`, or `{ typed: false, why }` with the gate's last reason
|
|
414
|
+
* once LIST_WAIT_MS is up. Nothing goes into a question, a form or a menu
|
|
415
|
+
* (#329, #416), nor into a tab the kit cannot tell about. Each look and its
|
|
416
|
+
* line are taken in the session's turn for a line (#482), unless the caller
|
|
417
|
+
* says it holds the session's typing turn already (`held`).
|
|
415
418
|
*/
|
|
416
|
-
async function typeListLine(home, tabId) {
|
|
419
|
+
export async function typeListLine(home, session, tabId, { line = LIST_LINE, held = false } = {}) {
|
|
417
420
|
const until = Date.now() + LIST_WAIT_MS;
|
|
418
421
|
for (;;) {
|
|
419
|
-
let
|
|
420
|
-
|
|
421
|
-
// Each look waits no longer than what is left of the wait.
|
|
422
|
-
found = tabToTypeInto(home, tabId, Math.max(1, Math.min(LIST_LOOK_MS, until - Date.now())));
|
|
423
|
-
} catch (error) {
|
|
424
|
-
return { typed: false, why: `Orca would not say whether it may be typed into: ${error.message}` };
|
|
425
|
-
}
|
|
426
|
-
// A yes that comes after the wait is too late: the wait is a cutoff, not a
|
|
427
|
-
// count of looks (review of PR #421).
|
|
428
|
-
if (found.handle !== undefined && Date.now() > until) {
|
|
429
|
-
return { typed: false, why: `the ${LIST_WAIT_MS / 1000} s wait for it ran out before the kit could tell it may be typed into` };
|
|
430
|
-
}
|
|
431
|
-
if (found.handle !== undefined) {
|
|
422
|
+
let turn;
|
|
423
|
+
if (!held) {
|
|
432
424
|
try {
|
|
433
|
-
|
|
434
|
-
return { typed: true };
|
|
425
|
+
turn = takeLineTurn(home, session, TYPING_WAIT_MS);
|
|
435
426
|
} catch (error) {
|
|
436
|
-
return { typed: false, why:
|
|
427
|
+
return { typed: false, why: error.message };
|
|
437
428
|
}
|
|
429
|
+
if (turn === undefined) return { typed: false, why: TYPING_HELD };
|
|
438
430
|
}
|
|
439
|
-
|
|
440
|
-
const
|
|
441
|
-
|
|
431
|
+
try {
|
|
432
|
+
const done = lookAndType(home, tabId, line, until);
|
|
433
|
+
if (done !== undefined) return done;
|
|
434
|
+
} finally {
|
|
435
|
+
turn?.release();
|
|
442
436
|
}
|
|
443
437
|
await pause(LIST_ASK_MS);
|
|
444
438
|
}
|
|
445
439
|
}
|
|
446
440
|
|
|
441
|
+
/** One look of typeListLine's, and its line when the gate lets it: what it returns, or undefined to look again. */
|
|
442
|
+
function lookAndType(home, tabId, line, until) {
|
|
443
|
+
let found;
|
|
444
|
+
try {
|
|
445
|
+
// Each look waits no longer than what is left of the wait.
|
|
446
|
+
found = tabToTypeInto(home, tabId, Math.max(1, Math.min(LIST_LOOK_MS, until - Date.now())));
|
|
447
|
+
} catch (error) {
|
|
448
|
+
return { typed: false, why: `Orca would not say whether it may be typed into: ${error.message}` };
|
|
449
|
+
}
|
|
450
|
+
// A yes that comes after the wait is too late: the wait is a cutoff, not a
|
|
451
|
+
// count of looks (review of PR #421).
|
|
452
|
+
if (found.handle !== undefined && Date.now() > until) {
|
|
453
|
+
return { typed: false, why: `the ${LIST_WAIT_MS / 1000} s wait for it ran out before the kit could tell it may be typed into` };
|
|
454
|
+
}
|
|
455
|
+
if (found.handle !== undefined) {
|
|
456
|
+
try {
|
|
457
|
+
typeIntoTab(found.handle, line);
|
|
458
|
+
return { typed: true };
|
|
459
|
+
} catch (error) {
|
|
460
|
+
return { typed: false, why: `Orca refused the line: ${error.message}` };
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
if (Date.now() >= until) {
|
|
464
|
+
const last = found.blocked !== undefined ? `it is waiting on ${found.blocked}` : found.unsure ?? 'no harness is running in it';
|
|
465
|
+
return { typed: false, why: `the ${LIST_WAIT_MS / 1000} s wait for it ran out: ${last}` };
|
|
466
|
+
}
|
|
467
|
+
return undefined;
|
|
468
|
+
}
|
|
469
|
+
|
|
447
470
|
/**
|
|
448
471
|
* The line that starts this session: resuming `resume`, or, with none, a fresh
|
|
449
472
|
* start carrying its duty. Returns `{ resume, prompt, promptFile, command, address }`.
|