@polygraph/opencode-plugin 0.4.24 → 0.4.25
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/package.json +1 -1
- package/server.js +88 -0
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { fileURLToPath } from 'node:url';
|
|
4
5
|
import yaml from 'js-yaml';
|
|
@@ -29,6 +30,18 @@ export const PolygraphPlugin = async () => {
|
|
|
29
30
|
output.env.POLYGRAPH_AGENT_SESSION_ID = input.sessionID;
|
|
30
31
|
output.env.POLYGRAPH_AGENT_TYPE = 'opencode';
|
|
31
32
|
},
|
|
33
|
+
|
|
34
|
+
// OpenCode has no SessionStart hook, but the Polygraph CLI already seeds the
|
|
35
|
+
// session id into context at launch. The one thing compaction can drop is
|
|
36
|
+
// that identity, so we steer the summary prompt to retain it. This fires
|
|
37
|
+
// before each compaction; the note is appended to the summarization prompt
|
|
38
|
+
// (best-effort — we trust the model to keep the id + repos in the summary).
|
|
39
|
+
'experimental.session.compacting': async (input, output) => {
|
|
40
|
+
const note = polygraphCompactionNote(input.sessionID);
|
|
41
|
+
if (note) {
|
|
42
|
+
output.context.push(note);
|
|
43
|
+
}
|
|
44
|
+
},
|
|
32
45
|
};
|
|
33
46
|
};
|
|
34
47
|
|
|
@@ -92,3 +105,78 @@ function numberValue(value) {
|
|
|
92
105
|
function recordValue(value) {
|
|
93
106
|
return value && typeof value === 'object' && !Array.isArray(value) ? value : undefined;
|
|
94
107
|
}
|
|
108
|
+
|
|
109
|
+
// --- Polygraph session context (mirrors source/hooks/reinject-polygraph-context.mjs) ---
|
|
110
|
+
//
|
|
111
|
+
// Resolve the Polygraph session for this OpenCode session id from local state,
|
|
112
|
+
// then build a short instruction telling the summarizer to keep the Polygraph
|
|
113
|
+
// session id and repo list in the compaction summary. Returns null when this is
|
|
114
|
+
// not a Polygraph session (no matching parent-log sidecar) — a silent no-op.
|
|
115
|
+
|
|
116
|
+
export function polygraphCompactionNote(agentSessionId, root) {
|
|
117
|
+
const session = readPolygraphSession(agentSessionId, root);
|
|
118
|
+
if (!session) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const repos = session.repos
|
|
123
|
+
.map((repo) => repo.repoFullName)
|
|
124
|
+
.filter(Boolean)
|
|
125
|
+
.join(', ');
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
`This conversation is running inside Polygraph session ${session.sessionId}` +
|
|
129
|
+
(repos ? ` (repos: ${repos})` : '') +
|
|
130
|
+
'. Preserve the Polygraph session id and the repo list verbatim in the ' +
|
|
131
|
+
'summary so they remain available after compaction.'
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function readPolygraphSession(
|
|
136
|
+
agentSessionId,
|
|
137
|
+
root = path.join(homedir(), '.polygraph')
|
|
138
|
+
) {
|
|
139
|
+
if (!agentSessionId) {
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const sidecarsDir = path.join(root, 'sidecars');
|
|
144
|
+
if (!existsSync(sidecarsDir)) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const fileName = `parent-${agentSessionId}.json`;
|
|
149
|
+
let polygraphSessionId;
|
|
150
|
+
for (const entry of readdirSync(sidecarsDir, { withFileTypes: true })) {
|
|
151
|
+
if (!entry.isDirectory()) continue;
|
|
152
|
+
const candidate = path.join(sidecarsDir, entry.name, fileName);
|
|
153
|
+
if (existsSync(candidate)) {
|
|
154
|
+
try {
|
|
155
|
+
polygraphSessionId = JSON.parse(readFileSync(candidate, 'utf8')).sessionId;
|
|
156
|
+
} catch {
|
|
157
|
+
polygraphSessionId = undefined;
|
|
158
|
+
}
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!polygraphSessionId) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
let session = {};
|
|
167
|
+
try {
|
|
168
|
+
session = JSON.parse(
|
|
169
|
+
readFileSync(
|
|
170
|
+
path.join(root, 'sessions', polygraphSessionId, 'session', 'session.json'),
|
|
171
|
+
'utf8'
|
|
172
|
+
)
|
|
173
|
+
);
|
|
174
|
+
} catch {
|
|
175
|
+
session = {};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
sessionId: polygraphSessionId,
|
|
180
|
+
repos: Array.isArray(session.repos) ? session.repos : [],
|
|
181
|
+
};
|
|
182
|
+
}
|