greprag 5.31.1 → 5.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codex-hook-events.d.ts +20 -0
- package/dist/codex-hook-events.js +156 -0
- package/dist/codex-hook-events.js.map +1 -0
- package/dist/commands/codex-app-server.d.ts +1 -0
- package/dist/commands/codex-app-server.js +179 -0
- package/dist/commands/codex-app-server.js.map +1 -0
- package/dist/commands/codex-doctor.js +3 -1
- package/dist/commands/codex-doctor.js.map +1 -1
- package/dist/commands/codex.js +6 -0
- package/dist/commands/codex.js.map +1 -1
- package/dist/commands/corpus/index.d.ts +1 -0
- package/dist/commands/corpus/index.js +5 -0
- package/dist/commands/corpus/index.js.map +1 -1
- package/dist/commands/corpus/refresh.d.ts +1 -0
- package/dist/commands/corpus/refresh.js +60 -0
- package/dist/commands/corpus/refresh.js.map +1 -1
- package/dist/commands/desk-line.d.ts +36 -0
- package/dist/commands/desk-line.js +230 -0
- package/dist/commands/desk-line.js.map +1 -0
- package/dist/commands/init.js +75 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/opencode-relay.d.ts +136 -0
- package/dist/commands/opencode-relay.js +529 -0
- package/dist/commands/opencode-relay.js.map +1 -0
- package/dist/commands/opencode-watch.d.ts +17 -0
- package/dist/commands/opencode-watch.js +493 -0
- package/dist/commands/opencode-watch.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.js +5 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/watcher-registry.d.ts +8 -0
- package/dist/commands/watcher-registry.js +19 -0
- package/dist/commands/watcher-registry.js.map +1 -1
- package/dist/hook.js +54 -83
- package/dist/hook.js.map +1 -1
- package/dist/index.js +220 -1
- package/dist/index.js.map +1 -1
- package/dist/opencode-plugin-helpers.d.ts +200 -0
- package/dist/opencode-plugin-helpers.js +512 -0
- package/dist/opencode-plugin-helpers.js.map +1 -0
- package/dist/opencode-plugin.d.ts +37 -134
- package/dist/opencode-plugin.js +648 -364
- package/dist/opencode-plugin.js.map +1 -1
- package/dist/session-id.d.ts +8 -6
- package/dist/session-id.js +10 -9
- package/dist/session-id.js.map +1 -1
- package/package.json +8 -4
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/** GrepRAG opencode plugin — test-friendly helpers.
|
|
2
|
+
*
|
|
3
|
+
* Pure functions and type definitions extracted from `opencode-plugin.ts` so
|
|
4
|
+
* the deployed plugin file can use a single `export = { id, server }` shape
|
|
5
|
+
* (no `__esModule: true` wrapper, no `__test` helper export). The opencode
|
|
6
|
+
* legacy plugin loader iterates `Object.values(mod)` and rejects any value
|
|
7
|
+
* that isn't a function or `{ server: function }`; an `__esModule: true`
|
|
8
|
+
* boolean in that iteration throws "Plugin export is not a function" and the
|
|
9
|
+
* plugin registers zero hooks. See `adr/opencode-monitor-relay.md` 2026-06-06
|
|
10
|
+
* entries (e) and (f) for the full diagnosis.
|
|
11
|
+
*
|
|
12
|
+
* Three callers, all out-of-band of opencode's loader:
|
|
13
|
+
* - `opencode-plugin.ts` — the deployed plugin source imports these for use
|
|
14
|
+
* inside the V1 server function (recap renderer + anchor + lockfile).
|
|
15
|
+
* - `hook.ts` — Claude/Codex SessionStart hook imports the recap renderer
|
|
16
|
+
* so the recap body pushed to the system prompt is identical between
|
|
17
|
+
* harnesses. The hook keeps its own preamble (setup warning, checkpoint
|
|
18
|
+
* hint) — those are session-start UX concerns, not recap content.
|
|
19
|
+
* - `tests/test-opencode-plugin.cjs` and `tests/test-opencode-relay-spawn.cjs`
|
|
20
|
+
* — unit tests pull the same helpers by `require()` to exercise envelope
|
|
21
|
+
* construction, anchor resolution, and lockfile dedup without booting
|
|
22
|
+
* opencode.
|
|
23
|
+
*
|
|
24
|
+
* opencode never loads this file directly. Its presence at
|
|
25
|
+
* `~/.config/opencode/plugins/greprag-memory-helpers.js` is incidental to the
|
|
26
|
+
* deploy step; only `greprag-memory.js` is registered in the user's
|
|
27
|
+
* `opencode.json` plugin list.
|
|
28
|
+
*/
|
|
29
|
+
declare const HOME: string;
|
|
30
|
+
interface TextPart {
|
|
31
|
+
type: 'text';
|
|
32
|
+
text: string;
|
|
33
|
+
synthetic?: boolean;
|
|
34
|
+
ignored?: boolean;
|
|
35
|
+
}
|
|
36
|
+
type ToolState = {
|
|
37
|
+
status: 'pending';
|
|
38
|
+
input: Record<string, unknown>;
|
|
39
|
+
} | {
|
|
40
|
+
status: 'running';
|
|
41
|
+
input: Record<string, unknown>;
|
|
42
|
+
title?: string;
|
|
43
|
+
} | {
|
|
44
|
+
status: 'completed';
|
|
45
|
+
input: Record<string, unknown>;
|
|
46
|
+
output: string;
|
|
47
|
+
title: string;
|
|
48
|
+
} | {
|
|
49
|
+
status: 'error';
|
|
50
|
+
input: Record<string, unknown>;
|
|
51
|
+
error: string;
|
|
52
|
+
};
|
|
53
|
+
interface ToolPart {
|
|
54
|
+
type: 'tool';
|
|
55
|
+
callID: string;
|
|
56
|
+
tool: string;
|
|
57
|
+
state: ToolState;
|
|
58
|
+
}
|
|
59
|
+
interface GenericPart {
|
|
60
|
+
type: string;
|
|
61
|
+
[key: string]: unknown;
|
|
62
|
+
}
|
|
63
|
+
type Part = TextPart | ToolPart | GenericPart;
|
|
64
|
+
interface ProjectAnchor {
|
|
65
|
+
projectId: string;
|
|
66
|
+
projectName: string;
|
|
67
|
+
memoryCapture: boolean;
|
|
68
|
+
sessionStartRecap: boolean;
|
|
69
|
+
inboxNotify: 'every_turn' | 'session_start_only' | 'off';
|
|
70
|
+
}
|
|
71
|
+
/** Parsed `.greprag/project.json` contents. `project_id` and `project_name` are
|
|
72
|
+
* both optional after v0.7 — a file may carry per-project settings only and
|
|
73
|
+
* let identity flow from git derivation. */
|
|
74
|
+
interface AnchorFile {
|
|
75
|
+
projectId?: string;
|
|
76
|
+
projectName?: string;
|
|
77
|
+
memoryCapture: boolean;
|
|
78
|
+
sessionStartRecap: boolean;
|
|
79
|
+
inboxNotify: 'every_turn' | 'session_start_only' | 'off';
|
|
80
|
+
}
|
|
81
|
+
declare function readAnchorFile(filePath: string): AnchorFile | null;
|
|
82
|
+
/** Walk up from cwd looking for an anchor file. Checks canonical `.greprag/`
|
|
83
|
+
* first, then legacy `.claude/` and `.opencode/` at each level. Returns the
|
|
84
|
+
* first hit. Skips home-level globals; those are reserved for the
|
|
85
|
+
* ephemeral-cwd path of the cascade. */
|
|
86
|
+
declare function findExistingAnchorFile(startDir: string): string | null;
|
|
87
|
+
/** Format the SHA-256 of an input string into a deterministic UUID v4-shape
|
|
88
|
+
* string. Must match the algorithm in packages/cli/src/project-anchor.ts so
|
|
89
|
+
* the plugin resolves identical IDs to the Claude Code CLI. */
|
|
90
|
+
declare function formatUuid(hashHex: string): string;
|
|
91
|
+
/** Derive a stable project_id from the repo's root commit SHA. Sorted +
|
|
92
|
+
* hashed so disjoint-history merges produce one deterministic id everywhere.
|
|
93
|
+
* Returns null when cwd isn't a git repo or has no commits yet. */
|
|
94
|
+
declare function computeGitDerivedProjectId(cwd: string): string | null;
|
|
95
|
+
/** Hash the cwd path into a stable UUID. Last-resort fallback — when no git
|
|
96
|
+
* history and no anchor file exist, this keeps capture flowing under a
|
|
97
|
+
* per-path identity that `greprag doctor` can later consolidate. */
|
|
98
|
+
declare function deterministicProjectId(cwd: string): string;
|
|
99
|
+
/** True when cwd is an ephemeral session path (Cowork, tmp dirs). The
|
|
100
|
+
* deterministic-hash fallback would mint a fresh id every session in those
|
|
101
|
+
* paths, so we prefer the global anchor instead. */
|
|
102
|
+
declare function isEphemeralCwd(cwd: string): boolean;
|
|
103
|
+
/** Resolve the project anchor for `worktree` using the same 4-level cascade
|
|
104
|
+
* the Claude Code CLI uses (packages/cli/src/project-anchor.ts). Settings
|
|
105
|
+
* always come from the nearest repo-level file when one exists, regardless
|
|
106
|
+
* of which identity level resolved.
|
|
107
|
+
*
|
|
108
|
+
* 1. Anchor file with explicit `project_id` → file-based identity
|
|
109
|
+
* 2. Git repo with at least one commit → root-commit-derived UUID
|
|
110
|
+
* 3. Ephemeral cwd + ~/.greprag/project.json exists → global anchor
|
|
111
|
+
* 4. Path-hash fallback (never returns null; lets capture flow until
|
|
112
|
+
* `greprag init` runs and `greprag doctor` consolidates) */
|
|
113
|
+
declare function readAnchor(worktree: string): ProjectAnchor;
|
|
114
|
+
declare function extractText(parts: Part[]): string;
|
|
115
|
+
interface ToolCallSummary {
|
|
116
|
+
name: string;
|
|
117
|
+
target?: string;
|
|
118
|
+
brief?: string;
|
|
119
|
+
}
|
|
120
|
+
/** Pull a one-line summary out of each tool call: name + a target string + an
|
|
121
|
+
* optional brief for shell commands. Mirrors the shape the Claude Code hook
|
|
122
|
+
* posts so server-side compaction sees identical structure regardless of
|
|
123
|
+
* client origin. */
|
|
124
|
+
declare function extractToolCalls(parts: Part[]): ToolCallSummary[];
|
|
125
|
+
declare function extractFilesTouched(parts: Part[]): string[];
|
|
126
|
+
type TurnProvenance = 'session-turn' | 'skill-injection' | 'continuation-summary' | 'chip-prompt';
|
|
127
|
+
declare function classifyUserText(text: string): TurnProvenance;
|
|
128
|
+
declare function provenanceElisionMarker(p: TurnProvenance, text: string): string;
|
|
129
|
+
interface Envelope {
|
|
130
|
+
userPrompt: string;
|
|
131
|
+
agentResponse: string;
|
|
132
|
+
toolCalls: ToolCallSummary[];
|
|
133
|
+
filesTouched: string[];
|
|
134
|
+
status: 'completed' | 'errored';
|
|
135
|
+
provenance: TurnProvenance;
|
|
136
|
+
}
|
|
137
|
+
declare function buildEnvelope(userParts: Part[], assistantParts: Part[], errored: boolean): Envelope;
|
|
138
|
+
/** True when the OS reports `pid` as a running process. Used to decide whether
|
|
139
|
+
* a stale-lockfile check should trust the recorded PID or treat the file as
|
|
140
|
+
* abandoned. */
|
|
141
|
+
export declare function isPidAlive(pid: number): boolean;
|
|
142
|
+
declare function relayLockPath(sessionId: string): string;
|
|
143
|
+
declare function tryClaimRelayLock(lockPath: string): {
|
|
144
|
+
ok: true;
|
|
145
|
+
fd: number;
|
|
146
|
+
} | {
|
|
147
|
+
ok: false;
|
|
148
|
+
reason: string;
|
|
149
|
+
};
|
|
150
|
+
/** One row from `/v1/memory/by-period`. Mirrors hook.ts ByPeriodRow — kept
|
|
151
|
+
* in sync intentionally so the two paths fetch the same shape. */
|
|
152
|
+
interface ByPeriodRow {
|
|
153
|
+
id: string;
|
|
154
|
+
projectId: string | null;
|
|
155
|
+
projectName: string | null;
|
|
156
|
+
crystallization: string;
|
|
157
|
+
content: string;
|
|
158
|
+
wordCount: number;
|
|
159
|
+
windowStart: string | null;
|
|
160
|
+
windowEnd: string | null;
|
|
161
|
+
branch: string | null;
|
|
162
|
+
artifactType: string | null;
|
|
163
|
+
artifactId: string | null;
|
|
164
|
+
artifactUrl: string | null;
|
|
165
|
+
createdAt: string;
|
|
166
|
+
}
|
|
167
|
+
/** Cap on the number of hourlies surfaced in the recap body. 3 — the hook's
|
|
168
|
+
* established value; if the user wants more they pull on demand via
|
|
169
|
+
* `greprag memory recap`. adr: adr/memory-recap-pyramid.md. */
|
|
170
|
+
declare const HOURLY_CAP = 3;
|
|
171
|
+
/** Strip noise blocks from compacted content before injection.
|
|
172
|
+
* Compactor contract: numbered items end with a trailer ("Open: ..." for
|
|
173
|
+
* hourly, "Shipped: ..." for daily) which may span multiple lines. Trailers
|
|
174
|
+
* always come AFTER the numbered list — so we drop from the trigger line
|
|
175
|
+
* through end-of-string.
|
|
176
|
+
*
|
|
177
|
+
* - daily: drop the deterministic "Shipped: <UUID-list>" trailer (useful for
|
|
178
|
+
* /greprag deep-dive, but a wall of IDs at session start)
|
|
179
|
+
* - hourly: drop the per-hour "Open:" block (stale snapshot of open items
|
|
180
|
+
* that were resolved or superseded in later hours) */
|
|
181
|
+
declare function stripRecapNoise(content: string, type: 'daily' | 'hourly'): string;
|
|
182
|
+
/** Render an hourly window's recency: "5 hours ago", "1 hour ago",
|
|
183
|
+
* "30 min ago", "just now". Reference is the end of the window — when the
|
|
184
|
+
* hour wrapped up. */
|
|
185
|
+
declare function fmtHoursAgo(windowEndIso: string, now: Date): string;
|
|
186
|
+
/** Build the recap body — hourlies-only render. Recap is hourlies-only by
|
|
187
|
+
* design: daily summaries used to render here (one prose paragraph per
|
|
188
|
+
* daily window) but added ~1500 tokens to every SessionStart for marginal
|
|
189
|
+
* value. Dailies still exist in the DB; agents who want historic context
|
|
190
|
+
* pull on demand via `greprag memory recap` (or
|
|
191
|
+
* `greprag memory search "<query>"` for a specific topic). Pull, don't push.
|
|
192
|
+
*
|
|
193
|
+
* Window: 2 days back to now (50-row pull), filtered to last 24h, sliced
|
|
194
|
+
* to HOURLY_CAP most-recent.
|
|
195
|
+
*
|
|
196
|
+
* Returns "" when there are no recent hourlies — caller treats that as
|
|
197
|
+
* "no recap block". Empty body is not an error; the query itself is the
|
|
198
|
+
* only network call and any failure is swallowed (returns ""). */
|
|
199
|
+
declare function buildRecapBody(apiUrl: string, apiKey: string, anchor: ProjectAnchor, now?: Date): Promise<string>;
|
|
200
|
+
export { HOME, type Part, type TextPart, type ToolPart, type ToolState, type GenericPart, type ProjectAnchor, type AnchorFile, type ToolCallSummary, type Envelope, type TurnProvenance, type ByPeriodRow, formatUuid, computeGitDerivedProjectId, deterministicProjectId, isEphemeralCwd, readAnchorFile, findExistingAnchorFile, readAnchor, extractText, extractToolCalls, extractFilesTouched, classifyUserText, provenanceElisionMarker, buildEnvelope, relayLockPath, tryClaimRelayLock, stripRecapNoise, fmtHoursAgo, buildRecapBody, HOURLY_CAP, };
|