cortena-ui 1.4.2 → 1.6.0

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.
Files changed (138) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/LICENSE +7 -0
  3. package/README.md +235 -3
  4. package/dist/a2ui/views.js +2 -2
  5. package/dist/agent-chat/a2ui-block.d.ts +60 -0
  6. package/dist/agent-chat/a2ui-block.js +69 -0
  7. package/dist/agent-chat/a2ui-block.js.map +1 -0
  8. package/dist/agent-chat/agui-client.d.ts +40 -0
  9. package/dist/agent-chat/agui-client.js +251 -0
  10. package/dist/agent-chat/agui-client.js.map +1 -0
  11. package/dist/agent-chat/bridge.d.ts +109 -0
  12. package/dist/agent-chat/bridge.js +353 -0
  13. package/dist/agent-chat/bridge.js.map +1 -0
  14. package/dist/agent-chat/session.d.ts +79 -0
  15. package/dist/agent-chat/session.js +391 -0
  16. package/dist/agent-chat/session.js.map +1 -0
  17. package/dist/agent-chat/step-label.d.ts +99 -0
  18. package/dist/agent-chat/step-label.js +116 -0
  19. package/dist/agent-chat/step-label.js.map +1 -0
  20. package/dist/agent-chat/store.d.ts +102 -0
  21. package/dist/agent-chat/store.js +876 -0
  22. package/dist/agent-chat/store.js.map +1 -0
  23. package/dist/agent-chat/types.d.ts +277 -0
  24. package/dist/agent-chat/types.js +17 -0
  25. package/dist/agent-chat/types.js.map +1 -0
  26. package/dist/agent-chat.d.ts +11 -0
  27. package/dist/agent-chat.js +11 -0
  28. package/dist/components/admin-permissions/admin-permissions.d.ts +66 -0
  29. package/dist/components/admin-permissions/admin-permissions.js +101 -0
  30. package/dist/components/admin-permissions/admin-permissions.js.map +1 -0
  31. package/dist/components/admin-permissions/context.d.ts +70 -0
  32. package/dist/components/admin-permissions/context.js +258 -0
  33. package/dist/components/admin-permissions/context.js.map +1 -0
  34. package/dist/components/admin-permissions/index.d.ts +10 -0
  35. package/dist/components/admin-permissions/licence.d.ts +15 -0
  36. package/dist/components/admin-permissions/licence.js +78 -0
  37. package/dist/components/admin-permissions/licence.js.map +1 -0
  38. package/dist/components/admin-permissions/matrix.d.ts +20 -0
  39. package/dist/components/admin-permissions/matrix.js +191 -0
  40. package/dist/components/admin-permissions/matrix.js.map +1 -0
  41. package/dist/components/admin-permissions/members.d.ts +18 -0
  42. package/dist/components/admin-permissions/members.js +185 -0
  43. package/dist/components/admin-permissions/members.js.map +1 -0
  44. package/dist/components/admin-permissions/role-assignment.d.ts +35 -0
  45. package/dist/components/admin-permissions/role-assignment.js +174 -0
  46. package/dist/components/admin-permissions/role-assignment.js.map +1 -0
  47. package/dist/components/admin-permissions/roles.d.ts +25 -0
  48. package/dist/components/admin-permissions/roles.js +168 -0
  49. package/dist/components/admin-permissions/roles.js.map +1 -0
  50. package/dist/components/admin-permissions/types.d.ts +152 -0
  51. package/dist/components/admin-permissions/types.js +63 -0
  52. package/dist/components/admin-permissions/types.js.map +1 -0
  53. package/dist/components/agent-chat-popup.d.ts +29 -0
  54. package/dist/components/agent-chat-popup.js +188 -0
  55. package/dist/components/agent-chat-popup.js.map +1 -0
  56. package/dist/components/agent-chat.d.ts +163 -0
  57. package/dist/components/agent-chat.js +673 -0
  58. package/dist/components/agent-chat.js.map +1 -0
  59. package/dist/components/app-shell.d.ts +126 -0
  60. package/dist/components/app-shell.js +297 -0
  61. package/dist/components/app-shell.js.map +1 -0
  62. package/dist/components/badge.d.ts +1 -1
  63. package/dist/components/button-link.js +1 -1
  64. package/dist/components/button.d.ts +1 -1
  65. package/dist/components/checkbox.d.ts +1 -1
  66. package/dist/components/combobox.d.ts +1 -1
  67. package/dist/components/combobox.js +1 -1
  68. package/dist/components/consent-screen.d.ts +65 -0
  69. package/dist/components/consent-screen.js +123 -0
  70. package/dist/components/consent-screen.js.map +1 -0
  71. package/dist/components/data-table/data-table.d.ts +15 -1
  72. package/dist/components/data-table/data-table.js +18 -4
  73. package/dist/components/data-table/data-table.js.map +1 -1
  74. package/dist/components/data-table/index.d.ts +4 -4
  75. package/dist/components/data-table/parts.d.ts +27 -3
  76. package/dist/components/data-table/parts.js +175 -55
  77. package/dist/components/data-table/parts.js.map +1 -1
  78. package/dist/components/data-table/types.d.ts +61 -0
  79. package/dist/components/data-table/use-data-table.js +91 -6
  80. package/dist/components/data-table/use-data-table.js.map +1 -1
  81. package/dist/components/data-table/use-server-source.js +119 -28
  82. package/dist/components/data-table/use-server-source.js.map +1 -1
  83. package/dist/components/help-panel.d.ts +131 -0
  84. package/dist/components/help-panel.js +545 -0
  85. package/dist/components/help-panel.js.map +1 -0
  86. package/dist/components/login-screen.d.ts +127 -0
  87. package/dist/components/login-screen.js +339 -0
  88. package/dist/components/login-screen.js.map +1 -0
  89. package/dist/components/session-guard.d.ts +268 -0
  90. package/dist/components/session-guard.js +632 -0
  91. package/dist/components/session-guard.js.map +1 -0
  92. package/dist/components/toast.d.ts +1 -1
  93. package/dist/core.d.ts +5 -1
  94. package/dist/core.js +11 -7
  95. package/dist/data-table.d.ts +13 -4
  96. package/dist/data-table.js +10 -2
  97. package/dist/hooks/use-cortena-theme.js +49 -3
  98. package/dist/hooks/use-cortena-theme.js.map +1 -1
  99. package/dist/index.d.ts +17 -4
  100. package/dist/index.js +21 -8
  101. package/dist/markdown.d.ts +2 -1
  102. package/dist/markdown.js +2 -1
  103. package/package.json +18 -5
  104. package/src/agent-chat/a2ui-block.ts +118 -0
  105. package/src/agent-chat/agui-client.ts +405 -0
  106. package/src/agent-chat/bridge.ts +445 -0
  107. package/src/agent-chat/session.ts +549 -0
  108. package/src/agent-chat/step-label.ts +177 -0
  109. package/src/agent-chat/store.ts +1234 -0
  110. package/src/agent-chat/types.ts +308 -0
  111. package/src/components/admin-permissions/admin-permissions.tsx +130 -0
  112. package/src/components/admin-permissions/context.tsx +376 -0
  113. package/src/components/admin-permissions/index.tsx +32 -0
  114. package/src/components/admin-permissions/licence.tsx +84 -0
  115. package/src/components/admin-permissions/matrix.tsx +257 -0
  116. package/src/components/admin-permissions/members.tsx +204 -0
  117. package/src/components/admin-permissions/role-assignment.tsx +239 -0
  118. package/src/components/admin-permissions/roles.tsx +169 -0
  119. package/src/components/admin-permissions/types.ts +231 -0
  120. package/src/components/agent-chat-popup.tsx +289 -0
  121. package/src/components/agent-chat.tsx +1006 -0
  122. package/src/components/app-shell.tsx +502 -0
  123. package/src/components/consent-screen.tsx +239 -0
  124. package/src/components/data-table/data-table.tsx +36 -0
  125. package/src/components/data-table/index.tsx +6 -1
  126. package/src/components/data-table/parts.tsx +223 -47
  127. package/src/components/data-table/types.ts +68 -0
  128. package/src/components/data-table/use-data-table.ts +152 -4
  129. package/src/components/data-table/use-server-source.ts +150 -12
  130. package/src/components/help-panel.tsx +765 -0
  131. package/src/components/login-screen.tsx +479 -0
  132. package/src/components/session-guard.tsx +1071 -0
  133. package/src/entries/agent-chat.ts +137 -0
  134. package/src/entries/core.ts +8 -0
  135. package/src/entries/data-table.ts +41 -0
  136. package/src/entries/markdown.ts +25 -0
  137. package/src/hooks/use-cortena-theme.ts +63 -4
  138. package/src/index.ts +6 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-label.js","names":[],"sources":["../../src/agent-chat/step-label.ts"],"sourcesContent":["/**\n * The wording map: one plain sentence per tool call (SKILLS-9).\n *\n * A run is a sequence of tool calls, and what the user sees of it today is a\n * tool name and a JSON blob. `engram_describe {\"id\":\"tasks.task.list\"}` is an\n * accurate description of nothing anybody asked for. This module turns the\n * three native tools — `engram_search`, `engram_describe`, `broker_invoke` —\n * into sentences a person can read while they wait.\n *\n * It is a pure function of the tool name and the arguments, in its own module,\n * for two reasons. It is the part most likely to be edited by someone who is\n * not editing the store, and it is the part worth testing exhaustively: the\n * store's job is start/end pairing, and the wording's job is being readable.\n *\n * Deliberately NOT here: anything that needs the result. The client cannot know\n * whether a `broker_invoke` is a read or a write before the reply comes back —\n * only the catalogue knows, and the model only carries `confirmed` once the\n * user has said yes — so an unconfirmed invoke is worded \"Fetching …\", which is\n * true of a read and harmless of a write that has not happened yet. The one\n * result-dependent wording, a 409 `confirmation_required`, is\n * `confirmationRequiredLabel` and the store applies it when the envelope\n * arrives.\n */\n\n/**\n * Which end of the step the label is for.\n *\n * Nearly every sentence reads the same either way, because it describes the\n * step rather than claiming an outcome — \"Reading skill: alerts\" is as true of\n * a finished read as of one in flight, and rewriting it on completion makes the\n * strip jump under the reader's eye for no gain. The exception is the confirmed\n * write, where \"Doing: tasks task create\" and \"Done: tasks task create\" are\n * genuinely different facts and the user needs the second one.\n */\nexport type AgentStepPhase = \"running\" | \"done\";\n\n/** Longest intent or title carried into a label, ellipsis included. */\nconst TEXT_LIMIT = 80;\n\n/**\n * An id as words: `tasks.task.list` -> \"tasks task list\".\n *\n * Deterministic and dumb on purpose. A cleverer mapping — reordering to \"list\n * tasks\", pluralising, looking up a display name — needs a table that has to be\n * maintained for every capability in every extension, and a table that is one\n * release out of date reads worse than the id did.\n */\nexport function humaniseId(id: string): string {\n return id\n .split(/[.\\-_]+/)\n .filter(Boolean)\n .join(\" \")\n .toLowerCase();\n}\n\n/** The topic of a skill id: `skill.platform.using-extensions` -> \"using extensions\". */\nfunction skillTopic(id: string): string {\n const parts = id.split(\".\").filter(Boolean);\n const last = parts[parts.length - 1];\n return last ? humaniseId(last) : humaniseId(id);\n}\n\n/**\n * One line of it, sanitised and bounded, with the ellipsis inside the limit.\n *\n * Everything interpolated into a label goes through this, including the ones\n * that look safe: a tool name, an operation id, a server's `message`. All three\n * arrive from outside — a catalogue entry, a broker reply — and none is worth\n * trusting with the length of a line or with the direction of it. Control and\n * format characters are stripped BEFORE the length check, so a run of\n * invisibles cannot eat the budget and a U+202E cannot flip the rest of the\n * strip right-to-left. Newlines have already become spaces by then, so the\n * strip does not silently join two words.\n */\nexport function truncate(text: string, limit: number = TEXT_LIMIT): string {\n const collapsed = text\n .replace(/\\s+/g, \" \")\n .trim()\n .replace(/[\\p{Cf}\\p{Cc}]/gu, \"\");\n return collapsed.length <= limit ? collapsed : `${collapsed.slice(0, limit - 1)}…`;\n}\n\n/**\n * The line for a call nothing better can be said about yet.\n *\n * Its own function because two other places have to RECOGNISE it: the store\n * re-words a step that finished on this line if its arguments turn up late, and\n * the strip holds it out of the live region rather than announcing\n * \"Working: broker_invoke\" to a screen reader a moment before the real sentence\n * replaces it.\n */\nexport function genericLabel(toolName: string): string {\n return `Working: ${truncate(toolName)}`;\n}\n\n/** Is this label the fallback rather than something the arguments produced? */\nexport function isGenericLabel(toolName: string, label: string): boolean {\n return label === genericLabel(toolName);\n}\n\nfunction readString(args: Record<string, unknown> | undefined, key: string): string {\n const value = args?.[key];\n return typeof value === \"string\" && value.trim() ? value : \"\";\n}\n\n/**\n * The line shown for one tool call.\n *\n * | tool | label |\n * | --- | --- |\n * | `engram_search` | Looking for a way to \\<intent\\> |\n * | `engram_describe`, `skill.*` | Reading skill: \\<title, or the topic\\> |\n * | `engram_describe`, anything else | Checking how to \\<id as words\\> |\n * | `broker_invoke`, `confirmed: true` | Doing: \\<operation\\> / Done: \\<operation\\> |\n * | `broker_invoke`, otherwise | Fetching \\<operation\\> |\n * | anything else | Working: \\<tool name\\> |\n *\n * The key argument missing falls through to the last row rather than inventing\n * a sentence about nothing: arguments arrive in a second event\n * (`TOOL_CALL_ARGS`), so \"no arguments yet\" is a state every call passes\n * through, and the generic line is what it should read as until they land.\n */\nexport function stepLabel(\n toolName: string,\n args: Record<string, unknown> | undefined,\n phase: AgentStepPhase,\n): string {\n switch (toolName) {\n case \"engram_search\": {\n const intent = readString(args, \"intent\");\n if (intent) {\n return `Looking for a way to ${truncate(intent)}`;\n }\n break;\n }\n case \"engram_describe\": {\n const id = readString(args, \"id\");\n if (!id) {\n break;\n }\n if (id.startsWith(\"skill.\")) {\n // Ingest carries the title on the row, not on the call, so it is only\n // here when the model has already seen the index and repeated it.\n const title = readString(args, \"title\");\n return `Reading skill: ${truncate(title ? title : skillTopic(id))}`;\n }\n return `Checking how to ${truncate(humaniseId(id))}`;\n }\n case \"broker_invoke\": {\n const operation = readString(args, \"operation\");\n if (!operation) {\n break;\n }\n const label = truncate(humaniseId(operation));\n if (args?.confirmed === true) {\n return phase === \"done\" ? `Done: ${label}` : `Doing: ${label}`;\n }\n return `Fetching ${label}`;\n }\n default:\n break;\n }\n return genericLabel(toolName);\n}\n\n/**\n * The label for a call the broker refused pending a yes.\n *\n * A 409 `confirmation_required` is not a failure — it is the broker doing its\n * job on a write the user has not approved — so the step keeps its tick and\n * changes its words. Drawn as an error it reads as \"the agent broke\"; drawn as\n * \"Fetching …\", completed, it reads as though the write went through.\n */\nexport function confirmationRequiredLabel(args: Record<string, unknown> | undefined): string {\n const operation = readString(args, \"operation\");\n return `Needs your confirmation: ${operation ? truncate(humaniseId(operation)) : \"that action\"}`;\n}\n"],"mappings":";;;AAqCA,MAAM,aAAa;;;;;;;;;AAUnB,SAAgB,WAAW,IAAoB;CAC7C,OAAO,GACJ,MAAM,SAAS,CAAC,CAChB,OAAO,OAAO,CAAC,CACf,KAAK,GAAG,CAAC,CACT,YAAY;AACjB;;AAGA,SAAS,WAAW,IAAoB;CACtC,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO;CAC1C,MAAM,OAAO,MAAM,MAAM,SAAS;CAClC,OAAO,OAAO,WAAW,IAAI,IAAI,WAAW,EAAE;AAChD;;;;;;;;;;;;;AAcA,SAAgB,SAAS,MAAc,QAAgB,YAAoB;CACzE,MAAM,YAAY,KACf,QAAQ,QAAQ,GAAG,CAAC,CACpB,KAAK,CAAC,CACN,QAAQ,oBAAoB,EAAE;CACjC,OAAO,UAAU,UAAU,QAAQ,YAAY,GAAG,UAAU,MAAM,GAAG,QAAQ,CAAC,EAAE;AAClF;;;;;;;;;;AAWA,SAAgB,aAAa,UAA0B;CACrD,OAAO,YAAY,SAAS,QAAQ;AACtC;;AAGA,SAAgB,eAAe,UAAkB,OAAwB;CACvE,OAAO,UAAU,aAAa,QAAQ;AACxC;AAEA,SAAS,WAAW,MAA2C,KAAqB;CAClF,MAAM,QAAQ,OAAO;CACrB,OAAO,OAAO,UAAU,YAAY,MAAM,KAAK,IAAI,QAAQ;AAC7D;;;;;;;;;;;;;;;;;;AAmBA,SAAgB,UACd,UACA,MACA,OACQ;CACR,QAAQ,UAAR;EACE,KAAK,iBAAiB;GACpB,MAAM,SAAS,WAAW,MAAM,QAAQ;GACxC,IAAI,QACF,OAAO,wBAAwB,SAAS,MAAM;GAEhD;EACF;EACA,KAAK,mBAAmB;GACtB,MAAM,KAAK,WAAW,MAAM,IAAI;GAChC,IAAI,CAAC,IACH;GAEF,IAAI,GAAG,WAAW,QAAQ,GAAG;IAG3B,MAAM,QAAQ,WAAW,MAAM,OAAO;IACtC,OAAO,kBAAkB,SAAS,QAAQ,QAAQ,WAAW,EAAE,CAAC;GAClE;GACA,OAAO,mBAAmB,SAAS,WAAW,EAAE,CAAC;EACnD;EACA,KAAK,iBAAiB;GACpB,MAAM,YAAY,WAAW,MAAM,WAAW;GAC9C,IAAI,CAAC,WACH;GAEF,MAAM,QAAQ,SAAS,WAAW,SAAS,CAAC;GAC5C,IAAI,MAAM,cAAc,MACtB,OAAO,UAAU,SAAS,SAAS,UAAU,UAAU;GAEzD,OAAO,YAAY;EACrB;CAGF;CACA,OAAO,aAAa,QAAQ;AAC9B;;;;;;;;;AAUA,SAAgB,0BAA0B,MAAmD;CAC3F,MAAM,YAAY,WAAW,MAAM,WAAW;CAC9C,OAAO,4BAA4B,YAAY,SAAS,WAAW,SAAS,CAAC,IAAI;AACnF"}
