@agimon-ai/po-prompt 0.0.0-alpha.21 → 0.0.0-alpha.23

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.
@@ -1,8 +1,8 @@
1
- import { apiResponse, createApiClient, defineApiRoutes, defineDockFace, defineGlobalStore, defineNativePlugin, defineUserMessageAction, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
1
+ import { apiResponse, createApiClient, defineApiRoutes, defineFill, defineGlobalStore, defineNativePlugin, defineUserMessageAction, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
2
+ import { Button, Input, Label, ListRow, Sheet, SheetBody, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, Spinner, Textarea, fontOf } from "@agimon-ai/po-native-components";
3
+ import { useCallback, useEffect, useState } from "react";
2
4
  import { View } from "react-native-unistyles/components/native/View";
3
5
  import { Text } from "react-native-unistyles/components/native/Text";
4
- import { Button, Input, Label, ListRow, SheetBody, SheetDescription, SheetFooter, Spinner, Textarea, fontOf } from "@agimon-ai/po-native-components";
5
- import { useCallback, useEffect, useState } from "react";
6
6
  import { StyleSheet } from "react-native-unistyles";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
8
  //#region src/extensions/workspaces/sessions/(frontend)/_lib/messagePromptDraft.native.ts
@@ -36,13 +36,6 @@ var save_message_native_default = defineUserMessageAction({
36
36
  });
37
37
  //#endregion
38
38
  //#region src/extensions/workspaces/sessions/(frontend)/_lib/promptsActions.ts
39
- /** The frame the cockpit sends to submit a message to a session. */
40
- function promptFrame(text) {
41
- return {
42
- type: "prompt",
43
- message: text
44
- };
45
- }
46
39
  /** Substring matching over the two columns a row shows. */
47
40
  function filterPrompts(prompts, filter) {
48
41
  const needle = filter.trim().toLowerCase();
@@ -131,7 +124,7 @@ const api = createApiClient(apiRoutes_default, {
131
124
  sessionAddress: sessionApiAddress
132
125
  });
133
126
  //#endregion
134
- //#region src/extensions/workspaces/sessions/(frontend)/dock/_lib/promptsApi.native.ts
127
+ //#region src/extensions/workspaces/sessions/(frontend)/fill/_lib/promptsApi.native.ts
135
128
  /**
136
129
  * The phone's copy of promptsApi: the same calls on the native generated
137
130
  * client, so the phone bundle never loads the web one. Keep the two in step.
@@ -170,19 +163,19 @@ async function deleteSavedPrompt(name, sessionId) {
170
163
  return result.ok ? void 0 : { error: result.status === 0 ? UNREACHABLE : messageOf(result) };
171
164
  }
172
165
  //#endregion
173
- //#region src/extensions/workspaces/sessions/(frontend)/dock/_components/PromptsDockPanel.native.tsx
166
+ //#region src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsInsertPanel.native.tsx
174
167
  /**
175
168
  * The phone's prompt library, drawn from the approved PromptsSheet (native)
176
- * mockup. Same behaviour as the web PromptsDialog: picking sends, managing is
177
- * secondary, a rename writes before it deletes.
169
+ * mockup. It is a page of the composer's Insert sheet: picking a prompt puts
170
+ * its text in the message box for the person to send, managing is secondary,
171
+ * and a rename writes before it deletes.
178
172
  *
179
173
  * AVOID:
180
- * - Sending with no session focused. There would be nowhere for it to land.
174
+ * - Sending from here. On a phone a mis-tap would send; Send stays the composer's.
181
175
  */
182
- const NO_SESSION = "Focus a session first: a prompt has to be sent somewhere.";
183
176
  const PROMPT_LINES = 6;
184
- /** The dock face: loads the library for the focused session and hands it to the view. */
185
- function PromptsDockPanel({ sessionId, sendSessionFrame }) {
177
+ /** The Insert sheet page: loads the library and hands a picked prompt to the composer. */
178
+ function PromptsInsertPanel({ sessionId, appendComposerDraft, initialDraft }) {
186
179
  const [prompts, setPrompts] = useState([]);
187
180
  const [loading, setLoading] = useState(true);
188
181
  const [loadError, setLoadError] = useState("");
@@ -203,30 +196,22 @@ function PromptsDockPanel({ sessionId, sendSessionFrame }) {
203
196
  load(controller.signal);
204
197
  return () => controller.abort();
205
198
  }, [load]);
206
- return /* @__PURE__ */ jsx(PromptsDockView, {
199
+ return /* @__PURE__ */ jsx(PromptsInsertView, {
207
200
  prompts,
208
201
  loading,
209
202
  loadError,
210
203
  sessionId,
204
+ initialDraft,
211
205
  onReload: () => load(),
212
- onSend: sendSessionFrame
206
+ onPick: appendComposerDraft
213
207
  });
214
208
  }
215
- function PromptsDockView({ prompts, loading, loadError, sessionId, initialDraft, onReload, onSend }) {
209
+ function PromptsInsertView({ prompts, loading, loadError, sessionId, initialDraft, onReload, onPick }) {
216
210
  const [filter, setFilter] = useState("");
217
211
  const [draft, setDraft] = useState(initialDraft);
218
212
  const [confirmation, setConfirmation] = useState(void 0);
219
213
  const [error, setError] = useState("");
220
214
  const [busy, setBusy] = useState(false);
221
- useEffect(() => subscribePromptDialogRequest((request) => setDraft(request.draft)), []);
222
- const send = (prompt) => {
223
- if (sessionId === null) {
224
- setError(NO_SESSION);
225
- return;
226
- }
227
- setError("");
228
- onSend(sessionId, promptFrame(prompt.text));
229
- };
230
215
  const runMutation = async (mutation) => {
231
216
  setBusy(true);
232
217
  setError("");
@@ -344,7 +329,7 @@ function PromptsDockView({ prompts, loading, loadError, sessionId, initialDraft,
344
329
  const shown = filterPrompts(prompts, filter);
345
330
  const listError = error || loadError;
346
331
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(SheetBody, { children: [
347
- /* @__PURE__ */ jsx(SheetDescription, { children: "Choose a prompt to send it now" }),
332
+ /* @__PURE__ */ jsx(SheetDescription, { children: "Choose a prompt to add it to your message" }),
348
333
  /* @__PURE__ */ jsx(Input, {
349
334
  accessibilityLabel: "Filter prompts",
350
335
  placeholder: "Filter prompts",
@@ -372,8 +357,8 @@ function PromptsDockView({ prompts, loading, loadError, sessionId, initialDraft,
372
357
  }) : /* @__PURE__ */ jsx(View, {
373
358
  style: styles.rows,
374
359
  children: shown.map((prompt, index) => /* @__PURE__ */ jsxs(View, { children: [index > 0 ? /* @__PURE__ */ jsx(View, { style: styles.separator }) : null, /* @__PURE__ */ jsx(ListRow, {
375
- accessibilityLabel: `Send /${prompt.name}`,
376
- onPress: busy ? void 0 : () => send(prompt),
360
+ accessibilityLabel: `Insert /${prompt.name}`,
361
+ onPress: busy ? void 0 : () => onPick(prompt.text),
377
362
  disclosure: false,
378
363
  style: styles.row,
379
364
  title: /* @__PURE__ */ jsxs(Text, {
@@ -518,13 +503,40 @@ const styles = StyleSheet.create((theme) => {
518
503
  };
519
504
  });
520
505
  //#endregion
521
- //#region src/extensions/workspaces/sessions/(frontend)/dock/prompts.native.tsx
522
- /** The phone's prompt library: a tab in the Activity sheet, beside Activity and Context. */
523
- var prompts_native_default = defineDockFace({
524
- id: "prompts",
525
- label: "Prompts",
526
- order: 40,
527
- panel: PromptsDockPanel
506
+ //#region src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsSaveSheet.native.tsx
507
+ /**
508
+ * The phone's PromptsDialogHost: always mounted in the session overlay, it owns
509
+ * "Save as prompt" requests and opens the library on the message's text.
510
+ */
511
+ function PromptsSaveSheet({ initialDraft, ...props }) {
512
+ const [draft, setDraft] = useState(initialDraft);
513
+ useEffect(() => subscribePromptDialogRequest((request) => setDraft(request.draft ?? EMPTY_DRAFT)), []);
514
+ const close = () => setDraft(void 0);
515
+ return /* @__PURE__ */ jsx(Sheet, {
516
+ open: draft !== void 0,
517
+ onOpenChange: (open) => !open && close(),
518
+ children: /* @__PURE__ */ jsxs(SheetContent, { children: [/* @__PURE__ */ jsx(SheetHeader, { children: /* @__PURE__ */ jsx(SheetTitle, { children: "Prompts" }) }), draft ? /* @__PURE__ */ jsx(PromptsInsertPanel, {
519
+ ...props,
520
+ initialDraft: draft,
521
+ appendComposerDraft: (text) => {
522
+ props.appendComposerDraft?.(text);
523
+ close();
524
+ }
525
+ }) : null] })
526
+ });
527
+ }
528
+ //#endregion
529
+ //#region src/extensions/workspaces/sessions/(frontend)/fill/PromptsDialog.overlay.native.tsx
530
+ var PromptsDialog_overlay_native_default = defineFill({ component: PromptsSaveSheet });
531
+ //#endregion
532
+ //#region src/extensions/workspaces/sessions/(frontend)/fill/PromptsMenu.composer-menu.native.tsx
533
+ /** The phone's Insert sheet draws `data` as the row and `component` as the page it opens. */
534
+ var PromptsMenu_composer_menu_native_default = defineFill({
535
+ data: {
536
+ title: "Prompts",
537
+ hint: "Add one of your saved prompts"
538
+ },
539
+ component: PromptsInsertPanel
528
540
  });
529
541
  //#endregion
530
542
  //#region generated/native.ts
@@ -535,8 +547,14 @@ const via = (identity, value) => value === void 0 ? void 0 : {
535
547
  const nativePlugin = defineNativePlugin({
536
548
  id: "prompts",
537
549
  session: {
538
- get dockFaces() {
539
- return [via({ id: "prompts" }, prompts_native_default)];
550
+ get fills() {
551
+ return [via({
552
+ slot: "overlay",
553
+ id: "prompts-dialog"
554
+ }, PromptsDialog_overlay_native_default), via({
555
+ slot: "composer-menu",
556
+ id: "prompts-menu"
557
+ }, PromptsMenu_composer_menu_native_default)];
540
558
  },
541
559
  get userMessageActions() {
542
560
  return [via({ id: "save" }, save_message_native_default)];
@@ -1 +1 @@
1
- {"version":3,"file":"native.mjs","names":["routes","WebPluginSlotProps","Button","fontOf","Input","Label","ListRow","SheetBody","SheetDescription","SheetFooter","Spinner","Textarea","useCallback","useEffect","useState","StyleSheet","SavedPromptView","subscribePromptDialogRequest","canSaveDraft","commitDraft","DraftState","draftOf","EMPTY_DRAFT","filterPrompts","promptFrame","deleteSavedPrompt","fetchSavedPrompts","saveSavedPrompt","NO_SESSION","PROMPT_LINES","Confirmation","kind","prompt","name","PromptsDockPanel","sessionId","sendSessionFrame","prompts","setPrompts","loading","setLoading","loadError","setLoadError","load","signal","AbortSignal","Promise","result","aborted","error","controller","AbortController","abort","PromptsDockViewProps","initialDraft","onReload","onSend","PromptsDockView","filter","setFilter","draft","setDraft","confirmation","setConfirmation","undefined","setError","busy","setBusy","request","send","text","runMutation","mutation","failure","commit","next","save","remove","saveDraft","trim","some","original","styles","alert","confirm","strong","actions","editing","field","shown","listError","errorText","length","empty","rows","map","index","separator","row","description","rowActions","count","String","create","theme","small","fontFamily","sans","fontSize","sm","lineHeight","borderTopWidth","hairlineWidth","borderBottomWidth","borderColor","colors","uni__dependencies","paddingHorizontal","spacing","height","backgroundColor","flexDirection","gap","color","hi","mono","base","fontWeight","semibold","dim","paddingVertical","textAlign","alignItems","padding","borderWidth","borderRadius","md","red","flex","justifyContent","dockPrompts","actionSave"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/_lib/messagePromptDraft.native.ts","../../src/extensions/workspaces/sessions/(frontend)/action/save.message.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/promptsActions.ts","../../src/constants/promptsApi.ts","../../src/constants/webPrompts.ts","../../src/types/apiRoutes.ts","../../generated/client.native.ts","../../src/extensions/workspaces/sessions/(frontend)/dock/_lib/promptsApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/dock/_components/PromptsDockPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/dock/prompts.native.tsx","../../generated/native.ts"],"sourcesContent":["import { defineGlobalStore, type UserMessageActionRunContext } from '@agimon-ai/po-core/native';\n\nimport type { PromptDialogRequest } from './messagePromptDraft';\nimport type { DraftState } from './promptsActions';\n\n/**\n * The phone's copy of messagePromptDraft: the same request pipe, built on the\n * native contract so the phone bundle never loads the web one. Keep the two in step.\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\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/native';\n\nimport { requestMessagePromptDraft } from '../_lib/messagePromptDraft.native';\n\n/** The web action without its icon: the phone draws its own row for a message action. */\nexport default defineUserMessageAction({\n label: 'Save as prompt',\n order: 40,\n run: requestMessagePromptDraft,\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","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, nativeApiTransport, sessionApiAddress } from '@agimon-ai/po-core/native';\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: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client.native';\nimport { NAME_PARAM } from '../../../../../../constants/promptsApi';\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\n\n/**\n * The phone's copy of promptsApi: the same calls on the native generated\n * client, so the phone bundle never loads the web one. Keep the two in step.\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; an abort is the caller's own doing.\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 { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport {\n Button,\n fontOf,\n Input,\n Label,\n ListRow,\n SheetBody,\n SheetDescription,\n SheetFooter,\n Spinner,\n Textarea,\n} from '@agimon-ai/po-native-components';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport { subscribePromptDialogRequest } from '../../_lib/messagePromptDraft.native';\nimport {\n canSaveDraft,\n commitDraft,\n type DraftState,\n draftOf,\n EMPTY_DRAFT,\n filterPrompts,\n promptFrame,\n} from '../../_lib/promptsActions';\nimport { deleteSavedPrompt, fetchSavedPrompts, saveSavedPrompt } from '../_lib/promptsApi.native';\n\n/**\n * The phone's prompt library, drawn from the approved PromptsSheet (native)\n * mockup. Same behaviour as the web PromptsDialog: picking sends, managing is\n * secondary, a rename writes before it deletes.\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.';\nconst PROMPT_LINES = 6;\n\ntype Confirmation = { kind: 'remove'; prompt: SavedPromptView } | { kind: 'replace'; name: string };\n\n/** The dock face: loads the library for the focused session and hands it to the view. */\nexport function PromptsDockPanel({ sessionId, sendSessionFrame }: WebPluginSlotProps) {\n const [prompts, setPrompts] = useState<readonly SavedPromptView[]>([]);\n const [loading, setLoading] = useState(true);\n const [loadError, setLoadError] = useState('');\n\n const load = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n setLoading(true);\n const result = await fetchSavedPrompts(signal, sessionId);\n if (signal?.aborted) return;\n setLoading(false);\n if ('error' in result) {\n setLoadError(result.error);\n return;\n }\n setLoadError('');\n setPrompts(result.prompts);\n },\n [sessionId],\n );\n\n useEffect(() => {\n const controller = new AbortController();\n void load(controller.signal);\n return () => controller.abort();\n }, [load]);\n\n return (\n <PromptsDockView\n prompts={prompts}\n loading={loading}\n loadError={loadError}\n sessionId={sessionId}\n onReload={() => load()}\n onSend={sendSessionFrame}\n />\n );\n}\n\nexport interface PromptsDockViewProps {\n prompts: readonly SavedPromptView[];\n loading: boolean;\n loadError: string;\n sessionId: string | null;\n /** The draft to open on, for stories; a \"Save as prompt\" request replaces it. */\n initialDraft?: DraftState;\n onReload: () => Promise<void>;\n onSend: WebPluginSlotProps['sendSessionFrame'];\n}\n\nexport function PromptsDockView({\n prompts,\n loading,\n loadError,\n sessionId,\n initialDraft,\n onReload,\n onSend,\n}: PromptsDockViewProps) {\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 const [busy, setBusy] = useState(false);\n\n // \"Save as prompt\" on a message lands here as a draft once this tab is open.\n useEffect(() => subscribePromptDialogRequest((request) => setDraft(request.draft)), []);\n\n const send = (prompt: SavedPromptView): void => {\n if (sessionId === null) {\n setError(NO_SESSION);\n return;\n }\n setError('');\n onSend(sessionId, promptFrame(prompt.text));\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 commit = (next: DraftState): Promise<void> =>\n runMutation(() =>\n commitDraft(next, {\n save: (name, text) => saveSavedPrompt(name, text, sessionId),\n remove: (name) => deleteSavedPrompt(name, sessionId),\n }),\n );\n\n const saveDraft = (): void => {\n if (!draft) return;\n const name = draft.name.trim();\n if (prompts.some((prompt) => prompt.name === name && prompt.name !== draft.original)) {\n setConfirmation({ kind: 'replace', name });\n return;\n }\n void commit(draft);\n };\n\n const failure = error === '' ? null : <Text style={styles.alert}>{error}</Text>;\n\n if (confirmation) {\n const remove = confirmation.kind === 'remove';\n const name = remove ? confirmation.prompt.name : confirmation.name;\n return (\n <SheetBody>\n <SheetDescription>Manage your saved prompt library</SheetDescription>\n {failure}\n <Text style={styles.confirm}>\n {remove ? 'Remove ' : null}\n <Text style={styles.strong}>/{name}</Text>\n {remove ? '? This cannot be undone.' : ' already exists. Replace its text with this draft?'}\n </Text>\n <View style={styles.actions}>\n <Button variant=\"outline\" disabled={busy} onPress={() => setConfirmation(undefined)}>\n {remove ? 'Cancel' : 'Go back'}\n </Button>\n <Button\n variant=\"danger\"\n disabled={busy}\n onPress={() =>\n void (remove ? runMutation(() => deleteSavedPrompt(name, sessionId)) : draft && commit(draft))\n }\n >\n {remove ? (busy ? 'Removing…' : 'Remove prompt') : busy ? 'Replacing…' : 'Replace prompt'}\n </Button>\n </View>\n </SheetBody>\n );\n }\n\n if (draft) {\n const editing = draft.original !== '';\n return (\n <SheetBody>\n <SheetDescription>\n {editing ? 'Make this prompt work your way' : 'Save a message you send often'}\n </SheetDescription>\n {failure}\n <View style={styles.field}>\n <Label>Prompt name</Label>\n <Input\n accessibilityLabel=\"Prompt name\"\n autoCapitalize=\"none\"\n value={draft.name}\n onChangeText={(name) => setDraft({ ...draft, name })}\n placeholder=\"Lowercase letters, digits and dashes\"\n />\n </View>\n <View style={styles.field}>\n <Label>Prompt text</Label>\n <Textarea\n accessibilityLabel=\"Prompt text\"\n numberOfLines={PROMPT_LINES}\n value={draft.text}\n onChangeText={(text) => setDraft({ ...draft, text })}\n placeholder=\"What Po should do when you send it\"\n />\n </View>\n <View style={styles.actions}>\n <Button variant=\"outline\" disabled={busy} onPress={() => setDraft(undefined)}>\n Cancel\n </Button>\n <Button variant=\"primary\" disabled={busy || !canSaveDraft(draft)} onPress={saveDraft}>\n {busy ? 'Saving…' : editing ? 'Save changes' : 'Save prompt'}\n </Button>\n </View>\n </SheetBody>\n );\n }\n\n const shown = filterPrompts(prompts, filter);\n const listError = error || loadError;\n return (\n <>\n <SheetBody>\n <SheetDescription>Choose a prompt to send it now</SheetDescription>\n <Input\n accessibilityLabel=\"Filter prompts\"\n placeholder=\"Filter prompts\"\n value={filter}\n onChangeText={setFilter}\n />\n {listError !== '' ? (\n <View style={styles.error}>\n <Text style={styles.errorText}>\n {loadError !== '' ? `Your prompts could not be loaded. ${loadError}` : listError}\n </Text>\n {loadError !== '' ? (\n <Button variant=\"outline\" size=\"sm\" onPress={() => void onReload()}>\n Retry\n </Button>\n ) : null}\n </View>\n ) : null}\n {loading && prompts.length === 0 ? (\n <Spinner label=\"Loading prompts…\" />\n ) : loadError !== '' ? null : prompts.length === 0 ? (\n <Text style={styles.empty}>No saved prompts yet. New prompt saves one for later.</Text>\n ) : shown.length === 0 ? (\n <Text style={styles.empty}>Nothing matches that filter</Text>\n ) : (\n <View style={styles.rows}>\n {shown.map((prompt, index) => (\n <View key={prompt.name}>\n {index > 0 ? <View style={styles.separator} /> : null}\n <ListRow\n accessibilityLabel={`Send /${prompt.name}`}\n onPress={busy ? undefined : () => send(prompt)}\n disclosure={false}\n style={styles.row}\n title={\n <Text numberOfLines={1} style={styles.name}>\n /{prompt.name}\n </Text>\n }\n description={\n <Text numberOfLines={1} style={styles.description}>\n {prompt.description}\n </Text>\n }\n trailing={\n <View style={styles.rowActions}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={busy}\n accessibilityLabel={`Edit /${prompt.name}`}\n onPress={() => setDraft(draftOf(prompt))}\n >\n Edit\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={busy}\n accessibilityLabel={`Remove /${prompt.name}`}\n onPress={() => setConfirmation({ kind: 'remove', prompt })}\n >\n Remove\n </Button>\n </View>\n }\n />\n </View>\n ))}\n </View>\n )}\n </SheetBody>\n <SheetFooter>\n <Text style={styles.count}>\n {prompts.length === 0 ? 'Build your reusable library' : `${String(prompts.length)} saved`}\n </Text>\n <Button variant=\"outline\" size=\"sm\" disabled={busy} onPress={() => setDraft(EMPTY_DRAFT)}>\n New prompt\n </Button>\n </SheetFooter>\n </>\n );\n}\n\nconst styles = StyleSheet.create((theme) => {\n const small = {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n };\n return {\n rows: {\n borderTopWidth: StyleSheet.hairlineWidth,\n borderBottomWidth: StyleSheet.hairlineWidth,\n borderColor: theme.colors['border-soft'],\n },\n row: { paddingHorizontal: theme.spacing(1) },\n separator: { height: StyleSheet.hairlineWidth, backgroundColor: theme.colors['border-soft'] },\n rowActions: { flexDirection: 'row', gap: theme.spacing(1) },\n name: {\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.mono),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n fontWeight: theme.fontWeight.semibold,\n },\n description: { ...small, color: theme.colors.dim },\n empty: { ...small, paddingVertical: theme.spacing(6), textAlign: 'center', color: theme.colors.dim },\n error: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.spacing(3),\n padding: theme.spacing(3),\n borderWidth: 1,\n borderRadius: theme.borderRadius.md,\n borderColor: theme.colors['edge-red'],\n },\n alert: { ...small, color: theme.colors.red },\n errorText: { ...small, flex: 1, color: theme.colors.red },\n count: { ...small, color: theme.colors.dim },\n confirm: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n strong: { color: theme.colors.hi, fontWeight: theme.fontWeight.semibold },\n field: { gap: theme.spacing(1.5) },\n actions: { flexDirection: 'row', justifyContent: 'flex-end', gap: theme.spacing(2) },\n };\n});\n","import { defineDockFace } from '@agimon-ai/po-core/native';\n\nimport { PromptsDockPanel } from './_components/PromptsDockPanel.native';\n\n/** The phone's prompt library: a tab in the Activity sheet, beside Activity and Context. */\nexport default defineDockFace({\n id: 'prompts',\n label: 'Prompts',\n order: 40,\n panel: PromptsDockPanel,\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineNativePlugin, type WebPluginContributions } from '@agimon-ai/po-core/native';\n\nimport actionSave from '../src/extensions/workspaces/sessions/(frontend)/action/save.message.native';\nimport dockPrompts from '../src/extensions/workspaces/sessions/(frontend)/dock/prompts.native';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const nativePlugin = defineNativePlugin({\n id: 'prompts',\n session: {\n get dockFaces(): WebPluginContributions['dockFaces'] { return [via({ id: 'prompts' }, dockPrompts)]; },\n get userMessageActions(): WebPluginContributions['userMessageActions'] { return [via({ id: 'save' }, actionSave)]; },\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"native.mjs","names":["routes","WebPluginSlotProps","Button","fontOf","Input","Label","ListRow","SheetBody","SheetDescription","SheetFooter","Spinner","Textarea","useCallback","useEffect","useState","StyleSheet","SavedPromptView","canSaveDraft","commitDraft","DraftState","draftOf","EMPTY_DRAFT","filterPrompts","deleteSavedPrompt","fetchSavedPrompts","saveSavedPrompt","PROMPT_LINES","Confirmation","kind","prompt","name","PromptsInsertPanel","sessionId","appendComposerDraft","initialDraft","prompts","setPrompts","loading","setLoading","loadError","setLoadError","load","signal","AbortSignal","Promise","result","aborted","error","controller","AbortController","abort","PromptsInsertViewProps","onReload","onPick","text","PromptsInsertView","filter","setFilter","draft","setDraft","confirmation","setConfirmation","undefined","setError","busy","setBusy","runMutation","mutation","failure","commit","next","save","remove","saveDraft","trim","some","original","styles","alert","confirm","strong","actions","editing","field","shown","listError","errorText","length","empty","rows","map","index","separator","row","description","rowActions","count","String","create","theme","small","fontFamily","sans","fontSize","sm","lineHeight","borderTopWidth","hairlineWidth","borderBottomWidth","borderColor","colors","uni__dependencies","paddingHorizontal","spacing","height","backgroundColor","flexDirection","gap","color","hi","mono","base","fontWeight","semibold","dim","paddingVertical","textAlign","alignItems","padding","borderWidth","borderRadius","md","red","flex","justifyContent","fillPromptsDialog","fillPromptsMenu","actionSave"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/_lib/messagePromptDraft.native.ts","../../src/extensions/workspaces/sessions/(frontend)/action/save.message.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/promptsActions.ts","../../src/constants/promptsApi.ts","../../src/constants/webPrompts.ts","../../src/types/apiRoutes.ts","../../generated/client.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/promptsApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsInsertPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PromptsSaveSheet.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/PromptsDialog.overlay.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/PromptsMenu.composer-menu.native.tsx","../../generated/native.ts"],"sourcesContent":["import { defineGlobalStore, type UserMessageActionRunContext } from '@agimon-ai/po-core/native';\n\nimport type { PromptDialogRequest } from './messagePromptDraft';\nimport type { DraftState } from './promptsActions';\n\n/**\n * The phone's copy of messagePromptDraft: the same request pipe, built on the\n * native contract so the phone bundle never loads the web one. Keep the two in step.\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\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/native';\n\nimport { requestMessagePromptDraft } from '../_lib/messagePromptDraft.native';\n\n/** The web action without its icon: the phone draws its own row for a message action. */\nexport default defineUserMessageAction({\n label: 'Save as prompt',\n order: 40,\n run: requestMessagePromptDraft,\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","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, nativeApiTransport, sessionApiAddress } from '@agimon-ai/po-core/native';\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: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client.native';\nimport { NAME_PARAM } from '../../../../../../constants/promptsApi';\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\n\n/**\n * The phone's copy of promptsApi: the same calls on the native generated\n * client, so the phone bundle never loads the web one. Keep the two in step.\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; an abort is the caller's own doing.\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 { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport {\n Button,\n fontOf,\n Input,\n Label,\n ListRow,\n SheetBody,\n SheetDescription,\n SheetFooter,\n Spinner,\n Textarea,\n} from '@agimon-ai/po-native-components';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { SavedPromptView } from '../../../../../../types/webPrompts';\nimport {\n canSaveDraft,\n commitDraft,\n type DraftState,\n draftOf,\n EMPTY_DRAFT,\n filterPrompts,\n} from '../../_lib/promptsActions';\nimport { deleteSavedPrompt, fetchSavedPrompts, saveSavedPrompt } from '../_lib/promptsApi.native';\n\n/**\n * The phone's prompt library, drawn from the approved PromptsSheet (native)\n * mockup. It is a page of the composer's Insert sheet: picking a prompt puts\n * its text in the message box for the person to send, managing is secondary,\n * and a rename writes before it deletes.\n *\n * AVOID:\n * - Sending from here. On a phone a mis-tap would send; Send stays the composer's.\n */\n\nconst PROMPT_LINES = 6;\n\ntype Confirmation = { kind: 'remove'; prompt: SavedPromptView } | { kind: 'replace'; name: string };\n\n/** The Insert sheet page: loads the library and hands a picked prompt to the composer. */\nexport function PromptsInsertPanel({\n sessionId,\n appendComposerDraft,\n initialDraft,\n}: WebPluginSlotProps & { initialDraft?: DraftState }) {\n const [prompts, setPrompts] = useState<readonly SavedPromptView[]>([]);\n const [loading, setLoading] = useState(true);\n const [loadError, setLoadError] = useState('');\n\n const load = useCallback(\n async (signal?: AbortSignal): Promise<void> => {\n setLoading(true);\n const result = await fetchSavedPrompts(signal, sessionId);\n if (signal?.aborted) return;\n setLoading(false);\n if ('error' in result) {\n setLoadError(result.error);\n return;\n }\n setLoadError('');\n setPrompts(result.prompts);\n },\n [sessionId],\n );\n\n useEffect(() => {\n const controller = new AbortController();\n void load(controller.signal);\n return () => controller.abort();\n }, [load]);\n\n return (\n <PromptsInsertView\n prompts={prompts}\n loading={loading}\n loadError={loadError}\n sessionId={sessionId}\n initialDraft={initialDraft}\n onReload={() => load()}\n onPick={appendComposerDraft}\n />\n );\n}\n\nexport interface PromptsInsertViewProps {\n prompts: readonly SavedPromptView[];\n loading: boolean;\n loadError: string;\n sessionId: string | null;\n /** The draft to open on: a \"Save as prompt\" request, or a story's fixture. */\n initialDraft?: DraftState;\n onReload: () => Promise<void>;\n /** Receives the picked prompt's text; the host puts it in the message box. */\n onPick: (text: string) => void;\n}\n\nexport function PromptsInsertView({\n prompts,\n loading,\n loadError,\n sessionId,\n initialDraft,\n onReload,\n onPick,\n}: PromptsInsertViewProps) {\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 const [busy, setBusy] = useState(false);\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 commit = (next: DraftState): Promise<void> =>\n runMutation(() =>\n commitDraft(next, {\n save: (name, text) => saveSavedPrompt(name, text, sessionId),\n remove: (name) => deleteSavedPrompt(name, sessionId),\n }),\n );\n\n const saveDraft = (): void => {\n if (!draft) return;\n const name = draft.name.trim();\n if (prompts.some((prompt) => prompt.name === name && prompt.name !== draft.original)) {\n setConfirmation({ kind: 'replace', name });\n return;\n }\n void commit(draft);\n };\n\n const failure = error === '' ? null : <Text style={styles.alert}>{error}</Text>;\n\n if (confirmation) {\n const remove = confirmation.kind === 'remove';\n const name = remove ? confirmation.prompt.name : confirmation.name;\n return (\n <SheetBody>\n <SheetDescription>Manage your saved prompt library</SheetDescription>\n {failure}\n <Text style={styles.confirm}>\n {remove ? 'Remove ' : null}\n <Text style={styles.strong}>/{name}</Text>\n {remove ? '? This cannot be undone.' : ' already exists. Replace its text with this draft?'}\n </Text>\n <View style={styles.actions}>\n <Button variant=\"outline\" disabled={busy} onPress={() => setConfirmation(undefined)}>\n {remove ? 'Cancel' : 'Go back'}\n </Button>\n <Button\n variant=\"danger\"\n disabled={busy}\n onPress={() =>\n void (remove ? runMutation(() => deleteSavedPrompt(name, sessionId)) : draft && commit(draft))\n }\n >\n {remove ? (busy ? 'Removing…' : 'Remove prompt') : busy ? 'Replacing…' : 'Replace prompt'}\n </Button>\n </View>\n </SheetBody>\n );\n }\n\n if (draft) {\n const editing = draft.original !== '';\n return (\n <SheetBody>\n <SheetDescription>\n {editing ? 'Make this prompt work your way' : 'Save a message you send often'}\n </SheetDescription>\n {failure}\n <View style={styles.field}>\n <Label>Prompt name</Label>\n <Input\n accessibilityLabel=\"Prompt name\"\n autoCapitalize=\"none\"\n value={draft.name}\n onChangeText={(name) => setDraft({ ...draft, name })}\n placeholder=\"Lowercase letters, digits and dashes\"\n />\n </View>\n <View style={styles.field}>\n <Label>Prompt text</Label>\n <Textarea\n accessibilityLabel=\"Prompt text\"\n numberOfLines={PROMPT_LINES}\n value={draft.text}\n onChangeText={(text) => setDraft({ ...draft, text })}\n placeholder=\"What Po should do when you send it\"\n />\n </View>\n <View style={styles.actions}>\n <Button variant=\"outline\" disabled={busy} onPress={() => setDraft(undefined)}>\n Cancel\n </Button>\n <Button variant=\"primary\" disabled={busy || !canSaveDraft(draft)} onPress={saveDraft}>\n {busy ? 'Saving…' : editing ? 'Save changes' : 'Save prompt'}\n </Button>\n </View>\n </SheetBody>\n );\n }\n\n const shown = filterPrompts(prompts, filter);\n const listError = error || loadError;\n return (\n <>\n <SheetBody>\n <SheetDescription>Choose a prompt to add it to your message</SheetDescription>\n <Input\n accessibilityLabel=\"Filter prompts\"\n placeholder=\"Filter prompts\"\n value={filter}\n onChangeText={setFilter}\n />\n {listError !== '' ? (\n <View style={styles.error}>\n <Text style={styles.errorText}>\n {loadError !== '' ? `Your prompts could not be loaded. ${loadError}` : listError}\n </Text>\n {loadError !== '' ? (\n <Button variant=\"outline\" size=\"sm\" onPress={() => void onReload()}>\n Retry\n </Button>\n ) : null}\n </View>\n ) : null}\n {loading && prompts.length === 0 ? (\n <Spinner label=\"Loading prompts…\" />\n ) : loadError !== '' ? null : prompts.length === 0 ? (\n <Text style={styles.empty}>No saved prompts yet. New prompt saves one for later.</Text>\n ) : shown.length === 0 ? (\n <Text style={styles.empty}>Nothing matches that filter</Text>\n ) : (\n <View style={styles.rows}>\n {shown.map((prompt, index) => (\n <View key={prompt.name}>\n {index > 0 ? <View style={styles.separator} /> : null}\n <ListRow\n accessibilityLabel={`Insert /${prompt.name}`}\n onPress={busy ? undefined : () => onPick(prompt.text)}\n disclosure={false}\n style={styles.row}\n title={\n <Text numberOfLines={1} style={styles.name}>\n /{prompt.name}\n </Text>\n }\n description={\n <Text numberOfLines={1} style={styles.description}>\n {prompt.description}\n </Text>\n }\n trailing={\n <View style={styles.rowActions}>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={busy}\n accessibilityLabel={`Edit /${prompt.name}`}\n onPress={() => setDraft(draftOf(prompt))}\n >\n Edit\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n disabled={busy}\n accessibilityLabel={`Remove /${prompt.name}`}\n onPress={() => setConfirmation({ kind: 'remove', prompt })}\n >\n Remove\n </Button>\n </View>\n }\n />\n </View>\n ))}\n </View>\n )}\n </SheetBody>\n <SheetFooter>\n <Text style={styles.count}>\n {prompts.length === 0 ? 'Build your reusable library' : `${String(prompts.length)} saved`}\n </Text>\n <Button variant=\"outline\" size=\"sm\" disabled={busy} onPress={() => setDraft(EMPTY_DRAFT)}>\n New prompt\n </Button>\n </SheetFooter>\n </>\n );\n}\n\nconst styles = StyleSheet.create((theme) => {\n const small = {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n };\n return {\n rows: {\n borderTopWidth: StyleSheet.hairlineWidth,\n borderBottomWidth: StyleSheet.hairlineWidth,\n borderColor: theme.colors['border-soft'],\n },\n row: { paddingHorizontal: theme.spacing(1) },\n separator: { height: StyleSheet.hairlineWidth, backgroundColor: theme.colors['border-soft'] },\n rowActions: { flexDirection: 'row', gap: theme.spacing(1) },\n name: {\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.mono),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n fontWeight: theme.fontWeight.semibold,\n },\n description: { ...small, color: theme.colors.dim },\n empty: { ...small, paddingVertical: theme.spacing(6), textAlign: 'center', color: theme.colors.dim },\n error: {\n flexDirection: 'row',\n alignItems: 'center',\n gap: theme.spacing(3),\n padding: theme.spacing(3),\n borderWidth: 1,\n borderRadius: theme.borderRadius.md,\n borderColor: theme.colors['edge-red'],\n },\n alert: { ...small, color: theme.colors.red },\n errorText: { ...small, flex: 1, color: theme.colors.red },\n count: { ...small, color: theme.colors.dim },\n confirm: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n strong: { color: theme.colors.hi, fontWeight: theme.fontWeight.semibold },\n field: { gap: theme.spacing(1.5) },\n actions: { flexDirection: 'row', justifyContent: 'flex-end', gap: theme.spacing(2) },\n };\n});\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { Sheet, SheetContent, SheetHeader, SheetTitle } from '@agimon-ai/po-native-components';\nimport { useEffect, useState } from 'react';\n\nimport { subscribePromptDialogRequest } from '../../_lib/messagePromptDraft.native';\nimport { type DraftState, EMPTY_DRAFT } from '../../_lib/promptsActions';\nimport { PromptsInsertPanel } from './PromptsInsertPanel.native';\n\n/**\n * The phone's PromptsDialogHost: always mounted in the session overlay, it owns\n * \"Save as prompt\" requests and opens the library on the message's text.\n */\nexport function PromptsSaveSheet({ initialDraft, ...props }: WebPluginSlotProps & { initialDraft?: DraftState }) {\n const [draft, setDraft] = useState<DraftState | undefined>(initialDraft);\n\n useEffect(() => subscribePromptDialogRequest((request) => setDraft(request.draft ?? EMPTY_DRAFT)), []);\n\n const close = (): void => setDraft(undefined);\n return (\n <Sheet open={draft !== undefined} onOpenChange={(open) => !open && close()}>\n <SheetContent>\n <SheetHeader>\n <SheetTitle>Prompts</SheetTitle>\n </SheetHeader>\n {draft ? (\n <PromptsInsertPanel\n {...props}\n initialDraft={draft}\n appendComposerDraft={(text) => {\n props.appendComposerDraft?.(text);\n close();\n }}\n />\n ) : null}\n </SheetContent>\n </Sheet>\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/native';\n\nimport { PromptsSaveSheet } from './_components/PromptsSaveSheet.native';\nexport default defineFill({ component: PromptsSaveSheet });\n","import { defineFill } from '@agimon-ai/po-core/native';\n\nimport { PromptsInsertPanel } from './_components/PromptsInsertPanel.native';\n\n/** The phone's Insert sheet draws `data` as the row and `component` as the page it opens. */\nexport default defineFill({\n data: { title: 'Prompts', hint: 'Add one of your saved prompts' },\n component: PromptsInsertPanel,\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineNativePlugin, type WebPluginContributions } from '@agimon-ai/po-core/native';\n\nimport actionSave from '../src/extensions/workspaces/sessions/(frontend)/action/save.message.native';\nimport fillPromptsDialog from '../src/extensions/workspaces/sessions/(frontend)/fill/PromptsDialog.overlay.native';\nimport fillPromptsMenu from '../src/extensions/workspaces/sessions/(frontend)/fill/PromptsMenu.composer-menu.native';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const nativePlugin = defineNativePlugin({\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.21",
3
+ "version": "0.0.0-alpha.23",
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.21",
69
- "@agimon-ai/po-web-components": "0.0.0-alpha.21",
70
- "@agimon-ai/po-web-security": "0.0.0-alpha.21",
68
+ "@agimon-ai/po-core": "0.0.0-alpha.23",
69
+ "@agimon-ai/po-web-components": "0.0.0-alpha.23",
70
+ "@agimon-ai/po-web-security": "0.0.0-alpha.23",
71
71
  "@deepseek-ai/cordis": "4.0.5",
72
72
  "hono": "4.13.13",
73
73
  "typebox": "1.3.37"
74
74
  },
75
75
  "devDependencies": {
76
- "@agimon-ai/po-build": "0.0.0-alpha.21",
77
- "@agimon-ai/po-native-components": "0.0.0-alpha.21",
78
- "@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.21",
76
+ "@agimon-ai/po-build": "0.0.0-alpha.23",
77
+ "@agimon-ai/po-native-components": "0.0.0-alpha.23",
78
+ "@agimon-ai/vibe-lint-plugin-po-extension": "0.0.0-alpha.23",
79
79
  "@earendil-works/pi-coding-agent": "1.3.0",
80
80
  "@types/node": "26.6.5",
81
81
  "@types/react": "19.3.0",