switchroom 0.14.77 → 0.14.78

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.
@@ -18,21 +18,45 @@ if [ -f "$MARKER" ]; then
18
18
  fi
19
19
  # Fire-and-forget refresh via MCP. Timeout bounded by Claude Code hook.
20
20
  # Output nothing on success or failure; errors are surfaced via doctor.
21
+ #
22
+ # Two bugs this fixes (2026-06-07):
23
+ # 1. The Hindsight server is STATELESS (HINDSIGHT_API_MCP_STATELESS=true) and
24
+ # returns NO mcp-session-id header, so the old code's `[ -n "$SESSION" ]`
25
+ # gate was ALWAYS false → the refresh NEVER fired. Stateless MCP needs no
26
+ # session — drop the gate (mirrors src/memory/hindsight.ts, which tolerates
27
+ # a missing session id).
28
+ # 2. refresh_mental_model takes `mental_model_id` (a UUID), NOT `name`. Passing
29
+ # `name` returns isError "Missing required argument: mental_model_id". So we
30
+ # list_mental_models, resolve the `user-profile` model's id, then refresh
31
+ # by id.
21
32
  {
22
- # JSON-RPC flow: initialize tools/call refresh_mental_model
23
- SESSION=$(curl -sS -X POST "$API_URL/mcp/" \
33
+ # initialize (no session id needed on the stateless server).
34
+ curl -sS -X POST "$API_URL/mcp/" \
24
35
  -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
25
- -H "X-Bank-Id: $BANK_ID" -D /tmp/mm-refresh-$$.headers \
36
+ -H "X-Bank-Id: $BANK_ID" \
26
37
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"mm-refresh","version":"0.1"}}}' \
27
- -m 3 -o /dev/null 2>/dev/null && grep -i mcp-session-id /tmp/mm-refresh-$$.headers | cut -d' ' -f2 | tr -d '\r\n')
28
- if [ -n "$SESSION" ]; then
38
+ -m 3 -o /dev/null 2>/dev/null || true
39
+
40
+ # Resolve the user-profile mental model's id (refresh is by id, not name).
41
+ # list_mental_models returns the items as a JSON STRING nested in
42
+ # .result.structuredContent.result, so parse with jq (fromjson). The agent
43
+ # image ships jq; if it's somehow absent, MM_ID stays empty → skip (the next
44
+ # Stop fires it again; fire-and-forget, no wedge).
45
+ MM_ID=$(curl -sS -X POST "$API_URL/mcp/" \
46
+ -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
47
+ -H "X-Bank-Id: $BANK_ID" \
48
+ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"list_mental_models","arguments":{}}}' \
49
+ -m 5 2>/dev/null \
50
+ | grep '^data:' | sed 's/^data: //' \
51
+ | jq -r '.result.structuredContent.result | fromjson | .items[] | select(.name=="user-profile") | .id' 2>/dev/null | head -1)
52
+
53
+ if [ -n "$MM_ID" ]; then
29
54
  curl -sS -X POST "$API_URL/mcp/" \
30
55
  -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
31
- -H "X-Bank-Id: $BANK_ID" -H "mcp-session-id: $SESSION" \
32
- -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"refresh_mental_model","arguments":{"name":"user-profile"}}}' \
56
+ -H "X-Bank-Id: $BANK_ID" \
57
+ -d "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\"params\":{\"name\":\"refresh_mental_model\",\"arguments\":{\"mental_model_id\":\"$MM_ID\"}}}" \
33
58
  -m 5 -o /dev/null 2>/dev/null || true
34
59
  fi
35
- rm -f /tmp/mm-refresh-$$.headers 2>/dev/null || true
36
60
  date +%s > "$MARKER"
37
61
  } &
38
62
  exit 0
@@ -14987,7 +14987,7 @@ async function ensureUserProfileMentalModel(apiUrl, bankId, opts) {
14987
14987
  name: "create_mental_model",
14988
14988
  arguments: {
14989
14989
  name: "user-profile",
14990
- query: "What are the key facts, preferences, context, and communication style about the user I talk to? Summarize what matters for making the agent feel like it knows them.",
14990
+ source_query: "What are the key facts, preferences, context, and communication style about the user I talk to? Summarize what matters for making the agent feel like it knows them.",
14991
14991
  types: ["world", "experience"]
14992
14992
  }
14993
14993
  }
