theokit 0.1.0-alpha.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions-virtual-module-E6PU47GV.js +175 -0
- package/dist/actions-virtual-module-E6PU47GV.js.map +1 -0
- package/dist/actions-virtual-module-E7IELVHL.js +174 -0
- package/dist/actions-virtual-module-E7IELVHL.js.map +1 -0
- package/dist/add-2ZFFGGE4.js +0 -0
- package/dist/app-typed-client-4L4L4BWD.js +289 -0
- package/dist/app-typed-client-4L4L4BWD.js.map +1 -0
- package/dist/app-typed-client-6PAT6VOL.js +289 -0
- package/dist/app-typed-client-6PAT6VOL.js.map +1 -0
- package/dist/aws-lambda-PONVF3UX.js +0 -0
- package/dist/broadcast-QOQGUNNK.js +0 -0
- package/dist/{build-IQQYCA3B.js → build-EWZDEDT3.js} +37 -11
- package/dist/build-EWZDEDT3.js.map +1 -0
- package/dist/build-request-body-preview-EOP2Y4F3.js +52 -0
- package/dist/build-request-body-preview-EOP2Y4F3.js.map +1 -0
- package/dist/build-request-body-preview-II2235E6.js +54 -0
- package/dist/build-request-body-preview-II2235E6.js.map +1 -0
- package/dist/bun-DITMZMKL.js +0 -0
- package/dist/check-PZR67OY5.js +0 -0
- package/dist/{chunk-GQSTRXXB.js → chunk-2BQYEBCK.js} +77 -68
- package/dist/chunk-2BQYEBCK.js.map +1 -0
- package/dist/{chunk-FRBYJANT.js → chunk-4W447H7M.js} +195 -41
- package/dist/chunk-4W447H7M.js.map +1 -0
- package/dist/chunk-5ODOE6EF.js +0 -0
- package/dist/chunk-7DHGV77J.js +140 -0
- package/dist/chunk-7DHGV77J.js.map +1 -0
- package/dist/{chunk-WQCPKA2L.js → chunk-C27AZN46.js} +570 -165
- package/dist/chunk-C27AZN46.js.map +1 -0
- package/dist/chunk-ERAZNHHR.js +73 -0
- package/dist/chunk-ERAZNHHR.js.map +1 -0
- package/dist/chunk-F3TG5FJV.js +97 -0
- package/dist/chunk-F3TG5FJV.js.map +1 -0
- package/dist/chunk-KJVEJILQ.js +109 -0
- package/dist/chunk-KJVEJILQ.js.map +1 -0
- package/dist/chunk-KT3MWNZG.js +0 -0
- package/dist/{chunk-MCP6Y5BA.js → chunk-M23FP2AS.js} +25 -1
- package/dist/chunk-M23FP2AS.js.map +1 -0
- package/dist/{chunk-S3JBIFKS.js → chunk-MG7H3LAW.js} +2 -2
- package/dist/chunk-MOT42NAH.js +165 -0
- package/dist/chunk-MOT42NAH.js.map +1 -0
- package/dist/chunk-O7335ZGH.js +0 -0
- package/dist/{chunk-OEB3OIYP.js → chunk-OJHO2X7C.js} +497 -168
- package/dist/chunk-OJHO2X7C.js.map +1 -0
- package/dist/chunk-QLGES2HC.js +189 -0
- package/dist/chunk-QLGES2HC.js.map +1 -0
- package/dist/{chunk-JZ5WEG3S.js → chunk-SEVYARIU.js} +9 -5
- package/dist/chunk-SEVYARIU.js.map +1 -0
- package/dist/{chunk-ZK5JCE5J.js → chunk-TFECHXR5.js} +201 -43
- package/dist/chunk-TFECHXR5.js.map +1 -0
- package/dist/chunk-WSJKACWB.js +17 -0
- package/dist/chunk-WSJKACWB.js.map +1 -0
- package/dist/chunk-WZ7CPVQB.js +0 -0
- package/dist/chunk-XMS5VRIK.js +0 -0
- package/dist/chunk-Y5KE6YFP.js +0 -0
- package/dist/{chunk-3Q36SEDK.js → chunk-ZBWROIIO.js} +43 -2
- package/dist/{chunk-3Q36SEDK.js.map → chunk-ZBWROIIO.js.map} +1 -1
- package/dist/chunk-ZOXNJV2O.js +358 -0
- package/dist/chunk-ZOXNJV2O.js.map +1 -0
- package/dist/cli/index.js +22 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/client/index.d.ts +31 -1
- package/dist/client/index.js +100 -0
- package/dist/client/index.js.map +1 -1
- package/dist/cloudflare-RBANU3SE.js +0 -0
- package/dist/configure-agent-registry-6YGTJYBC.js +0 -0
- package/dist/deno-deploy-J7LI6HNL.js +0 -0
- package/dist/{dev-VN6WS3CM.js → dev-74KPI5C5.js} +15 -7
- package/dist/dev-74KPI5C5.js.map +1 -0
- package/dist/dev-emit-3CHM73TV.js +390 -0
- package/dist/dev-emit-3CHM73TV.js.map +1 -0
- package/dist/dev-emit-I3CKOHML.js +44 -0
- package/dist/dev-emit-I3CKOHML.js.map +1 -0
- package/dist/devtools/entry.js +653 -243
- package/dist/devtools/entry.js.map +1 -1
- package/dist/dispatcher-AQJGI3HU.js +8 -0
- package/dist/dispatcher-E6QV32BO.js +83 -0
- package/dist/dispatcher-E6QV32BO.js.map +1 -0
- package/dist/{dist-UZV7J3YI.js → dist-R2Q7GVDW.js} +10412 -11961
- package/dist/dist-R2Q7GVDW.js.map +1 -0
- package/dist/docker-EZDA5FT7.js +0 -0
- package/dist/{generate-SIO4JSKJ.js → generate-DT4IIAHF.js} +88 -22
- package/dist/generate-DT4IIAHF.js.map +1 -0
- package/dist/index.d.ts +108 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/{info-B3UOXFUF.js → info-VM7EK4JC.js} +3 -3
- package/dist/lib-NST3PNZX.js +0 -0
- package/dist/netlify-IFY6ZGFV.js +0 -0
- package/dist/node-KWZI3CKV.js +0 -0
- package/dist/openapi-CBASKC7W.js +84 -0
- package/dist/openapi-CBASKC7W.js.map +1 -0
- package/dist/proper-lockfile-MVKMQGFK.js +0 -0
- package/dist/{registry-BB3UYAOG.js → registry-QGSNLJKJ.js} +2 -2
- package/dist/{routes-CAGFZKUK.js → routes-7O4NUDYS.js} +9 -7
- package/dist/{routes-CAGFZKUK.js.map → routes-7O4NUDYS.js.map} +1 -1
- package/dist/scan-C2BOKLSY.js +0 -0
- package/dist/{schema-Cxq2qqwh.d.ts → schema-CjVly9c_.d.ts} +43 -1
- package/dist/{schema-MVB2FVK6.js → schema-JAKF23GR.js} +2 -2
- package/dist/server/cost/index.d.ts +7 -0
- package/dist/server/cost/index.js +1 -1
- package/dist/server/index.d.ts +219 -47
- package/dist/server/index.js +101 -114
- package/dist/server/index.js.map +1 -1
- package/dist/services-typed-client-ZX5JUHH3.js +0 -0
- package/dist/sqlite-vec-54KB4RD3.js +0 -0
- package/dist/{start-CSLJQXV3.js → start-5JTFWF4T.js} +20 -14
- package/dist/start-5JTFWF4T.js.map +1 -0
- package/dist/{static-BH6JQNM2.js → static-6PZZBY7G.js} +4 -4
- package/dist/storage-manager-D5KBXXKB.js +0 -0
- package/dist/theo-cloud-3K4DGB3S.js +0 -0
- package/dist/{upgrade-readiness-OHL36FQL.js → upgrade-readiness-Q46KTG2J.js} +6 -1
- package/dist/upgrade-readiness-Q46KTG2J.js.map +1 -0
- package/dist/vercel-RHADE5IP.js +0 -0
- package/dist/vite-plugin/index.d.ts +25 -1
- package/dist/vite-plugin/index.js +5 -2
- package/dist/{vite-plugin-WA3G45YY.js → vite-plugin-3EQP2JYM.js} +7 -6
- package/dist/vite-plugin-3EQP2JYM.js.map +1 -0
- package/package.json +10 -8
- package/LICENSE +0 -201
- package/dist/build-IQQYCA3B.js.map +0 -1
- package/dist/chunk-FRBYJANT.js.map +0 -1
- package/dist/chunk-GQSTRXXB.js.map +0 -1
- package/dist/chunk-JZ5WEG3S.js.map +0 -1
- package/dist/chunk-MCP6Y5BA.js.map +0 -1
- package/dist/chunk-OEB3OIYP.js.map +0 -1
- package/dist/chunk-WQCPKA2L.js.map +0 -1
- package/dist/chunk-ZK5JCE5J.js.map +0 -1
- package/dist/dev-VN6WS3CM.js.map +0 -1
- package/dist/dist-UZV7J3YI.js.map +0 -1
- package/dist/generate-SIO4JSKJ.js.map +0 -1
- package/dist/start-CSLJQXV3.js.map +0 -1
- package/dist/upgrade-readiness-OHL36FQL.js.map +0 -1
- /package/dist/{chunk-S3JBIFKS.js.map → chunk-MG7H3LAW.js.map} +0 -0
- /package/dist/{schema-MVB2FVK6.js.map → dispatcher-AQJGI3HU.js.map} +0 -0
- /package/dist/{info-B3UOXFUF.js.map → info-VM7EK4JC.js.map} +0 -0
- /package/dist/{registry-BB3UYAOG.js.map → registry-QGSNLJKJ.js.map} +0 -0
- /package/dist/{vite-plugin-WA3G45YY.js.map → schema-JAKF23GR.js.map} +0 -0
- /package/dist/{static-BH6JQNM2.js.map → static-6PZZBY7G.js.map} +0 -0
package/dist/devtools/entry.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CHANNEL_CSRF_WARN,
|
|
3
|
+
CHANNEL_ERROR,
|
|
4
|
+
CHANNEL_MANIFEST,
|
|
5
|
+
CHANNEL_REQUEST,
|
|
6
|
+
CHANNEL_ROUTE_MATCHED,
|
|
7
|
+
RING_BUFFER_CAP,
|
|
8
|
+
STORAGE_VERSION,
|
|
9
|
+
dispatcher,
|
|
10
|
+
initialState
|
|
11
|
+
} from "../chunk-KJVEJILQ.js";
|
|
1
12
|
import "../chunk-DGUM43GV.js";
|
|
2
13
|
|
|
3
14
|
// src/devtools/entry.tsx
|
|
@@ -433,9 +444,448 @@ function Indicator() {
|
|
|
433
444
|
);
|
|
434
445
|
}
|
|
435
446
|
|
|
436
|
-
// src/devtools/components/Tabs/
|
|
437
|
-
import {
|
|
447
|
+
// src/devtools/components/Tabs/ActionsTab.tsx
|
|
448
|
+
import { useState } from "react";
|
|
449
|
+
|
|
450
|
+
// src/devtools/actions-row-state.ts
|
|
451
|
+
function toggleExpandedIds(prev, id) {
|
|
452
|
+
const next = new Set(prev);
|
|
453
|
+
if (next.has(id)) {
|
|
454
|
+
next.delete(id);
|
|
455
|
+
} else {
|
|
456
|
+
next.add(id);
|
|
457
|
+
}
|
|
458
|
+
return next;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// src/devtools/pii-mask.ts
|
|
462
|
+
var SENSITIVE_KEY_PATTERN = /(password|token|secret|api_?key|apikey|credit_?card|ssn|cpf|cnpj)/i;
|
|
463
|
+
function isSensitiveKey(key) {
|
|
464
|
+
return SENSITIVE_KEY_PATTERN.test(key);
|
|
465
|
+
}
|
|
466
|
+
function maskPiiFields(value) {
|
|
467
|
+
if (value === null || value === void 0) return value;
|
|
468
|
+
if (typeof value !== "object") return value;
|
|
469
|
+
if (Array.isArray(value)) {
|
|
470
|
+
return value.map((item) => maskPiiFields(item));
|
|
471
|
+
}
|
|
472
|
+
const out = {};
|
|
473
|
+
for (const [key, val] of Object.entries(value)) {
|
|
474
|
+
if (isSensitiveKey(key)) {
|
|
475
|
+
out[key] = "***";
|
|
476
|
+
} else {
|
|
477
|
+
out[key] = maskPiiFields(val);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return out;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// src/devtools/components/Tabs/ActionsTab.tsx
|
|
438
484
|
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
485
|
+
function formatTime(ts) {
|
|
486
|
+
const d = new Date(ts);
|
|
487
|
+
return d.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
488
|
+
}
|
|
489
|
+
function formatPayload(value, reveal) {
|
|
490
|
+
const display = reveal ? value : maskPiiFields(value);
|
|
491
|
+
try {
|
|
492
|
+
return JSON.stringify(display, null, 2);
|
|
493
|
+
} catch {
|
|
494
|
+
return "<unserializable>";
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
function buildActionsStyles(styles) {
|
|
498
|
+
return {
|
|
499
|
+
header: styles.css`
|
|
500
|
+
display: flex;
|
|
501
|
+
align-items: center;
|
|
502
|
+
justify-content: space-between;
|
|
503
|
+
padding: ${tokens.spacing.xs} ${tokens.spacing.sm};
|
|
504
|
+
color: ${tokens.colors.textMuted};
|
|
505
|
+
font-size: ${tokens.font.sizeXs};
|
|
506
|
+
border-bottom: 1px solid ${tokens.colors.borderSubtle};
|
|
507
|
+
`,
|
|
508
|
+
clearBtn: styles.css`
|
|
509
|
+
appearance: none;
|
|
510
|
+
background: transparent;
|
|
511
|
+
color: ${tokens.colors.textMuted};
|
|
512
|
+
border: 1px solid ${tokens.colors.borderSubtle};
|
|
513
|
+
padding: 2px 6px;
|
|
514
|
+
border-radius: ${tokens.radius.sm};
|
|
515
|
+
cursor: pointer;
|
|
516
|
+
font-size: ${tokens.font.sizeXs};
|
|
517
|
+
&:hover { color: ${tokens.colors.text}; }
|
|
518
|
+
`,
|
|
519
|
+
rowContainer: styles.css`
|
|
520
|
+
border-bottom: 1px solid ${tokens.colors.borderSubtle};
|
|
521
|
+
font-size: ${tokens.font.sizeXs};
|
|
522
|
+
`,
|
|
523
|
+
rowSummary: styles.css`
|
|
524
|
+
display: grid;
|
|
525
|
+
grid-template-columns: 24px 80px 1fr 80px 80px;
|
|
526
|
+
gap: ${tokens.spacing.sm};
|
|
527
|
+
align-items: center;
|
|
528
|
+
width: 100%;
|
|
529
|
+
padding: ${tokens.spacing.xs} ${tokens.spacing.sm};
|
|
530
|
+
background: transparent;
|
|
531
|
+
border: none;
|
|
532
|
+
color: ${tokens.colors.text};
|
|
533
|
+
text-align: left;
|
|
534
|
+
cursor: pointer;
|
|
535
|
+
font-family: ${tokens.font.family};
|
|
536
|
+
font-size: ${tokens.font.sizeXs};
|
|
537
|
+
&:hover { background: ${tokens.colors.bgPanelHover}; }
|
|
538
|
+
&[aria-expanded='true'] { background: ${tokens.colors.bgPanelHover}; }
|
|
539
|
+
.chev { color: ${tokens.colors.textMuted}; font-family: ${tokens.font.mono}; }
|
|
540
|
+
.name { font-family: ${tokens.font.mono}; }
|
|
541
|
+
.time { color: ${tokens.colors.textMuted}; font-family: ${tokens.font.mono}; }
|
|
542
|
+
.status-success { color: ${tokens.colors.accent}; }
|
|
543
|
+
.status-error { color: #c92a2a; }
|
|
544
|
+
.duration { color: ${tokens.colors.textMuted}; text-align: right; }
|
|
545
|
+
`,
|
|
546
|
+
detail: styles.css`
|
|
547
|
+
padding: ${tokens.spacing.sm} ${tokens.spacing.md};
|
|
548
|
+
background: ${tokens.colors.bgPanelHover};
|
|
549
|
+
border-top: 1px dashed ${tokens.colors.borderSubtle};
|
|
550
|
+
font-size: ${tokens.font.sizeXs};
|
|
551
|
+
pre {
|
|
552
|
+
margin: 0;
|
|
553
|
+
padding: ${tokens.spacing.xs};
|
|
554
|
+
background: ${tokens.colors.borderSubtle};
|
|
555
|
+
border-radius: ${tokens.radius.sm};
|
|
556
|
+
overflow: auto;
|
|
557
|
+
max-height: 200px;
|
|
558
|
+
font-family: ${tokens.font.mono};
|
|
559
|
+
}
|
|
560
|
+
.reveal-btn {
|
|
561
|
+
appearance: none;
|
|
562
|
+
background: transparent;
|
|
563
|
+
color: ${tokens.colors.textMuted};
|
|
564
|
+
border: 1px solid ${tokens.colors.borderSubtle};
|
|
565
|
+
padding: 2px 8px;
|
|
566
|
+
margin-bottom: ${tokens.spacing.xs};
|
|
567
|
+
border-radius: ${tokens.radius.sm};
|
|
568
|
+
cursor: pointer;
|
|
569
|
+
font-size: ${tokens.font.sizeXs};
|
|
570
|
+
}
|
|
571
|
+
.reveal-btn:hover { color: ${tokens.colors.text}; }
|
|
572
|
+
.section { margin-top: ${tokens.spacing.sm}; }
|
|
573
|
+
.field-errors { margin-top: ${tokens.spacing.xs}; color: #c92a2a; }
|
|
574
|
+
.field-errors li { margin-left: ${tokens.spacing.md}; }
|
|
575
|
+
`
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
function ActionsEmptyState() {
|
|
579
|
+
return /* @__PURE__ */ jsxs("div", { style: { color: tokens.colors.textMuted, padding: tokens.spacing.md }, children: [
|
|
580
|
+
"No action calls yet. Trigger a server action (via ",
|
|
581
|
+
/* @__PURE__ */ jsx3("code", { children: "useAction" }),
|
|
582
|
+
" or direct",
|
|
583
|
+
" ",
|
|
584
|
+
/* @__PURE__ */ jsx3("code", { children: "POST /_actions/<name>" }),
|
|
585
|
+
") to see it here. Production builds tree-shake this telemetry path."
|
|
586
|
+
] });
|
|
587
|
+
}
|
|
588
|
+
function ActionsTab() {
|
|
589
|
+
const { state, dispatch, styles } = useDevtoolsContext();
|
|
590
|
+
const [revealedIds, setRevealedIds] = useState(() => /* @__PURE__ */ new Set());
|
|
591
|
+
const [expandedIds, setExpandedIds] = useState(() => /* @__PURE__ */ new Set());
|
|
592
|
+
if (state.actionCalls.length === 0) return /* @__PURE__ */ jsx3(ActionsEmptyState, {});
|
|
593
|
+
const cls = buildActionsStyles(styles);
|
|
594
|
+
const toggleReveal = (id) => {
|
|
595
|
+
setRevealedIds((prev) => toggleExpandedIds(prev, id));
|
|
596
|
+
};
|
|
597
|
+
const toggleExpand = (id) => {
|
|
598
|
+
setExpandedIds((prev) => toggleExpandedIds(prev, id));
|
|
599
|
+
};
|
|
600
|
+
return /* @__PURE__ */ jsxs("div", { "data-testid": "devtools-actions-tab", children: [
|
|
601
|
+
/* @__PURE__ */ jsx3(
|
|
602
|
+
ActionsHeader,
|
|
603
|
+
{
|
|
604
|
+
className: cls.header,
|
|
605
|
+
clearBtnClass: cls.clearBtn,
|
|
606
|
+
count: state.actionCalls.length,
|
|
607
|
+
onClear: () => {
|
|
608
|
+
dispatch({ type: "RESET_ACTION_CALLS" });
|
|
609
|
+
setRevealedIds(/* @__PURE__ */ new Set());
|
|
610
|
+
setExpandedIds(/* @__PURE__ */ new Set());
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
),
|
|
614
|
+
/* @__PURE__ */ jsx3("div", { children: state.actionCalls.map((r) => /* @__PURE__ */ jsx3(
|
|
615
|
+
ActionRow,
|
|
616
|
+
{
|
|
617
|
+
record: r,
|
|
618
|
+
containerClass: cls.rowContainer,
|
|
619
|
+
summaryClass: cls.rowSummary,
|
|
620
|
+
detailClass: cls.detail,
|
|
621
|
+
expanded: expandedIds.has(r.id),
|
|
622
|
+
revealed: revealedIds.has(r.id),
|
|
623
|
+
onToggleExpand: () => {
|
|
624
|
+
toggleExpand(r.id);
|
|
625
|
+
},
|
|
626
|
+
onToggleReveal: () => {
|
|
627
|
+
toggleReveal(r.id);
|
|
628
|
+
}
|
|
629
|
+
},
|
|
630
|
+
r.id
|
|
631
|
+
)) })
|
|
632
|
+
] });
|
|
633
|
+
}
|
|
634
|
+
function ActionsHeader({
|
|
635
|
+
className,
|
|
636
|
+
clearBtnClass,
|
|
637
|
+
count,
|
|
638
|
+
onClear
|
|
639
|
+
}) {
|
|
640
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
641
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
642
|
+
count,
|
|
643
|
+
" call",
|
|
644
|
+
count === 1 ? "" : "s"
|
|
645
|
+
] }),
|
|
646
|
+
/* @__PURE__ */ jsx3("button", { type: "button", className: clearBtnClass, onClick: onClear, children: "Clear" })
|
|
647
|
+
] });
|
|
648
|
+
}
|
|
649
|
+
function ActionRow({
|
|
650
|
+
record,
|
|
651
|
+
containerClass,
|
|
652
|
+
summaryClass,
|
|
653
|
+
detailClass,
|
|
654
|
+
expanded,
|
|
655
|
+
revealed,
|
|
656
|
+
onToggleExpand,
|
|
657
|
+
onToggleReveal
|
|
658
|
+
}) {
|
|
659
|
+
const statusClass = record.status === "success" ? "status-success" : "status-error";
|
|
660
|
+
return /* @__PURE__ */ jsxs("div", { className: containerClass, "data-testid": "devtools-action-row", children: [
|
|
661
|
+
/* @__PURE__ */ jsxs(
|
|
662
|
+
"button",
|
|
663
|
+
{
|
|
664
|
+
type: "button",
|
|
665
|
+
className: summaryClass,
|
|
666
|
+
onClick: onToggleExpand,
|
|
667
|
+
"aria-expanded": expanded,
|
|
668
|
+
title: `${record.name} \u2014 click to ${expanded ? "collapse" : "expand"} details`,
|
|
669
|
+
children: [
|
|
670
|
+
/* @__PURE__ */ jsx3("span", { className: "chev", children: expanded ? "\u25BC" : "\u25B6" }),
|
|
671
|
+
/* @__PURE__ */ jsx3("span", { className: "time", children: formatTime(record.timestamp) }),
|
|
672
|
+
/* @__PURE__ */ jsx3("span", { className: "name", children: record.name }),
|
|
673
|
+
/* @__PURE__ */ jsx3("span", { className: statusClass, children: record.status }),
|
|
674
|
+
/* @__PURE__ */ jsxs("span", { className: "duration", children: [
|
|
675
|
+
record.durationMs,
|
|
676
|
+
"ms"
|
|
677
|
+
] })
|
|
678
|
+
]
|
|
679
|
+
}
|
|
680
|
+
),
|
|
681
|
+
expanded && /* @__PURE__ */ jsxs("div", { className: detailClass, children: [
|
|
682
|
+
/* @__PURE__ */ jsx3("button", { type: "button", className: "reveal-btn", onClick: onToggleReveal, children: revealed ? "Hide values" : "Reveal values" }),
|
|
683
|
+
/* @__PURE__ */ jsxs("div", { className: "section", children: [
|
|
684
|
+
/* @__PURE__ */ jsx3("strong", { children: "Input" }),
|
|
685
|
+
/* @__PURE__ */ jsx3("pre", { children: formatPayload(record.input, revealed) })
|
|
686
|
+
] }),
|
|
687
|
+
record.status === "success" && record.output !== void 0 && /* @__PURE__ */ jsxs("div", { className: "section", children: [
|
|
688
|
+
/* @__PURE__ */ jsx3("strong", { children: "Output" }),
|
|
689
|
+
/* @__PURE__ */ jsx3("pre", { children: formatPayload(record.output, revealed) })
|
|
690
|
+
] }),
|
|
691
|
+
record.status === "error" && record.error && /* @__PURE__ */ jsx3(ActionDetailError, { error: record.error })
|
|
692
|
+
] })
|
|
693
|
+
] });
|
|
694
|
+
}
|
|
695
|
+
function ActionDetailError({ error }) {
|
|
696
|
+
return /* @__PURE__ */ jsxs("div", { className: "section", children: [
|
|
697
|
+
/* @__PURE__ */ jsxs("strong", { children: [
|
|
698
|
+
"Error: ",
|
|
699
|
+
error.code
|
|
700
|
+
] }),
|
|
701
|
+
/* @__PURE__ */ jsx3("p", { children: error.message }),
|
|
702
|
+
error.fields && Object.keys(error.fields).length > 0 && /* @__PURE__ */ jsx3("ul", { className: "field-errors", children: Object.entries(error.fields).map(([field, msgs]) => /* @__PURE__ */ jsxs("li", { children: [
|
|
703
|
+
/* @__PURE__ */ jsxs("strong", { children: [
|
|
704
|
+
field || "(root)",
|
|
705
|
+
":"
|
|
706
|
+
] }),
|
|
707
|
+
" ",
|
|
708
|
+
msgs.join("; ")
|
|
709
|
+
] }, field)) })
|
|
710
|
+
] });
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// src/devtools/components/Tabs/AgentsTab.tsx
|
|
714
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
715
|
+
function formatTime2(ts) {
|
|
716
|
+
const d = new Date(ts);
|
|
717
|
+
return d.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", second: "2-digit" });
|
|
718
|
+
}
|
|
719
|
+
function formatCost(usd) {
|
|
720
|
+
if (usd === 0) return "$0.0000";
|
|
721
|
+
if (usd < 1e-4) return `<$0.0001`;
|
|
722
|
+
return `$${usd.toFixed(4)}`;
|
|
723
|
+
}
|
|
724
|
+
function AgentsTab() {
|
|
725
|
+
const { state, dispatch, styles } = useDevtoolsContext();
|
|
726
|
+
if (state.agentRuns.length === 0) {
|
|
727
|
+
return /* @__PURE__ */ jsxs2("div", { style: { color: tokens.colors.textMuted, padding: tokens.spacing.md }, children: [
|
|
728
|
+
"No agent runs yet. Trigger a request to an endpoint using ",
|
|
729
|
+
/* @__PURE__ */ jsx4("code", { children: "trackAgentRun" }),
|
|
730
|
+
" to see it here. (Wired in the saas template; opt-in elsewhere.)"
|
|
731
|
+
] });
|
|
732
|
+
}
|
|
733
|
+
const totalCost = state.agentRuns.reduce((sum, r) => sum + r.costUsd, 0);
|
|
734
|
+
const totalIn = state.agentRuns.reduce((sum, r) => sum + r.tokensInput, 0);
|
|
735
|
+
const totalOut = state.agentRuns.reduce((sum, r) => sum + r.tokensOutput, 0);
|
|
736
|
+
const headerClass = styles.css`
|
|
737
|
+
display: flex;
|
|
738
|
+
align-items: center;
|
|
739
|
+
justify-content: space-between;
|
|
740
|
+
padding: ${tokens.spacing.xs} ${tokens.spacing.sm};
|
|
741
|
+
color: ${tokens.colors.textMuted};
|
|
742
|
+
font-size: ${tokens.font.sizeXs};
|
|
743
|
+
border-bottom: 1px solid ${tokens.colors.borderSubtle};
|
|
744
|
+
`;
|
|
745
|
+
const clearBtn = styles.css`
|
|
746
|
+
appearance: none;
|
|
747
|
+
background: transparent;
|
|
748
|
+
color: ${tokens.colors.textMuted};
|
|
749
|
+
border: 1px solid ${tokens.colors.borderSubtle};
|
|
750
|
+
padding: 2px 6px;
|
|
751
|
+
border-radius: ${tokens.radius.sm};
|
|
752
|
+
cursor: pointer;
|
|
753
|
+
font-size: ${tokens.font.sizeXs};
|
|
754
|
+
&:hover { color: ${tokens.colors.text}; }
|
|
755
|
+
`;
|
|
756
|
+
const tableClass = styles.css`
|
|
757
|
+
width: 100%;
|
|
758
|
+
border-collapse: collapse;
|
|
759
|
+
font-size: ${tokens.font.sizeXs};
|
|
760
|
+
th, td {
|
|
761
|
+
text-align: left;
|
|
762
|
+
padding: 4px 8px;
|
|
763
|
+
border-bottom: 1px solid ${tokens.colors.borderSubtle};
|
|
764
|
+
}
|
|
765
|
+
th {
|
|
766
|
+
color: ${tokens.colors.textMuted};
|
|
767
|
+
font-weight: 500;
|
|
768
|
+
font-size: ${tokens.font.sizeXs};
|
|
769
|
+
}
|
|
770
|
+
tr.status-error td { color: #c92a2a; }
|
|
771
|
+
tr.status-aborted td { color: ${tokens.colors.textMuted}; }
|
|
772
|
+
`;
|
|
773
|
+
return /* @__PURE__ */ jsxs2("div", { "data-testid": "devtools-agents-tab", children: [
|
|
774
|
+
/* @__PURE__ */ jsxs2("div", { className: headerClass, children: [
|
|
775
|
+
/* @__PURE__ */ jsxs2("span", { children: [
|
|
776
|
+
state.agentRuns.length,
|
|
777
|
+
" run",
|
|
778
|
+
state.agentRuns.length === 1 ? "" : "s",
|
|
779
|
+
" \xB7 ",
|
|
780
|
+
"tokens ",
|
|
781
|
+
totalIn,
|
|
782
|
+
"/",
|
|
783
|
+
totalOut,
|
|
784
|
+
" \xB7 ",
|
|
785
|
+
formatCost(totalCost),
|
|
786
|
+
" total"
|
|
787
|
+
] }),
|
|
788
|
+
/* @__PURE__ */ jsx4(
|
|
789
|
+
"button",
|
|
790
|
+
{
|
|
791
|
+
type: "button",
|
|
792
|
+
className: clearBtn,
|
|
793
|
+
onClick: () => {
|
|
794
|
+
dispatch({ type: "RESET_AGENT_RUNS" });
|
|
795
|
+
},
|
|
796
|
+
children: "clear"
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
] }),
|
|
800
|
+
/* @__PURE__ */ jsxs2("table", { className: tableClass, children: [
|
|
801
|
+
/* @__PURE__ */ jsx4("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
|
|
802
|
+
/* @__PURE__ */ jsx4("th", { children: "Time" }),
|
|
803
|
+
/* @__PURE__ */ jsx4("th", { children: "User" }),
|
|
804
|
+
/* @__PURE__ */ jsx4("th", { children: "Model" }),
|
|
805
|
+
/* @__PURE__ */ jsx4("th", { children: "Tokens (in/out)" }),
|
|
806
|
+
/* @__PURE__ */ jsx4("th", { children: "Cost" }),
|
|
807
|
+
/* @__PURE__ */ jsx4("th", { children: "Status" })
|
|
808
|
+
] }) }),
|
|
809
|
+
/* @__PURE__ */ jsx4("tbody", { children: state.agentRuns.map((run) => /* @__PURE__ */ jsxs2("tr", { className: `status-${run.status}`, children: [
|
|
810
|
+
/* @__PURE__ */ jsx4("td", { children: formatTime2(run.timestamp) }),
|
|
811
|
+
/* @__PURE__ */ jsx4("td", { children: run.userId }),
|
|
812
|
+
/* @__PURE__ */ jsx4("td", { children: run.model }),
|
|
813
|
+
/* @__PURE__ */ jsxs2("td", { children: [
|
|
814
|
+
run.tokensInput,
|
|
815
|
+
"/",
|
|
816
|
+
run.tokensOutput
|
|
817
|
+
] }),
|
|
818
|
+
/* @__PURE__ */ jsx4("td", { children: formatCost(run.costUsd) }),
|
|
819
|
+
/* @__PURE__ */ jsx4("td", { children: run.status })
|
|
820
|
+
] }, run.id)) })
|
|
821
|
+
] })
|
|
822
|
+
] });
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// src/devtools/components/Tabs/CsrfReadinessTab.tsx
|
|
826
|
+
import { useEffect as useEffect2, useState as useState2, useCallback as useCallback2 } from "react";
|
|
827
|
+
|
|
828
|
+
// src/devtools/csrf-readiness-classify.ts
|
|
829
|
+
var NETWORK_ERROR_PATTERN = /failed to fetch|networkerror|network request failed/i;
|
|
830
|
+
function classifyCsrfReadinessError(input) {
|
|
831
|
+
if (input.kind === "http") {
|
|
832
|
+
return classifyHttpStatus(input.status);
|
|
833
|
+
}
|
|
834
|
+
return classifyThrown(input.error);
|
|
835
|
+
}
|
|
836
|
+
function classifyHttpStatus(status) {
|
|
837
|
+
if (status === 404) {
|
|
838
|
+
return {
|
|
839
|
+
kind: "store-not-wired",
|
|
840
|
+
summary: `Endpoint returned 404 \u2014 /__theo/csrf-readiness not registered.`,
|
|
841
|
+
hint: "Wire `csrfReadinessStore` in the api-middleware options to enable this tab."
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
if (status === 401 || status === 403) {
|
|
845
|
+
return {
|
|
846
|
+
kind: "unauthorized",
|
|
847
|
+
summary: `Endpoint returned ${String(status)} \u2014 the readiness route is auth-gated.`,
|
|
848
|
+
hint: "Authenticate (e.g. via session) before opening this tab, or move the route outside of requireAuth."
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
if (status >= 500 && status < 600) {
|
|
852
|
+
return {
|
|
853
|
+
kind: "server-crash",
|
|
854
|
+
summary: `Endpoint returned ${String(status)} \u2014 the readiness handler threw.`,
|
|
855
|
+
hint: "Check dev server logs (terminal running `theokit dev`) for the underlying stack trace."
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
kind: "unexpected-status",
|
|
860
|
+
summary: `Endpoint returned unexpected status ${String(status)}.`,
|
|
861
|
+
hint: "This is not a status the readiness route normally emits. Inspect the response body in Network tab."
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
function classifyThrown(error) {
|
|
865
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
866
|
+
return {
|
|
867
|
+
kind: "aborted",
|
|
868
|
+
summary: "Request aborted.",
|
|
869
|
+
hint: ""
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
873
|
+
if (error instanceof TypeError && NETWORK_ERROR_PATTERN.test(message)) {
|
|
874
|
+
return {
|
|
875
|
+
kind: "server-unreachable",
|
|
876
|
+
summary: "Dev server unreachable \u2014 request failed before any HTTP response.",
|
|
877
|
+
hint: "Restart the dev server (`theokit dev`) and verify the port matches the browser URL."
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
return {
|
|
881
|
+
kind: "unknown-error",
|
|
882
|
+
summary: message.length > 0 ? message : "Unknown error",
|
|
883
|
+
hint: "Open the browser DevTools Network panel to inspect the failed request."
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// src/devtools/components/Tabs/CsrfReadinessTab.tsx
|
|
888
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
439
889
|
function buildTabStyles(styles) {
|
|
440
890
|
return {
|
|
441
891
|
container: styles.css`
|
|
@@ -477,13 +927,13 @@ function ReadinessRow({
|
|
|
477
927
|
rowClass,
|
|
478
928
|
route
|
|
479
929
|
}) {
|
|
480
|
-
return /* @__PURE__ */
|
|
481
|
-
/* @__PURE__ */
|
|
482
|
-
/* @__PURE__ */
|
|
930
|
+
return /* @__PURE__ */ jsxs3("div", { className: rowClass, children: [
|
|
931
|
+
/* @__PURE__ */ jsx5("span", { style: { color: tokens.colors.accent }, children: route.method }),
|
|
932
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
483
933
|
route.path,
|
|
484
|
-
/* @__PURE__ */
|
|
934
|
+
/* @__PURE__ */ jsx5("span", { style: { color: tokens.colors.textMuted, marginLeft: tokens.spacing.sm }, children: route.reason })
|
|
485
935
|
] }),
|
|
486
|
-
/* @__PURE__ */
|
|
936
|
+
/* @__PURE__ */ jsxs3("span", { style: { color: tokens.colors.textMuted }, children: [
|
|
487
937
|
"\xD7",
|
|
488
938
|
String(route.count)
|
|
489
939
|
] })
|
|
@@ -492,21 +942,23 @@ function ReadinessRow({
|
|
|
492
942
|
function CsrfReadinessTab() {
|
|
493
943
|
const { styles } = useDevtoolsContext();
|
|
494
944
|
const cls = buildTabStyles(styles);
|
|
495
|
-
const [data, setData] =
|
|
496
|
-
const [error, setError] =
|
|
497
|
-
const [busy, setBusy] =
|
|
945
|
+
const [data, setData] = useState2(null);
|
|
946
|
+
const [error, setError] = useState2(null);
|
|
947
|
+
const [busy, setBusy] = useState2(false);
|
|
498
948
|
const fetchData = useCallback2(async () => {
|
|
499
949
|
try {
|
|
500
950
|
const res = await fetch("/__theo/csrf-readiness");
|
|
501
951
|
if (!res.ok) {
|
|
502
|
-
setError(
|
|
952
|
+
setError(classifyCsrfReadinessError({ kind: "http", status: res.status }));
|
|
503
953
|
return;
|
|
504
954
|
}
|
|
505
955
|
const json = await res.json();
|
|
506
956
|
setData(json);
|
|
507
957
|
setError(null);
|
|
508
958
|
} catch (e) {
|
|
509
|
-
|
|
959
|
+
const classified = classifyCsrfReadinessError({ kind: "thrown", error: e });
|
|
960
|
+
if (classified.kind === "aborted") return;
|
|
961
|
+
setError(classified);
|
|
510
962
|
}
|
|
511
963
|
}, []);
|
|
512
964
|
useEffect2(() => {
|
|
@@ -529,24 +981,28 @@ function CsrfReadinessTab() {
|
|
|
529
981
|
}
|
|
530
982
|
}, [fetchData]);
|
|
531
983
|
if (error) {
|
|
532
|
-
return /* @__PURE__ */
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
"
|
|
538
|
-
|
|
539
|
-
|
|
984
|
+
return /* @__PURE__ */ jsxs3(
|
|
985
|
+
"div",
|
|
986
|
+
{
|
|
987
|
+
className: cls.container,
|
|
988
|
+
"data-testid": "devtools-csrf-readiness-error",
|
|
989
|
+
"data-error-kind": error.kind,
|
|
990
|
+
children: [
|
|
991
|
+
/* @__PURE__ */ jsx5("div", { style: { color: tokens.colors.error.csrf }, children: error.summary }),
|
|
992
|
+
error.hint.length > 0 && /* @__PURE__ */ jsx5("p", { style: { color: tokens.colors.textMuted, marginTop: tokens.spacing.sm }, children: error.hint })
|
|
993
|
+
]
|
|
994
|
+
}
|
|
995
|
+
);
|
|
540
996
|
}
|
|
541
997
|
if (data === null) {
|
|
542
|
-
return /* @__PURE__ */
|
|
998
|
+
return /* @__PURE__ */ jsx5("div", { className: cls.container, "data-testid": "devtools-csrf-readiness-loading", children: "Loading\u2026" });
|
|
543
999
|
}
|
|
544
1000
|
const isEmpty = data.totalEvents === 0;
|
|
545
1001
|
const testid = isEmpty ? "devtools-csrf-readiness-empty" : "devtools-csrf-readiness";
|
|
546
|
-
return /* @__PURE__ */
|
|
547
|
-
/* @__PURE__ */
|
|
548
|
-
/* @__PURE__ */
|
|
549
|
-
/* @__PURE__ */
|
|
1002
|
+
return /* @__PURE__ */ jsxs3("div", { className: cls.container, "data-testid": testid, children: [
|
|
1003
|
+
/* @__PURE__ */ jsxs3("div", { className: cls.headerRow, children: [
|
|
1004
|
+
/* @__PURE__ */ jsx5("strong", { children: isEmpty ? "CSRF Readiness" : `CSRF Readiness \u2014 ${String(data.totalEvents)} event(s) across ${String(data.routes.length)} route(s)` }),
|
|
1005
|
+
/* @__PURE__ */ jsx5(
|
|
550
1006
|
"button",
|
|
551
1007
|
{
|
|
552
1008
|
type: "button",
|
|
@@ -559,13 +1015,13 @@ function CsrfReadinessTab() {
|
|
|
559
1015
|
}
|
|
560
1016
|
)
|
|
561
1017
|
] }),
|
|
562
|
-
isEmpty ? /* @__PURE__ */
|
|
1018
|
+
isEmpty ? /* @__PURE__ */ jsx5("div", { style: { color: tokens.colors.textMuted }, children: "No csrf.warn events recorded. Endpoints are ready for 0.3.0 strict CSRF." }) : data.routes.map((r) => /* @__PURE__ */ jsx5(ReadinessRow, { rowClass: cls.row, route: r }, `${r.method} ${r.path} ${r.reason}`))
|
|
563
1019
|
] });
|
|
564
1020
|
}
|
|
565
1021
|
|
|
566
1022
|
// src/devtools/components/ErrorRow.tsx
|
|
567
|
-
import { useState as
|
|
568
|
-
import { jsx as
|
|
1023
|
+
import { useState as useState3 } from "react";
|
|
1024
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
569
1025
|
var STACK_DISPLAY_LIMIT = 4096;
|
|
570
1026
|
function truncateStackForDisplay(stack, limit = STACK_DISPLAY_LIMIT) {
|
|
571
1027
|
if (!stack) return null;
|
|
@@ -596,7 +1052,7 @@ function typeIcon(type) {
|
|
|
596
1052
|
}
|
|
597
1053
|
}
|
|
598
1054
|
function ErrorRow({ error }) {
|
|
599
|
-
const [expanded, setExpanded] =
|
|
1055
|
+
const [expanded, setExpanded] = useState3(false);
|
|
600
1056
|
const { styles } = useDevtoolsContext();
|
|
601
1057
|
const containerClass = styles.css`
|
|
602
1058
|
display: block;
|
|
@@ -643,8 +1099,8 @@ function ErrorRow({ error }) {
|
|
|
643
1099
|
`;
|
|
644
1100
|
const displayedStack = truncateStackForDisplay(error.stack);
|
|
645
1101
|
const showDocsLink = typeof error.docsUrl === "string" && error.docsUrl.length > 0;
|
|
646
|
-
return /* @__PURE__ */
|
|
647
|
-
/* @__PURE__ */
|
|
1102
|
+
return /* @__PURE__ */ jsxs4("div", { className: containerClass, "data-testid": "devtools-error-row", children: [
|
|
1103
|
+
/* @__PURE__ */ jsxs4(
|
|
648
1104
|
"button",
|
|
649
1105
|
{
|
|
650
1106
|
type: "button",
|
|
@@ -655,9 +1111,9 @@ function ErrorRow({ error }) {
|
|
|
655
1111
|
"aria-expanded": expanded,
|
|
656
1112
|
title: error.message,
|
|
657
1113
|
children: [
|
|
658
|
-
/* @__PURE__ */
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
error.code && /* @__PURE__ */
|
|
1114
|
+
/* @__PURE__ */ jsx6("span", { className: iconClass, "aria-hidden": "true", children: typeIcon(error.type) }),
|
|
1115
|
+
/* @__PURE__ */ jsx6("span", { className: msgClass, children: error.message }),
|
|
1116
|
+
error.code && /* @__PURE__ */ jsx6(
|
|
661
1117
|
"span",
|
|
662
1118
|
{
|
|
663
1119
|
style: {
|
|
@@ -671,8 +1127,8 @@ function ErrorRow({ error }) {
|
|
|
671
1127
|
]
|
|
672
1128
|
}
|
|
673
1129
|
),
|
|
674
|
-
expanded && /* @__PURE__ */
|
|
675
|
-
showDocsLink && /* @__PURE__ */
|
|
1130
|
+
expanded && /* @__PURE__ */ jsxs4("div", { className: detailsClass, children: [
|
|
1131
|
+
showDocsLink && /* @__PURE__ */ jsx6("div", { style: { marginBottom: tokens.spacing.sm }, children: /* @__PURE__ */ jsx6(
|
|
676
1132
|
"a",
|
|
677
1133
|
{
|
|
678
1134
|
href: error.docsUrl,
|
|
@@ -682,7 +1138,7 @@ function ErrorRow({ error }) {
|
|
|
682
1138
|
children: "Open migration guide"
|
|
683
1139
|
}
|
|
684
1140
|
) }),
|
|
685
|
-
displayedStack && /* @__PURE__ */
|
|
1141
|
+
displayedStack && /* @__PURE__ */ jsx6(
|
|
686
1142
|
"pre",
|
|
687
1143
|
{
|
|
688
1144
|
style: {
|
|
@@ -706,11 +1162,11 @@ function ErrorRow({ error }) {
|
|
|
706
1162
|
}
|
|
707
1163
|
|
|
708
1164
|
// src/devtools/components/Tabs/ErrorsTab.tsx
|
|
709
|
-
import { jsx as
|
|
1165
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
710
1166
|
function ErrorsTab() {
|
|
711
1167
|
const { state, dispatch, styles } = useDevtoolsContext();
|
|
712
1168
|
if (state.errors.length === 0) {
|
|
713
|
-
return /* @__PURE__ */
|
|
1169
|
+
return /* @__PURE__ */ jsx7("div", { style: { color: tokens.colors.textMuted, padding: tokens.spacing.md }, children: "No errors yet. csrf.warn, console.error and unhandled rejections will surface here." });
|
|
714
1170
|
}
|
|
715
1171
|
const headerClass = styles.css`
|
|
716
1172
|
display: flex;
|
|
@@ -732,14 +1188,14 @@ function ErrorsTab() {
|
|
|
732
1188
|
font-size: ${tokens.font.sizeXs};
|
|
733
1189
|
&:hover { color: ${tokens.colors.text}; }
|
|
734
1190
|
`;
|
|
735
|
-
return /* @__PURE__ */
|
|
736
|
-
/* @__PURE__ */
|
|
737
|
-
/* @__PURE__ */
|
|
1191
|
+
return /* @__PURE__ */ jsxs5("div", { "data-testid": "devtools-errors-tab", children: [
|
|
1192
|
+
/* @__PURE__ */ jsxs5("div", { className: headerClass, children: [
|
|
1193
|
+
/* @__PURE__ */ jsxs5("span", { children: [
|
|
738
1194
|
state.errors.length,
|
|
739
1195
|
" error",
|
|
740
1196
|
state.errors.length === 1 ? "" : "s"
|
|
741
1197
|
] }),
|
|
742
|
-
/* @__PURE__ */
|
|
1198
|
+
/* @__PURE__ */ jsx7(
|
|
743
1199
|
"button",
|
|
744
1200
|
{
|
|
745
1201
|
type: "button",
|
|
@@ -751,16 +1207,16 @@ function ErrorsTab() {
|
|
|
751
1207
|
}
|
|
752
1208
|
)
|
|
753
1209
|
] }),
|
|
754
|
-
state.errors.map((err) => /* @__PURE__ */
|
|
1210
|
+
state.errors.map((err) => /* @__PURE__ */ jsx7(ErrorRow, { error: err }, err.id))
|
|
755
1211
|
] });
|
|
756
1212
|
}
|
|
757
1213
|
|
|
758
1214
|
// src/devtools/components/RequestRow.tsx
|
|
759
|
-
import { useState as
|
|
1215
|
+
import { useState as useState5 } from "react";
|
|
760
1216
|
|
|
761
1217
|
// src/devtools/components/JSONExplorer.tsx
|
|
762
|
-
import { useState as
|
|
763
|
-
import { jsx as
|
|
1218
|
+
import { useState as useState4 } from "react";
|
|
1219
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
764
1220
|
var PAGE_SIZE = 100;
|
|
765
1221
|
var MAX_STRING_DISPLAY = 256;
|
|
766
1222
|
function describe(value) {
|
|
@@ -782,8 +1238,8 @@ function JSONExplorer({
|
|
|
782
1238
|
defaultExpanded = false,
|
|
783
1239
|
depth = 0
|
|
784
1240
|
}) {
|
|
785
|
-
const [expanded, setExpanded] =
|
|
786
|
-
const [pageIndex, setPageIndex] =
|
|
1241
|
+
const [expanded, setExpanded] = useState4(defaultExpanded);
|
|
1242
|
+
const [pageIndex, setPageIndex] = useState4(0);
|
|
787
1243
|
const { styles } = useDevtoolsContext();
|
|
788
1244
|
const rowClass = styles.css`
|
|
789
1245
|
font-family: ${tokens.font.mono};
|
|
@@ -808,26 +1264,26 @@ function JSONExplorer({
|
|
|
808
1264
|
const keyClass = styles.css`color: ${tokens.colors.accent};`;
|
|
809
1265
|
const valClass = styles.css`color: ${tokens.colors.textMuted};`;
|
|
810
1266
|
if (value === null || value === void 0 || typeof value !== "object") {
|
|
811
|
-
return /* @__PURE__ */
|
|
812
|
-
/* @__PURE__ */
|
|
1267
|
+
return /* @__PURE__ */ jsxs6("div", { className: rowClass, children: [
|
|
1268
|
+
/* @__PURE__ */ jsx8("span", { className: keyClass, children: label }),
|
|
813
1269
|
":",
|
|
814
1270
|
" ",
|
|
815
|
-
/* @__PURE__ */
|
|
1271
|
+
/* @__PURE__ */ jsx8("span", { className: valClass, children: describe(value) })
|
|
816
1272
|
] });
|
|
817
1273
|
}
|
|
818
1274
|
const entries = Array.isArray(value) ? value.map((v, i) => [String(i), v]) : Object.entries(value);
|
|
819
1275
|
if (entries.length === 0) {
|
|
820
|
-
return /* @__PURE__ */
|
|
821
|
-
/* @__PURE__ */
|
|
1276
|
+
return /* @__PURE__ */ jsxs6("div", { className: rowClass, children: [
|
|
1277
|
+
/* @__PURE__ */ jsx8("span", { className: keyClass, children: label }),
|
|
822
1278
|
":",
|
|
823
1279
|
" ",
|
|
824
|
-
/* @__PURE__ */
|
|
1280
|
+
/* @__PURE__ */ jsx8("span", { className: valClass, children: Array.isArray(value) ? "[]" : "{}" })
|
|
825
1281
|
] });
|
|
826
1282
|
}
|
|
827
1283
|
const totalPages = Math.ceil(entries.length / PAGE_SIZE);
|
|
828
1284
|
const slice = entries.slice(pageIndex * PAGE_SIZE, (pageIndex + 1) * PAGE_SIZE);
|
|
829
|
-
return /* @__PURE__ */
|
|
830
|
-
/* @__PURE__ */
|
|
1285
|
+
return /* @__PURE__ */ jsxs6("div", { className: rowClass, children: [
|
|
1286
|
+
/* @__PURE__ */ jsxs6(
|
|
831
1287
|
"button",
|
|
832
1288
|
{
|
|
833
1289
|
type: "button",
|
|
@@ -837,15 +1293,15 @@ function JSONExplorer({
|
|
|
837
1293
|
},
|
|
838
1294
|
"aria-expanded": expanded,
|
|
839
1295
|
children: [
|
|
840
|
-
/* @__PURE__ */
|
|
841
|
-
/* @__PURE__ */
|
|
842
|
-
/* @__PURE__ */
|
|
1296
|
+
/* @__PURE__ */ jsx8("span", { children: expanded ? "\u25BE" : "\u25B8" }),
|
|
1297
|
+
/* @__PURE__ */ jsx8("span", { className: keyClass, children: label }),
|
|
1298
|
+
/* @__PURE__ */ jsx8("span", { className: valClass, children: describe(value) })
|
|
843
1299
|
]
|
|
844
1300
|
}
|
|
845
1301
|
),
|
|
846
|
-
expanded && /* @__PURE__ */
|
|
847
|
-
slice.map(([k, v]) => /* @__PURE__ */
|
|
848
|
-
totalPages > 1 && /* @__PURE__ */
|
|
1302
|
+
expanded && /* @__PURE__ */ jsxs6("div", { children: [
|
|
1303
|
+
slice.map(([k, v]) => /* @__PURE__ */ jsx8(JSONExplorer, { label: k, value: v, depth: depth + 1 }, k)),
|
|
1304
|
+
totalPages > 1 && /* @__PURE__ */ jsxs6(
|
|
849
1305
|
"div",
|
|
850
1306
|
{
|
|
851
1307
|
className: styles.css`padding-left: ${(depth + 1) * 12}px; color: ${tokens.colors.textMuted}; font-size: ${tokens.font.sizeXs};`,
|
|
@@ -854,7 +1310,7 @@ function JSONExplorer({
|
|
|
854
1310
|
pageIndex + 1,
|
|
855
1311
|
"/",
|
|
856
1312
|
totalPages,
|
|
857
|
-
pageIndex > 0 && /* @__PURE__ */
|
|
1313
|
+
pageIndex > 0 && /* @__PURE__ */ jsx8(
|
|
858
1314
|
"button",
|
|
859
1315
|
{
|
|
860
1316
|
type: "button",
|
|
@@ -865,7 +1321,7 @@ function JSONExplorer({
|
|
|
865
1321
|
children: "prev"
|
|
866
1322
|
}
|
|
867
1323
|
),
|
|
868
|
-
pageIndex < totalPages - 1 && /* @__PURE__ */
|
|
1324
|
+
pageIndex < totalPages - 1 && /* @__PURE__ */ jsx8(
|
|
869
1325
|
"button",
|
|
870
1326
|
{
|
|
871
1327
|
type: "button",
|
|
@@ -884,7 +1340,7 @@ function JSONExplorer({
|
|
|
884
1340
|
}
|
|
885
1341
|
|
|
886
1342
|
// src/devtools/components/RequestRow.tsx
|
|
887
|
-
import { jsx as
|
|
1343
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
888
1344
|
function buildRequestRowStyles(styles, request) {
|
|
889
1345
|
return {
|
|
890
1346
|
container: styles.css`
|
|
@@ -960,7 +1416,7 @@ function formatDuration(ms) {
|
|
|
960
1416
|
return `${Math.round(ms)}ms`;
|
|
961
1417
|
}
|
|
962
1418
|
function RequestRow({ request }) {
|
|
963
|
-
const [expanded, setExpanded] =
|
|
1419
|
+
const [expanded, setExpanded] = useState5(false);
|
|
964
1420
|
const { styles } = useDevtoolsContext();
|
|
965
1421
|
const cls = buildRequestRowStyles(styles, request);
|
|
966
1422
|
const containerClass = cls.container;
|
|
@@ -973,8 +1429,8 @@ function RequestRow({ request }) {
|
|
|
973
1429
|
const detailsClass = cls.details;
|
|
974
1430
|
const displayDuration = formatDuration(request.durationMs);
|
|
975
1431
|
const displayStatus = request.status === 0 ? "failed" : String(request.status);
|
|
976
|
-
return /* @__PURE__ */
|
|
977
|
-
/* @__PURE__ */
|
|
1432
|
+
return /* @__PURE__ */ jsxs7("div", { className: containerClass, "data-testid": "devtools-request-row", children: [
|
|
1433
|
+
/* @__PURE__ */ jsxs7(
|
|
978
1434
|
"button",
|
|
979
1435
|
{
|
|
980
1436
|
type: "button",
|
|
@@ -985,19 +1441,19 @@ function RequestRow({ request }) {
|
|
|
985
1441
|
"aria-expanded": expanded,
|
|
986
1442
|
title: request.path,
|
|
987
1443
|
children: [
|
|
988
|
-
/* @__PURE__ */
|
|
989
|
-
/* @__PURE__ */
|
|
990
|
-
/* @__PURE__ */
|
|
991
|
-
/* @__PURE__ */
|
|
992
|
-
/* @__PURE__ */
|
|
1444
|
+
/* @__PURE__ */ jsx9("span", { className: methodBadge, children: request.method }),
|
|
1445
|
+
/* @__PURE__ */ jsx9("span", { className: pathClass, children: request.path }),
|
|
1446
|
+
/* @__PURE__ */ jsx9("span", { className: statusClass, children: displayStatus }),
|
|
1447
|
+
/* @__PURE__ */ jsx9("span", { className: durClass, children: displayDuration }),
|
|
1448
|
+
/* @__PURE__ */ jsx9("span", { className: traceClass, children: request.traceId.slice(0, 8) })
|
|
993
1449
|
]
|
|
994
1450
|
}
|
|
995
1451
|
),
|
|
996
|
-
expanded && /* @__PURE__ */
|
|
997
|
-
request.csrfWarn && /* @__PURE__ */
|
|
1452
|
+
expanded && /* @__PURE__ */ jsxs7("div", { className: detailsClass, children: [
|
|
1453
|
+
request.csrfWarn && /* @__PURE__ */ jsxs7("div", { style: { color: tokens.colors.error.csrf, marginBottom: tokens.spacing.sm }, children: [
|
|
998
1454
|
"CSRF warn:",
|
|
999
1455
|
" ",
|
|
1000
|
-
/* @__PURE__ */
|
|
1456
|
+
/* @__PURE__ */ jsx9(
|
|
1001
1457
|
"a",
|
|
1002
1458
|
{
|
|
1003
1459
|
href: request.csrfWarn.docsUrl,
|
|
@@ -1008,8 +1464,8 @@ function RequestRow({ request }) {
|
|
|
1008
1464
|
}
|
|
1009
1465
|
)
|
|
1010
1466
|
] }),
|
|
1011
|
-
request.headers && /* @__PURE__ */
|
|
1012
|
-
request.bodyPreview !== void 0 && request.bodyPreview !== "" && /* @__PURE__ */
|
|
1467
|
+
request.headers && /* @__PURE__ */ jsx9(JSONExplorer, { label: "headers", value: request.headers, defaultExpanded: false }),
|
|
1468
|
+
request.bodyPreview !== void 0 && request.bodyPreview !== "" && /* @__PURE__ */ jsxs7(
|
|
1013
1469
|
"div",
|
|
1014
1470
|
{
|
|
1015
1471
|
style: {
|
|
@@ -1022,7 +1478,7 @@ function RequestRow({ request }) {
|
|
|
1022
1478
|
"body",
|
|
1023
1479
|
request.bodyTruncated ? ` (truncated, ${request.bodyLength} bytes)` : "",
|
|
1024
1480
|
":",
|
|
1025
|
-
/* @__PURE__ */
|
|
1481
|
+
/* @__PURE__ */ jsx9("pre", { style: { marginTop: 4, whiteSpace: "pre-wrap", wordBreak: "break-all" }, children: request.bodyPreview })
|
|
1026
1482
|
]
|
|
1027
1483
|
}
|
|
1028
1484
|
)
|
|
@@ -1031,11 +1487,11 @@ function RequestRow({ request }) {
|
|
|
1031
1487
|
}
|
|
1032
1488
|
|
|
1033
1489
|
// src/devtools/components/Tabs/RequestsTab.tsx
|
|
1034
|
-
import { jsx as
|
|
1490
|
+
import { jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1035
1491
|
function RequestsTab() {
|
|
1036
1492
|
const { state, dispatch, styles } = useDevtoolsContext();
|
|
1037
1493
|
if (state.requests.length === 0) {
|
|
1038
|
-
return /* @__PURE__ */
|
|
1494
|
+
return /* @__PURE__ */ jsx10("div", { style: { color: tokens.colors.textMuted, padding: tokens.spacing.md }, children: "No requests yet. Make a fetch call in your app to see it here." });
|
|
1039
1495
|
}
|
|
1040
1496
|
const headerClass = styles.css`
|
|
1041
1497
|
display: flex;
|
|
@@ -1057,14 +1513,14 @@ function RequestsTab() {
|
|
|
1057
1513
|
font-size: ${tokens.font.sizeXs};
|
|
1058
1514
|
&:hover { color: ${tokens.colors.text}; }
|
|
1059
1515
|
`;
|
|
1060
|
-
return /* @__PURE__ */
|
|
1061
|
-
/* @__PURE__ */
|
|
1062
|
-
/* @__PURE__ */
|
|
1516
|
+
return /* @__PURE__ */ jsxs8("div", { "data-testid": "devtools-requests-tab", children: [
|
|
1517
|
+
/* @__PURE__ */ jsxs8("div", { className: headerClass, children: [
|
|
1518
|
+
/* @__PURE__ */ jsxs8("span", { children: [
|
|
1063
1519
|
state.requests.length,
|
|
1064
1520
|
" request",
|
|
1065
1521
|
state.requests.length === 1 ? "" : "s"
|
|
1066
1522
|
] }),
|
|
1067
|
-
/* @__PURE__ */
|
|
1523
|
+
/* @__PURE__ */ jsx10(
|
|
1068
1524
|
"button",
|
|
1069
1525
|
{
|
|
1070
1526
|
type: "button",
|
|
@@ -1076,16 +1532,16 @@ function RequestsTab() {
|
|
|
1076
1532
|
}
|
|
1077
1533
|
)
|
|
1078
1534
|
] }),
|
|
1079
|
-
state.requests.map((req) => /* @__PURE__ */
|
|
1535
|
+
state.requests.map((req) => /* @__PURE__ */ jsx10(RequestRow, { request: req }, req.id))
|
|
1080
1536
|
] });
|
|
1081
1537
|
}
|
|
1082
1538
|
|
|
1083
1539
|
// src/devtools/components/Tabs/RoutesTab.tsx
|
|
1084
|
-
import { jsx as
|
|
1540
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1085
1541
|
function RoutesTab() {
|
|
1086
1542
|
const { state, styles } = useDevtoolsContext();
|
|
1087
1543
|
if (!state.routeManifest || state.routeManifest.routes.length === 0) {
|
|
1088
|
-
return /* @__PURE__ */
|
|
1544
|
+
return /* @__PURE__ */ jsx11("div", { style: { color: tokens.colors.textMuted, padding: tokens.spacing.md }, children: "Routes will appear when the manifest loads." });
|
|
1089
1545
|
}
|
|
1090
1546
|
const rowClass = styles.css`
|
|
1091
1547
|
display: flex;
|
|
@@ -1114,9 +1570,9 @@ function RoutesTab() {
|
|
|
1114
1570
|
console.warn("[theo devtools] Editor not configured");
|
|
1115
1571
|
});
|
|
1116
1572
|
}
|
|
1117
|
-
return /* @__PURE__ */
|
|
1573
|
+
return /* @__PURE__ */ jsx11("div", { "data-testid": "devtools-routes-tab", children: state.routeManifest.routes.map((route) => {
|
|
1118
1574
|
const active = state.activeRoutePath === route.path || state.activeChain.includes(route.absoluteFilePath);
|
|
1119
|
-
return /* @__PURE__ */
|
|
1575
|
+
return /* @__PURE__ */ jsxs9(
|
|
1120
1576
|
"button",
|
|
1121
1577
|
{
|
|
1122
1578
|
type: "button",
|
|
@@ -1127,7 +1583,7 @@ function RoutesTab() {
|
|
|
1127
1583
|
},
|
|
1128
1584
|
title: `Open ${route.absoluteFilePath} in editor`,
|
|
1129
1585
|
children: [
|
|
1130
|
-
/* @__PURE__ */
|
|
1586
|
+
/* @__PURE__ */ jsx11(
|
|
1131
1587
|
"span",
|
|
1132
1588
|
{
|
|
1133
1589
|
style: {
|
|
@@ -1137,8 +1593,8 @@ function RoutesTab() {
|
|
|
1137
1593
|
children: active ? "\u25B8" : " "
|
|
1138
1594
|
}
|
|
1139
1595
|
),
|
|
1140
|
-
/* @__PURE__ */
|
|
1141
|
-
/* @__PURE__ */
|
|
1596
|
+
/* @__PURE__ */ jsx11("span", { style: { flex: 1 }, children: route.path }),
|
|
1597
|
+
/* @__PURE__ */ jsx11("span", { style: { color: tokens.colors.textDim, fontSize: tokens.font.sizeXs }, children: route.absoluteFilePath.split("/").slice(-2).join("/") })
|
|
1142
1598
|
]
|
|
1143
1599
|
},
|
|
1144
1600
|
route.absoluteFilePath
|
|
@@ -1147,7 +1603,7 @@ function RoutesTab() {
|
|
|
1147
1603
|
}
|
|
1148
1604
|
|
|
1149
1605
|
// src/devtools/components/Tabs/SettingsTab.tsx
|
|
1150
|
-
import { jsx as
|
|
1606
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1151
1607
|
var POSITIONS = ["top-left", "top-right", "bottom-left", "bottom-right"];
|
|
1152
1608
|
var THEMES = ["light", "dark", "system"];
|
|
1153
1609
|
function SettingsTab() {
|
|
@@ -1168,11 +1624,11 @@ function SettingsTab() {
|
|
|
1168
1624
|
color: ${tokens.colors.text};
|
|
1169
1625
|
font-size: ${tokens.font.sizeSm};
|
|
1170
1626
|
`;
|
|
1171
|
-
return /* @__PURE__ */
|
|
1172
|
-
/* @__PURE__ */
|
|
1173
|
-
/* @__PURE__ */
|
|
1174
|
-
POSITIONS.map((p) => /* @__PURE__ */
|
|
1175
|
-
/* @__PURE__ */
|
|
1627
|
+
return /* @__PURE__ */ jsxs10("div", { "data-testid": "devtools-settings-tab", style: { padding: tokens.spacing.md }, children: [
|
|
1628
|
+
/* @__PURE__ */ jsxs10("fieldset", { className: sectionClass, style: { border: 0, padding: 0, margin: 0 }, children: [
|
|
1629
|
+
/* @__PURE__ */ jsx12("legend", { className: headingClass, children: "Position" }),
|
|
1630
|
+
POSITIONS.map((p) => /* @__PURE__ */ jsxs10("label", { className: radioRowClass, children: [
|
|
1631
|
+
/* @__PURE__ */ jsx12(
|
|
1176
1632
|
"input",
|
|
1177
1633
|
{
|
|
1178
1634
|
type: "radio",
|
|
@@ -1184,13 +1640,13 @@ function SettingsTab() {
|
|
|
1184
1640
|
}
|
|
1185
1641
|
}
|
|
1186
1642
|
),
|
|
1187
|
-
/* @__PURE__ */
|
|
1643
|
+
/* @__PURE__ */ jsx12("span", { children: p })
|
|
1188
1644
|
] }, p))
|
|
1189
1645
|
] }),
|
|
1190
|
-
/* @__PURE__ */
|
|
1191
|
-
/* @__PURE__ */
|
|
1192
|
-
THEMES.map((t) => /* @__PURE__ */
|
|
1193
|
-
/* @__PURE__ */
|
|
1646
|
+
/* @__PURE__ */ jsxs10("fieldset", { className: sectionClass, style: { border: 0, padding: 0, margin: 0 }, children: [
|
|
1647
|
+
/* @__PURE__ */ jsx12("legend", { className: headingClass, children: "Theme" }),
|
|
1648
|
+
THEMES.map((t) => /* @__PURE__ */ jsxs10("label", { className: radioRowClass, children: [
|
|
1649
|
+
/* @__PURE__ */ jsx12(
|
|
1194
1650
|
"input",
|
|
1195
1651
|
{
|
|
1196
1652
|
type: "radio",
|
|
@@ -1202,15 +1658,23 @@ function SettingsTab() {
|
|
|
1202
1658
|
}
|
|
1203
1659
|
}
|
|
1204
1660
|
),
|
|
1205
|
-
/* @__PURE__ */
|
|
1661
|
+
/* @__PURE__ */ jsx12("span", { children: t })
|
|
1206
1662
|
] }, t))
|
|
1207
1663
|
] })
|
|
1208
1664
|
] });
|
|
1209
1665
|
}
|
|
1210
1666
|
|
|
1211
1667
|
// src/devtools/components/Panel.tsx
|
|
1212
|
-
import { jsx as
|
|
1213
|
-
var TABS = [
|
|
1668
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1669
|
+
var TABS = [
|
|
1670
|
+
"requests",
|
|
1671
|
+
"routes",
|
|
1672
|
+
"agents",
|
|
1673
|
+
"actions",
|
|
1674
|
+
"errors",
|
|
1675
|
+
"csrf-readiness",
|
|
1676
|
+
"settings"
|
|
1677
|
+
];
|
|
1214
1678
|
function buildPanelStyles(styles, vertical, horizontal, verticalOffset) {
|
|
1215
1679
|
return {
|
|
1216
1680
|
panel: styles.css`
|
|
@@ -1295,7 +1759,7 @@ function Panel() {
|
|
|
1295
1759
|
const tabBtnClass = cls.tabBtn;
|
|
1296
1760
|
const closeBtnClass = cls.closeBtn;
|
|
1297
1761
|
const bodyClass = cls.body;
|
|
1298
|
-
return /* @__PURE__ */
|
|
1762
|
+
return /* @__PURE__ */ jsxs11(
|
|
1299
1763
|
"div",
|
|
1300
1764
|
{
|
|
1301
1765
|
role: "dialog",
|
|
@@ -1303,9 +1767,9 @@ function Panel() {
|
|
|
1303
1767
|
"data-theo-devtools-panel": "",
|
|
1304
1768
|
className: panelClass,
|
|
1305
1769
|
children: [
|
|
1306
|
-
/* @__PURE__ */
|
|
1307
|
-
/* @__PURE__ */
|
|
1308
|
-
/* @__PURE__ */
|
|
1770
|
+
/* @__PURE__ */ jsxs11("div", { className: headerClass, children: [
|
|
1771
|
+
/* @__PURE__ */ jsxs11("div", { className: tabsClass, role: "tablist", children: [
|
|
1772
|
+
/* @__PURE__ */ jsx13(
|
|
1309
1773
|
"span",
|
|
1310
1774
|
{
|
|
1311
1775
|
className: styles.css`
|
|
@@ -1315,10 +1779,10 @@ function Panel() {
|
|
|
1315
1779
|
opacity: 0.9;
|
|
1316
1780
|
`,
|
|
1317
1781
|
"aria-hidden": "true",
|
|
1318
|
-
children: /* @__PURE__ */
|
|
1782
|
+
children: /* @__PURE__ */ jsx13(TheoLogo, { size: 16 })
|
|
1319
1783
|
}
|
|
1320
1784
|
),
|
|
1321
|
-
TABS.map((t) => /* @__PURE__ */
|
|
1785
|
+
TABS.map((t) => /* @__PURE__ */ jsx13(
|
|
1322
1786
|
"button",
|
|
1323
1787
|
{
|
|
1324
1788
|
type: "button",
|
|
@@ -1334,7 +1798,7 @@ function Panel() {
|
|
|
1334
1798
|
t
|
|
1335
1799
|
))
|
|
1336
1800
|
] }),
|
|
1337
|
-
/* @__PURE__ */
|
|
1801
|
+
/* @__PURE__ */ jsx13(
|
|
1338
1802
|
"button",
|
|
1339
1803
|
{
|
|
1340
1804
|
type: "button",
|
|
@@ -1347,107 +1811,20 @@ function Panel() {
|
|
|
1347
1811
|
}
|
|
1348
1812
|
)
|
|
1349
1813
|
] }),
|
|
1350
|
-
/* @__PURE__ */
|
|
1351
|
-
state.activeTab === "requests" && /* @__PURE__ */
|
|
1352
|
-
state.activeTab === "routes" && /* @__PURE__ */
|
|
1353
|
-
state.activeTab === "
|
|
1354
|
-
state.activeTab === "
|
|
1355
|
-
state.activeTab === "
|
|
1814
|
+
/* @__PURE__ */ jsxs11("div", { className: bodyClass, "data-testid": "devtools-tab-body", children: [
|
|
1815
|
+
state.activeTab === "requests" && /* @__PURE__ */ jsx13(RequestsTab, {}),
|
|
1816
|
+
state.activeTab === "routes" && /* @__PURE__ */ jsx13(RoutesTab, {}),
|
|
1817
|
+
state.activeTab === "agents" && /* @__PURE__ */ jsx13(AgentsTab, {}),
|
|
1818
|
+
state.activeTab === "actions" && /* @__PURE__ */ jsx13(ActionsTab, {}),
|
|
1819
|
+
state.activeTab === "errors" && /* @__PURE__ */ jsx13(ErrorsTab, {}),
|
|
1820
|
+
state.activeTab === "csrf-readiness" && /* @__PURE__ */ jsx13(CsrfReadinessTab, {}),
|
|
1821
|
+
state.activeTab === "settings" && /* @__PURE__ */ jsx13(SettingsTab, {})
|
|
1356
1822
|
] })
|
|
1357
1823
|
]
|
|
1358
1824
|
}
|
|
1359
1825
|
);
|
|
1360
1826
|
}
|
|
1361
1827
|
|
|
1362
|
-
// src/devtools/shared.ts
|
|
1363
|
-
var RING_BUFFER_CAP = 50;
|
|
1364
|
-
var MAX_QUEUE_SIZE = 100;
|
|
1365
|
-
var STORAGE_VERSION = 1;
|
|
1366
|
-
var initialState = {
|
|
1367
|
-
open: false,
|
|
1368
|
-
visible: true,
|
|
1369
|
-
position: "bottom-right",
|
|
1370
|
-
theme: "system",
|
|
1371
|
-
activeTab: "requests",
|
|
1372
|
-
requests: [],
|
|
1373
|
-
errors: [],
|
|
1374
|
-
routeManifest: null,
|
|
1375
|
-
activeRoutePath: null,
|
|
1376
|
-
activeChain: []
|
|
1377
|
-
};
|
|
1378
|
-
var CHANNEL_REQUEST = "theo:devtools:request";
|
|
1379
|
-
var CHANNEL_ERROR = "theo:devtools:error";
|
|
1380
|
-
var CHANNEL_CSRF_WARN = "theo:devtools:csrf.warn";
|
|
1381
|
-
var CHANNEL_MANIFEST = "theo:devtools:manifest";
|
|
1382
|
-
var CHANNEL_ROUTE_MATCHED = "theo:devtools:route-matched";
|
|
1383
|
-
|
|
1384
|
-
// src/devtools/dispatcher.ts
|
|
1385
|
-
var _dispatch = null;
|
|
1386
|
-
var _queue = [];
|
|
1387
|
-
function queuable(fn) {
|
|
1388
|
-
return (...args) => {
|
|
1389
|
-
if (_dispatch) {
|
|
1390
|
-
try {
|
|
1391
|
-
fn(_dispatch, ...args);
|
|
1392
|
-
} catch (err) {
|
|
1393
|
-
console.error("[theo devtools] dispatch failed", err);
|
|
1394
|
-
}
|
|
1395
|
-
} else {
|
|
1396
|
-
if (_queue.length >= MAX_QUEUE_SIZE) _queue.shift();
|
|
1397
|
-
_queue.push((d) => {
|
|
1398
|
-
fn(d, ...args);
|
|
1399
|
-
});
|
|
1400
|
-
}
|
|
1401
|
-
};
|
|
1402
|
-
}
|
|
1403
|
-
function flushQueue() {
|
|
1404
|
-
while (_queue.length) {
|
|
1405
|
-
const fn = _queue.shift();
|
|
1406
|
-
if (!fn || !_dispatch) break;
|
|
1407
|
-
try {
|
|
1408
|
-
fn(_dispatch);
|
|
1409
|
-
} catch (err) {
|
|
1410
|
-
console.error("[theo devtools] queued event failed", err);
|
|
1411
|
-
}
|
|
1412
|
-
}
|
|
1413
|
-
}
|
|
1414
|
-
var dispatcher = {
|
|
1415
|
-
onRequest: queuable((d, req) => {
|
|
1416
|
-
d({ type: "REQUEST_ADD", request: req });
|
|
1417
|
-
}),
|
|
1418
|
-
onError: queuable((d, err) => {
|
|
1419
|
-
d({ type: "ERROR_ADD", error: err });
|
|
1420
|
-
}),
|
|
1421
|
-
onCsrfWarn: queuable((d, payload) => {
|
|
1422
|
-
d({ type: "CSRF_WARN", payload });
|
|
1423
|
-
}),
|
|
1424
|
-
onManifestUpdated: queuable((d, manifest) => {
|
|
1425
|
-
d({ type: "MANIFEST_UPDATED", manifest });
|
|
1426
|
-
}),
|
|
1427
|
-
onRouteMatched: queuable((d, path, chain) => {
|
|
1428
|
-
d({ type: "ROUTE_MATCHED", path, chain });
|
|
1429
|
-
}),
|
|
1430
|
-
/**
|
|
1431
|
-
* Wire React's dispatch function in. Idempotent (EC-24): only the
|
|
1432
|
-
* NULL → non-null transition flushes the queue; subsequent non-null
|
|
1433
|
-
* sets just replace the reference (used for StrictMode re-mount).
|
|
1434
|
-
*/
|
|
1435
|
-
setDispatch(d) {
|
|
1436
|
-
const prev = _dispatch;
|
|
1437
|
-
_dispatch = d;
|
|
1438
|
-
if (d && !prev) flushQueue();
|
|
1439
|
-
},
|
|
1440
|
-
/** Testing helper — clear queue + dispatch reference between tests. */
|
|
1441
|
-
_reset() {
|
|
1442
|
-
_dispatch = null;
|
|
1443
|
-
_queue.length = 0;
|
|
1444
|
-
},
|
|
1445
|
-
/** Testing helper — observe queue length. */
|
|
1446
|
-
_queueLength() {
|
|
1447
|
-
return _queue.length;
|
|
1448
|
-
}
|
|
1449
|
-
};
|
|
1450
|
-
|
|
1451
1828
|
// src/devtools/hmr-bridge.ts
|
|
1452
1829
|
function getHot() {
|
|
1453
1830
|
try {
|
|
@@ -1577,13 +1954,13 @@ function useActiveRoute() {
|
|
|
1577
1954
|
}
|
|
1578
1955
|
|
|
1579
1956
|
// src/devtools/hooks/useResolvedTheme.ts
|
|
1580
|
-
import { useEffect as useEffect4, useState as
|
|
1957
|
+
import { useEffect as useEffect4, useState as useState6 } from "react";
|
|
1581
1958
|
function getSystemTheme() {
|
|
1582
1959
|
if (typeof window === "undefined") return "dark";
|
|
1583
1960
|
return window.matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark";
|
|
1584
1961
|
}
|
|
1585
1962
|
function useResolvedTheme(theme) {
|
|
1586
|
-
const [systemTheme, setSystemTheme] =
|
|
1963
|
+
const [systemTheme, setSystemTheme] = useState6(() => getSystemTheme());
|
|
1587
1964
|
useEffect4(() => {
|
|
1588
1965
|
if (theme !== "system") return;
|
|
1589
1966
|
if (typeof window === "undefined") return;
|
|
@@ -1640,6 +2017,16 @@ function useShortcuts() {
|
|
|
1640
2017
|
}, [dispatch, state.open]);
|
|
1641
2018
|
}
|
|
1642
2019
|
|
|
2020
|
+
// src/devtools/install-global.ts
|
|
2021
|
+
function noopCleanup() {
|
|
2022
|
+
}
|
|
2023
|
+
function installDispatcherGlobal() {
|
|
2024
|
+
if (typeof window === "undefined") return noopCleanup;
|
|
2025
|
+
const w = window;
|
|
2026
|
+
w.__theoDevtoolsDispatcher = dispatcher;
|
|
2027
|
+
return noopCleanup;
|
|
2028
|
+
}
|
|
2029
|
+
|
|
1643
2030
|
// src/devtools/persistence.ts
|
|
1644
2031
|
var STORAGE_KEYS = {
|
|
1645
2032
|
version: "theo-devtools-storage-version",
|
|
@@ -1731,6 +2118,45 @@ function writeToStorage(s) {
|
|
|
1731
2118
|
function appendCapped(arr, item, cap = RING_BUFFER_CAP) {
|
|
1732
2119
|
return [item, ...arr].slice(0, cap);
|
|
1733
2120
|
}
|
|
2121
|
+
function reduceAppend(state, action) {
|
|
2122
|
+
switch (action.type) {
|
|
2123
|
+
case "REQUEST_ADD":
|
|
2124
|
+
return { ...state, requests: appendCapped(state.requests, action.request) };
|
|
2125
|
+
case "ERROR_ADD":
|
|
2126
|
+
return { ...state, errors: appendCapped(state.errors, action.error) };
|
|
2127
|
+
case "AGENT_RUN_ADD":
|
|
2128
|
+
return { ...state, agentRuns: appendCapped(state.agentRuns, action.run) };
|
|
2129
|
+
case "ACTION_CALL_ADD":
|
|
2130
|
+
return { ...state, actionCalls: appendCapped(state.actionCalls, action.record) };
|
|
2131
|
+
default:
|
|
2132
|
+
return null;
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
function reduceReset(state, action) {
|
|
2136
|
+
switch (action.type) {
|
|
2137
|
+
case "RESET_REQUESTS":
|
|
2138
|
+
return { ...state, requests: [] };
|
|
2139
|
+
case "RESET_ERRORS":
|
|
2140
|
+
return { ...state, errors: [] };
|
|
2141
|
+
case "RESET_AGENT_RUNS":
|
|
2142
|
+
return { ...state, agentRuns: [] };
|
|
2143
|
+
case "RESET_ACTION_CALLS":
|
|
2144
|
+
return { ...state, actionCalls: [] };
|
|
2145
|
+
default:
|
|
2146
|
+
return null;
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
function csrfWarnToErrorRecord(payload) {
|
|
2150
|
+
return {
|
|
2151
|
+
// eslint-disable-next-line sonarjs/pseudo-random -- non-secret correlation id for devtools UI
|
|
2152
|
+
id: `csrf-${String(Date.now())}-${Math.random().toString(36).slice(2, 8)}`,
|
|
2153
|
+
type: "csrf.warn",
|
|
2154
|
+
message: `CSRF warn: ${payload.method} ${payload.path} \u2014 ${payload.reason}`,
|
|
2155
|
+
code: payload.code,
|
|
2156
|
+
docsUrl: payload.docsUrl,
|
|
2157
|
+
timestamp: Date.now()
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
1734
2160
|
function devtoolsReducer(state, action) {
|
|
1735
2161
|
switch (action.type) {
|
|
1736
2162
|
case "TOGGLE_PANEL":
|
|
@@ -1743,32 +2169,14 @@ function devtoolsReducer(state, action) {
|
|
|
1743
2169
|
return { ...state, position: action.position };
|
|
1744
2170
|
case "SET_THEME":
|
|
1745
2171
|
return { ...state, theme: action.theme };
|
|
1746
|
-
case "
|
|
1747
|
-
return { ...state,
|
|
1748
|
-
case "ERROR_ADD":
|
|
1749
|
-
return { ...state, errors: appendCapped(state.errors, action.error) };
|
|
1750
|
-
case "CSRF_WARN": {
|
|
1751
|
-
const errorRecord = {
|
|
1752
|
-
// eslint-disable-next-line sonarjs/pseudo-random -- non-secret correlation id for devtools UI
|
|
1753
|
-
id: `csrf-${String(Date.now())}-${Math.random().toString(36).slice(2, 8)}`,
|
|
1754
|
-
type: "csrf.warn",
|
|
1755
|
-
message: `CSRF warn: ${action.payload.method} ${action.payload.path} \u2014 ${action.payload.reason}`,
|
|
1756
|
-
code: action.payload.code,
|
|
1757
|
-
docsUrl: action.payload.docsUrl,
|
|
1758
|
-
timestamp: Date.now()
|
|
1759
|
-
};
|
|
1760
|
-
return { ...state, errors: appendCapped(state.errors, errorRecord) };
|
|
1761
|
-
}
|
|
2172
|
+
case "CSRF_WARN":
|
|
2173
|
+
return { ...state, errors: appendCapped(state.errors, csrfWarnToErrorRecord(action.payload)) };
|
|
1762
2174
|
case "MANIFEST_UPDATED":
|
|
1763
2175
|
return { ...state, routeManifest: action.manifest };
|
|
1764
2176
|
case "ROUTE_MATCHED":
|
|
1765
2177
|
return { ...state, activeRoutePath: action.path, activeChain: action.chain };
|
|
1766
|
-
case "RESET_REQUESTS":
|
|
1767
|
-
return { ...state, requests: [] };
|
|
1768
|
-
case "RESET_ERRORS":
|
|
1769
|
-
return { ...state, errors: [] };
|
|
1770
2178
|
default:
|
|
1771
|
-
return state;
|
|
2179
|
+
return reduceAppend(state, action) ?? reduceReset(state, action) ?? state;
|
|
1772
2180
|
}
|
|
1773
2181
|
}
|
|
1774
2182
|
|
|
@@ -1799,7 +2207,7 @@ function createStyles(shadowRoot) {
|
|
|
1799
2207
|
}
|
|
1800
2208
|
|
|
1801
2209
|
// src/devtools/Overlay.tsx
|
|
1802
|
-
import { jsx as
|
|
2210
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1803
2211
|
function ActiveRouteTracker() {
|
|
1804
2212
|
useActiveRoute();
|
|
1805
2213
|
return null;
|
|
@@ -1810,7 +2218,7 @@ function ShortcutsTracker() {
|
|
|
1810
2218
|
}
|
|
1811
2219
|
function ThemeVars({ resolved }) {
|
|
1812
2220
|
const css = `:host { color-scheme: ${resolved}; ${buildThemeCssVars(resolved)} }`;
|
|
1813
|
-
return /* @__PURE__ */
|
|
2221
|
+
return /* @__PURE__ */ jsx14("style", { "data-theo-devtools-theme": resolved, children: css });
|
|
1814
2222
|
}
|
|
1815
2223
|
function Overlay({ shadowRoot }) {
|
|
1816
2224
|
const [state, dispatch] = useReducer(
|
|
@@ -1832,8 +2240,10 @@ function Overlay({ shadowRoot }) {
|
|
|
1832
2240
|
}, [state.position, state.theme, state.open, state.activeTab, state.visible]);
|
|
1833
2241
|
useInsertionEffect(() => {
|
|
1834
2242
|
dispatcher.setDispatch(dispatch);
|
|
2243
|
+
const uninstall = installDispatcherGlobal();
|
|
1835
2244
|
return () => {
|
|
1836
2245
|
dispatcher.setDispatch(null);
|
|
2246
|
+
uninstall();
|
|
1837
2247
|
};
|
|
1838
2248
|
}, []);
|
|
1839
2249
|
useEffect6(() => {
|
|
@@ -1842,17 +2252,17 @@ function Overlay({ shadowRoot }) {
|
|
|
1842
2252
|
sub.unsubscribe();
|
|
1843
2253
|
};
|
|
1844
2254
|
}, []);
|
|
1845
|
-
return /* @__PURE__ */
|
|
1846
|
-
/* @__PURE__ */
|
|
1847
|
-
/* @__PURE__ */
|
|
1848
|
-
/* @__PURE__ */
|
|
1849
|
-
/* @__PURE__ */
|
|
1850
|
-
/* @__PURE__ */
|
|
2255
|
+
return /* @__PURE__ */ jsx14(DevtoolsContext.Provider, { value: { shadowRoot, state, dispatch, styles }, children: /* @__PURE__ */ jsxs12(ShadowPortal, { children: [
|
|
2256
|
+
/* @__PURE__ */ jsx14(ThemeVars, { resolved: resolvedTheme }),
|
|
2257
|
+
/* @__PURE__ */ jsx14(ActiveRouteTracker, {}),
|
|
2258
|
+
/* @__PURE__ */ jsx14(ShortcutsTracker, {}),
|
|
2259
|
+
/* @__PURE__ */ jsx14(Indicator, {}),
|
|
2260
|
+
/* @__PURE__ */ jsx14(Panel, {})
|
|
1851
2261
|
] }) });
|
|
1852
2262
|
}
|
|
1853
2263
|
|
|
1854
2264
|
// src/devtools/entry.tsx
|
|
1855
|
-
import { jsx as
|
|
2265
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1856
2266
|
var PORTAL_TAG = "theo-devtools-portal";
|
|
1857
2267
|
function definePortalElement() {
|
|
1858
2268
|
if (typeof customElements === "undefined") return;
|
|
@@ -1879,7 +2289,7 @@ function mount() {
|
|
|
1879
2289
|
shadowRoot.appendChild(reactRootHost);
|
|
1880
2290
|
const root = createRoot(reactRootHost);
|
|
1881
2291
|
root.render(
|
|
1882
|
-
/* @__PURE__ */
|
|
2292
|
+
/* @__PURE__ */ jsx15(StrictMode, { children: /* @__PURE__ */ jsx15(Overlay, { shadowRoot }) })
|
|
1883
2293
|
);
|
|
1884
2294
|
}
|
|
1885
2295
|
if (typeof document !== "undefined") {
|