agenthub-multiagent-mcp 1.76.0 → 1.76.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.
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Which coding session is this agent's work being captured into, if any
3
+ * (add-session-report-numbers).
4
+ *
5
+ * `session_close_report` attaches the answer when its caller did not pass a
6
+ * `session_id`, so a report from a captured session links to that session and
7
+ * shows its `s-YYYYMMDD-NNN` beside the report's own `h-` number. Before this,
8
+ * the `/close-session` skill never passed one, so no report ever linked.
9
+ *
10
+ * Two places can know, mirroring the two capture paths in session-capture.sh:
11
+ *
12
+ * 1. A daemon shift: the daemon opens the session and stamps
13
+ * `AGENTHUB_SESSION_ID` into the shift's environment, which this MCP
14
+ * process inherits.
15
+ * 2. An interactive session whose owner consented: the capture hook resolves
16
+ * a session per Claude Code session id and caches it beside the grant file
17
+ * (`<dir of grant>/agenthub-capture-state/<claude session id>.json`). The
18
+ * Claude session id is read from the activity marker the PostToolUse hook
19
+ * writes.
20
+ *
21
+ * Anything else — no capture, consent refused, a missing or unreadable file —
22
+ * answers `undefined`, and the report is filed without a session, exactly as
23
+ * before. This never throws and never calls the network.
24
+ */
25
+ export interface CurrentCaptureSessionOptions {
26
+ env?: NodeJS.ProcessEnv;
27
+ workingDir?: string | null;
28
+ homeDir?: string;
29
+ }
30
+ export declare function currentCaptureSessionId(opts?: CurrentCaptureSessionOptions): string | undefined;
31
+ //# sourceMappingURL=currentCaptureSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currentCaptureSession.d.ts","sourceRoot":"","sources":["../src/currentCaptureSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAOH,MAAM,WAAW,4BAA4B;IAC3C,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,uBAAuB,CAAC,IAAI,GAAE,4BAAiC,GAAG,MAAM,GAAG,SAAS,CA8BnG"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Which coding session is this agent's work being captured into, if any
3
+ * (add-session-report-numbers).
4
+ *
5
+ * `session_close_report` attaches the answer when its caller did not pass a
6
+ * `session_id`, so a report from a captured session links to that session and
7
+ * shows its `s-YYYYMMDD-NNN` beside the report's own `h-` number. Before this,
8
+ * the `/close-session` skill never passed one, so no report ever linked.
9
+ *
10
+ * Two places can know, mirroring the two capture paths in session-capture.sh:
11
+ *
12
+ * 1. A daemon shift: the daemon opens the session and stamps
13
+ * `AGENTHUB_SESSION_ID` into the shift's environment, which this MCP
14
+ * process inherits.
15
+ * 2. An interactive session whose owner consented: the capture hook resolves
16
+ * a session per Claude Code session id and caches it beside the grant file
17
+ * (`<dir of grant>/agenthub-capture-state/<claude session id>.json`). The
18
+ * Claude session id is read from the activity marker the PostToolUse hook
19
+ * writes.
20
+ *
21
+ * Anything else — no capture, consent refused, a missing or unreadable file —
22
+ * answers `undefined`, and the report is filed without a session, exactly as
23
+ * before. This never throws and never calls the network.
24
+ */
25
+ import * as fs from "fs";
26
+ import * as os from "os";
27
+ import * as path from "path";
28
+ import { readActivityMarker } from "./activityMarker.js";
29
+ export function currentCaptureSessionId(opts = {}) {
30
+ const env = opts.env ?? process.env;
31
+ const fromEnv = (env.AGENTHUB_SESSION_ID || "").trim();
32
+ if (fromEnv)
33
+ return fromEnv;
34
+ if (!opts.workingDir)
35
+ return undefined;
36
+ const claudeSessionId = readActivityMarker(opts.workingDir)?.session_id;
37
+ if (!claudeSessionId)
38
+ return undefined;
39
+ const grantPath = (env.AGENTHUB_CAPTURE_GRANT || "").trim() ||
40
+ path.join(opts.homeDir ?? os.homedir(), ".claude", "agenthub-capture.json");
41
+ // Same file name rule as session-capture.sh: os.sep replaced by "_".
42
+ const stateFile = path.join(path.dirname(grantPath), "agenthub-capture-state", claudeSessionId.split(path.sep).join("_") + ".json");
43
+ try {
44
+ const state = JSON.parse(fs.readFileSync(stateFile, "utf8"));
45
+ if (state.denied)
46
+ return undefined;
47
+ const id = typeof state.session_id === "string" ? state.session_id.trim() : "";
48
+ return id || undefined;
49
+ }
50
+ catch {
51
+ return undefined;
52
+ }
53
+ }
54
+ //# sourceMappingURL=currentCaptureSession.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currentCaptureSession.js","sourceRoot":"","sources":["../src/currentCaptureSession.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAQzD,MAAM,UAAU,uBAAuB,CAAC,OAAqC,EAAE;IAC7E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAEpC,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,IAAI,OAAO;QAAE,OAAO,OAAO,CAAC;IAE5B,IAAI,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IACvC,MAAM,eAAe,GAAG,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxE,IAAI,CAAC,eAAe;QAAE,OAAO,SAAS,CAAC;IAEvC,MAAM,SAAS,GACb,CAAC,GAAG,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QACzC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,uBAAuB,CAAC,CAAC;IAC9E,qEAAqE;IACrE,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CACzB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EACvB,wBAAwB,EACxB,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CACpD,CAAC;IACF,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAG1D,CAAC;QACF,IAAI,KAAK,CAAC,MAAM;YAAE,OAAO,SAAS,CAAC;QACnC,MAAM,EAAE,GAAG,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,OAAO,EAAE,IAAI,SAAS,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=currentCaptureSession.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currentCaptureSession.test.d.ts","sourceRoot":"","sources":["../src/currentCaptureSession.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "vitest";
2
+ import * as fs from "fs";
3
+ import * as os from "os";
4
+ import * as path from "path";
5
+ import { currentCaptureSessionId } from "./currentCaptureSession.js";
6
+ import { writeActivityMarker } from "./activityMarker.js";
7
+ let tmp;
8
+ let work;
9
+ let grant;
10
+ beforeEach(() => {
11
+ tmp = fs.mkdtempSync(path.join(os.tmpdir(), "agenthub-capsess-"));
12
+ work = path.join(tmp, "work");
13
+ fs.mkdirSync(work);
14
+ grant = path.join(tmp, "claude", "agenthub-capture.json");
15
+ });
16
+ afterEach(() => {
17
+ fs.rmSync(tmp, { recursive: true, force: true });
18
+ });
19
+ function writeState(claudeSid, state) {
20
+ const dir = path.join(path.dirname(grant), "agenthub-capture-state");
21
+ fs.mkdirSync(dir, { recursive: true });
22
+ fs.writeFileSync(path.join(dir, `${claudeSid}.json`), JSON.stringify(state));
23
+ }
24
+ describe("currentCaptureSessionId", () => {
25
+ it("prefers AGENTHUB_SESSION_ID (a daemon shift)", () => {
26
+ writeActivityMarker(work, "editing", { session_id: "claude-1", transcript_path: "/t" });
27
+ writeState("claude-1", { session_id: "from-state" });
28
+ const env = { AGENTHUB_SESSION_ID: " shift-sess ", AGENTHUB_CAPTURE_GRANT: grant };
29
+ expect(currentCaptureSessionId({ env, workingDir: work })).toBe("shift-sess");
30
+ });
31
+ it("reads the capture hook's cached session for the current Claude session", () => {
32
+ writeActivityMarker(work, "editing", { session_id: "claude-1", transcript_path: "/t" });
33
+ writeState("claude-1", { session_id: "cs-uuid-1", notice_text: "x" });
34
+ expect(currentCaptureSessionId({ env: { AGENTHUB_CAPTURE_GRANT: grant }, workingDir: work })).toBe("cs-uuid-1");
35
+ });
36
+ it("answers nothing when capture was refused", () => {
37
+ writeActivityMarker(work, "editing", { session_id: "claude-1", transcript_path: "/t" });
38
+ writeState("claude-1", { denied: true, session_id: "stale" });
39
+ expect(currentCaptureSessionId({ env: { AGENTHUB_CAPTURE_GRANT: grant }, workingDir: work })).toBeUndefined();
40
+ });
41
+ it("answers nothing with no marker, no state file, or no working dir", () => {
42
+ expect(currentCaptureSessionId({ env: { AGENTHUB_CAPTURE_GRANT: grant }, workingDir: work })).toBeUndefined();
43
+ writeActivityMarker(work, "editing", { session_id: "claude-2", transcript_path: "/t" });
44
+ expect(currentCaptureSessionId({ env: { AGENTHUB_CAPTURE_GRANT: grant }, workingDir: work })).toBeUndefined();
45
+ expect(currentCaptureSessionId({ env: {}, workingDir: null })).toBeUndefined();
46
+ });
47
+ it("uses ~/.claude/agenthub-capture.json when no grant path is set", () => {
48
+ const home = path.join(tmp, "home");
49
+ grant = path.join(home, ".claude", "agenthub-capture.json");
50
+ writeActivityMarker(work, "editing", { session_id: "claude-3", transcript_path: "/t" });
51
+ writeState("claude-3", { session_id: "cs-home" });
52
+ expect(currentCaptureSessionId({ env: {}, workingDir: work, homeDir: home })).toBe("cs-home");
53
+ });
54
+ });
55
+ //# sourceMappingURL=currentCaptureSession.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currentCaptureSession.test.js","sourceRoot":"","sources":["../src/currentCaptureSession.test.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAqD,MAAM,cAAc,CAAC;AAOrG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAkH/D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,iBAAiB,EAAE,MAAM,MAAM,CAAC;IAChC,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,MAAM,CAAC;IAC5B,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;OAGG;IACH,cAAc,EAAE,MAAM,WAAW,CAAC;IAClC,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,WAAW,CAAC;IACpC,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAC7B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,KAAK,IAAI,CAAC;CACZ;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAyLD,wBAAgB,aAAa,IAAI,IAAI,EAAE,CAohGtC;AAqCD,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,OAAO,CAAC,CAwyFlB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAqD,MAAM,cAAc,CAAC;AAOrG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAmH/D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,iBAAiB,EAAE,MAAM,MAAM,CAAC;IAChC,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,EAAE,MAAM,MAAM,CAAC;IAC5B,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;;OAGG;IACH,cAAc,EAAE,MAAM,WAAW,CAAC;IAClC,gDAAgD;IAChD,eAAe,CAAC,EAAE,MAAM,WAAW,CAAC;IACpC,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAC7B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;KACvB,KAAK,IAAI,CAAC;CACZ;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAyLD,wBAAgB,aAAa,IAAI,IAAI,EAAE,CAohGtC;AAqCD,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,WAAW,GACnB,OAAO,CAAC,OAAO,CAAC,CA6yFlB"}
@@ -26,6 +26,7 @@ import * as path from "node:path";
26
26
  import { describeSendResult } from "../messageIdempotency.js";
