@rubytech/create-maxy-code 0.1.387 → 0.1.389

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 (101) hide show
  1. package/dist/__tests__/joblogic-excluded.test.js +39 -0
  2. package/dist/index.js +21 -0
  3. package/package.json +1 -1
  4. package/payload/platform/config/brand.json +1 -1
  5. package/payload/platform/plugins/.claude-plugin/marketplace.json +0 -5
  6. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +21 -2
  7. package/payload/platform/plugins/docs/references/admin-session.md +4 -0
  8. package/payload/platform/plugins/docs/references/admin-ui.md +18 -1
  9. package/payload/platform/plugins/docs/references/joblogic.md +2 -0
  10. package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +7 -3
  11. package/payload/platform/plugins/whatsapp/skills/manage-whatsapp-config/SKILL.md +2 -0
  12. package/payload/platform/plugins/work/PLUGIN.md +3 -0
  13. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.d.ts +2 -0
  14. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.d.ts.map +1 -0
  15. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js +98 -0
  16. package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js.map +1 -0
  17. package/payload/platform/plugins/work/mcp/dist/index.js +16 -0
  18. package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
  19. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.d.ts +53 -0
  20. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.d.ts.map +1 -0
  21. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js +80 -0
  22. package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js.map +1 -0
  23. package/payload/platform/plugins/work/mcp/package.json +2 -1
  24. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  25. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
  26. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  27. package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
  28. package/payload/platform/services/claude-session-manager/dist/http-server.js +98 -8
  29. package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
  30. package/payload/platform/services/claude-session-manager/dist/pricing.d.ts +45 -0
  31. package/payload/platform/services/claude-session-manager/dist/pricing.d.ts.map +1 -0
  32. package/payload/platform/services/claude-session-manager/dist/pricing.js +57 -0
  33. package/payload/platform/services/claude-session-manager/dist/pricing.js.map +1 -0
  34. package/payload/platform/services/claude-session-manager/dist/session-metering.d.ts +38 -0
  35. package/payload/platform/services/claude-session-manager/dist/session-metering.d.ts.map +1 -0
  36. package/payload/platform/services/claude-session-manager/dist/session-metering.js +292 -0
  37. package/payload/platform/services/claude-session-manager/dist/session-metering.js.map +1 -0
  38. package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
  39. package/payload/server/public/assets/{AdminLoginScreens-BejIjbmU.js → AdminLoginScreens-CerrEc_m.js} +1 -1
  40. package/payload/server/public/assets/AdminShell-cRTvNRbo.js +1 -0
  41. package/payload/server/public/assets/{Checkbox-1F1tzqca.js → Checkbox-Dh2pLMFN.js} +1 -1
  42. package/payload/server/public/assets/{Transcript-DkGa4CQH.js → Transcript-B_GVJujB.js} +1 -1
  43. package/payload/server/public/assets/{admin-DqQARkjy.js → admin-BXaYelnR.js} +1 -1
  44. package/payload/server/public/assets/{browser-nDtEK6RC.js → browser-fhjGE7fH.js} +1 -1
  45. package/payload/server/public/assets/calendar-PnZudAtc.js +1 -0
  46. package/payload/server/public/assets/chat-Dy_zrjKS.js +1 -0
  47. package/payload/server/public/assets/chevron-left-IB6TmMZ_.js +1 -0
  48. package/payload/server/public/assets/data-B2IcjAj6.js +1 -0
  49. package/payload/server/public/assets/{graph-DFyicKd7.js → graph-CycO3tkW.js} +2 -2
  50. package/payload/server/public/assets/{graph-labels-D3BQdcpD.js → graph-labels-DlSsSpBV.js} +1 -1
  51. package/payload/server/public/assets/{operator-BxrjWdT9.js → operator-L4kBC-zS.js} +1 -1
  52. package/payload/server/public/assets/page-D5E-Ng4D.js +1 -0
  53. package/payload/server/public/assets/page-M8sD9LOi.js +32 -0
  54. package/payload/server/public/assets/{public-DbdqfdYq.js → public-BmnajF3K.js} +1 -1
  55. package/payload/server/public/assets/{rotate-ccw-BkX8HODe.js → rotate-ccw-W5HhvAbo.js} +1 -1
  56. package/payload/server/public/assets/useSubAccountSwitcher-D1TI1xvd.css +1 -0
  57. package/payload/server/public/assets/useSubAccountSwitcher-UqZbmzYy.js +9 -0
  58. package/payload/server/public/browser.html +4 -4
  59. package/payload/server/public/calendar.html +5 -5
  60. package/payload/server/public/chat.html +8 -8
  61. package/payload/server/public/data.html +7 -7
  62. package/payload/server/public/graph.html +8 -8
  63. package/payload/server/public/index.html +10 -10
  64. package/payload/server/public/operator.html +10 -10
  65. package/payload/server/public/public.html +8 -8
  66. package/payload/server/server.js +444 -315
  67. package/payload/platform/plugins/joblogic/.claude-plugin/plugin.json +0 -21
  68. package/payload/platform/plugins/joblogic/PLUGIN.md +0 -182
  69. package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/index.js +0 -193
  70. package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/package.json +0 -3
  71. package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts +0 -2
  72. package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts.map +0 -1
  73. package/payload/platform/plugins/joblogic/mcp/dist/index.js +0 -229
  74. package/payload/platform/plugins/joblogic/mcp/dist/index.js.map +0 -1
  75. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts +0 -31
  76. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts.map +0 -1
  77. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js +0 -78
  78. package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js.map +0 -1
  79. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts +0 -35
  80. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts.map +0 -1
  81. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js +0 -106
  82. package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js.map +0 -1
  83. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts +0 -8
  84. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts.map +0 -1
  85. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js +0 -41
  86. package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js.map +0 -1
  87. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts +0 -21
  88. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts.map +0 -1
  89. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js +0 -47
  90. package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js.map +0 -1
  91. package/payload/platform/plugins/joblogic/mcp/package.json +0 -10
  92. package/payload/platform/plugins/joblogic/skills/joblogic/SKILL.md +0 -32
  93. package/payload/server/public/assets/AdminShell-D2-uBSB5.js +0 -1
  94. package/payload/server/public/assets/calendar-CO4Bwmho.js +0 -1
  95. package/payload/server/public/assets/chat-DeIge_bC.js +0 -1
  96. package/payload/server/public/assets/chevron-left-DhVdq0aN.js +0 -1
  97. package/payload/server/public/assets/data-B1GIdzHk.js +0 -1
  98. package/payload/server/public/assets/page-ByDLq_o1.js +0 -1
  99. package/payload/server/public/assets/page-D-Ep4bXd.js +0 -32
  100. package/payload/server/public/assets/useSubAccountSwitcher-DMbRhLPv.js +0 -9
  101. package/payload/server/public/assets/useSubAccountSwitcher-DS0iqSkP.css +0 -1
