shadok-ai 0.2.51 → 0.2.53

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.
@@ -10,13 +10,27 @@
10
10
  *
11
11
  * See docs/superpowers/specs/2026-08-08-claude-onboarding-design.md.
12
12
  */
13
+ /**
14
+ * Three states, not two.
15
+ *
16
+ * "I observed that it is signed out" and "I could not look" are different
17
+ * facts, and collapsing them was a real bug: `claude auth status` takes ~850ms
18
+ * and can fail (timeout, truncated output, a busy machine), which produced an
19
+ * empty stdout, which read as *signed out* — so the cockpit popped its sign-in
20
+ * card and spawned a `claude auth login` child on an instance that was
21
+ * perfectly signed in. Only `signed-out` is ever asserted; `unknown` is
22
+ * reported as such and acted on conservatively but never announced to the user.
23
+ */
24
+ export type AuthState = "signed-in" | "signed-out" | "unknown";
13
25
  export interface AuthStatus {
26
+ /** True only for `signed-in`. Kept for callers that just need a boolean. */
14
27
  loggedIn: boolean;
28
+ state: AuthState;
15
29
  authMethod?: string;
16
30
  email?: string;
17
31
  subscriptionType?: string;
18
32
  }
19
- /** Pure: `claude auth status --json`. Anything unreadable reads as logged out. */
33
+ /** Pure: `claude auth status --json`. Unreadable output is `unknown`, NOT signed out. */
20
34
  export declare function parseAuthStatus(stdout: string): AuthStatus;
21
35
  /** Pure: the OAuth URL the CLI printed, or null if it hasn't printed one yet. */
22
36
  export declare function parseLoginUrl(chunk: string): string | null;
@@ -35,6 +49,8 @@ export declare function loginPending(): boolean;
35
49
  export declare function cancelLogin(): void;
36
50
  export declare function startLogin(): Promise<{
37
51
  url: string;
52
+ } | {
53
+ alreadySignedIn: true;
38
54
  } | {
39
55
  error: string;
40
56
  }>;
@@ -1,21 +1,22 @@
1
1
  import { execFile, spawn } from "node:child_process";
2
- /** Pure: `claude auth status --json`. Anything unreadable reads as logged out. */
2
+ /** Pure: `claude auth status --json`. Unreadable output is `unknown`, NOT signed out. */
3
3
  export function parseAuthStatus(stdout) {
4
4
  try {
5
5
  const j = JSON.parse(stdout);
6
6
  if (!j || typeof j !== "object" || Array.isArray(j))
7
- return { loggedIn: false };
7
+ return { loggedIn: false, state: "unknown" };
8
8
  if (j.loggedIn !== true)
9
- return { loggedIn: false };
9
+ return { loggedIn: false, state: "signed-out" };
10
10
  return {
11
11
  loggedIn: true,
12
+ state: "signed-in",
12
13
  ...(typeof j.authMethod === "string" ? { authMethod: j.authMethod } : {}),
13
14
  ...(typeof j.email === "string" ? { email: j.email } : {}),
14
15
  ...(typeof j.subscriptionType === "string" ? { subscriptionType: j.subscriptionType } : {}),
15
16
  };
16
17
  }
17
18
  catch {
18
- return { loggedIn: false };
19
+ return { loggedIn: false, state: "unknown" };
19
20
  }
20
21
  }
