feat: integrate Memento MCP for shared memory across agents
- Add MEMENTO_MCP_SSE_URL/ACCESS_KEY/REMOTE_PATH to readEnvFile - Merge .env vars into cleanEnv for runner process inheritance - Claude Code runner: add memento-mcp via mcp-remote in mcpServers - Codex runner: inject memento-mcp section into config.toml - Various improvements: CI watch, task scheduler, DB, IPC auth
This commit is contained in:
@@ -531,6 +531,18 @@ async function runQuery(
|
||||
NANOCLAW_IS_MAIN: containerInput.isMain ? '1' : '0',
|
||||
},
|
||||
},
|
||||
...(process.env.MEMENTO_MCP_SSE_URL
|
||||
? {
|
||||
'memento-mcp': {
|
||||
command: process.env.MEMENTO_MCP_REMOTE_PATH || 'mcp-remote',
|
||||
args: [
|
||||
process.env.MEMENTO_MCP_SSE_URL,
|
||||
'--header',
|
||||
`Authorization:Bearer ${process.env.MEMENTO_ACCESS_KEY || ''}`,
|
||||
],
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
hooks: {
|
||||
PreCompact: [{ hooks: [createPreCompactHook(containerInput.assistantName)] }],
|
||||
|
||||
@@ -12,6 +12,7 @@ import path from 'path';
|
||||
import { CronExpressionParser } from 'cron-parser';
|
||||
import {
|
||||
buildCiWatchPrompt,
|
||||
DEFAULT_WATCH_CI_CONTEXT_MODE,
|
||||
normalizeWatchCiIntervalSeconds,
|
||||
} from './watch-ci.js';
|
||||
|
||||
@@ -174,8 +175,8 @@ server.tool(
|
||||
.describe('How often to poll in seconds. Default 60, minimum 30.'),
|
||||
context_mode: z
|
||||
.enum(['group', 'isolated'])
|
||||
.default('group')
|
||||
.describe('group=runs with chat history and memory, isolated=fresh session (include all context in check_instructions)'),
|
||||
.default(DEFAULT_WATCH_CI_CONTEXT_MODE)
|
||||
.describe('group=runs with chat history and memory, isolated=fresh session (include all context in check_instructions). Default: isolated.'),
|
||||
target_group_jid: z
|
||||
.string()
|
||||
.optional()
|
||||
@@ -211,7 +212,7 @@ server.tool(
|
||||
prompt,
|
||||
schedule_type: 'interval' as const,
|
||||
schedule_value: String(pollSeconds * 1000),
|
||||
context_mode: args.context_mode || 'group',
|
||||
context_mode: args.context_mode || DEFAULT_WATCH_CI_CONTEXT_MODE,
|
||||
targetJid,
|
||||
createdBy: groupFolder,
|
||||
timestamp: new Date().toISOString(),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
export const DEFAULT_WATCH_CI_INTERVAL_SECONDS = 60;
|
||||
export const MIN_WATCH_CI_INTERVAL_SECONDS = 30;
|
||||
export const MAX_WATCH_CI_INTERVAL_SECONDS = 3600;
|
||||
export const DEFAULT_WATCH_CI_CONTEXT_MODE = 'isolated';
|
||||
|
||||
export interface BuildCiWatchPromptArgs {
|
||||
taskId: string;
|
||||
@@ -49,12 +50,21 @@ Check instructions:
|
||||
${checkInstructions}
|
||||
|
||||
Rules:
|
||||
- Use the watch target and check instructions in this prompt as the source of truth for what to inspect.
|
||||
- On each run, check whether the target is still queued, pending, running, in progress, or otherwise non-terminal.
|
||||
- If it is still not finished, send no visible message and end this run quietly.
|
||||
- If it reached a terminal state such as success, failure, cancelled, timed out, neutral, skipped, or action required:
|
||||
1. Send exactly one concise completion message with \`send_message\`.
|
||||
2. Include the final status and only the most important details.
|
||||
3. Call \`cancel_task\` with task_id "${taskId}" so this watcher stops itself.
|
||||
2. Format it as a short multiline summary when possible, not one long paragraph.
|
||||
3. Preferred shape:
|
||||
- First line: \`CI 완료: <target>\`
|
||||
- Second line: \`판정: <one-line conclusion>\`
|
||||
- Then 2-4 flat bullet points with only the most important metrics, errors, or comparisons.
|
||||
- Optional final line: \`다음: <next action>\` if a concrete follow-up is needed.
|
||||
4. Adapt the content to the specific CI. Do not invent fixed fields when they do not fit.
|
||||
5. Avoid tables unless they are clearly the shortest readable format.
|
||||
6. Keep the message compact and easy for other agents to parse.
|
||||
7. Call \`cancel_task\` with task_id "${taskId}" so this watcher stops itself.
|
||||
- If you hit a transient problem such as a rate limit, network issue, or temporary auth failure, send no visible message and leave the task active for the next retry.
|
||||
- Prefer no normal final response. Use \`send_message\` for the completion message, and keep any non-user-facing notes inside \`<internal>\` tags if needed.
|
||||
- Do not claim continued monitoring after you cancel the task.
|
||||
|
||||
@@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest';
|
||||
|
||||
import {
|
||||
buildCiWatchPrompt,
|
||||
DEFAULT_WATCH_CI_CONTEXT_MODE,
|
||||
normalizeWatchCiIntervalSeconds,
|
||||
} from '../src/watch-ci.js';
|
||||
|
||||
@@ -18,6 +19,15 @@ describe('watch-ci helpers', () => {
|
||||
expect(prompt).toContain('cancel_task');
|
||||
expect(prompt).toContain('send_message');
|
||||
expect(prompt).toContain('gh pr checks 42');
|
||||
expect(prompt).toContain('CI 완료: <target>');
|
||||
expect(prompt).toContain('판정: <one-line conclusion>');
|
||||
expect(prompt).toContain(
|
||||
'Use the watch target and check instructions in this prompt as the source of truth',
|
||||
);
|
||||
});
|
||||
|
||||
it('defaults CI watchers to isolated context', () => {
|
||||
expect(DEFAULT_WATCH_CI_CONTEXT_MODE).toBe('isolated');
|
||||
});
|
||||
|
||||
it('normalizes valid poll intervals', () => {
|
||||
|
||||
64
runners/codex-runner/package-lock.json
generated
64
runners/codex-runner/package-lock.json
generated
@@ -8,7 +8,7 @@
|
||||
"name": "ejclaw-codex-runner",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@openai/codex-sdk": "^0.114.0"
|
||||
"@openai/codex-sdk": "^0.115.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.7",
|
||||
@@ -16,9 +16,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex": {
|
||||
"version": "0.114.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0.tgz",
|
||||
"integrity": "sha512-HMo8LRR6CtfKkaa28xvFK6eOarmBFTDfsrS9GJtEoaspGGemFok494CpafDspiTZaHZZGHfSUe5SWTUxYq7OaA==",
|
||||
"version": "0.115.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.115.0.tgz",
|
||||
"integrity": "sha512-uu689DHUzvuPcb39hJ+7fqy++TAvY32w9VggDpcz3HS0Sx0WadWoAPPcMK547P2T6AqfMsAtA8kspkR3tqErOg==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"codex": "bin/codex.js"
|
||||
@@ -27,19 +27,19 @@
|
||||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.114.0-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.114.0-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.114.0-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.114.0-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.114.0-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.114.0-win32-x64"
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.115.0-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.115.0-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.115.0-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.115.0-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.115.0-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.115.0-win32-x64"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-darwin-arm64.tgz",
|
||||
"integrity": "sha512-c9dlgo9O+66alr3s3G36fKE3KaO2+xrLZ/QcU3oujDruV86pqgVSEK2njHi+WIyyOa6m2AyWxdaHLEbKxPCNRg==",
|
||||
"version": "0.115.0-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.115.0-darwin-arm64.tgz",
|
||||
"integrity": "sha512-wTWV+YlDTL0y0mL+FMmbzhilm+dPkbIZTe/lH3LwBzcEMhgSGLsPdZLfAiMND4wFE21HS7H0pjMogNQEMLQmqg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -54,9 +54,9 @@
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-darwin-x64.tgz",
|
||||
"integrity": "sha512-oPAPeZSaJZ1AQneFPSJu44uqbZr63Bxut9FOTWZwuSqYx4YEees7i0HJmJcqQc0XnCbYtHJdqo/i07Uv374NLw==",
|
||||
"version": "0.115.0-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.115.0-darwin-x64.tgz",
|
||||
"integrity": "sha512-EPzgymU4CFp83qjv29wXFwhWib3zC8g6SLTJGh2OpcJiOYyLY0bO53FB+QchL1jC9gm1uLyD5j5F3ddI0AbjIg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -71,9 +71,9 @@
|
||||
},
|
||||
"node_modules/@openai/codex-linux-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-linux-arm64.tgz",
|
||||
"integrity": "sha512-oUFZGZgMiEqmo85C+dfhckpVApH25alLWfwBgfKr2IRgdx/tovy8vN101f6kj01E6nDDe4LfJdNSZGtZht4fRA==",
|
||||
"version": "0.115.0-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.115.0-linux-arm64.tgz",
|
||||
"integrity": "sha512-40+SCyI+LvVx/iX30qH7dTQzWt9MZxDaK2E6YRB4hoYej5UALrhkFNzweHa5uvqvhmqGZCuagZOYB8285eGCgw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -88,9 +88,9 @@
|
||||
},
|
||||
"node_modules/@openai/codex-linux-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-linux-x64.tgz",
|
||||
"integrity": "sha512-MF6RhxfBoccccd5CYII2C7TL2TvYzombBQhanDZfQAajr6n7IuoazCmoHDlrFHS4AcSw9bYA4MRlrwEjbEjgsw==",
|
||||
"version": "0.115.0-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.115.0-linux-x64.tgz",
|
||||
"integrity": "sha512-+6eRd2p4KMrhQvuF7XpjYIdCA2Ok2LbhOq+ywZdLpHbmwQ/Yynd0gJ/Q90xCeo2vloCwl9WsbsiVVSahG5FyWg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -104,12 +104,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-sdk": {
|
||||
"version": "0.114.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex-sdk/-/codex-sdk-0.114.0.tgz",
|
||||
"integrity": "sha512-28tV+pvoQhhoRADBCtlg24fR6LDTyeUA6C65NBTvYFnDoQVPJcHcAwRrbuWmUMcXdLrXwY2bmiMxyfXlUWQzgw==",
|
||||
"version": "0.115.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex-sdk/-/codex-sdk-0.115.0.tgz",
|
||||
"integrity": "sha512-BPoPhim0uUm3rzugY7JFaFJ+rPG/wMRhvKNFii//Dp3kTb+gFy3jrip7ijXqhswsnqXM3nwTiv7kYHt1+TMUPg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@openai/codex": "0.114.0"
|
||||
"@openai/codex": "0.115.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -117,9 +117,9 @@
|
||||
},
|
||||
"node_modules/@openai/codex-win32-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-win32-arm64.tgz",
|
||||
"integrity": "sha512-CnRMHopj3en9aqQ2UaDW7EgpEGkxHdZVLLRq2cOy5D0HyuzF6Qb6595ADoFVJHEmPeN5Iz/KUbiGs5GLDjUwOA==",
|
||||
"version": "0.115.0-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.115.0-win32-arm64.tgz",
|
||||
"integrity": "sha512-yaYhQ0kPL9Kithmrr1vh5A4c+gqAMhMZeA/htTtkpWW8RQkmwgcYYpX/Ky2cEzu0w51pvxQQy63LgHftc+pg1Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -134,9 +134,9 @@
|
||||
},
|
||||
"node_modules/@openai/codex-win32-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-win32-x64.tgz",
|
||||
"integrity": "sha512-ztRsH5Z+gPVZ5ZInx6HzXsTFFkuEdjk3Ay0UGVOhRRCWvevXQi/SL4eU8hwysCYrs8K/WRq3mo4c95w9zQ2wLw==",
|
||||
"version": "0.115.0-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.115.0-win32-x64.tgz",
|
||||
"integrity": "sha512-wtYf2HJCB+p+Uj7o1W08fRgZMzKCVGRQ4YdSfLRNfF4wwPqX5XsK9blsv7brukn5J9lclYxagiR6qGvbfHbD7w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user