@@ -0,0 +1,57 @@
1
+ // Dated pricing / FX / tokenizer constants for session metering (Task 1384).
2
+ //
3
+ // Every value here is NAMED and DATED with a source, never a bare literal in the
4
+ // cost math. When Anthropic changes list prices or the GBP rate drifts, edit the
5
+ // constant and bump OPUS_PRICE_DATE — `pricingIsStale` warns once the date ages
6
+ // past 90 days so a stale estimate is a visible signal, not a silent drift.
7
+ //
8
+ // Source: https://www.anthropic.com/pricing#api (list API prices, USD per 1M tokens)
9
+ // Captured: 2026-07-04.
10
+ export const PRICING_SOURCE = 'https://www.anthropic.com/pricing#api';
11
+ export const OPUS_PRICE_DATE = '2026-07-04';
12
+ /** Default GBP conversion. USD amounts are divided by this to yield GBP. */
13
+ export const USD_PER_GBP = 1.34;
14
+ /** Sonnet 4.6 uses an older tokenizer; every token count is multiplied by this
15
+ * factor before the Sonnet rate is applied, so its estimate reflects the token
16
+ * volume that tokenizer would have produced. Opus 4.8 counts are used as-is. */
17
+ export const SONNET_TOKENIZER_FACTOR = 0.7;
18
+ /** USD per 1,000,000 tokens. `cacheWrite5m` is the 5-minute cache-creation rate;
19
+ * session metering prices all `cache_creation_input_tokens` at this rate. */
20
+ export const OPUS_4_8 = { input: 5, cacheWrite5m: 6.25, cacheRead: 0.5, output: 25 };
21
+ export const SONNET_4_6 = { input: 3, cacheWrite5m: 3.75, cacheRead: 0.3, output: 15 };
22
+ export function defaultPricingConfig() {
23
+ return { usdPerGbp: USD_PER_GBP, tokenizerFactor: SONNET_TOKENIZER_FACTOR, priceDate: OPUS_PRICE_DATE };
24
+ }
25
+ function usdPerMillion(rate, t) {
26
+ return (t.input * rate.input +
27
+ t.cacheWrite * rate.cacheWrite5m +
28
+ t.cacheRead * rate.cacheRead +
29
+ t.output * rate.output) / 1_000_000;
30
+ }
31
+ /** GBP cost of a token bundle at the Opus 4.8 rate (no tokenizer scaling). */
32
+ export function opusCostGBP(t, cfg) {
33
+ return usdPerMillion(OPUS_4_8, t) / cfg.usdPerGbp;
34
+ }
35
+ /** GBP cost at the Sonnet 4.6 rate with every token count scaled by the
36
+ * tokenizer factor. */
37
+ export function sonnetCostGBP(t, cfg) {
38
+ const f = cfg.tokenizerFactor;
39
+ const scaled = {
40
+ input: t.input * f,
41
+ cacheWrite: t.cacheWrite * f,
42
+ cacheRead: t.cacheRead * f,
43
+ output: t.output * f,
44
+ };
45
+ return usdPerMillion(SONNET_4_6, scaled) / cfg.usdPerGbp;
46
+ }
47
+ /** True when `priceDate` is more than 90 days before `nowIso`. Both are ISO
48
+ * date strings; comparison is in whole UTC days. */
49
+ export function pricingIsStale(cfg, nowIso) {
50
+ const price = Date.parse(cfg.priceDate);
51
+ const now = Date.parse(nowIso);
52
+ if (!Number.isFinite(price) || !Number.isFinite(now))
53
+ return false;
54
+ const days = (now - price) / 86_400_000;
55
+ return days > 90;
56
+ }
57
+ //# sourceMappingURL=pricing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pricing.js","sourceRoot":"","sources":["../src/pricing.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,iFAAiF;AACjF,iFAAiF;AACjF,gFAAgF;AAChF,4EAA4E;AAC5E,EAAE;AACF,sFAAsF;AACtF,wBAAwB;AAExB,MAAM,CAAC,MAAM,cAAc,GAAG,uCAAuC,CAAA;AACrE,MAAM,CAAC,MAAM,eAAe,GAAG,YAAY,CAAA;AAE3C,4EAA4E;AAC5E,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAA;AAC/B;;iFAEiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAA;AAE1C;8EAC8E;AAC9E,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAW,CAAA;AAC7F,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAW,CAAA;AAmB/F,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,uBAAuB,EAAE,SAAS,EAAE,eAAe,EAAE,CAAA;AACzG,CAAC;AAED,SAAS,aAAa,CAAC,IAAe,EAAE,CAAiB;IACvD,OAAO,CACL,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK;QACpB,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,YAAY;QAChC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS;QAC5B,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CACvB,GAAG,SAAS,CAAA;AACf,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,WAAW,CAAC,CAAiB,EAAE,GAAkB;IAC/D,OAAO,aAAa,CAAC,QAAQ,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,SAAS,CAAA;AACnD,CAAC;AAED;wBACwB;AACxB,MAAM,UAAU,aAAa,CAAC,CAAiB,EAAE,GAAkB;IACjE,MAAM,CAAC,GAAG,GAAG,CAAC,eAAe,CAAA;IAC7B,MAAM,MAAM,GAAmB;QAC7B,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,CAAC;QAClB,UAAU,EAAE,CAAC,CAAC,UAAU,GAAG,CAAC;QAC5B,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,CAAC;QAC1B,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC;KACrB,CAAA;IACD,OAAO,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,SAAS,CAAA;AAC1D,CAAC;AAED;qDACqD;AACrD,MAAM,UAAU,cAAc,CAAC,GAAkB,EAAE,MAAc;IAC/D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAA;IAClE,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,UAAU,CAAA;IACvC,OAAO,IAAI,GAAG,EAAE,CAAA;AAClB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { type PricingConfig, type MeteringTokens } from './pricing.js';
2
+ export interface MeteringActive {
3
+ thinking: number;
4
+ messaging: number;
5
+ toolUse: number;
6
+ }
7
+ export interface MeteringCost {
8
+ opus: number;
9
+ sonnet: number;
10
+ }
11
+ export interface MeteringDay {
12
+ date: string;
13
+ activeMs: MeteringActive;
14
+ idleMs: number;
15
+ turns: number;
16
+ tools: number;
17
+ tokens: MeteringTokens;
18
+ costGBP: MeteringCost;
19
+ }
20
+ export interface MeteringSummary {
21
+ sessionId: string;
22
+ days: MeteringDay[];
23
+ totals: Omit<MeteringDay, 'date'>;
24
+ corrOutputVsActive: number;
25
+ pricing: {
26
+ opusPriceDate: string;
27
+ usdPerGbp: number;
28
+ tokenizerFactor: number;
29
+ };
30
+ }
31
+ export interface ComputeMeteringOpts {
32
+ pricing?: PricingConfig;
33
+ nowIso?: string;
34
+ logger?: (m: string) => void;
35
+ verbose?: boolean;
36
+ }
37
+ export declare function computeMetering(jsonlPath: string, opts?: ComputeMeteringOpts): Promise<MeteringSummary>;
38
+ //# sourceMappingURL=session-metering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-metering.d.ts","sourceRoot":"","sources":["../src/session-metering.ts"],"names":[],"mappings":"AA2BA,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,cAAc,EACpB,MAAM,cAAc,CAAA;AAIrB,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB;AACD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,cAAc,CAAA;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,cAAc,CAAA;IACtB,OAAO,EAAE,YAAY,CAAA;CACtB;AACD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,WAAW,EAAE,CAAA;IACnB,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;IACjC,kBAAkB,EAAE,MAAM,CAAA;IAC1B,OAAO,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAA;CAC/E;AAwCD,MAAM,WAAW,mBAAmB;IAClC,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA6N1B"}
@@ -0,0 +1,292 @@
1
+ // Deterministic per-day metering over a full session JSONL (Task 1384).
2
+ //
3
+ // One streaming pass produces per-day active time (thinking / messaging / tool
4
+ // use), idle time, turn and matched-tool counts, deduped token classes, and
5
+ // estimated GBP cost for Opus 4.8 and Sonnet 4.6. No LLM in the path — the same
6
+ // summary is served by the http endpoint and the MCP tool.
7
+ //
8
+ // Model (all values from the task-1384 evidence; see pricing.ts for constants):
9
+ // - Only `user` and `assistant` records anchor time. Auxiliary record types
10
+ // (attachment, queue-operation, last-prompt, system, mode) carry out-of-order
11
+ // timestamps and are ignored.
12
+ // - Each assistant JSONL line carries exactly one content block (thinking |
13
+ // text | tool_use). Time is tiled over consecutive records in FILE ORDER:
14
+ // the delta ending at a record is attributed by that record's kind. A
15
+ // negative delta (rare sub-second streaming write race) clamps to 0 and its
16
+ // magnitude accrues to residualMs.
17
+ // - A delta into the FIRST assistant block of a turn (prior record not an
18
+ // assistant block) counts as idle when it exceeds 120s (human wait); a
19
+ // tool_result delta is folded into tool use; a human inbound delta is idle.
20
+ // - Tokens are turn-level: `message.usage` repeats identically across a turn's
21
+ // block-lines, so they are deduped by `message.id` and attributed to the UTC
22
+ // day of that turn's first block-line. Thinking is redacted (`thinking:''`),
23
+ // so per-activity token attribution is structurally impossible.
24
+ import { createReadStream } from 'node:fs';
25
+ import { createInterface } from 'node:readline';
26
+ import { basename } from 'node:path';
27
+ import { defaultPricingConfig, opusCostGBP, sonnetCostGBP, pricingIsStale, OPUS_4_8, } from './pricing.js';
28
+ const IDLE_LEAD_MS = 120_000;
29
+ function zeroTokens() {
30
+ return { output: 0, input: 0, cacheWrite: 0, cacheRead: 0 };
31
+ }
32
+ function newDay() {
33
+ return {
34
+ activeMs: { thinking: 0, messaging: 0, toolUse: 0 },
35
+ idleMs: 0,
36
+ tokens: zeroTokens(),
37
+ turnIds: new Set(),
38
+ toolUseIds: [],
39
+ };
40
+ }
41
+ function dayKey(tsMs) {
42
+ return new Date(tsMs).toISOString().slice(0, 10);
43
+ }
44
+ function num(x) {
45
+ return typeof x === 'number' && Number.isFinite(x) ? x : 0;
46
+ }
47
+ export async function computeMetering(jsonlPath, opts = {}) {
48
+ const cfg = opts.pricing ?? defaultPricingConfig();
49
+ const sessionId = basename(jsonlPath).replace(/\.jsonl$/, '');
50
+ const log = (m) => opts.logger?.(`[metering] ${m}`);
51
+ const evs = [];
52
+ const usageById = new Map(); // first usage per turn
53
+ const firstLineById = new Map(); // first block-line ts per turn
54
+ const toolResultIds = new Set();
55
+ let thinkingBlocks = 0;
56
+ let thinkingWithText = 0;
57
+ const rl = createInterface({ input: createReadStream(jsonlPath, { encoding: 'utf8' }), crlfDelay: Infinity });
58
+ for await (const line of rl) {
59
+ if (!line)
60
+ continue;
61
+ let o;
62
+ try {
63
+ o = JSON.parse(line);
64
+ }
65
+ catch {
66
+ continue;
67
+ }
68
+ const type = o?.type;
69
+ if (type !== 'user' && type !== 'assistant')
70
+ continue;
71
+ const ts = typeof o.timestamp === 'string' ? Date.parse(o.timestamp) : NaN;
72
+ if (!Number.isFinite(ts))
73
+ continue;
74
+ const msg = o.message;
75
+ if (!msg || typeof msg !== 'object')
76
+ continue;
77
+ if (type === 'user') {
78
+ const content = msg.content;
79
+ if (Array.isArray(content)) {
80
+ const results = content.filter((b) => b && typeof b === 'object' && b.type === 'tool_result');
81
+ if (results.length > 0) {
82
+ for (const r of results) {
83
+ const id = r.tool_use_id;
84
+ if (typeof id === 'string')
85
+ toolResultIds.add(id);
86
+ }
87
+ evs.push({ ts, kind: 'toolResult', isAssistantBlock: false });
88
+ continue;
89
+ }
90
+ }
91
+ // string content, or a list with no tool_result → a human inbound turn
92
+ evs.push({ ts, kind: 'human', isAssistantBlock: false });
93
+ continue;
94
+ }
95
+ // assistant
96
+ const model = msg.model;
97
+ if (model === '<synthetic>')
98
+ continue; // CLI placeholder line, not a real turn
99
+ const messageId = typeof msg.id === 'string' ? msg.id : undefined;
100
+ const content = msg.content;
101
+ const block = Array.isArray(content) && content[0] && typeof content[0] === 'object' ? content[0] : null;
102
+ const btype = block?.type;
103
+ const usageRaw = msg.usage;
104
+ let usage;
105
+ if (usageRaw && typeof usageRaw === 'object') {
106
+ const u = usageRaw;
107
+ usage = {
108
+ output: num(u.output_tokens),
109
+ input: num(u.input_tokens),
110
+ cacheWrite: num(u.cache_creation_input_tokens),
111
+ cacheRead: num(u.cache_read_input_tokens),
112
+ };
113
+ }
114
+ if (messageId) {
115
+ if (!firstLineById.has(messageId))
116
+ firstLineById.set(messageId, ts);
117
+ if (usage && !usageById.has(messageId))
118
+ usageById.set(messageId, usage);
119
+ }
120
+ if (btype === 'thinking') {
121
+ thinkingBlocks += 1;
122
+ if (typeof block.thinking === 'string' && block.thinking.trim().length > 0)
123
+ thinkingWithText += 1;
124
+ evs.push({ ts, kind: 'thinking', isAssistantBlock: true, messageId, usage });
125
+ }
126
+ else if (btype === 'tool_use') {
127
+ const id = typeof block.id === 'string' ? block.id : undefined;
128
+ evs.push({ ts, kind: 'toolUse', isAssistantBlock: true, messageId, usage, toolUseId: id });
129
+ }
130
+ else {
131
+ // text (or any other single assistant block) — messaging
132
+ evs.push({ ts, kind: 'text', isAssistantBlock: true, messageId, usage });
133
+ }
134
+ }
135
+ const days = new Map();
136
+ const get = (key) => {
137
+ let d = days.get(key);
138
+ if (!d) {
139
+ d = newDay();
140
+ days.set(key, d);
141
+ }
142
+ return d;
143
+ };
144
+ // Time tiling — file order, clamp negatives into residual.
145
+ let residualMs = 0;
146
+ let prev = null;
147
+ for (const ev of evs) {
148
+ if (prev) {
149
+ let delta = ev.ts - prev.ts;
150
+ if (delta < 0) {
151
+ residualMs += -delta;
152
+ delta = 0;
153
+ }
154
+ const d = get(dayKey(ev.ts));
155
+ if (ev.kind === 'human') {
156
+ d.idleMs += delta;
157
+ }
158
+ else if (ev.kind === 'toolResult') {
159
+ d.activeMs.toolUse += delta;
160
+ }
161
+ else {
162
+ // assistant block
163
+ const leadIn = !prev.isAssistantBlock;
164
+ if (leadIn && delta > IDLE_LEAD_MS) {
165
+ d.idleMs += delta;
166
+ }
167
+ else if (ev.kind === 'thinking') {
168
+ d.activeMs.thinking += delta;
169
+ }
170
+ else if (ev.kind === 'text') {
171
+ d.activeMs.messaging += delta;
172
+ }
173
+ else {
174
+ d.activeMs.toolUse += delta;
175
+ }
176
+ }
177
+ }
178
+ prev = ev;
179
+ }
180
+ // Turns and tools per day.
181
+ for (const [id, ts] of firstLineById) {
182
+ get(dayKey(ts)).turnIds.add(id);
183
+ }
184
+ for (const ev of evs) {
185
+ if (ev.kind === 'toolUse' && ev.toolUseId)
186
+ get(dayKey(ev.ts)).toolUseIds.push(ev.toolUseId);
187
+ }
188
+ // Tokens per day, attributed to the turn's first-line day.
189
+ for (const [id, usage] of usageById) {
190
+ const ts = firstLineById.get(id);
191
+ if (ts === undefined)
192
+ continue;
193
+ const t = get(dayKey(ts)).tokens;
194
+ t.output += usage.output;
195
+ t.input += usage.input;
196
+ t.cacheWrite += usage.cacheWrite;
197
+ t.cacheRead += usage.cacheRead;
198
+ }
199
+ const sortedKeys = [...days.keys()].sort();
200
+ const dayRows = sortedKeys.map((date) => {
201
+ const d = days.get(date);
202
+ const tools = d.toolUseIds.filter((id) => toolResultIds.has(id)).length;
203
+ return {
204
+ date,
205
+ activeMs: { ...d.activeMs },
206
+ idleMs: d.idleMs,
207
+ turns: d.turnIds.size,
208
+ tools,
209
+ tokens: { ...d.tokens },
210
+ costGBP: { opus: opusCostGBP(d.tokens, cfg), sonnet: sonnetCostGBP(d.tokens, cfg) },
211
+ };
212
+ });
213
+ // Totals — cost re-derived from summed tokens (not summed rounded costs).
214
+ const totalTokens = zeroTokens();
215
+ const totalActive = { thinking: 0, messaging: 0, toolUse: 0 };
216
+ let totalIdle = 0;
217
+ let totalTurns = 0;
218
+ let totalTools = 0;
219
+ for (const r of dayRows) {
220
+ totalTokens.output += r.tokens.output;
221
+ totalTokens.input += r.tokens.input;
222
+ totalTokens.cacheWrite += r.tokens.cacheWrite;
223
+ totalTokens.cacheRead += r.tokens.cacheRead;
224
+ totalActive.thinking += r.activeMs.thinking;
225
+ totalActive.messaging += r.activeMs.messaging;
226
+ totalActive.toolUse += r.activeMs.toolUse;
227
+ totalIdle += r.idleMs;
228
+ totalTurns += r.turns;
229
+ totalTools += r.tools;
230
+ }
231
+ const totals = {
232
+ activeMs: totalActive,
233
+ idleMs: totalIdle,
234
+ turns: totalTurns,
235
+ tools: totalTools,
236
+ tokens: totalTokens,
237
+ costGBP: { opus: opusCostGBP(totalTokens, cfg), sonnet: sonnetCostGBP(totalTokens, cfg) },
238
+ };
239
+ const corr = pearson(dayRows.map((r) => r.tokens.output), dayRows.map((r) => r.activeMs.thinking + r.activeMs.messaging + r.activeMs.toolUse));
240
+ // Observability.
241
+ const usedTools = new Set(evs.filter((e) => e.kind === 'toolUse' && e.toolUseId).map((e) => e.toolUseId));
242
+ const matched = [...usedTools].filter((id) => toolResultIds.has(id)).length;
243
+ const spanMs = evs.length > 0 ? evs[evs.length - 1].ts - evs[0].ts : 0;
244
+ const nowIso = opts.nowIso ?? new Date().toISOString();
245
+ if (opts.verbose) {
246
+ for (const r of dayRows) {
247
+ const active = r.activeMs.thinking + r.activeMs.messaging + r.activeMs.toolUse;
248
+ const span = active + r.idleMs;
249
+ const idlePct = span > 0 ? Math.round((r.idleMs / span) * 100) : 0;
250
+ log(`session=${sessionId.slice(0, 8)} day=${r.date} activeMin=${(active / 60000).toFixed(1)} idleMin=${(r.idleMs / 60000).toFixed(1)} idlePct=${idlePct}`);
251
+ const opusUSDcacheRead = (r.tokens.cacheRead * OPUS_4_8.cacheRead) / 1_000_000;
252
+ const opusUSDtotal = r.costGBP.opus * cfg.usdPerGbp;
253
+ const cacheReadPct = opusUSDtotal > 0 ? Math.round((opusUSDcacheRead / opusUSDtotal) * 100) : 0;
254
+ log(`op=cost day=${r.date} opusGBP=${r.costGBP.opus.toFixed(2)} sonnetGBP=${r.costGBP.sonnet.toFixed(2)} cacheReadPct=${cacheReadPct}`);
255
+ }
256
+ }
257
+ log(`op=reconcile residualMs=${residualMs} spanMs=${spanMs}`);
258
+ log(`op=pricing opusPriceDate=${cfg.priceDate} usdPerGbp=${cfg.usdPerGbp} tokenizerFactor=${cfg.tokenizerFactor}`);
259
+ if (pricingIsStale(cfg, nowIso))
260
+ log(`WARN op=pricing stale opusPriceDate=${cfg.priceDate} now=${nowIso.slice(0, 10)}`);
261
+ log(`op=tool-pairs used=${usedTools.size} matched=${matched} orphaned=${usedTools.size - matched}`);
262
+ log(`op=turns count=${firstLineById.size} usageBearing=${usageById.size}`);
263
+ log(`op=thinking blocks=${thinkingBlocks} withText=${thinkingWithText}`);
264
+ return {
265
+ sessionId,
266
+ days: dayRows,
267
+ totals,
268
+ corrOutputVsActive: corr,
269
+ pricing: { opusPriceDate: cfg.priceDate, usdPerGbp: cfg.usdPerGbp, tokenizerFactor: cfg.tokenizerFactor },
270
+ };
271
+ }
272
+ function pearson(xs, ys) {
273
+ const n = xs.length;
274
+ if (n < 2)
275
+ return 0;
276
+ const mx = xs.reduce((a, b) => a + b, 0) / n;
277
+ const my = ys.reduce((a, b) => a + b, 0) / n;
278
+ let sxy = 0;
279
+ let sxx = 0;
280
+ let syy = 0;
281
+ for (let i = 0; i < n; i++) {
282
+ const dx = xs[i] - mx;
283
+ const dy = ys[i] - my;
284
+ sxy += dx * dy;
285
+ sxx += dx * dx;
286
+ syy += dy * dy;
287
+ }
288
+ if (sxx === 0 || syy === 0)
289
+ return 0;
290
+ return sxy / Math.sqrt(sxx * syy);
291
+ }
292
+ //# sourceMappingURL=session-metering.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-metering.js","sourceRoot":"","sources":["../src/session-metering.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ name: project-manager
3
3
  description: "Create, track, and complete tasks and projects, name sessions, and compose and run multi-step workflows. Delegate when the work is about organising what's on, tracking progress, or building a repeatable workflow."
