@assuredloop/orca-bot-kit 0.15.0 → 0.17.0
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/SETUP.md +6 -6
- package/package.json +1 -1
- package/rules/limits.md +1 -1
- package/skills/obk-bot-building/SKILL.md +16 -10
- package/skills/obk-finops/SKILL.md +4 -0
- package/skills/obk-fleet-review/SKILL.md +4 -0
- package/skills/obk-grooming/SKILL.md +4 -0
- package/src/cli.js +11 -1
- package/src/orca.js +35 -15
- package/src/up.js +65 -2
package/SETUP.md
CHANGED
|
@@ -194,12 +194,12 @@ waiting for:
|
|
|
194
194
|
| On screen | Send | Which is | Proven on |
|
|
195
195
|
|---|---|---|---|
|
|
196
196
|
| Claude Code's folder trust list | `\x1b[B\r` | down, then return: its selection starts on **No, exit** | Claude Code 2.1.283 |
|
|
197
|
-
| Codex's directory trust, `1. Trust and continue` (older: `1. Yes, continue`) | `\r` | return: its selection starts on **Trust and continue** | Codex 0.
|
|
198
|
-
| Codex's `Hooks need review` | `\x1b[B\r` | down, then return, to **Trust all and continue**; if the selection already starts there, return alone | Codex 0.
|
|
199
|
-
| Codex's `/new`: `Where should the new conversation run?` | `\r` | return: its selection starts on **Current checkout** (bot home) | Codex 0.
|
|
200
|
-
| Codex's update offer, `1. Update now` | `\r` | return: its selection starts on **Update now**, which accepts it | Codex 0.156.1; 0.157.1 has had no newer release to offer |
|
|
197
|
+
| Codex's directory trust, `1. Trust and continue` (older: `1. Yes, continue`) | `\r` | return: its selection starts on **Trust and continue** | Codex 0.158.0 |
|
|
198
|
+
| Codex's `Hooks need review` | `\x1b[B\r` | down, then return, to **Trust all and continue**; if the selection already starts there, return alone | Codex 0.158.0 |
|
|
199
|
+
| Codex's `/new`: `Where should the new conversation run?` | `\r` | return: its selection starts on **Current checkout** (bot home) | Codex 0.158.0 |
|
|
200
|
+
| Codex's update offer, `1. Update now` | `\r` | return: its selection starts on **Update now**, which accepts it | Codex 0.156.1; seen on 0.157.1 (offering 0.158.0) with the selection on **Update now**, not pressed; 0.158.0 has had no newer release to offer |
|
|
201
201
|
| `[oh-my-zsh] Would you like to update?` | `n` | they update their own shell | oh-my-zsh bf77e35 |
|
|
202
|
-
| Claude Code's `Teach auto mode about your environment?` | `\x1b` | Esc, which cancels it. On 2.1.283 it is a form, not a list: `How you use Claude here`, `Also scan shell history`, `Also scan your other repos`, `Continue`, and `Enter to continue · Esc to cancel`. **Never send a return**: Enter is **Continue**, which starts a scan of the project, recent Claude sessions and, by default, the machine's shell history | Not yet proven: Esc cancels in Claude Code 2.1.283's code, not yet seen live (#370); the form was seen live on 2.1.283 (#416); 2.1.278 showed a numbered list, answered with 2. Not now |
|
|
202
|
+
| Claude Code's `Teach auto mode about your environment?` | `\x1b` | Esc, which cancels it (**Not now**). On 2.1.283 it is a form, not a list: `How you use Claude here`, `Also scan shell history`, `Also scan your other repos`, `Continue`, and `Enter to continue · Esc to cancel`. **Never send a return**: Enter is **Continue**, which starts a scan of the project, recent Claude sessions and, by default, the machine's shell history | Not yet proven: Esc cancels in Claude Code 2.1.283's code, not yet seen live (#370); the form was seen live twice on 2.1.283, in #261's live test and #239's live run 1 (#416); 2.1.278 showed a numbered list, answered with 2. Not now |
|
|
203
203
|
|
|
204
204
|
Each key counts on where the selection starts, as it did on the version named.
|
|
205
205
|
Read the screen in front of you before you send: if the selection is somewhere
|
|
@@ -217,7 +217,7 @@ empty book and nothing says why.
|
|
|
217
217
|
Codex's trust question applies to the **repository root**, which for a bot means
|
|
218
218
|
the whole bots folder rather than the one bot. That is what they are agreeing to.
|
|
219
219
|
|
|
220
|
-
Codex's `/new` question (seen on 0.156.1 and 0.
|
|
220
|
+
Codex's `/new` question (seen on 0.156.1, 0.157.1 and 0.158.0) is always answered with the current checkout, which is the bot
|
|
221
221
|
home. The kit never makes a git worktree, so
|
|
222
222
|
`2. New worktree` is never the answer.
|
|
223
223
|
|
package/package.json
CHANGED
package/rules/limits.md
CHANGED
|
@@ -18,5 +18,5 @@ When something you were told to use is missing (a model, a tool, a file), say
|
|
|
18
18
|
so and ask. Quietly using a different one hides the change.
|
|
19
19
|
|
|
20
20
|
Permission rules in a harness's settings or rules files are the kit's to write,
|
|
21
|
-
after the user's yes to the exact rules: `obk bot change --allow <rule>` or
|
|
21
|
+
after the user's yes to the exact rules: `"${OBK_CLI:-obk}" bot change --allow <rule>` or
|
|
22
22
|
`--disallow <rule>`. Never edit one in or out yourself, Bot Father included.
|
|
@@ -19,6 +19,10 @@ own commands write them.
|
|
|
19
19
|
These are defaults for work where nothing says otherwise. A user who asks for
|
|
20
20
|
something else gets what they asked for; say which of these you left and why.
|
|
21
21
|
|
|
22
|
+
Where this skill says `obk`, run the kit that started your tab, `"${OBK_CLI:-obk}"`,
|
|
23
|
+
in its place: in a tab the kit launched that is the kit's own path, and anywhere
|
|
24
|
+
else it is plain `obk`.
|
|
25
|
+
|
|
22
26
|
## Ask whether this wants a new bot
|
|
23
27
|
|
|
24
28
|
Look at the fleet before you add to it. Where a bot already there could own
|
|
@@ -284,12 +288,12 @@ otherwise `/Applications/Orca.app/Contents/Resources/bin/orca`. A bare
|
|
|
284
288
|
| On screen | Send | Which is | Proven on |
|
|
285
289
|
|---|---|---|---|
|
|
286
290
|
| Claude Code's trust list | `\x1b[B\r` | down, return: off **No, exit** | Claude Code 2.1.283 |
|
|
287
|
-
| Codex's `Trust this folder?` | `\r` | return: it starts on yes | Codex 0.
|
|
288
|
-
| Codex's `Hooks need review` | `\x1b[B\r` | **Trust all and continue** | Codex 0.
|
|
289
|
-
| Codex's `Where should the new conversation run?` | `\r` | **Current checkout** | Codex 0.
|
|
291
|
+
| Codex's `Trust this folder?` | `\r` | return: it starts on yes | Codex 0.158.0 |
|
|
292
|
+
| Codex's `Hooks need review` | `\x1b[B\r` | **Trust all and continue** | Codex 0.158.0 |
|
|
293
|
+
| Codex's `Where should the new conversation run?` | `\r` | **Current checkout** | Codex 0.158.0 |
|
|
290
294
|
| Codex's update offer, `1. Update now` | `\r` | **Update now**, where it starts | Codex 0.156.1 |
|
|
291
295
|
| `[oh-my-zsh] Would you like to update?` | `n` | no: the user updates it | oh-my-zsh bf77e35 |
|
|
292
|
-
| Claude Code's `Teach auto mode…` | `\x1b` | Esc
|
|
296
|
+
| Claude Code's `Teach auto mode…` | `\x1b` | Esc: Not now; no return | Not yet proven, below |
|
|
293
297
|
|
|
294
298
|
Each key counts on where the selection starts on the version named. Read the
|
|
295
299
|
screen before you send: if the selection is elsewhere or the options have
|
|
@@ -297,17 +301,19 @@ moved, go to the answer with the arrows, then return. Never a digit and then
|
|
|
297
301
|
return: on Codex's update offer that took the highlighted **Update now**,
|
|
298
302
|
whatever the digit was. Codex's trust said `1. Yes, continue` on older
|
|
299
303
|
versions. Its hooks review sometimes starts on `2` already: then return alone.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
304
|
+
Its update offer was proven on 0.156.1; 0.157.1 showed it with the selection on
|
|
305
|
+
Update now, not pressed, and 0.158.0 has had no newer release to offer.
|
|
306
|
+
Claude Code's `Teach auto mode` on 2.1.283 is a form, not a list, ending
|
|
307
|
+
`Enter to continue · Esc to cancel`: never send it a return, since
|
|
303
308
|
Enter is Continue, which scans the project, recent sessions and the machine's
|
|
304
|
-
shell history. Esc cancels in its code; that is not yet proven
|
|
305
|
-
|
|
309
|
+
shell history. Esc cancels it (Not now) in its code; that is not yet proven
|
|
310
|
+
live, though the form was seen live twice on 2.1.283. On 2.1.278 it was a
|
|
311
|
+
numbered list, answered with `2. Not now`. Codex's hooks
|
|
306
312
|
question matters most. The kit's hook is how the book learns which
|
|
307
313
|
conversation the session is running, and until it is answered the
|
|
308
314
|
conversation has not started. Codex's trust applies to the repository root,
|
|
309
315
|
which is the whole bots folder. Codex's `/new` may ask where the new
|
|
310
|
-
conversation runs (0.156.1
|
|
316
|
+
conversation runs (0.156.1, 0.157.1 and 0.158.0 all did); the answer is
|
|
311
317
|
always the current checkout, the bot home, and never `2. New worktree`:
|
|
312
318
|
the kit never makes a git worktree.
|
|
313
319
|
|
|
@@ -24,6 +24,10 @@ kind that gets read once.
|
|
|
24
24
|
These are defaults for work where nothing says otherwise. A user who asks for
|
|
25
25
|
something else gets what they asked for; say which of these you left and why.
|
|
26
26
|
|
|
27
|
+
Where this skill says `obk`, run the kit that started your tab, `"${OBK_CLI:-obk}"`,
|
|
28
|
+
in its place: in a tab the kit launched that is the kit's own path, and anywhere
|
|
29
|
+
else it is plain `obk`.
|
|
30
|
+
|
|
27
31
|
## Start from what was used, not from an impression
|
|
28
32
|
|
|
29
33
|
The kit counts it for you. `obk usage` reports, per session, the conversations
|
|
@@ -25,6 +25,10 @@ act on your own, and that is set by the charter you are working under.
|
|
|
25
25
|
These are defaults for work where nothing says otherwise. A user who asks for
|
|
26
26
|
something else gets what they asked for; say which of these you left and why.
|
|
27
27
|
|
|
28
|
+
Where this skill says `obk`, run the kit that started your tab, `"${OBK_CLI:-obk}"`,
|
|
29
|
+
in its place: in a tab the kit launched that is the kit's own path, and anywhere
|
|
30
|
+
else it is plain `obk`.
|
|
31
|
+
|
|
28
32
|
## Start from what is on disk
|
|
29
33
|
|
|
30
34
|
Read the fleet before you talk about it. `obk roster` reports what each bot
|
|
@@ -22,6 +22,10 @@ reports the same thing every morning teaches its reader to stop looking.
|
|
|
22
22
|
These are defaults for work where nothing says otherwise. A user who asks for
|
|
23
23
|
something else gets what they asked for; say which of these you left and why.
|
|
24
24
|
|
|
25
|
+
Where this skill says `obk`, run the kit that started your tab, `"${OBK_CLI:-obk}"`,
|
|
26
|
+
in its place: in a tab the kit launched that is the kit's own path, and anywhere
|
|
27
|
+
else it is plain `obk`.
|
|
28
|
+
|
|
25
29
|
## Only what has happened since last time
|
|
26
30
|
|
|
27
31
|
Fix the end of the window before you read, not after. Take the moment you are
|
package/src/cli.js
CHANGED
|
@@ -1574,11 +1574,21 @@ function harnessLines(tab, bots) {
|
|
|
1574
1574
|
...ANSWER_IT,
|
|
1575
1575
|
];
|
|
1576
1576
|
|
|
1577
|
-
lines.push(...promptLines(tab));
|
|
1577
|
+
lines.push(...promptLines(tab), ...listLines(tab));
|
|
1578
1578
|
if (tab.unclaimed !== undefined) lines.push(...unclaimedLines(tab, bots));
|
|
1579
1579
|
return lines;
|
|
1580
1580
|
}
|
|
1581
1581
|
|
|
1582
|
+
/**
|
|
1583
|
+
* Whether a resumed Codex session was typed its one line so Orca lists it among
|
|
1584
|
+
* its agents, which it does only from a session's first turn (#226).
|
|
1585
|
+
*/
|
|
1586
|
+
function listLines(tab) {
|
|
1587
|
+
if (tab.listLine === true) return [' it was typed one line so Orca lists it among its agents: Codex tells Orca only at a first turn.'];
|
|
1588
|
+
if (tab.listLine === false) return [` it was not typed the line that makes Orca list it (${tab.listLineTrouble}): Orca lists it at its next turn.`];
|
|
1589
|
+
return [];
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1582
1592
|
/**
|
|
1583
1593
|
* Whether the session got its start prompt, as its own record has it (#274):
|
|
1584
1594
|
* received, or not confirmed yet. Nothing for a session that was told nothing.
|
package/src/orca.js
CHANGED
|
@@ -326,9 +326,11 @@ export const retitleTab = (handle, title) =>
|
|
|
326
326
|
* the screen, as `questionIn` answers, and `screenUnreadable` says why there
|
|
327
327
|
* was none.
|
|
328
328
|
*/
|
|
329
|
-
export function harnessInTab(handle, timeoutMs) {
|
|
329
|
+
export function harnessInTab(handle, timeoutMs, readMs) {
|
|
330
330
|
const args = ['terminal', 'wait', '--terminal', handle, '--for', 'tui-idle', '--timeout-ms', String(timeoutMs)];
|
|
331
|
-
|
|
331
|
+
// With `readMs`, each call to Orca is given that long on top of what it was
|
|
332
|
+
// asked to wait, and ends as TIMED_OUT when it has not answered (#422).
|
|
333
|
+
const answer = ask(args, readMs === undefined ? undefined : timeoutMs + readMs);
|
|
332
334
|
|
|
333
335
|
// Out of time means nothing went idle, busy or absent alike. That is an
|
|
334
336
|
// answer, not a breakdown.
|
|
@@ -336,20 +338,26 @@ export function harnessInTab(handle, timeoutMs) {
|
|
|
336
338
|
throw refusal(args, answer);
|
|
337
339
|
}
|
|
338
340
|
|
|
339
|
-
const shown = orca(['terminal', 'show', '--terminal', handle]).terminal;
|
|
341
|
+
const shown = orca(['terminal', 'show', '--terminal', handle], { timeoutMs: readMs }).terminal;
|
|
340
342
|
const agent = typeof shown?.agentIdentity === 'string' && shown.agentIdentity !== '' ? shown.agentIdentity : undefined;
|
|
341
343
|
return {
|
|
342
344
|
answered: answer.ok === true,
|
|
343
345
|
blockedReason: answer.result?.wait?.blockedReason,
|
|
344
346
|
agent,
|
|
345
|
-
...frontOf(handle, shown?.ptyId),
|
|
346
|
-
...screenOf(handle),
|
|
347
|
+
...frontOf(handle, shown?.ptyId, readMs),
|
|
348
|
+
...screenOf(handle, readMs),
|
|
347
349
|
};
|
|
348
350
|
}
|
|
349
351
|
|
|
350
352
|
/** Orca's reason for a folder-trust screen, which it can go on giving once that is answered (#342). */
|
|
351
353
|
const TRUST_REASON = 'agent-trust-workspace';
|
|
352
354
|
|
|
355
|
+
/**
|
|
356
|
+
* How long each call to Orca the typing gate makes is given, beyond any wait it
|
|
357
|
+
* asked for, before the gate gives up on it and cannot tell (#422).
|
|
358
|
+
*/
|
|
359
|
+
const GATE_READ_MS = 5000;
|
|
360
|
+
|
|
353
361
|
/** The kit's word for a tab whose screen shows a question of its harness's own (#329). */
|
|
354
362
|
export const QUESTION_ON_SCREEN = 'question-on-screen';
|
|
355
363
|
|
|
@@ -360,10 +368,10 @@ export const QUESTION_ON_SCREEN = 'question-on-screen';
|
|
|
360
368
|
* rendered screen: accumulated output comes back in fragments (tech notes,
|
|
361
369
|
* section 1).
|
|
362
370
|
*/
|
|
363
|
-
function screenOf(handle) {
|
|
371
|
+
function screenOf(handle, readMs) {
|
|
364
372
|
let read;
|
|
365
373
|
try {
|
|
366
|
-
read = orca(['terminal', 'read', '--terminal', handle, '--screen']).terminal;
|
|
374
|
+
read = orca(['terminal', 'read', '--terminal', handle, '--screen'], { timeoutMs: readMs }).terminal;
|
|
367
375
|
} catch (error) {
|
|
368
376
|
return { screenUnreadable: `Orca would not read its screen: ${error.message}` };
|
|
369
377
|
}
|
|
@@ -425,10 +433,18 @@ export function questionIn(rows) {
|
|
|
425
433
|
*/
|
|
426
434
|
export function tabToTypeInto(home, tabId, timeoutMs) {
|
|
427
435
|
if (tabId === undefined) return {};
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
436
|
+
// Every call to Orca here has a bound, so one slow reply cannot hold the
|
|
437
|
+
// command that asked: one that runs out is "cannot tell" (#422).
|
|
438
|
+
let live;
|
|
439
|
+
let seen;
|
|
440
|
+
try {
|
|
441
|
+
live = tabs(home, { timeoutMs: GATE_READ_MS }).find((tab) => tab.tabId === tabId);
|
|
442
|
+
if (live === undefined) return {};
|
|
443
|
+
seen = harnessInTab(live.handle, timeoutMs, GATE_READ_MS);
|
|
444
|
+
} catch (error) {
|
|
445
|
+
if (error.code !== TIMED_OUT) throw error;
|
|
446
|
+
return { unsure: `Orca did not answer in time (${error.message}), so the kit could not tell whether a harness is running in it, and nothing was typed` };
|
|
447
|
+
}
|
|
432
448
|
// A line typed into a screen waiting for an answer is that answer: once, it
|
|
433
449
|
// confirmed Claude Code's folder-trust default, `No, exit` (tech notes,
|
|
434
450
|
// section 1).
|
|
@@ -516,8 +532,8 @@ const psCli = () => process.env.OBK_PS || '/bin/ps';
|
|
|
516
532
|
* sandbox, where it does not start at all, Orca's runtime is asked instead
|
|
517
533
|
* (#298, ADR 0031).
|
|
518
534
|
*/
|
|
519
|
-
function frontOf(handle, ptyId) {
|
|
520
|
-
const read = frontByPs(ptyId);
|
|
535
|
+
function frontOf(handle, ptyId, readMs) {
|
|
536
|
+
const read = frontByPs(ptyId, readMs);
|
|
521
537
|
if (read.unreadable === undefined) return read;
|
|
522
538
|
const asked = frontByOrca(handle);
|
|
523
539
|
return asked.unreadable === undefined ? asked : { unreadable: `${read.unreadable}, and ${asked.unreadable}` };
|
|
@@ -556,13 +572,17 @@ function frontByOrca(handle) {
|
|
|
556
572
|
* `diagnostics memory` is a diagnostics command and may change, so everything
|
|
557
573
|
* here ends in "cannot tell" rather than in an error or a guess.
|
|
558
574
|
*/
|
|
559
|
-
function frontByPs(ptyId) {
|
|
575
|
+
function frontByPs(ptyId, readMs) {
|
|
560
576
|
let pane;
|
|
561
577
|
try {
|
|
562
|
-
pane = orca(['diagnostics', 'memory']).worktrees
|
|
578
|
+
pane = orca(['diagnostics', 'memory'], { timeoutMs: readMs }).worktrees
|
|
563
579
|
.flatMap((worktree) => worktree.sessions ?? [])
|
|
564
580
|
.find((session) => session.sessionId === ptyId)?.pid;
|
|
565
581
|
} catch (error) {
|
|
582
|
+
// Orca not answering within the bound the typing gate set is not a tab
|
|
583
|
+
// `ps` cannot read: it ends the gate as "cannot tell", with no fallback to
|
|
584
|
+
// the runtime (review of PR #424).
|
|
585
|
+
if (error.code === TIMED_OUT) throw error;
|
|
566
586
|
return { unreadable: `Orca would not give the pane's pid: ${error.message}` };
|
|
567
587
|
}
|
|
568
588
|
if (!Number.isInteger(pane) || pane <= 0) return { unreadable: 'Orca gave no pid for its pane' };
|
package/src/up.js
CHANGED
|
@@ -14,7 +14,7 @@ import { conversationsIn, hasConversation, heldAsUserTurn, transcriptsIn } from
|
|
|
14
14
|
import { installHook } from './hooks.js';
|
|
15
15
|
import { writePermissions } from './permissions.js';
|
|
16
16
|
import { addressOf, harnessOf, isAddressOf, isShortPrompt, launchCommand, mailboxStep, reachesMail, sessionTrouble, startPrompt, workDirOf } from './launch.js';
|
|
17
|
-
import { asFolderProject, coordinatorOf, findProject, harnessInTab, makeMailbox, makeProject, openTab, QUESTION_ON_SCREEN, retitleTab, tabs, TERMINAL_ENV, TIMED_OUT, tellWindow, typeIntoTab, useMailbox } from './orca.js';
|
|
17
|
+
import { asFolderProject, coordinatorOf, findProject, harnessInTab, makeMailbox, makeProject, openTab, QUESTION_ON_SCREEN, retitleTab, tabs, tabToTypeInto, TERMINAL_ENV, TIMED_OUT, tellWindow, typeIntoTab, useMailbox } from './orca.js';
|
|
18
18
|
import { TAB_ENV } from './record.js';
|
|
19
19
|
import { buildAgents, rulesStamp } from './rules.js';
|
|
20
20
|
import { linkSkills } from './skills.js';
|
|
@@ -369,6 +369,14 @@ async function bringUpSession(bots, home, live, session, bot, title) {
|
|
|
369
369
|
? undefined
|
|
370
370
|
: await heldInRecord(home, session.name, harness, launch.prompt, { launched, running: tui.running === true });
|
|
371
371
|
|
|
372
|
+
// A Codex session resumed here is not among Orca's agents until its first
|
|
373
|
+
// turn: Codex fires its SessionStart then and not at the resume, seen live on
|
|
374
|
+
// 0.157.1 (#226). So it is given one line, through the same gate as a mail
|
|
375
|
+
// notice, which the owner allowed. A fresh start's first turn is its prompt.
|
|
376
|
+
const list = harness === 'codex' && launch.resume !== undefined && tui.running === true
|
|
377
|
+
? await typeListLine(home, made.tabId)
|
|
378
|
+
: undefined;
|
|
379
|
+
|
|
372
380
|
return entry(made, {
|
|
373
381
|
bot: bot.name,
|
|
374
382
|
name: session.name,
|
|
@@ -382,9 +390,60 @@ async function bringUpSession(bots, home, live, session, bot, title) {
|
|
|
382
390
|
resumed: launch.resume !== undefined,
|
|
383
391
|
noConversation: which.noConversation,
|
|
384
392
|
unclaimed: which.unclaimed,
|
|
393
|
+
listLine: list?.typed,
|
|
394
|
+
listLineTrouble: list?.why,
|
|
385
395
|
});
|
|
386
396
|
}
|
|
387
397
|
|
|
398
|
+
/** The line a resumed Codex session is typed so Orca lists it, in the architect's words (#226). */
|
|
399
|
+
const LIST_LINE = 'obk: this session was resumed in a new tab, and this line is only so Orca lists it. Reply "ok"; nothing else is asked.';
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* How long a resumed Codex tab is given to be one the kit may type into: live,
|
|
403
|
+
* Orca named the agent 7 to 11 s after the restart (#226), and the gate waits
|
|
404
|
+
* for that name. How long each look waits on the tab, and the pause between.
|
|
405
|
+
*/
|
|
406
|
+
const LIST_WAIT_MS = 20000;
|
|
407
|
+
const LIST_LOOK_MS = 2000;
|
|
408
|
+
const LIST_ASK_MS = 500;
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Type LIST_LINE into the tab `tabId` once the gate every typed line goes
|
|
412
|
+
* through lets it: `{ typed: true }`, or `{ typed: false, why }` with the
|
|
413
|
+
* gate's last reason once LIST_WAIT_MS is up. Nothing goes into a question, a
|
|
414
|
+
* form or a menu (#329, #416), nor into a tab the kit cannot tell about.
|
|
415
|
+
*/
|
|
416
|
+
async function typeListLine(home, tabId) {
|
|
417
|
+
const until = Date.now() + LIST_WAIT_MS;
|
|
418
|
+
for (;;) {
|
|
419
|
+
let found;
|
|
420
|
+
try {
|
|
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) {
|
|
432
|
+
try {
|
|
433
|
+
typeIntoTab(found.handle, LIST_LINE);
|
|
434
|
+
return { typed: true };
|
|
435
|
+
} catch (error) {
|
|
436
|
+
return { typed: false, why: `Orca refused the line: ${error.message}` };
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
if (Date.now() >= until) {
|
|
440
|
+
const last = found.blocked !== undefined ? `it is waiting on ${found.blocked}` : found.unsure ?? 'no harness is running in it';
|
|
441
|
+
return { typed: false, why: `the ${LIST_WAIT_MS / 1000} s wait for it ran out: ${last}` };
|
|
442
|
+
}
|
|
443
|
+
await pause(LIST_ASK_MS);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
388
447
|
/**
|
|
389
448
|
* The line that starts this session: resuming `resume`, or, with none, a fresh
|
|
390
449
|
* start carrying its duty. Returns `{ resume, prompt, promptFile, command, address }`.
|
|
@@ -714,11 +773,15 @@ const ids = (setup, change) => ({ project: setup.projectId, setup: setup.id, cha
|
|
|
714
773
|
export const promptPath = (bots, bot, session) =>
|
|
715
774
|
path.join(`${bots}.prompts`, `${encodeURIComponent(bot)}.${encodeURIComponent(session)}.txt`);
|
|
716
775
|
|
|
717
|
-
function entry(tab, { bot, name, created, running = false, blockedReason, promptReceived, promptFile, resumed, noConversation, unclaimed, noMailbox = false }) {
|
|
776
|
+
function entry(tab, { bot, name, created, running = false, blockedReason, promptReceived, promptFile, resumed, noConversation, unclaimed, noMailbox = false, listLine, listLineTrouble }) {
|
|
718
777
|
const made = { bot, name, title: tab.title, tabId: tab.tabId, terminal: tab.handle, created, harnessStarted: running };
|
|
719
778
|
// Whether this run picked the session up where it was or started a new one.
|
|
720
779
|
// Only for a tab this run opened: a tab that was already there was left alone.
|
|
721
780
|
if (resumed !== undefined) made.resumed = resumed;
|
|
781
|
+
// Whether a resumed Codex session was typed its one line so Orca lists it,
|
|
782
|
+
// and why not when it was not (#226).
|
|
783
|
+
if (listLine !== undefined) made.listLine = listLine;
|
|
784
|
+
if (listLineTrouble !== undefined) made.listLineTrouble = listLineTrouble;
|
|
722
785
|
// The id the book held that had no conversation behind it, now in the history.
|
|
723
786
|
if (noConversation !== undefined) made.noConversation = noConversation;
|
|
724
787
|
// Orca's own words for what is on screen waiting to be answered, when it
|