switchroom 0.17.6 → 0.17.10

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 (155) hide show
  1. package/dist/agent-scheduler/index.js +38 -4
  2. package/dist/auth-broker/index.js +302 -203
  3. package/dist/cli/notion-write-pretool.mjs +35 -2
  4. package/dist/cli/switchroom.js +1178 -576
  5. package/dist/host-control/main.js +148 -14
  6. package/dist/vault/approvals/kernel-server.js +140 -55
  7. package/dist/vault/broker/server.js +142 -57
  8. package/package.json +1 -1
  9. package/profiles/_base/start.sh.hbs +50 -6
  10. package/profiles/default/CLAUDE.md +116 -0
  11. package/skills/mental-model-curator/SKILL.md +162 -0
  12. package/telegram-plugin/bridge/bridge.ts +80 -1
  13. package/telegram-plugin/bridge/ipc-client.ts +19 -0
  14. package/telegram-plugin/bridge/permission-ledger.ts +61 -0
  15. package/telegram-plugin/consolidation-legibility.ts +279 -0
  16. package/telegram-plugin/dist/bridge/bridge.js +85 -1
  17. package/telegram-plugin/dist/gateway/gateway.js +2565 -610
  18. package/telegram-plugin/dist/server.js +86 -2
  19. package/telegram-plugin/feed-heartbeat-climb.ts +206 -0
  20. package/telegram-plugin/gateway/activity-card-store.ts +293 -0
  21. package/telegram-plugin/gateway/gateway.ts +1376 -82
  22. package/telegram-plugin/gateway/inbound-spool.ts +22 -0
  23. package/telegram-plugin/gateway/mental-model-propose-card.ts +69 -0
  24. package/telegram-plugin/gateway/mental-model-propose-diff.ts +171 -0
  25. package/telegram-plugin/gateway/mental-model-propose-inbound-builders.ts +147 -0
  26. package/telegram-plugin/gateway/mental-model-propose-resolve.ts +201 -0
  27. package/telegram-plugin/gateway/missed-approvals-card.ts +161 -0
  28. package/telegram-plugin/gateway/missed-approvals-store.ts +167 -0
  29. package/telegram-plugin/gateway/permission-rearm.ts +115 -0
  30. package/telegram-plugin/gateway/scoped-grant-store.ts +89 -0
  31. package/telegram-plugin/memory-legibility.ts +217 -0
  32. package/telegram-plugin/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  33. package/telegram-plugin/scoped-approval.ts +59 -0
  34. package/telegram-plugin/silent-end.ts +78 -0
  35. package/telegram-plugin/subagent-watcher.ts +60 -6
  36. package/telegram-plugin/tests/activity-card-store.test.ts +436 -0
  37. package/telegram-plugin/tests/activity-card-wiring.test.ts +88 -0
  38. package/telegram-plugin/tests/consolidation-legibility.test.ts +224 -0
  39. package/telegram-plugin/tests/emission-authority-facade.test.ts +25 -10
  40. package/telegram-plugin/tests/feed-heartbeat-liveness-open.test.ts +33 -9
  41. package/telegram-plugin/tests/gateway-boot-marker-clear.test.ts +3 -3
  42. package/telegram-plugin/tests/inbound-spool.test.ts +105 -0
  43. package/telegram-plugin/tests/memory-legibility.test.ts +216 -0
  44. package/telegram-plugin/tests/mental-model-propose-callback-gate.test.ts +67 -0
  45. package/telegram-plugin/tests/mental-model-propose-card.test.ts +56 -0
  46. package/telegram-plugin/tests/mental-model-propose-diff.test.ts +201 -0
  47. package/telegram-plugin/tests/mental-model-propose-inbound-builders.test.ts +68 -0
  48. package/telegram-plugin/tests/mental-model-propose-resolve.test.ts +157 -0
  49. package/telegram-plugin/tests/missed-approvals-card.test.ts +145 -0
  50. package/telegram-plugin/tests/missed-approvals-store.test.ts +147 -0
  51. package/telegram-plugin/tests/missed-approvals-wiring.test.ts +89 -0
  52. package/telegram-plugin/tests/permission-ledger.test.ts +166 -0
  53. package/telegram-plugin/tests/permission-no-repeat-wiring.test.ts +1 -1
  54. package/telegram-plugin/tests/permission-rearm-wiring.test.ts +175 -0
  55. package/telegram-plugin/tests/permission-rearm.test.ts +126 -0
  56. package/telegram-plugin/tests/scoped-grant-persist.test.ts +223 -0
  57. package/telegram-plugin/tests/silent-end-transport.test.ts +290 -0
  58. package/telegram-plugin/tests/silent-turn-climb-transport.test.ts +337 -0
  59. package/telegram-plugin/tests/subagent-watcher.test.ts +139 -0
  60. package/telegram-plugin/tests/worktree-watch-cwds.test.ts +103 -0
  61. package/telegram-plugin/uat/assertions.ts +88 -4
  62. package/telegram-plugin/uat/feed-matcher.test.ts +69 -0
  63. package/telegram-plugin/uat/scenarios/fuzz-liveness-climb-dm.test.ts +155 -0
  64. package/telegram-plugin/uat/scenarios/jtbd-directive-capture-nudge-dm.test.ts +185 -0
  65. package/telegram-plugin/uat/scenarios/jtbd-liveness-climb-channel.test.ts +192 -0
  66. package/telegram-plugin/uat/scenarios/jtbd-liveness-climb-dm.test.ts +220 -0
  67. package/telegram-plugin/uat/scenarios/jtbd-liveness-narration-channel.test.ts +137 -0
  68. package/telegram-plugin/uat/scenarios/jtbd-liveness-narration-dm.test.ts +148 -0
  69. package/telegram-plugin/uat/scenarios/jtbd-memory-legibility-channel.test.ts +66 -0
  70. package/telegram-plugin/uat/scenarios/jtbd-memory-legibility-dm.test.ts +61 -0
  71. package/telegram-plugin/uat/scenarios/silent-end-recovery-channel.test.ts +136 -0
  72. package/telegram-plugin/uat/scenarios/silent-end-recovery-dm.test.ts +24 -2
  73. package/telegram-plugin/worktree-watch-cwds.ts +60 -0
  74. package/vendor/hindsight-memory/hooks/hooks.json +9 -0
  75. package/vendor/hindsight-memory/scripts/__pycache__/directive_verify.cpython-313.pyc +0 -0
  76. package/vendor/hindsight-memory/scripts/__pycache__/drain_pending.cpython-313.pyc +0 -0
  77. package/vendor/hindsight-memory/scripts/__pycache__/recall.cpython-313.pyc +0 -0
  78. package/vendor/hindsight-memory/scripts/__pycache__/retain.cpython-313.pyc +0 -0
  79. package/vendor/hindsight-memory/scripts/__pycache__/session_end.cpython-313.pyc +0 -0
  80. package/vendor/hindsight-memory/scripts/directive_verify.py +445 -0
  81. package/vendor/hindsight-memory/scripts/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  82. package/vendor/hindsight-memory/scripts/lib/__pycache__/bank.cpython-313.pyc +0 -0
  83. package/vendor/hindsight-memory/scripts/lib/__pycache__/client.cpython-313.pyc +0 -0
  84. package/vendor/hindsight-memory/scripts/lib/__pycache__/config.cpython-313.pyc +0 -0
  85. package/vendor/hindsight-memory/scripts/lib/__pycache__/content.cpython-313.pyc +0 -0
  86. package/vendor/hindsight-memory/scripts/lib/__pycache__/daemon.cpython-313.pyc +0 -0
  87. package/vendor/hindsight-memory/scripts/lib/__pycache__/directives.cpython-313.pyc +0 -0
  88. package/vendor/hindsight-memory/scripts/lib/__pycache__/gateway_ipc.cpython-313.pyc +0 -0
  89. package/vendor/hindsight-memory/scripts/lib/__pycache__/llm.cpython-313.pyc +0 -0
  90. package/vendor/hindsight-memory/scripts/lib/__pycache__/pending.cpython-313.pyc +0 -0
  91. package/vendor/hindsight-memory/scripts/lib/__pycache__/state.cpython-313.pyc +0 -0
  92. package/vendor/hindsight-memory/scripts/lib/__pycache__/switchroom_envelope.cpython-313.pyc +0 -0
  93. package/vendor/hindsight-memory/scripts/lib/config.py +37 -0
  94. package/vendor/hindsight-memory/scripts/lib/directives.py +88 -0
  95. package/vendor/hindsight-memory/scripts/lib/switchroom_envelope.py +77 -0
  96. package/vendor/hindsight-memory/scripts/recall.py +153 -4
  97. package/vendor/hindsight-memory/scripts/retain.py +17 -0
  98. package/vendor/hindsight-memory/scripts/setup_hooks.py +9 -0
  99. package/vendor/hindsight-memory/scripts/tests/__pycache__/__init__.cpython-313.pyc +0 -0
  100. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_config_client_casts.cpython-313-pytest-9.1.1.pyc +0 -0
  101. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_config_client_casts.cpython-313.pyc +0 -0
  102. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_capture_nudge.cpython-313-pytest-9.1.1.pyc +0 -0
  103. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_capture_nudge.cpython-313.pyc +0 -0
  104. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_verify.cpython-313-pytest-9.1.1.pyc +0 -0
  105. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directive_verify.cpython-313.pyc +0 -0
  106. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directives.cpython-313-pytest-9.1.1.pyc +0 -0
  107. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_directives.cpython-313.pyc +0 -0
  108. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_gateway_ipc.cpython-313-pytest-9.1.1.pyc +0 -0
  109. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_gateway_ipc.cpython-313.pyc +0 -0
  110. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_context_slice.cpython-313-pytest-9.1.1.pyc +0 -0
  111. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_context_slice.cpython-313.pyc +0 -0
  112. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_integration.cpython-313-pytest-9.1.1.pyc +0 -0
  113. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_integration.cpython-313.pyc +0 -0
  114. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_tag_filters.cpython-313-pytest-9.1.1.pyc +0 -0
  115. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_tag_filters.cpython-313.pyc +0 -0
  116. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_topic_filter.cpython-313-pytest-9.1.1.pyc +0 -0
  117. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_topic_filter.cpython-313.pyc +0 -0
  118. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_trivial_skip.cpython-313-pytest-9.1.1.pyc +0 -0
  119. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_recall_trivial_skip.cpython-313.pyc +0 -0
  120. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_retain_window.cpython-313-pytest-9.1.1.pyc +0 -0
  121. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_retain_window.cpython-313.pyc +0 -0
  122. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_sender_routing.cpython-313-pytest-9.1.1.pyc +0 -0
  123. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_sender_routing.cpython-313.pyc +0 -0
  124. package/vendor/hindsight-memory/scripts/tests/__pycache__/test_switchroom_envelope.cpython-313-pytest-9.1.1.pyc +0 -0
  125. package/vendor/hindsight-memory/scripts/tests/test_directive_capture_nudge.py +185 -0
  126. package/vendor/hindsight-memory/scripts/tests/test_directive_verify.py +516 -0
  127. package/vendor/hindsight-memory/scripts/tests/test_directives.py +49 -0
  128. package/vendor/hindsight-memory/scripts/tests/test_retain_window.py +66 -1
  129. package/vendor/hindsight-memory/scripts/tests/test_switchroom_envelope.py +69 -0
  130. package/vendor/hindsight-memory/tests/__pycache__/conftest.cpython-313-pytest-9.0.3.pyc +0 -0
  131. package/vendor/hindsight-memory/tests/__pycache__/conftest.cpython-313-pytest-9.1.1.pyc +0 -0
  132. package/vendor/hindsight-memory/tests/__pycache__/test_bank.cpython-313-pytest-9.1.1.pyc +0 -0
  133. package/vendor/hindsight-memory/tests/__pycache__/test_bank.cpython-313.pyc +0 -0
  134. package/vendor/hindsight-memory/tests/__pycache__/test_client.cpython-313-pytest-9.1.1.pyc +0 -0
  135. package/vendor/hindsight-memory/tests/__pycache__/test_client.cpython-313.pyc +0 -0
  136. package/vendor/hindsight-memory/tests/__pycache__/test_config.cpython-313-pytest-9.0.3.pyc +0 -0
  137. package/vendor/hindsight-memory/tests/__pycache__/test_config.cpython-313-pytest-9.1.1.pyc +0 -0
  138. package/vendor/hindsight-memory/tests/__pycache__/test_config.cpython-313.pyc +0 -0
  139. package/vendor/hindsight-memory/tests/__pycache__/test_content.cpython-313-pytest-9.1.1.pyc +0 -0
  140. package/vendor/hindsight-memory/tests/__pycache__/test_content.cpython-313.pyc +0 -0
  141. package/vendor/hindsight-memory/tests/__pycache__/test_drain_pending.cpython-313-pytest-9.1.1.pyc +0 -0
  142. package/vendor/hindsight-memory/tests/__pycache__/test_drain_pending.cpython-313.pyc +0 -0
  143. package/vendor/hindsight-memory/tests/__pycache__/test_hooks.cpython-313-pytest-9.1.1.pyc +0 -0
  144. package/vendor/hindsight-memory/tests/__pycache__/test_hooks.cpython-313.pyc +0 -0
  145. package/vendor/hindsight-memory/tests/__pycache__/test_manifest.cpython-313-pytest-9.1.1.pyc +0 -0
  146. package/vendor/hindsight-memory/tests/__pycache__/test_manifest.cpython-313.pyc +0 -0
  147. package/vendor/hindsight-memory/tests/__pycache__/test_pending.cpython-313-pytest-9.1.1.pyc +0 -0
  148. package/vendor/hindsight-memory/tests/__pycache__/test_pending.cpython-313.pyc +0 -0
  149. package/vendor/hindsight-memory/tests/__pycache__/test_recall_exit_codes.cpython-313-pytest-9.1.1.pyc +0 -0
  150. package/vendor/hindsight-memory/tests/__pycache__/test_recall_exit_codes.cpython-313.pyc +0 -0
  151. package/vendor/hindsight-memory/tests/__pycache__/test_session_end_pending.cpython-313-pytest-9.1.1.pyc +0 -0
  152. package/vendor/hindsight-memory/tests/__pycache__/test_session_end_pending.cpython-313.pyc +0 -0
  153. package/vendor/hindsight-memory/tests/__pycache__/test_state.cpython-313-pytest-9.1.1.pyc +0 -0
  154. package/vendor/hindsight-memory/tests/__pycache__/test_state.cpython-313.pyc +0 -0
  155. package/vendor/hindsight-memory/tests/test_recall_exit_codes.py +49 -2
