@agimon-ai/po-prompt 0.0.0-alpha.76 → 0.0.0-alpha.78
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/extensions/web.mjs +86 -81
- package/dist/extensions/web.mjs.map +1 -1
- package/package.json +7 -7
package/dist/extensions/web.mjs
CHANGED
|
@@ -421,6 +421,7 @@ function PromptsDialog({ open, prompts, loading, loadError, initialDraft, sessio
|
|
|
421
421
|
/* @__PURE__ */ jsx(DialogHeader, {
|
|
422
422
|
dismissible: true,
|
|
423
423
|
closeLabel: "Close prompts",
|
|
424
|
+
className: "px-6 py-4 sm:px-6",
|
|
424
425
|
children: /* @__PURE__ */ jsxs("div", {
|
|
425
426
|
className: "min-w-0",
|
|
426
427
|
children: [/* @__PURE__ */ jsx(DialogTitle, { children: title }), /* @__PURE__ */ jsx(DialogDescription, {
|
|
@@ -429,92 +430,96 @@ function PromptsDialog({ open, prompts, loading, loadError, initialDraft, sessio
|
|
|
429
430
|
})]
|
|
430
431
|
})
|
|
431
432
|
}),
|
|
432
|
-
/* @__PURE__ */ jsxs(DialogBody, {
|
|
433
|
-
className: "
|
|
434
|
-
"
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
children: [
|
|
442
|
-
"
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
433
|
+
/* @__PURE__ */ jsxs(DialogBody, {
|
|
434
|
+
className: "px-6 py-6 sm:px-6 sm:py-6",
|
|
435
|
+
children: [error === "" ? null : draft || confirmation ? /* @__PURE__ */ jsx("span", {
|
|
436
|
+
className: "text-sm text-po-red",
|
|
437
|
+
"data-testid": "prompts-error",
|
|
438
|
+
children: error
|
|
439
|
+
}) : null, confirmation?.kind === "remove" ? /* @__PURE__ */ jsxs("div", {
|
|
440
|
+
className: "flex flex-col gap-4",
|
|
441
|
+
"data-testid": "prompts-remove-confirmation",
|
|
442
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
443
|
+
className: "text-base leading-relaxed text-po-dim",
|
|
444
|
+
children: [
|
|
445
|
+
"Remove ",
|
|
446
|
+
/* @__PURE__ */ jsxs("strong", {
|
|
447
|
+
className: "text-po-hi",
|
|
448
|
+
children: ["/", confirmation.prompt.name]
|
|
449
|
+
}),
|
|
450
|
+
"? This cannot be undone."
|
|
451
|
+
]
|
|
452
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
453
|
+
className: "flex justify-end gap-2",
|
|
454
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
455
|
+
variant: "outline",
|
|
456
|
+
size: "md",
|
|
457
|
+
disabled: busy,
|
|
458
|
+
onClick: () => setConfirmation(void 0),
|
|
459
|
+
children: "Cancel"
|
|
460
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
461
|
+
variant: "danger",
|
|
462
|
+
size: "md",
|
|
463
|
+
"data-testid": "prompts-remove-confirm",
|
|
464
|
+
disabled: busy,
|
|
465
|
+
onClick: () => void runMutation(() => deleteSavedPrompt(confirmation.prompt.name, sessionId)),
|
|
466
|
+
children: busy ? "Removing…" : "Remove prompt"
|
|
467
|
+
})]
|
|
464
468
|
})]
|
|
465
|
-
})
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
}),
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
469
|
+
}) : confirmation?.kind === "replace" && draft ? /* @__PURE__ */ jsxs("div", {
|
|
470
|
+
className: "flex flex-col gap-4",
|
|
471
|
+
"data-testid": "prompts-replace-confirmation",
|
|
472
|
+
children: [/* @__PURE__ */ jsxs("p", {
|
|
473
|
+
className: "text-base leading-relaxed text-po-dim",
|
|
474
|
+
children: [/* @__PURE__ */ jsxs("strong", {
|
|
475
|
+
className: "text-po-hi",
|
|
476
|
+
children: ["/", confirmation.name]
|
|
477
|
+
}), " already exists. Replace its text with this draft?"]
|
|
478
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
479
|
+
className: "flex justify-end gap-2",
|
|
480
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
481
|
+
variant: "outline",
|
|
482
|
+
size: "md",
|
|
483
|
+
disabled: busy,
|
|
484
|
+
onClick: () => setConfirmation(void 0),
|
|
485
|
+
children: "Go back"
|
|
486
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
487
|
+
variant: "danger",
|
|
488
|
+
size: "md",
|
|
489
|
+
"data-testid": "prompts-replace-confirm",
|
|
490
|
+
disabled: busy,
|
|
491
|
+
onClick: () => void runMutation(() => commitDraft(draft, {
|
|
492
|
+
save: (name, text) => saveSavedPrompt(name, text, sessionId),
|
|
493
|
+
remove: (name) => deleteSavedPrompt(name, sessionId)
|
|
494
|
+
})),
|
|
495
|
+
children: busy ? "Replacing…" : "Replace prompt"
|
|
496
|
+
})]
|
|
493
497
|
})]
|
|
498
|
+
}) : draft ? /* @__PURE__ */ jsx(PromptEditor, {
|
|
499
|
+
draft,
|
|
500
|
+
busy,
|
|
501
|
+
onChange: setDraft,
|
|
502
|
+
onSave: saveDraft,
|
|
503
|
+
onCancel: () => setDraft(void 0)
|
|
504
|
+
}) : /* @__PURE__ */ jsx(PromptPickerList, {
|
|
505
|
+
prompts,
|
|
506
|
+
filter,
|
|
507
|
+
loading,
|
|
508
|
+
busy,
|
|
509
|
+
error: error || loadError,
|
|
510
|
+
onFilterChange: setFilter,
|
|
511
|
+
onSend: send,
|
|
512
|
+
onEdit: (prompt) => setDraft(draftOf(prompt)),
|
|
513
|
+
onDelete: (prompt) => setConfirmation({
|
|
514
|
+
kind: "remove",
|
|
515
|
+
prompt
|
|
516
|
+
}),
|
|
517
|
+
onRetry: () => void onReload()
|
|
494
518
|
})]
|
|
495
|
-
})
|
|
496
|
-
draft,
|
|
497
|
-
busy,
|
|
498
|
-
onChange: setDraft,
|
|
499
|
-
onSave: saveDraft,
|
|
500
|
-
onCancel: () => setDraft(void 0)
|
|
501
|
-
}) : /* @__PURE__ */ jsx(PromptPickerList, {
|
|
502
|
-
prompts,
|
|
503
|
-
filter,
|
|
504
|
-
loading,
|
|
505
|
-
busy,
|
|
506
|
-
error: error || loadError,
|
|
507
|
-
onFilterChange: setFilter,
|
|
508
|
-
onSend: send,
|
|
509
|
-
onEdit: (prompt) => setDraft(draftOf(prompt)),
|
|
510
|
-
onDelete: (prompt) => setConfirmation({
|
|
511
|
-
kind: "remove",
|
|
512
|
-
prompt
|
|
513
|
-
}),
|
|
514
|
-
onRetry: () => void onReload()
|
|
515
|
-
})] }),
|
|
519
|
+
}),
|
|
516
520
|
draft || confirmation ? null : /* @__PURE__ */ jsxs(DialogFooter, {
|
|
517
521
|
variant: "bar",
|
|
522
|
+
className: "px-6 py-4 sm:px-6 sm:py-4",
|
|
518
523
|
children: [/* @__PURE__ */ jsx("span", {
|
|
519
524
|
className: "text-sm text-po-dim",
|
|
520
525
|
children: prompts.length === 0 ? "Build your reusable library" : `${String(prompts.length)} saved`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.mjs","names":["routes","fillPromptsDialog","fillPromptsMenu","actionSave"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/_lib/messagePromptDraft.ts","../../src/extensions/workspaces/sessions/(frontend)/action/save.message.web.ts","../../src/constants/promptsApi.ts","../../src/constants/webPrompts.ts","../../src/types/apiRoutes.ts","../../generated/client.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/promptsApi.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/promptsActions.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptEditor.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptPickerList.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsDialog.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsDialogHost.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/PromptsDialog.overlay.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsComposerMenuItem.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/PromptsMenu.composer-menu.web.tsx","../../generated/web.ts"],"sourcesContent":["import { defineGlobalStore, type UserMessageActionRunContext } from '@agimon-ai/po-core/web';\n\nimport type { DraftState } from './promptsActions';\n\n/**\n * Package-local handoff from anything that asks for the prompt library to the\n * component that owns it.\n *\n * DESIGN PATTERNS:\n * - Neither caller has a React owner: a timeline action runs from the host's\n * menu, and a composer menu entry unmounts the moment the menu closes. Both\n * publish one short-lived request instead of holding dialog state.\n * - One request pipe, not two. A request carrying a draft opens the editor on\n * that text; a request carrying nothing opens the picker. The dialog owner\n * subscribes once and handles both.\n *\n * AVOID:\n * - Persisting drafts or message content in browser storage.\n * - Making the host understand prompt-specific dialog state.\n * - Signalling \"no draft\" with an empty draft: an empty draft is a real state\n * the editor can be in, so it cannot also mean the absence of one.\n */\n\n/** One ask for the prompt library. A absent draft opens the picker rather than the editor. */\nexport interface PromptDialogRequest {\n draft?: DraftState;\n}\n\ntype PromptDialogListener = (request: PromptDialogRequest) => void;\n\nconst promptDialogRequest = defineGlobalStore<PromptDialogRequest | undefined>(undefined);\n\nexport function requestMessagePromptDraft(context: UserMessageActionRunContext): void {\n const draft: DraftState = { name: '', text: context.text, original: '' };\n promptDialogRequest.update(() => ({ draft }));\n}\n\n/** Opens the library with nothing prefilled, as the composer menu entry does. */\nexport function requestPromptDialogOpen(): void {\n promptDialogRequest.update(() => ({}));\n}\n\nexport function subscribePromptDialogRequest(listener: PromptDialogListener): () => void {\n const deliver = (): void => {\n const request = promptDialogRequest.store.state;\n if (!request) return;\n promptDialogRequest.reset();\n listener(request);\n };\n const subscription = promptDialogRequest.store.subscribe(deliver);\n deliver();\n return () => subscription.unsubscribe();\n}\n","import { defineUserMessageAction } from '@agimon-ai/po-core/web';\nimport { BookmarkPlusIcon } from '@agimon-ai/po-web-components';\n\nimport { requestMessagePromptDraft } from '../_lib/messagePromptDraft';\nexport default defineUserMessageAction({\n label: 'Save as prompt',\n icon: BookmarkPlusIcon,\n order: 40,\n run: requestMessagePromptDraft,\n});\n","export const NAME_PARAM = 'name';\nexport const MAX_PROMPT_BYTES = 65_536;\nexport const STATUS = { badRequest: 400, notFound: 404, tooLarge: 413, failed: 500 } as const;\n","export const API_BASE_PATH = 'prompts';\nexport const PROMPTS_PATH = '/prompts';\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/po-core/native';\n\nimport { NAME_PARAM } from '../constants/promptsApi';\nimport { PROMPTS_PATH } from '../constants/webPrompts';\nimport type { SavedPromptListResponse, SavedPromptWriteResponse } from './webPrompts';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path. The build reads both off\n * `src/extensions/(backend)/api/prompts/`, so the mount is stated once, by the\n * folder that creates it. This package stated it three times before: a\n * constant, and the literal `prompts` twice more inside a URL builder that also\n * decided, on its own, whether a call was global or session scoped.\n *\n * The Hono app registers these paths and the browser addresses them, so a path\n * cannot move on one side alone.\n *\n * `:name` is Hono's own parameter syntax, because the app registers `path`\n * verbatim, and the client fills it from `params` on the call.\n */\nexport default defineApiRoutes({\n list: {\n method: 'GET',\n path: PROMPTS_PATH,\n response: apiResponse<SavedPromptListResponse>(),\n },\n save: {\n method: 'PUT',\n path: `${PROMPTS_PATH}/:${NAME_PARAM}`,\n response: apiResponse<SavedPromptWriteResponse>(),\n },\n /** The same path as `save`; the method is the whole of the difference. */\n remove: {\n method: 'DELETE',\n path: `${PROMPTS_PATH}/:${NAME_PARAM}`,\n },\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { createApiClient, sessionApiAddress } from '@agimon-ai/po-core/web';\nimport { browserTransport } from '@agimon-ai/po-web-security/browser';\n\nimport routes from '../src/types/apiRoutes';\n\n/** Scopes the tree mounts 'prompts' at. */\nexport const apiScopes = ['global', 'workspace', 'session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'prompts',\n transport: (input, init) => browserTransport.fetch(input, init),\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client';\nimport { NAME_PARAM } from '../../../../../../constants/promptsApi';\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\n\n/**\n * The browser half of the prompt library API.\n *\n * DESIGN PATTERNS:\n * - The generated client owns every URL and picks the scope, so nothing here\n * spells a mount. Passing a session id selects the session's own copy of the\n * API; passing none addresses the hub, which is the same branch the deleted\n * URL builder made by hand.\n * - Failures come back as values, never thrown: the panel shows one message\n * next to the thing that failed instead of losing the page to an error.\n * - Every call still travels over the sealed transport, which is what the\n * client is built on, so a remote listener gets the protection the host\n * expects either way.\n *\n * AVOID:\n * - Caching answers in this module. The panel owns state.\n */\n\nconst UNREACHABLE = 'The hub did not answer.';\n\ninterface Failure {\n error: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The hub, or one session's own copy of it; a null session id is the hub. */\nfunction scoped(sessionId?: string | null) {\n return sessionId == null ? api.global : api.session(sessionId);\n}\n\n/** The message a reader is shown for a refused call: the route's own words, or the status. */\nfunction messageOf(result: { status: number; error: string }): string {\n return result.error === '' ? `The hub answered ${String(result.status)}.` : result.error;\n}\n\nexport async function fetchSavedPrompts(\n signal?: AbortSignal,\n sessionId?: string | null,\n): Promise<{ prompts: readonly SavedPromptView[] } | Failure> {\n const result = await scoped(sessionId).list(signal ? { signal } : {});\n if (!result.ok) {\n // Status 0 is the transport never answering, which covers both a dead hub\n // and the caller replacing this request. An abort is the caller's own doing\n // and is reported as no answer rather than as a failure to show.\n if (result.status === 0) return { error: signal?.aborted === true ? '' : UNREACHABLE };\n return { error: messageOf(result) };\n }\n if (!isRecord(result.data)) return { error: 'The hub sent a malformed prompt list.' };\n const prompts = result.data.prompts;\n return { prompts: Array.isArray(prompts) ? (prompts as readonly SavedPromptView[]) : [] };\n}\n\nexport async function saveSavedPrompt(\n name: string,\n text: string,\n sessionId?: string | null,\n): Promise<Failure | undefined> {\n const result = await scoped(sessionId).save({ params: { [NAME_PARAM]: name }, body: { text } });\n return result.ok ? undefined : { error: result.status === 0 ? UNREACHABLE : messageOf(result) };\n}\n\nexport async function deleteSavedPrompt(name: string, sessionId?: string | null): Promise<Failure | undefined> {\n const result = await scoped(sessionId).remove({ params: { [NAME_PARAM]: name } });\n return result.ok ? undefined : { error: result.status === 0 ? UNREACHABLE : messageOf(result) };\n}\n","import type { SavedPromptView } from '../../../../../types/webPrompts';\n\n/**\n * What the panel does to the library, independent of how it is drawn.\n *\n * DESIGN PATTERNS:\n * - The API is a parameter, so the ordering rules here are testable without a\n * transport, and the panel keeps only state and markup.\n * - A rename is a write followed by a delete of the old template, never the\n * other way round: a failed write must not lose the original.\n *\n * AVOID:\n * - Reporting success when the cleanup delete failed. The library would then\n * hold two copies and the page would show a state nobody chose.\n */\n\nexport interface DraftState {\n name: string;\n text: string;\n /** The name being replaced, or '' while creating. */\n original: string;\n}\n\nexport interface PromptsMutationApi {\n save(name: string, text: string): Promise<{ error: string } | undefined>;\n remove(name: string): Promise<{ error: string } | undefined>;\n}\n\n/** The frame the cockpit sends to submit a message to a session. */\nexport function promptFrame(text: string): Record<string, unknown> {\n return { type: 'prompt', message: text };\n}\n\n/** Substring matching over the two columns a row shows. */\nexport function filterPrompts(prompts: readonly SavedPromptView[], filter: string): readonly SavedPromptView[] {\n const needle = filter.trim().toLowerCase();\n if (needle === '') return prompts;\n return prompts.filter(\n (prompt) => prompt.name.toLowerCase().includes(needle) || prompt.description.toLowerCase().includes(needle),\n );\n}\n\nexport const EMPTY_DRAFT: DraftState = { name: '', text: '', original: '' };\n\nexport function draftOf(prompt: SavedPromptView): DraftState {\n return { name: prompt.name, text: prompt.text, original: prompt.name };\n}\n\n/** Whether the draft is complete enough to send. */\nexport function canSaveDraft(draft: DraftState): boolean {\n return draft.name.trim().length > 0 && draft.text.trim().length > 0;\n}\n\n/** The template a rename leaves behind, or undefined when nothing was renamed. */\nexport function renamedFrom(draft: DraftState): string | undefined {\n const name = draft.name.trim();\n return draft.original !== '' && draft.original !== name ? draft.original : undefined;\n}\n\n/** Writes the draft, then clears the template a rename orphaned. */\nexport async function commitDraft(draft: DraftState, api: PromptsMutationApi): Promise<{ error: string } | undefined> {\n const name = draft.name.trim();\n const failure = await api.save(name, draft.text);\n if (failure) return failure;\n\n const orphan = renamedFrom(draft);\n if (orphan === undefined) return undefined;\n\n const cleanup = await api.remove(orphan);\n if (cleanup) return { error: `Saved /${name}, but /${orphan} could not be removed: ${cleanup.error}` };\n return undefined;\n}\n\n/** Build once per library revision, keeping the two visible search columns separate. */\nexport function promptSearchIndex(prompts: readonly SavedPromptView[]) {\n return prompts.map((prompt) => ({\n prompt,\n name: prompt.name.toLowerCase(),\n description: prompt.description.toLowerCase(),\n }));\n}\n\nexport function searchPromptIndex(index: ReturnType<typeof promptSearchIndex>, filter: string) {\n const needle = filter.trim().toLowerCase();\n return index\n .filter((entry) => entry.name.includes(needle) || entry.description.includes(needle))\n .map((entry) => entry.prompt);\n}\n","import { Button, Input, Textarea } from '@agimon-ai/po-web-components';\n\nimport { canSaveDraft, type DraftState } from '../../_lib/promptsActions';\n\n/**\n * The create and edit form for one saved prompt.\n *\n * DESIGN PATTERNS:\n * - Presentational: the draft and every action come from props, so the panel\n * owns the state and this file stays a form.\n * - Save stays disabled until the draft could actually be written, which keeps\n * the obvious mistakes off the network without duplicating the server rule.\n *\n * AVOID:\n * - Validating the name shape here. The API owns that rule and reports it.\n */\n\nexport interface PromptEditorProps {\n draft: DraftState;\n busy: boolean;\n onChange: (draft: DraftState) => void;\n onSave: () => void;\n onCancel: () => void;\n}\n\nexport function PromptEditor({ draft, busy, onChange, onSave, onCancel }: PromptEditorProps) {\n const editing = draft.original !== '';\n return (\n <div data-testid=\"prompts-editor\" className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"prompts-name\" className=\"text-base font-medium text-po-text\">\n Prompt name\n </label>\n <Input\n id=\"prompts-name\"\n data-testid=\"prompts-name\"\n className=\"w-full\"\n value={draft.name}\n placeholder=\"Lowercase letters, digits and dashes\"\n autoComplete=\"off\"\n autoFocus\n onChange={(event) => onChange({ ...draft, name: event.target.value })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"prompts-text\" className=\"text-base font-medium text-po-text\">\n Prompt text\n </label>\n <Textarea\n id=\"prompts-text\"\n data-testid=\"prompts-text\"\n className=\"w-full\"\n rows={8}\n value={draft.text}\n placeholder=\"What Po should do when you send it\"\n onChange={(event) => onChange({ ...draft, text: event.target.value })}\n />\n </div>\n <div className=\"flex items-center justify-end gap-2\">\n <Button variant=\"outline\" size=\"md\" data-testid=\"prompts-cancel\" disabled={busy} onClick={onCancel}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n size=\"md\"\n data-testid=\"prompts-save\"\n disabled={busy || !canSaveDraft(draft)}\n onClick={onSave}\n >\n {busy ? 'Saving…' : editing ? 'Save changes' : 'Save prompt'}\n </Button>\n </div>\n </div>\n );\n}\n","import { Button, Input } from '@agimon-ai/po-web-components';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport { filterPrompts } from '../../_lib/promptsActions';\n\n/**\n * The list-first body of the prompt dialog.\n *\n * DESIGN PATTERNS:\n * - Sending is the row's large primary target; management actions stay visible.\n * - Rows are separated by hairlines, not boxed, so the list reads as one quiet\n * column and the mono slash name reads as the command it also is.\n * - Loading, failure and empty states occupy the list instead of looking like a\n * successfully loaded empty library.\n *\n * AVOID:\n * - Fetching or mutating here. The dialog owns behavior, this owns markup.\n */\n\nexport interface PromptPickerListProps {\n prompts: readonly SavedPromptView[];\n filter: string;\n loading: boolean;\n busy: boolean;\n error: string;\n onFilterChange: (filter: string) => void;\n onSend: (prompt: SavedPromptView) => void;\n onEdit: (prompt: SavedPromptView) => void;\n onDelete: (prompt: SavedPromptView) => void;\n onRetry: () => void;\n}\n\nexport function PromptPickerList(props: PromptPickerListProps) {\n const visible = filterPrompts(props.prompts, props.filter);\n\n return (\n <div data-testid=\"prompts-picker\" className=\"flex flex-col gap-3\">\n <Input\n data-testid=\"prompts-filter\"\n value={props.filter}\n placeholder=\"Filter prompts\"\n aria-label=\"Filter prompts\"\n onChange={(event) => props.onFilterChange(event.target.value)}\n />\n\n {props.loading ? (\n <p data-testid=\"prompts-loading\" className=\"py-6 text-center text-sm text-po-dim\">\n Loading prompts…\n </p>\n ) : props.error !== '' ? (\n <div className=\"flex items-center justify-between gap-3 rounded-md border border-po-red/40 p-3\">\n <span className=\"text-sm text-po-red\" data-testid=\"prompts-error\">\n {props.error}\n </span>\n <Button variant=\"outline\" size=\"sm\" data-testid=\"prompts-retry\" onClick={props.onRetry}>\n Retry\n </Button>\n </div>\n ) : visible.length === 0 ? (\n <p data-testid=\"prompts-empty\" className=\"py-6 text-center text-sm text-po-dim\">\n {props.prompts.length === 0\n ? 'No saved prompts yet. New prompt saves one for later.'\n : 'Nothing matches that filter'}\n </p>\n ) : null}\n\n {props.loading || props.error !== '' || visible.length === 0 ? null : (\n <ul className=\"flex flex-col divide-y divide-po-border-soft border-y border-po-border-soft\">\n {visible.map((prompt) => (\n <li\n key={prompt.name}\n data-testid={`prompts-item-${prompt.name}`}\n className=\"flex min-h-11 items-center gap-1 py-1 text-po-text\"\n >\n <Button\n variant=\"ghost\"\n size=\"md\"\n className=\"h-auto min-w-0 flex-1 flex-col items-start justify-center gap-0.5 px-2 py-1.5 text-left\"\n data-testid={`prompts-send-${prompt.name}`}\n title=\"Send this prompt to the focused session\"\n onClick={() => props.onSend(prompt)}\n >\n <span className=\"w-full truncate font-mono text-base font-semibold text-po-hi\">/{prompt.name}</span>\n <span className=\"w-full truncate text-sm font-normal text-po-dim\">{prompt.description}</span>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n data-testid={`prompts-edit-${prompt.name}`}\n aria-label={`Edit /${prompt.name}`}\n onClick={() => props.onEdit(prompt)}\n >\n Edit\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n data-testid={`prompts-delete-${prompt.name}`}\n aria-label={`Remove /${prompt.name}`}\n disabled={props.busy}\n onClick={() => props.onDelete(prompt)}\n >\n Remove\n </Button>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n","import type { SessionFrameSender } from '@agimon-ai/po-core/web';\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@agimon-ai/po-web-components';\nimport { useEffect, useState } from 'react';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport { commitDraft, type DraftState, draftOf, EMPTY_DRAFT, promptFrame } from '../../_lib/promptsActions';\nimport { deleteSavedPrompt, saveSavedPrompt } from '../_lib/promptsApi';\nimport { PromptEditor } from './PromptEditor';\nimport { PromptPickerList } from './PromptPickerList';\n\n/**\n * The prompt picker, opened from the activity dock.\n *\n * DESIGN PATTERNS:\n * - Picking sends. A saved prompt is a message the reader already wrote, so the\n * primary action submits it to the focused session and closes the dialog.\n * - Managing is secondary and lives in the same dialog, because a library with\n * no way to fix an entry is a library nobody trusts.\n * - This file is chrome and state; the rows are PromptPickerList.\n *\n * AVOID:\n * - Sending with no session focused. There would be nowhere for it to land.\n */\n\nconst NO_SESSION = 'Focus a session first: a prompt has to be sent somewhere.';\n\nexport interface PromptsDialogProps {\n open: boolean;\n prompts: readonly SavedPromptView[];\n loading: boolean;\n loadError: string;\n initialDraft?: DraftState;\n sessionId: string | null;\n onOpenChange: (open: boolean) => void;\n onReload: () => Promise<void>;\n onSend: SessionFrameSender;\n}\n\ntype Confirmation = { kind: 'remove'; prompt: SavedPromptView } | { kind: 'replace'; name: string };\n\nexport function PromptsDialog({\n open,\n prompts,\n loading,\n loadError,\n initialDraft,\n sessionId,\n onOpenChange,\n onReload,\n onSend,\n}: PromptsDialogProps) {\n const [filter, setFilter] = useState('');\n const [draft, setDraft] = useState<DraftState | undefined>(initialDraft);\n const [confirmation, setConfirmation] = useState<Confirmation | undefined>(undefined);\n const [error, setError] = useState('');\n\n useEffect(() => {\n if (open && initialDraft) setDraft(initialDraft);\n }, [initialDraft, open]);\n const [busy, setBusy] = useState(false);\n\n const resetView = (): void => {\n setFilter('');\n setDraft(undefined);\n setConfirmation(undefined);\n setError('');\n };\n\n const changeOpen = (next: boolean): void => {\n if (!next) resetView();\n onOpenChange(next);\n };\n\n const send = (prompt: SavedPromptView): void => {\n if (sessionId === null) {\n setError(NO_SESSION);\n return;\n }\n onSend(sessionId, promptFrame(prompt.text));\n changeOpen(false);\n };\n\n const runMutation = async (mutation: () => Promise<{ error: string } | undefined>): Promise<void> => {\n setBusy(true);\n setError('');\n const failure = await mutation();\n if (failure) {\n setBusy(false);\n setError(failure.error);\n return;\n }\n await onReload();\n setBusy(false);\n setDraft(undefined);\n setConfirmation(undefined);\n };\n\n const saveDraft = (): void => {\n if (!draft) return;\n const name = draft.name.trim();\n const replacesAnother = prompts.some((prompt) => prompt.name === name && prompt.name !== draft.original);\n if (replacesAnother) {\n setConfirmation({ kind: 'replace', name });\n return;\n }\n void runMutation(() =>\n commitDraft(draft, {\n save: (nextName, text) => saveSavedPrompt(nextName, text, sessionId),\n remove: (previousName) => deleteSavedPrompt(previousName, sessionId),\n }),\n );\n };\n\n const title =\n confirmation?.kind === 'remove'\n ? 'Remove prompt'\n : confirmation?.kind === 'replace'\n ? 'Replace prompt'\n : draft\n ? draft.original === ''\n ? 'New prompt'\n : 'Edit prompt'\n : 'Prompts';\n const description = confirmation\n ? 'Manage your saved prompt library'\n : draft\n ? draft.original === ''\n ? 'Save a message you send often'\n : 'Make this prompt work your way'\n : 'Choose a prompt to send it now';\n\n return (\n <Dialog open={open} onOpenChange={changeOpen}>\n <DialogContent\n data-testid=\"prompts-dialog\"\n onOpenAutoFocus={(event) => {\n if (!initialDraft) event.preventDefault();\n }}\n aria-describedby=\"prompts-dialog-description\"\n >\n <DialogHeader dismissible closeLabel=\"Close prompts\">\n <div className=\"min-w-0\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription id=\"prompts-dialog-description\">{description}</DialogDescription>\n </div>\n </DialogHeader>\n\n <DialogBody>\n {error === '' ? null : draft || confirmation ? (\n <span className=\"text-sm text-po-red\" data-testid=\"prompts-error\">\n {error}\n </span>\n ) : null}\n\n {confirmation?.kind === 'remove' ? (\n <div className=\"flex flex-col gap-4\" data-testid=\"prompts-remove-confirmation\">\n <p className=\"text-base leading-relaxed text-po-dim\">\n Remove <strong className=\"text-po-hi\">/{confirmation.prompt.name}</strong>? This cannot be undone.\n </p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" size=\"md\" disabled={busy} onClick={() => setConfirmation(undefined)}>\n Cancel\n </Button>\n <Button\n variant=\"danger\"\n size=\"md\"\n data-testid=\"prompts-remove-confirm\"\n disabled={busy}\n onClick={() => void runMutation(() => deleteSavedPrompt(confirmation.prompt.name, sessionId))}\n >\n {busy ? 'Removing…' : 'Remove prompt'}\n </Button>\n </div>\n </div>\n ) : confirmation?.kind === 'replace' && draft ? (\n <div className=\"flex flex-col gap-4\" data-testid=\"prompts-replace-confirmation\">\n <p className=\"text-base leading-relaxed text-po-dim\">\n <strong className=\"text-po-hi\">/{confirmation.name}</strong> already exists. Replace its text with this\n draft?\n </p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" size=\"md\" disabled={busy} onClick={() => setConfirmation(undefined)}>\n Go back\n </Button>\n <Button\n variant=\"danger\"\n size=\"md\"\n data-testid=\"prompts-replace-confirm\"\n disabled={busy}\n onClick={() =>\n void runMutation(() =>\n commitDraft(draft, {\n save: (name, text) => saveSavedPrompt(name, text, sessionId),\n remove: (name) => deleteSavedPrompt(name, sessionId),\n }),\n )\n }\n >\n {busy ? 'Replacing…' : 'Replace prompt'}\n </Button>\n </div>\n </div>\n ) : draft ? (\n <PromptEditor\n draft={draft}\n busy={busy}\n onChange={setDraft}\n onSave={saveDraft}\n onCancel={() => setDraft(undefined)}\n />\n ) : (\n <PromptPickerList\n prompts={prompts}\n filter={filter}\n loading={loading}\n busy={busy}\n error={error || loadError}\n onFilterChange={setFilter}\n onSend={send}\n onEdit={(prompt) => setDraft(draftOf(prompt))}\n onDelete={(prompt) => setConfirmation({ kind: 'remove', prompt })}\n onRetry={() => void onReload()}\n />\n )}\n </DialogBody>\n\n {draft || confirmation ? null : (\n <DialogFooter variant=\"bar\">\n <span className=\"text-sm text-po-dim\">\n {prompts.length === 0 ? 'Build your reusable library' : `${String(prompts.length)} saved`}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n data-testid=\"prompts-new\"\n disabled={busy}\n onClick={() => setDraft(EMPTY_DRAFT)}\n >\n New prompt\n </Button>\n </DialogFooter>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/web';\nimport { useCallback, useEffect, useState } from 'react';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport { subscribePromptDialogRequest } from '../../_lib/messagePromptDraft';\nimport type { DraftState } from '../../_lib/promptsActions';\nimport { fetchSavedPrompts } from '../_lib/promptsApi';\nimport { PromptsDialog } from './PromptsDialog';\n\n/**\n * The prompt library's dialog and the state behind it.\n *\n * DESIGN PATTERNS:\n * - This fills an overlay, which the host keeps mounted for the whole page.\n * The two ways in are both transient (a timeline action has no component at\n * all, a composer menu entry unmounts when the menu closes), so the state\n * they open has to live somewhere neither of them owns.\n * - Every way in arrives as one request on the package's own store, so this\n * component has a single opening path rather than one per caller.\n * - The library loads on mount, again on open, and after every mutation so the\n * visible list is never an aborted or stale snapshot.\n *\n * AVOID:\n * - Rendering anything while the dialog is closed. This sits in an overlay\n * over the whole cockpit.\n * - Holding this state in the menu entry. It would be discarded on every close.\n */\n\nexport function PromptsDialogHost({ sessionId, sendSessionFrame }: WebPluginSlotProps) {\n const [prompts, setPrompts] = useState<readonly SavedPromptView[]>([]);\n const [open, setOpen] = useState(false);\n const [initialDraft, setInitialDraft] = useState<DraftState | undefined>(undefined);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(true);\n\n const loadPrompts = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n setLoading(true);\n const result = await fetchSavedPrompts(signal, sessionId);\n if (signal?.aborted) return;\n if ('error' in result) setError(result.error);\n else {\n setError('');\n setPrompts(result.prompts);\n }\n setLoading(false);\n },\n [sessionId],\n );\n\n useEffect(() => {\n const controller = new AbortController();\n void loadPrompts(controller.signal);\n return () => controller.abort();\n }, [loadPrompts, open]);\n\n useEffect(\n () =>\n subscribePromptDialogRequest((request) => {\n setInitialDraft(request.draft);\n setOpen(true);\n }),\n [],\n );\n\n const changeOpen = (next: boolean): void => {\n if (!next) setInitialDraft(undefined);\n setOpen(next);\n };\n\n return (\n <PromptsDialog\n open={open}\n prompts={prompts}\n loading={loading}\n loadError={error}\n initialDraft={initialDraft}\n sessionId={sessionId}\n onOpenChange={changeOpen}\n onReload={loadPrompts}\n onSend={sendSessionFrame}\n />\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/web';\n\nimport { PromptsDialogHost } from './_components/PromptsDialogHost';\nexport default defineFill({ component: PromptsDialogHost });\n","import { BookmarkPlusIcon, OptionLabel, OptionRow } from '@agimon-ai/po-web-components';\n\nimport { requestPromptDialogOpen } from '../../_lib/messagePromptDraft';\n\n/**\n * The library's entry in the composer's '+' menu.\n *\n * DESIGN PATTERNS:\n * - Stateless on purpose. The menu unmounts this on every close, so it owns\n * the click and nothing else; the dialog and its state live in the overlay.\n * - role=\"menuitem\" overrides OptionRow's listbox default, because this row\n * sits in a menu rather than in a list of choices over one field.\n *\n * AVOID:\n * - Holding dialog state, loading prompts, or subscribing to anything here.\n */\n\nexport function PromptsComposerMenuItem() {\n return (\n <OptionRow\n role=\"menuitem\"\n density=\"compact\"\n data-testid=\"composer-menu-prompts\"\n className=\"w-full text-po-text hover:bg-po-tint-blue\"\n onClick={requestPromptDialogOpen}\n >\n <BookmarkPlusIcon className=\"h-3 w-3 shrink-0\" />\n <OptionLabel density=\"compact\">Prompt template</OptionLabel>\n </OptionRow>\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/web';\n\nimport { PromptsComposerMenuItem } from './_components/PromptsComposerMenuItem';\nexport default defineFill({ component: PromptsComposerMenuItem });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/po-core/web';\n\nimport actionSave from '../src/extensions/workspaces/sessions/(frontend)/action/save.message.web';\nimport fillPromptsDialog from '../src/extensions/workspaces/sessions/(frontend)/fill/PromptsDialog.overlay.web';\nimport fillPromptsMenu from '../src/extensions/workspaces/sessions/(frontend)/fill/PromptsMenu.composer-menu.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'prompts',\n session: {\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'overlay', id: 'prompts-dialog' }, fillPromptsDialog), via({ slot: 'composer-menu', id: 'prompts-menu' }, fillPromptsMenu)]; },\n get userMessageActions(): WebPluginContributions['userMessageActions'] { return [via({ id: 'save' }, actionSave)]; },\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"web.mjs","names":["routes","fillPromptsDialog","fillPromptsMenu","actionSave"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/_lib/messagePromptDraft.ts","../../src/extensions/workspaces/sessions/(frontend)/action/save.message.web.ts","../../src/constants/promptsApi.ts","../../src/constants/webPrompts.ts","../../src/types/apiRoutes.ts","../../generated/client.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/promptsApi.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/promptsActions.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptEditor.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptPickerList.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsDialog.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsDialogHost.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/PromptsDialog.overlay.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsComposerMenuItem.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/PromptsMenu.composer-menu.web.tsx","../../generated/web.ts"],"sourcesContent":["import { defineGlobalStore, type UserMessageActionRunContext } from '@agimon-ai/po-core/web';\n\nimport type { DraftState } from './promptsActions';\n\n/**\n * Package-local handoff from anything that asks for the prompt library to the\n * component that owns it.\n *\n * DESIGN PATTERNS:\n * - Neither caller has a React owner: a timeline action runs from the host's\n * menu, and a composer menu entry unmounts the moment the menu closes. Both\n * publish one short-lived request instead of holding dialog state.\n * - One request pipe, not two. A request carrying a draft opens the editor on\n * that text; a request carrying nothing opens the picker. The dialog owner\n * subscribes once and handles both.\n *\n * AVOID:\n * - Persisting drafts or message content in browser storage.\n * - Making the host understand prompt-specific dialog state.\n * - Signalling \"no draft\" with an empty draft: an empty draft is a real state\n * the editor can be in, so it cannot also mean the absence of one.\n */\n\n/** One ask for the prompt library. A absent draft opens the picker rather than the editor. */\nexport interface PromptDialogRequest {\n draft?: DraftState;\n}\n\ntype PromptDialogListener = (request: PromptDialogRequest) => void;\n\nconst promptDialogRequest = defineGlobalStore<PromptDialogRequest | undefined>(undefined);\n\nexport function requestMessagePromptDraft(context: UserMessageActionRunContext): void {\n const draft: DraftState = { name: '', text: context.text, original: '' };\n promptDialogRequest.update(() => ({ draft }));\n}\n\n/** Opens the library with nothing prefilled, as the composer menu entry does. */\nexport function requestPromptDialogOpen(): void {\n promptDialogRequest.update(() => ({}));\n}\n\nexport function subscribePromptDialogRequest(listener: PromptDialogListener): () => void {\n const deliver = (): void => {\n const request = promptDialogRequest.store.state;\n if (!request) return;\n promptDialogRequest.reset();\n listener(request);\n };\n const subscription = promptDialogRequest.store.subscribe(deliver);\n deliver();\n return () => subscription.unsubscribe();\n}\n","import { defineUserMessageAction } from '@agimon-ai/po-core/web';\nimport { BookmarkPlusIcon } from '@agimon-ai/po-web-components';\n\nimport { requestMessagePromptDraft } from '../_lib/messagePromptDraft';\nexport default defineUserMessageAction({\n label: 'Save as prompt',\n icon: BookmarkPlusIcon,\n order: 40,\n run: requestMessagePromptDraft,\n});\n","export const NAME_PARAM = 'name';\nexport const MAX_PROMPT_BYTES = 65_536;\nexport const STATUS = { badRequest: 400, notFound: 404, tooLarge: 413, failed: 500 } as const;\n","export const API_BASE_PATH = 'prompts';\nexport const PROMPTS_PATH = '/prompts';\n","import { apiResponse, defineApiRoutes } from '@agimon-ai/po-core/native';\n\nimport { NAME_PARAM } from '../constants/promptsApi';\nimport { PROMPTS_PATH } from '../constants/webPrompts';\nimport type { SavedPromptListResponse, SavedPromptWriteResponse } from './webPrompts';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path. The build reads both off\n * `src/extensions/(backend)/api/prompts/`, so the mount is stated once, by the\n * folder that creates it. This package stated it three times before: a\n * constant, and the literal `prompts` twice more inside a URL builder that also\n * decided, on its own, whether a call was global or session scoped.\n *\n * The Hono app registers these paths and the browser addresses them, so a path\n * cannot move on one side alone.\n *\n * `:name` is Hono's own parameter syntax, because the app registers `path`\n * verbatim, and the client fills it from `params` on the call.\n */\nexport default defineApiRoutes({\n list: {\n method: 'GET',\n path: PROMPTS_PATH,\n response: apiResponse<SavedPromptListResponse>(),\n },\n save: {\n method: 'PUT',\n path: `${PROMPTS_PATH}/:${NAME_PARAM}`,\n response: apiResponse<SavedPromptWriteResponse>(),\n },\n /** The same path as `save`; the method is the whole of the difference. */\n remove: {\n method: 'DELETE',\n path: `${PROMPTS_PATH}/:${NAME_PARAM}`,\n },\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { createApiClient, sessionApiAddress } from '@agimon-ai/po-core/web';\nimport { browserTransport } from '@agimon-ai/po-web-security/browser';\n\nimport routes from '../src/types/apiRoutes';\n\n/** Scopes the tree mounts 'prompts' at. */\nexport const apiScopes = ['global', 'workspace', 'session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'prompts',\n transport: (input, init) => browserTransport.fetch(input, init),\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client';\nimport { NAME_PARAM } from '../../../../../../constants/promptsApi';\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\n\n/**\n * The browser half of the prompt library API.\n *\n * DESIGN PATTERNS:\n * - The generated client owns every URL and picks the scope, so nothing here\n * spells a mount. Passing a session id selects the session's own copy of the\n * API; passing none addresses the hub, which is the same branch the deleted\n * URL builder made by hand.\n * - Failures come back as values, never thrown: the panel shows one message\n * next to the thing that failed instead of losing the page to an error.\n * - Every call still travels over the sealed transport, which is what the\n * client is built on, so a remote listener gets the protection the host\n * expects either way.\n *\n * AVOID:\n * - Caching answers in this module. The panel owns state.\n */\n\nconst UNREACHABLE = 'The hub did not answer.';\n\ninterface Failure {\n error: string;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The hub, or one session's own copy of it; a null session id is the hub. */\nfunction scoped(sessionId?: string | null) {\n return sessionId == null ? api.global : api.session(sessionId);\n}\n\n/** The message a reader is shown for a refused call: the route's own words, or the status. */\nfunction messageOf(result: { status: number; error: string }): string {\n return result.error === '' ? `The hub answered ${String(result.status)}.` : result.error;\n}\n\nexport async function fetchSavedPrompts(\n signal?: AbortSignal,\n sessionId?: string | null,\n): Promise<{ prompts: readonly SavedPromptView[] } | Failure> {\n const result = await scoped(sessionId).list(signal ? { signal } : {});\n if (!result.ok) {\n // Status 0 is the transport never answering, which covers both a dead hub\n // and the caller replacing this request. An abort is the caller's own doing\n // and is reported as no answer rather than as a failure to show.\n if (result.status === 0) return { error: signal?.aborted === true ? '' : UNREACHABLE };\n return { error: messageOf(result) };\n }\n if (!isRecord(result.data)) return { error: 'The hub sent a malformed prompt list.' };\n const prompts = result.data.prompts;\n return { prompts: Array.isArray(prompts) ? (prompts as readonly SavedPromptView[]) : [] };\n}\n\nexport async function saveSavedPrompt(\n name: string,\n text: string,\n sessionId?: string | null,\n): Promise<Failure | undefined> {\n const result = await scoped(sessionId).save({ params: { [NAME_PARAM]: name }, body: { text } });\n return result.ok ? undefined : { error: result.status === 0 ? UNREACHABLE : messageOf(result) };\n}\n\nexport async function deleteSavedPrompt(name: string, sessionId?: string | null): Promise<Failure | undefined> {\n const result = await scoped(sessionId).remove({ params: { [NAME_PARAM]: name } });\n return result.ok ? undefined : { error: result.status === 0 ? UNREACHABLE : messageOf(result) };\n}\n","import type { SavedPromptView } from '../../../../../types/webPrompts';\n\n/**\n * What the panel does to the library, independent of how it is drawn.\n *\n * DESIGN PATTERNS:\n * - The API is a parameter, so the ordering rules here are testable without a\n * transport, and the panel keeps only state and markup.\n * - A rename is a write followed by a delete of the old template, never the\n * other way round: a failed write must not lose the original.\n *\n * AVOID:\n * - Reporting success when the cleanup delete failed. The library would then\n * hold two copies and the page would show a state nobody chose.\n */\n\nexport interface DraftState {\n name: string;\n text: string;\n /** The name being replaced, or '' while creating. */\n original: string;\n}\n\nexport interface PromptsMutationApi {\n save(name: string, text: string): Promise<{ error: string } | undefined>;\n remove(name: string): Promise<{ error: string } | undefined>;\n}\n\n/** The frame the cockpit sends to submit a message to a session. */\nexport function promptFrame(text: string): Record<string, unknown> {\n return { type: 'prompt', message: text };\n}\n\n/** Substring matching over the two columns a row shows. */\nexport function filterPrompts(prompts: readonly SavedPromptView[], filter: string): readonly SavedPromptView[] {\n const needle = filter.trim().toLowerCase();\n if (needle === '') return prompts;\n return prompts.filter(\n (prompt) => prompt.name.toLowerCase().includes(needle) || prompt.description.toLowerCase().includes(needle),\n );\n}\n\nexport const EMPTY_DRAFT: DraftState = { name: '', text: '', original: '' };\n\nexport function draftOf(prompt: SavedPromptView): DraftState {\n return { name: prompt.name, text: prompt.text, original: prompt.name };\n}\n\n/** Whether the draft is complete enough to send. */\nexport function canSaveDraft(draft: DraftState): boolean {\n return draft.name.trim().length > 0 && draft.text.trim().length > 0;\n}\n\n/** The template a rename leaves behind, or undefined when nothing was renamed. */\nexport function renamedFrom(draft: DraftState): string | undefined {\n const name = draft.name.trim();\n return draft.original !== '' && draft.original !== name ? draft.original : undefined;\n}\n\n/** Writes the draft, then clears the template a rename orphaned. */\nexport async function commitDraft(draft: DraftState, api: PromptsMutationApi): Promise<{ error: string } | undefined> {\n const name = draft.name.trim();\n const failure = await api.save(name, draft.text);\n if (failure) return failure;\n\n const orphan = renamedFrom(draft);\n if (orphan === undefined) return undefined;\n\n const cleanup = await api.remove(orphan);\n if (cleanup) return { error: `Saved /${name}, but /${orphan} could not be removed: ${cleanup.error}` };\n return undefined;\n}\n\n/** Build once per library revision, keeping the two visible search columns separate. */\nexport function promptSearchIndex(prompts: readonly SavedPromptView[]) {\n return prompts.map((prompt) => ({\n prompt,\n name: prompt.name.toLowerCase(),\n description: prompt.description.toLowerCase(),\n }));\n}\n\nexport function searchPromptIndex(index: ReturnType<typeof promptSearchIndex>, filter: string) {\n const needle = filter.trim().toLowerCase();\n return index\n .filter((entry) => entry.name.includes(needle) || entry.description.includes(needle))\n .map((entry) => entry.prompt);\n}\n","import { Button, Input, Textarea } from '@agimon-ai/po-web-components';\n\nimport { canSaveDraft, type DraftState } from '../../_lib/promptsActions';\n\n/**\n * The create and edit form for one saved prompt.\n *\n * DESIGN PATTERNS:\n * - Presentational: the draft and every action come from props, so the panel\n * owns the state and this file stays a form.\n * - Save stays disabled until the draft could actually be written, which keeps\n * the obvious mistakes off the network without duplicating the server rule.\n *\n * AVOID:\n * - Validating the name shape here. The API owns that rule and reports it.\n */\n\nexport interface PromptEditorProps {\n draft: DraftState;\n busy: boolean;\n onChange: (draft: DraftState) => void;\n onSave: () => void;\n onCancel: () => void;\n}\n\nexport function PromptEditor({ draft, busy, onChange, onSave, onCancel }: PromptEditorProps) {\n const editing = draft.original !== '';\n return (\n <div data-testid=\"prompts-editor\" className=\"flex flex-col gap-4\">\n <div className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"prompts-name\" className=\"text-base font-medium text-po-text\">\n Prompt name\n </label>\n <Input\n id=\"prompts-name\"\n data-testid=\"prompts-name\"\n className=\"w-full\"\n value={draft.name}\n placeholder=\"Lowercase letters, digits and dashes\"\n autoComplete=\"off\"\n autoFocus\n onChange={(event) => onChange({ ...draft, name: event.target.value })}\n />\n </div>\n <div className=\"flex flex-col gap-1.5\">\n <label htmlFor=\"prompts-text\" className=\"text-base font-medium text-po-text\">\n Prompt text\n </label>\n <Textarea\n id=\"prompts-text\"\n data-testid=\"prompts-text\"\n className=\"w-full\"\n rows={8}\n value={draft.text}\n placeholder=\"What Po should do when you send it\"\n onChange={(event) => onChange({ ...draft, text: event.target.value })}\n />\n </div>\n <div className=\"flex items-center justify-end gap-2\">\n <Button variant=\"outline\" size=\"md\" data-testid=\"prompts-cancel\" disabled={busy} onClick={onCancel}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n size=\"md\"\n data-testid=\"prompts-save\"\n disabled={busy || !canSaveDraft(draft)}\n onClick={onSave}\n >\n {busy ? 'Saving…' : editing ? 'Save changes' : 'Save prompt'}\n </Button>\n </div>\n </div>\n );\n}\n","import { Button, Input } from '@agimon-ai/po-web-components';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport { filterPrompts } from '../../_lib/promptsActions';\n\n/**\n * The list-first body of the prompt dialog.\n *\n * DESIGN PATTERNS:\n * - Sending is the row's large primary target; management actions stay visible.\n * - Rows are separated by hairlines, not boxed, so the list reads as one quiet\n * column and the mono slash name reads as the command it also is.\n * - Loading, failure and empty states occupy the list instead of looking like a\n * successfully loaded empty library.\n *\n * AVOID:\n * - Fetching or mutating here. The dialog owns behavior, this owns markup.\n */\n\nexport interface PromptPickerListProps {\n prompts: readonly SavedPromptView[];\n filter: string;\n loading: boolean;\n busy: boolean;\n error: string;\n onFilterChange: (filter: string) => void;\n onSend: (prompt: SavedPromptView) => void;\n onEdit: (prompt: SavedPromptView) => void;\n onDelete: (prompt: SavedPromptView) => void;\n onRetry: () => void;\n}\n\nexport function PromptPickerList(props: PromptPickerListProps) {\n const visible = filterPrompts(props.prompts, props.filter);\n\n return (\n <div data-testid=\"prompts-picker\" className=\"flex flex-col gap-3\">\n <Input\n data-testid=\"prompts-filter\"\n value={props.filter}\n placeholder=\"Filter prompts\"\n aria-label=\"Filter prompts\"\n onChange={(event) => props.onFilterChange(event.target.value)}\n />\n\n {props.loading ? (\n <p data-testid=\"prompts-loading\" className=\"py-6 text-center text-sm text-po-dim\">\n Loading prompts…\n </p>\n ) : props.error !== '' ? (\n <div className=\"flex items-center justify-between gap-3 rounded-md border border-po-red/40 p-3\">\n <span className=\"text-sm text-po-red\" data-testid=\"prompts-error\">\n {props.error}\n </span>\n <Button variant=\"outline\" size=\"sm\" data-testid=\"prompts-retry\" onClick={props.onRetry}>\n Retry\n </Button>\n </div>\n ) : visible.length === 0 ? (\n <p data-testid=\"prompts-empty\" className=\"py-6 text-center text-sm text-po-dim\">\n {props.prompts.length === 0\n ? 'No saved prompts yet. New prompt saves one for later.'\n : 'Nothing matches that filter'}\n </p>\n ) : null}\n\n {props.loading || props.error !== '' || visible.length === 0 ? null : (\n <ul className=\"flex flex-col divide-y divide-po-border-soft border-y border-po-border-soft\">\n {visible.map((prompt) => (\n <li\n key={prompt.name}\n data-testid={`prompts-item-${prompt.name}`}\n className=\"flex min-h-11 items-center gap-1 py-1 text-po-text\"\n >\n <Button\n variant=\"ghost\"\n size=\"md\"\n className=\"h-auto min-w-0 flex-1 flex-col items-start justify-center gap-0.5 px-2 py-1.5 text-left\"\n data-testid={`prompts-send-${prompt.name}`}\n title=\"Send this prompt to the focused session\"\n onClick={() => props.onSend(prompt)}\n >\n <span className=\"w-full truncate font-mono text-base font-semibold text-po-hi\">/{prompt.name}</span>\n <span className=\"w-full truncate text-sm font-normal text-po-dim\">{prompt.description}</span>\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n data-testid={`prompts-edit-${prompt.name}`}\n aria-label={`Edit /${prompt.name}`}\n onClick={() => props.onEdit(prompt)}\n >\n Edit\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n data-testid={`prompts-delete-${prompt.name}`}\n aria-label={`Remove /${prompt.name}`}\n disabled={props.busy}\n onClick={() => props.onDelete(prompt)}\n >\n Remove\n </Button>\n </li>\n ))}\n </ul>\n )}\n </div>\n );\n}\n","import type { SessionFrameSender } from '@agimon-ai/po-core/web';\nimport {\n Button,\n Dialog,\n DialogBody,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from '@agimon-ai/po-web-components';\nimport { useEffect, useState } from 'react';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport { commitDraft, type DraftState, draftOf, EMPTY_DRAFT, promptFrame } from '../../_lib/promptsActions';\nimport { deleteSavedPrompt, saveSavedPrompt } from '../_lib/promptsApi';\nimport { PromptEditor } from './PromptEditor';\nimport { PromptPickerList } from './PromptPickerList';\n\n/**\n * The prompt picker, opened from the activity dock.\n *\n * DESIGN PATTERNS:\n * - Picking sends. A saved prompt is a message the reader already wrote, so the\n * primary action submits it to the focused session and closes the dialog.\n * - Managing is secondary and lives in the same dialog, because a library with\n * no way to fix an entry is a library nobody trusts.\n * - This file is chrome and state; the rows are PromptPickerList.\n *\n * AVOID:\n * - Sending with no session focused. There would be nowhere for it to land.\n */\n\nconst NO_SESSION = 'Focus a session first: a prompt has to be sent somewhere.';\n\nexport interface PromptsDialogProps {\n open: boolean;\n prompts: readonly SavedPromptView[];\n loading: boolean;\n loadError: string;\n initialDraft?: DraftState;\n sessionId: string | null;\n onOpenChange: (open: boolean) => void;\n onReload: () => Promise<void>;\n onSend: SessionFrameSender;\n}\n\ntype Confirmation = { kind: 'remove'; prompt: SavedPromptView } | { kind: 'replace'; name: string };\n\nexport function PromptsDialog({\n open,\n prompts,\n loading,\n loadError,\n initialDraft,\n sessionId,\n onOpenChange,\n onReload,\n onSend,\n}: PromptsDialogProps) {\n const [filter, setFilter] = useState('');\n const [draft, setDraft] = useState<DraftState | undefined>(initialDraft);\n const [confirmation, setConfirmation] = useState<Confirmation | undefined>(undefined);\n const [error, setError] = useState('');\n\n useEffect(() => {\n if (open && initialDraft) setDraft(initialDraft);\n }, [initialDraft, open]);\n const [busy, setBusy] = useState(false);\n\n const resetView = (): void => {\n setFilter('');\n setDraft(undefined);\n setConfirmation(undefined);\n setError('');\n };\n\n const changeOpen = (next: boolean): void => {\n if (!next) resetView();\n onOpenChange(next);\n };\n\n const send = (prompt: SavedPromptView): void => {\n if (sessionId === null) {\n setError(NO_SESSION);\n return;\n }\n onSend(sessionId, promptFrame(prompt.text));\n changeOpen(false);\n };\n\n const runMutation = async (mutation: () => Promise<{ error: string } | undefined>): Promise<void> => {\n setBusy(true);\n setError('');\n const failure = await mutation();\n if (failure) {\n setBusy(false);\n setError(failure.error);\n return;\n }\n await onReload();\n setBusy(false);\n setDraft(undefined);\n setConfirmation(undefined);\n };\n\n const saveDraft = (): void => {\n if (!draft) return;\n const name = draft.name.trim();\n const replacesAnother = prompts.some((prompt) => prompt.name === name && prompt.name !== draft.original);\n if (replacesAnother) {\n setConfirmation({ kind: 'replace', name });\n return;\n }\n void runMutation(() =>\n commitDraft(draft, {\n save: (nextName, text) => saveSavedPrompt(nextName, text, sessionId),\n remove: (previousName) => deleteSavedPrompt(previousName, sessionId),\n }),\n );\n };\n\n const title =\n confirmation?.kind === 'remove'\n ? 'Remove prompt'\n : confirmation?.kind === 'replace'\n ? 'Replace prompt'\n : draft\n ? draft.original === ''\n ? 'New prompt'\n : 'Edit prompt'\n : 'Prompts';\n const description = confirmation\n ? 'Manage your saved prompt library'\n : draft\n ? draft.original === ''\n ? 'Save a message you send often'\n : 'Make this prompt work your way'\n : 'Choose a prompt to send it now';\n\n return (\n <Dialog open={open} onOpenChange={changeOpen}>\n <DialogContent\n data-testid=\"prompts-dialog\"\n onOpenAutoFocus={(event) => {\n if (!initialDraft) event.preventDefault();\n }}\n aria-describedby=\"prompts-dialog-description\"\n >\n <DialogHeader dismissible closeLabel=\"Close prompts\" className=\"px-6 py-4 sm:px-6\">\n <div className=\"min-w-0\">\n <DialogTitle>{title}</DialogTitle>\n <DialogDescription id=\"prompts-dialog-description\">{description}</DialogDescription>\n </div>\n </DialogHeader>\n\n <DialogBody className=\"px-6 py-6 sm:px-6 sm:py-6\">\n {error === '' ? null : draft || confirmation ? (\n <span className=\"text-sm text-po-red\" data-testid=\"prompts-error\">\n {error}\n </span>\n ) : null}\n\n {confirmation?.kind === 'remove' ? (\n <div className=\"flex flex-col gap-4\" data-testid=\"prompts-remove-confirmation\">\n <p className=\"text-base leading-relaxed text-po-dim\">\n Remove <strong className=\"text-po-hi\">/{confirmation.prompt.name}</strong>? This cannot be undone.\n </p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" size=\"md\" disabled={busy} onClick={() => setConfirmation(undefined)}>\n Cancel\n </Button>\n <Button\n variant=\"danger\"\n size=\"md\"\n data-testid=\"prompts-remove-confirm\"\n disabled={busy}\n onClick={() => void runMutation(() => deleteSavedPrompt(confirmation.prompt.name, sessionId))}\n >\n {busy ? 'Removing…' : 'Remove prompt'}\n </Button>\n </div>\n </div>\n ) : confirmation?.kind === 'replace' && draft ? (\n <div className=\"flex flex-col gap-4\" data-testid=\"prompts-replace-confirmation\">\n <p className=\"text-base leading-relaxed text-po-dim\">\n <strong className=\"text-po-hi\">/{confirmation.name}</strong> already exists. Replace its text with this\n draft?\n </p>\n <div className=\"flex justify-end gap-2\">\n <Button variant=\"outline\" size=\"md\" disabled={busy} onClick={() => setConfirmation(undefined)}>\n Go back\n </Button>\n <Button\n variant=\"danger\"\n size=\"md\"\n data-testid=\"prompts-replace-confirm\"\n disabled={busy}\n onClick={() =>\n void runMutation(() =>\n commitDraft(draft, {\n save: (name, text) => saveSavedPrompt(name, text, sessionId),\n remove: (name) => deleteSavedPrompt(name, sessionId),\n }),\n )\n }\n >\n {busy ? 'Replacing…' : 'Replace prompt'}\n </Button>\n </div>\n </div>\n ) : draft ? (\n <PromptEditor\n draft={draft}\n busy={busy}\n onChange={setDraft}\n onSave={saveDraft}\n onCancel={() => setDraft(undefined)}\n />\n ) : (\n <PromptPickerList\n prompts={prompts}\n filter={filter}\n loading={loading}\n busy={busy}\n error={error || loadError}\n onFilterChange={setFilter}\n onSend={send}\n onEdit={(prompt) => setDraft(draftOf(prompt))}\n onDelete={(prompt) => setConfirmation({ kind: 'remove', prompt })}\n onRetry={() => void onReload()}\n />\n )}\n </DialogBody>\n\n {draft || confirmation ? null : (\n <DialogFooter variant=\"bar\" className=\"px-6 py-4 sm:px-6 sm:py-4\">\n <span className=\"text-sm text-po-dim\">\n {prompts.length === 0 ? 'Build your reusable library' : `${String(prompts.length)} saved`}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n data-testid=\"prompts-new\"\n disabled={busy}\n onClick={() => setDraft(EMPTY_DRAFT)}\n >\n New prompt\n </Button>\n </DialogFooter>\n )}\n </DialogContent>\n </Dialog>\n );\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/web';\nimport { useCallback, useEffect, useState } from 'react';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport { subscribePromptDialogRequest } from '../../_lib/messagePromptDraft';\nimport type { DraftState } from '../../_lib/promptsActions';\nimport { fetchSavedPrompts } from '../_lib/promptsApi';\nimport { PromptsDialog } from './PromptsDialog';\n\n/**\n * The prompt library's dialog and the state behind it.\n *\n * DESIGN PATTERNS:\n * - This fills an overlay, which the host keeps mounted for the whole page.\n * The two ways in are both transient (a timeline action has no component at\n * all, a composer menu entry unmounts when the menu closes), so the state\n * they open has to live somewhere neither of them owns.\n * - Every way in arrives as one request on the package's own store, so this\n * component has a single opening path rather than one per caller.\n * - The library loads on mount, again on open, and after every mutation so the\n * visible list is never an aborted or stale snapshot.\n *\n * AVOID:\n * - Rendering anything while the dialog is closed. This sits in an overlay\n * over the whole cockpit.\n * - Holding this state in the menu entry. It would be discarded on every close.\n */\n\nexport function PromptsDialogHost({ sessionId, sendSessionFrame }: WebPluginSlotProps) {\n const [prompts, setPrompts] = useState<readonly SavedPromptView[]>([]);\n const [open, setOpen] = useState(false);\n const [initialDraft, setInitialDraft] = useState<DraftState | undefined>(undefined);\n const [error, setError] = useState('');\n const [loading, setLoading] = useState(true);\n\n const loadPrompts = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n setLoading(true);\n const result = await fetchSavedPrompts(signal, sessionId);\n if (signal?.aborted) return;\n if ('error' in result) setError(result.error);\n else {\n setError('');\n setPrompts(result.prompts);\n }\n setLoading(false);\n },\n [sessionId],\n );\n\n useEffect(() => {\n const controller = new AbortController();\n void loadPrompts(controller.signal);\n return () => controller.abort();\n }, [loadPrompts, open]);\n\n useEffect(\n () =>\n subscribePromptDialogRequest((request) => {\n setInitialDraft(request.draft);\n setOpen(true);\n }),\n [],\n );\n\n const changeOpen = (next: boolean): void => {\n if (!next) setInitialDraft(undefined);\n setOpen(next);\n };\n\n return (\n <PromptsDialog\n open={open}\n prompts={prompts}\n loading={loading}\n loadError={error}\n initialDraft={initialDraft}\n sessionId={sessionId}\n onOpenChange={changeOpen}\n onReload={loadPrompts}\n onSend={sendSessionFrame}\n />\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/web';\n\nimport { PromptsDialogHost } from './_components/PromptsDialogHost';\nexport default defineFill({ component: PromptsDialogHost });\n","import { BookmarkPlusIcon, OptionLabel, OptionRow } from '@agimon-ai/po-web-components';\n\nimport { requestPromptDialogOpen } from '../../_lib/messagePromptDraft';\n\n/**\n * The library's entry in the composer's '+' menu.\n *\n * DESIGN PATTERNS:\n * - Stateless on purpose. The menu unmounts this on every close, so it owns\n * the click and nothing else; the dialog and its state live in the overlay.\n * - role=\"menuitem\" overrides OptionRow's listbox default, because this row\n * sits in a menu rather than in a list of choices over one field.\n *\n * AVOID:\n * - Holding dialog state, loading prompts, or subscribing to anything here.\n */\n\nexport function PromptsComposerMenuItem() {\n return (\n <OptionRow\n role=\"menuitem\"\n density=\"compact\"\n data-testid=\"composer-menu-prompts\"\n className=\"w-full text-po-text hover:bg-po-tint-blue\"\n onClick={requestPromptDialogOpen}\n >\n <BookmarkPlusIcon className=\"h-3 w-3 shrink-0\" />\n <OptionLabel density=\"compact\">Prompt template</OptionLabel>\n </OptionRow>\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/web';\n\nimport { PromptsComposerMenuItem } from './_components/PromptsComposerMenuItem';\nexport default defineFill({ component: PromptsComposerMenuItem });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/po-core/web';\n\nimport actionSave from '../src/extensions/workspaces/sessions/(frontend)/action/save.message.web';\nimport fillPromptsDialog from '../src/extensions/workspaces/sessions/(frontend)/fill/PromptsDialog.overlay.web';\nimport fillPromptsMenu from '../src/extensions/workspaces/sessions/(frontend)/fill/PromptsMenu.composer-menu.web';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const webPlugin = defineWebPlugin({\n id: 'prompts',\n session: {\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'overlay', id: 'prompts-dialog' }, fillPromptsDialog), via({ slot: 'composer-menu', id: 'prompts-menu' }, fillPromptsMenu)]; },\n get userMessageActions(): WebPluginContributions['userMessageActions'] { return [via({ id: 'save' }, actionSave)]; },\n },\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/po-prompt",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.78",
|
|
4
4
|
"description": "Staged recent prompts and saved prompt templates for Po",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -65,17 +65,17 @@
|
|
|
65
65
|
"access": "public"
|
|
66
66
|
},
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@agimon-ai/po-core": "0.0.0-alpha.
|
|
69
|
-
"@agimon-ai/po-web-components": "0.0.0-alpha.
|
|
70
|
-
"@agimon-ai/po-web-security": "0.0.0-alpha.
|
|
68
|
+
"@agimon-ai/po-core": "0.0.0-alpha.78",
|
|
69
|
+
"@agimon-ai/po-web-components": "0.0.0-alpha.78",
|
|
70
|
+
"@agimon-ai/po-web-security": "0.0.0-alpha.78",
|
|
71
71
|
"@deepseek-ai/cordis": "4.0.5",
|
|
72
72
|
"hono": "4.13.13",
|
|
73
73
|
"typebox": "1.4.2"
|
|
74
74
|
},
|
|
75
75
|
"devDependencies": {
|
|
76
|
-
"@agimon-ai/po-build": "0.0.0-alpha.
|
|
77
|
-
"@agimon-ai/po-native-components": "0.0.0-alpha.
|
|
78
|
-
"@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.
|
|
76
|
+
"@agimon-ai/po-build": "0.0.0-alpha.78",
|
|
77
|
+
"@agimon-ai/po-native-components": "0.0.0-alpha.78",
|
|
78
|
+
"@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.78",
|
|
79
79
|
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
80
80
|
"@types/node": "26.6.5",
|
|
81
81
|
"@types/react": "19.3.0",
|