@volter/supercode-teams 0.2.167 → 0.2.169

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/workspace.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { hostname } from 'node:os';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { existsSync, readFileSync, realpathSync, rmSync } from 'node:fs';
5
- import { basename, isAbsolute, join, resolve } from 'node:path';
5
+ import { basename, join, resolve } from 'node:path';
6
6
  import { execFileSync, spawn } from 'node:child_process';
7
7
  import { createHash } from 'node:crypto';
8
8
  import { SupercodeHarnessClient } from '@volter/supercode-harness-sdk';
@@ -676,17 +676,22 @@ async function machinesCommand(sub, { flags, rest, output, client, context, team
676
676
  async function syncCommand(sub, { flags, rest, output, client, context, team, home }) {
677
677
  if (sub === 'list') return output(await team.syncRules.list(optional(flags, ['machine'])));
678
678
  if (sub === 'add' && flags.enrollment) {
679
- // A custodian's rule for a machine it enrolled: the path is the machine's own, and its root id is the one the
680
- // machine's connector registers for it (sha256 of machine id and path). The harness is named, as this computer
681
- // cannot ask that machine's native core.
682
- requireArgs(rest, 0, 0, 'teams sync add --enrollment FILE --repo PATH --harness ID'); if (!flags.repo) usage('--repo is required'); if (!flags.harness) usage('--harness is required with --enrollment');
679
+ // A custodian's rule for a machine it enrolled: the root is one that machine's connector registered (the
680
+ // server keeps each root's id and folder name, never its path, which the machine resolves for itself), chosen
681
+ // by --root ID or by the folder name of --repo. A root not registered yet is refused; `connect --cwd` registers it.
682
+ requireArgs(rest, 0, 0, 'teams sync add --enrollment FILE (--root ROOT_ID | --repo PATH) --harness ID');
683
+ if (!flags.root && !flags.repo) usage('--root or --repo is required with --enrollment'); if (!flags.harness) usage('--harness is required with --enrollment');
683
684
  const enrolled = JSON.parse(readFileSync(resolve(flags.enrollment), 'utf8'));
684
685
  if (enrolled.kind !== 'machine-enrollment' || enrolled.team_id !== context.team_id) usage('--enrollment names no machine of this team');
685
- // connect registers the folder's real path; name it the same way (absolute, normalized, no symlink).
686
- if (!isAbsolute(flags.repo)) usage('--repo with --enrollment is the machine\'s absolute path');
687
- const repo = resolve(flags.repo);
688
- const root_id = `root_${createHash('sha256').update(`${enrolled.machine.id}\0${repo}`).digest('hex').slice(0, 32)}`;
689
- return output(await team.syncRules.create({ machine_id: enrolled.machine.id, source_id: enrolled.source.id, selector: { root_id, harnesses: [flags.harness] }, visibility: flags.visibility ?? 'restricted', backfill: backfill(flags.backfill ?? 'none') }));
686
+ const roots = (await team.machines.roots(enrolled.machine.id)).items ?? [];
687
+ const folder = flags.root ? null : basename(String(flags.repo).replace(/[\\/]+$/, ''));
688
+ if (!flags.root && (!folder || folder === '.' || folder === '..')) usage('--repo names the root by its folder; give the folder, or --root ROOT_ID');
689
+ const matches = flags.root ? roots.filter((r) => r.id === flags.root) : roots.filter((r) => r.name === folder);
690
+ if (!matches.length) unsupported(`the machine has not registered ${flags.root ?? flags.repo} yet; its connect --cwd registers it`);
691
+ if (matches.length > 1) usage(`the machine has ${matches.length} roots named ${matches[0].name}; name one with --root (${matches.map((r) => r.id).join(', ')})`);
692
+ const root = matches[0];
693
+ if (!root.harnesses?.includes(flags.harness)) unsupported(`that root reports no ${flags.harness} discovery adapter`);
694
+ return output(await team.syncRules.create({ machine_id: enrolled.machine.id, source_id: enrolled.source.id, selector: { root_id: root.id, harnesses: [flags.harness] }, visibility: flags.visibility ?? 'restricted', backfill: backfill(flags.backfill ?? 'none') }));
690
695
  }
691
696
  if (sub === 'add') {
692
697
  requireArgs(rest, 0, 0, 'teams sync add --repo PATH'); if (!flags.repo) usage('--repo is required');
@@ -18,7 +18,9 @@ export class NativeEffects {
18
18
  if (existing && JSON.stringify(existing.params) === JSON.stringify(params)) { existing.seen = true; existing.ruleId = ruleId; return; }
19
19
  const { capabilities } = await c.core.runtimeCapabilities(params);
20
20
  if (!capabilities.attach_existing_process || !capabilities.stream_events) return;
21
- const runtime = await c.core.attachManagedRuntime(params);
21
+ // A live endpoint whose runtime is gone (its receipt's process ended) has nothing to bind: that is quiet.
22
+ let runtime;
23
+ try { runtime = await c.core.attachManagedRuntime(params); } catch { return; }
22
24
  try {
23
25
  const actions = ['attach_observe'];
24
26
  if (capabilities.send_input) actions.push('interact');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/supercode-teams",
3
- "version": "0.2.167",
3
+ "version": "0.2.169",
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",