@tangle-network/agent-app 0.50.1 → 0.50.3

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.
@@ -1,14 +1,15 @@
1
1
  import { type ReactNode } from 'react';
2
- import type { ChannelsClient } from './types';
2
+ import type { ChannelsClient, ChannelsReadClient } from './types';
3
3
  /** Mount below authentication. Changing scope remounts all channel state. */
4
4
  export declare function ChannelsProvider({ client, pollInterval, children }: {
5
- client: ChannelsClient;
5
+ client: ChannelsReadClient;
6
6
  /** Poll after a read settles, never concurrently. false disables polling. */
7
7
  pollInterval?: number | false;
8
8
  children: ReactNode;
9
9
  }): import("react").JSX.Element;
10
+ /** Management hooks keep the existing full-client contract; read views never call this. */
10
11
  export declare function useChannelsClient(): ChannelsClient;
11
12
  export declare function useChannelsContext(): {
12
- client: ChannelsClient;
13
+ client: ChannelsReadClient;
13
14
  pollInterval: number | false;
14
15
  };
@@ -1,5 +1,5 @@
1
- /** Browser-safe channel UI. Supply one authenticated ChannelsClient; no server wiring is bundled. */
2
- export type { ChannelsClient, ChannelConnection, ChannelNumber, ChannelReadContext, ChannelVerification, ConnectChannelInput, LinePayment, Line, LineAttachment, LineFromConnectionInput, LineMessage, LineThread, LineTransport, HubNumberOrder, HubNumberQuote, HubNumberReadiness, } from './types';
1
+ /** Browser-safe channel UI. Supply authenticated read or management capabilities; no server wiring is bundled. */
2
+ export type { ChannelsClient, ChannelsReadClient, ChannelConnection, ChannelNumber, ChannelReadContext, ChannelVerification, ConnectChannelInput, LinePayment, Line, LineAttachment, LineFromConnectionInput, LineMessage, LineThread, LineTransport, HubNumberOrder, HubNumberQuote, HubNumberReadiness, } from './types';
3
3
  export { ChannelsProvider, useChannelsClient } from './context';
4
4
  export { useChannels, useChannelConnections, useWhatsAppNumbers, useConnectChannel, useChannel, useChannelConversations, useChannelConversation, verificationExpired, type VerificationAction, } from './hooks';
5
5
  export { ChannelConnect, ChannelVerificationPanel, IMessageChannel, WhatsAppChannel, SMSChannel, EmailChannel, NumberChannel, ChannelConversation, ChannelConversations, channelMessageLink, type ChannelConnectProps, } from './components';
@@ -18,7 +18,11 @@ function ChannelsProvider({ client, pollInterval = 3e3, children }) {
18
18
  return /* @__PURE__ */ jsx(Context.Provider, { value: { client, pollInterval }, children }, client.scope);
19
19
  }
20
20
  function useChannelsClient() {
21
- return useChannelsContext().client;
21
+ const { client } = useChannelsContext();
22
+ if (!("setup" in client) || !client.setup || !("fromConnection" in client.lines) || typeof client.lines.fromConnection !== "function") {
23
+ throw new Error("Channel setup requires a management client.");
24
+ }
25
+ return client;
22
26
  }
