@guuey/chat 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/hitl.d.ts +58 -0
- package/dist/hitl.d.ts.map +1 -0
- package/dist/hitl.js +81 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/native/components.d.ts +110 -0
- package/dist/native/components.d.ts.map +1 -0
- package/dist/native/components.js +341 -0
- package/dist/native/markdown.d.ts +31 -0
- package/dist/native/markdown.d.ts.map +1 -0
- package/dist/native/markdown.js +69 -0
- package/dist/native/theme-native.d.ts +27 -0
- package/dist/native/theme-native.d.ts.map +1 -0
- package/dist/native/theme-native.js +28 -0
- package/dist/native/transcript.d.ts +48 -0
- package/dist/native/transcript.d.ts.map +1 -0
- package/dist/native/transcript.js +86 -0
- package/dist/native.d.ts +26 -0
- package/dist/native.d.ts.map +1 -0
- package/dist/native.js +27 -0
- package/dist/plan.d.ts +15 -0
- package/dist/plan.d.ts.map +1 -1
- package/dist/plan.js +211 -13
- package/dist/policy.d.ts +4 -0
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +2 -0
- package/dist/react/components.d.ts +42 -5
- package/dist/react/components.d.ts.map +1 -1
- package/dist/react/components.js +51 -1
- package/dist/react/guuey-chat.d.ts +62 -4
- package/dist/react/guuey-chat.d.ts.map +1 -1
- package/dist/react/guuey-chat.js +73 -8
- package/dist/react/transcript.d.ts +1 -1
- package/dist/react/transcript.d.ts.map +1 -1
- package/dist/react/transcript.js +2 -2
- package/dist/react/use-transcript.d.ts +21 -2
- package/dist/react/use-transcript.d.ts.map +1 -1
- package/dist/react/use-transcript.js +57 -3
- package/dist/react.d.ts +2 -2
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +1 -1
- package/dist/strings.d.ts +13 -0
- package/dist/strings.d.ts.map +1 -1
- package/dist/strings.js +8 -0
- package/dist/types.d.ts +146 -7
- package/dist/types.d.ts.map +1 -1
- package/package.json +18 -7
- package/src/corpus/README.md +13 -1
- package/src/corpus/__snapshots__/corpus.test.ts.snap +304 -0
- package/src/corpus/drive.ts +3 -3
- package/src/corpus/fixtures.ts +220 -1
- package/src/hitl.ts +103 -0
- package/src/index.ts +15 -0
- package/src/native/components.tsx +812 -0
- package/src/native/markdown.tsx +205 -0
- package/src/native/theme-native.ts +48 -0
- package/src/native/transcript.tsx +189 -0
- package/src/native.tsx +63 -0
- package/src/plan.ts +233 -20
- package/src/policy.ts +4 -0
- package/src/react/components.tsx +171 -8
- package/src/react/guuey-chat.tsx +143 -9
- package/src/react/transcript.tsx +4 -3
- package/src/react/use-transcript.ts +83 -5
- package/src/react.tsx +3 -1
- package/src/strings.ts +25 -0
- package/src/types.ts +152 -6
- package/styles.css +21 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* `<NativeTranscript>` — the plan walker + the §3.2 renderer obligations,
|
|
4
|
+
* restated over React Native's own mechanics:
|
|
5
|
+
*
|
|
6
|
+
* - **Scroll contract, the inverted way.** The list is an INVERTED
|
|
7
|
+
* FlatList over the reversed plan (the chat-app contract portal's
|
|
8
|
+
* agent-chat screen ratified — guuey#94/#100): content grows at the
|
|
9
|
+
* scroll ORIGIN, so "stick to bottom while streaming" and "never shift
|
|
10
|
+
* the viewport while the reader is up in history" hold by construction
|
|
11
|
+
* — no scrollTo calls during streaming, no re-pin race with content
|
|
12
|
+
* resize (an R6 card growing at the origin cannot move the reader's
|
|
13
|
+
* viewport). "Release on scroll-up" is likewise structural; the kit
|
|
14
|
+
* adds the jump-to-latest affordance when the reader has left the
|
|
15
|
+
* newest turn, and its scroll animation respects the platform
|
|
16
|
+
* reduce-motion setting.
|
|
17
|
+
* - **Windowing** is the list primitive's own virtualization — FlatList
|
|
18
|
+
* windows the DOM-equivalent natively; the plan's stable keys are the
|
|
19
|
+
* `keyExtractor`, so item identity survives streaming updates.
|
|
20
|
+
* - **Accessibility** lives on the item components (`components.tsx`).
|
|
21
|
+
*
|
|
22
|
+
* Platform chrome (keyboard insets, dismiss modes, dock scroll policies)
|
|
23
|
+
* stays HOST-OWNED: `listProps` passes the host's FlatList behavior
|
|
24
|
+
* through, with the kit composing `onScroll` so both the host's policy and
|
|
25
|
+
* the jump affordance see every event. The kit owns data/renderItem/keys/
|
|
26
|
+
* inversion — a host overriding those would be fighting the plan.
|
|
27
|
+
*/
|
|
28
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
29
|
+
import { AccessibilityInfo, FlatList, Pressable, Text, View, } from "react-native";
|
|
30
|
+
import { DEFAULT_CHAT_THEME } from "../theme.js";
|
|
31
|
+
import { defaultChatStrings } from "../strings.js";
|
|
32
|
+
import { nativeTranscriptComponents, renderNativeItem, } from "./components.js";
|
|
33
|
+
import { resolveNativeTheme } from "./theme-native.js";
|
|
34
|
+
/** Offset (px) past which the reader counts as "up in history". */
|
|
35
|
+
const JUMP_THRESHOLD_PX = 160;
|
|
36
|
+
export function NativeTranscript(props) {
|
|
37
|
+
const { plan, components, strings = defaultChatStrings, theme = DEFAULT_CHAT_THEME, mode = "light", listProps, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase, onViewRef, } = props;
|
|
38
|
+
const tokens = useMemo(() => resolveNativeTheme(theme, mode), [theme, mode]);
|
|
39
|
+
const resolvedComponents = useMemo(() => ({ ...nativeTranscriptComponents, ...components }), [components]);
|
|
40
|
+
const ctx = useMemo(() => ({ strings, tokens, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase, onViewRef }), [strings, tokens, onToggle, onRetry, onPromptAction, onErrorAction, resolvedMounts, onViewPhase, onViewRef]);
|
|
41
|
+
// Inverted-list data: reversed plan, newest at index 0 (the visual
|
|
42
|
+
// bottom / scroll origin). Keys are the plan's stable keys.
|
|
43
|
+
const data = useMemo(() => [...plan.items].reverse(), [plan.items]);
|
|
44
|
+
// Reduce motion: the ONE animation the kit owns is the jump scroll.
|
|
45
|
+
const [reduceMotion, setReduceMotion] = useState(false);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
let alive = true;
|
|
48
|
+
void AccessibilityInfo.isReduceMotionEnabled().then((v) => {
|
|
49
|
+
if (alive)
|
|
50
|
+
setReduceMotion(v);
|
|
51
|
+
});
|
|
52
|
+
const sub = AccessibilityInfo.addEventListener("reduceMotionChanged", setReduceMotion);
|
|
53
|
+
return () => {
|
|
54
|
+
alive = false;
|
|
55
|
+
sub.remove();
|
|
56
|
+
};
|
|
57
|
+
}, []);
|
|
58
|
+
const listRef = useRef(null);
|
|
59
|
+
const [showJump, setShowJump] = useState(false);
|
|
60
|
+
const hostOnScroll = listProps?.onScroll;
|
|
61
|
+
const onScroll = useCallback((e) => {
|
|
62
|
+
// Inverted coordinates: offset 0 IS the newest turn.
|
|
63
|
+
setShowJump(e.nativeEvent.contentOffset.y > JUMP_THRESHOLD_PX);
|
|
64
|
+
hostOnScroll?.(e);
|
|
65
|
+
}, [hostOnScroll]);
|
|
66
|
+
const StatusComponent = resolvedComponents.status;
|
|
67
|
+
return (_jsxs(View, { style: { flex: 1, backgroundColor: tokens.palette.canvas }, children: [_jsx(FlatList, { ref: listRef, ...listProps, onScroll: onScroll, scrollEventThrottle: listProps?.scrollEventThrottle ?? 16,
|
|
68
|
+
// Inverted only while non-empty: an inverted ListEmptyComponent
|
|
69
|
+
// renders upside-down (RN gotcha — portal's receipt).
|
|
70
|
+
inverted: data.length > 0, data: data, keyExtractor: (item) => item.key, renderItem: ({ item }) => (_jsx(View, { style: { paddingVertical: tokens.gap / 2 }, children: renderNativeItem(item, resolvedComponents, ctx) })),
|
|
71
|
+
// Inverted list: the header renders at the VISUAL BOTTOM — where
|
|
72
|
+
// the live status line belongs.
|
|
73
|
+
ListHeaderComponent: plan.status !== null ? _jsx(StatusComponent, { item: plan.status, ctx: ctx }) : null }), showJump ? (_jsx(Pressable, { accessibilityRole: "button", onPress: () => {
|
|
74
|
+
setShowJump(false);
|
|
75
|
+
listRef.current?.scrollToOffset({ offset: 0, animated: !reduceMotion });
|
|
76
|
+
}, style: {
|
|
77
|
+
position: "absolute",
|
|
78
|
+
bottom: 12,
|
|
79
|
+
alignSelf: "center",
|
|
80
|
+
backgroundColor: tokens.palette.surface,
|
|
81
|
+
borderRadius: 999,
|
|
82
|
+
paddingHorizontal: 14,
|
|
83
|
+
paddingVertical: 8,
|
|
84
|
+
elevation: 3,
|
|
85
|
+
}, children: _jsx(Text, { style: { color: tokens.palette.ink, fontSize: tokens.fontSize - 2, fontFamily: tokens.fontFamily }, children: strings.jumpToLatest }) })) : null] }));
|
|
86
|
+
}
|
package/dist/native.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Native entry point (`@guuey/chat/native`) — the RN renderer over
|
|
3
|
+
* the SAME headless view-model as `./react` (wave 3c, guuey#135).
|
|
4
|
+
*
|
|
5
|
+
* Zero duplication by construction: the view-model, policies, theme
|
|
6
|
+
* schema, and strings are the root subpath's exports, and the
|
|
7
|
+
* renderer-state hooks (`useTranscript`, `useTranscriptInputs`) are the
|
|
8
|
+
* SAME modules the web kit uses — they are React-generic (no DOM), so both
|
|
9
|
+
* arms share one implementation. Only the walk differs: RN primitives, the
|
|
10
|
+
* inverted-list scroll contract, and the schema's native theme projection
|
|
11
|
+
* (`resolveNativeTheme` — CSS custom properties are the web projection).
|
|
12
|
+
*
|
|
13
|
+
* The R6 default is the documented native default-gap: this tier ships
|
|
14
|
+
* WITHOUT a WebView dependency, so `view` is a required override (a
|
|
15
|
+
* labeled placeholder renders otherwise — never blank). See
|
|
16
|
+
* `native/components.tsx`.
|
|
17
|
+
*
|
|
18
|
+
* `react` and `react-native` are OPTIONAL peers — the root subpath stays
|
|
19
|
+
* importable everywhere; this arm loads only inside an RN runtime.
|
|
20
|
+
*/
|
|
21
|
+
export { NativeTranscript, type NativeTranscriptProps, type NativeTranscriptListProps, } from "./native/transcript.js";
|
|
22
|
+
export { nativeTranscriptComponents, renderNativeItem, NativeUserMessage, NativeText, NativeReasoning, NativeTool, NativeToolGroup, NativeDataResult, NativeView, NativeViewRef, NativeMedia, NativeCode, NativeCitations, NativePrompt, NativeError, NativeHistoryBoundary, NativeCompaction, NativeUnknown, NativeStatus, type NativeTranscriptComponents, type NativeTranscriptItemContext, } from "./native/components.js";
|
|
23
|
+
export { NativeMarkdown } from "./native/markdown.js";
|
|
24
|
+
export { resolveNativeTheme, type NativeChatTokens, type NativeThemeMode, } from "./native/theme-native.js";
|
|
25
|
+
export { useTranscript, useTranscriptInputs, type UseTranscriptArgs, type UseTranscriptResult, type UseTranscriptInputsResult, } from "./react/use-transcript.js";
|
|
26
|
+
//# sourceMappingURL=native.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../src/native.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,gBAAgB,EAChB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,GAC/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,0BAA0B,EAC1B,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,UAAU,EACV,aAAa,EACb,WAAW,EACX,UAAU,EACV,eAAe,EACf,YAAY,EACZ,WAAW,EACX,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,YAAY,EACZ,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EACL,kBAAkB,EAClB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,GAC/B,MAAM,2BAA2B,CAAC"}
|
package/dist/native.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Native entry point (`@guuey/chat/native`) — the RN renderer over
|
|
3
|
+
* the SAME headless view-model as `./react` (wave 3c, guuey#135).
|
|
4
|
+
*
|
|
5
|
+
* Zero duplication by construction: the view-model, policies, theme
|
|
6
|
+
* schema, and strings are the root subpath's exports, and the
|
|
7
|
+
* renderer-state hooks (`useTranscript`, `useTranscriptInputs`) are the
|
|
8
|
+
* SAME modules the web kit uses — they are React-generic (no DOM), so both
|
|
9
|
+
* arms share one implementation. Only the walk differs: RN primitives, the
|
|
10
|
+
* inverted-list scroll contract, and the schema's native theme projection
|
|
11
|
+
* (`resolveNativeTheme` — CSS custom properties are the web projection).
|
|
12
|
+
*
|
|
13
|
+
* The R6 default is the documented native default-gap: this tier ships
|
|
14
|
+
* WITHOUT a WebView dependency, so `view` is a required override (a
|
|
15
|
+
* labeled placeholder renders otherwise — never blank). See
|
|
16
|
+
* `native/components.tsx`.
|
|
17
|
+
*
|
|
18
|
+
* `react` and `react-native` are OPTIONAL peers — the root subpath stays
|
|
19
|
+
* importable everywhere; this arm loads only inside an RN runtime.
|
|
20
|
+
*/
|
|
21
|
+
export { NativeTranscript, } from "./native/transcript.js";
|
|
22
|
+
export { nativeTranscriptComponents, renderNativeItem, NativeUserMessage, NativeText, NativeReasoning, NativeTool, NativeToolGroup, NativeDataResult, NativeView, NativeViewRef, NativeMedia, NativeCode, NativeCitations, NativePrompt, NativeError, NativeHistoryBoundary, NativeCompaction, NativeUnknown, NativeStatus, } from "./native/components.js";
|
|
23
|
+
export { NativeMarkdown } from "./native/markdown.js";
|
|
24
|
+
export { resolveNativeTheme, } from "./native/theme-native.js";
|
|
25
|
+
// The React-generic renderer-state owner + live assembler — shared with
|
|
26
|
+
// the web kit (one implementation, two walks).
|
|
27
|
+
export { useTranscript, useTranscriptInputs, } from "./react/use-transcript.js";
|
package/dist/plan.d.ts
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
|
+
import { type ViewMount } from "@guuey/mcp-apps-host";
|
|
1
2
|
import type { TranscriptPolicy } from "./policy.js";
|
|
2
3
|
import type { TranscriptInputs, TranscriptOverrides, TranscriptPlan } from "./types.js";
|
|
3
4
|
/** The one pure function (spec §7). */
|
|
4
5
|
export declare function planTranscript(inputs: TranscriptInputs, policy: TranscriptPolicy, overrides?: TranscriptOverrides): TranscriptPlan;
|
|
6
|
+
/**
|
|
7
|
+
* The plan key of the NEWEST mountable view — what a "most recent card"
|
|
8
|
+
* stage (the widget's CanvasPane) will show, derived in the same family
|
|
9
|
+
* the plan's own emission uses: live fold mounts (transcript order, last
|
|
10
|
+
* wins) outrank history cards (ascending `seq`). `undefined` when nothing
|
|
11
|
+
* narrows to a mountable resource. Hosts pass the key back as
|
|
12
|
+
* `TranscriptInputs.promotedViewKey`; `channel` lets a host decline to
|
|
13
|
+
* promote a bare locator when no reader is wired (the stage would show
|
|
14
|
+
* nothing, and a chip must never point at an empty canvas).
|
|
15
|
+
*/
|
|
16
|
+
export declare function newestViewKey(inputs: Pick<TranscriptInputs, "result" | "historyCards">): {
|
|
17
|
+
key: string;
|
|
18
|
+
channel: ViewMount["channel"];
|
|
19
|
+
} | undefined;
|
|
5
20
|
//# sourceMappingURL=plan.d.ts.map
|
package/dist/plan.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../src/plan.ts"],"names":[],"mappings":"AAkCA,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACzG,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,OAAO,KAAK,EASV,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EAIf,MAAM,YAAY,CAAC;AAslBpB,uCAAuC;AACvC,wBAAgB,cAAc,CAC5B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,gBAAgB,EACxB,SAAS,GAAE,mBAAwB,GAClC,cAAc,CA0QhB;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,GAAG,cAAc,CAAC,GACxD;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,SAAS,CAiB5D"}
|
package/dist/plan.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { snapshotViewMount, toolResultViewMount, uiLocator } from "@guuey/mcp-apps-host";
|
|
2
|
+
import { grantModeDisplay } from "./hitl.js";
|
|
2
3
|
/** R5's giant threshold: above this byte count the state is `giant`. */
|
|
3
4
|
const GIANT_RESULT_BYTES = 16_384;
|
|
4
5
|
/** Approximate byte size of a JSON value — deterministic, allocation-bounded. */
|
|
@@ -28,6 +29,13 @@ function resolveExpanded(key, policyDefault, overrides) {
|
|
|
28
29
|
const override = overrides[key]?.expanded;
|
|
29
30
|
return override ?? policyDefault;
|
|
30
31
|
}
|
|
32
|
+
/** R16 notice text: the message's text blocks, joined (non-text blocks carry no notice prose). */
|
|
33
|
+
function noticeText(content) {
|
|
34
|
+
return content
|
|
35
|
+
.filter((b) => b.type === "text")
|
|
36
|
+
.map((b) => b.text)
|
|
37
|
+
.join("\n");
|
|
38
|
+
}
|
|
31
39
|
function foldAssistantSources(result, inFlight, aborted) {
|
|
32
40
|
// Real pod folds carry `tool-result` blocks in separate `role: "tool"`
|
|
33
41
|
// messages between assistant turns (the production ggui-render capture is
|
|
@@ -35,21 +43,49 @@ function foldAssistantSources(result, inFlight, aborted) {
|
|
|
35
43
|
// assistant-only filter orphans every call and drops every mount. A tool
|
|
36
44
|
// message's blocks belong to the PRECEDING assistant slot's walk, exactly
|
|
37
45
|
// the whole-fold message order the retired first-party renderers used.
|
|
46
|
+
//
|
|
47
|
+
// LIVE detection is turn-identity-based where the fold carries it: while
|
|
48
|
+
// a turn is in flight, an assistant message whose `turnId` maps to a turn
|
|
49
|
+
// record WITHOUT an `outcome` belongs to the open turn — settled earlier
|
|
50
|
+
// turns stay settled even mid-session (what makes the tail alignment
|
|
51
|
+
// below count them correctly). Nothing is live once the status is back to
|
|
52
|
+
// `ready`, whatever the records say (a fold that missed `turn.done` must
|
|
53
|
+
// not pin a settled turn open forever). Folds without turn identity (a
|
|
54
|
+
// hand-driven fold that never saw `turn.*` lifecycle) fall back to the
|
|
55
|
+
// last-source-is-live-iff-in-flight heuristic — the pre-refinement
|
|
56
|
+
// behaviour, kept so identity-less folds plan exactly as before.
|
|
57
|
+
const openTurns = new Set(result.turns.filter((t) => t.outcome === undefined).map((t) => t.turnId));
|
|
58
|
+
const hasTurnIdentity = result.messages.some((m) => m.role === "assistant" && m.turnId !== undefined);
|
|
38
59
|
const sources = [];
|
|
60
|
+
const notices = [];
|
|
39
61
|
for (const m of result.messages) {
|
|
40
62
|
if (m.role === "assistant") {
|
|
41
|
-
sources.push({
|
|
63
|
+
sources.push({
|
|
64
|
+
blocks: [...m.content],
|
|
65
|
+
live: inFlight && hasTurnIdentity && m.turnId !== undefined && openTurns.has(m.turnId),
|
|
66
|
+
stopped: false,
|
|
67
|
+
});
|
|
42
68
|
}
|
|
43
69
|
else if (m.role === "tool" && sources.length > 0) {
|
|
44
70
|
sources[sources.length - 1].blocks.push(...m.content);
|
|
45
71
|
}
|
|
72
|
+
else if (m.role === "notice") {
|
|
73
|
+
// R16 (spec draft.2): a session annotation — a PEER row, never folded
|
|
74
|
+
// into assistant content; it anchors after the source it followed.
|
|
75
|
+
notices.push({
|
|
76
|
+
text: noticeText(m.content),
|
|
77
|
+
source: m.noticeSource ?? null,
|
|
78
|
+
afterSourceIndex: sources.length - 1,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
46
81
|
}
|
|
47
82
|
const last = sources[sources.length - 1];
|
|
48
83
|
if (last) {
|
|
49
|
-
|
|
84
|
+
if (!hasTurnIdentity)
|
|
85
|
+
last.live = inFlight;
|
|
50
86
|
last.stopped = aborted;
|
|
51
87
|
}
|
|
52
|
-
return sources;
|
|
88
|
+
return { sources, notices };
|
|
53
89
|
}
|
|
54
90
|
function flatAssistantSources(inputs, inFlight) {
|
|
55
91
|
const settled = inputs.messages
|
|
@@ -521,11 +557,74 @@ export function planTranscript(inputs, policy, overrides = {}) {
|
|
|
521
557
|
}
|
|
522
558
|
const inFlight = inputs.status !== "ready";
|
|
523
559
|
const users = inputs.messages.filter((m) => m.role === "user");
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
560
|
+
// R16 — notice rows are session annotations anchored between turns: a
|
|
561
|
+
// flat notice renders after the conversation slot of the user turn it
|
|
562
|
+
// followed (usersSeen-1; -1 = before the conversation). They are PEER
|
|
563
|
+
// rows — excluded from both the user pairing and the assistant seam
|
|
564
|
+
// count, so the fold alignment below never sees them.
|
|
565
|
+
const notices = [];
|
|
566
|
+
if (policy.notice.show) {
|
|
567
|
+
let usersSeen = 0;
|
|
568
|
+
inputs.messages.forEach((m, i) => {
|
|
569
|
+
if (m.role === "user")
|
|
570
|
+
usersSeen += 1;
|
|
571
|
+
else if (m.role === "notice") {
|
|
572
|
+
notices.push({ key: `n${i}`, text: m.text, source: m.noticeSource ?? null, afterSlot: usersSeen - 1 });
|
|
573
|
+
}
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
// Turn-scoped fold composition (guuey#135 kit refinement): the fold owns
|
|
577
|
+
// the TRAILING assistant turns it actually covers — its settled sources
|
|
578
|
+
// replace that many trailing flat assistant entries; any EARLIER flat
|
|
579
|
+
// entries (a rehydrated/persisted prefix the session's Reducer never saw)
|
|
580
|
+
// keep rendering as flat text slots in front. When the fold spans the
|
|
581
|
+
// whole conversation (a pure-live session — the corpus's world), the kept
|
|
582
|
+
// prefix is empty and the plan is byte-identical to the old wholesale
|
|
583
|
+
// replace. Alignment is by COUNT (trailing flat entries ↔ settled fold
|
|
584
|
+
// sources): flat rows carry no turn identity, so a persisted CARD-ONLY
|
|
585
|
+
// turn inside the fold's span (an empty-text assistant row the assembler
|
|
586
|
+
// dropped) can offset the seam by one — a documented approximation, same
|
|
587
|
+
// class as the header's read-plane-seq note, resolved for the visible
|
|
588
|
+
// cards by the actionScope dedupe below.
|
|
589
|
+
let assistants;
|
|
590
|
+
if (inputs.result) {
|
|
591
|
+
const fold = foldAssistantSources(inputs.result, inFlight, inputs.aborted === true);
|
|
592
|
+
const foldSources = fold.sources;
|
|
593
|
+
const settledFoldCount = foldSources.filter((s) => !s.live).length;
|
|
594
|
+
const flatSettled = inputs.messages.filter((m) => m.role === "assistant");
|
|
595
|
+
const keep = Math.max(0, flatSettled.length - settledFoldCount);
|
|
596
|
+
assistants = [
|
|
597
|
+
...flatSettled.slice(0, keep).map((m) => ({
|
|
598
|
+
blocks: [{ type: "text", text: m.text }],
|
|
599
|
+
live: false,
|
|
600
|
+
stopped: false,
|
|
601
|
+
})),
|
|
602
|
+
...foldSources,
|
|
603
|
+
];
|
|
604
|
+
if (policy.notice.show) {
|
|
605
|
+
// Fold-borne notices anchor to the fold source they followed, which
|
|
606
|
+
// sits at global slot `keep + afterSourceIndex` after the seam.
|
|
607
|
+
fold.notices.forEach((n, i) => {
|
|
608
|
+
notices.push({ key: `nf${i}`, text: n.text, source: n.source, afterSlot: keep + n.afterSourceIndex });
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
assistants = flatAssistantSources(inputs, inFlight);
|
|
614
|
+
}
|
|
527
615
|
const slots = Math.max(users.length, assistants.length);
|
|
528
616
|
const conversation = [];
|
|
617
|
+
const noticeItem = (n) => ({
|
|
618
|
+
kind: "notice",
|
|
619
|
+
key: n.key,
|
|
620
|
+
expanded: true,
|
|
621
|
+
text: n.text,
|
|
622
|
+
source: n.source,
|
|
623
|
+
sourceLabel: policy.debugDetail && n.source !== null ? n.source : null,
|
|
624
|
+
});
|
|
625
|
+
for (const n of notices)
|
|
626
|
+
if (n.afterSlot < 0)
|
|
627
|
+
conversation.push(noticeItem(n));
|
|
529
628
|
for (let slot = 0; slot < slots; slot++) {
|
|
530
629
|
const user = users[slot];
|
|
531
630
|
if (user) {
|
|
@@ -546,15 +645,37 @@ export function planTranscript(inputs, policy, overrides = {}) {
|
|
|
546
645
|
if (assistant) {
|
|
547
646
|
conversation.push(...planAssistantSource(assistant, slot, inputs, policy, overrides));
|
|
548
647
|
}
|
|
648
|
+
for (const n of notices)
|
|
649
|
+
if (n.afterSlot === slot)
|
|
650
|
+
conversation.push(noticeItem(n));
|
|
549
651
|
}
|
|
550
652
|
items.push(...groupTools(conversation, policy, overrides));
|
|
551
653
|
// R13 — persisted cards, seq order. (Position: after the settled
|
|
552
654
|
// conversation; true in-turn interleave needs read-plane seqs the flat
|
|
553
655
|
// surface lacks — the 3b assemblers own that refinement.)
|
|
656
|
+
//
|
|
657
|
+
// Dedupe against LIVE mounts by actionScope (the persisted `ui://`
|
|
658
|
+
// identity both sides carry): a session whose fold still holds a turn the
|
|
659
|
+
// read plane has ALSO persisted — the #192 adopted turn, a thread view's
|
|
660
|
+
// post-handoff refetch — would otherwise render the same card twice. The
|
|
661
|
+
// fold's view row owns it (richer phase state); the history snapshot
|
|
662
|
+
// renders only when no live mount claims its identity.
|
|
663
|
+
const liveViewScopes = new Set();
|
|
664
|
+
for (const item of items) {
|
|
665
|
+
if (item.kind === "view" && item.actionScope !== null)
|
|
666
|
+
liveViewScopes.add(item.actionScope);
|
|
667
|
+
}
|
|
554
668
|
const cards = [...(inputs.historyCards ?? [])].sort((a, b) => a.seq - b.seq);
|
|
555
669
|
for (const card of cards) {
|
|
556
670
|
const key = `card.${card.seq}`;
|
|
557
671
|
const mount = snapshotViewMount(card.cardSnapshot);
|
|
672
|
+
const scope = mount === undefined
|
|
673
|
+
? null
|
|
674
|
+
: mount.channel === "locator"
|
|
675
|
+
? mount.resourceUri
|
|
676
|
+
: mount.resource.uri;
|
|
677
|
+
if (scope !== null && liveViewScopes.has(scope))
|
|
678
|
+
continue; // live mount owns it
|
|
558
679
|
const view = {
|
|
559
680
|
kind: "view",
|
|
560
681
|
key,
|
|
@@ -565,18 +686,40 @@ export function planTranscript(inputs, policy, overrides = {}) {
|
|
|
565
686
|
label: null,
|
|
566
687
|
attribution: null,
|
|
567
688
|
toolTitle: null,
|
|
568
|
-
actionScope:
|
|
569
|
-
? null
|
|
570
|
-
: mount.channel === "locator"
|
|
571
|
-
? mount.resourceUri
|
|
572
|
-
: mount.resource.uri,
|
|
689
|
+
actionScope: scope,
|
|
573
690
|
};
|
|
574
691
|
view.label = viewLabel(view, policy);
|
|
575
692
|
items.push(view);
|
|
576
693
|
}
|
|
577
|
-
// R10 — prompts, in input order
|
|
694
|
+
// R10 — prompts, in input order (narrow on `kind`: the guuey-wire
|
|
695
|
+
// profile arm vs the AgJSON hitl arm, spec draft.2).
|
|
578
696
|
for (const prompt of inputs.prompts) {
|
|
579
697
|
const key = `p.${prompt.id}`;
|
|
698
|
+
if (prompt.kind === "hitl") {
|
|
699
|
+
const chosen = prompt.grantModeId !== undefined
|
|
700
|
+
? (prompt.ask.grantModes ?? []).find((m) => m.id === prompt.grantModeId)
|
|
701
|
+
: undefined;
|
|
702
|
+
items.push({
|
|
703
|
+
kind: "prompt",
|
|
704
|
+
key,
|
|
705
|
+
promptId: prompt.id,
|
|
706
|
+
// `cancelled` collapses to a dismissed record but stays expandable —
|
|
707
|
+
// guuey's re-askable ruling (silverprotocol#16); pending opens.
|
|
708
|
+
expanded: resolveExpanded(key, prompt.state === "pending", overrides),
|
|
709
|
+
promptKind: "hitl",
|
|
710
|
+
ask: prompt.ask,
|
|
711
|
+
message: prompt.ask.message ?? null,
|
|
712
|
+
askKind: prompt.ask.kind,
|
|
713
|
+
grantModes: prompt.ask.grantModes ?? [],
|
|
714
|
+
state: prompt.state,
|
|
715
|
+
chosenModeId: prompt.grantModeId ?? null,
|
|
716
|
+
chosenModeLabel: chosen !== undefined ? grantModeDisplay(chosen) : null,
|
|
717
|
+
raw: policy.prompt.rawPayload
|
|
718
|
+
? { askId: prompt.ask.askId, kind: prompt.ask.kind, state: prompt.state, grantModeId: prompt.grantModeId ?? null }
|
|
719
|
+
: null,
|
|
720
|
+
});
|
|
721
|
+
continue;
|
|
722
|
+
}
|
|
580
723
|
items.push({
|
|
581
724
|
kind: "prompt",
|
|
582
725
|
key,
|
|
@@ -621,9 +764,64 @@ export function planTranscript(inputs, policy, overrides = {}) {
|
|
|
621
764
|
verbatim: policy.error.verbatim ? `${code ?? "uncoded"}: ${inputs.error.message}` : null,
|
|
622
765
|
});
|
|
623
766
|
}
|
|
767
|
+
// guuey#204 "promote and reference": the ONE mount a host-owned stage
|
|
768
|
+
// shows (`inputs.promotedViewKey`) renders as a compact reference chip
|
|
769
|
+
// instead of a second live app instance. A key matching nothing (stale
|
|
770
|
+
// host state) or an expired mount promotes nothing — the honest no-op;
|
|
771
|
+
// the next render's key corrects it. The chip keeps the mount's key, so
|
|
772
|
+
// overrides and phase reports survive a swap back to the full mount.
|
|
773
|
+
const promoted = inputs.promotedViewKey;
|
|
774
|
+
const finalItems = promoted === undefined
|
|
775
|
+
? items
|
|
776
|
+
: items.map((item) => {
|
|
777
|
+
if (item.kind !== "view" || item.key !== promoted)
|
|
778
|
+
return item;
|
|
779
|
+
if (item.phase === "expired" || item.mount === null)
|
|
780
|
+
return item;
|
|
781
|
+
const title = item.toolTitle ?? policy.strings.viewRefFallbackTitle;
|
|
782
|
+
const ref = {
|
|
783
|
+
kind: "viewRef",
|
|
784
|
+
key: item.key,
|
|
785
|
+
expanded: false,
|
|
786
|
+
title,
|
|
787
|
+
label: policy.strings.viewPromoted(title),
|
|
788
|
+
};
|
|
789
|
+
return ref;
|
|
790
|
+
});
|
|
624
791
|
return {
|
|
625
|
-
items,
|
|
792
|
+
items: finalItems,
|
|
626
793
|
status: deriveStatus(inputs, policy),
|
|
627
794
|
recovery: inputs.adopted === true && policy.debugDetail ? policy.strings.recoveredFromHistory : null,
|
|
628
795
|
};
|
|
629
796
|
}
|
|
797
|
+
/**
|
|
798
|
+
* The plan key of the NEWEST mountable view — what a "most recent card"
|
|
799
|
+
* stage (the widget's CanvasPane) will show, derived in the same family
|
|
800
|
+
* the plan's own emission uses: live fold mounts (transcript order, last
|
|
801
|
+
* wins) outrank history cards (ascending `seq`). `undefined` when nothing
|
|
802
|
+
* narrows to a mountable resource. Hosts pass the key back as
|
|
803
|
+
* `TranscriptInputs.promotedViewKey`; `channel` lets a host decline to
|
|
804
|
+
* promote a bare locator when no reader is wired (the stage would show
|
|
805
|
+
* nothing, and a chip must never point at an empty canvas).
|
|
806
|
+
*/
|
|
807
|
+
export function newestViewKey(inputs) {
|
|
808
|
+
let newest;
|
|
809
|
+
const cards = [...(inputs.historyCards ?? [])].sort((a, b) => a.seq - b.seq);
|
|
810
|
+
for (const card of cards) {
|
|
811
|
+
const mount = snapshotViewMount(card.cardSnapshot);
|
|
812
|
+
if (mount === undefined)
|
|
813
|
+
continue;
|
|
814
|
+
newest = { key: `card.${card.seq}`, channel: mount.channel };
|
|
815
|
+
}
|
|
816
|
+
for (const message of inputs.result?.messages ?? []) {
|
|
817
|
+
for (const block of message.content) {
|
|
818
|
+
if (block.type !== "tool-result")
|
|
819
|
+
continue;
|
|
820
|
+
const mount = toolResultViewMount(block);
|
|
821
|
+
if (mount === undefined)
|
|
822
|
+
continue;
|
|
823
|
+
newest = { key: `view.${block.toolCallId}`, channel: mount.channel };
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return newest;
|
|
827
|
+
}
|
package/dist/policy.d.ts
CHANGED
|
@@ -93,6 +93,10 @@ export interface TranscriptPolicy {
|
|
|
93
93
|
wakingMs: number;
|
|
94
94
|
longStartMs: number;
|
|
95
95
|
};
|
|
96
|
+
/** R16 (spec draft.2) — notice rows; provenance facet shows under debug. */
|
|
97
|
+
notice: {
|
|
98
|
+
show: boolean;
|
|
99
|
+
};
|
|
96
100
|
/** R14. */
|
|
97
101
|
compaction: {
|
|
98
102
|
show: boolean;
|
package/dist/policy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtF,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,WAAW,CAAC;IACrB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU;IACV,WAAW,EAAE;QAAE,eAAe,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,+EAA+E;IAC/E,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5B,UAAU;IACV,SAAS,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,CAAC;IACzD,UAAU;IACV,IAAI,EAAE;QACJ,eAAe,EAAE,OAAO,CAAC;QACzB,WAAW,EAAE,OAAO,CAAC;QACrB,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;KAC7C,CAAC;IACF,iEAAiE;IACjE,SAAS,EAAE;QAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAC;IACzC,UAAU;IACV,UAAU,EAAE;QACV,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,OAAO,CAAC;QACrB,eAAe,EAAE,OAAO,CAAC;QACzB,+EAA+E;QAC/E,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,kEAAkE;IAClE,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,UAAU;IACV,KAAK,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IACxD,UAAU;IACV,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IACxC,UAAU;IACV,SAAS,EAAE;QAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,CAAC;IACvC,WAAW;IACX,MAAM,EAAE;QAAE,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/D;;;;;;;;;;;OAWG;IACH,KAAK,EAAE;QACL,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;KAC1C,CAAC;IACF,oFAAoF;IACpF,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,WAAW;IACX,UAAU,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,WAAW;IACX,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C;
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAwC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAEtF,MAAM,WAAW,gBAAgB;IAC/B,6EAA6E;IAC7E,OAAO,EAAE,WAAW,CAAC;IACrB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU;IACV,WAAW,EAAE;QAAE,eAAe,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,+EAA+E;IAC/E,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IAC5B,UAAU;IACV,SAAS,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,iBAAiB,EAAE,OAAO,CAAA;KAAE,CAAC;IACzD,UAAU;IACV,IAAI,EAAE;QACJ,eAAe,EAAE,OAAO,CAAC;QACzB,WAAW,EAAE,OAAO,CAAC;QACrB,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;KAC7C,CAAC;IACF,iEAAiE;IACjE,SAAS,EAAE;QAAE,SAAS,EAAE,MAAM,GAAG,KAAK,CAAA;KAAE,CAAC;IACzC,UAAU;IACV,UAAU,EAAE;QACV,MAAM,EAAE,MAAM,CAAC;QACf,WAAW,EAAE,OAAO,CAAC;QACrB,eAAe,EAAE,OAAO,CAAC;QACzB,+EAA+E;QAC/E,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,kEAAkE;IAClE,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,UAAU;IACV,KAAK,EAAE;QAAE,iBAAiB,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;IACxD,UAAU;IACV,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IACxC,UAAU;IACV,SAAS,EAAE;QAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,CAAC;IACvC,WAAW;IACX,MAAM,EAAE;QAAE,SAAS,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/D;;;;;;;;;;;OAWG;IACH,KAAK,EAAE;QACL,QAAQ,EAAE,OAAO,CAAC;QAClB,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,aAAa,EAAE,SAAS,MAAM,EAAE,GAAG,KAAK,CAAC;KAC1C,CAAC;IACF,oFAAoF;IACpF,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,4EAA4E;IAC5E,MAAM,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1B,WAAW;IACX,UAAU,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,WAAW;IACX,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC;CAC1C;AAoDD,0DAA0D;AAC1D,wBAAgB,UAAU,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAElF;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAcnF"}
|
package/dist/policy.js
CHANGED
|
@@ -27,6 +27,7 @@ function withOverrides(base, overrides) {
|
|
|
27
27
|
prompt: { ...base.prompt, ...(overrides.prompt ?? {}) },
|
|
28
28
|
error: { ...base.error, ...(overrides.error ?? {}) },
|
|
29
29
|
status: { ...base.status, ...(overrides.status ?? {}) },
|
|
30
|
+
notice: { ...base.notice, ...(overrides.notice ?? {}) },
|
|
30
31
|
compaction: { ...base.compaction, ...(overrides.compaction ?? {}) },
|
|
31
32
|
unknown: { ...base.unknown, ...(overrides.unknown ?? {}) },
|
|
32
33
|
};
|
|
@@ -46,6 +47,7 @@ function calmBase() {
|
|
|
46
47
|
media: { inlineImageCapRem: 20, chipOnly: false },
|
|
47
48
|
code: { capRem: 16, wrap: false },
|
|
48
49
|
citations: { style: "chips" },
|
|
50
|
+
notice: { show: true },
|
|
49
51
|
prompt: { placement: "inline", rawPayload: false },
|
|
50
52
|
error: { verbatim: false, copyByCode: {}, verbatimCodes: [] },
|
|
51
53
|
status: { wakingMs: 2500, longStartMs: 15_000 },
|
|
@@ -22,7 +22,7 @@ import { type ComponentType, type ReactNode } from "react";
|
|
|
22
22
|
import { type GuueyViewProps } from "@guuey/mcp-apps-host/react";
|
|
23
23
|
import type { ResolvedViewMount, ViewHostPhase } from "@guuey/mcp-apps-host";
|
|
24
24
|
import type { ChatStrings } from "../strings.js";
|
|
25
|
-
import type { CitationsItem, CodeItem, CompactionItem, DataResultItem, DisplayItem, ErrorItem, HistoryBoundaryItem, ItemKey, MediaItem, PromptItem, ReasoningItem, StatusLineItem, ToolGroupItem, ToolItem, UnknownItem, UserMessageItem, TextItem, ViewMountItem } from "../types.js";
|
|
25
|
+
import type { CitationsItem, CodeItem, CompactionItem, DataResultItem, DisplayItem, ErrorItem, HistoryBoundaryItem, ItemKey, MediaItem, NoticeItem, PromptItem, ReasoningItem, StatusLineItem, ToolGroupItem, ToolItem, UnknownItem, UserMessageItem, TextItem, ViewMountItem, ViewRefItem } from "../types.js";
|
|
26
26
|
/** Everything a rendered item may need beyond itself. */
|
|
27
27
|
export interface TranscriptItemContext {
|
|
28
28
|
strings: ChatStrings;
|
|
@@ -30,17 +30,40 @@ export interface TranscriptItemContext {
|
|
|
30
30
|
onToggle: (key: ItemKey) => void;
|
|
31
31
|
/** R0 failed-send retry. */
|
|
32
32
|
onRetry?: (item: UserMessageItem) => void;
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* R10 prompt actions — the host owns what accept/decline DO. A hitl card
|
|
35
|
+
* with declared grant modes reports the pick as `{ grantModeId }` (spec
|
|
36
|
+
* draft.2); plain accepts stay the `"accept"` string.
|
|
37
|
+
*/
|
|
38
|
+
onPromptAction?: (item: PromptItem, action: "accept" | "decline" | "dismiss" | {
|
|
39
|
+
grantModeId: string;
|
|
40
|
+
}) => void;
|
|
35
41
|
/** R11 action slots (sign-in / upgrade / retry affordances). */
|
|
36
42
|
onErrorAction?: (item: ErrorItem) => void;
|
|
37
43
|
/** R6: locator mounts resolved by `useTranscript` ("expired" = failed). */
|
|
38
44
|
resolvedMounts: ReadonlyMap<ItemKey, ResolvedViewMount | "expired">;
|
|
39
45
|
/** R6: live phase reports wired back into the next plan. */
|
|
40
46
|
onViewPhase: (key: ItemKey, phase: ViewHostPhase) => void;
|
|
41
|
-
/**
|
|
42
|
-
|
|
47
|
+
/**
|
|
48
|
+
* guuey#204: a promoted-view reference chip was activated — the host
|
|
49
|
+
* focuses/reveals its stage (canvas). Absent ⇒ the chip renders as a
|
|
50
|
+
* non-interactive label.
|
|
51
|
+
*/
|
|
52
|
+
onViewRef?: (item: ViewRefItem) => void;
|
|
53
|
+
/**
|
|
54
|
+
* R6 pass-through (sandbox overrides, the two-origin mount, relay hooks
|
|
55
|
+
* — policy-gated by the host). Static, or a FUNCTION of the mount being
|
|
56
|
+
* rendered: view configuration legitimately varies per mount — the
|
|
57
|
+
* relay-page URL picks a per-channel egress grant (`?channel=`), and a
|
|
58
|
+
* `tools/call` hook scopes to the item's persisted locator (guuey#158) —
|
|
59
|
+
* so the function form receives the item and its resolved mount and is
|
|
60
|
+
* called only when something actually mounts. Static keeps working
|
|
61
|
+
* unchanged.
|
|
62
|
+
*/
|
|
63
|
+
viewProps?: ViewSlotProps | ((item: ViewMountItem, mount: ResolvedViewMount) => ViewSlotProps);
|
|
43
64
|
}
|
|
65
|
+
/** The per-view slice of `GuueyViewProps` a transcript may configure. */
|
|
66
|
+
export type ViewSlotProps = Pick<GuueyViewProps, "hostCapabilities" | "hostInfo" | "hostContext" | "onCallTool" | "onReadResource" | "onSizeChanged" | "negotiationTimeoutMs" | "dangerouslyAddSandboxFlags" | "allow" | "sandboxPageUrl" | "autoResize">;
|
|
44
67
|
interface ItemProps<T> {
|
|
45
68
|
item: T;
|
|
46
69
|
ctx: TranscriptItemContext;
|
|
@@ -52,10 +75,22 @@ export declare function DefaultDataResult({ item, ctx }: ItemProps<DataResultIte
|
|
|
52
75
|
export declare function DefaultTool({ item, ctx }: ItemProps<ToolItem>): ReactNode;
|
|
53
76
|
export declare function DefaultToolGroup({ item, ctx }: ItemProps<ToolGroupItem>): ReactNode;
|
|
54
77
|
export declare function DefaultView({ item, ctx }: ItemProps<ViewMountItem>): ReactNode;
|
|
78
|
+
/**
|
|
79
|
+
* guuey#204: the "promote and reference" chip — stands in for the one
|
|
80
|
+
* mount the host's stage shows. A real button when the host wires
|
|
81
|
+
* `onViewRef` (keyboard-accessible for free); a plain label otherwise.
|
|
82
|
+
*/
|
|
83
|
+
export declare function DefaultViewRef({ item, ctx }: ItemProps<ViewRefItem>): ReactNode;
|
|
55
84
|
export declare function DefaultMedia({ item }: ItemProps<MediaItem>): ReactNode;
|
|
56
85
|
export declare function DefaultCode({ item, ctx }: ItemProps<CodeItem>): ReactNode;
|
|
57
86
|
export declare function DefaultCitations({ item, ctx }: ItemProps<CitationsItem>): ReactNode;
|
|
58
87
|
export declare function DefaultPrompt({ item, ctx }: ItemProps<PromptItem>): ReactNode;
|
|
88
|
+
/**
|
|
89
|
+
* A `role:"notice"` session annotation (spec draft.2) — a labeled,
|
|
90
|
+
* non-conversational row that must never read as agent-authored. Calm
|
|
91
|
+
* shows the quiet label; debug appends the provenance facet verbatim.
|
|
92
|
+
*/
|
|
93
|
+
export declare function DefaultNotice({ item, ctx }: ItemProps<NoticeItem>): ReactNode;
|
|
59
94
|
export declare function DefaultError({ item, ctx }: ItemProps<ErrorItem>): ReactNode;
|
|
60
95
|
export declare function DefaultHistoryBoundary({ item }: ItemProps<HistoryBoundaryItem>): ReactNode;
|
|
61
96
|
export declare function DefaultCompaction({ item }: ItemProps<CompactionItem>): ReactNode;
|
|
@@ -70,10 +105,12 @@ export interface TranscriptComponents {
|
|
|
70
105
|
toolGroup: ComponentType<ItemProps<ToolGroupItem>>;
|
|
71
106
|
dataResult: ComponentType<ItemProps<DataResultItem>>;
|
|
72
107
|
view: ComponentType<ItemProps<ViewMountItem>>;
|
|
108
|
+
viewRef: ComponentType<ItemProps<ViewRefItem>>;
|
|
73
109
|
media: ComponentType<ItemProps<MediaItem>>;
|
|
74
110
|
code: ComponentType<ItemProps<CodeItem>>;
|
|
75
111
|
citations: ComponentType<ItemProps<CitationsItem>>;
|
|
76
112
|
prompt: ComponentType<ItemProps<PromptItem>>;
|
|
113
|
+
notice: ComponentType<ItemProps<NoticeItem>>;
|
|
77
114
|
error: ComponentType<ItemProps<ErrorItem>>;
|
|
78
115
|
history: ComponentType<ItemProps<HistoryBoundaryItem>>;
|
|
79
116
|
compaction: ComponentType<ItemProps<CompactionItem>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/react/components.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,KAAK,EACV,aAAa,EACb,QAAQ,EACR,cAAc,EACd,cAAc,EACd,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,OAAO,EACP,SAAS,EACT,UAAU,EACV,aAAa,EACb,cAAc,EACd,aAAa,EACb,QAAQ,EACR,WAAW,EACX,eAAe,EACf,QAAQ,EACR,aAAa,
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/react/components.tsx"],"names":[],"mappings":"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"}
|