@@ -14998,6 +14998,13 @@ async function ensureUserProfileMentalModel(apiUrl, bankId, opts) {
14998
14998
  if (!createResponse.ok) {
14999
14999
  return { ok: false, reason: `Create MM HTTP ${createResponse.status}` };
15000
15000
  }
15001
+ try {
15002
+ const created = await parseSseOrJson(createResponse);
15003
+ if (created.result?.isError === true) {
15004
+ const msg = created.result.content?.[0]?.text ?? "create returned isError";
15005
+ return { ok: false, reason: msg };
15006
+ }
15007
+ } catch {}
15001
15008
  return { ok: true };
15002
15009
  } catch (err) {
15003
15010
  if (err.name === "AbortError") {
@@ -15204,6 +15211,13 @@ async function addMemoryTag(apiUrl, bankId, memoryId, tag, opts) {
15204
15211
  if (!toolResponse.ok) {
15205
15212
  return { ok: false, reason: `Tool call HTTP ${toolResponse.status}` };
15206
15213
  }
15214
+ try {
15215
+ const parsed = await parseSseOrJson(toolResponse);
15216
+ if (parsed.result?.isError === true) {
15217
+ const msg = parsed.result.content?.[0]?.text ?? "tool returned isError";
15218
+ return { ok: false, reason: msg };
15219
+ }
15220
+ } catch {}
15207
15221
  return { ok: true };
15208
15222
  } catch (err) {
15209
15223
  if (err.name === "AbortError") {
@@ -49681,8 +49695,8 @@ var {
49681
49695
  } = import__.default;
49682
49696
 
49683
49697
  // src/build-info.ts
49684
- var VERSION = "0.14.77";
49685
- var COMMIT_SHA = "2473dbbf";
49698
+ var VERSION = "0.14.78";
49699
+ var COMMIT_SHA = "ac0dae98";
49686
49700
 
49687
49701
  // src/cli/agent.ts
49688
49702
  init_source();
@@ -59174,9 +59188,8 @@ function makeHttpHindsightClient(apiUrl, opts) {
59174
59188
  });
59175
59189
  return { items: res.items ?? [], total: res.total ?? 0 };
59176
59190
  },
59177
- async deleteMemory(bankId, memoryId) {
59178
- const sid = await initSession(bankId);
59179
- await callTool(bankId, sid, "delete_memory", { bank_id: bankId, memory_id: memoryId });
59191
+ async deleteMemory(_bankId, _memoryId) {
59192
+ throw new Error("hindsight exposes no single-memory delete API (delete_memory is not a " + "real tool; a memory id is not a document_id) \u2014 matched secrets cannot " + "be auto-scrubbed; redact manually via the bank UI");
59180
59193
  }
59181
59194
  };
59182
59195
  }
@@ -59206,11 +59219,18 @@ ${mem.context ?? ""}`;
59206
59219
  }
59207
59220
  let deleted = 0;
59208
59221
  if (!opts.dryRun) {
59222
+ let warnedOnce = false;
59209
59223
  for (const m of matched) {
59210
59224
  try {
59211
59225
  await client.deleteMemory(bankId, m.id);
59212
59226
  deleted++;
59213
- } catch {}
59227
+ } catch (err) {
59228
+ if (!warnedOnce) {
59229
+ warnedOnce = true;
59230
+ process.stderr.write(`vault-sweep: ${matched.length} secret(s) matched in bank '${bankId}' but ` + `could NOT be auto-deleted: ${err.message}
59231
+ `);
59232
+ }
59233
+ }
59214
59234
  }
59215
59235
  }
59216
59236
  return { matched, deleted };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "switchroom",
3
- "version": "0.14.77",
3
+ "version": "0.14.78",
4
4
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -52821,11 +52821,11 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
52821
52821
  }
52822
52822
 
52823
52823
  // ../src/build-info.ts
52824
- var VERSION = "0.14.77";
52825
- var COMMIT_SHA = "2473dbbf";
52826
- var COMMIT_DATE = "2026-06-07T00:02:11+10:00";
52824
+ var VERSION = "0.14.78";
52825
+ var COMMIT_SHA = "ac0dae98";
52826
+ var COMMIT_DATE = "2026-06-07T09:07:56+10:00";
52827
52827
  var LATEST_PR = null;
52828
- var COMMITS_AHEAD_OF_TAG = 4;
52828
+ var COMMITS_AHEAD_OF_TAG = 3;
52829
52829
 
52830
52830
  // gateway/boot-version.ts
52831
52831
  function formatRelativeAgo(iso) {