21
22
  /**
@@ -57,13 +58,22 @@ let cached = null;
57
58
  export function invalidateAuthStatus() {
58
59
  cached = null;
59
60
  }
61
+ const probe = () => new Promise((resolve) => {
62
+ execFile("claude", ["auth", "status", "--json"], { timeout: 15_000 }, (_err, stdout) => resolve(parseAuthStatus(stdout ?? "")));
63
+ });
60
64
  export async function authStatus(force = false) {
61
65
  if (!force && cached && Date.now() - cached.at < STATUS_TTL_MS)
62
66
  return cached.status;
63
- const status = await new Promise((resolve) => {
64
- execFile("claude", ["auth", "status", "--json"], { timeout: 15_000 }, (_err, stdout) => resolve(parseAuthStatus(stdout ?? "")));
65
- });
66
- cached = { at: Date.now(), status };
67
+ let status = await probe();
68
+ // One retry, because the probe is a ~850ms process spawn and a busy machine
69
+ // makes it flake. A single retry turns the common transient failure into a
70
+ // definite answer instead of a wrong one.
71
+ if (status.state === "unknown")
72
+ status = await probe();
73
+ // NEVER cache "unknown": holding a failed probe for 30s would keep the whole
74
+ // instance in a doubtful state long after the cause passed.
75
+ if (status.state !== "unknown")
76
+ cached = { at: Date.now(), status };
67
77
  return status;
68
78
  }
69
79
  /**
@@ -90,6 +100,11 @@ export async function startLogin() {
90
100
  // second tab, would otherwise do.
91
101
  if (flow && !flow.ended && flow.url)
92
102
  return { url: flow.url };
103
+ // Never spawn a sign-in on an instance that is already signed in. This is the
104
+ // backstop for the whole class of "it launched for nothing": whatever led the
105
+ // caller here, a forced re-check has the last word.
106
+ if ((await authStatus(true)).state === "signed-in")
107
+ return { alreadySignedIn: true };
93
108
  cancelLogin();
94
109
  const child = spawn("claude", ["auth", "login", "--claudeai"], {
95
110
  // BROWSER is neutralised: on a desktop host the CLI would otherwise open a
@@ -1 +1 @@
1
- {"version":3,"file":"claude-auth.js","sourceRoot":"","sources":["../src/claude-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAuC,MAAM,oBAAoB,CAAC;AAsB1F,kFAAkF;AAClF,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAChF,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QACpD,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,GAAG,CAAC,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzE,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,OAAO,CAAC,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5F,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,YAAY,CAAC,CAAS;IAC7B,OAAO,CAAC;QACN,kEAAkE;SACjE,OAAO,CAAC,uCAAuC,EAAE,EAAE,CAAC;QACrD,wCAAwC;SACvC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,CAAC,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAChE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3E,CAAC;AAED,gFAAgF;AAChF,MAAM,aAAa,GAAG,MAAM,CAAC;AAC7B,iFAAiF;AACjF,MAAM,YAAY,GAAG,EAAE,GAAG,MAAM,CAAC;AAEjC,IAAI,MAAM,GAA8C,IAAI,CAAC;AAE7D,MAAM,UAAU,oBAAoB;IAClC,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAK,GAAG,KAAK;IAC5C,IAAI,CAAC,KAAK,IAAI,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,aAAa;QAAE,OAAO,MAAM,CAAC,MAAM,CAAC;IACrF,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAa,CAAC,OAAO,EAAE,EAAE;QACvD,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CACrF,OAAO,CAAC,eAAe,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CACvC,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC;IACpC,OAAO,MAAM,CAAC;AAChB,CAAC;AAiBD;;;;;GAKG;AACH,IAAI,IAAI,GAAgB,IAAI,CAAC;AAE7B,MAAM,UAAU,YAAY;IAC1B,OAAO,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,IAAI;QAAE,OAAO;IAClB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAClB,IAAI,GAAG,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,0EAA0E;IAC1E,6EAA6E;IAC7E,wEAAwE;IACxE,kCAAkC;IAClC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,GAAG;QAAE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;IAC9D,WAAW,EAAE,CAAC;IACd,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE;QAC7D,2EAA2E;QAC3E,+DAA+D;QAC/D,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE;QACjD,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAC;IACH,MAAM,CAAC,GAAS;QACd,KAAK;QACL,GAAG,EAAE,IAAI;QACT,GAAG,EAAE,EAAE;QACP,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,YAAY,CAAC;KACrD,CAAC;IACF,IAAI,GAAG,CAAC,CAAC;IAET,MAAM,MAAM,GAAG,CAAC,CAAU,EAAE,EAAE;QAC5B,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC;QACvB,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;QACjB,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACZ,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE;QAC3B,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QACtB,IAAI,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,cAAc;YAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAC1E,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,qDAAqD;IACrD,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACxB,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;QACf,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IACH,6EAA6E;IAC7E,oCAAoC;IACpC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC;QACf,MAAM,CAAC,OAAO,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE;YAC/B,WAAW,EAAE,CAAC;YACd,OAAO,CAAC,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAC,CAAC;QACpE,CAAC,EAAE,MAAM,CAAC,CAAC;QACX,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE;YAC5B,MAAM,GAAG,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACjC,IAAI,GAAG,EAAE,CAAC;gBACR,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;gBACZ,aAAa,CAAC,IAAI,CAAC,CAAC;gBACpB,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACvB,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YACnB,CAAC;iBAAM,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;gBACjC,aAAa,CAAC,IAAI,CAAC,CAAC;gBACpB,YAAY,CAAC,QAAQ,CAAC,CAAC;gBACvB,OAAO,CAAC,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC,CAAC;YACtE,CAAC;QACH,CAAC,EAAE,GAAG,CAAC,CAAC;IACV,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAY;IAEZ,MAAM,CAAC,GAAG,IAAI,CAAC;IACf,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,6CAA6C,EAAE,CAAC;IAC9F,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAExD,+DAA+D;IAC/D,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,CAAC,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,YAAY,CAAC,CAAC;IACxD,6EAA6E;IAC7E,iDAAiD;IACjD,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC;IAEX,MAAM,OAAO,GAAG,MAAM,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;QACrD,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE;YACxB,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;YACjB,OAAO,CAAC,SAAS,CAAC,CAAC;QACrB,CAAC,EAAE,MAAM,CAAC,CAAC;QACX,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,EAAE;YAChB,YAAY,CAAC,CAAC,CAAC,CAAC;YAChB,OAAO,CAAC,CAAC,CAAC,CAAC;QACb,CAAC,CAAC;QACF,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,WAAW,EAAE,CAAC;QACd,oBAAoB,EAAE,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,KAAK,cAAc;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,0DAA0D,EAAE,CAAC;IAC1F,IAAI,OAAO,KAAK,OAAO;QACrB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,yDAAyD,EAAE,CAAC;IACzF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mCAAmC,EAAE,CAAC;AACnE,CAAC"}
1
+ {"version":3,"file":"claude-auth.js","sourceRoot":"","sources":["../src/claude-auth.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -23,7 +23,7 @@ import { scanUsage, sessionFilePath, tailSession, clearTailPos, isNothingToShow
23
23
  import { computePace, paceBlock, WINDOW_SEC } from "./pace.js";
24
24
  import { getUsage } from "./usage.js";
25
25
  import { loadChannels, loadGroups, saveGroups, upsertChannel, removeChannel, mergeClientChannels, loadTgGroup, saveTgGroup, } from "./channels.js";
26
- import { startTelegram, renameTelegramTopic, closeTelegramTopic, probeToken, isStalePreface, announceLoggedOut, resetLoggedOutNotice, } from "./telegram.js";
26
+ import { startTelegram, renameTelegramTopic, closeTelegramTopic, probeToken, isStalePreface, announceLoggedOut, resetLoggedOutNotice, attachmentPrompt, pasteExtension, MEDIA_DIR, } from "./telegram.js";
27
27
  import { migrateTgBindings } from "./channels.js";
28
28
  import { loadCrons, saveCrons, upsertCron, removeCron, resolveCronId, resolveCronTarget, nextRunFor, nextRunAfterFailure, isTransient, CRON_MAX_RETRIES, markCronPrompt, normalizeSchedule, scheduleLabel, cronTimeZone, defaultTimeZone, systemTimeZone, isValidTimeZone, } from "./crons.js";
29
29
  import { linkRefusal, markAgentPrompt, notificationText, } from "./kinship.js";
@@ -62,6 +62,8 @@ if (!instanceLock.ok) {
62
62
  process.on("exit", () => releaseInstanceLock());
63
63
  const app = express();
64
64
  app.use(express.json({ limit: "1mb" }));
65
+ /** A pasted screenshot is a few hundred kB; past this it is not a paste. */
66
+ const PASTE_LIMIT = "12mb";
65
67
  // ── Optional GUI password ────────────────────────────────────────────────