@@ -1,5 +1,34 @@
1
1
  import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
2
4
  var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
12
+ var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
20
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
21
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
+ for (let key of __getOwnPropNames(mod))
23
+ if (!__hasOwnProp.call(to, key))
24
+ __defProp(to, key, {
25
+ get: __accessProp.bind(mod, key),
26
+ enumerable: true
27
+ });
28
+ if (canCache)
29
+ cache.set(mod, to);
30
+ return to;
31
+ };
3
32
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
4
33
  var __returnValue = (v) => v;
5
34
  function __exportSetter(name, newValue) {
@@ -14,6 +43,7 @@ var __export = (target, all) => {
14
43
  set: __exportSetter.bind(all, name)
15
44
  });
16
45
  };
46
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
47
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
18
48
 
19
49
  // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/nodes/identity.js
@@ -6931,60 +6961,99 @@ var require_public_api = __commonJS((exports) => {
6931
6961
  exports.stringify = stringify;
6932
6962
  });
6933
6963
 
6964
+ // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/index.js
6965
+ var require_dist = __commonJS((exports) => {
6966
+ var composer = require_composer();
6967
+ var Document = require_Document();
6968
+ var Schema = require_Schema();
6969
+ var errors = require_errors();
6970
+ var Alias = require_Alias();
6971
+ var identity = require_identity();
6972
+ var Pair = require_Pair();
6973
+ var Scalar = require_Scalar();
6974
+ var YAMLMap = require_YAMLMap();
6975
+ var YAMLSeq = require_YAMLSeq();
6976
+ var cst = require_cst();
6977
+ var lexer = require_lexer();
6978
+ var lineCounter = require_line_counter();
6979
+ var parser = require_parser();
6980
+ var publicApi = require_public_api();
6981
+ var visit = require_visit();
6982
+ exports.Composer = composer.Composer;
6983
+ exports.Document = Document.Document;
6984
+ exports.Schema = Schema.Schema;
6985
+ exports.YAMLError = errors.YAMLError;
6986
+ exports.YAMLParseError = errors.YAMLParseError;
6987
+ exports.YAMLWarning = errors.YAMLWarning;
6988
+ exports.Alias = Alias.Alias;
6989
+ exports.isAlias = identity.isAlias;
6990
+ exports.isCollection = identity.isCollection;
6991
+ exports.isDocument = identity.isDocument;
6992
+ exports.isMap = identity.isMap;
6993
+ exports.isNode = identity.isNode;
6994
+ exports.isPair = identity.isPair;
6995
+ exports.isScalar = identity.isScalar;
6996
+ exports.isSeq = identity.isSeq;
6997
+ exports.Pair = Pair.Pair;
6998
+ exports.Scalar = Scalar.Scalar;
6999
+ exports.YAMLMap = YAMLMap.YAMLMap;
7000
+ exports.YAMLSeq = YAMLSeq.YAMLSeq;
7001
+ exports.CST = cst;
7002
+ exports.Lexer = lexer.Lexer;
7003
+ exports.LineCounter = lineCounter.LineCounter;
7004
+ exports.Parser = parser.Parser;
7005
+ exports.parse = publicApi.parse;
7006
+ exports.parseAllDocuments = publicApi.parseAllDocuments;
7007
+ exports.parseDocument = publicApi.parseDocument;
7008
+ exports.stringify = publicApi.stringify;
7009
+ exports.visit = visit.visit;
7010
+ exports.visitAsync = visit.visitAsync;
7011
+ });
7012
+
7013
+ // src/util/atomic.ts
7014
+ import { randomBytes } from "node:crypto";
7015
+ import { closeSync, constants, fsyncSync, openSync, renameSync, rmSync, writeSync } from "node:fs";
7016
+ function atomicWriteFileSync(destPath, contents, mode = 384) {
7017
+ const tmp = `${destPath}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;
7018
+ const buf = typeof contents === "string" ? Buffer.from(contents, "utf-8") : contents;
7019
+ let fd = null;
7020
+ try {
7021
+ fd = openSync(tmp, TMP_OPEN_FLAGS, mode);
7022
+ writeSync(fd, buf, 0, buf.length, 0);
7023
+ fsyncSync(fd);
7024
+ closeSync(fd);
7025
+ fd = null;
7026
+ renameSync(tmp, destPath);
7027
+ } catch (err) {
7028
+ if (fd !== null) {
7029
+ try {
7030
+ closeSync(fd);
7031
+ } catch {}
7032
+ }
7033
+ try {
7034
+ rmSync(tmp, { force: true });
7035
+ } catch {}
7036
+ throw err;
7037
+ }
7038
+ }
7039
+ function atomicWriteJsonSync(destPath, value, mode = 384) {
7040
+ atomicWriteFileSync(destPath, JSON.stringify(value, null, 2) + `
7041
+ `, mode);
7042
+ }
7043
+ var TMP_OPEN_FLAGS;
7044
+ var init_atomic = __esm(() => {
7045
+ TMP_OPEN_FLAGS = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0);
7046
+ });
7047
+
6934
7048
  // src/auth/broker/index.ts
6935
7049
  import { existsSync as existsSync8, readFileSync as readFileSync7 } from "node:fs";
6936
7050
 
6937
7051
  // src/config/loader.ts
7052
+ var import_yaml2 = __toESM(require_dist(), 1);
6938
7053
  import { readFileSync as readFileSync2, existsSync as existsSync3 } from "node:fs";
6939
7054
  import { homedir } from "node:os";
6940
7055
  import { resolve as resolve3 } from "node:path";
6941
7056
 
6942
- // node_modules/.bun/yaml@2.8.3/node_modules/yaml/dist/index.js
6943
- var composer = require_composer();
6944
- var Document = require_Document();
6945
- var Schema = require_Schema();
6946
- var errors = require_errors();
6947
- var Alias = require_Alias();
6948
- var identity = require_identity();
6949
- var Pair = require_Pair();
6950
- var Scalar = require_Scalar();
6951
- var YAMLMap = require_YAMLMap();
6952
- var YAMLSeq = require_YAMLSeq();
6953
- var cst = require_cst();
6954
- var lexer = require_lexer();
6955
- var lineCounter = require_line_counter();
6956
- var parser = require_parser();
6957
- var publicApi = require_public_api();
6958
- var visit = require_visit();
6959
- var $Composer = composer.Composer;
6960
- var $Document = Document.Document;
6961
- var $Schema = Schema.Schema;
6962
- var $YAMLError = errors.YAMLError;
6963
- var $YAMLParseError = errors.YAMLParseError;
6964
- var $YAMLWarning = errors.YAMLWarning;
6965
- var $Alias = Alias.Alias;
6966
- var $isAlias = identity.isAlias;
6967
- var $isCollection = identity.isCollection;
6968
- var $isDocument = identity.isDocument;
6969
- var $isMap = identity.isMap;
6970
- var $isNode = identity.isNode;
6971
- var $isPair = identity.isPair;
6972
- var $isScalar = identity.isScalar;
6973
- var $isSeq = identity.isSeq;
6974
- var $Pair = Pair.Pair;
6975
- var $Scalar = Scalar.Scalar;
6976
- var $YAMLMap = YAMLMap.YAMLMap;
6977
- var $YAMLSeq = YAMLSeq.YAMLSeq;
6978
- var $Lexer = lexer.Lexer;
6979
- var $LineCounter = lineCounter.LineCounter;
6980
- var $Parser = parser.Parser;
6981
- var $parse = publicApi.parse;
6982
- var $parseAllDocuments = publicApi.parseAllDocuments;
6983
- var $parseDocument = publicApi.parseDocument;
6984
- var $stringify = publicApi.stringify;
6985
- var $visit = visit.visit;
6986
- var $visitAsync = visit.visitAsync;
6987
-
6988
7057
  // node_modules/.bun/zod@3.25.76/node_modules/zod/v3/external.js
6989
7058
  var exports_external = {};
6990
7059
  __export(exports_external, {
@@ -11070,8 +11139,35 @@ var AgentMemorySchema = exports_external.object({
11070
11139
  auto_recall: exports_external.boolean().default(true).describe("Auto-search memories before each response"),
11071
11140
  file: exports_external.boolean().default(true).describe("Maintain a curated workspace MEMORY.md file (seeded once, " + "auto-loaded every turn). Set false for hindsight-only memory: " + "the file is not seeded or re-created, so once migrated into " + "Hindsight and deleted it stays gone. Recall + directives carry " + "the memory instead. Cascade: override (per-agent wins over default)."),
11072
11141
  isolation: exports_external.enum(["default", "strict"]).default("default").describe("strict = never shared cross-agent, default = eligible for reflect"),
11073
- bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize results"),
11074
- retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain"),
11142
+ bank_mission: exports_external.string().optional().describe("Bank-level mission statement used during recall to contextualize " + "results. NOTE: this is an alias for the Hindsight engine's " + "`reflect_mission` field (verified live: switchroom's bank_mission " + "lands in `config.reflect_mission`). Prefer `reflect_mission` going " + "forward; `bank_mission` is retained for back-compat. If both are " + "set, `reflect_mission` wins. Cascade: override."),
11143
+ reflect_mission: exports_external.string().optional().describe("Mission/context steering Hindsight Reflect operations (the bank's " + "'who am I / what matters' framing applied during recall). The " + "engine-accurate name for what `bank_mission` sets. Cascade: override."),
11144
+ retain_mission: exports_external.string().optional().describe("Instructions for the fact extraction LLM during retain. Cascade: override."),
11145
+ mental_models: exports_external.array(exports_external.object({
11146
+ name: exports_external.string().min(1).describe("Stable model name (identity key for idempotent ensure). Two " + "declarations with the same name in one agent are rejected."),
11147
+ source_query: exports_external.string().min(1).max(2000).describe("The reflection query the model answers, semantically " + "refreshed from the bank's content. Capped at 2000 chars — a " + "standing reflection query, not a document; the ceiling also " + "bounds what an agent-proposed model can smuggle past the " + "operator approval card."),
11148
+ refresh_after_consolidation: exports_external.boolean().optional().describe("Refresh this model after each consolidation. Defaults OFF — " + "refresh adds bounded background model-spend + timeout risk " + "(RFC Phase 5), so it is opt-in per model."),
11149
+ max_tokens: exports_external.number().int().positive().max(8192).optional().describe("Cap on the synthesized model's token size. Upper-bounded at " + "8192 — a mental model is a standing summary, not a corpus; the " + "ceiling also caps what an agent-proposed model can request.")
11150
+ })).superRefine((models, ctx) => {
11151
+ const seen = new Set;
11152
+ for (let i = 0;i < models.length; i++) {
11153
+ const key = models[i].name;
11154
+ if (seen.has(key)) {
11155
+ ctx.addIssue({
11156
+ code: exports_external.ZodIssueCode.custom,
11157
+ path: [i, "name"],
11158
+ message: `duplicate mental_models name "${key}" — model names must be ` + `unique within an agent (they are the idempotent-ensure key)`
11159
+ });
11160
+ }
11161
+ seen.add(key);
11162
+ }
11163
+ }).optional().describe("Operator-declared, per-specialist Hindsight mental models (RFC " + "Phase 5). Named, opt-in curated reflections this agent's bank should " + "carry — e.g. a coach's 'training-plan-state' or a lawyer's " + "'open-matters'. Ensured idempotently at scaffold/reconcile: NOTHING " + "is created unless declared here (zero declarations = zero models, " + "matching post-#2447 behaviour), and no fixed identity model is " + "reintroduced — 'who the user is' stays owned by dedicated profile " + "banks (users.*.profile_bank), never a per-agent model. Per-agent " + "ONLY: intentionally not accepted at the defaults/profile tier, so a " + "model can never be fleet-seeded — each specialist opts in on its own " + "(the invariant-clean inverse of the retired blind auto-seeding)."),
11164
+ observations_mission: exports_external.string().optional().describe("Steers what the observation-consolidation LLM synthesises from raw " + "facts (the higher-order 'what patterns matter' lens). Cascade: override."),
11165
+ disposition: exports_external.object({
11166
+ skepticism: exports_external.number().int().min(1).max(5).optional().describe("How much the bank doubts unverified claims (1-5; engine default 3)."),
11167
+ literalism: exports_external.number().int().min(1).max(5).optional().describe("How literally the bank reads statements vs inferring intent (1-5; engine default 3)."),
11168
+ empathy: exports_external.number().int().min(1).max(5).optional().describe("How much the bank weights emotional/relational context (1-5; engine default 3).")
11169
+ }).optional().describe("Personality traits (1-5 each) steering how this bank frames recall, " + "reflect, and observation synthesis — a coach leans empathy-high, a " + "lawyer/analyst leans skepticism/literalism-high. Maps to the engine's " + "flat `disposition_skepticism`/`_literalism`/`_empathy` fields. " + "Cascade: per-key merge (an agent overrides individual traits and " + "inherits the rest, matching `recall`)."),
11170
+ directive_capture_nudge: exports_external.boolean().optional().describe("Deterministic directive-capture nudge (issue #2848 Stage B). When " + "on (switchroom default true — Stage A measured a ~55% miss rate on " + "durable corrections), the auto-recall hook regex-detects correction " + '/ standing-rule-shaped inbound ("always/never …", "from now on …", ' + `"stop doing …", a stated preference, "that's wrong, it's …") and ` + "appends a terse advisory to the turn's context telling the model to " + "persist the rule with mcp__hindsight__create_directive if it IS " + "durable. Detection is pure regex — the model does the judgment " + "in-session and calls create_directive itself (no model callsite, no " + "silent hook-side write). Set false to disable per-agent. " + "Cascade: override (per-agent wins over default)."),
11075
11171
  recall: exports_external.object({
11076
11172
  max_memories: exports_external.number().int().min(0).optional().describe("Cap on the number of memories injected into the prompt by " + "auto-recall, regardless of token budget. Plugin default is 12. " + "0 disables the cap (all memories Hindsight returns are injected)."),
11077
11173
  cache_ttl_secs: exports_external.number().int().min(0).optional().describe("Per-session recall cache TTL in seconds. When > 0, identical " + "(prompt, bank) within the same session reuse the cached recall " + "result instead of round-tripping to Hindsight. 0 disables. " + "Default is 600 (10 min) for switchroom-managed agents."),
@@ -11336,6 +11432,7 @@ var profileFields = {
11336
11432
  auto_recall: exports_external.boolean().optional(),
11337
11433
  file: exports_external.boolean().optional(),
11338
11434
  isolation: exports_external.enum(["default", "strict"]).optional(),
11435
+ directive_capture_nudge: exports_external.boolean().optional(),
11339
11436
  recall: exports_external.object({
11340
11437
  max_memories: exports_external.number().int().min(0).optional(),
11341
11438
  cache_ttl_secs: exports_external.number().int().min(0).optional(),
@@ -11687,6 +11784,7 @@ function resolveDualPath(pathStr) {
11687
11784
  }
11688
11785
 
11689
11786
  // src/config/overlay-loader.ts
11787
+ var import_yaml = __toESM(require_dist(), 1);
11690
11788
  import { existsSync as existsSync2, readFileSync, readdirSync, statSync } from "node:fs";
11691
11789
  import { basename, resolve as resolve2 } from "node:path";
11692
11790
 
@@ -11762,7 +11860,7 @@ function applyAgentOverlays(config) {
11762
11860
  for (const file of files) {
11763
11861
  try {
11764
11862
  const raw = readFileSync(file, "utf-8");
11765
- const parsed = $parse(raw);
11863
+ const parsed = import_yaml.parse(raw);
11766
11864
  const doc = OverlayDocSchema.parse(parsed);
11767
11865
  const title = deriveOverlayTitle(raw, basename(file));
11768
11866
  for (const entry of doc.schedule ?? []) {
@@ -11803,7 +11901,7 @@ function applyAgentOverlays(config) {
11803
11901
  for (const file of skillFiles) {
11804
11902
  try {
11805
11903
  const raw = readFileSync(file, "utf-8");
11806
- const parsed = $parse(raw);
11904
+ const parsed = import_yaml.parse(raw);
11807
11905
  const doc = OverlayDocSchema.parse(parsed);
11808
11906
  for (const skillName of doc.skills ?? []) {
11809
11907
  if (seen.has(skillName))
@@ -11979,6 +12077,11 @@ function mergeAgentConfig(defaultsIn, agentIn) {
11979
12077
  continue;
11980
12078
  if (k === "recall" && base.recall && typeof v === "object" && v !== null && !Array.isArray(v)) {
11981
12079
  combined[k] = { ...base.recall, ...v };
12080
+ } else if (k === "disposition" && base.disposition && typeof v === "object" && v !== null && !Array.isArray(v)) {
12081
+ combined[k] = {
12082
+ ...base.disposition,
12083
+ ...v
12084
+ };
11982
12085
  } else {
11983
12086
  combined[k] = v;
11984
12087
  }
@@ -12320,7 +12423,7 @@ function loadConfig(configPath) {
12320
12423
  }
12321
12424
  let parsed;
12322
12425
  try {
12323
- parsed = $parse(raw);
12426
+ parsed = import_yaml2.parse(raw);
12324
12427
  } catch (err) {
12325
12428
  throw new ConfigError(`Invalid YAML in ${filePath}`, [
12326
12429
  ` ${err.message}`
@@ -12440,8 +12543,31 @@ function isReservedAgentName(name) {
12440
12543
  return RESERVED_AGENT_NAMES.has(name);
12441
12544
  }
12442
12545
 
12546
+ // src/setup/hindsight.ts
12547
+ var HINDSIGHT_DEFAULT_API_PORT = 18888;
12548
+ var HINDSIGHT_DEFAULT_MCP_URL = `http://127.0.0.1:${HINDSIGHT_DEFAULT_API_PORT}/mcp/`;
12549
+ var HINDSIGHT_DEFAULT_API_BASE_URL = HINDSIGHT_DEFAULT_MCP_URL.replace(/\/mcp\/?$/, "");
12550
+ var HINDSIGHT_CONSUMER_NAME = "hindsight";
12551
+ var HINDSIGHT_IMAGE_REPO = "ghcr.io/switchroom/switchroom-hindsight";
12552
+ var HINDSIGHT_IMAGE = `${HINDSIGHT_IMAGE_REPO}:latest`;
12553
+ var HINDSIGHT_BROKER_SOCK_VOLUME = `auth-broker-${HINDSIGHT_CONSUMER_NAME}-sock`;
12554
+ var HINDSIGHT_HEALTHCHECK_PY = 'import urllib.request,sys; sys.exit(0 if urllib.request.urlopen("http://localhost:8888/health",timeout=4).getcode()==200 else 1)';
12555
+ var HINDSIGHT_HEALTHCHECK_CMD = `python3 -c '${HINDSIGHT_HEALTHCHECK_PY}'`;
12556
+
12443
12557
  // src/memory/hindsight.ts