23
27
  function useChannelsContext() {
24
28
  const value = useContext(Context);
@@ -71,15 +75,15 @@ function useChannels() {
71
75
  return useChannelResource(() => client.lines.list(), []);
72
76
  }
73
77
  function useChannelConnections(transport) {
74
- const { client } = useChannelsContext();
78
+ const client = useChannelsClient();
75
79
  return useChannelResource((context) => client.setup.connections(transport, context), [transport], true, false);
76
80
  }
77
81
  function useWhatsAppNumbers(connectionId) {
78
- const { client } = useChannelsContext();
82
+ const client = useChannelsClient();
79
83
  return useChannelResource((context) => client.setup.whatsappNumbers(connectionId, context), [connectionId], !!connectionId, false);
80
84
  }
81
85
  function useConnectChannel(onConnected) {
82
- const { client } = useChannelsContext();
86
+ const client = useChannelsClient();
83
87
  return useChannelMutation(async (input) => {
84
88
  if (input.kind === "connection") {
85
89
  if (!input.input.connectionId.trim()) throw new Error("Choose a connection.");
@@ -99,7 +103,7 @@ function verificationExpired(test, now = Date.now()) {
99
103
  return test.expired || test.status !== "verified" && test.expiresAt <= now;
100
104
  }
101
105
  function useChannel(lineId) {
102
- const { client } = useChannelsContext();
106
+ const client = useChannelsClient();
103
107
  const resource = useChannelResource(async (context) => {
104
108
  const [line, verification] = await Promise.all([client.lines.get(lineId), client.setup.verification(lineId, context)]);
105
109
  if (line.id !== lineId || line.attachment && line.attachment.lineId !== lineId || verification && verification.lineId !== lineId) throw new Error("Channel binding changed. Reload channel setup.");
@@ -175,7 +179,7 @@ function numberStage(order) {
175
179
  return "Provisioning";
176
180
  }
177
181
  function useNumberChannel(transport) {
178
- const { client } = useChannelsContext();
182
+ const client = useChannelsClient();
179
183
  const ordering = client.ordering;
180
184
  const reference = ordering?.references[transport];
181
185
  const [quote, setQuote] = useState(null);
@@ -635,7 +639,7 @@ function safeCheckoutUrl(value) {
635
639
  return url.href;
636
640
  }
637
641
  function useLinePayment(lineId) {
638
- const { client } = useChannelsContext();
642
+ const client = useChannelsClient();
639
643
  const resource = useChannelResource((context) => {
640
644
  if (!client.payment) throw new Error("Payments are unavailable for this line.");
641
645
  return client.payment.read(lineId, context);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/channels/context.tsx","../../src/channels/hooks.ts","../../src/channels/components.tsx","../../src/channels/numbers.ts","../../src/channels/ui.tsx","../../src/channels/payment.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react'\nimport type { ChannelsClient } from './types'\n\nconst Context = createContext<{ client: ChannelsClient; pollInterval: number | false } | null>(null)\n\n/** Mount below authentication. Changing scope remounts all channel state. */\nexport function ChannelsProvider({ client, pollInterval = 3000, children }: {\n client: ChannelsClient\n /** Poll after a read settles, never concurrently. false disables polling. */\n pollInterval?: number | false\n children: ReactNode\n}) {\n if (pollInterval !== false && (!Number.isFinite(pollInterval) || pollInterval < 100)) {\n throw new Error('ChannelsProvider pollInterval must be false or at least 100 ms.')\n }\n return <Context.Provider value={{ client, pollInterval }} key={client.scope}>{children}</Context.Provider>\n}\n\nexport function useChannelsClient(): ChannelsClient {\n return useChannelsContext().client\n}\n\nexport function useChannelsContext() {\n const value = useContext(Context)\n if (!value) throw new Error('Channel components and hooks require ChannelsProvider.')\n return value\n}\n","import { useCallback, useEffect, useRef } from 'react'\nimport { confirmWrite, rejectWrite, useAsyncResource, useConfirmedMutation } from '../web-react/async'\nimport type { AsyncLoadContext, AsyncResourceState, MutationOutcome } from '../web-react/async'\nimport { useChannelsContext } from './context'\nimport type { ChannelVerification, ConnectChannelInput, Line, LineTransport } from './types'\n\n/** Reuse the kit's abort/sequence-aware read machine; polling never overlaps a read. */\nexport function useChannelResource<T>(load: (context: AsyncLoadContext) => Promise<T>, deps: readonly unknown[], enabled = true, poll = true): AsyncResourceState<T> {\n const { client, pollInterval } = useChannelsContext()\n const resource = useAsyncResource({ load, deps: [client, client.scope, ...deps], enabled })\n useEffect(() => {\n if (!enabled || !poll || pollInterval === false || resource.status === 'loading' || resource.status === 'idle') return\n const delay = typeof document !== 'undefined' && document.hidden ? Math.max(15000, pollInterval) : pollInterval\n const timer = setTimeout(resource.retry, delay)\n return () => clearTimeout(timer)\n }, [enabled, poll, pollInterval, resource.status, resource.retry, resource])\n return enabled ? resource : { status: 'idle', retry: resource.retry }\n}\n\n/** Single-flight on top of the shared confirmed-write primitive. */\nexport function useChannelMutation<I, O>(mutate: (input: I, context: AsyncLoadContext) => Promise<O>, onSucceeded?: (value: O) => void) {\n const { client } = useChannelsContext()\n const lock = useRef<object | null>(null)\n const mutation = useConfirmedMutation<I, O>({\n mutate: async (input, context) => confirmWrite(await mutate(input, context)),\n onSucceeded,\n })\n const { reset, run } = mutation\n useEffect(() => {\n reset()\n return () => { lock.current = null; reset() }\n }, [client, client.scope, reset])\n const singleRun = useCallback(async (input: I): Promise<MutationOutcome<O>> => {\n if (lock.current) return rejectWrite('Another channel operation is still in progress.')\n const token = {}\n lock.current = token\n try { return await run(input) }\n finally { if (lock.current === token) lock.current = null }\n }, [run])\n return { ...mutation, run: singleRun }\n}\n\nexport function useChannels() {\n const { client } = useChannelsContext()\n return useChannelResource(() => client.lines.list(), [])\n}\n\nexport function useChannelConnections(transport: LineTransport) {\n const { client } = useChannelsContext()\n return useChannelResource(context => client.setup.connections(transport, context), [transport], true, false)\n}\n\nexport function useWhatsAppNumbers(connectionId: string) {\n const { client } = useChannelsContext()\n return useChannelResource(context => client.setup.whatsappNumbers(connectionId, context), [connectionId], !!connectionId, false)\n}\n\n/** Connect only acquires/binds a line. It never labels it verified or activates replies. */\nexport function useConnectChannel(onConnected?: (line: Line) => void) {\n const { client } = useChannelsContext()\n return useChannelMutation<ConnectChannelInput, Line>(async input => {\n if (input.kind === 'connection') {\n if (!input.input.connectionId.trim()) throw new Error('Choose a connection.')\n if (input.input.transport === 'whatsapp' && !input.input.phoneNumberId.trim()) throw new Error('Choose a WhatsApp number.')\n return client.lines.fromConnection(input.input)\n }\n if (input.kind === 'order') {\n if (!input.orderId.trim()) throw new Error('Choose a number order.')\n return client.setup.fromOrder(input.orderId)\n }\n const address = input.address.trim().toLowerCase()\n if (!input.connectionId.trim() || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(address)) throw new Error('Choose a connection and enter a valid mailbox address.')\n return client.setup.fromEmail({ connectionId: input.connectionId, address })\n }, onConnected)\n}\n\nexport function verificationExpired(test: ChannelVerification, now = Date.now()): boolean {\n return test.expired || (test.status !== 'verified' && test.expiresAt <= now)\n}\n\nexport type VerificationAction = 'start' | 'resume' | 'send' | 'activate' | 'reset'\n\nexport function useChannel(lineId: string) {\n const { client } = useChannelsContext()\n const resource = useChannelResource(async context => {\n const [line, verification] = await Promise.all([client.lines.get(lineId), client.setup.verification(lineId, context)])\n if (line.id !== lineId || (line.attachment && line.attachment.lineId !== lineId) || (verification && verification.lineId !== lineId)) throw new Error('Channel binding changed. Reload channel setup.')\n return { line, verification }\n }, [lineId], !!lineId)\n const mutation = useChannelMutation<{ action: VerificationAction; confirm?: boolean }, void>(async ({ action, confirm }) => {\n if (resource.status !== 'ready') throw new Error('Read the current channel state before changing it.')\n const { line, verification: test } = resource.value\n if (line.id !== lineId) throw new Error('Channel binding changed. Reload channel setup.')\n if (action !== 'reset' && line.status !== 'active') throw new Error('This line is not active.')\n if (action === 'start') {\n if (test && test.status !== 'revoked') throw new Error('Stop the existing test before starting another.')\n await client.setup.start(lineId)\n return\n }\n if (!test || test.lineId !== lineId) throw new Error('Start a channel test first.')\n if (action === 'reset') {\n if (confirm !== true) throw new Error('Confirm stopping this test.')\n await client.setup.reset(lineId, test.id)\n return\n }\n if (verificationExpired(test)) throw new Error('This test expired. Stop it and start a new test.')\n if (action === 'activate') {\n if (test.status !== 'verified') throw new Error('Verify inbound delivery and the test reply before activation.')\n const activated = await client.setup.activate(lineId, test.id)\n if (activated.id !== lineId || activated.status !== 'active' || activated.attachment?.status !== 'active' || activated.attachment.lineId !== lineId) throw new Error('Messaging activation was not confirmed.')\n } else if (action === 'send') {\n if (test.status !== 'received') throw new Error('Wait for the inbound test message before sending a reply.')\n await client.setup.send(lineId, test.id)\n } else {\n if (test.status !== 'configuring' && test.status !== 'uncertain') throw new Error('This test is not waiting for a setup check.')\n await client.setup.resume(lineId, test.id)\n }\n }, resource.retry)\n useEffect(() => mutation.reset(), [lineId, mutation.reset])\n return { resource, ...mutation }\n}\n\nexport function useChannelConversations(lineId: string) {\n const { client } = useChannelsContext()\n return useChannelResource(async () => {\n const threads = await client.lines.threads(lineId).list()\n if (threads.some(thread => thread.lineId !== lineId)) throw new Error('The thread response belongs to another line.')\n return threads\n }, [lineId], !!lineId)\n}\n\nexport function useChannelConversation(lineId: string, threadId: string) {\n const { client } = useChannelsContext()\n return useChannelResource(async () => {\n const messages = await client.lines.threads(lineId).messages(threadId)\n // The SDK returns newest first. Never mutate it, and never render another thread.\n if (messages.some(message => message.threadId !== threadId)) throw new Error('The message response belongs to another conversation.')\n return [...new Map(messages.map(message => [message.id, message])).values()]\n .sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id))\n }, [lineId, threadId], !!lineId && !!threadId)\n}\n","import { useEffect, useId, useState } from 'react'\nimport { useChannelsClient } from './context'\nimport { useChannel, useChannelConnections, useChannelConversation, useChannelConversations, useChannels, useConnectChannel, useWhatsAppNumbers, verificationExpired } from './hooks'\nimport { NUMBER_CHARGE_NOTICE, NUMBER_RETRY_NOTICE, numberStage, useNumberChannel } from './numbers'\nimport type { Line, LineTransport } from './types'\nimport { ChannelFailure, ChannelState, buttonClass, primaryButtonClass, inputClass, panelClass } from './ui'\n\nconst labels: Record<LineTransport, string> = { imessage: 'iMessage', whatsapp: 'WhatsApp', sms: 'SMS', email: 'Email' }\n\n/** User-facing deep links, not provider API calls. Invalid addresses render as text only. */\nexport function channelMessageLink(line: Line, instruction: string): string | null {\n if (line.transport === 'email') {\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(line.address)) return null\n return `mailto:${encodeURIComponent(line.address)}?subject=Channel%20test&body=${encodeURIComponent(instruction)}`\n }\n const address = line.routerAddress ?? line.address\n if (!/^\\+[1-9]\\d{7,14}$/.test(address)) return null\n if (line.transport === 'whatsapp') return `https://wa.me/${address.slice(1)}?text=${encodeURIComponent(instruction)}`\n return `sms:${address}?body=${encodeURIComponent(line.connect ?? instruction)}`\n}\n\nfunction CopyLine({ text }: { text: string }) {\n const [message, setMessage] = useState('')\n return <div className=\"space-y-2\"><div className=\"flex items-start gap-2 rounded-md bg-muted p-3\">\n <code className=\"min-w-0 flex-1 break-all\">{text}</code>\n <button type=\"button\" className={buttonClass} aria-label={`Copy ${text}`} onClick={async () => {\n try { await navigator.clipboard.writeText(text); setMessage('Copied') }\n catch { setMessage('Copy is unavailable. Select and copy the displayed text.') }\n }}>Copy</button>\n </div>{message && <p role=\"status\" className=\"text-sm\">{message}</p>}</div>\n}\n\n/** Delivery evidence comes exclusively from the host. An acquired line is not proof. */\nexport function ChannelVerificationPanel({ lineId, className = '' }: { lineId: string; className?: string }) {\n const channel = useChannel(lineId)\n const [confirming, setConfirming] = useState(false)\n useEffect(() => setConfirming(false), [lineId])\n const busy = channel.state.status === 'pending'\n const act = (action: 'start' | 'resume' | 'send' | 'activate') => void channel.run({ action })\n return <section className={`${panelClass} ${className}`} aria-label=\"Channel verification\" aria-busy={busy}>\n <h2 className=\"text-lg font-semibold\">Verify this channel</h2>\n <ChannelState resource={channel.resource} empty=\"The channel is unavailable.\">{({ line, verification: test }) => {\n const expired = test ? verificationExpired(test) : false\n const active = line.status === 'active' && line.attachment?.status === 'active'\n const link = test ? channelMessageLink(line, test.instruction) : null\n return <>\n <p className=\"break-all font-medium\">{labels[line.transport]} · {line.address}</p>\n {line.status !== 'active' ? <p role=\"alert\">This line is {line.status}. Check the line’s status before testing or activating it.</p>\n : active && test?.status === 'verified' && !expired ? <>\n <p role=\"status\">Both directions verified. Answering {labels[line.transport]} messages.</p>\n <p>{line.connect && line.routerAddress ? `Share this: send ${line.connect} to ${line.routerAddress}.` : 'Share this channel address so people can start a conversation.'}</p>\n <CopyLine text={line.connect ?? line.address} />\n </>\n : !test || test.status === 'revoked' ? <>\n {active && <p>Attached to an agent, but no completed delivery test was returned.</p>}\n <p>Test inbound delivery and a reply before this agent answers people.</p>\n <button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('start')}>Start channel test</button>\n </> : expired ? <p role=\"alert\">This test expired. Stop it before starting a new test.</p>\n : test.status === 'verified' ? <><p>Both directions verified. Messaging is not turned on yet.</p>\n <button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('activate')}>Turn on messaging</button></>\n : test.status === 'configuring' ? <><p>Connecting incoming messages to Tangle.</p>\n <button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('resume')}>Check setup</button></>\n : test.status === 'waiting' ? <>\n {line.connect && line.routerAddress && <><p>First, send this to {line.routerAddress}. The router replies with your agent’s number.</p><CopyLine text={line.connect} /></>}\n <p>{line.transport === 'email' ? `From another email address, send this line to ${line.address}.` : line.connect ? 'Then send this in the conversation the router opens:' : `From your phone, send this to ${line.address}:`}</p>\n <CopyLine text={test.instruction} />\n {link && <a className={primaryButtonClass} href={link} target={line.transport === 'whatsapp' ? '_blank' : undefined} rel=\"noopener noreferrer\">Open {line.transport === 'email' ? 'Email' : line.transport === 'whatsapp' ? 'WhatsApp' : 'Messages'}</a>}\n </> : test.status === 'received' ? <><p role=\"status\">Your test message arrived.</p><button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('send')}>Send test reply</button></>\n : test.status === 'sending' ? <p role=\"status\">The test reply is being sent. Do not send another.</p>\n : test.status === 'uncertain' ? <><p role=\"alert\">The reply result is uncertain. Check its status instead of sending another.</p><button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('resume')}>Check reply status</button></>\n : test.status === 'needs_review' ? <p role=\"alert\">Incoming message setup needs operator review. No delivery success is claimed.</p>\n : <p>Reply with the CONFIRM line in the message you received, in the same conversation.</p>}\n {test?.error && <p role=\"alert\" className=\"text-destructive\">{test.error}</p>}\n {test && test.status !== 'revoked' && !(active && test.status === 'verified' && !expired) && <>\n {!confirming ? <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setConfirming(true)}>Stop this test</button> : <fieldset className=\"space-y-2\"><legend>Stop this test and revoke its setup?</legend>\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={async () => { const outcome = await channel.run({ action: 'reset', confirm: true }); if (outcome.succeeded) setConfirming(false) }}>Confirm stop</button>{' '}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setConfirming(false)}>Keep testing</button>\n </fieldset>}\n </>}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={channel.resource.retry}>Refresh channel status</button>\n </>\n }}</ChannelState>\n <ChannelFailure state={channel.state} />\n </section>\n}\n\nfunction ConnectionPicker({ transport, onConnected }: { transport: Exclude<LineTransport, 'sms'>; onConnected: (line: Line) => void }) {\n const client = useChannelsClient()\n const connections = useChannelConnections(transport)\n const [connectionId, setConnectionId] = useState('')\n const [numberId, setNumberId] = useState('')\n const [address, setAddress] = useState('')\n const [showNumbers, setShowNumbers] = useState(false)\n const numbers = useWhatsAppNumbers(showNumbers ? connectionId : '')\n const connect = useConnectChannel(onConnected)\n const busy = connect.state.status === 'pending'\n useEffect(() => { setConnectionId(''); setNumberId(''); setShowNumbers(false); setAddress('') }, [client, transport])\n useEffect(() => {\n if (connections.status === 'ready' && connections.value.length === 1) setConnectionId(connections.value[0]!.id)\n }, [connections])\n useEffect(() => {\n if (numbers.status === 'ready' && numbers.value.length === 1) setNumberId(numbers.value[0]!.id)\n }, [numbers])\n return <>\n <ChannelState resource={connections} empty=\"No eligible Hub connections. Connect an identity in your app’s Integrations first.\">{items => <form className=\"space-y-4\" onSubmit={event => {\n event.preventDefault()\n if (transport === 'email') void connect.run({ kind: 'email', connectionId, address })\n else if (transport === 'whatsapp') void connect.run({ kind: 'connection', input: { transport, connectionId, phoneNumberId: numberId } })\n else void connect.run({ kind: 'connection', input: { transport, connectionId } })\n }}>\n <label className=\"block\">Connection<select className={inputClass} value={connectionId} disabled={busy} onChange={event => { setConnectionId(event.target.value); setNumberId(''); setShowNumbers(false) }} required>\n <option value=\"\">Choose a connection</option>{items.map(item => <option key={item.id} value={item.id}>{item.account ?? item.displayName}</option>)}\n </select></label>\n {transport === 'email' && <label className=\"block\">Mailbox address<input className={inputClass} type=\"email\" required value={address} disabled={busy} onChange={event => setAddress(event.target.value)} placeholder=\"hello@example.com\" /></label>}\n {transport === 'whatsapp' && <>\n <button type=\"button\" className={buttonClass} disabled={!connectionId || busy} onClick={() => { setShowNumbers(true); numbers.retry() }}>Show owned numbers</button>\n {showNumbers && <ChannelState resource={numbers} empty=\"This connection has no eligible WhatsApp numbers.\">{owned => <label className=\"block\">WhatsApp number<select className={inputClass} required value={numberId} disabled={busy} onChange={event => setNumberId(event.target.value)}>\n <option value=\"\">Choose a number</option>{owned.map(number => <option key={number.id} value={number.id}>{number.address}</option>)}\n </select></label>}</ChannelState>}\n </>}\n <p className=\"text-sm text-muted-foreground\">Connect an owned line, then test both directions. Each person must message first. Permissions remain managed in Tangle Hub.</p>\n <button type=\"submit\" className={primaryButtonClass} disabled={busy || !connectionId || (transport === 'email' && !address.trim()) || (transport === 'whatsapp' && (!numberId || !showNumbers || numbers.status !== 'ready'))}>{busy ? 'Connecting…' : 'Connect channel'}</button>\n </form>}</ChannelState>\n <ChannelFailure state={connect.state} />\n </>\n}\n\nexport interface ChannelConnectProps { transport: LineTransport; initialLineId?: string; className?: string }\n\n/** Select an existing line or connect an owned source, then verify it. */\nexport function ChannelConnect({ transport, initialLineId = '', className = '' }: ChannelConnectProps) {\n const [selected, setSelected] = useState(initialLineId)\n const lines = useChannels()\n const id = useId()\n useEffect(() => setSelected(initialLineId), [transport, initialLineId])\n return <div className={`space-y-4 ${className}`}>\n <section className={panelClass} aria-label={`${labels[transport]} channel`}>\n <h2 className=\"text-lg font-semibold\">Connect {labels[transport]}</h2>\n {transport === 'imessage' && <p>Use a free shared iMessage identity, or acquire a dedicated number. A shared identity requires a connect message to the router first.</p>}\n <ChannelState resource={lines} empty=\"No lines connected to this agent yet.\">{all => {\n const matching = all.filter(line => line.transport === transport && line.status !== 'released')\n return matching.length ? <><label htmlFor={id}>Existing line</label><select id={id} className={inputClass} value={selected} onChange={event => setSelected(event.target.value)}>\n <option value=\"\">Choose or connect a line</option>{matching.map(line => <option value={line.id} key={line.id}>{line.label ?? line.address}</option>)}\n </select></> : <p>No {labels[transport]} lines connected yet.</p>\n }}</ChannelState>\n {!selected && transport !== 'sms' && <ConnectionPicker key={transport} transport={transport} onConnected={line => { setSelected(line.id); lines.retry() }} />}\n {selected && <button type=\"button\" className={buttonClass} onClick={() => setSelected('')}>Choose another line</button>}\n </section>\n {selected ? <ChannelVerificationPanel key={selected} lineId={selected} /> : (transport === 'sms' || transport === 'imessage') && <NumberChannel transport={transport} />}\n </div>\n}\n\ntype TransportPanelProps = Omit<ChannelConnectProps, 'transport'>\nexport function IMessageChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"imessage\" /> }\nexport function WhatsAppChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"whatsapp\" /> }\nexport function EmailChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"email\" /> }\nexport function SMSChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"sms\" /> }\n\n/** A transport's managed number activation, with explicit consent and cancellation. */\nexport function NumberChannel({ transport, className = '' }: { transport: 'sms' | 'imessage'; className?: string }) {\n const client = useChannelsClient()\n const number = useNumberChannel(transport)\n const [consent, setConsent] = useState(false)\n const [cancelId, setCancelId] = useState<string | null>(null)\n const [lineId, setLineId] = useState('')\n const connect = useConnectChannel(line => setLineId(line.id))\n useEffect(() => { setConsent(false) }, [number.quote?.token])\n useEffect(() => { setCancelId(null); setLineId(''); connect.reset() }, [transport, client, connect.reset])\n const busy = number.state.status === 'pending' || connect.state.status === 'pending'\n const money = (cents: number) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(cents / 100)\n return <section className={`${panelClass} ${className}`} aria-label={`${labels[transport]} number`} aria-busy={busy}>\n <h2 className=\"text-lg font-semibold\">Get a {labels[transport]} number</h2>\n {!client.ordering ? <p>Number ordering is unavailable. Existing numbers are unchanged.</p> : <ChannelState resource={number.resource} empty=\"Number availability has not been confirmed.\">{({ readiness, complete }) => <>\n {!readiness.configured && <p>New orders are disabled. Existing numbers still require separate cancellation.</p>}\n {!complete && <p role=\"alert\">The order list is incomplete. New purchases are disabled until ownership can be confirmed.</p>}\n {number.held && <p>This agent already holds an order for this transport. Cancel and release it before ordering another.</p>}\n <button type=\"button\" className={primaryButtonClass} disabled={busy || !complete || !readiness.configured || !readiness.transports.includes(transport) || !!number.held || number.uncertain} onClick={() => void number.run({ action: 'quote' })}>See activation price</button>\n </>}</ChannelState>}\n {number.quote && <div className=\"space-y-3 rounded-md border border-border p-4\">\n <h3 className=\"font-medium\">Activation · {money(number.quote.activationCents)}</h3>\n <p className=\"whitespace-pre-wrap\">{number.quote.terms || 'Published activation terms are missing. Ordering is disabled.'}</p>\n <p>{NUMBER_CHARGE_NOTICE}</p>\n <label className=\"flex items-start gap-2\"><input type=\"checkbox\" checked={consent} disabled={busy} onChange={event => setConsent(event.target.checked)} />I authorize this one-time activation charge. The number is not live until channel setup is complete.</label>\n {!number.uncertain && number.quote.expiresAt <= Date.now() && <p role=\"alert\">This quote expired. Read a new activation price before ordering.</p>}\n <button type=\"button\" className={primaryButtonClass} disabled={busy || !consent || !number.quote.terms.trim() || (!number.uncertain && number.quote.expiresAt <= Date.now())} onClick={() => void number.run({ action: 'purchase', consent })}>{number.uncertain ? 'Retry approved purchase' : `Order for ${money(number.quote.activationCents)}`}</button>\n </div>}\n {number.uncertain && <p role=\"alert\">The purchase response was lost or refused. Its outcome is not confirmed. {NUMBER_RETRY_NOTICE}</p>}\n {number.orders.map(order => <article key={order.id} className=\"space-y-3 rounded-md border border-border p-4\">\n <h3 className=\"break-all font-medium\">{order.address ?? 'Your number order'}</h3><p>{numberStage(order)}</p>\n {order.errorCode && <p role=\"status\">Status: {order.errorCode.replace(/_/g, ' ')}</p>}\n {order.status === 'ready_for_setup' && order.cancellation === 'none' && <><p>The number is acquired, not delivery-verified. Test it before connecting conversations.</p>\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => void connect.run({ kind: 'order', orderId: order.id })}>Test this number</button></>}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => void number.run({ action: 'advance', orderId: order.id })}>Check progress</button>{' '}\n {order.cancellation === 'none' && (cancelId !== order.id ? <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setCancelId(order.id)}>Cancel number</button> : <fieldset className=\"space-y-2\"><legend>Cancel this number? Access will be removed. Paid activation is not automatically refunded.</legend>\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={async () => { const result = await number.run({ action: 'cancel', orderId: order.id, confirm: true }); if (result.succeeded) setCancelId(null) }}>Confirm cancellation</button>{' '}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setCancelId(null)}>Keep number</button>\n </fieldset>)}\n </article>)}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={number.resource.retry}>Refresh number status</button>\n <p className=\"text-sm text-muted-foreground\">SMS and iMessage are separate activations. Buying a number does not enable WhatsApp.</p>\n <ChannelFailure state={number.state} /><ChannelFailure state={connect.state} />\n {lineId && <ChannelVerificationPanel lineId={lineId} key={lineId} />}\n </section>\n}\n\n/** Read-only history. Messages stay on their original channel; no synthetic composer. */\nexport function ChannelConversation({ lineId, threadId, className = '' }: { lineId: string; threadId: string; className?: string }) {\n const messages = useChannelConversation(lineId, threadId)\n return <section className={`${panelClass} ${className}`} aria-label=\"Channel conversation\">\n <h3 className=\"font-semibold\">Conversation</h3>\n <ChannelState resource={messages} empty=\"No messages in this conversation yet.\">{items => <ol role=\"log\" aria-live=\"polite\" aria-label=\"Messages\" className=\"space-y-3\">\n {items.map(message => <li key={message.id} className=\"space-y-1 rounded-md bg-muted p-3\" data-direction={message.direction}>\n <p className=\"text-xs text-muted-foreground\">{message.direction === 'in' ? 'Incoming' : 'Outgoing'} · {message.kind} · <time dateTime={message.createdAt}>{message.createdAt}</time></p>\n <p className=\"whitespace-pre-wrap break-words\">{message.text ?? 'Non-text message'}</p>\n <p className=\"text-xs\">{message.status}{message.errorCode ? ` · ${message.errorCode}` : ''}</p>\n </li>)}\n </ol>}</ChannelState>\n <button type=\"button\" className={buttonClass} onClick={messages.retry}>Refresh messages</button>\n </section>\n}\n\n/** A channel's separate member threads. Changing line never reuses another line's selection. */\nexport function ChannelConversations({ lineId, className = '' }: { lineId: string; className?: string }) {\n const threads = useChannelConversations(lineId)\n const [selected, setSelected] = useState<{ lineId: string; threadId: string } | null>(null)\n const threadId = selected?.lineId === lineId ? selected.threadId : ''\n return <div className={`space-y-4 ${className}`}>\n <section className={panelClass} aria-label=\"Channel conversations\"><h2 className=\"text-lg font-semibold\">Conversations</h2>\n <ChannelState resource={threads} empty=\"No conversations yet. Members must message the line first.\">{items => <nav aria-label=\"Choose a conversation\" className=\"flex flex-wrap gap-2\">\n {items.map(thread => <button type=\"button\" key={thread.id} className={buttonClass} aria-pressed={thread.id === threadId} onClick={() => setSelected({ lineId, threadId: thread.id })}>{thread.memberId} · {thread.status}</button>)}\n </nav>}</ChannelState>\n </section>\n {threadId && <ChannelConversation key={`${lineId}:${threadId}`} lineId={lineId} threadId={threadId} />}\n </div>\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { HubNumberOrder, HubNumberQuote } from '@tangle-network/hub-sdk'\nimport { useChannelsContext } from './context'\nimport { useChannelMutation, useChannelResource } from './hooks'\n\nexport const NUMBER_CHARGE_NOTICE = 'This is a one-time activation charge. Tangle does not bill recurring carrier rental for this number. Your provider’s message rates are separate.'\nexport const NUMBER_RETRY_NOTICE = 'Retry uses the same approved quote, not a new purchase. Do not order again while the result is unknown.'\n\nexport function holdsNumber(order: HubNumberOrder): boolean {\n return order.cancellation !== 'released' && order.cancellation !== 'abandoned'\n}\n\nexport function numberStage(order: HubNumberOrder): string {\n if (order.cancellation === 'released' || order.cancellation === 'abandoned') return 'Released'\n if (order.cancellation === 'needs_review') return 'Release needs review'\n if (order.cancellation === 'requested' || order.status === 'cancelled') return 'Cancelling'\n if (order.status === 'needs_review') return 'Needs operator review'\n if (order.status === 'ready_for_setup') return 'Number acquired — channel setup next'\n if (order.errorCode === 'funding_required') return 'Add funds to continue'\n if (order.errorCode === 'sms_not_ready') return 'Waiting for SMS activation'\n return 'Provisioning'\n}\n\n/** Hub owns prices, terms, idempotency, funding, and cancellation. */\nexport function useNumberChannel(transport: 'sms' | 'imessage') {\n const { client } = useChannelsContext()\n const ordering = client.ordering\n const reference = ordering?.references[transport]\n const [quote, setQuote] = useState<HubNumberQuote | null>(null)\n const [receipts, setReceipts] = useState<HubNumberOrder[]>([])\n const [uncertain, setUncertain] = useState(false)\n // Set synchronously at dispatch, before React renders another click.\n const attempted = useRef(false)\n const resource = useChannelResource(async ({ signal }) => {\n if (!ordering || !reference) throw new Error('Number ordering is unavailable.')\n const readiness = await ordering.numbers.readiness()\n const orders: HubNumberOrder[] = []\n const seen = new Set<string>()\n let cursor: string | undefined\n let complete = false\n do {\n if (signal.aborted) throw new Error('Number read was superseded.')\n const page = await ordering.numbers.list({ clientReference: reference, cursor, limit: 100 })\n if (page.orders.some(order => order.clientReference !== reference || order.transport !== transport)) throw new Error('The number list belongs to another binding.')\n orders.push(...page.orders)\n if (page.nextCursor == null) {\n // Older Hub responses omit cursor metadata. An incomplete page cannot\n // establish that this agent has no order, even when the page is empty.\n complete = page.nextCursor === null\n break\n }\n if (seen.has(page.nextCursor) || seen.size >= 100) throw new Error('The number list could not be read completely.')\n seen.add(page.nextCursor)\n cursor = page.nextCursor\n } while (cursor)\n return { readiness, orders, complete }\n }, [ordering, reference, transport], !!ordering)\n const loaded = resource.status === 'ready' ? resource.value : null\n const orders = [...new Map([...(loaded?.orders ?? []), ...receipts].map(order => [order.id, order])).values()]\n const held = orders.find(holdsNumber) ?? null\n\n const mutation = useChannelMutation<\n | { action: 'quote' }\n | { action: 'purchase'; consent: boolean }\n | { action: 'advance'; orderId: string }\n | { action: 'cancel'; orderId: string; confirm: boolean }, void\n >(async (input, { signal }) => {\n if (!ordering || !reference) throw new Error('Number ordering is unavailable.')\n if (input.action === 'quote') {\n if (attempted.current) throw new Error('The previous purchase is unresolved. Retry its approved quote or check progress.')\n if (!loaded?.complete || !loaded.readiness.configured || !loaded.readiness.transports.includes(transport)) throw new Error('Number availability and existing orders must be confirmed first.')\n if (held) throw new Error('This agent already holds a number order for this transport.')\n const { quote: next } = await ordering.numbers.quote({ transport, clientReference: reference })\n if (next.transport !== transport || (next.clientReference !== undefined && next.clientReference !== reference)) throw new Error('The quote belongs to another binding.')\n if (!signal.aborted) setQuote(next)\n return\n }\n if (input.action === 'purchase') {\n if (!quote || !input.consent) throw new Error('Approve the quoted activation charge before ordering.')\n if (!quote.terms.trim() || !Number.isSafeInteger(quote.activationCents) || quote.activationCents < 0 || !quote.token) throw new Error('A valid price and published activation terms are required.')\n if (held) throw new Error('This agent already holds a number order for this transport.')\n if (!attempted.current && (!loaded?.complete || !loaded.readiness.configured || quote.expiresAt <= Date.now())) throw new Error('The quote or order information expired. Read the current state first.')\n attempted.current = true\n try {\n const { order } = await ordering.numbers.create({ quoteToken: quote.token, consent: true, clientReference: reference, transport })\n if (order.clientReference !== reference || order.transport !== transport) throw new Error('The purchase response belongs to another binding. Check progress before ordering again.')\n if (!signal.aborted) {\n // Preserve the acknowledged order before a follow-up read can fail.\n setReceipts(current => [order, ...current.filter(item => item.id !== order.id)])\n setQuote(null)\n setUncertain(false)\n }\n } catch (error) {\n if (!signal.aborted) setUncertain(true)\n throw error\n } finally {\n if (!signal.aborted) resource.retry()\n }\n return\n }\n if (!orders.some(order => order.id === input.orderId)) throw new Error('Read this number order before changing it.')\n if (input.action === 'cancel' && !input.confirm) throw new Error('Confirm cancelling this number.')\n const { order } = await ordering.numbers[input.action](input.orderId)\n if (order.id !== input.orderId || order.clientReference !== reference || order.transport !== transport) throw new Error('The number response belongs to another binding.')\n if (!signal.aborted) {\n setReceipts(current => [order, ...current.filter(item => item.id !== order.id)])\n resource.retry()\n }\n })\n useEffect(() => {\n setQuote(null); setReceipts([]); setUncertain(false); attempted.current = false\n mutation.reset()\n }, [client, client.scope, transport, reference, mutation.reset])\n useEffect(() => {\n if (loaded) setReceipts(current => current.filter(receipt => !loaded.orders.some(order => order.id === receipt.id)))\n if (loaded?.orders.some(holdsNumber)) {\n setQuote(null); setUncertain(false); attempted.current = false\n } else if (!uncertain && !quote && loaded?.complete && orders.length > 0 && orders.every(order => !holdsNumber(order))) {\n attempted.current = false\n }\n }, [loaded])\n return { resource, orders, held, quote, uncertain, ...mutation }\n}\n","import type { ReactNode } from 'react'\nimport { AsyncView, MutationStatus, type AsyncResourceState, type MutationState } from '../web-react/async'\n\nexport const panelClass = 'space-y-4 rounded-xl border border-border bg-card p-6 text-foreground'\nexport const buttonClass = 'inline-flex items-center justify-center rounded-md border border-border px-3 py-2 text-sm font-medium transition hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-50'\nexport const primaryButtonClass = `${buttonClass} border-primary bg-primary text-primary-foreground hover:bg-primary/90`\nexport const inputClass = 'block w-full rounded-md border border-input bg-background px-3 py-2 text-foreground focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring'\n\nexport function ChannelFailure({ state }: { state: MutationState<unknown> }) {\n return state.status === 'failed' ? <MutationStatus state={state} className=\"text-sm text-destructive\" /> : null\n}\n\n/** Channel copy around the shared async view, not a second state renderer. */\nexport function ChannelState<T>({ resource, children, empty }: { resource: AsyncResourceState<T>; children: (value: T) => ReactNode; empty: string }) {\n return <AsyncView state={resource} empty={{ title: empty, action: { label: 'Refresh', onClick: resource.retry } }}\n loadingLabel=\"Loading channel…\" retryLabel=\"Try again\"\n renderIdle={() => <p className=\"text-sm text-muted-foreground\">Choose a channel to continue.</p>}>\n {children}\n </AsyncView>\n}\n","import { useEffect, useState } from 'react'\nimport { useChannelsContext } from './context'\nimport { useChannelMutation, useChannelResource } from './hooks'\nimport { ChannelState, ChannelFailure, buttonClass, primaryButtonClass, panelClass } from './ui'\n\n/** Only same-origin relative paths or credential-free HTTPS checkout URLs. */\nexport function safeCheckoutUrl(value: string): string {\n if (/^\\/(?!\\/)/.test(value) && !/[\\\\\\s]/.test(value)) return value\n const url = new URL(value)\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error('Checkout returned an unsafe URL.')\n return url.href\n}\n\nexport function useLinePayment(lineId: string) {\n const { client } = useChannelsContext()\n const resource = useChannelResource(context => {\n if (!client.payment) throw new Error('Payments are unavailable for this line.')\n return client.payment.read(lineId, context)\n }, [lineId], !!lineId && !!client.payment)\n const mutation = useChannelMutation<{ consent: boolean }, string>(async ({ consent }) => {\n if (!client.payment || resource.status !== 'ready') throw new Error('Read the current allowance before checkout.')\n const { plan, allowance, terms } = resource.value\n if (!consent || !terms.trim()) throw new Error('Accept the published terms before checkout.')\n if (!plan.configured || !plan.paid || !Number.isFinite(plan.paid.priceUsdMonthly) || plan.paid.priceUsdMonthly <= 0 || allowance.decision !== 'paywall' || !allowance.paywall || allowance.tier !== 'free') throw new Error('Checkout is not available for this allowance.')\n return safeCheckoutUrl((await client.payment.checkout(lineId)).url)\n })\n useEffect(() => mutation.reset(), [lineId, mutation.reset])\n return { resource, ...mutation, available: !!client.payment }\n}\n\n/** End-user allowance/checkout page, not number acquisition or creator payouts. */\nexport function LinePayPage({ lineId, className = '' }: { lineId: string; className?: string }) {\n const payment = useLinePayment(lineId)\n const [consentedTerms, setConsentedTerms] = useState<string | null>(null)\n const currentTerms = payment.resource.status === 'ready'\n ? JSON.stringify([lineId, payment.resource.value.terms, payment.resource.value.plan.paid])\n : null\n const consent = currentTerms !== null && consentedTerms === currentTerms\n return <section className={`${panelClass} ${className}`} aria-label=\"Line subscription\">\n <h2 className=\"text-lg font-semibold\">Your line plan</h2>\n {!payment.available ? <p>Payments are unavailable for this line.</p> : <ChannelState resource={payment.resource} empty=\"No plan is available.\">{value => <>\n <h3 className=\"font-medium\">{value.label}</h3>\n <p>{value.allowance.turns.used} of {value.allowance.turns.limit} turns used today.</p>\n {value.allowance.tier === 'paid' ? <p role=\"status\">Your paid allowance is active.{value.allowance.decision === 'allowance_reached' ? ' Its current limit is exhausted; another checkout cannot lift it.' : ''}</p> : value.allowance.decision === 'paywall' && value.plan.paid ? <>\n <p>{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value.plan.paid.priceUsdMonthly)} per month · {value.plan.paid.turnsPerDay} turns per day.</p>\n <p className=\"whitespace-pre-wrap\">{value.terms || 'Plan terms are unavailable. Checkout is disabled.'}</p>\n <label className=\"flex items-start gap-2\"><input type=\"checkbox\" checked={consent} onChange={event => setConsentedTerms(event.target.checked ? currentTerms : null)} />I accept these subscription terms.</label>\n <button type=\"button\" className={primaryButtonClass} disabled={!consent || !value.terms.trim() || payment.state.status === 'pending'} onClick={() => void payment.run({ consent })}>Continue to checkout</button>\n <p className=\"text-sm text-muted-foreground\">Payment is confirmed by the server after settlement, not by returning to this page.</p>\n </> : <p>{value.allowance.decision === 'allowance_reached' ? 'Your allowance is exhausted. Paying does not lift this limit today.' : 'Your current allowance is available.'} Resets at {value.allowance.resetsAt}.</p>}\n <button type=\"button\" className={buttonClass} onClick={payment.resource.retry}>Check payment status</button>\n </>}</ChannelState>}\n {payment.state.status === 'succeeded' && consent && <a className=\"underline\" href={payment.state.value} rel=\"noopener noreferrer\">Open secure checkout</a>}\n <ChannelFailure state={payment.state} />\n </section>\n}\n"],"mappings":"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","names":["useEffect","useState","useEffect","useRef","useRef","orders","order","useEffect","jsx","jsx","useState","useEffect","useEffect","useState","Fragment","jsx","jsxs","useEffect","useState"]}
1
+ {"version":3,"sources":["../../src/channels/context.tsx","../../src/channels/hooks.ts","../../src/channels/components.tsx","../../src/channels/numbers.ts","../../src/channels/ui.tsx","../../src/channels/payment.tsx"],"sourcesContent":["import { createContext, useContext, type ReactNode } from 'react'\nimport type { ChannelsClient, ChannelsReadClient } from './types'\n\nconst Context = createContext<{ client: ChannelsReadClient; pollInterval: number | false } | null>(null)\n\n/** Mount below authentication. Changing scope remounts all channel state. */\nexport function ChannelsProvider({ client, pollInterval = 3000, children }: {\n client: ChannelsReadClient\n /** Poll after a read settles, never concurrently. false disables polling. */\n pollInterval?: number | false\n children: ReactNode\n}) {\n if (pollInterval !== false && (!Number.isFinite(pollInterval) || pollInterval < 100)) {\n throw new Error('ChannelsProvider pollInterval must be false or at least 100 ms.')\n }\n return <Context.Provider value={{ client, pollInterval }} key={client.scope}>{children}</Context.Provider>\n}\n\n/** Management hooks keep the existing full-client contract; read views never call this. */\nexport function useChannelsClient(): ChannelsClient {\n const { client } = useChannelsContext()\n if (!('setup' in client) || !client.setup || !('fromConnection' in client.lines) || typeof client.lines.fromConnection !== 'function') {\n throw new Error('Channel setup requires a management client.')\n }\n return client as ChannelsClient\n}\n\nexport function useChannelsContext() {\n const value = useContext(Context)\n if (!value) throw new Error('Channel components and hooks require ChannelsProvider.')\n return value\n}\n","import { useCallback, useEffect, useRef } from 'react'\nimport { confirmWrite, rejectWrite, useAsyncResource, useConfirmedMutation } from '../web-react/async'\nimport type { AsyncLoadContext, AsyncResourceState, MutationOutcome } from '../web-react/async'\nimport { useChannelsClient, useChannelsContext } from './context'\nimport type { ChannelVerification, ConnectChannelInput, Line, LineTransport } from './types'\n\n/** Reuse the kit's abort/sequence-aware read machine; polling never overlaps a read. */\nexport function useChannelResource<T>(load: (context: AsyncLoadContext) => Promise<T>, deps: readonly unknown[], enabled = true, poll = true): AsyncResourceState<T> {\n const { client, pollInterval } = useChannelsContext()\n const resource = useAsyncResource({ load, deps: [client, client.scope, ...deps], enabled })\n useEffect(() => {\n if (!enabled || !poll || pollInterval === false || resource.status === 'loading' || resource.status === 'idle') return\n const delay = typeof document !== 'undefined' && document.hidden ? Math.max(15000, pollInterval) : pollInterval\n const timer = setTimeout(resource.retry, delay)\n return () => clearTimeout(timer)\n }, [enabled, poll, pollInterval, resource.status, resource.retry, resource])\n return enabled ? resource : { status: 'idle', retry: resource.retry }\n}\n\n/** Single-flight on top of the shared confirmed-write primitive. */\nexport function useChannelMutation<I, O>(mutate: (input: I, context: AsyncLoadContext) => Promise<O>, onSucceeded?: (value: O) => void) {\n const { client } = useChannelsContext()\n const lock = useRef<object | null>(null)\n const mutation = useConfirmedMutation<I, O>({\n mutate: async (input, context) => confirmWrite(await mutate(input, context)),\n onSucceeded,\n })\n const { reset, run } = mutation\n useEffect(() => {\n reset()\n return () => { lock.current = null; reset() }\n }, [client, client.scope, reset])\n const singleRun = useCallback(async (input: I): Promise<MutationOutcome<O>> => {\n if (lock.current) return rejectWrite('Another channel operation is still in progress.')\n const token = {}\n lock.current = token\n try { return await run(input) }\n finally { if (lock.current === token) lock.current = null }\n }, [run])\n return { ...mutation, run: singleRun }\n}\n\nexport function useChannels() {\n const { client } = useChannelsContext()\n return useChannelResource(() => client.lines.list(), [])\n}\n\nexport function useChannelConnections(transport: LineTransport) {\n const client = useChannelsClient()\n return useChannelResource(context => client.setup.connections(transport, context), [transport], true, false)\n}\n\nexport function useWhatsAppNumbers(connectionId: string) {\n const client = useChannelsClient()\n return useChannelResource(context => client.setup.whatsappNumbers(connectionId, context), [connectionId], !!connectionId, false)\n}\n\n/** Connect only acquires/binds a line. It never labels it verified or activates replies. */\nexport function useConnectChannel(onConnected?: (line: Line) => void) {\n const client = useChannelsClient()\n return useChannelMutation<ConnectChannelInput, Line>(async input => {\n if (input.kind === 'connection') {\n if (!input.input.connectionId.trim()) throw new Error('Choose a connection.')\n if (input.input.transport === 'whatsapp' && !input.input.phoneNumberId.trim()) throw new Error('Choose a WhatsApp number.')\n return client.lines.fromConnection(input.input)\n }\n if (input.kind === 'order') {\n if (!input.orderId.trim()) throw new Error('Choose a number order.')\n return client.setup.fromOrder(input.orderId)\n }\n const address = input.address.trim().toLowerCase()\n if (!input.connectionId.trim() || !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(address)) throw new Error('Choose a connection and enter a valid mailbox address.')\n return client.setup.fromEmail({ connectionId: input.connectionId, address })\n }, onConnected)\n}\n\nexport function verificationExpired(test: ChannelVerification, now = Date.now()): boolean {\n return test.expired || (test.status !== 'verified' && test.expiresAt <= now)\n}\n\nexport type VerificationAction = 'start' | 'resume' | 'send' | 'activate' | 'reset'\n\nexport function useChannel(lineId: string) {\n const client = useChannelsClient()\n const resource = useChannelResource(async context => {\n const [line, verification] = await Promise.all([client.lines.get(lineId), client.setup.verification(lineId, context)])\n if (line.id !== lineId || (line.attachment && line.attachment.lineId !== lineId) || (verification && verification.lineId !== lineId)) throw new Error('Channel binding changed. Reload channel setup.')\n return { line, verification }\n }, [lineId], !!lineId)\n const mutation = useChannelMutation<{ action: VerificationAction; confirm?: boolean }, void>(async ({ action, confirm }) => {\n if (resource.status !== 'ready') throw new Error('Read the current channel state before changing it.')\n const { line, verification: test } = resource.value\n if (line.id !== lineId) throw new Error('Channel binding changed. Reload channel setup.')\n if (action !== 'reset' && line.status !== 'active') throw new Error('This line is not active.')\n if (action === 'start') {\n if (test && test.status !== 'revoked') throw new Error('Stop the existing test before starting another.')\n await client.setup.start(lineId)\n return\n }\n if (!test || test.lineId !== lineId) throw new Error('Start a channel test first.')\n if (action === 'reset') {\n if (confirm !== true) throw new Error('Confirm stopping this test.')\n await client.setup.reset(lineId, test.id)\n return\n }\n if (verificationExpired(test)) throw new Error('This test expired. Stop it and start a new test.')\n if (action === 'activate') {\n if (test.status !== 'verified') throw new Error('Verify inbound delivery and the test reply before activation.')\n const activated = await client.setup.activate(lineId, test.id)\n if (activated.id !== lineId || activated.status !== 'active' || activated.attachment?.status !== 'active' || activated.attachment.lineId !== lineId) throw new Error('Messaging activation was not confirmed.')\n } else if (action === 'send') {\n if (test.status !== 'received') throw new Error('Wait for the inbound test message before sending a reply.')\n await client.setup.send(lineId, test.id)\n } else {\n if (test.status !== 'configuring' && test.status !== 'uncertain') throw new Error('This test is not waiting for a setup check.')\n await client.setup.resume(lineId, test.id)\n }\n }, resource.retry)\n useEffect(() => mutation.reset(), [lineId, mutation.reset])\n return { resource, ...mutation }\n}\n\nexport function useChannelConversations(lineId: string) {\n const { client } = useChannelsContext()\n return useChannelResource(async () => {\n const threads = await client.lines.threads(lineId).list()\n if (threads.some(thread => thread.lineId !== lineId)) throw new Error('The thread response belongs to another line.')\n return threads\n }, [lineId], !!lineId)\n}\n\nexport function useChannelConversation(lineId: string, threadId: string) {\n const { client } = useChannelsContext()\n return useChannelResource(async () => {\n const messages = await client.lines.threads(lineId).messages(threadId)\n // The SDK returns newest first. Never mutate it, and never render another thread.\n if (messages.some(message => message.threadId !== threadId)) throw new Error('The message response belongs to another conversation.')\n return [...new Map(messages.map(message => [message.id, message])).values()]\n .sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id))\n }, [lineId, threadId], !!lineId && !!threadId)\n}\n","import { useEffect, useId, useState } from 'react'\nimport { useChannelsClient } from './context'\nimport { useChannel, useChannelConnections, useChannelConversation, useChannelConversations, useChannels, useConnectChannel, useWhatsAppNumbers, verificationExpired } from './hooks'\nimport { NUMBER_CHARGE_NOTICE, NUMBER_RETRY_NOTICE, numberStage, useNumberChannel } from './numbers'\nimport type { Line, LineTransport } from './types'\nimport { ChannelFailure, ChannelState, buttonClass, primaryButtonClass, inputClass, panelClass } from './ui'\n\nconst labels: Record<LineTransport, string> = { imessage: 'iMessage', whatsapp: 'WhatsApp', sms: 'SMS', email: 'Email' }\n\n/** User-facing deep links, not provider API calls. Invalid addresses render as text only. */\nexport function channelMessageLink(line: Line, instruction: string): string | null {\n if (line.transport === 'email') {\n if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(line.address)) return null\n return `mailto:${encodeURIComponent(line.address)}?subject=Channel%20test&body=${encodeURIComponent(instruction)}`\n }\n const address = line.routerAddress ?? line.address\n if (!/^\\+[1-9]\\d{7,14}$/.test(address)) return null\n if (line.transport === 'whatsapp') return `https://wa.me/${address.slice(1)}?text=${encodeURIComponent(instruction)}`\n return `sms:${address}?body=${encodeURIComponent(line.connect ?? instruction)}`\n}\n\nfunction CopyLine({ text }: { text: string }) {\n const [message, setMessage] = useState('')\n return <div className=\"space-y-2\"><div className=\"flex items-start gap-2 rounded-md bg-muted p-3\">\n <code className=\"min-w-0 flex-1 break-all\">{text}</code>\n <button type=\"button\" className={buttonClass} aria-label={`Copy ${text}`} onClick={async () => {\n try { await navigator.clipboard.writeText(text); setMessage('Copied') }\n catch { setMessage('Copy is unavailable. Select and copy the displayed text.') }\n }}>Copy</button>\n </div>{message && <p role=\"status\" className=\"text-sm\">{message}</p>}</div>\n}\n\n/** Delivery evidence comes exclusively from the host. An acquired line is not proof. */\nexport function ChannelVerificationPanel({ lineId, className = '' }: { lineId: string; className?: string }) {\n const channel = useChannel(lineId)\n const [confirming, setConfirming] = useState(false)\n useEffect(() => setConfirming(false), [lineId])\n const busy = channel.state.status === 'pending'\n const act = (action: 'start' | 'resume' | 'send' | 'activate') => void channel.run({ action })\n return <section className={`${panelClass} ${className}`} aria-label=\"Channel verification\" aria-busy={busy}>\n <h2 className=\"text-lg font-semibold\">Verify this channel</h2>\n <ChannelState resource={channel.resource} empty=\"The channel is unavailable.\">{({ line, verification: test }) => {\n const expired = test ? verificationExpired(test) : false\n const active = line.status === 'active' && line.attachment?.status === 'active'\n const link = test ? channelMessageLink(line, test.instruction) : null\n return <>\n <p className=\"break-all font-medium\">{labels[line.transport]} · {line.address}</p>\n {line.status !== 'active' ? <p role=\"alert\">This line is {line.status}. Check the line’s status before testing or activating it.</p>\n : active && test?.status === 'verified' && !expired ? <>\n <p role=\"status\">Both directions verified. Answering {labels[line.transport]} messages.</p>\n <p>{line.connect && line.routerAddress ? `Share this: send ${line.connect} to ${line.routerAddress}.` : 'Share this channel address so people can start a conversation.'}</p>\n <CopyLine text={line.connect ?? line.address} />\n </>\n : !test || test.status === 'revoked' ? <>\n {active && <p>Attached to an agent, but no completed delivery test was returned.</p>}\n <p>Test inbound delivery and a reply before this agent answers people.</p>\n <button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('start')}>Start channel test</button>\n </> : expired ? <p role=\"alert\">This test expired. Stop it before starting a new test.</p>\n : test.status === 'verified' ? <><p>Both directions verified. Messaging is not turned on yet.</p>\n <button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('activate')}>Turn on messaging</button></>\n : test.status === 'configuring' ? <><p>Connecting incoming messages to Tangle.</p>\n <button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('resume')}>Check setup</button></>\n : test.status === 'waiting' ? <>\n {line.connect && line.routerAddress && <><p>First, send this to {line.routerAddress}. The router replies with your agent’s number.</p><CopyLine text={line.connect} /></>}\n <p>{line.transport === 'email' ? `From another email address, send this line to ${line.address}.` : line.connect ? 'Then send this in the conversation the router opens:' : `From your phone, send this to ${line.address}:`}</p>\n <CopyLine text={test.instruction} />\n {link && <a className={primaryButtonClass} href={link} target={line.transport === 'whatsapp' ? '_blank' : undefined} rel=\"noopener noreferrer\">Open {line.transport === 'email' ? 'Email' : line.transport === 'whatsapp' ? 'WhatsApp' : 'Messages'}</a>}\n </> : test.status === 'received' ? <><p role=\"status\">Your test message arrived.</p><button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('send')}>Send test reply</button></>\n : test.status === 'sending' ? <p role=\"status\">The test reply is being sent. Do not send another.</p>\n : test.status === 'uncertain' ? <><p role=\"alert\">The reply result is uncertain. Check its status instead of sending another.</p><button type=\"button\" className={primaryButtonClass} disabled={busy} onClick={() => act('resume')}>Check reply status</button></>\n : test.status === 'needs_review' ? <p role=\"alert\">Incoming message setup needs operator review. No delivery success is claimed.</p>\n : <p>Reply with the CONFIRM line in the message you received, in the same conversation.</p>}\n {test?.error && <p role=\"alert\" className=\"text-destructive\">{test.error}</p>}\n {test && test.status !== 'revoked' && !(active && test.status === 'verified' && !expired) && <>\n {!confirming ? <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setConfirming(true)}>Stop this test</button> : <fieldset className=\"space-y-2\"><legend>Stop this test and revoke its setup?</legend>\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={async () => { const outcome = await channel.run({ action: 'reset', confirm: true }); if (outcome.succeeded) setConfirming(false) }}>Confirm stop</button>{' '}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setConfirming(false)}>Keep testing</button>\n </fieldset>}\n </>}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={channel.resource.retry}>Refresh channel status</button>\n </>\n }}</ChannelState>\n <ChannelFailure state={channel.state} />\n </section>\n}\n\nfunction ConnectionPicker({ transport, onConnected }: { transport: Exclude<LineTransport, 'sms'>; onConnected: (line: Line) => void }) {\n const client = useChannelsClient()\n const connections = useChannelConnections(transport)\n const [connectionId, setConnectionId] = useState('')\n const [numberId, setNumberId] = useState('')\n const [address, setAddress] = useState('')\n const [showNumbers, setShowNumbers] = useState(false)\n const numbers = useWhatsAppNumbers(showNumbers ? connectionId : '')\n const connect = useConnectChannel(onConnected)\n const busy = connect.state.status === 'pending'\n useEffect(() => { setConnectionId(''); setNumberId(''); setShowNumbers(false); setAddress('') }, [client, transport])\n useEffect(() => {\n if (connections.status === 'ready' && connections.value.length === 1) setConnectionId(connections.value[0]!.id)\n }, [connections])\n useEffect(() => {\n if (numbers.status === 'ready' && numbers.value.length === 1) setNumberId(numbers.value[0]!.id)\n }, [numbers])\n return <>\n <ChannelState resource={connections} empty=\"No eligible Hub connections. Connect an identity in your app’s Integrations first.\">{items => <form className=\"space-y-4\" onSubmit={event => {\n event.preventDefault()\n if (transport === 'email') void connect.run({ kind: 'email', connectionId, address })\n else if (transport === 'whatsapp') void connect.run({ kind: 'connection', input: { transport, connectionId, phoneNumberId: numberId } })\n else void connect.run({ kind: 'connection', input: { transport, connectionId } })\n }}>\n <label className=\"block\">Connection<select className={inputClass} value={connectionId} disabled={busy} onChange={event => { setConnectionId(event.target.value); setNumberId(''); setShowNumbers(false) }} required>\n <option value=\"\">Choose a connection</option>{items.map(item => <option key={item.id} value={item.id}>{item.account ?? item.displayName}</option>)}\n </select></label>\n {transport === 'email' && <label className=\"block\">Mailbox address<input className={inputClass} type=\"email\" required value={address} disabled={busy} onChange={event => setAddress(event.target.value)} placeholder=\"hello@example.com\" /></label>}\n {transport === 'whatsapp' && <>\n <button type=\"button\" className={buttonClass} disabled={!connectionId || busy} onClick={() => { setShowNumbers(true); numbers.retry() }}>Show owned numbers</button>\n {showNumbers && <ChannelState resource={numbers} empty=\"This connection has no eligible WhatsApp numbers.\">{owned => <label className=\"block\">WhatsApp number<select className={inputClass} required value={numberId} disabled={busy} onChange={event => setNumberId(event.target.value)}>\n <option value=\"\">Choose a number</option>{owned.map(number => <option key={number.id} value={number.id}>{number.address}</option>)}\n </select></label>}</ChannelState>}\n </>}\n <p className=\"text-sm text-muted-foreground\">Connect an owned line, then test both directions. Each person must message first. Permissions remain managed in Tangle Hub.</p>\n <button type=\"submit\" className={primaryButtonClass} disabled={busy || !connectionId || (transport === 'email' && !address.trim()) || (transport === 'whatsapp' && (!numberId || !showNumbers || numbers.status !== 'ready'))}>{busy ? 'Connecting…' : 'Connect channel'}</button>\n </form>}</ChannelState>\n <ChannelFailure state={connect.state} />\n </>\n}\n\nexport interface ChannelConnectProps { transport: LineTransport; initialLineId?: string; className?: string }\n\n/** Select an existing line or connect an owned source, then verify it. */\nexport function ChannelConnect({ transport, initialLineId = '', className = '' }: ChannelConnectProps) {\n const [selected, setSelected] = useState(initialLineId)\n const lines = useChannels()\n const id = useId()\n useEffect(() => setSelected(initialLineId), [transport, initialLineId])\n return <div className={`space-y-4 ${className}`}>\n <section className={panelClass} aria-label={`${labels[transport]} channel`}>\n <h2 className=\"text-lg font-semibold\">Connect {labels[transport]}</h2>\n {transport === 'imessage' && <p>Use a free shared iMessage identity, or acquire a dedicated number. A shared identity requires a connect message to the router first.</p>}\n <ChannelState resource={lines} empty=\"No lines connected to this agent yet.\">{all => {\n const matching = all.filter(line => line.transport === transport && line.status !== 'released')\n return matching.length ? <><label htmlFor={id}>Existing line</label><select id={id} className={inputClass} value={selected} onChange={event => setSelected(event.target.value)}>\n <option value=\"\">Choose or connect a line</option>{matching.map(line => <option value={line.id} key={line.id}>{line.label ?? line.address}</option>)}\n </select></> : <p>No {labels[transport]} lines connected yet.</p>\n }}</ChannelState>\n {!selected && transport !== 'sms' && <ConnectionPicker key={transport} transport={transport} onConnected={line => { setSelected(line.id); lines.retry() }} />}\n {selected && <button type=\"button\" className={buttonClass} onClick={() => setSelected('')}>Choose another line</button>}\n </section>\n {selected ? <ChannelVerificationPanel key={selected} lineId={selected} /> : (transport === 'sms' || transport === 'imessage') && <NumberChannel transport={transport} />}\n </div>\n}\n\ntype TransportPanelProps = Omit<ChannelConnectProps, 'transport'>\nexport function IMessageChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"imessage\" /> }\nexport function WhatsAppChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"whatsapp\" /> }\nexport function EmailChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"email\" /> }\nexport function SMSChannel(props: TransportPanelProps) { return <ChannelConnect {...props} transport=\"sms\" /> }\n\n/** A transport's managed number activation, with explicit consent and cancellation. */\nexport function NumberChannel({ transport, className = '' }: { transport: 'sms' | 'imessage'; className?: string }) {\n const client = useChannelsClient()\n const number = useNumberChannel(transport)\n const [consent, setConsent] = useState(false)\n const [cancelId, setCancelId] = useState<string | null>(null)\n const [lineId, setLineId] = useState('')\n const connect = useConnectChannel(line => setLineId(line.id))\n useEffect(() => { setConsent(false) }, [number.quote?.token])\n useEffect(() => { setCancelId(null); setLineId(''); connect.reset() }, [transport, client, connect.reset])\n const busy = number.state.status === 'pending' || connect.state.status === 'pending'\n const money = (cents: number) => new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(cents / 100)\n return <section className={`${panelClass} ${className}`} aria-label={`${labels[transport]} number`} aria-busy={busy}>\n <h2 className=\"text-lg font-semibold\">Get a {labels[transport]} number</h2>\n {!client.ordering ? <p>Number ordering is unavailable. Existing numbers are unchanged.</p> : <ChannelState resource={number.resource} empty=\"Number availability has not been confirmed.\">{({ readiness, complete }) => <>\n {!readiness.configured && <p>New orders are disabled. Existing numbers still require separate cancellation.</p>}\n {!complete && <p role=\"alert\">The order list is incomplete. New purchases are disabled until ownership can be confirmed.</p>}\n {number.held && <p>This agent already holds an order for this transport. Cancel and release it before ordering another.</p>}\n <button type=\"button\" className={primaryButtonClass} disabled={busy || !complete || !readiness.configured || !readiness.transports.includes(transport) || !!number.held || number.uncertain} onClick={() => void number.run({ action: 'quote' })}>See activation price</button>\n </>}</ChannelState>}\n {number.quote && <div className=\"space-y-3 rounded-md border border-border p-4\">\n <h3 className=\"font-medium\">Activation · {money(number.quote.activationCents)}</h3>\n <p className=\"whitespace-pre-wrap\">{number.quote.terms || 'Published activation terms are missing. Ordering is disabled.'}</p>\n <p>{NUMBER_CHARGE_NOTICE}</p>\n <label className=\"flex items-start gap-2\"><input type=\"checkbox\" checked={consent} disabled={busy} onChange={event => setConsent(event.target.checked)} />I authorize this one-time activation charge. The number is not live until channel setup is complete.</label>\n {!number.uncertain && number.quote.expiresAt <= Date.now() && <p role=\"alert\">This quote expired. Read a new activation price before ordering.</p>}\n <button type=\"button\" className={primaryButtonClass} disabled={busy || !consent || !number.quote.terms.trim() || (!number.uncertain && number.quote.expiresAt <= Date.now())} onClick={() => void number.run({ action: 'purchase', consent })}>{number.uncertain ? 'Retry approved purchase' : `Order for ${money(number.quote.activationCents)}`}</button>\n </div>}\n {number.uncertain && <p role=\"alert\">The purchase response was lost or refused. Its outcome is not confirmed. {NUMBER_RETRY_NOTICE}</p>}\n {number.orders.map(order => <article key={order.id} className=\"space-y-3 rounded-md border border-border p-4\">\n <h3 className=\"break-all font-medium\">{order.address ?? 'Your number order'}</h3><p>{numberStage(order)}</p>\n {order.errorCode && <p role=\"status\">Status: {order.errorCode.replace(/_/g, ' ')}</p>}\n {order.status === 'ready_for_setup' && order.cancellation === 'none' && <><p>The number is acquired, not delivery-verified. Test it before connecting conversations.</p>\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => void connect.run({ kind: 'order', orderId: order.id })}>Test this number</button></>}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => void number.run({ action: 'advance', orderId: order.id })}>Check progress</button>{' '}\n {order.cancellation === 'none' && (cancelId !== order.id ? <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setCancelId(order.id)}>Cancel number</button> : <fieldset className=\"space-y-2\"><legend>Cancel this number? Access will be removed. Paid activation is not automatically refunded.</legend>\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={async () => { const result = await number.run({ action: 'cancel', orderId: order.id, confirm: true }); if (result.succeeded) setCancelId(null) }}>Confirm cancellation</button>{' '}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={() => setCancelId(null)}>Keep number</button>\n </fieldset>)}\n </article>)}\n <button type=\"button\" className={buttonClass} disabled={busy} onClick={number.resource.retry}>Refresh number status</button>\n <p className=\"text-sm text-muted-foreground\">SMS and iMessage are separate activations. Buying a number does not enable WhatsApp.</p>\n <ChannelFailure state={number.state} /><ChannelFailure state={connect.state} />\n {lineId && <ChannelVerificationPanel lineId={lineId} key={lineId} />}\n </section>\n}\n\n/** Read-only history. Messages stay on their original channel; no synthetic composer. */\nexport function ChannelConversation({ lineId, threadId, className = '' }: { lineId: string; threadId: string; className?: string }) {\n const messages = useChannelConversation(lineId, threadId)\n return <section className={`${panelClass} ${className}`} aria-label=\"Channel conversation\">\n <h3 className=\"font-semibold\">Conversation</h3>\n <ChannelState resource={messages} empty=\"No messages in this conversation yet.\">{items => <ol role=\"log\" aria-live=\"polite\" aria-label=\"Messages\" className=\"space-y-3\">\n {items.map(message => <li key={message.id} className=\"space-y-1 rounded-md bg-muted p-3\" data-direction={message.direction}>\n <p className=\"text-xs text-muted-foreground\">{message.direction === 'in' ? 'Incoming' : 'Outgoing'} · {message.kind} · <time dateTime={message.createdAt}>{message.createdAt}</time></p>\n <p className=\"whitespace-pre-wrap break-words\">{message.text ?? 'Non-text message'}</p>\n <p className=\"text-xs\">{message.status}{message.errorCode ? ` · ${message.errorCode}` : ''}</p>\n </li>)}\n </ol>}</ChannelState>\n <button type=\"button\" className={buttonClass} onClick={messages.retry}>Refresh messages</button>\n </section>\n}\n\n/** A channel's separate member threads. Changing line never reuses another line's selection. */\nexport function ChannelConversations({ lineId, className = '' }: { lineId: string; className?: string }) {\n const threads = useChannelConversations(lineId)\n const [selected, setSelected] = useState<{ lineId: string; threadId: string } | null>(null)\n const threadId = selected?.lineId === lineId ? selected.threadId : ''\n return <div className={`space-y-4 ${className}`}>\n <section className={panelClass} aria-label=\"Channel conversations\"><h2 className=\"text-lg font-semibold\">Conversations</h2>\n <ChannelState resource={threads} empty=\"No conversations yet. Members must message the line first.\">{items => <nav aria-label=\"Choose a conversation\" className=\"flex flex-wrap gap-2\">\n {items.map(thread => <button type=\"button\" key={thread.id} className={buttonClass} aria-pressed={thread.id === threadId} onClick={() => setSelected({ lineId, threadId: thread.id })}>{thread.memberId} · {thread.status}</button>)}\n </nav>}</ChannelState>\n </section>\n {threadId && <ChannelConversation key={`${lineId}:${threadId}`} lineId={lineId} threadId={threadId} />}\n </div>\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { HubNumberOrder, HubNumberQuote } from '@tangle-network/hub-sdk'\nimport { useChannelsClient } from './context'\nimport { useChannelMutation, useChannelResource } from './hooks'\n\nexport const NUMBER_CHARGE_NOTICE = 'This is a one-time activation charge. Tangle does not bill recurring carrier rental for this number. Your provider’s message rates are separate.'\nexport const NUMBER_RETRY_NOTICE = 'Retry uses the same approved quote, not a new purchase. Do not order again while the result is unknown.'\n\nexport function holdsNumber(order: HubNumberOrder): boolean {\n return order.cancellation !== 'released' && order.cancellation !== 'abandoned'\n}\n\nexport function numberStage(order: HubNumberOrder): string {\n if (order.cancellation === 'released' || order.cancellation === 'abandoned') return 'Released'\n if (order.cancellation === 'needs_review') return 'Release needs review'\n if (order.cancellation === 'requested' || order.status === 'cancelled') return 'Cancelling'\n if (order.status === 'needs_review') return 'Needs operator review'\n if (order.status === 'ready_for_setup') return 'Number acquired — channel setup next'\n if (order.errorCode === 'funding_required') return 'Add funds to continue'\n if (order.errorCode === 'sms_not_ready') return 'Waiting for SMS activation'\n return 'Provisioning'\n}\n\n/** Hub owns prices, terms, idempotency, funding, and cancellation. */\nexport function useNumberChannel(transport: 'sms' | 'imessage') {\n const client = useChannelsClient()\n const ordering = client.ordering\n const reference = ordering?.references[transport]\n const [quote, setQuote] = useState<HubNumberQuote | null>(null)\n const [receipts, setReceipts] = useState<HubNumberOrder[]>([])\n const [uncertain, setUncertain] = useState(false)\n // Set synchronously at dispatch, before React renders another click.\n const attempted = useRef(false)\n const resource = useChannelResource(async ({ signal }) => {\n if (!ordering || !reference) throw new Error('Number ordering is unavailable.')\n const readiness = await ordering.numbers.readiness()\n const orders: HubNumberOrder[] = []\n const seen = new Set<string>()\n let cursor: string | undefined\n let complete = false\n do {\n if (signal.aborted) throw new Error('Number read was superseded.')\n const page = await ordering.numbers.list({ clientReference: reference, cursor, limit: 100 })\n if (page.orders.some(order => order.clientReference !== reference || order.transport !== transport)) throw new Error('The number list belongs to another binding.')\n orders.push(...page.orders)\n if (page.nextCursor == null) {\n // Older Hub responses omit cursor metadata. An incomplete page cannot\n // establish that this agent has no order, even when the page is empty.\n complete = page.nextCursor === null\n break\n }\n if (seen.has(page.nextCursor) || seen.size >= 100) throw new Error('The number list could not be read completely.')\n seen.add(page.nextCursor)\n cursor = page.nextCursor\n } while (cursor)\n return { readiness, orders, complete }\n }, [ordering, reference, transport], !!ordering)\n const loaded = resource.status === 'ready' ? resource.value : null\n const orders = [...new Map([...(loaded?.orders ?? []), ...receipts].map(order => [order.id, order])).values()]\n const held = orders.find(holdsNumber) ?? null\n\n const mutation = useChannelMutation<\n | { action: 'quote' }\n | { action: 'purchase'; consent: boolean }\n | { action: 'advance'; orderId: string }\n | { action: 'cancel'; orderId: string; confirm: boolean }, void\n >(async (input, { signal }) => {\n if (!ordering || !reference) throw new Error('Number ordering is unavailable.')\n if (input.action === 'quote') {\n if (attempted.current) throw new Error('The previous purchase is unresolved. Retry its approved quote or check progress.')\n if (!loaded?.complete || !loaded.readiness.configured || !loaded.readiness.transports.includes(transport)) throw new Error('Number availability and existing orders must be confirmed first.')\n if (held) throw new Error('This agent already holds a number order for this transport.')\n const { quote: next } = await ordering.numbers.quote({ transport, clientReference: reference })\n if (next.transport !== transport || (next.clientReference !== undefined && next.clientReference !== reference)) throw new Error('The quote belongs to another binding.')\n if (!signal.aborted) setQuote(next)\n return\n }\n if (input.action === 'purchase') {\n if (!quote || !input.consent) throw new Error('Approve the quoted activation charge before ordering.')\n if (!quote.terms.trim() || !Number.isSafeInteger(quote.activationCents) || quote.activationCents < 0 || !quote.token) throw new Error('A valid price and published activation terms are required.')\n if (held) throw new Error('This agent already holds a number order for this transport.')\n if (!attempted.current && (!loaded?.complete || !loaded.readiness.configured || quote.expiresAt <= Date.now())) throw new Error('The quote or order information expired. Read the current state first.')\n attempted.current = true\n try {\n const { order } = await ordering.numbers.create({ quoteToken: quote.token, consent: true, clientReference: reference, transport })\n if (order.clientReference !== reference || order.transport !== transport) throw new Error('The purchase response belongs to another binding. Check progress before ordering again.')\n if (!signal.aborted) {\n // Preserve the acknowledged order before a follow-up read can fail.\n setReceipts(current => [order, ...current.filter(item => item.id !== order.id)])\n setQuote(null)\n setUncertain(false)\n }\n } catch (error) {\n if (!signal.aborted) setUncertain(true)\n throw error\n } finally {\n if (!signal.aborted) resource.retry()\n }\n return\n }\n if (!orders.some(order => order.id === input.orderId)) throw new Error('Read this number order before changing it.')\n if (input.action === 'cancel' && !input.confirm) throw new Error('Confirm cancelling this number.')\n const { order } = await ordering.numbers[input.action](input.orderId)\n if (order.id !== input.orderId || order.clientReference !== reference || order.transport !== transport) throw new Error('The number response belongs to another binding.')\n if (!signal.aborted) {\n setReceipts(current => [order, ...current.filter(item => item.id !== order.id)])\n resource.retry()\n }\n })\n useEffect(() => {\n setQuote(null); setReceipts([]); setUncertain(false); attempted.current = false\n mutation.reset()\n }, [client, client.scope, transport, reference, mutation.reset])\n useEffect(() => {\n if (loaded) setReceipts(current => current.filter(receipt => !loaded.orders.some(order => order.id === receipt.id)))\n if (loaded?.orders.some(holdsNumber)) {\n setQuote(null); setUncertain(false); attempted.current = false\n } else if (!uncertain && !quote && loaded?.complete && orders.length > 0 && orders.every(order => !holdsNumber(order))) {\n attempted.current = false\n }\n }, [loaded])\n return { resource, orders, held, quote, uncertain, ...mutation }\n}\n","import type { ReactNode } from 'react'\nimport { AsyncView, MutationStatus, type AsyncResourceState, type MutationState } from '../web-react/async'\n\nexport const panelClass = 'space-y-4 rounded-xl border border-border bg-card p-6 text-foreground'\nexport const buttonClass = 'inline-flex items-center justify-center rounded-md border border-border px-3 py-2 text-sm font-medium transition hover:bg-accent focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring focus-visible:outline-offset-2 disabled:cursor-not-allowed disabled:opacity-50'\nexport const primaryButtonClass = `${buttonClass} border-primary bg-primary text-primary-foreground hover:bg-primary/90`\nexport const inputClass = 'block w-full rounded-md border border-input bg-background px-3 py-2 text-foreground focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring'\n\nexport function ChannelFailure({ state }: { state: MutationState<unknown> }) {\n return state.status === 'failed' ? <MutationStatus state={state} className=\"text-sm text-destructive\" /> : null\n}\n\n/** Channel copy around the shared async view, not a second state renderer. */\nexport function ChannelState<T>({ resource, children, empty }: { resource: AsyncResourceState<T>; children: (value: T) => ReactNode; empty: string }) {\n return <AsyncView state={resource} empty={{ title: empty, action: { label: 'Refresh', onClick: resource.retry } }}\n loadingLabel=\"Loading channel…\" retryLabel=\"Try again\"\n renderIdle={() => <p className=\"text-sm text-muted-foreground\">Choose a channel to continue.</p>}>\n {children}\n </AsyncView>\n}\n","import { useEffect, useState } from 'react'\nimport { useChannelsClient } from './context'\nimport { useChannelMutation, useChannelResource } from './hooks'\nimport { ChannelState, ChannelFailure, buttonClass, primaryButtonClass, panelClass } from './ui'\n\n/** Only same-origin relative paths or credential-free HTTPS checkout URLs. */\nexport function safeCheckoutUrl(value: string): string {\n if (/^\\/(?!\\/)/.test(value) && !/[\\\\\\s]/.test(value)) return value\n const url = new URL(value)\n if (url.protocol !== 'https:' || url.username || url.password) throw new Error('Checkout returned an unsafe URL.')\n return url.href\n}\n\nexport function useLinePayment(lineId: string) {\n const client = useChannelsClient()\n const resource = useChannelResource(context => {\n if (!client.payment) throw new Error('Payments are unavailable for this line.')\n return client.payment.read(lineId, context)\n }, [lineId], !!lineId && !!client.payment)\n const mutation = useChannelMutation<{ consent: boolean }, string>(async ({ consent }) => {\n if (!client.payment || resource.status !== 'ready') throw new Error('Read the current allowance before checkout.')\n const { plan, allowance, terms } = resource.value\n if (!consent || !terms.trim()) throw new Error('Accept the published terms before checkout.')\n if (!plan.configured || !plan.paid || !Number.isFinite(plan.paid.priceUsdMonthly) || plan.paid.priceUsdMonthly <= 0 || allowance.decision !== 'paywall' || !allowance.paywall || allowance.tier !== 'free') throw new Error('Checkout is not available for this allowance.')\n return safeCheckoutUrl((await client.payment.checkout(lineId)).url)\n })\n useEffect(() => mutation.reset(), [lineId, mutation.reset])\n return { resource, ...mutation, available: !!client.payment }\n}\n\n/** End-user allowance/checkout page, not number acquisition or creator payouts. */\nexport function LinePayPage({ lineId, className = '' }: { lineId: string; className?: string }) {\n const payment = useLinePayment(lineId)\n const [consentedTerms, setConsentedTerms] = useState<string | null>(null)\n const currentTerms = payment.resource.status === 'ready'\n ? JSON.stringify([lineId, payment.resource.value.terms, payment.resource.value.plan.paid])\n : null\n const consent = currentTerms !== null && consentedTerms === currentTerms\n return <section className={`${panelClass} ${className}`} aria-label=\"Line subscription\">\n <h2 className=\"text-lg font-semibold\">Your line plan</h2>\n {!payment.available ? <p>Payments are unavailable for this line.</p> : <ChannelState resource={payment.resource} empty=\"No plan is available.\">{value => <>\n <h3 className=\"font-medium\">{value.label}</h3>\n <p>{value.allowance.turns.used} of {value.allowance.turns.limit} turns used today.</p>\n {value.allowance.tier === 'paid' ? <p role=\"status\">Your paid allowance is active.{value.allowance.decision === 'allowance_reached' ? ' Its current limit is exhausted; another checkout cannot lift it.' : ''}</p> : value.allowance.decision === 'paywall' && value.plan.paid ? <>\n <p>{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value.plan.paid.priceUsdMonthly)} per month · {value.plan.paid.turnsPerDay} turns per day.</p>\n <p className=\"whitespace-pre-wrap\">{value.terms || 'Plan terms are unavailable. Checkout is disabled.'}</p>\n <label className=\"flex items-start gap-2\"><input type=\"checkbox\" checked={consent} onChange={event => setConsentedTerms(event.target.checked ? currentTerms : null)} />I accept these subscription terms.</label>\n <button type=\"button\" className={primaryButtonClass} disabled={!consent || !value.terms.trim() || payment.state.status === 'pending'} onClick={() => void payment.run({ consent })}>Continue to checkout</button>\n <p className=\"text-sm text-muted-foreground\">Payment is confirmed by the server after settlement, not by returning to this page.</p>\n </> : <p>{value.allowance.decision === 'allowance_reached' ? 'Your allowance is exhausted. Paying does not lift this limit today.' : 'Your current allowance is available.'} Resets at {value.allowance.resetsAt}.</p>}\n <button type=\"button\" className={buttonClass} onClick={payment.resource.retry}>Check payment status</button>\n </>}</ChannelState>}\n {payment.state.status === 'succeeded' && consent && <a className=\"underline\" href={payment.state.value} rel=\"noopener noreferrer\">Open secure checkout</a>}\n <ChannelFailure state={payment.state} />\n </section>\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,eAAe,kBAAkC;AAejD;AAZT,IAAM,UAAU,cAAmF,IAAI;AAGhG,SAAS,iBAAiB,EAAE,QAAQ,eAAe,KAAM,SAAS,GAKtE;AACD,MAAI,iBAAiB,UAAU,CAAC,OAAO,SAAS,YAAY,KAAK,eAAe,MAAM;AACpF,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AACA,SAAO,oBAAC,QAAQ,UAAR,EAAiB,OAAO,EAAE,QAAQ,aAAa,GAAuB,YAAf,OAAO,KAAiB;AACzF;AAGO,SAAS,oBAAoC;AAClD,QAAM,EAAE,OAAO,IAAI,mBAAmB;AACtC,MAAI,EAAE,WAAW,WAAW,CAAC,OAAO,SAAS,EAAE,oBAAoB,OAAO,UAAU,OAAO,OAAO,MAAM,mBAAmB,YAAY;AACrI,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO;AACT;AAEO,SAAS,qBAAqB;AACnC,QAAM,QAAQ,WAAW,OAAO;AAChC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,wDAAwD;AACpF,SAAO;AACT;;;AC/BA,SAAS,aAAa,WAAW,cAAc;AAOxC,SAAS,mBAAsB,MAAiD,MAA0B,UAAU,MAAM,OAAO,MAA6B;AACnK,QAAM,EAAE,QAAQ,aAAa,IAAI,mBAAmB;AACpD,QAAM,WAAW,iBAAiB,EAAE,MAAM,MAAM,CAAC,QAAQ,OAAO,OAAO,GAAG,IAAI,GAAG,QAAQ,CAAC;AAC1F,YAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,QAAQ,iBAAiB,SAAS,SAAS,WAAW,aAAa,SAAS,WAAW,OAAQ;AAChH,UAAM,QAAQ,OAAO,aAAa,eAAe,SAAS,SAAS,KAAK,IAAI,MAAO,YAAY,IAAI;AACnG,UAAM,QAAQ,WAAW,SAAS,OAAO,KAAK;AAC9C,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,SAAS,MAAM,cAAc,SAAS,QAAQ,SAAS,OAAO,QAAQ,CAAC;AAC3E,SAAO,UAAU,WAAW,EAAE,QAAQ,QAAQ,OAAO,SAAS,MAAM;AACtE;AAGO,SAAS,mBAAyB,QAA6D,aAAkC;AACtI,QAAM,EAAE,OAAO,IAAI,mBAAmB;AACtC,QAAM,OAAO,OAAsB,IAAI;AACvC,QAAM,WAAW,qBAA2B;AAAA,IAC1C,QAAQ,OAAO,OAAO,YAAY,aAAa,MAAM,OAAO,OAAO,OAAO,CAAC;AAAA,IAC3E;AAAA,EACF,CAAC;AACD,QAAM,EAAE,OAAO,IAAI,IAAI;AACvB,YAAU,MAAM;AACd,UAAM;AACN,WAAO,MAAM;AAAE,WAAK,UAAU;AAAM,YAAM;AAAA,IAAE;AAAA,EAC9C,GAAG,CAAC,QAAQ,OAAO,OAAO,KAAK,CAAC;AAChC,QAAM,YAAY,YAAY,OAAO,UAA0C;AAC7E,QAAI,KAAK,QAAS,QAAO,YAAY,iDAAiD;AACtF,UAAM,QAAQ,CAAC;AACf,SAAK,UAAU;AACf,QAAI;AAAE,aAAO,MAAM,IAAI,KAAK;AAAA,IAAE,UAC9B;AAAU,UAAI,KAAK,YAAY,MAAO,MAAK,UAAU;AAAA,IAAK;AAAA,EAC5D,GAAG,CAAC,GAAG,CAAC;AACR,SAAO,EAAE,GAAG,UAAU,KAAK,UAAU;AACvC;AAEO,SAAS,cAAc;AAC5B,QAAM,EAAE,OAAO,IAAI,mBAAmB;AACtC,SAAO,mBAAmB,MAAM,OAAO,MAAM,KAAK,GAAG,CAAC,CAAC;AACzD;AAEO,SAAS,sBAAsB,WAA0B;AAC9D,QAAM,SAAS,kBAAkB;AACjC,SAAO,mBAAmB,aAAW,OAAO,MAAM,YAAY,WAAW,OAAO,GAAG,CAAC,SAAS,GAAG,MAAM,KAAK;AAC7G;AAEO,SAAS,mBAAmB,cAAsB;AACvD,QAAM,SAAS,kBAAkB;AACjC,SAAO,mBAAmB,aAAW,OAAO,MAAM,gBAAgB,cAAc,OAAO,GAAG,CAAC,YAAY,GAAG,CAAC,CAAC,cAAc,KAAK;AACjI;AAGO,SAAS,kBAAkB,aAAoC;AACpE,QAAM,SAAS,kBAAkB;AACjC,SAAO,mBAA8C,OAAM,UAAS;AAClE,QAAI,MAAM,SAAS,cAAc;AAC/B,UAAI,CAAC,MAAM,MAAM,aAAa,KAAK,EAAG,OAAM,IAAI,MAAM,sBAAsB;AAC5E,UAAI,MAAM,MAAM,cAAc,cAAc,CAAC,MAAM,MAAM,cAAc,KAAK,EAAG,OAAM,IAAI,MAAM,2BAA2B;AAC1H,aAAO,OAAO,MAAM,eAAe,MAAM,KAAK;AAAA,IAChD;AACA,QAAI,MAAM,SAAS,SAAS;AAC1B,UAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,OAAM,IAAI,MAAM,wBAAwB;AACnE,aAAO,OAAO,MAAM,UAAU,MAAM,OAAO;AAAA,IAC7C;AACA,UAAM,UAAU,MAAM,QAAQ,KAAK,EAAE,YAAY;AACjD,QAAI,CAAC,MAAM,aAAa,KAAK,KAAK,CAAC,6BAA6B,KAAK,OAAO,EAAG,OAAM,IAAI,MAAM,wDAAwD;AACvJ,WAAO,OAAO,MAAM,UAAU,EAAE,cAAc,MAAM,cAAc,QAAQ,CAAC;AAAA,EAC7E,GAAG,WAAW;AAChB;AAEO,SAAS,oBAAoB,MAA2B,MAAM,KAAK,IAAI,GAAY;AACxF,SAAO,KAAK,WAAY,KAAK,WAAW,cAAc,KAAK,aAAa;AAC1E;AAIO,SAAS,WAAW,QAAgB;AACzC,QAAM,SAAS,kBAAkB;AACjC,QAAM,WAAW,mBAAmB,OAAM,YAAW;AACnD,UAAM,CAAC,MAAM,YAAY,IAAI,MAAM,QAAQ,IAAI,CAAC,OAAO,MAAM,IAAI,MAAM,GAAG,OAAO,MAAM,aAAa,QAAQ,OAAO,CAAC,CAAC;AACrH,QAAI,KAAK,OAAO,UAAW,KAAK,cAAc,KAAK,WAAW,WAAW,UAAY,gBAAgB,aAAa,WAAW,OAAS,OAAM,IAAI,MAAM,gDAAgD;AACtM,WAAO,EAAE,MAAM,aAAa;AAAA,EAC9B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;AACrB,QAAM,WAAW,mBAA4E,OAAO,EAAE,QAAQ,QAAQ,MAAM;AAC1H,QAAI,SAAS,WAAW,QAAS,OAAM,IAAI,MAAM,oDAAoD;AACrG,UAAM,EAAE,MAAM,cAAc,KAAK,IAAI,SAAS;AAC9C,QAAI,KAAK,OAAO,OAAQ,OAAM,IAAI,MAAM,gDAAgD;AACxF,QAAI,WAAW,WAAW,KAAK,WAAW,SAAU,OAAM,IAAI,MAAM,0BAA0B;AAC9F,QAAI,WAAW,SAAS;AACtB,UAAI,QAAQ,KAAK,WAAW,UAAW,OAAM,IAAI,MAAM,iDAAiD;AACxG,YAAM,OAAO,MAAM,MAAM,MAAM;AAC/B;AAAA,IACF;AACA,QAAI,CAAC,QAAQ,KAAK,WAAW,OAAQ,OAAM,IAAI,MAAM,6BAA6B;AAClF,QAAI,WAAW,SAAS;AACtB,UAAI,YAAY,KAAM,OAAM,IAAI,MAAM,6BAA6B;AACnE,YAAM,OAAO,MAAM,MAAM,QAAQ,KAAK,EAAE;AACxC;AAAA,IACF;AACA,QAAI,oBAAoB,IAAI,EAAG,OAAM,IAAI,MAAM,kDAAkD;AACjG,QAAI,WAAW,YAAY;AACzB,UAAI,KAAK,WAAW,WAAY,OAAM,IAAI,MAAM,+DAA+D;AAC/G,YAAM,YAAY,MAAM,OAAO,MAAM,SAAS,QAAQ,KAAK,EAAE;AAC7D,UAAI,UAAU,OAAO,UAAU,UAAU,WAAW,YAAY,UAAU,YAAY,WAAW,YAAY,UAAU,WAAW,WAAW,OAAQ,OAAM,IAAI,MAAM,yCAAyC;AAAA,IAChN,WAAW,WAAW,QAAQ;AAC5B,UAAI,KAAK,WAAW,WAAY,OAAM,IAAI,MAAM,2DAA2D;AAC3G,YAAM,OAAO,MAAM,KAAK,QAAQ,KAAK,EAAE;AAAA,IACzC,OAAO;AACL,UAAI,KAAK,WAAW,iBAAiB,KAAK,WAAW,YAAa,OAAM,IAAI,MAAM,6CAA6C;AAC/H,YAAM,OAAO,MAAM,OAAO,QAAQ,KAAK,EAAE;AAAA,IAC3C;AAAA,EACF,GAAG,SAAS,KAAK;AACjB,YAAU,MAAM,SAAS,MAAM,GAAG,CAAC,QAAQ,SAAS,KAAK,CAAC;AAC1D,SAAO,EAAE,UAAU,GAAG,SAAS;AACjC;AAEO,SAAS,wBAAwB,QAAgB;AACtD,QAAM,EAAE,OAAO,IAAI,mBAAmB;AACtC,SAAO,mBAAmB,YAAY;AACpC,UAAM,UAAU,MAAM,OAAO,MAAM,QAAQ,MAAM,EAAE,KAAK;AACxD,QAAI,QAAQ,KAAK,YAAU,OAAO,WAAW,MAAM,EAAG,OAAM,IAAI,MAAM,8CAA8C;AACpH,WAAO;AAAA,EACT,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;AACvB;AAEO,SAAS,uBAAuB,QAAgB,UAAkB;AACvE,QAAM,EAAE,OAAO,IAAI,mBAAmB;AACtC,SAAO,mBAAmB,YAAY;AACpC,UAAM,WAAW,MAAM,OAAO,MAAM,QAAQ,MAAM,EAAE,SAAS,QAAQ;AAErE,QAAI,SAAS,KAAK,aAAW,QAAQ,aAAa,QAAQ,EAAG,OAAM,IAAI,MAAM,uDAAuD;AACpI,WAAO,CAAC,GAAG,IAAI,IAAI,SAAS,IAAI,aAAW,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,OAAO,CAAC,EACxE,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,KAAK,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AAAA,EACtF,GAAG,CAAC,QAAQ,QAAQ,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,QAAQ;AAC/C;;;AC5IA,SAAS,aAAAA,YAAW,OAAO,YAAAC,iBAAgB;;;ACA3C,SAAS,aAAAC,YAAW,UAAAC,SAAQ,gBAAgB;AAKrC,IAAM,uBAAuB;AAC7B,IAAM,sBAAsB;AAE5B,SAAS,YAAY,OAAgC;AAC1D,SAAO,MAAM,iBAAiB,cAAc,MAAM,iBAAiB;AACrE;AAEO,SAAS,YAAY,OAA+B;AACzD,MAAI,MAAM,iBAAiB,cAAc,MAAM,iBAAiB,YAAa,QAAO;AACpF,MAAI,MAAM,iBAAiB,eAAgB,QAAO;AAClD,MAAI,MAAM,iBAAiB,eAAe,MAAM,WAAW,YAAa,QAAO;AAC/E,MAAI,MAAM,WAAW,eAAgB,QAAO;AAC5C,MAAI,MAAM,WAAW,kBAAmB,QAAO;AAC/C,MAAI,MAAM,cAAc,mBAAoB,QAAO;AACnD,MAAI,MAAM,cAAc,gBAAiB,QAAO;AAChD,SAAO;AACT;AAGO,SAAS,iBAAiB,WAA+B;AAC9D,QAAM,SAAS,kBAAkB;AACjC,QAAM,WAAW,OAAO;AACxB,QAAM,YAAY,UAAU,WAAW,SAAS;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAgC,IAAI;AAC9D,QAAM,CAAC,UAAU,WAAW,IAAI,SAA2B,CAAC,CAAC;AAC7D,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAEhD,QAAM,YAAYC,QAAO,KAAK;AAC9B,QAAM,WAAW,mBAAmB,OAAO,EAAE,OAAO,MAAM;AACxD,QAAI,CAAC,YAAY,CAAC,UAAW,OAAM,IAAI,MAAM,iCAAiC;AAC9E,UAAM,YAAY,MAAM,SAAS,QAAQ,UAAU;AACnD,UAAMC,UAA2B,CAAC;AAClC,UAAM,OAAO,oBAAI,IAAY;AAC7B,QAAI;AACJ,QAAI,WAAW;AACf,OAAG;AACD,UAAI,OAAO,QAAS,OAAM,IAAI,MAAM,6BAA6B;AACjE,YAAM,OAAO,MAAM,SAAS,QAAQ,KAAK,EAAE,iBAAiB,WAAW,QAAQ,OAAO,IAAI,CAAC;AAC3F,UAAI,KAAK,OAAO,KAAK,WAAS,MAAM,oBAAoB,aAAa,MAAM,cAAc,SAAS,EAAG,OAAM,IAAI,MAAM,6CAA6C;AAClK,MAAAA,QAAO,KAAK,GAAG,KAAK,MAAM;AAC1B,UAAI,KAAK,cAAc,MAAM;AAG3B,mBAAW,KAAK,eAAe;AAC/B;AAAA,MACF;AACA,UAAI,KAAK,IAAI,KAAK,UAAU,KAAK,KAAK,QAAQ,IAAK,OAAM,IAAI,MAAM,+CAA+C;AAClH,WAAK,IAAI,KAAK,UAAU;AACxB,eAAS,KAAK;AAAA,IAChB,SAAS;AACT,WAAO,EAAE,WAAW,QAAAA,SAAQ,SAAS;AAAA,EACvC,GAAG,CAAC,UAAU,WAAW,SAAS,GAAG,CAAC,CAAC,QAAQ;AAC/C,QAAM,SAAS,SAAS,WAAW,UAAU,SAAS,QAAQ;AAC9D,QAAM,SAAS,CAAC,GAAG,IAAI,IAAI,CAAC,GAAI,QAAQ,UAAU,CAAC,GAAI,GAAG,QAAQ,EAAE,IAAI,WAAS,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC;AAC7G,QAAM,OAAO,OAAO,KAAK,WAAW,KAAK;AAEzC,QAAM,WAAW,mBAKf,OAAO,OAAO,EAAE,OAAO,MAAM;AAC7B,QAAI,CAAC,YAAY,CAAC,UAAW,OAAM,IAAI,MAAM,iCAAiC;AAC9E,QAAI,MAAM,WAAW,SAAS;AAC5B,UAAI,UAAU,QAAS,OAAM,IAAI,MAAM,kFAAkF;AACzH,UAAI,CAAC,QAAQ,YAAY,CAAC,OAAO,UAAU,cAAc,CAAC,OAAO,UAAU,WAAW,SAAS,SAAS,EAAG,OAAM,IAAI,MAAM,kEAAkE;AAC7L,UAAI,KAAM,OAAM,IAAI,MAAM,6DAA6D;AACvF,YAAM,EAAE,OAAO,KAAK,IAAI,MAAM,SAAS,QAAQ,MAAM,EAAE,WAAW,iBAAiB,UAAU,CAAC;AAC9F,UAAI,KAAK,cAAc,aAAc,KAAK,oBAAoB,UAAa,KAAK,oBAAoB,UAAY,OAAM,IAAI,MAAM,uCAAuC;AACvK,UAAI,CAAC,OAAO,QAAS,UAAS,IAAI;AAClC;AAAA,IACF;AACA,QAAI,MAAM,WAAW,YAAY;AAC/B,UAAI,CAAC,SAAS,CAAC,MAAM,QAAS,OAAM,IAAI,MAAM,uDAAuD;AACrG,UAAI,CAAC,MAAM,MAAM,KAAK,KAAK,CAAC,OAAO,cAAc,MAAM,eAAe,KAAK,MAAM,kBAAkB,KAAK,CAAC,MAAM,MAAO,OAAM,IAAI,MAAM,4DAA4D;AAClM,UAAI,KAAM,OAAM,IAAI,MAAM,6DAA6D;AACvF,UAAI,CAAC,UAAU,YAAY,CAAC,QAAQ,YAAY,CAAC,OAAO,UAAU,cAAc,MAAM,aAAa,KAAK,IAAI,GAAI,OAAM,IAAI,MAAM,uEAAuE;AACvM,gBAAU,UAAU;AACpB,UAAI;AACF,cAAM,EAAE,OAAAC,OAAM,IAAI,MAAM,SAAS,QAAQ,OAAO,EAAE,YAAY,MAAM,OAAO,SAAS,MAAM,iBAAiB,WAAW,UAAU,CAAC;AACjI,YAAIA,OAAM,oBAAoB,aAAaA,OAAM,cAAc,UAAW,OAAM,IAAI,MAAM,yFAAyF;AACnL,YAAI,CAAC,OAAO,SAAS;AAEnB,sBAAY,aAAW,CAACA,QAAO,GAAG,QAAQ,OAAO,UAAQ,KAAK,OAAOA,OAAM,EAAE,CAAC,CAAC;AAC/E,mBAAS,IAAI;AACb,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF,SAAS,OAAO;AACd,YAAI,CAAC,OAAO,QAAS,cAAa,IAAI;AACtC,cAAM;AAAA,MACR,UAAE;AACA,YAAI,CAAC,OAAO,QAAS,UAAS,MAAM;AAAA,MACtC;AACA;AAAA,IACF;AACA,QAAI,CAAC,OAAO,KAAK,CAAAA,WAASA,OAAM,OAAO,MAAM,OAAO,EAAG,OAAM,IAAI,MAAM,4CAA4C;AACnH,QAAI,MAAM,WAAW,YAAY,CAAC,MAAM,QAAS,OAAM,IAAI,MAAM,iCAAiC;AAClG,UAAM,EAAE,MAAM,IAAI,MAAM,SAAS,QAAQ,MAAM,MAAM,EAAE,MAAM,OAAO;AACpE,QAAI,MAAM,OAAO,MAAM,WAAW,MAAM,oBAAoB,aAAa,MAAM,cAAc,UAAW,OAAM,IAAI,MAAM,iDAAiD;AACzK,QAAI,CAAC,OAAO,SAAS;AACnB,kBAAY,aAAW,CAAC,OAAO,GAAG,QAAQ,OAAO,UAAQ,KAAK,OAAO,MAAM,EAAE,CAAC,CAAC;AAC/E,eAAS,MAAM;AAAA,IACjB;AAAA,EACF,CAAC;AACD,EAAAC,WAAU,MAAM;AACd,aAAS,IAAI;AAAG,gBAAY,CAAC,CAAC;AAAG,iBAAa,KAAK;AAAG,cAAU,UAAU;AAC1E,aAAS,MAAM;AAAA,EACjB,GAAG,CAAC,QAAQ,OAAO,OAAO,WAAW,WAAW,SAAS,KAAK,CAAC;AAC/D,EAAAA,WAAU,MAAM;AACd,QAAI,OAAQ,aAAY,aAAW,QAAQ,OAAO,aAAW,CAAC,OAAO,OAAO,KAAK,WAAS,MAAM,OAAO,QAAQ,EAAE,CAAC,CAAC;AACnH,QAAI,QAAQ,OAAO,KAAK,WAAW,GAAG;AACpC,eAAS,IAAI;AAAG,mBAAa,KAAK;AAAG,gBAAU,UAAU;AAAA,IAC3D,WAAW,CAAC,aAAa,CAAC,SAAS,QAAQ,YAAY,OAAO,SAAS,KAAK,OAAO,MAAM,WAAS,CAAC,YAAY,KAAK,CAAC,GAAG;AACtH,gBAAU,UAAU;AAAA,IACtB;AAAA,EACF,GAAG,CAAC,MAAM,CAAC;AACX,SAAO,EAAE,UAAU,QAAQ,MAAM,OAAO,WAAW,GAAG,SAAS;AACjE;;;ACjHqC,gBAAAC,YAAA;AAN9B,IAAM,aAAa;AACnB,IAAM,cAAc;AACpB,IAAM,qBAAqB,GAAG,WAAW;AACzC,IAAM,aAAa;AAEnB,SAAS,eAAe,EAAE,MAAM,GAAsC;AAC3E,SAAO,MAAM,WAAW,WAAW,gBAAAA,KAAC,kBAAe,OAAc,WAAU,4BAA2B,IAAK;AAC7G;AAGO,SAAS,aAAgB,EAAE,UAAU,UAAU,MAAM,GAA0F;AACpJ,SAAO,gBAAAA;AAAA,IAAC;AAAA;AAAA,MAAU,OAAO;AAAA,MAAU,OAAO,EAAE,OAAO,OAAO,QAAQ,EAAE,OAAO,WAAW,SAAS,SAAS,MAAM,EAAE;AAAA,MAC9G,cAAa;AAAA,MAAmB,YAAW;AAAA,MAC3C,YAAY,MAAM,gBAAAA,KAAC,OAAE,WAAU,iCAAgC,2CAA6B;AAAA,MAC3F;AAAA;AAAA,EACH;AACF;;;AFIoC,SAyB4B,UAxB5D,OAAAC,MADgC;AAhBpC,IAAM,SAAwC,EAAE,UAAU,YAAY,UAAU,YAAY,KAAK,OAAO,OAAO,QAAQ;AAGhH,SAAS,mBAAmB,MAAY,aAAoC;AACjF,MAAI,KAAK,cAAc,SAAS;AAC9B,QAAI,CAAC,6BAA6B,KAAK,KAAK,OAAO,EAAG,QAAO;AAC7D,WAAO,UAAU,mBAAmB,KAAK,OAAO,CAAC,gCAAgC,mBAAmB,WAAW,CAAC;AAAA,EAClH;AACA,QAAM,UAAU,KAAK,iBAAiB,KAAK;AAC3C,MAAI,CAAC,oBAAoB,KAAK,OAAO,EAAG,QAAO;AAC/C,MAAI,KAAK,cAAc,WAAY,QAAO,iBAAiB,QAAQ,MAAM,CAAC,CAAC,SAAS,mBAAmB,WAAW,CAAC;AACnH,SAAO,OAAO,OAAO,SAAS,mBAAmB,KAAK,WAAW,WAAW,CAAC;AAC/E;AAEA,SAAS,SAAS,EAAE,KAAK,GAAqB;AAC5C,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAS,EAAE;AACzC,SAAO,qBAAC,SAAI,WAAU,aAAY;AAAA,yBAAC,SAAI,WAAU,kDAC/C;AAAA,sBAAAD,KAAC,UAAK,WAAU,4BAA4B,gBAAK;AAAA,MACjD,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,cAAY,QAAQ,IAAI,IAAI,SAAS,YAAY;AAC7F,YAAI;AAAE,gBAAM,UAAU,UAAU,UAAU,IAAI;AAAG,qBAAW,QAAQ;AAAA,QAAE,QAChE;AAAE,qBAAW,0DAA0D;AAAA,QAAE;AAAA,MACjF,GAAG,kBAAI;AAAA,OACT;AAAA,IAAO,WAAW,gBAAAA,KAAC,OAAE,MAAK,UAAS,WAAU,WAAW,mBAAQ;AAAA,KAAK;AACvE;AAGO,SAAS,yBAAyB,EAAE,QAAQ,YAAY,GAAG,GAA2C;AAC3G,QAAM,UAAU,WAAW,MAAM;AACjC,QAAM,CAAC,YAAY,aAAa,IAAIC,UAAS,KAAK;AAClD,EAAAC,WAAU,MAAM,cAAc,KAAK,GAAG,CAAC,MAAM,CAAC;AAC9C,QAAM,OAAO,QAAQ,MAAM,WAAW;AACtC,QAAM,MAAM,CAAC,WAAqD,KAAK,QAAQ,IAAI,EAAE,OAAO,CAAC;AAC7F,SAAO,qBAAC,aAAQ,WAAW,GAAG,UAAU,IAAI,SAAS,IAAI,cAAW,wBAAuB,aAAW,MACpG;AAAA,oBAAAF,KAAC,QAAG,WAAU,yBAAwB,iCAAmB;AAAA,IACzD,gBAAAA,KAAC,gBAAa,UAAU,QAAQ,UAAU,OAAM,+BAA+B,WAAC,EAAE,MAAM,cAAc,KAAK,MAAM;AAC/G,YAAM,UAAU,OAAO,oBAAoB,IAAI,IAAI;AACnD,YAAM,SAAS,KAAK,WAAW,YAAY,KAAK,YAAY,WAAW;AACvE,YAAM,OAAO,OAAO,mBAAmB,MAAM,KAAK,WAAW,IAAI;AACjE,aAAO,iCACL;AAAA,6BAAC,OAAE,WAAU,yBAAyB;AAAA,iBAAO,KAAK,SAAS;AAAA,UAAE;AAAA,UAAI,KAAK;AAAA,WAAQ;AAAA,QAC7E,KAAK,WAAW,WAAW,qBAAC,OAAE,MAAK,SAAQ;AAAA;AAAA,UAAc,KAAK;AAAA,UAAO;AAAA,WAA0D,IAC5H,UAAU,MAAM,WAAW,cAAc,CAAC,UAAU,iCACpD;AAAA,+BAAC,OAAE,MAAK,UAAS;AAAA;AAAA,YAAqC,OAAO,KAAK,SAAS;AAAA,YAAE;AAAA,aAAU;AAAA,UACvF,gBAAAA,KAAC,OAAG,eAAK,WAAW,KAAK,gBAAgB,oBAAoB,KAAK,OAAO,OAAO,KAAK,aAAa,MAAM,kEAAiE;AAAA,UACzK,gBAAAA,KAAC,YAAS,MAAM,KAAK,WAAW,KAAK,SAAS;AAAA,WAChD,IACE,CAAC,QAAQ,KAAK,WAAW,YAAY,iCACpC;AAAA,oBAAU,gBAAAA,KAAC,OAAE,gFAAkE;AAAA,UAChF,gBAAAA,KAAC,OAAE,iFAAmE;AAAA,UACtE,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,MAAM,SAAS,MAAM,IAAI,OAAO,GAAG,gCAAkB;AAAA,WACtH,IAAM,UAAU,gBAAAA,KAAC,OAAE,MAAK,SAAQ,oEAAsD,IACpF,KAAK,WAAW,aAAa,iCAAE;AAAA,0BAAAA,KAAC,OAAE,uEAAyD;AAAA,UAC3F,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,MAAM,SAAS,MAAM,IAAI,UAAU,GAAG,+BAAiB;AAAA,WAAS,IAC/H,KAAK,WAAW,gBAAgB,iCAAE;AAAA,0BAAAA,KAAC,OAAE,qDAAuC;AAAA,UAC5E,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,MAAM,SAAS,MAAM,IAAI,QAAQ,GAAG,yBAAW;AAAA,WAAS,IACvH,KAAK,WAAW,YAAY,iCAC3B;AAAA,eAAK,WAAW,KAAK,iBAAiB,iCAAE;AAAA,iCAAC,OAAE;AAAA;AAAA,cAAqB,KAAK;AAAA,cAAc;AAAA,eAA8C;AAAA,YAAI,gBAAAA,KAAC,YAAS,MAAM,KAAK,SAAS;AAAA,aAAE;AAAA,UACtK,gBAAAA,KAAC,OAAG,eAAK,cAAc,UAAU,iDAAiD,KAAK,OAAO,MAAM,KAAK,UAAU,yDAAyD,iCAAiC,KAAK,OAAO,KAAI;AAAA,UAC7N,gBAAAA,KAAC,YAAS,MAAM,KAAK,aAAa;AAAA,UACjC,QAAQ,qBAAC,OAAE,WAAW,oBAAoB,MAAM,MAAM,QAAQ,KAAK,cAAc,aAAa,WAAW,QAAW,KAAI,uBAAsB;AAAA;AAAA,YAAM,KAAK,cAAc,UAAU,UAAU,KAAK,cAAc,aAAa,aAAa;AAAA,aAAW;AAAA,WACtP,IAAM,KAAK,WAAW,aAAa,iCAAE;AAAA,0BAAAA,KAAC,OAAE,MAAK,UAAS,wCAA0B;AAAA,UAAI,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,MAAM,SAAS,MAAM,IAAI,MAAM,GAAG,6BAAe;AAAA,WAAS,IAC3M,KAAK,WAAW,YAAY,gBAAAA,KAAC,OAAE,MAAK,UAAS,gEAAkD,IAC/F,KAAK,WAAW,cAAc,iCAAE;AAAA,0BAAAA,KAAC,OAAE,MAAK,SAAQ,yFAA2E;AAAA,UAAI,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,MAAM,SAAS,MAAM,IAAI,QAAQ,GAAG,gCAAkB;AAAA,WAAS,IAC7P,KAAK,WAAW,iBAAiB,gBAAAA,KAAC,OAAE,MAAK,SAAQ,2FAA6E,IAC9H,gBAAAA,KAAC,OAAE,gGAAkF;AAAA,QACxF,MAAM,SAAS,gBAAAA,KAAC,OAAE,MAAK,SAAQ,WAAU,oBAAoB,eAAK,OAAM;AAAA,QACxE,QAAQ,KAAK,WAAW,aAAa,EAAE,UAAU,KAAK,WAAW,cAAc,CAAC,YAAY,gBAAAA,KAAA,YAC1F,WAAC,aAAa,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,MAAM,cAAc,IAAI,GAAG,4BAAc,IAAY,qBAAC,cAAS,WAAU,aAAY;AAAA,0BAAAA,KAAC,YAAO,kDAAoC;AAAA,UACrN,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,YAAY;AAAE,kBAAM,UAAU,MAAM,QAAQ,IAAI,EAAE,QAAQ,SAAS,SAAS,KAAK,CAAC;AAAG,gBAAI,QAAQ,UAAW,eAAc,KAAK;AAAA,UAAE,GAAG,0BAAY;AAAA,UAAU;AAAA,UACjO,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,MAAM,cAAc,KAAK,GAAG,0BAAY;AAAA,WACjH,GACF;AAAA,QACA,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,QAAQ,SAAS,OAAO,oCAAsB;AAAA,SACvH;AAAA,IACF,GAAE;AAAA,IACF,gBAAAA,KAAC,kBAAe,OAAO,QAAQ,OAAO;AAAA,KACxC;AACF;AAEA,SAAS,iBAAiB,EAAE,WAAW,YAAY,GAAoF;AACrI,QAAM,SAAS,kBAAkB;AACjC,QAAM,cAAc,sBAAsB,SAAS;AACnD,QAAM,CAAC,cAAc,eAAe,IAAIC,UAAS,EAAE;AACnD,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAS,EAAE;AAC3C,QAAM,CAAC,SAAS,UAAU,IAAIA,UAAS,EAAE;AACzC,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,KAAK;AACpD,QAAM,UAAU,mBAAmB,cAAc,eAAe,EAAE;AAClE,QAAM,UAAU,kBAAkB,WAAW;AAC7C,QAAM,OAAO,QAAQ,MAAM,WAAW;AACtC,EAAAC,WAAU,MAAM;AAAE,oBAAgB,EAAE;AAAG,gBAAY,EAAE;AAAG,mBAAe,KAAK;AAAG,eAAW,EAAE;AAAA,EAAE,GAAG,CAAC,QAAQ,SAAS,CAAC;AACpH,EAAAA,WAAU,MAAM;AACd,QAAI,YAAY,WAAW,WAAW,YAAY,MAAM,WAAW,EAAG,iBAAgB,YAAY,MAAM,CAAC,EAAG,EAAE;AAAA,EAChH,GAAG,CAAC,WAAW,CAAC;AAChB,EAAAA,WAAU,MAAM;AACd,QAAI,QAAQ,WAAW,WAAW,QAAQ,MAAM,WAAW,EAAG,aAAY,QAAQ,MAAM,CAAC,EAAG,EAAE;AAAA,EAChG,GAAG,CAAC,OAAO,CAAC;AACZ,SAAO,iCACL;AAAA,oBAAAF,KAAC,gBAAa,UAAU,aAAa,OAAM,2FAAsF,qBAAS,qBAAC,UAAK,WAAU,aAAY,UAAU,WAAS;AACvL,YAAM,eAAe;AACrB,UAAI,cAAc,QAAS,MAAK,QAAQ,IAAI,EAAE,MAAM,SAAS,cAAc,QAAQ,CAAC;AAAA,eAC3E,cAAc,WAAY,MAAK,QAAQ,IAAI,EAAE,MAAM,cAAc,OAAO,EAAE,WAAW,cAAc,eAAe,SAAS,EAAE,CAAC;AAAA,UAClI,MAAK,QAAQ,IAAI,EAAE,MAAM,cAAc,OAAO,EAAE,WAAW,aAAa,EAAE,CAAC;AAAA,IAClF,GACE;AAAA,2BAAC,WAAM,WAAU,SAAQ;AAAA;AAAA,QAAU,qBAAC,YAAO,WAAW,YAAY,OAAO,cAAc,UAAU,MAAM,UAAU,WAAS;AAAE,0BAAgB,MAAM,OAAO,KAAK;AAAG,sBAAY,EAAE;AAAG,yBAAe,KAAK;AAAA,QAAE,GAAG,UAAQ,MACjN;AAAA,0BAAAA,KAAC,YAAO,OAAM,IAAG,iCAAmB;AAAA,UAAU,MAAM,IAAI,UAAQ,gBAAAA,KAAC,YAAqB,OAAO,KAAK,IAAK,eAAK,WAAW,KAAK,eAA/C,KAAK,EAAsD,CAAS;AAAA,WACnJ;AAAA,SAAS;AAAA,MACR,cAAc,WAAW,qBAAC,WAAM,WAAU,SAAQ;AAAA;AAAA,QAAe,gBAAAA,KAAC,WAAM,WAAW,YAAY,MAAK,SAAQ,UAAQ,MAAC,OAAO,SAAS,UAAU,MAAM,UAAU,WAAS,WAAW,MAAM,OAAO,KAAK,GAAG,aAAY,qBAAoB;AAAA,SAAE;AAAA,MAC1O,cAAc,cAAc,iCAC3B;AAAA,wBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,CAAC,gBAAgB,MAAM,SAAS,MAAM;AAAE,yBAAe,IAAI;AAAG,kBAAQ,MAAM;AAAA,QAAE,GAAG,gCAAkB;AAAA,QAC1J,eAAe,gBAAAA,KAAC,gBAAa,UAAU,SAAS,OAAM,qDAAqD,qBAAS,qBAAC,WAAM,WAAU,SAAQ;AAAA;AAAA,UAAe,qBAAC,YAAO,WAAW,YAAY,UAAQ,MAAC,OAAO,UAAU,UAAU,MAAM,UAAU,WAAS,YAAY,MAAM,OAAO,KAAK,GACrR;AAAA,4BAAAA,KAAC,YAAO,OAAM,IAAG,6BAAe;AAAA,YAAU,MAAM,IAAI,YAAU,gBAAAA,KAAC,YAAuB,OAAO,OAAO,IAAK,iBAAO,WAArC,OAAO,EAAsC,CAAS;AAAA,aACnI;AAAA,WAAS,GAAS;AAAA,SACpB;AAAA,MACA,gBAAAA,KAAC,OAAE,WAAU,iCAAgC,yIAA2H;AAAA,MACxK,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,QAAQ,CAAC,gBAAiB,cAAc,WAAW,CAAC,QAAQ,KAAK,KAAO,cAAc,eAAe,CAAC,YAAY,CAAC,eAAe,QAAQ,WAAW,UAAY,iBAAO,qBAAgB,mBAAkB;AAAA,OAC3Q,GAAQ;AAAA,IACR,gBAAAA,KAAC,kBAAe,OAAO,QAAQ,OAAO;AAAA,KACxC;AACF;AAKO,SAAS,eAAe,EAAE,WAAW,gBAAgB,IAAI,YAAY,GAAG,GAAwB;AACrG,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAS,aAAa;AACtD,QAAM,QAAQ,YAAY;AAC1B,QAAM,KAAK,MAAM;AACjB,EAAAC,WAAU,MAAM,YAAY,aAAa,GAAG,CAAC,WAAW,aAAa,CAAC;AACtE,SAAO,qBAAC,SAAI,WAAW,aAAa,SAAS,IAC3C;AAAA,yBAAC,aAAQ,WAAW,YAAY,cAAY,GAAG,OAAO,SAAS,CAAC,YAC9D;AAAA,2BAAC,QAAG,WAAU,yBAAwB;AAAA;AAAA,QAAS,OAAO,SAAS;AAAA,SAAE;AAAA,MAChE,cAAc,cAAc,gBAAAF,KAAC,OAAE,mJAAqI;AAAA,MACrK,gBAAAA,KAAC,gBAAa,UAAU,OAAO,OAAM,yCAAyC,mBAAO;AACnF,cAAM,WAAW,IAAI,OAAO,UAAQ,KAAK,cAAc,aAAa,KAAK,WAAW,UAAU;AAC9F,eAAO,SAAS,SAAS,iCAAE;AAAA,0BAAAA,KAAC,WAAM,SAAS,IAAI,2BAAa;AAAA,UAAQ,qBAAC,YAAO,IAAQ,WAAW,YAAY,OAAO,UAAU,UAAU,WAAS,YAAY,MAAM,OAAO,KAAK,GAC3K;AAAA,4BAAAA,KAAC,YAAO,OAAM,IAAG,sCAAwB;AAAA,YAAU,SAAS,IAAI,UAAQ,gBAAAA,KAAC,YAAO,OAAO,KAAK,IAAmB,eAAK,SAAS,KAAK,WAA7B,KAAK,EAAgC,CAAS;AAAA,aACrJ;AAAA,WAAS,IAAM,qBAAC,OAAE;AAAA;AAAA,UAAI,OAAO,SAAS;AAAA,UAAE;AAAA,WAAqB;AAAA,MAC/D,GAAE;AAAA,MACD,CAAC,YAAY,cAAc,SAAS,gBAAAA,KAAC,oBAAiC,WAAsB,aAAa,UAAQ;AAAE,oBAAY,KAAK,EAAE;AAAG,cAAM,MAAM;AAAA,MAAE,KAA5F,SAA+F;AAAA,MAC1J,YAAY,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,SAAS,MAAM,YAAY,EAAE,GAAG,iCAAmB;AAAA,OAChH;AAAA,IACC,WAAW,gBAAAA,KAAC,4BAAwC,QAAQ,YAAlB,QAA4B,KAAM,cAAc,SAAS,cAAc,eAAe,gBAAAA,KAAC,iBAAc,WAAsB;AAAA,KACxK;AACF;AAGO,SAAS,gBAAgB,OAA4B;AAAE,SAAO,gBAAAA,KAAC,kBAAgB,GAAG,OAAO,WAAU,YAAW;AAAG;AACjH,SAAS,gBAAgB,OAA4B;AAAE,SAAO,gBAAAA,KAAC,kBAAgB,GAAG,OAAO,WAAU,YAAW;AAAG;AACjH,SAAS,aAAa,OAA4B;AAAE,SAAO,gBAAAA,KAAC,kBAAgB,GAAG,OAAO,WAAU,SAAQ;AAAG;AAC3G,SAAS,WAAW,OAA4B;AAAE,SAAO,gBAAAA,KAAC,kBAAgB,GAAG,OAAO,WAAU,OAAM;AAAG;AAGvG,SAAS,cAAc,EAAE,WAAW,YAAY,GAAG,GAA0D;AAClH,QAAM,SAAS,kBAAkB;AACjC,QAAM,SAAS,iBAAiB,SAAS;AACzC,QAAM,CAAC,SAAS,UAAU,IAAIC,UAAS,KAAK;AAC5C,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAwB,IAAI;AAC5D,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAS,EAAE;AACvC,QAAM,UAAU,kBAAkB,UAAQ,UAAU,KAAK,EAAE,CAAC;AAC5D,EAAAC,WAAU,MAAM;AAAE,eAAW,KAAK;AAAA,EAAE,GAAG,CAAC,OAAO,OAAO,KAAK,CAAC;AAC5D,EAAAA,WAAU,MAAM;AAAE,gBAAY,IAAI;AAAG,cAAU,EAAE;AAAG,YAAQ,MAAM;AAAA,EAAE,GAAG,CAAC,WAAW,QAAQ,QAAQ,KAAK,CAAC;AACzG,QAAM,OAAO,OAAO,MAAM,WAAW,aAAa,QAAQ,MAAM,WAAW;AAC3E,QAAM,QAAQ,CAAC,UAAkB,IAAI,KAAK,aAAa,SAAS,EAAE,OAAO,YAAY,UAAU,MAAM,CAAC,EAAE,OAAO,QAAQ,GAAG;AAC1H,SAAO,qBAAC,aAAQ,WAAW,GAAG,UAAU,IAAI,SAAS,IAAI,cAAY,GAAG,OAAO,SAAS,CAAC,WAAW,aAAW,MAC7G;AAAA,yBAAC,QAAG,WAAU,yBAAwB;AAAA;AAAA,MAAO,OAAO,SAAS;AAAA,MAAE;AAAA,OAAO;AAAA,IACrE,CAAC,OAAO,WAAW,gBAAAF,KAAC,OAAE,6EAA+D,IAAO,gBAAAA,KAAC,gBAAa,UAAU,OAAO,UAAU,OAAM,+CAA+C,WAAC,EAAE,WAAW,SAAS,MAAM,iCACrN;AAAA,OAAC,UAAU,cAAc,gBAAAA,KAAC,OAAE,4FAA8E;AAAA,MAC1G,CAAC,YAAY,gBAAAA,KAAC,OAAE,MAAK,SAAQ,wGAA0F;AAAA,MACvH,OAAO,QAAQ,gBAAAA,KAAC,OAAE,kHAAoG;AAAA,MACvH,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,QAAQ,CAAC,YAAY,CAAC,UAAU,cAAc,CAAC,UAAU,WAAW,SAAS,SAAS,KAAK,CAAC,CAAC,OAAO,QAAQ,OAAO,WAAW,SAAS,MAAM,KAAK,OAAO,IAAI,EAAE,QAAQ,QAAQ,CAAC,GAAG,kCAAoB;AAAA,OACxQ,GAAI;AAAA,IACH,OAAO,SAAS,qBAAC,SAAI,WAAU,iDAC9B;AAAA,2BAAC,QAAG,WAAU,eAAc;AAAA;AAAA,QAAc,MAAM,OAAO,MAAM,eAAe;AAAA,SAAE;AAAA,MAC9E,gBAAAA,KAAC,OAAE,WAAU,uBAAuB,iBAAO,MAAM,SAAS,iEAAgE;AAAA,MAC1H,gBAAAA,KAAC,OAAG,gCAAqB;AAAA,MACzB,qBAAC,WAAM,WAAU,0BAAyB;AAAA,wBAAAA,KAAC,WAAM,MAAK,YAAW,SAAS,SAAS,UAAU,MAAM,UAAU,WAAS,WAAW,MAAM,OAAO,OAAO,GAAG;AAAA,QAAE;AAAA,SAAoG;AAAA,MAC7P,CAAC,OAAO,aAAa,OAAO,MAAM,aAAa,KAAK,IAAI,KAAK,gBAAAA,KAAC,OAAE,MAAK,SAAQ,8EAAgE;AAAA,MAC9I,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,QAAQ,CAAC,WAAW,CAAC,OAAO,MAAM,MAAM,KAAK,KAAM,CAAC,OAAO,aAAa,OAAO,MAAM,aAAa,KAAK,IAAI,GAAI,SAAS,MAAM,KAAK,OAAO,IAAI,EAAE,QAAQ,YAAY,QAAQ,CAAC,GAAI,iBAAO,YAAY,4BAA4B,aAAa,MAAM,OAAO,MAAM,eAAe,CAAC,IAAG;AAAA,OACpV;AAAA,IACC,OAAO,aAAa,qBAAC,OAAE,MAAK,SAAQ;AAAA;AAAA,MAA0E;AAAA,OAAoB;AAAA,IAClI,OAAO,OAAO,IAAI,WAAS,qBAAC,aAAuB,WAAU,iDAC5D;AAAA,sBAAAA,KAAC,QAAG,WAAU,yBAAyB,gBAAM,WAAW,qBAAoB;AAAA,MAAK,gBAAAA,KAAC,OAAG,sBAAY,KAAK,GAAE;AAAA,MACvG,MAAM,aAAa,qBAAC,OAAE,MAAK,UAAS;AAAA;AAAA,QAAS,MAAM,UAAU,QAAQ,MAAM,GAAG;AAAA,SAAE;AAAA,MAChF,MAAM,WAAW,qBAAqB,MAAM,iBAAiB,UAAU,iCAAE;AAAA,wBAAAA,KAAC,OAAE,qGAAuF;AAAA,QAClK,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,MAAM,KAAK,QAAQ,IAAI,EAAE,MAAM,SAAS,SAAS,MAAM,GAAG,CAAC,GAAG,8BAAgB;AAAA,SAAS;AAAA,MAChK,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,MAAM,KAAK,OAAO,IAAI,EAAE,QAAQ,WAAW,SAAS,MAAM,GAAG,CAAC,GAAG,4BAAc;AAAA,MAAU;AAAA,MAC/J,MAAM,iBAAiB,WAAW,aAAa,MAAM,KAAK,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,MAAM,YAAY,MAAM,EAAE,GAAG,2BAAa,IAAY,qBAAC,cAAS,WAAU,aAAY;AAAA,wBAAAA,KAAC,YAAO,wGAA0F;AAAA,QACxT,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,YAAY;AAAE,gBAAM,SAAS,MAAM,OAAO,IAAI,EAAE,QAAQ,UAAU,SAAS,MAAM,IAAI,SAAS,KAAK,CAAC;AAAG,cAAI,OAAO,UAAW,aAAY,IAAI;AAAA,QAAE,GAAG,kCAAoB;AAAA,QAAU;AAAA,QACvP,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,MAAM,YAAY,IAAI,GAAG,yBAAW;AAAA,SAC7G;AAAA,SATwC,MAAM,EAUhD,CAAU;AAAA,IACV,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,UAAU,MAAM,SAAS,OAAO,SAAS,OAAO,mCAAqB;AAAA,IACnH,gBAAAA,KAAC,OAAE,WAAU,iCAAgC,kGAAoF;AAAA,IACjI,gBAAAA,KAAC,kBAAe,OAAO,OAAO,OAAO;AAAA,IAAE,gBAAAA,KAAC,kBAAe,OAAO,QAAQ,OAAO;AAAA,IAC5E,UAAU,gBAAAA,KAAC,4BAAyB,UAAqB,MAAQ;AAAA,KACpE;AACF;AAGO,SAAS,oBAAoB,EAAE,QAAQ,UAAU,YAAY,GAAG,GAA6D;AAClI,QAAM,WAAW,uBAAuB,QAAQ,QAAQ;AACxD,SAAO,qBAAC,aAAQ,WAAW,GAAG,UAAU,IAAI,SAAS,IAAI,cAAW,wBAClE;AAAA,oBAAAA,KAAC,QAAG,WAAU,iBAAgB,0BAAY;AAAA,IAC1C,gBAAAA,KAAC,gBAAa,UAAU,UAAU,OAAM,yCAAyC,qBAAS,gBAAAA,KAAC,QAAG,MAAK,OAAM,aAAU,UAAS,cAAW,YAAW,WAAU,aACzJ,gBAAM,IAAI,aAAW,qBAAC,QAAoB,WAAU,qCAAoC,kBAAgB,QAAQ,WAC/G;AAAA,2BAAC,OAAE,WAAU,iCAAiC;AAAA,gBAAQ,cAAc,OAAO,aAAa;AAAA,QAAW;AAAA,QAAI,QAAQ;AAAA,QAAK;AAAA,QAAG,gBAAAA,KAAC,UAAK,UAAU,QAAQ,WAAY,kBAAQ,WAAU;AAAA,SAAO;AAAA,MACpL,gBAAAA,KAAC,OAAE,WAAU,mCAAmC,kBAAQ,QAAQ,oBAAmB;AAAA,MACnF,qBAAC,OAAE,WAAU,WAAW;AAAA,gBAAQ;AAAA,QAAQ,QAAQ,YAAY,SAAM,QAAQ,SAAS,KAAK;AAAA,SAAG;AAAA,SAH9D,QAAQ,EAIvC,CAAK,GACP,GAAM;AAAA,IACN,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,SAAS,SAAS,OAAO,8BAAgB;AAAA,KACzF;AACF;AAGO,SAAS,qBAAqB,EAAE,QAAQ,YAAY,GAAG,GAA2C;AACvG,QAAM,UAAU,wBAAwB,MAAM;AAC9C,QAAM,CAAC,UAAU,WAAW,IAAIC,UAAsD,IAAI;AAC1F,QAAM,WAAW,UAAU,WAAW,SAAS,SAAS,WAAW;AACnE,SAAO,qBAAC,SAAI,WAAW,aAAa,SAAS,IAC3C;AAAA,yBAAC,aAAQ,WAAW,YAAY,cAAW,yBAAwB;AAAA,sBAAAD,KAAC,QAAG,WAAU,yBAAwB,2BAAa;AAAA,MACpH,gBAAAA,KAAC,gBAAa,UAAU,SAAS,OAAM,8DAA8D,qBAAS,gBAAAA,KAAC,SAAI,cAAW,yBAAwB,WAAU,wBAC7J,gBAAM,IAAI,YAAU,qBAAC,YAAO,MAAK,UAAyB,WAAW,aAAa,gBAAc,OAAO,OAAO,UAAU,SAAS,MAAM,YAAY,EAAE,QAAQ,UAAU,OAAO,GAAG,CAAC,GAAI;AAAA,eAAO;AAAA,QAAS;AAAA,QAAI,OAAO;AAAA,WAAlK,OAAO,EAAkK,CAAS,GACpO,GAAO;AAAA,OACT;AAAA,IACC,YAAY,gBAAAA,KAAC,uBAAkD,QAAgB,YAAzC,GAAG,MAAM,IAAI,QAAQ,EAAwC;AAAA,KACtG;AACF;;;AG1OA,SAAS,aAAAG,YAAW,YAAAC,iBAAgB;AAuChC,SAIoR,YAAAC,WAJpR,OAAAC,MAGE,QAAAC,aAHF;AAjCG,SAAS,gBAAgB,OAAuB;AACrD,MAAI,YAAY,KAAK,KAAK,KAAK,CAAC,SAAS,KAAK,KAAK,EAAG,QAAO;AAC7D,QAAM,MAAM,IAAI,IAAI,KAAK;AACzB,MAAI,IAAI,aAAa,YAAY,IAAI,YAAY,IAAI,SAAU,OAAM,IAAI,MAAM,kCAAkC;AACjH,SAAO,IAAI;AACb;AAEO,SAAS,eAAe,QAAgB;AAC7C,QAAM,SAAS,kBAAkB;AACjC,QAAM,WAAW,mBAAmB,aAAW;AAC7C,QAAI,CAAC,OAAO,QAAS,OAAM,IAAI,MAAM,yCAAyC;AAC9E,WAAO,OAAO,QAAQ,KAAK,QAAQ,OAAO;AAAA,EAC5C,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,OAAO;AACzC,QAAM,WAAW,mBAAiD,OAAO,EAAE,QAAQ,MAAM;AACvF,QAAI,CAAC,OAAO,WAAW,SAAS,WAAW,QAAS,OAAM,IAAI,MAAM,6CAA6C;AACjH,UAAM,EAAE,MAAM,WAAW,MAAM,IAAI,SAAS;AAC5C,QAAI,CAAC,WAAW,CAAC,MAAM,KAAK,EAAG,OAAM,IAAI,MAAM,6CAA6C;AAC5F,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,QAAQ,CAAC,OAAO,SAAS,KAAK,KAAK,eAAe,KAAK,KAAK,KAAK,mBAAmB,KAAK,UAAU,aAAa,aAAa,CAAC,UAAU,WAAW,UAAU,SAAS,OAAQ,OAAM,IAAI,MAAM,+CAA+C;AAC3Q,WAAO,iBAAiB,MAAM,OAAO,QAAQ,SAAS,MAAM,GAAG,GAAG;AAAA,EACpE,CAAC;AACD,EAAAC,WAAU,MAAM,SAAS,MAAM,GAAG,CAAC,QAAQ,SAAS,KAAK,CAAC;AAC1D,SAAO,EAAE,UAAU,GAAG,UAAU,WAAW,CAAC,CAAC,OAAO,QAAQ;AAC9D;AAGO,SAAS,YAAY,EAAE,QAAQ,YAAY,GAAG,GAA2C;AAC9F,QAAM,UAAU,eAAe,MAAM;AACrC,QAAM,CAAC,gBAAgB,iBAAiB,IAAIC,UAAwB,IAAI;AACxE,QAAM,eAAe,QAAQ,SAAS,WAAW,UAC7C,KAAK,UAAU,CAAC,QAAQ,QAAQ,SAAS,MAAM,OAAO,QAAQ,SAAS,MAAM,KAAK,IAAI,CAAC,IACvF;AACJ,QAAM,UAAU,iBAAiB,QAAQ,mBAAmB;AAC5D,SAAO,gBAAAF,MAAC,aAAQ,WAAW,GAAG,UAAU,IAAI,SAAS,IAAI,cAAW,qBAClE;AAAA,oBAAAD,KAAC,QAAG,WAAU,yBAAwB,4BAAc;AAAA,IACnD,CAAC,QAAQ,YAAY,gBAAAA,KAAC,OAAE,qDAAuC,IAAO,gBAAAA,KAAC,gBAAa,UAAU,QAAQ,UAAU,OAAM,yBAAyB,qBAAS,gBAAAC,MAAAF,WAAA,EACvJ;AAAA,sBAAAC,KAAC,QAAG,WAAU,eAAe,gBAAM,OAAM;AAAA,MACzC,gBAAAC,MAAC,OAAG;AAAA,cAAM,UAAU,MAAM;AAAA,QAAK;AAAA,QAAK,MAAM,UAAU,MAAM;AAAA,QAAM;AAAA,SAAkB;AAAA,MACjF,MAAM,UAAU,SAAS,SAAS,gBAAAA,MAAC,OAAE,MAAK,UAAS;AAAA;AAAA,QAA+B,MAAM,UAAU,aAAa,sBAAsB,sEAAsE;AAAA,SAAG,IAAO,MAAM,UAAU,aAAa,aAAa,MAAM,KAAK,OAAO,gBAAAA,MAAAF,WAAA,EAChR;AAAA,wBAAAE,MAAC,OAAG;AAAA,cAAI,KAAK,aAAa,SAAS,EAAE,OAAO,YAAY,UAAU,MAAM,CAAC,EAAE,OAAO,MAAM,KAAK,KAAK,eAAe;AAAA,UAAE;AAAA,UAAc,MAAM,KAAK,KAAK;AAAA,UAAY;AAAA,WAAe;AAAA,QAC5K,gBAAAD,KAAC,OAAE,WAAU,uBAAuB,gBAAM,SAAS,qDAAoD;AAAA,QACvG,gBAAAC,MAAC,WAAM,WAAU,0BAAyB;AAAA,0BAAAD,KAAC,WAAM,MAAK,YAAW,SAAS,SAAS,UAAU,WAAS,kBAAkB,MAAM,OAAO,UAAU,eAAe,IAAI,GAAG;AAAA,UAAE;AAAA,WAAkC;AAAA,QACzM,gBAAAA,KAAC,YAAO,MAAK,UAAS,WAAW,oBAAoB,UAAU,CAAC,WAAW,CAAC,MAAM,MAAM,KAAK,KAAK,QAAQ,MAAM,WAAW,WAAW,SAAS,MAAM,KAAK,QAAQ,IAAI,EAAE,QAAQ,CAAC,GAAG,kCAAoB;AAAA,QACxM,gBAAAA,KAAC,OAAE,WAAU,iCAAgC,iGAAmF;AAAA,SAClI,IAAM,gBAAAC,MAAC,OAAG;AAAA,cAAM,UAAU,aAAa,sBAAsB,wEAAwE;AAAA,QAAuC;AAAA,QAAY,MAAM,UAAU;AAAA,QAAS;AAAA,SAAC;AAAA,MAClN,gBAAAD,KAAC,YAAO,MAAK,UAAS,WAAW,aAAa,SAAS,QAAQ,SAAS,OAAO,kCAAoB;AAAA,OACrG,GAAI;AAAA,IACH,QAAQ,MAAM,WAAW,eAAe,WAAW,gBAAAA,KAAC,OAAE,WAAU,aAAY,MAAM,QAAQ,MAAM,OAAO,KAAI,uBAAsB,kCAAoB;AAAA,IACtJ,gBAAAA,KAAC,kBAAe,OAAO,QAAQ,OAAO;AAAA,KACxC;AACF;","names":["useEffect","useState","useEffect","useRef","useRef","orders","order","useEffect","jsx","jsx","useState","useEffect","useEffect","useState","Fragment","jsx","jsxs","useEffect","useState"]}
@@ -42,8 +42,16 @@ export type ConnectChannelInput = {
42
42
  kind: 'order';
43
43
  orderId: string;
44
44
  };
45
+ /** Read-only, authenticated conversation access; no setup, purchase, or activation stubs. */
46
+ export interface ChannelsReadClient {
47
+ /** Changes whenever the authenticated agent or owner changes. Not an auth credential. */
48
+ scope: string;
49
+ lines: Pick<LinesClient, 'get' | 'threads'> & {
50
+ list(): Promise<Line[]>;
51
+ };
52
+ }
45
53
  /**
46
- * The one authenticated, agent-scoped boundary. Keep this object stable.
54
+ * The one authenticated, agent-scoped management boundary. Keep this object stable.
47
55
  *
48
56
  * `lines` delegates to Sandbox SDK client.lines (list MUST be scoped to this
49
57
  * agent). `setup` is the host's existing Hub/hosted-agent control plane: it
@@ -57,12 +65,8 @@ export type ConnectChannelInput = {
57
65
  * The hosted-agent export is server-only. Its existing attachLine operation
58
66
  * belongs in setup.activate after proof validation, never in this browser bundle.
59
67
  */
60
- export interface ChannelsClient {
61
- /** Changes whenever the authenticated agent or owner changes. Not an auth credential. */
62
- scope: string;
63
- lines: Pick<LinesClient, 'fromConnection' | 'get' | 'threads'> & {
64
- list(): Promise<Line[]>;
65
- };
68
+ export interface ChannelsClient extends ChannelsReadClient {
69
+ lines: ChannelsReadClient['lines'] & Pick<LinesClient, 'fromConnection'>;
66
70
  setup: {
67
71
  connections(transport: LineTransport, context: ChannelReadContext): Promise<ChannelConnection[]>;
68
72
  whatsappNumbers(connectionId: string, context: ChannelReadContext): Promise<ChannelNumber[]>;
@@ -143,6 +143,7 @@ function LineSetup({ client, scopeKey, initialTargetId, targetLabel, canManage,
143
143
  const reconnectChoice = Boolean(selected && occupied?.length === 1 && occupiedLine && canOfferReconnect(occupiedLine, selected));
144
144
  const reconnecting = Boolean(reconnectChoice && selected && occupiedLine && matchesLineIdentity(occupiedLine, selected.identity, enteredNumber));
145
145
  const blockedByExistingLine = Boolean(occupied?.length && !reconnecting);
146
+ const answeringCount = snapshot?.lines.filter((line) => line.answering).length ?? 0;
146
147
  async function connect() {
147
148
  if (!canManage || !canConnect || !selected || !selectedTarget || !selectedMode || needsNumber && !enteredNumber || blockedByExistingLine || busy || loading || refreshFailed) return;
148
149
  const requestIncarnation = incarnation.current;
@@ -205,25 +206,30 @@ function LineSetup({ client, scopeKey, initialTargetId, targetLabel, canManage,
205
206
  " can use one line per transport."
206
207
  ] })
207
208
  ] }),
208
- snapshot && /* @__PURE__ */ jsxs("span", { className: "tangle-lines__count", children: [
209
- snapshot.lines.filter((line) => line.answering).length,
209
+ answeringCount > 1 && /* @__PURE__ */ jsxs("span", { className: "tangle-lines__count", children: [
210
+ answeringCount,
210
211
  " answering"
211
212
  ] })
212
213
  ] }),
213
214
  error && /* @__PURE__ */ jsxs("div", { className: "tangle-lines__error", role: "alert", children: [
214
- /* @__PURE__ */ jsx("span", { children: error }),
215
+ /* @__PURE__ */ jsxs("div", { children: [
216
+ /* @__PURE__ */ jsx("strong", { children: refreshFailed ? "Lines are unavailable" : "Line action failed" }),
217
+ /* @__PURE__ */ jsx("p", { children: error })
218
+ ] }),
215
219
  (!snapshot || refreshFailed) && /* @__PURE__ */ jsx("button", { type: "button", disabled: loading, onClick: retry, children: "Retry" })
216
220
  ] }),
217
221
  loading && /* @__PURE__ */ jsx("p", { className: "tangle-lines__muted", role: "status", children: "Loading lines\u2026" }),
218
222
  snapshot && /* @__PURE__ */ jsxs(Fragment, { children: [
219
223
  /* @__PURE__ */ jsxs("div", { className: "tangle-lines__list", children: [
220
- snapshot.lines.filter((line) => line.status !== "released").length === 0 && /* @__PURE__ */ jsx("p", { className: "tangle-lines__empty", children: "No line answers for this workspace yet." }),
224
+ snapshot.lines.filter((line) => line.status !== "released").length === 0 && /* @__PURE__ */ jsxs("div", { className: "tangle-lines__empty", children: [
225
+ /* @__PURE__ */ jsx("strong", { children: "No lines connected" }),
226
+ /* @__PURE__ */ jsx("p", { children: canManage && showConnectionSetup ? "Connect an owned identity below to let this workspace answer messages." : "There are no connected lines in this workspace." })
227
+ ] }),
221
228
  snapshot.lines.filter((line) => line.status !== "released").map((line) => /* @__PURE__ */ jsxs("div", { className: "tangle-lines__row", children: [
222
229
  /* @__PURE__ */ jsxs("div", { className: "tangle-lines__row-main", children: [
223
- /* @__PURE__ */ jsxs("span", { className: "tangle-lines__eyebrow", children: [
224
- TRANSPORT[line.transport],
225
- " \xB7 ",
226
- line.answering ? "Answering" : line.targetId === null ? "Disconnected" : line.status === "active" ? "Awaiting member" : line.status
230
+ /* @__PURE__ */ jsxs("div", { className: "tangle-lines__row-heading", children: [
231
+ /* @__PURE__ */ jsx("span", { className: "tangle-lines__transport", children: TRANSPORT[line.transport] }),
232
+ /* @__PURE__ */ jsx("span", { className: `tangle-lines__status${line.answering ? " tangle-lines__status--answering" : ""}`, children: line.answering ? "Answering" : line.targetId === null ? "Disconnected" : line.status === "active" ? "Awaiting member" : line.status })
227
233
  ] }),
228
234
  /* @__PURE__ */ jsx("strong", { children: line.routerAddress ?? line.address }),
229
235
  line.connect && line.targetId !== null && /* @__PURE__ */ jsxs("p", { children: [
@@ -253,6 +259,7 @@ function LineSetup({ client, scopeKey, initialTargetId, targetLabel, canManage,
253
259
  ] }, line.id))
254
260
  ] }),
255
261
  canManage && showConnectionSetup && (snapshot.connections === null || choices.length > 0 || allChoices.length === 0) && /* @__PURE__ */ jsxs("div", { className: "tangle-lines__setup", children: [
262
+ /* @__PURE__ */ jsx("span", { className: "tangle-lines__overline", children: "New line" }),
256
263
  /* @__PURE__ */ jsx("h3", { children: "Connect an identity you own" }),
257
264
  /* @__PURE__ */ jsx("p", { children: "Choose an identity already connected in Hub. Billing details appear below." }),
258
265
  snapshot.connections === null ? /* @__PURE__ */ jsxs("div", { className: "tangle-lines__error", role: "status", children: [
@@ -591,9 +598,18 @@ function ApplicationLineSetupScope({ client, enabled, ...props }) {
591
598
  }), [client, canConnect, address, turnsPerDay]);
592
599
  return /* @__PURE__ */ jsxs4(Fragment4, { children: [
593
600
  props.canManage && /* @__PURE__ */ jsxs4("section", { className: "tangle-lines tangle-lines--application", "aria-label": "Application access", children: [
594
- /* @__PURE__ */ jsx4("h2", { children: "Text your workspace" }),
595
- /* @__PURE__ */ jsx4("p", { children: "Use the same agent, conversation and saved work. Only the sender you authorize can issue commands." }),
596
- !enabled ? /* @__PURE__ */ jsx4("p", { role: "status", children: "New connections are disabled. You can still disconnect an existing line below." }) : /* @__PURE__ */ jsxs4(Fragment4, { children: [
601
+ /* @__PURE__ */ jsxs4("header", { className: "tangle-lines__application-heading", children: [
602
+ /* @__PURE__ */ jsx4("h2", { children: "Text your workspace" }),
603
+ /* @__PURE__ */ jsx4("p", { children: "Continue a conversation from a number or mailbox you own. The agent keeps the same context and saved work." })
604
+ ] }),
605
+ !enabled ? /* @__PURE__ */ jsxs4("div", { className: "tangle-lines__notice", role: "status", children: [
606
+ /* @__PURE__ */ jsx4("strong", { children: "New connections are disabled" }),
607
+ /* @__PURE__ */ jsx4("p", { children: "You can still review and disconnect an existing line below." })
608
+ ] }) : /* @__PURE__ */ jsxs4("div", { className: "tangle-lines__authorization", children: [
609
+ /* @__PURE__ */ jsxs4("div", { className: "tangle-lines__authorization-heading", children: [
610
+ /* @__PURE__ */ jsx4("h3", { children: "Authorize a sender" }),
611
+ /* @__PURE__ */ jsx4("p", { children: "Only this sender can issue commands through the line you connect." })
612
+ ] }),
597
613
  /* @__PURE__ */ jsxs4("div", { className: "tangle-lines__fields", children: [
598
614
  /* @__PURE__ */ jsxs4("label", { children: [
599
615
  "Authorized sender",
@@ -640,7 +656,7 @@ function ApplicationLineSetupScope({ client, enabled, ...props }) {
640
656
  ),
641
657
  "I authorize this sender to work in the conversation I select below using my application access and compute budget."
642
658
  ] }),
643
- /* @__PURE__ */ jsx4("p", { children: "The daily message limit is not a dollar cap. The first inbound message establishes messaging consent. STOP stops replies, not an already accepted task; cancel that task in the application." })
659
+ /* @__PURE__ */ jsx4("p", { className: "tangle-lines__fine-print", children: "The daily message limit is not a dollar cap. The first inbound message establishes messaging consent. STOP stops replies, not an already accepted task; cancel that task in the application." })
644
660
  ] })
645
661
  ] }),
646
662
  /* @__PURE__ */ jsx4(LineSetup, { ...props, targetLabel: props.targetLabel ?? "Conversation", client: lineClient, canConnect, showConnectionSetup: enabled })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/hosted-agent/react/LineSetup.tsx","../../../src/hosted-agent/react/LineMembers.tsx","../../../src/hosted-agent/react/LineBilling.tsx","../../../src/hosted-agent/react/ApplicationLineSetup.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { Line } from '@tangle-network/sandbox'\nimport type {\n LineBoxMode, LineConnectionOption, LineIdentityKind, LineIdentityOption,\n LineSetupLine, LineSetupProps, LineSetupSnapshot,\n} from './contracts'\n\nconst useBrowserLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect\n\nconst TRANSPORT: Record<Line['transport'], string> = {\n imessage: 'iMessage', sms: 'SMS', whatsapp: 'WhatsApp', email: 'Email',\n}\nconst IDENTITY: Record<LineIdentityKind, string> = {\n handle: 'Inkbox handle', number: 'Dedicated number', email: 'Email line',\n}\n\ntype Choice = { key: string; connection: LineConnectionOption; identity: LineIdentityOption }\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : 'The line request failed. Try again.'\n}\n\nfunction dateTime(value: string): string {\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : date.toLocaleString()\n}\n\nfunction choicesFor(snapshot: LineSetupSnapshot): Choice[] {\n return (snapshot.connections ?? []).flatMap(connection => connection.identities.map((identity, index) => ({\n key: `${connection.id}:${index}`,\n connection,\n identity,\n })))\n}\n\nfunction canOfferReconnect(line: LineSetupLine, choice: Choice): boolean {\n if (line.connectionId !== choice.connection.id || line.transport !== choice.identity.transport || line.targetId !== null) return false\n if (line.providerNumberId === null) return line.transport !== 'whatsapp' && !choice.identity.phoneNumberId && !choice.identity.requiresPhoneNumberId\n return choice.identity.phoneNumberId === line.providerNumberId ||\n (!choice.identity.phoneNumberId && choice.identity.requiresPhoneNumberId === true)\n}\n\nfunction matchesLineIdentity(line: LineSetupLine, identity: LineIdentityOption, numberId: string): boolean {\n if (line.transport !== identity.transport) return false\n if (line.providerNumberId === null) return line.transport !== 'whatsapp' && !identity.phoneNumberId && !identity.requiresPhoneNumberId\n return numberId === line.providerNumberId\n}\n\n/** Set up an owned identity through a host route backed by sandbox.lines and Hub. */\nexport function LineSetup({ client, scopeKey, initialTargetId, targetLabel, canManage, canConnect = canManage, showConnectionSetup = true, onNotice }: LineSetupProps) {\n const clientRef = useRef(client)\n clientRef.current = client\n const sequence = useRef(0)\n const incarnation = useRef(0)\n const confirmButton = useRef<HTMLButtonElement>(null)\n const heading = useRef<HTMLHeadingElement>(null)\n const disconnectTriggers = useRef(new Map<string, HTMLButtonElement>())\n const restoreFocusTo = useRef<string | null>(null)\n useBrowserLayoutEffect(() => {\n incarnation.current++\n return () => { incarnation.current++ }\n }, [scopeKey, initialTargetId])\n const [loadedSnapshot, setLoadedSnapshot] = useState<{ scopeKey: string; initialTargetId: string | undefined; value: LineSetupSnapshot } | null>(null)\n const snapshot = loadedSnapshot?.scopeKey === scopeKey && loadedSnapshot.initialTargetId === initialTargetId ? loadedSnapshot.value : null\n const [loading, setLoading] = useState(true)\n const [refreshFailed, setRefreshFailed] = useState(false)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [kind, setKind] = useState<LineIdentityKind>('handle')\n const [choiceKey, setChoiceKey] = useState('')\n const [targetId, setTargetId] = useState(initialTargetId ?? '')\n const [boxMode, setBoxMode] = useState<LineBoxMode>('per-member')\n const [phoneNumberId, setPhoneNumberId] = useState('')\n const [confirmLineId, setConfirmLineId] = useState<string | null>(null)\n\n function stillCurrent(requestIncarnation: number): boolean {\n return requestIncarnation === incarnation.current\n }\n\n async function reload(requestIncarnation: number): Promise<LineSetupSnapshot | null> {\n const request = ++sequence.current\n try {\n const next = await clientRef.current.load()\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return null\n setLoadedSnapshot({ scopeKey, initialTargetId, value: next })\n setError(null)\n setRefreshFailed(false)\n setTargetId(current => next.targets.some(target => target.id === current)\n ? current : next.targets.find(target => target.id === initialTargetId)?.id ?? next.targets[0]?.id ?? '')\n setLoading(false)\n return next\n } catch (cause) {\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return null\n setError(message(cause))\n setRefreshFailed(true)\n setLoading(false)\n return null\n }\n }\n\n function retry() {\n if (loading) return\n setLoading(true)\n void reload(incarnation.current)\n }\n\n function closeConfirmation(lineId: string) {\n restoreFocusTo.current = lineId\n setConfirmLineId(null)\n }\n\n useEffect(() => {\n setLoading(true)\n setLoadedSnapshot(null)\n setError(null)\n setRefreshFailed(false)\n setBusy(false)\n setKind('handle')\n setChoiceKey('')\n setTargetId(initialTargetId ?? '')\n setBoxMode('per-member')\n setPhoneNumberId('')\n setConfirmLineId(null)\n restoreFocusTo.current = null\n void reload(incarnation.current)\n return () => { sequence.current++ }\n }, [scopeKey, initialTargetId])\n\n useEffect(() => {\n if (confirmLineId) confirmButton.current?.focus()\n }, [confirmLineId])\n\n useEffect(() => {\n const lineId = restoreFocusTo.current\n if (confirmLineId !== null || lineId === null) return\n restoreFocusTo.current = null\n const trigger = disconnectTriggers.current.get(lineId)\n if (trigger && !trigger.disabled) trigger.focus()\n else heading.current?.focus()\n }, [confirmLineId, snapshot, refreshFailed])\n\n const allChoices = snapshot ? choicesFor(snapshot) : []\n const choices = snapshot ? allChoices.filter(choice => {\n const occupied = snapshot.lines.filter(line => line.status !== 'released' && line.transport === choice.identity.transport)\n const [line] = occupied\n return occupied.length === 0 || (occupied.length === 1 && line !== undefined && canOfferReconnect(line, choice))\n }) : []\n const availableKinds = (['handle', 'number', 'email'] as const).filter(value => choices.some(choice => choice.identity.kind === value))\n const selectedKind = availableKinds.includes(kind) ? kind : availableKinds[0]\n const kindChoices = choices.filter(choice => choice.identity.kind === selectedKind)\n const selected = kindChoices.find(choice => choice.key === choiceKey) ?? kindChoices[0]\n const selectedTarget = snapshot?.targets.find(target => target.id === targetId)\n const selectedMode = selectedTarget?.modes.includes(boxMode) ? boxMode : selectedTarget?.modes[0]\n const enteredNumber = selected?.identity.phoneNumberId ?? phoneNumberId.trim()\n const needsNumber = selected?.identity.transport === 'whatsapp' || selected?.identity.requiresPhoneNumberId\n const occupied = selected && snapshot?.lines.filter(line => line.status !== 'released' && line.transport === selected.identity.transport)\n const [occupiedLine] = occupied || []\n const reconnectChoice = Boolean(selected && occupied?.length === 1 && occupiedLine && canOfferReconnect(occupiedLine, selected))\n const reconnecting = Boolean(reconnectChoice && selected && occupiedLine &&\n matchesLineIdentity(occupiedLine, selected.identity, enteredNumber))\n const blockedByExistingLine = Boolean(occupied?.length && !reconnecting)\n\n async function connect() {\n if (!canManage || !canConnect || !selected || !selectedTarget || !selectedMode || (needsNumber && !enteredNumber) || blockedByExistingLine || busy || loading || refreshFailed) return\n const requestIncarnation = incarnation.current\n setBusy(true)\n setError(null)\n try {\n await clientRef.current.connect({\n connectionId: selected.connection.id,\n transport: selected.identity.transport,\n ...(enteredNumber ? { phoneNumberId: enteredNumber } : {}),\n targetId: selectedTarget.id,\n boxMode: selectedMode,\n })\n if (!stillCurrent(requestIncarnation)) return\n const updated = await reload(requestIncarnation)\n if (!stillCurrent(requestIncarnation)) return\n if (!updated) {\n onNotice?.({ kind: 'error', message: 'Line connected, but its current status could not be loaded.' })\n return\n }\n const line = updated.lines.find(item => item.status !== 'released' && item.connectionId === selected.connection.id &&\n item.transport === selected.identity.transport && item.providerNumberId === (enteredNumber || null))\n onNotice?.({ kind: 'success', message: line?.answering ? 'The line is answering.' : 'Line connected. Add a member to start answers.' })\n } catch (cause) {\n if (!stillCurrent(requestIncarnation)) return\n const detail = message(cause)\n setError(detail)\n onNotice?.({ kind: 'error', message: detail })\n } finally {\n if (stillCurrent(requestIncarnation)) setBusy(false)\n }\n }\n\n async function disconnect(lineId: string) {\n if (busy || loading || refreshFailed) return\n const requestIncarnation = incarnation.current\n setBusy(true)\n setError(null)\n try {\n const expectedAttachmentId = snapshot?.lines.find(line => line.id === lineId)?.attachmentId ?? undefined\n await clientRef.current.disconnect(lineId, expectedAttachmentId)\n if (!stillCurrent(requestIncarnation)) return\n const updated = await reload(requestIncarnation)\n if (!stillCurrent(requestIncarnation)) return\n closeConfirmation(lineId)\n onNotice?.(updated\n ? { kind: 'success', message: 'The line stopped answering.' }\n : { kind: 'error', message: 'Line disconnected, but its current status could not be loaded.' })\n } catch (cause) {\n if (!stillCurrent(requestIncarnation)) return\n const detail = message(cause)\n setError(detail)\n onNotice?.({ kind: 'error', message: detail })\n } finally {\n if (stillCurrent(requestIncarnation)) setBusy(false)\n }\n }\n\n return <section className=\"tangle-lines\" aria-label=\"Agent lines\">\n <header className=\"tangle-lines__heading\">\n <div>\n <h2 ref={heading} tabIndex={-1}>Lines</h2>\n {snapshot && <p>{snapshot.workspaceName} can use one line per transport.</p>}\n </div>\n {snapshot && <span className=\"tangle-lines__count\">{snapshot.lines.filter(line => line.answering).length} answering</span>}\n </header>\n\n {error && <div className=\"tangle-lines__error\" role=\"alert\">\n <span>{error}</span>\n {(!snapshot || refreshFailed) && <button type=\"button\" disabled={loading} onClick={retry}>Retry</button>}\n </div>}\n {loading && <p className=\"tangle-lines__muted\" role=\"status\">Loading lines…</p>}\n\n {snapshot && <>\n <div className=\"tangle-lines__list\">\n {snapshot.lines.filter(line => line.status !== 'released').length === 0 &&\n <p className=\"tangle-lines__empty\">No line answers for this workspace yet.</p>}\n {snapshot.lines.filter(line => line.status !== 'released').map(line =>\n <div className=\"tangle-lines__row\" key={line.id}>\n <div className=\"tangle-lines__row-main\">\n <span className=\"tangle-lines__eyebrow\">{TRANSPORT[line.transport]} · {line.answering ? 'Answering' : line.targetId === null ? 'Disconnected' : line.status === 'active' ? 'Awaiting member' : line.status}</span>\n <strong>{line.routerAddress ?? line.address}</strong>\n {line.connect && line.targetId !== null && <p>To reach this agent, text <code>{line.connect}</code>.</p>}\n <p>{line.targetLabel ?? 'No agent or box assigned'}{line.boxMode && ` · ${line.boxMode === 'per-member' ? 'one box per member' : 'shared box'}`}</p>\n {line.lastTurn.kind === 'latest' ? <p>Last turn: {line.lastTurn.status} · {dateTime(line.lastTurn.at)}</p>\n : <p>{line.lastTurn.kind === 'none' ? 'No turns yet.' : 'Turn history unavailable.'}</p>}\n </div>\n {canManage && line.canDisconnect && line.targetId !== null && line.status === 'active' && <div className=\"tangle-lines__row-actions\">\n {confirmLineId === line.id ? <div className=\"tangle-lines__confirm\" role=\"group\" aria-label={`Disconnect ${line.address}?`}>\n <span>Disconnect this line?</span>\n <button ref={confirmButton} type=\"button\" className=\"tangle-lines__danger\" disabled={busy || loading || refreshFailed} onClick={() => void disconnect(line.id)}>Disconnect</button>\n <button type=\"button\" disabled={busy} onClick={() => closeConfirmation(line.id)}>Keep line</button>\n </div> : <button ref={node => { if (node) disconnectTriggers.current.set(line.id, node); else disconnectTriggers.current.delete(line.id) }} type=\"button\" className=\"tangle-lines__quiet\" disabled={busy || loading || refreshFailed} onClick={() => setConfirmLineId(line.id)}>Disconnect line</button>}\n </div>}\n </div>)}\n </div>\n\n {canManage && showConnectionSetup && (snapshot.connections === null || choices.length > 0 || allChoices.length === 0) && <div className=\"tangle-lines__setup\">\n <h3>Connect an identity you own</h3>\n <p>Choose an identity already connected in Hub. Billing details appear below.</p>\n {snapshot.connections === null ? <div className=\"tangle-lines__error\" role=\"status\">\n <span>Hub connections could not be read. Check Hub access and try again.</span>\n <button type=\"button\" disabled={loading} onClick={retry}>Retry</button>\n </div>\n : availableKinds.length === 0 ? <p className=\"tangle-lines__empty\">\n Connect an owned handle, number, or mailbox in Hub, then <button type=\"button\" disabled={loading} onClick={retry}>reload</button>.\n </p>\n : <>\n <div className=\"tangle-lines__kinds\" role=\"group\" aria-label=\"Identity type\">\n {availableKinds.map(value => <button key={value} type=\"button\" aria-pressed={selectedKind === value} onClick={() => { setKind(value); setChoiceKey(''); setPhoneNumberId('') }}>{IDENTITY[value]}</button>)}\n </div>\n <div className=\"tangle-lines__fields\">\n <label>Owned connection\n <select value={selected?.key ?? ''} onChange={event => { setChoiceKey(event.target.value); setPhoneNumberId('') }}>\n {kindChoices.map(choice => <option key={choice.key} value={choice.key}>{choice.connection.label} · {choice.identity.label}</option>)}\n </select>\n </label>\n <label>{targetLabel ?? 'Agent or box'}\n <select value={selectedTarget?.id ?? ''} onChange={event => setTargetId(event.target.value)}>\n {snapshot.targets.map(target => <option key={target.id} value={target.id}>{target.label}{targetLabel ? '' : ` · ${target.kind}`}</option>)}\n </select>\n </label>\n {selectedTarget && selectedTarget.modes.length > 1 && <fieldset>\n <legend>Conversation space</legend>\n <label><input type=\"radio\" name={`line-box-mode-${scopeKey}`} value=\"per-member\" checked={selectedMode === 'per-member'} disabled={!selectedTarget?.modes.includes('per-member')} onChange={() => setBoxMode('per-member')} /> One box per member</label>\n <label><input type=\"radio\" name={`line-box-mode-${scopeKey}`} value=\"shared\" checked={selectedMode === 'shared'} disabled={!selectedTarget?.modes.includes('shared')} onChange={() => setBoxMode('shared')} /> Shared box for a team</label>\n </fieldset>}\n {needsNumber && !selected?.identity.phoneNumberId && <label>Existing provider number ID\n <input value={phoneNumberId} onChange={event => setPhoneNumberId(event.target.value)} autoComplete=\"off\" placeholder=\"Number ID from Hub\" />\n </label>}\n </div>\n {reconnectChoice && blockedByExistingLine && <p className=\"tangle-lines__warning\">Enter this line's current provider number ID to reconnect.</p>}\n <button className=\"tangle-lines__primary\" type=\"button\" disabled={!canConnect || busy || loading || refreshFailed || !selected || !selectedTarget || !selectedMode || (needsNumber && !enteredNumber) || blockedByExistingLine} onClick={() => void connect()}>\n {busy ? (reconnectChoice ? 'Reconnecting…' : 'Connecting…') : `${reconnectChoice ? 'Reconnect' : 'Connect'} ${selected ? TRANSPORT[selected.identity.transport] : 'line'}`}\n </button>\n </>}\n </div>}\n </>}\n </section>\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { LineMember } from '@tangle-network/sandbox'\nimport type { LineMembersProps } from './contracts'\n\nconst useBrowserLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect\n\nconst STATUS: Record<LineMember['status'], { label: string; detail: string }> = {\n invited: { label: 'Awaiting consent', detail: 'The first message from this address confirms consent.' },\n active: { label: 'Consented', detail: 'This member has sent a message to the line.' },\n stopped: { label: 'Stopped', detail: 'The member texted STOP. Only a message from them with START resumes replies.' },\n removed: { label: 'Removed', detail: 'This address no longer has access to the line.' },\n}\n\nfunction errorMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : 'The member request failed. Try again.'\n}\n\n/** Manage Hub line members while keeping consent and STOP authority with the sender. */\nexport function LineMembers({ lineId, scopeKey, client, roles, canManage, canAdd = true, maxMembers, allowRoleChange = true, allowRemoveLastOwner = false, onNotice }: LineMembersProps) {\n const clientRef = useRef(client)\n clientRef.current = client\n const sequence = useRef(0)\n const incarnation = useRef(0)\n const confirmButton = useRef<HTMLButtonElement>(null)\n const heading = useRef<HTMLHeadingElement>(null)\n const removeTriggers = useRef(new Map<string, HTMLButtonElement>())\n const restoreFocusTo = useRef<string | null>(null)\n useBrowserLayoutEffect(() => {\n incarnation.current++\n return () => { incarnation.current++ }\n }, [lineId, scopeKey])\n const [memberSnapshot, setMemberSnapshot] = useState<{ lineId: string; scopeKey: string; members: LineMember[] } | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [refreshFailed, setRefreshFailed] = useState(false)\n const [address, setAddress] = useState('')\n const [label, setLabel] = useState('')\n const [role, setRole] = useState('member')\n const [busy, setBusy] = useState<string | null>(null)\n const [confirmId, setConfirmId] = useState<string | null>(null)\n const members = memberSnapshot?.lineId === lineId && memberSnapshot.scopeKey === scopeKey ? memberSnapshot.members : null\n\n function stillCurrent(requestIncarnation: number): boolean {\n return requestIncarnation === incarnation.current\n }\n\n async function reload(requestIncarnation: number): Promise<boolean> {\n const request = ++sequence.current\n try {\n const next = await clientRef.current.list(lineId)\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return false\n setMemberSnapshot({ lineId, scopeKey, members: next })\n setError(null)\n setRefreshFailed(false)\n return true\n } catch (cause) {\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return false\n setError(errorMessage(cause))\n setRefreshFailed(true)\n return false\n }\n }\n\n async function retry() {\n if (busy) return\n const requestIncarnation = incarnation.current\n setBusy('refresh')\n try { await reload(requestIncarnation) }\n finally { if (stillCurrent(requestIncarnation)) setBusy(null) }\n }\n\n function closeConfirmation(memberId: string) {\n restoreFocusTo.current = memberId\n setConfirmId(null)\n }\n\n useEffect(() => {\n setMemberSnapshot(null)\n setError(null)\n setRefreshFailed(false)\n setAddress('')\n setLabel('')\n setRole('member')\n setConfirmId(null)\n restoreFocusTo.current = null\n setBusy(null)\n void reload(incarnation.current)\n return () => { sequence.current++ }\n }, [lineId, scopeKey])\n\n useEffect(() => {\n if (confirmId) confirmButton.current?.focus()\n }, [confirmId])\n\n useEffect(() => {\n const memberId = restoreFocusTo.current\n if (confirmId !== null || memberId === null) return\n restoreFocusTo.current = null\n const trigger = removeTriggers.current.get(memberId)\n if (trigger && !trigger.disabled) trigger.focus()\n else heading.current?.focus()\n }, [confirmId, members, refreshFailed])\n\n const selectedRole = roles.some(item => item.value === role) ? role : roles.find(item => item.value === 'member')?.value ?? roles[0]?.value ?? ''\n const activeMembers = members?.filter(member => member.status !== 'removed').length ?? 0\n const activeOwners = members?.filter(member => member.role === 'owner' && member.status !== 'removed').length ?? 0\n\n async function mutate(key: string, action: () => Promise<void>, success: string, onSuccess?: () => void) {\n if (busy || refreshFailed) return\n const requestIncarnation = incarnation.current\n setBusy(key)\n setError(null)\n try {\n await action()\n if (!stillCurrent(requestIncarnation)) return\n const refreshed = await reload(requestIncarnation)\n if (!stillCurrent(requestIncarnation)) return\n onSuccess?.()\n onNotice?.(refreshed\n ? { kind: 'success', message: success }\n : { kind: 'error', message: 'Member updated, but the current member list could not be loaded.' })\n } catch (cause) {\n if (!stillCurrent(requestIncarnation)) return\n const detail = errorMessage(cause)\n setError(detail)\n onNotice?.({ kind: 'error', message: detail })\n } finally {\n if (stillCurrent(requestIncarnation)) setBusy(null)\n }\n }\n\n function add() {\n const trimmed = address.trim()\n if (!trimmed || !selectedRole || members === null || (maxMembers !== undefined && activeMembers >= maxMembers)) return\n void mutate('add', () => clientRef.current.add(lineId, { address: trimmed, role: selectedRole, ...(label.trim() ? { label: label.trim() } : {}) }), 'Member invited. Their first message confirms consent.', () => {\n setAddress('')\n setLabel('')\n })\n }\n\n return <section className=\"tangle-lines\" aria-label=\"Line members\">\n <header className=\"tangle-lines__heading\">\n <div><h2 ref={heading} tabIndex={-1}>Members</h2><p>Each address controls its own consent and STOP state.</p></div>\n {members && <span className=\"tangle-lines__count\">{activeMembers} {activeMembers === 1 ? 'member' : 'members'}</span>}\n </header>\n {error && <div className=\"tangle-lines__error\" role=\"alert\">\n <span>{error}</span>\n {(members === null || refreshFailed) && <button type=\"button\" disabled={busy !== null} onClick={() => void retry()}>Retry</button>}\n </div>}\n {members === null ? !error && <p className=\"tangle-lines__muted\" role=\"status\">Loading members…</p> : <div className=\"tangle-lines__list\">\n {members.length === 0 && <p className=\"tangle-lines__empty\">{canAdd ? 'No members yet. Invite an address that you own or have permission to add.' : 'No members yet.'}</p>}\n {members.map(member => {\n const lastOwner = member.role === 'owner' && activeOwners <= 1\n const editable = canManage && member.status !== 'removed' && (!lastOwner || allowRemoveLastOwner)\n return <div className=\"tangle-lines__row\" key={member.id}>\n <div className=\"tangle-lines__row-main\">\n <span className={`tangle-lines__state tangle-lines__state--${member.status}`}>{STATUS[member.status].label}</span>\n <strong>{member.label || member.address}</strong>\n {member.label && <p>{member.address}</p>}\n <p>{STATUS[member.status].detail}</p>\n </div>\n <div className=\"tangle-lines__row-actions\">\n {editable ? <>\n {allowRoleChange && !lastOwner ? <label className=\"tangle-lines__compact-label\">Role\n <select value={member.role} disabled={busy !== null || refreshFailed} onChange={event => void mutate(member.id, () => clientRef.current.update(lineId, member.id, { role: event.target.value }), 'Role updated.')}>\n {!roles.some(item => item.value === member.role) && <option value={member.role}>{member.role}</option>}\n {roles.map(item => <option key={item.value} value={item.value}>{item.label}{item.tools === 'chat' ? ' · chat only' : ''}</option>)}\n </select>\n </label> : <span className=\"tangle-lines__role\">{roles.find(item => item.value === member.role)?.label ?? member.role}</span>}\n {confirmId === member.id ? <div className=\"tangle-lines__confirm\" role=\"group\" aria-label={`Remove ${member.label || member.address}?`}>\n <span>Remove {member.label || member.address}?</span>\n <button ref={confirmButton} type=\"button\" className=\"tangle-lines__danger\" disabled={busy !== null || refreshFailed} onClick={() => void mutate(member.id, () => clientRef.current.remove(lineId, member.id), 'Member removed.', () => closeConfirmation(member.id))}>Remove</button>\n <button type=\"button\" disabled={busy !== null} onClick={() => closeConfirmation(member.id)}>Keep</button>\n </div> : <button ref={node => { if (node) removeTriggers.current.set(member.id, node); else removeTriggers.current.delete(member.id) }} type=\"button\" className=\"tangle-lines__quiet\" disabled={busy !== null || refreshFailed} onClick={() => setConfirmId(member.id)}>Remove</button>}\n </> : <span className=\"tangle-lines__role\">{roles.find(item => item.value === member.role)?.label ?? member.role}</span>}\n </div>\n </div>\n })}\n </div>}\n\n {canManage && canAdd && members !== null && (maxMembers === undefined || activeMembers < maxMembers) && <div className=\"tangle-lines__setup\">\n <h3>Invite a member</h3>\n <p>Hub marks the address as invited. The member confirms by messaging the line.</p>\n <div className=\"tangle-lines__fields\">\n <label>Phone number or email\n <input value={address} onChange={event => setAddress(event.target.value)} autoComplete=\"off\" placeholder=\"+15551234567 or name@example.com\" />\n </label>\n <label>Name (optional)\n <input value={label} onChange={event => setLabel(event.target.value)} placeholder=\"Member name\" />\n </label>\n <label>Role\n <select value={selectedRole} disabled={roles.length === 0} onChange={event => setRole(event.target.value)}>\n {roles.map(item => <option key={item.value} value={item.value}>{item.label}{item.tools === 'chat' ? ' · chat only' : ''}</option>)}\n </select>\n </label>\n </div>\n <button type=\"button\" className=\"tangle-lines__primary\" disabled={busy !== null || refreshFailed || !address.trim() || !selectedRole} onClick={add}>\n {busy === 'add' ? 'Inviting…' : 'Invite member'}\n </button>\n </div>}\n </section>\n}\n","import type { LineBillingProps } from './contracts'\n\nfunction resetTime(value: string): string {\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : date.toLocaleString()\n}\n\n/** Read-only billing facts from the line attachment and Hub allowance status. */\nexport function LineBilling({ view }: LineBillingProps) {\n return <section className=\"tangle-lines\" aria-label=\"Line billing\">\n <header className=\"tangle-lines__heading\">\n <div><h2>Billing</h2><p>{view.lineAddress}</p></div>\n </header>\n <dl className=\"tangle-lines__billing\">\n <div>\n <dt>Line</dt>\n <dd>{view.linePayer.kind === 'workspace' ? view.linePayer.label : 'Payer not verified'}</dd>\n {view.linePayer.kind === 'workspace' && <dd className=\"tangle-lines__billing-detail\">Charged to {view.workspaceName}.</dd>}\n </div>\n <div>\n <dt>Agent turns</dt>\n <dd>{view.turnPayer.kind === 'unverified' ? 'Payer not verified' : view.turnPayer.label}</dd>\n {view.turnPayer.kind === 'member' && <dd className=\"tangle-lines__billing-detail\">Each member pays for their own admitted turns.</dd>}\n </div>\n <div>\n <dt>Allowance</dt>\n {view.allowance ? <>\n <dd>{view.allowance.turnsPerMemberPerDay} turns per member each day</dd>\n {view.allowance.used !== undefined && view.allowance.limit !== undefined &&\n <dd className=\"tangle-lines__billing-detail\">{view.allowance.used} of {view.allowance.limit} turns used{view.allowance.resetsAt ? ` · resets ${resetTime(view.allowance.resetsAt)}` : ''}</dd>}\n </> : <dd>No allowance reported</dd>}\n </div>\n </dl>\n </section>\n}\n","import { useMemo, useState } from 'react'\nimport { LineSetup } from './LineSetup'\nimport type { LineConnectInput, LineSetupClient, LineSetupProps } from './contracts'\n\nexport interface ApplicationLineConnectInput extends LineConnectInput {\n operatorAddress: string\n turnsPerDay: number\n}\nexport interface ApplicationLineSetupClient extends Omit<LineSetupClient, 'connect'> {\n connect(input: ApplicationLineConnectInput): Promise<void>\n}\nexport interface ApplicationLineSetupProps extends Omit<LineSetupProps, 'client' | 'canConnect'> {\n client: ApplicationLineSetupClient\n /** Disable new grants without preventing disconnection of an existing line. */\n enabled: boolean\n}\n\n/** Nominate a sender explicitly, then use the existing connection and disconnect UI. */\nexport function ApplicationLineSetup(props: ApplicationLineSetupProps) {\n return <ApplicationLineSetupScope key={props.scopeKey} {...props} />\n}\n\nfunction ApplicationLineSetupScope({ client, enabled, ...props }: ApplicationLineSetupProps) {\n const [operatorAddress, setAddress] = useState('')\n const [limit, setLimit] = useState('20')\n const [approved, setApproved] = useState<string | null>(null)\n const address = operatorAddress.trim()\n const turnsPerDay = Number(limit)\n const nomination = JSON.stringify({ address, turnsPerDay })\n const valid = address.length <= 320 && (/^\\+[1-9]\\d{6,14}$/.test(address) || /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(address))\n && Number.isSafeInteger(turnsPerDay) && turnsPerDay >= 1 && turnsPerDay <= 10_000\n const canConnect = props.canManage && enabled && valid && approved === nomination\n const lineClient = useMemo<LineSetupClient>(() => ({\n load: () => client.load(),\n disconnect: (id, expectedAttachmentId) => client.disconnect(id, expectedAttachmentId),\n connect: input => {\n if (!canConnect) throw new Error('Confirm the sender and daily limit before connecting')\n return client.connect({ ...input, operatorAddress: address, turnsPerDay })\n },\n }), [client, canConnect, address, turnsPerDay])\n return <>\n {props.canManage && <section className=\"tangle-lines tangle-lines--application\" aria-label=\"Application access\">\n <h2>Text your workspace</h2>\n <p>Use the same agent, conversation and saved work. Only the sender you authorize can issue commands.</p>\n {!enabled ? <p role=\"status\">New connections are disabled. You can still disconnect an existing line below.</p> : <>\n <div className=\"tangle-lines__fields\">\n <label>Authorized sender\n <input value={operatorAddress} onChange={e => { setAddress(e.target.value); setApproved(null) }}\n autoComplete=\"off\" placeholder=\"+15550100001 or your Apple ID / email\" />\n </label>\n <label>Maximum messages per day\n <input type=\"number\" min={1} max={10_000} step={1} value={limit}\n onChange={e => { setLimit(e.target.value); setApproved(null) }} />\n </label>\n </div>\n <label className=\"tangle-lines__delegation\">\n <input type=\"checkbox\" checked={approved === nomination} disabled={!valid}\n onChange={e => setApproved(e.target.checked ? nomination : null)} />\n I authorize this sender to work in the conversation I select below using my application access and compute budget.\n </label>\n <p>The daily message limit is not a dollar cap. The first inbound message establishes messaging consent.\n STOP stops replies, not an already accepted task; cancel that task in the application.</p>\n </>}\n </section>}\n <LineSetup {...props} targetLabel={props.targetLabel ?? 'Conversation'} client={lineClient} canConnect={canConnect} showConnectionSetup={enabled} />\n </>\n}\n"],"mappings":"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","names":["occupied","line","useEffect","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useBrowserLayoutEffect","Fragment","jsx","jsxs","useState","Fragment","jsx","jsxs","useState"]}
1
+ {"version":3,"sources":["../../../src/hosted-agent/react/LineSetup.tsx","../../../src/hosted-agent/react/LineMembers.tsx","../../../src/hosted-agent/react/LineBilling.tsx","../../../src/hosted-agent/react/ApplicationLineSetup.tsx"],"sourcesContent":["import { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { Line } from '@tangle-network/sandbox'\nimport type {\n LineBoxMode, LineConnectionOption, LineIdentityKind, LineIdentityOption,\n LineSetupLine, LineSetupProps, LineSetupSnapshot,\n} from './contracts'\n\nconst useBrowserLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect\n\nconst TRANSPORT: Record<Line['transport'], string> = {\n imessage: 'iMessage', sms: 'SMS', whatsapp: 'WhatsApp', email: 'Email',\n}\nconst IDENTITY: Record<LineIdentityKind, string> = {\n handle: 'Inkbox handle', number: 'Dedicated number', email: 'Email line',\n}\n\ntype Choice = { key: string; connection: LineConnectionOption; identity: LineIdentityOption }\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : 'The line request failed. Try again.'\n}\n\nfunction dateTime(value: string): string {\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : date.toLocaleString()\n}\n\nfunction choicesFor(snapshot: LineSetupSnapshot): Choice[] {\n return (snapshot.connections ?? []).flatMap(connection => connection.identities.map((identity, index) => ({\n key: `${connection.id}:${index}`,\n connection,\n identity,\n })))\n}\n\nfunction canOfferReconnect(line: LineSetupLine, choice: Choice): boolean {\n if (line.connectionId !== choice.connection.id || line.transport !== choice.identity.transport || line.targetId !== null) return false\n if (line.providerNumberId === null) return line.transport !== 'whatsapp' && !choice.identity.phoneNumberId && !choice.identity.requiresPhoneNumberId\n return choice.identity.phoneNumberId === line.providerNumberId ||\n (!choice.identity.phoneNumberId && choice.identity.requiresPhoneNumberId === true)\n}\n\nfunction matchesLineIdentity(line: LineSetupLine, identity: LineIdentityOption, numberId: string): boolean {\n if (line.transport !== identity.transport) return false\n if (line.providerNumberId === null) return line.transport !== 'whatsapp' && !identity.phoneNumberId && !identity.requiresPhoneNumberId\n return numberId === line.providerNumberId\n}\n\n/** Set up an owned identity through a host route backed by sandbox.lines and Hub. */\nexport function LineSetup({ client, scopeKey, initialTargetId, targetLabel, canManage, canConnect = canManage, showConnectionSetup = true, onNotice }: LineSetupProps) {\n const clientRef = useRef(client)\n clientRef.current = client\n const sequence = useRef(0)\n const incarnation = useRef(0)\n const confirmButton = useRef<HTMLButtonElement>(null)\n const heading = useRef<HTMLHeadingElement>(null)\n const disconnectTriggers = useRef(new Map<string, HTMLButtonElement>())\n const restoreFocusTo = useRef<string | null>(null)\n useBrowserLayoutEffect(() => {\n incarnation.current++\n return () => { incarnation.current++ }\n }, [scopeKey, initialTargetId])\n const [loadedSnapshot, setLoadedSnapshot] = useState<{ scopeKey: string; initialTargetId: string | undefined; value: LineSetupSnapshot } | null>(null)\n const snapshot = loadedSnapshot?.scopeKey === scopeKey && loadedSnapshot.initialTargetId === initialTargetId ? loadedSnapshot.value : null\n const [loading, setLoading] = useState(true)\n const [refreshFailed, setRefreshFailed] = useState(false)\n const [busy, setBusy] = useState(false)\n const [error, setError] = useState<string | null>(null)\n const [kind, setKind] = useState<LineIdentityKind>('handle')\n const [choiceKey, setChoiceKey] = useState('')\n const [targetId, setTargetId] = useState(initialTargetId ?? '')\n const [boxMode, setBoxMode] = useState<LineBoxMode>('per-member')\n const [phoneNumberId, setPhoneNumberId] = useState('')\n const [confirmLineId, setConfirmLineId] = useState<string | null>(null)\n\n function stillCurrent(requestIncarnation: number): boolean {\n return requestIncarnation === incarnation.current\n }\n\n async function reload(requestIncarnation: number): Promise<LineSetupSnapshot | null> {\n const request = ++sequence.current\n try {\n const next = await clientRef.current.load()\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return null\n setLoadedSnapshot({ scopeKey, initialTargetId, value: next })\n setError(null)\n setRefreshFailed(false)\n setTargetId(current => next.targets.some(target => target.id === current)\n ? current : next.targets.find(target => target.id === initialTargetId)?.id ?? next.targets[0]?.id ?? '')\n setLoading(false)\n return next\n } catch (cause) {\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return null\n setError(message(cause))\n setRefreshFailed(true)\n setLoading(false)\n return null\n }\n }\n\n function retry() {\n if (loading) return\n setLoading(true)\n void reload(incarnation.current)\n }\n\n function closeConfirmation(lineId: string) {\n restoreFocusTo.current = lineId\n setConfirmLineId(null)\n }\n\n useEffect(() => {\n setLoading(true)\n setLoadedSnapshot(null)\n setError(null)\n setRefreshFailed(false)\n setBusy(false)\n setKind('handle')\n setChoiceKey('')\n setTargetId(initialTargetId ?? '')\n setBoxMode('per-member')\n setPhoneNumberId('')\n setConfirmLineId(null)\n restoreFocusTo.current = null\n void reload(incarnation.current)\n return () => { sequence.current++ }\n }, [scopeKey, initialTargetId])\n\n useEffect(() => {\n if (confirmLineId) confirmButton.current?.focus()\n }, [confirmLineId])\n\n useEffect(() => {\n const lineId = restoreFocusTo.current\n if (confirmLineId !== null || lineId === null) return\n restoreFocusTo.current = null\n const trigger = disconnectTriggers.current.get(lineId)\n if (trigger && !trigger.disabled) trigger.focus()\n else heading.current?.focus()\n }, [confirmLineId, snapshot, refreshFailed])\n\n const allChoices = snapshot ? choicesFor(snapshot) : []\n const choices = snapshot ? allChoices.filter(choice => {\n const occupied = snapshot.lines.filter(line => line.status !== 'released' && line.transport === choice.identity.transport)\n const [line] = occupied\n return occupied.length === 0 || (occupied.length === 1 && line !== undefined && canOfferReconnect(line, choice))\n }) : []\n const availableKinds = (['handle', 'number', 'email'] as const).filter(value => choices.some(choice => choice.identity.kind === value))\n const selectedKind = availableKinds.includes(kind) ? kind : availableKinds[0]\n const kindChoices = choices.filter(choice => choice.identity.kind === selectedKind)\n const selected = kindChoices.find(choice => choice.key === choiceKey) ?? kindChoices[0]\n const selectedTarget = snapshot?.targets.find(target => target.id === targetId)\n const selectedMode = selectedTarget?.modes.includes(boxMode) ? boxMode : selectedTarget?.modes[0]\n const enteredNumber = selected?.identity.phoneNumberId ?? phoneNumberId.trim()\n const needsNumber = selected?.identity.transport === 'whatsapp' || selected?.identity.requiresPhoneNumberId\n const occupied = selected && snapshot?.lines.filter(line => line.status !== 'released' && line.transport === selected.identity.transport)\n const [occupiedLine] = occupied || []\n const reconnectChoice = Boolean(selected && occupied?.length === 1 && occupiedLine && canOfferReconnect(occupiedLine, selected))\n const reconnecting = Boolean(reconnectChoice && selected && occupiedLine &&\n matchesLineIdentity(occupiedLine, selected.identity, enteredNumber))\n const blockedByExistingLine = Boolean(occupied?.length && !reconnecting)\n const answeringCount = snapshot?.lines.filter(line => line.answering).length ?? 0\n\n async function connect() {\n if (!canManage || !canConnect || !selected || !selectedTarget || !selectedMode || (needsNumber && !enteredNumber) || blockedByExistingLine || busy || loading || refreshFailed) return\n const requestIncarnation = incarnation.current\n setBusy(true)\n setError(null)\n try {\n await clientRef.current.connect({\n connectionId: selected.connection.id,\n transport: selected.identity.transport,\n ...(enteredNumber ? { phoneNumberId: enteredNumber } : {}),\n targetId: selectedTarget.id,\n boxMode: selectedMode,\n })\n if (!stillCurrent(requestIncarnation)) return\n const updated = await reload(requestIncarnation)\n if (!stillCurrent(requestIncarnation)) return\n if (!updated) {\n onNotice?.({ kind: 'error', message: 'Line connected, but its current status could not be loaded.' })\n return\n }\n const line = updated.lines.find(item => item.status !== 'released' && item.connectionId === selected.connection.id &&\n item.transport === selected.identity.transport && item.providerNumberId === (enteredNumber || null))\n onNotice?.({ kind: 'success', message: line?.answering ? 'The line is answering.' : 'Line connected. Add a member to start answers.' })\n } catch (cause) {\n if (!stillCurrent(requestIncarnation)) return\n const detail = message(cause)\n setError(detail)\n onNotice?.({ kind: 'error', message: detail })\n } finally {\n if (stillCurrent(requestIncarnation)) setBusy(false)\n }\n }\n\n async function disconnect(lineId: string) {\n if (busy || loading || refreshFailed) return\n const requestIncarnation = incarnation.current\n setBusy(true)\n setError(null)\n try {\n const expectedAttachmentId = snapshot?.lines.find(line => line.id === lineId)?.attachmentId ?? undefined\n await clientRef.current.disconnect(lineId, expectedAttachmentId)\n if (!stillCurrent(requestIncarnation)) return\n const updated = await reload(requestIncarnation)\n if (!stillCurrent(requestIncarnation)) return\n closeConfirmation(lineId)\n onNotice?.(updated\n ? { kind: 'success', message: 'The line stopped answering.' }\n : { kind: 'error', message: 'Line disconnected, but its current status could not be loaded.' })\n } catch (cause) {\n if (!stillCurrent(requestIncarnation)) return\n const detail = message(cause)\n setError(detail)\n onNotice?.({ kind: 'error', message: detail })\n } finally {\n if (stillCurrent(requestIncarnation)) setBusy(false)\n }\n }\n\n return <section className=\"tangle-lines\" aria-label=\"Agent lines\">\n <header className=\"tangle-lines__heading\">\n <div>\n <h2 ref={heading} tabIndex={-1}>Lines</h2>\n {snapshot && <p>{snapshot.workspaceName} can use one line per transport.</p>}\n </div>\n {answeringCount > 1 && <span className=\"tangle-lines__count\">{answeringCount} answering</span>}\n </header>\n\n {error && <div className=\"tangle-lines__error\" role=\"alert\">\n <div><strong>{refreshFailed ? 'Lines are unavailable' : 'Line action failed'}</strong><p>{error}</p></div>\n {(!snapshot || refreshFailed) && <button type=\"button\" disabled={loading} onClick={retry}>Retry</button>}\n </div>}\n {loading && <p className=\"tangle-lines__muted\" role=\"status\">Loading lines…</p>}\n\n {snapshot && <>\n <div className=\"tangle-lines__list\">\n {snapshot.lines.filter(line => line.status !== 'released').length === 0 &&\n <div className=\"tangle-lines__empty\"><strong>No lines connected</strong><p>{canManage && showConnectionSetup\n ? 'Connect an owned identity below to let this workspace answer messages.'\n : 'There are no connected lines in this workspace.'}</p></div>}\n {snapshot.lines.filter(line => line.status !== 'released').map(line =>\n <div className=\"tangle-lines__row\" key={line.id}>\n <div className=\"tangle-lines__row-main\">\n <div className=\"tangle-lines__row-heading\"><span className=\"tangle-lines__transport\">{TRANSPORT[line.transport]}</span><span className={`tangle-lines__status${line.answering ? ' tangle-lines__status--answering' : ''}`}>{line.answering ? 'Answering' : line.targetId === null ? 'Disconnected' : line.status === 'active' ? 'Awaiting member' : line.status}</span></div>\n <strong>{line.routerAddress ?? line.address}</strong>\n {line.connect && line.targetId !== null && <p>To reach this agent, text <code>{line.connect}</code>.</p>}\n <p>{line.targetLabel ?? 'No agent or box assigned'}{line.boxMode && ` · ${line.boxMode === 'per-member' ? 'one box per member' : 'shared box'}`}</p>\n {line.lastTurn.kind === 'latest' ? <p>Last turn: {line.lastTurn.status} · {dateTime(line.lastTurn.at)}</p>\n : <p>{line.lastTurn.kind === 'none' ? 'No turns yet.' : 'Turn history unavailable.'}</p>}\n </div>\n {canManage && line.canDisconnect && line.targetId !== null && line.status === 'active' && <div className=\"tangle-lines__row-actions\">\n {confirmLineId === line.id ? <div className=\"tangle-lines__confirm\" role=\"group\" aria-label={`Disconnect ${line.address}?`}>\n <span>Disconnect this line?</span>\n <button ref={confirmButton} type=\"button\" className=\"tangle-lines__danger\" disabled={busy || loading || refreshFailed} onClick={() => void disconnect(line.id)}>Disconnect</button>\n <button type=\"button\" disabled={busy} onClick={() => closeConfirmation(line.id)}>Keep line</button>\n </div> : <button ref={node => { if (node) disconnectTriggers.current.set(line.id, node); else disconnectTriggers.current.delete(line.id) }} type=\"button\" className=\"tangle-lines__quiet\" disabled={busy || loading || refreshFailed} onClick={() => setConfirmLineId(line.id)}>Disconnect line</button>}\n </div>}\n </div>)}\n </div>\n\n {canManage && showConnectionSetup && (snapshot.connections === null || choices.length > 0 || allChoices.length === 0) && <div className=\"tangle-lines__setup\">\n <span className=\"tangle-lines__overline\">New line</span>\n <h3>Connect an identity you own</h3>\n <p>Choose an identity already connected in Hub. Billing details appear below.</p>\n {snapshot.connections === null ? <div className=\"tangle-lines__error\" role=\"status\">\n <span>Hub connections could not be read. Check Hub access and try again.</span>\n <button type=\"button\" disabled={loading} onClick={retry}>Retry</button>\n </div>\n : availableKinds.length === 0 ? <p className=\"tangle-lines__empty\">\n Connect an owned handle, number, or mailbox in Hub, then <button type=\"button\" disabled={loading} onClick={retry}>reload</button>.\n </p>\n : <>\n <div className=\"tangle-lines__kinds\" role=\"group\" aria-label=\"Identity type\">\n {availableKinds.map(value => <button key={value} type=\"button\" aria-pressed={selectedKind === value} onClick={() => { setKind(value); setChoiceKey(''); setPhoneNumberId('') }}>{IDENTITY[value]}</button>)}\n </div>\n <div className=\"tangle-lines__fields\">\n <label>Owned connection\n <select value={selected?.key ?? ''} onChange={event => { setChoiceKey(event.target.value); setPhoneNumberId('') }}>\n {kindChoices.map(choice => <option key={choice.key} value={choice.key}>{choice.connection.label} · {choice.identity.label}</option>)}\n </select>\n </label>\n <label>{targetLabel ?? 'Agent or box'}\n <select value={selectedTarget?.id ?? ''} onChange={event => setTargetId(event.target.value)}>\n {snapshot.targets.map(target => <option key={target.id} value={target.id}>{target.label}{targetLabel ? '' : ` · ${target.kind}`}</option>)}\n </select>\n </label>\n {selectedTarget && selectedTarget.modes.length > 1 && <fieldset>\n <legend>Conversation space</legend>\n <label><input type=\"radio\" name={`line-box-mode-${scopeKey}`} value=\"per-member\" checked={selectedMode === 'per-member'} disabled={!selectedTarget?.modes.includes('per-member')} onChange={() => setBoxMode('per-member')} /> One box per member</label>\n <label><input type=\"radio\" name={`line-box-mode-${scopeKey}`} value=\"shared\" checked={selectedMode === 'shared'} disabled={!selectedTarget?.modes.includes('shared')} onChange={() => setBoxMode('shared')} /> Shared box for a team</label>\n </fieldset>}\n {needsNumber && !selected?.identity.phoneNumberId && <label>Existing provider number ID\n <input value={phoneNumberId} onChange={event => setPhoneNumberId(event.target.value)} autoComplete=\"off\" placeholder=\"Number ID from Hub\" />\n </label>}\n </div>\n {reconnectChoice && blockedByExistingLine && <p className=\"tangle-lines__warning\">Enter this line's current provider number ID to reconnect.</p>}\n <button className=\"tangle-lines__primary\" type=\"button\" disabled={!canConnect || busy || loading || refreshFailed || !selected || !selectedTarget || !selectedMode || (needsNumber && !enteredNumber) || blockedByExistingLine} onClick={() => void connect()}>\n {busy ? (reconnectChoice ? 'Reconnecting…' : 'Connecting…') : `${reconnectChoice ? 'Reconnect' : 'Connect'} ${selected ? TRANSPORT[selected.identity.transport] : 'line'}`}\n </button>\n </>}\n </div>}\n </>}\n </section>\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from 'react'\nimport type { LineMember } from '@tangle-network/sandbox'\nimport type { LineMembersProps } from './contracts'\n\nconst useBrowserLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect\n\nconst STATUS: Record<LineMember['status'], { label: string; detail: string }> = {\n invited: { label: 'Awaiting consent', detail: 'The first message from this address confirms consent.' },\n active: { label: 'Consented', detail: 'This member has sent a message to the line.' },\n stopped: { label: 'Stopped', detail: 'The member texted STOP. Only a message from them with START resumes replies.' },\n removed: { label: 'Removed', detail: 'This address no longer has access to the line.' },\n}\n\nfunction errorMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : 'The member request failed. Try again.'\n}\n\n/** Manage Hub line members while keeping consent and STOP authority with the sender. */\nexport function LineMembers({ lineId, scopeKey, client, roles, canManage, canAdd = true, maxMembers, allowRoleChange = true, allowRemoveLastOwner = false, onNotice }: LineMembersProps) {\n const clientRef = useRef(client)\n clientRef.current = client\n const sequence = useRef(0)\n const incarnation = useRef(0)\n const confirmButton = useRef<HTMLButtonElement>(null)\n const heading = useRef<HTMLHeadingElement>(null)\n const removeTriggers = useRef(new Map<string, HTMLButtonElement>())\n const restoreFocusTo = useRef<string | null>(null)\n useBrowserLayoutEffect(() => {\n incarnation.current++\n return () => { incarnation.current++ }\n }, [lineId, scopeKey])\n const [memberSnapshot, setMemberSnapshot] = useState<{ lineId: string; scopeKey: string; members: LineMember[] } | null>(null)\n const [error, setError] = useState<string | null>(null)\n const [refreshFailed, setRefreshFailed] = useState(false)\n const [address, setAddress] = useState('')\n const [label, setLabel] = useState('')\n const [role, setRole] = useState('member')\n const [busy, setBusy] = useState<string | null>(null)\n const [confirmId, setConfirmId] = useState<string | null>(null)\n const members = memberSnapshot?.lineId === lineId && memberSnapshot.scopeKey === scopeKey ? memberSnapshot.members : null\n\n function stillCurrent(requestIncarnation: number): boolean {\n return requestIncarnation === incarnation.current\n }\n\n async function reload(requestIncarnation: number): Promise<boolean> {\n const request = ++sequence.current\n try {\n const next = await clientRef.current.list(lineId)\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return false\n setMemberSnapshot({ lineId, scopeKey, members: next })\n setError(null)\n setRefreshFailed(false)\n return true\n } catch (cause) {\n if (request !== sequence.current || !stillCurrent(requestIncarnation)) return false\n setError(errorMessage(cause))\n setRefreshFailed(true)\n return false\n }\n }\n\n async function retry() {\n if (busy) return\n const requestIncarnation = incarnation.current\n setBusy('refresh')\n try { await reload(requestIncarnation) }\n finally { if (stillCurrent(requestIncarnation)) setBusy(null) }\n }\n\n function closeConfirmation(memberId: string) {\n restoreFocusTo.current = memberId\n setConfirmId(null)\n }\n\n useEffect(() => {\n setMemberSnapshot(null)\n setError(null)\n setRefreshFailed(false)\n setAddress('')\n setLabel('')\n setRole('member')\n setConfirmId(null)\n restoreFocusTo.current = null\n setBusy(null)\n void reload(incarnation.current)\n return () => { sequence.current++ }\n }, [lineId, scopeKey])\n\n useEffect(() => {\n if (confirmId) confirmButton.current?.focus()\n }, [confirmId])\n\n useEffect(() => {\n const memberId = restoreFocusTo.current\n if (confirmId !== null || memberId === null) return\n restoreFocusTo.current = null\n const trigger = removeTriggers.current.get(memberId)\n if (trigger && !trigger.disabled) trigger.focus()\n else heading.current?.focus()\n }, [confirmId, members, refreshFailed])\n\n const selectedRole = roles.some(item => item.value === role) ? role : roles.find(item => item.value === 'member')?.value ?? roles[0]?.value ?? ''\n const activeMembers = members?.filter(member => member.status !== 'removed').length ?? 0\n const activeOwners = members?.filter(member => member.role === 'owner' && member.status !== 'removed').length ?? 0\n\n async function mutate(key: string, action: () => Promise<void>, success: string, onSuccess?: () => void) {\n if (busy || refreshFailed) return\n const requestIncarnation = incarnation.current\n setBusy(key)\n setError(null)\n try {\n await action()\n if (!stillCurrent(requestIncarnation)) return\n const refreshed = await reload(requestIncarnation)\n if (!stillCurrent(requestIncarnation)) return\n onSuccess?.()\n onNotice?.(refreshed\n ? { kind: 'success', message: success }\n : { kind: 'error', message: 'Member updated, but the current member list could not be loaded.' })\n } catch (cause) {\n if (!stillCurrent(requestIncarnation)) return\n const detail = errorMessage(cause)\n setError(detail)\n onNotice?.({ kind: 'error', message: detail })\n } finally {\n if (stillCurrent(requestIncarnation)) setBusy(null)\n }\n }\n\n function add() {\n const trimmed = address.trim()\n if (!trimmed || !selectedRole || members === null || (maxMembers !== undefined && activeMembers >= maxMembers)) return\n void mutate('add', () => clientRef.current.add(lineId, { address: trimmed, role: selectedRole, ...(label.trim() ? { label: label.trim() } : {}) }), 'Member invited. Their first message confirms consent.', () => {\n setAddress('')\n setLabel('')\n })\n }\n\n return <section className=\"tangle-lines\" aria-label=\"Line members\">\n <header className=\"tangle-lines__heading\">\n <div><h2 ref={heading} tabIndex={-1}>Members</h2><p>Each address controls its own consent and STOP state.</p></div>\n {members && <span className=\"tangle-lines__count\">{activeMembers} {activeMembers === 1 ? 'member' : 'members'}</span>}\n </header>\n {error && <div className=\"tangle-lines__error\" role=\"alert\">\n <span>{error}</span>\n {(members === null || refreshFailed) && <button type=\"button\" disabled={busy !== null} onClick={() => void retry()}>Retry</button>}\n </div>}\n {members === null ? !error && <p className=\"tangle-lines__muted\" role=\"status\">Loading members…</p> : <div className=\"tangle-lines__list\">\n {members.length === 0 && <p className=\"tangle-lines__empty\">{canAdd ? 'No members yet. Invite an address that you own or have permission to add.' : 'No members yet.'}</p>}\n {members.map(member => {\n const lastOwner = member.role === 'owner' && activeOwners <= 1\n const editable = canManage && member.status !== 'removed' && (!lastOwner || allowRemoveLastOwner)\n return <div className=\"tangle-lines__row\" key={member.id}>\n <div className=\"tangle-lines__row-main\">\n <span className={`tangle-lines__state tangle-lines__state--${member.status}`}>{STATUS[member.status].label}</span>\n <strong>{member.label || member.address}</strong>\n {member.label && <p>{member.address}</p>}\n <p>{STATUS[member.status].detail}</p>\n </div>\n <div className=\"tangle-lines__row-actions\">\n {editable ? <>\n {allowRoleChange && !lastOwner ? <label className=\"tangle-lines__compact-label\">Role\n <select value={member.role} disabled={busy !== null || refreshFailed} onChange={event => void mutate(member.id, () => clientRef.current.update(lineId, member.id, { role: event.target.value }), 'Role updated.')}>\n {!roles.some(item => item.value === member.role) && <option value={member.role}>{member.role}</option>}\n {roles.map(item => <option key={item.value} value={item.value}>{item.label}{item.tools === 'chat' ? ' · chat only' : ''}</option>)}\n </select>\n </label> : <span className=\"tangle-lines__role\">{roles.find(item => item.value === member.role)?.label ?? member.role}</span>}\n {confirmId === member.id ? <div className=\"tangle-lines__confirm\" role=\"group\" aria-label={`Remove ${member.label || member.address}?`}>\n <span>Remove {member.label || member.address}?</span>\n <button ref={confirmButton} type=\"button\" className=\"tangle-lines__danger\" disabled={busy !== null || refreshFailed} onClick={() => void mutate(member.id, () => clientRef.current.remove(lineId, member.id), 'Member removed.', () => closeConfirmation(member.id))}>Remove</button>\n <button type=\"button\" disabled={busy !== null} onClick={() => closeConfirmation(member.id)}>Keep</button>\n </div> : <button ref={node => { if (node) removeTriggers.current.set(member.id, node); else removeTriggers.current.delete(member.id) }} type=\"button\" className=\"tangle-lines__quiet\" disabled={busy !== null || refreshFailed} onClick={() => setConfirmId(member.id)}>Remove</button>}\n </> : <span className=\"tangle-lines__role\">{roles.find(item => item.value === member.role)?.label ?? member.role}</span>}\n </div>\n </div>\n })}\n </div>}\n\n {canManage && canAdd && members !== null && (maxMembers === undefined || activeMembers < maxMembers) && <div className=\"tangle-lines__setup\">\n <h3>Invite a member</h3>\n <p>Hub marks the address as invited. The member confirms by messaging the line.</p>\n <div className=\"tangle-lines__fields\">\n <label>Phone number or email\n <input value={address} onChange={event => setAddress(event.target.value)} autoComplete=\"off\" placeholder=\"+15551234567 or name@example.com\" />\n </label>\n <label>Name (optional)\n <input value={label} onChange={event => setLabel(event.target.value)} placeholder=\"Member name\" />\n </label>\n <label>Role\n <select value={selectedRole} disabled={roles.length === 0} onChange={event => setRole(event.target.value)}>\n {roles.map(item => <option key={item.value} value={item.value}>{item.label}{item.tools === 'chat' ? ' · chat only' : ''}</option>)}\n </select>\n </label>\n </div>\n <button type=\"button\" className=\"tangle-lines__primary\" disabled={busy !== null || refreshFailed || !address.trim() || !selectedRole} onClick={add}>\n {busy === 'add' ? 'Inviting…' : 'Invite member'}\n </button>\n </div>}\n </section>\n}\n","import type { LineBillingProps } from './contracts'\n\nfunction resetTime(value: string): string {\n const date = new Date(value)\n return Number.isNaN(date.getTime()) ? value : date.toLocaleString()\n}\n\n/** Read-only billing facts from the line attachment and Hub allowance status. */\nexport function LineBilling({ view }: LineBillingProps) {\n return <section className=\"tangle-lines\" aria-label=\"Line billing\">\n <header className=\"tangle-lines__heading\">\n <div><h2>Billing</h2><p>{view.lineAddress}</p></div>\n </header>\n <dl className=\"tangle-lines__billing\">\n <div>\n <dt>Line</dt>\n <dd>{view.linePayer.kind === 'workspace' ? view.linePayer.label : 'Payer not verified'}</dd>\n {view.linePayer.kind === 'workspace' && <dd className=\"tangle-lines__billing-detail\">Charged to {view.workspaceName}.</dd>}\n </div>\n <div>\n <dt>Agent turns</dt>\n <dd>{view.turnPayer.kind === 'unverified' ? 'Payer not verified' : view.turnPayer.label}</dd>\n {view.turnPayer.kind === 'member' && <dd className=\"tangle-lines__billing-detail\">Each member pays for their own admitted turns.</dd>}\n </div>\n <div>\n <dt>Allowance</dt>\n {view.allowance ? <>\n <dd>{view.allowance.turnsPerMemberPerDay} turns per member each day</dd>\n {view.allowance.used !== undefined && view.allowance.limit !== undefined &&\n <dd className=\"tangle-lines__billing-detail\">{view.allowance.used} of {view.allowance.limit} turns used{view.allowance.resetsAt ? ` · resets ${resetTime(view.allowance.resetsAt)}` : ''}</dd>}\n </> : <dd>No allowance reported</dd>}\n </div>\n </dl>\n </section>\n}\n","import { useMemo, useState } from 'react'\nimport { LineSetup } from './LineSetup'\nimport type { LineConnectInput, LineSetupClient, LineSetupProps } from './contracts'\n\nexport interface ApplicationLineConnectInput extends LineConnectInput {\n operatorAddress: string\n turnsPerDay: number\n}\nexport interface ApplicationLineSetupClient extends Omit<LineSetupClient, 'connect'> {\n connect(input: ApplicationLineConnectInput): Promise<void>\n}\nexport interface ApplicationLineSetupProps extends Omit<LineSetupProps, 'client' | 'canConnect'> {\n client: ApplicationLineSetupClient\n /** Disable new grants without preventing disconnection of an existing line. */\n enabled: boolean\n}\n\n/** Nominate a sender explicitly, then use the existing connection and disconnect UI. */\nexport function ApplicationLineSetup(props: ApplicationLineSetupProps) {\n return <ApplicationLineSetupScope key={props.scopeKey} {...props} />\n}\n\nfunction ApplicationLineSetupScope({ client, enabled, ...props }: ApplicationLineSetupProps) {\n const [operatorAddress, setAddress] = useState('')\n const [limit, setLimit] = useState('20')\n const [approved, setApproved] = useState<string | null>(null)\n const address = operatorAddress.trim()\n const turnsPerDay = Number(limit)\n const nomination = JSON.stringify({ address, turnsPerDay })\n const valid = address.length <= 320 && (/^\\+[1-9]\\d{6,14}$/.test(address) || /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(address))\n && Number.isSafeInteger(turnsPerDay) && turnsPerDay >= 1 && turnsPerDay <= 10_000\n const canConnect = props.canManage && enabled && valid && approved === nomination\n const lineClient = useMemo<LineSetupClient>(() => ({\n load: () => client.load(),\n disconnect: (id, expectedAttachmentId) => client.disconnect(id, expectedAttachmentId),\n connect: input => {\n if (!canConnect) throw new Error('Confirm the sender and daily limit before connecting')\n return client.connect({ ...input, operatorAddress: address, turnsPerDay })\n },\n }), [client, canConnect, address, turnsPerDay])\n return <>\n {props.canManage && <section className=\"tangle-lines tangle-lines--application\" aria-label=\"Application access\">\n <header className=\"tangle-lines__application-heading\">\n <h2>Text your workspace</h2>\n <p>Continue a conversation from a number or mailbox you own. The agent keeps the same context and saved work.</p>\n </header>\n {!enabled ? <div className=\"tangle-lines__notice\" role=\"status\">\n <strong>New connections are disabled</strong>\n <p>You can still review and disconnect an existing line below.</p>\n </div> : <div className=\"tangle-lines__authorization\">\n <div className=\"tangle-lines__authorization-heading\">\n <h3>Authorize a sender</h3>\n <p>Only this sender can issue commands through the line you connect.</p>\n </div>\n <div className=\"tangle-lines__fields\">\n <label>Authorized sender\n <input value={operatorAddress} onChange={e => { setAddress(e.target.value); setApproved(null) }}\n autoComplete=\"off\" placeholder=\"+15550100001 or your Apple ID / email\" />\n </label>\n <label>Maximum messages per day\n <input type=\"number\" min={1} max={10_000} step={1} value={limit}\n onChange={e => { setLimit(e.target.value); setApproved(null) }} />\n </label>\n </div>\n <label className=\"tangle-lines__delegation\">\n <input type=\"checkbox\" checked={approved === nomination} disabled={!valid}\n onChange={e => setApproved(e.target.checked ? nomination : null)} />\n I authorize this sender to work in the conversation I select below using my application access and compute budget.\n </label>\n <p className=\"tangle-lines__fine-print\">The daily message limit is not a dollar cap. The first inbound message establishes messaging consent.\n STOP stops replies, not an already accepted task; cancel that task in the application.</p>\n </div>}\n </section>}\n <LineSetup {...props} targetLabel={props.targetLabel ?? 'Conversation'} client={lineClient} canConnect={canConnect} showConnectionSetup={enabled} />\n </>\n}\n"],"mappings":"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","names":["occupied","line","useEffect","useLayoutEffect","useRef","useState","Fragment","jsx","jsxs","useBrowserLayoutEffect","Fragment","jsx","jsxs","useState","Fragment","jsx","jsxs","useState"]}
@@ -4,10 +4,13 @@
4
4
  --tl-border: var(--line-kit-border, var(--border-default, var(--line-subtle, #dbe1e7)));
5
5
  --tl-surface: var(--line-kit-surface, var(--bg-input, #fff));
6
6
  --tl-accent: var(--line-kit-accent, var(--brand-primary, #2856a1));
7
- --tl-accent-foreground: var(--line-kit-accent-foreground, hsl(var(--primary-foreground, 0 0% 100%)));
7
+ --tl-accent-foreground: var(--line-kit-accent-foreground, #fff);
8
8
  --tl-success: var(--line-kit-success, var(--success-11, hsl(var(--success, 160 84% 26%))));
9
9
  --tl-warning: var(--line-kit-warning, var(--warning-11, hsl(var(--warning-strong, 41 96% 27%))));
10
10
  --tl-danger: var(--line-kit-danger, var(--text-danger, #a62f3b));
11
+ --tl-panel: var(--md3-surface-container, var(--tl-surface));
12
+ --tl-soft: var(--md3-surface-container-low, color-mix(in srgb, var(--tl-panel) 94%, var(--tl-accent)));
13
+ --tl-danger-soft: color-mix(in srgb, var(--tl-panel) 92%, var(--tl-danger));
11
14
  color: var(--tl-text);
12
15
  font: inherit;
13
16
  width: 100%;
@@ -15,8 +18,8 @@
15
18
 
16
19
  .tangle-lines * { box-sizing: border-box; }
17
20
  .tangle-lines h2, .tangle-lines h3, .tangle-lines p { margin: 0; }
18
- .tangle-lines h2 { font-size: 1.35rem; font-weight: 650; line-height: 1.25; }
19
- .tangle-lines h3 { font-size: 1.05rem; font-weight: 650; line-height: 1.3; }
21
+ .tangle-lines h2 { font-size: clamp(1.4rem, 2.2vw, 1.8rem); font-weight: 700; letter-spacing: -.025em; line-height: 1.18; }
22
+ .tangle-lines h3 { font-size: 1.12rem; font-weight: 650; line-height: 1.3; }
20
23
  .tangle-lines p { line-height: 1.45; }
21
24
  .tangle-lines button, .tangle-lines input, .tangle-lines select { font: inherit; }
22
25
  .tangle-lines button { cursor: pointer; }
@@ -29,24 +32,29 @@
29
32
  display: flex;
30
33
  gap: 1rem;
31
34
  justify-content: space-between;
32
- margin-bottom: 1rem;
35
+ margin-bottom: 1.1rem;
33
36
  }
34
37
  .tangle-lines__heading p { color: var(--tl-muted); font-size: .91rem; margin-top: .25rem; }
35
- .tangle-lines__count { color: var(--tl-muted); font-size: .82rem; padding-top: .25rem; white-space: nowrap; }
36
- .tangle-lines__list { border-top: 1px solid var(--tl-border); }
38
+ .tangle-lines__count { background: var(--tl-soft); border: 1px solid var(--tl-border); border-radius: 999px; color: var(--tl-text); font-size: .78rem; font-weight: 600; padding: .35rem .7rem; white-space: nowrap; }
39
+ .tangle-lines__list { background: var(--tl-panel); border: 1px solid var(--tl-border); border-radius: .95rem; overflow: hidden; }
37
40
  .tangle-lines__row {
38
41
  align-items: start;
39
42
  border-bottom: 1px solid var(--tl-border);
40
43
  display: flex;
41
44
  gap: 1rem;
42
45
  justify-content: space-between;
43
- padding: 1rem 0;
46
+ padding: 1.15rem 1.25rem;
44
47
  }
48
+ .tangle-lines__row:last-child { border-bottom: 0; }
45
49
  .tangle-lines__row-main { min-width: 0; }
46
- .tangle-lines__row-main strong { display: block; font-size: 1rem; font-weight: 600; overflow-wrap: anywhere; }
50
+ .tangle-lines__row-main strong { display: block; font-size: 1.08rem; font-weight: 650; overflow-wrap: anywhere; }
47
51
  .tangle-lines__row-main p { color: var(--tl-muted); font-size: .85rem; margin-top: .3rem; }
48
- .tangle-lines__row-main code { color: var(--tl-text); font-size: .92em; font-weight: 600; white-space: nowrap; }
52
+ .tangle-lines__row-main code { color: var(--tl-text); font-size: .92em; font-weight: 600; overflow-wrap: anywhere; }
49
53
  .tangle-lines__eyebrow { color: var(--tl-muted); display: block; font-size: .79rem; margin-bottom: .25rem; }
54
+ .tangle-lines__row-heading { align-items: center; display: flex; flex-wrap: wrap; gap: .45rem; margin-bottom: .45rem; }
55
+ .tangle-lines__transport { color: var(--tl-muted); font-size: .78rem; font-weight: 650; letter-spacing: .055em; text-transform: uppercase; }
56
+ .tangle-lines__status { border: 1px solid var(--tl-border); border-radius: 999px; color: var(--tl-muted); font-size: .76rem; font-weight: 600; line-height: 1.3; padding: .2rem .55rem; }
57
+ .tangle-lines__status--answering { background: color-mix(in srgb, var(--tl-panel) 90%, var(--tl-success)); border-color: color-mix(in srgb, var(--tl-border) 75%, var(--tl-success)); color: var(--tl-success); }
50
58
  .tangle-lines__row-actions { align-items: end; display: flex; flex-direction: column; gap: .5rem; }
51
59
  .tangle-lines__row-actions button, .tangle-lines__error button, .tangle-lines__empty button { background: none; border: 0; color: var(--tl-accent); padding: .25rem 0; white-space: nowrap; }
52
60
  .tangle-lines__row-actions button:hover, .tangle-lines__error button:hover, .tangle-lines__empty button:hover { text-decoration: underline; }
@@ -61,7 +69,7 @@
61
69
  .tangle-lines__compact-label { color: var(--tl-muted); font-size: .8rem; }
62
70
  .tangle-lines__compact-label select { margin-top: .2rem; min-width: 8rem; }
63
71
 
64
- .tangle-lines__setup { border: 1px solid var(--tl-border); border-radius: .8rem; margin-top: 1.25rem; padding: 1.15rem; }
72
+ .tangle-lines__setup { background: var(--tl-panel); border: 1px solid var(--tl-border); border-radius: .95rem; margin-top: 1.25rem; padding: 1.4rem; }
65
73
  .tangle-lines__setup > p { color: var(--tl-muted); font-size: .87rem; margin-top: .35rem; }
66
74
  .tangle-lines__kinds { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: 1rem; }
67
75
  .tangle-lines__kinds button {
@@ -71,7 +79,7 @@
71
79
  color: var(--tl-muted);
72
80
  padding: .48rem .72rem;
73
81
  }
74
- .tangle-lines__kinds button[aria-pressed="true"] { background: var(--tl-text); border-color: var(--tl-text); color: var(--tl-surface); }
82
+ .tangle-lines__kinds button[aria-pressed="true"] { background: var(--tl-soft); border-color: var(--tl-accent); color: var(--tl-text); font-weight: 650; }
75
83
  .tangle-lines__fields { display: grid; gap: .9rem; grid-template-columns: repeat(2, minmax(0, 1fr)); margin: 1rem 0; }
76
84
  .tangle-lines__fields > label, .tangle-lines__compact-label { display: flex; flex-direction: column; gap: .28rem; }
77
85
  .tangle-lines__fields > label, .tangle-lines__fields legend { color: var(--tl-text); font-size: .85rem; font-weight: 550; }
@@ -89,8 +97,13 @@
89
97
  .tangle-lines__fields fieldset input { accent-color: var(--tl-accent); margin: 0; }
90
98
  .tangle-lines__primary { background: var(--tl-accent); border: 1px solid var(--tl-accent); border-radius: .5rem; color: var(--tl-accent-foreground); font-size: .88rem; font-weight: 600; min-height: 2.55rem; padding: .55rem .85rem; }
91
99
  .tangle-lines__primary:hover:not(:disabled) { filter: brightness(.92); }
92
- .tangle-lines__muted, .tangle-lines__empty { color: var(--tl-muted); font-size: .88rem; padding: .7rem 0; }
93
- .tangle-lines__error { align-items: center; border: 1px solid var(--tl-danger); border-radius: .5rem; color: var(--tl-danger); display: flex; font-size: .85rem; gap: .7rem; justify-content: space-between; margin-bottom: .8rem; padding: .65rem .8rem; }
100
+ .tangle-lines__primary:disabled { background: var(--tl-soft); border-color: var(--tl-border); color: var(--tl-muted); opacity: 1; }
101
+ .tangle-lines__muted { color: var(--tl-muted); font-size: .88rem; padding: 1rem 0; }
102
+ .tangle-lines__empty { color: var(--tl-muted); font-size: .88rem; padding: 1.5rem 1.25rem; }
103
+ .tangle-lines__empty strong { color: var(--tl-text); display: block; font-size: .95rem; margin-bottom: .3rem; }
104
+ .tangle-lines__error { align-items: center; background: var(--tl-danger-soft); border: 1px solid color-mix(in srgb, var(--tl-border) 65%, var(--tl-danger)); border-radius: .75rem; color: var(--tl-danger); display: flex; font-size: .88rem; gap: 1rem; justify-content: space-between; margin-bottom: 1rem; padding: 1rem 1.15rem; }
105
+ .tangle-lines__error strong { display: block; font-size: .94rem; margin-bottom: .2rem; }
106
+ .tangle-lines__error p { color: var(--tl-text); overflow-wrap: anywhere; }
94
107
  .tangle-lines__warning { color: var(--tl-warning); font-size: .85rem; margin-bottom: .8rem !important; }
95
108
 
96
109
  .tangle-lines__billing { border-top: 1px solid var(--tl-border); margin: 0; }
@@ -100,16 +113,28 @@
100
113
  .tangle-lines__billing dd.tangle-lines__billing-detail { color: var(--tl-muted); font-size: .81rem; font-weight: 400; grid-column: 2; }
101
114
 
102
115
  @media (max-width: 600px) {
103
- .tangle-lines__heading { align-items: start; }
116
+ .tangle-lines__heading { align-items: start; flex-wrap: wrap; }
104
117
  .tangle-lines__row { flex-direction: column; gap: .7rem; }
105
118
  .tangle-lines__row-actions { align-items: start; width: 100%; }
106
119
  .tangle-lines__confirm { justify-content: flex-start; }
107
120
  .tangle-lines__fields { grid-template-columns: 1fr; }
108
121
  .tangle-lines__billing > div { grid-template-columns: 1fr; }
109
122
  .tangle-lines__billing dd.tangle-lines__billing-detail { grid-column: 1; }
123
+ .tangle-lines__setup { padding: 1.15rem; }
124
+ .tangle-lines__error { align-items: flex-start; flex-direction: column; }
110
125
  }
111
126
 
112
- .tangle-lines__delegation { display: flex; align-items: flex-start; gap: .65rem; font-size: .9rem; line-height: 1.5; }
127
+ .tangle-lines__delegation { align-items: flex-start; background: var(--tl-soft); border: 1px solid var(--tl-border); border-radius: .65rem; display: flex; gap: .75rem; font-size: .9rem; line-height: 1.5; padding: .9rem 1rem; }
113
128
  .tangle-lines__delegation input { flex: 0 0 auto; margin-top: .25rem; }
114
- .tangle-lines--application { display: grid; gap: 1rem; margin-bottom: 1.5rem; }
129
+ .tangle-lines--application { display: grid; gap: 1.15rem; margin-bottom: 2.25rem; }
115
130
  .tangle-lines--application p { overflow-wrap: anywhere; }
131
+ .tangle-lines__application-heading { display: grid; gap: .55rem; padding: .15rem .1rem .3rem; }
132
+ .tangle-lines__application-heading p { color: var(--tl-muted); font-size: .98rem; max-width: 55ch; }
133
+ .tangle-lines__overline { color: var(--tl-accent); display: block; font-size: .72rem; font-weight: 700; letter-spacing: .11em; line-height: 1.4; margin-bottom: .15rem; text-transform: uppercase; }
134
+ .tangle-lines__authorization { background: var(--tl-panel); border: 1px solid var(--tl-border); border-radius: .95rem; padding: 1.4rem; }
135
+ .tangle-lines__authorization-heading p { color: var(--tl-muted); font-size: .88rem; margin-top: .25rem; }
136
+ .tangle-lines__fine-print { color: var(--tl-muted); font-size: .79rem; line-height: 1.5; margin-top: .85rem !important; }
137
+ .tangle-lines__notice { background: var(--tl-soft); border: 1px solid var(--tl-border); border-radius: .75rem; padding: 1rem 1.2rem; }
138
+ .tangle-lines__notice strong { display: block; font-size: .93rem; margin-bottom: .25rem; }
139
+ .tangle-lines__notice p { color: var(--tl-muted); font-size: .86rem; }
140
+ @media (max-width: 600px) { .tangle-lines__authorization { padding: 1.15rem; } }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-app",
3
- "version": "0.50.1",
3
+ "version": "0.50.3",
4
4
  "packageManager": "pnpm@11.24.0",
5
5
  "description": "Build agent applications with typed chat, tools, sandboxes, integrations, billing, and evaluation.",
6
6
  "keywords": [