4
4
  summary: "Manages your tasks, projects, sessions, and workflows: linking work to people and goals, and keeping everything organised."
5
5
  model: claude-sonnet-5
6
- tools: mcp__plugin_work_work__work-create, mcp__plugin_work_work__work-update, mcp__plugin_work_work__work-list, mcp__plugin_work_work__work-get, mcp__plugin_work_work__work-relate, mcp__plugin_work_work__work-complete, mcp__plugin_work_work__work-ready, mcp__plugin_work_work__project-create, mcp__plugin_work_work__project-list, mcp__plugin_work_work__project-get, mcp__plugin_work_work__project-update, mcp__plugin_work_work__project-complete, mcp__plugin_work_work__session-list, mcp__plugin_work_work__session-name, mcp__plugin_workflows_workflows__workflow-create, mcp__plugin_workflows_workflows__workflow-list, mcp__plugin_workflows_workflows__workflow-get, mcp__plugin_workflows_workflows__workflow-update, mcp__plugin_workflows_workflows__workflow-delete, mcp__plugin_workflows_workflows__workflow-validate, mcp__plugin_workflows_workflows__workflow-execute, mcp__plugin_workflows_workflows__workflow-runs, mcp__plugin_memory_memory__memory-search, Skill
6
+ tools: mcp__plugin_work_work__work-create, mcp__plugin_work_work__work-update, mcp__plugin_work_work__work-list, mcp__plugin_work_work__work-get, mcp__plugin_work_work__work-relate, mcp__plugin_work_work__work-complete, mcp__plugin_work_work__work-ready, mcp__plugin_work_work__project-create, mcp__plugin_work_work__project-list, mcp__plugin_work_work__project-get, mcp__plugin_work_work__project-update, mcp__plugin_work_work__project-complete, mcp__plugin_work_work__session-list, mcp__plugin_work_work__session-name, mcp__plugin_work_work__session-metering, mcp__plugin_workflows_workflows__workflow-create, mcp__plugin_workflows_workflows__workflow-list, mcp__plugin_workflows_workflows__workflow-get, mcp__plugin_workflows_workflows__workflow-update, mcp__plugin_workflows_workflows__workflow-delete, mcp__plugin_workflows_workflows__workflow-validate, mcp__plugin_workflows_workflows__workflow-execute, mcp__plugin_workflows_workflows__workflow-runs, mcp__plugin_memory_memory__memory-search, Skill
7
7
  ---
