kibi-opencode 0.5.2 → 0.5.3
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/README.md +13 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -7
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +50 -2
- package/dist/scheduler.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -150,6 +150,19 @@ Config files (project overrides global):
|
|
|
150
150
|
|
|
151
151
|
Per ADR-016, prompt text injection uses only `experimental.chat.system.transform`. The `chat.params` hook is reserved for model option enrichment (temperature, topP, etc.) and never carries prompt text.
|
|
152
152
|
|
|
153
|
+
### Logging Policy
|
|
154
|
+
|
|
155
|
+
The plugin follows a **silent-except-errors** policy for terminal output:
|
|
156
|
+
|
|
157
|
+
| Channel | Terminal | Structured log |
|
|
158
|
+
|---------|----------|---------------|
|
|
159
|
+
| Normal operation (sync success, guidance injection, session summaries) | No | Yes, via `client.app.log()` |
|
|
160
|
+
| Error-class events (bootstrap-needed, sync/check failure, hook/init failure) | Yes, via `console.error` | Yes, via `client.app.log()` |
|
|
161
|
+
|
|
162
|
+
Routine diagnostics route through [`client.app.log()`](https://opencode.ai/docs/plugins/) and never appear in the terminal. Only error-class events break terminal silence. This keeps the developer's workspace clean while preserving full visibility in structured logs for debugging.
|
|
163
|
+
|
|
164
|
+
The `experimental.chat.system.transform` hook handles prompt injection (see [Hook Policy](#hook-policy)). The `chat.params` hook is compatibility-only and never carries prompt text.
|
|
165
|
+
|
|
153
166
|
### Hook Modes
|
|
154
167
|
|
|
155
168
|
- `auto`: Use `experimental.chat.system.transform` (primary); `chat.params` is a no-op registration for host compatibility
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import * as config from "./config.js";
|
|
|
4
4
|
import * as fileFilter from "./file-filter.js";
|
|
5
5
|
import * as logger from "./logger.js";
|
|
6
6
|
import { analyzePath } from "./path-kind.js";
|
|
7
|
-
import {
|
|
7
|
+
import { buildPrompt, SENTINEL } from "./prompt.js";
|
|
8
8
|
import { isMustPriorityRequirement } from "./requirement-doc.js";
|
|
9
9
|
import { createSyncScheduler } from "./scheduler.js";
|
|
10
10
|
import { getSessionTracker } from "./session-tracker.js";
|
|
@@ -56,9 +56,15 @@ const kibiOpencodePlugin = async (input) => {
|
|
|
56
56
|
return {};
|
|
57
57
|
}
|
|
58
58
|
// Check workspace health for bootstrap nudges
|
|
59
|
+
// Reset the logger client first to avoid leaking a previous invocation's
|
|
60
|
+
// client into this instance, then set the new one if provided.
|
|
61
|
+
logger.resetClient();
|
|
62
|
+
if (input.client) {
|
|
63
|
+
logger.setClient(input.client);
|
|
64
|
+
}
|
|
59
65
|
const workspaceHealth = checkWorkspaceHealth(input.worktree);
|
|
60
66
|
if (workspaceHealth.needsBootstrap) {
|
|
61
|
-
logger.
|
|
67
|
+
logger.error("kibi-opencode: workspace needs Kibi bootstrap");
|
|
62
68
|
getSessionTracker().recordWarning("bootstrap-needed", input.worktree, "Workspace missing Kibi bootstrap");
|
|
63
69
|
}
|
|
64
70
|
// Log session summary periodically (gated on config)
|
|
@@ -131,7 +137,7 @@ const kibiOpencodePlugin = async (input) => {
|
|
|
131
137
|
: suggestion.suggestionType === "adr"
|
|
132
138
|
? "long-comment-missed-adr"
|
|
133
139
|
: "missing-traceability";
|
|
134
|
-
logger.
|
|
140
|
+
logger.warn(`kibi-opencode: detected durable ${suggestion.suggestionType} knowledge in ${filePath}`);
|
|
135
141
|
getSessionTracker().recordWarning(warningCategory, filePath, `Consider routing this ${suggestion.suggestionType} knowledge to Kibi instead of inline comments: ${suggestion.reasoning}`);
|
|
136
142
|
}
|
|
137
143
|
}
|
|
@@ -172,15 +178,23 @@ const kibiOpencodePlugin = async (input) => {
|
|
|
172
178
|
const hookMode = cfg.prompt.hookMode;
|
|
173
179
|
if (hookMode === "system-transform" || hookMode === "auto") {
|
|
174
180
|
hooks["experimental.chat.system.transform"] = async (_input, output) => {
|
|
175
|
-
|
|
176
|
-
|
|
181
|
+
// Skip if sentinel already present in any existing entry
|
|
182
|
+
if (output.system.some((entry) => entry.includes(SENTINEL))) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
// Build only the guidance block and append it; existing entries are preserved
|
|
186
|
+
const guidance = buildPrompt({
|
|
177
187
|
recentEdits,
|
|
178
188
|
workspaceHealth,
|
|
179
189
|
hasRecentKbEdit,
|
|
180
190
|
recentCommentSuggestion,
|
|
181
191
|
});
|
|
182
|
-
output.system.length
|
|
183
|
-
|
|
192
|
+
const last = output.system.length > 0
|
|
193
|
+
? output.system[output.system.length - 1]
|
|
194
|
+
: undefined;
|
|
195
|
+
if (last !== guidance) {
|
|
196
|
+
output.system.push(guidance);
|
|
197
|
+
}
|
|
184
198
|
};
|
|
185
199
|
}
|
|
186
200
|
if (hookMode === "chat-params" || hookMode === "auto") {
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
export interface PluginClient {
|
|
2
|
+
app: {
|
|
3
|
+
log: (payload: Record<string, unknown>) => Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
}
|
|
6
|
+
export declare function setClient(c: PluginClient): void;
|
|
7
|
+
export declare function resetClient(): void;
|
|
1
8
|
export declare function info(msg: string): void;
|
|
2
9
|
export declare function warn(msg: string): void;
|
|
3
10
|
export declare function error(msg: string): void;
|
package/dist/logger.js
CHANGED
|
@@ -1,11 +1,59 @@
|
|
|
1
1
|
// implements REQ-opencode-kibi-plugin-v1
|
|
2
|
+
let client = null;
|
|
3
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
4
|
+
export function setClient(c) {
|
|
5
|
+
client = c;
|
|
6
|
+
}
|
|
7
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
8
|
+
export function resetClient() {
|
|
9
|
+
client = null;
|
|
10
|
+
}
|
|
11
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
2
12
|
export function info(msg) {
|
|
3
|
-
|
|
13
|
+
if (client) {
|
|
14
|
+
void client.app
|
|
15
|
+
.log({
|
|
16
|
+
body: {
|
|
17
|
+
service: "kibi-opencode",
|
|
18
|
+
level: "info",
|
|
19
|
+
message: msg,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
.catch(console.error);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
// Fallback when no client is available (e.g. during tests or early init)
|
|
4
26
|
}
|
|
27
|
+
// implements REQ-opencode-kibi-plugin-v1
|
|
5
28
|
export function warn(msg) {
|
|
6
|
-
|
|
29
|
+
if (client) {
|
|
30
|
+
void client.app
|
|
31
|
+
.log({
|
|
32
|
+
body: {
|
|
33
|
+
service: "kibi-opencode",
|
|
34
|
+
level: "warn",
|
|
35
|
+
message: msg,
|
|
36
|
+
},
|
|
37
|
+
})
|
|
38
|
+
.catch(console.error);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
// Fallback when no client is available
|
|
7
42
|
}
|
|
8
43
|
// implements REQ-opencode-kibi-plugin-v1
|
|
9
44
|
export function error(msg) {
|
|
45
|
+
// Always emit to console for user visibility
|
|
10
46
|
console.error("[kibi-opencode]", msg);
|
|
47
|
+
// Also emit to structured logs if client is available
|
|
48
|
+
if (client) {
|
|
49
|
+
void client.app
|
|
50
|
+
.log({
|
|
51
|
+
body: {
|
|
52
|
+
service: "kibi-opencode",
|
|
53
|
+
level: "error",
|
|
54
|
+
message: msg,
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
.catch(console.error);
|
|
58
|
+
}
|
|
11
59
|
}
|
package/dist/scheduler.js
CHANGED
|
@@ -114,7 +114,7 @@ class WorktreeSyncScheduler {
|
|
|
114
114
|
const checkResult = await this.runCheck(this.worktree, checkRules);
|
|
115
115
|
checkExitCode = checkResult.exitCode;
|
|
116
116
|
if (checkExitCode !== 0) {
|
|
117
|
-
logger.
|
|
117
|
+
logger.error(`check.failed ${JSON.stringify({ rules: checkRules, exitCode: checkExitCode })}`);
|
|
118
118
|
}
|
|
119
119
|
else {
|
|
120
120
|
logger.info(`check.succeeded ${JSON.stringify({ rules: checkRules })}`);
|
|
@@ -157,7 +157,7 @@ class WorktreeSyncScheduler {
|
|
|
157
157
|
logger.info(`sync.succeeded ${JSON.stringify(meta)}`);
|
|
158
158
|
}
|
|
159
159
|
else {
|
|
160
|
-
logger.
|
|
160
|
+
logger.error(`sync.failed ${JSON.stringify(meta)}`);
|
|
161
161
|
}
|
|
162
162
|
this.onRunComplete?.(meta);
|
|
163
163
|
}
|