12444
12558
  var DEFAULT_RETAIN_MISSION = "Extract user preferences, ongoing projects, recurring commitments, " + "important context, and durable facts that should help across future " + "conversations. Skip one-off chatter and temporary task noise.";
12559
+ var PROFILE_MEMORY_DEFAULTS = {
12560
+ "health-coach": {
12561
+ disposition: { skepticism: 2, literalism: 2, empathy: 5 },
12562
+ observations_mission: "Synthesise the person's wellbeing patterns, motivations, and emotional " + "context — how habits, setbacks, and encouragement connect over time."
12563
+ },
12564
+ "executive-assistant": {
12565
+ disposition: { skepticism: 4, literalism: 4, empathy: 3 }
12566
+ },
12567
+ coding: {
12568
+ disposition: { skepticism: 4, literalism: 5, empathy: 2 }
12569
+ }
12570
+ };
12445
12571
 
12446
12572
  // src/agents/reconcile-default-skills.ts
12447
12573
  var warnedMissingPool = new Set;
@@ -12657,37 +12783,8 @@ function resolveConsumerProbeIntervalMs(env) {
12657
12783
  return DEFAULT_CONSUMER_PROBE_INTERVAL_MS;
12658
12784
  }
12659
12785
 
12660
- // src/util/atomic.ts
12661
- import { randomBytes } from "node:crypto";
12662
- import { closeSync, constants, fsyncSync, openSync, renameSync, rmSync, writeSync } from "node:fs";
12663
- var TMP_OPEN_FLAGS = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0);
12664
- function atomicWriteFileSync(destPath, contents, mode = 384) {
12665
- const tmp = `${destPath}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;
12666
- const buf = typeof contents === "string" ? Buffer.from(contents, "utf-8") : contents;
12667
- let fd = null;
12668
- try {
12669
- fd = openSync(tmp, TMP_OPEN_FLAGS, mode);
12670
- writeSync(fd, buf, 0, buf.length, 0);
12671
- fsyncSync(fd);
12672
- closeSync(fd);
12673
- fd = null;
12674
- renameSync(tmp, destPath);
12675
- } catch (err) {
12676
- if (fd !== null) {
12677
- try {
12678
- closeSync(fd);
12679
- } catch {}
12680
- }
12681
- try {
12682
- rmSync(tmp, { force: true });
12683
- } catch {}
12684
- throw err;
12685
- }
12686
- }
12687
- function atomicWriteJsonSync(destPath, value, mode = 384) {
12688
- atomicWriteFileSync(destPath, JSON.stringify(value, null, 2) + `
12689
- `, mode);
12690
- }
12786
+ // src/auth/broker/server.ts
12787
+ init_atomic();
12691
12788
 
12692
12789
  // src/auth/account-store.ts
12693
12790
  import {
@@ -13341,6 +13438,7 @@ function resolveMicrosoftClientId(configClientId) {
13341
13438
  }
13342
13439
 
13343
13440
  // src/auth/broker/google-storage.ts
13441
+ init_atomic();
13344
13442
  import { existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync as readdirSync3, readFileSync as readFileSync4, rmSync as rmSync3, statSync as statSync3 } from "node:fs";
13345
13443
  import { dirname, join as join2, resolve as resolve5 } from "node:path";
13346
13444
  function normalizeGoogleAccountForStorage(account) {
@@ -13409,6 +13507,7 @@ function listGoogleAccounts(stateDir) {
13409
13507
  }
13410
13508
 
13411
13509
  // src/auth/broker/microsoft-storage.ts
13510
+ init_atomic();
13412
13511
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync5, rmSync as rmSync4, statSync as statSync4 } from "node:fs";
13413
13512
  import { dirname as dirname2, join as join3, resolve as resolve6 } from "node:path";
13414
13513
  function normalizeMicrosoftAccountForStorage(account) {
@@ -13527,19 +13626,19 @@ function classify(socketPath, config) {
13527
13626
  return null;
13528
13627
  }
13529
13628
  function validateConsumerNames(config) {
13530
- const errors3 = [];
13629
+ const errors2 = [];
13531
13630
  for (const c of config.consumers) {
13532
13631
  if (RESERVED_NAMES.has(c)) {
13533
- errors3.push(`consumer name '${c}' is reserved`);
13632
+ errors2.push(`consumer name '${c}' is reserved`);
13534
13633
  }
13535
13634
  if (config.agents.includes(c)) {
13536
- errors3.push(`consumer name '${c}' collides with an agent name`);
13635
+ errors2.push(`consumer name '${c}' collides with an agent name`);
13537
13636
  }
13538
13637
  if (config.adminAgents.includes(c)) {
13539
- errors3.push(`consumer name '${c}' is an admin agent (consumers cannot be admins)`);
13638
+ errors2.push(`consumer name '${c}' is an admin agent (consumers cannot be admins)`);
13540
13639
  }
13541
13640
  }
13542
- return errors3;
13641
+ return errors2;
13543
13642
  }
13544
13643
 
13545
13644
  // src/auth/broker/protocol.ts
@@ -14119,7 +14218,7 @@ class AuthBroker {
14119
14218
  const sockPath = this.operatorSocketPath();
14120
14219
  await this.bindListener(sockPath, operatorUid, 384, { kind: "operator" });
14121
14220
  }
14122
- async bindListener(sockPath, targetUid, sockMode, identity2) {
14221
+ async bindListener(sockPath, targetUid, sockMode, identity) {
14123
14222
  const dir = dirname3(sockPath);
14124
14223
  if (existsSync7(dir)) {
14125
14224
  try {
@@ -14138,7 +14237,7 @@ class AuthBroker {
14138
14237
  }
14139
14238
  await new Promise((resolveP, rejectP) => {
14140
14239
  const server = net.createServer((sock) => {
14141
- this.handleConnection(sock, sockPath, identity2);
14240
+ this.handleConnection(sock, sockPath, identity);
14142
14241
  });
14143
14242
  server.on("error", (err) => rejectP(err));
14144
14243
  server.listen(sockPath, () => {
@@ -14151,7 +14250,7 @@ class AuthBroker {
14151
14250
  try {
14152
14251
  chownSync2(dir, targetUid, targetUid);
14153
14252
  } catch {}
14154
- this.listeners.set(sockPath, { server, identity: identity2, socketPath: sockPath });
14253
+ this.listeners.set(sockPath, { server, identity, socketPath: sockPath });
14155
14254
  resolveP();
14156
14255
  });
14157
14256
  });
@@ -14195,7 +14294,7 @@ class AuthBroker {
14195
14294
  socket.write(encodeError(reqId, "INVALID_ARGS", err.message));
14196
14295
  return;
14197
14296
  }
14198
- const identity2 = classify(sockPath, configToShape(this.config)) ?? boundIdentity;
14297
+ const identity = classify(sockPath, configToShape(this.config)) ?? boundIdentity;
14199
14298
  try {
14200
14299
  switch (req.op) {
14201
14300
  case "get-credentials": {
@@ -14205,22 +14304,22 @@ class AuthBroker {
14205
14304
  break;
14206
14305
  }
14207
14306
  if (provider === "anthropic") {
14208
- await this.opGetCredentials(socket, reqId, identity2);
14307
+ await this.opGetCredentials(socket, reqId, identity);
14209
14308
  break;
14210
14309
  }
14211
14310
  if (provider === "google") {
14212
- await this.opGoogleGetCredentials(socket, reqId, identity2);
14311
+ await this.opGoogleGetCredentials(socket, reqId, identity);
14213
14312
  break;
14214
14313
  }
14215
14314
  if (provider === "microsoft") {
14216
- await this.opMicrosoftGetCredentials(socket, reqId, identity2);
14315
+ await this.opMicrosoftGetCredentials(socket, reqId, identity);
14217
14316
  break;
14218
14317
  }
14219
14318
  socket.write(encodeError(reqId, "INTERNAL", `unhandled provider '${provider}' in get-credentials dispatch`));
14220
14319
  break;
14221
14320
  }
14222
14321
  case "list-state":
14223
- await this.opListState(socket, reqId, identity2);
14322
+ await this.opListState(socket, reqId, identity);
14224
14323
  break;
14225
14324
  case "set-active": {
14226
14325
  const provider = req.provider ?? "anthropic";
@@ -14228,11 +14327,11 @@ class AuthBroker {
14228
14327
  socket.write(encodeError(reqId, "INVALID_ARGS", `set-active is Anthropic-only — Google's account-active model is per-agent via google_accounts.enabled_for[]`));
14229
14328
  break;
14230
14329
  }
