@plumeai/plugin-sdk 0.0.0-stage → 0.1.3
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/LICENSE +21 -0
- package/bin/plume-plugin.mjs +70 -0
- package/dist/client/styles/src/index.d.ts +123 -0
- package/dist/client/ui/src/avatar/AgentAvatar.d.ts +42 -0
- package/dist/client/ui/src/avatar/AvatarPile.d.ts +36 -0
- package/dist/client/ui/src/avatar/AvatarStack.d.ts +26 -0
- package/dist/client/ui/src/avatar/art.d.ts +32 -0
- package/dist/client/ui/src/fileIcon.d.ts +33 -0
- package/dist/client/ui/src/hooks/useCopied.d.ts +16 -0
- package/dist/client/ui/src/hooks/useLiveRefresh.d.ts +22 -0
- package/dist/client/ui/src/hooks/useNarrow.d.ts +16 -0
- package/dist/client/ui/src/i18n/context.d.ts +17 -0
- package/dist/client/ui/src/i18n/index.d.ts +2 -0
- package/dist/client/ui/src/i18n/list.d.ts +20 -0
- package/dist/client/ui/src/i18n/locales.d.ts +10 -0
- package/dist/client/ui/src/i18n/messages/en.d.ts +1418 -0
- package/dist/client/ui/src/i18n/messages/index.d.ts +6 -0
- package/dist/client/ui/src/i18n/messages/zh-CN.d.ts +1263 -0
- package/dist/client/ui/src/i18n/plural.d.ts +16 -0
- package/dist/client/ui/src/i18n/translate.d.ts +43 -0
- package/dist/client/ui/src/icons/index.d.ts +5 -0
- package/dist/client/ui/src/image/AnnotateCanvas.d.ts +29 -0
- package/dist/client/ui/src/image/AnnotateToolbar.d.ts +73 -0
- package/dist/client/ui/src/image/Annotator.d.ts +154 -0
- package/dist/client/ui/src/image/annotate.d.ts +227 -0
- package/dist/client/ui/src/image/paint.d.ts +35 -0
- package/dist/client/ui/src/image/screenshot-geometry.d.ts +112 -0
- package/dist/client/ui/src/image/useBarDrag.d.ts +31 -0
- package/dist/client/ui/src/image/useMovableBar.d.ts +26 -0
- package/dist/client/ui/src/image/useToolbarPlacement.d.ts +42 -0
- package/dist/client/ui/src/index.d.ts +140 -0
- package/dist/client/ui/src/inputs/ColorField.d.ts +9 -0
- package/dist/client/ui/src/inputs/ComposerToggle.d.ts +23 -0
- package/dist/client/ui/src/inputs/DateRangeField.d.ts +25 -0
- package/dist/client/ui/src/inputs/NativeField.d.ts +5 -0
- package/dist/client/ui/src/inputs/SearchField.d.ts +21 -0
- package/dist/client/ui/src/inputs/Segmented.d.ts +23 -0
- package/dist/client/ui/src/inputs/Select.d.ts +32 -0
- package/dist/client/ui/src/inputs/ShortcutRecorder.d.ts +8 -0
- package/dist/client/ui/src/inputs/Slider.d.ts +13 -0
- package/dist/client/ui/src/inputs/TextArea.d.ts +30 -0
- package/dist/client/ui/src/inputs/Toggle.d.ts +10 -0
- package/dist/client/ui/src/inputs/WorktreeToggle.d.ts +19 -0
- package/dist/client/ui/src/inputs/day-range.d.ts +57 -0
- package/dist/client/ui/src/inputs/pickers.d.ts +40 -0
- package/dist/client/ui/src/inputs/useFieldFade.d.ts +1 -0
- package/dist/client/ui/src/keyboard.d.ts +21 -0
- package/dist/client/ui/src/layout/ApprovalFrame.d.ts +33 -0
- package/dist/client/ui/src/layout/Collapse.d.ts +9 -0
- package/dist/client/ui/src/layout/CopyMark.d.ts +19 -0
- package/dist/client/ui/src/layout/Disclosure.d.ts +66 -0
- package/dist/client/ui/src/layout/ErrorBoundary.d.ts +26 -0
- package/dist/client/ui/src/layout/PageTopRow.d.ts +19 -0
- package/dist/client/ui/src/layout/PanelEmpty.d.ts +17 -0
- package/dist/client/ui/src/layout/ResizeHandle.d.ts +24 -0
- package/dist/client/ui/src/layout/RetainedViews.d.ts +32 -0
- package/dist/client/ui/src/layout/Settings.d.ts +41 -0
- package/dist/client/ui/src/layout/Splitter.d.ts +25 -0
- package/dist/client/ui/src/lib/agent-avatar.d.ts +58 -0
- package/dist/client/ui/src/lib/code/font-stack.d.ts +12 -0
- package/dist/client/ui/src/lib/code/themes.d.ts +35 -0
- package/dist/client/ui/src/lib/date-format.d.ts +8 -0
- package/dist/client/ui/src/lib/dispatches.d.ts +8 -0
- package/dist/client/ui/src/lib/hour-style.d.ts +13 -0
- package/dist/client/ui/src/lib/number-draft.d.ts +24 -0
- package/dist/client/ui/src/lib/relative-time.d.ts +18 -0
- package/dist/client/ui/src/lib/tiling.d.ts +89 -0
- package/dist/client/ui/src/lib/typing.d.ts +19 -0
- package/dist/client/ui/src/motion/RollWords.d.ts +26 -0
- package/dist/client/ui/src/motion/RollingText.d.ts +43 -0
- package/dist/client/ui/src/motion/TypedText.d.ts +9 -0
- package/dist/client/ui/src/motion/freeze.d.ts +22 -0
- package/dist/client/ui/src/motion/held.d.ts +17 -0
- package/dist/client/ui/src/motion/loaders.d.ts +65 -0
- package/dist/client/ui/src/motion/reduced.d.ts +13 -0
- package/dist/client/ui/src/motion/ticked.d.ts +24 -0
- package/dist/client/ui/src/motion/ticker.d.ts +31 -0
- package/dist/client/ui/src/motion/tokens.d.ts +29 -0
- package/dist/client/ui/src/motion/useNow.d.ts +6 -0
- package/dist/client/ui/src/overlay/Confirm.d.ts +96 -0
- package/dist/client/ui/src/overlay/ContextMenu.d.ts +40 -0
- package/dist/client/ui/src/overlay/Dialog.d.ts +60 -0
- package/dist/client/ui/src/overlay/Menu.d.ts +90 -0
- package/dist/client/ui/src/overlay/Overlay.d.ts +17 -0
- package/dist/client/ui/src/overlay/Popover.d.ts +127 -0
- package/dist/client/ui/src/overlay/Tooltip.d.ts +14 -0
- package/dist/client/ui/src/overlay/afterimage.d.ts +20 -0
- package/dist/client/ui/src/overlay/chrome-top.d.ts +8 -0
- package/dist/client/ui/src/overlay/hover-layers.d.ts +41 -0
- package/dist/client/ui/src/overlay/portal.d.ts +21 -0
- package/dist/client/ui/src/overlay/scrims.d.ts +20 -0
- package/dist/client/ui/src/overlay/tooltip-attribute.d.ts +62 -0
- package/dist/client/ui/src/primitives/Button.d.ts +64 -0
- package/dist/client/ui/src/primitives/Caret.d.ts +25 -0
- package/dist/client/ui/src/primitives/ChoiceMark.d.ts +12 -0
- package/dist/client/ui/src/primitives/ClosableTab.d.ts +23 -0
- package/dist/client/ui/src/primitives/CountUp.d.ts +21 -0
- package/dist/client/ui/src/primitives/GitHubMark.d.ts +12 -0
- package/dist/client/ui/src/primitives/IconButton.d.ts +55 -0
- package/dist/client/ui/src/primitives/MarkNumber.d.ts +12 -0
- package/dist/client/ui/src/primitives/RowDeleteButton.d.ts +6 -0
- package/dist/client/ui/src/primitives/Skeleton.d.ts +36 -0
- package/dist/client/ui/src/primitives/TabStrip.d.ts +29 -0
- package/dist/client/ui/src/primitives/Text.d.ts +341 -0
- package/dist/client/ui/src/primitives/TimeAgo.d.ts +13 -0
- package/dist/client/ui/src/primitives/useCountUp.d.ts +23 -0
- package/dist/client/ui/src/row/FlowRow.d.ts +31 -0
- package/dist/client/ui/src/row/HoverRow.d.ts +28 -0
- package/dist/client/ui/src/scroll/BackToLatest.d.ts +19 -0
- package/dist/client/ui/src/scroll/OverlayScrollbar.d.ts +9 -0
- package/dist/client/ui/src/scroll/ScrollText.d.ts +24 -0
- package/dist/client/ui/src/scroll/Scroller.d.ts +66 -0
- package/dist/client/ui/src/scroll/Sideways.d.ts +30 -0
- package/dist/client/ui/src/scroll/fade.d.ts +2 -0
- package/dist/client/ui/src/scroll/follow.d.ts +157 -0
- package/dist/client/ui/src/scroll/measure-batch.d.ts +13 -0
- package/dist/client/ui/src/scroll/memory.d.ts +22 -0
- package/dist/client/ui/src/scroll/signature.d.ts +24 -0
- package/dist/client/ui/src/scroll/useFollowBottom.d.ts +80 -0
- package/dist/client/ui/src/scroll/useSideways.d.ts +29 -0
- package/dist/contract/src/app.d.ts +16 -0
- package/dist/contract/src/changes.d.ts +50 -0
- package/dist/contract/src/diagnostics.d.ts +86 -0
- package/dist/contract/src/index.d.ts +18 -0
- package/dist/contract/src/plugin.d.ts +1391 -0
- package/dist/contract/src/resources.d.ts +79 -0
- package/dist/contract/src/service.d.ts +806 -0
- package/dist/contract/src/ui.d.ts +1039 -0
- package/dist/contract/src/usage.d.ts +102 -0
- package/dist/core/llm/ai/anthropic-messages-request.d.ts +82 -0
- package/dist/core/llm/ai/anthropic-messages.d.ts +43 -0
- package/dist/core/llm/ai/cache-routing.d.ts +53 -0
- package/dist/core/llm/ai/chat-delta.d.ts +107 -0
- package/dist/core/llm/ai/compat-key.d.ts +19 -0
- package/dist/core/llm/ai/endpoint.d.ts +57 -0
- package/dist/core/llm/ai/failure.d.ts +181 -0
- package/dist/core/llm/ai/index.d.ts +16 -0
- package/dist/core/llm/ai/openai-chat-completions-request.d.ts +49 -0
- package/dist/core/llm/ai/openai-chat-completions.d.ts +37 -0
- package/dist/core/llm/ai/openai-responses-request.d.ts +63 -0
- package/dist/core/llm/ai/openai-responses.d.ts +11 -0
- package/dist/core/llm/ai/prefix-fingerprint.d.ts +20 -0
- package/dist/core/llm/ai/reasoning-compat.d.ts +69 -0
- package/dist/core/llm/ai/request-params-compat.d.ts +39 -0
- package/dist/core/llm/ai/retry.d.ts +130 -0
- package/dist/core/llm/ai/sanitize-history.d.ts +23 -0
- package/dist/core/llm/ai/think-tag.d.ts +37 -0
- package/dist/core/llm/ai/thinking-options.d.ts +35 -0
- package/dist/core/llm/ai/tool-names.d.ts +17 -0
- package/dist/core/llm/ai/tool-pairing-compat.d.ts +53 -0
- package/dist/core/llm/ai/tool-result-images-compat.d.ts +24 -0
- package/dist/core/llm/ai/tool-schema.d.ts +20 -0
- package/dist/core/llm/ai/usage-fields.d.ts +30 -0
- package/dist/core/llm/ai/vendors/index.d.ts +20 -0
- package/dist/core/llm/ai/vendors/thinking.d.ts +39 -0
- package/dist/core/llm/ai/vendors/types.d.ts +47 -0
- package/dist/core/llm/config/image-models.d.ts +34 -0
- package/dist/core/llm/config/retry-policy.d.ts +35 -0
- package/dist/core/llm/images/chat-images.d.ts +11 -0
- package/dist/core/llm/images/dimensions.d.ts +15 -0
- package/dist/core/llm/images/generate.d.ts +15 -0
- package/dist/core/llm/images/openai-images.d.ts +11 -0
- package/dist/core/llm/images/quota.d.ts +9 -0
- package/dist/core/llm/images/shape.d.ts +44 -0
- package/dist/core/llm/images/types.d.ts +118 -0
- package/dist/core/llm/model-catalog-format.d.ts +50 -0
- package/dist/core/llm/model-catalog.d.ts +51 -0
- package/dist/core/llm/types/message.d.ts +450 -0
- package/dist/core/llm/types/provider.d.ts +169 -0
- package/dist/core/llm/types/tool.d.ts +23 -0
- package/dist/core/llm/types.d.ts +10 -0
- package/dist/core/llm/utils/pricing.d.ts +18 -0
- package/dist/core/llm/utils/record.d.ts +2 -0
- package/dist/core/llm/utils/sse.d.ts +69 -0
- package/dist/infra/rpc/src/endpoint.d.ts +36 -0
- package/dist/infra/rpc/src/index.d.ts +2 -0
- package/dist/infra/rpc/src/rpc.d.ts +54 -0
- package/dist/theme.css +336 -0
- package/dist/ui.d.ts +2 -0
- package/lib/build.mjs +143 -0
- package/lib/check.mjs +23 -0
- package/lib/dev.mjs +52 -0
- package/lib/icons.mjs +2 -0
- package/lib/init.mjs +109 -0
- package/lib/install.mjs +80 -0
- package/lib/link.mjs +44 -0
- package/lib/lint/i18n.mjs +149 -0
- package/lib/lint/imports.mjs +83 -0
- package/lib/lint/index.mjs +54 -0
- package/lib/lint/styles.mjs +160 -0
- package/lib/manifest.d.mts +9 -0
- package/lib/manifest.mjs +99 -0
- package/lib/targets.mjs +60 -0
- package/package.json +34 -4
- package/skill/SKILL.md +150 -0
- package/skill/references/components.md +2830 -0
- package/skill/references/logic.md +526 -0
- package/skill/references/style-i18n.md +70 -0
- package/skill/references/ui.md +532 -0
- package/template/AGENTS.md +17 -0
- package/template/CLAUDE.md +1 -0
- package/template/README.md +12 -0
- package/template/gitignore +2 -0
- package/template/src/index.ts +28 -0
- package/template/src/messages.ts +16 -0
- package/template/src/types.ts +8 -0
- package/template/src/ui.tsx +30 -0
- package/template/tsconfig.json +7 -0
- package/tsconfig.json +25 -0
- package/README.md +0 -3
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Direction } from "./follow.ts";
|
|
2
|
+
/**
|
|
3
|
+
* 应用里唯一的滚动面。
|
|
4
|
+
*
|
|
5
|
+
* 原生滚动容器做不到、而参考设计处处都有的几件事:
|
|
6
|
+
*
|
|
7
|
+
* - 滚动条浮在内容上,而不是预留一条槽,列表一长过它的盒子,内容不会横向重排;
|
|
8
|
+
* - 边缘说明那个方向还藏着东西,画成边界实际的样子:内容化进空白的地方是渐隐,滑到实心的东西
|
|
9
|
+
* 底下的地方是一道细线。见 `top`——选错了,列表看起来就像坏了。
|
|
10
|
+
*
|
|
11
|
+
* `overscroll-contain` 让滚到头的滚轮停在这里,而不是传给后面的窗口——否则嵌套列表一到底就会带着
|
|
12
|
+
* 父级一起滚。
|
|
13
|
+
*
|
|
14
|
+
* 嵌在外层滚动面里的面(比如转录里的工具卡片、错误日志、代码输出),用 `overscroll="auto"`,
|
|
15
|
+
* 里面滚到边界之后自然地接到外层。
|
|
16
|
+
*/
|
|
17
|
+
export declare function Scroller({ children, className, contentClassName, top, fadeTop, bottom, overscroll, onScroll, onResize, onUserScroll, onHold, scrollRef, }: {
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
className?: string;
|
|
20
|
+
contentClassName?: string;
|
|
21
|
+
/**
|
|
22
|
+
* 滚到自己的边界之后,滚轮还传不传给外面。
|
|
23
|
+
*
|
|
24
|
+
* 判断标准是这一块**是页面里的一段内容,还是一块独立的面**。一段内容——设置页里的发版说明、一列
|
|
25
|
+
* 搜索结果——读到底了还想接着往下看页面,是很自然的一件事,那就该给 `"auto"`。一块
|
|
26
|
+
* 独立的面——弹窗、浮层、菜单、转录本身——滚到底就该停住,不然一个嵌套列表刚到底就把它背后的整页
|
|
27
|
+
* 带跑了,那是默认的 `"contain"` 要挡的事。
|
|
28
|
+
*
|
|
29
|
+
* 「滚不动的面要不要拦」不用在这里操心:它一律放行,见下面 `chain` 那段。
|
|
30
|
+
*/
|
|
31
|
+
overscroll?: "contain" | "auto";
|
|
32
|
+
/**
|
|
33
|
+
* 上沿怎么收尾。
|
|
34
|
+
*
|
|
35
|
+
* `"fade"` 把最后几行柔化掉,不画任何东西就说出「这边还有」。上面是什么都成立——空窗格也好、
|
|
36
|
+
* 不透明的导航也好——因为它降的是内容自己的 alpha,而不是往上面刷颜色;为什么这一点就是全部,
|
|
37
|
+
* 见 `ui/scroll.css` 里 `.plume-fade-y` 上面那段。
|
|
38
|
+
*
|
|
39
|
+
* 只在确实有东西滚到底下去之后才出现,短列表完全没有边缘处理:边界在起作用时才值得画。
|
|
40
|
+
*/
|
|
41
|
+
top?: "fade" | "none";
|
|
42
|
+
/** 默认值不适合这个列表时,上沿渐隐伸进去多深,单位 px。 */
|
|
43
|
+
fadeTop?: number;
|
|
44
|
+
/** 下沿的同一个问题。 */
|
|
45
|
+
bottom?: "fade" | "none";
|
|
46
|
+
onScroll?: (element: HTMLDivElement) => void;
|
|
47
|
+
/** 内容或视口尺寸变了就调用。 */
|
|
48
|
+
onResize?: (element: HTMLDivElement) => void;
|
|
49
|
+
/**
|
|
50
|
+
* 下面滑块的一次拖动,按它本来的手势报出来。
|
|
51
|
+
*
|
|
52
|
+
* 滑块是视口的兄弟节点,靠赋值 `scrollTop` 移动视口,于是拖动传到跟随方那里,是一个和浏览器
|
|
53
|
+
* 夹住正在变短的转录分不开的滚动事件——而跟随方不能因为一次来路不明的位置变化就脱离(见
|
|
54
|
+
* `follow.ts`),就永远发现不了读者在往外拉。这是唯一知道真相的组件把那个手势明说出来。
|
|
55
|
+
*/
|
|
56
|
+
onUserScroll?: (direction: Direction) => void;
|
|
57
|
+
/**
|
|
58
|
+
* 读者刚把手指按在了什么上面。
|
|
59
|
+
*
|
|
60
|
+
* 给跟随底部的那一方一个机会,把接下来这一次长高认成「读者点开了手里这一块」而不是「新消息
|
|
61
|
+
* 到了」——两者在 `onResize` 里长得一模一样,而处理方式正好相反。
|
|
62
|
+
*/
|
|
63
|
+
onHold?: (target: EventTarget | null) => void;
|
|
64
|
+
/** 给自己驱动滚动位置的调用方用,比如转录。 */
|
|
65
|
+
scrollRef?: React.RefObject<HTMLDivElement | null>;
|
|
66
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一条横着滚的标签栏。
|
|
3
|
+
*
|
|
4
|
+
* 普通滚轮直接横着走,触摸板两指一划照旧——见 `useSideways` 的 `plainWheel`。标签栏都长在头部或
|
|
5
|
+
* 底边,上面没有要竖着滚的东西,把滚轮让出去也没人接。
|
|
6
|
+
*
|
|
7
|
+
* 这里从前两头各浮一枚方向键,那是给「只有鼠标、又不知道 Shift + 滚轮」的人准备的;滚轮能直接
|
|
8
|
+
* 横滚之后它们只剩下压住两端标签的那一块,于是拿掉了。附件条躺在可滚动的转录区里,滚轮得留给
|
|
9
|
+
* 上层,它还用着 `SidewaysArrow`。
|
|
10
|
+
*/
|
|
11
|
+
export declare function Sideways({ children, className, trackRef, ...rest }: {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
/** 给会滚的那一层,`overflow-x-auto` 和「我在父级里占多大」的类都写在这里。 */
|
|
14
|
+
className?: string;
|
|
15
|
+
/** 需要自己够到滚动容器的地方传进来——比如「把选中的标签滚进视野」。 */
|
|
16
|
+
trackRef?: React.RefObject<HTMLDivElement | null>;
|
|
17
|
+
} & Omit<React.HTMLAttributes<HTMLDivElement>, "className" | "children">): import("react").JSX.Element;
|
|
18
|
+
/**
|
|
19
|
+
* 附件条两头的方向键:那里滚轮要留给转录区,只有鼠标的人得靠它们。
|
|
20
|
+
*
|
|
21
|
+
* - **不占地方。** 绝对定位浮在两端、压在渐隐上,不进 flex 流——占位置的话,刚好排得下的一条会
|
|
22
|
+
* 因为多了两个按钮而排不下。定位壳由附件条自己提供。
|
|
23
|
+
* - **到头就没有。** 和渐隐读同一个「这边还有没有」,永远同进同出;`disabled` 的灰按钮不说明任何事。
|
|
24
|
+
* - **一次滚八成。** 整屏翻页会把刚看到的那个也带走,留一点重叠,眼睛才接得上。
|
|
25
|
+
*/
|
|
26
|
+
export declare function SidewaysArrow({ side, shown, track }: {
|
|
27
|
+
side: "left" | "right";
|
|
28
|
+
shown: boolean;
|
|
29
|
+
track: React.RefObject<HTMLElement | null>;
|
|
30
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一个滚动面是不是在跟随自己的底部,以及什么东西有权改变这一点。
|
|
3
|
+
*
|
|
4
|
+
* 窗口里每一份转录——对话、侧聊、委派的日志——要的都是同一种行为:有东西进来时贴着底部走,读者
|
|
5
|
+
* 往上翻去看什么时留在原地,并且给一条回来的路。三份各自长出来的实现会慢慢走样,所以这个文件是
|
|
6
|
+
* 规则,每个滚动面都只是调用方。
|
|
7
|
+
*
|
|
8
|
+
* 这里什么都不碰 DOM。每样东西都是一次几何读数加一个事件的纯函数,这样那些有意思的情形——只在
|
|
9
|
+
* 一轮输出中途的某一帧出现的那些——才能写成测试,而不是靠手去复现。
|
|
10
|
+
*
|
|
11
|
+
* 这里唯一值得带走的想法:
|
|
12
|
+
*
|
|
13
|
+
* 跟随是一种**意图**,不是一个位置。
|
|
14
|
+
*
|
|
15
|
+
* 在每次滚动事件里问「scrollTop 是不是接近末尾」并把答案当成读者的意愿,是行不通的。scrollTop
|
|
16
|
+
* 不只是读者在写,程序也在写——视口变矮、图片加载、面板隐藏又显示,都会挪动它——于是程序会一直用
|
|
17
|
+
* 自己的写入推翻读者。所以 `nextState` 是不对称的:离开由事件驱动(滚轮往上一格是明确的,不管多小),
|
|
18
|
+
* 回来由位置驱动(没有一个事件叫「我想重新跟随」;到达底部是唯一的表达方式)。
|
|
19
|
+
*
|
|
20
|
+
* 这个不对称有一条推论,同一个毛病犯了第二次才学到:
|
|
21
|
+
*
|
|
22
|
+
* 位置变化可以**恢复**跟随,永远不能结束它。
|
|
23
|
+
*
|
|
24
|
+
* 留一道后门的做法是:一次位置往上移的滚动事件,只要最近 300ms 里见过某个输入,就结束跟随——这个
|
|
25
|
+
* 时间窗之所以在,是因为滚动锚定会自己挪 `scrollTop`,不能被当成读者。可它分不清两者。输入是从整个
|
|
26
|
+
* 窗口听来的,于是在任何地方松开鼠标——侧栏、面板、输入框——都会打开这个窗口,落在窗口里的任何重排
|
|
27
|
+
* 都被读成「读者往上走了」。一组工具落定、运行行折叠、最旧的一轮离开挂载范围:每一件都会让一份没人碰
|
|
28
|
+
* 过的转录停止跟随,在读者正看着内容进来的会话上留下「有新内容」。
|
|
29
|
+
*
|
|
30
|
+
* 所以一次单纯的位置变化,现在只说它能诚实说出的那一件事,那就是 `arrived`。所有结束跟随的东西都以
|
|
31
|
+
* 手势的形式到来,来自一个叫得出它名字的监听器。
|
|
32
|
+
*/
|
|
33
|
+
export type FollowState =
|
|
34
|
+
/** 贴着底部走:尾部长高和视口变化都会重新钉住。 */
|
|
35
|
+
"following"
|
|
36
|
+
/** 读者在上面某处,除了读者自己,谁都不能挪动他们。 */
|
|
37
|
+
| "detached"
|
|
38
|
+
/** 正在滑回底部。可以打断——见 `nextState`。 */
|
|
39
|
+
| "returning";
|
|
40
|
+
/**
|
|
41
|
+
* 换掉滚动面之后还留着的意图。
|
|
42
|
+
*
|
|
43
|
+
* 正在回去的面已经被要求跟随末尾了;动画只是这个意图正在被执行的方式。滑动途中打开了另一个会话,
|
|
44
|
+
* 要是把它记成 detached,旧的面恢复时就停在半路,又一次给出「回到最新」。
|
|
45
|
+
*/
|
|
46
|
+
export declare function followsAfterRestore(state: FollowState): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 某一瞬间滚动面的样子:这里每个判断都从这三个数出发。
|
|
49
|
+
*
|
|
50
|
+
* 有意只有几何。浮在最后一段内容上的东西——审批卡、回到最新的按钮——在它该在的地方处理,作为滚动
|
|
51
|
+
* 内容底部的内边距(`--plume-bottom-inset`),好让页面的底部是最新消息真正看得见的地方。把重叠量折进
|
|
52
|
+
* 这里的算术是双重错误:`scrollTop` 不可能超过 `scrollHeight - clientHeight`,一个正的 inset 会让
|
|
53
|
+
* `atBottom` 永远够不着,钉住一份永远满足不了自己判断的转录。
|
|
54
|
+
*/
|
|
55
|
+
export interface Reading {
|
|
56
|
+
scrollTop: number;
|
|
57
|
+
scrollHeight: number;
|
|
58
|
+
clientHeight: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 让内容末尾贴住视口底边的 scrollTop。
|
|
62
|
+
*
|
|
63
|
+
* 整数,而且只是近似:`scrollHeight` 和 `clientHeight` 都取过整,所以这个值最多比内容真正的末尾
|
|
64
|
+
* 差一个像素。对下面那些都留了一像素余量的距离判断够用;拿来写不够——见 `targetScrollTop`。
|
|
65
|
+
*/
|
|
66
|
+
export declare function visualBottom(reading: Reading): number;
|
|
67
|
+
/** 读者离底部多远。 */
|
|
68
|
+
export declare function distanceToBottom(reading: Reading): number;
|
|
69
|
+
/** 内容没填满视口。永远算「在底部」,永远不值得一个按钮。 */
|
|
70
|
+
export declare function fitsInView(reading: Reading): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* 滚动面不在屏幕上时拿到的读数。
|
|
73
|
+
*
|
|
74
|
+
* 用 `display: none` 收起的窗格、最小化的窗口、元素被摘下时触发的 `ResizeObserver`:报的都是零,
|
|
75
|
+
* 而零满足所有「在底部」的判断。这样的读数什么都证明不了,绝不能进状态机——按它行事,切换面板就会
|
|
76
|
+
* 把一个会话记住的位置覆盖成「转录顶部,并且算作钉住」。
|
|
77
|
+
*/
|
|
78
|
+
export declare function isDegenerate(reading: Reading): boolean;
|
|
79
|
+
/** 读者在哪,只分要紧的两段。 */
|
|
80
|
+
export declare function atBottom(reading: Reading): boolean;
|
|
81
|
+
export declare function isAway(reading: Reading): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* 一个手势往哪个方向,在能知道的时候。
|
|
84
|
+
*
|
|
85
|
+
* 滚轮、按键、拖滑块都直接说了。按下手指没说,报成 `"unknown"`:由之后的位置决定,和一次停在底部的
|
|
86
|
+
* 拖动一直遵守的规则一样。
|
|
87
|
+
*/
|
|
88
|
+
export type Direction = "up" | "down" | "unknown";
|
|
89
|
+
/**
|
|
90
|
+
* 什么可以改变意图。
|
|
91
|
+
*
|
|
92
|
+
* 几何有意不在这里——内容追加、上面有东西折叠、输入框长高。它们都不能改变意图,把新几何读回来当作
|
|
93
|
+
* 「读者想不想跟随」的答案,正是往一个长高 200px 的输入框里打字会冒出「回到最新」按钮、一个窗格短暂
|
|
94
|
+
* 报 0×0 会得到一份滚在顶部却算作钉住的转录的原因。它们作为位置应用(`targetScrollTop`),从不喂给
|
|
95
|
+
* `nextState`。
|
|
96
|
+
*/
|
|
97
|
+
export type FollowEvent =
|
|
98
|
+
/** 读者动了,这是唯一可以结束跟随意图的事件。 */
|
|
99
|
+
{
|
|
100
|
+
kind: "user-scroll";
|
|
101
|
+
direction: Direction;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* 面停在一个这里没人要求过的位置。
|
|
105
|
+
*
|
|
106
|
+
* 每一次不是这个模块自己写的滚动:甩动的尾巴、浏览器夹住一份刚失去最旧一轮的转录、上方展开一段
|
|
107
|
+
* 推理时锚定稳住一行。到达状态机时它们只是四个来路不明的数,彼此分不开,也没有一个是手势。所以
|
|
108
|
+
* 唯一能做的断言是面回到了末尾——唯一能做的事是重新开始跟随。见文件顶部的推论。
|
|
109
|
+
*/
|
|
110
|
+
| {
|
|
111
|
+
kind: "arrived";
|
|
112
|
+
}
|
|
113
|
+
/** 读者要求回去:按钮、End 键、发送一条消息。 */
|
|
114
|
+
| {
|
|
115
|
+
kind: "user-return";
|
|
116
|
+
}
|
|
117
|
+
/** 一次滑动到达了。 */
|
|
118
|
+
| {
|
|
119
|
+
kind: "settle";
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* 整个状态机。
|
|
123
|
+
*
|
|
124
|
+
* 有意写得像一张表:它要防的毛病,都是一个分支和另一个分支在一个谁都没点名的情形上意见不一。
|
|
125
|
+
*/
|
|
126
|
+
export declare function nextState(state: FollowState, event: FollowEvent, reading: Reading): FollowState;
|
|
127
|
+
/**
|
|
128
|
+
* 一个事件之后面应该在哪,`null` 表示别动它。
|
|
129
|
+
*
|
|
130
|
+
* 和 `nextState` 分开,是因为它们回答的问题不同、被调用的时机也不同:状态在事件处理里决定,位置在
|
|
131
|
+
* 绘制前的布局副作用里应用。返回 `null`——而不是当前的 `scrollTop`——调用方才能整个跳过写入,而跳过
|
|
132
|
+
* 写入正是惯性滚动不被打断的原因。
|
|
133
|
+
*/
|
|
134
|
+
export declare function targetScrollTop(state: FollowState, reading: Reading): number | null;
|
|
135
|
+
/**
|
|
136
|
+
* 足够判断到底有没有新东西来的那一部分转录。
|
|
137
|
+
*
|
|
138
|
+
* 只看 `count` 会漏掉正在写的回复——一条消息,在长。只看 `tail` 会漏掉同时落地、结尾看着一样的
|
|
139
|
+
* 两条消息。两个合起来才够回答「这还是我上次看的那份转录吗」,而且——要紧的是——两个都是**值**,
|
|
140
|
+
* 所以从磁盘重读、以新数组交回的转录,和它替换掉的那份比较起来相等。
|
|
141
|
+
*/
|
|
142
|
+
export interface Marker {
|
|
143
|
+
count: number;
|
|
144
|
+
/** 最后一行变了它就变的东西:它的键加上它已经有多少。 */
|
|
145
|
+
tail: string;
|
|
146
|
+
}
|
|
147
|
+
export declare function marker(count: number, tail: string): Marker;
|
|
148
|
+
/**
|
|
149
|
+
* 读者上次看到末尾之后,来了多少条消息。
|
|
150
|
+
*
|
|
151
|
+
* 它要杜绝的毛病:一份只是又被交给了 React 一次的转录,亮起「有新内容」。打开一个会话会设置两遍
|
|
152
|
+
* 消息——一遍来自缓存,一遍是磁盘读完落地——第二遍改变了数组的引用,别的什么都没变。按引用判断的
|
|
153
|
+
* 未读标记把那当成了新内容。这里按上面那两个数判断,第二遍什么都不贡献。
|
|
154
|
+
*
|
|
155
|
+
* 回退和压缩会让转录变短。两者都不是新内容,也都没给读者留下什么要追的,所以都报零。
|
|
156
|
+
*/
|
|
157
|
+
export declare function unreadSince(seen: Marker | null, now: Marker): number;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 各个滚动面板下一帧要量的东西,合进同一个 rAF:先把所有面板都读完,再一起写。
|
|
3
|
+
*
|
|
4
|
+
* 每个 `Scroller` 各量各的时候,一个面板刚写完滑块,下一个面板读 `scrollTop` 就得为它把整页的样式
|
|
5
|
+
* 和布局先算一遍——几个面板同时在输出,滚动事件一来就是一串交错的读写。量过:滚动事件里同步量
|
|
6
|
+
* 占了渲染主线程 9%,几乎全是这种被逼出来的排版。
|
|
7
|
+
*
|
|
8
|
+
* 推到 rAF 不会让滑块晚一帧:滚动事件在同一帧的 rAF 回调之前派发,这里约的回调当帧就跑。
|
|
9
|
+
*/
|
|
10
|
+
/** 读这一帧要的数,交回一个只写不读的函数。 */
|
|
11
|
+
export type Measure = () => () => void;
|
|
12
|
+
export declare function queueMeasure(measure: Measure): void;
|
|
13
|
+
export declare function cancelMeasure(measure: Measure): void;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 读的人读到了哪里,和读的是什么分开存。
|
|
3
|
+
*
|
|
4
|
+
* 阅读位置要是和转录缓存放在一起,就没用了:你在别处时一个会话说了新东西,它缓存的转录会被丢掉
|
|
5
|
+
* ——这是对的,事件里的信息不够重建它——阅读位置也跟着一起没了。而还在后台跑的那个会话,恰恰是
|
|
6
|
+
* 你最想回到原处的那一个。
|
|
7
|
+
*
|
|
8
|
+
* 所以单独一份存储,按界面分键,只放错了也不要紧的东西。这里每个字段缺了都能退回一个合理的默认值,
|
|
9
|
+
* 这也是它可以是一个模块级的普通 Map、而不是应用状态一部分的原因——别处不用读它,它变了不用重新
|
|
10
|
+
* 渲染,全丢了也只是多滚一次到底。
|
|
11
|
+
*/
|
|
12
|
+
import type { Marker } from "./follow.ts";
|
|
13
|
+
export interface FollowSnapshot {
|
|
14
|
+
/** 意图,比位置优先:跟随的意思是「带我到末尾」,不管末尾现在在哪。 */
|
|
15
|
+
following: boolean;
|
|
16
|
+
/** 只在不跟随时有意义。 */
|
|
17
|
+
scrollTop: number;
|
|
18
|
+
/** 转录已经看过多少,未读数离开再回来也还在。 */
|
|
19
|
+
seen: Marker | null;
|
|
20
|
+
}
|
|
21
|
+
export declare function readFollow(namespace: string, id: string): FollowSnapshot | undefined;
|
|
22
|
+
export declare function writeFollow(namespace: string, id: string, snapshot: FollowSnapshot): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 转录末尾变了它才变的一个值。
|
|
3
|
+
*
|
|
4
|
+
* `useFollowBottom` 要回答「到底有没有新东西来」,而比较数组答不了:打开一个会话时 React 会拿到
|
|
5
|
+
* 两遍同样的消息——一遍来自缓存,一遍是磁盘读完落地——两个数组是不同的对象、内容完全一样。按引用
|
|
6
|
+
* 判断的未读标记把第二遍当成了新内容,于是一个谁都没往里加过东西的会话,一打开就是「有新内容」。
|
|
7
|
+
*
|
|
8
|
+
* 所以改问内容。两个数就够:有几条消息,最后一条多大。正在写的回复条数不变、大小在长;一条回复
|
|
9
|
+
* 写完、下一条开始,条数变了。从磁盘重读的转录两个都不变。
|
|
10
|
+
*/
|
|
11
|
+
import type { Message } from "../../../../contract/src/index.d.ts";
|
|
12
|
+
/**
|
|
13
|
+
* 转录尾部的签名。
|
|
14
|
+
*
|
|
15
|
+
* `extra` 带上消息列表之外、同样算作新内容到来的东西——有几次工具运行、几次已经落定,委派的最终
|
|
16
|
+
* 报告——因为它们不碰任何消息也会改变屏幕上的内容。
|
|
17
|
+
*
|
|
18
|
+
* 看两条而不是一条,这不是多此一举。调用了工具的回复,在工具结果落到它后面时仍是**进行中**的那条,
|
|
19
|
+
* 而存储是原地更新它的:数组以 `[…, assistant(进行中), toolResult]` 结尾,真正在长的是倒数第二条。
|
|
20
|
+
* 只问最后一条得到的是 `toolResult:<固定时间戳>:0`——只要那条回复还在继续,签名就一直冻着——而签名
|
|
21
|
+
* 冻住,跟随底部的那个布局副作用就永远不跑。多看一条不花什么:两条消息本来就在手上,也没有哪个
|
|
22
|
+
* 转录会同时有第三条在变。
|
|
23
|
+
*/
|
|
24
|
+
export declare function tailSignature(messages: readonly Message[], extra?: string | number): string;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一个滚动面和它自己底部的关系。
|
|
3
|
+
*
|
|
4
|
+
* 规则在 `follow.ts`,不用浏览器就能测。这里是所有需要 DOM 的部分:读者的意图从哪里听来、位置什么
|
|
5
|
+
* 时候写、回去的那一段怎么动。
|
|
6
|
+
*
|
|
7
|
+
* 每份转录都调用它——对话(侧聊也是一份)和委派的。各自留一份近似的副本会慢慢走样:余量不同、只有
|
|
8
|
+
* 一份在看内容改尺寸、只有一份给回去的路。一处修好了另外两处照样坏着,这才是它存在的真正原因。
|
|
9
|
+
*/
|
|
10
|
+
import { type Direction } from "./follow.ts";
|
|
11
|
+
export interface FollowBottom {
|
|
12
|
+
/** 交给 `Scroller` 的 `scrollRef`。 */
|
|
13
|
+
scrollRef: React.RefObject<HTMLDivElement | null>;
|
|
14
|
+
/**
|
|
15
|
+
* 放在滚动内容的最末尾。
|
|
16
|
+
*
|
|
17
|
+
* 「你已经看到最新消息了」指的就是它,而且必须是一个元素,不能是一道算术题:往上滚两屏、读完新到
|
|
18
|
+
* 的三段、停在那里的读者已经跟上了,任何离底距离的门槛都分不清他和没跟上的人。
|
|
19
|
+
*
|
|
20
|
+
* 用回调而不用 ref 对象,这不是风格问题。转录容器按会话作键,所以打开一个会话——或者空白对话在
|
|
21
|
+
* 第一条消息后拿到 id——会扔掉整棵子树重建。ref 对象会悄悄改指向新的哨兵,观察器却还盯着一个已经
|
|
22
|
+
* 不在文档里、因此再也不会和任何东西相交的节点:标记已读一次都不会触发,「有新内容」永远亮着。
|
|
23
|
+
*/
|
|
24
|
+
tailRef: (node: HTMLDivElement | null) => void;
|
|
25
|
+
/** 要不要给出回去的路。 */
|
|
26
|
+
away: boolean;
|
|
27
|
+
/** 读者离开期间来了多少条消息。除非真的来了东西,否则是零。 */
|
|
28
|
+
unread: number;
|
|
29
|
+
/** 读者要求回去:按了按钮,或者刚发出了什么。 */
|
|
30
|
+
returnToBottom(instant?: boolean): void;
|
|
31
|
+
/** 明确的导航拥有滚动位置,回复正在输出时也一样。 */
|
|
32
|
+
detach(): void;
|
|
33
|
+
/** 立刻跳过去;从那以后位置归导航。 */
|
|
34
|
+
scrollTo(top: number): void;
|
|
35
|
+
/** 交给 `Scroller` 的 `onScroll`。 */
|
|
36
|
+
onScroll(el: HTMLDivElement): void;
|
|
37
|
+
/** 交给 `Scroller` 的 `onResize`。 */
|
|
38
|
+
onResize(el: HTMLDivElement): void;
|
|
39
|
+
/**
|
|
40
|
+
* 交给 `Scroller` 的 `onUserScroll`:视口自己听不到的那一种手势。
|
|
41
|
+
*
|
|
42
|
+
* 浮动滚动条画在视口旁边而不是里面,靠赋值移动滚动面,所以拖滑块不产生滚轮、触摸或按键——只有
|
|
43
|
+
* 一个滚动事件,而按 `follow.ts` 的规则它不能让任何东西脱离跟随。`Scroller` 是唯一知道拖动就是拖动
|
|
44
|
+
* 的地方,所以由它说出来,而不是事后和其他一切挪动转录的东西一起从位置里猜。
|
|
45
|
+
*/
|
|
46
|
+
onUserScroll(direction: Direction): void;
|
|
47
|
+
/**
|
|
48
|
+
* 交给 `Scroller` 的 `onHold`:读者刚把手指按在了什么上面。
|
|
49
|
+
*
|
|
50
|
+
* 展开一段折叠区会让转录长高,而长高本身分不清是「新消息到了」还是「读者点开了手里这一块」。
|
|
51
|
+
* 这一条就是那个区别:按下时记住按到的元素在视口的哪个高度,接下来这一次长高把它放回原处,
|
|
52
|
+
* 跟随底部让路。没有它,点开历史里的一个工具组会把读者直接甩到转录末尾。
|
|
53
|
+
*/
|
|
54
|
+
hold(target: EventTarget | null): void;
|
|
55
|
+
/**
|
|
56
|
+
* 接下来这一阵子的高度变化里,把这个元素留在视口的原位——只在读者没跟着底部时。
|
|
57
|
+
*
|
|
58
|
+
* 跟着底部时底部本来就钉着,元素下面没变它就不动;这时按住反而让跟随底部让路 `HOLD_MS`,底下随后
|
|
59
|
+
* 冒出来的东西没人带进视口。不能拿 `away` 来问:它要离底过了门槛才亮,滚开几十像素时已经不跟了、它还没亮。
|
|
60
|
+
*/
|
|
61
|
+
keep(target: HTMLElement): void;
|
|
62
|
+
}
|
|
63
|
+
export declare function useFollowBottom({ surfaceId, count, tail, namespace, ready, live, }: {
|
|
64
|
+
/** 这是哪个对话、侧聊或委派。没东西可显示时是 `null`。 */
|
|
65
|
+
surfaceId: string | null;
|
|
66
|
+
/** 转录有多少行。 */
|
|
67
|
+
count: number;
|
|
68
|
+
/** 最后一行变了它就变的东西——见 `Marker`。 */
|
|
69
|
+
tail: string;
|
|
70
|
+
/** 记在哪一类界面名下;见 `memory.ts`。 */
|
|
71
|
+
namespace: string;
|
|
72
|
+
/** 恢复的偏移只有在这个面的内容到了之后才有意义。 */
|
|
73
|
+
ready?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* 这份转录此刻是不是正在被写。只有这时——以及之后的 `TAIL_MS`,最后几个字还在放出来——长高才算
|
|
76
|
+
* 输出,也只有输出才追:静止时长高是一张卡片或一张图片晚到了——交付卡片挂载后才去取文件——为它
|
|
77
|
+
* 滑动,等于把整段历史从下面往上拖。
|
|
78
|
+
*/
|
|
79
|
+
live: boolean;
|
|
80
|
+
}): FollowBottom;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一条横着滚的东西,怎么让人滚得动、以及怎么说明它还没滚完。
|
|
3
|
+
*
|
|
4
|
+
* 两件事一直缺,而且缺在每一个横向容器上——标签栏、附件条、宽表格。
|
|
5
|
+
*
|
|
6
|
+
* **滚得动。** 横向滚动在这个应用里此前只有触摸板能做:两指一划。用鼠标的人手上只有一个垂直
|
|
7
|
+
* 滚轮,而垂直滚轮在一个只能横着滚的容器上什么也不做——内容明明溢出了,滚轮转起来毫无反应,看
|
|
8
|
+
* 起来就像卡住了。Shift + 滚轮是这件事在别处的通用手势,这里把它接上。
|
|
9
|
+
*
|
|
10
|
+
* 默认只接管按住 Shift 的那一下,不碰光秃秃的垂直滚轮。后者要留给上层:附件条就躺在输入框里,
|
|
11
|
+
* 输入框躺在转录区里,吃掉它等于让人滚不动这一整页。标签栏长在头部或底边,上面没有要竖着滚的
|
|
12
|
+
* 东西,传 `plainWheel` 让普通滚轮直接横着走——那里就不再需要一对方向键。
|
|
13
|
+
*
|
|
14
|
+
* **说明还没滚完。** 两端各一道渐隐,按滚动位置来:左边滚出去了左边才有,右边还有货右边才有。
|
|
15
|
+
* 硬边缘和「刚好排满」长得一模一样,而它们的意思相反——一个是「右边还有三个标签」,另一个是
|
|
16
|
+
* 「就这些了」。`plume-fade-tail` 那张遮罩早就在,只是 `--plume-fade-left/right` 从来没人喂过值,于是
|
|
17
|
+
* 三个标签栏都挂着一张全不透明的遮罩,等于没有。
|
|
18
|
+
*
|
|
19
|
+
* 量的是滚动条自己的三个数,不是鼠标做了什么:内容变了、窗口宽了、程序改了 `scrollLeft`,渐隐
|
|
20
|
+
* 都得跟着变,而这些一个都不经过滚轮。
|
|
21
|
+
*/
|
|
22
|
+
/** 两头各自还有没有东西。渐隐和方向键读的是同一份,所以永远同进同出。 */
|
|
23
|
+
export interface SidewaysEdges {
|
|
24
|
+
canLeft: boolean;
|
|
25
|
+
canRight: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function useSideways(ref: React.RefObject<HTMLElement | null>, { plainWheel }?: {
|
|
28
|
+
plainWheel?: boolean;
|
|
29
|
+
}): SidewaysEdges;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* agent 和装配它的应用之间的约定:应用提供要加载的插件,接收日志。
|
|
3
|
+
*/
|
|
4
|
+
/** 待加载的插件。load 导入逻辑入口,返回模块的默认导出。 */
|
|
5
|
+
export interface PluginEntry {
|
|
6
|
+
/** 出错时用来指认插件;拿不到名字时(导入失败、导出不合法)状态里也用它。 */
|
|
7
|
+
key: string;
|
|
8
|
+
load(): Promise<unknown>;
|
|
9
|
+
/** 界面入口的地址。 */
|
|
10
|
+
ui?: string;
|
|
11
|
+
/** 随应用发的插件,见 `PluginStatus.builtin`。 */
|
|
12
|
+
builtin?: boolean;
|
|
13
|
+
/** 插件目录(`package.json` 所在处),经 `ctx.plugins.list()` 告诉别的插件。只测宿主时可以不给。 */
|
|
14
|
+
dir?: string;
|
|
15
|
+
}
|
|
16
|
+
export type Log = (source: string, level: "info" | "warn" | "error", message: string) => void;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** 文件工具留下的本轮净变化;快照和撤销由提供 file.changes 服务的插件负责。 */
|
|
2
|
+
export interface ChangeHunk {
|
|
3
|
+
oldStart: number;
|
|
4
|
+
newStart: number;
|
|
5
|
+
lines: {
|
|
6
|
+
type: "context" | "add" | "remove";
|
|
7
|
+
text: string;
|
|
8
|
+
oldLine?: number;
|
|
9
|
+
newLine?: number;
|
|
10
|
+
}[];
|
|
11
|
+
}
|
|
12
|
+
export interface ChangedFile {
|
|
13
|
+
/** 真实绝对路径;界面只在显示时相对化,文件菜单和撤销不丢失工作目录。 */
|
|
14
|
+
path: string;
|
|
15
|
+
added: number;
|
|
16
|
+
removed: number;
|
|
17
|
+
hunks: ChangeHunk[];
|
|
18
|
+
canUndo: boolean;
|
|
19
|
+
/** 不能撤销时给人看的原因,按当前界面语言返回。 */
|
|
20
|
+
undoReason?: string;
|
|
21
|
+
/** 不能撤销的原因归哪一类;快照读不出来时不给,那时 `FileChangesSummary.warnings` 不为空。 */
|
|
22
|
+
undoProblem?: UndoProblem;
|
|
23
|
+
}
|
|
24
|
+
/** 不能自动退回的几种情况:改动来自命令、中途被别处改过、不在项目内、之后被改过。 */
|
|
25
|
+
export type UndoProblem = "command" | "interleaved" | "outside" | "modified";
|
|
26
|
+
export interface FileChangesSummary {
|
|
27
|
+
files: ChangedFile[];
|
|
28
|
+
warnings: string[];
|
|
29
|
+
}
|
|
30
|
+
/** 快照标识来自工具结果的 changeId / changeIds,不接受界面传来的文件原文。 */
|
|
31
|
+
export interface FileChangesService {
|
|
32
|
+
collect(sessionId: string, cwd: string, ids: readonly string[]): Promise<FileChangesSummary>;
|
|
33
|
+
/** path 不给时撤销全部;写入前重新校验快照、当前内容和项目边界。 */
|
|
34
|
+
undo(sessionId: string, cwd: string, ids: readonly string[], path?: string): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
/** 撤回、编辑重发截掉一段对话时,那段里改过的一个文件。`problem` 为 null 的能安全退回到截断点之前。 */
|
|
37
|
+
export interface RevertFile {
|
|
38
|
+
path: string;
|
|
39
|
+
added: number;
|
|
40
|
+
removed: number;
|
|
41
|
+
problem: UndoProblem | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 截掉的那段改过哪些文件。`unrecorded` 说有改动没记下来(快照缺了、命令影响的文件太多没记全),这时退回的不完整,
|
|
45
|
+
* 一个文件都不该写。
|
|
46
|
+
*/
|
|
47
|
+
export interface RevertPlan {
|
|
48
|
+
files: RevertFile[];
|
|
49
|
+
unrecorded: boolean;
|
|
50
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { AssistantMessage, Message, ToolSpec } from "../../core/llm/types.d.ts";
|
|
2
|
+
import type { AgentEvent, TurnStop } from "./service.ts";
|
|
3
|
+
/** 会话的只读运行观察,不包含供应商配置、请求头和密钥。观察者失败不影响运行。 */
|
|
4
|
+
export interface SessionObservation {
|
|
5
|
+
sessionId: string;
|
|
6
|
+
/** 观察时已有的消息数;撤回时诊断记录跟着截断。 */
|
|
7
|
+
at: number;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
event: Extract<AgentEvent, {
|
|
10
|
+
type: "toolStart" | "approval" | "hiccups" | "notice" | "rewound";
|
|
11
|
+
}> | {
|
|
12
|
+
type: "request";
|
|
13
|
+
id: string;
|
|
14
|
+
provider: string;
|
|
15
|
+
model: string;
|
|
16
|
+
systemPrompt: string;
|
|
17
|
+
messages: Message[];
|
|
18
|
+
tools: ToolSpec[];
|
|
19
|
+
} | {
|
|
20
|
+
type: "response";
|
|
21
|
+
id: string;
|
|
22
|
+
reply: AssistantMessage;
|
|
23
|
+
} | {
|
|
24
|
+
type: "running";
|
|
25
|
+
running: boolean;
|
|
26
|
+
}
|
|
27
|
+
/** 一轮收场了、为什么收场:完成、出错、被停下、用满步数、原地打转,退出应用时停下的是 `interrupted`。 */
|
|
28
|
+
| {
|
|
29
|
+
type: "turnEnd";
|
|
30
|
+
stop: TurnStop;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** 后台进程只按所属会话和任务 id 操作,不能传 pid 或日志路径。 */
|
|
34
|
+
export interface BackgroundJobInfo {
|
|
35
|
+
id: string;
|
|
36
|
+
command: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
startedAt: number;
|
|
39
|
+
finishedAt?: number;
|
|
40
|
+
exitCode: number | null;
|
|
41
|
+
pid?: number;
|
|
42
|
+
status: "running" | "stopping" | "exited" | "failed";
|
|
43
|
+
error?: string;
|
|
44
|
+
kind?: "monitor";
|
|
45
|
+
}
|
|
46
|
+
export interface BackgroundJobsService {
|
|
47
|
+
list(sessionId: string): BackgroundJobInfo[];
|
|
48
|
+
/** 尾部输出;不标记为模型已读,不消费后台送达。 */
|
|
49
|
+
output(sessionId: string, jobId: string): Promise<{
|
|
50
|
+
text: string;
|
|
51
|
+
done: boolean;
|
|
52
|
+
truncated: boolean;
|
|
53
|
+
error?: string;
|
|
54
|
+
}>;
|
|
55
|
+
stop(sessionId: string, jobId: string, force: boolean): boolean;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 模型给一个会话安排的「以后再接着做」:`schedule_wakeup` 的一次性唤醒(`kind: "wakeup"`)或 `cron_create` 的定时触发,还没触发的那一个。
|
|
59
|
+
* 只活在 agent 进程的内存里:退出应用、人按停止、撤回或编辑重发都会取消。
|
|
60
|
+
*/
|
|
61
|
+
export interface SessionWakeup {
|
|
62
|
+
/** `wake-1`、`cron-2`,在会话里唯一。 */
|
|
63
|
+
id: string;
|
|
64
|
+
kind: "wakeup" | "cron";
|
|
65
|
+
/** 到点时送给模型的那段话,模型写给自己的。 */
|
|
66
|
+
prompt: string;
|
|
67
|
+
/** 给人看的几个字(一次性唤醒必填);没有时界面用 `prompt` 的第一行。 */
|
|
68
|
+
reason?: string;
|
|
69
|
+
/** 5 段 cron 表达式,本地时间;一次性唤醒没有。 */
|
|
70
|
+
cron?: string;
|
|
71
|
+
recurring: boolean;
|
|
72
|
+
createdAt: number;
|
|
73
|
+
/** 下一次触发的时刻。 */
|
|
74
|
+
nextAt: number;
|
|
75
|
+
/** 循环任务过期的时刻,之后不再触发。 */
|
|
76
|
+
expiresAt?: number;
|
|
77
|
+
/** 已经触发过几次。 */
|
|
78
|
+
fired: number;
|
|
79
|
+
}
|
|
80
|
+
/** 服务 `session.wakeups`:读、取消会话里待触发的定时唤醒。内置插件 plume.tools 提供(它注册 `schedule_wakeup`、`cron_*` 这几件工具)。 */
|
|
81
|
+
export interface SessionWakeupsService {
|
|
82
|
+
/** 按下一次触发的先后;会话没有、没安排过时是空数组。 */
|
|
83
|
+
list(sessionId: string): SessionWakeup[];
|
|
84
|
+
/** 取消一个;已经触发了、不存在时返回 false。 */
|
|
85
|
+
cancel(sessionId: string, id: string): boolean;
|
|
86
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 共享类型:跨包、跨进程的约定都在这里,只有类型,没有运行时代码。按用途分文件:
|
|
3
|
+
*
|
|
4
|
+
* - `plugin.ts`:插件逻辑入口的 API(钩子、工具、ctx);界面入口的在 `ui.ts`(`@plume/contract/ui`);`resources.ts`:服务 `resources` 的资源地址;
|
|
5
|
+
* - `service.ts`:agent 进程给界面的 AgentService、事件和视图;`usage.ts`:存储页和插件读的使用统计数据;
|
|
6
|
+
* - `app.ts`:agent 和装配它的应用之间的约定(待加载的插件、日志)。
|
|
7
|
+
*
|
|
8
|
+
* 消息类型定义在 `@plume/llm`,在这里转出,使用方一律从 `@plume/contract` 引用。
|
|
9
|
+
*/
|
|
10
|
+
export type { ApiFormat, AssistantMessage, DeliveredReport, ImageContent, Message, MessageAttachment, PeerLetter, TextContent, ToolResultMessage, ToolSpec, UserContent, UserMessage, } from "../../core/llm/types.d.ts";
|
|
11
|
+
export type { CallContext } from "../../infra/rpc/src/index.d.ts";
|
|
12
|
+
export type * from "./app.ts";
|
|
13
|
+
export type * from "./changes.ts";
|
|
14
|
+
export type * from "./diagnostics.ts";
|
|
15
|
+
export type * from "./plugin.ts";
|
|
16
|
+
export type * from "./resources.ts";
|
|
17
|
+
export type * from "./service.ts";
|
|
18
|
+
export type * from "./usage.ts";
|