summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-02-10 23:28:55 +0000
committersoryu <soryu@soryu.co>2026-02-10 23:28:55 +0000
commit284fdf2ffb186d0f1637dafd7655ee42dc36b942 (patch)
tree970bd594097cd9e2956ad6f313efba23e57dbf4f
parent339c1769379a851c4126021132573bd4b7994cf2 (diff)
downloadsoryu-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.json15
-rw-r--r--makima/frontend/src/lib/api.ts183
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();
+}