diff options
| author | soryu <soryu@soryu.co> | 2026-02-10 23:28:55 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-02-10 23:28:55 +0000 |
| commit | 284fdf2ffb186d0f1637dafd7655ee42dc36b942 (patch) | |
| tree | 970bd594097cd9e2956ad6f313efba23e57dbf4f | |
| parent | 339c1769379a851c4126021132573bd4b7994cf2 (diff) | |
| download | soryu-makima/makima--add-an-optional-memory-system-for-directiv-91523cbb.tar.gz soryu-makima/makima--add-an-optional-memory-system-for-directiv-91523cbb.zip | |
feat: makima: Add an optional memory system for directives: Add frontend API functions and types for directive memorymakima/makima--add-an-optional-memory-system-for-directiv-91523cbb
| -rw-r--r-- | makima/frontend/package-lock.json | 15 | ||||
| -rw-r--r-- | makima/frontend/src/lib/api.ts | 183 |
2 files changed, 184 insertions, 14 deletions
diff --git a/makima/frontend/package-lock.json b/makima/frontend/package-lock.json index 38adfc4..f1d54d6 100644 --- a/makima/frontend/package-lock.json +++ b/makima/frontend/package-lock.json @@ -55,7 +55,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -962,7 +961,6 @@ "resolved": "https://registry.npmjs.org/@react-router/dev/-/dev-7.11.0.tgz", "integrity": "sha512-g1ou5Zw3r4mCU0L+EXH4vRtAiyt8qz1JOvL1k+PW4rZ4+71h5nBy/fLgD7cg5BnzQZmjRO1PzCgpF5BIrlKYxQ==", "dev": true, - "peer": true, "dependencies": { "@babel/core": "^7.27.7", "@babel/generator": "^7.27.5", @@ -1894,7 +1892,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "devOptional": true, - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -2043,7 +2040,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2242,7 +2238,6 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -2937,7 +2932,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -3009,7 +3003,6 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3018,7 +3011,6 @@ "version": "19.2.3", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -3036,7 +3028,6 @@ "version": "9.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -3068,7 +3059,6 @@ "version": "7.11.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.11.0.tgz", "integrity": "sha512-uI4JkMmjbWCZc01WVP2cH7ZfSzH91JAZUDd7/nIprDgWxBV1TkkmLToFh7EbMTcMak8URFRa2YoBL/W8GWnCTQ==", - "peer": true, "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" @@ -3128,8 +3118,7 @@ "node_modules/redux": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", - "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", - "peer": true + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -3266,7 +3255,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3358,7 +3346,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts index b1422df..0f9a5ea 100644 --- a/makima/frontend/src/lib/api.ts +++ b/makima/frontend/src/lib/api.ts @@ -3020,6 +3020,8 @@ export interface Directive { localPath: string | null; baseBranch: string | null; orchestratorTaskId: string | null; + /** Whether the memory system is enabled for this directive */ + memoryEnabled: boolean; goalUpdatedAt: string; startedAt: string | null; version: number; @@ -3055,6 +3057,8 @@ export interface DirectiveSummary { status: DirectiveStatus; repositoryUrl: string | null; orchestratorTaskId: string | null; + /** Whether the memory system is enabled for this directive */ + memoryEnabled: boolean; version: number; createdAt: string; updatedAt: string; @@ -3075,6 +3079,8 @@ export interface CreateDirectiveRequest { repositoryUrl?: string; localPath?: string; baseBranch?: string; + /** Enable the memory system for this directive (default: false) */ + memoryEnabled?: boolean; } export interface UpdateDirectiveRequest { @@ -3085,6 +3091,8 @@ export interface UpdateDirectiveRequest { localPath?: string; baseBranch?: string; orchestratorTaskId?: string; + /** Enable or disable the memory system for this directive */ + memoryEnabled?: boolean; version?: number; } @@ -3225,4 +3233,179 @@ export async function updateDirectiveGoal(id: string, goal: string): Promise<Dir return res.json(); } +// ============================================================================= +// Directive Memory Types & API +// ============================================================================= + +/** Category of a directive memory entry */ +export type MemoryCategory = + | "decision" + | "learning" + | "context" + | "preference" + | "issue" + | "progress" + | "other"; + +/** A single memory entry associated with a directive */ +export interface DirectiveMemory { + id: string; + directiveId: string; + /** The memory content text */ + content: string; + /** Category for organizing memories */ + category: MemoryCategory; + /** Which step created this memory (null if directive-level) */ + stepId: string | null; + /** Which task created this memory (null if manually added) */ + taskId: string | null; + /** Importance score (1-10, higher = more important) */ + importance: number; + createdAt: string; + updatedAt: string; +} + +/** Response from listing directive memories */ +export interface DirectiveMemoryListResponse { + memories: DirectiveMemory[]; + total: number; +} + +/** Request to create a new directive memory */ +export interface CreateDirectiveMemoryRequest { + content: string; + category?: MemoryCategory; + stepId?: string; + taskId?: string; + importance?: number; +} + +/** Request to update a directive memory */ +export interface UpdateDirectiveMemoryRequest { + content?: string; + category?: MemoryCategory; + importance?: number; +} +// Directive Memory API functions + +/** + * List all memories for a directive. + * Optionally filter by category or step. + */ +export async function listDirectiveMemories( + directiveId: string, + params?: { category?: MemoryCategory; stepId?: string } +): Promise<DirectiveMemoryListResponse> { + const searchParams = new URLSearchParams(); + if (params?.category) searchParams.set("category", params.category); + if (params?.stepId) searchParams.set("stepId", params.stepId); + const query = searchParams.toString(); + const url = `${API_BASE}/api/v1/directives/${directiveId}/memories${query ? `?${query}` : ""}`; + const res = await authFetch(url); + if (!res.ok) throw new Error(`Failed to list directive memories: ${res.statusText}`); + return res.json(); +} + +/** + * Get a single memory entry by ID. + */ +export async function getDirectiveMemory( + directiveId: string, + memoryId: string +): Promise<DirectiveMemory> { + const res = await authFetch( + `${API_BASE}/api/v1/directives/${directiveId}/memories/${memoryId}` + ); + if (!res.ok) throw new Error(`Failed to get directive memory: ${res.statusText}`); + return res.json(); +} + +/** + * Create a new memory entry for a directive. + */ +export async function createDirectiveMemory( + directiveId: string, + req: CreateDirectiveMemoryRequest +): Promise<DirectiveMemory> { + const res = await authFetch(`${API_BASE}/api/v1/directives/${directiveId}/memories`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(req), + }); + if (!res.ok) throw new Error(`Failed to create directive memory: ${res.statusText}`); + return res.json(); +} + +/** + * Update an existing memory entry. + */ +export async function updateDirectiveMemory( + directiveId: string, + memoryId: string, + req: UpdateDirectiveMemoryRequest +): Promise<DirectiveMemory> { + const res = await authFetch( + `${API_BASE}/api/v1/directives/${directiveId}/memories/${memoryId}`, + { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(req), + } + ); + if (!res.ok) throw new Error(`Failed to update directive memory: ${res.statusText}`); + return res.json(); +} + +/** + * Delete a memory entry. + */ +export async function deleteDirectiveMemory( + directiveId: string, + memoryId: string +): Promise<void> { + const res = await authFetch( + `${API_BASE}/api/v1/directives/${directiveId}/memories/${memoryId}`, + { method: "DELETE" } + ); + if (!res.ok) throw new Error(`Failed to delete directive memory: ${res.statusText}`); +} + +/** + * Batch create multiple memory entries for a directive. + * Useful when a task completes and wants to store multiple learnings at once. + */ +export async function batchCreateDirectiveMemories( + directiveId: string, + memories: CreateDirectiveMemoryRequest[] +): Promise<DirectiveMemory[]> { + const res = await authFetch( + `${API_BASE}/api/v1/directives/${directiveId}/memories/batch`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(memories), + } + ); + if (!res.ok) throw new Error(`Failed to batch create directive memories: ${res.statusText}`); + return res.json(); +} + +/** + * Get a formatted memory context string for a directive. + * This returns memories formatted for injection into task prompts. + * Optionally filter by category or limit the number of memories returned. + */ +export async function getDirectiveMemoryContext( + directiveId: string, + params?: { category?: MemoryCategory; limit?: number } +): Promise<{ context: string; memoryCount: number }> { + const searchParams = new URLSearchParams(); + if (params?.category) searchParams.set("category", params.category); + if (params?.limit) searchParams.set("limit", params.limit.toString()); + const query = searchParams.toString(); + const url = `${API_BASE}/api/v1/directives/${directiveId}/memories/context${query ? `?${query}` : ""}`; + const res = await authFetch(url); + if (!res.ok) throw new Error(`Failed to get directive memory context: ${res.statusText}`); + return res.json(); +} |
