qlogicagent 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/README.md +45 -45
  2. package/package.json +56 -42
  3. package/dist/agent/agent.d.ts +0 -43
  4. package/dist/agent/agent.js +0 -113
  5. package/dist/agent/tool-loop.d.ts +0 -64
  6. package/dist/agent/tool-loop.js +0 -575
  7. package/dist/agent/types.d.ts +0 -175
  8. package/dist/agent/types.js +0 -14
  9. package/dist/cli/main.d.ts +0 -11
  10. package/dist/cli/main.js +0 -23
  11. package/dist/cli/stdio-server.d.ts +0 -45
  12. package/dist/cli/stdio-server.js +0 -463
  13. package/dist/config/config.d.ts +0 -17
  14. package/dist/config/config.js +0 -21
  15. package/dist/contracts/hooks.d.ts +0 -120
  16. package/dist/contracts/hooks.js +0 -7
  17. package/dist/contracts/index.d.ts +0 -10
  18. package/dist/contracts/index.js +0 -10
  19. package/dist/contracts/planner.d.ts +0 -35
  20. package/dist/contracts/planner.js +0 -2
  21. package/dist/contracts/skill-candidate.d.ts +0 -63
  22. package/dist/contracts/skill-candidate.js +0 -195
  23. package/dist/contracts/todo.d.ts +0 -14
  24. package/dist/contracts/todo.js +0 -9
  25. package/dist/index.d.ts +0 -13
  26. package/dist/index.js +0 -15
  27. package/dist/llm/builtin-providers.d.ts +0 -10
  28. package/dist/llm/builtin-providers.js +0 -531
  29. package/dist/llm/index.d.ts +0 -15
  30. package/dist/llm/index.js +0 -14
  31. package/dist/llm/llm-client.d.ts +0 -43
  32. package/dist/llm/llm-client.js +0 -67
  33. package/dist/llm/model-catalog.d.ts +0 -53
  34. package/dist/llm/model-catalog.js +0 -191
  35. package/dist/llm/provider-def.d.ts +0 -59
  36. package/dist/llm/provider-def.js +0 -12
  37. package/dist/llm/provider-registry.d.ts +0 -54
  38. package/dist/llm/provider-registry.js +0 -147
  39. package/dist/llm/transport.d.ts +0 -62
  40. package/dist/llm/transport.js +0 -27
  41. package/dist/llm/transports/anthropic-messages.d.ts +0 -31
  42. package/dist/llm/transports/anthropic-messages.js +0 -293
  43. package/dist/llm/transports/openai-chat.d.ts +0 -36
  44. package/dist/llm/transports/openai-chat.js +0 -165
  45. package/dist/orchestration/agent-registry.d.ts +0 -41
  46. package/dist/orchestration/agent-registry.js +0 -116
  47. package/dist/orchestration/approval-aware-tool-plan.d.ts +0 -32
  48. package/dist/orchestration/approval-aware-tool-plan.js +0 -87
  49. package/dist/orchestration/context-compression.d.ts +0 -220
  50. package/dist/orchestration/context-compression.js +0 -583
  51. package/dist/orchestration/conversation-repair.d.ts +0 -61
  52. package/dist/orchestration/conversation-repair.js +0 -429
  53. package/dist/orchestration/curator-scheduler.d.ts +0 -119
  54. package/dist/orchestration/curator-scheduler.js +0 -135
  55. package/dist/orchestration/embedded-failover-policy.d.ts +0 -110
  56. package/dist/orchestration/embedded-failover-policy.js +0 -168
  57. package/dist/orchestration/error-classification.d.ts +0 -12
  58. package/dist/orchestration/error-classification.js +0 -77
  59. package/dist/orchestration/failover-classification.d.ts +0 -8
  60. package/dist/orchestration/failover-classification.js +0 -381
  61. package/dist/orchestration/failover-error.d.ts +0 -33
  62. package/dist/orchestration/failover-error.js +0 -198
  63. package/dist/orchestration/fork-subagent.d.ts +0 -100
  64. package/dist/orchestration/fork-subagent.js +0 -98
  65. package/dist/orchestration/index.d.ts +0 -120
  66. package/dist/orchestration/index.js +0 -267
  67. package/dist/orchestration/memory-flush-policy.d.ts +0 -57
  68. package/dist/orchestration/memory-flush-policy.js +0 -85
  69. package/dist/orchestration/memory-provider.d.ts +0 -14
  70. package/dist/orchestration/memory-provider.js +0 -2
  71. package/dist/orchestration/parallel-tool-calls.d.ts +0 -41
  72. package/dist/orchestration/parallel-tool-calls.js +0 -59
  73. package/dist/orchestration/prompt-cache-strategy.d.ts +0 -126
  74. package/dist/orchestration/prompt-cache-strategy.js +0 -228
  75. package/dist/orchestration/reactive-compact.d.ts +0 -73
  76. package/dist/orchestration/reactive-compact.js +0 -78
  77. package/dist/orchestration/retry-loop.d.ts +0 -22
  78. package/dist/orchestration/retry-loop.js +0 -24
  79. package/dist/orchestration/skill-candidate.d.ts +0 -52
  80. package/dist/orchestration/skill-candidate.js +0 -141
  81. package/dist/orchestration/skill-consolidation.d.ts +0 -123
  82. package/dist/orchestration/skill-consolidation.js +0 -220
  83. package/dist/orchestration/skill-improvement.d.ts +0 -59
  84. package/dist/orchestration/skill-improvement.js +0 -66
  85. package/dist/orchestration/skill-similarity.d.ts +0 -98
  86. package/dist/orchestration/skill-similarity.js +0 -131
  87. package/dist/orchestration/streaming-tool-executor.d.ts +0 -73
  88. package/dist/orchestration/streaming-tool-executor.js +0 -96
  89. package/dist/orchestration/team-orchestration.d.ts +0 -195
  90. package/dist/orchestration/team-orchestration.js +0 -369
  91. package/dist/orchestration/team-tool-loop-wiring.d.ts +0 -92
  92. package/dist/orchestration/team-tool-loop-wiring.js +0 -147
  93. package/dist/orchestration/tool-choice-policy.d.ts +0 -54
  94. package/dist/orchestration/tool-choice-policy.js +0 -164
  95. package/dist/orchestration/tool-loop-state.d.ts +0 -50
  96. package/dist/orchestration/tool-loop-state.js +0 -133
  97. package/dist/orchestration/tool-schema.d.ts +0 -39
  98. package/dist/orchestration/tool-schema.js +0 -297
  99. package/dist/orchestration/transcript-repair.d.ts +0 -42
  100. package/dist/orchestration/transcript-repair.js +0 -426
  101. package/dist/orchestration/turn-loop-guard.d.ts +0 -86
  102. package/dist/orchestration/turn-loop-guard.js +0 -92
  103. package/dist/orchestration/web-browser-policy.d.ts +0 -17
  104. package/dist/orchestration/web-browser-policy.js +0 -39
  105. package/dist/runtime/context-compression.d.ts +0 -61
  106. package/dist/runtime/context-compression.js +0 -274
  107. package/dist/runtime/hook-registry.d.ts +0 -12
  108. package/dist/runtime/hook-registry.js +0 -53
  109. package/dist/runtime/memory-hooks.d.ts +0 -23
  110. package/dist/runtime/memory-hooks.js +0 -65
  111. package/dist/runtime/tool-eligibility.d.ts +0 -59
  112. package/dist/runtime/tool-eligibility.js +0 -111
  113. package/dist/skills/index.d.ts +0 -108
  114. package/dist/skills/index.js +0 -82
  115. package/dist/skills/memory-extractor.d.ts +0 -64
  116. package/dist/skills/memory-extractor.js +0 -173
  117. package/dist/skills/memory-query-tool.d.ts +0 -43
  118. package/dist/skills/memory-query-tool.js +0 -127
  119. package/dist/skills/memory-store.d.ts +0 -66
  120. package/dist/skills/memory-store.js +0 -228
  121. package/dist/skills/memory-tool.d.ts +0 -67
  122. package/dist/skills/memory-tool.js +0 -192
  123. package/dist/skills/portable-tool.d.ts +0 -71
  124. package/dist/skills/portable-tool.js +0 -14
  125. package/dist/skills/qmemory-adapter.d.ts +0 -52
  126. package/dist/skills/qmemory-adapter.js +0 -165
  127. package/dist/skills/skill-frontmatter.d.ts +0 -19
  128. package/dist/skills/skill-frontmatter.js +0 -344
  129. package/dist/skills/skill-guard.d.ts +0 -23
  130. package/dist/skills/skill-guard.js +0 -229
  131. package/dist/skills/skill-loader.d.ts +0 -16
  132. package/dist/skills/skill-loader.js +0 -303
  133. package/dist/skills/skill-source.d.ts +0 -119
  134. package/dist/skills/skill-source.js +0 -126
  135. package/dist/skills/skill-types.d.ts +0 -199
  136. package/dist/skills/skill-types.js +0 -6
  137. package/dist/skills/think-tool.d.ts +0 -16
  138. package/dist/skills/think-tool.js +0 -59
  139. package/dist/skills/todo-tool.d.ts +0 -63
  140. package/dist/skills/todo-tool.js +0 -114
  141. package/dist/skills/tools/agent-tool.d.ts +0 -91
  142. package/dist/skills/tools/agent-tool.js +0 -142
  143. package/dist/skills/tools/apply-patch-tool.d.ts +0 -29
  144. package/dist/skills/tools/apply-patch-tool.js +0 -184
  145. package/dist/skills/tools/ask-user-tool.d.ts +0 -80
  146. package/dist/skills/tools/ask-user-tool.js +0 -121
  147. package/dist/skills/tools/brief-tool.d.ts +0 -74
  148. package/dist/skills/tools/brief-tool.js +0 -95
  149. package/dist/skills/tools/browser-tool.d.ts +0 -114
  150. package/dist/skills/tools/browser-tool.js +0 -155
  151. package/dist/skills/tools/checkpoint-tool.d.ts +0 -66
  152. package/dist/skills/tools/checkpoint-tool.js +0 -102
  153. package/dist/skills/tools/config-tool.d.ts +0 -63
  154. package/dist/skills/tools/config-tool.js +0 -143
  155. package/dist/skills/tools/cron-tool.d.ts +0 -116
  156. package/dist/skills/tools/cron-tool.js +0 -175
  157. package/dist/skills/tools/edit-tool.d.ts +0 -43
  158. package/dist/skills/tools/edit-tool.js +0 -70
  159. package/dist/skills/tools/exec-tool.d.ts +0 -102
  160. package/dist/skills/tools/exec-tool.js +0 -133
  161. package/dist/skills/tools/image-generate-tool.d.ts +0 -62
  162. package/dist/skills/tools/image-generate-tool.js +0 -67
  163. package/dist/skills/tools/instructions-tool.d.ts +0 -103
  164. package/dist/skills/tools/instructions-tool.js +0 -187
  165. package/dist/skills/tools/lsp-tool.d.ts +0 -153
  166. package/dist/skills/tools/lsp-tool.js +0 -227
  167. package/dist/skills/tools/mcp-client-types.d.ts +0 -269
  168. package/dist/skills/tools/mcp-client-types.js +0 -53
  169. package/dist/skills/tools/mcp-tool.d.ts +0 -249
  170. package/dist/skills/tools/mcp-tool.js +0 -503
  171. package/dist/skills/tools/memory-tool.d.ts +0 -74
  172. package/dist/skills/tools/memory-tool.js +0 -88
  173. package/dist/skills/tools/monitor-tool.d.ts +0 -113
  174. package/dist/skills/tools/monitor-tool.js +0 -131
  175. package/dist/skills/tools/music-generate-tool.d.ts +0 -55
  176. package/dist/skills/tools/music-generate-tool.js +0 -62
  177. package/dist/skills/tools/notify-tool.d.ts +0 -53
  178. package/dist/skills/tools/notify-tool.js +0 -62
  179. package/dist/skills/tools/patch-tool.d.ts +0 -45
  180. package/dist/skills/tools/patch-tool.js +0 -505
  181. package/dist/skills/tools/pdf-tool.d.ts +0 -66
  182. package/dist/skills/tools/pdf-tool.js +0 -88
  183. package/dist/skills/tools/plan-mode-tool.d.ts +0 -59
  184. package/dist/skills/tools/plan-mode-tool.js +0 -122
  185. package/dist/skills/tools/read-tool.d.ts +0 -51
  186. package/dist/skills/tools/read-tool.js +0 -84
  187. package/dist/skills/tools/repl-tool.d.ts +0 -70
  188. package/dist/skills/tools/repl-tool.js +0 -69
  189. package/dist/skills/tools/search-tool.d.ts +0 -112
  190. package/dist/skills/tools/search-tool.js +0 -225
  191. package/dist/skills/tools/send-message-tool.d.ts +0 -51
  192. package/dist/skills/tools/send-message-tool.js +0 -76
  193. package/dist/skills/tools/skill-list-tool.d.ts +0 -33
  194. package/dist/skills/tools/skill-list-tool.js +0 -54
  195. package/dist/skills/tools/skill-manage-tool.d.ts +0 -73
  196. package/dist/skills/tools/skill-manage-tool.js +0 -153
  197. package/dist/skills/tools/skill-view-tool.d.ts +0 -37
  198. package/dist/skills/tools/skill-view-tool.js +0 -72
  199. package/dist/skills/tools/sleep-tool.d.ts +0 -49
  200. package/dist/skills/tools/sleep-tool.js +0 -81
  201. package/dist/skills/tools/structured-output-tool.d.ts +0 -116
  202. package/dist/skills/tools/structured-output-tool.js +0 -176
  203. package/dist/skills/tools/task-tool.d.ts +0 -104
  204. package/dist/skills/tools/task-tool.js +0 -161
  205. package/dist/skills/tools/team-tool.d.ts +0 -89
  206. package/dist/skills/tools/team-tool.js +0 -105
  207. package/dist/skills/tools/tool-search-tool.d.ts +0 -51
  208. package/dist/skills/tools/tool-search-tool.js +0 -110
  209. package/dist/skills/tools/tts-tool.d.ts +0 -38
  210. package/dist/skills/tools/tts-tool.js +0 -45
  211. package/dist/skills/tools/video-edit-tool.d.ts +0 -69
  212. package/dist/skills/tools/video-edit-tool.js +0 -74
  213. package/dist/skills/tools/video-generate-tool.d.ts +0 -62
  214. package/dist/skills/tools/video-generate-tool.js +0 -66
  215. package/dist/skills/tools/video-merge-tool.d.ts +0 -105
  216. package/dist/skills/tools/video-merge-tool.js +0 -92
  217. package/dist/skills/tools/video-upscale-tool.d.ts +0 -45
  218. package/dist/skills/tools/video-upscale-tool.js +0 -52
  219. package/dist/skills/tools/web-fetch-tool.d.ts +0 -78
  220. package/dist/skills/tools/web-fetch-tool.js +0 -92
  221. package/dist/skills/tools/web-search-tool.d.ts +0 -57
  222. package/dist/skills/tools/web-search-tool.js +0 -86
  223. package/dist/skills/tools/worktree-tool.d.ts +0 -69
  224. package/dist/skills/tools/worktree-tool.js +0 -147
  225. package/dist/skills/tools/write-tool.d.ts +0 -45
  226. package/dist/skills/tools/write-tool.js +0 -81
