@rubytech/create-maxy-code 0.1.347 → 0.1.349
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/payload/platform/lib/graph-style/dist/index.d.ts +1 -1
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +20 -12
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +9 -9
- package/payload/platform/lib/graph-style/src/index.ts +20 -12
- package/payload/platform/lib/graph-write/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-write/dist/index.js +3 -2
- package/payload/platform/lib/graph-write/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-write/src/index.ts +3 -2
- package/payload/platform/neo4j/schema.cypher +110 -31
- package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
- package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +36 -3
- package/payload/platform/plugins/docs/references/calendar-booking.md +1 -1
- package/payload/platform/plugins/docs/references/joblogic.md +28 -0
- package/payload/platform/plugins/docs/references/memory-guide.md +1 -1
- package/payload/platform/plugins/joblogic/.claude-plugin/plugin.json +21 -0
- package/payload/platform/plugins/joblogic/PLUGIN.md +182 -0
- package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/index.js +193 -0
- package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/package.json +3 -0
- package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts +2 -0
- package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/index.js +229 -0
- package/payload/platform/plugins/joblogic/mcp/dist/index.js.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts +31 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js +78 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts +35 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js +106 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts +8 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js +41 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts +21 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js +47 -0
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js.map +1 -0
- package/payload/platform/plugins/joblogic/mcp/package.json +10 -0
- package/payload/platform/plugins/joblogic/skills/joblogic/SKILL.md +32 -0
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relationship-patterns.test.js +28 -22
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/relationship-patterns.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js +8 -4
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-cypher-drift.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js +39 -10
- package/payload/platform/plugins/memory/mcp/dist/lib/__tests__/schema-write-path-task802.test.js.map +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/relationship-patterns.d.ts +1 -1
- package/payload/platform/plugins/memory/mcp/dist/lib/relationship-patterns.js +1 -1
- package/payload/platform/plugins/memory/references/schema-construction.md +152 -57
- package/payload/platform/plugins/memory/references/schema-trades.md +22 -24
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +46 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-GELNKMk6.js → AdminLoginScreens-BEzoTk56.js} +1 -1
- package/payload/server/public/assets/{AdminShell-C_KsjYH6.js → AdminShell-BG7YD4UO.js} +1 -1
- package/payload/server/public/assets/{Checkbox-iE6iVP7-.js → Checkbox-CvTFOczj.js} +1 -1
- package/payload/server/public/assets/{OperatorConversations-C4Cx814-.css → OperatorConversations-CnP9Y6g2.css} +1 -1
- package/payload/server/public/assets/OperatorConversations-DU8CqO-z.js +9 -0
- package/payload/server/public/assets/{admin-Ci2tLhyx.js → admin-Bhxa1HOy.js} +1 -1
- package/payload/server/public/assets/{browser-9dxtgr6y.js → browser-BAQFuyma.js} +1 -1
- package/payload/server/public/assets/calendar-sSr6zUjW.js +1 -0
- package/payload/server/public/assets/chat-ZH4Fsyu0.js +1 -0
- package/payload/server/public/assets/{data-BpTErRH6.js → data-CH6GNBO3.js} +1 -1
- package/payload/server/public/assets/{graph-DfQblprL.js → graph-DbGjFYPS.js} +1 -1
- package/payload/server/public/assets/graph-labels-IGIEr-uc.js +1 -0
- package/payload/server/public/assets/{operator-CHSf3dma.js → operator-Ba5afDyM.js} +1 -1
- package/payload/server/public/assets/{page-uweci4TA.js → page-D7uwMUOy.js} +1 -1
- package/payload/server/public/assets/{public-ZdqJjwT3.js → public-DikYWzOd.js} +1 -1
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +4 -4
- package/payload/server/public/chat.html +5 -5
- package/payload/server/public/data.html +4 -4
- package/payload/server/public/graph.html +6 -6
- package/payload/server/public/index.html +6 -6
- package/payload/server/public/operator.html +7 -7
- package/payload/server/public/public.html +5 -5
- package/payload/server/server.js +32 -15
- package/payload/server/public/assets/OperatorConversations-DAPefQEH.js +0 -9
- package/payload/server/public/assets/calendar-BmwMyHcQ.js +0 -1
- package/payload/server/public/assets/chat-CnG7zUb7.js +0 -1
- package/payload/server/public/assets/graph-labels-Bjyky6oK.js +0 -1
|
@@ -1,39 +1,86 @@
|
|
|
1
|
-
# Schema Reference — Construction
|
|
1
|
+
# Schema Reference — Construction / Field Service
|
|
2
2
|
|
|
3
|
-
Vertical schema for `businessType: "construction"` —
|
|
3
|
+
Vertical schema for `businessType: "construction"` — building firms, contractors, and
|
|
4
|
+
field-service operators (the SiteDesk brand). This is the **canonical, opinionated** SiteDesk
|
|
5
|
+
service-delivery ontology, authored from JobLogic's proven field-service domain so that an
|
|
6
|
+
operator's job maps onto shipped labels without inventing the model. JobLogic's term is the
|
|
7
|
+
canonical label name for each concept.
|
|
4
8
|
|
|
5
|
-
This reference extends the base schema. All base node types (Person, Organization, Invoice,
|
|
9
|
+
This reference extends the base schema. All base node types (Person, Organization, Invoice,
|
|
10
|
+
PostalAddress, Event, etc.) remain valid. Load `schema-base.md` first.
|
|
6
11
|
|
|
7
12
|
When loading this reference, confirm: "Using schema-base + schema-construction".
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
| Entity | Neo4j Label | Schema.org Type | Required Properties |
|
|
14
|
-
|--------|-------------|-----------------|---------------------|
|
|
15
|
-
| Job | `Job` | `schema:Project` | `accountId`, `jobId`, `client`, `address`, `status` (quoting/active/complete), `contractValue` |
|
|
16
|
-
| LineItem | `LineItem` | `cdm:LineItem` | `accountId`, `jobId`, `trade`, `description`, `contractValue` |
|
|
17
|
-
| Valuation | `Valuation` | `schema:MonetaryAmount` | `accountId`, `jobId`, `valuationNumber`, `date`, `totalValue` |
|
|
18
|
-
| Milestone | `Milestone` | `schema:Event` (subtype) | `accountId`, `jobId`, `name`, `completedDate` |
|
|
19
|
-
| QuoteDocument | `QuoteDocument` | `schema:DigitalDocument` | `accountId`, `jobId`, `ref`, `totalPaymentDue`, `date`, `status` (draft/sent/accepted) |
|
|
20
|
-
| VariationNote | `VariationNote` | `schema:DigitalDocument` | `accountId`, `jobId`, `variationNumber`, `description`, `totalPaymentDue`, `status` |
|
|
21
|
-
| InboundInvoice | `InboundInvoice` | `schema:Invoice` | `accountId`, `supplier`, `confirmationNumber`, `totalPaymentDue`, `status` (pending/approved/processed) |
|
|
22
|
-
| Worker | `Worker` (label on `Person`) | `schema:Person` (config) | `accountId`, `personId`, `name`, `engagement` (employee/cis), `dayRatePence`, `showCisDeduction`, `invoiceEmail` |
|
|
23
|
-
| CheckIn | `CheckIn` | `schema:Action` | `accountId`, `personId`, `source`, `date`, `site`, `description`, `dayHundredths` |
|
|
24
|
-
| WhatsAppGroup | `WhatsAppGroup` | `cdm:Channel` | `accountId`, `groupId`, `jobId`, `clientName` |
|
|
25
|
-
|
|
26
|
-
`awardedDate` on `Job` is expected once `status` is `active` or `complete` — a job still `quoting` has no award date. Never write a sentinel value (`"pending"`, `""`) to stand in for an unknown date; omit the property until the real date is known.
|
|
27
|
-
|
|
28
|
-
These entities model a general builder job folder: a `Job` has a generated client `QuoteDocument` that carries many `LineItem` rows organised by trade stage, supplier and sub-contractor invoices, and per-trade structure. A residential building job's line items typically span stages such as groundworks, sub-structure, superstructure, roof, structural alterations & envelope, first fix, drylining & plastering, floor screed, second fixing, knock-throughs, windows & doors, completion items and preliminaries, plus sub-contractor trades (scaffolding, roofing, electrical, plumbing, plastering, tiling, decorations). The schema carries no client, job, or pricing data of its own — those are per-account runtime values.
|
|
29
|
-
|
|
30
|
-
### Distinctions from schema-trades
|
|
31
|
-
|
|
32
|
-
`QuoteDocument` is the generated client quote artefact (the `Q-XXXX` document), distinct from schema-trades' `Quote` (a pre-acceptance Order estimate). `InboundInvoice` is a received/payable invoice with job + trade assignment, distinct from the base `Invoice`. A subcontractor company's received invoices use the same `InboundInvoice` model as any other supplier.
|
|
14
|
+
Property fidelity: properties marked **(JobLogic-exact)** are taken from JobLogic's API field
|
|
15
|
+
model; properties marked **(authored)** are modelled from JobLogic's vocabulary plus the
|
|
16
|
+
field-service domain where the captured reference does not document the entity at field level.
|
|
33
17
|
|
|
34
|
-
|
|
18
|
+
---
|
|
35
19
|
|
|
36
|
-
|
|
20
|
+
## Top-level node types (operator-entry, natural key)
|
|
21
|
+
|
|
22
|
+
| Entity | Neo4j Label | Schema.org Type | Required Properties | Fidelity |
|
|
23
|
+
|--------|-------------|-----------------|---------------------|----------|
|
|
24
|
+
| Job | `Job` | `schema:Project` | `accountId`, `jobId`, `status` | JobLogic-exact |
|
|
25
|
+
| Customer | `Customer` | `schema:Organization` | `accountId`, `customerId`, `name`, `customerType` | JobLogic-exact |
|
|
26
|
+
| Site | `Site` | `schema:Place` | `accountId`, `siteId`, `name`, `region` | JobLogic-exact |
|
|
27
|
+
| Asset | `Asset` | `schema:Product` | `accountId`, `assetId`, `name`, `assetType`, `assetClass`, `condition` | authored |
|
|
28
|
+
| Visit | `Visit` | `schema:Event` (subtype) | `accountId`, `visitId`, `status`, `startDate`, `purpose` | authored |
|
|
29
|
+
| Quote | `Quote` | `schema:Order` (estimate) | `accountId`, `ref`, `status`, `totalPaymentDue`, `date` | authored |
|
|
30
|
+
| Supplier invoice | `InboundInvoice` | `schema:Invoice` | `accountId`, `supplier`, `confirmationNumber`, `totalPaymentDue` | JobLogic-exact |
|
|
31
|
+
| Part | `Part` | `schema:Product` | `accountId`, `partId`, `name`, `sku`, `partCategory` | authored |
|
|
32
|
+
| Purchase Order | `PurchaseOrder` | `schema:Order` | `accountId`, `poNumber`, `status`, `completionStatus`, `dateRaised` | JobLogic-exact |
|
|
33
|
+
| PPM Contract | `PpmContract` | `schema:Service` (contract) | `accountId`, `contractId`, `name`, `startDate`, `endDate` | authored |
|
|
34
|
+
| WhatsApp Group | `WhatsAppGroup` | `cdm:Channel` | `accountId`, `groupId`, `jobId`, `clientName` | n/a (transport) |
|
|
35
|
+
|
|
36
|
+
`Job.status` is one of JobLogic's job statuses: `New Job`, `Allocated`, `Attended`,
|
|
37
|
+
`Parts To Fit`, `Awaiting Parts`, `Completed`, `Costed`, `Reqs. Invoice`, `Invoiced`, `Paid`,
|
|
38
|
+
`Cancelled`, `Recall`. `Job.jobType` is the highest categorisation (Call out, Installation,
|
|
39
|
+
Maintenance, Out of Hours, Reactive, Non-Productive); `Job.jobCategory` is the finer trade
|
|
40
|
+
detail. `Site.region` is one of `East`, `North`, `South`, `West`. `PurchaseOrder.status` is one
|
|
41
|
+
of `InProgress`, `Sent`, `Cancelled`, `NeedsApproval`; `PurchaseOrder.completionStatus` one of
|
|
42
|
+
`NotApplicable`, `NotCompleted`, `PartiallyCompleted`, `FullyCompleted`. Never write a sentinel
|
|
43
|
+
value for an unknown date — omit the property until the real value is known.
|
|
44
|
+
|
|
45
|
+
Two distinct invoice documents. The received supplier invoice is `InboundInvoice` (keyed
|
|
46
|
+
`(accountId, supplier, confirmationNumber)`), now linked to the `PurchaseOrder` it pays — a
|
|
47
|
+
subcontractor company's received invoice uses the same model as any other supplier. The
|
|
48
|
+
customer-facing outbound bill is the base `Invoice` (`schema-base.md`), whose billing chain is
|
|
49
|
+
the child `InvoiceLine`, `InvoicePayment`, and `Credit`. The two labels carry different required
|
|
50
|
+
fields (supplier vs customer), so they stay distinct rather than one label with a direction flag.
|
|
51
|
+
|
|
52
|
+
## Child node types (write-time MERGE; reached via parent neighbourhood)
|
|
53
|
+
|
|
54
|
+
| Entity | Neo4j Label | Required Properties | Fidelity |
|
|
55
|
+
|--------|-------------|---------------------|----------|
|
|
56
|
+
| Quote line | `QuoteLine` | `accountId`, `jobId`, `trade`, `description`, `contractValue` | authored |
|
|
57
|
+
| Valuation | `Valuation` | `accountId`, `jobId`, `valuationNumber`, `date`, `totalValue` | authored |
|
|
58
|
+
| Milestone | `Milestone` | `accountId`, `jobId`, `name`, `completedDate` | authored |
|
|
59
|
+
| Variation | `VariationNote` | `accountId`, `jobId`, `variationNumber`, `description`, `totalPaymentDue`, `status` | authored |
|
|
60
|
+
| Job cost | `JobCost` | `accountId`, `costType` | JobLogic-exact |
|
|
61
|
+
| Contact | `Contact` | `accountId`, `contactId`, `name` | JobLogic-exact |
|
|
62
|
+
| PO line | `PurchaseOrderLine` | `accountId`, `poNumber`, `lineId`, `description`, `quantity`, `pricePerUnit` | JobLogic-exact |
|
|
63
|
+
| Invoice line | `InvoiceLine` | `accountId`, `invoiceId`, `lineId`, `description`, `quantity`, `amount` | authored |
|
|
64
|
+
| Invoice payment | `InvoicePayment` | `accountId`, `invoiceId`, `paymentId`, `amount`, `date`, `paymentType` | JobLogic-exact |
|
|
65
|
+
| Credit | `Credit` | `accountId`, `creditId`, `amount`, `date` | authored |
|
|
66
|
+
|
|
67
|
+
`JobCost.costType` is one of `labour`, `material`, `travel`, `mileage`, `expense`,
|
|
68
|
+
`subcontractor`, `scheduleOfRates` — the JobLogic cost-line taxonomy. A logged labour day (the
|
|
69
|
+
old check-in) is a `JobCost` with `costType:'labour'`. `JobCost.priceCalculationType` is `0`
|
|
70
|
+
(Non-Chargeable), `1` (Calculated Price), or `2` (Fixed Price), JobLogic's enum.
|
|
71
|
+
|
|
72
|
+
`QuoteLine` is one priced row of the `Quote` contract schedule — the line a `Valuation` measures
|
|
73
|
+
percent-complete against. It is **not** a `JobCost`: the quote line is the priced contract value,
|
|
74
|
+
the job cost is the incurred cost. Per-line percent-complete a valuation records is carried
|
|
75
|
+
valuation state, not a property of the line or the edge.
|
|
76
|
+
|
|
77
|
+
## Additional labels on a base node
|
|
78
|
+
|
|
79
|
+
`Engineer` is an additional label on the field engineer's `:Person` (`accountId`, `engineerId`,
|
|
80
|
+
`name`, `engagement` (employee/cis), `dayRatePence`, `showCisDeduction`, `invoiceEmail`); there
|
|
81
|
+
is no standalone `:Engineer`. `Supplier` is an additional label on a supplier's `:Organization`
|
|
82
|
+
(`accountId`, `supplierId`, `accountNumber`); there is no standalone `:Supplier`. Both are set
|
|
83
|
+
via `memory-update`, mirroring how the field worker was modelled before the JobLogic adoption.
|
|
37
84
|
|
|
38
85
|
---
|
|
39
86
|
|
|
@@ -42,55 +89,103 @@ A field worker's time and pay is the `:Worker`/`:CheckIn` model. `:Worker` is an
|
|
|
42
89
|
MERGE keys per label:
|
|
43
90
|
|
|
44
91
|
- `:Job` — `(accountId, jobId)`
|
|
92
|
+
- `:Customer` — `(accountId, customerId)`
|
|
93
|
+
- `:Site` — `(accountId, siteId)`
|
|
94
|
+
- `:Asset` — `(accountId, assetId)`
|
|
95
|
+
- `:Visit` — `(accountId, visitId)`
|
|
96
|
+
- `:Quote` — `(accountId, ref)`
|
|
97
|
+
- `:InboundInvoice` — `(accountId, supplier, confirmationNumber)` — the received supplier invoice
|
|
98
|
+
- `:Invoice` — `(accountId, confirmationNumber)` — the base outbound customer invoice (schema-base.md)
|
|
99
|
+
- `:Part` — `(accountId, partId)`
|
|
100
|
+
- `:PurchaseOrder` — `(accountId, poNumber)`
|
|
101
|
+
- `:PpmContract` — `(accountId, contractId)`
|
|
102
|
+
- `:WhatsAppGroup` — `(accountId, groupId)`
|
|
103
|
+
- `:QuoteLine` — `(accountId, jobId, trade, description)` — child of `:Quote`, write-time MERGE
|
|
45
104
|
- `:Valuation` — `(accountId, jobId, valuationNumber)`
|
|
46
|
-
- `:
|
|
105
|
+
- `:Milestone` — `(accountId, jobId, name)` — child of `:Job`, write-time MERGE
|
|
47
106
|
- `:VariationNote` — `(accountId, jobId, variationNumber)`
|
|
48
|
-
- `:
|
|
49
|
-
- `:
|
|
50
|
-
- `:
|
|
51
|
-
- `:
|
|
52
|
-
- `:
|
|
53
|
-
- `:
|
|
107
|
+
- `:JobCost` — `(accountId, costId)` — write-time MERGE; `jobId` is set when the cost is job-scoped, omitted for a worker-day labour roll-up
|
|
108
|
+
- `:Contact` — `(accountId, contactId)` — write-time MERGE
|
|
109
|
+
- `:PurchaseOrderLine` — `(accountId, poNumber, lineId)` — child of `:PurchaseOrder`
|
|
110
|
+
- `:InvoiceLine` — `(accountId, invoiceId, lineId)` — child of `:Invoice`
|
|
111
|
+
- `:InvoicePayment` — `(accountId, invoiceId, paymentId)` — child of `:Invoice`
|
|
112
|
+
- `:Credit` — `(accountId, creditId)` — child of `:Invoice`
|
|
113
|
+
- `:Engineer` — `(accountId, personId)` — additional label on `:Person`, set via `memory-update`
|
|
114
|
+
- `:Supplier` — `(accountId, organizationId)` — additional label on `:Organization`
|
|
54
115
|
|
|
55
116
|
---
|
|
56
117
|
|
|
57
118
|
## Relationship Patterns
|
|
58
119
|
|
|
59
120
|
```
|
|
121
|
+
(:Job)-[:FOR_CUSTOMER]->(:Customer)
|
|
122
|
+
(:Customer)-[:HAS_SITE]->(:Site)
|
|
123
|
+
(:Job)-[:AT_SITE]->(:Site)
|
|
124
|
+
(:Site)-[:HAS_ASSET]->(:Asset)
|
|
125
|
+
(:Job)-[:HAS_VISIT]->(:Visit)
|
|
126
|
+
(:Visit)-[:ATTENDED_BY]->(:Engineer)
|
|
127
|
+
(:Job)-[:HAS_QUOTE]->(:Quote)
|
|
128
|
+
(:Quote)-[:HAS_LINE]->(:QuoteLine)
|
|
60
129
|
(:Job)-[:HAS_VALUATION]->(:Valuation)
|
|
61
|
-
(:
|
|
62
|
-
(:Job)-[:HAS_QUOTE]->(:QuoteDocument)
|
|
63
|
-
(:QuoteDocument)-[:HAS_LINE_ITEM]->(:LineItem)
|
|
64
|
-
(:Valuation)-[:VALUES]->(:LineItem)
|
|
130
|
+
(:Valuation)-[:VALUES]->(:QuoteLine)
|
|
65
131
|
(:Job)-[:HAS_VARIATION]->(:VariationNote)
|
|
66
|
-
(:Job)-[:
|
|
67
|
-
(:Job)-[:
|
|
68
|
-
(:
|
|
69
|
-
(:
|
|
70
|
-
(:
|
|
132
|
+
(:Job)-[:HAS_MILESTONE]->(:Milestone)
|
|
133
|
+
(:Job)-[:HAS_COST]->(:JobCost)
|
|
134
|
+
(:JobCost)-[:INCURRED_BY]->(:Engineer)
|
|
135
|
+
(:PurchaseOrder)-[:HAS_PO_LINE]->(:PurchaseOrderLine)
|
|
136
|
+
(:PurchaseOrderLine)-[:FOR_PART]->(:Part)
|
|
137
|
+
(:PurchaseOrder)-[:FROM_SUPPLIER]->(:Supplier)
|
|
138
|
+
(:InboundInvoice)-[:ON_PURCHASE_ORDER]->(:PurchaseOrder)
|
|
139
|
+
(:Invoice)-[:HAS_INVOICE_LINE]->(:InvoiceLine)
|
|
140
|
+
(:Invoice)-[:HAS_PAYMENT]->(:InvoicePayment)
|
|
141
|
+
(:Invoice)-[:HAS_CREDIT]->(:Credit)
|
|
142
|
+
(:PpmContract)-[:FOR_CUSTOMER]->(:Customer)
|
|
143
|
+
(:PpmContract)-[:COVERS_SITE]->(:Site)
|
|
144
|
+
(:Contact)-[:CONTACT_FOR]->(:Customer)
|
|
71
145
|
(:WhatsAppGroup)-[:MAPPED_TO]->(:Job)
|
|
72
146
|
```
|
|
73
147
|
|
|
74
|
-
Every `:Job` is the
|
|
148
|
+
Every `:Job` is the hub for its visits, quotes, valuations, variations, milestones, and costs,
|
|
149
|
+
satisfying the ≥1-adjacency write-gate doctrine. Quote lines are reached from the job through
|
|
150
|
+
the quote — `(:Job)-[:HAS_QUOTE]->(:Quote)-[:HAS_LINE]->(:QuoteLine)` — and each valuation links
|
|
151
|
+
the lines it measures with `(:Valuation)-[:VALUES]->(:QuoteLine)`. A job links to its customer
|
|
152
|
+
and site; an asset hangs off the site it lives at. Costs link to the engineer who incurred them.
|
|
153
|
+
Procurement is a `:PurchaseOrder` of `:PurchaseOrderLine`s for `:Part`s from a `:Supplier`; the
|
|
154
|
+
received supplier invoice is an `:InboundInvoice` on that PO. A `:PpmContract` is a
|
|
155
|
+
planned-maintenance agreement for a customer/site, distinct from a reactive `:Job`.
|
|
75
156
|
|
|
76
157
|
---
|
|
77
158
|
|
|
78
159
|
## Filesystem ↔ graph (base template)
|
|
79
160
|
|
|
80
|
-
The graph is
|
|
161
|
+
The graph is the canonical ontology; the operator's job folder is a conforming projection of it.
|
|
162
|
+
Every node corresponds to a filesystem artefact, and the edges follow the folder containment.
|
|
163
|
+
This mapping is the **base template** — the default a standard field-service job folder projects
|
|
164
|
+
into. It is shipped-generic; the folder names below are the common default, not any operator's
|
|
165
|
+
data. On any divergence, the graph is canonical.
|
|
81
166
|
|
|
82
167
|
A standard job folder, `{jobId} - {name}, {address} ({client})/`, projects as:
|
|
83
168
|
|
|
84
169
|
| Folder / artefact | Node | Edge from the job |
|
|
85
170
|
|---|---|---|
|
|
86
|
-
| the job folder itself | `:Job` | — (the hub); `(:Job)-[:
|
|
87
|
-
| `Quotations/` — the client quote
|
|
88
|
-
| `Finances/Valuations/` — one interim valuation per cycle | `:Valuation`; each measures the priced lines | `(:Job)-[:HAS_VALUATION]->(:Valuation)-[:VALUES]->(:
|
|
171
|
+
| the job folder itself | `:Job` | — (the hub); `(:Job)-[:FOR_CUSTOMER]->(:Customer)`, `(:Job)-[:AT_SITE]->(:Site)` |
|
|
172
|
+
| `Quotations/` — the client quote and its priced schedule | `:Quote`; its priced rows → `:QuoteLine` | `(:Job)-[:HAS_QUOTE]->(:Quote)-[:HAS_LINE]->(:QuoteLine)` |
|
|
173
|
+
| `Finances/Valuations/` — one interim valuation per cycle | `:Valuation`; each measures the priced lines | `(:Job)-[:HAS_VALUATION]->(:Valuation)-[:VALUES]->(:QuoteLine)` |
|
|
89
174
|
| the variations register | `:VariationNote` | `(:Job)-[:HAS_VARIATION]->(:VariationNote)` |
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
175
|
+
| `Costs/` — labour days, materials, travel, mileage, expenses, subcontractor | `:JobCost` (by `costType`) | `(:Job)-[:HAS_COST]->(:JobCost)-[:INCURRED_BY]->(:Engineer)` |
|
|
176
|
+
| `Visits/` — attendance records | `:Visit` | `(:Job)-[:HAS_VISIT]->(:Visit)-[:ATTENDED_BY]->(:Engineer)` |
|
|
177
|
+
| `Suppliers/<Supplier>/{Quotes,POs,Invoices}` | `:Organization:Supplier`; POs → `:PurchaseOrder`+`:PurchaseOrderLine`; received invoices → `:InboundInvoice` | `(:PurchaseOrder)-[:FROM_SUPPLIER]->(:Supplier)`, `(:InboundInvoice)-[:ON_PURCHASE_ORDER]->(:PurchaseOrder)` |
|
|
178
|
+
| `Assets/` — serviced plant on the site | `:Asset` | `(:Site)-[:HAS_ASSET]->(:Asset)` |
|
|
179
|
+
| `Drawings/`, `Health & Safety/`, `Emails/`, `Snagging/`, `Admin/` | ingested documents (`:KnowledgeDocument` + `:Section`) | linked to the `:Job` |
|
|
180
|
+
|
|
181
|
+
A contractor who keeps the whole job in one master workbook holds the same model in sheets
|
|
182
|
+
rather than folders: a cover/calculation sheet is the priced schedule (`:Quote` + `:QuoteLine`s),
|
|
183
|
+
one sheet per valuation cycle is a `:Valuation`, a variations sheet is the `:VariationNote`
|
|
184
|
+
register, a costs sheet is the `:JobCost` lines, and per-supplier sheets are the procurement
|
|
185
|
+
packages. Folder and workbook are two views of one job; both project into this same graph.
|
|
186
|
+
|
|
187
|
+
Operators vary this template — they rename folders, add trades, restructure their workbook. This
|
|
188
|
+
template is the shipped-generic default the agent projects against; the graph follows this one
|
|
189
|
+
canonical ontology, not a per-operator schema. Where a real folder does not fit the default, the
|
|
190
|
+
agent maps it to the nearest canonical node rather than inventing a node or edge type absent from
|
|
191
|
+
this reference.
|
|
@@ -1,36 +1,34 @@
|
|
|
1
1
|
# Schema Reference — Trades
|
|
2
2
|
|
|
3
|
-
Vertical schema for `businessType: "trades"` — home services
|
|
3
|
+
Vertical schema for `businessType: "trades"` — home services and tradespeople (plumber,
|
|
4
|
+
electrician, builder, decorator). Trades and construction share the **one canonical SiteDesk
|
|
5
|
+
service-delivery ontology** authored from JobLogic (see `schema-construction.md` for the full
|
|
6
|
+
label set, properties, idempotency keys, relationships, and the filesystem↔graph template).
|
|
7
|
+
There are no trades-specific labels that diverge from the canonical model.
|
|
4
8
|
|
|
5
|
-
This reference extends the base schema. All base node types (Person, Organization, Order, Event,
|
|
9
|
+
This reference extends the base schema. All base node types (Person, Organization, Order, Event,
|
|
10
|
+
Invoice, Service, etc.) remain valid. Load `schema-base.md` first.
|
|
6
11
|
|
|
7
12
|
When loading this reference, confirm: "Using schema-base + schema-trades".
|
|
8
13
|
|
|
9
14
|
---
|
|
10
15
|
|
|
11
|
-
##
|
|
16
|
+
## Canonical labels for the trades case
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
|--------|-------------|-----------------|---------------------|
|
|
15
|
-
| Quote | `Quote` | `schema:Order` + `cdm:Opportunity` | `accountId`, `quoteNumber`, `customer` (id), `lineItems`, `validUntil`, `totalPrice` |
|
|
16
|
-
| SiteVisit | `SiteVisit` | `schema:Event` (subtype) | `accountId`, `address` (id), `engineer` (id), `startDate`, `purpose` |
|
|
17
|
-
| Inspection | `Inspection` | `cdm:Case` (subtype) | `accountId`, `address` (id), `findings`, `recommendations`, `photos` |
|
|
18
|
-
| Certification | `Certification` | `schema:DigitalDocument` | `accountId`, `type` (gas safe, NICEIC, etc.), `issuedDate`, `expiryDate` |
|
|
19
|
-
| Material | `Material` | `schema:Product` | `accountId`, `name`, `sku`, `unitCost`, `supplier` (id) |
|
|
18
|
+
A tradesperson's work maps onto the same canonical labels as a contractor's:
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
| Trades concept | Canonical label | Notes |
|
|
21
|
+
|----------------|-----------------|-------|
|
|
22
|
+
| The job / call-out | Job | `jobType` distinguishes Call out / Installation / Maintenance / Reactive |
|
|
23
|
+
| Customer and the work address | Customer, Site | site is the work location, distinct from the customer |
|
|
24
|
+
| An attendance / site visit | Visit | the lifecycle attendance record on a job (was the homegrown SiteVisit) |
|
|
25
|
+
| The estimate / quote | Quote, QuoteLine | priced estimate and its lines |
|
|
26
|
+
| Parts and materials used | Part, JobCost (costType material) | catalogue part vs the incurred material cost on a job |
|
|
27
|
+
| Serviced equipment on site | Asset | boiler, AC unit, alarm panel, etc. |
|
|
28
|
+
| A planned-maintenance agreement | PpmContract | recurring service contract, distinct from a reactive Job |
|
|
22
29
|
|
|
23
|
-
|
|
30
|
+
Trade certifications (Gas Safe, NICEIC, Part P) a person holds are recorded as a credential on
|
|
31
|
+
that person's `:Person` node via the base credential model, not as a separate construction label.
|
|
32
|
+
Inspection findings are recorded as notes/documents on the `:Visit` or `:Asset` they concern.
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## Relationship Patterns
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
(:Order)-[:REQUIRES_VISIT]->(:SiteVisit)
|
|
31
|
-
(:Order)-[:USES_MATERIAL]->(:Material)
|
|
32
|
-
(:SiteVisit)-[:AT_ADDRESS]->(:PostalAddress)
|
|
33
|
-
(:Certification)-[:HELD_BY]->(:Person)
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
The `(:Certification)-[:HELD_BY]->(:Person)` relationship tracks which staff member holds a trade certification (e.g., Gas Safe, NICEIC, Part P).
|
|
34
|
+
See `schema-construction.md` for the authoritative definition of every label above.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,
|
|
1
|
+
{"version":3,"file":"canonical-tool-names.generated.d.ts","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"AAQA,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,EAAE,SAAS,MAAM,EAmB7C,CAAA;AAED,gEAAgE;AAChE,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAkPtD,CAAA"}
|
package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js
CHANGED
|
@@ -14,6 +14,7 @@ export const MAXY_MCP_PLUGINS = [
|
|
|
14
14
|
"email",
|
|
15
15
|
"graph",
|
|
16
16
|
"graph-viewer",
|
|
17
|
+
"joblogic",
|
|
17
18
|
"memory",
|
|
18
19
|
"outlook",
|
|
19
20
|
"quickbooks",
|
|
@@ -109,6 +110,51 @@ export const CANONICAL_MAXY_TOOL_NAMES = [
|
|
|
109
110
|
"mcp__plugin_graph_graph__maxy-graph-get_neo4j_schema",
|
|
110
111
|
"mcp__plugin_graph_graph__maxy-graph-read_neo4j_cypher",
|
|
111
112
|
"mcp__plugin_graph_graph__maxy-graph-write_neo4j_cypher",
|
|
113
|
+
"mcp__plugin_joblogic_joblogic__joblogic-asset-create",
|
|
114
|
+
"mcp__plugin_joblogic_joblogic__joblogic-asset-get",
|
|
115
|
+
"mcp__plugin_joblogic_joblogic__joblogic-asset-list",
|
|
116
|
+
"mcp__plugin_joblogic_joblogic__joblogic-asset-update",
|
|
117
|
+
"mcp__plugin_joblogic_joblogic__joblogic-attachment-url-generate",
|
|
118
|
+
"mcp__plugin_joblogic_joblogic__joblogic-connection-status",
|
|
119
|
+
"mcp__plugin_joblogic_joblogic__joblogic-credentials-set",
|
|
120
|
+
"mcp__plugin_joblogic_joblogic__joblogic-customer-create",
|
|
121
|
+
"mcp__plugin_joblogic_joblogic__joblogic-customer-get",
|
|
122
|
+
"mcp__plugin_joblogic_joblogic__joblogic-customer-list",
|
|
123
|
+
"mcp__plugin_joblogic_joblogic__joblogic-customer-update",
|
|
124
|
+
"mcp__plugin_joblogic_joblogic__joblogic-engineer-get",
|
|
125
|
+
"mcp__plugin_joblogic_joblogic__joblogic-engineer-list",
|
|
126
|
+
"mcp__plugin_joblogic_joblogic__joblogic-engineer-map-list",
|
|
127
|
+
"mcp__plugin_joblogic_joblogic__joblogic-engineer-map-set",
|
|
128
|
+
"mcp__plugin_joblogic_joblogic__joblogic-invoice-create",
|
|
129
|
+
"mcp__plugin_joblogic_joblogic__joblogic-invoice-get",
|
|
130
|
+
"mcp__plugin_joblogic_joblogic__joblogic-invoice-list",
|
|
131
|
+
"mcp__plugin_joblogic_joblogic__joblogic-invoice-payment-create",
|
|
132
|
+
"mcp__plugin_joblogic_joblogic__joblogic-job-approve",
|
|
133
|
+
"mcp__plugin_joblogic_joblogic__joblogic-job-create",
|
|
134
|
+
"mcp__plugin_joblogic_joblogic__joblogic-job-get",
|
|
135
|
+
"mcp__plugin_joblogic_joblogic__joblogic-job-list",
|
|
136
|
+
"mcp__plugin_joblogic_joblogic__joblogic-job-set-status",
|
|
137
|
+
"mcp__plugin_joblogic_joblogic__joblogic-job-update",
|
|
138
|
+
"mcp__plugin_joblogic_joblogic__joblogic-jobcost-create",
|
|
139
|
+
"mcp__plugin_joblogic_joblogic__joblogic-jobcost-update",
|
|
140
|
+
"mcp__plugin_joblogic_joblogic__joblogic-note-create",
|
|
141
|
+
"mcp__plugin_joblogic_joblogic__joblogic-quote-approve",
|
|
142
|
+
"mcp__plugin_joblogic_joblogic__joblogic-quote-create",
|
|
143
|
+
"mcp__plugin_joblogic_joblogic__joblogic-quote-get",
|
|
144
|
+
"mcp__plugin_joblogic_joblogic__joblogic-quote-list",
|
|
145
|
+
"mcp__plugin_joblogic_joblogic__joblogic-site-create",
|
|
146
|
+
"mcp__plugin_joblogic_joblogic__joblogic-site-get",
|
|
147
|
+
"mcp__plugin_joblogic_joblogic__joblogic-site-list",
|
|
148
|
+
"mcp__plugin_joblogic_joblogic__joblogic-site-update",
|
|
149
|
+
"mcp__plugin_joblogic_joblogic__joblogic-timesheet-create",
|
|
150
|
+
"mcp__plugin_joblogic_joblogic__joblogic-timesheet-list",
|
|
151
|
+
"mcp__plugin_joblogic_joblogic__joblogic-timesheet-update",
|
|
152
|
+
"mcp__plugin_joblogic_joblogic__joblogic-visit-cancel",
|
|
153
|
+
"mcp__plugin_joblogic_joblogic__joblogic-visit-create",
|
|
154
|
+
"mcp__plugin_joblogic_joblogic__joblogic-visit-deploy",
|
|
155
|
+
"mcp__plugin_joblogic_joblogic__joblogic-visit-get",
|
|
156
|
+
"mcp__plugin_joblogic_joblogic__joblogic-visit-search-planner",
|
|
157
|
+
"mcp__plugin_joblogic_joblogic__joblogic-visit-update",
|
|
112
158
|
"mcp__plugin_memory_memory__conversation-archive-derive-insights",
|
|
113
159
|
"mcp__plugin_memory_memory__conversation-archive-enrich-rejection",
|
|
114
160
|
"mcp__plugin_memory_memory__conversation-archive-list-chunks",
|
package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"canonical-tool-names.generated.js","sourceRoot":"","sources":["../src/canonical-tool-names.generated.ts"],"names":[],"mappings":"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"}
|
package/payload/server/public/assets/{AdminLoginScreens-GELNKMk6.js → AdminLoginScreens-BEzoTk56.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./chunk-CAM3fms7.js";import{A as t,C as n,U as r,b as i,x as a,z as o}from"./OperatorConversations-DAPefQEH.js";import{i as s}from"./admin-types-Dg11L4MQ.js";import{g as c,u as l}from"./AdminShell-C_KsjYH6.js";import{t as u}from"./Checkbox-iE6iVP7-.js";var d=`admin-landing-redirected`,f=`/graph`;function p(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var m=e(r(),1);function h(e=`admin`){let[t,n]=(0,m.useState)(`loading`),[r,i]=(0,m.useState)(``),[a,l]=(0,m.useState)(``),[u,h]=(0,m.useState)(``),[g,_]=(0,m.useState)(!1),[v,y]=(0,m.useState)(!1),[b,x]=(0,m.useState)(!1),[S,C]=(0,m.useState)(!1),[w,T]=(0,m.useState)(!1),[E,D]=(0,m.useState)(null),[O,k]=(0,m.useState)(null),[A,j]=(0,m.useState)(void 0),[M,N]=(0,m.useState)(null),[P,F]=(0,m.useState)(void 0),[I,L]=(0,m.useState)(null),[ee,R]=(0,m.useState)(null),[z,B]=(0,m.useState)([]),[V,H]=(0,m.useState)(!1),[U,W]=(0,m.useState)(void 0),G=(0,m.useRef)(void 0),[K,q]=(0,m.useState)(!1);(0,m.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&q(!0)}).catch(()=>{})},[]);let J=(0,m.useRef)(null),Y=(0,m.useRef)(null);(0,m.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let r=await t.json();D(r.session_key),R(r.sessionId??null),j(r.businessName),N(r.role??null),F(r.userName===void 0?null:r.userName),L(r.avatar??null);let i=s(r.thinkingView);return G.current=i,W(i),n(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(r=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check returned ${i.status} after retries`),n(`set-pin`);return}let a=await i.json();if(!a.pin_configured){n(`set-pin`);return}if(!a.claude_authenticated){n(`connect-claude`);return}if(await e())return;n(`enter-pin`)}catch(e){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check failed:`,e),n(`set-pin`)}}t()},[]),(0,m.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,m.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(d)===`1`}catch{}if(p({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(d,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${f}`),window.location.replace(f)}},[t,e]);let X=(0,m.useRef)(null);(0,m.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();if(t.auth_status===`dead`||t.auth_status===`missing`){n(`connect-claude`);return}}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){o(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),X.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,m.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&n(`enter-pin`)}).catch(()=>{})},[t]);async function Z(e,t){y(!0);try{let r=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!r.ok){h((await r.json().catch(()=>({}))).error||`Invalid PIN`);return}let a=await r.json();if(a.accounts&&!a.session_key){console.log(`[admin] account picker shown: userId=${a.userId} accountCount=${a.accounts.length}`),B(a.accounts),n(`account-picker`);return}D(a.session_key),R(a.sessionId??null),j(a.businessName),N(a.role??null),F(a.userName===void 0?null:a.userName),L(a.avatar??null);let o=s(a.thinkingView);if(G.current=o,W(o),t)try{sessionStorage.setItem(`maxy-account-id`,t)}catch{}try{sessionStorage.setItem(`maxy-admin-session-key`,a.session_key)}catch{}i(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1),H(!1)}}let Q=(0,m.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=a.trim();if(!t){h(`Please enter your name.`);return}if(r.length<4){h(`PIN must be at least 4 characters.`);return}let o=r;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let r=await e.json();r.pin_configured&&r.claude_authenticated?n(`enter-pin`):r.pin_configured?n(`connect-claude`):h(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await Z(o);return}i(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[r,v,a]),te=(0,m.useCallback)(async e=>{e.preventDefault(),h(``),await Z(r)},[r]),ne=(0,m.useCallback)(async()=>{T(!0);try{if(!await c())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}return n(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,m.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}i(``),h(``),n(`enter-pin`)},[]);return(0,m.useEffect)(()=>{X.current=$},[$]),{appState:t,setAppState:n,pin:r,setPin:i,operatorName:a,setOperatorName:l,pinError:u,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:ee,setSessionId:R,accounts:z,accountPickerLoading:V,expandAll:U,setExpandAll:W,expandAllDefaultRef:G,remoteAuthEnabled:K,pinInputRef:J,setPinFormRef:Y,handleSetPin:Q,handleLogin:te,handleAccountSelect:(0,m.useCallback)(async e=>{H(!0),h(``),await Z(r,e)},[r]),handleDisconnect:ne,handleLogout:$,handleChangePin:(0,m.useCallback)(async()=>{if(!r){h(`Enter your current PIN first.`);return}y(!0),h(``);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({currentPin:r})});if(!e.ok){h((await e.json().catch(()=>({error:`Incorrect PIN.`}))).error||`Incorrect PIN.`);return}i(``),h(``),n(`set-pin`)}catch(e){console.error(`[admin-auth] change pin failed:`,e),h(e instanceof Error?e.message:String(e))}finally{y(!1)}},[r])}}var g=n();function _({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,m.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,g.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,g.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function v(e){let{pin:t,setPin:n,showPin:r,setShowPin:o,pinLoading:s,pinError:c,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:h}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,i.productName]}),(0,g.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,i.productName,` who you are, then choose a PIN.`]}),(0,g.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>h(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,g.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r}),(0,g.jsx)(l,{variant:`send`,type:`submit`,disabled:!t||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsx)(u,{checked:r,onChange:()=>o(e=>!e),label:`Show PIN`})]}),c&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:c})]})})}function y(e){let{pin:t,setPin:n,showPin:r,setShowPin:o,pinLoading:s,pinError:c,pinInputRef:d,onSubmit:f,onChangePin:p,remoteAuthEnabled:m,onSignOutRemote:h}=e;return(0,g.jsxs)(`div`,{className:`connect-page`,children:[m&&h&&(0,g.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:h,children:`Sign out`}),(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:i.productName}),(0,g.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r,autoFocus:!0}),(0,g.jsx)(l,{variant:`send`,type:`submit`,disabled:!t,loading:s,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsxs)(`div`,{className:`pin-options`,children:[(0,g.jsx)(u,{checked:r,onChange:()=>o(e=>!e),label:`Show PIN`}),(0,g.jsx)(l,{type:`button`,variant:`ghost`,onClick:p,children:`Change PIN`})]})]}),c&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:c})]})]})}function b(e){let{accounts:n,loading:r,error:o,onSelect:s}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:i.productName}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Select an account`}),(0,g.jsx)(`div`,{className:`account-picker-list`,children:n.map(e=>(0,g.jsxs)(`button`,{className:`account-picker-card`,onClick:()=>s(e.accountId),disabled:r,type:`button`,children:[(0,g.jsx)(`span`,{className:`account-picker-name`,children:e.businessName||e.accountId}),(0,g.jsx)(`span`,{className:`account-picker-role`,children:e.role}),r&&(0,g.jsx)(t,{className:`account-picker-spinner`,size:16})]},e.accountId))}),o&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:o})]})})}function x(e){let{authPolling:t,setAuthPolling:n,authLoading:r,setAuthLoading:o,pinError:s,setPinError:c,setAppState:u}=e,[d,f]=(0,m.useState)(!1),[p,h]=(0,m.useState)(!1);async function _(){h(!0),c(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&c(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),c(`Could not launch browser.`)}h(!1)}async function v(){o(!0),c(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){n(!0),f(!0),o(!1);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}c(`Timed out waiting for sign-in. Try again.`),n(!1)}else e.error&&c(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),c(`Could not start auth flow.`)}o(!1)}async function y(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),c(``)}return t||d?(0,g.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,g.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[t?(0,g.jsx)(`button`,{onClick:y,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,g.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,g.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,g.jsx)(`p`,{className:`chat-intro`,children:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,g.jsx)(`div`,{style:{marginTop:`12px`},children:(0,g.jsx)(l,{variant:`primary`,onClick:v,disabled:r,children:r?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})})]}),(0,g.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,g.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,g.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsxs)(`div`,{className:`connect-logos`,children:[(0,g.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,g.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,g.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,g.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsx)(`span`,{className:`connect-logo-label`,children:i.productName})]})]}),(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,i.productName]}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,g.jsx)(l,{variant:`primary`,onClick:v,disabled:r,children:r?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,g.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,g.jsx)(`button`,{onClick:_,disabled:p,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:p?`Launching…`:`Open browser first`}),s&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function S({auth:e}){return e.appState===`loading`?(0,g.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,g.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,g.jsx)(x,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,g.jsx)(y,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,onChangePin:e.handleChangePin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):e.appState===`account-picker`?(0,g.jsx)(b,{accounts:e.accounts,loading:e.accountPickerLoading,error:e.pinError,onSelect:e.handleAccountSelect}):null}export{h as n,S as t};
|
|
1
|
+
import{o as e}from"./chunk-CAM3fms7.js";import{A as t,C as n,U as r,b as i,x as a,z as o}from"./OperatorConversations-DU8CqO-z.js";import{i as s}from"./admin-types-Dg11L4MQ.js";import{g as c,u as l}from"./AdminShell-BG7YD4UO.js";import{t as u}from"./Checkbox-CvTFOczj.js";var d=`admin-landing-redirected`,f=`/graph`;function p(e){return e.variant===`operator`?!1:e.appState===`chat`&&!e.alreadyRedirected}var m=e(r(),1);function h(e=`admin`){let[t,n]=(0,m.useState)(`loading`),[r,i]=(0,m.useState)(``),[a,l]=(0,m.useState)(``),[u,h]=(0,m.useState)(``),[g,_]=(0,m.useState)(!1),[v,y]=(0,m.useState)(!1),[b,x]=(0,m.useState)(!1),[S,C]=(0,m.useState)(!1),[w,T]=(0,m.useState)(!1),[E,D]=(0,m.useState)(null),[O,k]=(0,m.useState)(null),[A,j]=(0,m.useState)(void 0),[M,N]=(0,m.useState)(null),[P,F]=(0,m.useState)(void 0),[I,L]=(0,m.useState)(null),[ee,R]=(0,m.useState)(null),[z,B]=(0,m.useState)([]),[V,H]=(0,m.useState)(!1),[U,W]=(0,m.useState)(void 0),G=(0,m.useRef)(void 0),[K,q]=(0,m.useState)(!1);(0,m.useEffect)(()=>{typeof window>`u`||fetch(`/api/remote-auth/status`).then(e=>e.ok?e.json():null).then(e=>{e?.configured&&q(!0)}).catch(()=>{})},[]);let J=(0,m.useRef)(null),Y=(0,m.useRef)(null);(0,m.useEffect)(()=>{async function e(){let e=null;try{e=sessionStorage.getItem(`maxy-admin-session-key`)}catch{}if(!e)return!1;try{let t=await fetch(`/api/admin/session?session_key=${encodeURIComponent(e)}`);if(t.status===401){try{sessionStorage.removeItem(`maxy-admin-session-key`)}catch{}return!1}if(!t.ok)return!1;let r=await t.json();D(r.session_key),R(r.sessionId??null),j(r.businessName),N(r.role??null),F(r.userName===void 0?null:r.userName),L(r.avatar??null);let i=s(r.thinkingView);return G.current=i,W(i),n(`chat`),!0}catch(e){return console.error(`[admin] session restore failed:`,e),!1}}async function t(r=2){try{let i=await fetch(`/api/health`);if(!i.ok){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check returned ${i.status} after retries`),n(`set-pin`);return}let a=await i.json();if(!a.pin_configured){n(`set-pin`);return}if(!a.claude_authenticated){n(`connect-claude`);return}if(await e())return;n(`enter-pin`)}catch(e){if(r>0)return await new Promise(e=>setTimeout(e,1500)),t(r-1);console.error(`[admin] health check failed:`,e),n(`set-pin`)}}t()},[]),(0,m.useEffect)(()=>{t===`chat`&&fetch(`/api/admin/claude-info`).then(e=>{if(e.ok)return e.json()}).then(e=>{e&&k(e)}).catch(()=>{})},[t]),(0,m.useEffect)(()=>{if(typeof window>`u`)return;let n=!1;try{n=sessionStorage.getItem(d)===`1`}catch{}if(p({appState:t,alreadyRedirected:n,variant:e})){try{sessionStorage.setItem(d,`1`)}catch{}console.info(`[admin-ui] landing-redirect target=${f}`),window.location.replace(f)}},[t,e]);let X=(0,m.useRef)(null);(0,m.useEffect)(()=>{if(t!==`chat`)return;let e=setInterval(async()=>{try{let e=await fetch(`/api/health`);if(e.ok){let t=await e.json();if(t.auth_status===`dead`||t.auth_status===`missing`){n(`connect-claude`);return}}}catch{}if(E)try{let e=await fetch(`/api/admin/session?session_key=${encodeURIComponent(E)}`);if(e.status!==401)return;let t=(await e.clone().json().catch(()=>null))?.code??`unknown-401`;if(t===`remote-auth-required`){o(`heartbeat`,`/api/admin/session`);return}console.warn(`[admin-auth] outcome=heartbeat-detected-expiry code=${t}`),X.current?.()}catch{}},300*1e3);return()=>clearInterval(e)},[t,E]),(0,m.useEffect)(()=>{t===`connect-claude`&&fetch(`/api/health`).then(e=>e.ok?e.json():null).then(e=>{e?.claude_authenticated&&n(`enter-pin`)}).catch(()=>{})},[t]);async function Z(e,t){y(!0);try{let r=await fetch(`/api/admin/session`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:e,...t?{accountId:t}:{}})});if(!r.ok){h((await r.json().catch(()=>({}))).error||`Invalid PIN`);return}let a=await r.json();if(a.accounts&&!a.session_key){console.log(`[admin] account picker shown: userId=${a.userId} accountCount=${a.accounts.length}`),B(a.accounts),n(`account-picker`);return}D(a.session_key),R(a.sessionId??null),j(a.businessName),N(a.role??null),F(a.userName===void 0?null:a.userName),L(a.avatar??null);let o=s(a.thinkingView);if(G.current=o,W(o),t)try{sessionStorage.setItem(`maxy-account-id`,t)}catch{}try{sessionStorage.setItem(`maxy-admin-session-key`,a.session_key)}catch{}i(``),n(`chat`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1),H(!1)}}let Q=(0,m.useCallback)(async e=>{if(e.preventDefault(),v)return;h(``);let t=a.trim();if(!t){h(`Please enter your name.`);return}if(r.length<4){h(`PIN must be at least 4 characters.`);return}let o=r;y(!0);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({pin:o,name:t})});if(!e.ok){let t=await e.json().catch(()=>({}));if(e.status===409){console.log(`[admin] PIN already configured — re-checking health`);try{let e=await fetch(`/api/health`);if(e.ok){let r=await e.json();r.pin_configured&&r.claude_authenticated?n(`enter-pin`):r.pin_configured?n(`connect-claude`):h(t.error||`Failed to set PIN.`)}else n(`enter-pin`)}catch{n(`enter-pin`)}return}h(t.error||`Failed to set PIN.`);return}let r=await fetch(`/api/health`);if((r.ok?await r.json():null)?.claude_authenticated){await Z(o);return}i(``),n(`connect-claude`)}catch(e){console.error(`[admin] connection error:`,e),h(`Could not connect.`)}finally{y(!1)}},[r,v,a]),te=(0,m.useCallback)(async e=>{e.preventDefault(),h(``),await Z(r)},[r]),ne=(0,m.useCallback)(async()=>{T(!0);try{if(!await c())return console.warn(`[admin-ui] claude-disconnect not verified — credentials may persist; staying put`),!1;D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}return n(`connect-claude`),!0}finally{T(!1)}},[]),$=(0,m.useCallback)(()=>{D(null),N(null),F(void 0),L(null);try{sessionStorage.removeItem(`maxy-admin-session-key`),sessionStorage.removeItem(`maxy-account-id`),sessionStorage.removeItem(d)}catch{}i(``),h(``),n(`enter-pin`)},[]);return(0,m.useEffect)(()=>{X.current=$},[$]),{appState:t,setAppState:n,pin:r,setPin:i,operatorName:a,setOperatorName:l,pinError:u,setPinError:h,showPin:g,setShowPin:_,pinLoading:v,authPolling:b,setAuthPolling:x,authLoading:S,setAuthLoading:C,disconnecting:w,cacheKey:E,setCacheKey:D,claudeInfo:O,setClaudeInfo:k,businessName:A,role:M,userName:P,userAvatar:I,sessionId:ee,setSessionId:R,accounts:z,accountPickerLoading:V,expandAll:U,setExpandAll:W,expandAllDefaultRef:G,remoteAuthEnabled:K,pinInputRef:J,setPinFormRef:Y,handleSetPin:Q,handleLogin:te,handleAccountSelect:(0,m.useCallback)(async e=>{H(!0),h(``),await Z(r,e)},[r]),handleDisconnect:ne,handleLogout:$,handleChangePin:(0,m.useCallback)(async()=>{if(!r){h(`Enter your current PIN first.`);return}y(!0),h(``);try{let e=await fetch(`/api/onboarding/set-pin`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({currentPin:r})});if(!e.ok){h((await e.json().catch(()=>({error:`Incorrect PIN.`}))).error||`Incorrect PIN.`);return}i(``),h(``),n(`set-pin`)}catch(e){console.error(`[admin-auth] change pin failed:`,e),h(e instanceof Error?e.message:String(e))}finally{y(!1)}},[r])}}var g=n();function _({inputRef:e,value:t,onChange:n,onComplete:r,showPin:i,autoFocus:a}){let o=(0,m.useRef)([]);function s(e,r){r.key===`Backspace`?(r.preventDefault(),t[e]?n(t.slice(0,e)+t.slice(e+1)):e>0&&(n(t.slice(0,e-1)+t.slice(e)),o.current[e-1]?.focus())):r.key===`ArrowLeft`&&e>0?o.current[e-1]?.focus():r.key===`ArrowRight`&&e<5?o.current[e+1]?.focus():r.key===`Enter`&&(r.preventDefault(),r.currentTarget.form?.requestSubmit())}function c(e,i){let a=i.nativeEvent.data;if(!a||!/^\d$/.test(a))return;let s=t.split(``);for(s[e]=a;s.length<e;)s.push(``);let c=s.join(``).replace(/\D/g,``).slice(0,6);n(c),c.length===6?r?.(c):e<5&&o.current[e+1]?.focus()}function l(e){e.preventDefault();let t=e.clipboardData.getData(`text`).replace(/\D/g,``).slice(0,6);t&&(n(t),t.length===6?r?.(t):o.current[t.length]?.focus())}return(0,g.jsx)(`div`,{className:`pin-field`,children:Array.from({length:6}).map((n,r)=>(0,g.jsx)(`input`,{ref:t=>{o.current[r]=t,r===0&&e&&(e.current=t)},type:`text`,inputMode:`numeric`,className:`pin-box${t[r]?` pin-box-filled`:``}`,value:t[r]?i?t[r]:`•`:``,onKeyDown:e=>s(r,e),onInput:e=>c(r,e),onPaste:l,onFocus:e=>e.target.select(),autoFocus:a&&r===0,autoComplete:`off`,maxLength:1,"aria-label":`PIN digit ${r+1}`},r))})}function v(e){let{pin:t,setPin:n,showPin:r,setShowPin:o,pinLoading:s,pinError:c,pinInputRef:d,setPinFormRef:f,onSubmit:p,operatorName:m,setOperatorName:h}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Welcome to `,i.productName]}),(0,g.jsxs)(`p`,{className:`connect-subtitle`,children:[`Tell `,i.productName,` who you are, then choose a PIN.`]}),(0,g.jsxs)(`form`,{ref:f,onSubmit:p,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(`input`,{type:`text`,className:`connect-name-input`,placeholder:`Your full name`,value:m,onChange:e=>h(e.target.value),autoComplete:`name`,autoFocus:!0,required:!0,"aria-label":`Your full name`}),(0,g.jsx)(`div`,{style:{width:38,flexShrink:0},"aria-hidden":`true`})]}),(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r}),(0,g.jsx)(l,{variant:`send`,type:`submit`,disabled:!t||!m.trim(),loading:s,"aria-label":`Set PIN`,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsx)(u,{checked:r,onChange:()=>o(e=>!e),label:`Show PIN`})]}),c&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:c})]})})}function y(e){let{pin:t,setPin:n,showPin:r,setShowPin:o,pinLoading:s,pinError:c,pinInputRef:d,onSubmit:f,onChangePin:p,remoteAuthEnabled:m,onSignOutRemote:h}=e;return(0,g.jsxs)(`div`,{className:`connect-page`,children:[m&&h&&(0,g.jsx)(`button`,{type:`button`,className:`connect-signout`,onClick:h,children:`Sign out`}),(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:i.productName}),(0,g.jsxs)(`form`,{onSubmit:f,className:`connect-pin-form`,children:[(0,g.jsxs)(`div`,{className:`pin-input-row`,children:[(0,g.jsx)(_,{inputRef:d,value:t,onChange:n,onComplete:()=>{},showPin:r,autoFocus:!0}),(0,g.jsx)(l,{variant:`send`,type:`submit`,disabled:!t,loading:s,children:(0,g.jsxs)(`svg`,{viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,g.jsx)(`line`,{x1:`5`,y1:`12`,x2:`19`,y2:`12`}),(0,g.jsx)(`polyline`,{points:`12 5 19 12 12 19`})]})})]}),(0,g.jsxs)(`div`,{className:`pin-options`,children:[(0,g.jsx)(u,{checked:r,onChange:()=>o(e=>!e),label:`Show PIN`}),(0,g.jsx)(l,{type:`button`,variant:`ghost`,onClick:p,children:`Change PIN`})]})]}),c&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:c})]})]})}function b(e){let{accounts:n,loading:r,error:o,onSelect:s}=e;return(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsx)(`h1`,{className:`connect-title`,children:i.productName}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Select an account`}),(0,g.jsx)(`div`,{className:`account-picker-list`,children:n.map(e=>(0,g.jsxs)(`button`,{className:`account-picker-card`,onClick:()=>s(e.accountId),disabled:r,type:`button`,children:[(0,g.jsx)(`span`,{className:`account-picker-name`,children:e.businessName||e.accountId}),(0,g.jsx)(`span`,{className:`account-picker-role`,children:e.role}),r&&(0,g.jsx)(t,{className:`account-picker-spinner`,size:16})]},e.accountId))}),o&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:o})]})})}function x(e){let{authPolling:t,setAuthPolling:n,authLoading:r,setAuthLoading:o,pinError:s,setPinError:c,setAppState:u}=e,[d,f]=(0,m.useState)(!1),[p,h]=(0,m.useState)(!1);async function _(){h(!0),c(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`launch-browser`})})).json();e.launched?f(!0):e.error&&c(e.error)}catch(e){console.error(`[admin] browser launch error:`,e),c(`Could not launch browser.`)}h(!1)}async function v(){o(!0),c(``);try{let e=await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`})).json();if(e.started){n(!0),f(!0),o(!1);for(let e=0;e<120;e++)if(await new Promise(e=>setTimeout(e,2e3)),(await(await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`wait`})})).json()).authenticated){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),u(`enter-pin`);return}c(`Timed out waiting for sign-in. Try again.`),n(!1)}else e.error&&c(e.error)}catch(e){console.error(`[admin] auth flow error:`,e),c(`Could not start auth flow.`)}o(!1)}async function y(){await fetch(`/api/onboarding/claude-auth`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:`stop`})}),n(!1),c(``)}return t||d?(0,g.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,height:`100dvh`,overflow:`auto`},children:[(0,g.jsxs)(`header`,{className:`chat-header`,style:{paddingBottom:`12px`,flexShrink:0,position:`relative`,maxWidth:`680px`,width:`100%`,margin:`0 auto`,padding:`24px 20px 12px`},children:[t?(0,g.jsx)(`button`,{onClick:y,style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Cancel`,children:`✕`}):(0,g.jsx)(`button`,{onClick:()=>f(!1),style:{position:`absolute`,top:`12px`,right:`12px`,background:`none`,border:`none`,color:`#999`,fontSize:`13px`,cursor:`pointer`,padding:`4px 8px`},"aria-label":`Close browser`,children:`✕`}),(0,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`chat-logo`}),(0,g.jsx)(`h1`,{className:`chat-tagline`,children:`Connect Claude`}),(0,g.jsx)(`p`,{className:`chat-intro`,children:t?`Sign in and authorize in the browser below.`:`Open your email or prepare your accounts, then sign in.`}),!t&&(0,g.jsx)(`div`,{style:{marginTop:`12px`},children:(0,g.jsx)(l,{variant:`primary`,onClick:v,disabled:r,children:r?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`})})]}),(0,g.jsx)(`div`,{style:{flex:1,display:`flex`,flexDirection:`column`,minHeight:0,gap:`10px`,padding:`0 0 16px`},children:(0,g.jsx)(`iframe`,{src:`/vnc-viewer.html`,style:{flex:1,width:`100%`,minHeight:0,border:`none`,background:`#111`,display:`block`},title:`Claude Sign-in`})}),s&&(0,g.jsx)(`p`,{className:`admin-pin-error`,style:{textAlign:`center`,padding:`0 20px 16px`},children:s})]}):(0,g.jsx)(`div`,{className:`connect-page`,children:(0,g.jsxs)(`div`,{className:`connect-content`,children:[(0,g.jsxs)(`div`,{className:`connect-logos`,children:[(0,g.jsx)(`div`,{className:`connect-logo-wrap`,children:(0,g.jsx)(`img`,{src:`/brand/claude.png`,alt:`Claude`,className:`connect-logo`})}),(0,g.jsx)(`svg`,{className:`connect-arrow`,viewBox:`0 0 48 24`,fill:`none`,xmlns:`http://www.w3.org/2000/svg`,children:(0,g.jsx)(`path`,{d:`M0 12h44m0 0l-8-8m8 8l-8 8`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`})}),(0,g.jsxs)(`div`,{className:`connect-logo-wrap`,children:[(0,g.jsx)(`img`,{src:a,alt:i.productName,className:`connect-logo connect-logo--maxy`}),!i.logoContainsName&&(0,g.jsx)(`span`,{className:`connect-logo-label`,children:i.productName})]})]}),(0,g.jsxs)(`h1`,{className:`connect-title`,children:[`Connect Claude to power `,i.productName]}),(0,g.jsx)(`p`,{className:`connect-subtitle`,children:`Sign in with your Anthropic account to get started.`}),(0,g.jsx)(l,{variant:`primary`,onClick:v,disabled:r,children:r?(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(`span`,{className:`spin`,style:{display:`inline-block`},children:`✱`}),` Connecting…`]}):`Sign in to Claude`}),(0,g.jsx)(`p`,{style:{marginTop:`6px`,fontSize:`11px`,color:`#999`,maxWidth:`300px`,textAlign:`center`,lineHeight:`1.4`},children:`First time? You may need to sign into your email and Anthropic account in the browser before connecting.`}),(0,g.jsx)(`button`,{onClick:_,disabled:p,style:{marginTop:`12px`,background:`none`,border:`none`,color:`var(--color-primary, #666)`,fontSize:`13px`,cursor:`pointer`,textDecoration:`underline`,textUnderlineOffset:`3px`},children:p?`Launching…`:`Open browser first`}),s&&(0,g.jsx)(`p`,{className:`admin-pin-error`,children:s})]})})}function S({auth:e}){return e.appState===`loading`?(0,g.jsx)(`div`,{className:`connect-page`}):e.appState===`set-pin`?(0,g.jsx)(v,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,setPinFormRef:e.setPinFormRef,onSubmit:e.handleSetPin,operatorName:e.operatorName,setOperatorName:e.setOperatorName}):e.appState===`connect-claude`?(0,g.jsx)(x,{authPolling:e.authPolling,setAuthPolling:e.setAuthPolling,authLoading:e.authLoading,setAuthLoading:e.setAuthLoading,pinError:e.pinError,setPinError:e.setPinError,setAppState:e.setAppState}):e.appState===`enter-pin`?(0,g.jsx)(y,{pin:e.pin,setPin:e.setPin,showPin:e.showPin,setShowPin:e.setShowPin,pinLoading:e.pinLoading,pinError:e.pinError,pinInputRef:e.pinInputRef,onSubmit:e.handleLogin,onChangePin:e.handleChangePin,remoteAuthEnabled:e.remoteAuthEnabled,onSignOutRemote:()=>{console.info(`[admin-ui] remote-auth sign-out → /__remote-auth/logout`),window.location.href=`/__remote-auth/logout`}}):e.appState===`account-picker`?(0,g.jsx)(b,{accounts:e.accounts,loading:e.accountPickerLoading,error:e.pinError,onSelect:e.handleAccountSelect}):null}export{h as n,S as t};
|