14231
- await this.opSetActive(socket, reqId, identity2, req.account);
14330
+ await this.opSetActive(socket, reqId, identity, req.account);
14232
14331
  break;
14233
14332
  }
14234
14333
  case "mark-exhausted":
14235
- await this.opMarkExhausted(socket, reqId, identity2, req.until);
14334
+ await this.opMarkExhausted(socket, reqId, identity, req.until);
14236
14335
  break;
14237
14336
  case "refresh-account": {
14238
14337
  const provider = req.provider ?? "anthropic";
@@ -14241,7 +14340,7 @@ class AuthBroker {
14241
14340
  break;
14242
14341
  }
14243
14342
  if (provider === "anthropic") {
14244
- await this.opRefreshAccount(socket, reqId, identity2, req.account);
14343
+ await this.opRefreshAccount(socket, reqId, identity, req.account);
14245
14344
  break;
14246
14345
  }
14247
14346
  socket.write(encodeError(reqId, "INVALID_ARGS", `refresh-account dispatch through provider '${provider}' storage path lands in Phase 3b.2c (vault-broker-mediated, not direct-to-disk like Anthropic)`));
@@ -14260,17 +14359,17 @@ class AuthBroker {
14260
14359
  }
14261
14360
  if (provider === "anthropic") {
14262
14361
  const anthropicCreds = req.credentials;
14263
- await this.opAddAccount(socket, reqId, identity2, req.label, anthropicCreds, req.replace ?? false);
14362
+ await this.opAddAccount(socket, reqId, identity, req.label, anthropicCreds, req.replace ?? false);
14264
14363
  break;
14265
14364
  }
14266
14365
  if (provider === "google") {
14267
14366
  const googleCreds = req.credentials;
14268
- await this.opGoogleAddAccount(socket, reqId, identity2, req.label, googleCreds, req.replace ?? false);
14367
+ await this.opGoogleAddAccount(socket, reqId, identity, req.label, googleCreds, req.replace ?? false);
14269
14368
  break;
14270
14369
  }
14271
14370
  if (provider === "microsoft") {
14272
14371
  const microsoftCreds = req.credentials;
14273
- await this.opMicrosoftAddAccount(socket, reqId, identity2, req.label, microsoftCreds, req.replace ?? false);
14372
+ await this.opMicrosoftAddAccount(socket, reqId, identity, req.label, microsoftCreds, req.replace ?? false);
14274
14373
  break;
14275
14374
  }
14276
14375
  socket.write(encodeError(reqId, "INTERNAL", `unhandled provider '${provider}' in add-account dispatch`));
@@ -14283,71 +14382,71 @@ class AuthBroker {
14283
14382
  break;
14284
14383
  }
14285
14384
  if (provider === "anthropic") {
14286
- await this.opRmAccount(socket, reqId, identity2, req.label);
14385
+ await this.opRmAccount(socket, reqId, identity, req.label);
14287
14386
  break;
14288
14387
  }
14289
14388
  if (provider === "google") {
14290
- await this.opGoogleRmAccount(socket, reqId, identity2, req.label);
14389
+ await this.opGoogleRmAccount(socket, reqId, identity, req.label);
14291
14390
  break;
14292
14391
  }
14293
14392
  if (provider === "microsoft") {
14294
- await this.opMicrosoftRmAccount(socket, reqId, identity2, req.label);
14393
+ await this.opMicrosoftRmAccount(socket, reqId, identity, req.label);
14295
14394
  break;
14296
14395
  }
14297
14396
  socket.write(encodeError(reqId, "INTERNAL", `unhandled provider '${provider}' in rm-account dispatch`));
14298
14397
  break;
14299
14398
  }
