mirror of
https://github.com/cursor/plugins.git
synced 2026-09-14 20:00:00 +08:00
Prefer agent CLI for continual learning hook
Co-authored-by: Eric Zakariasson <ericzakariasson@users.noreply.github.com>
This commit is contained in:
@@ -22,13 +22,14 @@ It is designed to avoid noisy rewrites by:
|
||||
|
||||
## How it works
|
||||
|
||||
On eligible `stop` events, the hook may emit a `followup_message` that asks the agent to run the `continual-learning` skill.
|
||||
On eligible `stop` events, the hook prefers launching the `agent` CLI in print mode when `agent` is available on `PATH`. If the CLI is unavailable or cannot be started, the hook falls back to emitting a `followup_message` that asks the current session to run the `continual-learning` skill.
|
||||
|
||||
The skill is marked `disable-model-invocation: true`, so it will not be auto-selected during normal model invocation. When it does run, it delegates the full memory update flow to `agents-memory-updater`.
|
||||
|
||||
The hook keeps local runtime state in:
|
||||
|
||||
- `.cursor/hooks/state/continual-learning.json` (cadence state)
|
||||
- `.cursor/hooks/state/continual-learning-agent.log` (best-effort `agent` CLI output when launched from the hook)
|
||||
|
||||
The updater uses an incremental transcript index at:
|
||||
|
||||
|
||||
@@ -1,13 +1,23 @@
|
||||
/// <reference types="bun-types-no-globals/lib/index.d.ts" />
|
||||
|
||||
import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
||||
import {
|
||||
closeSync,
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
openSync,
|
||||
readFileSync,
|
||||
statSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { spawn, spawnSync } from "node:child_process";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import { stdin } from "bun";
|
||||
|
||||
const STATE_PATH = resolve(".cursor/hooks/state/continual-learning.json");
|
||||
const INCREMENTAL_INDEX_PATH = resolve(
|
||||
".cursor/hooks/state/continual-learning-index.json"
|
||||
);
|
||||
const PROJECT_DIR = resolve(process.env.CURSOR_PROJECT_DIR ?? ".");
|
||||
const STATE_DIR = resolve(PROJECT_DIR, ".cursor/hooks/state");
|
||||
const STATE_PATH = resolve(STATE_DIR, "continual-learning.json");
|
||||
const INCREMENTAL_INDEX_PATH = resolve(STATE_DIR, "continual-learning-index.json");
|
||||
const AGENT_LOG_PATH = resolve(STATE_DIR, "continual-learning-agent.log");
|
||||
const DEFAULT_MIN_TURNS = 10;
|
||||
const DEFAULT_MIN_MINUTES = 120;
|
||||
const TRIAL_DEFAULT_MIN_TURNS = 3;
|
||||
@@ -138,6 +148,50 @@ function shouldCountTurn(input: StopHookInput): boolean {
|
||||
return input.status === "completed" && input.loop_count === 0;
|
||||
}
|
||||
|
||||
function canSpawnAgentCli(): boolean {
|
||||
const result = spawnSync("agent", ["--version"], {
|
||||
stdio: "ignore",
|
||||
cwd: PROJECT_DIR,
|
||||
env: process.env,
|
||||
});
|
||||
return result.error === undefined;
|
||||
}
|
||||
|
||||
function triggerAgentCli(): boolean {
|
||||
if (!canSpawnAgentCli()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let logFd: number | null = null;
|
||||
|
||||
try {
|
||||
if (!existsSync(STATE_DIR)) {
|
||||
mkdirSync(STATE_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
logFd = openSync(AGENT_LOG_PATH, "a");
|
||||
const child = spawn(
|
||||
"agent",
|
||||
["-p", "--force", "--workspace", PROJECT_DIR, "--", FOLLOWUP_MESSAGE],
|
||||
{
|
||||
cwd: PROJECT_DIR,
|
||||
detached: true,
|
||||
stdio: ["ignore", logFd, logFd],
|
||||
env: process.env,
|
||||
}
|
||||
);
|
||||
child.unref();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("[continual-learning-stop] failed to spawn agent CLI", error);
|
||||
return false;
|
||||
} finally {
|
||||
if (logFd !== null) {
|
||||
closeSync(logFd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function parseHookInput<T>(): Promise<T> {
|
||||
const text = await stdin.text();
|
||||
return JSON.parse(text) as T;
|
||||
@@ -224,6 +278,11 @@ async function main(): Promise<number> {
|
||||
state.lastTranscriptMtimeMs = transcriptMtimeMs;
|
||||
saveState(state);
|
||||
|
||||
if (triggerAgentCli()) {
|
||||
console.log(JSON.stringify({}));
|
||||
return 0;
|
||||
}
|
||||
|
||||
console.log(
|
||||
JSON.stringify({
|
||||
followup_message: FOLLOWUP_MESSAGE,
|
||||
|
||||
Reference in New Issue
Block a user