@plumeai/plugin-sdk 0.1.6 → 0.1.7

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.
@@ -186,6 +186,12 @@ export declare const en: {
186
186
  "projectList.projects": string;
187
187
  "projectList.recent": string;
188
188
  "projectList.newLooseChat": string;
189
+ "welcome.lateNight": string;
190
+ "welcome.morning": string;
191
+ "welcome.forenoon": string;
192
+ "welcome.noon": string;
193
+ "welcome.afternoon": string;
194
+ "welcome.evening": string;
189
195
  "empty.chat": string;
190
196
  "empty.projectQuestion": string;
191
197
  "empty.explore": string;
@@ -160,6 +160,12 @@ export declare const zhCN: {
160
160
  readonly "projectList.projects": "项目";
161
161
  readonly "projectList.recent": "聊天";
162
162
  readonly "projectList.newLooseChat": "新对话(不在项目中)";
163
+ readonly "welcome.lateNight": "夜深了";
164
+ readonly "welcome.morning": "早上好";
165
+ readonly "welcome.forenoon": "上午好";
166
+ readonly "welcome.noon": "中午好";
167
+ readonly "welcome.afternoon": "下午好";
168
+ readonly "welcome.evening": "晚上好";
163
169
  readonly "empty.chat": "想聊点什么?";
164
170
  readonly "empty.projectQuestion": "要在 {project} 内开发什么?";
165
171
  readonly "empty.explore": "理解代码";
@@ -468,11 +468,15 @@ export type AgentEvent = {
468
468
  type: "projects";
469
469
  projects: ProjectEntry[];
470
470
  }
471
- /** 一条消息写进了会话。回复(assistant)同时顶替正在写的草稿,不另发清空草稿的 draft 事件。 */
471
+ /**
472
+ * 一条消息写进了会话,`count` 是写进它以后的条数(它是第 `count - 1` 条)。回复(assistant)同时顶替正在写的草稿,不另发清空草稿的 draft 事件。
473
+ * 按位置放而不是接在末尾:界面拿快照接上事件流时会把快照里已有的几条再收一遍,放回原位就不会重复。
474
+ */
472
475
  | {
473
476
  type: "message";
474
477
  sessionId: string;
475
478
  message: Message;
479
+ count: number;
476
480
  }
477
481
  /** 会话截掉了尾巴(撤回、编辑重发):只留前 `count` 条消息,压缩记录和压缩行换成留下的那些。 */
478
482
  | {
@@ -692,16 +696,21 @@ export interface AgentService {
692
696
  * 正在跑时报错。图片块可以只带 `media`(会话里存着的那张),不用把像素再传一遍。
693
697
  * `files` 为真时先把截掉的那段改过的文件退回去(钩子 session.rewind),退不回去就报错,对话不截、也不重发。
694
698
  * 插件的子会话也能编辑重发(插件经 `ConversationProps.reask` 同意了),但不带 `files`;撤回、演算、分叉仍然只给人自己的会话。
699
+ * `timestamp` 是界面上那一条的时间戳:序号对不上时按它认回那一条,认不出就报错,不截错地方。
695
700
  */
696
701
  editMessage(sessionId: string, index: number, message: OutgoingMessage, options?: {
697
702
  files?: boolean;
703
+ timestamp?: number;
698
704
  }): Promise<void>;
699
- /** 撤回:第 `index` 条(人发的消息)连同它之后的全部截掉。正在跑时报错。`files` 同 `editMessage`。 */
705
+ /** 撤回:第 `index` 条(人发的消息)连同它之后的全部截掉。正在跑时报错。`files`、`timestamp` 同 `editMessage`。 */
700
706
  revertMessage(sessionId: string, index: number, options?: {
701
707
  files?: boolean;
708
+ timestamp?: number;
702
709
  }): Promise<void>;
703
- /** 撤回、编辑重发第 `index` 条会截掉的那段改过哪些文件、能不能一起退回,只演算,不写(钩子 session.rewind)。 */
704
- revertPlan(sessionId: string, index: number): Promise<RevertPlan>;
710
+ /** 撤回、编辑重发第 `index` 条会截掉的那段改过哪些文件、能不能一起退回,只演算,不写(钩子 session.rewind)。`timestamp` 同 `editMessage`。 */
711
+ revertPlan(sessionId: string, index: number, options?: {
712
+ timestamp?: number;
713
+ }): Promise<RevertPlan>;
705
714
  /**
706
715
  * 从第 `index` 条分叉出一个新会话,原会话不动。人发的消息:新会话停在它之前;落定的回复:新会话带着它。
707
716
  * `timestamp` 用来核对是不是那一条,对不上时按时间戳重找。正在跑也可以分叉。
@@ -709,6 +709,12 @@ export interface SessionChange {
709
709
  type: "messages" | "summary" | "deleted";
710
710
  tools?: string[];
711
711
  }
712
+ /** 欢迎页问候下面那一行(`ui.welcomeLine`):一句话,可以带出处。 */
713
+ export interface WelcomeLine {
714
+ text: string;
715
+ /** 出处(人名、书名),跟在这句话后面,小一号、更淡。 */
716
+ source?: string;
717
+ }
712
718
  /** 插件在 `@` 菜单里提供的一项,选中只插入 token,不会自动发送。 */
713
719
  export interface ComposerMention {
714
720
  id: string;
@@ -875,6 +881,11 @@ export interface UiContext {
875
881
  sessionId?: string;
876
882
  }) => ComposerMention[] | Promise<ComposerMention[]>): void;
877
883
  composerHint(hint: (session: SessionView) => string | undefined): void;
884
+ /**
885
+ * 换掉欢迎页问候下面的那一行(默认是「要在某个项目里开发什么?」):宿主每次画欢迎页时按界面语言问一次,等答复时那一行先空着,
886
+ * 回来了再淡入。只问最后注册的那一个;返回 undefined、空串或抛错时显示默认的那一句。一个插件只能有一个,再注册换掉上一个。
887
+ */
888
+ welcomeLine(line: (locale: Locale) => WelcomeLine | undefined | PromiseLike<WelcomeLine | undefined>): void;
878
889
  /**
879
890
  * 画回复的正文、复制回复之前,把字过一遍:插件让模型在回复里顺带写的标记(下一步建议的 `:followup[…]`)从这里拿掉。
880
891
  * 只改显示和复制,会话里存的、下一轮发给模型的都不变。正在生成的回复也会过,写了一半的标记也该拿掉。
package/dist/theme.css CHANGED
@@ -289,7 +289,7 @@
289
289
  --font-mono: var(--plume-font-mono);
290
290
 
291
291
  /*
292
- * 字号七档加代码一档,都是界面字号的 calc,改一个数整套一起动。档与档至少差 1px,各自带行高和字距:
292
+ * 字号八档加代码一档,都是界面字号的 calc,改一个数整套一起动。档与档至少差 1px,各自带行高和字距:
293
293
  * 字越大字距越紧。字重不放进档里,和字号配对写在用的地方(title 用 medium,heading、display 用 semibold)。
294
294
  */
295
295
  --text-caption: calc(var(--plume-ui-size) - 2px);
@@ -311,6 +311,10 @@
311
311
  --text-display: calc(var(--plume-ui-size) + 16px);
312
312
  --text-display--line-height: 1.2;
313
313
  --text-display--letter-spacing: -0.022em;
314
+ /* 只给欢迎页的问候:整页只有这一行字,比设置页的标题还大一档;配 font-medium,大字不再加粗。 */
315
+ --text-hero: calc(var(--plume-ui-size) + 22px);
316
+ --text-hero--line-height: 1.15;
317
+ --text-hero--letter-spacing: -0.025em;
314
318
  /* 代码另起一档:另一种字体,按列读;行高 1.6 比正文紧,缩进和括号的形状不被拉散。 */
315
319
  --text-code: var(--plume-code-size);
316
320
  --text-code--line-height: var(--plume-code-line-height);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumeai/plugin-sdk",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "写 Plume 插件用的类型、命令(新建、检查、构建、安装)、插件模板和给 agent 的 skill。随 Plume 应用带一份,也发在 npm 上(插件仓库按版本依赖)。",
5
5
  "license": "MIT",
6
6
  "repository": {
package/skill/SKILL.md CHANGED
@@ -46,7 +46,7 @@ description: 写、改、排查 Plume 插件:工具、钩子(tool.execute、
46
46
  - 在最新结束的回复下面画卡片(`ui.turnFooter`),随转录滚走,新一轮开始就撤下;每一轮回复底下的操作排里加按钮(`ui.replyAction`);复用产品的高亮差异(`ui.FileDiff`)、文件预览(`ui.FilePreview`)、统一只读文档预览(`ui.DocumentPreview`;经 `ui.documentViewer` 按扩展名注册,读取与权限仍由调用方负责)、文件右键菜单(`ui.useFileMenu`),经 `ui.openFile` 打开指定会话工作目录内的文件。
47
47
  - 用 `ui.codeBlock(language, Component)` 接管助手正文的某种围栏代码块;解析、具体 UI、状态和使用说明都归插件,收到原文、会话/消息/块标识、流式与完成状态;可选 `copyText` 在复制回复时提供当前可见值的文字。解析失败返回 `fallback`;宿主在渲染失败或停用时回到源码。完整块里真实点击后可经 `send(text, event)` 回到所属会话,不能在渲染或计时器中发送。
48
48
  - 用 `ui.mentions` 给 `@` 菜单提供当前目录可用的智能体或技能引用;选中只插入 token,不自动发送。页面角标 `ui.pageBadge` 可带 `attention: true` 同时进入通知菜单。
49
- - 给输入框一句灰字建议,人按 Tab 填进去(`ui.composerHint`);画回复前拿掉插件让模型顺带写的标记(`ui.replyText`,只改显示和复制);改会话标题(`ctx.sessions.setTitle`)。
49
+ - 给输入框一句灰字建议,人按 Tab 填进去(`ui.composerHint`);换掉欢迎页问候下面的那一行(`ui.welcomeLine`);画回复前拿掉插件让模型顺带写的标记(`ui.replyText`,只改显示和复制);改会话标题(`ctx.sessions.setTitle`)。
50
50
  - 用设置里的生图模型画图、改图(`ctx.model.findImageModel`、`ctx.model.image`),图存进会话媒体目录(`ctx.media`);界面入口显示(`ui.mediaUrl`)、用产品的看图器看和标注(`ui.openImage`),另存、复制(`ui.saveImage`、`ui.copyImage`),把图带回某个会话的输入框(`ui.draftInSession`),跳到某次工具调用的卡片(`ui.revealToolCall`);媒体图可在文件面板打开或在系统文件管理器定位(`ui.openMediaFile`、`ui.revealMediaFile`,菜单名取 `ui.revealMediaLabel()`)。
51
51
  - 侧栏会话行首空闲时画自己的记号(`ui.sessionMark`);删除确认框里补一句会连带、会留下什么(`ui.deleteNote`);人点了按钮时归档会话(`ctx.sessions.setArchived`);模型照人的要求归档它所在的对话时,工具那次调用经 `run.archiveAfterTurn()` 交给本体,这一轮以完成收场后才归档(只有顶层会话有)。
52
52
  - 弹提示条(界面入口 `ui.notify`,逻辑入口 `ctx.notice`)、打开、关闭自己的面板(`ui.openPanel`、`ui.closePanel`)、把一段话写进输入框等人自己发(`ui.draftInSession`,`replace` 时整段换掉),或在项目签那一行的格子里,人点了写明要发什么的按钮时以人的身份直接发(`send`);逻辑入口用默认模型做一次性的小调用(`ctx.model.complete`)、读会话(`ctx.sessions`)、读模型调用的花销(`ctx.model.usage`)。一次性结果要覆盖持久化内容时用 `ModelCompletion.requireComplete` 拒收截断结果;经 `ctx.sessions.onContextReset` 在压缩、撤回或上下文来源变化时作废自己的缓存。
@@ -41,6 +41,7 @@ export default {
41
41
  | `ui.environmentSection(id, Component, { label, order, attention? })` | 往会话的环境卡片(`plume.diagnostics` 画)里加一节,收到 `{ session }`;返回 null 不占位、不画分隔线;`label` 是卡片「显示哪些内容」菜单里的名字;`attention(session)` 是 hook,有事等人决定时返回一句话,卡片收着时开关上挂圆点 |
42
42
  | `ui.mentions(provider)` | 每次打开 `@` 时传 `{ cwd?, sessionId? }`,返回 `ComposerMention[]` 或 Promise:`id/title/kind/token` 必填,kind 是 subagent 或 plugin,可带 description/origin/avatar;只插入 token,用户自行发送,停用自动撤销 |
43
43
  | `ui.composerHint(session => text)` | 输入框空着时的灰字建议,按 Tab 填进去 |
44
+ | `ui.welcomeLine(locale => ({ text, source }))` | 换掉欢迎页问候下面的那一行(默认问要在哪个项目里做什么),只问最后注册的那一个 |
44
45
  | `ui.replyText(text => text)` | 画回复正文、复制回复前过一遍,拿掉插件让模型顺带写的标记 |
45
46
  | `ui.sessionMark(Component)` | 侧栏会话行首空闲时的记号,收到 `{ session, fallback }`,不是自己的会话返回 `fallback` |
46
47
  | `ui.deleteNote((sessionId, locale) => text)` | 删除确认框里补一句:删掉这个会话会连带什么、会留下什么 |
@@ -314,6 +315,18 @@ ui.replyText((text) => withoutFollowups(text));
314
315
  - `ui.replyText(transform)`:回复正文画出来、复制出去之前过一遍,只改显示和复制,会话里存的、发给模型的都不变。正在生成的回复也会过:写了一半的标记也要拿掉。拿完只剩空白的一段整段不画。
315
316
  - 两样每个插件各只能有一个,再注册换掉上一个;停用时撤下。
316
317
 
318
+ ## 欢迎页的那一行
319
+
320
+ ```ts
321
+ ui.welcomeLine((locale) => api.today(locale));
322
+ ```
323
+
324
+ 欢迎页问候(早上好、下午好……)下面的那一行字,默认是「要在某个项目里开发什么?」(不在项目里时「想聊点什么?」)。宿主每次画欢迎页时按界面语言问一次,可以返回 Promise:等答复时那一行先空着,回来了再淡入,不会先闪一下默认的那句;`text` 是这句话,`source` 是出处(可不给),跟在后面、小一号、更淡。
325
+
326
+ - 只问最后注册的那一个;它停用后还给前一个,都没有就是默认的那句。
327
+ - 返回 undefined、空串或抛错时显示默认的那句(抛错记日志)。每个插件只能有一个,再注册换掉上一个。
328
+ - 要花时间的事(调模型、读网络)放在逻辑入口里做好缓存,界面入口经 `remote()` 取;欢迎页常开,别每次打开都调一次模型。
329
+
317
330
  ## 侧栏的记号、删除确认框
318
331
 
319
332
  ```tsx