14300
14399
  case "set-override":
14301
- await this.opSetOverride(socket, reqId, identity2, req.agent, req.account);
14400
+ await this.opSetOverride(socket, reqId, identity, req.agent, req.account);
14302
14401
  break;
14303
14402
  case "list-google-accounts":
14304
- await this.opListGoogleAccounts(socket, reqId, identity2);
14403
+ await this.opListGoogleAccounts(socket, reqId, identity);
14305
14404
  break;
14306
14405
  case "list-microsoft-accounts":
14307
- await this.opListMicrosoftAccounts(socket, reqId, identity2);
14406
+ await this.opListMicrosoftAccounts(socket, reqId, identity);
14308
14407
  break;
14309
14408
  case "probe-quota":
14310
- await this.opProbeQuota(socket, reqId, identity2, req.accounts, req.timeoutMs, req.forceLive);
14409
+ await this.opProbeQuota(socket, reqId, identity, req.accounts, req.timeoutMs, req.forceLive);
14311
14410
  break;
14312
14411
  case "claim-notification":
14313
- this.opClaimNotification(socket, reqId, identity2, req.key, req.windowMs);
14412
+ this.opClaimNotification(socket, reqId, identity, req.key, req.windowMs);
14314
14413
  break;
14315
14414
  }
14316
14415
  } catch (err) {
14317
14416
  socket.write(encodeError(reqId, "INTERNAL", err.message));
14318
14417
  }
14319
14418
  }
