@volter/supercode-teams 0.3.125 → 0.3.126
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/bin/teams.mjs +8 -2
- package/codex-startup.mjs +10 -1
- package/machine.mjs +28 -8
- package/package.json +1 -1
package/bin/teams.mjs
CHANGED
|
@@ -55,7 +55,7 @@ import { APP_DOOR_PATH, appDoorFile, appDoorLink, normalOrigin, readAppDoor, rea
|
|
|
55
55
|
|
|
56
56
|
const MACHINE_VERBS = new Set(['machine', 'slow', 'describe', 'records', 'panes', 'input', 'suspend', 'resume', 'files', 'ports', 'port', 'browser', 'stream', 'jobs', 'workspace', 'title', 'attention', 'watch', 'rpc', 'launches', 'log', 'mail', 'board', 'health', 'app-door']);
|
|
57
57
|
// Every flag a machine verb reads; any other is refused rather than silently ignored.
|
|
58
|
-
const KNOWN_FLAGS = new Set(['home', 'since', 'machine', 'context', 'floor', 'supercode', 'tmux-socket', 'verbose', 'lines', 'input', 'name', 'for', 'urgency', 'reason', 'interrupt', 'query', 'out', 'in', 'interval', 'no-enter', 'when-composer-empty', 'key', 'listen', 'list', 'from', 'to', 'path', 'to-path', 'repo', 'branch', 'solo', 'card', 'create', 'presence-only', 'processes', 'panes', 'clear-draft', 'message-ids', 'harness', 'observe', 'attach-context', 'json', 'all', 'origin', 'port', 'remove-origin', 'open']);
|
|
58
|
+
const KNOWN_FLAGS = new Set(['home', 'since', 'machine', 'context', 'floor', 'supercode', 'tmux-socket', 'verbose', 'lines', 'input', 'name', 'for', 'urgency', 'reason', 'interrupt', 'query', 'out', 'in', 'interval', 'no-enter', 'when-composer-empty', 'key', 'listen', 'list', 'from', 'to', 'path', 'to-path', 'repo', 'branch', 'solo', 'card', 'create', 'presence-only', 'processes', 'panes', 'clear-draft', 'message-ids', 'harness', 'observe', 'attach-context', 'json', 'all', 'origin', 'port', 'remove-origin', 'open', 'foreign']);
|
|
59
59
|
|
|
60
60
|
const argv = process.argv.slice(2);
|
|
61
61
|
const flags = {};
|
|
@@ -247,7 +247,13 @@ async function main() {
|
|
|
247
247
|
flags.processes ? 'panes.processes' : flags['presence-only'] ? 'panes.present' : 'panes.list',
|
|
248
248
|
flags['presence-only'] && typeof flags.panes === 'string' ? { panes: flags.panes.split(',').filter(Boolean) } : {})));
|
|
249
249
|
if (sub === 'capture') return withNode(async (rpc) => out((await rpc.call('panes.capture', { pane: rest[0], lines: Number(flags.lines ?? 200) })).text));
|
|
250
|
-
|
|
250
|
+
// One pane, named: `--foreign` closes a pane another session started, and is said for that pane alone.
|
|
251
|
+
if (sub === 'close') {
|
|
252
|
+
// the flag parser takes `--foreign p_…` as the flag's value: that pane is the one named
|
|
253
|
+
const named = typeof flags.foreign === 'string' ? [flags.foreign, ...rest] : rest;
|
|
254
|
+
if (named.length !== 1) die('panes close <pane> [--foreign]: one pane per close');
|
|
255
|
+
return withNode(async (rpc) => out(await rpc.call('panes.close', { pane: named[0], foreign: flags.foreign !== undefined, ...(await acting()) })));
|
|
256
|
+
}
|
|
251
257
|
// `window <pane> [machine]`: a terminal window on this machine's screen showing the pane, this machine's or, named,
|
|
252
258
|
// another machine's (attached through Teams, in that machine's Teams context `--attach-context`); `--observe` shows it
|
|
253
259
|
// read-only.
|
package/codex-startup.mjs
CHANGED
|
@@ -42,7 +42,16 @@ export function codexStartupArguments(args = []) {
|
|
|
42
42
|
}
|
|
43
43
|
normalized.push(argument);
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
// Codex 0.160's `resume` does not take this override from before the subcommand: a resumed TUI with it there still
|
|
46
|
+
// stopped on "Update available" once another Codex had cached a newer version, and `codex resume <id> -c …` did not
|
|
47
|
+
// (yuerans, 2026-10-06). It goes after the subcommand and its session id (readers of the process take the word after
|
|
48
|
+
// `resume` as the id: codex_peer.rs `resumed_session_in`), in front when there is no subcommand. `fork` is placed the
|
|
49
|
+
// same way by extension; only `resume` was measured.
|
|
50
|
+
const subcommand = normalized.findIndex((argument, index) => ['resume', 'fork'].includes(argument)
|
|
51
|
+
&& !['-c', '--config'].includes(normalized[index - 1]) && !normalized.slice(0, index).includes('--'));
|
|
52
|
+
const id = subcommand >= 0 && normalized[subcommand + 1] !== undefined && normalized[subcommand + 1] !== '--' && !normalized[subcommand + 1].startsWith('-');
|
|
53
|
+
const at = subcommand < 0 ? 0 : subcommand + (id ? 2 : 1);
|
|
54
|
+
return [...normalized.slice(0, at), '-c', 'check_for_update_on_startup=false', ...normalized.slice(at)];
|
|
46
55
|
}
|
|
47
56
|
|
|
48
57
|
export function codexUpdatePrompt(screen) {
|
package/machine.mjs
CHANGED
|
@@ -2079,16 +2079,22 @@ export class TeamsMachine extends MachineCore {
|
|
|
2079
2079
|
}
|
|
2080
2080
|
|
|
2081
2081
|
#refuseForeign(pane, caller) {
|
|
2082
|
-
|
|
2082
|
+
const starter = this.#foreignStarter(pane, caller);
|
|
2083
|
+
if (starter) throw Object.assign(new Error(`pane ${pane} ${starter}, not by ${caller}: a session acts only on the panes it started. Nothing was done; reach that session through its own doors (supercode message send)`), { code: 403 });
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
/** Who started `pane`, said, when `caller` is a session that did not start it; null when the caller may act on it (a
|
|
2087
|
+
* person, a board, its starter). */
|
|
2088
|
+
#foreignStarter(pane, caller) {
|
|
2089
|
+
if (typeof caller !== 'string' || !caller || /^sc:[^:]+:board:/.test(caller)) return null;
|
|
2083
2090
|
const launch = this.launches.all().find((entry) => entry.pane === pane);
|
|
2084
2091
|
const by = launch?.by ?? null;
|
|
2085
|
-
if (by === caller) return;
|
|
2092
|
+
if (by === caller) return null;
|
|
2086
2093
|
// A pane that resumes a session is that session's as well: its first starter acts on it as before the resume
|
|
2087
2094
|
// (t_09a795fd item 18). The starter is the oldest harness launch whose own transcript confirmed it started that
|
|
2088
2095
|
// session, never a launch row's claim (any caller can launch a program with --session-id S).
|
|
2089
|
-
if (launch?.resumes && this.#sessionOrigin(launch.resumes)?.by === caller) return;
|
|
2090
|
-
|
|
2091
|
-
throw Object.assign(new Error(`pane ${pane} ${starter}, not by ${caller}: a session acts only on the panes it started. Nothing was done; reach that session through its own doors (supercode message send)`), { code: 403 });
|
|
2096
|
+
if (launch?.resumes && this.#sessionOrigin(launch.resumes)?.by === caller) return null;
|
|
2097
|
+
return by ? `was started by ${by}` : 'was not started by a session (a person or an earlier daemon started it)';
|
|
2092
2098
|
}
|
|
2093
2099
|
|
|
2094
2100
|
/** The launch that started native Claude session `session`: the oldest journal row of a Claude launch whose own
|
|
@@ -3307,7 +3313,7 @@ export class TeamsMachine extends MachineCore {
|
|
|
3307
3313
|
}
|
|
3308
3314
|
const contextKey = params.pane ?? `p_${randomBytes(9).toString('base64url')}`;
|
|
3309
3315
|
// Who started the pane: the launching session's (or board's) address, null for a person. A session's later
|
|
3310
|
-
// input on the pane is refused unless it is this one (#refuseForeign); close
|
|
3316
|
+
// input on the pane is refused unless it is this one (#refuseForeign); its close needs `foreign` (panes.close).
|
|
3311
3317
|
// Who to tell when the pane ends (`open --new … --notify-when-ended`): a session's mail address, and this
|
|
3312
3318
|
// machine's name as the address a notice from its pane comes from.
|
|
3313
3319
|
if (params.notify !== undefined && !(params.notify && typeof params.notify.to === 'string' && /^sc:[^:\s]+:[^:\s]+:\S+$/.test(params.notify.to) && typeof params.notify.machine === 'string' && /^[a-z0-9][a-z0-9-]*$/.test(params.notify.machine))) throw Object.assign(new Error('launch notify is { to: <sc: address>, machine: <this machine\'s mail name> }'), { code: 400 });
|
|
@@ -3459,14 +3465,28 @@ export class TeamsMachine extends MachineCore {
|
|
|
3459
3465
|
case 'harness.v1.panes.close':
|
|
3460
3466
|
case 'panes.close': {
|
|
3461
3467
|
need('control', `pane:${params.pane}`);
|
|
3462
|
-
|
|
3468
|
+
// A session closes the panes it started and the one it runs in. Another's pane is closed only when the caller
|
|
3469
|
+
// says so (`foreign`), one pane at a time, by name: a listing piped into close is refused pane by pane rather
|
|
3470
|
+
// than ending every session on the machine (docs/adr/0004-pane-close-authority.md).
|
|
3471
|
+
const starting = [...this.pendingStartups.values()].filter((pending) => pending.pane === params.pane);
|
|
3472
|
+
// only a pane here (open, or still starting) is anyone's: one this machine lacks is answered as absent, before
|
|
3473
|
+
// the caller is asked for
|
|
3474
|
+
const here = starting.length > 0 || Boolean(await this.#paneByContext(params.pane));
|
|
3475
|
+
const closeBy = here ? await this.#callerOf(entry, params) : null;
|
|
3476
|
+
const starter = params.foreign === true || !here ? null : this.#foreignStarter(params.pane, closeBy);
|
|
3477
|
+
// the pane the caller runs in: a Claude row names it as its tmux locator (`p_…:@window.%pane`), the others as the pane
|
|
3478
|
+
if (starter && !this.live.sessions().some((live) => live.address === closeBy && String(live.pane ?? '').split(':')[0] === params.pane)) {
|
|
3479
|
+
act('close', `pane:${params.pane}`, 'refused', `foreign: ${starter}`);
|
|
3480
|
+
throw Object.assign(new Error(`pane ${params.pane} ${starter}, not by ${closeBy}. Nothing was closed. A session closes the panes it started; closing another's is deliberate: read what the pane holds, settle it with whoever started it, then close that one pane with --foreign`), { code: 403 });
|
|
3481
|
+
}
|
|
3482
|
+
for (const pending of starting) pending.abort.abort();
|
|
3463
3483
|
const session = await this.#paneByContext(params.pane);
|
|
3464
3484
|
if (!session) {
|
|
3465
3485
|
act('close', `pane:${params.pane}`, 'ok', 'already absent');
|
|
3466
3486
|
return { closed: params.pane, alreadyAbsent: true };
|
|
3467
3487
|
}
|
|
3468
3488
|
await this.host.closeSession(session.id);
|
|
3469
|
-
act('close', `pane:${params.pane}`);
|
|
3489
|
+
act('close', `pane:${params.pane}`, 'ok', params.foreign === true ? `foreign, by ${closeBy ?? 'a person'}` : null);
|
|
3470
3490
|
this.#panesChanged();
|
|
3471
3491
|
return { closed: params.pane };
|
|
3472
3492
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-teams",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.126",
|
|
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",
|