@rubytech/create-maxy-code 0.1.329 → 0.1.331
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/dist/index.js +19 -2
- package/package.json +1 -1
- package/payload/platform/config/brand.json +1 -0
- package/payload/platform/lib/account-enumeration/dist/index.d.ts +33 -0
- package/payload/platform/lib/account-enumeration/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/account-enumeration/dist/index.js +76 -0
- package/payload/platform/lib/account-enumeration/dist/index.js.map +1 -1
- package/payload/platform/lib/account-enumeration/src/index.ts +78 -0
- package/payload/platform/plugins/admin/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/admin/PLUGIN.md +13 -1
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.js +1 -2
- package/payload/platform/plugins/admin/mcp/dist/__tests__/admin-authoring-skill-gate.test.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.d.ts +1 -1
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.d.ts.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.js +18 -13
- package/payload/platform/plugins/admin/mcp/dist/content-producer-authoring-skills.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/index.js +102 -0
- package/payload/platform/plugins/admin/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.d.ts +2 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.js +57 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/__tests__/account-lifecycle.test.js.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts +34 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.d.ts.map +1 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js +78 -0
- package/payload/platform/plugins/admin/mcp/dist/tools/account-lifecycle.js.map +1 -0
- package/payload/platform/plugins/admin/skills/plainly/SKILL.md +7 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +2 -2
- package/payload/platform/plugins/contacts/mcp/dist/index.js +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.d.ts +2 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.d.ts.map +1 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js +71 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/__tests__/contact-lookup.test.js.map +1 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts +1 -0
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.d.ts.map +1 -1
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js +10 -3
- package/payload/platform/plugins/contacts/mcp/dist/tools/contact-lookup.js.map +1 -1
- package/payload/platform/plugins/contacts/mcp/package.json +4 -2
- package/payload/platform/plugins/docs/references/admin-ui.md +1 -1
- package/payload/platform/plugins/memory/.claude-plugin/plugin.json +1 -1
- package/payload/platform/plugins/memory/PLUGIN.md +1 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js +3 -1
- package/payload/platform/plugins/memory/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js +39 -0
- package/payload/platform/plugins/memory/mcp/dist/tools/__tests__/memory-lookup-by-name.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.d.ts.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js +13 -1
- package/payload/platform/plugins/memory/mcp/dist/tools/memory-lookup-by-name.js.map +1 -1
- package/payload/platform/plugins/slides/skills/deck-system/SKILL.md +1 -1
- package/payload/platform/scripts/__tests__/provision-role-stamp.test.sh +40 -0
- package/payload/platform/scripts/__tests__/sweep-durability.test.sh +103 -0
- package/payload/platform/scripts/lib/provision-account-dir.sh +319 -0
- package/payload/platform/scripts/lib/resolve-account-dir.sh +79 -132
- package/payload/platform/scripts/setup-account.sh +28 -361
- 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 +4 -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/config.d.ts +18 -0
- package/payload/platform/services/claude-session-manager/dist/config.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/config.js +63 -7
- package/payload/platform/services/claude-session-manager/dist/config.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +44 -2
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/index.js +50 -2
- package/payload/platform/services/claude-session-manager/dist/index.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-child-log.d.ts +13 -0
- package/payload/platform/services/claude-session-manager/dist/rc-child-log.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/rc-child-log.js +52 -0
- package/payload/platform/services/claude-session-manager/dist/rc-child-log.js.map +1 -0
- 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 +7 -0
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts +5 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js +8 -0
- package/payload/platform/services/claude-session-manager/dist/session-sidecar.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts +70 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js +213 -0
- package/payload/platform/services/claude-session-manager/dist/stuck-turn.js.map +1 -0
- package/payload/platform/services/webchat-channel/dist/instructions.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/instructions.js +25 -1
- package/payload/platform/services/webchat-channel/dist/instructions.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.d.ts +17 -0
- package/payload/platform/services/webchat-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/notification.js +14 -0
- package/payload/platform/services/webchat-channel/dist/notification.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.d.ts.map +1 -1
- package/payload/platform/services/webchat-channel/dist/server.js +66 -2
- package/payload/platform/services/webchat-channel/dist/server.js.map +1 -1
- package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts +28 -0
- package/payload/platform/services/webchat-channel/dist/turn-follow.d.ts.map +1 -0
- package/payload/platform/services/webchat-channel/dist/turn-follow.js +188 -0
- package/payload/platform/services/webchat-channel/dist/turn-follow.js.map +1 -0
- package/payload/platform/services/whatsapp-channel/dist/notification.d.ts.map +1 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js +24 -1
- package/payload/platform/services/whatsapp-channel/dist/notification.js.map +1 -1
- package/payload/platform/templates/account.json +2 -0
- package/payload/premium-plugins/management-consulting/skills/pitch-deck/SKILL.md +44 -37
- package/payload/server/public/assets/AdminLoginScreens-DexSvtjD.js +1 -0
- package/payload/server/public/assets/AdminShell-Bf9tndNg.js +1 -0
- package/payload/server/public/assets/{Checkbox-DWGpkJD5.js → Checkbox-D58GsKoQ.js} +1 -1
- package/payload/server/public/assets/{OperatorConversations-BWu6GMQM.css → OperatorConversations-CDdp2nVn.css} +1 -1
- package/payload/server/public/assets/OperatorConversations-RmqANYz8.js +9 -0
- package/payload/server/public/assets/{admin-CnIlm4Yi.js → admin-CH5Vkkt4.js} +1 -1
- package/payload/server/public/assets/{browser-ePr5LxPd.js → browser-BwDtzSlr.js} +1 -1
- package/payload/server/public/assets/chat-3GY0LmYH.js +1 -0
- package/payload/server/public/assets/data-CttrzhfL.js +1 -0
- package/payload/server/public/assets/{graph-B5uxt5YB.js → graph-CZSdF2jv.js} +3 -3
- package/payload/server/public/assets/{graph-labels-fx-bv3Y-.js → graph-labels-Bi0fu8Ns.js} +1 -1
- package/payload/server/public/assets/operator-BEivxmRy.js +1 -0
- package/payload/server/public/assets/page-DUvT07SB.js +30 -0
- package/payload/server/public/assets/{public-DXAdRKJe.js → public-B3eIlVbd.js} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/chat.html +5 -5
- package/payload/server/public/data.html +4 -4
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +6 -6
- package/payload/server/public/operator.html +7 -7
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +314 -222
- package/payload/server/public/assets/AdminLoginScreens-DstNf4M-.js +0 -1
- package/payload/server/public/assets/AdminShell-B5EcXCYR.js +0 -1
- package/payload/server/public/assets/OperatorConversations-CSQnX7Dx.js +0 -9
- package/payload/server/public/assets/chat-XjXSornk.js +0 -1
- package/payload/server/public/assets/data-DuObS80U.js +0 -1
- package/payload/server/public/assets/operator-CIGXegWd.js +0 -1
- package/payload/server/public/assets/page-BVOAwj-e.js +0 -30
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// Turn-end detector for the webchat native channel (Task 980). A faithful
|
|
2
|
+
// mirror of whatsapp-channel/turn-follow.ts — `reduceTurnFromLines` folds one
|
|
3
|
+
// turn's JSONL lines into the delivery decision and `followTurnEnds` tails the
|
|
4
|
+
// session JSONL from a byte offset and reports every assistant end_turn (not
|
|
5
|
+
// just the first), so a follow-on turn produced from a mid-turn-queued message
|
|
6
|
+
// is covered too. Pure of the MCP SDK so it unit-tests in isolation.
|
|
7
|
+
//
|
|
8
|
+
// The divergence from the WhatsApp twin: webchat has no fallback delivery and
|
|
9
|
+
// no reply-document tool. The follower exists ONLY to detect the
|
|
10
|
+
// turn-undelivered anomaly — a channel turn that ends with substantive
|
|
11
|
+
// assistant text but never called the reply tool, so the operator (who sees
|
|
12
|
+
// only reply-tool text in the browser reader) receives nothing. The reply text
|
|
13
|
+
// itself is never delivered or re-sent here; the gateway logs the anomaly.
|
|
14
|
+
import { closeSync, existsSync, openSync, readdirSync, readSync, statSync, watch } from 'node:fs';
|
|
15
|
+
import { homedir } from 'node:os';
|
|
16
|
+
import { join } from 'node:path';
|
|
17
|
+
// The reply tool the agent uses to deliver to the webchat browser. Its presence
|
|
18
|
+
// in a turn means the operator received something this turn. Mirrors
|
|
19
|
+
// WEBCHAT_CHANNEL_SERVER_NAME ('webchat-channel') in claude-session-manager's
|
|
20
|
+
// webchat-channel-mcp.ts; kept as a literal here to avoid a cross-package
|
|
21
|
+
// import. Webchat exposes no reply-document tool, so this set has one member.
|
|
22
|
+
const REPLY_TOOL_NAMES = new Set(['mcp__webchat-channel__reply']);
|
|
23
|
+
/** Fold one turn's JSONL line strings into the delivery decision. Pure. */
|
|
24
|
+
export function reduceTurnFromLines(lines) {
|
|
25
|
+
let replied = false;
|
|
26
|
+
let finalText = '';
|
|
27
|
+
let reachedEndTurn = false;
|
|
28
|
+
for (const line of lines) {
|
|
29
|
+
if (!line)
|
|
30
|
+
continue;
|
|
31
|
+
let ev;
|
|
32
|
+
try {
|
|
33
|
+
ev = JSON.parse(line);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (ev.type !== 'assistant')
|
|
39
|
+
continue;
|
|
40
|
+
const msg = ev.message;
|
|
41
|
+
const isEnd = msg?.stop_reason === 'end_turn';
|
|
42
|
+
if (!msg || !Array.isArray(msg.content)) {
|
|
43
|
+
if (isEnd) {
|
|
44
|
+
reachedEndTurn = true;
|
|
45
|
+
finalText = '';
|
|
46
|
+
}
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
let endText = '';
|
|
50
|
+
for (const block of msg.content) {
|
|
51
|
+
if (block?.type === 'tool_use' && typeof block.name === 'string' && REPLY_TOOL_NAMES.has(block.name)) {
|
|
52
|
+
replied = true;
|
|
53
|
+
}
|
|
54
|
+
else if (block?.type === 'text' && typeof block.text === 'string' && isEnd) {
|
|
55
|
+
endText += block.text;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (isEnd) {
|
|
59
|
+
reachedEndTurn = true;
|
|
60
|
+
finalText = endText;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { replied, finalText, reachedEndTurn };
|
|
64
|
+
}
|
|
65
|
+
/** True iff `line` is an assistant message with stop_reason 'end_turn'. */
|
|
66
|
+
function isAssistantEndTurn(line) {
|
|
67
|
+
if (!line)
|
|
68
|
+
return false;
|
|
69
|
+
let ev;
|
|
70
|
+
try {
|
|
71
|
+
ev = JSON.parse(line);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
return ev.type === 'assistant' && ev.message?.stop_reason === 'end_turn';
|
|
77
|
+
}
|
|
78
|
+
function claudeConfigRoot(env) {
|
|
79
|
+
return env.CLAUDE_CONFIG_DIR ?? join(homedir(), '.claude');
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Walk `${CLAUDE_CONFIG_DIR}/projects/<slug>/` for `${sessionId}.jsonl` (live
|
|
83
|
+
* and archived). Returns the first match or null. Inlined from
|
|
84
|
+
* whatsapp-channel/jsonl-watch.ts (itself inlined from
|
|
85
|
+
* claude-session-manager/src/jsonl-path.ts) to avoid a cross-package dep.
|
|
86
|
+
*/
|
|
87
|
+
export function findJsonlForSessionId(sessionId, env = process.env) {
|
|
88
|
+
const projectsRoot = join(claudeConfigRoot(env), 'projects');
|
|
89
|
+
if (!existsSync(projectsRoot))
|
|
90
|
+
return null;
|
|
91
|
+
let slugs;
|
|
92
|
+
try {
|
|
93
|
+
slugs = readdirSync(projectsRoot, { withFileTypes: true })
|
|
94
|
+
.filter((d) => d.isDirectory())
|
|
95
|
+
.map((d) => d.name);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const basename = `${sessionId}.jsonl`;
|
|
101
|
+
for (const slug of slugs) {
|
|
102
|
+
const live = join(projectsRoot, slug, basename);
|
|
103
|
+
if (existsSync(live))
|
|
104
|
+
return live;
|
|
105
|
+
const archived = join(projectsRoot, slug, 'archive', basename);
|
|
106
|
+
if (existsSync(archived))
|
|
107
|
+
return archived;
|
|
108
|
+
}
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Tail `jsonlPath` from `startOffset` for the life of the session, invoking
|
|
113
|
+
* `onTurnEnd` once for every assistant end_turn with that turn's outcome. It
|
|
114
|
+
* segments the JSONL at each end_turn so a follow-on turn produced from a
|
|
115
|
+
* mid-turn-queued message is reported too. The process dies with the session,
|
|
116
|
+
* so there is no per-turn timeout; the promise resolves only when the file
|
|
117
|
+
* becomes unreadable. Never rejects. (Mirror of the WhatsApp twin.)
|
|
118
|
+
*/
|
|
119
|
+
export async function followTurnEnds(jsonlPath, startOffset, onTurnEnd) {
|
|
120
|
+
let baseSize;
|
|
121
|
+
try {
|
|
122
|
+
baseSize = statSync(jsonlPath).size;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
return new Promise((resolve) => {
|
|
128
|
+
let offset = Math.min(startOffset, baseSize);
|
|
129
|
+
let carry = '';
|
|
130
|
+
let segment = [];
|
|
131
|
+
let settled = false;
|
|
132
|
+
const settle = () => {
|
|
133
|
+
if (settled)
|
|
134
|
+
return;
|
|
135
|
+
settled = true;
|
|
136
|
+
watcher.close();
|
|
137
|
+
clearInterval(poll);
|
|
138
|
+
resolve();
|
|
139
|
+
};
|
|
140
|
+
// Poll as well as watch: fs.watch misses appends on some platforms (notably
|
|
141
|
+
// macOS), so a light poll guarantees growth is seen within the interval.
|
|
142
|
+
const poll = setInterval(() => drain(), 200);
|
|
143
|
+
const drain = () => {
|
|
144
|
+
let end;
|
|
145
|
+
try {
|
|
146
|
+
end = statSync(jsonlPath).size;
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
settle();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (end <= offset)
|
|
153
|
+
return;
|
|
154
|
+
let buf;
|
|
155
|
+
try {
|
|
156
|
+
const fd = openSync(jsonlPath, 'r');
|
|
157
|
+
try {
|
|
158
|
+
buf = Buffer.alloc(end - offset);
|
|
159
|
+
readSync(fd, buf, 0, buf.length, offset);
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
closeSync(fd);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
settle();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
offset = end;
|
|
170
|
+
carry += buf.toString('utf8');
|
|
171
|
+
let nl = carry.indexOf('\n');
|
|
172
|
+
while (nl !== -1) {
|
|
173
|
+
const line = carry.slice(0, nl);
|
|
174
|
+
carry = carry.slice(nl + 1);
|
|
175
|
+
nl = carry.indexOf('\n');
|
|
176
|
+
segment.push(line);
|
|
177
|
+
if (isAssistantEndTurn(line)) {
|
|
178
|
+
onTurnEnd(reduceTurnFromLines(segment));
|
|
179
|
+
segment = [];
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
const watcher = watch(jsonlPath, { persistent: false }, () => drain());
|
|
184
|
+
watcher.on('error', () => settle());
|
|
185
|
+
drain(); // catch lines already present between startOffset and now
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=turn-follow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-follow.js","sourceRoot":"","sources":["../src/turn-follow.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,CAAA;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,qEAAqE;IACrE,QAAQ,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAA;IACZ,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAA;IACnB;;;kFAG8E;IAC9E,KAAK,EAAE,YAAY,EAAE,CAAA;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,mBAAmB,
|
|
1
|
+
{"version":3,"file":"notification.d.ts","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"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"}
|
|
@@ -54,13 +54,36 @@ export const REFRAME_INSTRUCTION = 'Choose the installed specialist that owns th
|
|
|
54
54
|
'Call the reply tool right away to acknowledge you are on it, ' +
|
|
55
55
|
'send a brief progress note with the reply tool before each long step, and call the reply tool again with the result — ' +
|
|
56
56
|
'never stay silent until the end. ' +
|
|
57
|
+
// Task 980 — the channel/visibility model. A channel turn can end with its
|
|
58
|
+
// substantive answer written as plain assistant text and no reply-tool call;
|
|
59
|
+
// the operator never receives it. The bare cadence clause above read as
|
|
60
|
+
// progress-note etiquette, so this clause states the mechanism and consequence
|
|
61
|
+
// outright: the operator sees ONLY reply-tool text, so a turn-final plain text
|
|
62
|
+
// block delivers nothing. IDENTICAL to the webchat twin's clause in
|
|
63
|
+
// ADMIN_REFRAME_INSTRUCTION (recipient-neutral so the literal matches),
|
|
64
|
+
// drift-guarded by a test in each service.
|
|
65
|
+
'Remember you are answering over a channel: the person you are replying to is not watching this session ' +
|
|
66
|
+
'and sees only the text you send with the reply tool. ' +
|
|
67
|
+
'Anything you write as an ordinary assistant message, without calling the reply tool, is invisible to them. ' +
|
|
68
|
+
'So a turn that answers them is finished only once you have called the reply tool with the full answer; ' +
|
|
69
|
+
'a turn that ends without a reply tool call delivers nothing, no matter what you wrote. ' +
|
|
57
70
|
// Task 919 — the bridge forwards a SendUserFile call to this conversation as a
|
|
58
71
|
// real attachment. Steer the agent to deliver the file, not describe it. This
|
|
59
72
|
// clause is identical in the webchat twin (ADMIN_REFRAME_INSTRUCTION) and
|
|
60
73
|
// drift-guarded by a test in each service.
|
|
61
74
|
'When you have produced a file to deliver, deliver it by calling SendUserFile with its path — ' +
|
|
62
75
|
'the platform forwards it to this conversation as an attachment; ' +
|
|
63
|
-
'a reply that only names or describes the file is not delivery.'
|
|
76
|
+
'a reply that only names or describes the file is not delivery. ' +
|
|
77
|
+
// Task 982 — plain English on every operator-facing reply, not only on explicit
|
|
78
|
+
// "explain in plain English" requests. The plainly skill is installed but
|
|
79
|
+
// otherwise triggers only on that explicit ask, so ordinary replies carry the
|
|
80
|
+
// AI tells it already catalogues. This clause points the agent at the skill for
|
|
81
|
+
// every reply form. IDENTICAL to the webchat twin's clause in
|
|
82
|
+
// ADMIN_REFRAME_INSTRUCTION (recipient-neutral so the literal matches),
|
|
83
|
+
// drift-guarded by a test in each service.
|
|
84
|
+
'Write every reply you send (acknowledgement, progress note, answer, or deliverable summary) ' +
|
|
85
|
+
'in plain English, in the spoken register and free of the AI tells the plainly skill catalogues; ' +
|
|
86
|
+
'load that skill for the full rules.';
|
|
64
87
|
/**
|
|
65
88
|
* Shape an inbound WhatsApp payload as a Claude Code channel notification.
|
|
66
89
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notification.js","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,yEAAyE;AACzE,yEAAyE;AAsBzE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,8FAA8F;IAC9F,8GAA8G;IAC9G,iFAAiF;IACjF,0EAA0E;IAC1E,gDAAgD;IAChD,sGAAsG;IACtG,iHAAiH;IACjH,iDAAiD;IACjD,qGAAqG;IACrG,mHAAmH;IACnH,qBAAqB;IACrB,+DAA+D;IAC/D,wHAAwH;IACxH,mCAAmC;IACnC,+EAA+E;IAC/E,8EAA8E;IAC9E,0EAA0E;IAC1E,2CAA2C;IAC3C,+FAA+F;IAC/F,kEAAkE;IAClE,
|
|
1
|
+
{"version":3,"file":"notification.js","sourceRoot":"","sources":["../src/notification.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: pitch-deck
|
|
3
|
-
description: Composes a presentation deck in the operator's own voice. It states plainly what is being proposed and how it works; it does not sell or perform. Three kinds: a deck that wins new work, a deck that presents findings and a recommendation, and a deck that sets out a point of view. Use for a consulting pitch deck, a capabilities or credentials deck, a client findings or recommendation deck, a board or steering-committee deck, or a thought-leadership deck.
|
|
3
|
+
description: Composes a presentation deck in the operator's own voice. It states plainly what is being proposed and how it works; it does not sell or perform. Three kinds: a deck that wins new work, a deck that presents findings and a recommendation, and a deck that sets out a point of view. Use for a consulting pitch deck, a capabilities or credentials deck, a client findings or recommendation deck, a board or steering-committee deck, or a thought-leadership deck. The admin runs it: it asks the operator the deck kind, light or dark, and the colour set, then delegates composing the words and rendering to `specialists:content-producer`, with the words approved before anything is built. Never invents a number. Not a founder fundraise deck; that is `venture-studio:investor-data-room`. Not a generic renderer for arbitrary HTML slides; that is `admin:deck-pages`.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Pitch Deck
|
|
7
7
|
|
|
8
|
-
The consulting bundle's deck. It states plainly what is being proposed and how it works. The
|
|
8
|
+
The consulting bundle's deck. It states plainly what is being proposed and how it works. The admin runs this skill and owns every choice the operator must make; content-producer does the composing and the rendering. The words are approved before anything is built. It composes only from facts the operator already curated, and it never invents a number.
|
|
9
9
|
|
|
10
10
|
## When to use
|
|
11
11
|
|
|
12
|
-
Pick the kind of deck from the brief.
|
|
12
|
+
Pick the kind of deck from the brief.
|
|
13
13
|
|
|
14
14
|
| Kind | Use it when |
|
|
15
15
|
|------|-------------|
|
|
@@ -22,65 +22,70 @@ Pick the kind of deck from the brief. All three are built the same way: words fi
|
|
|
22
22
|
- **Founder fundraise deck** (seed or Series raise, investor pitch under the founder's own name) routes to `venture-studio:investor-data-room`.
|
|
23
23
|
- **A deck the operator already wrote, an arbitrary fixed-dimension slide layout, "save this HTML as a deck"** routes to `admin:deck-pages` (the format spec and generic slide renderer).
|
|
24
24
|
|
|
25
|
-
##
|
|
25
|
+
## Who does what
|
|
26
26
|
|
|
27
|
-
Invoked
|
|
27
|
+
Invoked by the admin agent. The split exists because only the admin can ask the operator a question; a specialist cannot.
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
- **The admin** owns every operator decision: the deck kind, light or dark, the colour set, and approval of the words. It asks the operator directly and never relies on the subagent to raise these.
|
|
30
|
+
- **content-producer** does the two mechanical steps the admin delegates: write the words to a file, and render with the choices passed in. It owns no question to the operator.
|
|
30
31
|
|
|
31
|
-
The order
|
|
32
|
+
## The order (fixed)
|
|
32
33
|
|
|
33
|
-
1. **
|
|
34
|
-
2. **
|
|
35
|
-
3. **
|
|
34
|
+
1. **Intake (admin).** Ask the operator three things: which kind of deck (win the work, findings, point of view), light or dark, and the colour set (the brand default, or a set the operator names). These are the same questions for every deck, so ask them up front. Do not delegate anything until you have the answers.
|
|
35
|
+
2. **Compose (delegate to content-producer).** Dispatch content-producer (Agent tool, `subagent_type: content-producer`) with the kind, the topic, and the source facts. It writes the full deck text to a file, voice-conditioned (below), and returns the file path. It makes no visual choice and does not render.
|
|
36
|
+
3. **Approve (admin).** Read the words file back to the operator. Take their edits, iterate, until they approve.
|
|
37
|
+
4. **Render (delegate to content-producer).** Dispatch content-producer again with the approved-words file path, the kind, the mode (light or dark), and the colour set. It renders and exports the PDF.
|
|
36
38
|
|
|
37
|
-
## Writing the words
|
|
39
|
+
## Writing the words (content-producer, compose step)
|
|
38
40
|
|
|
39
|
-
Load `plainly` and write in its **statement register**: say what each thing is, in a sensible order, with no selling, no story arc, and no performance. `plainly` carries the full rule and the habits to strip; do not restate them
|
|
41
|
+
Load `plainly` and write in its **statement register**: say what each thing is, in a sensible order, with no selling, no story arc, and no performance. `plainly` carries the full rule and the habits to strip; apply them, do not restate them. The points that matter most for a deck:
|
|
40
42
|
|
|
41
43
|
- **Each slide's header says what the slide is, or states its one fact.** "Using AI to handle insurance rejections", not a slogan. Never bend a header to land a word in a set place or to match the shape of another header.
|
|
42
44
|
- **Put the point first.** Say what you are proposing, then explain it. Do not build up to it.
|
|
43
|
-
- **Order the slides so the whole thing is clear:** where they are now, what you would do, how it works, what it costs to start, what you are asking for. Read the headers on their own, in order
|
|
45
|
+
- **Order the slides so the whole thing is clear:** where they are now, what you would do, how it works, what it costs to start, what you are asking for. Read the headers on their own, in order; they should lay the whole thing out plainly.
|
|
44
46
|
- **Each section covers something the others do not.** No overlap, no gaps. If two slides say the same thing, merge them.
|
|
45
47
|
- **One point per slide.** Cut any slide that does not say something the reader needs.
|
|
46
48
|
- **Every slide with a number shows where the number came from:** a graph node, a named source, or the operator's own figures. A number with no source is a defect.
|
|
47
49
|
- **Never invent a number.** If one is missing, leave a visible gap and ask for it. Do not fill it.
|
|
48
50
|
|
|
51
|
+
Write the words to a file under `output/` and return the path. Do not render, and do not choose light or dark or a colour set; those are the admin's, passed back to you at the render step.
|
|
52
|
+
|
|
49
53
|
### Voice (hard gate)
|
|
50
54
|
|
|
51
|
-
A deck goes out under the business name, so it uses the **house voice
|
|
55
|
+
A deck goes out under the business name, so it uses the **house voice**. A deck is mostly short copy with some longer prose, so retrieve both profiles and condition each part on the right one:
|
|
56
|
+
|
|
57
|
+
- **`marketing-copy`** for the short copy: headlines, taglines, calls to action, the one-line slide points.
|
|
58
|
+
- **`article`** for any longer body prose: a paragraph of context, an executive summary.
|
|
52
59
|
|
|
53
|
-
|
|
60
|
+
Call `voice-retrieve-conditioning` for each, with `length: "long"`, `scope: "org"`, and `topic` set to the engagement domain. The tool emits its own `[voice-retrieve] …` line per call.
|
|
54
61
|
|
|
55
|
-
|
|
56
|
-
- **`no-data` | `error`**: stop. Write no slide text. Tell the operator the deck voice is not established, and offer two routes: establish the house voice through the voice-mirror skill, then re-run; or supply the words themselves, which this skill will only structure and run through `plainly`, never generate.
|
|
62
|
+
Gate on the `marketing-copy` result, since the deck is mostly short copy:
|
|
57
63
|
|
|
58
|
-
|
|
64
|
+
- **`ok`**: condition the short copy on the marketing-copy style card and the body on the article style card, then write.
|
|
65
|
+
- **`no-data` | `error`**: stop. Write no slide text. Return to the admin: the deck voice is not established, and offer two routes. Establish the house voice through the voice-mirror skill then re-run, or have the operator supply the words, which this skill only structures and runs through `plainly`, never generates.
|
|
66
|
+
|
|
67
|
+
Emit one decision line after the gate:
|
|
59
68
|
|
|
60
69
|
```
|
|
61
70
|
[pitch-deck] voice-gate status=<ok|no-data|error> action=<conditioned|stopped|operator-prose>
|
|
62
71
|
```
|
|
63
72
|
|
|
64
|
-
##
|
|
65
|
-
|
|
66
|
-
Show the operator the full text of the deck, every slide, before building anything. Take their edits and fold them in. Repeat until they approve. The approval is the gate to the build step; do not render a deck the operator has not signed off.
|
|
73
|
+
## Rendering (content-producer, render step)
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
Render only when the admin has handed you all three inputs: the approved-words file, the mode (light or dark), and the colour set. **If any of the three is missing, do not render.** Return to the admin naming what is missing and emit:
|
|
69
76
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
2. **Apply the brand's design tokens.** Read `brand.json` and take the colours and fonts from it. This is a prerequisite of the build, not a finishing pass. Do not invent colours; if the brand omits a value, fall back to the default brand's value.
|
|
74
|
-
3. **Render.** Hand the approved words to `slides:deck-system`, which carries the components, the themes, and the PDF export. content-producer renders on the same seat and exports the PDF through the existing path. There is no new renderer.
|
|
77
|
+
```
|
|
78
|
+
[pitch-deck] render-refused missing=<words|mode|colour>
|
|
79
|
+
```
|
|
75
80
|
|
|
76
|
-
If `slides` is not enabled, say so and fall back to the always-present `admin:deck-pages` format spec.
|
|
81
|
+
With all three present: apply the brand's design tokens for the chosen colour set (read `brand.json`; do not invent colours, fall back to the default brand's value for any missing token), render the approved words through `slides:deck-system` in the chosen mode, and export the PDF through the existing path. There is no new renderer. If `slides` is not enabled, say so and fall back to the always-present `admin:deck-pages` format spec. Build in the operator's own brand; never embed a named firm's branded template or assets.
|
|
77
82
|
|
|
78
83
|
## The three kinds, and how each is ordered
|
|
79
84
|
|
|
80
|
-
The voice and register are the same for all three. They differ only in
|
|
85
|
+
The voice and register are the same for all three. They differ only in which slides they hold and in what order.
|
|
81
86
|
|
|
82
|
-
- **Win the work.** A fixed set of slides
|
|
83
|
-
- **Present findings and a recommendation.** One slide that states the recommendation and the few facts behind it, then where things stand now, what is wrong, what you found, what you recommend, how it would roll out, and what happens next. The first slide stands on its own
|
|
87
|
+
- **Win the work.** A fixed set of slides plus a few specific to the engagement: who you are, how you work, what you do, the work you have done before, the people, how to reach you. Add only the sections this prospect needs. Aim for eleven to fourteen slides.
|
|
88
|
+
- **Present findings and a recommendation.** One slide that states the recommendation and the few facts behind it, then where things stand now, what is wrong, what you found, what you recommend, how it would roll out, and what happens next. The first slide stands on its own.
|
|
84
89
|
- **Set out a point of view.** The topic first, then the data, then what it means and what to do about it, then a short note on who you are at the end. No client-specific recommendation and no sell.
|
|
85
90
|
|
|
86
91
|
## Charts
|
|
@@ -109,16 +114,18 @@ The deck composes the outputs of the other consulting skills. Numbers come from
|
|
|
109
114
|
|
|
110
115
|
## Done when
|
|
111
116
|
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
+
- The admin asked the operator the kind, the mode, and the colour set before delegating.
|
|
118
|
+
- content-producer wrote the words to a file and the operator approved them before any render.
|
|
119
|
+
- The render ran only with the approved words, the mode, and the colour set all present.
|
|
120
|
+
- The short copy was conditioned on `marketing-copy` and the body on `article`.
|
|
121
|
+
- Every line passes the said-aloud test in `plainly`'s statement register.
|
|
122
|
+
- Every slide with a number shows its source, and the deck renders to HTML and exports a PDF.
|
|
117
123
|
|
|
118
124
|
## Observability
|
|
119
125
|
|
|
120
126
|
```
|
|
121
127
|
[pitch-deck] voice-gate status=<ok|no-data|error> action=<conditioned|stopped|operator-prose>
|
|
128
|
+
[pitch-deck] render-refused missing=<words|mode|colour>
|
|
122
129
|
```
|
|
123
130
|
|
|
124
|
-
The `[voice-retrieve] …` line is emitted by the voice tool. A render or export failure surfaces through `content-producer`'s existing `[tool-failure-diag]` line.
|
|
131
|
+
The `[voice-retrieve] …` line is emitted by the voice tool, once per profile. A `render-refused` line means the admin tried to build without all three inputs, which is the guard working. A render or export failure surfaces through `content-producer`'s existing `[tool-failure-diag]` line.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{o as e}from"./chunk-Pqm5yXtL.js";import{H as t,R as n,S as r,b as i,k as a,y as o}from"./OperatorConversations-RmqANYz8.js";import{i as s}from"./admin-types-CJrGd46U.js";import{g as c,u as l}from"./AdminShell-Bf9tndNg.js";import{t as u}from"./Checkbox-D58GsKoQ.js";var d=`admin-landing-redirected`,f=`/graph`;function p(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var m=e(t(),1);function h(e=`admin`){let[t,r]=(0,m.useState)(`loading`),[i,a]=(0,m.useState)(``),[o,l]=(0,m.useState)(``),[u,h]=(0,m.useState)(``),[g,_]=(0,m.useState)(!1),[v,y]=(0,m.useState)(!1),[b,x]=(0,m.useState)(!1),[S,C]=(0,m.useState)(!1),[w,T]=(0,m.useState)(!1),[E,D]=(0,m.useState)(null),[O,k]=(0,m.useState)(null),[A,j]=(0,m.useState)(void 0),[M,N]=(0,m.useState)(null),[P,F]=(0,m.useState)(void 0),[I,L]=(0,m.useState)(null),[ee,R]=(0,m.useState)(null),[z,B]=(0,m.useState)([]),[V,H]=(0,m.useState)(!1),[U,W]=(0,m.useState)(void 0),G=(0,m.useRef)(void 0),[K,q]=(0,m.useState)(!1);(0,m.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&q(!0)}).catch(()=>{})},[]);let J=(0,m.useRef)(null),Y=(0,m.useRef)(null);(0,m.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),R(n.sessionId??null),j(n.businessName),N(n.role??null),F(n.userName===void 0?null:n.userName),L(n.avatar??null);let i=s(n.thinkingView);return G.current=i,W(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}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,m.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,m.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(d)===`1`}catch{}if(p({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(d,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${f}`),window.location.replace(f)}},[t,e]);let X=(0,m.useRef)(null);(0,m.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`){r(`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`){n(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),X.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,m.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&r(`enter-pin`)}).catch(()=>{})},[t]);async function Z(e,t){y(!0);try{let n=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!n.ok){h((await n.json().catch(()=>({}))).error||`Invalid PIN`);return}let i=await n.json();if(i.accounts&&!i.session_key){console.log(`[admin] account picker shown: userId=${i.userId} accountCount=${i.accounts.length}`),B(i.accounts),r(`account-picker`);return}D(i.session_key),R(i.sessionId??null),j(i.businessName),N(i.role??null),F(i.userName===void 0?null:i.userName),L(i.avatar??null);let o=s(i.thinkingView);if(G.current=o,W(o),t)try{sessionStorage.setItem(`maxy-account-id`,t)}catch{}try{sessionStorage.setItem(`maxy-admin-session-key`,i.session_key)}catch{}a(``),r(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1),H(!1)}}let Q=(0,m.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=o.trim();if(!t){h(`Please enter your name.`);return}if(i.length<4){h(`PIN must be at least 4 characters.`);return}let n=i;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:n,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));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 Z(n);return}a(``),r(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[i,v,o]),te=(0,m.useCallback)(async e=>{e.preventDefault(),h(``),await Z(i)},[i]),ne=(0,m.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(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}return r(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,m.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}a(``),h(``),r(`enter-pin`)},[]);return(0,m.useEffect)(()=>{X.current=$},[$]),{appState:t,setAppState:r,pin:i,setPin:a,operatorName:o,setOperatorName:l,pinError:u,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:ee,setSessionId:R,accounts:z,accountPickerLoading:V,expandAll:U,setExpandAll:W,expandAllDefaultRef:G,remoteAuthEnabled:K,pinInputRef:J,setPinFormRef:Y,handleSetPin:Q,handleLogin:te,handleAccountSelect:(0,m.useCallback)(async e=>{H(!0),h(``),await Z(i,e)},[i]),handleDisconnect:ne,handleLogout:$,handleChangePin:(0,m.useCallback)(async()=>{if(!i){h(`Enter your current PIN first.`);return}y(!0),h(``);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({currentPin:i})});if(!e.ok){h((await e.json().catch(()=>({error:`Incorrect PIN.`}))).error||`Incorrect PIN.`);return}a(``),h(``),r(`set-pin`)}catch(e){console.error(`[admin-auth] change pin failed:`,e),h(e instanceof Error?e.message:String(e))}finally{y(!1)}},[i])}}var g=r();function _({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,m.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,g.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,g.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 v(e){let{pin:t,setPin:n,showPin:r,setShowPin:a,pinLoading:s,pinError:c,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:h}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:i,alt:o.productName,className:`connect-logo connect-logo--maxy`}),!o.logoContainsName&&(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,o.productName]}),(0,g.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,o.productName,` who you are, then choose a PIN.`]}),(0,g.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>h(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,g.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r}),(0,g.jsx)(l,{variant:`send`,type:`submit`,disabled:!t||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsx)(u,{checked:r,onChange:()=>a(e=>!e),label:`Show PIN`})]}),c&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:c})]})})}function y(e){let{pin:t,setPin:n,showPin:r,setShowPin:a,pinLoading:s,pinError:c,pinInputRef:d,onSubmit:f,onChangePin:p,remoteAuthEnabled:m,onSignOutRemote:h}=e;return(0,g.jsxs)(`div`,{className:`connect-page`,children:[m&&h&&(0,g.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:h,children:`Sign out`}),(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:i,alt:o.productName,className:`connect-logo connect-logo--maxy`}),!o.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:o.productName}),(0,g.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r,autoFocus:!0}),(0,g.jsx)(l,{variant:`send`,type:`submit`,disabled:!t,loading:s,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsxs)(`div`,{className:`pin-options`,children:[(0,g.jsx)(u,{checked:r,onChange:()=>a(e=>!e),label:`Show PIN`}),(0,g.jsx)(l,{type:`button`,variant:`ghost`,onClick:p,children:`Change PIN`})]})]}),c&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:c})]})]})}function b(e){let{accounts:t,loading:n,error:r,onSelect:s}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:i,alt:o.productName,className:`connect-logo connect-logo--maxy`}),!o.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:o.productName}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Select an account`}),(0,g.jsx)(`div`,{className:`account-picker-list`,children:t.map(e=>(0,g.jsxs)(`button`,{className:`account-picker-card`,onClick:()=>s(e.accountId),disabled:n,type:`button`,children:[(0,g.jsx)(`span`,{className:`account-picker-name`,children:e.businessName||e.accountId}),(0,g.jsx)(`span`,{className:`account-picker-role`,children:e.role}),n&&(0,g.jsx)(a,{className:`account-picker-spinner`,size:16})]},e.accountId))}),r&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:r})]})})}function x(e){let{authPolling:t,setAuthPolling:n,authLoading:r,setAuthLoading:a,pinError:s,setPinError:c,setAppState:u}=e,[d,f]=(0,m.useState)(!1),[p,h]=(0,m.useState)(!1);async function _(){h(!0),c(``);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&&c(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),c(`Could not launch browser.`)}h(!1)}async function v(){a(!0),c(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){n(!0),f(!0),a(!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}c(`Timed out waiting for sign-in. Try again.`),n(!1)}else e.error&&c(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),c(`Could not start auth flow.`)}a(!1)}async function y(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),c(``)}return t||d?(0,g.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,g.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,g.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,g.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,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,g.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,g.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,g.jsx)(`div`,{style:{marginTop:`12px`},children:(0,g.jsx)(l,{variant:`primary`,onClick:v,disabled:r,children:r?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})})]}),(0,g.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,g.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,g.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsxs)(`div`,{className:`connect-logos`,children:[(0,g.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,g.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,g.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,g.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,g.jsx)(`img`,{src:i,alt:o.productName,className:`connect-logo connect-logo--maxy`}),!o.logoContainsName&&(0,g.jsx)(`span`,{className:`connect-logo-label`,children:o.productName})]})]}),(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,o.productName]}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,g.jsx)(l,{variant:`primary`,onClick:v,disabled:r,children:r?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,g.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,g.jsx)(`button`,{onClick:_,disabled:p,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:p?`Launching…`:`Open browser first`}),s&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function S({auth:e}){return e.appState===`loading`?(0,g.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,g.jsx)(v,{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,g.jsx)(x,{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,g.jsx)(y,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,onChangePin:e.handleChangePin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):e.appState===`account-picker`?(0,g.jsx)(b,{accounts:e.accounts,loading:e.accountPickerLoading,error:e.pinError,onSelect:e.handleAccountSelect}):null}export{h as n,S as t};
|