@volter/supercode-teams 0.3.114 → 0.3.115
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/machine.mjs +40 -3
- package/package.json +1 -1
package/machine.mjs
CHANGED
|
@@ -126,6 +126,13 @@ export function claudeUsageLimitWait(screen) {
|
|
|
126
126
|
/** The settle floor for a pane whose kind has no composer pattern: the screen
|
|
127
127
|
* must have stopped changing for this long before the pane counts as ready. */
|
|
128
128
|
const INITIAL_INPUT_SETTLE_MS = 1_000;
|
|
129
|
+
/** A Windows Codex's typed first input waits, before pasting, for an empty composer on a screen unchanged this long
|
|
130
|
+
* (CODEX_PASTE_SETTLE_DEADLINE_MS at most); gives the paste CODEX_PASTE_SHOWN_MS to show, and watches
|
|
131
|
+
* CODEX_PASTE_LATE_MS more to clear one shown after that. */
|
|
132
|
+
const CODEX_PASTE_SETTLE_MS = 1_500;
|
|
133
|
+
const CODEX_PASTE_SETTLE_DEADLINE_MS = 30_000;
|
|
134
|
+
const CODEX_PASTE_SHOWN_MS = 5_000;
|
|
135
|
+
const CODEX_PASTE_LATE_MS = 15_000;
|
|
129
136
|
|
|
130
137
|
/**
|
|
131
138
|
* Claude asks whether to trust a folder it has not opened before, whatever its permission mode, and has no flag that
|
|
@@ -2367,18 +2374,37 @@ export class TeamsMachine extends MachineCore {
|
|
|
2367
2374
|
const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
2368
2375
|
// Styled, so the composer's dim placeholder ("Ask Codex to do anything") reads as empty.
|
|
2369
2376
|
const composer = async () => terminal.composerText?.('codex', await this.host.capture(session.id, { preserveEscapes: true })) ?? null;
|
|
2370
|
-
|
|
2377
|
+
// A composer that reads ready can still be mid-layout: a fresh Codex redraws its screen for about a second more
|
|
2378
|
+
// (measured on volter-desktop: ready from the first frame, redrawn at ~1.1 s and ~1.3 s), and a paste sent into
|
|
2379
|
+
// that is shown late or not at all. Paste only into an empty composer on a screen that has stopped changing.
|
|
2380
|
+
let settled = false;
|
|
2381
|
+
for (const until = Date.now() + CODEX_PASTE_SETTLE_DEADLINE_MS; !settled && !signal.aborted && Date.now() < until;) {
|
|
2382
|
+
const capture = await this.host.capture(session.id, { preserveEscapes: true });
|
|
2383
|
+
settled = terminal.composerText?.('codex', capture) === '' &&
|
|
2384
|
+
this.#screenUnchangedMs(session.id, capture, Date.now()) >= CODEX_PASTE_SETTLE_MS;
|
|
2385
|
+
if (!settled) await pause(150);
|
|
2386
|
+
}
|
|
2387
|
+
if (signal.aborted) return { delivered: false, reason: 'aborted' };
|
|
2388
|
+
if (!settled) return { delivered: false, reason: await composer() === '' ? 'screen-unsettled' : 'composer-not-empty' };
|
|
2371
2389
|
for (const paste of codexWindowsPastes(body)) {
|
|
2372
2390
|
if (signal.aborted) return { delivered: false, reason: 'aborted' };
|
|
2373
2391
|
await this.host.sendInput(session.id, paste, { submitMode: 'none' });
|
|
2374
2392
|
await pause(300);
|
|
2375
2393
|
}
|
|
2376
2394
|
let held = false;
|
|
2377
|
-
for (
|
|
2395
|
+
for (const until = Date.now() + CODEX_PASTE_SHOWN_MS; !held && !signal.aborted && Date.now() < until;) {
|
|
2378
2396
|
held = Boolean(await composer());
|
|
2379
2397
|
if (!held) await pause(150);
|
|
2380
2398
|
}
|
|
2381
|
-
if (!held)
|
|
2399
|
+
if (!held) {
|
|
2400
|
+
// A paste shown after this gave up would sit in the composer unsent: watch a while longer and clear it, so the
|
|
2401
|
+
// pane is left as it was found (the launch records the input as undelivered either way).
|
|
2402
|
+
for (const until = Date.now() + CODEX_PASTE_LATE_MS; !signal.aborted && Date.now() < until;) {
|
|
2403
|
+
if (await composer()) { await this.#clearCodexComposer(session, composer, pause); break; }
|
|
2404
|
+
await pause(250);
|
|
2405
|
+
}
|
|
2406
|
+
return { delivered: false, reason: 'paste-unconfirmed' };
|
|
2407
|
+
}
|
|
2382
2408
|
await this.host.sendInput(session.id, '\r', { submitMode: 'single' });
|
|
2383
2409
|
return { delivered: true };
|
|
2384
2410
|
} catch (error) {
|
|
@@ -2388,6 +2414,17 @@ export class TeamsMachine extends MachineCore {
|
|
|
2388
2414
|
}
|
|
2389
2415
|
}
|
|
2390
2416
|
|
|
2417
|
+
/** Empty a Windows Codex composer this launch pasted into: line clear, then deletes until it reads empty (a paste
|
|
2418
|
+
* placeholder goes with one delete). Never Enter, Escape or Ctrl-C. */
|
|
2419
|
+
async #clearCodexComposer(session, composer, pause) {
|
|
2420
|
+
await this.host.sendInput(session.id, '\u0015', { submitMode: 'none' });
|
|
2421
|
+
await pause(300);
|
|
2422
|
+
for (let round = 0; round < 40 && await composer(); round += 1) {
|
|
2423
|
+
await this.host.sendInput(session.id, '\u007f'.repeat(200), { submitMode: 'none' });
|
|
2424
|
+
await pause(200);
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2391
2428
|
async #deliverPaneText(session, contextKey, text, options = {}) {
|
|
2392
2429
|
const kind = this.#paneKind(contextKey, session);
|
|
2393
2430
|
if (kind === 'codex' && codexUpdatePrompt(await this.host.capture(session.id, { lines: 120 }))) return { delivered: false, reason: 'codex-update-prompt: delivery refused; restart Codex with check_for_update_on_startup=false' };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-teams",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.115",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A machine daemon serving this machine's doors, and a local or remote Teams server for shared session discovery, OpenTelemetry ingestion and access to enrolled machines.",
|
|
6
6
|
"license": "MIT",
|