kibi-opencode 0.9.0 → 0.10.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.
Files changed (51) hide show
  1. package/README.md +36 -12
  2. package/dist/brief-intent.d.ts +15 -4
  3. package/dist/brief-intent.js +63 -25
  4. package/dist/briefing-runtime.js +2 -1
  5. package/dist/config.d.ts +3 -0
  6. package/dist/config.js +9 -0
  7. package/dist/e2e-coverage-signals.d.ts +6 -0
  8. package/dist/e2e-coverage-signals.js +186 -0
  9. package/dist/file-entity-links.d.ts +15 -0
  10. package/dist/file-entity-links.js +254 -0
  11. package/dist/file-operation-reminders.d.ts +24 -0
  12. package/dist/file-operation-reminders.js +55 -0
  13. package/dist/file-operation-state.d.ts +29 -0
  14. package/dist/file-operation-state.js +113 -0
  15. package/dist/idle-brief-audit.d.ts +36 -0
  16. package/dist/idle-brief-audit.js +186 -0
  17. package/dist/idle-brief-paths.d.ts +6 -0
  18. package/dist/idle-brief-paths.js +120 -0
  19. package/dist/idle-brief-reader.d.ts +25 -0
  20. package/dist/idle-brief-reader.js +142 -0
  21. package/dist/idle-brief-runtime.d.ts +48 -0
  22. package/dist/idle-brief-runtime.js +443 -0
  23. package/dist/idle-brief-store.d.ts +96 -0
  24. package/dist/idle-brief-store.js +209 -0
  25. package/dist/index.d.ts +14 -1
  26. package/dist/index.js +626 -50
  27. package/dist/init-kibi-alias.d.ts +14 -0
  28. package/dist/init-kibi-alias.js +38 -0
  29. package/dist/init-kibi-capability.d.ts +32 -0
  30. package/dist/init-kibi-capability.js +202 -0
  31. package/dist/logger.js +9 -3
  32. package/dist/plugin-startup.d.ts +1 -0
  33. package/dist/plugin-startup.js +11 -2
  34. package/dist/prompt.d.ts +15 -3
  35. package/dist/prompt.js +103 -33
  36. package/dist/reconcile-engine.d.ts +15 -0
  37. package/dist/reconcile-engine.js +112 -0
  38. package/dist/scheduler.d.ts +1 -0
  39. package/dist/scheduler.js +37 -1
  40. package/dist/session-edit-state.d.ts +25 -0
  41. package/dist/session-edit-state.js +177 -0
  42. package/dist/session-fingerprint.d.ts +11 -0
  43. package/dist/session-fingerprint.js +21 -0
  44. package/dist/source-linked-guidance.d.ts +1 -2
  45. package/dist/source-linked-guidance.js +5 -168
  46. package/dist/startup-notifier.js +42 -31
  47. package/dist/toast.d.ts +21 -22
  48. package/dist/toast.js +36 -14
  49. package/dist/tui-brief-delivery.d.ts +47 -0
  50. package/dist/tui-brief-delivery.js +138 -0
  51. package/package.json +4 -3
