@tablation/crew 0.72.0 → 0.72.1

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.
Files changed (2) hide show
  1. package/dist/cli.js +35 -20
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8798,40 +8798,47 @@ function readPointers(stateDir) {
8798
8798
  try {
8799
8799
  const parsed = JSON.parse(readFileSync16(lastSessionFile(stateDir), "utf8"));
8800
8800
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
8801
- return Object.fromEntries(Object.entries(parsed).filter((e) => typeof e[1] === "string"));
8801
+ const out = {};
8802
+ for (const [host, v] of Object.entries(parsed)) {
8803
+ const slugs = (Array.isArray(v) ? v : [v]).filter((x) => typeof x === "string" && x !== "");
8804
+ if (slugs.length) out[host] = slugs;
8805
+ }
8806
+ return out;
8802
8807
  } catch {
8803
8808
  return {};
8804
8809
  }
8805
8810
  }
8811
+ function writePointers(stateDir, pointers) {
8812
+ const file = lastSessionFile(stateDir);
8813
+ mkdirSync10(dirname8(file), { recursive: true });
8814
+ writeFileSync11(file, `${JSON.stringify(pointers, null, 2)}
8815
+ `, { mode: 384 });
8816
+ }
8806
8817
  function rememberSession(stateDir, host, workspaceSlug) {
8807
8818
  try {
8808
- const file = lastSessionFile(stateDir);
8809
- mkdirSync10(dirname8(file), { recursive: true });
8810
- writeFileSync11(file, `${JSON.stringify({ ...readPointers(stateDir), [host]: workspaceSlug }, null, 2)}
8811
- `, { mode: 384 });
8819
+ const all = readPointers(stateDir);
8820
+ writePointers(stateDir, { ...all, [host]: [...(all[host] ?? []).filter((w) => w !== workspaceSlug), workspaceSlug] });
8812
8821
  } catch {
8813
8822
  }
8814
8823
  }
8815
- async function resumeKeychainSession(o) {
8816
- const workspace = readPointers(o.stateDir)[o.host];
8817
- if (!workspace) return void 0;
8818
- try {
8819
- const stored = await o.store.get(o.host, workspace);
8820
- if (!stored?.apiKey) return void 0;
8821
- if (!await o.verify(stored.apiKey)) return void 0;
8822
- return { workspace, apiKey: stored.apiKey };
8823
- } catch {
8824
- return void 0;
8824
+ async function resumableSessions(o) {
8825
+ const out = [];
8826
+ for (const workspace of readPointers(o.stateDir)[o.host] ?? []) {
8827
+ try {
8828
+ const stored = await o.store.get(o.host, workspace);
8829
+ if (stored?.apiKey && await o.verify(stored.apiKey)) out.push({ workspace, apiKey: stored.apiKey });
8830
+ } catch {
8831
+ }
8825
8832
  }
8833
+ return out;
8826
8834
  }
8827
8835
  function rememberedSessions(stateDir) {
8828
- return Object.entries(readPointers(stateDir)).map(([host, workspace]) => ({ host, workspace }));
8836
+ return Object.entries(readPointers(stateDir)).flatMap(([host, ws]) => ws.map((workspace) => ({ host, workspace })));
8829
8837
  }
8830
8838
  function forgetSession(stateDir, host) {
8831
8839
  try {
8832
8840
  const { [host]: _gone, ...rest } = readPointers(stateDir);
8833
- if (Object.keys(rest).length) writeFileSync11(lastSessionFile(stateDir), `${JSON.stringify(rest, null, 2)}
8834
- `, { mode: 384 });
8841
+ if (Object.keys(rest).length) writePointers(stateDir, rest);
8835
8842
  else rmSync10(lastSessionFile(stateDir), { force: true });
8836
8843
  } catch {
8837
8844
  }
@@ -18686,8 +18693,8 @@ ${reconstruction.prompt}
18686
18693
  }
18687
18694
  }
18688
18695
  let signInSource = apiKey ? "key" : "device";
18689
- if (!apiKey && !workspace && dryRun && store) {
18690
- const resumed = await resumeKeychainSession({
18696
+ if (!apiKey && !workspace && store) {
18697
+ const resumable = await resumableSessions({
18691
18698
  store,
18692
18699
  stateDir: cfg.ship.stateDir,
18693
18700
  host: hostFromUrl4(baseUrl),
@@ -18700,6 +18707,14 @@ ${reconstruction.prompt}
18700
18707
  }
18701
18708
  }
18702
18709
  });
18710
+ if (resumable.length > 1 && connectEvents.json) {
18711
+ stopForChoice(
18712
+ "workspace",
18713
+ `${resumable.length} workspaces have a remembered sign-in on ${hostFromUrl4(baseUrl)} \u2014 which one?`,
18714
+ resumable.map((r) => ({ value: r.workspace, label: r.workspace }))
18715
+ );
18716
+ }
18717
+ const resumed = resumable.length === 1 ? resumable[0] : void 0;
18703
18718
  if (resumed) {
18704
18719
  apiKey = resumed.apiKey;
18705
18720
  workspace = resumed.workspace;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tablation/crew",
3
- "version": "0.72.0",
3
+ "version": "0.72.1",
4
4
  "description": "A standing team of headless agents that picks work off a Tablation board, does it on a machine you control, and reports back.",
5
5
  "type": "module",
6
6
  "license": "MIT",