@co-engram/core 0.1.1 → 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/dist/bootstrap/classify.d.ts +67 -0
- package/dist/bootstrap/classify.d.ts.map +1 -0
- package/dist/bootstrap/classify.js +119 -0
- package/dist/bootstrap/classify.js.map +1 -0
- package/dist/bootstrap/index.d.ts +89 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +158 -0
- package/dist/bootstrap/index.js.map +1 -0
- package/dist/concepts/dictionary.d.ts +260 -0
- package/dist/concepts/dictionary.d.ts.map +1 -0
- package/dist/concepts/dictionary.js +253 -0
- package/dist/concepts/dictionary.js.map +1 -0
- package/dist/concepts/index.d.ts +11 -0
- package/dist/concepts/index.d.ts.map +1 -0
- package/dist/concepts/index.js +10 -0
- package/dist/concepts/index.js.map +1 -0
- package/dist/concepts/types.d.ts +65 -0
- package/dist/concepts/types.d.ts.map +1 -0
- package/dist/concepts/types.js +15 -0
- package/dist/concepts/types.js.map +1 -0
- package/dist/config/defaults.d.ts +32 -3
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +52 -2
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/index.d.ts +18 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +75 -3
- package/dist/config/index.js.map +1 -1
- package/dist/config/loader.d.ts +10 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +10 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/types.d.ts +97 -1
- package/dist/config/types.d.ts.map +1 -1
- package/dist/contradiction/auto-degrade.d.ts +11 -2
- package/dist/contradiction/auto-degrade.d.ts.map +1 -1
- package/dist/contradiction/auto-degrade.js +22 -0
- package/dist/contradiction/auto-degrade.js.map +1 -1
- package/dist/contradiction/resolver.d.ts.map +1 -1
- package/dist/contradiction/resolver.js +7 -1
- package/dist/contradiction/resolver.js.map +1 -1
- package/dist/dreaming/index.d.ts +1 -0
- package/dist/dreaming/index.d.ts.map +1 -1
- package/dist/dreaming/index.js +1 -0
- package/dist/dreaming/index.js.map +1 -1
- package/dist/dreaming/llm-pattern-abstraction.d.ts +31 -0
- package/dist/dreaming/llm-pattern-abstraction.d.ts.map +1 -0
- package/dist/dreaming/llm-pattern-abstraction.js +70 -0
- package/dist/dreaming/llm-pattern-abstraction.js.map +1 -0
- package/dist/dreaming/rem.d.ts.map +1 -1
- package/dist/dreaming/rem.js +1 -0
- package/dist/dreaming/rem.js.map +1 -1
- package/dist/dreaming/scheduler.d.ts +13 -0
- package/dist/dreaming/scheduler.d.ts.map +1 -1
- package/dist/dreaming/scheduler.js +14 -2
- package/dist/dreaming/scheduler.js.map +1 -1
- package/dist/evolution/triggered.d.ts.map +1 -1
- package/dist/evolution/triggered.js +1 -0
- package/dist/evolution/triggered.js.map +1 -1
- package/dist/generative/hypothesis.d.ts.map +1 -1
- package/dist/generative/hypothesis.js +1 -0
- package/dist/generative/hypothesis.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1262 -32
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/index.d.ts +34 -1
- package/dist/i18n/index.d.ts.map +1 -1
- package/dist/i18n/index.js +36 -7
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/zh.d.ts +698 -32
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +1267 -33
- package/dist/i18n/zh.js.map +1 -1
- package/dist/index/graph-builder.js +3 -3
- package/dist/index/graph-builder.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/learning/loop.d.ts +9 -0
- package/dist/learning/loop.d.ts.map +1 -1
- package/dist/learning/loop.js +42 -1
- package/dist/learning/loop.js.map +1 -1
- package/dist/maintenance/types.d.ts +11 -0
- package/dist/maintenance/types.d.ts.map +1 -1
- package/dist/maintenance/types.js.map +1 -1
- package/dist/merge/synapse-merger.js +6 -0
- package/dist/merge/synapse-merger.js.map +1 -1
- package/dist/merge-driver.cjs +64 -5
- package/dist/observability/audit-log.d.ts +7 -1
- package/dist/observability/audit-log.d.ts.map +1 -1
- package/dist/observability/audit-log.js.map +1 -1
- package/dist/observability/necessity-evaluator.d.ts +29 -0
- package/dist/observability/necessity-evaluator.d.ts.map +1 -1
- package/dist/observability/necessity-evaluator.js +240 -13
- package/dist/observability/necessity-evaluator.js.map +1 -1
- package/dist/observability/proposal-engine.d.ts.map +1 -1
- package/dist/observability/proposal-engine.js +12 -0
- package/dist/observability/proposal-engine.js.map +1 -1
- package/dist/observability/runtime-description-check.d.ts +55 -0
- package/dist/observability/runtime-description-check.d.ts.map +1 -0
- package/dist/observability/runtime-description-check.js +63 -0
- package/dist/observability/runtime-description-check.js.map +1 -0
- package/dist/prompt-signals/cache.d.ts +73 -0
- package/dist/prompt-signals/cache.d.ts.map +1 -1
- package/dist/prompt-signals/cache.js +102 -0
- package/dist/prompt-signals/cache.js.map +1 -1
- package/dist/prompt-signals/event-bus.d.ts +82 -0
- package/dist/prompt-signals/event-bus.d.ts.map +1 -0
- package/dist/prompt-signals/event-bus.js +105 -0
- package/dist/prompt-signals/event-bus.js.map +1 -0
- package/dist/prompt-signals/index.d.ts +2 -1
- package/dist/prompt-signals/index.d.ts.map +1 -1
- package/dist/prompt-signals/index.js +2 -1
- package/dist/prompt-signals/index.js.map +1 -1
- package/dist/reinforcement/ltp.d.ts +15 -1
- package/dist/reinforcement/ltp.d.ts.map +1 -1
- package/dist/reinforcement/ltp.js +24 -5
- package/dist/reinforcement/ltp.js.map +1 -1
- package/dist/reinforcement/related.d.ts +31 -2
- package/dist/reinforcement/related.d.ts.map +1 -1
- package/dist/reinforcement/related.js +39 -3
- package/dist/reinforcement/related.js.map +1 -1
- package/dist/retrieval/filter.d.ts.map +1 -1
- package/dist/retrieval/filter.js +7 -0
- package/dist/retrieval/filter.js.map +1 -1
- package/dist/retrieval/fts.d.ts +6 -5
- package/dist/retrieval/fts.d.ts.map +1 -1
- package/dist/retrieval/fts.js +74 -22
- package/dist/retrieval/fts.js.map +1 -1
- package/dist/status/index.d.ts +7 -0
- package/dist/status/index.d.ts.map +1 -0
- package/dist/status/index.js +7 -0
- package/dist/status/index.js.map +1 -0
- package/dist/status/status.d.ts +132 -0
- package/dist/status/status.d.ts.map +1 -0
- package/dist/status/status.js +437 -0
- package/dist/status/status.js.map +1 -0
- package/dist/storage/engram-store.d.ts.map +1 -1
- package/dist/storage/engram-store.js +17 -2
- package/dist/storage/engram-store.js.map +1 -1
- package/dist/storage/git.d.ts +168 -0
- package/dist/storage/git.d.ts.map +1 -1
- package/dist/storage/git.js +616 -33
- package/dist/storage/git.js.map +1 -1
- package/dist/storage/index.d.ts +1 -0
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -0
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/infra-doctor.d.ts +42 -0
- package/dist/storage/infra-doctor.d.ts.map +1 -0
- package/dist/storage/infra-doctor.js +92 -0
- package/dist/storage/infra-doctor.js.map +1 -0
- package/dist/storage/obsidian-links.d.ts +73 -0
- package/dist/storage/obsidian-links.d.ts.map +1 -0
- package/dist/storage/obsidian-links.js +177 -0
- package/dist/storage/obsidian-links.js.map +1 -0
- package/dist/storage/path.d.ts +24 -0
- package/dist/storage/path.d.ts.map +1 -1
- package/dist/storage/path.js +53 -0
- package/dist/storage/path.js.map +1 -1
- package/dist/storage/repository.d.ts +37 -1
- package/dist/storage/repository.d.ts.map +1 -1
- package/dist/storage/repository.js +235 -17
- package/dist/storage/repository.js.map +1 -1
- package/dist/storage/synapse-store.d.ts +7 -1
- package/dist/storage/synapse-store.d.ts.map +1 -1
- package/dist/storage/synapse-store.js +8 -0
- package/dist/storage/synapse-store.js.map +1 -1
- package/dist/tools/audit-query-tool.d.ts +53 -0
- package/dist/tools/audit-query-tool.d.ts.map +1 -0
- package/dist/tools/audit-query-tool.js +123 -0
- package/dist/tools/audit-query-tool.js.map +1 -0
- package/dist/tools/doctor-tools.d.ts +5 -0
- package/dist/tools/doctor-tools.d.ts.map +1 -1
- package/dist/tools/doctor-tools.js +11 -3
- package/dist/tools/doctor-tools.js.map +1 -1
- package/dist/tools/engram-tools.d.ts +13 -0
- package/dist/tools/engram-tools.d.ts.map +1 -1
- package/dist/tools/engram-tools.js +72 -8
- package/dist/tools/engram-tools.js.map +1 -1
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/llm-descriptions.d.ts +28 -28
- package/dist/tools/llm-descriptions.d.ts.map +1 -1
- package/dist/tools/llm-descriptions.js +56 -489
- package/dist/tools/llm-descriptions.js.map +1 -1
- package/dist/tools/normalization.d.ts +43 -0
- package/dist/tools/normalization.d.ts.map +1 -0
- package/dist/tools/normalization.js +68 -0
- package/dist/tools/normalization.js.map +1 -0
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +6 -0
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/schemas.d.ts +67 -11
- package/dist/tools/schemas.d.ts.map +1 -1
- package/dist/tools/schemas.js +61 -6
- package/dist/tools/schemas.js.map +1 -1
- package/dist/tools/skill-tools.js +1 -1
- package/dist/tools/skill-tools.js.map +1 -1
- package/dist/tools/synapse-tools.d.ts.map +1 -1
- package/dist/tools/synapse-tools.js +1 -0
- package/dist/tools/synapse-tools.js.map +1 -1
- package/dist/tools/sync-tools.d.ts +102 -0
- package/dist/tools/sync-tools.d.ts.map +1 -0
- package/dist/tools/sync-tools.js +309 -0
- package/dist/tools/sync-tools.js.map +1 -0
- package/dist/tools/synthesize-tools.d.ts +79 -0
- package/dist/tools/synthesize-tools.d.ts.map +1 -0
- package/dist/tools/synthesize-tools.js +297 -0
- package/dist/tools/synthesize-tools.js.map +1 -0
- package/dist/tools/tool-profile.d.ts +68 -0
- package/dist/tools/tool-profile.d.ts.map +1 -0
- package/dist/tools/tool-profile.js +174 -0
- package/dist/tools/tool-profile.js.map +1 -0
- package/dist/tools/tool.d.ts +24 -0
- package/dist/tools/tool.d.ts.map +1 -1
- package/dist/tools/tool.js.map +1 -1
- package/dist/types/disclosure.d.ts +7 -0
- package/dist/types/disclosure.d.ts.map +1 -1
- package/dist/types/repository-types.d.ts +17 -1
- package/dist/types/repository-types.d.ts.map +1 -1
- package/dist/types/synapse.d.ts +19 -1
- package/dist/types/synapse.d.ts.map +1 -1
- package/package.json +9 -9
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 仓库同步工具集
|
|
3
|
+
*
|
|
4
|
+
* - engram_sync 手动触发 pull → commit → push(赋予用户掌控感)
|
|
5
|
+
*
|
|
6
|
+
* 设计要点:
|
|
7
|
+
* - 用户主动触发,与系统自动 markDirty 区分
|
|
8
|
+
* - 流程编排严格按"先 pull 合并远端 → 再 commit 本地 → 最后 push"
|
|
9
|
+
* - 不硬编码任何主机/URL/refspec,继承用户 git 环境
|
|
10
|
+
* - 冲突不自动 resolve,rebase --abort 后清晰报告让用户决策
|
|
11
|
+
* - dryRun 完全只读(不写 .gitignore,不动 git index),只预测变更
|
|
12
|
+
*
|
|
13
|
+
* @module @co-engram/core/tools
|
|
14
|
+
*/
|
|
15
|
+
import { z } from "zod";
|
|
16
|
+
import type { Tool } from "./tool.js";
|
|
17
|
+
export declare const EngramSyncInputSchema: z.ZodObject<{
|
|
18
|
+
message: z.ZodOptional<z.ZodString>;
|
|
19
|
+
dryRun: z.ZodOptional<z.ZodBoolean>;
|
|
20
|
+
pull: z.ZodOptional<z.ZodBoolean>;
|
|
21
|
+
push: z.ZodOptional<z.ZodBoolean>;
|
|
22
|
+
untrackCache: z.ZodOptional<z.ZodBoolean>;
|
|
23
|
+
}, "strict", z.ZodTypeAny, {
|
|
24
|
+
push?: boolean | undefined;
|
|
25
|
+
message?: string | undefined;
|
|
26
|
+
dryRun?: boolean | undefined;
|
|
27
|
+
pull?: boolean | undefined;
|
|
28
|
+
untrackCache?: boolean | undefined;
|
|
29
|
+
}, {
|
|
30
|
+
push?: boolean | undefined;
|
|
31
|
+
message?: string | undefined;
|
|
32
|
+
dryRun?: boolean | undefined;
|
|
33
|
+
pull?: boolean | undefined;
|
|
34
|
+
untrackCache?: boolean | undefined;
|
|
35
|
+
}>;
|
|
36
|
+
export type EngramSyncToolInput = z.infer<typeof EngramSyncInputSchema>;
|
|
37
|
+
/** pull 阶段结果(对齐 GitPullResult,增加 skipped 标记) */
|
|
38
|
+
export interface SyncPullPhase {
|
|
39
|
+
readonly ok: boolean;
|
|
40
|
+
/** 是否被跳过(pull=false 时) */
|
|
41
|
+
readonly skipped: boolean;
|
|
42
|
+
readonly upToDate?: boolean;
|
|
43
|
+
readonly fetchedCount?: number;
|
|
44
|
+
readonly conflicts?: readonly string[];
|
|
45
|
+
}
|
|
46
|
+
/** commit 阶段结果 */
|
|
47
|
+
export interface SyncCommitPhase {
|
|
48
|
+
readonly ok: boolean;
|
|
49
|
+
/** 无变更时为 true(已跳过 commit) */
|
|
50
|
+
readonly nothingToCommit?: boolean;
|
|
51
|
+
readonly sha?: string;
|
|
52
|
+
readonly branch?: string;
|
|
53
|
+
readonly filesChanged: number;
|
|
54
|
+
readonly message: string;
|
|
55
|
+
}
|
|
56
|
+
/** push 阶段结果 */
|
|
57
|
+
export interface SyncPushPhase {
|
|
58
|
+
readonly ok: boolean;
|
|
59
|
+
readonly skipped: boolean;
|
|
60
|
+
readonly reason?: string;
|
|
61
|
+
readonly remote?: string;
|
|
62
|
+
/** 实际生效的 push 模式;fallback 成功时为 "gerrit-review" */
|
|
63
|
+
readonly mode?: "direct" | "gerrit-review";
|
|
64
|
+
/** 仅在 direct 拒绝后自动 fallback 到 gerrit-review 成功时为 true */
|
|
65
|
+
readonly autoFallback?: true;
|
|
66
|
+
}
|
|
67
|
+
export interface EngramSyncResult {
|
|
68
|
+
/**
|
|
69
|
+
* 整体成功/失败机器判断位。
|
|
70
|
+
*
|
|
71
|
+
* pull 失败或 push 失败(非 skipped)→ false;push skipped(无 remote / push=false)
|
|
72
|
+
* 视为预期降级,不影响 ok。让 host adapter 据此决定是否给用户追加高亮提示,
|
|
73
|
+
* 不必解析 summary 字符串。
|
|
74
|
+
*/
|
|
75
|
+
readonly ok: boolean;
|
|
76
|
+
/** 仓库绝对路径(=dataRoot) */
|
|
77
|
+
readonly repoPath: string;
|
|
78
|
+
/** 本次是否新建了 .gitignore(dryRun 时为 false,只预测) */
|
|
79
|
+
readonly gitignoreCreated: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* 本次是否向已存在的 .gitignore 追加了 `private/` 规则。
|
|
82
|
+
*
|
|
83
|
+
* 用于历史仓库升级:旧 .gitignore 没有 private/ 行,engram_sync 自动补上。
|
|
84
|
+
* 与 gitignoreCreated 互斥(新建的 .gitignore 模板已含 private/,无需再追加)。
|
|
85
|
+
* dryRun 时为 false,只预测。
|
|
86
|
+
*/
|
|
87
|
+
readonly privateGitignoreAppended: boolean;
|
|
88
|
+
/** 本次是否把 .co-engram/ 从 git index 移除(磁盘保留) */
|
|
89
|
+
readonly cacheUntracked: boolean;
|
|
90
|
+
/** 当前 .co-engram/ 下已被 git track 的文件数(用于让用户判断是否需要 untrackCache) */
|
|
91
|
+
readonly trackedCacheCount: number;
|
|
92
|
+
/** dryRun=true 时的变更预览(相对仓库根路径) */
|
|
93
|
+
readonly changedFiles?: readonly string[];
|
|
94
|
+
readonly pulled?: SyncPullPhase;
|
|
95
|
+
readonly committed?: SyncCommitPhase;
|
|
96
|
+
readonly pushed?: SyncPushPhase;
|
|
97
|
+
/** 整体结论摘要(给 LLM 用的自然语言一句话) */
|
|
98
|
+
readonly summary: string;
|
|
99
|
+
}
|
|
100
|
+
export declare const engramSyncTool: Tool<EngramSyncToolInput, EngramSyncResult>;
|
|
101
|
+
export declare const ALL_SYNC_TOOLS: readonly Tool[];
|
|
102
|
+
//# sourceMappingURL=sync-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-tools.d.ts","sourceRoot":"","sources":["../../src/tools/sync-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,WAAW,CAAC;AAsBnD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;EAiCvB,CAAC;AAEZ,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAExE,gDAAgD;AAChD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,0BAA0B;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAED,kBAAkB;AAClB,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,6BAA6B;IAC7B,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,gBAAgB;AAChB,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,eAAe,CAAC;IAC3C,yDAAyD;IACzD,QAAQ,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,gBAAgB;IAC/B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,wBAAwB;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAC;IAC3C,6CAA6C;IAC7C,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,kEAAkE;IAClE,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,kCAAkC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,SAAS,CAAC,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,8BAA8B;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAeD,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,mBAAmB,EAAE,gBAAgB,CA6JtE,CAAC;AAiJF,eAAO,MAAM,cAAc,EAAE,SAAS,IAAI,EAAqB,CAAC"}
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 仓库同步工具集
|
|
3
|
+
*
|
|
4
|
+
* - engram_sync 手动触发 pull → commit → push(赋予用户掌控感)
|
|
5
|
+
*
|
|
6
|
+
* 设计要点:
|
|
7
|
+
* - 用户主动触发,与系统自动 markDirty 区分
|
|
8
|
+
* - 流程编排严格按"先 pull 合并远端 → 再 commit 本地 → 最后 push"
|
|
9
|
+
* - 不硬编码任何主机/URL/refspec,继承用户 git 环境
|
|
10
|
+
* - 冲突不自动 resolve,rebase --abort 后清晰报告让用户决策
|
|
11
|
+
* - dryRun 完全只读(不写 .gitignore,不动 git index),只预测变更
|
|
12
|
+
*
|
|
13
|
+
* @module @co-engram/core/tools
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { z } from "zod";
|
|
18
|
+
import { validateInput } from "./tool.js";
|
|
19
|
+
import { appendToGitignore, commitFiles, countTrackedCoEngramCache, ensureGitignore, getGitStatusShort, gitignoreContainsRule, hasRemote, isGitRepo, pullRepo, pushRepo, untrackCoEngramCache, } from "../storage/git.js";
|
|
20
|
+
// ============================================================
|
|
21
|
+
// engram_sync
|
|
22
|
+
// ============================================================
|
|
23
|
+
export const EngramSyncInputSchema = z
|
|
24
|
+
.object({
|
|
25
|
+
message: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe("Custom commit message. If omitted, auto-generates `co-engram sync: YYYY-MM-DD`."),
|
|
29
|
+
dryRun: z
|
|
30
|
+
.boolean()
|
|
31
|
+
.optional()
|
|
32
|
+
.describe("Preview-only: return what would be committed, do not pull/commit/push. Default false."),
|
|
33
|
+
pull: z
|
|
34
|
+
.boolean()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("Pull with --rebase before committing. Default true. Set false to commit against current HEAD only."),
|
|
37
|
+
push: z
|
|
38
|
+
.boolean()
|
|
39
|
+
.optional()
|
|
40
|
+
.describe("Push to remote after committing. Default true. Auto-degrades to commit-only when no remote is configured."),
|
|
41
|
+
untrackCache: z
|
|
42
|
+
.boolean()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("If .co-engram/ files are already git-tracked (legacy), run `git rm -r --cached .co-engram/` to untrack them in this commit (disk files kept locally). NOTE: teammates who pull this commit will see git delete those files on their disk too. Default false — opt-in. dryRun reports the tracked count regardless."),
|
|
45
|
+
})
|
|
46
|
+
.strict();
|
|
47
|
+
/**
|
|
48
|
+
* 生成默认 commit 信息: `co-engram sync: YYYY-MM-DD`
|
|
49
|
+
*
|
|
50
|
+
* 用本地日期(非 UTC),匹配用户主观"今天"概念。
|
|
51
|
+
*/
|
|
52
|
+
function defaultCommitMessage() {
|
|
53
|
+
const now = new Date();
|
|
54
|
+
const yyyy = now.getFullYear();
|
|
55
|
+
const mm = String(now.getMonth() + 1).padStart(2, "0");
|
|
56
|
+
const dd = String(now.getDate()).padStart(2, "0");
|
|
57
|
+
return `co-engram sync: ${yyyy}-${mm}-${dd}`;
|
|
58
|
+
}
|
|
59
|
+
export const engramSyncTool = {
|
|
60
|
+
name: "engram_sync",
|
|
61
|
+
description: "Manually trigger a full memory sync: pull (rebase) → commit → push. Gives the user explicit control over when memories are persisted to the remote, as opposed to the automatic dirty-marking that just flags the repo as changed. Auto-creates a .gitignore excluding the .co-engram/ cache directory if missing. Handles conflicts by aborting the rebase and reporting conflict files for manual resolution. Degrades to commit-only when no remote is configured. Compatible with any git host (GitHub / GitLab / Gerrit / internal) — does not hardcode URLs, Change-Id, or push refspecs.",
|
|
62
|
+
inputSchema: EngramSyncInputSchema,
|
|
63
|
+
execute(input, ctx) {
|
|
64
|
+
const parsed = validateInput(EngramSyncInputSchema, input);
|
|
65
|
+
const repoPath = resolveRepoPathFromContext(ctx);
|
|
66
|
+
if (!isGitRepo(repoPath)) {
|
|
67
|
+
throw new Error(`engram_sync requires a git repo. dataRoot is not a git repository: ${repoPath}. Initialize with: cd ${repoPath} && git init && git remote add origin <url>`);
|
|
68
|
+
}
|
|
69
|
+
const pull = parsed.pull !== false;
|
|
70
|
+
const push = parsed.push !== false;
|
|
71
|
+
const dryRun = parsed.dryRun === true;
|
|
72
|
+
const untrackCacheRequested = parsed.untrackCache === true;
|
|
73
|
+
// 只读检测:已有 .gitignore?已含 private/ 规则?已 tracked 缓存数?
|
|
74
|
+
const gitignoreExists = existsSync(join(repoPath, ".gitignore"));
|
|
75
|
+
const privateRulePresent = gitignoreContainsRule(repoPath, "private/");
|
|
76
|
+
const trackedCacheCount = countTrackedCoEngramCache(repoPath);
|
|
77
|
+
// 1. dryRun:完全只读 —— 不创建 .gitignore、不动 git index
|
|
78
|
+
// 只预测 effective changedFiles:
|
|
79
|
+
// - 若 untrackCacheRequested=true,模拟 .co-engram/ 退出跟踪 →
|
|
80
|
+
// 从 changedFiles 排除 .co-engram/(因为它们会变成 staged delete,
|
|
81
|
+
// 但不会作为"新内容"出现在 commit 里,只是退出 tracking)
|
|
82
|
+
// - 否则按当前 git status 报告
|
|
83
|
+
if (dryRun) {
|
|
84
|
+
const allFiles = getGitStatusShort(repoPath);
|
|
85
|
+
const effectiveFiles = untrackCacheRequested
|
|
86
|
+
? allFiles.filter((f) => !f.startsWith(".co-engram/"))
|
|
87
|
+
: allFiles;
|
|
88
|
+
const wouldCreateGitignore = !gitignoreExists;
|
|
89
|
+
// 历史 .gitignore 不含 private/ 时,本次 sync 会追加(用于让用户预知)
|
|
90
|
+
const wouldAppendPrivate = gitignoreExists && !privateRulePresent;
|
|
91
|
+
const summary = buildDryRunSummary({
|
|
92
|
+
effectiveCount: effectiveFiles.length,
|
|
93
|
+
pull,
|
|
94
|
+
push,
|
|
95
|
+
wouldCreateGitignore,
|
|
96
|
+
wouldAppendPrivate,
|
|
97
|
+
trackedCacheCount,
|
|
98
|
+
untrackCacheRequested,
|
|
99
|
+
});
|
|
100
|
+
return {
|
|
101
|
+
ok: true,
|
|
102
|
+
repoPath,
|
|
103
|
+
gitignoreCreated: false,
|
|
104
|
+
privateGitignoreAppended: false,
|
|
105
|
+
cacheUntracked: false,
|
|
106
|
+
trackedCacheCount,
|
|
107
|
+
changedFiles: effectiveFiles,
|
|
108
|
+
summary,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// 2. 非 dryRun:执行 .gitignore + 追加 private/ 规则(若缺) + 可选 untrack
|
|
112
|
+
const gitignoreCreated = ensureGitignore(repoPath);
|
|
113
|
+
// 历史仓库升级:.gitignore 已存在但缺 private/ 行 → 追加
|
|
114
|
+
// (ensureGitignore 新建的 .gitignore 模板已含 private/,此处追加 noop)
|
|
115
|
+
const privateGitignoreAppended = gitignoreCreated
|
|
116
|
+
? false
|
|
117
|
+
: appendToGitignore(repoPath, "private/");
|
|
118
|
+
let cacheUntracked = false;
|
|
119
|
+
if (untrackCacheRequested) {
|
|
120
|
+
const removed = untrackCoEngramCache(repoPath);
|
|
121
|
+
cacheUntracked = removed > 0;
|
|
122
|
+
}
|
|
123
|
+
// 3. pull 阶段(--rebase,autostash;冲突时 abort 并报告)
|
|
124
|
+
let pulled;
|
|
125
|
+
if (pull) {
|
|
126
|
+
const r = pullRepo(repoPath);
|
|
127
|
+
pulled = {
|
|
128
|
+
ok: r.ok,
|
|
129
|
+
skipped: false,
|
|
130
|
+
...(r.upToDate !== undefined ? { upToDate: r.upToDate } : {}),
|
|
131
|
+
...(r.fetchedCount !== undefined
|
|
132
|
+
? { fetchedCount: r.fetchedCount }
|
|
133
|
+
: {}),
|
|
134
|
+
...(r.conflicts !== undefined ? { conflicts: r.conflicts } : {}),
|
|
135
|
+
};
|
|
136
|
+
if (!r.ok && r.conflicts) {
|
|
137
|
+
const fileList = r.conflicts.join(", ");
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
repoPath,
|
|
141
|
+
gitignoreCreated,
|
|
142
|
+
privateGitignoreAppended,
|
|
143
|
+
cacheUntracked,
|
|
144
|
+
trackedCacheCount,
|
|
145
|
+
pulled,
|
|
146
|
+
summary: `pull failed: ${r.conflicts.length} conflict(s) after rebase — ${fileList}. Rebase auto-aborted. Resolve manually and rerun engram_sync.`,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
pulled = { ok: true, skipped: true };
|
|
152
|
+
}
|
|
153
|
+
// 4. commit 阶段(git add -A + commit;无变更跳过)
|
|
154
|
+
const message = parsed.message?.trim() || defaultCommitMessage();
|
|
155
|
+
const commitResult = commitFiles({
|
|
156
|
+
repoPath,
|
|
157
|
+
files: [],
|
|
158
|
+
message,
|
|
159
|
+
});
|
|
160
|
+
const committed = {
|
|
161
|
+
ok: true,
|
|
162
|
+
filesChanged: commitResult.filesChanged,
|
|
163
|
+
message,
|
|
164
|
+
...(commitResult.commitHash
|
|
165
|
+
? { sha: commitResult.commitHash, branch: commitResult.branch }
|
|
166
|
+
: { nothingToCommit: true }),
|
|
167
|
+
};
|
|
168
|
+
// 5. push 阶段(无 remote 自动降级为 skipped,不报错)
|
|
169
|
+
let pushed;
|
|
170
|
+
if (push) {
|
|
171
|
+
if (!hasRemote(repoPath)) {
|
|
172
|
+
pushed = {
|
|
173
|
+
ok: true,
|
|
174
|
+
skipped: true,
|
|
175
|
+
reason: "no remote configured (commit only)",
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
const r = pushRepo(repoPath);
|
|
180
|
+
pushed = toSyncPushPhase(r);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
pushed = { ok: true, skipped: true, reason: "push disabled by caller" };
|
|
185
|
+
}
|
|
186
|
+
return {
|
|
187
|
+
ok: computeOverallOk(pulled, pushed),
|
|
188
|
+
repoPath,
|
|
189
|
+
gitignoreCreated,
|
|
190
|
+
privateGitignoreAppended,
|
|
191
|
+
cacheUntracked,
|
|
192
|
+
trackedCacheCount,
|
|
193
|
+
pulled,
|
|
194
|
+
committed,
|
|
195
|
+
pushed,
|
|
196
|
+
summary: buildSummary(pulled, committed, pushed, {
|
|
197
|
+
cacheUntracked,
|
|
198
|
+
trackedCacheCount,
|
|
199
|
+
privateGitignoreAppended,
|
|
200
|
+
}),
|
|
201
|
+
};
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
function toSyncPushPhase(r) {
|
|
205
|
+
return {
|
|
206
|
+
ok: r.ok,
|
|
207
|
+
skipped: r.skipped,
|
|
208
|
+
...(r.reason !== undefined ? { reason: r.reason } : {}),
|
|
209
|
+
...(r.remote !== undefined ? { remote: r.remote } : {}),
|
|
210
|
+
...(r.mode !== undefined ? { mode: r.mode } : {}),
|
|
211
|
+
...(r.autoFallback === true ? { autoFallback: true } : {}),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* 从 ToolContext 解析仓库根路径。
|
|
216
|
+
*
|
|
217
|
+
* repository.config.rootPath 是 dataRoot 的权威来源(host 注入时已规范化)。
|
|
218
|
+
*/
|
|
219
|
+
function resolveRepoPathFromContext(ctx) {
|
|
220
|
+
const repo = ctx.repository;
|
|
221
|
+
return repo.config.rootPath;
|
|
222
|
+
}
|
|
223
|
+
function buildDryRunSummary(opts) {
|
|
224
|
+
const parts = [];
|
|
225
|
+
parts.push(`dry-run: ${opts.effectiveCount} file(s) would be committed (pull=${opts.pull}, push=${opts.push})`);
|
|
226
|
+
if (opts.wouldCreateGitignore) {
|
|
227
|
+
parts.push(".gitignore would be created (excludes .co-engram/ + private/)");
|
|
228
|
+
}
|
|
229
|
+
if (opts.wouldAppendPrivate) {
|
|
230
|
+
parts.push("private/ would be appended to existing .gitignore (isolates visibility='private' engrams from team git)");
|
|
231
|
+
}
|
|
232
|
+
if (opts.trackedCacheCount > 0) {
|
|
233
|
+
if (opts.untrackCacheRequested) {
|
|
234
|
+
parts.push(`${opts.trackedCacheCount} .co-engram/* file(s) would be untracked in this commit (teammates pulling will see git delete these on their disk)`);
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
parts.push(`WARNING: ${opts.trackedCacheCount} .co-engram/* file(s) already tracked — they will be committed unless you pass untrackCache=true (consider implications for teammates)`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return parts.join("; ") + ".";
|
|
241
|
+
}
|
|
242
|
+
function buildSummary(pulled, committed, pushed, opts) {
|
|
243
|
+
const parts = [];
|
|
244
|
+
const pushFailed = pushed !== undefined && !pushed.skipped && !pushed.ok;
|
|
245
|
+
// push 失败时提到最前,避免被前面的"成功"段掩盖(partial-success masking):
|
|
246
|
+
// 挑剔用户看漏末尾的 push failed 会以为整体成功。
|
|
247
|
+
if (pushFailed) {
|
|
248
|
+
parts.push(`push failed: ${pushed.reason ?? "unknown"}`);
|
|
249
|
+
parts.push(`local commit ${committed?.sha?.slice(0, 8) ?? "?"} saved — manual push or gerrit review (refs/for/<branch>) required`);
|
|
250
|
+
}
|
|
251
|
+
if (opts.privateGitignoreAppended) {
|
|
252
|
+
parts.push("appended private/ to .gitignore (visibility='private' engrams now isolated from team git)");
|
|
253
|
+
}
|
|
254
|
+
if (opts.cacheUntracked) {
|
|
255
|
+
parts.push(`untracked ${opts.trackedCacheCount} .co-engram/* file(s) (teammates pulling will see git delete these on disk)`);
|
|
256
|
+
}
|
|
257
|
+
if (pulled) {
|
|
258
|
+
if (pulled.skipped) {
|
|
259
|
+
parts.push("pull skipped");
|
|
260
|
+
}
|
|
261
|
+
else if (pulled.upToDate) {
|
|
262
|
+
parts.push("already up-to-date with remote");
|
|
263
|
+
}
|
|
264
|
+
else if (!pulled.ok) {
|
|
265
|
+
parts.push(`pull failed (${pulled.conflicts?.length ?? 0} conflicts)`);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
parts.push(`pulled ${pulled.fetchedCount ?? 0} commit(s) via rebase`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (committed) {
|
|
272
|
+
if (committed.nothingToCommit) {
|
|
273
|
+
parts.push("nothing to commit");
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
parts.push(`committed ${committed.filesChanged} file(s) as ${committed.sha?.slice(0, 8) ?? "?"}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (pushed && !pushFailed) {
|
|
280
|
+
if (pushed.skipped) {
|
|
281
|
+
parts.push(`push skipped (${pushed.reason ?? "unknown"})`);
|
|
282
|
+
}
|
|
283
|
+
else if (pushed.autoFallback) {
|
|
284
|
+
parts.push(`pushed via gerrit-review (refs/for/<branch>, auto-fallback) to ${pushed.remote ?? "origin"}`);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
parts.push(`pushed to ${pushed.remote ?? "origin"}`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return parts.join("; ") + ".";
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* 整体成功/失败判定:pull 失败或 push 失败(非 skipped)→ false。
|
|
294
|
+
*
|
|
295
|
+
* push skipped 是预期降级(无 remote / push=false),不算失败。
|
|
296
|
+
* committed 阶段现状总是 ok=true(无变更时 nothingToCommit 但 ok 仍 true),不影响判定。
|
|
297
|
+
*/
|
|
298
|
+
function computeOverallOk(pulled, pushed) {
|
|
299
|
+
if (pulled && !pulled.ok)
|
|
300
|
+
return false;
|
|
301
|
+
if (pushed && !pushed.ok && !pushed.skipped)
|
|
302
|
+
return false;
|
|
303
|
+
return true;
|
|
304
|
+
}
|
|
305
|
+
// ============================================================
|
|
306
|
+
// 注册
|
|
307
|
+
// ============================================================
|
|
308
|
+
export const ALL_SYNC_TOOLS = [engramSyncTool];
|
|
309
|
+
//# sourceMappingURL=sync-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-tools.js","sourceRoot":"","sources":["../../src/tools/sync-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* engram_synthesize 工具(Feature 1:手工触发 REM)
|
|
3
|
+
*
|
|
4
|
+
* 接受一组 engram id,调 LLM 综合形成 pattern engram,并对每个源 engram 创建
|
|
5
|
+
* `derives_from` synapse(pattern → source)。
|
|
6
|
+
*
|
|
7
|
+
* 与 REM dreaming 的关系:
|
|
8
|
+
* - REM 是自动聚类 + 启发式抽象,后台定时跑
|
|
9
|
+
* - 本工具是用户/agent 显式触发,语义层 LLM 抽象,精确度高
|
|
10
|
+
* - Feature 2 会把 REM dreaming 的 abstractionProvider 替换为同等 LLM 路径
|
|
11
|
+
*
|
|
12
|
+
* 与 proposal-engine 的区别:
|
|
13
|
+
* - proposal-engine 监听对话流自动累积 cluster → promotion
|
|
14
|
+
* - 本工具不依赖 proposal-engine,直接由调用方提供源 engram id 列表
|
|
15
|
+
*
|
|
16
|
+
* @module @co-engram/core/tools
|
|
17
|
+
*/
|
|
18
|
+
import type { Tool } from "./tool.js";
|
|
19
|
+
import { type EngramSynthesizeToolInput } from "./schemas.js";
|
|
20
|
+
/** LLM 综合产物(供 dry-run 返回 / 实际创建共用) */
|
|
21
|
+
export interface SynthesisDraft {
|
|
22
|
+
readonly title: string;
|
|
23
|
+
readonly content: string;
|
|
24
|
+
readonly summary: string;
|
|
25
|
+
readonly domainTags: readonly string[];
|
|
26
|
+
/** LLM 自评置信度 [0,1] */
|
|
27
|
+
readonly confidence: number;
|
|
28
|
+
/** LLM 给出的综合理由(展示给用户) */
|
|
29
|
+
readonly reason: string;
|
|
30
|
+
}
|
|
31
|
+
/** engram_synthesize 返回值 */
|
|
32
|
+
export interface EngramSynthesizeResult {
|
|
33
|
+
/** dry-run 时为 undefined */
|
|
34
|
+
readonly patternEngramId?: string;
|
|
35
|
+
/** dry-run 时为空数组 */
|
|
36
|
+
readonly synapseIds: readonly string[];
|
|
37
|
+
/** 综合的源 engram id(去重后) */
|
|
38
|
+
readonly sourceIds: readonly string[];
|
|
39
|
+
/** LLM 草拟的 title/content/summary(永远返回,供调用方审计/调试) */
|
|
40
|
+
readonly draft: SynthesisDraft;
|
|
41
|
+
/** dry-run 标志 */
|
|
42
|
+
readonly dryRun: boolean;
|
|
43
|
+
}
|
|
44
|
+
export declare const SYNTHESIS_PROMPT = "You are synthesizing a team memory pattern from a set of related engrams.\n\nA \"pattern\" is a higher-order insight that connects or abstracts multiple specific memories into a reusable lesson, principle, or design rationale. It should be more than a summary \u2014 it should reveal what these memories have in common at a level that will help future conversations.\n\nBelow are <SAMPLE_COUNT> source engrams:\n\n<SAMPLES_BLOCK>\n\n<HINTS_BLOCK>\n\nSynthesize them into ONE pattern. Return STRICT JSON only (no markdown, no prose) with this shape:\n\n{\n \"title\": \"<4-10 word pattern title, must NOT just copy any source title>\",\n \"summary\": \"<1-2 sentence plain-language summary of the pattern>\",\n \"content\": \"<full pattern body in markdown, 100-500 words; explain the insight, evidence from sources, and how to apply it>\",\n \"domainTags\": [\"<3-6 lowercase tags>\"],\n \"confidence\": <number 0..1 \u2014 how confident this is a real pattern vs cherry-picked coincidence>,\n \"reason\": \"<one sentence on why these sources support this pattern>\"\n}\n\n STRICT rules:\n 1. The pattern must be NON-TRIVIAL \u2014 if the sources are too unrelated, set confidence < 0.4 and explain why in reason.\n 2. Title must be different from every source title; reuse is a failure mode.\n 3. Content must reference specific details from sources (not generic platitudes).\n 4. domainTags should be the shared vocabulary across sources, not a union of all tags.\n 5. If any source is clearly off-topic from the others, exclude it mentally but list it in reason.";
|
|
45
|
+
/**
|
|
46
|
+
* 解析 LLM 综合输出
|
|
47
|
+
*
|
|
48
|
+
* 容忍 markdown fence / 前后 prose / 嵌套 JSON 等不规范输出。
|
|
49
|
+
* 返回 null 表示无法解析,调用方 fallback / 抛错。
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseSynthesisOutput(raw: string): SynthesisDraft | null;
|
|
52
|
+
interface SourceEngram {
|
|
53
|
+
readonly id: string;
|
|
54
|
+
readonly title: string;
|
|
55
|
+
readonly content: string;
|
|
56
|
+
readonly summary: string;
|
|
57
|
+
readonly domainTags: readonly string[];
|
|
58
|
+
}
|
|
59
|
+
/** 构造给 LLM 的样本块(共享:engram_synthesize 工具 + REM LlmPatternAbstraction) */
|
|
60
|
+
export declare function buildSamplesBlock(sources: readonly SourceEngram[]): string;
|
|
61
|
+
/**
|
|
62
|
+
* engram_synthesize 工具
|
|
63
|
+
*
|
|
64
|
+
* 输入:ids + 可选 createdBy/domainTags/synthesisHints/dryRun
|
|
65
|
+
* 输出:patternEngramId + synapseIds + sourceIds + draft
|
|
66
|
+
*
|
|
67
|
+
* 副作用:创建 pattern engram(kind=pattern, sourceType=inferred) +
|
|
68
|
+
* 对每个源创建 derives_from synapse + append audit。
|
|
69
|
+
*
|
|
70
|
+
* 失败模式:
|
|
71
|
+
* - ctx.llmClient 缺失 → 抛错带安装指引
|
|
72
|
+
* - 源 engram 部分不存在 → 抛错列出缺失的 id(不部分执行)
|
|
73
|
+
* - LLM 返回非 JSON → 抛错(不创建 engram,避免垃圾数据)
|
|
74
|
+
* - LLM 调用抛错 → 透传(由调用方决定重试 / fallback)
|
|
75
|
+
*/
|
|
76
|
+
export declare const engramSynthesizeTool: Tool<EngramSynthesizeToolInput, EngramSynthesizeResult>;
|
|
77
|
+
export declare const ALL_SYNTHESIZE_TOOLS: readonly Tool[];
|
|
78
|
+
export {};
|
|
79
|
+
//# sourceMappingURL=synthesize-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synthesize-tools.d.ts","sourceRoot":"","sources":["../../src/tools/synthesize-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAOH,OAAO,KAAK,EAAE,IAAI,EAAe,MAAM,WAAW,CAAC;AAEnD,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,cAAc,CAAC;AAMtB,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,sBAAsB;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,4BAA4B;AAC5B,MAAM,WAAW,sBAAsB;IACrC,2BAA2B;IAC3B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,oBAAoB;IACpB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,0BAA0B;IAC1B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,iBAAiB;IACjB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CAC1B;AAMD,eAAO,MAAM,gBAAgB,6iDA0BuE,CAAC;AAMrG;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAmEvE;AAMD,UAAU,YAAY;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC;AAmCD,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAiB1E;AAMD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,EAAE,IAAI,CACrC,yBAAyB,EACzB,sBAAsB,CAyKvB,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,SAAS,IAAI,EAA2B,CAAC"}
|