( deps: CtxNoteToolDeps, )
| 179 | } |
| 180 | |
| 181 | export function createCtxNoteTool( |
| 182 | deps: CtxNoteToolDeps, |
| 183 | ): ToolDefinition<typeof ParamsSchema> { |
| 184 | return { |
| 185 | name: "ctx_note", |
| 186 | label: "Magic Context: Notes", |
| 187 | description: CTX_NOTE_DESCRIPTION, |
| 188 | parameters: ParamsSchema, |
| 189 | async execute(_toolCallId, params: CtxNoteParams, _signal, _onUpdate, ctx) { |
| 190 | const sessionId = ctx.sessionManager.getSessionId(); |
| 191 | // Infer write only on NON-EMPTY content. GPT-family models fill every |
| 192 | // optional param (content:"" for a read), so a bare `typeof === "string"` |
| 193 | // check would mis-infer `write` and then reject the empty content. |
| 194 | const action = |
| 195 | params.action ?? (params.content?.trim() ? "write" : "read"); |
| 196 | |
| 197 | if (action === "write") { |
| 198 | const content = params.content?.trim(); |
| 199 | if (!content) |
| 200 | return err("Error: 'content' is required when action is 'write'."); |
| 201 | |
| 202 | // Anchor the note to the live conversation tail so it can be |
| 203 | // traced back later via ctx_expand. Best-effort — null when |
| 204 | // there's no indexed tail yet. |
| 205 | const anchorOrdinal = captureAnchorOrdinal(deps.db, sessionId); |
| 206 | |
| 207 | const surfaceCondition = params.surface_condition?.trim(); |
| 208 | if (surfaceCondition) { |
| 209 | if (deps.dreamerEnabled !== true) { |
| 210 | return err( |
| 211 | "Error: Smart notes require dreamer to be enabled. Enable dreamer in magic-context.jsonc to use surface_condition.", |
| 212 | ); |
| 213 | } |
| 214 | const projectIdentity = resolveProjectIdentity(ctx.cwd); |
| 215 | if (!projectIdentity) { |
| 216 | return err( |
| 217 | "Error: Could not resolve project identity for smart note.", |
| 218 | ); |
| 219 | } |
| 220 | const note = addNote(deps.db, "smart", { |
| 221 | content, |
| 222 | projectPath: projectIdentity, |
| 223 | surfaceCondition, |
| 224 | anchorOrdinal, |
| 225 | }); |
| 226 | return ok( |
| 227 | `Created smart note #${note.id}. Dreamer will evaluate the condition during nightly runs:\n- Content: ${content}\n- Condition: ${surfaceCondition}`, |
| 228 | ); |
| 229 | } |
| 230 | |
| 231 | const note = addNote(deps.db, "session", { |
| 232 | sessionId, |
| 233 | content, |
| 234 | anchorOrdinal, |
| 235 | }); |
| 236 | return ok(`Saved session note #${note.id}.`); |
| 237 | } |
| 238 |
no outgoing calls