@schlenkr/ragents 0.1.13 → 0.1.15

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 (145) hide show
  1. package/apps/server/package.json +1 -1
  2. package/apps/server/src/api/contracts.ts +19 -1
  3. package/apps/server/src/api/core-methods.ts +12 -0
  4. package/apps/server/src/chat-handler.ts +19 -0
  5. package/apps/server/src/host-api.json +2 -0
  6. package/apps/server/src/host-api.ts +2 -2
  7. package/apps/server/src/plugin-build/build.ts +1 -1
  8. package/apps/server/src/plugin-support/actor-programs/app-project.ts +61 -17
  9. package/apps/server/src/plugin-support/actor-programs/contract.ts +18 -1
  10. package/apps/server/src/plugin-support/actor-programs/service.ts +22 -1
  11. package/apps/server/src/plugin-support/plugin-folder.ts +14 -1
  12. package/apps/server/src/plugin-support/run-scripts.ts +27 -2
  13. package/apps/server/src/profile/compose.ts +2 -0
  14. package/apps/server/src/provider.ts +31 -6
  15. package/apps/server/src/ragents/chat-projection.ts +7 -0
  16. package/apps/server/src/ragents/global-chat.ts +5 -1
  17. package/apps/server/src/ragents/run-script-tools.ts +66 -0
  18. package/apps/server/src/ragents/session.ts +122 -60
  19. package/apps/server/src/title-compactor.ts +1 -1
  20. package/apps/web/dist/assets/{highlighted-body-KPVGNVTW-CpPi6QLr.js → highlighted-body-KPVGNVTW-BwD4uYEe.js} +1 -1
  21. package/apps/web/dist/assets/main-KBrc5Q77.js +11 -0
  22. package/apps/web/dist/assets/{mermaid-HWGCJPDP-q-mf1kLN.js → mermaid-HWGCJPDP-CSCkaArr.js} +88 -88
  23. package/apps/web/dist/assets/runPanel-BjG5NBKm.js +26 -0
  24. package/apps/web/dist/help/guide-clients.html +21 -4
  25. package/apps/web/dist/help/guide-clients.md +23 -4
  26. package/apps/web/dist/help/guide-plugins.html +12 -2
  27. package/apps/web/dist/help/guide-plugins.md +9 -2
  28. package/apps/web/dist/help/guide-programs.html +8 -2
  29. package/apps/web/dist/help/guide-programs.md +9 -2
  30. package/apps/web/dist/help/guide-runtime.html +3 -2
  31. package/apps/web/dist/help/guide-runtime.md +3 -2
  32. package/apps/web/dist/help/index.html +1 -1
  33. package/apps/web/dist/help/mini-app.css +16 -2
  34. package/apps/web/dist/host-web.json +13 -13
  35. package/apps/web/dist/index.html +2 -2
  36. package/apps/web/dist/run-panel.html +2 -2
  37. package/apps/web/package.json +1 -1
  38. package/apps/web/src/App.tsx +12 -1
  39. package/apps/web/src/PluginRegistry.tsx +2 -2
  40. package/apps/web/src/SessionList.tsx +7 -6
  41. package/apps/web/src/SettingsModal.tsx +3 -3
  42. package/apps/web/src/actor-programs/client-ui/FilePicker.tsx +1 -1
  43. package/apps/web/src/api.ts +2 -0
  44. package/apps/web/src/run-overview.ts +1 -1
  45. package/apps/web/src/run-panel/RunPanelApp.tsx +1 -1
  46. package/apps/web/src/run-panel/RunPanelMenu.tsx +47 -11
  47. package/apps/web/src/ui/relative-time.ts +1 -1
  48. package/bundles/ragents.activity/ragents-bundle.json +1 -1
  49. package/bundles/ragents.actor-programs/ragents-bundle.json +4 -2
  50. package/bundles/ragents.actor-programs/server/index.js +437 -24
  51. package/bundles/ragents.actor-programs/server/index.js.map +4 -4
  52. package/bundles/ragents.actor-programs/web/index.js.map +1 -1
  53. package/bundles/ragents.ask/ragents-bundle.json +2 -2
  54. package/bundles/ragents.ask/server/index.js +1 -0
  55. package/bundles/ragents.ask/server/index.js.map +2 -2
  56. package/bundles/ragents.browser/ragents-bundle.json +1 -1
  57. package/bundles/ragents.documents/ragents-bundle.json +2 -2
  58. package/bundles/ragents.documents/web/classes.json +1 -1
  59. package/bundles/ragents.documents/web/index.js +1 -1
  60. package/bundles/ragents.documents/web/index.js.map +2 -2
  61. package/bundles/ragents.lsp-fsharp/ragents-bundle.json +1 -1
  62. package/bundles/ragents.lsp-roslyn/ragents-bundle.json +1 -1
  63. package/bundles/ragents.lsp-typescript/ragents-bundle.json +1 -1
  64. package/bundles/ragents.model-relay/ragents-bundle.json +1 -1
  65. package/bundles/ragents.orchestration/ragents-bundle.json +7 -4
  66. package/bundles/ragents.orchestration/server/chunks/chunk-QS3WJ3D7.js +11 -0
  67. package/bundles/ragents.orchestration/server/chunks/chunk-QS3WJ3D7.js.map +7 -0
  68. package/bundles/ragents.orchestration/server/exports/server/contract.js +9 -0
  69. package/bundles/ragents.orchestration/server/exports/server/contract.js.map +7 -0
  70. package/bundles/ragents.orchestration/server/index.js +49 -3
  71. package/bundles/ragents.orchestration/server/index.js.map +2 -2
  72. package/bundles/ragents.orchestration/surface.hbs +5 -0
  73. package/bundles/ragents.orchestration/web/index.js +3 -3
  74. package/bundles/ragents.orchestration/web/index.js.map +2 -2
  75. package/bundles/ragents.overseer/ragents-bundle.json +4 -3
  76. package/bundles/ragents.overseer/web/classes.json +1 -1
  77. package/bundles/ragents.overseer/web/index.js +1 -1
  78. package/bundles/ragents.overseer/web/index.js.map +4 -4
  79. package/bundles/ragents.processes/ragents-bundle.json +2 -2
  80. package/bundles/ragents.processes/web/classes.json +1 -1
  81. package/bundles/ragents.processes/web/index.js +1 -1
  82. package/bundles/ragents.processes/web/index.js.map +2 -2
  83. package/bundles/ragents.product/ragents-bundle.json +1 -1
  84. package/bundles/ragents.profile-distribution/ragents-bundle.json +1 -1
  85. package/bundles/ragents.reference/actors/notebook/package.json +16 -0
  86. package/bundles/ragents.reference/actors/notebook/src/client.tsx +31 -0
  87. package/bundles/ragents.reference/actors/notebook/src/server.ts +27 -0
  88. package/bundles/ragents.reference/actors/notebook/tests/program.test.ts +27 -0
  89. package/bundles/ragents.reference/ragents-bundle.json +4 -3
  90. package/bundles/ragents.reference/run-scripts/quick-note/RUN.md +14 -0
  91. package/bundles/ragents.reference/run-scripts/quick-note/package.json +9 -0
  92. package/bundles/ragents.reference/run-scripts/quick-note/src/server.ts +29 -0
  93. package/bundles/ragents.reference/run-scripts/quick-note/tests/program.test.ts +43 -0
  94. package/bundles/ragents.reference/run-scripts/run-roster/RUN.md +19 -0
  95. package/bundles/ragents.reference/run-scripts/run-roster/package.json +9 -0
  96. package/bundles/ragents.reference/run-scripts/run-roster/src/server.ts +26 -0
  97. package/bundles/ragents.reference/run-scripts/run-roster/tests/program.test.ts +47 -0
  98. package/bundles/ragents.todo/ragents-bundle.json +1 -1
  99. package/bundles/ragents.transcript/ragents-bundle.json +1 -1
  100. package/bundles/ragents.watch/ragents-bundle.json +1 -1
  101. package/bundles/ragents.workspace/ragents-bundle.json +2 -2
  102. package/bundles/ragents.workspace/web/classes.json +1 -1
  103. package/bundles/ragents.workspace/web/index.js +1 -1
  104. package/bundles/ragents.workspace/web/index.js.map +2 -2
  105. package/package.json +3 -3
  106. package/packages/ragents/src/domain/vocabulary.ts +4 -0
  107. package/packages/ragents/src/index.ts +3 -1
  108. package/packages/ragents/src/plugin-host.ts +62 -10
  109. package/packages/ragents/src/plugin-types.ts +11 -0
  110. package/packages/ragents/src/runtime/guards.ts +2 -1
  111. package/packages/ragents/src/typescript/async-compiler.ts +11 -1
  112. package/plugins/ragents.actor-programs/server/index.ts +3 -0
  113. package/plugins/ragents.actor-programs/server/runtime.ts +424 -28
  114. package/plugins/ragents.actor-programs/server/script-state.ts +54 -0
  115. package/plugins/ragents.actor-programs/server/tool-contributor.ts +2 -0
  116. package/plugins/ragents.ask/server/ask-tool.ts +1 -0
  117. package/plugins/ragents.documents/web/DocumentViewer.tsx +2 -2
  118. package/plugins/ragents.orchestration/ragents-plugin.json +1 -0
  119. package/plugins/ragents.orchestration/server/contract.ts +14 -0
  120. package/plugins/ragents.orchestration/server/index.ts +4 -1
  121. package/plugins/ragents.orchestration/server/surface-tool.ts +58 -2
  122. package/plugins/ragents.orchestration/surface.hbs +5 -0
  123. package/plugins/ragents.orchestration/web/ExecutionsPanel.tsx +1 -1
  124. package/plugins/ragents.orchestration/web/FlowInspector.tsx +1 -1
  125. package/plugins/ragents.orchestration/web/JournalStatus.tsx +1 -1
  126. package/plugins/ragents.orchestration/web/format.ts +1 -1
  127. package/plugins/ragents.overseer/web/index.tsx +51 -3
  128. package/plugins/ragents.processes/web/processes.ts +1 -1
  129. package/plugins/ragents.reference/actors/notebook/package.json +16 -0
  130. package/plugins/ragents.reference/actors/notebook/src/client.tsx +31 -0
  131. package/plugins/ragents.reference/actors/notebook/src/server.ts +27 -0
  132. package/plugins/ragents.reference/actors/notebook/tests/program.test.ts +27 -0
  133. package/plugins/ragents.reference/run-scripts/quick-note/RUN.md +14 -0
  134. package/plugins/ragents.reference/run-scripts/quick-note/package.json +9 -0
  135. package/plugins/ragents.reference/run-scripts/quick-note/src/server.ts +29 -0
  136. package/plugins/ragents.reference/run-scripts/quick-note/tests/program.test.ts +43 -0
  137. package/plugins/ragents.reference/run-scripts/run-roster/RUN.md +19 -0
  138. package/plugins/ragents.reference/run-scripts/run-roster/package.json +9 -0
  139. package/plugins/ragents.reference/run-scripts/run-roster/src/server.ts +26 -0
  140. package/plugins/ragents.reference/run-scripts/run-roster/tests/program.test.ts +47 -0
  141. package/plugins/ragents.workspace/web/FileBrowser.tsx +1 -1
  142. package/scripts/agent/agent-cli.ts +46 -2
  143. package/scripts/package/ragents.mjs +3 -1
  144. package/apps/web/dist/assets/main-DJmCHGzM.js +0 -11
  145. package/apps/web/dist/assets/runPanel-nk_aMxSn.js +0 -21