14320
- isAdmin(identity2) {
14321
- if (identity2.kind === "operator")
14419
+ isAdmin(identity) {
14420
+ if (identity.kind === "operator")
14322
14421
  return true;
14323
- if (identity2.kind === "agent")
14324
- return identity2.admin;
14422
+ if (identity.kind === "agent")
14423
+ return identity.admin;
14325
14424
  return false;
14326
14425
  }
14327
14426
  respondForbidden(socket, id, why) {
14328
14427
  socket.write(encodeError(id, "FORBIDDEN", why));
14329
14428
  }
14330
- callerAccount(identity2) {
14429
+ callerAccount(identity) {
14331
14430
  const auth = this.config.auth;
14332
14431
  if (!auth)
14333
14432
  return null;
14334
- if (identity2.kind === "operator")
14433
+ if (identity.kind === "operator")
14335
14434
  return auth.active ?? null;
14336
- if (identity2.kind === "consumer") {
14337
- const c = (auth.consumers ?? []).find((x) => x.name === identity2.name);
14435
+ if (identity.kind === "consumer") {
14436
+ const c = (auth.consumers ?? []).find((x) => x.name === identity.name);
14338
14437
  if (!c)
14339
14438
  return null;
14340
14439
  return c.account ?? auth.active ?? null;
14341
14440
  }
14342
- const agent = (this.config.agents ?? {})[identity2.name];
14441
+ const agent = (this.config.agents ?? {})[identity.name];
14343
14442
  const override = agent?.auth?.override;
14344
14443
  if (override)
14345
14444
  return override;
14346
14445
  return auth.active ?? null;
14347
14446
  }
14348
- servingAccount(identity2) {
14349
- const account = this.callerAccount(identity2);
14350
- if (identity2.kind === "operator")
14447
+ servingAccount(identity) {
14448
+ const account = this.callerAccount(identity);
14449
+ if (identity.kind === "operator")
14351
14450
  return account;
14352
14451
  return this.accountWithFailover(account);
14353
14452
  }
@@ -14439,24 +14538,24 @@ class AuthBroker {
14439
14538
  }
14440
14539
  return account;
14441
14540
  }
14442
- async opGetCredentials(socket, id, identity2) {
14443
- const account = this.servingAccount(identity2);
14541
+ async opGetCredentials(socket, id, identity) {
14542
+ const account = this.servingAccount(identity);
14444
14543
  if (!account) {
14445
- this.audit({ op: "get-credentials", identity: identity2, accountKind: "claude", ok: false, error: "no-active-account" });
14544
+ this.audit({ op: "get-credentials", identity, accountKind: "claude", ok: false, error: "no-active-account" });
14446
14545
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", "no active account configured"));
14447
14546
  return;
14448
14547
  }
14449
14548
  const creds = readAccountCredentials(account, this.home);
14450
14549
  if (!creds) {
14451
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "claude", ok: false, error: "missing-credentials" });
14550
+ this.audit({ op: "get-credentials", identity, account, accountKind: "claude", ok: false, error: "missing-credentials" });
14452
14551
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", `no credentials for account '${account}'`));
14453
14552
  return;
14454
14553
  }
14455
14554
  const expiresAt = creds.claudeAiOauth?.expiresAt;
14456
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "claude", ok: true });
14555
+ this.audit({ op: "get-credentials", identity, account, accountKind: "claude", ok: true });
14457
14556
  socket.write(encodeSuccess(id, { account, credentials: creds, expiresAt }));
14458
14557
  }