@@ -0,0 +1,209 @@
1
+ import * as crypto from "node:crypto";
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null;
4
+ }
5
+ function isStringArray(value) {
6
+ return (Array.isArray(value) && value.every((entry) => typeof entry === "string"));
7
+ }
8
+ function isCitation(value) {
9
+ return isRecord(value) && typeof value.id === "string";
10
+ }
11
+ function isStatement(value) {
12
+ return (isRecord(value) &&
13
+ typeof value.statement === "string" &&
14
+ isStringArray(value.citationIds));
15
+ }
16
+ function isValidationViolation(value) {
17
+ return (isRecord(value) &&
18
+ typeof value.rule === "string" &&
19
+ typeof value.entityId === "string" &&
20
+ typeof value.description === "string");
21
+ }
22
+ function isValidationDiagnostic(value) {
23
+ return (isRecord(value) &&
24
+ typeof value.category === "string" &&
25
+ typeof value.severity === "string" &&
26
+ typeof value.message === "string");
27
+ }
28
+ function isAuditCursor(value) {
29
+ return (isRecord(value) &&
30
+ typeof value.lastTimestamp === "string" &&
31
+ typeof value.lastOperation === "string" &&
32
+ typeof value.entryCount === "number" &&
33
+ typeof value.fileSize === "number");
34
+ }
35
+ function isValidation(value) {
36
+ return (isRecord(value) &&
37
+ Array.isArray(value.violations) &&
38
+ value.violations.every(isValidationViolation) &&
39
+ typeof value.count === "number" &&
40
+ Array.isArray(value.diagnostics) &&
41
+ value.diagnostics.every(isValidationDiagnostic));
42
+ }
43
+ function isBriefingBase(value) {
44
+ return (isRecord(value) &&
45
+ typeof value.tldr === "string" &&
46
+ typeof value.promptBlock === "string" &&
47
+ Array.isArray(value.citations) &&
48
+ value.citations.every(isCitation) &&
49
+ (value.constraints === undefined ||
50
+ (Array.isArray(value.constraints) &&
51
+ value.constraints.every(isStatement))) &&
52
+ (value.regressionRisks === undefined ||
53
+ (Array.isArray(value.regressionRisks) &&
54
+ value.regressionRisks.every(isStatement))) &&
55
+ (value.missingEvidence === undefined ||
56
+ (Array.isArray(value.missingEvidence) &&
57
+ value.missingEvidence.every(isStatement))));
58
+ }
59
+ function isBriefingV2(value) {
60
+ return (isBriefingBase(value) &&
61
+ isStringArray(value.changeNarrative));
62
+ }
63
+ function isChangeItem(value) {
64
+ return (isRecord(value) &&
65
+ typeof value.id === "string" &&
66
+ typeof value.type === "string");
67
+ }
68
+ export function isIdleBriefEnvelope(
69
+ // implements REQ-opencode-kibi-briefing-v4
70
+ value) {
71
+ if (!isRecord(value))
72
+ return false;
73
+ const hasBaseFields = (value.schemaVersion === "1.0" || value.schemaVersion === "2.0") &&
74
+ typeof value.briefId === "string" &&
75
+ (value.type === "success" || value.type === "warning") &&
76
+ typeof value.sessionId === "string" &&
77
+ typeof value.branch === "string" &&
78
+ typeof value.createdAt === "string" &&
79
+ typeof value.unread === "boolean" &&
80
+ isAuditCursor(value.auditCursor) &&
81
+ typeof value.summary === "string" &&
82
+ isValidation(value.validation) &&
83
+ typeof value.contentHash === "string";
84
+ if (!hasBaseFields)
85
+ return false;
86
+ if (value.schemaVersion === "1.0") {
87
+ return (isRecord(value.counts) &&
88
+ typeof value.counts.requirementsAdded === "number" &&
89
+ typeof value.counts.relationshipsAdded === "number" &&
90
+ typeof value.counts.entitiesDeleted === "number" &&
91
+ isBriefingBase(value.briefing));
92
+ }
93
+ return (isRecord(value.counts) &&
94
+ typeof value.counts.entitiesAdded === "number" &&
95
+ typeof value.counts.entitiesModified === "number" &&
96
+ typeof value.counts.entitiesRemoved === "number" &&
97
+ typeof value.counts.relationshipsChanged === "number" &&
98
+ isRecord(value.changes) &&
99
+ isRecord(value.changes.entities) &&
100
+ Array.isArray(value.changes.entities.added) &&
101
+ value.changes.entities.added.every(isChangeItem) &&
102
+ Array.isArray(value.changes.entities.modified) &&
103
+ value.changes.entities.modified.every(isChangeItem) &&
104
+ Array.isArray(value.changes.entities.removed) &&
105
+ value.changes.entities.removed.every(isChangeItem) &&
106
+ isRecord(value.changes.relationships) &&
107
+ typeof value.changes.relationships.changed === "number" &&
108
+ isBriefingV2(value.briefing));
109
+ }
110
+ export function createBriefId() {
111
+ // implements REQ-opencode-kibi-briefing-v4
112
+ return `brief-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
113
+ }
114
+ export function computeContentHash(payload) {
115
+ // implements REQ-opencode-kibi-briefing-v4
116
+ const env = payload;
117
+ // Normalize string: trim and collapse internal whitespace
118
+ const norm = (s) => s.trim().replace(/\s+/g, " ");
119
+ const normalizeCitations = (citations) => citations.map((c) => ({
120
+ id: c.id,
121
+ ...(c.type ? { type: norm(c.type) } : {}),
122
+ ...(c.title ? { title: norm(c.title) } : {}),
123
+ ...(c.source ? { source: norm(c.source) } : {}),
124
+ ...(c.textRef ? { textRef: norm(c.textRef) } : {}),
125
+ }));
126
+ const normalizeStatements = (statements = []) => statements.map((statement) => ({
127
+ statement: norm(statement.statement),
128
+ citationIds: statement.citationIds,
129
+ }));
130
+ const normalizeChangeItems = (items) => items.map((item) => ({
131
+ id: item.id,
132
+ type: norm(item.type),
133
+ ...(item.title ? { title: norm(item.title) } : {}),
134
+ ...(item.source ? { source: norm(item.source) } : {}),
135
+ ...(item.textRef ? { textRef: norm(item.textRef) } : {}),
136
+ }));
137
+ // Build canonical visible-content projection (ignoring volatile fields)
138
+ const projection = env.schemaVersion === "2.0"
139
+ ? {
140
+ schemaVersion: "2.0",
141
+ type: env.type,
142
+ summary: norm(env.summary),
143
+ counts: env.counts,
144
+ changes: {
145
+ entities: {
146
+ added: normalizeChangeItems(env.changes.entities.added),
147
+ modified: normalizeChangeItems(env.changes.entities.modified),
148
+ removed: normalizeChangeItems(env.changes.entities.removed),
149
+ },
150
+ relationships: {
151
+ changed: env.changes.relationships.changed,
152
+ },
153
+ },
154
+ briefing: {
155
+ tldr: norm(env.briefing.tldr),
156
+ normalizedPromptBlock: norm(env.briefing.promptBlock),
157
+ citations: normalizeCitations(env.briefing.citations ?? []),
158
+ changeNarrative: env.briefing.changeNarrative.map((line) => norm(line)),
159
+ constraints: normalizeStatements(env.briefing.constraints),
160
+ regressionRisks: normalizeStatements(env.briefing.regressionRisks),
161
+ missingEvidence: normalizeStatements(env.briefing.missingEvidence),
162
+ },
163
+ validation: {
164
+ count: env.validation.count,
165
+ violations: env.validation.violations.map((v) => ({
166
+ rule: v.rule,
167
+ entityId: v.entityId,
168
+ description: norm(v.description),
169
+ })),
170
+ },
171
+ }
172
+ : {
173
+ type: env.type,
174
+ summary: norm(env.summary),
175
+ counts: env.counts,
176
+ briefing: {
177
+ tldr: norm(env.briefing.tldr),
178
+ normalizedPromptBlock: norm(env.briefing.promptBlock),
179
+ citations: (env.briefing.citations ?? []).map((c) => ({
180
+ id: c.id,
181
+ title: c.title ?? "",
182
+ })),
183
+ constraints: (env.briefing.constraints ?? []).map((c) => ({
184
+ statement: norm(c.statement),
185
+ citationIds: c.citationIds,
186
+ })),
187
+ regressionRisks: (env.briefing.regressionRisks ?? []).map((r) => ({
188
+ statement: norm(r.statement),
189
+ citationIds: r.citationIds,
190
+ })),
191
+ missingEvidence: (env.briefing.missingEvidence ?? []).map((m) => ({
192
+ statement: norm(m.statement),
193
+ citationIds: m.citationIds,
194
+ })),
195
+ },
196
+ validation: {
197
+ count: env.validation.count,
198
+ violations: env.validation.violations.map((v) => ({
199
+ rule: v.rule,
200
+ entityId: v.entityId,
201
+ description: norm(v.description),
202
+ })),
203
+ },
204
+ };
205
+ return crypto
206
+ .createHash("sha256")
207
+ .update(JSON.stringify(projection))
208
+ .digest("hex");
209
+ }
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
+ import { type OpenCodeConfigHookInput } from "./init-kibi-capability.js";
1
2
  export interface PluginInput {
2
3
  worktree: string;
3
4
  directory: string;
5
+ sessionId?: string;
6
+ serverUrl?: unknown;
4
7
  workspace?: string;
5
8
  project?: unknown;
6
- serverUrl?: unknown;
7
9
  $?: unknown;
8
10
  client?: {
9
11
  tui?: {
@@ -13,6 +15,16 @@ export interface PluginInput {
13
15
  message: string;
14
16
  duration?: number;
15
17
  }) => void | Promise<void>;
18
+ showToast?: (payload: {
19
+ body: {
20
+ variant?: "info" | "success" | "warning" | "error";
21
+ title?: string;
22
+ message: string;
23
+ duration?: number;
24
+ };
25
+ }) => void | Promise<void>;
26
+ clearPrompt?: () => void | Promise<void>;
27
+ submitPrompt?: () => void | Promise<void>;
16
28
  };
17
29
  app: {
18
30
  log: (payload: Record<string, unknown>) => Promise<void>;
@@ -31,6 +43,7 @@ interface SystemTransformOutput {
31
43
  }
32
44
  export interface Hooks {
33
45
  event?: (input: EventHookInput) => void | Promise<void>;
46
+ config?: (input: OpenCodeConfigHookInput) => void | Promise<void>;
34
47
  "experimental.chat.system.transform"?: (input: unknown, output: SystemTransformOutput) => void | Promise<void>;
35
48
  "chat.params"?: (input: unknown, output: unknown) => void | Promise<void>;
36
49
  }