8
8
 
9
9
  # Project Manager
@@ -1 +1 @@
1
- import{o as e}from"./chunk-CAM3fms7.js";import{A as t,L as n,M as r,N as i,O as a}from"./useSubAccountSwitcher-DMbRhLPv.js";import{i as o}from"./admin-types-hioowVct.js";import{v as s,y as c}from"./AdminShell-D2-uBSB5.js";import{t as l}from"./Checkbox-1F1tzqca.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(n(),1);function m(e=`admin`){let[t,n]=(0,p.useState)(`loading`),[r,a]=(0,p.useState)(``),[s,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let G=(0,p.useRef)(null),K=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let r=await t.json();D(r.session_key),z(r.sessionId??null),j(r.businessName),N(r.role??null),F(r.userName===void 0?null:r.userName),L(r.avatar??null);let i=o(r.thinkingView);return H.current=i,V(i),n(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(r=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check returned ${i.status} after retries`),n(`set-pin`);return}let a=await i.json();if(!a.pin_configured){n(`set-pin`);return}if(!a.claude_authenticated){n(`connect-claude`);return}if(await e())return;n(`enter-pin`)}catch(e){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check failed:`,e),n(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let q=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();if(t.auth_status===`dead`||t.auth_status===`missing`){n(`connect-claude`);return}}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){i(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),q.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&n(`enter-pin`)}).catch(()=>{})},[t]);async function J(e,t){y(!0);try{let r=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!r.ok){let e=await r.json().catch(()=>({}));if(r.status===401&&e?.code===`remote-auth-required`){i(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await r.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Y=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=s.trim();if(!t){h(`Please enter your name.`);return}if(r.length<4){h(`PIN must be at least 4 characters.`);return}let o=r;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){i(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let r=await e.json();r.pin_configured&&r.claude_authenticated?n(`enter-pin`):r.pin_configured?n(`connect-claude`):h(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await J(o);return}a(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[r,v,s]),X=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await J(r)},[r]),Z=(0,p.useCallback)(async()=>{T(!0);try{if(!await c())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return n(`connect-claude`),!0}finally{T(!1)}},[]),Q=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),n(`enter-pin`)},[]);return(0,p.useEffect)(()=>{q.current=Q},[Q]),{appState:t,setAppState:n,pin:r,setPin:a,operatorName:s,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,pinInputRef:G,setPinFormRef:K,handleSetPin:Y,handleLogin:X,handleDisconnect:Z,handleLogout:Q}}var h=r();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:c,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,a.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,a.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!n||!m.trim(),loading:c,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:c,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:a.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!n,loading:c,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:n,setAuthPolling:r,authLoading:i,setAuthLoading:o,pinError:c,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1);async function _(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function v(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){r(!0),f(!0),o(!1);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),r(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function y(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),r(!1),l(``)}return n||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[n?(0,h.jsx)(`button`,{onClick:y,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:n?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!n&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(s,{variant:`primary`,onClick:v,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),c&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:c})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:a.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,a.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(s,{variant:`primary`,onClick:v,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:_,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),c&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:c})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};
1
+ import{o as e}from"./chunk-CAM3fms7.js";import{A as t,L as n,M as r,N as i,O as a}from"./useSubAccountSwitcher-UqZbmzYy.js";import{i as o}from"./admin-types-hioowVct.js";import{b as s,y as c}from"./AdminShell-cRTvNRbo.js";import{t as l}from"./Checkbox-Dh2pLMFN.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(n(),1);function m(e=`admin`){let[t,n]=(0,p.useState)(`loading`),[r,a]=(0,p.useState)(``),[c,l]=(0,p.useState)(``),[m,h]=(0,p.useState)(``),[g,_]=(0,p.useState)(!1),[v,y]=(0,p.useState)(!1),[b,x]=(0,p.useState)(!1),[S,C]=(0,p.useState)(!1),[w,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(null),[A,j]=(0,p.useState)(void 0),[M,N]=(0,p.useState)(null),[P,F]=(0,p.useState)(void 0),[I,L]=(0,p.useState)(null),[R,z]=(0,p.useState)(null),[B,V]=(0,p.useState)(void 0),H=(0,p.useRef)(void 0),[U,W]=(0,p.useState)(!1);(0,p.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&W(!0)}).catch(()=>{})},[]);let G=(0,p.useRef)(null),K=(0,p.useRef)(null);(0,p.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let r=await t.json();D(r.session_key),z(r.sessionId??null),j(r.businessName),N(r.role??null),F(r.userName===void 0?null:r.userName),L(r.avatar??null);let i=o(r.thinkingView);return H.current=i,V(i),n(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(r=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check returned ${i.status} after retries`),n(`set-pin`);return}let a=await i.json();if(!a.pin_configured){n(`set-pin`);return}if(!a.claude_authenticated){n(`connect-claude`);return}if(await e())return;n(`enter-pin`)}catch(e){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check failed:`,e),n(`set-pin`)}}t()},[]),(0,p.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,p.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(u)===`1`}catch{}if(f({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(u,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${d}`),window.location.replace(d)}},[t,e]);let q=(0,p.useRef)(null);(0,p.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();if(t.auth_status===`dead`||t.auth_status===`missing`){n(`connect-claude`);return}}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){i(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),q.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,p.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&n(`enter-pin`)}).catch(()=>{})},[t]);async function J(e,t){y(!0);try{let r=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!r.ok){let e=await r.json().catch(()=>({}));if(r.status===401&&e?.code===`remote-auth-required`){i(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await r.json();D(s.session_key),z(s.sessionId??null),j(s.businessName),N(s.role??null),F(s.userName===void 0?null:s.userName),L(s.avatar??null);let c=o(s.thinkingView);H.current=c,V(c);try{sessionStorage.setItem(`maxy-admin-session-key`,s.session_key)}catch{}a(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Y=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=c.trim();if(!t){h(`Please enter your name.`);return}if(r.length<4){h(`PIN must be at least 4 characters.`);return}let o=r;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===401&&t?.code===`remote-auth-required`){i(`set-pin`,`/api/onboarding/set-pin`);return}if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let r=await e.json();r.pin_configured&&r.claude_authenticated?n(`enter-pin`):r.pin_configured?n(`connect-claude`):h(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await J(o);return}a(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[r,v,c]),X=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await J(r)},[r]),Z=(0,p.useCallback)(async()=>{T(!0);try{if(!await s())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return n(`connect-claude`),!0}finally{T(!1)}},[]),Q=(0,p.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}a(``),h(``),n(`enter-pin`)},[]);return(0,p.useEffect)(()=>{q.current=Q},[Q]),{appState:t,setAppState:n,pin:r,setPin:a,operatorName:c,setOperatorName:l,pinError:m,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:R,setSessionId:z,expandAll:B,setExpandAll:V,expandAllDefaultRef:H,remoteAuthEnabled:U,pinInputRef:G,setPinFormRef:K,handleSetPin:Y,handleLogin:X,handleDisconnect:Z,handleLogout:Q}}var h=r();function g({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,p.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,h.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,h.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function _(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:_}=e;return(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,a.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,a.productName,` who you are, then choose a PIN.`]}),(0,h.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>_(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,h.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!n||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})})}function v(e){let{pin:n,setPin:r,showPin:i,setShowPin:o,pinLoading:s,pinError:u,pinInputRef:d,onSubmit:f,remoteAuthEnabled:p,onSignOutRemote:m}=e;return(0,h.jsxs)(`div`,{className:`connect-page`,children:[p&&m&&(0,h.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:m,children:`Sign out`}),(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:a.productName}),(0,h.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,h.jsxs)(`div`,{className:`pin-input-row`,children:[(0,h.jsx)(g,{inputRef:d,value:n,onChange:r,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(c,{variant:`send`,type:`submit`,disabled:!n,loading:s,children:(0,h.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,h.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,h.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,h.jsx)(`div`,{className:`pin-options`,children:(0,h.jsx)(l,{checked:i,onChange:()=>o(e=>!e),label:`Show PIN`})})]}),u&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:u})]})]})}function y(e){let{authPolling:n,setAuthPolling:r,authLoading:i,setAuthLoading:o,pinError:s,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1);async function _(){g(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&l(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),l(`Could not launch browser.`)}g(!1)}async function v(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){r(!0),f(!0),o(!1);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}l(`Timed out waiting for sign-in. Try again.`),r(!1)}else e.error&&l(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),l(`Could not start auth flow.`)}o(!1)}async function y(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),r(!1),l(``)}return n||d?(0,h.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,h.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[n?(0,h.jsx)(`button`,{onClick:y,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,h.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,h.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,h.jsx)(`p`,{className:`chat-intro`,children:n?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!n&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(c,{variant:`primary`,onClick:v,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})})]}),(0,h.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,h.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,h.jsx)(`div`,{className:`connect-page`,children:(0,h.jsxs)(`div`,{className:`connect-content`,children:[(0,h.jsxs)(`div`,{className:`connect-logos`,children:[(0,h.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,h.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,h.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,h.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,h.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,h.jsx)(`img`,{src:t,alt:a.productName,className:`connect-logo connect-logo--maxy`}),!a.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:a.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,a.productName]}),(0,h.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,h.jsx)(c,{variant:`primary`,onClick:v,disabled:i,children:i?(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,h.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,h.jsx)(`button`,{onClick:_,disabled:m,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:m?`Launching…`:`Open browser first`}),s&&(0,h.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function b({auth:e}){return e.appState===`loading`?(0,h.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,h.jsx)(_,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,h.jsx)(y,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,h.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):null}export{m as n,b as t};