14459
- async opListState(socket, id, identity2) {
14558
+ async opListState(socket, id, identity) {
14460
14559
  const auth = this.config.auth ?? {};
14461
14560
  const accounts = listAccounts(this.home).map((label) => {
14462
14561
  const creds = readAccountCredentials(label, this.home);
@@ -14484,8 +14583,8 @@ class AuthBroker {
14484
14583
  account: c.account ?? auth.active ?? "",
14485
14584
  last_seen_at: this.consumerLastSeen[c.name] ?? null
14486
14585
  }));
14487
- const active_overage_serving = this.isActiveOverageServing(this.callerAccount(identity2));
14488
- this.audit({ op: "list-state", identity: identity2, ok: true });
14586
+ const active_overage_serving = this.isActiveOverageServing(this.callerAccount(identity));
14587
+ this.audit({ op: "list-state", identity, ok: true });
14489
14588
  socket.write(encodeSuccess(id, {
14490
14589
  active: auth.active ?? "",
14491
14590
  fallback_order: auth.fallback_order ?? [],
@@ -14495,7 +14594,7 @@ class AuthBroker {
14495
14594
  active_overage_serving
14496
14595
  }));
14497
14596
  }
14498
- async opListGoogleAccounts(socket, id, identity2) {
14597
+ async opListGoogleAccounts(socket, id, identity) {
14499
14598
  const accounts = listGoogleAccounts(this.stateDir).map((account) => {
14500
14599
  const creds = readGoogleAccountCredentials(this.stateDir, account);
14501
14600
  if (!creds)
@@ -14507,10 +14606,10 @@ class AuthBroker {
14507
14606
  clientId: creds.googleOauth.clientId
14508
14607
  };
14509
14608
  }).filter((entry) => entry !== null).sort((a, b) => a.account.localeCompare(b.account));
14510
- this.audit({ op: "list-google-accounts", identity: identity2, accountKind: "google", ok: true });
14609
+ this.audit({ op: "list-google-accounts", identity, accountKind: "google", ok: true });
14511
14610
  socket.write(encodeSuccess(id, { accounts }));
14512
14611
  }
14513
- async opProbeQuota(socket, id, identity2, accounts, timeoutMs, forceLive) {
14612
+ async opProbeQuota(socket, id, identity, accounts, timeoutMs, forceLive) {
14514
14613
  const ttlMs = forceLive ? 0 : quotaProbeTtlMs();
14515
14614
  const results = await Promise.all(accounts.map(async (label) => {
14516
14615
  const cached = this.lastQuotaCache[label];
@@ -14527,13 +14626,13 @@ class AuthBroker {
14527
14626
  ok: false,
14528
14627
  reason: "no credentials for account in broker store"
14529
14628
  };
14530
- this.audit({ op: "probe-quota", identity: identity2, account: label, accountKind: "claude", ok: false, error: "missing-credentials" });
14629
+ this.audit({ op: "probe-quota", identity, account: label, accountKind: "claude", ok: false, error: "missing-credentials" });
14531
14630
  return { label, result: result2 };
14532
14631
  }
14533
14632
  const result = await this.probeQuotaSingleFlight(label, token, timeoutMs);
14534
14633
  this.audit({
14535
14634
  op: "probe-quota",
14536
- identity: identity2,
14635
+ identity,
14537
14636
  account: label,
14538
14637
  accountKind: "claude",
14539
14638
  ok: result.ok,
@@ -14654,14 +14753,14 @@ class AuthBroker {
14654
14753
  this.fanoutToAffectedConsumers(label);
14655
14754
  }
14656
14755
  }
14657
- async opSetActive(socket, id, identity2, account) {
14658
- if (!this.isAdmin(identity2)) {
14659
- this.audit({ op: "set-active", identity: identity2, account, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14756
+ async opSetActive(socket, id, identity, account) {
14757
+ if (!this.isAdmin(identity)) {
14758
+ this.audit({ op: "set-active", identity, account, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14660
14759
  this.respondForbidden(socket, id, "set-active requires admin");
14661
14760
  return;
14662
14761
  }
14663
14762
  if (!accountExists(account, this.home)) {
14664
- this.audit({ op: "set-active", identity: identity2, account, accountKind: "claude", ok: false, error: "ACCOUNT_NOT_FOUND" });
14763
+ this.audit({ op: "set-active", identity, account, accountKind: "claude", ok: false, error: "ACCOUNT_NOT_FOUND" });
14665
14764
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", `account '${account}' not found`));
14666
14765
  return;
14667
14766
  }
@@ -14673,21 +14772,21 @@ class AuthBroker {
14673
14772
  this.persistActiveOverride(account);
14674
14773
  const fanned = this.fanoutToAffectedAgents(account);
14675
14774
  this.fanoutAllConsumers();
14676
- this.audit({ op: "set-active", identity: identity2, account, accountKind: "claude", ok: true });
14775
+ this.audit({ op: "set-active", identity, account, accountKind: "claude", ok: true });
14677
14776
  socket.write(encodeSuccess(id, { active: account, fanned }));
14678
14777
  }
14679
- async opMarkExhausted(socket, id, identity2, until) {
14680
- const account = this.callerAccount(identity2);
14778
+ async opMarkExhausted(socket, id, identity, until) {
14779
+ const account = this.callerAccount(identity);
14681
14780
  if (!account) {
14682
- this.audit({ op: "mark-exhausted", identity: identity2, accountKind: "claude", ok: false, error: "no-active-account" });
14781
+ this.audit({ op: "mark-exhausted", identity, accountKind: "claude", ok: false, error: "no-active-account" });
14683
14782
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", "no active account configured"));
14684
14783
  return;
14685
14784
  }
14686
- const { rolled, rolledTo } = await this.markExhaustedAndRoll(account, until, identity2);
14687
- this.audit({ op: "mark-exhausted", identity: identity2, account, accountKind: "claude", ok: true });
14785
+ const { rolled, rolledTo } = await this.markExhaustedAndRoll(account, until, identity);
14786
+ this.audit({ op: "mark-exhausted", identity, account, accountKind: "claude", ok: true });
14688
14787
  socket.write(encodeSuccess(id, { account, rolled, rolledTo }));
14689
14788
  }
14690
- async markExhaustedAndRoll(account, until, identity2) {
14789
+ async markExhaustedAndRoll(account, until, identity) {
14691
14790
  const now = this.now();
14692
14791
  const exhaustedUntil = clampMarkExpiry({
14693
14792
  proposedUntil: until ?? now + MARK_EXHAUSTED_DEFAULT_MS,
@@ -14707,7 +14806,7 @@ class AuthBroker {
14707
14806
  };
14708
14807
  this.persistActiveOverride(rolledTo);
14709
14808
  this.fanoutAllConsumers();
14710
- this.audit({ op: "auto-promote-active", identity: identity2, account: rolledTo, accountKind: "claude", ok: true });
14809
+ this.audit({ op: "auto-promote-active", identity, account: rolledTo, accountKind: "claude", ok: true });
14711
14810
  process.stdout.write(`auth-broker: auto-promoted auth.active ${account} → ${rolledTo} ` + `(${account} exhausted until ${new Date(exhaustedUntil).toISOString()}) — persisted
14712
14811
  `);
14713
14812
  }
@@ -14721,7 +14820,7 @@ class AuthBroker {
14721
14820
  return false;
14722
14821
  return !overageLiftsWall(snapshot, this.isOverageAllowed(account));
14723
14822
  }
14724
- opClaimNotification(socket, id, identity2, key, windowMs) {
14823
+ opClaimNotification(socket, id, identity, key, windowMs) {
14725
14824
  const now = this.now();
14726
14825
  const prev = this.notificationClaims[key];
14727
14826
  const granted = prev === undefined || now - prev >= windowMs;
@@ -14732,35 +14831,35 @@ class AuthBroker {
14732
14831
  delete this.notificationClaims[k];
14733
14832
  }
14734
14833
  this.persistNotificationClaims();
14735
- this.audit({ op: "claim-notification", identity: identity2, account: key, ok: true });
14834
+ this.audit({ op: "claim-notification", identity, account: key, ok: true });
14736
14835
  }
14737
14836
  socket.write(encodeSuccess(id, { granted }));
14738
14837
  }
14739
- async opRefreshAccount(socket, id, identity2, account) {
14740
- if (!this.isAdmin(identity2)) {
14741
- this.audit({ op: "refresh-account", identity: identity2, account, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14838
+ async opRefreshAccount(socket, id, identity, account) {
14839
+ if (!this.isAdmin(identity)) {
14840
+ this.audit({ op: "refresh-account", identity, account, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14742
14841
  this.respondForbidden(socket, id, "refresh-account requires admin");
14743
14842
  return;
14744
14843
  }
14745
14844
  if (!accountExists(account, this.home)) {
14746
- this.audit({ op: "refresh-account", identity: identity2, account, accountKind: "claude", ok: false, error: "ACCOUNT_NOT_FOUND" });
14845
+ this.audit({ op: "refresh-account", identity, account, accountKind: "claude", ok: false, error: "ACCOUNT_NOT_FOUND" });
14747
14846
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", `account '${account}' not found`));
14748
14847
  return;
14749
14848
  }
14750
14849
  const result = await this.refreshOneAccount(account, true);
14751
14850
  if (result.kind === "failed") {
14752
- this.audit({ op: "refresh-account", identity: identity2, account, accountKind: "claude", ok: false, error: result.error });
14851
+ this.audit({ op: "refresh-account", identity, account, accountKind: "claude", ok: false, error: result.error });
14753
14852
  socket.write(encodeError(id, "REFRESH_FAILED", result.error));
14754
14853
  return;
14755
14854
  }
14756
14855
  const creds = readAccountCredentials(account, this.home);
14757
14856
  const expiresAt = creds?.claudeAiOauth?.expiresAt;
14758
- this.audit({ op: "refresh-account", identity: identity2, account, accountKind: "claude", ok: true });
14857
+ this.audit({ op: "refresh-account", identity, account, accountKind: "claude", ok: true });
14759
14858
  socket.write(encodeSuccess(id, { account, expiresAt }));
14760
14859
  }
14761
- async opAddAccount(socket, id, identity2, label, credentials, replace) {
14762
- if (!this.isAdmin(identity2)) {
14763
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14860
+ async opAddAccount(socket, id, identity, label, credentials, replace) {
14861
+ if (!this.isAdmin(identity)) {
14862
+ this.audit({ op: "add-account", identity, account: label, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14764
14863
  this.respondForbidden(socket, id, "add-account requires admin");
14765
14864
  return;
14766
14865
  }
@@ -14771,7 +14870,7 @@ class AuthBroker {
14771
14870
  return;
14772
14871
  }
14773
14872
  if (accountExists(label, this.home) && !replace) {
14774
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "claude", ok: false, error: "ACCOUNT_ALREADY_EXISTS" });
14873
+ this.audit({ op: "add-account", identity, account: label, accountKind: "claude", ok: false, error: "ACCOUNT_ALREADY_EXISTS" });
14775
14874
  socket.write(encodeError(id, "ACCOUNT_ALREADY_EXISTS", `account '${label}' already exists; pass replace:true to overwrite`));
14776
14875
  return;
14777
14876
  }
@@ -14789,12 +14888,12 @@ class AuthBroker {
14789
14888
  this.persistShaIndex();
14790
14889
  this.fanoutToAffectedAgents(label);
14791
14890
  const expiresAt = credentials.claudeAiOauth?.expiresAt;
14792
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "claude", ok: true, replace });
14891
+ this.audit({ op: "add-account", identity, account: label, accountKind: "claude", ok: true, replace });
14793
14892
  socket.write(encodeSuccess(id, { label, expiresAt }));
14794
14893
  }
14795
- async opRmAccount(socket, id, identity2, label) {
14796
- if (!this.isAdmin(identity2)) {
14797
- this.audit({ op: "rm-account", identity: identity2, account: label, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14894
+ async opRmAccount(socket, id, identity, label) {
14895
+ if (!this.isAdmin(identity)) {
14896
+ this.audit({ op: "rm-account", identity, account: label, accountKind: "claude", ok: false, error: "FORBIDDEN" });
14798
14897
  this.respondForbidden(socket, id, "rm-account requires admin");
14799
14898
  return;
14800
14899
  }
@@ -14827,42 +14926,42 @@ class AuthBroker {
14827
14926
  this.persistQuota();
14828
14927
  this.persistThresholdViolations();
14829
14928
  this.persistLastQuotaCache();
14830
- this.audit({ op: "rm-account", identity: identity2, account: label, accountKind: "claude", ok: true });
14929
+ this.audit({ op: "rm-account", identity, account: label, accountKind: "claude", ok: true });
14831
14930
  socket.write(encodeSuccess(id, { label }));
14832
14931
  }
14833
- async opGoogleGetCredentials(socket, id, identity2) {
14834
- if (identity2.kind !== "agent") {
14835
- socket.write(encodeError(id, "INVALID_ARGS", `Google get-credentials is per-agent only (caller kind '${identity2.kind}' not supported); use the agent's per-agent socket bind`));
14932
+ async opGoogleGetCredentials(socket, id, identity) {
14933
+ if (identity.kind !== "agent") {
14934
+ socket.write(encodeError(id, "INVALID_ARGS", `Google get-credentials is per-agent only (caller kind '${identity.kind}' not supported); use the agent's per-agent socket bind`));
14836
14935
  return;
14837
14936
  }
14838
- const agentName = identity2.name;
14937
+ const agentName = identity.name;
14839
14938
  const agent = (this.config.agents ?? {})[agentName];
14840
14939
  const account = agent?.google_workspace?.account;
14841
14940
  if (!account) {
14842
- this.audit({ op: "get-credentials", identity: identity2, accountKind: "google", ok: false, error: "no-google-account-configured" });
14941
+ this.audit({ op: "get-credentials", identity, accountKind: "google", ok: false, error: "no-google-account-configured" });
14843
14942
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", `agent '${agentName}' has no google_workspace.account configured in switchroom.yaml`));
14844
14943
  return;
14845
14944
  }
14846
14945
  const ga = this.config.google_accounts;
14847
14946
  const enabledFor = ga?.[account]?.enabled_for ?? [];
14848
14947
  if (!enabledFor.includes(agentName)) {
14849
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "google", ok: false, error: "acl-deny" });
14948
+ this.audit({ op: "get-credentials", identity, account, accountKind: "google", ok: false, error: "acl-deny" });
14850
14949
  socket.write(encodeError(id, "FORBIDDEN", `agent '${agentName}' not in google_accounts['${account}'].enabled_for[] — operator must run \`switchroom auth google enable ${account} ${agentName}\``));
14851
14950
  return;
14852
14951
  }
14853
14952
  const creds = readGoogleAccountCredentials(this.stateDir, account);
14854
14953
  if (!creds) {
14855
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "google", ok: false, error: "missing-credentials" });
14954
+ this.audit({ op: "get-credentials", identity, account, accountKind: "google", ok: false, error: "missing-credentials" });
14856
14955
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", `no Google credentials for account '${account}' — operator must run \`switchroom auth google account add ${account}\``));
14857
14956
  return;
14858
14957
  }
14859
14958
  const expiresAt = creds.googleOauth?.expiresAt;
14860
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "google", ok: true });
14959
+ this.audit({ op: "get-credentials", identity, account, accountKind: "google", ok: true });
14861
14960
  socket.write(encodeSuccess(id, { account, credentials: creds, expiresAt }));
14862
14961
  }
14863
- async opGoogleAddAccount(socket, id, identity2, label, credentials, replace) {
14864
- if (!this.isAdmin(identity2)) {
14865
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "google", ok: false, error: "FORBIDDEN" });
14962
+ async opGoogleAddAccount(socket, id, identity, label, credentials, replace) {
14963
+ if (!this.isAdmin(identity)) {
14964
+ this.audit({ op: "add-account", identity, account: label, accountKind: "google", ok: false, error: "FORBIDDEN" });
14866
14965
  this.respondForbidden(socket, id, "add-account requires admin");
14867
14966
  return;
14868
14967
  }
@@ -14873,7 +14972,7 @@ class AuthBroker {
14873
14972
  return;
14874
14973
  }
14875
14974
  if (googleAccountExists(this.stateDir, label) && !replace) {
14876
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "google", ok: false, error: "ACCOUNT_ALREADY_EXISTS" });
14975
+ this.audit({ op: "add-account", identity, account: label, accountKind: "google", ok: false, error: "ACCOUNT_ALREADY_EXISTS" });
14877
14976
  socket.write(encodeError(id, "ACCOUNT_ALREADY_EXISTS", `google account '${label}' already exists; pass replace:true to overwrite`));
14878
14977
  return;
14879
14978
  }
@@ -14884,12 +14983,12 @@ class AuthBroker {
14884
14983
  return;
14885
14984
  }
14886
14985
  const expiresAt = credentials.googleOauth?.expiresAt;
14887
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "google", ok: true, replace });
14986
+ this.audit({ op: "add-account", identity, account: label, accountKind: "google", ok: true, replace });
14888
14987
  socket.write(encodeSuccess(id, { label, expiresAt }));
14889
14988
  }
14890
- async opGoogleRmAccount(socket, id, identity2, label) {
14891
- if (!this.isAdmin(identity2)) {
14892
- this.audit({ op: "rm-account", identity: identity2, account: label, accountKind: "google", ok: false, error: "FORBIDDEN" });
14989
+ async opGoogleRmAccount(socket, id, identity, label) {
14990
+ if (!this.isAdmin(identity)) {
14991
+ this.audit({ op: "rm-account", identity, account: label, accountKind: "google", ok: false, error: "FORBIDDEN" });
14893
14992
  this.respondForbidden(socket, id, "rm-account requires admin");
14894
14993
  return;
14895
14994
  }
@@ -14915,42 +15014,42 @@ class AuthBroker {
14915
15014
  socket.write(encodeError(id, "INTERNAL", err.message));
14916
15015
  return;
14917
15016
  }
14918
- this.audit({ op: "rm-account", identity: identity2, account: label, accountKind: "google", ok: true });
15017
+ this.audit({ op: "rm-account", identity, account: label, accountKind: "google", ok: true });
14919
15018
  socket.write(encodeSuccess(id, { label }));
14920
15019
  }
14921
- async opMicrosoftGetCredentials(socket, id, identity2) {
14922
- if (identity2.kind !== "agent") {
14923
- socket.write(encodeError(id, "INVALID_ARGS", `Microsoft get-credentials is per-agent only (caller kind '${identity2.kind}' not supported); use the agent's per-agent socket bind`));
15020
+ async opMicrosoftGetCredentials(socket, id, identity) {
15021
+ if (identity.kind !== "agent") {
15022
+ socket.write(encodeError(id, "INVALID_ARGS", `Microsoft get-credentials is per-agent only (caller kind '${identity.kind}' not supported); use the agent's per-agent socket bind`));
14924
15023
  return;
14925
15024
  }
14926
- const agentName = identity2.name;
15025
+ const agentName = identity.name;
14927
15026
  const agent = (this.config.agents ?? {})[agentName];
14928
15027
  const account = agent?.microsoft_workspace?.account;
14929
15028
  if (!account) {
14930
- this.audit({ op: "get-credentials", identity: identity2, accountKind: "microsoft", ok: false, error: "no-microsoft-account-configured" });
15029
+ this.audit({ op: "get-credentials", identity, accountKind: "microsoft", ok: false, error: "no-microsoft-account-configured" });
14931
15030
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", `agent '${agentName}' has no microsoft_workspace.account configured in switchroom.yaml`));
14932
15031
  return;
14933
15032
  }
14934
15033
  const ma = this.config.microsoft_accounts;
14935
15034
  const enabledFor = ma?.[account]?.enabled_for ?? [];
14936
15035
  if (!enabledFor.includes(agentName)) {
14937
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "microsoft", ok: false, error: "acl-deny" });
15036
+ this.audit({ op: "get-credentials", identity, account, accountKind: "microsoft", ok: false, error: "acl-deny" });
14938
15037
  socket.write(encodeError(id, "FORBIDDEN", `agent '${agentName}' not in microsoft_accounts['${account}'].enabled_for[] — operator must run \`switchroom auth microsoft enable ${account} ${agentName}\``));
14939
15038
  return;
14940
15039
  }
14941
15040
  const creds = readMicrosoftAccountCredentials(this.stateDir, account);
14942
15041
  if (!creds) {
14943
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "microsoft", ok: false, error: "missing-credentials" });
15042
+ this.audit({ op: "get-credentials", identity, account, accountKind: "microsoft", ok: false, error: "missing-credentials" });
14944
15043
  socket.write(encodeError(id, "ACCOUNT_NOT_FOUND", `no Microsoft credentials for account '${account}' — operator must run \`switchroom auth microsoft account add ${account}\``));
14945
15044
  return;
14946
15045
  }
14947
15046
  const expiresAt = creds.microsoftOauth?.expiresAt;
14948
- this.audit({ op: "get-credentials", identity: identity2, account, accountKind: "microsoft", ok: true });
15047
+ this.audit({ op: "get-credentials", identity, account, accountKind: "microsoft", ok: true });
14949
15048
  socket.write(encodeSuccess(id, { account, credentials: creds, expiresAt }));
14950
15049
  }
14951
- async opMicrosoftAddAccount(socket, id, identity2, label, credentials, replace) {
14952
- if (!this.isAdmin(identity2)) {
14953
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "microsoft", ok: false, error: "FORBIDDEN" });
15050
+ async opMicrosoftAddAccount(socket, id, identity, label, credentials, replace) {
15051
+ if (!this.isAdmin(identity)) {
15052
+ this.audit({ op: "add-account", identity, account: label, accountKind: "microsoft", ok: false, error: "FORBIDDEN" });
14954
15053
  this.respondForbidden(socket, id, "add-account requires admin");
14955
15054
  return;
14956
15055
  }
@@ -14961,7 +15060,7 @@ class AuthBroker {
14961
15060
  return;
14962
15061
  }
14963
15062
  if (microsoftAccountExists(this.stateDir, label) && !replace) {
14964
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "microsoft", ok: false, error: "ACCOUNT_ALREADY_EXISTS" });
15063
+ this.audit({ op: "add-account", identity, account: label, accountKind: "microsoft", ok: false, error: "ACCOUNT_ALREADY_EXISTS" });
14965
15064
  socket.write(encodeError(id, "ACCOUNT_ALREADY_EXISTS", `microsoft account '${label}' already exists; pass replace:true to overwrite`));
14966
15065
  return;
14967
15066
  }
@@ -14972,12 +15071,12 @@ class AuthBroker {
14972
15071
  return;
14973
15072
  }
14974
15073
  const expiresAt = credentials.microsoftOauth?.expiresAt;
14975
- this.audit({ op: "add-account", identity: identity2, account: label, accountKind: "microsoft", ok: true, replace });
15074
+ this.audit({ op: "add-account", identity, account: label, accountKind: "microsoft", ok: true, replace });
14976
15075
  socket.write(encodeSuccess(id, { label, expiresAt }));
14977
15076
  }
14978
- async opMicrosoftRmAccount(socket, id, identity2, label) {
14979
- if (!this.isAdmin(identity2)) {
14980
- this.audit({ op: "rm-account", identity: identity2, account: label, accountKind: "microsoft", ok: false, error: "FORBIDDEN" });
15077
+ async opMicrosoftRmAccount(socket, id, identity, label) {
15078
+ if (!this.isAdmin(identity)) {
15079
+ this.audit({ op: "rm-account", identity, account: label, accountKind: "microsoft", ok: false, error: "FORBIDDEN" });
14981
15080
  this.respondForbidden(socket, id, "rm-account requires admin");
14982
15081
  return;
14983
15082
  }
@@ -15003,10 +15102,10 @@ class AuthBroker {
15003
15102
  socket.write(encodeError(id, "INTERNAL", err.message));
15004
15103
  return;
15005
15104
  }
15006
- this.audit({ op: "rm-account", identity: identity2, account: label, accountKind: "microsoft", ok: true });
15105
+ this.audit({ op: "rm-account", identity, account: label, accountKind: "microsoft", ok: true });
15007
15106
  socket.write(encodeSuccess(id, { label }));
15008
15107
  }
15009
- async opListMicrosoftAccounts(socket, id, identity2) {
15108
+ async opListMicrosoftAccounts(socket, id, identity) {
15010
15109
  const accounts = listMicrosoftAccounts(this.stateDir).map((account) => {
15011
15110
  const creds = readMicrosoftAccountCredentials(this.stateDir, account);
15012
15111
  if (!creds)
@@ -15019,12 +15118,12 @@ class AuthBroker {
15019
15118
  accountType: creds.microsoftOauth.accountType
15020
15119
  };
15021
15120
  }).filter((entry) => entry !== null).sort((a, b) => a.account.localeCompare(b.account));
15022
- this.audit({ op: "list-microsoft-accounts", identity: identity2, accountKind: "microsoft", ok: true });
15121
+ this.audit({ op: "list-microsoft-accounts", identity, accountKind: "microsoft", ok: true });
15023
15122
  socket.write(encodeSuccess(id, { accounts }));
15024
15123
  }
15025
- async opSetOverride(socket, id, identity2, agentName, account) {
15026
- if (!this.isAdmin(identity2)) {
15027
- this.audit({ op: "set-override", identity: identity2, account: account ?? undefined, accountKind: "claude", ok: false, error: "FORBIDDEN" });
15124
+ async opSetOverride(socket, id, identity, agentName, account) {
15125
+ if (!this.isAdmin(identity)) {
15126
+ this.audit({ op: "set-override", identity, account: account ?? undefined, accountKind: "claude", ok: false, error: "FORBIDDEN" });
15028
15127
  this.respondForbidden(socket, id, "set-override requires admin");
15029
15128
  return;
15030
15129
  }
@@ -15046,7 +15145,7 @@ class AuthBroker {
15046
15145
  agents[agentName] = { ...cur, auth };
15047
15146
  this.config = { ...this.config, agents };
15048
15147
  this.fanoutForAgent(agentName);
15049
- this.audit({ op: "set-override", identity: identity2, account: account ?? undefined, accountKind: "claude", ok: true });
15148
+ this.audit({ op: "set-override", identity, account: account ?? undefined, accountKind: "claude", ok: true });
15050
15149
  socket.write(encodeSuccess(id, { agent: agentName, account }));
15051
15150
  }
15052
15151
  async refreshTick() {