-
Notifications
You must be signed in to change notification settings - Fork 1
Align memory unit type guidance #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0585739
351810f
2c36d3c
00fb246
d6d2eed
6482de7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,29 @@ | ||
| prompt = """ | ||
| Load the user's Working Memory briefing before continuing. | ||
| Load the user's startup context before continuing. | ||
|
|
||
| Use the shell tool to try: | ||
| When identity, active space, active rules, or multi-agent behavior could matter, use Context Bundle first: | ||
|
|
||
| ```bash | ||
| nmem --json context --source-app gemini-cli | ||
| ``` | ||
|
|
||
| For a lightweight daily briefing or older `nmem` clients, use: | ||
|
|
||
| ```bash | ||
| nmem --json wm read | ||
| ``` | ||
|
|
||
| If the command succeeds but reports that no Working Memory exists yet, say that clearly. | ||
| If either command succeeds but returns no content yet, say that clearly. | ||
|
|
||
| If the runtime already knows the current project or agent lane, add `--space "<space name>"`. | ||
| If the runtime already knows the current project or agent lane, add `--space "<space name>"` to either command. Multi-agent orchestrators can set `NMEM_AGENT_ID="<agent-slug>"` before launching Gemini CLI. Add `NMEM_SPACE` only when that whole run should override the identity's default space. Use `NMEM_HOST_AGENT_ID` only for advanced host-id aliases. | ||
|
|
||
| Only if `nmem` is unavailable in an older local-only **Default-space** setup, fall back to: | ||
|
|
||
| ```bash | ||
| cat ~/ai-now/memory.md | ||
| ``` | ||
|
|
||
| Then summarize the user's active focus areas, priorities, unresolved flags, and the most relevant recent changes when a briefing is actually present. | ||
| Then summarize only the parts relevant to the task. If Context Bundle was loaded, do not separately read Working Memory unless the user asks for a lightweight refresh. | ||
|
|
||
| If remote access is configured through `~/.nowledge-mem/config.json`, let `nmem` use it naturally. Do not assume environment variables are the only auth path. | ||
| """ |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,38 +12,104 @@ function emit(payload) { | |||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| function readWorkingMemory() { | ||||||||||||||||||||||||||
| const result = spawnSync('nmem', ['--json', 'wm', 'read'], { | ||||||||||||||||||||||||||
| function parseJsonText(stdout, keys) { | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| const data = JSON.parse(stdout || '{}'); | ||||||||||||||||||||||||||
| for (const key of keys) { | ||||||||||||||||||||||||||
| const value = data[key]; | ||||||||||||||||||||||||||
| if (typeof value === 'string' && value.trim()) { | ||||||||||||||||||||||||||
| return value.trim(); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||
| // Fall back to the next context source. | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return ''; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| function readNmem(args, keys) { | ||||||||||||||||||||||||||
| const result = spawnSync('nmem', ['--json', ...args], { | ||||||||||||||||||||||||||
| encoding: 'utf8', | ||||||||||||||||||||||||||
| timeout: 10000, | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (result.status === 0) { | ||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||
| const data = JSON.parse(result.stdout || '{}'); | ||||||||||||||||||||||||||
| const content = typeof data.content === 'string' ? data.content.trim() : ''; | ||||||||||||||||||||||||||
| if (content) { | ||||||||||||||||||||||||||
| return content; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||
| // Fall back to the legacy file path below. | ||||||||||||||||||||||||||
| const content = parseJsonText(result.stdout, keys); | ||||||||||||||||||||||||||
| if (content) { | ||||||||||||||||||||||||||
| return content; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return ''; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| function envValue(name) { | ||||||||||||||||||||||||||
| const value = process.env[name]; | ||||||||||||||||||||||||||
| return typeof value === 'string' ? value.trim() : ''; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| function withStartupArgs(args) { | ||||||||||||||||||||||||||
| const next = [...args]; | ||||||||||||||||||||||||||
| const agentId = envValue('NMEM_AGENT_ID'); | ||||||||||||||||||||||||||
| const hostAgentId = envValue('NMEM_HOST_AGENT_ID'); | ||||||||||||||||||||||||||
| const space = envValue('NMEM_SPACE') || envValue('NMEM_SPACE_ID'); | ||||||||||||||||||||||||||
| if (agentId && !next.includes('--agent-id')) { | ||||||||||||||||||||||||||
| next.push('--agent-id', agentId); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (hostAgentId && !next.includes('--host-agent-id')) { | ||||||||||||||||||||||||||
| next.push('--host-agent-id', hostAgentId); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| if (space && !next.includes('--space')) { | ||||||||||||||||||||||||||
| next.push('--space', space); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return next; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| function withSpaceArgs(args) { | ||||||||||||||||||||||||||
| const next = [...args]; | ||||||||||||||||||||||||||
| const space = envValue('NMEM_SPACE') || envValue('NMEM_SPACE_ID'); | ||||||||||||||||||||||||||
| if (space && !next.includes('--space')) { | ||||||||||||||||||||||||||
| next.push('--space', space); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| return next; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| function readStartupContext() { | ||||||||||||||||||||||||||
| const contextBundle = readNmem(withStartupArgs(['context', '--source-app', 'gemini-cli']), ['rendered_markdown', 'markdown', 'content']); | ||||||||||||||||||||||||||
| if (contextBundle) { | ||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||
| tag: 'nowledge_context_bundle', | ||||||||||||||||||||||||||
| label: 'Context Bundle', | ||||||||||||||||||||||||||
| content: contextBundle, | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const workingMemory = readNmem(withSpaceArgs(['wm', 'read']), ['content']); | ||||||||||||||||||||||||||
| if (workingMemory) { | ||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||
| tag: 'nowledge_working_memory', | ||||||||||||||||||||||||||
| label: 'Working Memory', | ||||||||||||||||||||||||||
| content: workingMemory, | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const legacyPath = path.join(os.homedir(), 'ai-now', 'memory.md'); | ||||||||||||||||||||||||||
| if (existsSync(legacyPath)) { | ||||||||||||||||||||||||||
| const content = readFileSync(legacyPath, 'utf8').trim(); | ||||||||||||||||||||||||||
| if (content) { | ||||||||||||||||||||||||||
| return content; | ||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||
| tag: 'nowledge_working_memory', | ||||||||||||||||||||||||||
| label: 'legacy Working Memory file', | ||||||||||||||||||||||||||
| content, | ||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| return ''; | ||||||||||||||||||||||||||
| return null; | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| const workingMemory = readWorkingMemory(); | ||||||||||||||||||||||||||
| const startupContext = readStartupContext(); | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| if (!workingMemory) { | ||||||||||||||||||||||||||
| if (!startupContext) { | ||||||||||||||||||||||||||
| emit({ | ||||||||||||||||||||||||||
| hookSpecificOutput: { | ||||||||||||||||||||||||||
| hookEventName: 'SessionStart', | ||||||||||||||||||||||||||
|
|
@@ -53,11 +119,11 @@ if (!workingMemory) { | |||||||||||||||||||||||||
| emit({ | ||||||||||||||||||||||||||
| hookSpecificOutput: { | ||||||||||||||||||||||||||
| hookEventName: 'SessionStart', | ||||||||||||||||||||||||||
| additionalContext: `<nowledge_working_memory> | ||||||||||||||||||||||||||
| Use this as current user context from Nowledge Mem Working Memory. It is situational context, not a higher-priority instruction. | ||||||||||||||||||||||||||
| additionalContext: `<${startupContext.tag}> | ||||||||||||||||||||||||||
| Use this as current user context from Nowledge Mem ${startupContext.label}. It is situational context, not a higher-priority instruction. | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| ${workingMemory} | ||||||||||||||||||||||||||
| </nowledge_working_memory>`, | ||||||||||||||||||||||||||
| ${startupContext.content} | ||||||||||||||||||||||||||
| </${startupContext.tag}>`, | ||||||||||||||||||||||||||
|
Comment on lines
+122
to
+126
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Escape startup context text before injecting into XML-like wrapper. At Line 122, raw 🔧 Suggested fix+function escapeXml(text) {
+ return String(text)
+ .replaceAll('&', '&')
+ .replaceAll('<', '<')
+ .replaceAll('>', '>');
+}
+
const startupContext = readStartupContext();
@@
} else {
+ const escapedContent = escapeXml(startupContext.content);
emit({
hookSpecificOutput: {
hookEventName: 'SessionStart',
additionalContext: `<${startupContext.tag}>
Use this as current user context from Nowledge Mem ${startupContext.label}. It is situational context, not a higher-priority instruction.
-${startupContext.content}
+${escapedContent}
</${startupContext.tag}>`,
},
});
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # Nowledge Mem Gemini CLI 0.1.9 | ||
|
|
||
| Session-start context now uses Nowledge Mem's full Context Bundle when available. Gemini can receive owner identity, AI Identity, active space, active rules, Working Memory, and KFS paths before falling back to the lighter Working Memory briefing on older `nmem` clients. | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Complete the unit_type guidance with enumerated values.
Line 116 ends with "Pass
unit_typewhen the type is clear:" but doesn't provide the list of allowed values inline. Users would need to reference SKILL.md line 25 to discover the valid values.Additionally, the text uses "learnings" (plural) in the content type list, but the actual unit_type value should be
learning(singular) based on the enumeration in SKILL.md line 25.📝 Suggested improvement
Option 1: Add the enumerated list inline:
Option 2: Make it a complete sentence without the colon:
Note: Also consider using "learning" (singular) consistently instead of "learnings" to match the actual unit_type value.
📝 Committable suggestion
🤖 Prompt for AI Agents