@rubytech/create-realagent-code 0.1.461 → 0.1.462
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.
- package/package.json +1 -1
- package/payload/platform/lib/graph-mcp/dist/index.d.ts +2 -1
- package/payload/platform/lib/graph-mcp/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-mcp/dist/index.js +14 -22
- package/payload/platform/lib/graph-mcp/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-mcp/src/index.ts +15 -22
- package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts +8 -7
- package/payload/platform/lib/mcp-spawn-tee/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/mcp-spawn-tee/dist/index.js +19 -19
- package/payload/platform/lib/mcp-spawn-tee/dist/index.js.map +1 -1
- package/payload/platform/lib/mcp-spawn-tee/src/__tests__/spawn-tee.test.ts +34 -5
- package/payload/platform/lib/mcp-spawn-tee/src/index.ts +22 -19
- package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts +35 -17
- package/payload/platform/lib/mcp-stderr-tee/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js +41 -48
- package/payload/platform/lib/mcp-stderr-tee/dist/index.js.map +1 -1
- package/payload/platform/lib/mcp-stderr-tee/src/index.ts +42 -51
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js +27 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/audit.test.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js +49 -0
- package/payload/platform/lib/storage-broker/dist/__tests__/cf-exec.test.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/audit.d.ts +11 -0
- package/payload/platform/lib/storage-broker/dist/audit.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/audit.js +16 -0
- package/payload/platform/lib/storage-broker/dist/audit.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts +18 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/cf-exec.js +77 -0
- package/payload/platform/lib/storage-broker/dist/cf-exec.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/house-scoped-token.js +3 -0
- package/payload/platform/lib/storage-broker/dist/house-scoped-token.js.map +1 -1
- package/payload/platform/lib/storage-broker/dist/registry.d.ts +1 -1
- package/payload/platform/lib/storage-broker/dist/registry.d.ts.map +1 -1
- package/payload/platform/lib/storage-broker/dist/registry.js.map +1 -1
- package/payload/platform/lib/storage-broker/src/__tests__/audit.test.ts +32 -1
- package/payload/platform/lib/storage-broker/src/__tests__/cf-exec.test.ts +61 -0
- package/payload/platform/lib/storage-broker/src/audit.ts +45 -0
- package/payload/platform/lib/storage-broker/src/cf-exec.ts +91 -0
- package/payload/platform/lib/storage-broker/src/house-scoped-token.ts +3 -0
- package/payload/platform/lib/storage-broker/src/registry.ts +5 -1
- package/payload/platform/plugins/admin/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +22 -11
- package/payload/platform/plugins/aeo/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/browser/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/cloudflare/PLUGIN.md +1 -1
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js +5 -5
- package/payload/platform/plugins/cloudflare/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/cloudflare/references/hosting-sites.md +2 -0
- package/payload/platform/plugins/cloudflare/skills/calendar-site/SKILL.md +1 -1
- package/payload/platform/plugins/cloudflare/skills/site-deploy/SKILL.md +2 -0
- package/payload/platform/plugins/connector/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/contacts/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/docs/references/admin-session.md +3 -3
- package/payload/platform/plugins/docs/references/cloudflare.md +2 -0
- package/payload/platform/plugins/docs/references/outlook-guide.md +11 -4
- package/payload/platform/plugins/docs/references/plugins-guide.md +8 -6
- package/payload/platform/plugins/email/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/filesystem/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/graph-viewer/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js +2 -2
- package/payload/platform/plugins/memory/mcp/dist/lib/log-ingest.js.map +1 -1
- package/payload/platform/plugins/outlook/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/outlook/PLUGIN.md +2 -2
- package/payload/platform/plugins/outlook/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.d.ts +2 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.d.ts.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.js +238 -0
- package/payload/platform/plugins/outlook/mcp/dist/__tests__/draft-threaded.test.js.map +1 -0
- package/payload/platform/plugins/outlook/mcp/dist/index.js +9 -5
- package/payload/platform/plugins/outlook/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts +58 -9
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.d.ts.map +1 -1
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js +113 -19
- package/payload/platform/plugins/outlook/mcp/dist/tools/draft.js.map +1 -1
- package/payload/platform/plugins/outlook/skills/outlook/SKILL.md +5 -2
- package/payload/platform/plugins/quickbooks/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/replicate/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/scheduling/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/storage-broker/PLUGIN.md +9 -1
- package/payload/platform/plugins/storage-broker/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.d.ts.map +1 -1
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js +16 -5
- package/payload/platform/plugins/storage-broker/mcp/dist/confine-path.js.map +1 -1
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js +49 -0
- package/payload/platform/plugins/storage-broker/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/url-get/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/voice-mirror/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/web-designer/PLUGIN.md +1 -1
- package/payload/platform/plugins/web-designer/commands/website.md +6 -0
- package/payload/platform/plugins/web-designer/skills/web-design/references/deploy.md +12 -0
- package/payload/platform/plugins/whatsapp/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/work/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/plugins/workflows/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/platform/scripts/__tests__/logs-rotate.test.sh +24 -20
- package/payload/platform/scripts/logs-read.sh +31 -0
- package/payload/platform/scripts/logs-rotate.sh +21 -18
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +2 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +37 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +5 -3
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/premium-plugins/real-agent/plugins/buyers/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/premium-plugins/real-agent/plugins/estate-sales/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/premium-plugins/real-agent/plugins/loop/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/premium-plugins/real-agent/plugins/property-data/lib/mcp-spawn-tee/index.js +19 -19
- package/payload/server/{chunk-JXWFVE5X.js → chunk-BBSPFN45.js} +65 -0
- package/payload/server/public/assets/{AdminLoginScreens-BFbpkEUS.js → AdminLoginScreens-Bed8SDxY.js} +1 -1
- package/payload/server/public/assets/{AdminShell-CdOGObaZ.js → AdminShell-BLh9O6dn.js} +1 -1
- package/payload/server/public/assets/{Checkbox-RFD_F0c0.js → Checkbox-BC_KSbpS.js} +1 -1
- package/payload/server/public/assets/{admin-CYGdL-1O.js → admin-DfWgJVI3.js} +1 -1
- package/payload/server/public/assets/{browser-DVfa_plj.js → browser-C0vkv-hH.js} +1 -1
- package/payload/server/public/assets/{calendar-JC_Dxa4n.js → calendar-_pfHw0Hp.js} +1 -1
- package/payload/server/public/assets/chat-CufidiBQ.js +1 -0
- package/payload/server/public/assets/chevron-left-BnpVBu51.js +1 -0
- package/payload/server/public/assets/data-CR-fbPWr.js +1 -0
- package/payload/server/public/assets/{graph-hBUrRSkr.js → graph-BZiudUGr.js} +1 -1
- package/payload/server/public/assets/{graph-labels-CHh6zs8t.js → graph-labels-BzmmJwCR.js} +1 -1
- package/payload/server/public/assets/{maximize-2-DjxE4rm9.js → maximize-2-Bhdsv0U-.js} +1 -1
- package/payload/server/public/assets/{operator-BqU9SQuu.js → operator-Cj0B_usT.js} +1 -1
- package/payload/server/public/assets/page-84Fdwiu_.js +32 -0
- package/payload/server/public/assets/{page-DiQhU6lD.js → page-8AB3jUa_.js} +1 -1
- package/payload/server/public/assets/{public-Cu_eALgY.js → public-BkNW9e9T.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-F9DsSTSJ.js → rotate-ccw-D_5cETGt.js} +1 -1
- package/payload/server/public/assets/{tasks-CE-D0f50.js → tasks-EyKLXINi.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-D2rsWhov.js → time-entry-format-DAwmmR3i.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-QxOmoobV.js → useCopyFeedback-rOWd_lzl.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-RIzNqFjV.js → useSelectionMode-DDmLmPph.js} +1 -1
- package/payload/server/public/assets/{useSubAccountSwitcher-BW_fK1Nt.css → useSubAccountSwitcher-pu0jjLCz.css} +1 -1
- package/payload/server/public/assets/{useVoiceRecorder-WrWurSYI.js → useVoiceRecorder-azG8zSUI.js} +1 -1
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +12 -12
- package/payload/server/public/data.html +10 -10
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +13 -13
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/public.html +12 -12
- package/payload/server/public/tasks.html +5 -5
- package/payload/server/server.js +526 -174
- package/payload/server/{src-4F37OHLK.js → src-YLGAZY36.js} +5 -1
- package/payload/server/public/assets/chat-Yf8Nkop8.js +0 -1
- package/payload/server/public/assets/chevron-left-CAiAUBxO.js +0 -1
- package/payload/server/public/assets/data-hqdYXaEn.js +0 -1
- package/payload/server/public/assets/page-B4c4_4HP.js +0 -32
- /package/payload/server/public/assets/{useSubAccountSwitcher-wo_qGW-I.js → useSubAccountSwitcher-CU-lOxTd.js} +0 -0
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Claude Code CLI → shim (this file) = node running <real-entry> in-process
|
|
15
15
|
* stdin/stdout : untouched (JSON-RPC channel)
|
|
16
|
-
* stderr : process.stderr.write teed →
|
|
16
|
+
* stderr : process.stderr.write teed → raw sink + passthrough
|
|
17
17
|
*
|
|
18
|
-
* Destinations
|
|
19
|
-
* - `${LOG_DIR}/mcp-<name
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Destinations:
|
|
19
|
+
* - `${LOG_DIR}/mcp-<name>-<SESSION_ID>.log` — raw stderr + lifecycle lines.
|
|
20
|
+
* The sole raw sink. Task 1721 retired the per-date twin: its date was
|
|
21
|
+
* pinned at spawn, no reader ever parsed it, and mcp-stderr-tee wrote the
|
|
22
|
+
* same file, so every line landed twice.
|
|
23
|
+
* - `${LOG_DIR}/mcp-<name>-nosession.log` — the same, for a spawn with
|
|
24
|
+
* no SESSION_ID (enumeration). One fixed file per server.
|
|
24
25
|
* - `server.log` via the loopback log-ingest route — best-effort mirror of
|
|
25
26
|
* the [mcp-helper] lifecycle lines.
|
|
26
27
|
*
|
|
@@ -49,13 +50,13 @@ const PLATFORM_PORT = process.env.PLATFORM_PORT;
|
|
|
49
50
|
const ENTRY = process.argv[2];
|
|
50
51
|
const SESSION_ID8 = SESSION_ID ? SESSION_ID.slice(0, 8) : "—";
|
|
51
52
|
const spawnStamp = Date.now();
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}
|
|
53
|
+
// The one raw sink (Task 1721). A sessionless spawn (rc-daemon stamps
|
|
54
|
+
// SESSION_ID='' — rc-daemon.ts:513 — while still stamping LOG_DIR) shares one
|
|
55
|
+
// fixed file per server rather than a date-named one: the date was never read
|
|
56
|
+
// by any reader and named a process lifetime, not a day. Interleaved spawns in
|
|
57
|
+
// the nosession file are separated by the [mcp-helper] op=spawn pid= lines.
|
|
58
|
+
const rawSinkPath = LOG_DIR
|
|
59
|
+
? (0, node_path_1.resolve)(LOG_DIR, SESSION_ID ? `mcp-${SERVER_NAME}-${SESSION_ID}.log` : `mcp-${SERVER_NAME}-nosession.log`)
|
|
59
60
|
: undefined;
|
|
60
61
|
// Rolling tail of entry stderr for op=exit. Capped so a chatty server cannot
|
|
61
62
|
// grow the buffer without bound.
|
|
@@ -66,7 +67,7 @@ let exitEmitted = false;
|
|
|
66
67
|
let exitSignal;
|
|
67
68
|
// The real stderr writer, captured before the tee replaces it. Lifecycle lines
|
|
68
69
|
// and stderr passthrough both go through this so they are never re-teed into
|
|
69
|
-
// the
|
|
70
|
+
// the raw sink nor recursed back into the patched writer.
|
|
70
71
|
const rawStderrWrite = process.stderr.write.bind(process.stderr);
|
|
71
72
|
// LOG_DIR is created once, lazily, on the first successful append — not per
|
|
72
73
|
// chunk. teeWrite runs on the server's own stderr hot path now, so a per-call
|
|
@@ -115,7 +116,7 @@ function postToServerLog(suffix, level) {
|
|
|
115
116
|
// log-ingest route rejects newlines).
|
|
116
117
|
function emitLifecycle(suffix, level) {
|
|
117
118
|
const line = `[mcp-helper] ${suffix}\n`;
|
|
118
|
-
appendSafe(
|
|
119
|
+
appendSafe(rawSinkPath, line);
|
|
119
120
|
try {
|
|
120
121
|
rawStderrWrite(line);
|
|
121
122
|
}
|
|
@@ -127,12 +128,11 @@ if (!ENTRY) {
|
|
|
127
128
|
process.exit(2);
|
|
128
129
|
}
|
|
129
130
|
// Replace process.stderr.write with a tee: mirror every server stderr byte to
|
|
130
|
-
// the
|
|
131
|
+
// the raw sink, keep a rolling tail for op=exit, emit
|
|
131
132
|
// op=boot on the first bytes, then pass the write through to the real stderr.
|
|
132
133
|
const teeWrite = ((...args) => {
|
|
133
134
|
const chunk = args[0];
|
|
134
|
-
appendSafe(
|
|
135
|
-
appendSafe(perSessionPath, chunk); // per-session raw (Task 706)
|
|
135
|
+
appendSafe(rawSinkPath, chunk); // raw sink (Task 1721)
|
|
136
136
|
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
137
137
|
stderrTail = (stderrTail + text).slice(-TAIL_CAP);
|
|
138
138
|
if (!bootEmitted) {
|
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Claude Code CLI → shim (this file) = node running <real-entry> in-process
|
|
15
15
|
* stdin/stdout : untouched (JSON-RPC channel)
|
|
16
|
-
* stderr : process.stderr.write teed →
|
|
16
|
+
* stderr : process.stderr.write teed → raw sink + passthrough
|
|
17
17
|
*
|
|
18
|
-
* Destinations
|
|
19
|
-
* - `${LOG_DIR}/mcp-<name
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Destinations:
|
|
19
|
+
* - `${LOG_DIR}/mcp-<name>-<SESSION_ID>.log` — raw stderr + lifecycle lines.
|
|
20
|
+
* The sole raw sink. Task 1721 retired the per-date twin: its date was
|
|
21
|
+
* pinned at spawn, no reader ever parsed it, and mcp-stderr-tee wrote the
|
|
22
|
+
* same file, so every line landed twice.
|
|
23
|
+
* - `${LOG_DIR}/mcp-<name>-nosession.log` — the same, for a spawn with
|
|
24
|
+
* no SESSION_ID (enumeration). One fixed file per server.
|
|
24
25
|
* - `server.log` via the loopback log-ingest route — best-effort mirror of
|
|
25
26
|
* the [mcp-helper] lifecycle lines.
|
|
26
27
|
*
|
|
@@ -49,13 +50,13 @@ const PLATFORM_PORT = process.env.PLATFORM_PORT;
|
|
|
49
50
|
const ENTRY = process.argv[2];
|
|
50
51
|
const SESSION_ID8 = SESSION_ID ? SESSION_ID.slice(0, 8) : "—";
|
|
51
52
|
const spawnStamp = Date.now();
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}
|
|
53
|
+
// The one raw sink (Task 1721). A sessionless spawn (rc-daemon stamps
|
|
54
|
+
// SESSION_ID='' — rc-daemon.ts:513 — while still stamping LOG_DIR) shares one
|
|
55
|
+
// fixed file per server rather than a date-named one: the date was never read
|
|
56
|
+
// by any reader and named a process lifetime, not a day. Interleaved spawns in
|
|
57
|
+
// the nosession file are separated by the [mcp-helper] op=spawn pid= lines.
|
|
58
|
+
const rawSinkPath = LOG_DIR
|
|
59
|
+
? (0, node_path_1.resolve)(LOG_DIR, SESSION_ID ? `mcp-${SERVER_NAME}-${SESSION_ID}.log` : `mcp-${SERVER_NAME}-nosession.log`)
|
|
59
60
|
: undefined;
|
|
60
61
|
// Rolling tail of entry stderr for op=exit. Capped so a chatty server cannot
|
|
61
62
|
// grow the buffer without bound.
|
|
@@ -66,7 +67,7 @@ let exitEmitted = false;
|
|
|
66
67
|
let exitSignal;
|
|
67
68
|
// The real stderr writer, captured before the tee replaces it. Lifecycle lines
|
|
68
69
|
// and stderr passthrough both go through this so they are never re-teed into
|
|
69
|
-
// the
|
|
70
|
+
// the raw sink nor recursed back into the patched writer.
|
|
70
71
|
const rawStderrWrite = process.stderr.write.bind(process.stderr);
|
|
71
72
|
// LOG_DIR is created once, lazily, on the first successful append — not per
|
|
72
73
|
// chunk. teeWrite runs on the server's own stderr hot path now, so a per-call
|
|
@@ -115,7 +116,7 @@ function postToServerLog(suffix, level) {
|
|
|
115
116
|
// log-ingest route rejects newlines).
|
|
116
117
|
function emitLifecycle(suffix, level) {
|
|
117
118
|
const line = `[mcp-helper] ${suffix}\n`;
|
|
118
|
-
appendSafe(
|
|
119
|
+
appendSafe(rawSinkPath, line);
|
|
119
120
|
try {
|
|
120
121
|
rawStderrWrite(line);
|
|
121
122
|
}
|
|
@@ -127,12 +128,11 @@ if (!ENTRY) {
|
|
|
127
128
|
process.exit(2);
|
|
128
129
|
}
|
|
129
130
|
// Replace process.stderr.write with a tee: mirror every server stderr byte to
|
|
130
|
-
// the
|
|
131
|
+
// the raw sink, keep a rolling tail for op=exit, emit
|
|
131
132
|
// op=boot on the first bytes, then pass the write through to the real stderr.
|
|
132
133
|
const teeWrite = ((...args) => {
|
|
133
134
|
const chunk = args[0];
|
|
134
|
-
appendSafe(
|
|
135
|
-
appendSafe(perSessionPath, chunk); // per-session raw (Task 706)
|
|
135
|
+
appendSafe(rawSinkPath, chunk); // raw sink (Task 1721)
|
|
136
136
|
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
137
137
|
stderrTail = (stderrTail + text).slice(-TAIL_CAP);
|
|
138
138
|
if (!bootEmitted) {
|
|
@@ -13,14 +13,15 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Claude Code CLI → shim (this file) = node running <real-entry> in-process
|
|
15
15
|
* stdin/stdout : untouched (JSON-RPC channel)
|
|
16
|
-
* stderr : process.stderr.write teed →
|
|
16
|
+
* stderr : process.stderr.write teed → raw sink + passthrough
|
|
17
17
|
*
|
|
18
|
-
* Destinations
|
|
19
|
-
* - `${LOG_DIR}/mcp-<name
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Destinations:
|
|
19
|
+
* - `${LOG_DIR}/mcp-<name>-<SESSION_ID>.log` — raw stderr + lifecycle lines.
|
|
20
|
+
* The sole raw sink. Task 1721 retired the per-date twin: its date was
|
|
21
|
+
* pinned at spawn, no reader ever parsed it, and mcp-stderr-tee wrote the
|
|
22
|
+
* same file, so every line landed twice.
|
|
23
|
+
* - `${LOG_DIR}/mcp-<name>-nosession.log` — the same, for a spawn with
|
|
24
|
+
* no SESSION_ID (enumeration). One fixed file per server.
|
|
24
25
|
* - `server.log` via the loopback log-ingest route — best-effort mirror of
|
|
25
26
|
* the [mcp-helper] lifecycle lines.
|
|
26
27
|
*
|
|
@@ -49,13 +50,13 @@ const PLATFORM_PORT = process.env.PLATFORM_PORT;
|
|
|
49
50
|
const ENTRY = process.argv[2];
|
|
50
51
|
const SESSION_ID8 = SESSION_ID ? SESSION_ID.slice(0, 8) : "—";
|
|
51
52
|
const spawnStamp = Date.now();
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
? (0, node_path_1.resolve)(LOG_DIR, `mcp-${SERVER_NAME}
|
|
53
|
+
// The one raw sink (Task 1721). A sessionless spawn (rc-daemon stamps
|
|
54
|
+
// SESSION_ID='' — rc-daemon.ts:513 — while still stamping LOG_DIR) shares one
|
|
55
|
+
// fixed file per server rather than a date-named one: the date was never read
|
|
56
|
+
// by any reader and named a process lifetime, not a day. Interleaved spawns in
|
|
57
|
+
// the nosession file are separated by the [mcp-helper] op=spawn pid= lines.
|
|
58
|
+
const rawSinkPath = LOG_DIR
|
|
59
|
+
? (0, node_path_1.resolve)(LOG_DIR, SESSION_ID ? `mcp-${SERVER_NAME}-${SESSION_ID}.log` : `mcp-${SERVER_NAME}-nosession.log`)
|
|
59
60
|
: undefined;
|
|
60
61
|
// Rolling tail of entry stderr for op=exit. Capped so a chatty server cannot
|
|
61
62
|
// grow the buffer without bound.
|
|
@@ -66,7 +67,7 @@ let exitEmitted = false;
|
|
|
66
67
|
let exitSignal;
|
|
67
68
|
// The real stderr writer, captured before the tee replaces it. Lifecycle lines
|
|
68
69
|
// and stderr passthrough both go through this so they are never re-teed into
|
|
69
|
-
// the
|
|
70
|
+
// the raw sink nor recursed back into the patched writer.
|
|
70
71
|
const rawStderrWrite = process.stderr.write.bind(process.stderr);
|
|
71
72
|
// LOG_DIR is created once, lazily, on the first successful append — not per
|
|
72
73
|
// chunk. teeWrite runs on the server's own stderr hot path now, so a per-call
|
|
@@ -115,7 +116,7 @@ function postToServerLog(suffix, level) {
|
|
|
115
116
|
// log-ingest route rejects newlines).
|
|
116
117
|
function emitLifecycle(suffix, level) {
|
|
117
118
|
const line = `[mcp-helper] ${suffix}\n`;
|
|
118
|
-
appendSafe(
|
|
119
|
+
appendSafe(rawSinkPath, line);
|
|
119
120
|
try {
|
|
120
121
|
rawStderrWrite(line);
|
|
121
122
|
}
|
|
@@ -127,12 +128,11 @@ if (!ENTRY) {
|
|
|
127
128
|
process.exit(2);
|
|
128
129
|
}
|
|
129
130
|
// Replace process.stderr.write with a tee: mirror every server stderr byte to
|
|
130
|
-
// the
|
|
131
|
+
// the raw sink, keep a rolling tail for op=exit, emit
|
|
131
132
|
// op=boot on the first bytes, then pass the write through to the real stderr.
|
|
132
133
|
const teeWrite = ((...args) => {
|
|
133
134
|
const chunk = args[0];
|
|
134
|
-
appendSafe(
|
|
135
|
-
appendSafe(perSessionPath, chunk); // per-session raw (Task 706)
|
|
135
|
+
appendSafe(rawSinkPath, chunk); // raw sink (Task 1721)
|
|
136
136
|
const text = typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
137
137
|
stderrTail = (stderrTail + text).slice(-TAIL_CAP);
|
|
138
138
|
if (!bootEmitted) {
|
|
@@ -136,6 +136,8 @@ function keyForScope(scope) {
|
|
|
136
136
|
return "CF_STORAGE_TOKEN";
|
|
137
137
|
case "calendar-d1":
|
|
138
138
|
return "CF_CALENDAR_D1_TOKEN";
|
|
139
|
+
case "pages":
|
|
140
|
+
return "CF_PAGES_D1_TOKEN";
|
|
139
141
|
default:
|
|
140
142
|
return "";
|
|
141
143
|
}
|
|
@@ -287,6 +289,49 @@ function makeCfExec(cred, run = defaultRun2, fetchFn = defaultFetch) {
|
|
|
287
289
|
async r2Create(name) {
|
|
288
290
|
await run("npx", ["wrangler", "r2", "bucket", "create", name], env);
|
|
289
291
|
},
|
|
292
|
+
// --- Pages (Task 1728) -------------------------------------------------
|
|
293
|
+
//
|
|
294
|
+
// Publishing is house-run: a client account's secrets carry no master after
|
|
295
|
+
// the 1631 remediation, and cf-token.sh refuses to mint the pages scope for
|
|
296
|
+
// a non-house caller. These two run under the house credential only.
|
|
297
|
+
async pagesProjectList() {
|
|
298
|
+
const base = `https://api.cloudflare.com/client/v4/accounts/${cred.accountId}/pages/projects`;
|
|
299
|
+
const projects = [];
|
|
300
|
+
const seen = /* @__PURE__ */ new Set();
|
|
301
|
+
let cursor;
|
|
302
|
+
for (; ; ) {
|
|
303
|
+
const url = cursor === void 0 ? base : `${base}?cursor=${encodeURIComponent(cursor)}`;
|
|
304
|
+
const { parsed } = await cfApiJson(
|
|
305
|
+
fetchFn,
|
|
306
|
+
url,
|
|
307
|
+
{ method: "GET", headers: { Authorization: `Bearer ${cred.apiToken}` } },
|
|
308
|
+
"pages project list"
|
|
309
|
+
);
|
|
310
|
+
const page = parsed;
|
|
311
|
+
for (const p of page.result ?? []) projects.push({ name: p.name });
|
|
312
|
+
const next = page.result_info?.cursor;
|
|
313
|
+
if (!next) return projects;
|
|
314
|
+
if (seen.has(next)) {
|
|
315
|
+
throw new Error(
|
|
316
|
+
`storage-broker: pages project list returned a repeated pagination cursor: ${next}`
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
seen.add(next);
|
|
320
|
+
cursor = next;
|
|
321
|
+
}
|
|
322
|
+
},
|
|
323
|
+
async pagesDeploy(dir, project, branch) {
|
|
324
|
+
const args = ["wrangler", "pages", "deploy", dir, "--project-name", project];
|
|
325
|
+
if (branch !== void 0) args.push("--branch", branch);
|
|
326
|
+
const { stdout } = await run("npx", args, env);
|
|
327
|
+
const plain = stdout.replace(/\[[0-9;]*m/g, "");
|
|
328
|
+
const urls = plain.match(/https:\/\/[A-Za-z0-9._-]+\.pages\.dev/g);
|
|
329
|
+
const url = urls?.[urls.length - 1];
|
|
330
|
+
if (!url) {
|
|
331
|
+
throw new Error(`storage-broker: pages deploy returned no deployment url: ${stdout}`);
|
|
332
|
+
}
|
|
333
|
+
return { url };
|
|
334
|
+
},
|
|
290
335
|
// --- R2 objects (Task 1691) -------------------------------------------
|
|
291
336
|
//
|
|
292
337
|
// The v4 REST API exposes the object surface under
|
|
@@ -368,6 +413,13 @@ async function makeHouseCfExec(platformRoot, run = defaultRun2, fetchFn = defaul
|
|
|
368
413
|
const scoped = await resolveHouseScopedToken("storage", houseEnvPath, cfTokenSh, run);
|
|
369
414
|
return makeCfExec({ apiToken: scoped, accountId: cred.accountId }, run, fetchFn);
|
|
370
415
|
}
|
|
416
|
+
async function makeHousePagesExec(platformRoot, run = defaultRun2, fetchFn = defaultFetch) {
|
|
417
|
+
const cred = readHouseCredential(platformRoot);
|
|
418
|
+
const houseEnvPath = join2(platformRoot, "config", "cloudflare-house.env");
|
|
419
|
+
const cfTokenSh = join2(platformRoot, "plugins/cloudflare/bin/cf-token.sh");
|
|
420
|
+
const scoped = await resolveHouseScopedToken("pages", houseEnvPath, cfTokenSh, run);
|
|
421
|
+
return makeCfExec({ apiToken: scoped, accountId: cred.accountId }, run, fetchFn);
|
|
422
|
+
}
|
|
371
423
|
|
|
372
424
|
// ../lib/storage-broker/src/audit.ts
|
|
373
425
|
var ACCOUNT_WIDE_KEYS = ["CLOUDFLARE_API_TOKEN", "CF_PAGES_D1_TOKEN", "CF_PAGES_TOKEN"];
|
|
@@ -398,6 +450,17 @@ async function reconcileStorage(deps) {
|
|
|
398
450
|
}
|
|
399
451
|
return { strays };
|
|
400
452
|
}
|
|
453
|
+
async function reconcilePages(deps) {
|
|
454
|
+
const [cf, registered] = await Promise.all([deps.cfProjects(), deps.registeredProjects()]);
|
|
455
|
+
const cfSet = new Set(cf);
|
|
456
|
+
const regSet = new Set(registered);
|
|
457
|
+
return {
|
|
458
|
+
projects: cfSet.size,
|
|
459
|
+
registered: regSet.size,
|
|
460
|
+
orphans: [...cfSet].filter((name) => !regSet.has(name)),
|
|
461
|
+
phantoms: [...regSet].filter((name) => !cfSet.has(name))
|
|
462
|
+
};
|
|
463
|
+
}
|
|
401
464
|
|
|
402
465
|
// ../lib/storage-broker/src/remediate.ts
|
|
403
466
|
var STRIP_KEYS = [
|
|
@@ -437,7 +500,9 @@ export {
|
|
|
437
500
|
resolveHouseScopedToken,
|
|
438
501
|
makeCfExec,
|
|
439
502
|
makeHouseCfExec,
|
|
503
|
+
makeHousePagesExec,
|
|
440
504
|
reconcileStorage,
|
|
505
|
+
reconcilePages,
|
|
441
506
|
validateMapping,
|
|
442
507
|
stripAccountWideTokens
|
|
443
508
|
};
|
package/payload/server/public/assets/{AdminLoginScreens-BFbpkEUS.js → AdminLoginScreens-Bed8SDxY.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./chunk-Ck5AOu5v.js";import{E as t,S as n,_ as r,x as i,y as a}from"./useSubAccountSwitcher-wo_qGW-I.js";import{E as o}from"./useVoiceRecorder-WrWurSYI.js";import{v as s,y as c}from"./AdminShell-CdOGObaZ.js";import{t as l}from"./Checkbox-RFD_F0c0.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(t(),1);function m(e=`admin`){let[t,r]=(0,p.useState)(`loading`),[i,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),[G,K]=(0,p.useState)(!0);(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 q=(0,p.useRef)(null),J=(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 n=await t.json();D(n.session_key),z(n.sessionId??null),j(n.businessName),N(n.role??null),F(n.userName===void 0?null:n.userName),L(n.avatar??null);let i=o(n.thinkingView);return H.current=i,V(i),r(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(n=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check returned ${i.status} after retries`),r(`set-pin`);return}let a=await i.json();if(!a.pin_configured){r(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){r(`connect-claude`);return}}if(await e())return;r(`enter-pin`)}catch(e){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check failed:`,e),r(`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 Y=(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();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}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`){n(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.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&&(K(!0),r(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let i=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!i.ok){let e=await i.json().catch(()=>({}));if(i.status===401&&e?.code===`remote-auth-required`){n(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await i.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(``),r(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=s.trim();if(!t){h(`Please enter your name.`);return}if(i.length<4){h(`PIN must be at least 4 characters.`);return}let o=i;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`){n(`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 n=await e.json();n.pin_configured&&n.claude_authenticated?r(`enter-pin`):n.pin_configured?r(`connect-claude`):h(t.error||`Failed to set PIN.`)}else r(`enter-pin`)}catch{r(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let i=await fetch(`/api/health`);if((i.ok?await i.json():null)?.claude_authenticated){await X(o);return}a(``),r(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[i,v,s]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(i)},[i]),ee=(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;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return r(`connect-claude`),!0}finally{T(!1)}},[]),$=(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(``),r(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:r,pin:i,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,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=i();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:t,setPin:n,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:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,r.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,r.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:t,onChange:n,onComplete:()=>{},showPin:i}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!t||!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:t,setPin:n,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:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:r.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:t,onChange:n,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!t,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:t,setAuthPolling:n,authLoading:i,setAuthLoading:o,pinError:c,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){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 T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){n(!0),f(!0),o(!1),v(e.transport||``);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.`),n(!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 E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),l(``)}return t||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:[t?(0,h.jsx)(`button`,{onClick:E,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:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(s,{variant:`primary`,onClick:T,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`})}),t&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(s,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(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:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:r.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,r.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:T,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:w,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-Ck5AOu5v.js";import{E as t,S as n,_ as r,x as i,y as a}from"./useSubAccountSwitcher-CU-lOxTd.js";import{E as o}from"./useVoiceRecorder-azG8zSUI.js";import{v as s,y as c}from"./AdminShell-BLh9O6dn.js";import{t as l}from"./Checkbox-BC_KSbpS.js";var u=`admin-landing-redirected`,d=`/graph`;function f(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var p=e(t(),1);function m(e=`admin`){let[t,r]=(0,p.useState)(`loading`),[i,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),[G,K]=(0,p.useState)(!0);(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 q=(0,p.useRef)(null),J=(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 n=await t.json();D(n.session_key),z(n.sessionId??null),j(n.businessName),N(n.role??null),F(n.userName===void 0?null:n.userName),L(n.avatar??null);let i=o(n.thinkingView);return H.current=i,V(i),r(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(n=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check returned ${i.status} after retries`),r(`set-pin`);return}let a=await i.json();if(!a.pin_configured){r(`set-pin`);return}K(!!a.claude_authenticated);let o=!1;try{o=new URLSearchParams(window.location.search).get(`connect`)===`claude`}catch{}if(o){try{let e=new URL(window.location.href);e.searchParams.delete(`connect`),window.history.replaceState(null,``,e.pathname+e.search+e.hash)}catch{}if(!a.claude_authenticated){r(`connect-claude`);return}}if(await e())return;r(`enter-pin`)}catch(e){if(n>0)return await new Promise(e=>setTimeout(e,1500)),t(n-1);console.error(`[admin] health check failed:`,e),r(`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 Y=(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();K(t.auth_status!==`dead`&&t.auth_status!==`missing`)}}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`){n(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),Y.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&&(K(!0),r(`enter-pin`))}).catch(()=>{})},[t]);async function X(e,t){y(!0);try{let i=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!i.ok){let e=await i.json().catch(()=>({}));if(i.status===401&&e?.code===`remote-auth-required`){n(`enter-pin`,`/api/admin/session`);return}h(e.error||`Invalid PIN`);return}let s=await i.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(``),r(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}}let Z=(0,p.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=s.trim();if(!t){h(`Please enter your name.`);return}if(i.length<4){h(`PIN must be at least 4 characters.`);return}let o=i;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`){n(`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 n=await e.json();n.pin_configured&&n.claude_authenticated?r(`enter-pin`):n.pin_configured?r(`connect-claude`):h(t.error||`Failed to set PIN.`)}else r(`enter-pin`)}catch{r(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let i=await fetch(`/api/health`);if((i.ok?await i.json():null)?.claude_authenticated){await X(o);return}a(``),r(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[i,v,s]),Q=(0,p.useCallback)(async e=>{e.preventDefault(),h(``),await X(i)},[i]),ee=(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;K(!1),D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(u)}catch{}return r(`connect-claude`),!0}finally{T(!1)}},[]),$=(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(``),r(`enter-pin`)},[]);return(0,p.useEffect)(()=>{Y.current=$},[$]),{appState:t,setAppState:r,pin:i,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,claudeConnected:G,pinInputRef:q,setPinFormRef:J,handleSetPin:Z,handleLogin:Q,handleDisconnect:ee,handleLogout:$}}var h=i();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:t,setPin:n,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:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,r.productName]}),(0,h.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,r.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:t,onChange:n,onComplete:()=>{},showPin:i}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!t||!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:t,setPin:n,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:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`h1`,{className:`connect-title`,children:r.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:t,onChange:n,onComplete:()=>{},showPin:i,autoFocus:!0}),(0,h.jsx)(s,{variant:`send`,type:`submit`,disabled:!t,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:t,setAuthPolling:n,authLoading:i,setAuthLoading:o,pinError:c,setPinError:l,setAppState:u}=e,[d,f]=(0,p.useState)(!1),[m,g]=(0,p.useState)(!1),[_,v]=(0,p.useState)(``),[y,b]=(0,p.useState)(``),[x,S]=(0,p.useState)(``);async function C(){S(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`paste-code`,code:y})})).json();e.accepted?(S(`Code submitted. Finishing sign-in…`),b(``)):S(e.error||`Could not submit code.`)}catch(e){console.error(`[admin] paste-code error:`,e),S(`Could not submit code.`)}}async function w(){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 T(){o(!0),l(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){n(!0),f(!0),o(!1),v(e.transport||``);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.`),n(!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 E(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),l(``)}return t||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:[t?(0,h.jsx)(`button`,{onClick:E,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:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,h.jsx)(`div`,{style:{marginTop:`12px`},children:(0,h.jsx)(s,{variant:`primary`,onClick:T,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`})}),t&&_===`native`&&(0,h.jsxs)(`div`,{style:{marginTop:`14px`,maxWidth:`420px`,margin:`14px auto 0`,display:`flex`,flexDirection:`column`,gap:`8px`},children:[(0,h.jsx)(`label`,{style:{fontSize:`12px`,color:`#999`,lineHeight:1.4},children:`If the browser didn't finish sign-in, paste the code or full redirect URL from Claude's page:`}),(0,h.jsxs)(`div`,{style:{display:`flex`,gap:`8px`},children:[(0,h.jsx)(`input`,{type:`text`,value:y,onChange:e=>b(e.target.value),placeholder:`Paste code or redirect URL`,style:{flex:1,padding:`8px 10px`,fontSize:`13px`,border:`1px solid #ccc`,borderRadius:`6px`}}),(0,h.jsx)(s,{variant:`primary`,onClick:C,disabled:!y.trim(),children:`Submit`})]}),x&&(0,h.jsx)(`p`,{style:{fontSize:`12px`,color:`#999`,margin:0},children:x})]})]}),(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:a,alt:r.productName,className:`connect-logo connect-logo--maxy`}),!r.logoContainsName&&(0,h.jsx)(`span`,{className:`connect-logo-label`,children:r.productName})]})]}),(0,h.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,r.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:T,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:w,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};
|