@volter/supercode-teams 0.2.101 → 0.2.102
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/fleet.mjs +16 -1
- package/bin/teams.mjs +24 -9
- package/package.json +1 -1
package/bin/fleet.mjs
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
// `--on` names an enrolled machine of the selected context, reached through
|
|
17
17
|
// its Teams server. Omitted, every verb acts on this OS user's own daemon, so
|
|
18
18
|
// the remote arm and the local arm are one code path.
|
|
19
|
+
import { spawnSync } from 'node:child_process';
|
|
19
20
|
import { attachPane, attachRuntime } from '../client.mjs';
|
|
20
21
|
import { openOn, harnessRequest, nodeRequest, fleetDiscover } from '../fleet.mjs';
|
|
21
22
|
|
|
@@ -45,6 +46,20 @@ function channelForOn() {
|
|
|
45
46
|
return openOn(onName(), { context: contextName() });
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
// Who starts a pane: supercode names it when it runs this CLI (empty: a person); run on its own, supercode is asked
|
|
50
|
+
// (`teams caller`), and a launch no supercode answers for records no starter (so no session may act on the pane).
|
|
51
|
+
let launcherAnswer;
|
|
52
|
+
function launcher() {
|
|
53
|
+
if (launcherAnswer === undefined) {
|
|
54
|
+
if (process.env.SUPERCODE_CALLER !== undefined) launcherAnswer = process.env.SUPERCODE_CALLER || null;
|
|
55
|
+
else {
|
|
56
|
+
const r = spawnSync(process.env.SUPERCODE_BIN || 'supercode', ['teams', 'caller'], { encoding: 'utf8', shell: process.platform === 'win32', windowsHide: true });
|
|
57
|
+
try { launcherAnswer = JSON.parse(r.stdout.trim().split('\n').pop()).caller ?? null; } catch { launcherAnswer = null; }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return launcherAnswer;
|
|
61
|
+
}
|
|
62
|
+
|
|
48
63
|
async function main() {
|
|
49
64
|
switch (verb) {
|
|
50
65
|
case 'discover': {
|
|
@@ -87,7 +102,7 @@ async function main() {
|
|
|
87
102
|
...(flags.popup === 'false' ? { popup: false } : {}),
|
|
88
103
|
// Who starts the pane (the session or board supercode resolved; unset for a person), and whether the pane
|
|
89
104
|
// runs its one verb as that caller (`close`/`stop` on another machine).
|
|
90
|
-
...(
|
|
105
|
+
...(launcher() ? { caller: launcher() } : {}),
|
|
91
106
|
...(flags['act-for-caller'] ? { actForCaller: true } : {}),
|
|
92
107
|
// `open --notify-when-ended`: the launching session's address, told once when the pane ends, and the
|
|
93
108
|
// machine's mail name the notice comes from.
|
package/bin/teams.mjs
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
// members, groups, sources, sync, machines, sessions) is the Teams workspace
|
|
27
27
|
// CLI in ./workspace.mjs.
|
|
28
28
|
import { createWriteStream, readFileSync, writeFileSync } from 'node:fs';
|
|
29
|
+
import { spawnSync } from 'node:child_process';
|
|
29
30
|
import { SupercodeHarnessClient } from '@volter/supercode-harness-sdk';
|
|
30
31
|
|
|
31
32
|
// A Windows scheduled task keeps no output (launchd and systemd name log files), so its unit names one here.
|
|
@@ -106,9 +107,23 @@ async function machineChannel() {
|
|
|
106
107
|
return openMachine({ machine: flags.machine ? String(flags.machine) : null, context: flags.context ? String(flags.context) : null, home });
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
// The session (or board) this command acts for
|
|
110
|
-
//
|
|
111
|
-
|
|
110
|
+
// The session (or board) this command acts for: the pane doors refuse a session acting on a pane it did not start.
|
|
111
|
+
// supercode names it when it runs this CLI (empty: a person); run on its own (`supercode-teams`), this CLI asks
|
|
112
|
+
// supercode (`teams caller`), which reads the session from this process's ancestry, and refuses when none answers.
|
|
113
|
+
let callerAnswer;
|
|
114
|
+
function caller() {
|
|
115
|
+
if (callerAnswer === undefined) {
|
|
116
|
+
if (process.env.SUPERCODE_CALLER !== undefined) callerAnswer = process.env.SUPERCODE_CALLER || null;
|
|
117
|
+
else {
|
|
118
|
+
const r = spawnSync(process.env.SUPERCODE_BIN || 'supercode', ['teams', 'caller'], { encoding: 'utf8', shell: process.platform === 'win32', windowsHide: true });
|
|
119
|
+
let answer;
|
|
120
|
+
try { answer = JSON.parse(r.stdout.trim().split('\n').pop()); } catch { /* no answer */ }
|
|
121
|
+
if (!answer || !('caller' in answer)) die(`cannot tell which session runs this, so the pane doors cannot hold it to the panes it started; nothing was done. Run it as \`supercode teams …\` (${(r.error?.message ?? r.stderr ?? '').trim().slice(0, 200)})`, 1);
|
|
122
|
+
callerAnswer = answer.caller ?? null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return callerAnswer ?? undefined;
|
|
126
|
+
}
|
|
112
127
|
|
|
113
128
|
async function withNode(fn) {
|
|
114
129
|
const channel = await machineChannel();
|
|
@@ -153,7 +168,7 @@ async function main() {
|
|
|
153
168
|
case 'panes': {
|
|
154
169
|
if (sub === 'ls') return withNode(async (rpc) => out(await rpc.call('panes.list')));
|
|
155
170
|
if (sub === 'capture') return withNode(async (rpc) => out((await rpc.call('panes.capture', { pane: rest[0], lines: Number(flags.lines ?? 200) })).text));
|
|
156
|
-
if (sub === 'close') return withNode(async (rpc) => out(await rpc.call('panes.close', { pane: rest[0], caller })));
|
|
171
|
+
if (sub === 'close') return withNode(async (rpc) => out(await rpc.call('panes.close', { pane: rest[0], caller: caller() })));
|
|
157
172
|
die('panes ls|capture|close');
|
|
158
173
|
}
|
|
159
174
|
case 'title': {
|
|
@@ -177,9 +192,9 @@ async function main() {
|
|
|
177
192
|
die('attention ls | rank | request <pane> [--urgency now|soon|whenever] [--reason text] | clear <pane>');
|
|
178
193
|
}
|
|
179
194
|
case 'suspend':
|
|
180
|
-
return withNode(async (rpc) => out(await rpc.call('panes.suspend', { pane: sub, interrupt: Boolean(flags.interrupt), caller })));
|
|
195
|
+
return withNode(async (rpc) => out(await rpc.call('panes.suspend', { pane: sub, interrupt: Boolean(flags.interrupt), caller: caller() })));
|
|
181
196
|
case 'resume':
|
|
182
|
-
return withNode(async (rpc) => out(await rpc.call('panes.resume', { pane: sub, input: flags.input ? String(flags.input) : null, caller })));
|
|
197
|
+
return withNode(async (rpc) => out(await rpc.call('panes.resume', { pane: sub, input: flags.input ? String(flags.input) : null, caller: caller() })));
|
|
183
198
|
case 'files': {
|
|
184
199
|
const path = rest[0];
|
|
185
200
|
if (sub === 'ls') return withNode(async (rpc) => out(await rpc.call('files.list', { path })));
|
|
@@ -218,10 +233,10 @@ async function main() {
|
|
|
218
233
|
// (answers `delivered: false` with the reason when it holds a draft).
|
|
219
234
|
if (flags.key !== undefined) {
|
|
220
235
|
if (flags.key === true || rest.length) die('input <pane> --key NAMES: keys by tmux name, space- or comma-separated (Escape, Enter, Tab, BTab, BSpace, Space, Up, Down, Left, Right, Home, End, PPage, NPage, DC, C-a … C-z)');
|
|
221
|
-
return withNode(async (rpc) => out(await rpc.call('panes.input', { pane: sub, text: keyBytes(String(flags.key)), submit: false, keys: true, caller })));
|
|
236
|
+
return withNode(async (rpc) => out(await rpc.call('panes.input', { pane: sub, text: keyBytes(String(flags.key)), submit: false, keys: true, caller: caller() })));
|
|
222
237
|
}
|
|
223
|
-
if (flags['when-composer-empty']) return withNode(async (rpc) => out(await rpc.call('panes.turn', { pane: sub, text: rest.join(' '), caller })));
|
|
224
|
-
return withNode(async (rpc) => out(await rpc.call('panes.input', { pane: sub, text: rest.join(' '), submit: !flags['no-enter'], caller })));
|
|
238
|
+
if (flags['when-composer-empty']) return withNode(async (rpc) => out(await rpc.call('panes.turn', { pane: sub, text: rest.join(' '), caller: caller() })));
|
|
239
|
+
return withNode(async (rpc) => out(await rpc.call('panes.input', { pane: sub, text: rest.join(' '), submit: !flags['no-enter'], caller: caller() })));
|
|
225
240
|
case 'port': {
|
|
226
241
|
// `port <pane>/<n> [--listen host:port]`: a machine port forwarded here. Stays up until ctrl-c.
|
|
227
242
|
const spec = String(sub ?? '');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-teams",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.102",
|
|
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",
|