27
27
  import { readZohoAttachments } from "../zohoAttachments.js";
28
28
  import { isUnknownSendOutcome, unknownSendOutcomeError } from "../zohoSendOutcome.js";
29
+ import { currentCaptureSessionId } from "../currentCaptureSession.js";
29
30
  // fix-message-send-idempotency — shared by the four message tools.
30
31
  const IDEMPOTENCY_KEY_DESCRIPTION = "Optional. Leave unset: a key derived from the message content is sent, so " +
31
32
  "re-issuing this exact call (e.g. after a timeout) never delivers it twice. " +
@@ -2461,13 +2462,13 @@ export function registerTools() {
2461
2462
  // Session handoff tools (add-session-handoff)
2462
2463
  {
2463
2464
  name: "session_close_report",
2464
- description: "Upload a session-close handoff report to AgentHub. Call this at the end of every session after running the close-session skill. Shares what shipped + what the next session should pick up, so /start-session on the next run (any machine) can resume cleanly.",
2465
+ description: "Upload a session-close handoff report to AgentHub. Call this at the end of every session after running the close-session skill. Shares what shipped + what the next session should pick up, so /start-session on the next run (any machine) can resume cleanly. The reply carries `display_number` (the report's own `h-YYYYMMDD-NNN`, always) and `session_display_number` (the captured coding session's `s-YYYYMMDD-NNN`, only when this session is captured).",
2465
2466
  inputSchema: {
2466
2467
  type: "object",
2467
2468
  properties: {
2468
2469
  summary: { type: "string", description: "Markdown summary of what shipped this session" },
2469
2470
  next_plan: { type: "string", description: "Markdown of what the next session should pick up" },
2470
- session_id: { type: "string", description: "Optional session UUID or display number `s-YYYYMMDD-NNN` for upsert keying. Server resolves either form to the canonical UUID before storing." },
2471
+ session_id: { type: "string", description: "Optional session UUID or display number `s-YYYYMMDD-NNN` for upsert keying. Server resolves either form to the canonical UUID before storing. Omit it normally: when this session is being captured, the tool attaches the capture session itself." },
2471
2472
  commits: {
2472
2473
  type: "array",
2473
2474
  description: "Commits pushed this session",
@@ -5348,8 +5349,12 @@ export async function handleToolCall(name, args, client, context) {
5348
5349
  summary,
5349
5350
  next_plan: nextPlan,
5350
5351
  };
5351
- if (args.session_id)
5352
- body.session_id = args.session_id;
5352
+ // add-session-report-numbers: a caller's session_id wins; otherwise link
5353
+ // the session this work is being captured into, when there is one.
5354
+ const sessionId = args.session_id ||
5355
+ currentCaptureSessionId({ workingDir: context.getWorkingDir() });
5356
+ if (sessionId)
5357
+ body.session_id = sessionId;
5353
5358
  if (args.commits)
5354
5359
  body.commits = args.commits;
5355
5360
  if (args.open_threads)