Compare commits
14
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6bdc4f2ada | ||
|
|
cafd9a54e5 | ||
|
|
a64fb5a168 | ||
|
|
c9aff06ed5 | ||
|
|
e6706450e4 | ||
|
|
fd441794b1 | ||
|
|
284e8f365f | ||
|
|
10a84345b7 | ||
|
|
e5c9c540cd | ||
|
|
9c4d163333 | ||
|
|
b6d428ba35 | ||
|
|
1728c95eae | ||
|
|
0cb0a40dc8 | ||
|
|
a2050d848f |
@@ -17,3 +17,20 @@
|
||||
- 模块边界、公开契约与隔离档位见 `policy/modules/`(如有)与 PROJECT.md。
|
||||
- 跨仓 gitlink 变更须经组合验证后在 Dev 仓推进;受保护分支经 PR 合入。
|
||||
- 验证命令见 PROJECT.md「验证」节;完成声明须附实际命令输出证据。
|
||||
|
||||
## Gitea 与 Git 访问事实(2026-09-30 实测)
|
||||
|
||||
历史文档与旧链接里的 `git-panel.u1680832.nyat.app:30319` 已失效(TLS 握手失败),
|
||||
见到一律按过期处理,不要再试。当前权威通道:
|
||||
|
||||
- **Web / API(HTTPS)**:`https://git-home.u1680832.nyat.app:30319`(Gitea 1.27.3,
|
||||
API 前缀 `/api/v1`;偶发 broken pipe / 超时,重试即可)。
|
||||
- **Git over SSH**:`ssh://git@git-ssh.u1680832.nyat.app:31411/weichen/<Repo>.git`
|
||||
(各仓 origin 与 gitlink 均为此格式)。
|
||||
- **API token**:`~/.secrets/gitea`,两行键值 `URL_PREFIX=…` 与
|
||||
`ACCESS_TOKEN=<40 位 hex>`;取值 `grep ACCESS_TOKEN ~/.secrets/gitea | cut -d= -f2-`,
|
||||
用作 `Authorization: token <值>` 请求头。**token 值不入仓、不回显、不写进产出物**
|
||||
(baseline 硬边界 2:只记录来源、字段与可用状态)。
|
||||
- **SSH key**:`~/.ssh/home_gitea`(ED25519,公钥指纹
|
||||
`SHA256:GYXaOXIMeloQ1fKSfdJ/ndgPQzs/Ix7Hk62ekfkfQ20`,Gitea 侧密钥名 GMKtec);
|
||||
`~/.ssh/config` 已有 `git-ssh.u1680832.nyat.app` 主机条目,克隆/推送直接可用。
|
||||
|
||||
+9
-2
@@ -47,6 +47,7 @@ func sampleMessage() Message {
|
||||
{Type: PartToolResult, Process: true, ToolResult: &ToolResultPart{CallID: "call_1", Status: "ok", Summary: "3 条命中"}},
|
||||
{Type: PartText, Text: "根据历史记录……"},
|
||||
{Type: PartArtifactRef, Artifact: &ArtifactRef{ArtifactID: "art_abc123def456", Name: "报告.md", Kind: "document"}},
|
||||
{Type: PartCard, Card: &CardPart{Kind: "result", Data: []UINode{{Type: "markdown", Markdown: "全文见卡片"}}, CardID: "card_abc123def456"}},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -63,7 +64,7 @@ func TestGoldenDomain(t *testing.T) {
|
||||
golden(t, "message", sampleMessage())
|
||||
golden(t, "run", sampleRun())
|
||||
golden(t, "project", Project{ID: "prj_abc123def456", Name: "示例项目"})
|
||||
golden(t, "conversation", Conversation{ID: "cnv_abc123def456", ProjectID: "prj_abc123def456", Title: "新会话"})
|
||||
golden(t, "conversation", Conversation{ID: "cnv_abc123def456", ProjectID: "prj_abc123def456", Title: "新会话", AllowCrossRead: true, CrossPrivate: true})
|
||||
golden(t, "artifact", Artifact{ID: "art_abc123def456", ProjectID: "prj_abc123def456", Name: "报告.md", Kind: "document", MIME: "text/markdown", Size: 128})
|
||||
}
|
||||
|
||||
@@ -125,6 +126,12 @@ func TestGoldenCardEvents(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGoldenUIVocabularies(t *testing.T) {
|
||||
golden(t, "ui_avatar", []UINode{
|
||||
{Type: UIAvatar, Avatar: &UIAvatarSpec{Name: "weichen", Sub: "OWNER"}},
|
||||
{Type: UIAvatar, Avatar: &UIAvatarSpec{
|
||||
Stack: []UIAvatarSpec{{Name: "甲", Tone: "ok"}, {Name: "乙", Tone: "warn"}, {Name: "丙"}},
|
||||
}},
|
||||
})
|
||||
golden(t, "ui_vocabularies", []UINode{
|
||||
{Type: UIProgress, Progress: &UIProgressSpec{Label: "市场可行性 78%", Value: 0.78, Tone: "ok"}},
|
||||
{Type: UICompare, Compare: &UICompareSpec{
|
||||
@@ -170,7 +177,7 @@ func TestGoldenProfileAndTools(t *testing.T) {
|
||||
golden(t, "tool_http", ToolDesc{
|
||||
Name: "http_translate", Description: "调用翻译 API", Source: SourceUser,
|
||||
Parameters: json.RawMessage(`{"type":"object","properties":{"text":{"type":"string"}},"required":["text"]}`),
|
||||
HTTP: &HTTPToolSpec{Method: "POST", URL: "https://api.example.com/translate", BodyTemplate: `{"q":"{{param.text}}"}`, TimeoutMs: 10000, ResultPath: "data.0"},
|
||||
HTTP: &HTTPToolSpec{Method: "POST", URL: "https://api.example.com/translate", BodyTemplate: `{"q":"{{param.text}}"}`, TimeoutMs: 10000, ResultPath: "data.0"},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,10 @@ type Conversation struct {
|
||||
Owner ID `json:"owner,omitempty"` // 冗余自项目,查询过滤用
|
||||
Title string `json:"title"`
|
||||
ProfileID ID `json:"profileId,omitempty"` // 空为默认画像
|
||||
Pinned bool `json:"pinned,omitempty"` // 侧栏置顶(方案 A P6/P8:本端组织偏好,服务端权威)
|
||||
Archived bool `json:"archived,omitempty"` // 归档:列表默认隐藏,数据保留
|
||||
AllowCrossRead bool `json:"allowCrossRead,omitempty"` // 跨会话出站:本会话读取同项目其他会话记录(需项目开关 crossSession.read)
|
||||
CrossPrivate bool `json:"crossPrivate,omitempty"` // 跨会话入站:私有会话,不被他读、不出现在他方列表
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
||||
@@ -120,9 +124,12 @@ type ErrorPart struct {
|
||||
}
|
||||
|
||||
// CardPart.Data 是 UI schema 节点(4.6 有限词汇)。
|
||||
// CardID 非空 = 收件箱 ActivityCard 的引用部件(如 submit_card 产卡:卡片为产物
|
||||
// 权威载体,消息只存引用+锚点渲染);空 = 插件内嵌卡片部件(自包含 Data)。
|
||||
type CardPart struct {
|
||||
Kind string `json:"kind"`
|
||||
Data []UINode `json:"data"`
|
||||
Kind string `json:"kind"`
|
||||
Data []UINode `json:"data"`
|
||||
CardID ID `json:"cardId,omitempty"`
|
||||
}
|
||||
|
||||
// ---- Run(一切运行皆 Run)----
|
||||
|
||||
@@ -11,6 +11,9 @@ type AgentProfile struct {
|
||||
Builtin bool `json:"builtin,omitempty"`
|
||||
Source string `json:"source,omitempty"` // builtin | plugin | user
|
||||
SystemPrompt string `json:"systemPrompt"`
|
||||
// PromptModules 引用提示词库模块 ID(有序;空 = 组装默认基座全集)。
|
||||
// SystemPrompt 兼容保留:非空时作为附加段追加在模块组装结果之后。
|
||||
PromptModules []string `json:"promptModules,omitempty"`
|
||||
Model ModelRoute `json:"model"`
|
||||
Tools ToolPolicy `json:"tools"`
|
||||
Context ContextPolicy `json:"context"`
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
package core
|
||||
|
||||
// 提示词模块契约(prompt-library):提示词从代码移入数据,按层组装、按触发注入。
|
||||
//
|
||||
// 分层(Layer):
|
||||
// - base 常驻基座块(身份/行为/谨慎/工具/风格),始终组装
|
||||
// - env 动态环境段(占位符填充:日期/模型/附件清单)
|
||||
// - task 任务技能(触发命中才注入;同层只注入优先级最高者)
|
||||
// - agent 子代理/小队角色提示词(派生 run 时取用)
|
||||
// - tool 工具描述文案(ToolDecl.description 的数据来源)
|
||||
// - aux 辅助模板(压缩摘要/标题生成等;入库先行,接线随功能走)
|
||||
// - style 输出风格(叠加在基座之上的表达方式变体)
|
||||
type PromptModule struct {
|
||||
ID string `json:"id"` // "base.identity" / "task.doc-minutes"
|
||||
Layer string `json:"layer"` // base|env|task|agent|tool|aux|style
|
||||
Version int `json:"version"` // 内置升级判定
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"` // 给人看(设置界面/命令菜单)
|
||||
Priority int `json:"priority,omitempty"` // task 层多命中时的取舍;缺省 50,大者优先
|
||||
Triggers []PromptTrigger `json:"triggers,omitempty"` // 空 = 基座,始终组装
|
||||
RequiresAttachments bool `json:"requiresAttachments,omitempty"` // 命中还需本轮有附件
|
||||
Body string `json:"body"` // 模板正文,{{placeholder}} 占位
|
||||
OutputContract string `json:"outputContract,omitempty"` // 期望产出形态(注入模型 + 供验收)
|
||||
Source string `json:"source,omitempty"` // builtin | plugin | user
|
||||
Owner string `json:"owner,omitempty"`
|
||||
BasedOnVersion int `json:"basedOnVersion,omitempty"` // 用户副本基于的内置版本
|
||||
Drifted bool `json:"drifted,omitempty"` // 用户副本落后于当前内置版本(提示用,不阻断)
|
||||
Disabled bool `json:"disabled,omitempty"` // 用户停用
|
||||
}
|
||||
|
||||
// PromptTrigger 触发条件;模块命中 = 任一 trigger 命中(再过 RequiresAttachments)。
|
||||
type PromptTrigger struct {
|
||||
Kind string `json:"kind"` // intent | command | attachment | manual
|
||||
Keywords []string `json:"keywords,omitempty"`
|
||||
Command string `json:"command,omitempty"` // "/minutes"
|
||||
}
|
||||
|
||||
// 触发 Kind 常量。
|
||||
const (
|
||||
TriggerIntent = "intent"
|
||||
TriggerCommand = "command"
|
||||
TriggerAttachment = "attachment"
|
||||
TriggerManual = "manual"
|
||||
)
|
||||
|
||||
// 层常量。
|
||||
const (
|
||||
LayerBase = "base"
|
||||
LayerEnv = "env"
|
||||
LayerTask = "task"
|
||||
LayerAgent = "agent"
|
||||
LayerTool = "tool"
|
||||
LayerAux = "aux"
|
||||
LayerStyle = "style"
|
||||
)
|
||||
|
||||
// PromptBlock 组装产物:一个已解析占位符的 system 段。
|
||||
type PromptBlock struct {
|
||||
ModuleID string `json:"moduleId"`
|
||||
Version int `json:"version"`
|
||||
Layer string `json:"layer"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
// PromptHitRecord 触发判定记录(可观测:哪个技能因何种原因注入/让位)。
|
||||
type PromptHitRecord struct {
|
||||
ModuleID string `json:"moduleId"`
|
||||
Layer string `json:"layer"`
|
||||
Reason string `json:"reason"` // "intent:纪要" / "command:/minutes" / "always" / "superseded-by:<id>"
|
||||
Injected bool `json:"injected"`
|
||||
}
|
||||
Vendored
+2
@@ -2,6 +2,8 @@
|
||||
"id": "cnv_abc123def456",
|
||||
"projectId": "prj_abc123def456",
|
||||
"title": "新会话",
|
||||
"allowCrossRead": true,
|
||||
"crossPrivate": true,
|
||||
"createdAt": "0001-01-01T00:00:00Z",
|
||||
"updatedAt": "0001-01-01T00:00:00Z"
|
||||
}
|
||||
|
||||
Vendored
+13
@@ -39,6 +39,19 @@
|
||||
"name": "报告.md",
|
||||
"kind": "document"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "card",
|
||||
"card": {
|
||||
"kind": "result",
|
||||
"data": [
|
||||
{
|
||||
"type": "markdown",
|
||||
"markdown": "全文见卡片"
|
||||
}
|
||||
],
|
||||
"cardId": "card_abc123def456"
|
||||
}
|
||||
}
|
||||
],
|
||||
"createdAt": "0001-01-01T00:00:00Z"
|
||||
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{
|
||||
"type": "avatar",
|
||||
"avatar": {
|
||||
"name": "weichen",
|
||||
"sub": "OWNER"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "avatar",
|
||||
"avatar": {
|
||||
"stack": [
|
||||
{
|
||||
"name": "甲",
|
||||
"tone": "ok"
|
||||
},
|
||||
{
|
||||
"name": "乙",
|
||||
"tone": "warn"
|
||||
},
|
||||
{
|
||||
"name": "丙"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -20,6 +20,9 @@ type ToolDesc struct {
|
||||
Source SourceKind `json:"source"`
|
||||
PluginID string `json:"pluginId,omitempty"`
|
||||
HTTP *HTTPToolSpec `json:"http,omitempty"` // 声明式 HTTP 工具(无代码)
|
||||
// Hidden 预留能力形态:默认不对模型与 /api/tools 列表可见,须运行时开关
|
||||
// (如 runtime.fsTools)或管理动作开启后可用(提案 2026-09-30-file-preview-and-reserved-capabilities)。
|
||||
Hidden bool `json:"hidden,omitempty"`
|
||||
}
|
||||
|
||||
// HTTPToolSpec:无代码自定义工具(4.8)。模板变量 {{param.x}} 从调用参数注入。
|
||||
|
||||
+26
-2
@@ -13,6 +13,8 @@ export interface Project {
|
||||
|
||||
export interface Conversation {
|
||||
id: ID; projectId: ID; owner?: ID; title: string; profileId?: ID;
|
||||
pinned?: boolean; archived?: boolean;
|
||||
allowCrossRead?: boolean; crossPrivate?: boolean;
|
||||
createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
@@ -30,7 +32,7 @@ export interface Part {
|
||||
artifact?: { artifactId: ID; name: string; kind?: string };
|
||||
hitl?: { cardId: ID; question: string; resolved: boolean; answer?: string };
|
||||
plan?: PlanSnapshot;
|
||||
card?: { kind: string; data: UINode[] };
|
||||
card?: { kind: string; data: UINode[]; cardId?: ID }; // cardId 非空 = 收件箱卡片引用部件(submit_card)
|
||||
error?: { code: string; message: string };
|
||||
process?: boolean; // run 终态后折叠为摘要行
|
||||
}
|
||||
@@ -151,7 +153,7 @@ export interface HITLResponse {
|
||||
|
||||
export type UINodeType =
|
||||
| 'section' | 'list' | 'kv' | 'form' | 'markdown' | 'doc-ref' | 'actions' | 'chart-lite'
|
||||
| 'progress' | 'compare' | 'tree' | 'table' | 'steps' | 'tabs' | 'timeline';
|
||||
| 'avatar' | 'progress' | 'compare' | 'tree' | 'table' | 'steps' | 'tabs' | 'timeline';
|
||||
|
||||
export interface UINode {
|
||||
type: UINodeType;
|
||||
@@ -165,6 +167,7 @@ export interface UINode {
|
||||
chart?: { kind: 'bar' | 'line'; labels: string[]; series: number[] };
|
||||
children?: UINode[];
|
||||
|
||||
avatar?: { name?: string; sub?: string; tone?: string; stack?: { name?: string; sub?: string; tone?: string }[] };
|
||||
progress?: { label?: string; value: number; tone?: string };
|
||||
compare?: {
|
||||
left: { title?: string; tone?: string; nodes?: UINode[] };
|
||||
@@ -191,11 +194,32 @@ export interface UIField {
|
||||
options?: string[]; required?: boolean; placeholder?: string; help?: string; default?: string;
|
||||
}
|
||||
|
||||
// ---- 提示词库(prompt-library)----
|
||||
|
||||
export interface PromptTrigger {
|
||||
kind: 'intent' | 'command' | 'attachment' | 'manual';
|
||||
keywords?: string[]; command?: string;
|
||||
}
|
||||
|
||||
export interface PromptModule {
|
||||
id: string; layer: 'base' | 'env' | 'task' | 'agent' | 'tool' | 'aux' | 'style';
|
||||
version: number; title: string; description?: string; priority?: number;
|
||||
triggers?: PromptTrigger[]; requiresAttachments?: boolean;
|
||||
body: string; outputContract?: string;
|
||||
source?: 'builtin' | 'plugin' | 'user'; owner?: string;
|
||||
basedOnVersion?: number; drifted?: boolean; disabled?: boolean;
|
||||
}
|
||||
|
||||
export interface PromptBlock { moduleId: string; version: number; layer: string; body: string; }
|
||||
export interface PromptHitRecord { moduleId: string; layer: string; reason: string; injected: boolean; }
|
||||
|
||||
// ---- 画像 / 设置 ----
|
||||
|
||||
export interface AgentProfile {
|
||||
id: string; owner?: string; name: string; description?: string; builtin?: boolean; source?: string;
|
||||
systemPrompt: string;
|
||||
/** 提示词库模块引用(有序;空 = 默认 base+env 全集)。 */
|
||||
promptModules?: string[];
|
||||
model: { chat?: string; lightweight?: string; embedding?: string; rerank?: string };
|
||||
tools: { allow: string[]; deny?: string[]; confirm?: string[] };
|
||||
context: {
|
||||
|
||||
@@ -17,6 +17,7 @@ const (
|
||||
UIChartLite UINodeType = "chart-lite"
|
||||
// —— 收件箱/工作区扩展词汇(提案 D28;graph 远期,追溯视图按"对象为中心 +
|
||||
// 分组泳道 + 逐层展开"约束设计,禁止力导向裸图)——
|
||||
UIAvatar UINodeType = "avatar" // 头像(成员/责任人展示;UI 能力平台,插件可用)
|
||||
UIProgress UINodeType = "progress" // 进度条(摄取/生成/填充度)
|
||||
UICompare UINodeType = "compare" // 左右对比(基线 vs 新内容、diff 确认)
|
||||
UITree UINodeType = "tree" // 树(文档树/笔记树骨架;节点带状态灯/徽标/计数)
|
||||
@@ -27,24 +28,33 @@ const (
|
||||
)
|
||||
|
||||
type UINode struct {
|
||||
Type UINodeType `json:"type"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Items []string `json:"items,omitempty"` // list
|
||||
KV [][2]string `json:"kv,omitempty"` // kv
|
||||
Fields []UIField `json:"fields,omitempty"` // form
|
||||
Markdown string `json:"markdown,omitempty"`
|
||||
DocID ID `json:"docId,omitempty"` // doc-ref
|
||||
Actions []UIAction `json:"actions,omitempty"`
|
||||
Chart *UIChart `json:"chart,omitempty"`
|
||||
Children []UINode `json:"children,omitempty"` // section
|
||||
Type UINodeType `json:"type"`
|
||||
Title string `json:"title,omitempty"`
|
||||
Items []string `json:"items,omitempty"` // list
|
||||
KV [][2]string `json:"kv,omitempty"` // kv
|
||||
Fields []UIField `json:"fields,omitempty"` // form
|
||||
Markdown string `json:"markdown,omitempty"`
|
||||
DocID ID `json:"docId,omitempty"` // doc-ref
|
||||
Actions []UIAction `json:"actions,omitempty"`
|
||||
Chart *UIChart `json:"chart,omitempty"`
|
||||
Children []UINode `json:"children,omitempty"` // section
|
||||
|
||||
Progress *UIProgressSpec `json:"progress,omitempty"` // progress
|
||||
Compare *UICompareSpec `json:"compare,omitempty"` // compare
|
||||
Tree *UITreeSpec `json:"tree,omitempty"` // tree
|
||||
Table *UITableSpec `json:"table,omitempty"` // table
|
||||
Steps *UIStepsSpec `json:"steps,omitempty"` // steps
|
||||
Tabs *UITabsSpec `json:"tabs,omitempty"` // tabs
|
||||
Timeline *UITimelineSpec `json:"timeline,omitempty"` // timeline
|
||||
Avatar *UIAvatarSpec `json:"avatar,omitempty"` // avatar
|
||||
Progress *UIProgressSpec `json:"progress,omitempty"` // progress
|
||||
Compare *UICompareSpec `json:"compare,omitempty"` // compare
|
||||
Tree *UITreeSpec `json:"tree,omitempty"` // tree
|
||||
Table *UITableSpec `json:"table,omitempty"` // table
|
||||
Steps *UIStepsSpec `json:"steps,omitempty"` // steps
|
||||
Tabs *UITabsSpec `json:"tabs,omitempty"` // tabs
|
||||
Timeline *UITimelineSpec `json:"timeline,omitempty"` // timeline
|
||||
}
|
||||
|
||||
// UIAvatar:头像(成员/责任人;Name 取首字,Tone 走语义色;Stack 为叠放组)。
|
||||
type UIAvatarSpec struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
Sub string `json:"sub,omitempty"` // 名字旁的小注(角色/状态)
|
||||
Tone string `json:"tone,omitempty"` // ok/warn/danger/info/留空=品牌色
|
||||
Stack []UIAvatarSpec `json:"stack,omitempty"` // 叠放头像组(多成员)
|
||||
}
|
||||
|
||||
// UIProgress:0–1 归一进度或 n/m 计数(Value=Done/Total 任一形式,前端按 <1 判定)。
|
||||
@@ -88,9 +98,9 @@ type UITableColumn struct {
|
||||
}
|
||||
|
||||
type UITableRow struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Cells [][2]string `json:"cells"` // 与 Columns.Key 对应的有序单元格
|
||||
Actions []UIAction `json:"actions,omitempty"` // 行级操作(走命令总线)
|
||||
ID string `json:"id,omitempty"`
|
||||
Cells [][2]string `json:"cells"` // 与 Columns.Key 对应的有序单元格
|
||||
Actions []UIAction `json:"actions,omitempty"` // 行级操作(走命令总线)
|
||||
}
|
||||
|
||||
type UITableSpec struct {
|
||||
@@ -146,7 +156,7 @@ type UIField struct {
|
||||
type UIAction struct {
|
||||
ID string `json:"id"`
|
||||
Label string `json:"label"`
|
||||
Style string `json:"style,omitempty"` // primary | default | danger
|
||||
Style string `json:"style,omitempty"` // primary | default | danger
|
||||
Command string `json:"command,omitempty"` // 绑定命令总线命令 id;空则降级为发消息
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user