trantor 0.17.42 → 0.17.43

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.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Trantor — the hub-world for AI agent crews: live message bus, presence, project Kanban/flow board + context-handoff for independent AI coding agents (Claude, Codex, Gemini, …)",
9
- "version": "0.17.42"
9
+ "version": "0.17.43"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "trantor",
14
14
  "source": "./",
15
15
  "description": "The hub-world for AI agent crews. Say \"fire up the crew\" and Claude becomes the architect: a plan-aware Advisor routes the work (solo / cheap inline calls / live crew of Codex, Gemini, Kimi & DeepSeek in their own terminal windows), a Kanban/flow command center with a testing gate tracks it, and an economics brain (Scrooge) keeps the receipts. Includes the relay MCP, a SessionStart auto-discovery hook, and a PreCompact context-handoff so a fresh session can take over a full window instead of compacting.",
16
- "version": "0.17.42",
16
+ "version": "0.17.43",
17
17
  "author": {
18
18
  "name": "Sasha Bogojevic"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trantor",
3
- "version": "0.17.42",
3
+ "version": "0.17.43",
4
4
  "description": "Trantor — the hub-world for AI agent crews: live message bus, presence, project Kanban/flow board + crew orchestration for independent AI coding agents (Claude, Codex, Gemini, Kimi, DeepSeek)",
5
5
  "mcpServers": {
6
6
  "relay": {
package/hooks/hooks.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
- "description": "trantor — auto-register each session + inject live roster (SessionStart); post an in-flight 'doing' card when a sub-agent is dispatched (PreToolUse); heartbeat presence on every tool call + deliver unread bus messages to a busy session mid-turn + mirror the session's TodoWrite list onto the board as cards (PostToolUse); write a handoff before compaction (PreCompact); card each sub-agent's notional API cost when it finishes (SubagentStop)",
2
+ "description": "trantor — auto-register each session + inject live roster (SessionStart); turn each substantive user prompt into the session's live 'focus' card so a regular session's own work shows IN PROGRESS (UserPromptSubmit); post an in-flight 'doing' card when a sub-agent is dispatched (PreToolUse); heartbeat presence on every tool call + deliver unread bus messages to a busy session mid-turn + mirror the session's TodoWrite list onto the board as cards (PostToolUse); write a handoff before compaction (PreCompact); card each sub-agent's notional API cost when it finishes (SubagentStop)",
3
3
  "hooks": {
4
4
  "SessionStart": [
5
5
  { "matcher": "", "hooks": [ { "type": "command", "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/sessionstart.mjs" } ] }
6
6
  ],
7
+ "UserPromptSubmit": [
8
+ { "matcher": "", "hooks": [ { "type": "command", "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/prompt-focus.mjs" } ] }
9
+ ],
7
10
  "PreToolUse": [
8
11
  { "matcher": "Task|Agent", "hooks": [ { "type": "command", "command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/subagent-start.mjs" } ] }
9
12
  ],
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ // trantor UserPromptSubmit hook — turn each substantive user prompt into the session's live "focus" card,
3
+ // so a REGULAR (non-crew) Claude session's OWN work shows IN PROGRESS on the board as it happens — not only
4
+ // when it commits or dispatches a sub-agent. ONE rolling card per session (the hub re-titles it as the focus
5
+ // shifts and closes it to "done" when the session goes offline). Trivial acks ("yes", "go ahead") don't
6
+ // refocus. Fail-silent + fast: NO LLM call (the title is a heuristic clean of the prompt; Scrooge-summarized
7
+ // titles are a follow-up). Never blocks or delays the turn.
8
+ import { readFileSync, existsSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { homedir } from "node:os";
11
+ import { resolveProject, hostId } from "../lib/project.mjs";
12
+
13
+ function readStdin() {
14
+ return new Promise(res => { let d = ""; process.stdin.setEncoding("utf8");
15
+ process.stdin.on("data", c => (d += c)); process.stdin.on("end", () => res(d));
16
+ setTimeout(() => res(d), 100); });
17
+ }
18
+ function relayUrl() {
19
+ if (process.env.RELAY_URL) return process.env.RELAY_URL;
20
+ try { const c = join(homedir(), ".agent-bus", "config.json"); if (existsSync(c)) { const u = JSON.parse(readFileSync(c, "utf8")).url; if (u) return u; } } catch {}
21
+ return "http://127.0.0.1:4477";
22
+ }
23
+ // A prompt that is JUST an acknowledgement/continuation (anchored to end) — not a new focus.
24
+ const ACK = /^(y|yes|yep|yeah|ok|okay|sure|go|go ahead|continue|proceed|do it|please|thanks|thank you|ty|next|k|cool|nice|great|perfect|sounds good|👍)[\s.!]*$/i;
25
+ function titleFrom(prompt) {
26
+ let s = String(prompt || "").replace(/\s+/g, " ").trim();
27
+ // strip a leading politeness/imperative wrapper so the card reads as the WORK, not "can you please…"
28
+ s = s.replace(/^(please|can you|could you|would you|hey,?|ok,?|now,?|let's|lets|i want you to|i'd like you to|i need you to|go ahead and)\s+/i, "");
29
+ return s.slice(0, 120);
30
+ }
31
+
32
+ try {
33
+ if (process.env.TRANTOR_NO_FOCUS === "1") { process.stdout.write("{}"); process.exit(0); } // opt-out
34
+ const input = JSON.parse((await readStdin()) || "{}");
35
+ const prompt = String(input.prompt || "");
36
+ const cwd = input.cwd || process.env.CLAUDE_PROJECT_DIR || process.cwd();
37
+ // don't card home-dir sessions (matches sessionstart's phantom-project guard)
38
+ if (!process.env.RELAY_SESSION && !process.env.RELAY_PROJECT && cwd === homedir()) { process.stdout.write("{}"); process.exit(0); }
39
+ const trimmed = prompt.replace(/\s+/g, " ").trim();
40
+ // skip empties, tiny continuations, and pure acks — they're not a new focus
41
+ if (!trimmed || trimmed.length < 12 || ACK.test(trimmed)) { process.stdout.write("{}"); process.exit(0); }
42
+ const project = resolveProject(cwd);
43
+ const session = process.env.RELAY_SESSION
44
+ || (process.env.RELAY_AGENT ? `${process.env.RELAY_AGENT}:${project}` : `${hostId()}:${project}`);
45
+ await fetch(`${relayUrl()}/focus`, {
46
+ method: "POST", headers: { "content-type": "application/json" },
47
+ body: JSON.stringify({ session, project, title: titleFrom(trimmed), by: session }),
48
+ signal: AbortSignal.timeout(1500),
49
+ }).catch(() => {});
50
+ } catch (e) {
51
+ process.stderr.write(`[trantor] prompt-focus error: ${e?.message || e}\n`);
52
+ }
53
+ process.stdout.write("{}");
54
+ process.exit(0);
package/hub.mjs CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trantor",
3
- "version": "0.17.42",
3
+ "version": "0.17.43",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "trantor": "bin/cli.mjs"
@@ -10,7 +10,7 @@
10
10
  "zod": "^4.4.3"
11
11
  },
12
12
  "scripts": {
13
- "test": "node test.mjs && node test-scenarios.mjs && node test-failure.mjs && node test-handoff.mjs && node test-agents.mjs && node test-update.mjs && node test-handoff-guard.mjs && node test-balances.mjs && node test-subagent-cost.mjs && node test-inbox.mjs && node test-inflight.mjs"
13
+ "test": "node test.mjs && node test-scenarios.mjs && node test-failure.mjs && node test-handoff.mjs && node test-agents.mjs && node test-update.mjs && node test-handoff-guard.mjs && node test-balances.mjs && node test-subagent-cost.mjs && node test-inbox.mjs && node test-inflight.mjs && node test-focus.mjs"
14
14
  },
15
15
  "description": "The hub-world for AI agent crews — orchestrate Claude Code, Codex, Gemini, Kimi & DeepSeek as live crews with a plan-aware Advisor, a Kanban/flow command center, a testing gate, and an economics brain (Scrooge).",
16
16
  "files": [