@@ -28,8 +28,8 @@ const formatTimestamp = (time: number): string => {
28
28
  const today = new Date();
29
29
  const sameDay = date.toDateString() === today.toDateString();
30
30
  return sameDay
31
- ? date.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit" })
32
- : date.toLocaleDateString("en-US", { day: "2-digit", month: "2-digit" });
31
+ ? date.toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit" })
32
+ : date.toLocaleDateString(undefined, { day: "2-digit", month: "2-digit" });
33
33
  };
34
34
 
35
35
  /** Running, unread, locked and resting runs differ only in their accent color; the card layout stays the same. */
@@ -111,7 +111,7 @@ export function SessionList({
111
111
  aria-current={session.id === activeId ? "true" : undefined}
112
112
  aria-pressed={selectMode ? selectedIds.has(session.id) : undefined}
113
113
  className={cn(
114
- "flex min-h-[148px] min-w-0 flex-1 cursor-pointer flex-col items-stretch gap-2.5 rounded-[11px] px-4 pb-4 text-left focus-visible:outline-2 focus-visible:outline-primary focus-visible:outline-offset-2 disabled:cursor-default",
114
+ "flex max-h-[240px] min-h-[148px] min-w-0 flex-1 cursor-pointer flex-col items-stretch gap-2.5 overflow-hidden rounded-[11px] px-4 pb-4 text-left focus-visible:outline-2 focus-visible:outline-primary focus-visible:outline-offset-2 disabled:cursor-default",
115
115
  selectMode && "pl-9",
116
116
  )}
117
117
  disabled={session.locked !== undefined && !selectMode}
@@ -119,7 +119,7 @@ export function SessionList({
119
119
  type="button"
120
120
  >
121
121
  <span className={cn("-mx-4 flex flex-col gap-2.5 rounded-t-[11px] border-t-[3px] px-4 pt-3.5 pb-3", tone.head, selectMode && "-ml-9 pl-9")}>
122
- <span className="pr-6 text-[0.9rem] leading-[1.45] font-semibold [overflow-wrap:anywhere]" title={session.title}>{session.title}</span>
122
+ <span className="line-clamp-2 pr-6 text-[0.9rem] leading-[1.45] font-semibold [overflow-wrap:anywhere]" title={session.title}>{session.title}</span>
123
123
  <span className="flex min-h-[18px] flex-wrap items-center gap-x-3.5 gap-y-1.5">
124
124
  <span className={cn("flex items-center gap-[7px] text-[0.75rem]", tone.text)}>
125
125
  {session.running ? <Spinner aria-hidden className="size-3" /> : <span aria-hidden className="size-[7px] flex-none rounded-full bg-current" />}
@@ -131,14 +131,15 @@ export function SessionList({
131
131
  </span>
132
132
  </span>
133
133
  {session.locked !== undefined
134
- ? <span className="text-[0.75rem] leading-[1.45] text-destructive [overflow-wrap:anywhere]">{session.locked}</span>
134
+ ? <span className="line-clamp-3 text-[0.75rem] leading-[1.45] text-destructive [overflow-wrap:anywhere]" title={session.locked}>{session.locked}</span>
135
135
  : registry.sessionMetadata.map(({ id, Metadata }) => (
136
136
  <Metadata key={id} placement="list" session={session} />
137
137
  ))}
138
138
  <span className="mt-auto grid gap-0.5 text-muted-foreground">
139
139
  {session.createdAt !== undefined && <span className="text-[0.7rem] tabular-nums">Created <time dateTime={new Date(session.createdAt).toISOString()}>
140
- {new Date(session.createdAt).toLocaleString("en-US", { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" })}
140
+ {new Date(session.createdAt).toLocaleString(undefined, { day: "2-digit", month: "2-digit", year: "numeric", hour: "2-digit", minute: "2-digit" })}
141
141
  </time></span>}
142
+ {session.ownerLabel !== undefined && <span className="text-[0.7rem] [overflow-wrap:anywhere]">Created by {session.ownerLabel}</span>}
142
143
  <span className="text-[0.7rem] tabular-nums">Last activity {formatTimestamp(session.updatedAt)}</span>
143
144
  </span>
144
145
  </button>
@@ -931,10 +931,10 @@ const skillFileText = (file: SettingsSkillFile) =>
931
931
 
932
932
  const formatDuration = (milliseconds: number) => {
933
933
  const seconds = milliseconds / 1000;
934
- if (seconds < 60) return `${seconds.toLocaleString("en-US")} s`;
934
+ if (seconds < 60) return `${seconds.toLocaleString()} s`;
935
935
  const minutes = seconds / 60;
936
- if (minutes < 60) return `${minutes.toLocaleString("en-US")} min`;
937
- return `${(minutes / 60).toLocaleString("en-US")} h`;
936
+ if (minutes < 60) return `${minutes.toLocaleString()} min`;
937
+ return `${(minutes / 60).toLocaleString()} h`;
938
938
  };
939
939
 
940
940
  const sensitiveKey = (key: string) => /secret|token|password|credential|api.?key|authorization|cookie/i.test(key);
@@ -57,7 +57,7 @@ export function FilePicker({ label, files, onChange, disabled, showPreview = tru
57
57
  </div>
58
58
  {error && <p className="mt-2 text-sm text-destructive" role="alert">{error}</p>}
59
59
  {files.length > 0 && <ul className="mt-2 divide-y">{files.map((file, index) => <li className="py-2" key={`${file.name}:${file.size}:${file.lastModified}:${index}`}>
60
- <div className="flex items-start justify-between gap-3"><span className="min-w-0 break-words"><strong>{file.name}</strong> <small className="block text-muted-foreground">{new Intl.NumberFormat("en-US").format(file.size)} bytes</small></span>
60
+ <div className="flex items-start justify-between gap-3"><span className="min-w-0 break-words"><strong>{file.name}</strong> <small className="block text-muted-foreground">{new Intl.NumberFormat().format(file.size)} bytes</small></span>
61
61
  <Button aria-label={`Remove ${file.name}`} disabled={blocked} onClick={() => { void change(() => files.filter((_, position) => position !== index)); }} size="sm" variant="outline">Remove</Button></div>
62
62
  {showPreview && <FilePreview file={file} />}
63
63
  </li>)}</ul>}
@@ -43,6 +43,8 @@ export interface SessionInfo {
43
43
  running?: boolean;
44
44
  /** Whether the viewer can reach the run's workspace; missing as long as the server has not listed the run yet. */
45
45
  workspaceAccessible?: boolean;
46
+ /** Display name of the user who created the run; missing for a run created without sign-in. */
47
+ ownerLabel?: string;
46
48
  metadata?: Readonly<Record<string, unknown>>;
47
49
  /** Why a metadata contribution has no value: failed or did not answer in time. */
48
50
  metadataUnavailable?: Readonly<Record<string, string>>;
@@ -18,7 +18,7 @@ export function groupRunsByActivity(sessions: readonly SessionInfo[], now = new
18
18
  const key = dayKey(date);
19
19
  const group = groups.get(key) ?? {
20
20
  date: key,
21
- label: key === today ? "Today" : key === dayKey(yesterday) ? "Yesterday" : date.toLocaleDateString("en-US", { weekday: "long", day: "numeric", month: "long", ...(date.getFullYear() === now.getFullYear() ? {} : { year: "numeric" }) }),
21
+ label: key === today ? "Today" : key === dayKey(yesterday) ? "Yesterday" : date.toLocaleDateString(undefined, { weekday: "long", day: "numeric", month: "long", ...(date.getFullYear() === now.getFullYear() ? {} : { year: "numeric" }) }),
22
22
  sessions: [],
23
23
  };
24
24
  group.sessions.push(session);
@@ -231,7 +231,7 @@ function RunPanelPage({ connection, initialRunId, registry }: { connection: stri
231
231
  <RunStateIcon className="self-center px-1.5" state={session?.running ? "running" : "idle"} />
232
232
  <StopButton className="self-center" disabled={!writeRuns} label="Stop run" onClick={stop} size="icon-lg" title="Stop the run with all agents and flows" />
233
233
  <div aria-label="Panel tools" className="flex flex-none items-center empty:hidden" ref={setToolsContainer} role="toolbar" />
234
- <RunPanelMenu onOpenSettings={openSettings} />
234
+ <RunPanelMenu onOpenSettings={openSettings} runId={runId} />
235
235
  </header>
236
236
  {stopError && <Alert variant="destructive">{stopError}</Alert>}
237
237
  <main className="relative z-1 flex min-h-0 min-w-0 flex-1 @container/chat-content">
@@ -1,35 +1,71 @@
1
1
  import { useId, useRef, useState } from "react";
2
- import { ExternalLinkIcon, LogOutIcon, MoreVerticalIcon, SettingsIcon } from "lucide-react";
2
+ import { ChevronLeftIcon, ExternalLinkIcon, LogOutIcon, MoreVerticalIcon, PlayIcon, SettingsIcon } from "lucide-react";
3
+ import { coreContracts } from "@ragents/host/api/contracts";
4
+ import type { RunScriptListing } from "../../../server/src/chat-handler";
3
5
  import { useAccess } from "../AccessContext";
6
+ import { rpc } from "../rpc";
4
7
  import { Button, Popover, PopoverContent } from "../ui";
5
8
  import { useRunPanelHost } from "./host";
6
9
 
7
- const itemClass = "flex w-full cursor-pointer items-center gap-2.5 rounded-md px-2 py-1.5 text-left hover:bg-accent focus-visible:outline-2 focus-visible:outline-ring/60 focus-visible:-outline-offset-2 disabled:cursor-default disabled:opacity-50 [&>svg]:size-4 [&>svg]:flex-none [&>svg]:text-muted-foreground";
10
+ const itemClass = "flex w-full cursor-pointer items-center gap-2.5 rounded-md px-2 py-1.5 text-left hover:bg-accent focus-visible:outline-2 focus-visible:outline-ring/60 focus-visible:-outline-offset-2 disabled:cursor-default disabled:opacity-50 disabled:hover:bg-transparent [&>svg]:size-4 [&>svg]:flex-none [&>svg]:text-muted-foreground";
8
11
 
9
- /** The menu at the top right of the panel: settings, server in the browser, and sign-out behind one button. */
10
- export function RunPanelMenu({ onOpenSettings }: { onOpenSettings: () => void }) {
12
+ const messageOf = (cause: unknown): string => cause instanceof Error ? cause.message : String(cause);
13
+
14
+ type Scripts = { readonly kind: "loading" } | { readonly kind: "ready"; readonly scripts: readonly RunScriptListing[] };
15
+
16
+ /** The menu at the top right of the panel: settings, run scripts for the open run, server in the browser, and sign-out behind one button. */
17
+ export function RunPanelMenu({ onOpenSettings, runId }: { onOpenSettings: () => void; runId?: string }) {
11
18
  const host = useRunPanelHost();
12
19
  const access = useAccess();
13
20
  const [open, setOpen] = useState(false);
14
21
  const [pending, setPending] = useState(false);
15
22
  const [error, setError] = useState<string>();
23
+ const [scripts, setScripts] = useState<Scripts>();
16
24
  const buttonRef = useRef<HTMLButtonElement>(null);
17
25
  const panelId = useId();
18
26
  const pressedAnchor = (details: { reason: string; event: Event }) =>
19
27
  details.reason === "outside-press" && details.event.target instanceof Node && buttonRef.current?.contains(details.event.target) === true;
28
+ const close = () => { setOpen(false); setScripts(undefined); setError(undefined); };
20
29
  const logout = () => {
21
30
  if (host.kind === "vscode") { host.requestLogout(); setOpen(false); return; }
22
31
  setPending(true);
23
32
  setError(undefined);
24
- void access.logout().then(() => setOpen(false)).catch((cause: unknown) => setError(cause instanceof Error ? cause.message : String(cause))).finally(() => setPending(false));
33
+ void access.logout().then(() => setOpen(false)).catch((cause: unknown) => setError(messageOf(cause))).finally(() => setPending(false));
34
+ };
35
+ const listScripts = (run: string) => {
36
+ setScripts({ kind: "loading" });
37
+ setError(undefined);
38
+ void rpc.call(coreContracts.runs.scripts, { runId: run }).then((listed) => setScripts({ kind: "ready", scripts: listed }))
39
+ .catch((cause: unknown) => { setScripts({ kind: "ready", scripts: [] }); setError(messageOf(cause)); });
40
+ };
41
+ const startScript = (run: string, entry: string) => {
42
+ setPending(true);
43
+ setError(undefined);
44
+ void rpc.call(coreContracts.runs.startScript, { runId: run, entry, input: null }).then(close)
45
+ .catch((cause: unknown) => setError(messageOf(cause))).finally(() => setPending(false));
25
46
  };
47
+ const scriptRun = runId !== undefined && access.can("runs.write") ? runId : undefined;
26
48
  return <>
27
- <Button aria-controls={open ? panelId : undefined} aria-expanded={open} aria-haspopup="dialog" aria-label="Panel menu" className="self-center" onClick={() => setOpen((value) => !value)} ref={buttonRef} size="icon-lg" title="Menu" variant="ghost"><MoreVerticalIcon /></Button>
28
- <Popover onOpenChange={(next, details) => { if (!next && pressedAnchor(details)) return; setOpen(next); }} open={open}>
29
- <PopoverContent align="end" anchor={buttonRef} aria-label="Panel menu" className="w-[220px] gap-0 p-1 text-[0.8rem]" collisionPadding={8} dim id={panelId} role="dialog" side="bottom">
30
- <button className={itemClass} onClick={() => { setOpen(false); onOpenSettings(); }} type="button"><SettingsIcon />Settings</button>
31
- {host.kind === "vscode" && <button className={itemClass} onClick={() => { setOpen(false); host.openExternal(new URL("/", window.location.href).toString()); }} type="button"><ExternalLinkIcon />Open in browser</button>}
32
- {access.enabled && access.user && <button className={itemClass} disabled={pending} onClick={logout} title={access.user.id} type="button"><LogOutIcon /><span className="grid min-w-0"><span>Sign out</span><span className="truncate text-[0.68rem] text-muted-foreground">{access.user.label}</span></span></button>}
49
+ <Button aria-controls={open ? panelId : undefined} aria-expanded={open} aria-haspopup="dialog" aria-label="Panel menu" className="self-center" onClick={() => (open ? close() : setOpen(true))} ref={buttonRef} size="icon-lg" title="Menu" variant="ghost"><MoreVerticalIcon /></Button>
50
+ <Popover onOpenChange={(next, details) => { if (!next && pressedAnchor(details)) return; if (next) setOpen(true); else close(); }} open={open}>
51
+ <PopoverContent align="end" anchor={buttonRef} aria-label="Panel menu" className="w-[260px] gap-0 p-1 text-[0.8rem]" collisionPadding={8} dim id={panelId} role="dialog" side="bottom">
52
+ {scripts && scriptRun !== undefined ? <>
53
+ <button className={itemClass} onClick={() => { setScripts(undefined); setError(undefined); }} type="button"><ChevronLeftIcon />Run script</button>
54
+ <div aria-label="Run scripts" className="grid max-h-[50vh] overflow-auto border-t border-border-soft pt-1" role="list">
55
+ {scripts.kind === "loading" && <p className="px-2 py-1.5 text-muted-foreground">Loading run scripts ...</p>}
56
+ {scripts.kind === "ready" && scripts.scripts.length === 0 && !error && <p className="px-2 py-1.5 text-muted-foreground">This profile has no run scripts for you.</p>}
57
+ {scripts.kind === "ready" && scripts.scripts.map((script) => <button className={itemClass} disabled={pending || !script.available} key={script.id}
58
+ onClick={() => startScript(scriptRun, script.id)} role="listitem" title={script.reason ?? script.description} type="button">
59
+ <span className="grid min-w-0"><span className="truncate">{script.title}</span>
60
+ <span className="line-clamp-2 text-[0.68rem] text-muted-foreground">{script.available ? script.description : script.reason}</span></span>
61
+ </button>)}
62
+ </div>
63
+ </> : <>
64
+ <button className={itemClass} onClick={() => { close(); onOpenSettings(); }} type="button"><SettingsIcon />Settings</button>
65
+ {scriptRun !== undefined && <button className={itemClass} onClick={() => listScripts(scriptRun)} type="button"><PlayIcon />Run script</button>}
66
+ {host.kind === "vscode" && <button className={itemClass} onClick={() => { close(); host.openExternal(new URL("/", window.location.href).toString()); }} type="button"><ExternalLinkIcon />Open in browser</button>}
67
+ {access.enabled && access.user && <button className={itemClass} disabled={pending} onClick={logout} title={access.user.id} type="button"><LogOutIcon /><span className="grid min-w-0"><span>Sign out</span><span className="truncate text-[0.68rem] text-muted-foreground">{access.user.label}</span></span></button>}
68
+ </>}
33
69
  {error && <p className="px-2 py-1.5 text-[0.72rem] text-destructive" role="alert">{error}</p>}
34
70
  </PopoverContent>
35
71
  </Popover>
@@ -4,7 +4,7 @@ const DAY = 24 * HOUR;
4
4
  const WEEK = 7 * DAY;
5
5
 
6
6
  const date = (at: number, year: boolean): string =>
7
- new Date(at).toLocaleDateString("en-US", year ? { day: "2-digit", month: "2-digit", year: "numeric" } : { day: "2-digit", month: "2-digit" });
7
+ new Date(at).toLocaleDateString(undefined, year ? { day: "2-digit", month: "2-digit", year: "numeric" } : { day: "2-digit", month: "2-digit" });
8
8
 
9
9
  /** The time in the list: now, 5 min, 3 h, 2 d, from seven days on the date. Without "ago", without a special case for yesterday. */
10
10
  export const shortTime = (at: number, now: number = Date.now()): string => {
@@ -23,7 +23,7 @@
23
23
  }
24
24
  },
25
25
  "revision": "b7b04d050f5f4bcb0980880167b8e2cdd3ad533ba07f589dd0de471b9e55c0fd",
26
- "sourceRevision": "d0f96d5406c652a4ed17f8642adfc889bb3be49fc7948f84e0f889ecb910f26e",
26
+ "sourceRevision": "047290b262944aedbbbb4c4a819509c4bc3a7e0df4fa76b38d9e21ebe5626828",
27
27
  "server": "server/index.js",
28
28
  "web": {
29
29
  "entry": "web/index.js",
@@ -18,6 +18,7 @@
18
18
  "handleKey",
19
19
  "holdsUsable",
20
20
  "implement",
21
+ "inheritedGrants",
21
22
  "runCapabilityBindingHash",
22
23
  "runCapabilityContractHash",
23
24
  "schemaComplaints",
@@ -26,6 +27,7 @@
26
27
  "@ragents/host/plugin-support/actor-programs/app-project": [
27
28
  "compileAppBackend",
28
29
  "installServerSdk",
30
+ "packageIdentity",
29
31
  "prepareAppProject",
30
32
  "prepareAppWorkspace",
31
33
  "projectSourceFiles",
@@ -192,8 +194,8 @@
192
194
  ]
193
195
  }
194
196
  },
195
- "revision": "e25685f9ef95c00333e76e28047747da063b0367833419273d936820fbf1078a",
196
- "sourceRevision": "a90150418157ee1b04b3a4c91d1502f32d2e4b7dde1924b63598df7f9ff7360b",
197
+ "revision": "15fc5afb9aac414335069c28989cae4fa95fec8a2937584f8497a42ce01ffaba",
198
+ "sourceRevision": "6abd7c9e82683655c2bf5010641391a3960ccf495729a87ef00ef58cfb07f7af",
197
199
  "server": "server/index.js",
198
200
  "web": {
199
201
  "entry": "web/index.js",