66
68
  // If SHADOK_GUI_PASSWORD is set (at startup, via env or the CLI --password
67
69
  // flag), the whole GUI — pages, endpoints AND the WebSocket — requires a login.
@@ -538,6 +540,36 @@ app.get(["/", "/index.html"], (_req, res) => {
538
540
  res.setHeader("Content-Security-Policy", cspHeader(nonce));
539
541
  res.type("html").send(injectNonce(html, nonce));
540
542
  });
543
+ /**
544
+ * An image pasted into the composer. The web had no way to hand a file to an
545
+ * agent at all — only Telegram did — so a screenshot meant saving it somewhere
546
+ * and typing the path by hand.
547
+ *
548
+ * Same destination as the Telegram attachments (`MEDIA_DIR`): one folder, one
549
+ * purge, and the agent reads the file by absolute path exactly the same way.
550
+ *
551
+ * `requestFromBrowser` (stricter than the WS origin guard, cf. the profile
552
+ * guardrails): this route WRITES a file, so an `Origin`-less caller — a script,
553
+ * a curl — has no business here even on loopback.
554
+ */
555
+ app.post("/paste", express.raw({ type: "image/*", limit: PASTE_LIMIT }), (req, res) => {
556
+ if (!requestFromBrowser(req))
557
+ return res.status(403).json({ error: "same-origin browser only" });
558
+ const body = req.body;
559
+ if (!Buffer.isBuffer(body) || !body.length)
560
+ return res.status(400).json({ error: "empty body" });
561
+ const ext = pasteExtension(String(req.headers["content-type"] ?? ""));
562
+ try {
563
+ fs.mkdirSync(MEDIA_DIR, { recursive: true });
564
+ const file = path.join(MEDIA_DIR, `paste-${randomUUID()}.${ext}`);
565
+ fs.writeFileSync(file, body);
566
+ // The very wording Telegram already uses, so an agent sees one format.
567
+ res.json({ path: file, line: attachmentPrompt([{ path: file, kind: "image" }]) });
568
+ }
569
+ catch (e) {
570
+ res.status(500).json({ error: e instanceof Error ? e.message : String(e) });
571
+ }
572
+ });
541
573
  app.use(express.static(path.join(__dirname, "..", "public")));
