@rubytech/create-maxy-code 0.1.388 → 0.1.391

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 (121) hide show
  1. package/dist/__tests__/claude-bin.test.js +51 -0
  2. package/dist/__tests__/claude-upgrade-privilege.test.js +17 -0
  3. package/dist/__tests__/joblogic-excluded.test.js +39 -0
  4. package/dist/__tests__/launchd-plist.test.js +36 -1
  5. package/dist/__tests__/macos-darwin-branch.test.js +18 -0
  6. package/dist/__tests__/neo4j-datadir.test.js +14 -0
  7. package/dist/claude-bin.js +78 -0
  8. package/dist/claude-upgrade-privilege.js +21 -0
  9. package/dist/index.js +262 -34
  10. package/dist/launchd-plist.js +25 -9
  11. package/dist/neo4j-datadir.js +15 -0
  12. package/package.json +1 -1
  13. package/payload/platform/config/brand.json +1 -1
  14. package/payload/platform/plugins/.claude-plugin/marketplace.json +0 -5
  15. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +24 -5
  16. package/payload/platform/plugins/docs/references/admin-session.md +4 -0
  17. package/payload/platform/plugins/docs/references/admin-ui.md +18 -1
  18. package/payload/platform/plugins/docs/references/joblogic.md +2 -0
  19. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +2 -0
  20. package/payload/platform/plugins/work/PLUGIN.md +3 -0
  21. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.d.ts +2 -0
  22. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.d.ts.map +1 -0
  23. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js +98 -0
  24. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js.map +1 -0
  25. package/payload/platform/plugins/work/mcp/dist/index.js +16 -0
  26. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
  27. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.d.ts +53 -0
  28. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.d.ts.map +1 -0
  29. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js +80 -0
  30. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js.map +1 -0
  31. package/payload/platform/plugins/work/mcp/package.json +2 -1
  32. package/payload/platform/scripts/smoke-boot-services.sh +35 -10
  33. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  34. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  35. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  36. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts +11 -0
  37. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts.map +1 -0
  38. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js +37 -0
  39. package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js.map +1 -0
  40. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  41. package/payload/platform/services/claude-session-manager/dist/http-server.js +98 -8
  42. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  43. package/payload/platform/services/claude-session-manager/dist/pricing.d.ts +45 -0
  44. package/payload/platform/services/claude-session-manager/dist/pricing.d.ts.map +1 -0
  45. package/payload/platform/services/claude-session-manager/dist/pricing.js +57 -0
  46. package/payload/platform/services/claude-session-manager/dist/pricing.js.map +1 -0
  47. package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
  48. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +7 -0
  49. package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
  50. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +1 -1
  51. package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
  52. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +5 -1
  53. package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
  54. package/payload/platform/services/claude-session-manager/dist/session-metering.d.ts +38 -0
  55. package/payload/platform/services/claude-session-manager/dist/session-metering.d.ts.map +1 -0
  56. package/payload/platform/services/claude-session-manager/dist/session-metering.js +292 -0
  57. package/payload/platform/services/claude-session-manager/dist/session-metering.js.map +1 -0
  58. package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
  59. package/payload/server/public/assets/{AdminLoginScreens-BejIjbmU.js → AdminLoginScreens-CL27ZV86.js} +1 -1
  60. package/payload/server/public/assets/AdminShell-CBcSh9Yd.js +1 -0
  61. package/payload/server/public/assets/{Checkbox-1F1tzqca.js → Checkbox-DRIcYN9r.js} +1 -1
  62. package/payload/server/public/assets/{Transcript-DkGa4CQH.js → Transcript-CRc72hkG.js} +1 -1
  63. package/payload/server/public/assets/{admin-DqQARkjy.js → admin-iKYYnv3w.js} +1 -1
  64. package/payload/server/public/assets/{browser-nDtEK6RC.js → browser--8gzAe-E.js} +1 -1
  65. package/payload/server/public/assets/calendar-7xAT81N_.js +1 -0
  66. package/payload/server/public/assets/chat-B8Z9W42Z.js +1 -0
  67. package/payload/server/public/assets/chevron-left-DDselYau.js +1 -0
  68. package/payload/server/public/assets/data-Ece320dZ.js +1 -0
  69. package/payload/server/public/assets/{graph-DFyicKd7.js → graph-B3haz2DN.js} +2 -2
  70. package/payload/server/public/assets/{graph-labels-D3BQdcpD.js → graph-labels-Ba_fyw6I.js} +1 -1
  71. package/payload/server/public/assets/{operator-BxrjWdT9.js → operator-BYL1IFz9.js} +1 -1
  72. package/payload/server/public/assets/page-Bj6lB07z.js +32 -0
  73. package/payload/server/public/assets/page-CLKVCquw.js +1 -0
  74. package/payload/server/public/assets/{public-DbdqfdYq.js → public-BKJUKC76.js} +1 -1
  75. package/payload/server/public/assets/{rotate-ccw-BkX8HODe.js → rotate-ccw-BypBbSI4.js} +1 -1
  76. package/payload/server/public/assets/useSubAccountSwitcher-4qilMyPX.css +1 -0
  77. package/payload/server/public/assets/useSubAccountSwitcher-CsRv6MEd.js +9 -0
  78. package/payload/server/public/browser.html +4 -4
  79. package/payload/server/public/calendar.html +5 -5
  80. package/payload/server/public/chat.html +8 -8
  81. package/payload/server/public/data.html +7 -7
  82. package/payload/server/public/graph.html +8 -8
  83. package/payload/server/public/index.html +10 -10
  84. package/payload/server/public/operator.html +10 -10
  85. package/payload/server/public/public.html +8 -8
  86. package/payload/server/server.js +327 -255
  87. package/payload/platform/plugins/joblogic/.claude-plugin/plugin.json +0 -21
  88. package/payload/platform/plugins/joblogic/PLUGIN.md +0 -182
  89. package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/index.js +0 -193
  90. package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/package.json +0 -3
  91. package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts +0 -2
  92. package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts.map +0 -1
  93. package/payload/platform/plugins/joblogic/mcp/dist/index.js +0 -229
  94. package/payload/platform/plugins/joblogic/mcp/dist/index.js.map +0 -1
  95. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts +0 -31
  96. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts.map +0 -1
  97. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js +0 -78
  98. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js.map +0 -1
  99. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts +0 -35
  100. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts.map +0 -1
  101. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js +0 -106
  102. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js.map +0 -1
  103. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts +0 -8
  104. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts.map +0 -1
  105. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js +0 -41
  106. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js.map +0 -1
  107. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts +0 -21
  108. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts.map +0 -1
  109. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js +0 -47
  110. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js.map +0 -1
  111. package/payload/platform/plugins/joblogic/mcp/package.json +0 -10
  112. package/payload/platform/plugins/joblogic/skills/joblogic/SKILL.md +0 -32
  113. package/payload/server/public/assets/AdminShell-D2-uBSB5.js +0 -1
  114. package/payload/server/public/assets/calendar-CO4Bwmho.js +0 -1
  115. package/payload/server/public/assets/chat-DeIge_bC.js +0 -1
  116. package/payload/server/public/assets/chevron-left-DhVdq0aN.js +0 -1
  117. package/payload/server/public/assets/data-B1GIdzHk.js +0 -1
  118. package/payload/server/public/assets/page-ByDLq_o1.js +0 -1
  119. package/payload/server/public/assets/page-D-Ep4bXd.js +0 -32
  120. package/payload/server/public/assets/useSubAccountSwitcher-DMbRhLPv.js +0 -9
  121. package/payload/server/public/assets/useSubAccountSwitcher-DS0iqSkP.css +0 -1