@@ -1,66 +0,0 @@
1
- export declare const MEMORY_ENTRY_DELIMITER = "\n\u00A7\n";
2
- export declare const DEFAULT_MEMORY_CHAR_LIMIT = 2200;
3
- export declare const DEFAULT_USER_CHAR_LIMIT = 1375;
4
- export type MemoryStoreTarget = "memory" | "user";
5
- export interface MemoryStoreResult {
6
- ok: boolean;
7
- message: string;
8
- target: MemoryStoreTarget;
9
- entries: readonly string[];
10
- entryCount: number;
11
- usage: string;
12
- errorCode?: string;
13
- }
14
- export interface MemoryStoreOptions {
15
- memoryCharLimit?: number;
16
- userCharLimit?: number;
17
- }
18
- export interface MemoryStoreSerialized {
19
- memory: string;
20
- user: string;
21
- }
22
- export declare class MemoryStore {
23
- private memoryEntries;
24
- private userEntries;
25
- private frozenSnapshot;
26
- private snapshotFrozen;
27
- private readonly memoryCharLimit;
28
- private readonly userCharLimit;
29
- constructor(options?: MemoryStoreOptions);
30
- /**
31
- * Load from serialized form (e.g. from PG or filesystem).
32
- * Deduplicates entries on load.
33
- */
34
- loadFromSerialized(data: Partial<MemoryStoreSerialized>): void;
35
- /**
36
- * Serialize current live state for persistence.
37
- */
38
- serialize(): MemoryStoreSerialized;
39
- /**
40
- * Freeze current entries for system prompt injection.
41
- * Call once at session start. After freezing, mutations update
42
- * live state but NOT the system prompt block.
43
- */
44
- freezeSnapshot(): void;
45
- /**
46
- * Get frozen system prompt block for the given target.
47
- * Returns empty string if no entries or not yet frozen.
48
- */
49
- getSystemPromptBlock(target: MemoryStoreTarget): string;
50
- add(target: MemoryStoreTarget, content: string): MemoryStoreResult;
51
- replace(target: MemoryStoreTarget, oldText: string, newContent: string): MemoryStoreResult;
52
- remove(target: MemoryStoreTarget, oldText: string): MemoryStoreResult;
53
- getEntries(target: MemoryStoreTarget): readonly string[];
54
- getUsage(target: MemoryStoreTarget): {
55
- used: number;
56
- limit: number;
57
- percent: number;
58
- };
59
- isEmpty(): boolean;
60
- private entriesFor;
61
- private charLimitFor;
62
- private formatUsage;
63
- private renderBlock;
64
- private successResult;
65
- private errorResult;
66
- }
@@ -1,228 +0,0 @@
1
- // ============================================================
2
- // Memory Store — character-bounded local memory for agent notes.
3
- //
4
- // Inspired by Hermes' MemoryStore design:
5
- // - Two targets: "memory" (agent notes) + "user" (user profile)
6
- // - § delimiter between entries
7
- // - Frozen snapshot for system prompt (KV cache stability)
8
- // - Exact duplicate rejection
9
- // - Content safety scanning
10
- // - Pure in-memory; persistence is the consumer's responsibility.
11
- // ============================================================
12
- import { isMemoryContentSafe } from "./memory-tool.js";
13
- // ── Constants ───────────────────────────────────────────────
14
- export const MEMORY_ENTRY_DELIMITER = "\n§\n";
15
- export const DEFAULT_MEMORY_CHAR_LIMIT = 2200;
16
- export const DEFAULT_USER_CHAR_LIMIT = 1375;
17
- // ── MemoryStore class ───────────────────────────────────────
18
- export class MemoryStore {
19
- memoryEntries = [];
20
- userEntries = [];
21
- frozenSnapshot = { memory: "", user: "" };
22
- snapshotFrozen = false;
23
- memoryCharLimit;
24
- userCharLimit;
25
- constructor(options) {
26
- this.memoryCharLimit = options?.memoryCharLimit ?? DEFAULT_MEMORY_CHAR_LIMIT;
27
- this.userCharLimit = options?.userCharLimit ?? DEFAULT_USER_CHAR_LIMIT;
28
- }
29
- // ── Load / Serialize ────────────────────────────────────
30
- /**
31
- * Load from serialized form (e.g. from PG or filesystem).
32
- * Deduplicates entries on load.
33
- */
34
- loadFromSerialized(data) {
35
- this.memoryEntries = deduplicateEntries(parseEntries(data.memory ?? ""));
36
- this.userEntries = deduplicateEntries(parseEntries(data.user ?? ""));
37
- }
38
- /**
39
- * Serialize current live state for persistence.
40
- */
41
- serialize() {
42
- return {
43
- memory: this.memoryEntries.join(MEMORY_ENTRY_DELIMITER),
44
- user: this.userEntries.join(MEMORY_ENTRY_DELIMITER),
45
- };
46
- }
47
- // ── Snapshot (frozen for system prompt) ─────────────────
48
- /**
49
- * Freeze current entries for system prompt injection.
50
- * Call once at session start. After freezing, mutations update
51
- * live state but NOT the system prompt block.
52
- */
53
- freezeSnapshot() {
54
- this.frozenSnapshot = {
55
- memory: this.renderBlock("memory", this.memoryEntries),
56
- user: this.renderBlock("user", this.userEntries),
57
- };
58
- this.snapshotFrozen = true;
59
- }
60
- /**
61
- * Get frozen system prompt block for the given target.
62
- * Returns empty string if no entries or not yet frozen.
63
- */
64
- getSystemPromptBlock(target) {
65
- if (!this.snapshotFrozen) {
66
- // Auto-freeze on first access
67
- this.freezeSnapshot();
68
- }
69
- return this.frozenSnapshot[target];
70
- }
71
- // ── Mutations ───────────────────────────────────────────
72
- add(target, content) {
73
- const trimmed = content.trim();
74
- if (!trimmed) {
75
- return this.errorResult(target, "Content cannot be empty.", "empty_content");
76
- }
77
- if (!isMemoryContentSafe(trimmed)) {
78
- return this.errorResult(target, "Content rejected: potential injection detected.", "unsafe_content");
79
- }
80
- const entries = this.entriesFor(target);
81
- // Exact duplicate check
82
- if (entries.includes(trimmed)) {
83
- return this.successResult(target, "Entry already exists (no change).");
84
- }
85
- // Character budget check
86
- const newEntries = [...entries, trimmed];
87
- const newTotal = newEntries.join(MEMORY_ENTRY_DELIMITER).length;
88
- if (newTotal > this.charLimitFor(target)) {
89
- const usage = this.formatUsage(target);
90
- return this.errorResult(target, `Memory full (${usage}). Remove old entries first.`, "over_limit");
91
- }
92
- entries.push(trimmed);
93
- return this.successResult(target, "Entry added.");
94
- }
95
- replace(target, oldText, newContent) {
96
- const searchText = oldText.trim();
97
- const replacement = newContent.trim();
98
- if (!searchText) {
99
- return this.errorResult(target, "old_text cannot be empty.", "empty_old_text");
100
- }
101
- if (!replacement) {
102
- return this.errorResult(target, "content cannot be empty.", "empty_content");
103
- }
104
- if (!isMemoryContentSafe(replacement)) {
105
- return this.errorResult(target, "Content rejected: potential injection detected.", "unsafe_content");
106
- }
107
- const entries = this.entriesFor(target);
108
- const matchIndices = entries
109
- .map((entry, i) => entry.includes(searchText) ? i : -1)
110
- .filter((i) => i >= 0);
111
- if (matchIndices.length === 0) {
112
- return this.errorResult(target, `No entry contains: "${clipForMessage(searchText)}"`, "not_found");
113
- }
114
- if (matchIndices.length > 1) {
115
- // Check if all matches are identical (harmless duplicate)
116
- const unique = new Set(matchIndices.map((i) => entries[i]));
117
- if (unique.size > 1) {
118
- return this.errorResult(target, `Multiple entries match: "${clipForMessage(searchText)}" (${matchIndices.length} matches). Be more specific.`, "ambiguous_match");
119
- }
120
- }
121
- // Replace first match
122
- const matchIndex = matchIndices[0];
123
- // Check char limit with replacement
124
- const projected = [...entries];
125
- projected[matchIndex] = replacement;
126
- const projectedTotal = projected.join(MEMORY_ENTRY_DELIMITER).length;
127
- if (projectedTotal > this.charLimitFor(target)) {
128
- const usage = this.formatUsage(target);
129
- return this.errorResult(target, `Replacement would exceed limit (${usage}).`, "over_limit");
130
- }
131
- entries[matchIndex] = replacement;
132
- return this.successResult(target, "Entry replaced.");
133
- }
134
- remove(target, oldText) {
135
- const searchText = oldText.trim();
136
- if (!searchText) {
137
- return this.errorResult(target, "old_text cannot be empty.", "empty_old_text");
138
- }
139
- const entries = this.entriesFor(target);
140
- const matchIndices = entries
141
- .map((entry, i) => entry.includes(searchText) ? i : -1)
142
- .filter((i) => i >= 0);
143
- if (matchIndices.length === 0) {
144
- return this.errorResult(target, `No entry contains: "${clipForMessage(searchText)}"`, "not_found");
145
- }
146
- // Remove all matches (safe: if they all contain the substring, remove them all)
147
- for (let i = matchIndices.length - 1; i >= 0; i--) {
148
- entries.splice(matchIndices[i], 1);
149
- }
150
- return this.successResult(target, matchIndices.length === 1 ? "Entry removed." : `${matchIndices.length} entries removed.`);
151
- }
152
- // ── Read-only accessors ─────────────────────────────────
153
- getEntries(target) {
154
- return this.entriesFor(target);
155
- }
156
- getUsage(target) {
157
- const entries = this.entriesFor(target);
158
- const used = entries.length > 0 ? entries.join(MEMORY_ENTRY_DELIMITER).length : 0;
159
- const limit = this.charLimitFor(target);
160
- return { used, limit, percent: limit > 0 ? Math.round((used / limit) * 100) : 0 };
161
- }
162
- isEmpty() {
163
- return this.memoryEntries.length === 0 && this.userEntries.length === 0;
164
- }
165
- // ── Private helpers ─────────────────────────────────────
166
- entriesFor(target) {
167
- return target === "user" ? this.userEntries : this.memoryEntries;
168
- }
169
- charLimitFor(target) {
170
- return target === "user" ? this.userCharLimit : this.memoryCharLimit;
171
- }
172
- formatUsage(target) {
173
- const { used, limit, percent } = this.getUsage(target);
174
- return `${percent}% — ${used}/${limit} chars`;
175
- }
176
- renderBlock(target, entries) {
177
- if (entries.length === 0)
178
- return "";
179
- const label = target === "user" ? "USER PROFILE" : "MEMORY";
180
- const usage = this.formatUsage(target);
181
- const divider = "══════════════════════════════════════════════════════════";
182
- const body = entries.join(MEMORY_ENTRY_DELIMITER);
183
- return `${divider}\n${label} (your personal notes) [${usage}]\n${divider}\n${body}`;
184
- }
185
- successResult(target, message) {
186
- const entries = this.entriesFor(target);
187
- return {
188
- ok: true,
189
- message,
190
- target,
191
- entries,
192
- entryCount: entries.length,
193
- usage: this.formatUsage(target),
194
- };
195
- }
196
- errorResult(target, message, errorCode) {
197
- const entries = this.entriesFor(target);
198
- return {
199
- ok: false,
200
- message,
201
- target,
202
- entries,
203
- entryCount: entries.length,
204
- usage: this.formatUsage(target),
205
- errorCode,
206
- };
207
- }
208
- }
209
- // ── Utilities ─────────────────────────────────────────────
210
- function parseEntries(raw) {
211
- if (!raw.trim())
212
- return [];
213
- return raw.split(MEMORY_ENTRY_DELIMITER).map((e) => e.trim()).filter(Boolean);
214
- }
215
- function deduplicateEntries(entries) {
216
- const seen = new Set();
217
- return entries.filter((entry) => {
218
- if (seen.has(entry))
219
- return false;
220
- seen.add(entry);
221
- return true;
222
- });
223
- }
224
- function clipForMessage(text, maxLength = 60) {
225
- if (text.length <= maxLength)
226
- return text;
227
- return `${text.slice(0, maxLength - 1).trimEnd()}…`;
228
- }
@@ -1,67 +0,0 @@
1
- import type { MemoryProvider, MemorySearchResult } from "qlogicagent-runtime-contracts";
2
- import type { MemoryStore, MemoryStoreTarget } from "./memory-store.js";
3
- export declare const MEMORY_TOOL_NAME: "memory";
4
- export declare const MEMORY_TOOL_MAX_CONTENT_LENGTH = 2000;
5
- export declare const MEMORY_TOOL_ACTIONS: readonly ["add", "replace", "remove", "search"];
6
- export type MemoryToolAction = (typeof MEMORY_TOOL_ACTIONS)[number];
7
- export declare const MEMORY_TOOL_SCHEMA: {
8
- readonly type: "object";
9
- readonly properties: {
10
- readonly action: {
11
- readonly type: "string";
12
- readonly enum: string[];
13
- readonly description: string;
14
- };
15
- readonly target: {
16
- readonly type: "string";
17
- readonly enum: readonly ["memory", "user"];
18
- readonly description: string;
19
- };
20
- readonly content: {
21
- readonly type: "string";
22
- readonly description: string;
23
- };
24
- readonly old_text: {
25
- readonly type: "string";
26
- readonly description: "Required for 'replace' and 'remove'. A substring that uniquely identifies the note entry to modify.";
27
- };
28
- readonly query: {
29
- readonly type: "string";
30
- readonly description: "Required for 'search'. Natural language query to find relevant memories.";
31
- };
32
- };
33
- readonly required: readonly ["action"];
34
- };
35
- export declare const MEMORY_TOOL_DESCRIPTION: string;
36
- export declare const MEMORY_TOOL_LABEL = "Memory";
37
- export declare function isMemoryContentSafe(text: string): boolean;
38
- export interface MemoryToolParams {
39
- action: MemoryToolAction;
40
- target?: MemoryStoreTarget;
41
- content?: string;
42
- old_text?: string;
43
- query?: string;
44
- }
45
- export interface MemoryToolResult {
46
- ok: boolean;
47
- message: string;
48
- action: string;
49
- /** For MD store operations: live entry count */
50
- entryCount?: number;
51
- /** For MD store operations: usage string */
52
- usage?: string;
53
- /** For search: qmemory results */
54
- results?: MemorySearchResult[];
55
- /** Indicates MD store was mutated (consumer should persist) */
56
- storeModified?: boolean;
57
- errorCode?: string;
58
- }
59
- export interface MemoryToolExecutorDeps {
60
- /** QMemory provider for semantic search. */
61
- provider: MemoryProvider;
62
- /** Local MD memory store for notes. */
63
- store?: MemoryStore;
64
- userId: string;
65
- sessionId?: string;
66
- }
67
- export declare function executeMemoryTool(params: MemoryToolParams, deps: MemoryToolExecutorDeps): Promise<MemoryToolResult>;
@@ -1,192 +0,0 @@
1
- // ============================================================
2
- // Memory Tool Contract — dual-layer agent memory system.
3
- //
4
- // Two independent layers (Hermes-inspired):
5
- //
6
- // 1. **MD Memory** (local notes, always in system prompt):
7
- // Agent explicitly manages via add / replace / remove.
8
- // Character-bounded, no LLM needed, zero-cost.
9
- // Frozen snapshot in system prompt for KV cache stability.
10
- //
11
- // 2. **QMemory** (semantic long-term memory):
12
- // Automatic extraction from every conversation turn.
13
- // Agent queries via search action. Vector-based recall.
14
- //
15
- // The two layers are independent — no cross-dedup, no sync.
16
- // MD = curated highlights; QMemory = conversation sediment.
17
- // ============================================================
18
- // ── Constants ───────────────────────────────────────────────────
19
- export const MEMORY_TOOL_NAME = "memory";
20
- export const MEMORY_TOOL_MAX_CONTENT_LENGTH = 2000;
21
- export const MEMORY_TOOL_ACTIONS = ["add", "replace", "remove", "search"];
22
- // ── Tool schema (JSON Schema compatible) ────────────────────
23
- export const MEMORY_TOOL_SCHEMA = {
24
- type: "object",
25
- properties: {
26
- action: {
27
- type: "string",
28
- enum: MEMORY_TOOL_ACTIONS,
29
- description: [
30
- "The operation to perform:",
31
- "• 'add' — Save a concise note about this user (→ local notes, always visible)",
32
- "• 'replace' — Update an existing note by matching a substring (→ local notes)",
33
- "• 'remove' — Delete a note by matching a substring (→ local notes)",
34
- "• 'search' — Semantic search across long-term memory (→ qmemory)",
35
- ].join("\n"),
36
- },
37
- target: {
38
- type: "string",
39
- enum: ["memory", "user"],
40
- description: [
41
- "Which note target to operate on (for add/replace/remove):",
42
- "• 'memory' — Your personal observations/notes about this user (default)",
43
- "• 'user' — User profile facts (preferences, timezone, etc.)",
44
- ].join("\n"),
45
- },
46
- content: {
47
- type: "string",
48
- description: [
49
- "Required for 'add' and 'replace'. The note content to store.",
50
- "Write a concise, factual statement.",
51
- "Good: '用户是后端工程师,主要使用 TypeScript 和 Go'",
52
- "Good: 'User prefers dark UI themes and minimalist design'",
53
- "Bad: '用户说了很多话' (too vague)",
54
- "Bad: entire conversation transcripts (too long)",
55
- ].join("\n"),
56
- },
57
- old_text: {
58
- type: "string",
59
- description: "Required for 'replace' and 'remove'. A substring that uniquely identifies the note entry to modify.",
60
- },
61
- query: {
62
- type: "string",
63
- description: "Required for 'search'. Natural language query to find relevant memories.",
64
- },
65
- },
66
- required: ["action"],
67
- };
68
- export const MEMORY_TOOL_DESCRIPTION = [
69
- "Manage your notes about this user and search long-term memory.",
70
- "",
71
- "Your notes (add/replace/remove) are always visible in the system prompt.",
72
- "Long-term memories are automatically extracted from every conversation",
73
- "and searchable via 'search'.",
74
- "",
75
- "Guidelines:",
76
- "- Use 'add' to record important user preferences, facts, or context",
77
- "- Use 'replace' to update outdated notes (match by substring)",
78
- "- Use 'remove' to delete incorrect notes (match by substring)",
79
- "- Use 'search' to recall conversation history and past interactions",
80
- "- Keep notes concise — there's a character limit",
81
- ].join("\n");
82
- export const MEMORY_TOOL_LABEL = "Memory";
83
- // ── Content safety ──────────────────────────────────────────
84
- const BLOCKED_PATTERNS = [
85
- /ignore\s+(previous|all|above|prior)\s+instructions/i,
86
- /you\s+are\s+now\s+/i,
87
- /do\s+not\s+tell\s+the\s+user/i,
88
- /system\s+prompt\s+override/i,
89
- ];
90
- export function isMemoryContentSafe(text) {
91
- return !BLOCKED_PATTERNS.some((pattern) => pattern.test(text));
92
- }
93
- export async function executeMemoryTool(params, deps) {
94
- const { action } = params;
95
- const target = params.target ?? "memory";
96
- // ── MD store operations: add / replace / remove ───────
97
- if (action === "add") {
98
- if (!deps.store) {
99
- return { ok: false, message: "Local memory store is not available.", action, errorCode: "no_store" };
100
- }
101
- const content = params.content?.trim();
102
- if (!content) {
103
- return { ok: false, message: "content is required for 'add' action.", action, errorCode: "empty_content" };
104
- }
105
- if (content.length > MEMORY_TOOL_MAX_CONTENT_LENGTH) {
106
- return { ok: false, message: `Content too long (${content.length} chars, max ${MEMORY_TOOL_MAX_CONTENT_LENGTH}).`, action, errorCode: "too_long" };
107
- }
108
- const result = deps.store.add(target, content);
109
- return {
110
- ok: result.ok,
111
- message: result.ok
112
- ? `${result.message} [${result.usage}]`
113
- : result.message,
114
- action,
115
- entryCount: result.entryCount,
116
- usage: result.usage,
117
- storeModified: result.ok,
118
- errorCode: result.errorCode,
119
- };
120
- }
121
- if (action === "replace") {
122
- if (!deps.store) {
123
- return { ok: false, message: "Local memory store is not available.", action, errorCode: "no_store" };
124
- }
125
- const oldText = params.old_text?.trim();
126
- const content = params.content?.trim();
127
- if (!oldText) {
128
- return { ok: false, message: "old_text is required for 'replace' action.", action, errorCode: "empty_old_text" };
129
- }
130
- if (!content) {
131
- return { ok: false, message: "content is required for 'replace' action.", action, errorCode: "empty_content" };
132
- }
133
- if (content.length > MEMORY_TOOL_MAX_CONTENT_LENGTH) {
134
- return { ok: false, message: `Content too long (${content.length} chars, max ${MEMORY_TOOL_MAX_CONTENT_LENGTH}).`, action, errorCode: "too_long" };
135
- }
136
- const result = deps.store.replace(target, oldText, content);
137
- return {
138
- ok: result.ok,
139
- message: result.ok
140
- ? `${result.message} [${result.usage}]`
141
- : result.message,
142
- action,
143
- entryCount: result.entryCount,
144
- usage: result.usage,
145
- storeModified: result.ok,
146
- errorCode: result.errorCode,
147
- };
148
- }
149
- if (action === "remove") {
150
- if (!deps.store) {
151
- return { ok: false, message: "Local memory store is not available.", action, errorCode: "no_store" };
152
- }
153
- const oldText = params.old_text?.trim();
154
- if (!oldText) {
155
- return { ok: false, message: "old_text is required for 'remove' action.", action, errorCode: "empty_old_text" };
156
- }
157
- const result = deps.store.remove(target, oldText);
158
- return {
159
- ok: result.ok,
160
- message: result.ok
161
- ? `${result.message} [${result.usage}]`
162
- : result.message,
163
- action,
164
- entryCount: result.entryCount,
165
- usage: result.usage,
166
- storeModified: result.ok,
167
- errorCode: result.errorCode,
168
- };
169
- }
170
- if (action === "search") {
171
- const query = params.query?.trim();
172
- if (!query) {
173
- return { ok: false, message: "query is required for 'search' action.", action, errorCode: "empty_query" };
174
- }
175
- try {
176
- const results = await deps.provider.search(query, deps.userId, { limit: 10 });
177
- if (results.length === 0) {
178
- return { ok: true, message: "No matching memories found.", action, results: [] };
179
- }
180
- return {
181
- ok: true,
182
- message: results.map((r, i) => `${i + 1}. [${r.blockId}] ${r.text}`).join("\n"),
183
- action,
184
- results,
185
- };
186
- }
187
- catch (error) {
188
- return { ok: false, message: `Search failed: ${error instanceof Error ? error.message : String(error)}`, action, errorCode: "search_failed" };
189
- }
190
- }
191
- return { ok: false, message: `Unknown action: ${action}. Use 'add', 'replace', 'remove', or 'search'.`, action, errorCode: "unknown_action" };
192
- }
@@ -1,71 +0,0 @@
1
- /**
2
- * Content block returned by tool execution.
3
- * Compatible with OpenAI / Anthropic content array format.
4
- */
5
- export interface ToolContentBlock {
6
- type: "text" | "image";
7
- text?: string;
8
- /** base64-encoded image data (only when type === "image") */
9
- data?: string;
10
- mimeType?: string;
11
- }
12
- /**
13
- * Result of executing a portable tool.
14
- */
15
- export interface PortableToolResult {
16
- content: ToolContentBlock[];
17
- /** Arbitrary structured metadata for the calling runtime. */
18
- details?: Record<string, unknown>;
19
- }
20
- /**
21
- * A runtime-agnostic tool definition.
22
- *
23
- * @typeParam TParams The expected parameter shape (for TypeScript consumers).
24
- */
25
- export interface PortableTool<TParams = Record<string, unknown>> {
26
- /** Unique tool name (e.g. "think", "todo", "memory_query"). */
27
- name: string;
28
- /** Human-readable label. */
29
- label: string;
30
- /** Tool description shown to the LLM. */
31
- description: string;
32
- /** JSON Schema object describing the tool's parameters. */
33
- parameters: Record<string, unknown>;
34
- /**
35
- * When true, the tool should NOT appear in the default tool list.
36
- * The host injects it only for complex tasks (e.g. multi-step reasoning)
37
- * or when explicitly activated via tool_search.
38
- * This saves context tokens in simple conversations.
39
- */
40
- shouldDefer?: boolean;
41
- /**
42
- * Whether the tool can safely run concurrently with other tools.
43
- * When true, the runtime may execute this tool in parallel with others.
44
- * Default: false (sequential execution assumed).
45
- */
46
- isConcurrencySafe?: boolean;
47
- /**
48
- * Whether the tool only reads state and never mutates anything.
49
- * Read-only tools can skip confirmation prompts in strict permission modes.
50
- */
51
- isReadOnly?: boolean;
52
- /**
53
- * Brief keyword hint for tool_search to match against
54
- * (e.g. "return the final response as structured JSON").
55
- */
56
- searchHint?: string;
57
- /**
58
- * Maximum allowed content size in characters for the tool result.
59
- * The runtime should truncate/reject results exceeding this.
60
- */
61
- maxResultSizeChars?: number;
62
- /**
63
- * Execute the tool.
64
- *
65
- * @param toolCallId - Unique ID for this tool invocation (for tracing).
66
- * @param params - Parsed parameters matching the JSON Schema.
67
- * @param signal - Optional abort signal.
68
- * @returns Tool result with content blocks + optional details.
69
- */
70
- execute(toolCallId: string, params: TParams, signal?: AbortSignal): Promise<PortableToolResult>;
71
- }
@@ -1,14 +0,0 @@
1
- // ============================================================
2
- // Portable Tool Contract — runtime-agnostic tool interface.
3
- //
4
- // This is the minimal tool definition that any agent runtime
5
- // (openclaw, Hub, Electron, third-party) can consume. It uses
6
- // plain JSON Schema objects instead of @sinclair/typebox so
7
- // there are zero external dependencies.
8
- //
9
- // Consumers wrap PortableTool into their own tool system:
10
- // - openclaw → AgentTool<TSchema> (via typebox adapter)
11
- // - Hub → hub-managed tool registration
12
- // - Electron → desktop tool host
13
- // ============================================================
14
- export {};