@agimon-ai/po-plan 0.0.0-alpha.83 → 0.0.0-alpha.85
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,7 +1,7 @@
|
|
|
1
1
|
import { createApiClient, defineActivityGroup, defineFill, defineNativePlugin, defineToolRenderer, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
|
|
2
2
|
import { View } from "react-native-unistyles/components/native/View";
|
|
3
3
|
import { Text } from "react-native-unistyles/components/native/Text";
|
|
4
|
-
import { Button, ListRow, Markdown, MessageItem, MessageItemBody, MessageItemHeader, SegmentedControl, Textarea, fontOf, toolTone } from "@agimon-ai/po-native-components";
|
|
4
|
+
import { Button, ChevronDownIcon, ChevronRightIcon, ListRow, Markdown, MessageItem, MessageItemBody, MessageItemHeader, Panel, SegmentedControl, Textarea, fontOf, toolTone } from "@agimon-ai/po-native-components";
|
|
5
5
|
import { StyleSheet } from "react-native-unistyles";
|
|
6
6
|
import { ScrollView } from "react-native-unistyles/components/native/ScrollView";
|
|
7
7
|
import { useEffect, useState } from "react";
|
|
@@ -13,7 +13,8 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
13
13
|
* plan is most worth reading while the agent implements it.
|
|
14
14
|
*/
|
|
15
15
|
const PLAN_STATUS_KEY = "po-plan-document";
|
|
16
|
-
|
|
16
|
+
/** The same options as bare labels, which is all Pi's select and the composer prompt need. */
|
|
17
|
+
const PLAN_REVIEW_OPTIONS = [{
|
|
17
18
|
label: "Exit plan mode and start implementation",
|
|
18
19
|
value: "exit"
|
|
19
20
|
}, {
|
|
@@ -194,11 +195,11 @@ function PlanPanel({ sessionId, statuses, closeTransientTab, fileTabFor, openTra
|
|
|
194
195
|
}
|
|
195
196
|
};
|
|
196
197
|
return /* @__PURE__ */ jsxs(ScrollView, {
|
|
197
|
-
contentContainerStyle: styles$
|
|
198
|
+
contentContainerStyle: styles$3.panel,
|
|
198
199
|
testID: "plan-panel",
|
|
199
200
|
children: [
|
|
200
201
|
/* @__PURE__ */ jsx(Text, {
|
|
201
|
-
style: styles$
|
|
202
|
+
style: styles$3.title,
|
|
202
203
|
children: detail?.title ?? "plan"
|
|
203
204
|
}),
|
|
204
205
|
/* @__PURE__ */ jsx(SegmentedControl, {
|
|
@@ -214,19 +215,19 @@ function PlanPanel({ sessionId, statuses, closeTransientTab, fileTabFor, openTra
|
|
|
214
215
|
onValueChange: setView
|
|
215
216
|
}),
|
|
216
217
|
sessionId === null ? /* @__PURE__ */ jsx(Text, {
|
|
217
|
-
style: styles$
|
|
218
|
+
style: styles$3.meta,
|
|
218
219
|
children: "Select a session."
|
|
219
220
|
}) : loading && !detail ? /* @__PURE__ */ jsx(Text, {
|
|
220
|
-
style: styles$
|
|
221
|
+
style: styles$3.meta,
|
|
221
222
|
children: "reading this session's plan…"
|
|
222
223
|
}) : null,
|
|
223
224
|
error ? /* @__PURE__ */ jsx(Text, {
|
|
224
225
|
accessibilityRole: "alert",
|
|
225
|
-
style: styles$
|
|
226
|
+
style: styles$3.error,
|
|
226
227
|
children: error
|
|
227
228
|
}) : null,
|
|
228
229
|
detail ? detail.unavailable ? /* @__PURE__ */ jsx(Text, {
|
|
229
|
-
style: styles$
|
|
230
|
+
style: styles$3.meta,
|
|
230
231
|
children: detail.reason ?? "this plan cannot be shown"
|
|
231
232
|
}) : view === "preview" ? /* @__PURE__ */ jsx(Markdown, {
|
|
232
233
|
text: draft ?? detail.content,
|
|
@@ -242,7 +243,7 @@ function PlanPanel({ sessionId, statuses, closeTransientTab, fileTabFor, openTra
|
|
|
242
243
|
numberOfLines: 12
|
|
243
244
|
}),
|
|
244
245
|
/* @__PURE__ */ jsxs(View, {
|
|
245
|
-
style: styles$
|
|
246
|
+
style: styles$3.actions,
|
|
246
247
|
children: [/* @__PURE__ */ jsx(Button, {
|
|
247
248
|
variant: "primary",
|
|
248
249
|
disabled: draft === void 0 || saving,
|
|
@@ -255,13 +256,13 @@ function PlanPanel({ sessionId, statuses, closeTransientTab, fileTabFor, openTra
|
|
|
255
256
|
}) : null]
|
|
256
257
|
}),
|
|
257
258
|
note ? /* @__PURE__ */ jsx(Text, {
|
|
258
|
-
style: note === "saved" ? styles$
|
|
259
|
+
style: note === "saved" ? styles$3.success : styles$3.error,
|
|
259
260
|
children: note
|
|
260
261
|
}) : null
|
|
261
262
|
] }) : null,
|
|
262
263
|
detail ? /* @__PURE__ */ jsx(Text, {
|
|
263
264
|
selectable: true,
|
|
264
|
-
style: styles$
|
|
265
|
+
style: styles$3.path,
|
|
265
266
|
children: detail.path
|
|
266
267
|
}) : null,
|
|
267
268
|
/* @__PURE__ */ jsx(Button, {
|
|
@@ -279,7 +280,7 @@ function planTab() {
|
|
|
279
280
|
panel: PlanPanel
|
|
280
281
|
};
|
|
281
282
|
}
|
|
282
|
-
const styles$
|
|
283
|
+
const styles$3 = StyleSheet.create((theme) => ({
|
|
283
284
|
panel: {
|
|
284
285
|
padding: theme.spacing(4),
|
|
285
286
|
gap: theme.spacing(3),
|
|
@@ -328,7 +329,7 @@ const styles$2 = StyleSheet.create((theme) => ({
|
|
|
328
329
|
function PlanActivitySection({ sessionId, statuses, openTransientTab }) {
|
|
329
330
|
const view = parsePlanStatus(statuses[PLAN_STATUS_KEY]);
|
|
330
331
|
if (!view) return /* @__PURE__ */ jsx(Text, {
|
|
331
|
-
style: styles$
|
|
332
|
+
style: styles$2.meta,
|
|
332
333
|
children: "no plan written yet"
|
|
333
334
|
});
|
|
334
335
|
return /* @__PURE__ */ jsxs(View, {
|
|
@@ -341,12 +342,12 @@ function PlanActivitySection({ sessionId, statuses, openTransientTab }) {
|
|
|
341
342
|
if (sessionId !== null) openTransientTab(planTab());
|
|
342
343
|
}
|
|
343
344
|
}), /* @__PURE__ */ jsx(Text, {
|
|
344
|
-
style: styles$
|
|
345
|
+
style: styles$2.meta,
|
|
345
346
|
children: "open to read or edit; the agent reads what you save."
|
|
346
347
|
})]
|
|
347
348
|
});
|
|
348
349
|
}
|
|
349
|
-
const styles$
|
|
350
|
+
const styles$2 = StyleSheet.create((theme) => ({ meta: {
|
|
350
351
|
fontFamily: fontOf(theme.fontFamily.sans),
|
|
351
352
|
fontSize: theme.fontSize.sm,
|
|
352
353
|
lineHeight: theme.lineHeight.sm,
|
|
@@ -361,7 +362,130 @@ var Plan_activity_plan_native_default = defineFill({
|
|
|
361
362
|
component: PlanActivitySection
|
|
362
363
|
});
|
|
363
364
|
//#endregion
|
|
365
|
+
//#region src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanReviewPrompt.native.tsx
|
|
366
|
+
function PlanReviewPrompt({ dialog, answer, cancel, defaultExpanded = true }) {
|
|
367
|
+
const [open, setOpen] = useState(defaultExpanded);
|
|
368
|
+
return /* @__PURE__ */ jsxs(Panel, {
|
|
369
|
+
style: styles$1.prompt,
|
|
370
|
+
testID: "plan-review-prompt",
|
|
371
|
+
onAccessibilityEscape: cancel,
|
|
372
|
+
children: [/* @__PURE__ */ jsxs(Button, {
|
|
373
|
+
variant: "ghost",
|
|
374
|
+
size: "card",
|
|
375
|
+
style: styles$1.header,
|
|
376
|
+
accessibilityLabel: open ? "Collapse plan review" : "Expand plan review",
|
|
377
|
+
accessibilityState: { expanded: open },
|
|
378
|
+
"aria-expanded": open,
|
|
379
|
+
onPress: () => setOpen(!open),
|
|
380
|
+
children: [
|
|
381
|
+
/* @__PURE__ */ jsx(Text, {
|
|
382
|
+
style: styles$1.label,
|
|
383
|
+
children: "Plan review"
|
|
384
|
+
}),
|
|
385
|
+
!open ? /* @__PURE__ */ jsx(Text, {
|
|
386
|
+
style: [styles$1.description, styles$1.pending],
|
|
387
|
+
children: "Awaiting decision"
|
|
388
|
+
}) : null,
|
|
389
|
+
open ? /* @__PURE__ */ jsx(ChevronDownIcon, { size: 16 }) : /* @__PURE__ */ jsx(ChevronRightIcon, { size: 16 })
|
|
390
|
+
]
|
|
391
|
+
}), open ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(ScrollView, {
|
|
392
|
+
style: styles$1.scroll,
|
|
393
|
+
contentContainerStyle: styles$1.content,
|
|
394
|
+
keyboardShouldPersistTaps: "handled",
|
|
395
|
+
children: [
|
|
396
|
+
/* @__PURE__ */ jsx(Text, {
|
|
397
|
+
style: styles$1.title,
|
|
398
|
+
accessibilityRole: "header",
|
|
399
|
+
children: dialog.title
|
|
400
|
+
}),
|
|
401
|
+
/* @__PURE__ */ jsx(Text, {
|
|
402
|
+
style: styles$1.description,
|
|
403
|
+
children: "Review the plan in the conversation before choosing what happens next."
|
|
404
|
+
}),
|
|
405
|
+
dialog.options.map((option, index) => /* @__PURE__ */ jsx(Button, {
|
|
406
|
+
variant: "outline",
|
|
407
|
+
size: "card",
|
|
408
|
+
testID: `plan-review-option-${index}`,
|
|
409
|
+
onPress: () => answer(option),
|
|
410
|
+
children: option
|
|
411
|
+
}, option))
|
|
412
|
+
]
|
|
413
|
+
}), /* @__PURE__ */ jsx(View, {
|
|
414
|
+
style: styles$1.footer,
|
|
415
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
416
|
+
variant: "ghost",
|
|
417
|
+
size: "card",
|
|
418
|
+
testID: "plan-review-cancel",
|
|
419
|
+
onPress: cancel,
|
|
420
|
+
children: "Cancel"
|
|
421
|
+
})
|
|
422
|
+
})] }) : null]
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
const styles$1 = StyleSheet.create((theme) => ({
|
|
426
|
+
prompt: {
|
|
427
|
+
flexShrink: 1,
|
|
428
|
+
margin: theme.spacing(4),
|
|
429
|
+
uni__dependencies: [0]
|
|
430
|
+
},
|
|
431
|
+
header: {
|
|
432
|
+
flexDirection: "row",
|
|
433
|
+
alignItems: "center",
|
|
434
|
+
justifyContent: "space-between",
|
|
435
|
+
paddingHorizontal: theme.spacing(3),
|
|
436
|
+
paddingVertical: theme.spacing(2),
|
|
437
|
+
borderRadius: 0,
|
|
438
|
+
uni__dependencies: [0]
|
|
439
|
+
},
|
|
440
|
+
pending: { marginLeft: "auto" },
|
|
441
|
+
label: {
|
|
442
|
+
fontFamily: fontOf(theme.fontFamily.sans),
|
|
443
|
+
fontSize: theme.fontSize.sm,
|
|
444
|
+
lineHeight: theme.lineHeight.sm,
|
|
445
|
+
fontWeight: theme.fontWeight.semibold,
|
|
446
|
+
color: theme.colors.dim,
|
|
447
|
+
uni__dependencies: [0]
|
|
448
|
+
},
|
|
449
|
+
scroll: {
|
|
450
|
+
flexGrow: 0,
|
|
451
|
+
flexShrink: 1
|
|
452
|
+
},
|
|
453
|
+
content: {
|
|
454
|
+
gap: theme.spacing(3),
|
|
455
|
+
paddingHorizontal: theme.spacing(3),
|
|
456
|
+
paddingBottom: theme.spacing(3),
|
|
457
|
+
uni__dependencies: [0]
|
|
458
|
+
},
|
|
459
|
+
title: {
|
|
460
|
+
fontFamily: fontOf(theme.fontFamily.sans),
|
|
461
|
+
fontSize: theme.fontSize.base,
|
|
462
|
+
lineHeight: theme.lineHeight.base,
|
|
463
|
+
fontWeight: theme.fontWeight.semibold,
|
|
464
|
+
color: theme.colors.hi,
|
|
465
|
+
uni__dependencies: [0]
|
|
466
|
+
},
|
|
467
|
+
description: {
|
|
468
|
+
fontFamily: fontOf(theme.fontFamily.sans),
|
|
469
|
+
fontSize: theme.fontSize.sm,
|
|
470
|
+
lineHeight: theme.lineHeight.sm,
|
|
471
|
+
color: theme.colors.dim,
|
|
472
|
+
uni__dependencies: [0]
|
|
473
|
+
},
|
|
474
|
+
footer: {
|
|
475
|
+
flexDirection: "row",
|
|
476
|
+
justifyContent: "flex-end",
|
|
477
|
+
padding: theme.spacing(2),
|
|
478
|
+
borderTopWidth: 1,
|
|
479
|
+
borderTopColor: theme.colors["border-soft"],
|
|
480
|
+
uni__dependencies: [0]
|
|
481
|
+
}
|
|
482
|
+
}));
|
|
483
|
+
//#endregion
|
|
364
484
|
//#region src/extensions/workspaces/sessions/(frontend)/tool/_lib/planToolRender.ts
|
|
485
|
+
/** Claims only the selector opened by complete_plan, on either platform. */
|
|
486
|
+
function claimsPlanReviewPrompt(dialog) {
|
|
487
|
+
return dialog.method === "select" && dialog.title === "Plan complete. What would you like to do?" && dialog.options.length === PLAN_REVIEW_OPTIONS.length && PLAN_REVIEW_OPTIONS.every((option, index) => dialog.options[index] === option);
|
|
488
|
+
}
|
|
365
489
|
const COLLAPSED_BODY_LINES = 12;
|
|
366
490
|
const PREVIEW_LENGTH = 72;
|
|
367
491
|
const EVIDENCE_LISTS = [
|
|
@@ -763,7 +887,11 @@ var plan_native_default = defineToolRenderer({
|
|
|
763
887
|
"write_plan",
|
|
764
888
|
"complete_plan"
|
|
765
889
|
],
|
|
766
|
-
message: PlanToolMessage
|
|
890
|
+
message: PlanToolMessage,
|
|
891
|
+
prompt: {
|
|
892
|
+
claims: claimsPlanReviewPrompt,
|
|
893
|
+
component: PlanReviewPrompt
|
|
894
|
+
}
|
|
767
895
|
});
|
|
768
896
|
//#endregion
|
|
769
897
|
//#region generated/native.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.mjs","names":["WebPluginSlotProps","Button","Markdown","SegmentedControl","Textarea","fontOf","PoNativeTheme","useEffect","useState","StyleSheet","PLAN_STATUS_KEY","PlanDetailView","fetchPlan","savePlan","PLAN_TAB_ID","PlanPanel","sessionId","statuses","closeTransientTab","fileTabFor","openTransientTab","detail","setDetail","error","setError","loading","setLoading","view","setView","draft","setDraft","saving","setSaving","note","setNote","revision","cancelled","then","result","ok","undefined","catch","failure","Error","message","String","save","unavailable","hash","refreshed","styles","panel","title","value","label","meta","reason","content","path","tab","actions","success","planTab","Parameters","id","create","theme","padding","spacing","gap","uni__dependencies","fontFamily","sans","fontSize","lg","lineHeight","fontWeight","color","colors","hi","sm","dim","mono","red","green","flexDirection","flexWrap","styles","WebPluginSlotProps","ListRow","fontOf","PoNativeTheme","StyleSheet","parsePlanStatus","PLAN_STATUS_KEY","planTab","PlanActivitySection","sessionId","statuses","openTransientTab","view","styles","meta","title","stamp","undefined","create","theme","fontFamily","sans","fontSize","sm","lineHeight","color","colors","dim","uni__dependencies","styles","ToolMessageRenderProps","fontOf","MessageItem","MessageItemBody","MessageItemHeader","toolTone","PoNativeTheme","StyleSheet","LineTone","planCallSummary","planFailureReason","planResultLines","ToolLine","PlanToolMessage","toolName","args","result","running","isError","summary","collapsed","expanded","isPartial","full","reason","primary","detail","secondary","metadata","length","action","styles","undefined","sans","join","error","lines","map","entry","index","String","text","ToneLine","TONE_STYLE","tone","bold","indent","EvidenceGroup","label","values","evidenceGroups","groups","push","slice","trimStart","EvidenceBody","status","facts","evidence","group","value","create","theme","flex","flexDirection","alignItems","gap","spacing","minWidth","uni__dependencies","fontFamily","fontSize","base","lineHeight","flexShrink","maxWidth","color","colors","faint","paddingTop","borderTopWidth","borderTopColor","sm","fontWeight","semibold","dim","paddingLeft","red","hi","muted","success","green","warning","yellow","accent","blue","Readonly","Record","activityGroupPlan","fillPlan","toolPlan"],"sources":["../../src/types/planApi.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.native.ts","../../src/types/apiRoutes.ts","../../generated/client.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/planApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanActivitySection.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/planToolRender.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanToolMessage.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/plan.native.tsx","../../generated/native.ts"],"sourcesContent":["/**\n * The wire vocabulary this package's API shares with whatever calls it.\n *\n * It lives under src/types because that is the one server root a browser\n * bundle may read: the routes answer with these shapes and the cockpit plugin\n * reads them, so neither half can drift from the other. The paths themselves\n * are not here; they are declared once in `./apiRoutes`, which the Hono app\n * and the generated client both read.\n *\n * Two routes, and neither takes a path. A session has one current plan, so\n * `current` answers it and `content` takes the manual save back; the file they\n * act on is the one write_plan recorded, never one the page named. That is\n * also why there is nothing to escape here: a reader cannot address a second\n * file through these URLs.\n */\n\n/** Where a host mounts this package's API; the segment after /api/plugins/. */\nexport const API_BASE_PATH = 'plans';\n\n/**\n * Footer status key the session publishes once a plan exists, which is what\n * makes the cockpit's activity group appear at all. It outlives plan mode: the\n * plan is most worth reading while the agent implements it.\n */\nexport const PLAN_STATUS_KEY = 'po-plan-document';\n\n/** The selector contract shared by complete_plan and its cockpit composer prompt. */\nexport const PLAN_REVIEW_TITLE = 'Plan complete. What would you like to do?';\nexport const EXIT_PLAN_MODE_CHOICE = 'Exit plan mode and start implementation';\nexport const CONTINUE_PLANNING_CHOICE = 'Continue planning';\nexport const EXIT_PLAN_DECISION = 'exit';\nexport const CONTINUE_PLAN_DECISION = 'continue';\n\n/**\n * The label the reader sees paired with the decision the tool acts on. A headless\n * client answers with `value`, so a server plugin never has to recognise the wording; Pi's\n * own `ui.select` carries labels only, so its half maps the label back itself.\n */\nexport const PLAN_REVIEW_CHOICES = [\n { label: EXIT_PLAN_MODE_CHOICE, value: EXIT_PLAN_DECISION },\n { label: CONTINUE_PLANNING_CHOICE, value: CONTINUE_PLAN_DECISION },\n] as const;\n\n/** The same options as bare labels, which is all Pi's select and the composer prompt need. */\nexport const PLAN_REVIEW_OPTIONS = PLAN_REVIEW_CHOICES.map((choice) => choice.label);\n\n/** Between the plan's title and the stamp that marks a rewrite. */\nconst STATUS_SEPARATOR = ' · ';\n\n/** Strips the colour a session may have themed a status with. */\nconst ANSI = /\u001b\\[[0-9;]*m/gu;\n\n/** The status line the session publishes; the stamp changes on every write. */\nexport function formatPlanStatus(title: string, stamp: string): string {\n return `${title}${STATUS_SEPARATOR}${stamp}`;\n}\n\n/** What a reader gets out of the status line. */\nexport interface PlanStatusView {\n title: string;\n /** When the plan was last written, as the session worded it; empty when it said nothing. */\n stamp: string;\n}\n\n/**\n * Reading the status line back. Statuses reach a plugin raw, so the colour a\n * session may have added comes off here. A title can itself contain the\n * separator, so the stamp is taken from the last one rather than the first.\n */\nexport function parsePlanStatus(raw: string | undefined): PlanStatusView | undefined {\n if (raw === undefined) return undefined;\n const text = raw.replace(ANSI, '').trim();\n if (text === '') return undefined;\n const cut = text.lastIndexOf(STATUS_SEPARATOR);\n if (cut === -1) return { title: text, stamp: '' };\n return { title: text.slice(0, cut).trim(), stamp: text.slice(cut + STATUS_SEPARATOR.length).trim() };\n}\n\n/**\n * What write_plan recorded about this session's plan.\n *\n * The absolute path is the point of it: the extension resolves the plans\n * directory against the harness root, which no other process knows, so it\n * writes down where the plan landed rather than leaving the API to derive a\n * location it would sometimes get wrong.\n */\nexport interface PlanPointerRecord {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n}\n\n/** The plan as it stands on disk right now, which is what the source view edits. */\nexport interface PlanDetailView {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n content: string;\n /** sha256 of the content; the token a save hands back to prove it is not stale. */\n hash: string;\n /** True when the plan is missing or past the size cap, so `content` is empty. */\n unavailable: boolean;\n reason?: string;\n}\n\n/** What the save route takes. */\nexport interface PlanSaveRequest {\n /** The hash the reader loaded; a mismatch means the plan moved underneath them. */\n expectedHash: string;\n content: string;\n}\n\n/** What the save route answers with. */\nexport interface PlanSaveView {\n hash: string;\n}\n\n/** What a route reports when it refuses; the page shows `error` verbatim. */\nexport interface PlanErrorView {\n error: string;\n /** On a stale save, the hash the plan actually has now. */\n hash?: string;\n}\n","import { defineActivityGroup } from '@agimon-ai/po-core/native';\n\nimport { PLAN_STATUS_KEY } from '../../../../../types/planApi';\n\n// Keyed off the saved plan rather than the mode because the plan remains useful\n// while it is being implemented after the read-only mode exits.\nexport default defineActivityGroup({\n name: 'plan',\n keys: 'p e',\n statusKey: PLAN_STATUS_KEY,\n marksBackgroundWork: false,\n order: 25,\n});\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport type { PlanDetailView, PlanSaveView } from './planApi';\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/workspaces/sessions/(backend)/api/plans/`, so the mount is\n * stated once, by the folder that creates it. The paths used to be written\n * here as helpers, again in the contract, and again inside every URL the page\n * built, and the copies were free to disagree.\n *\n * This is the one file the routes, the Hono app and the browser all read, so a\n * path cannot move on one side alone.\n *\n * Neither route takes a query or a path parameter: a session has one current\n * plan, so `current` answers it and `save` takes the manual write back.\n */\nconst routes = {\n current: {\n method: 'GET',\n path: '/current',\n response: undefined as unknown as ApiResponseOf<PlanDetailView>,\n },\n save: {\n method: 'PUT',\n path: '/content',\n response: undefined as unknown as ApiResponseOf<PlanSaveView>,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\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 'plans' at. */\nexport const apiScopes = ['session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'plans',\n transport: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client.native';\nimport type { PlanDetailView } from '../../../../../../types/planApi';\n\n/**\n * The page's half of this package's session API: the current plan, and the\n * manual save.\n *\n * These are adapters now, not a transport. The generated client owns the URL\n * and the sealed transport with it, so nothing here spells a route or reaches\n * for `fetch`. What stays is this package's own vocabulary: which refusals the\n * reader is shown, and the stale-save contract the editor depends on.\n */\n\nconst UNREACHABLE = 'The session is unreachable.';\nconst NO_PLAN = 'This session has not written a plan yet.';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The message a reader is shown: the route's own words, or why there were none. */\nfunction messageOf(result: { status: number; error: string }): string {\n if (result.status === 0) return UNREACHABLE;\n return result.error === '' ? `The session answered ${String(result.status)}.` : result.error;\n}\n\nexport type FetchPlanResult = { ok: true; detail: PlanDetailView } | { ok: false; error: string };\n\nexport async function fetchPlan(sessionId: string): Promise<FetchPlanResult> {\n const result = await api.session(sessionId).current();\n // A session that has written nothing answers 404, which is not a failure the\n // reader should be shown as one.\n if (result.status === 404) return { ok: false, error: result.ok || result.error === '' ? NO_PLAN : result.error };\n if (!result.ok) return { ok: false, error: messageOf(result) };\n if (!isRecord(result.data)) return { ok: false, error: 'The session answered with no plan.' };\n return { ok: true, detail: result.data };\n}\n\nexport type SavePlanResult =\n | { ok: true; hash: string }\n /** The plan moved under the editor; `hash` is what it holds now. */\n | { ok: false; stale: true; error: string; hash?: string }\n | { ok: false; stale: false; error: string };\n\nexport async function savePlan(sessionId: string, expectedHash: string, content: string): Promise<SavePlanResult> {\n const result = await api.session(sessionId).save({ body: { expectedHash, content } });\n // The agent can rewrite the plan while a reader is still editing it. A moved\n // hash is the one refusal the editor recovers from, so it is read before the\n // generic failure.\n if (result.status === 409) {\n const data = result.ok ? undefined : result.data;\n const hash = isRecord(data) && typeof data.hash === 'string' ? data.hash : undefined;\n return {\n ok: false,\n stale: true,\n error: result.ok ? 'The plan changed since it was opened.' : messageOf(result),\n ...(hash === undefined ? {} : { hash }),\n };\n }\n if (!result.ok) return { ok: false, stale: false, error: messageOf(result) };\n return { ok: true, hash: isRecord(result.data) && typeof result.data.hash === 'string' ? result.data.hash : '' };\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { Button, Markdown, SegmentedControl, Textarea, fontOf } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useEffect, useState } from 'react';\nimport { ScrollView, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { PLAN_STATUS_KEY, type PlanDetailView } from '../../../../../../types/planApi';\nimport { fetchPlan, savePlan } from '../_lib/planApi.native';\n\nexport const PLAN_TAB_ID = 'plan-document';\n\n/** The saved plan, with edits guarded by its on-disk hash, never a caller-supplied path. */\nexport function PlanPanel({\n sessionId,\n statuses,\n closeTransientTab,\n fileTabFor,\n openTransientTab,\n}: WebPluginSlotProps) {\n const [detail, setDetail] = useState<PlanDetailView>();\n const [error, setError] = useState<string>();\n const [loading, setLoading] = useState(true);\n const [view, setView] = useState('preview');\n const [draft, setDraft] = useState<string>();\n const [saving, setSaving] = useState(false);\n const [note, setNote] = useState<string>();\n const revision = statuses[PLAN_STATUS_KEY];\n useEffect(() => {\n if (sessionId === null) return;\n let cancelled = false;\n void fetchPlan(sessionId)\n .then((result) => {\n if (cancelled) return;\n setLoading(false);\n if (result.ok) {\n setDetail(result.detail);\n setError(undefined);\n setDraft(undefined);\n setNote(undefined);\n } else {\n setDetail(undefined);\n setError(result.error);\n }\n })\n .catch((failure: unknown) => {\n if (!cancelled) {\n setLoading(false);\n setError(failure instanceof Error ? failure.message : String(failure));\n }\n });\n return () => {\n cancelled = true;\n };\n }, [sessionId, revision]);\n\n const save = async () => {\n if (sessionId === null || !detail || draft === undefined || detail.unavailable || saving) return;\n setSaving(true);\n try {\n const result = await savePlan(sessionId, detail.hash, draft);\n if (!result.ok) {\n setNote(result.error);\n return;\n }\n setNote('saved');\n const refreshed = await fetchPlan(sessionId);\n if (refreshed.ok) {\n setDetail(refreshed.detail);\n setDraft(undefined);\n } else setError(refreshed.error);\n } catch (failure) {\n setNote(failure instanceof Error ? failure.message : String(failure));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <ScrollView contentContainerStyle={styles.panel} testID=\"plan-panel\">\n <Text style={styles.title}>{detail?.title ?? 'plan'}</Text>\n <SegmentedControl\n accessibilityLabel=\"plan view\"\n options={[\n { value: 'preview', label: 'preview' },\n { value: 'source', label: 'source' },\n ]}\n value={view}\n onValueChange={setView}\n />\n {sessionId === null ? (\n <Text style={styles.meta}>Select a session.</Text>\n ) : loading && !detail ? (\n <Text style={styles.meta}>reading this session's plan…</Text>\n ) : null}\n {error ? (\n <Text accessibilityRole=\"alert\" style={styles.error}>\n {error}\n </Text>\n ) : null}\n {detail ? (\n detail.unavailable ? (\n <Text style={styles.meta}>{detail.reason ?? 'this plan cannot be shown'}</Text>\n ) : view === 'preview' ? (\n <Markdown\n text={draft ?? detail.content}\n onFileLink={(path) => {\n const tab = fileTabFor(path);\n return tab ? () => openTransientTab(tab) : undefined;\n }}\n />\n ) : (\n <>\n <Textarea\n accessibilityLabel=\"plan source\"\n value={draft ?? detail.content}\n onChangeText={setDraft}\n numberOfLines={12}\n />\n <View style={styles.actions}>\n <Button variant=\"primary\" disabled={draft === undefined || saving} onPress={() => void save()}>\n save to disk\n </Button>\n {draft !== undefined ? (\n <Button variant=\"ghost\" onPress={() => setDraft(undefined)}>\n discard edits\n </Button>\n ) : null}\n </View>\n {note ? <Text style={note === 'saved' ? styles.success : styles.error}>{note}</Text> : null}\n </>\n )\n ) : null}\n {detail ? (\n <Text selectable style={styles.path}>\n {detail.path}\n </Text>\n ) : null}\n <Button variant=\"ghost\" onPress={() => closeTransientTab(PLAN_TAB_ID)}>\n close\n </Button>\n </ScrollView>\n );\n}\n\nexport function planTab(): Parameters<WebPluginSlotProps['openTransientTab']>[0] {\n return { id: PLAN_TAB_ID, label: 'plan', panel: PlanPanel };\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { padding: theme.spacing(4), gap: theme.spacing(3) },\n title: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.lg,\n lineHeight: theme.lineHeight.lg,\n fontWeight: '600',\n color: theme.colors.hi,\n },\n meta: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm, color: theme.colors.dim },\n path: { fontFamily: fontOf(theme.fontFamily.mono), fontSize: theme.fontSize.sm, color: theme.colors.dim },\n error: { fontSize: theme.fontSize.sm, color: theme.colors.red },\n success: { fontSize: theme.fontSize.sm, color: theme.colors.green },\n actions: { flexDirection: 'row', flexWrap: 'wrap', gap: theme.spacing(2) },\n}));\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { ListRow, fontOf } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { parsePlanStatus, PLAN_STATUS_KEY } from '../../../../../../types/planApi';\nimport { planTab } from './PlanPanel.native';\n\n/** The document row, not its group header, is the way into a saved plan. */\nexport function PlanActivitySection({ sessionId, statuses, openTransientTab }: WebPluginSlotProps) {\n const view = parsePlanStatus(statuses[PLAN_STATUS_KEY]);\n if (!view) return <Text style={styles.meta}>no plan written yet</Text>;\n return (\n <View testID=\"activity-plan\">\n <ListRow\n title={view.title}\n description={view.stamp || undefined}\n disabled={sessionId === null}\n onPress={() => {\n if (sessionId !== null) openTransientTab(planTab());\n }}\n />\n <Text style={styles.meta}>open to read or edit; the agent reads what you save.</Text>\n </View>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n meta: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n color: theme.colors.dim,\n },\n}));\n","import { defineFill } from '@agimon-ai/po-core/native';\n\nimport { PlanActivitySection } from './_components/PlanActivitySection.native';\n\nexport default defineFill({ slot: 'activity.plan', id: 'plan', component: PlanActivitySection });\n","import type { ToolResultView } from '@agimon-ai/po-core/web';\nimport type { MessageLine, MessageLineTone } from '@agimon-ai/po-web-components';\n\n/**\n * Purpose-first summaries for the plan-mode tools. The TUI leaves these on\n * Pi's default shell, so the shapes here come straight from the tool\n * definitions in src/services/planServerSession/index.ts: write_plan and complete_plan\n * report through `details` (written, path, phase, exited), run_fable_plan\n * carries the broker result, and record_debug_evidence only confirms.\n */\n\nexport const PLAN_TOOL_NAMES = ['record_debug_evidence', 'run_fable_plan', 'write_plan', 'complete_plan'] as const;\n\n/** The toned lines the shared MessageLines draws; the vocabulary is the components package's. */\nexport type LineTone = MessageLineTone;\n/** `label` names an evidence field the text leads with, so a layout can set it apart without parsing the text. */\nexport type ToolLine = MessageLine & { label?: string };\n\nexport interface PlanCallSummary {\n action: string;\n detail?: string;\n metadata: string[];\n}\n\nexport interface PlanRenderOptions {\n expanded: boolean;\n isError: boolean;\n isPartial: boolean;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nconst COLLAPSED_BODY_LINES = 12;\nconst PREVIEW_LENGTH = 72;\n\nconst EVIDENCE_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['logs', 'log'],\n ['correlatedTraceEvidence', 'trace'],\n ['processOutput', 'process output'],\n ['browserConsoleEvidence', 'console entry'],\n ['correlationIds', 'correlation id'],\n ['timestamps', 'timestamp'],\n ['verifiedFacts', 'verified fact'],\n ['hypotheses', 'hypothesis'],\n ['unavailableEvidence', 'unavailable item'],\n];\n\nconst PACKET_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['goal', 'goal'],\n ['constraints', 'constraint'],\n ['decisions', 'decision'],\n ['verifiedFindings', 'verified finding'],\n ['inferredFindings', 'inferred finding'],\n ['unresolvedQuestions', 'open question'],\n];\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? (value as JsonRecord) : undefined;\n}\n\nfunction inlineText(value: string): string {\n let normalized = '';\n for (const character of value) {\n const code = character.codePointAt(0) ?? 0;\n normalized += code <= 31 || code === 127 ? ' ' : character;\n }\n return normalized.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction readString(record: JsonRecord | undefined, key: string): string | undefined {\n const value = record?.[key];\n return typeof value === 'string' ? inlineText(value) || undefined : undefined;\n}\n\nfunction readNumber(record: JsonRecord | undefined, key: string): number | undefined {\n const value = record?.[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction listLength(record: JsonRecord, key: string): number {\n const value = record[key];\n return Array.isArray(value) ? value.length : 0;\n}\n\nfunction plural(count: number, singular: string): string {\n if (count === 1) return singular;\n if (singular.endsWith('y')) return `${singular.slice(0, -1)}ies`;\n return `${singular}s`;\n}\n\nfunction preview(value: string | undefined): string | undefined {\n if (!value) return undefined;\n return value.length > PREVIEW_LENGTH ? `${value.slice(0, PREVIEW_LENGTH - 3)}…` : value;\n}\n\nfunction countMetadata(args: JsonRecord, lists: ReadonlyArray<[string, string]>): string[] {\n return lists.flatMap(([key, label]) => {\n const count = listLength(args, key);\n return count > 0 ? [`${count} ${plural(count, label)}`] : [];\n });\n}\n\nfunction line(text: string, tone: LineTone, extra: Omit<ToolLine, 'text' | 'tone'> = {}): ToolLine {\n return { text, tone, ...extra };\n}\n\nfunction outputText(result: ToolResultView | null): string {\n if (!result) return '';\n return result.content\n .flatMap((item) => {\n const record = asRecord(item);\n return record?.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n })\n .join('\\n');\n}\n\nfunction bodyLines(text: string, expanded: boolean): ToolLine[] {\n const all = text\n .split('\\n')\n .map((entry) => entry.trimEnd())\n .filter((entry) => entry.length > 0);\n const shown = expanded ? all : all.slice(0, COLLAPSED_BODY_LINES);\n const lines = shown.map((entry) => line(entry, 'text'));\n if (all.length > shown.length) lines.push(line(`… ${all.length - shown.length} more lines`, 'dim'));\n return lines;\n}\n\n/** The header beside the tool name: what the call is for and how much it carries. */\nexport function planCallSummary(toolName: string, args: JsonRecord): PlanCallSummary {\n if (toolName === 'record_debug_evidence') {\n const issue = preview(readString(args, 'issue'));\n return {\n action: 'record evidence',\n ...(issue ? { detail: issue } : {}),\n metadata: countMetadata(args, EVIDENCE_LISTS),\n };\n }\n if (toolName === 'run_fable_plan') {\n const metadata = countMetadata(args, PACKET_LISTS);\n if (readString(args, 'currentPlan')) metadata.push('with current plan');\n return { action: 'fable draft', metadata };\n }\n if (toolName === 'write_plan') return { action: 'save plan', metadata: [] };\n const decision = readString(args, 'decision');\n return { action: decision ? `decide ${decision}` : 'request approval', metadata: [] };\n}\n\nfunction evidenceLines(args: JsonRecord, result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const recorded = asRecord(result?.details)?.recorded === true;\n const lines = [\n recorded\n ? line('✓ evidence recorded as planning context', 'success')\n : line(`○ ${inlineText(outputText(result)) || 'not recorded'}`, 'muted'),\n ];\n if (!options.expanded) return lines;\n const fields: ReadonlyArray<[string, string]> = [\n ['issue', 'issue'],\n ['expectedBehavior', 'expected'],\n ['reproductionAttempt', 'reproduction'],\n ['actualBehavior', 'actual'],\n ];\n for (const [key, label] of fields) {\n const value = readString(args, key);\n if (value) lines.push(line(`${label} ${value}`, 'text', { label }));\n }\n for (const [key, label] of EVIDENCE_LISTS) {\n const raw = args[key];\n const items = Array.isArray(raw) ? raw.filter((item): item is string => typeof item === 'string') : [];\n if (items.length === 0) continue;\n lines.push(line(plural(items.length, label), 'hi', { bold: true }));\n lines.push(...items.map((item) => line(inlineText(item), 'text', { indent: true })));\n }\n return lines;\n}\n\nfunction fableLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const text = outputText(result);\n if (details?.started !== true) {\n const code = readString(details, 'errorCode');\n return [line(`○ ${inlineText(text) || 'fable planning did not start'}${code ? ` · ${code}` : ''}`, 'muted')];\n }\n const status = readString(details, 'status') ?? 'unknown';\n const draft = typeof details?.draft === 'string' ? details.draft : undefined;\n const code = readString(details, 'errorCode');\n if (!draft) return [line(`✗ fable planning ${status}${code ? ` · ${code}` : ''}`, 'error')];\n const finished = status === 'completed';\n return [\n line(\n `${finished ? '✓' : '!'} fable draft · ${status}${code ? ` · ${code}` : ''}`,\n finished ? 'success' : 'warning',\n {\n bold: true,\n },\n ),\n ...bodyLines(draft, options.expanded),\n ];\n}\n\nfunction writeLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const path = readString(details, 'path');\n if (options.isPartial) {\n const phase = readString(details, 'phase') ?? 'checking';\n return [line(`◐ ${phase}${path ? ` ${path}` : ''}`, 'warning')];\n }\n const duration = readNumber(details, 'durationMs');\n if (details?.written === true) {\n return [line(`✓ wrote ${path ?? 'the plan'}${duration === undefined ? '' : ` · ${duration}ms`}`, 'success')];\n }\n const lines = [line(`○ ${inlineText(outputText(result)) || 'plan not written'}`, 'muted')];\n if (path) lines.push(line(`path ${path}`, 'dim'));\n return lines;\n}\n\nfunction completeLines(result: ToolResultView | null): ToolLine[] {\n const text = inlineText(outputText(result));\n if (asRecord(result?.details)?.exited === true) {\n return [line(`✓ plan mode exited${text ? ` · ${text}` : ''}`, 'success')];\n }\n return [line(`○ staying in plan mode${text ? ` · ${text}` : ''}`, 'muted')];\n}\n\n/** Why a plan tool call failed, as the tool said it on one line; empty when it said nothing. */\nexport function planFailureReason(result: ToolResultView | null): string {\n return inlineText(outputText(result));\n}\n\n/** The body of a plan tool card: the outcome line, plus the carried detail once expanded. */\nexport function planResultLines(\n toolName: string,\n args: JsonRecord,\n result: ToolResultView | null,\n options: PlanRenderOptions,\n): ToolLine[] {\n if (options.isError) {\n return [line(`✗ ${planFailureReason(result) || `${toolName} failed`}`, 'error')];\n }\n if (toolName === 'record_debug_evidence') return evidenceLines(args, result, options);\n if (toolName === 'run_fable_plan') {\n if (options.isPartial) return [line('◐ drafting with the local Fable broker', 'warning')];\n return fableLines(result, options);\n }\n if (toolName === 'write_plan') return writeLines(result, options);\n if (options.isPartial) return [line('◐ waiting for the review decision', 'warning')];\n return completeLines(result);\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/native';\nimport { fontOf, MessageItem, MessageItemBody, MessageItemHeader, toolTone } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport {\n type LineTone,\n planCallSummary,\n planFailureReason,\n planResultLines,\n type ToolLine,\n} from '../_lib/planToolRender';\n\n/**\n * The plan tools' timeline item on native, as the web's: the plan action as\n * the title, the issue and what the packet carries beside it on one line, and\n * the outcome line in the body (shown collapsed too, as the web does), with\n * the recorded evidence or the Fable draft once expanded. A failure shows only the tool's reason; the edge and icon say it failed.\n */\nexport function PlanToolMessage({ toolName, args, result, running, isError }: ToolMessageRenderProps) {\n const summary = planCallSummary(toolName, args);\n const collapsed = planResultLines(toolName, args, result, { expanded: false, isError, isPartial: running });\n const full = planResultLines(toolName, args, result, { expanded: true, isError, isPartial: running });\n const reason = isError ? planFailureReason(result) : '';\n // The issue is what the call is about, so it leads; the counts are the detail that yields first.\n const primary = summary.detail;\n const secondary = summary.metadata;\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={!isError && full.length > collapsed.length}>\n {({ expanded }) => (\n <>\n <MessageItemHeader title={summary.action}>\n <View testID={`tool-call-${toolName}`} style={styles.summary}>\n {primary !== undefined ? (\n <Text numberOfLines={1} style={[styles.sans, styles.primary]}>\n {primary}\n </Text>\n ) : null}\n {secondary.length > 0 ? (\n <Text numberOfLines={1} style={[styles.sans, styles.secondary]}>\n {primary !== undefined ? `· ${secondary.join(' · ')}` : secondary.join(' · ')}\n </Text>\n ) : null}\n </View>\n </MessageItemHeader>\n {isError ? (\n reason.length > 0 ? (\n <MessageItemBody testID={`tool-result-${toolName}`}>\n <Text selectable style={[styles.sans, styles.error]}>\n {reason}\n </Text>\n </MessageItemBody>\n ) : null\n ) : expanded && toolName === 'record_debug_evidence' && full.length > 1 ? (\n <MessageItemBody testID={`tool-result-${toolName}`}>\n <EvidenceBody lines={full} />\n </MessageItemBody>\n ) : (expanded ? full : collapsed).length > 0 ? (\n <MessageItemBody testID={`tool-result-${toolName}`}>\n <View style={styles.lines}>\n {(expanded ? full : collapsed).map((entry, index) => (\n <ToneLine key={`${String(index)}-${entry.text}`} entry={entry} />\n ))}\n </View>\n </MessageItemBody>\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n\nfunction ToneLine({ entry }: { entry: ToolLine }) {\n return (\n <Text\n selectable\n style={[\n styles.sans,\n TONE_STYLE[entry.tone],\n entry.bold === true ? styles.bold : null,\n entry.indent === true ? styles.indent : null,\n ]}\n >\n {entry.text}\n </Text>\n );\n}\n\ninterface EvidenceGroup {\n label: string;\n values: string[];\n}\n\n/*\n * The shared lines name each evidence field in `label`, carry list labels as\n * bold lines, and list items as indented lines; the phone regroups them so\n * every label sits in one style above its values.\n */\nfunction evidenceGroups(lines: readonly ToolLine[]): EvidenceGroup[] {\n const groups: EvidenceGroup[] = [];\n for (const entry of lines) {\n if (entry.bold === true) groups.push({ label: entry.text, values: [] });\n else if (entry.indent === true && groups.length > 0) groups[groups.length - 1]?.values.push(entry.text);\n else if (entry.label !== undefined)\n groups.push({ label: entry.label, values: [entry.text.slice(entry.label.length).trimStart()] });\n else groups.push({ label: entry.text, values: [] });\n }\n return groups;\n}\n\n/** The expanded evidence: the outcome line, then each label over its values, set apart from the outcome. */\nfunction EvidenceBody({ lines }: { lines: readonly ToolLine[] }) {\n const [status, ...facts] = lines;\n return (\n <View style={styles.evidence}>\n {status !== undefined ? <ToneLine entry={status} /> : null}\n <View style={styles.facts}>\n {evidenceGroups(facts).map((group) => (\n <View key={group.label} style={styles.group}>\n <Text style={styles.label}>{group.label}</Text>\n {group.values.map((value, index) => (\n <Text key={`${String(index)}-${value}`} selectable style={[styles.sans, styles.text]}>\n {value}\n </Text>\n ))}\n </View>\n ))}\n </View>\n </View>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n // One line on the title's row: the issue stays whole up to most of the row, the counts truncate first.\n summary: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n sans: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n primary: { flexShrink: 0, maxWidth: '70%', color: theme.colors.text },\n secondary: { flexShrink: 1, color: theme.colors.faint },\n lines: { gap: theme.spacing(0.5) },\n evidence: { gap: theme.spacing(3) },\n facts: {\n gap: theme.spacing(3),\n paddingTop: theme.spacing(3),\n borderTopWidth: 1,\n borderTopColor: theme.colors['border-soft'],\n },\n group: { gap: theme.spacing(0.5) },\n label: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n fontWeight: theme.fontWeight.semibold,\n color: theme.colors.dim,\n },\n bold: { fontWeight: theme.fontWeight.semibold },\n indent: { paddingLeft: theme.spacing(4) },\n error: { color: theme.colors.red },\n hi: { color: theme.colors.hi },\n text: { color: theme.colors.text },\n dim: { color: theme.colors.dim },\n muted: { color: theme.colors.faint },\n success: { color: theme.colors.green },\n warning: { color: theme.colors.yellow },\n accent: { color: theme.colors.blue },\n}));\n\n/** The line tones of the web's MessageLines, drawn with the same theme tokens. */\nconst TONE_STYLE: Readonly<Record<LineTone, object>> = {\n hi: styles.hi,\n text: styles.text,\n dim: styles.dim,\n muted: styles.muted,\n success: styles.success,\n error: styles.error,\n warning: styles.warning,\n accent: styles.accent,\n};\n","import { defineToolRenderer } from '@agimon-ai/po-core/native';\n\nimport { PlanToolMessage } from './_components/PlanToolMessage.native';\nimport type { PLAN_TOOL_NAMES } from './_lib/planToolRender';\n\n/*\n * The phone half of plan.web.tsx: one card for every plan tool. The names are\n * spelled out because the native renderer check reads only `.native.` files;\n * `satisfies` keeps them to the shared PLAN_TOOL_NAMES list.\n */\nexport default defineToolRenderer({\n tools: ['record_debug_evidence', 'run_fable_plan', 'write_plan', 'complete_plan'] satisfies Array<\n (typeof PLAN_TOOL_NAMES)[number]\n >,\n message: PlanToolMessage,\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 activityGroupPlan from '../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.native';\nimport fillPlan from '../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.native';\nimport toolPlan from '../src/extensions/workspaces/sessions/(frontend)/tool/plan.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: 'plan',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'plan' }, activityGroupPlan)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.plan', id: 'plan' }, fillPlan)]; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['plan'] }, toolPlan)]; },\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"native.mjs","names":["WebPluginSlotProps","Button","Markdown","SegmentedControl","Textarea","fontOf","PoNativeTheme","useEffect","useState","StyleSheet","PLAN_STATUS_KEY","PlanDetailView","fetchPlan","savePlan","PLAN_TAB_ID","PlanPanel","sessionId","statuses","closeTransientTab","fileTabFor","openTransientTab","detail","setDetail","error","setError","loading","setLoading","view","setView","draft","setDraft","saving","setSaving","note","setNote","revision","cancelled","then","result","ok","undefined","catch","failure","Error","message","String","save","unavailable","hash","refreshed","styles","panel","title","value","label","meta","reason","content","path","tab","actions","success","planTab","Parameters","id","create","theme","padding","spacing","gap","uni__dependencies","fontFamily","sans","fontSize","lg","lineHeight","fontWeight","color","colors","hi","sm","dim","mono","red","green","flexDirection","flexWrap","styles","WebPluginSlotProps","ListRow","fontOf","PoNativeTheme","StyleSheet","parsePlanStatus","PLAN_STATUS_KEY","planTab","PlanActivitySection","sessionId","statuses","openTransientTab","view","styles","meta","title","stamp","undefined","create","theme","fontFamily","sans","fontSize","sm","lineHeight","color","colors","dim","uni__dependencies","styles","ToolPromptRenderProps","Button","ChevronDownIcon","ChevronRightIcon","fontOf","Panel","PoNativeTheme","useState","StyleSheet","PlanReviewPrompt","dialog","answer","cancel","defaultExpanded","open","setOpen","styles","prompt","header","expanded","label","description","pending","scroll","content","title","options","map","option","index","footer","create","theme","flexShrink","margin","spacing","uni__dependencies","flexDirection","alignItems","justifyContent","paddingHorizontal","paddingVertical","borderRadius","marginLeft","fontFamily","sans","fontSize","sm","lineHeight","fontWeight","semibold","color","colors","dim","flexGrow","gap","paddingBottom","base","hi","padding","borderTopWidth","borderTopColor","styles","ToolMessageRenderProps","fontOf","MessageItem","MessageItemBody","MessageItemHeader","toolTone","PoNativeTheme","StyleSheet","LineTone","planCallSummary","planFailureReason","planResultLines","ToolLine","PlanToolMessage","toolName","args","result","running","isError","summary","collapsed","expanded","isPartial","full","reason","primary","detail","secondary","metadata","length","action","styles","undefined","sans","join","error","lines","map","entry","index","String","text","ToneLine","TONE_STYLE","tone","bold","indent","EvidenceGroup","label","values","evidenceGroups","groups","push","slice","trimStart","EvidenceBody","status","facts","evidence","group","value","create","theme","flex","flexDirection","alignItems","gap","spacing","minWidth","uni__dependencies","fontFamily","fontSize","base","lineHeight","flexShrink","maxWidth","color","colors","faint","paddingTop","borderTopWidth","borderTopColor","sm","fontWeight","semibold","dim","paddingLeft","red","hi","muted","success","green","warning","yellow","accent","blue","Readonly","Record","activityGroupPlan","fillPlan","toolPlan"],"sources":["../../src/types/planApi.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.native.ts","../../src/types/apiRoutes.ts","../../generated/client.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/planApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanActivitySection.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanReviewPrompt.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/planToolRender.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanToolMessage.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/plan.native.tsx","../../generated/native.ts"],"sourcesContent":["/**\n * The wire vocabulary this package's API shares with whatever calls it.\n *\n * It lives under src/types because that is the one server root a browser\n * bundle may read: the routes answer with these shapes and the cockpit plugin\n * reads them, so neither half can drift from the other. The paths themselves\n * are not here; they are declared once in `./apiRoutes`, which the Hono app\n * and the generated client both read.\n *\n * Two routes, and neither takes a path. A session has one current plan, so\n * `current` answers it and `content` takes the manual save back; the file they\n * act on is the one write_plan recorded, never one the page named. That is\n * also why there is nothing to escape here: a reader cannot address a second\n * file through these URLs.\n */\n\n/** Where a host mounts this package's API; the segment after /api/plugins/. */\nexport const API_BASE_PATH = 'plans';\n\n/**\n * Footer status key the session publishes once a plan exists, which is what\n * makes the cockpit's activity group appear at all. It outlives plan mode: the\n * plan is most worth reading while the agent implements it.\n */\nexport const PLAN_STATUS_KEY = 'po-plan-document';\n\n/** The selector contract shared by complete_plan and its cockpit composer prompt. */\nexport const PLAN_REVIEW_TITLE = 'Plan complete. What would you like to do?';\nexport const EXIT_PLAN_MODE_CHOICE = 'Exit plan mode and start implementation';\nexport const CONTINUE_PLANNING_CHOICE = 'Continue planning';\nexport const EXIT_PLAN_DECISION = 'exit';\nexport const CONTINUE_PLAN_DECISION = 'continue';\n\n/**\n * The label the reader sees paired with the decision the tool acts on. A headless\n * client answers with `value`, so a server plugin never has to recognise the wording; Pi's\n * own `ui.select` carries labels only, so its half maps the label back itself.\n */\nexport const PLAN_REVIEW_CHOICES = [\n { label: EXIT_PLAN_MODE_CHOICE, value: EXIT_PLAN_DECISION },\n { label: CONTINUE_PLANNING_CHOICE, value: CONTINUE_PLAN_DECISION },\n] as const;\n\n/** The same options as bare labels, which is all Pi's select and the composer prompt need. */\nexport const PLAN_REVIEW_OPTIONS = PLAN_REVIEW_CHOICES.map((choice) => choice.label);\n\n/** Between the plan's title and the stamp that marks a rewrite. */\nconst STATUS_SEPARATOR = ' · ';\n\n/** Strips the colour a session may have themed a status with. */\nconst ANSI = /\u001b\\[[0-9;]*m/gu;\n\n/** The status line the session publishes; the stamp changes on every write. */\nexport function formatPlanStatus(title: string, stamp: string): string {\n return `${title}${STATUS_SEPARATOR}${stamp}`;\n}\n\n/** What a reader gets out of the status line. */\nexport interface PlanStatusView {\n title: string;\n /** When the plan was last written, as the session worded it; empty when it said nothing. */\n stamp: string;\n}\n\n/**\n * Reading the status line back. Statuses reach a plugin raw, so the colour a\n * session may have added comes off here. A title can itself contain the\n * separator, so the stamp is taken from the last one rather than the first.\n */\nexport function parsePlanStatus(raw: string | undefined): PlanStatusView | undefined {\n if (raw === undefined) return undefined;\n const text = raw.replace(ANSI, '').trim();\n if (text === '') return undefined;\n const cut = text.lastIndexOf(STATUS_SEPARATOR);\n if (cut === -1) return { title: text, stamp: '' };\n return { title: text.slice(0, cut).trim(), stamp: text.slice(cut + STATUS_SEPARATOR.length).trim() };\n}\n\n/**\n * What write_plan recorded about this session's plan.\n *\n * The absolute path is the point of it: the extension resolves the plans\n * directory against the harness root, which no other process knows, so it\n * writes down where the plan landed rather than leaving the API to derive a\n * location it would sometimes get wrong.\n */\nexport interface PlanPointerRecord {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n}\n\n/** The plan as it stands on disk right now, which is what the source view edits. */\nexport interface PlanDetailView {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n content: string;\n /** sha256 of the content; the token a save hands back to prove it is not stale. */\n hash: string;\n /** True when the plan is missing or past the size cap, so `content` is empty. */\n unavailable: boolean;\n reason?: string;\n}\n\n/** What the save route takes. */\nexport interface PlanSaveRequest {\n /** The hash the reader loaded; a mismatch means the plan moved underneath them. */\n expectedHash: string;\n content: string;\n}\n\n/** What the save route answers with. */\nexport interface PlanSaveView {\n hash: string;\n}\n\n/** What a route reports when it refuses; the page shows `error` verbatim. */\nexport interface PlanErrorView {\n error: string;\n /** On a stale save, the hash the plan actually has now. */\n hash?: string;\n}\n","import { defineActivityGroup } from '@agimon-ai/po-core/native';\n\nimport { PLAN_STATUS_KEY } from '../../../../../types/planApi';\n\n// Keyed off the saved plan rather than the mode because the plan remains useful\n// while it is being implemented after the read-only mode exits.\nexport default defineActivityGroup({\n name: 'plan',\n keys: 'p e',\n statusKey: PLAN_STATUS_KEY,\n marksBackgroundWork: false,\n order: 25,\n});\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport type { PlanDetailView, PlanSaveView } from './planApi';\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/workspaces/sessions/(backend)/api/plans/`, so the mount is\n * stated once, by the folder that creates it. The paths used to be written\n * here as helpers, again in the contract, and again inside every URL the page\n * built, and the copies were free to disagree.\n *\n * This is the one file the routes, the Hono app and the browser all read, so a\n * path cannot move on one side alone.\n *\n * Neither route takes a query or a path parameter: a session has one current\n * plan, so `current` answers it and `save` takes the manual write back.\n */\nconst routes = {\n current: {\n method: 'GET',\n path: '/current',\n response: undefined as unknown as ApiResponseOf<PlanDetailView>,\n },\n save: {\n method: 'PUT',\n path: '/content',\n response: undefined as unknown as ApiResponseOf<PlanSaveView>,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\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 'plans' at. */\nexport const apiScopes = ['session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'plans',\n transport: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client.native';\nimport type { PlanDetailView } from '../../../../../../types/planApi';\n\n/**\n * The page's half of this package's session API: the current plan, and the\n * manual save.\n *\n * These are adapters now, not a transport. The generated client owns the URL\n * and the sealed transport with it, so nothing here spells a route or reaches\n * for `fetch`. What stays is this package's own vocabulary: which refusals the\n * reader is shown, and the stale-save contract the editor depends on.\n */\n\nconst UNREACHABLE = 'The session is unreachable.';\nconst NO_PLAN = 'This session has not written a plan yet.';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The message a reader is shown: the route's own words, or why there were none. */\nfunction messageOf(result: { status: number; error: string }): string {\n if (result.status === 0) return UNREACHABLE;\n return result.error === '' ? `The session answered ${String(result.status)}.` : result.error;\n}\n\nexport type FetchPlanResult = { ok: true; detail: PlanDetailView } | { ok: false; error: string };\n\nexport async function fetchPlan(sessionId: string): Promise<FetchPlanResult> {\n const result = await api.session(sessionId).current();\n // A session that has written nothing answers 404, which is not a failure the\n // reader should be shown as one.\n if (result.status === 404) return { ok: false, error: result.ok || result.error === '' ? NO_PLAN : result.error };\n if (!result.ok) return { ok: false, error: messageOf(result) };\n if (!isRecord(result.data)) return { ok: false, error: 'The session answered with no plan.' };\n return { ok: true, detail: result.data };\n}\n\nexport type SavePlanResult =\n | { ok: true; hash: string }\n /** The plan moved under the editor; `hash` is what it holds now. */\n | { ok: false; stale: true; error: string; hash?: string }\n | { ok: false; stale: false; error: string };\n\nexport async function savePlan(sessionId: string, expectedHash: string, content: string): Promise<SavePlanResult> {\n const result = await api.session(sessionId).save({ body: { expectedHash, content } });\n // The agent can rewrite the plan while a reader is still editing it. A moved\n // hash is the one refusal the editor recovers from, so it is read before the\n // generic failure.\n if (result.status === 409) {\n const data = result.ok ? undefined : result.data;\n const hash = isRecord(data) && typeof data.hash === 'string' ? data.hash : undefined;\n return {\n ok: false,\n stale: true,\n error: result.ok ? 'The plan changed since it was opened.' : messageOf(result),\n ...(hash === undefined ? {} : { hash }),\n };\n }\n if (!result.ok) return { ok: false, stale: false, error: messageOf(result) };\n return { ok: true, hash: isRecord(result.data) && typeof result.data.hash === 'string' ? result.data.hash : '' };\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { Button, Markdown, SegmentedControl, Textarea, fontOf } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useEffect, useState } from 'react';\nimport { ScrollView, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { PLAN_STATUS_KEY, type PlanDetailView } from '../../../../../../types/planApi';\nimport { fetchPlan, savePlan } from '../_lib/planApi.native';\n\nexport const PLAN_TAB_ID = 'plan-document';\n\n/** The saved plan, with edits guarded by its on-disk hash, never a caller-supplied path. */\nexport function PlanPanel({\n sessionId,\n statuses,\n closeTransientTab,\n fileTabFor,\n openTransientTab,\n}: WebPluginSlotProps) {\n const [detail, setDetail] = useState<PlanDetailView>();\n const [error, setError] = useState<string>();\n const [loading, setLoading] = useState(true);\n const [view, setView] = useState('preview');\n const [draft, setDraft] = useState<string>();\n const [saving, setSaving] = useState(false);\n const [note, setNote] = useState<string>();\n const revision = statuses[PLAN_STATUS_KEY];\n useEffect(() => {\n if (sessionId === null) return;\n let cancelled = false;\n void fetchPlan(sessionId)\n .then((result) => {\n if (cancelled) return;\n setLoading(false);\n if (result.ok) {\n setDetail(result.detail);\n setError(undefined);\n setDraft(undefined);\n setNote(undefined);\n } else {\n setDetail(undefined);\n setError(result.error);\n }\n })\n .catch((failure: unknown) => {\n if (!cancelled) {\n setLoading(false);\n setError(failure instanceof Error ? failure.message : String(failure));\n }\n });\n return () => {\n cancelled = true;\n };\n }, [sessionId, revision]);\n\n const save = async () => {\n if (sessionId === null || !detail || draft === undefined || detail.unavailable || saving) return;\n setSaving(true);\n try {\n const result = await savePlan(sessionId, detail.hash, draft);\n if (!result.ok) {\n setNote(result.error);\n return;\n }\n setNote('saved');\n const refreshed = await fetchPlan(sessionId);\n if (refreshed.ok) {\n setDetail(refreshed.detail);\n setDraft(undefined);\n } else setError(refreshed.error);\n } catch (failure) {\n setNote(failure instanceof Error ? failure.message : String(failure));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <ScrollView contentContainerStyle={styles.panel} testID=\"plan-panel\">\n <Text style={styles.title}>{detail?.title ?? 'plan'}</Text>\n <SegmentedControl\n accessibilityLabel=\"plan view\"\n options={[\n { value: 'preview', label: 'preview' },\n { value: 'source', label: 'source' },\n ]}\n value={view}\n onValueChange={setView}\n />\n {sessionId === null ? (\n <Text style={styles.meta}>Select a session.</Text>\n ) : loading && !detail ? (\n <Text style={styles.meta}>reading this session's plan…</Text>\n ) : null}\n {error ? (\n <Text accessibilityRole=\"alert\" style={styles.error}>\n {error}\n </Text>\n ) : null}\n {detail ? (\n detail.unavailable ? (\n <Text style={styles.meta}>{detail.reason ?? 'this plan cannot be shown'}</Text>\n ) : view === 'preview' ? (\n <Markdown\n text={draft ?? detail.content}\n onFileLink={(path) => {\n const tab = fileTabFor(path);\n return tab ? () => openTransientTab(tab) : undefined;\n }}\n />\n ) : (\n <>\n <Textarea\n accessibilityLabel=\"plan source\"\n value={draft ?? detail.content}\n onChangeText={setDraft}\n numberOfLines={12}\n />\n <View style={styles.actions}>\n <Button variant=\"primary\" disabled={draft === undefined || saving} onPress={() => void save()}>\n save to disk\n </Button>\n {draft !== undefined ? (\n <Button variant=\"ghost\" onPress={() => setDraft(undefined)}>\n discard edits\n </Button>\n ) : null}\n </View>\n {note ? <Text style={note === 'saved' ? styles.success : styles.error}>{note}</Text> : null}\n </>\n )\n ) : null}\n {detail ? (\n <Text selectable style={styles.path}>\n {detail.path}\n </Text>\n ) : null}\n <Button variant=\"ghost\" onPress={() => closeTransientTab(PLAN_TAB_ID)}>\n close\n </Button>\n </ScrollView>\n );\n}\n\nexport function planTab(): Parameters<WebPluginSlotProps['openTransientTab']>[0] {\n return { id: PLAN_TAB_ID, label: 'plan', panel: PlanPanel };\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { padding: theme.spacing(4), gap: theme.spacing(3) },\n title: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.lg,\n lineHeight: theme.lineHeight.lg,\n fontWeight: '600',\n color: theme.colors.hi,\n },\n meta: { fontSize: theme.fontSize.sm, lineHeight: theme.lineHeight.sm, color: theme.colors.dim },\n path: { fontFamily: fontOf(theme.fontFamily.mono), fontSize: theme.fontSize.sm, color: theme.colors.dim },\n error: { fontSize: theme.fontSize.sm, color: theme.colors.red },\n success: { fontSize: theme.fontSize.sm, color: theme.colors.green },\n actions: { flexDirection: 'row', flexWrap: 'wrap', gap: theme.spacing(2) },\n}));\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { ListRow, fontOf } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { parsePlanStatus, PLAN_STATUS_KEY } from '../../../../../../types/planApi';\nimport { planTab } from './PlanPanel.native';\n\n/** The document row, not its group header, is the way into a saved plan. */\nexport function PlanActivitySection({ sessionId, statuses, openTransientTab }: WebPluginSlotProps) {\n const view = parsePlanStatus(statuses[PLAN_STATUS_KEY]);\n if (!view) return <Text style={styles.meta}>no plan written yet</Text>;\n return (\n <View testID=\"activity-plan\">\n <ListRow\n title={view.title}\n description={view.stamp || undefined}\n disabled={sessionId === null}\n onPress={() => {\n if (sessionId !== null) openTransientTab(planTab());\n }}\n />\n <Text style={styles.meta}>open to read or edit; the agent reads what you save.</Text>\n </View>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n meta: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n color: theme.colors.dim,\n },\n}));\n","import { defineFill } from '@agimon-ai/po-core/native';\n\nimport { PlanActivitySection } from './_components/PlanActivitySection.native';\n\nexport default defineFill({ slot: 'activity.plan', id: 'plan', component: PlanActivitySection });\n","import type { ToolPromptRenderProps } from '@agimon-ai/po-core/native';\nimport { Button, ChevronDownIcon, ChevronRightIcon, fontOf, Panel } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useState } from 'react';\nimport { ScrollView, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type {} from '../../../../../../types/unistyles.native';\n\nexport function PlanReviewPrompt({\n dialog,\n answer,\n cancel,\n defaultExpanded = true,\n}: ToolPromptRenderProps & { defaultExpanded?: boolean }) {\n const [open, setOpen] = useState(defaultExpanded);\n return (\n <Panel style={styles.prompt} testID=\"plan-review-prompt\" onAccessibilityEscape={cancel}>\n <Button\n variant=\"ghost\"\n size=\"card\"\n style={styles.header}\n accessibilityLabel={open ? 'Collapse plan review' : 'Expand plan review'}\n accessibilityState={{ expanded: open }}\n aria-expanded={open}\n onPress={() => setOpen(!open)}\n >\n <Text style={styles.label}>Plan review</Text>\n {!open ? <Text style={[styles.description, styles.pending]}>Awaiting decision</Text> : null}\n {open ? <ChevronDownIcon size={16} /> : <ChevronRightIcon size={16} />}\n </Button>\n {open ? (\n <>\n <ScrollView style={styles.scroll} contentContainerStyle={styles.content} keyboardShouldPersistTaps=\"handled\">\n <Text style={styles.title} accessibilityRole=\"header\">\n {dialog.title}\n </Text>\n <Text style={styles.description}>\n Review the plan in the conversation before choosing what happens next.\n </Text>\n {dialog.options.map((option, index) => (\n <Button\n key={option}\n variant=\"outline\"\n size=\"card\"\n testID={`plan-review-option-${index}`}\n onPress={() => answer(option)}\n >\n {option}\n </Button>\n ))}\n </ScrollView>\n <View style={styles.footer}>\n <Button variant=\"ghost\" size=\"card\" testID=\"plan-review-cancel\" onPress={cancel}>\n Cancel\n </Button>\n </View>\n </>\n ) : null}\n </Panel>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n prompt: { flexShrink: 1, margin: theme.spacing(4) },\n header: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingHorizontal: theme.spacing(3),\n paddingVertical: theme.spacing(2),\n borderRadius: 0,\n },\n pending: { marginLeft: 'auto' },\n label: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n fontWeight: theme.fontWeight.semibold,\n color: theme.colors.dim,\n },\n scroll: { flexGrow: 0, flexShrink: 1 },\n content: { gap: theme.spacing(3), paddingHorizontal: theme.spacing(3), paddingBottom: theme.spacing(3) },\n title: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n fontWeight: theme.fontWeight.semibold,\n color: theme.colors.hi,\n },\n description: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n color: theme.colors.dim,\n },\n footer: {\n flexDirection: 'row',\n justifyContent: 'flex-end',\n padding: theme.spacing(2),\n borderTopWidth: 1,\n borderTopColor: theme.colors['border-soft'],\n },\n}));\n","import type { ToolPromptDialog, ToolResultView } from '@agimon-ai/po-core/web';\nimport type { MessageLine, MessageLineTone } from '@agimon-ai/po-web-components';\n\nimport { PLAN_REVIEW_OPTIONS, PLAN_REVIEW_TITLE } from '../../../../../../types/planApi';\n\n/**\n * Purpose-first summaries for the plan-mode tools. The TUI leaves these on\n * Pi's default shell, so the shapes here come straight from the tool\n * definitions in src/services/planServerSession/index.ts: write_plan and complete_plan\n * report through `details` (written, path, phase, exited), run_fable_plan\n * carries the broker result, and record_debug_evidence only confirms.\n */\n\nexport const PLAN_TOOL_NAMES = ['record_debug_evidence', 'run_fable_plan', 'write_plan', 'complete_plan'] as const;\n\n/** Claims only the selector opened by complete_plan, on either platform. */\nexport function claimsPlanReviewPrompt(dialog: ToolPromptDialog): boolean {\n return (\n dialog.method === 'select' &&\n dialog.title === PLAN_REVIEW_TITLE &&\n dialog.options.length === PLAN_REVIEW_OPTIONS.length &&\n PLAN_REVIEW_OPTIONS.every((option, index) => dialog.options[index] === option)\n );\n}\n\n/** The toned lines the shared MessageLines draws; the vocabulary is the components package's. */\nexport type LineTone = MessageLineTone;\n/** `label` names an evidence field the text leads with, so a layout can set it apart without parsing the text. */\nexport type ToolLine = MessageLine & { label?: string };\n\nexport interface PlanCallSummary {\n action: string;\n detail?: string;\n metadata: string[];\n}\n\nexport interface PlanRenderOptions {\n expanded: boolean;\n isError: boolean;\n isPartial: boolean;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nconst COLLAPSED_BODY_LINES = 12;\nconst PREVIEW_LENGTH = 72;\n\nconst EVIDENCE_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['logs', 'log'],\n ['correlatedTraceEvidence', 'trace'],\n ['processOutput', 'process output'],\n ['browserConsoleEvidence', 'console entry'],\n ['correlationIds', 'correlation id'],\n ['timestamps', 'timestamp'],\n ['verifiedFacts', 'verified fact'],\n ['hypotheses', 'hypothesis'],\n ['unavailableEvidence', 'unavailable item'],\n];\n\nconst PACKET_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['goal', 'goal'],\n ['constraints', 'constraint'],\n ['decisions', 'decision'],\n ['verifiedFindings', 'verified finding'],\n ['inferredFindings', 'inferred finding'],\n ['unresolvedQuestions', 'open question'],\n];\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? (value as JsonRecord) : undefined;\n}\n\nfunction inlineText(value: string): string {\n let normalized = '';\n for (const character of value) {\n const code = character.codePointAt(0) ?? 0;\n normalized += code <= 31 || code === 127 ? ' ' : character;\n }\n return normalized.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction readString(record: JsonRecord | undefined, key: string): string | undefined {\n const value = record?.[key];\n return typeof value === 'string' ? inlineText(value) || undefined : undefined;\n}\n\nfunction readNumber(record: JsonRecord | undefined, key: string): number | undefined {\n const value = record?.[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction listLength(record: JsonRecord, key: string): number {\n const value = record[key];\n return Array.isArray(value) ? value.length : 0;\n}\n\nfunction plural(count: number, singular: string): string {\n if (count === 1) return singular;\n if (singular.endsWith('y')) return `${singular.slice(0, -1)}ies`;\n return `${singular}s`;\n}\n\nfunction preview(value: string | undefined): string | undefined {\n if (!value) return undefined;\n return value.length > PREVIEW_LENGTH ? `${value.slice(0, PREVIEW_LENGTH - 3)}…` : value;\n}\n\nfunction countMetadata(args: JsonRecord, lists: ReadonlyArray<[string, string]>): string[] {\n return lists.flatMap(([key, label]) => {\n const count = listLength(args, key);\n return count > 0 ? [`${count} ${plural(count, label)}`] : [];\n });\n}\n\nfunction line(text: string, tone: LineTone, extra: Omit<ToolLine, 'text' | 'tone'> = {}): ToolLine {\n return { text, tone, ...extra };\n}\n\nfunction outputText(result: ToolResultView | null): string {\n if (!result) return '';\n return result.content\n .flatMap((item) => {\n const record = asRecord(item);\n return record?.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n })\n .join('\\n');\n}\n\nfunction bodyLines(text: string, expanded: boolean): ToolLine[] {\n const all = text\n .split('\\n')\n .map((entry) => entry.trimEnd())\n .filter((entry) => entry.length > 0);\n const shown = expanded ? all : all.slice(0, COLLAPSED_BODY_LINES);\n const lines = shown.map((entry) => line(entry, 'text'));\n if (all.length > shown.length) lines.push(line(`… ${all.length - shown.length} more lines`, 'dim'));\n return lines;\n}\n\n/** The header beside the tool name: what the call is for and how much it carries. */\nexport function planCallSummary(toolName: string, args: JsonRecord): PlanCallSummary {\n if (toolName === 'record_debug_evidence') {\n const issue = preview(readString(args, 'issue'));\n return {\n action: 'record evidence',\n ...(issue ? { detail: issue } : {}),\n metadata: countMetadata(args, EVIDENCE_LISTS),\n };\n }\n if (toolName === 'run_fable_plan') {\n const metadata = countMetadata(args, PACKET_LISTS);\n if (readString(args, 'currentPlan')) metadata.push('with current plan');\n return { action: 'fable draft', metadata };\n }\n if (toolName === 'write_plan') return { action: 'save plan', metadata: [] };\n const decision = readString(args, 'decision');\n return { action: decision ? `decide ${decision}` : 'request approval', metadata: [] };\n}\n\nfunction evidenceLines(args: JsonRecord, result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const recorded = asRecord(result?.details)?.recorded === true;\n const lines = [\n recorded\n ? line('✓ evidence recorded as planning context', 'success')\n : line(`○ ${inlineText(outputText(result)) || 'not recorded'}`, 'muted'),\n ];\n if (!options.expanded) return lines;\n const fields: ReadonlyArray<[string, string]> = [\n ['issue', 'issue'],\n ['expectedBehavior', 'expected'],\n ['reproductionAttempt', 'reproduction'],\n ['actualBehavior', 'actual'],\n ];\n for (const [key, label] of fields) {\n const value = readString(args, key);\n if (value) lines.push(line(`${label} ${value}`, 'text', { label }));\n }\n for (const [key, label] of EVIDENCE_LISTS) {\n const raw = args[key];\n const items = Array.isArray(raw) ? raw.filter((item): item is string => typeof item === 'string') : [];\n if (items.length === 0) continue;\n lines.push(line(plural(items.length, label), 'hi', { bold: true }));\n lines.push(...items.map((item) => line(inlineText(item), 'text', { indent: true })));\n }\n return lines;\n}\n\nfunction fableLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const text = outputText(result);\n if (details?.started !== true) {\n const code = readString(details, 'errorCode');\n return [line(`○ ${inlineText(text) || 'fable planning did not start'}${code ? ` · ${code}` : ''}`, 'muted')];\n }\n const status = readString(details, 'status') ?? 'unknown';\n const draft = typeof details?.draft === 'string' ? details.draft : undefined;\n const code = readString(details, 'errorCode');\n if (!draft) return [line(`✗ fable planning ${status}${code ? ` · ${code}` : ''}`, 'error')];\n const finished = status === 'completed';\n return [\n line(\n `${finished ? '✓' : '!'} fable draft · ${status}${code ? ` · ${code}` : ''}`,\n finished ? 'success' : 'warning',\n {\n bold: true,\n },\n ),\n ...bodyLines(draft, options.expanded),\n ];\n}\n\nfunction writeLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const path = readString(details, 'path');\n if (options.isPartial) {\n const phase = readString(details, 'phase') ?? 'checking';\n return [line(`◐ ${phase}${path ? ` ${path}` : ''}`, 'warning')];\n }\n const duration = readNumber(details, 'durationMs');\n if (details?.written === true) {\n return [line(`✓ wrote ${path ?? 'the plan'}${duration === undefined ? '' : ` · ${duration}ms`}`, 'success')];\n }\n const lines = [line(`○ ${inlineText(outputText(result)) || 'plan not written'}`, 'muted')];\n if (path) lines.push(line(`path ${path}`, 'dim'));\n return lines;\n}\n\nfunction completeLines(result: ToolResultView | null): ToolLine[] {\n const text = inlineText(outputText(result));\n if (asRecord(result?.details)?.exited === true) {\n return [line(`✓ plan mode exited${text ? ` · ${text}` : ''}`, 'success')];\n }\n return [line(`○ staying in plan mode${text ? ` · ${text}` : ''}`, 'muted')];\n}\n\n/** Why a plan tool call failed, as the tool said it on one line; empty when it said nothing. */\nexport function planFailureReason(result: ToolResultView | null): string {\n return inlineText(outputText(result));\n}\n\n/** The body of a plan tool card: the outcome line, plus the carried detail once expanded. */\nexport function planResultLines(\n toolName: string,\n args: JsonRecord,\n result: ToolResultView | null,\n options: PlanRenderOptions,\n): ToolLine[] {\n if (options.isError) {\n return [line(`✗ ${planFailureReason(result) || `${toolName} failed`}`, 'error')];\n }\n if (toolName === 'record_debug_evidence') return evidenceLines(args, result, options);\n if (toolName === 'run_fable_plan') {\n if (options.isPartial) return [line('◐ drafting with the local Fable broker', 'warning')];\n return fableLines(result, options);\n }\n if (toolName === 'write_plan') return writeLines(result, options);\n if (options.isPartial) return [line('◐ waiting for the review decision', 'warning')];\n return completeLines(result);\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/native';\nimport { fontOf, MessageItem, MessageItemBody, MessageItemHeader, toolTone } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport {\n type LineTone,\n planCallSummary,\n planFailureReason,\n planResultLines,\n type ToolLine,\n} from '../_lib/planToolRender';\n\n/**\n * The plan tools' timeline item on native, as the web's: the plan action as\n * the title, the issue and what the packet carries beside it on one line, and\n * the outcome line in the body (shown collapsed too, as the web does), with\n * the recorded evidence or the Fable draft once expanded. A failure shows only the tool's reason; the edge and icon say it failed.\n */\nexport function PlanToolMessage({ toolName, args, result, running, isError }: ToolMessageRenderProps) {\n const summary = planCallSummary(toolName, args);\n const collapsed = planResultLines(toolName, args, result, { expanded: false, isError, isPartial: running });\n const full = planResultLines(toolName, args, result, { expanded: true, isError, isPartial: running });\n const reason = isError ? planFailureReason(result) : '';\n // The issue is what the call is about, so it leads; the counts are the detail that yields first.\n const primary = summary.detail;\n const secondary = summary.metadata;\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={!isError && full.length > collapsed.length}>\n {({ expanded }) => (\n <>\n <MessageItemHeader title={summary.action}>\n <View testID={`tool-call-${toolName}`} style={styles.summary}>\n {primary !== undefined ? (\n <Text numberOfLines={1} style={[styles.sans, styles.primary]}>\n {primary}\n </Text>\n ) : null}\n {secondary.length > 0 ? (\n <Text numberOfLines={1} style={[styles.sans, styles.secondary]}>\n {primary !== undefined ? `· ${secondary.join(' · ')}` : secondary.join(' · ')}\n </Text>\n ) : null}\n </View>\n </MessageItemHeader>\n {isError ? (\n reason.length > 0 ? (\n <MessageItemBody testID={`tool-result-${toolName}`}>\n <Text selectable style={[styles.sans, styles.error]}>\n {reason}\n </Text>\n </MessageItemBody>\n ) : null\n ) : expanded && toolName === 'record_debug_evidence' && full.length > 1 ? (\n <MessageItemBody testID={`tool-result-${toolName}`}>\n <EvidenceBody lines={full} />\n </MessageItemBody>\n ) : (expanded ? full : collapsed).length > 0 ? (\n <MessageItemBody testID={`tool-result-${toolName}`}>\n <View style={styles.lines}>\n {(expanded ? full : collapsed).map((entry, index) => (\n <ToneLine key={`${String(index)}-${entry.text}`} entry={entry} />\n ))}\n </View>\n </MessageItemBody>\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n\nfunction ToneLine({ entry }: { entry: ToolLine }) {\n return (\n <Text\n selectable\n style={[\n styles.sans,\n TONE_STYLE[entry.tone],\n entry.bold === true ? styles.bold : null,\n entry.indent === true ? styles.indent : null,\n ]}\n >\n {entry.text}\n </Text>\n );\n}\n\ninterface EvidenceGroup {\n label: string;\n values: string[];\n}\n\n/*\n * The shared lines name each evidence field in `label`, carry list labels as\n * bold lines, and list items as indented lines; the phone regroups them so\n * every label sits in one style above its values.\n */\nfunction evidenceGroups(lines: readonly ToolLine[]): EvidenceGroup[] {\n const groups: EvidenceGroup[] = [];\n for (const entry of lines) {\n if (entry.bold === true) groups.push({ label: entry.text, values: [] });\n else if (entry.indent === true && groups.length > 0) groups[groups.length - 1]?.values.push(entry.text);\n else if (entry.label !== undefined)\n groups.push({ label: entry.label, values: [entry.text.slice(entry.label.length).trimStart()] });\n else groups.push({ label: entry.text, values: [] });\n }\n return groups;\n}\n\n/** The expanded evidence: the outcome line, then each label over its values, set apart from the outcome. */\nfunction EvidenceBody({ lines }: { lines: readonly ToolLine[] }) {\n const [status, ...facts] = lines;\n return (\n <View style={styles.evidence}>\n {status !== undefined ? <ToneLine entry={status} /> : null}\n <View style={styles.facts}>\n {evidenceGroups(facts).map((group) => (\n <View key={group.label} style={styles.group}>\n <Text style={styles.label}>{group.label}</Text>\n {group.values.map((value, index) => (\n <Text key={`${String(index)}-${value}`} selectable style={[styles.sans, styles.text]}>\n {value}\n </Text>\n ))}\n </View>\n ))}\n </View>\n </View>\n );\n}\n\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n // One line on the title's row: the issue stays whole up to most of the row, the counts truncate first.\n summary: { flex: 1, flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2), minWidth: 0 },\n sans: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n lineHeight: theme.lineHeight.base,\n },\n primary: { flexShrink: 0, maxWidth: '70%', color: theme.colors.text },\n secondary: { flexShrink: 1, color: theme.colors.faint },\n lines: { gap: theme.spacing(0.5) },\n evidence: { gap: theme.spacing(3) },\n facts: {\n gap: theme.spacing(3),\n paddingTop: theme.spacing(3),\n borderTopWidth: 1,\n borderTopColor: theme.colors['border-soft'],\n },\n group: { gap: theme.spacing(0.5) },\n label: {\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n fontWeight: theme.fontWeight.semibold,\n color: theme.colors.dim,\n },\n bold: { fontWeight: theme.fontWeight.semibold },\n indent: { paddingLeft: theme.spacing(4) },\n error: { color: theme.colors.red },\n hi: { color: theme.colors.hi },\n text: { color: theme.colors.text },\n dim: { color: theme.colors.dim },\n muted: { color: theme.colors.faint },\n success: { color: theme.colors.green },\n warning: { color: theme.colors.yellow },\n accent: { color: theme.colors.blue },\n}));\n\n/** The line tones of the web's MessageLines, drawn with the same theme tokens. */\nconst TONE_STYLE: Readonly<Record<LineTone, object>> = {\n hi: styles.hi,\n text: styles.text,\n dim: styles.dim,\n muted: styles.muted,\n success: styles.success,\n error: styles.error,\n warning: styles.warning,\n accent: styles.accent,\n};\n","import { defineToolRenderer } from '@agimon-ai/po-core/native';\n\nimport { PlanReviewPrompt } from './_components/PlanReviewPrompt.native';\nimport { PlanToolMessage } from './_components/PlanToolMessage.native';\nimport { claimsPlanReviewPrompt, type PLAN_TOOL_NAMES } from './_lib/planToolRender';\n\n/*\n * The phone half of plan.web.tsx: one card for every plan tool. The names are\n * spelled out because the native renderer check reads only `.native.` files;\n * `satisfies` keeps them to the shared PLAN_TOOL_NAMES list.\n */\nexport default defineToolRenderer({\n tools: ['record_debug_evidence', 'run_fable_plan', 'write_plan', 'complete_plan'] satisfies Array<\n (typeof PLAN_TOOL_NAMES)[number]\n >,\n message: PlanToolMessage,\n prompt: { claims: claimsPlanReviewPrompt, component: PlanReviewPrompt },\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 activityGroupPlan from '../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.native';\nimport fillPlan from '../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.native';\nimport toolPlan from '../src/extensions/workspaces/sessions/(frontend)/tool/plan.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: 'plan',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'plan' }, activityGroupPlan)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.plan', id: 'plan' }, fillPlan)]; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['plan'] }, toolPlan)]; },\n },\n});\n"],"mappings":"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"}
|
package/dist/extensions/web.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createApiClient, defineActivityGroup, defineFill, defineLeaderBinding, defineMinorModeFile, defineSettingsSection, defineToolRenderer, defineWebPlugin, sessionApiAddress } from "@agimon-ai/po-core/web";
|
|
2
|
-
import { Button, CodeEditor, Kbd, Markdown, MessageItem, MessageItemBody, MessageItemHeader, MessageLines, OptionList, SectionLabel, TaskIcon, handleOptionListKey, optionListHint, toolTone } from "@agimon-ai/po-web-components";
|
|
2
|
+
import { Button, ChevronDownIcon, ChevronRightIcon, CodeEditor, Collapsible, CollapsibleContent, CollapsibleTrigger, Kbd, Markdown, MessageItem, MessageItemBody, MessageItemHeader, MessageLines, OptionList, SectionLabel, TaskIcon, handleOptionListKey, optionListHint, toolTone } from "@agimon-ai/po-web-components";
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import { browserTransport } from "@agimon-ai/po-web-security/browser";
|
|
5
5
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -500,60 +500,76 @@ var mode_web_default = defineMinorModeFile({
|
|
|
500
500
|
});
|
|
501
501
|
//#endregion
|
|
502
502
|
//#region src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanReviewPrompt.tsx
|
|
503
|
-
/**
|
|
504
|
-
function
|
|
505
|
-
|
|
506
|
-
}
|
|
507
|
-
/** Keeps plan approval in the composer so the conversation remains visible while the user decides. */
|
|
508
|
-
function PlanReviewPrompt({ dialog, answer, cancel }) {
|
|
503
|
+
/** Keeps the pending decision available without covering the plan being reviewed. */
|
|
504
|
+
function PlanReviewPrompt({ dialog, answer, cancel, defaultExpanded = true }) {
|
|
505
|
+
const [open, setOpen] = useState(defaultExpanded);
|
|
509
506
|
const [cursor, setCursor] = useState(0);
|
|
510
507
|
const frame = useRef(null);
|
|
511
|
-
useEffect(() => frame.current?.focus(), [dialog.id]);
|
|
512
|
-
return /* @__PURE__ */ jsxs(
|
|
508
|
+
useEffect(() => frame.current?.querySelector("[role=\"listbox\"]")?.focus(), [dialog.id]);
|
|
509
|
+
return /* @__PURE__ */ jsxs(Collapsible, {
|
|
513
510
|
ref: frame,
|
|
511
|
+
open,
|
|
512
|
+
onOpenChange: setOpen,
|
|
514
513
|
role: "group",
|
|
515
|
-
|
|
514
|
+
"aria-label": "Plan review",
|
|
516
515
|
"data-testid": "plan-review-prompt",
|
|
517
|
-
className: "flex min-w-0 flex-col overflow-hidden
|
|
516
|
+
className: "flex min-w-0 flex-col overflow-hidden",
|
|
518
517
|
onKeyDown: (event) => {
|
|
519
518
|
if (event.key === "Escape") {
|
|
520
519
|
event.preventDefault();
|
|
521
520
|
event.stopPropagation();
|
|
522
521
|
cancel();
|
|
523
|
-
return;
|
|
524
522
|
}
|
|
525
|
-
handleOptionListKey(event, {
|
|
526
|
-
options: dialog.options,
|
|
527
|
-
cursor,
|
|
528
|
-
onCursorChange: setCursor,
|
|
529
|
-
onSelect: answer
|
|
530
|
-
});
|
|
531
523
|
},
|
|
532
|
-
children: [
|
|
533
|
-
|
|
534
|
-
|
|
524
|
+
children: [/* @__PURE__ */ jsx(CollapsibleTrigger, {
|
|
525
|
+
asChild: true,
|
|
526
|
+
children: /* @__PURE__ */ jsxs(Button, {
|
|
527
|
+
variant: "ghost",
|
|
528
|
+
"aria-label": open ? "Collapse plan review" : "Expand plan review",
|
|
529
|
+
className: "h-11 w-full justify-between rounded-none px-3.5",
|
|
535
530
|
children: [
|
|
536
531
|
/* @__PURE__ */ jsx(SectionLabel, { children: "plan review" }),
|
|
537
|
-
/* @__PURE__ */ jsx("
|
|
538
|
-
className: "text-
|
|
539
|
-
children:
|
|
540
|
-
}),
|
|
541
|
-
/* @__PURE__ */ jsx(
|
|
542
|
-
className: "text-sm leading-relaxed text-po-dim",
|
|
543
|
-
children: "Review the plan in the conversation before choosing what happens next."
|
|
544
|
-
})
|
|
532
|
+
!open ? /* @__PURE__ */ jsx("span", {
|
|
533
|
+
className: "ml-auto text-sm font-normal text-po-dim",
|
|
534
|
+
children: "Awaiting decision"
|
|
535
|
+
}) : null,
|
|
536
|
+
open ? /* @__PURE__ */ jsx(ChevronDownIcon, { size: 16 }) : /* @__PURE__ */ jsx(ChevronRightIcon, { size: 16 })
|
|
545
537
|
]
|
|
538
|
+
})
|
|
539
|
+
}), /* @__PURE__ */ jsxs(CollapsibleContent, { children: [
|
|
540
|
+
/* @__PURE__ */ jsxs("div", {
|
|
541
|
+
className: "flex flex-col gap-1 px-3.5 pb-2",
|
|
542
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
543
|
+
className: "text-base font-semibold leading-relaxed text-po-hi",
|
|
544
|
+
children: dialog.title
|
|
545
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
546
|
+
className: "text-sm leading-relaxed text-po-dim",
|
|
547
|
+
children: "Review the plan in the conversation before choosing what happens next."
|
|
548
|
+
})]
|
|
546
549
|
}),
|
|
547
550
|
/* @__PURE__ */ jsx(OptionList, {
|
|
548
551
|
options: dialog.options,
|
|
549
552
|
cursor,
|
|
550
553
|
onCursorChange: setCursor,
|
|
551
554
|
onSelect: answer,
|
|
555
|
+
onFocus: (event) => {
|
|
556
|
+
const index = Array.from(event.currentTarget.children).indexOf(event.target);
|
|
557
|
+
if (index !== -1) setCursor(index);
|
|
558
|
+
},
|
|
559
|
+
tabIndex: -1,
|
|
560
|
+
onKeyDown: (event) => {
|
|
561
|
+
handleOptionListKey(event, {
|
|
562
|
+
options: dialog.options,
|
|
563
|
+
cursor,
|
|
564
|
+
onCursorChange: setCursor,
|
|
565
|
+
onSelect: answer
|
|
566
|
+
});
|
|
567
|
+
},
|
|
552
568
|
testIdPrefix: "plan-review-option",
|
|
553
|
-
className: "max-h-48 px-3.5 pb-3"
|
|
569
|
+
className: "max-h-48 px-3.5 pb-3 outline-none"
|
|
554
570
|
}),
|
|
555
571
|
/* @__PURE__ */ jsxs("div", {
|
|
556
|
-
className: "flex
|
|
572
|
+
className: "flex items-center gap-2 border-t border-po-border-soft px-3.5 py-2",
|
|
557
573
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
558
574
|
className: "text-sm text-po-dim",
|
|
559
575
|
children: [
|
|
@@ -571,7 +587,7 @@ function PlanReviewPrompt({ dialog, answer, cancel }) {
|
|
|
571
587
|
children: "cancel"
|
|
572
588
|
})]
|
|
573
589
|
})
|
|
574
|
-
]
|
|
590
|
+
] })]
|
|
575
591
|
});
|
|
576
592
|
}
|
|
577
593
|
//#endregion
|
|
@@ -589,6 +605,10 @@ const PLAN_TOOL_NAMES = [
|
|
|
589
605
|
"write_plan",
|
|
590
606
|
"complete_plan"
|
|
591
607
|
];
|
|
608
|
+
/** Claims only the selector opened by complete_plan, on either platform. */
|
|
609
|
+
function claimsPlanReviewPrompt(dialog) {
|
|
610
|
+
return dialog.method === "select" && dialog.title === "Plan complete. What would you like to do?" && dialog.options.length === PLAN_REVIEW_OPTIONS.length && PLAN_REVIEW_OPTIONS.every((option, index) => dialog.options[index] === option);
|
|
611
|
+
}
|
|
592
612
|
const COLLAPSED_BODY_LINES = 12;
|
|
593
613
|
const PREVIEW_LENGTH = 72;
|
|
594
614
|
const EVIDENCE_LISTS = [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.mjs","names":["settingPlan","settingPlan2","activityGroupPlan","fillPlan","leaderToggle","modePlan","toolPlan"],"sources":["../../src/types/planSettings.ts","../../src/extensions/(frontend)/_lib/planSettings.ts","../../src/extensions/(frontend)/setting/plan.web.ts","../../src/extensions/workspaces/(frontend)/setting/plan.web.ts","../../src/types/planApi.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.web.ts","../../src/types/apiRoutes.ts","../../generated/client.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/planApi.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanPanel.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanActivitySection.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/leader/toggle.web.ts","../../src/extensions/workspaces/sessions/(frontend)/mode/plan/mode.web.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanReviewPrompt.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/planToolRender.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/plan.web.tsx","../../generated/web.ts"],"sourcesContent":["/**\n * The planning settings, described once for both surfaces.\n *\n * The terminal panel and the cockpit settings page render the same five fields,\n * and the one thing they must agree on is which config key each one writes. So\n * the ids, labels and key paths live here rather than in either renderer.\n *\n * It lives under src/types because that is the one server root a browser bundle\n * may read, which also means it may import nothing: pulling the config package\n * in for the thinking levels would drag a node module into the page. They are\n * spelled out instead, and a test asserts they still match the parser's.\n */\n\nexport const PLAN_CONFIG_SECTION_ID = 'planning';\nconst PLANNING_PATH = ['modes', PLAN_CONFIG_SECTION_ID] as const;\nconst MAIN_KEY = 'main';\nconst SUBAGENTS_KEY = 'subagents';\n\n/** Both agents fall back to the session's own settings when left unset. */\nconst INHERIT_MODEL = 'inherit the session model';\nconst INHERIT_THINKING = 'inherit';\n\n/** Mirrors PO_PLANNING_THINKING_LEVELS; pinned by planConfig's test. */\nexport const PLAN_THINKING_LEVELS: readonly string[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];\n\nexport interface PlanSettingShape {\n readonly id: string;\n readonly label: string;\n readonly keyPath: readonly string[];\n readonly placeholder: string;\n readonly detail: string;\n /** Present for a closed set; a renderer offers these rather than free text. */\n readonly options?: readonly string[];\n /** Offers the machine's authenticated models rather than free text. */\n readonly models?: boolean;\n}\n\nexport const PLAN_SETTING_SHAPES: readonly PlanSettingShape[] = [\n {\n id: 'main.model',\n label: 'main model',\n keyPath: [...PLANNING_PATH, MAIN_KEY, 'model'],\n placeholder: INHERIT_MODEL,\n detail: 'model the main agent switches to while plan mode is on.',\n models: true,\n },\n {\n id: 'main.thinking',\n label: 'main thinking',\n keyPath: [...PLANNING_PATH, MAIN_KEY, 'thinking'],\n placeholder: INHERIT_THINKING,\n detail: 'thinking level appended to the main model while planning.',\n options: PLAN_THINKING_LEVELS,\n },\n {\n id: 'subagents.model',\n label: 'subagent model',\n keyPath: [...PLANNING_PATH, SUBAGENTS_KEY, 'model'],\n placeholder: INHERIT_MODEL,\n detail: 'model forced onto delegated planning subagents.',\n models: true,\n },\n {\n id: 'subagents.thinking',\n label: 'subagent thinking',\n keyPath: [...PLANNING_PATH, SUBAGENTS_KEY, 'thinking'],\n placeholder: INHERIT_THINKING,\n detail: 'thinking level appended to the subagent model.',\n options: PLAN_THINKING_LEVELS,\n },\n {\n id: 'plansdirectory',\n label: 'plans directory',\n keyPath: [...PLANNING_PATH, 'plansDirectory'],\n placeholder: '~/.po/plans',\n detail: 'absolute, repo-relative, or under ~. written plans land here.',\n },\n];\n","import type { SettingsSectionContribution } from '@agimon-ai/po-core/web';\n\nimport { PLAN_CONFIG_SECTION_ID, PLAN_SETTING_SHAPES } from '../../../types/planSettings';\n\n/**\n * The planning settings, as the cockpit's settings page renders them.\n *\n * Built from the same descriptor table the terminal panel uses, so the two\n * surfaces cannot disagree about which config key a field writes. The host owns\n * the scope switch and the writes; this only says what the fields are.\n */\nexport const planSettingsSection: SettingsSectionContribution = {\n id: PLAN_CONFIG_SECTION_ID,\n label: 'planning',\n detail: 'the models plan mode switches to, and where written plans land',\n order: 30,\n fields: PLAN_SETTING_SHAPES.map((shape) => ({\n id: shape.id,\n label: shape.label,\n // A model field offers the machine's authenticated models, which only the\n // host can enumerate; the rest are a closed set or free text.\n kind: shape.models === true || shape.options !== undefined ? ('select' as const) : ('text' as const),\n keyPath: shape.keyPath,\n detail: shape.detail,\n placeholder: shape.placeholder,\n ...(shape.models === true ? { optionsFrom: 'models' as const } : {}),\n ...(shape.options === undefined\n ? {}\n : { options: shape.options.map((option) => ({ value: option, label: option })) }),\n })),\n};\n","import { defineSettingsSection } from '@agimon-ai/po-core/web';\nimport { TaskIcon } from '@agimon-ai/po-web-components';\n\nimport { planSettingsSection } from '../_lib/planSettings';\n\nexport default defineSettingsSection({ ...planSettingsSection, icon: TaskIcon });\n","import { defineSettingsSection } from '@agimon-ai/po-core/web';\nimport { TaskIcon } from '@agimon-ai/po-web-components';\n\nimport { planSettingsSection } from '../../../(frontend)/_lib/planSettings';\n\nexport default defineSettingsSection({ ...planSettingsSection, icon: TaskIcon });\n","/**\n * The wire vocabulary this package's API shares with whatever calls it.\n *\n * It lives under src/types because that is the one server root a browser\n * bundle may read: the routes answer with these shapes and the cockpit plugin\n * reads them, so neither half can drift from the other. The paths themselves\n * are not here; they are declared once in `./apiRoutes`, which the Hono app\n * and the generated client both read.\n *\n * Two routes, and neither takes a path. A session has one current plan, so\n * `current` answers it and `content` takes the manual save back; the file they\n * act on is the one write_plan recorded, never one the page named. That is\n * also why there is nothing to escape here: a reader cannot address a second\n * file through these URLs.\n */\n\n/** Where a host mounts this package's API; the segment after /api/plugins/. */\nexport const API_BASE_PATH = 'plans';\n\n/**\n * Footer status key the session publishes once a plan exists, which is what\n * makes the cockpit's activity group appear at all. It outlives plan mode: the\n * plan is most worth reading while the agent implements it.\n */\nexport const PLAN_STATUS_KEY = 'po-plan-document';\n\n/** The selector contract shared by complete_plan and its cockpit composer prompt. */\nexport const PLAN_REVIEW_TITLE = 'Plan complete. What would you like to do?';\nexport const EXIT_PLAN_MODE_CHOICE = 'Exit plan mode and start implementation';\nexport const CONTINUE_PLANNING_CHOICE = 'Continue planning';\nexport const EXIT_PLAN_DECISION = 'exit';\nexport const CONTINUE_PLAN_DECISION = 'continue';\n\n/**\n * The label the reader sees paired with the decision the tool acts on. A headless\n * client answers with `value`, so a server plugin never has to recognise the wording; Pi's\n * own `ui.select` carries labels only, so its half maps the label back itself.\n */\nexport const PLAN_REVIEW_CHOICES = [\n { label: EXIT_PLAN_MODE_CHOICE, value: EXIT_PLAN_DECISION },\n { label: CONTINUE_PLANNING_CHOICE, value: CONTINUE_PLAN_DECISION },\n] as const;\n\n/** The same options as bare labels, which is all Pi's select and the composer prompt need. */\nexport const PLAN_REVIEW_OPTIONS = PLAN_REVIEW_CHOICES.map((choice) => choice.label);\n\n/** Between the plan's title and the stamp that marks a rewrite. */\nconst STATUS_SEPARATOR = ' · ';\n\n/** Strips the colour a session may have themed a status with. */\nconst ANSI = /\u001b\\[[0-9;]*m/gu;\n\n/** The status line the session publishes; the stamp changes on every write. */\nexport function formatPlanStatus(title: string, stamp: string): string {\n return `${title}${STATUS_SEPARATOR}${stamp}`;\n}\n\n/** What a reader gets out of the status line. */\nexport interface PlanStatusView {\n title: string;\n /** When the plan was last written, as the session worded it; empty when it said nothing. */\n stamp: string;\n}\n\n/**\n * Reading the status line back. Statuses reach a plugin raw, so the colour a\n * session may have added comes off here. A title can itself contain the\n * separator, so the stamp is taken from the last one rather than the first.\n */\nexport function parsePlanStatus(raw: string | undefined): PlanStatusView | undefined {\n if (raw === undefined) return undefined;\n const text = raw.replace(ANSI, '').trim();\n if (text === '') return undefined;\n const cut = text.lastIndexOf(STATUS_SEPARATOR);\n if (cut === -1) return { title: text, stamp: '' };\n return { title: text.slice(0, cut).trim(), stamp: text.slice(cut + STATUS_SEPARATOR.length).trim() };\n}\n\n/**\n * What write_plan recorded about this session's plan.\n *\n * The absolute path is the point of it: the extension resolves the plans\n * directory against the harness root, which no other process knows, so it\n * writes down where the plan landed rather than leaving the API to derive a\n * location it would sometimes get wrong.\n */\nexport interface PlanPointerRecord {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n}\n\n/** The plan as it stands on disk right now, which is what the source view edits. */\nexport interface PlanDetailView {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n content: string;\n /** sha256 of the content; the token a save hands back to prove it is not stale. */\n hash: string;\n /** True when the plan is missing or past the size cap, so `content` is empty. */\n unavailable: boolean;\n reason?: string;\n}\n\n/** What the save route takes. */\nexport interface PlanSaveRequest {\n /** The hash the reader loaded; a mismatch means the plan moved underneath them. */\n expectedHash: string;\n content: string;\n}\n\n/** What the save route answers with. */\nexport interface PlanSaveView {\n hash: string;\n}\n\n/** What a route reports when it refuses; the page shows `error` verbatim. */\nexport interface PlanErrorView {\n error: string;\n /** On a stale save, the hash the plan actually has now. */\n hash?: string;\n}\n","import { defineActivityGroup } from '@agimon-ai/po-core/web';\n\nimport { PLAN_STATUS_KEY } from '../../../../../types/planApi';\n\n// Keyed off the saved plan rather than the mode because the plan remains useful\n// while it is being implemented after the read-only mode exits.\nexport default defineActivityGroup({\n name: 'plan',\n keys: 'p e',\n statusKey: PLAN_STATUS_KEY,\n marksBackgroundWork: false,\n order: 25,\n});\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport type { PlanDetailView, PlanSaveView } from './planApi';\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/workspaces/sessions/(backend)/api/plans/`, so the mount is\n * stated once, by the folder that creates it. The paths used to be written\n * here as helpers, again in the contract, and again inside every URL the page\n * built, and the copies were free to disagree.\n *\n * This is the one file the routes, the Hono app and the browser all read, so a\n * path cannot move on one side alone.\n *\n * Neither route takes a query or a path parameter: a session has one current\n * plan, so `current` answers it and `save` takes the manual write back.\n */\nconst routes = {\n current: {\n method: 'GET',\n path: '/current',\n response: undefined as unknown as ApiResponseOf<PlanDetailView>,\n },\n save: {\n method: 'PUT',\n path: '/content',\n response: undefined as unknown as ApiResponseOf<PlanSaveView>,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\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 'plans' at. */\nexport const apiScopes = ['session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'plans',\n transport: (input, init) => browserTransport.fetch(input, init),\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client';\nimport type { PlanDetailView } from '../../../../../../types/planApi';\n\n/**\n * The page's half of this package's session API: the current plan, and the\n * manual save.\n *\n * These are adapters now, not a transport. The generated client owns the URL\n * and the sealed transport with it, so nothing here spells a route or reaches\n * for `fetch`. What stays is this package's own vocabulary: which refusals the\n * reader is shown, and the stale-save contract the editor depends on.\n */\n\nconst UNREACHABLE = 'The session is unreachable.';\nconst NO_PLAN = 'This session has not written a plan yet.';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The message a reader is shown: the route's own words, or why there were none. */\nfunction messageOf(result: { status: number; error: string }): string {\n if (result.status === 0) return UNREACHABLE;\n return result.error === '' ? `The session answered ${String(result.status)}.` : result.error;\n}\n\nexport type FetchPlanResult = { ok: true; detail: PlanDetailView } | { ok: false; error: string };\n\nexport async function fetchPlan(sessionId: string): Promise<FetchPlanResult> {\n const result = await api.session(sessionId).current();\n // A session that has written nothing answers 404, which is not a failure the\n // reader should be shown as one.\n if (result.status === 404) return { ok: false, error: result.ok || result.error === '' ? NO_PLAN : result.error };\n if (!result.ok) return { ok: false, error: messageOf(result) };\n if (!isRecord(result.data)) return { ok: false, error: 'The session answered with no plan.' };\n return { ok: true, detail: result.data };\n}\n\nexport type SavePlanResult =\n | { ok: true; hash: string }\n /** The plan moved under the editor; `hash` is what it holds now. */\n | { ok: false; stale: true; error: string; hash?: string }\n | { ok: false; stale: false; error: string };\n\nexport async function savePlan(sessionId: string, expectedHash: string, content: string): Promise<SavePlanResult> {\n const result = await api.session(sessionId).save({ body: { expectedHash, content } });\n // The agent can rewrite the plan while a reader is still editing it. A moved\n // hash is the one refusal the editor recovers from, so it is read before the\n // generic failure.\n if (result.status === 409) {\n const data = result.ok ? undefined : result.data;\n const hash = isRecord(data) && typeof data.hash === 'string' ? data.hash : undefined;\n return {\n ok: false,\n stale: true,\n error: result.ok ? 'The plan changed since it was opened.' : messageOf(result),\n ...(hash === undefined ? {} : { hash }),\n };\n }\n if (!result.ok) return { ok: false, stale: false, error: messageOf(result) };\n return { ok: true, hash: isRecord(result.data) && typeof result.data.hash === 'string' ? result.data.hash : '' };\n}\n","import type { TransientTab, WebPluginSlotProps } from '@agimon-ai/po-core/web';\nimport { Button, CodeEditor, Markdown } from '@agimon-ai/po-web-components';\nimport { useEffect, useState } from 'react';\n\nimport { PLAN_STATUS_KEY, type PlanDetailView } from '../../../../../../types/planApi';\nimport { fetchPlan, savePlan } from '../_lib/planApi';\n\n/**\n * The plan's tab: what the agent decided, and what the reader wants changed.\n *\n * Two views over the same file. A plan is read, not diffed, so preview is\n * where it opens; source is a real editor, line numbers and markdown colour\n * and all, because a reader who corrects a step themselves is cheaper than a\n * turn spent asking for it. The save goes to the plan file the\n * session recorded, and the next turn reads that file, so a correction made\n * here is the plan the agent implements.\n *\n * The tab is transient: it belongs to the session and the page, and closing it\n * is how it ends. It refetches whenever the session republishes its plan\n * status, which is what a rewrite by the agent looks like from here.\n */\n\ntype View = 'preview' | 'source';\n\n/** One tab per session; the plan is singular, so the id needs nothing else. */\nexport const PLAN_TAB_ID = 'plan-document';\n\n/** The one note that is not an error: anything else in that slot failed. */\nconst SAVED_NOTE = 'saved';\n\nexport function PlanPanel({ sessionId, statuses, closeTransientTab }: WebPluginSlotProps) {\n const [detail, setDetail] = useState<PlanDetailView | undefined>(undefined);\n const [error, setError] = useState<string | undefined>(undefined);\n const [loading, setLoading] = useState(false);\n const [view, setView] = useState<View>('preview');\n const [draft, setDraft] = useState<string | undefined>(undefined);\n const [saving, setSaving] = useState(false);\n const [saveNote, setSaveNote] = useState<string | undefined>(undefined);\n\n // One fetch per open, and again whenever the session republishes the status:\n // its stamp changes on every write, which is the cheapest signal that the\n // agent has revised the plan under the reader.\n const revision = statuses[PLAN_STATUS_KEY] ?? '';\n useEffect(() => {\n if (sessionId === null) return;\n let cancelled = false;\n // The fetch below is the external system; this marks it in flight before it starts.\n // oxlint-disable-next-line react/set-state-in-effect\n setLoading(true);\n void fetchPlan(sessionId).then((result) => {\n if (cancelled) return;\n setLoading(false);\n if (result.ok) {\n setDetail(result.detail);\n setError(undefined);\n // A rewrite invalidates an unsaved edit's baseline, so the editor goes\n // back to what is on disk rather than offering a save that must fail.\n setDraft(undefined);\n setSaveNote(undefined);\n return;\n }\n setDetail(undefined);\n setError(result.error);\n });\n return () => {\n cancelled = true;\n };\n }, [sessionId, revision]);\n\n const content = draft ?? detail?.content ?? '';\n\n const save = async (): Promise<void> => {\n if (sessionId === null || detail === undefined || draft === undefined) return;\n setSaving(true);\n const result = await savePlan(sessionId, detail.hash, draft);\n setSaving(false);\n if (result.ok) {\n setSaveNote(SAVED_NOTE);\n setDraft(undefined);\n const refreshed = await fetchPlan(sessionId);\n if (refreshed.ok) setDetail(refreshed.detail);\n else setError(refreshed.error);\n return;\n }\n setSaveNote(result.error);\n };\n\n return (\n <div data-testid=\"plan-panel\" className=\"flex min-h-0 flex-1 flex-col\">\n <header className=\"flex shrink-0 items-center gap-2 border-b border-po-border px-4 py-2\">\n <span data-testid=\"plan-title\" className=\"min-w-0 flex-1 truncate text-lg font-semibold text-po-hi\">\n {detail?.title ?? 'plan'}\n </span>\n <nav className=\"flex shrink-0 items-center gap-1\">\n {(['preview', 'source'] as View[]).map((entry) => (\n <Button\n key={entry}\n variant={view === entry ? 'outline' : 'ghost'}\n size=\"xs\"\n data-testid={`plan-view-${entry}`}\n onClick={() => setView(entry)}\n >\n {entry}\n </Button>\n ))}\n </nav>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-testid=\"plan-close\"\n onClick={() => closeTransientTab(PLAN_TAB_ID)}\n className=\"shrink-0\"\n >\n close\n </Button>\n </header>\n\n {loading && detail === undefined ? (\n <p data-testid=\"plan-loading\" className=\"px-4 py-3 text-sm text-po-dim\">\n reading this session's plan…\n </p>\n ) : null}\n {error === undefined ? null : (\n <p data-testid=\"plan-error\" className=\"px-4 py-3 text-sm text-po-red\">\n {error}\n </p>\n )}\n\n <div className=\"flex min-h-0 flex-1 flex-col\">\n {detail === undefined ? null : detail.unavailable ? (\n <p data-testid=\"plan-unavailable\" className=\"px-4 py-3 text-sm text-po-dim\">\n {detail.reason ?? 'this plan cannot be shown'}\n </p>\n ) : view === 'preview' ? (\n <div\n data-testid=\"plan-preview\"\n className=\"flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto p-4 text-base text-po-text\"\n >\n <Markdown text={content} />\n </div>\n ) : (\n <>\n {/* The editor owns the scrolling: its gutter has to stay put while\n the text moves, which an outer scroll container would break. */}\n <CodeEditor\n data-testid=\"plan-source\"\n value={content}\n path={detail.path}\n onChange={setDraft}\n className=\"min-h-0 flex-1\"\n />\n <div className=\"flex shrink-0 items-center gap-2 border-t border-po-border px-3 py-2\">\n <Button\n variant=\"outline\"\n size=\"xs\"\n data-testid=\"plan-save\"\n loading={saving}\n disabled={draft === undefined || saving}\n onClick={() => void save()}\n >\n save to disk\n </Button>\n {draft === undefined ? null : (\n <Button variant=\"ghost\" size=\"xs\" data-testid=\"plan-revert\" onClick={() => setDraft(undefined)}>\n discard edits\n </Button>\n )}\n {saveNote === undefined ? null : (\n <span\n data-testid=\"plan-save-note\"\n className={saveNote === SAVED_NOTE ? 'text-sm text-po-green' : 'text-sm text-po-red'}\n >\n {saveNote}\n </span>\n )}\n </div>\n </>\n )}\n </div>\n\n {detail === undefined ? null : (\n <footer data-testid=\"plan-source-path\" className=\"shrink-0 truncate border-t border-po-border px-4 py-1.5\">\n <span className=\"font-mono text-sm text-po-dim\">{detail.path}</span>\n </footer>\n )}\n </div>\n );\n}\n\n/** The transient tab the plan opens in; opening it again only focuses it. */\nexport function planTab(): TransientTab {\n return { id: PLAN_TAB_ID, label: 'plan', panel: PlanPanel };\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/web';\nimport { Button } from '@agimon-ai/po-web-components';\n\nimport { parsePlanStatus, PLAN_STATUS_KEY } from '../../../../../../types/planApi';\nimport { planTab } from './PlanPanel';\n\n/**\n * The plan group's body in the activity dock: the plan this session wrote, and\n * the way in.\n *\n * A plan is one document, so the group is one row rather than a list. The row\n * is the whole point of the group: a written plan the reader cannot open is a\n * path in a tool card, which is what this replaces.\n *\n * The session's status line carries the title and the time it was last\n * written, so the row says what the plan is and whether the agent has revised\n * it since the reader last looked, without the dock holding any state.\n */\nexport function PlanActivitySection({ sessionId, statuses, openTransientTab }: WebPluginSlotProps) {\n const view = parsePlanStatus(statuses[PLAN_STATUS_KEY]);\n\n if (view === undefined) {\n return (\n <p data-testid=\"activity-summary-plan\" className=\"px-1 text-sm text-po-dim\">\n no plan written yet\n </p>\n );\n }\n\n return (\n <div data-testid=\"activity-plan\" className=\"flex flex-col gap-0.5\">\n <Button\n variant=\"ghost\"\n size=\"card\"\n data-testid=\"activity-plan-open\"\n title={`open ${view.title}`}\n disabled={sessionId === null}\n onClick={() => {\n if (sessionId === null) return;\n openTransientTab(planTab());\n }}\n className=\"min-w-0 gap-0.5 rounded-md px-1 py-1 hover:bg-po-panel\"\n >\n <span className=\"flex w-full min-w-0 items-center gap-1.5\">\n <span\n data-testid=\"activity-plan-title\"\n className=\"min-w-0 flex-1 truncate text-left text-base font-semibold text-po-hi\"\n >\n {view.title}\n </span>\n {view.stamp === '' ? null : (\n <span data-testid=\"activity-plan-stamp\" className=\"shrink-0 text-sm tabular-nums text-po-dim\">\n {view.stamp}\n </span>\n )}\n </span>\n </Button>\n <p className=\"px-1 text-sm leading-relaxed text-po-dim\">open to read or edit; the agent reads what you save.</p>\n </div>\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/web';\n\nimport { PlanActivitySection } from './_components/PlanActivitySection';\n\nexport default defineFill({ slot: 'activity.plan', id: 'plan', component: PlanActivitySection });\n","import { defineLeaderBinding } from '@agimon-ai/po-core/web';\n\nexport default defineLeaderBinding({\n id: 'plan.toggle',\n path: [\n { key: 'p', label: 'plan', detail: 'read-only planning modes' },\n { key: 'e', label: 'toggle', detail: 'enter or leave read-only planning' },\n ],\n command: 'minor plan',\n});\n","import { defineMinorModeFile } from '@agimon-ai/po-core/web';\n\nexport default defineMinorModeFile({ name: 'plan', keys: 'p e', statusKey: 'plan-mode', order: 20 });\n","import type { ToolPromptDialog, ToolPromptRenderProps } from '@agimon-ai/po-core/web';\nimport {\n Button,\n handleOptionListKey,\n Kbd,\n OptionList,\n optionListHint,\n SectionLabel,\n} from '@agimon-ai/po-web-components';\nimport { useEffect, useRef, useState } from 'react';\n\nimport { PLAN_REVIEW_OPTIONS, PLAN_REVIEW_TITLE } from '../../../../../../types/planApi';\n\n/** Claims only the selector opened by complete_plan, leaving unrelated extension dialogs alone. */\nexport function claimsPlanReviewPrompt(dialog: ToolPromptDialog): boolean {\n return (\n dialog.method === 'select' &&\n dialog.title === PLAN_REVIEW_TITLE &&\n dialog.options.length === PLAN_REVIEW_OPTIONS.length &&\n PLAN_REVIEW_OPTIONS.every((option, index) => dialog.options[index] === option)\n );\n}\n\n/** Keeps plan approval in the composer so the conversation remains visible while the user decides. */\nexport function PlanReviewPrompt({ dialog, answer, cancel }: ToolPromptRenderProps) {\n const [cursor, setCursor] = useState(0);\n const frame = useRef<HTMLDivElement>(null);\n\n useEffect(() => frame.current?.focus(), [dialog.id]);\n\n return (\n <div\n ref={frame}\n role=\"group\"\n tabIndex={-1}\n data-testid=\"plan-review-prompt\"\n className=\"flex min-w-0 flex-col overflow-hidden outline-none\"\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n cancel();\n return;\n }\n handleOptionListKey(event, {\n options: dialog.options,\n cursor,\n onCursorChange: setCursor,\n onSelect: answer,\n });\n }}\n >\n <div className=\"flex flex-col gap-1 px-3.5 pt-3 pb-2\">\n <SectionLabel>plan review</SectionLabel>\n <p className=\"text-base font-semibold leading-relaxed text-po-hi\">{dialog.title}</p>\n <p className=\"text-sm leading-relaxed text-po-dim\">\n Review the plan in the conversation before choosing what happens next.\n </p>\n </div>\n\n <OptionList\n options={dialog.options}\n cursor={cursor}\n onCursorChange={setCursor}\n onSelect={answer}\n testIdPrefix=\"plan-review-option\"\n className=\"max-h-48 px-3.5 pb-3\"\n />\n\n <div className=\"flex min-h-[34px] items-center gap-2 border-t border-po-border-soft px-3.5 py-2\">\n <span className=\"text-sm text-po-dim\">\n {optionListHint(dialog.options.length)} · <Kbd>esc</Kbd> cancels\n </span>\n <Button variant=\"outline\" size=\"sm\" data-testid=\"plan-review-cancel\" className=\"ml-auto\" onClick={cancel}>\n cancel\n </Button>\n </div>\n </div>\n );\n}\n","import type { ToolResultView } from '@agimon-ai/po-core/web';\nimport type { MessageLine, MessageLineTone } from '@agimon-ai/po-web-components';\n\n/**\n * Purpose-first summaries for the plan-mode tools. The TUI leaves these on\n * Pi's default shell, so the shapes here come straight from the tool\n * definitions in src/services/planServerSession/index.ts: write_plan and complete_plan\n * report through `details` (written, path, phase, exited), run_fable_plan\n * carries the broker result, and record_debug_evidence only confirms.\n */\n\nexport const PLAN_TOOL_NAMES = ['record_debug_evidence', 'run_fable_plan', 'write_plan', 'complete_plan'] as const;\n\n/** The toned lines the shared MessageLines draws; the vocabulary is the components package's. */\nexport type LineTone = MessageLineTone;\n/** `label` names an evidence field the text leads with, so a layout can set it apart without parsing the text. */\nexport type ToolLine = MessageLine & { label?: string };\n\nexport interface PlanCallSummary {\n action: string;\n detail?: string;\n metadata: string[];\n}\n\nexport interface PlanRenderOptions {\n expanded: boolean;\n isError: boolean;\n isPartial: boolean;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nconst COLLAPSED_BODY_LINES = 12;\nconst PREVIEW_LENGTH = 72;\n\nconst EVIDENCE_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['logs', 'log'],\n ['correlatedTraceEvidence', 'trace'],\n ['processOutput', 'process output'],\n ['browserConsoleEvidence', 'console entry'],\n ['correlationIds', 'correlation id'],\n ['timestamps', 'timestamp'],\n ['verifiedFacts', 'verified fact'],\n ['hypotheses', 'hypothesis'],\n ['unavailableEvidence', 'unavailable item'],\n];\n\nconst PACKET_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['goal', 'goal'],\n ['constraints', 'constraint'],\n ['decisions', 'decision'],\n ['verifiedFindings', 'verified finding'],\n ['inferredFindings', 'inferred finding'],\n ['unresolvedQuestions', 'open question'],\n];\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? (value as JsonRecord) : undefined;\n}\n\nfunction inlineText(value: string): string {\n let normalized = '';\n for (const character of value) {\n const code = character.codePointAt(0) ?? 0;\n normalized += code <= 31 || code === 127 ? ' ' : character;\n }\n return normalized.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction readString(record: JsonRecord | undefined, key: string): string | undefined {\n const value = record?.[key];\n return typeof value === 'string' ? inlineText(value) || undefined : undefined;\n}\n\nfunction readNumber(record: JsonRecord | undefined, key: string): number | undefined {\n const value = record?.[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction listLength(record: JsonRecord, key: string): number {\n const value = record[key];\n return Array.isArray(value) ? value.length : 0;\n}\n\nfunction plural(count: number, singular: string): string {\n if (count === 1) return singular;\n if (singular.endsWith('y')) return `${singular.slice(0, -1)}ies`;\n return `${singular}s`;\n}\n\nfunction preview(value: string | undefined): string | undefined {\n if (!value) return undefined;\n return value.length > PREVIEW_LENGTH ? `${value.slice(0, PREVIEW_LENGTH - 3)}…` : value;\n}\n\nfunction countMetadata(args: JsonRecord, lists: ReadonlyArray<[string, string]>): string[] {\n return lists.flatMap(([key, label]) => {\n const count = listLength(args, key);\n return count > 0 ? [`${count} ${plural(count, label)}`] : [];\n });\n}\n\nfunction line(text: string, tone: LineTone, extra: Omit<ToolLine, 'text' | 'tone'> = {}): ToolLine {\n return { text, tone, ...extra };\n}\n\nfunction outputText(result: ToolResultView | null): string {\n if (!result) return '';\n return result.content\n .flatMap((item) => {\n const record = asRecord(item);\n return record?.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n })\n .join('\\n');\n}\n\nfunction bodyLines(text: string, expanded: boolean): ToolLine[] {\n const all = text\n .split('\\n')\n .map((entry) => entry.trimEnd())\n .filter((entry) => entry.length > 0);\n const shown = expanded ? all : all.slice(0, COLLAPSED_BODY_LINES);\n const lines = shown.map((entry) => line(entry, 'text'));\n if (all.length > shown.length) lines.push(line(`… ${all.length - shown.length} more lines`, 'dim'));\n return lines;\n}\n\n/** The header beside the tool name: what the call is for and how much it carries. */\nexport function planCallSummary(toolName: string, args: JsonRecord): PlanCallSummary {\n if (toolName === 'record_debug_evidence') {\n const issue = preview(readString(args, 'issue'));\n return {\n action: 'record evidence',\n ...(issue ? { detail: issue } : {}),\n metadata: countMetadata(args, EVIDENCE_LISTS),\n };\n }\n if (toolName === 'run_fable_plan') {\n const metadata = countMetadata(args, PACKET_LISTS);\n if (readString(args, 'currentPlan')) metadata.push('with current plan');\n return { action: 'fable draft', metadata };\n }\n if (toolName === 'write_plan') return { action: 'save plan', metadata: [] };\n const decision = readString(args, 'decision');\n return { action: decision ? `decide ${decision}` : 'request approval', metadata: [] };\n}\n\nfunction evidenceLines(args: JsonRecord, result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const recorded = asRecord(result?.details)?.recorded === true;\n const lines = [\n recorded\n ? line('✓ evidence recorded as planning context', 'success')\n : line(`○ ${inlineText(outputText(result)) || 'not recorded'}`, 'muted'),\n ];\n if (!options.expanded) return lines;\n const fields: ReadonlyArray<[string, string]> = [\n ['issue', 'issue'],\n ['expectedBehavior', 'expected'],\n ['reproductionAttempt', 'reproduction'],\n ['actualBehavior', 'actual'],\n ];\n for (const [key, label] of fields) {\n const value = readString(args, key);\n if (value) lines.push(line(`${label} ${value}`, 'text', { label }));\n }\n for (const [key, label] of EVIDENCE_LISTS) {\n const raw = args[key];\n const items = Array.isArray(raw) ? raw.filter((item): item is string => typeof item === 'string') : [];\n if (items.length === 0) continue;\n lines.push(line(plural(items.length, label), 'hi', { bold: true }));\n lines.push(...items.map((item) => line(inlineText(item), 'text', { indent: true })));\n }\n return lines;\n}\n\nfunction fableLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const text = outputText(result);\n if (details?.started !== true) {\n const code = readString(details, 'errorCode');\n return [line(`○ ${inlineText(text) || 'fable planning did not start'}${code ? ` · ${code}` : ''}`, 'muted')];\n }\n const status = readString(details, 'status') ?? 'unknown';\n const draft = typeof details?.draft === 'string' ? details.draft : undefined;\n const code = readString(details, 'errorCode');\n if (!draft) return [line(`✗ fable planning ${status}${code ? ` · ${code}` : ''}`, 'error')];\n const finished = status === 'completed';\n return [\n line(\n `${finished ? '✓' : '!'} fable draft · ${status}${code ? ` · ${code}` : ''}`,\n finished ? 'success' : 'warning',\n {\n bold: true,\n },\n ),\n ...bodyLines(draft, options.expanded),\n ];\n}\n\nfunction writeLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const path = readString(details, 'path');\n if (options.isPartial) {\n const phase = readString(details, 'phase') ?? 'checking';\n return [line(`◐ ${phase}${path ? ` ${path}` : ''}`, 'warning')];\n }\n const duration = readNumber(details, 'durationMs');\n if (details?.written === true) {\n return [line(`✓ wrote ${path ?? 'the plan'}${duration === undefined ? '' : ` · ${duration}ms`}`, 'success')];\n }\n const lines = [line(`○ ${inlineText(outputText(result)) || 'plan not written'}`, 'muted')];\n if (path) lines.push(line(`path ${path}`, 'dim'));\n return lines;\n}\n\nfunction completeLines(result: ToolResultView | null): ToolLine[] {\n const text = inlineText(outputText(result));\n if (asRecord(result?.details)?.exited === true) {\n return [line(`✓ plan mode exited${text ? ` · ${text}` : ''}`, 'success')];\n }\n return [line(`○ staying in plan mode${text ? ` · ${text}` : ''}`, 'muted')];\n}\n\n/** Why a plan tool call failed, as the tool said it on one line; empty when it said nothing. */\nexport function planFailureReason(result: ToolResultView | null): string {\n return inlineText(outputText(result));\n}\n\n/** The body of a plan tool card: the outcome line, plus the carried detail once expanded. */\nexport function planResultLines(\n toolName: string,\n args: JsonRecord,\n result: ToolResultView | null,\n options: PlanRenderOptions,\n): ToolLine[] {\n if (options.isError) {\n return [line(`✗ ${planFailureReason(result) || `${toolName} failed`}`, 'error')];\n }\n if (toolName === 'record_debug_evidence') return evidenceLines(args, result, options);\n if (toolName === 'run_fable_plan') {\n if (options.isPartial) return [line('◐ drafting with the local Fable broker', 'warning')];\n return fableLines(result, options);\n }\n if (toolName === 'write_plan') return writeLines(result, options);\n if (options.isPartial) return [line('◐ waiting for the review decision', 'warning')];\n return completeLines(result);\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItem, MessageItemBody, MessageItemHeader, MessageLines, toolTone } from '@agimon-ai/po-web-components';\n\nimport { planCallSummary, planResultLines } from '../_lib/planToolRender';\n\n/**\n * The plan tools' timeline item: the plan action, the issue or decision it\n * targets, and what the packet carries in the header; the outcome line, with\n * the recorded evidence or the Fable draft once expanded, in the body.\n */\nexport function PlanToolMessage({ toolName, args, result, running, isError }: ToolMessageRenderProps) {\n const summary = planCallSummary(toolName, args);\n const collapsed = planResultLines(toolName, args, result, { expanded: false, isError, isPartial: running });\n const full = planResultLines(toolName, args, result, { expanded: true, isError, isPartial: running });\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={full.length > collapsed.length}>\n {({ expanded }) => (\n <>\n <MessageItemHeader title={summary.action}>\n <span\n data-testid={`tool-call-${toolName}`}\n title={[summary.detail, ...summary.metadata].filter(Boolean).join(' · ') || undefined}\n className=\"min-w-0 flex-1 truncate text-po-dim\"\n >\n {[summary.detail, ...summary.metadata].filter(Boolean).join(' · ')}\n </span>\n </MessageItemHeader>\n {(expanded ? full : collapsed).length > 0 ? (\n <MessageItemBody data-testid={`tool-result-${toolName}`}>\n <MessageLines lines={expanded ? full : collapsed} />\n </MessageItemBody>\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { claimsPlanReviewPrompt, PlanReviewPrompt } from './_components/PlanReviewPrompt';\nimport { PlanToolMessage } from './_components/PlanToolMessage';\nimport { PLAN_TOOL_NAMES } from './_lib/planToolRender';\n\nexport default defineToolRenderer({\n tools: [...PLAN_TOOL_NAMES],\n message: PlanToolMessage,\n prompt: { claims: claimsPlanReviewPrompt, component: PlanReviewPrompt },\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/po-core/web';\n\nimport settingPlan from '../src/extensions/(frontend)/setting/plan.web';\nimport settingPlan2 from '../src/extensions/workspaces/(frontend)/setting/plan.web';\nimport activityGroupPlan from '../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.web';\nimport fillPlan from '../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.web';\nimport leaderToggle from '../src/extensions/workspaces/sessions/(frontend)/leader/toggle.web';\nimport modePlan from '../src/extensions/workspaces/sessions/(frontend)/mode/plan/mode.web';\nimport toolPlan from '../src/extensions/workspaces/sessions/(frontend)/tool/plan.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: 'plan',\n global: {\n get settingsSections(): WebPluginContributions['settingsSections'] { return [via({ id: 'plan' }, settingPlan)]; },\n },\n workspace: {\n get settingsSections(): WebPluginContributions['settingsSections'] { return [via({ id: 'plan' }, settingPlan2)]; },\n },\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'plan' }, activityGroupPlan)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.plan', id: 'plan' }, fillPlan)]; },\n get leaderBindings(): WebPluginContributions['leaderBindings'] { return [via({ id: 'plan.toggle' }, leaderToggle)]; },\n get minorModes(): WebPluginContributions['minorModes'] { return [via({ name: 'plan' }, modePlan)]; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['plan'] }, toolPlan)]; },\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"web.mjs","names":["settingPlan","settingPlan2","activityGroupPlan","fillPlan","leaderToggle","modePlan","toolPlan"],"sources":["../../src/types/planSettings.ts","../../src/extensions/(frontend)/_lib/planSettings.ts","../../src/extensions/(frontend)/setting/plan.web.ts","../../src/extensions/workspaces/(frontend)/setting/plan.web.ts","../../src/types/planApi.ts","../../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.web.ts","../../src/types/apiRoutes.ts","../../generated/client.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_lib/planApi.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanPanel.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/_components/PlanActivitySection.tsx","../../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.web.tsx","../../src/extensions/workspaces/sessions/(frontend)/leader/toggle.web.ts","../../src/extensions/workspaces/sessions/(frontend)/mode/plan/mode.web.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanReviewPrompt.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/_lib/planToolRender.ts","../../src/extensions/workspaces/sessions/(frontend)/tool/_components/PlanToolMessage.tsx","../../src/extensions/workspaces/sessions/(frontend)/tool/plan.web.tsx","../../generated/web.ts"],"sourcesContent":["/**\n * The planning settings, described once for both surfaces.\n *\n * The terminal panel and the cockpit settings page render the same five fields,\n * and the one thing they must agree on is which config key each one writes. So\n * the ids, labels and key paths live here rather than in either renderer.\n *\n * It lives under src/types because that is the one server root a browser bundle\n * may read, which also means it may import nothing: pulling the config package\n * in for the thinking levels would drag a node module into the page. They are\n * spelled out instead, and a test asserts they still match the parser's.\n */\n\nexport const PLAN_CONFIG_SECTION_ID = 'planning';\nconst PLANNING_PATH = ['modes', PLAN_CONFIG_SECTION_ID] as const;\nconst MAIN_KEY = 'main';\nconst SUBAGENTS_KEY = 'subagents';\n\n/** Both agents fall back to the session's own settings when left unset. */\nconst INHERIT_MODEL = 'inherit the session model';\nconst INHERIT_THINKING = 'inherit';\n\n/** Mirrors PO_PLANNING_THINKING_LEVELS; pinned by planConfig's test. */\nexport const PLAN_THINKING_LEVELS: readonly string[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max'];\n\nexport interface PlanSettingShape {\n readonly id: string;\n readonly label: string;\n readonly keyPath: readonly string[];\n readonly placeholder: string;\n readonly detail: string;\n /** Present for a closed set; a renderer offers these rather than free text. */\n readonly options?: readonly string[];\n /** Offers the machine's authenticated models rather than free text. */\n readonly models?: boolean;\n}\n\nexport const PLAN_SETTING_SHAPES: readonly PlanSettingShape[] = [\n {\n id: 'main.model',\n label: 'main model',\n keyPath: [...PLANNING_PATH, MAIN_KEY, 'model'],\n placeholder: INHERIT_MODEL,\n detail: 'model the main agent switches to while plan mode is on.',\n models: true,\n },\n {\n id: 'main.thinking',\n label: 'main thinking',\n keyPath: [...PLANNING_PATH, MAIN_KEY, 'thinking'],\n placeholder: INHERIT_THINKING,\n detail: 'thinking level appended to the main model while planning.',\n options: PLAN_THINKING_LEVELS,\n },\n {\n id: 'subagents.model',\n label: 'subagent model',\n keyPath: [...PLANNING_PATH, SUBAGENTS_KEY, 'model'],\n placeholder: INHERIT_MODEL,\n detail: 'model forced onto delegated planning subagents.',\n models: true,\n },\n {\n id: 'subagents.thinking',\n label: 'subagent thinking',\n keyPath: [...PLANNING_PATH, SUBAGENTS_KEY, 'thinking'],\n placeholder: INHERIT_THINKING,\n detail: 'thinking level appended to the subagent model.',\n options: PLAN_THINKING_LEVELS,\n },\n {\n id: 'plansdirectory',\n label: 'plans directory',\n keyPath: [...PLANNING_PATH, 'plansDirectory'],\n placeholder: '~/.po/plans',\n detail: 'absolute, repo-relative, or under ~. written plans land here.',\n },\n];\n","import type { SettingsSectionContribution } from '@agimon-ai/po-core/web';\n\nimport { PLAN_CONFIG_SECTION_ID, PLAN_SETTING_SHAPES } from '../../../types/planSettings';\n\n/**\n * The planning settings, as the cockpit's settings page renders them.\n *\n * Built from the same descriptor table the terminal panel uses, so the two\n * surfaces cannot disagree about which config key a field writes. The host owns\n * the scope switch and the writes; this only says what the fields are.\n */\nexport const planSettingsSection: SettingsSectionContribution = {\n id: PLAN_CONFIG_SECTION_ID,\n label: 'planning',\n detail: 'the models plan mode switches to, and where written plans land',\n order: 30,\n fields: PLAN_SETTING_SHAPES.map((shape) => ({\n id: shape.id,\n label: shape.label,\n // A model field offers the machine's authenticated models, which only the\n // host can enumerate; the rest are a closed set or free text.\n kind: shape.models === true || shape.options !== undefined ? ('select' as const) : ('text' as const),\n keyPath: shape.keyPath,\n detail: shape.detail,\n placeholder: shape.placeholder,\n ...(shape.models === true ? { optionsFrom: 'models' as const } : {}),\n ...(shape.options === undefined\n ? {}\n : { options: shape.options.map((option) => ({ value: option, label: option })) }),\n })),\n};\n","import { defineSettingsSection } from '@agimon-ai/po-core/web';\nimport { TaskIcon } from '@agimon-ai/po-web-components';\n\nimport { planSettingsSection } from '../_lib/planSettings';\n\nexport default defineSettingsSection({ ...planSettingsSection, icon: TaskIcon });\n","import { defineSettingsSection } from '@agimon-ai/po-core/web';\nimport { TaskIcon } from '@agimon-ai/po-web-components';\n\nimport { planSettingsSection } from '../../../(frontend)/_lib/planSettings';\n\nexport default defineSettingsSection({ ...planSettingsSection, icon: TaskIcon });\n","/**\n * The wire vocabulary this package's API shares with whatever calls it.\n *\n * It lives under src/types because that is the one server root a browser\n * bundle may read: the routes answer with these shapes and the cockpit plugin\n * reads them, so neither half can drift from the other. The paths themselves\n * are not here; they are declared once in `./apiRoutes`, which the Hono app\n * and the generated client both read.\n *\n * Two routes, and neither takes a path. A session has one current plan, so\n * `current` answers it and `content` takes the manual save back; the file they\n * act on is the one write_plan recorded, never one the page named. That is\n * also why there is nothing to escape here: a reader cannot address a second\n * file through these URLs.\n */\n\n/** Where a host mounts this package's API; the segment after /api/plugins/. */\nexport const API_BASE_PATH = 'plans';\n\n/**\n * Footer status key the session publishes once a plan exists, which is what\n * makes the cockpit's activity group appear at all. It outlives plan mode: the\n * plan is most worth reading while the agent implements it.\n */\nexport const PLAN_STATUS_KEY = 'po-plan-document';\n\n/** The selector contract shared by complete_plan and its cockpit composer prompt. */\nexport const PLAN_REVIEW_TITLE = 'Plan complete. What would you like to do?';\nexport const EXIT_PLAN_MODE_CHOICE = 'Exit plan mode and start implementation';\nexport const CONTINUE_PLANNING_CHOICE = 'Continue planning';\nexport const EXIT_PLAN_DECISION = 'exit';\nexport const CONTINUE_PLAN_DECISION = 'continue';\n\n/**\n * The label the reader sees paired with the decision the tool acts on. A headless\n * client answers with `value`, so a server plugin never has to recognise the wording; Pi's\n * own `ui.select` carries labels only, so its half maps the label back itself.\n */\nexport const PLAN_REVIEW_CHOICES = [\n { label: EXIT_PLAN_MODE_CHOICE, value: EXIT_PLAN_DECISION },\n { label: CONTINUE_PLANNING_CHOICE, value: CONTINUE_PLAN_DECISION },\n] as const;\n\n/** The same options as bare labels, which is all Pi's select and the composer prompt need. */\nexport const PLAN_REVIEW_OPTIONS = PLAN_REVIEW_CHOICES.map((choice) => choice.label);\n\n/** Between the plan's title and the stamp that marks a rewrite. */\nconst STATUS_SEPARATOR = ' · ';\n\n/** Strips the colour a session may have themed a status with. */\nconst ANSI = /\u001b\\[[0-9;]*m/gu;\n\n/** The status line the session publishes; the stamp changes on every write. */\nexport function formatPlanStatus(title: string, stamp: string): string {\n return `${title}${STATUS_SEPARATOR}${stamp}`;\n}\n\n/** What a reader gets out of the status line. */\nexport interface PlanStatusView {\n title: string;\n /** When the plan was last written, as the session worded it; empty when it said nothing. */\n stamp: string;\n}\n\n/**\n * Reading the status line back. Statuses reach a plugin raw, so the colour a\n * session may have added comes off here. A title can itself contain the\n * separator, so the stamp is taken from the last one rather than the first.\n */\nexport function parsePlanStatus(raw: string | undefined): PlanStatusView | undefined {\n if (raw === undefined) return undefined;\n const text = raw.replace(ANSI, '').trim();\n if (text === '') return undefined;\n const cut = text.lastIndexOf(STATUS_SEPARATOR);\n if (cut === -1) return { title: text, stamp: '' };\n return { title: text.slice(0, cut).trim(), stamp: text.slice(cut + STATUS_SEPARATOR.length).trim() };\n}\n\n/**\n * What write_plan recorded about this session's plan.\n *\n * The absolute path is the point of it: the extension resolves the plans\n * directory against the harness root, which no other process knows, so it\n * writes down where the plan landed rather than leaving the API to derive a\n * location it would sometimes get wrong.\n */\nexport interface PlanPointerRecord {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n}\n\n/** The plan as it stands on disk right now, which is what the source view edits. */\nexport interface PlanDetailView {\n path: string;\n title: string;\n writtenAt: string;\n planId?: string;\n content: string;\n /** sha256 of the content; the token a save hands back to prove it is not stale. */\n hash: string;\n /** True when the plan is missing or past the size cap, so `content` is empty. */\n unavailable: boolean;\n reason?: string;\n}\n\n/** What the save route takes. */\nexport interface PlanSaveRequest {\n /** The hash the reader loaded; a mismatch means the plan moved underneath them. */\n expectedHash: string;\n content: string;\n}\n\n/** What the save route answers with. */\nexport interface PlanSaveView {\n hash: string;\n}\n\n/** What a route reports when it refuses; the page shows `error` verbatim. */\nexport interface PlanErrorView {\n error: string;\n /** On a stale save, the hash the plan actually has now. */\n hash?: string;\n}\n","import { defineActivityGroup } from '@agimon-ai/po-core/web';\n\nimport { PLAN_STATUS_KEY } from '../../../../../types/planApi';\n\n// Keyed off the saved plan rather than the mode because the plan remains useful\n// while it is being implemented after the read-only mode exits.\nexport default defineActivityGroup({\n name: 'plan',\n keys: 'p e',\n statusKey: PLAN_STATUS_KEY,\n marksBackgroundWork: false,\n order: 25,\n});\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport type { PlanDetailView, PlanSaveView } from './planApi';\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/workspaces/sessions/(backend)/api/plans/`, so the mount is\n * stated once, by the folder that creates it. The paths used to be written\n * here as helpers, again in the contract, and again inside every URL the page\n * built, and the copies were free to disagree.\n *\n * This is the one file the routes, the Hono app and the browser all read, so a\n * path cannot move on one side alone.\n *\n * Neither route takes a query or a path parameter: a session has one current\n * plan, so `current` answers it and `save` takes the manual write back.\n */\nconst routes = {\n current: {\n method: 'GET',\n path: '/current',\n response: undefined as unknown as ApiResponseOf<PlanDetailView>,\n },\n save: {\n method: 'PUT',\n path: '/content',\n response: undefined as unknown as ApiResponseOf<PlanSaveView>,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\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 'plans' at. */\nexport const apiScopes = ['session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'plans',\n transport: (input, init) => browserTransport.fetch(input, init),\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../../generated/client';\nimport type { PlanDetailView } from '../../../../../../types/planApi';\n\n/**\n * The page's half of this package's session API: the current plan, and the\n * manual save.\n *\n * These are adapters now, not a transport. The generated client owns the URL\n * and the sealed transport with it, so nothing here spells a route or reaches\n * for `fetch`. What stays is this package's own vocabulary: which refusals the\n * reader is shown, and the stale-save contract the editor depends on.\n */\n\nconst UNREACHABLE = 'The session is unreachable.';\nconst NO_PLAN = 'This session has not written a plan yet.';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** The message a reader is shown: the route's own words, or why there were none. */\nfunction messageOf(result: { status: number; error: string }): string {\n if (result.status === 0) return UNREACHABLE;\n return result.error === '' ? `The session answered ${String(result.status)}.` : result.error;\n}\n\nexport type FetchPlanResult = { ok: true; detail: PlanDetailView } | { ok: false; error: string };\n\nexport async function fetchPlan(sessionId: string): Promise<FetchPlanResult> {\n const result = await api.session(sessionId).current();\n // A session that has written nothing answers 404, which is not a failure the\n // reader should be shown as one.\n if (result.status === 404) return { ok: false, error: result.ok || result.error === '' ? NO_PLAN : result.error };\n if (!result.ok) return { ok: false, error: messageOf(result) };\n if (!isRecord(result.data)) return { ok: false, error: 'The session answered with no plan.' };\n return { ok: true, detail: result.data };\n}\n\nexport type SavePlanResult =\n | { ok: true; hash: string }\n /** The plan moved under the editor; `hash` is what it holds now. */\n | { ok: false; stale: true; error: string; hash?: string }\n | { ok: false; stale: false; error: string };\n\nexport async function savePlan(sessionId: string, expectedHash: string, content: string): Promise<SavePlanResult> {\n const result = await api.session(sessionId).save({ body: { expectedHash, content } });\n // The agent can rewrite the plan while a reader is still editing it. A moved\n // hash is the one refusal the editor recovers from, so it is read before the\n // generic failure.\n if (result.status === 409) {\n const data = result.ok ? undefined : result.data;\n const hash = isRecord(data) && typeof data.hash === 'string' ? data.hash : undefined;\n return {\n ok: false,\n stale: true,\n error: result.ok ? 'The plan changed since it was opened.' : messageOf(result),\n ...(hash === undefined ? {} : { hash }),\n };\n }\n if (!result.ok) return { ok: false, stale: false, error: messageOf(result) };\n return { ok: true, hash: isRecord(result.data) && typeof result.data.hash === 'string' ? result.data.hash : '' };\n}\n","import type { TransientTab, WebPluginSlotProps } from '@agimon-ai/po-core/web';\nimport { Button, CodeEditor, Markdown } from '@agimon-ai/po-web-components';\nimport { useEffect, useState } from 'react';\n\nimport { PLAN_STATUS_KEY, type PlanDetailView } from '../../../../../../types/planApi';\nimport { fetchPlan, savePlan } from '../_lib/planApi';\n\n/**\n * The plan's tab: what the agent decided, and what the reader wants changed.\n *\n * Two views over the same file. A plan is read, not diffed, so preview is\n * where it opens; source is a real editor, line numbers and markdown colour\n * and all, because a reader who corrects a step themselves is cheaper than a\n * turn spent asking for it. The save goes to the plan file the\n * session recorded, and the next turn reads that file, so a correction made\n * here is the plan the agent implements.\n *\n * The tab is transient: it belongs to the session and the page, and closing it\n * is how it ends. It refetches whenever the session republishes its plan\n * status, which is what a rewrite by the agent looks like from here.\n */\n\ntype View = 'preview' | 'source';\n\n/** One tab per session; the plan is singular, so the id needs nothing else. */\nexport const PLAN_TAB_ID = 'plan-document';\n\n/** The one note that is not an error: anything else in that slot failed. */\nconst SAVED_NOTE = 'saved';\n\nexport function PlanPanel({ sessionId, statuses, closeTransientTab }: WebPluginSlotProps) {\n const [detail, setDetail] = useState<PlanDetailView | undefined>(undefined);\n const [error, setError] = useState<string | undefined>(undefined);\n const [loading, setLoading] = useState(false);\n const [view, setView] = useState<View>('preview');\n const [draft, setDraft] = useState<string | undefined>(undefined);\n const [saving, setSaving] = useState(false);\n const [saveNote, setSaveNote] = useState<string | undefined>(undefined);\n\n // One fetch per open, and again whenever the session republishes the status:\n // its stamp changes on every write, which is the cheapest signal that the\n // agent has revised the plan under the reader.\n const revision = statuses[PLAN_STATUS_KEY] ?? '';\n useEffect(() => {\n if (sessionId === null) return;\n let cancelled = false;\n // The fetch below is the external system; this marks it in flight before it starts.\n // oxlint-disable-next-line react/set-state-in-effect\n setLoading(true);\n void fetchPlan(sessionId).then((result) => {\n if (cancelled) return;\n setLoading(false);\n if (result.ok) {\n setDetail(result.detail);\n setError(undefined);\n // A rewrite invalidates an unsaved edit's baseline, so the editor goes\n // back to what is on disk rather than offering a save that must fail.\n setDraft(undefined);\n setSaveNote(undefined);\n return;\n }\n setDetail(undefined);\n setError(result.error);\n });\n return () => {\n cancelled = true;\n };\n }, [sessionId, revision]);\n\n const content = draft ?? detail?.content ?? '';\n\n const save = async (): Promise<void> => {\n if (sessionId === null || detail === undefined || draft === undefined) return;\n setSaving(true);\n const result = await savePlan(sessionId, detail.hash, draft);\n setSaving(false);\n if (result.ok) {\n setSaveNote(SAVED_NOTE);\n setDraft(undefined);\n const refreshed = await fetchPlan(sessionId);\n if (refreshed.ok) setDetail(refreshed.detail);\n else setError(refreshed.error);\n return;\n }\n setSaveNote(result.error);\n };\n\n return (\n <div data-testid=\"plan-panel\" className=\"flex min-h-0 flex-1 flex-col\">\n <header className=\"flex shrink-0 items-center gap-2 border-b border-po-border px-4 py-2\">\n <span data-testid=\"plan-title\" className=\"min-w-0 flex-1 truncate text-lg font-semibold text-po-hi\">\n {detail?.title ?? 'plan'}\n </span>\n <nav className=\"flex shrink-0 items-center gap-1\">\n {(['preview', 'source'] as View[]).map((entry) => (\n <Button\n key={entry}\n variant={view === entry ? 'outline' : 'ghost'}\n size=\"xs\"\n data-testid={`plan-view-${entry}`}\n onClick={() => setView(entry)}\n >\n {entry}\n </Button>\n ))}\n </nav>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-testid=\"plan-close\"\n onClick={() => closeTransientTab(PLAN_TAB_ID)}\n className=\"shrink-0\"\n >\n close\n </Button>\n </header>\n\n {loading && detail === undefined ? (\n <p data-testid=\"plan-loading\" className=\"px-4 py-3 text-sm text-po-dim\">\n reading this session's plan…\n </p>\n ) : null}\n {error === undefined ? null : (\n <p data-testid=\"plan-error\" className=\"px-4 py-3 text-sm text-po-red\">\n {error}\n </p>\n )}\n\n <div className=\"flex min-h-0 flex-1 flex-col\">\n {detail === undefined ? null : detail.unavailable ? (\n <p data-testid=\"plan-unavailable\" className=\"px-4 py-3 text-sm text-po-dim\">\n {detail.reason ?? 'this plan cannot be shown'}\n </p>\n ) : view === 'preview' ? (\n <div\n data-testid=\"plan-preview\"\n className=\"flex min-h-0 flex-1 flex-col gap-2 overflow-y-auto p-4 text-base text-po-text\"\n >\n <Markdown text={content} />\n </div>\n ) : (\n <>\n {/* The editor owns the scrolling: its gutter has to stay put while\n the text moves, which an outer scroll container would break. */}\n <CodeEditor\n data-testid=\"plan-source\"\n value={content}\n path={detail.path}\n onChange={setDraft}\n className=\"min-h-0 flex-1\"\n />\n <div className=\"flex shrink-0 items-center gap-2 border-t border-po-border px-3 py-2\">\n <Button\n variant=\"outline\"\n size=\"xs\"\n data-testid=\"plan-save\"\n loading={saving}\n disabled={draft === undefined || saving}\n onClick={() => void save()}\n >\n save to disk\n </Button>\n {draft === undefined ? null : (\n <Button variant=\"ghost\" size=\"xs\" data-testid=\"plan-revert\" onClick={() => setDraft(undefined)}>\n discard edits\n </Button>\n )}\n {saveNote === undefined ? null : (\n <span\n data-testid=\"plan-save-note\"\n className={saveNote === SAVED_NOTE ? 'text-sm text-po-green' : 'text-sm text-po-red'}\n >\n {saveNote}\n </span>\n )}\n </div>\n </>\n )}\n </div>\n\n {detail === undefined ? null : (\n <footer data-testid=\"plan-source-path\" className=\"shrink-0 truncate border-t border-po-border px-4 py-1.5\">\n <span className=\"font-mono text-sm text-po-dim\">{detail.path}</span>\n </footer>\n )}\n </div>\n );\n}\n\n/** The transient tab the plan opens in; opening it again only focuses it. */\nexport function planTab(): TransientTab {\n return { id: PLAN_TAB_ID, label: 'plan', panel: PlanPanel };\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/web';\nimport { Button } from '@agimon-ai/po-web-components';\n\nimport { parsePlanStatus, PLAN_STATUS_KEY } from '../../../../../../types/planApi';\nimport { planTab } from './PlanPanel';\n\n/**\n * The plan group's body in the activity dock: the plan this session wrote, and\n * the way in.\n *\n * A plan is one document, so the group is one row rather than a list. The row\n * is the whole point of the group: a written plan the reader cannot open is a\n * path in a tool card, which is what this replaces.\n *\n * The session's status line carries the title and the time it was last\n * written, so the row says what the plan is and whether the agent has revised\n * it since the reader last looked, without the dock holding any state.\n */\nexport function PlanActivitySection({ sessionId, statuses, openTransientTab }: WebPluginSlotProps) {\n const view = parsePlanStatus(statuses[PLAN_STATUS_KEY]);\n\n if (view === undefined) {\n return (\n <p data-testid=\"activity-summary-plan\" className=\"px-1 text-sm text-po-dim\">\n no plan written yet\n </p>\n );\n }\n\n return (\n <div data-testid=\"activity-plan\" className=\"flex flex-col gap-0.5\">\n <Button\n variant=\"ghost\"\n size=\"card\"\n data-testid=\"activity-plan-open\"\n title={`open ${view.title}`}\n disabled={sessionId === null}\n onClick={() => {\n if (sessionId === null) return;\n openTransientTab(planTab());\n }}\n className=\"min-w-0 gap-0.5 rounded-md px-1 py-1 hover:bg-po-panel\"\n >\n <span className=\"flex w-full min-w-0 items-center gap-1.5\">\n <span\n data-testid=\"activity-plan-title\"\n className=\"min-w-0 flex-1 truncate text-left text-base font-semibold text-po-hi\"\n >\n {view.title}\n </span>\n {view.stamp === '' ? null : (\n <span data-testid=\"activity-plan-stamp\" className=\"shrink-0 text-sm tabular-nums text-po-dim\">\n {view.stamp}\n </span>\n )}\n </span>\n </Button>\n <p className=\"px-1 text-sm leading-relaxed text-po-dim\">open to read or edit; the agent reads what you save.</p>\n </div>\n );\n}\n","import { defineFill } from '@agimon-ai/po-core/web';\n\nimport { PlanActivitySection } from './_components/PlanActivitySection';\n\nexport default defineFill({ slot: 'activity.plan', id: 'plan', component: PlanActivitySection });\n","import { defineLeaderBinding } from '@agimon-ai/po-core/web';\n\nexport default defineLeaderBinding({\n id: 'plan.toggle',\n path: [\n { key: 'p', label: 'plan', detail: 'read-only planning modes' },\n { key: 'e', label: 'toggle', detail: 'enter or leave read-only planning' },\n ],\n command: 'minor plan',\n});\n","import { defineMinorModeFile } from '@agimon-ai/po-core/web';\n\nexport default defineMinorModeFile({ name: 'plan', keys: 'p e', statusKey: 'plan-mode', order: 20 });\n","import type { ToolPromptRenderProps } from '@agimon-ai/po-core/web';\nimport {\n Button,\n ChevronDownIcon,\n ChevronRightIcon,\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n handleOptionListKey,\n Kbd,\n OptionList,\n optionListHint,\n SectionLabel,\n} from '@agimon-ai/po-web-components';\nimport { useEffect, useRef, useState } from 'react';\n\n/** Keeps the pending decision available without covering the plan being reviewed. */\nexport function PlanReviewPrompt({\n dialog,\n answer,\n cancel,\n defaultExpanded = true,\n}: ToolPromptRenderProps & { defaultExpanded?: boolean }) {\n const [open, setOpen] = useState(defaultExpanded);\n const [cursor, setCursor] = useState(0);\n const frame = useRef<HTMLDivElement>(null);\n\n useEffect(() => frame.current?.querySelector<HTMLElement>('[role=\"listbox\"]')?.focus(), [dialog.id]);\n\n return (\n <Collapsible\n ref={frame}\n open={open}\n onOpenChange={setOpen}\n role=\"group\"\n aria-label=\"Plan review\"\n data-testid=\"plan-review-prompt\"\n className=\"flex min-w-0 flex-col overflow-hidden\"\n onKeyDown={(event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n event.stopPropagation();\n cancel();\n }\n }}\n >\n <CollapsibleTrigger asChild>\n <Button\n variant=\"ghost\"\n aria-label={open ? 'Collapse plan review' : 'Expand plan review'}\n className=\"h-11 w-full justify-between rounded-none px-3.5\"\n >\n <SectionLabel>plan review</SectionLabel>\n {!open ? <span className=\"ml-auto text-sm font-normal text-po-dim\">Awaiting decision</span> : null}\n {open ? <ChevronDownIcon size={16} /> : <ChevronRightIcon size={16} />}\n </Button>\n </CollapsibleTrigger>\n <CollapsibleContent>\n <div className=\"flex flex-col gap-1 px-3.5 pb-2\">\n <p className=\"text-base font-semibold leading-relaxed text-po-hi\">{dialog.title}</p>\n <p className=\"text-sm leading-relaxed text-po-dim\">\n Review the plan in the conversation before choosing what happens next.\n </p>\n </div>\n <OptionList\n options={dialog.options}\n cursor={cursor}\n onCursorChange={setCursor}\n onSelect={answer}\n onFocus={(event) => {\n const index = Array.from(event.currentTarget.children).indexOf(event.target);\n if (index !== -1) setCursor(index);\n }}\n tabIndex={-1}\n onKeyDown={(event) => {\n handleOptionListKey(event, {\n options: dialog.options,\n cursor,\n onCursorChange: setCursor,\n onSelect: answer,\n });\n }}\n testIdPrefix=\"plan-review-option\"\n className=\"max-h-48 px-3.5 pb-3 outline-none\"\n />\n <div className=\"flex items-center gap-2 border-t border-po-border-soft px-3.5 py-2\">\n <span className=\"text-sm text-po-dim\">\n {optionListHint(dialog.options.length)} · <Kbd>esc</Kbd> cancels\n </span>\n <Button variant=\"outline\" size=\"sm\" data-testid=\"plan-review-cancel\" className=\"ml-auto\" onClick={cancel}>\n cancel\n </Button>\n </div>\n </CollapsibleContent>\n </Collapsible>\n );\n}\n","import type { ToolPromptDialog, ToolResultView } from '@agimon-ai/po-core/web';\nimport type { MessageLine, MessageLineTone } from '@agimon-ai/po-web-components';\n\nimport { PLAN_REVIEW_OPTIONS, PLAN_REVIEW_TITLE } from '../../../../../../types/planApi';\n\n/**\n * Purpose-first summaries for the plan-mode tools. The TUI leaves these on\n * Pi's default shell, so the shapes here come straight from the tool\n * definitions in src/services/planServerSession/index.ts: write_plan and complete_plan\n * report through `details` (written, path, phase, exited), run_fable_plan\n * carries the broker result, and record_debug_evidence only confirms.\n */\n\nexport const PLAN_TOOL_NAMES = ['record_debug_evidence', 'run_fable_plan', 'write_plan', 'complete_plan'] as const;\n\n/** Claims only the selector opened by complete_plan, on either platform. */\nexport function claimsPlanReviewPrompt(dialog: ToolPromptDialog): boolean {\n return (\n dialog.method === 'select' &&\n dialog.title === PLAN_REVIEW_TITLE &&\n dialog.options.length === PLAN_REVIEW_OPTIONS.length &&\n PLAN_REVIEW_OPTIONS.every((option, index) => dialog.options[index] === option)\n );\n}\n\n/** The toned lines the shared MessageLines draws; the vocabulary is the components package's. */\nexport type LineTone = MessageLineTone;\n/** `label` names an evidence field the text leads with, so a layout can set it apart without parsing the text. */\nexport type ToolLine = MessageLine & { label?: string };\n\nexport interface PlanCallSummary {\n action: string;\n detail?: string;\n metadata: string[];\n}\n\nexport interface PlanRenderOptions {\n expanded: boolean;\n isError: boolean;\n isPartial: boolean;\n}\n\ntype JsonRecord = Record<string, unknown>;\n\nconst COLLAPSED_BODY_LINES = 12;\nconst PREVIEW_LENGTH = 72;\n\nconst EVIDENCE_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['logs', 'log'],\n ['correlatedTraceEvidence', 'trace'],\n ['processOutput', 'process output'],\n ['browserConsoleEvidence', 'console entry'],\n ['correlationIds', 'correlation id'],\n ['timestamps', 'timestamp'],\n ['verifiedFacts', 'verified fact'],\n ['hypotheses', 'hypothesis'],\n ['unavailableEvidence', 'unavailable item'],\n];\n\nconst PACKET_LISTS: ReadonlyArray<[key: string, label: string]> = [\n ['goal', 'goal'],\n ['constraints', 'constraint'],\n ['decisions', 'decision'],\n ['verifiedFindings', 'verified finding'],\n ['inferredFindings', 'inferred finding'],\n ['unresolvedQuestions', 'open question'],\n];\n\nfunction asRecord(value: unknown): JsonRecord | undefined {\n return value !== null && typeof value === 'object' && !Array.isArray(value) ? (value as JsonRecord) : undefined;\n}\n\nfunction inlineText(value: string): string {\n let normalized = '';\n for (const character of value) {\n const code = character.codePointAt(0) ?? 0;\n normalized += code <= 31 || code === 127 ? ' ' : character;\n }\n return normalized.replace(/\\s+/gu, ' ').trim();\n}\n\nfunction readString(record: JsonRecord | undefined, key: string): string | undefined {\n const value = record?.[key];\n return typeof value === 'string' ? inlineText(value) || undefined : undefined;\n}\n\nfunction readNumber(record: JsonRecord | undefined, key: string): number | undefined {\n const value = record?.[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction listLength(record: JsonRecord, key: string): number {\n const value = record[key];\n return Array.isArray(value) ? value.length : 0;\n}\n\nfunction plural(count: number, singular: string): string {\n if (count === 1) return singular;\n if (singular.endsWith('y')) return `${singular.slice(0, -1)}ies`;\n return `${singular}s`;\n}\n\nfunction preview(value: string | undefined): string | undefined {\n if (!value) return undefined;\n return value.length > PREVIEW_LENGTH ? `${value.slice(0, PREVIEW_LENGTH - 3)}…` : value;\n}\n\nfunction countMetadata(args: JsonRecord, lists: ReadonlyArray<[string, string]>): string[] {\n return lists.flatMap(([key, label]) => {\n const count = listLength(args, key);\n return count > 0 ? [`${count} ${plural(count, label)}`] : [];\n });\n}\n\nfunction line(text: string, tone: LineTone, extra: Omit<ToolLine, 'text' | 'tone'> = {}): ToolLine {\n return { text, tone, ...extra };\n}\n\nfunction outputText(result: ToolResultView | null): string {\n if (!result) return '';\n return result.content\n .flatMap((item) => {\n const record = asRecord(item);\n return record?.type === 'text' && typeof record.text === 'string' ? [record.text] : [];\n })\n .join('\\n');\n}\n\nfunction bodyLines(text: string, expanded: boolean): ToolLine[] {\n const all = text\n .split('\\n')\n .map((entry) => entry.trimEnd())\n .filter((entry) => entry.length > 0);\n const shown = expanded ? all : all.slice(0, COLLAPSED_BODY_LINES);\n const lines = shown.map((entry) => line(entry, 'text'));\n if (all.length > shown.length) lines.push(line(`… ${all.length - shown.length} more lines`, 'dim'));\n return lines;\n}\n\n/** The header beside the tool name: what the call is for and how much it carries. */\nexport function planCallSummary(toolName: string, args: JsonRecord): PlanCallSummary {\n if (toolName === 'record_debug_evidence') {\n const issue = preview(readString(args, 'issue'));\n return {\n action: 'record evidence',\n ...(issue ? { detail: issue } : {}),\n metadata: countMetadata(args, EVIDENCE_LISTS),\n };\n }\n if (toolName === 'run_fable_plan') {\n const metadata = countMetadata(args, PACKET_LISTS);\n if (readString(args, 'currentPlan')) metadata.push('with current plan');\n return { action: 'fable draft', metadata };\n }\n if (toolName === 'write_plan') return { action: 'save plan', metadata: [] };\n const decision = readString(args, 'decision');\n return { action: decision ? `decide ${decision}` : 'request approval', metadata: [] };\n}\n\nfunction evidenceLines(args: JsonRecord, result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const recorded = asRecord(result?.details)?.recorded === true;\n const lines = [\n recorded\n ? line('✓ evidence recorded as planning context', 'success')\n : line(`○ ${inlineText(outputText(result)) || 'not recorded'}`, 'muted'),\n ];\n if (!options.expanded) return lines;\n const fields: ReadonlyArray<[string, string]> = [\n ['issue', 'issue'],\n ['expectedBehavior', 'expected'],\n ['reproductionAttempt', 'reproduction'],\n ['actualBehavior', 'actual'],\n ];\n for (const [key, label] of fields) {\n const value = readString(args, key);\n if (value) lines.push(line(`${label} ${value}`, 'text', { label }));\n }\n for (const [key, label] of EVIDENCE_LISTS) {\n const raw = args[key];\n const items = Array.isArray(raw) ? raw.filter((item): item is string => typeof item === 'string') : [];\n if (items.length === 0) continue;\n lines.push(line(plural(items.length, label), 'hi', { bold: true }));\n lines.push(...items.map((item) => line(inlineText(item), 'text', { indent: true })));\n }\n return lines;\n}\n\nfunction fableLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const text = outputText(result);\n if (details?.started !== true) {\n const code = readString(details, 'errorCode');\n return [line(`○ ${inlineText(text) || 'fable planning did not start'}${code ? ` · ${code}` : ''}`, 'muted')];\n }\n const status = readString(details, 'status') ?? 'unknown';\n const draft = typeof details?.draft === 'string' ? details.draft : undefined;\n const code = readString(details, 'errorCode');\n if (!draft) return [line(`✗ fable planning ${status}${code ? ` · ${code}` : ''}`, 'error')];\n const finished = status === 'completed';\n return [\n line(\n `${finished ? '✓' : '!'} fable draft · ${status}${code ? ` · ${code}` : ''}`,\n finished ? 'success' : 'warning',\n {\n bold: true,\n },\n ),\n ...bodyLines(draft, options.expanded),\n ];\n}\n\nfunction writeLines(result: ToolResultView | null, options: PlanRenderOptions): ToolLine[] {\n const details = asRecord(result?.details);\n const path = readString(details, 'path');\n if (options.isPartial) {\n const phase = readString(details, 'phase') ?? 'checking';\n return [line(`◐ ${phase}${path ? ` ${path}` : ''}`, 'warning')];\n }\n const duration = readNumber(details, 'durationMs');\n if (details?.written === true) {\n return [line(`✓ wrote ${path ?? 'the plan'}${duration === undefined ? '' : ` · ${duration}ms`}`, 'success')];\n }\n const lines = [line(`○ ${inlineText(outputText(result)) || 'plan not written'}`, 'muted')];\n if (path) lines.push(line(`path ${path}`, 'dim'));\n return lines;\n}\n\nfunction completeLines(result: ToolResultView | null): ToolLine[] {\n const text = inlineText(outputText(result));\n if (asRecord(result?.details)?.exited === true) {\n return [line(`✓ plan mode exited${text ? ` · ${text}` : ''}`, 'success')];\n }\n return [line(`○ staying in plan mode${text ? ` · ${text}` : ''}`, 'muted')];\n}\n\n/** Why a plan tool call failed, as the tool said it on one line; empty when it said nothing. */\nexport function planFailureReason(result: ToolResultView | null): string {\n return inlineText(outputText(result));\n}\n\n/** The body of a plan tool card: the outcome line, plus the carried detail once expanded. */\nexport function planResultLines(\n toolName: string,\n args: JsonRecord,\n result: ToolResultView | null,\n options: PlanRenderOptions,\n): ToolLine[] {\n if (options.isError) {\n return [line(`✗ ${planFailureReason(result) || `${toolName} failed`}`, 'error')];\n }\n if (toolName === 'record_debug_evidence') return evidenceLines(args, result, options);\n if (toolName === 'run_fable_plan') {\n if (options.isPartial) return [line('◐ drafting with the local Fable broker', 'warning')];\n return fableLines(result, options);\n }\n if (toolName === 'write_plan') return writeLines(result, options);\n if (options.isPartial) return [line('◐ waiting for the review decision', 'warning')];\n return completeLines(result);\n}\n","import type { ToolMessageRenderProps } from '@agimon-ai/po-core/web';\nimport { MessageItem, MessageItemBody, MessageItemHeader, MessageLines, toolTone } from '@agimon-ai/po-web-components';\n\nimport { planCallSummary, planResultLines } from '../_lib/planToolRender';\n\n/**\n * The plan tools' timeline item: the plan action, the issue or decision it\n * targets, and what the packet carries in the header; the outcome line, with\n * the recorded evidence or the Fable draft once expanded, in the body.\n */\nexport function PlanToolMessage({ toolName, args, result, running, isError }: ToolMessageRenderProps) {\n const summary = planCallSummary(toolName, args);\n const collapsed = planResultLines(toolName, args, result, { expanded: false, isError, isPartial: running });\n const full = planResultLines(toolName, args, result, { expanded: true, isError, isPartial: running });\n return (\n <MessageItem tone={toolTone({ running, isError })} expandable={full.length > collapsed.length}>\n {({ expanded }) => (\n <>\n <MessageItemHeader title={summary.action}>\n <span\n data-testid={`tool-call-${toolName}`}\n title={[summary.detail, ...summary.metadata].filter(Boolean).join(' · ') || undefined}\n className=\"min-w-0 flex-1 truncate text-po-dim\"\n >\n {[summary.detail, ...summary.metadata].filter(Boolean).join(' · ')}\n </span>\n </MessageItemHeader>\n {(expanded ? full : collapsed).length > 0 ? (\n <MessageItemBody data-testid={`tool-result-${toolName}`}>\n <MessageLines lines={expanded ? full : collapsed} />\n </MessageItemBody>\n ) : null}\n </>\n )}\n </MessageItem>\n );\n}\n","import { defineToolRenderer } from '@agimon-ai/po-core/web';\n\nimport { PlanReviewPrompt } from './_components/PlanReviewPrompt';\nimport { PlanToolMessage } from './_components/PlanToolMessage';\nimport { claimsPlanReviewPrompt, PLAN_TOOL_NAMES } from './_lib/planToolRender';\n\nexport default defineToolRenderer({\n tools: [...PLAN_TOOL_NAMES],\n message: PlanToolMessage,\n prompt: { claims: claimsPlanReviewPrompt, component: PlanReviewPrompt },\n});\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineWebPlugin, type WebPluginContributions } from '@agimon-ai/po-core/web';\n\nimport settingPlan from '../src/extensions/(frontend)/setting/plan.web';\nimport settingPlan2 from '../src/extensions/workspaces/(frontend)/setting/plan.web';\nimport activityGroupPlan from '../src/extensions/workspaces/sessions/(frontend)/activity-group/plan.web';\nimport fillPlan from '../src/extensions/workspaces/sessions/(frontend)/fill/Plan.activity.plan.web';\nimport leaderToggle from '../src/extensions/workspaces/sessions/(frontend)/leader/toggle.web';\nimport modePlan from '../src/extensions/workspaces/sessions/(frontend)/mode/plan/mode.web';\nimport toolPlan from '../src/extensions/workspaces/sessions/(frontend)/tool/plan.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: 'plan',\n global: {\n get settingsSections(): WebPluginContributions['settingsSections'] { return [via({ id: 'plan' }, settingPlan)]; },\n },\n workspace: {\n get settingsSections(): WebPluginContributions['settingsSections'] { return [via({ id: 'plan' }, settingPlan2)]; },\n },\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'plan' }, activityGroupPlan)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.plan', id: 'plan' }, fillPlan)]; },\n get leaderBindings(): WebPluginContributions['leaderBindings'] { return [via({ id: 'plan.toggle' }, leaderToggle)]; },\n get minorModes(): WebPluginContributions['minorModes'] { return [via({ name: 'plan' }, modePlan)]; },\n get toolRenderers(): WebPluginContributions['toolRenderers'] { return [via({ tools: ['plan'] }, toolPlan)]; },\n },\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agimon-ai/po-plan",
|
|
3
|
-
"version": "0.0.0-alpha.
|
|
3
|
+
"version": "0.0.0-alpha.85",
|
|
4
4
|
"description": "Reviewable Pi planning mode that removes file-editing tools and persists implementation plans.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -84,18 +84,18 @@
|
|
|
84
84
|
"registry": "https://registry.npmjs.org/"
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
|
-
"@agimon-ai/po-config": "0.0.0-alpha.
|
|
88
|
-
"@agimon-ai/po-core": "0.0.0-alpha.
|
|
89
|
-
"@agimon-ai/po-minor-mode": "0.0.0-alpha.
|
|
90
|
-
"@agimon-ai/po-web-components": "0.0.0-alpha.
|
|
91
|
-
"@agimon-ai/po-web-security": "0.0.0-alpha.
|
|
87
|
+
"@agimon-ai/po-config": "0.0.0-alpha.85",
|
|
88
|
+
"@agimon-ai/po-core": "0.0.0-alpha.85",
|
|
89
|
+
"@agimon-ai/po-minor-mode": "0.0.0-alpha.85",
|
|
90
|
+
"@agimon-ai/po-web-components": "0.0.0-alpha.85",
|
|
91
|
+
"@agimon-ai/po-web-security": "0.0.0-alpha.85",
|
|
92
92
|
"@deepseek-ai/cordis": "4.0.5",
|
|
93
93
|
"hono": "4.13.13",
|
|
94
94
|
"typebox": "1.4.2"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"@agimon-ai/po-build": "0.0.0-alpha.
|
|
98
|
-
"@agimon-ai/po-native-components": "0.0.0-alpha.
|
|
97
|
+
"@agimon-ai/po-build": "0.0.0-alpha.85",
|
|
98
|
+
"@agimon-ai/po-native-components": "0.0.0-alpha.85",
|
|
99
99
|
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
100
100
|
"@tanstack/react-store": "0.11.2",
|
|
101
101
|
"@tanstack/store": "0.11.2",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"vitest": "5.0.4"
|
|
112
112
|
},
|
|
113
113
|
"peerDependencies": {
|
|
114
|
-
"@agimon-ai/po-native-components": "0.0.0-alpha.
|
|
114
|
+
"@agimon-ai/po-native-components": "0.0.0-alpha.85",
|
|
115
115
|
"@earendil-works/pi-coding-agent": "1.4.0",
|
|
116
116
|
"react-native": "0.88.0",
|
|
117
117
|
"react-native-unistyles": "^3.5.3"
|