@@ -0,0 +1,102 @@
1
+ "use client";
2
+ import { A2UIChatBlock } from "./a2ui-block.js";
3
+ import { AgentApprovalDecision, AgentApprovalRequest, AgentChatClient, AgentChatMessage, AgentChatStep, AgentSession, AgentToolResultMetadata } from "./types.js";
4
+ //#region src/agent-chat/store.d.ts
5
+ export interface AgentToolEntry {
6
+ id: string;
7
+ name: string;
8
+ status: "running" | "complete" | "error";
9
+ input?: unknown;
10
+ output?: unknown;
11
+ startedAt: number;
12
+ completedAt?: number;
13
+ }
14
+ export interface AgentChatState {
15
+ sessionKey: string | null;
16
+ messages: AgentChatMessage[];
17
+ streaming: boolean;
18
+ streamText: string;
19
+ streamThinkingText: string;
20
+ streamA2ui: A2UIChatBlock[];
21
+ runId: string | null;
22
+ hasMoreHistory: boolean;
23
+ loadingHistory: boolean;
24
+ toolOrder: string[];
25
+ tools: Record<string, AgentToolEntry>;
26
+ /**
27
+ * The turn's tool calls in plain words, in arrival order (SKILLS-9).
28
+ *
29
+ * The same calls as `tools`, worded rather than dumped, and rendered under
30
+ * the assistant turn instead of in the strip at the foot. Cleared when the
31
+ * next run starts, so the list is always "what is happening now" or "what
32
+ * just happened", never a transcript.
33
+ */
34
+ steps: AgentChatStep[];
35
+ /**
36
+ * Ids of steps the `STEP_LIMIT` cap has already dropped.
37
+ *
38
+ * A runaway turn pushes the first calls off the front of the list, and their
39
+ * results arrive afterwards. Without this the store saw an id it did not
40
+ * know, took it for a call nobody announced, and appended a fresh
41
+ * "Working: tool" line at the BOTTOM of the strip — the oldest call in the
42
+ * turn, drawn as the newest, with no words on it. Bounded, because it exists
43
+ * to recognise a handful of stragglers, not to keep a transcript.
44
+ */
45
+ retiredSteps: string[];
46
+ approvals: AgentApprovalRequest[];
47
+ /**
48
+ * Transcript RECORDS loaded, which is not `messages.length`.
49
+ *
50
+ * `parseHistoryMessages` folds a turn — an assistant preamble, the tool call,
51
+ * the tool result, the answer — into one visible message, so the two numbers
52
+ * diverge on the very first agent turn. `offset` is an offset into the
53
+ * server's records, and paging with the folded count asked for records the
54
+ * screen already had and skipped the ones it did not: "load older" silently
55
+ * lost messages the further back a user read.
56
+ */
57
+ historyCount: number;
58
+ sessions: AgentSession[];
59
+ loadingSessions: boolean;
60
+ /** A failure the user has to be told about, e.g. no template for the slug. */
61
+ error: string | null;
62
+ }
63
+ /**
64
+ * `TOOL_CALL_RESULT.metadata`, read defensively.
65
+ *
66
+ * `null` when nothing usable arrived, which a transport that predates the
67
+ * contract will produce. A step with no metadata at all is treated as a
68
+ * success by `tool.complete` and as a failure by `tool.error`, which is the
69
+ * most either event can honestly claim on its own.
70
+ *
71
+ * Note what is NOT here: any reading of `content`. The result text is the
72
+ * model's copy of the reply, in whatever shape the tool returned, and the
73
+ * client's previous attempt to find `ok: false` in it matched nothing real —
74
+ * a Cortena tool result is `{ content: [...], details }`, so the envelope it
75
+ * was looking for was two levels down when it existed at all.
76
+ */
77
+ export declare function readResultMetadata(raw: unknown): AgentToolResultMetadata | null;
78
+ export interface UseAgentChatOptions {
79
+ client: AgentChatClient;
80
+ /**
81
+ * Names the `sessionStorage` slot the current session key lives in. Two
82
+ * pop-ups with different scopes never share a key, which is what keeps one
83
+ * extension's chat out of another's.
84
+ */
85
+ storageScope: string;
86
+ /** Skip reading and writing `sessionStorage`; for a transient mount. */
87
+ ephemeral?: boolean;
88
+ thinking?: "low" | "medium" | "high";
89
+ }
90
+ export interface UseAgentChatResult extends AgentChatState {
91
+ send: (text: string, attachments?: unknown[]) => void;
92
+ sendAction: (action: NonNullable<Parameters<AgentChatClient["send"]>[0]["a2uiAction"]>) => void;
93
+ abort: () => void;
94
+ resolveApproval: (id: string, decision: AgentApprovalDecision) => void;
95
+ newSession: () => void;
96
+ resumeSession: (key: string) => void;
97
+ loadOlder: () => void;
98
+ refreshSessions: () => void;
99
+ }
100
+ export declare function useAgentChat({ client, storageScope, ephemeral, thinking }: UseAgentChatOptions): UseAgentChatResult;
101
+ //#endregion
102
+ //# sourceMappingURL=store.d.ts.map