542
574
  // Markdown parser served locally (history rendering on the client).
543
575
  // Résolu via require.resolve, pas un chemin en dur : dans l'install npm
@@ -652,7 +684,7 @@ app.post("/auth/login", async (_req, res) => {
652
684
  const r = await startLogin();
653
685
  if ("error" in r)
654
686
  return res.status(502).json(r);
655
- res.json(r);
687
+ res.json(r); // {url} or {alreadySignedIn:true} — the latter spawns nothing
656
688
  });
657
689
  app.post("/auth/code", async (req, res) => {
658
690
  const code = typeof req.body?.code === "string" ? req.body.code : "";
@@ -1781,7 +1813,16 @@ wss.on("connection", (ws) => {
1781
1813
  // allowed to start without one", and then sat on the first-run screen
1782
1814
  // for a day. `code` lets a machine client classify the refusal
1783
1815
  // without matching on message text (same contract as "busy").
1784
- if (!(await authStatus()).loggedIn) {
1816
+ // Only a state we OBSERVED refuses a spawn. A probe that failed
1817
+ // ("unknown") means we could not look, not that the instance is
1818
+ // signed out — punishing the user for our own flakiness would block
1819
+ // an agent on a machine that is perfectly fine. The seeding already
1820
+ // removed the silent-zombie failure this guard was protecting
1821
+ // against, and an agent spawned without credentials now fails loudly.
1822
+ const auth = await authStatus();
1823
+ if (auth.state === "unknown")
1824
+ console.log(`auth: could not verify sign-in state, allowing the spawn anyway`);
1825
+ if (auth.state === "signed-out") {
1785
1826
  // Telling the user is the whole point: a cron refused at 4am must
1786
1827
  // not be discovered a day later. Deduplicated inside, so a
1787
1828
  // five-minute cron does not turn one sign-out into a flood.
@@ -2007,7 +2048,7 @@ wss.on("connection", (ws) => {
2007
2048
  // dump de sa garde) noyait la réponse dans les deux interfaces. La
2008
2049
  // marque dans le contenu assure le même masquage à la relecture.
2009
2050
  if (origin !== "cron")
2010
- broadcast(session, { type: "prompt-echo", text, ...(origin ? { origin } : {}) }, ws);
2051
+ broadcast(session, { type: "prompt-echo", text, ...(origin ? { origin } : {}), ...(msg.from ? { from: msg.from } : {}) }, ws);
2011
2052
  session.busy = true;
2012
2053
  session.turnStartedAt = Date.now();
2013
2054
  broadcast(session, workingMessage(session));