@@ -0,0 +1,11 @@
1
+ /** Max time (ms) a spawned claude waits for the host to finish refreshing an
2
+ * expiring token before erroring. The host heartbeat refreshes proactively
3
+ * inside the 5-minute expiry window, so an in-flight refresh at spawn time is
4
+ * rare; 30s is a generous ceiling that never wedges a spawn. */
5
+ export declare const HOST_AUTH_REFRESH_TIMEOUT_MS = "30000";
6
+ /** Mutate `env` in place to enable claude's host-managed credentials-file mode
7
+ * when running on darwin, then return it. No-op on every other platform.
8
+ * `claudeConfigDir` is the brand's `.claude` dir; the credentials file is its
9
+ * `.credentials.json` child. */
10
+ export declare function applyHostCredsEnv(env: NodeJS.ProcessEnv, claudeConfigDir: string, platform?: NodeJS.Platform): NodeJS.ProcessEnv;
11
+ //# sourceMappingURL=claude-host-creds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-host-creds.d.ts","sourceRoot":"","sources":["../src/claude-host-creds.ts"],"names":[],"mappings":"AAsBA;;;iEAGiE;AACjE,eAAO,MAAM,4BAA4B,UAAU,CAAA;AAEnD;;;iCAGiC;AACjC,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,eAAe,EAAE,MAAM,EACvB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,CAAC,UAAU,CAMnB"}
@@ -0,0 +1,37 @@
1
+ // Task 1395 gap 1 — macOS credential-store bridge.
2
+ //
3
+ // On macOS the `claude` CLI stores its OAuth token in the login Keychain,
4
+ // while this platform reads and refreshes the token from a FILE
5
+ // (`<CLAUDE_CONFIG_DIR>/.credentials.json`, the same path the UI server's
6
+ // readCredentials()/writeOAuthCredentials() own). Left alone the two never
7
+ // meet: auth-health reads an empty file and reports `missing` forever.
8
+ //
9
+ // `claude` exposes a host-managed credentials-file mode: point
10
+ // CLAUDE_CODE_HOST_CREDS_FILE at that file and the spawned claude reads/writes
11
+ // the token there instead of the Keychain, and — crucially — does NOT run its
12
+ // own refresh, waiting up to CLAUDE_CODE_HOST_AUTH_REFRESH_TIMEOUT_MS for the
13
+ // host (this platform's auth-health heartbeat) to refresh an expiring token.
14
+ // That keeps a single refresh owner and no double-refresh race.
15
+ //
16
+ // Darwin-only: on Linux `claude` already defaults to the same file under
17
+ // CLAUDE_CONFIG_DIR, so setting host-creds mode there would needlessly switch
18
+ // refresh ownership. The regression boundary is that Linux stays byte-for-byte
19
+ // unchanged.
20
+ import { join } from 'node:path';
21
+ /** Max time (ms) a spawned claude waits for the host to finish refreshing an
22
+ * expiring token before erroring. The host heartbeat refreshes proactively
23
+ * inside the 5-minute expiry window, so an in-flight refresh at spawn time is
24
+ * rare; 30s is a generous ceiling that never wedges a spawn. */
25
+ export const HOST_AUTH_REFRESH_TIMEOUT_MS = '30000';
26
+ /** Mutate `env` in place to enable claude's host-managed credentials-file mode
27
+ * when running on darwin, then return it. No-op on every other platform.
28
+ * `claudeConfigDir` is the brand's `.claude` dir; the credentials file is its
29
+ * `.credentials.json` child. */
30
+ export function applyHostCredsEnv(env, claudeConfigDir, platform = process.platform) {
31
+ if (platform === 'darwin' && claudeConfigDir) {
32
+ env.CLAUDE_CODE_HOST_CREDS_FILE = join(claudeConfigDir, '.credentials.json');
33
+ env.CLAUDE_CODE_HOST_AUTH_REFRESH_TIMEOUT_MS = HOST_AUTH_REFRESH_TIMEOUT_MS;
34
+ }
35
+ return env;
36
+ }
37
+ //# sourceMappingURL=claude-host-creds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-host-creds.js","sourceRoot":"","sources":["../src/claude-host-creds.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,0EAA0E;AAC1E,gEAAgE;AAChE,0EAA0E;AAC1E,2EAA2E;AAC3E,uEAAuE;AACvE,EAAE;AACF,+DAA+D;AAC/D,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,gEAAgE;AAChE,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,+EAA+E;AAC/E,aAAa;AAEb,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC;;;iEAGiE;AACjE,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAA;AAEnD;;;iCAGiC;AACjC,MAAM,UAAU,iBAAiB,CAC/B,GAAsB,EACtB,eAAuB,EACvB,WAA4B,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,QAAQ,IAAI,eAAe,EAAE,CAAC;QAC7C,GAAG,CAAC,2BAA2B,GAAG,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAA;QAC5E,GAAG,CAAC,wCAAwC,GAAG,4BAA4B,CAAA;IAC7E,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAe3B,OAAO,EAkBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AA4BzB,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAA;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAgFlE,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,WAAW,EAAE,kBAAkB,CAAA;IAC/B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;6BAGyB;IACzB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;;;sCAGkC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAsFD;;;;;;mEAMmE;AACnE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC9D;AAMD;;;;;;iBAMiB;AACjB,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAmCvF;AAID;;;;;;yBAMyB;AACzB,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAiCzD;AAkCD,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpG;AAgBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAUD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMvE;AAMD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAER;AAkCD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5F;AAwJD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AA8CD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CA6qFpD"}
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAe3B,OAAO,EAkBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AA6BzB,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAA;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAyFlE,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,WAAW,EAAE,kBAAkB,CAAA;IAC/B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;6BAGyB;IACzB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;;;sCAGkC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAsFD;;;;;;mEAMmE;AACnE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC9D;AAMD;;;;;;iBAMiB;AACjB,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAmCvF;AAID;;;;;;yBAMyB;AACzB,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAiCzD;AAkCD,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpG;AAgBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAUD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMvE;AAMD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAER;AAkCD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5F;AAwJD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AA8CD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CA4vFpD"}
@@ -27,7 +27,7 @@ import { buildWebchatChannelMcpServers, buildWebchatChannelArgv, webchatChannelM
27
27
  import { buildTelegramChannelMcpServers, buildTelegramChannelArgv, telegramChannelMcpConfigPath } from './telegram-channel-mcp.js';
28
28
  import { buildChannelMcpServers, buildChannelArgv, channelMcpConfigPath } from './channel-mcp.js';
29
29
  import { mergeTarget, isMultiTarget, targetKinds } from './channel-targets.js';
30
- import { randomUUID } from 'node:crypto';
30
+ import { randomUUID, createHash } from 'node:crypto';
31
31
  import { execFile, execFileSync } from 'node:child_process';
32
32
  import { buildRcChildEnv, reapplyAdminLevers } from './rc-daemon.js';
33
33
  import { runConnectorAuthLogin } from './connector-auth.js';
@@ -44,6 +44,7 @@ import { createRcChildLog } from './rc-child-log.js';
44
44
  // --append-system-prompt for channel-bound admin sessions.
45
45
  import { extractVoiceSection } from './system-prompt.js';
46
46
  import { readJsonlSession } from './jsonl-enumerator.js';
47
+ import { computeMetering } from './session-metering.js';
47
48
  import { claudeStateRoot, projectSlugForCwd, jsonlPathForSessionId, sidecarPathForSessionId, permissionModeLogPathForSessionId, findExistingJsonlForSessionId, slugForExistingJsonl, jsonlPathForSlug, sidecarPathForSlug, detectRemoteControlSlug, classifyBindBlocker, } from './jsonl-path.js';
48
49
  import { basename, dirname, join } from 'node:path';
49
50
  import { validateUserTitle } from './user-title-store.js';
@@ -54,6 +55,15 @@ const CHANNELS = ['browser', 'whatsapp', 'telegram', 'webchat', 'email'];
54
55
  // sessionId UUID (v4) minted by createNewAdminConversation in
55
56
  // platform/ui/app/lib/neo4j-store.ts.
56
57
  const UUID_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
58
+ // Task 1392 — the WhatsApp-channel launch-param override. Every WhatsApp admin
59
+ // session runs Sonnet 5 / effort max / bypass, overriding the Task 956 fixed admin
60
+ // params (Opus 4.8 / medium, resolved from settings.json). Expressed as an explicit
61
+ // constant set mirroring the rc-daemon `ADMIN_*` shape. Permission mode is already
62
+ // bypassPermissions (settings.json), so only model + effort are asserted here. `max`
63
+ // is session-only and invalid as a settings.json `effortLevel`, so it rides the
64
+ // `--effort max` argv flag, not the inline settings.
65
+ const WHATSAPP_ADMIN_MODEL = SONNET_MODEL;
66
+ const WHATSAPP_ADMIN_EFFORT = 'max';
57
67
  function parseAboutOwner(raw) {
58
68
  if (!raw || typeof raw !== 'object')
59
69
  return undefined;
@@ -1402,6 +1412,37 @@ export function buildHttpApp(deps) {
1402
1412
  timed(deps.logger, 'GET', `/${id}/meta`, 200, Date.now() - start);
1403
1413
  return c.json(payload, 200);
1404
1414
  });
1415
+ // Task 1384 — deterministic per-day usage & GBP cost for one session. Reads
1416
+ // whichever location holds the JSONL (top level or archive subdir), runs the
1417
+ // full-parse metering core (no AI), and returns the summary. The `op=surface`
1418
+ // checksum lets the http and MCP callers be proven to agree on one session.
1419
+ app.get('/:sessionId/metering', async (c) => {
1420
+ const start = Date.now();
1421
+ const id = c.req.param('sessionId');
1422
+ if (!SESSION_ID_PATTERN.test(id)) {
1423
+ timed(deps.logger, 'GET', `/${id}/metering`, 400, Date.now() - start);
1424
+ return c.json({ error: 'invalid-session-id' }, 400);
1425
+ }
1426
+ const row = resolveRow(deps.watcher, id);
1427
+ if (!row) {
1428
+ timed(deps.logger, 'GET', `/${id}/metering`, 404, Date.now() - start);
1429
+ return c.json({ error: 'session-not-found' }, 404);
1430
+ }
1431
+ const topJsonl = jsonlPathForSessionId(deps.spawnCwd, row.sessionId);
1432
+ const archivedJsonl = jsonlPathForSessionId(deps.spawnCwd, row.sessionId, { archived: true });
1433
+ const jsonlPath = existsSync(topJsonl) ? topJsonl : archivedJsonl;
1434
+ if (!existsSync(jsonlPath)) {
1435
+ timed(deps.logger, 'GET', `/${id}/metering`, 404, Date.now() - start);
1436
+ return c.json({ error: 'session-not-found' }, 404);
1437
+ }
1438
+ const summary = await computeMetering(jsonlPath, { logger: deps.logger });
1439
+ const checksum = createHash('sha256').update(JSON.stringify(summary)).digest('hex').slice(0, 16);
1440
+ const bytes = statSync(jsonlPath).size;
1441
+ deps.logger(`[metering] op=surface caller=http sessionId=${row.sessionId.slice(0, 8)} checksum=${checksum}`);
1442
+ deps.logger(`[metering] op=http sessionId=${row.sessionId.slice(0, 8)} ms=${Date.now() - start} bytes=${bytes}`);
1443
+ timed(deps.logger, 'GET', `/${id}/metering`, 200, Date.now() - start);
1444
+ return c.json(summary, 200);
1445
+ });
1405
1446
  app.post('/:sessionId/archive', async (c) => {
1406
1447
  const start = Date.now();
1407
1448
  const id = c.req.param('sessionId');
@@ -2394,6 +2435,28 @@ export function buildHttpApp(deps) {
2394
2435
  // ingest, public, specialist, channel cold-start) on the settings defaults
2395
2436
  // even if a future caller were to put model/effort on its body.
2396
2437
  const freshAdminLevers = mode === 'fresh' && rcRole === 'admin';
2438
+ // Task 1392 — resolve whether this spawn runs under the WhatsApp Sonnet-5/max
2439
+ // override, for BOTH the argv and the reported launch params below. Only
2440
+ // sessions BORN under the override adopt it, so an existing Opus-born WhatsApp
2441
+ // session finishes its life on Opus:
2442
+ // - fresh: a WhatsApp admin spawn (gateway body carries role:'admin',
2443
+ // channel:'whatsapp', and waChannel) is birthed under the override. The
2444
+ // channel gate matches exactly what the classification sidecar records
2445
+ // (`classifyChannel`), so the argv override and the born-stamp can never
2446
+ // disagree.
2447
+ // - resume: the override is inherited iff the session's classification
2448
+ // sidecar was stamped model=SONNET_MODEL at birth. A bare operator/PIN
2449
+ // resume omits role/channel/waChannel, so the sidecar — not the request
2450
+ // body — is the authoritative born-under-override signal (no other spawn
2451
+ // path stamps a WhatsApp-admin sidecar with a Sonnet model).
2452
+ const whatsappResumeSidecar = mode === 'resume' && sessionId
2453
+ ? readSidecar(sidecarPathForSessionId(effectiveAccountDir, sessionId), deps.logger).sidecar
2454
+ : null;
2455
+ const whatsappSonnetSpawn = mode === 'fresh'
2456
+ ? rcRole === 'admin' && adminChannel === 'whatsapp' && waChannel !== undefined
2457
+ : whatsappResumeSidecar?.role === 'admin' &&
2458
+ whatsappResumeSidecar?.channel === 'whatsapp' &&
2459
+ whatsappResumeSidecar?.model === WHATSAPP_ADMIN_MODEL;
2397
2460
  const argv = ['--remote-control'];
2398
2461
  // Task 945 — `name` is the row's display label, never a prompt. It must NOT
2399
2462
  // be pushed as a positional: the CLI treats a bare positional as the initial
@@ -2419,11 +2482,16 @@ export function buildHttpApp(deps) {
2419
2482
  }
2420
2483
  else if (sessionId) {
2421
2484
  argv.push(mode === 'resume' ? '--resume' : '--session-id', sessionId);
2422
- // Task 969 — a fresh new-session spawn (the /chat new-session popover)
2423
- // carries the picked model as the canonical --model flag. A resume keeps
2424
- // the model its JSONL already ran under, and an absent/invalid model
2485
+ // Task 1392 — a WhatsApp admin session (fresh spawn or a resume born under
2486
+ // the override) is pinned to Sonnet 5 on both branches, so the model holds
2487
+ // for the session's whole life and cannot revert to the settings default.
2488
+ // Task 969 — otherwise, a fresh new-session spawn (the /chat new-session
2489
+ // popover) carries the picked model as the canonical --model flag. A resume
2490
+ // keeps the model its JSONL already ran under, and an absent/invalid model
2425
2491
  // (reseatModel null) leaves the settings.json default model in force.
2426
- if (freshAdminLevers && reseatModel)
2492
+ if (whatsappSonnetSpawn)
2493
+ argv.push('--model', WHATSAPP_ADMIN_MODEL);
2494
+ else if (freshAdminLevers && reseatModel)
2427
2495
  argv.push('--model', reseatModel);
2428
2496
  }
2429
2497
  // Task 592 — per-spawn bypass-permissions waiver. The brand settings.json
@@ -2445,6 +2513,14 @@ export function buildHttpApp(deps) {
2445
2513
  if (reseatEffort)
2446
2514
  inlineSettings.effortLevel = reseatEffort;
2447
2515
  }
2516
+ else if (whatsappSonnetSpawn) {
2517
+ // Task 1392 — WhatsApp admin effort is pinned to `max` on both the fresh
2518
+ // spawn and every resume born under the override. `max` is session-only
2519
+ // (invalid as a settings.json effortLevel), so it rides the --effort argv
2520
+ // flag; asserting it on resume too stops the effort reverting to the
2521
+ // settings default (medium) on the session's second turn.
2522
+ argv.push('--effort', WHATSAPP_ADMIN_EFFORT);
2523
+ }
2448
2524
  else if (freshAdminLevers && freshEffort) {
2449
2525
  if (freshEffort === 'max')
2450
2526
  argv.push('--effort', 'max');
@@ -2731,11 +2807,21 @@ export function buildHttpApp(deps) {
2731
2807
  // Task 969 — a fresh new-session spawn carrying picked levers runs under
2732
2808
  // them too (not just a fork), so the sidecar + lifeline + the /chat params
2733
2809
  // row report the model/effort the session actually launched on.
2734
- const effectiveRcModel = (forkFromSessionId !== null || freshAdminLevers) && reseatModel ? reseatModel : resolveSettingsModel(deps.claudeConfigDir);
2810
+ const effectiveRcModel = whatsappSonnetSpawn
2811
+ ? WHATSAPP_ADMIN_MODEL
2812
+ : (forkFromSessionId !== null || freshAdminLevers) && reseatModel
2813
+ ? reseatModel
2814
+ : resolveSettingsModel(deps.claudeConfigDir);
2735
2815
  // Task 970 — the fork path reports its 4-level effort; the fresh path reports
2736
2816
  // its 5-level pick (incl. `max`). Falls back to the settings-resolved effort
2737
2817
  // when neither path carries one (absent on a fork, invalid/absent on a fresh).
2738
- const pickedRcEffort = forkFromSessionId !== null ? reseatEffort : freshAdminLevers ? freshEffort : undefined;
2818
+ const pickedRcEffort = whatsappSonnetSpawn
2819
+ ? WHATSAPP_ADMIN_EFFORT
2820
+ : forkFromSessionId !== null
2821
+ ? reseatEffort
2822
+ : freshAdminLevers
2823
+ ? freshEffort
2824
+ : undefined;
2739
2825
  const effectiveRcEffort = pickedRcEffort ?? resolveSettingsEffort(deps.claudeConfigDir);
2740
2826
  // Step 2 — the exact claude argv (the inner command). The systemd-run
2741
2827
  // wrap is composed by the spawnPty adapter; logging the inner argv
@@ -2859,7 +2945,11 @@ export function buildHttpApp(deps) {
2859
2945
  // passes no --debug=auto-mode.
2860
2946
  permissionMode: effectiveRcPermissionMode,
2861
2947
  effectivePermissionMode: null,
2862
- model: null,
2948
+ // Task 1392 — a fresh WhatsApp admin spawn stamps its Sonnet model
2949
+ // here so a later resume can read this marker back and re-assert the
2950
+ // override; every other spawn leaves this null (the wire `model`
2951
+ // still derives from the JSONL, per the sidecar field contract).
2952
+ model: whatsappSonnetSpawn ? WHATSAPP_ADMIN_MODEL : null,
2863
2953
  hidden: false,
2864
2954
  specialist: null,
2865
2955
  scopeUnitToken: unitToken,