clikit-plugin 0.2.26 → 0.2.27
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/index.d.ts +0 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -968
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
2
|
declare const CliKitPlugin: Plugin;
|
|
3
3
|
export default CliKitPlugin;
|
|
4
|
-
export { getBuiltinAgents } from "./agents";
|
|
5
|
-
export { getBuiltinCommands } from "./commands";
|
|
6
|
-
export { getBuiltinSkills, findSkill } from "./skills";
|
|
7
|
-
export type { SkillConfig } from "./skills";
|
|
8
|
-
export { loadCliKitConfig, filterAgents, filterCommands } from "./config";
|
|
9
|
-
export type { CliKitConfig, AgentOverride, LspServerConfig, HooksConfig } from "./config";
|
|
10
|
-
export type { AgentConfig, CommandConfig } from "./types";
|
|
11
|
-
export { checkTodoCompletion, formatIncompleteWarning, isEmptyContent, sanitizeContent, checkDangerousCommand, formatBlockedWarning, scanContentForSecrets, isSensitiveFile, formatSecurityWarning, containsQuestion, isSubagentTool, formatBlockerWarning, checkCommentDensity, hasExcessiveAIComments, formatCommentWarning, collectEnvInfo, buildEnvBlock, formatEnvSummary, shouldFormat, runFormatter, formatAutoFormatLog, isTypeScriptFile, runTypeCheck, formatTypeCheckWarning, sendNotification, buildIdleNotification, buildErrorNotification, formatNotificationLog, shouldTruncate, truncateOutput, formatTruncationLog, collectCompactionPayload, buildCompactionBlock, formatCompactionLog, } from "./hooks";
|
|
12
|
-
export { memoryRead, memorySearch, memoryGet, memoryTimeline, memoryUpdate, memoryAdmin, type MemorySearchParams, type MemorySearchResult, type MemoryObservation, type MemoryUpdateParams, type MemoryTimelineParams, type MemoryAdminParams, type MemoryAdminResult, createObservation, getObservationsByType, getObservationsByBead, linkObservations, type ObservationParams, type ObservationResult, swarm, type SwarmParams, type SwarmTask, type SwarmResult, beadsMemorySync, type BeadsMemorySyncParams, type BeadsMemorySyncResult, quickResearch, type QuickResearchParams, type QuickResearchResult, contextSummary, type ContextSummaryParams, type ContextSummaryResult, } from "./tools";
|
|
13
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA6DlD,QAAA,MAAM,YAAY,EAAE,MAuTnB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AA6DlD,QAAA,MAAM,YAAY,EAAE,MAuTnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4909,918 +4909,6 @@ function formatCompactionLog(payload) {
|
|
|
4909
4909
|
// src/hooks/ritual-enforcer.ts
|
|
4910
4910
|
import * as path8 from "path";
|
|
4911
4911
|
var RITUAL_FILE = path8.join(process.cwd(), ".opencode", "memory", "ritual-state.json");
|
|
4912
|
-
// src/skills/index.ts
|
|
4913
|
-
var import_gray_matter3 = __toESM(require_gray_matter(), 1);
|
|
4914
|
-
import * as fs8 from "fs";
|
|
4915
|
-
import * as path9 from "path";
|
|
4916
|
-
var SKILLS_DIR = path9.join(import.meta.dir, "../skill");
|
|
4917
|
-
function getBuiltinSkills() {
|
|
4918
|
-
const skills = {};
|
|
4919
|
-
if (!fs8.existsSync(SKILLS_DIR)) {
|
|
4920
|
-
console.warn("[CliKit] Skills directory not found:", SKILLS_DIR);
|
|
4921
|
-
return skills;
|
|
4922
|
-
}
|
|
4923
|
-
const skillDirs = fs8.readdirSync(SKILLS_DIR, { withFileTypes: true });
|
|
4924
|
-
for (const dirent of skillDirs) {
|
|
4925
|
-
if (!dirent.isDirectory())
|
|
4926
|
-
continue;
|
|
4927
|
-
const skillName = dirent.name;
|
|
4928
|
-
const skillPath = path9.join(SKILLS_DIR, skillName);
|
|
4929
|
-
const skillMdPath = path9.join(skillPath, "SKILL.md");
|
|
4930
|
-
if (!fs8.existsSync(skillMdPath)) {
|
|
4931
|
-
console.warn(`[CliKit] Missing SKILL.md for skill: ${skillName}`);
|
|
4932
|
-
continue;
|
|
4933
|
-
}
|
|
4934
|
-
try {
|
|
4935
|
-
const fileContent = fs8.readFileSync(skillMdPath, "utf-8");
|
|
4936
|
-
const { data, content } = import_gray_matter3.default(fileContent);
|
|
4937
|
-
skills[skillName] = {
|
|
4938
|
-
name: data.name || skillName,
|
|
4939
|
-
description: data.description || "",
|
|
4940
|
-
content: content.trim(),
|
|
4941
|
-
location: skillPath
|
|
4942
|
-
};
|
|
4943
|
-
} catch (err) {
|
|
4944
|
-
console.warn(`[CliKit] Failed to parse skill ${skillName}:`, err);
|
|
4945
|
-
}
|
|
4946
|
-
}
|
|
4947
|
-
return skills;
|
|
4948
|
-
}
|
|
4949
|
-
function findSkill(skills, query) {
|
|
4950
|
-
if (typeof query !== "string") {
|
|
4951
|
-
return null;
|
|
4952
|
-
}
|
|
4953
|
-
const lowerQuery = query.trim().toLowerCase();
|
|
4954
|
-
if (!lowerQuery) {
|
|
4955
|
-
return null;
|
|
4956
|
-
}
|
|
4957
|
-
if (skills[lowerQuery]) {
|
|
4958
|
-
return skills[lowerQuery];
|
|
4959
|
-
}
|
|
4960
|
-
for (const [name, skill] of Object.entries(skills)) {
|
|
4961
|
-
const skillName = (skill.name || "").toLowerCase();
|
|
4962
|
-
if (name.toLowerCase().includes(lowerQuery) || skillName.includes(lowerQuery)) {
|
|
4963
|
-
return skill;
|
|
4964
|
-
}
|
|
4965
|
-
}
|
|
4966
|
-
for (const skill of Object.values(skills)) {
|
|
4967
|
-
const description = (skill.description || "").toLowerCase();
|
|
4968
|
-
if (description.includes(lowerQuery)) {
|
|
4969
|
-
return skill;
|
|
4970
|
-
}
|
|
4971
|
-
}
|
|
4972
|
-
return null;
|
|
4973
|
-
}
|
|
4974
|
-
// src/tools/memory.ts
|
|
4975
|
-
import * as path10 from "path";
|
|
4976
|
-
import * as fs9 from "fs";
|
|
4977
|
-
import { Database } from "bun:sqlite";
|
|
4978
|
-
var MEMORY_DIR = path10.join(process.cwd(), ".opencode", "memory");
|
|
4979
|
-
var MEMORY_DB = path10.join(MEMORY_DIR, "memory.db");
|
|
4980
|
-
function parseStringArray(value) {
|
|
4981
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
4982
|
-
return [];
|
|
4983
|
-
}
|
|
4984
|
-
try {
|
|
4985
|
-
const parsed = JSON.parse(value);
|
|
4986
|
-
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
4987
|
-
} catch {
|
|
4988
|
-
return [];
|
|
4989
|
-
}
|
|
4990
|
-
}
|
|
4991
|
-
function normalizeLimit(value, fallback = 10) {
|
|
4992
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4993
|
-
return fallback;
|
|
4994
|
-
}
|
|
4995
|
-
return Math.max(1, Math.floor(value));
|
|
4996
|
-
}
|
|
4997
|
-
function getDb() {
|
|
4998
|
-
if (!fs9.existsSync(MEMORY_DIR)) {
|
|
4999
|
-
fs9.mkdirSync(MEMORY_DIR, { recursive: true });
|
|
5000
|
-
}
|
|
5001
|
-
const db = new Database(MEMORY_DB);
|
|
5002
|
-
db.exec(`
|
|
5003
|
-
CREATE TABLE IF NOT EXISTS observations (
|
|
5004
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
5005
|
-
type TEXT NOT NULL,
|
|
5006
|
-
narrative TEXT NOT NULL,
|
|
5007
|
-
facts TEXT DEFAULT '[]',
|
|
5008
|
-
confidence REAL DEFAULT 1.0,
|
|
5009
|
-
files_read TEXT DEFAULT '[]',
|
|
5010
|
-
files_modified TEXT DEFAULT '[]',
|
|
5011
|
-
concepts TEXT DEFAULT '[]',
|
|
5012
|
-
bead_id TEXT,
|
|
5013
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
5014
|
-
expires_at TEXT
|
|
5015
|
-
);
|
|
5016
|
-
|
|
5017
|
-
CREATE VIRTUAL TABLE IF NOT EXISTS observations_fts USING fts5(
|
|
5018
|
-
id UNINDEXED,
|
|
5019
|
-
type,
|
|
5020
|
-
narrative,
|
|
5021
|
-
facts,
|
|
5022
|
-
content='observations',
|
|
5023
|
-
content_rowid='id'
|
|
5024
|
-
);
|
|
5025
|
-
|
|
5026
|
-
CREATE TRIGGER IF NOT EXISTS observations_ai AFTER INSERT ON observations BEGIN
|
|
5027
|
-
INSERT INTO observations_fts (id, type, narrative, facts)
|
|
5028
|
-
VALUES (new.id, new.type, new.narrative, new.facts);
|
|
5029
|
-
END;
|
|
5030
|
-
|
|
5031
|
-
CREATE TRIGGER IF NOT EXISTS observations_ad AFTER DELETE ON observations BEGIN
|
|
5032
|
-
INSERT INTO observations_fts (observations_fts, id, type, narrative, facts)
|
|
5033
|
-
VALUES ('delete', old.id, old.type, old.narrative, old.facts);
|
|
5034
|
-
END;
|
|
5035
|
-
|
|
5036
|
-
CREATE TRIGGER IF NOT EXISTS observations_au AFTER UPDATE ON observations BEGIN
|
|
5037
|
-
INSERT INTO observations_fts (observations_fts, id, type, narrative, facts)
|
|
5038
|
-
VALUES ('delete', old.id, old.type, old.narrative, old.facts);
|
|
5039
|
-
INSERT INTO observations_fts (id, type, narrative, facts)
|
|
5040
|
-
VALUES (new.id, new.type, new.narrative, new.facts);
|
|
5041
|
-
END;
|
|
5042
|
-
`);
|
|
5043
|
-
try {
|
|
5044
|
-
db.exec(`ALTER TABLE observations ADD COLUMN concepts TEXT DEFAULT '[]'`);
|
|
5045
|
-
} catch {}
|
|
5046
|
-
try {
|
|
5047
|
-
db.exec(`ALTER TABLE observations ADD COLUMN bead_id TEXT`);
|
|
5048
|
-
} catch {}
|
|
5049
|
-
try {
|
|
5050
|
-
db.exec(`ALTER TABLE observations ADD COLUMN expires_at TEXT`);
|
|
5051
|
-
} catch {}
|
|
5052
|
-
return db;
|
|
5053
|
-
}
|
|
5054
|
-
function memoryRead(relativePath) {
|
|
5055
|
-
if (typeof relativePath !== "string" || !relativePath.trim()) {
|
|
5056
|
-
return null;
|
|
5057
|
-
}
|
|
5058
|
-
const fullPath = path10.join(MEMORY_DIR, relativePath);
|
|
5059
|
-
if (!fs9.existsSync(fullPath)) {
|
|
5060
|
-
return null;
|
|
5061
|
-
}
|
|
5062
|
-
return fs9.readFileSync(fullPath, "utf-8");
|
|
5063
|
-
}
|
|
5064
|
-
function memorySearch(params) {
|
|
5065
|
-
if (!params || typeof params !== "object") {
|
|
5066
|
-
return [];
|
|
5067
|
-
}
|
|
5068
|
-
const p = params;
|
|
5069
|
-
if (!p.query || typeof p.query !== "string") {
|
|
5070
|
-
return [];
|
|
5071
|
-
}
|
|
5072
|
-
const db = getDb();
|
|
5073
|
-
const limit = normalizeLimit(p.limit, 10);
|
|
5074
|
-
let sql;
|
|
5075
|
-
let args;
|
|
5076
|
-
if (p.type) {
|
|
5077
|
-
sql = `
|
|
5078
|
-
SELECT o.id, o.type, o.narrative, o.confidence, o.created_at
|
|
5079
|
-
FROM observations o
|
|
5080
|
-
JOIN observations_fts fts ON o.id = fts.id
|
|
5081
|
-
WHERE observations_fts MATCH ? AND o.type = ?
|
|
5082
|
-
ORDER BY o.confidence DESC, o.created_at DESC
|
|
5083
|
-
LIMIT ?
|
|
5084
|
-
`;
|
|
5085
|
-
args = [p.query, p.type, limit];
|
|
5086
|
-
} else {
|
|
5087
|
-
sql = `
|
|
5088
|
-
SELECT o.id, o.type, o.narrative, o.confidence, o.created_at
|
|
5089
|
-
FROM observations o
|
|
5090
|
-
JOIN observations_fts fts ON o.id = fts.id
|
|
5091
|
-
WHERE observations_fts MATCH ?
|
|
5092
|
-
ORDER BY o.confidence DESC, o.created_at DESC
|
|
5093
|
-
LIMIT ?
|
|
5094
|
-
`;
|
|
5095
|
-
args = [p.query, limit];
|
|
5096
|
-
}
|
|
5097
|
-
const rows = db.prepare(sql).all(...args);
|
|
5098
|
-
return rows;
|
|
5099
|
-
}
|
|
5100
|
-
function memoryGet(ids) {
|
|
5101
|
-
if (typeof ids !== "string" || !ids) {
|
|
5102
|
-
return [];
|
|
5103
|
-
}
|
|
5104
|
-
const db = getDb();
|
|
5105
|
-
const idList = ids.split(",").map((id) => parseInt(id.trim(), 10)).filter((id) => Number.isFinite(id));
|
|
5106
|
-
if (idList.length === 0) {
|
|
5107
|
-
return [];
|
|
5108
|
-
}
|
|
5109
|
-
const placeholders = idList.map(() => "?").join(",");
|
|
5110
|
-
const sql = `SELECT * FROM observations WHERE id IN (${placeholders})`;
|
|
5111
|
-
const rows = db.prepare(sql).all(...idList);
|
|
5112
|
-
return rows.map((row) => ({
|
|
5113
|
-
...row,
|
|
5114
|
-
facts: parseStringArray(row.facts),
|
|
5115
|
-
files_read: parseStringArray(row.files_read),
|
|
5116
|
-
files_modified: parseStringArray(row.files_modified)
|
|
5117
|
-
}));
|
|
5118
|
-
}
|
|
5119
|
-
function memoryTimeline(params) {
|
|
5120
|
-
if (!params || typeof params !== "object") {
|
|
5121
|
-
return [];
|
|
5122
|
-
}
|
|
5123
|
-
const p = params;
|
|
5124
|
-
if (typeof p.id !== "number") {
|
|
5125
|
-
return [];
|
|
5126
|
-
}
|
|
5127
|
-
const db = getDb();
|
|
5128
|
-
const before = normalizeLimit(p.before, 3);
|
|
5129
|
-
const after = normalizeLimit(p.after, 3);
|
|
5130
|
-
const sql = `
|
|
5131
|
-
SELECT * FROM (
|
|
5132
|
-
SELECT * FROM observations WHERE id < ? ORDER BY id DESC LIMIT ?
|
|
5133
|
-
UNION
|
|
5134
|
-
SELECT * FROM observations WHERE id = ?
|
|
5135
|
-
UNION
|
|
5136
|
-
SELECT * FROM observations WHERE id > ? ORDER BY id ASC LIMIT ?
|
|
5137
|
-
) ORDER BY id ASC
|
|
5138
|
-
`;
|
|
5139
|
-
const rows = db.prepare(sql).all(p.id, before, p.id, p.id, after);
|
|
5140
|
-
return rows.map((row) => ({
|
|
5141
|
-
...row,
|
|
5142
|
-
facts: parseStringArray(row.facts),
|
|
5143
|
-
files_read: parseStringArray(row.files_read),
|
|
5144
|
-
files_modified: parseStringArray(row.files_modified)
|
|
5145
|
-
}));
|
|
5146
|
-
}
|
|
5147
|
-
function memoryUpdate(params) {
|
|
5148
|
-
if (!params || typeof params !== "object") {
|
|
5149
|
-
return null;
|
|
5150
|
-
}
|
|
5151
|
-
const p = params;
|
|
5152
|
-
if (!p.type || !p.narrative) {
|
|
5153
|
-
return null;
|
|
5154
|
-
}
|
|
5155
|
-
const db = getDb();
|
|
5156
|
-
const sql = `
|
|
5157
|
-
INSERT INTO observations (type, narrative, facts, confidence, files_read, files_modified, expires_at)
|
|
5158
|
-
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
5159
|
-
`;
|
|
5160
|
-
const result = db.prepare(sql).run(p.type, p.narrative, JSON.stringify(p.facts || []), p.confidence || 1, JSON.stringify(p.files_read || []), JSON.stringify(p.files_modified || []), p.expires_at || null);
|
|
5161
|
-
return { id: result.lastInsertRowid };
|
|
5162
|
-
}
|
|
5163
|
-
function memoryAdmin(params) {
|
|
5164
|
-
if (!params || typeof params !== "object") {
|
|
5165
|
-
return { operation: "unknown", success: false, details: { error: "Invalid params" } };
|
|
5166
|
-
}
|
|
5167
|
-
const p = params;
|
|
5168
|
-
if (!p.operation) {
|
|
5169
|
-
return { operation: "unknown", success: false, details: { error: "Missing operation" } };
|
|
5170
|
-
}
|
|
5171
|
-
const db = getDb();
|
|
5172
|
-
switch (p.operation) {
|
|
5173
|
-
case "status": {
|
|
5174
|
-
const count = db.prepare("SELECT COUNT(*) as count FROM observations").get();
|
|
5175
|
-
const types = db.prepare("SELECT type, COUNT(*) as count FROM observations GROUP BY type").all();
|
|
5176
|
-
return {
|
|
5177
|
-
operation: "status",
|
|
5178
|
-
success: true,
|
|
5179
|
-
details: { total_observations: count.count, by_type: types }
|
|
5180
|
-
};
|
|
5181
|
-
}
|
|
5182
|
-
case "archive": {
|
|
5183
|
-
const days = p.older_than_days || 90;
|
|
5184
|
-
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000).toISOString();
|
|
5185
|
-
if (p.dry_run) {
|
|
5186
|
-
const count = db.prepare("SELECT COUNT(*) as count FROM observations WHERE created_at < ?").get(cutoff);
|
|
5187
|
-
return {
|
|
5188
|
-
operation: "archive",
|
|
5189
|
-
success: true,
|
|
5190
|
-
details: { would_archive: count.count, cutoff_date: cutoff }
|
|
5191
|
-
};
|
|
5192
|
-
}
|
|
5193
|
-
const result = db.prepare("DELETE FROM observations WHERE created_at < ?").run(cutoff);
|
|
5194
|
-
return {
|
|
5195
|
-
operation: "archive",
|
|
5196
|
-
success: true,
|
|
5197
|
-
details: { archived: result.changes, cutoff_date: cutoff }
|
|
5198
|
-
};
|
|
5199
|
-
}
|
|
5200
|
-
case "checkpoint": {
|
|
5201
|
-
const checkpointPath = path10.join(MEMORY_DIR, `checkpoint-${Date.now()}.db`);
|
|
5202
|
-
fs9.copyFileSync(MEMORY_DB, checkpointPath);
|
|
5203
|
-
return {
|
|
5204
|
-
operation: "checkpoint",
|
|
5205
|
-
success: true,
|
|
5206
|
-
details: { checkpoint_path: checkpointPath }
|
|
5207
|
-
};
|
|
5208
|
-
}
|
|
5209
|
-
case "vacuum": {
|
|
5210
|
-
db.exec("VACUUM");
|
|
5211
|
-
const stats = fs9.statSync(MEMORY_DB);
|
|
5212
|
-
return {
|
|
5213
|
-
operation: "vacuum",
|
|
5214
|
-
success: true,
|
|
5215
|
-
details: { db_size_bytes: stats.size }
|
|
5216
|
-
};
|
|
5217
|
-
}
|
|
5218
|
-
case "migrate": {
|
|
5219
|
-
return {
|
|
5220
|
-
operation: "migrate",
|
|
5221
|
-
success: true,
|
|
5222
|
-
details: { message: "Migration not implemented - SQLite is already the storage backend" }
|
|
5223
|
-
};
|
|
5224
|
-
}
|
|
5225
|
-
default:
|
|
5226
|
-
return {
|
|
5227
|
-
operation: p.operation || "unknown",
|
|
5228
|
-
success: false,
|
|
5229
|
-
details: { error: "Unknown operation" }
|
|
5230
|
-
};
|
|
5231
|
-
}
|
|
5232
|
-
}
|
|
5233
|
-
// src/tools/observation.ts
|
|
5234
|
-
import * as path11 from "path";
|
|
5235
|
-
import * as fs10 from "fs";
|
|
5236
|
-
import { Database as Database2 } from "bun:sqlite";
|
|
5237
|
-
var MEMORY_DIR2 = path11.join(process.cwd(), ".opencode", "memory");
|
|
5238
|
-
var MEMORY_DB2 = path11.join(MEMORY_DIR2, "memory.db");
|
|
5239
|
-
function parseStringArray2(value) {
|
|
5240
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
5241
|
-
return [];
|
|
5242
|
-
}
|
|
5243
|
-
try {
|
|
5244
|
-
const parsed = JSON.parse(value);
|
|
5245
|
-
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
5246
|
-
} catch {
|
|
5247
|
-
return [];
|
|
5248
|
-
}
|
|
5249
|
-
}
|
|
5250
|
-
function normalizeLimit2(value, fallback = 10) {
|
|
5251
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
5252
|
-
return fallback;
|
|
5253
|
-
}
|
|
5254
|
-
return Math.max(1, Math.floor(value));
|
|
5255
|
-
}
|
|
5256
|
-
function getDb2() {
|
|
5257
|
-
if (!fs10.existsSync(MEMORY_DIR2)) {
|
|
5258
|
-
fs10.mkdirSync(MEMORY_DIR2, { recursive: true });
|
|
5259
|
-
}
|
|
5260
|
-
const db = new Database2(MEMORY_DB2);
|
|
5261
|
-
db.exec(`
|
|
5262
|
-
CREATE TABLE IF NOT EXISTS observations (
|
|
5263
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
5264
|
-
type TEXT NOT NULL,
|
|
5265
|
-
narrative TEXT NOT NULL,
|
|
5266
|
-
facts TEXT DEFAULT '[]',
|
|
5267
|
-
confidence REAL DEFAULT 1.0,
|
|
5268
|
-
files_read TEXT DEFAULT '[]',
|
|
5269
|
-
files_modified TEXT DEFAULT '[]',
|
|
5270
|
-
concepts TEXT DEFAULT '[]',
|
|
5271
|
-
bead_id TEXT,
|
|
5272
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
5273
|
-
expires_at TEXT
|
|
5274
|
-
);
|
|
5275
|
-
|
|
5276
|
-
CREATE INDEX IF NOT EXISTS idx_observations_type ON observations(type);
|
|
5277
|
-
CREATE INDEX IF NOT EXISTS idx_observations_bead_id ON observations(bead_id);
|
|
5278
|
-
CREATE INDEX IF NOT EXISTS idx_observations_created_at ON observations(created_at);
|
|
5279
|
-
`);
|
|
5280
|
-
try {
|
|
5281
|
-
db.exec(`ALTER TABLE observations ADD COLUMN concepts TEXT DEFAULT '[]'`);
|
|
5282
|
-
} catch {}
|
|
5283
|
-
try {
|
|
5284
|
-
db.exec(`ALTER TABLE observations ADD COLUMN bead_id TEXT`);
|
|
5285
|
-
} catch {}
|
|
5286
|
-
try {
|
|
5287
|
-
db.exec(`ALTER TABLE observations ADD COLUMN expires_at TEXT`);
|
|
5288
|
-
} catch {}
|
|
5289
|
-
return db;
|
|
5290
|
-
}
|
|
5291
|
-
function createObservation(params) {
|
|
5292
|
-
if (!params || typeof params !== "object") {
|
|
5293
|
-
return null;
|
|
5294
|
-
}
|
|
5295
|
-
const p = params;
|
|
5296
|
-
if (!p.type || !p.narrative) {
|
|
5297
|
-
return null;
|
|
5298
|
-
}
|
|
5299
|
-
const db = getDb2();
|
|
5300
|
-
const sql = `
|
|
5301
|
-
INSERT INTO observations (type, narrative, facts, confidence, files_read, files_modified, concepts, bead_id, expires_at)
|
|
5302
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
5303
|
-
`;
|
|
5304
|
-
const result = db.prepare(sql).run(p.type, p.narrative, JSON.stringify(p.facts || []), p.confidence || 1, JSON.stringify(p.files_read || []), JSON.stringify(p.files_modified || []), JSON.stringify(p.concepts || []), p.bead_id || null, p.expires_at || null);
|
|
5305
|
-
return {
|
|
5306
|
-
id: result.lastInsertRowid,
|
|
5307
|
-
type: p.type,
|
|
5308
|
-
narrative: p.narrative,
|
|
5309
|
-
facts: p.facts || [],
|
|
5310
|
-
confidence: p.confidence || 1,
|
|
5311
|
-
files_read: p.files_read || [],
|
|
5312
|
-
files_modified: p.files_modified || [],
|
|
5313
|
-
concepts: p.concepts || [],
|
|
5314
|
-
bead_id: p.bead_id,
|
|
5315
|
-
created_at: new Date().toISOString()
|
|
5316
|
-
};
|
|
5317
|
-
}
|
|
5318
|
-
function getObservationsByType(type, limit = 10) {
|
|
5319
|
-
if (typeof type !== "string" || !type.trim()) {
|
|
5320
|
-
return [];
|
|
5321
|
-
}
|
|
5322
|
-
const db = getDb2();
|
|
5323
|
-
const safeLimit = normalizeLimit2(limit, 10);
|
|
5324
|
-
const sql = `SELECT * FROM observations WHERE type = ? ORDER BY created_at DESC LIMIT ?`;
|
|
5325
|
-
let rows = [];
|
|
5326
|
-
try {
|
|
5327
|
-
rows = db.prepare(sql).all(type.trim(), safeLimit);
|
|
5328
|
-
} catch (err) {
|
|
5329
|
-
if (err instanceof Error && /datatype mismatch/i.test(err.message)) {
|
|
5330
|
-
try {
|
|
5331
|
-
rows = db.prepare(sql).all(type.trim(), String(safeLimit));
|
|
5332
|
-
} catch {
|
|
5333
|
-
return [];
|
|
5334
|
-
}
|
|
5335
|
-
} else {
|
|
5336
|
-
return [];
|
|
5337
|
-
}
|
|
5338
|
-
}
|
|
5339
|
-
return rows.map((row) => ({
|
|
5340
|
-
...row,
|
|
5341
|
-
facts: parseStringArray2(row.facts),
|
|
5342
|
-
files_read: parseStringArray2(row.files_read),
|
|
5343
|
-
files_modified: parseStringArray2(row.files_modified),
|
|
5344
|
-
concepts: parseStringArray2(row.concepts)
|
|
5345
|
-
}));
|
|
5346
|
-
}
|
|
5347
|
-
function getObservationsByBead(beadId) {
|
|
5348
|
-
if (typeof beadId !== "string" || !beadId.trim()) {
|
|
5349
|
-
return [];
|
|
5350
|
-
}
|
|
5351
|
-
const db = getDb2();
|
|
5352
|
-
const sql = `SELECT * FROM observations WHERE bead_id = ? ORDER BY created_at DESC`;
|
|
5353
|
-
let rows = [];
|
|
5354
|
-
try {
|
|
5355
|
-
rows = db.prepare(sql).all(beadId.trim());
|
|
5356
|
-
} catch {
|
|
5357
|
-
return [];
|
|
5358
|
-
}
|
|
5359
|
-
return rows.map((row) => ({
|
|
5360
|
-
...row,
|
|
5361
|
-
facts: parseStringArray2(row.facts),
|
|
5362
|
-
files_read: parseStringArray2(row.files_read),
|
|
5363
|
-
files_modified: parseStringArray2(row.files_modified),
|
|
5364
|
-
concepts: parseStringArray2(row.concepts)
|
|
5365
|
-
}));
|
|
5366
|
-
}
|
|
5367
|
-
function linkObservations(observationId, concept) {
|
|
5368
|
-
const db = getDb2();
|
|
5369
|
-
const row = db.prepare("SELECT concepts FROM observations WHERE id = ?").get(observationId);
|
|
5370
|
-
if (row) {
|
|
5371
|
-
const concepts = parseStringArray2(row.concepts);
|
|
5372
|
-
if (!concepts.includes(concept)) {
|
|
5373
|
-
concepts.push(concept);
|
|
5374
|
-
db.prepare("UPDATE observations SET concepts = ? WHERE id = ?").run(JSON.stringify(concepts), observationId);
|
|
5375
|
-
}
|
|
5376
|
-
}
|
|
5377
|
-
}
|
|
5378
|
-
// src/tools/swarm.ts
|
|
5379
|
-
var swarmState = {
|
|
5380
|
-
planId: null,
|
|
5381
|
-
tasks: new Map,
|
|
5382
|
-
parallelism: 3
|
|
5383
|
-
};
|
|
5384
|
-
function swarm(params) {
|
|
5385
|
-
if (!params || typeof params !== "object") {
|
|
5386
|
-
return { planId: "none", tasks: [], parallelism: 3, estimatedTime: "0m" };
|
|
5387
|
-
}
|
|
5388
|
-
const p = params;
|
|
5389
|
-
switch (p.operation) {
|
|
5390
|
-
case "plan":
|
|
5391
|
-
return swarmPlan(p);
|
|
5392
|
-
case "monitor":
|
|
5393
|
-
return swarmMonitor(p);
|
|
5394
|
-
case "delegate":
|
|
5395
|
-
return swarmDelegate(p);
|
|
5396
|
-
case "abort":
|
|
5397
|
-
return swarmAbort(p);
|
|
5398
|
-
default:
|
|
5399
|
-
return { planId: "none", tasks: [], parallelism: 3, estimatedTime: "0m" };
|
|
5400
|
-
}
|
|
5401
|
-
}
|
|
5402
|
-
function swarmPlan(params) {
|
|
5403
|
-
const planId = `swarm-${Date.now()}`;
|
|
5404
|
-
swarmState.planId = planId;
|
|
5405
|
-
swarmState.tasks.clear();
|
|
5406
|
-
swarmState.parallelism = params.parallelism || 3;
|
|
5407
|
-
for (const task of params.tasks) {
|
|
5408
|
-
swarmState.tasks.set(task.id, { ...task, status: task.status || "pending" });
|
|
5409
|
-
}
|
|
5410
|
-
const completedDeps = findReadyTasks();
|
|
5411
|
-
for (const taskId of completedDeps) {
|
|
5412
|
-
const task = swarmState.tasks.get(taskId);
|
|
5413
|
-
if (task && task.status === "pending") {
|
|
5414
|
-
task.status = "in_progress";
|
|
5415
|
-
}
|
|
5416
|
-
}
|
|
5417
|
-
return {
|
|
5418
|
-
planId,
|
|
5419
|
-
tasks: Array.from(swarmState.tasks.values()),
|
|
5420
|
-
parallelism: swarmState.parallelism,
|
|
5421
|
-
estimatedTime: estimateTime(params.tasks)
|
|
5422
|
-
};
|
|
5423
|
-
}
|
|
5424
|
-
function swarmMonitor(params) {
|
|
5425
|
-
const tasks = Array.from(swarmState.tasks.values());
|
|
5426
|
-
if (params.taskId) {
|
|
5427
|
-
const task = swarmState.tasks.get(params.taskId);
|
|
5428
|
-
if (!task) {
|
|
5429
|
-
throw new Error(`Task not found: ${params.taskId}`);
|
|
5430
|
-
}
|
|
5431
|
-
}
|
|
5432
|
-
return {
|
|
5433
|
-
planId: swarmState.planId || "none",
|
|
5434
|
-
totalTasks: tasks.length,
|
|
5435
|
-
completed: tasks.filter((t) => t.status === "completed").length,
|
|
5436
|
-
inProgress: tasks.filter((t) => t.status === "in_progress").length,
|
|
5437
|
-
pending: tasks.filter((t) => t.status === "pending").length,
|
|
5438
|
-
failed: tasks.filter((t) => t.status === "failed").length,
|
|
5439
|
-
tasks
|
|
5440
|
-
};
|
|
5441
|
-
}
|
|
5442
|
-
function swarmDelegate(params) {
|
|
5443
|
-
const task = swarmState.tasks.get(params.taskId);
|
|
5444
|
-
if (!task) {
|
|
5445
|
-
throw new Error(`Task not found: ${params.taskId}`);
|
|
5446
|
-
}
|
|
5447
|
-
task.agentRole = params.agentRole;
|
|
5448
|
-
task.status = "in_progress";
|
|
5449
|
-
return {
|
|
5450
|
-
taskId: params.taskId,
|
|
5451
|
-
delegatedTo: `@${params.agentRole}`,
|
|
5452
|
-
status: "delegated"
|
|
5453
|
-
};
|
|
5454
|
-
}
|
|
5455
|
-
function swarmAbort(params) {
|
|
5456
|
-
const task = swarmState.tasks.get(params.taskId);
|
|
5457
|
-
if (!task) {
|
|
5458
|
-
throw new Error(`Task not found: ${params.taskId}`);
|
|
5459
|
-
}
|
|
5460
|
-
task.status = "failed";
|
|
5461
|
-
return {
|
|
5462
|
-
taskId: params.taskId,
|
|
5463
|
-
aborted: true,
|
|
5464
|
-
reason: params.reason
|
|
5465
|
-
};
|
|
5466
|
-
}
|
|
5467
|
-
function findReadyTasks() {
|
|
5468
|
-
const ready = [];
|
|
5469
|
-
for (const [id, task] of swarmState.tasks) {
|
|
5470
|
-
if (task.status !== "pending")
|
|
5471
|
-
continue;
|
|
5472
|
-
const deps = task.dependencies || [];
|
|
5473
|
-
const allDepsComplete = deps.every((depId) => {
|
|
5474
|
-
const dep = swarmState.tasks.get(depId);
|
|
5475
|
-
return dep && dep.status === "completed";
|
|
5476
|
-
});
|
|
5477
|
-
if (allDepsComplete) {
|
|
5478
|
-
ready.push(id);
|
|
5479
|
-
}
|
|
5480
|
-
}
|
|
5481
|
-
return ready;
|
|
5482
|
-
}
|
|
5483
|
-
function estimateTime(tasks) {
|
|
5484
|
-
const totalTasks = tasks.length;
|
|
5485
|
-
const parallelism = swarmState.parallelism;
|
|
5486
|
-
const avgTaskTime = 5;
|
|
5487
|
-
const batches = Math.ceil(totalTasks / parallelism);
|
|
5488
|
-
const totalMinutes = batches * avgTaskTime;
|
|
5489
|
-
if (totalMinutes < 60) {
|
|
5490
|
-
return `${totalMinutes} minutes`;
|
|
5491
|
-
} else {
|
|
5492
|
-
const hours = Math.floor(totalMinutes / 60);
|
|
5493
|
-
const mins = totalMinutes % 60;
|
|
5494
|
-
return `${hours}h ${mins}m`;
|
|
5495
|
-
}
|
|
5496
|
-
}
|
|
5497
|
-
// src/tools/beads-memory-sync.ts
|
|
5498
|
-
import * as path12 from "path";
|
|
5499
|
-
import * as fs11 from "fs";
|
|
5500
|
-
import { Database as Database3 } from "bun:sqlite";
|
|
5501
|
-
var MEMORY_DIR3 = path12.join(process.cwd(), ".opencode", "memory");
|
|
5502
|
-
var BEADS_DIR = path12.join(process.cwd(), ".beads");
|
|
5503
|
-
var MEMORY_DB3 = path12.join(MEMORY_DIR3, "memory.db");
|
|
5504
|
-
function getMemoryDb() {
|
|
5505
|
-
if (!fs11.existsSync(MEMORY_DIR3)) {
|
|
5506
|
-
fs11.mkdirSync(MEMORY_DIR3, { recursive: true });
|
|
5507
|
-
}
|
|
5508
|
-
const db = new Database3(MEMORY_DB3);
|
|
5509
|
-
db.exec(`
|
|
5510
|
-
CREATE TABLE IF NOT EXISTS observations (
|
|
5511
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
5512
|
-
type TEXT NOT NULL,
|
|
5513
|
-
narrative TEXT NOT NULL,
|
|
5514
|
-
facts TEXT DEFAULT '[]',
|
|
5515
|
-
confidence REAL DEFAULT 1.0,
|
|
5516
|
-
files_read TEXT DEFAULT '[]',
|
|
5517
|
-
files_modified TEXT DEFAULT '[]',
|
|
5518
|
-
concepts TEXT DEFAULT '[]',
|
|
5519
|
-
bead_id TEXT,
|
|
5520
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
5521
|
-
expires_at TEXT
|
|
5522
|
-
)
|
|
5523
|
-
`);
|
|
5524
|
-
try {
|
|
5525
|
-
db.exec(`ALTER TABLE observations ADD COLUMN concepts TEXT DEFAULT '[]'`);
|
|
5526
|
-
} catch {}
|
|
5527
|
-
try {
|
|
5528
|
-
db.exec(`ALTER TABLE observations ADD COLUMN bead_id TEXT`);
|
|
5529
|
-
} catch {}
|
|
5530
|
-
try {
|
|
5531
|
-
db.exec(`ALTER TABLE observations ADD COLUMN expires_at TEXT`);
|
|
5532
|
-
} catch {}
|
|
5533
|
-
return db;
|
|
5534
|
-
}
|
|
5535
|
-
function getBeadsDb() {
|
|
5536
|
-
const beadsDbPath = path12.join(BEADS_DIR, "beads.db");
|
|
5537
|
-
if (!fs11.existsSync(beadsDbPath)) {
|
|
5538
|
-
return null;
|
|
5539
|
-
}
|
|
5540
|
-
return new Database3(beadsDbPath);
|
|
5541
|
-
}
|
|
5542
|
-
function beadsMemorySync(params) {
|
|
5543
|
-
if (!params || typeof params !== "object") {
|
|
5544
|
-
return { success: false, operation: "unknown", details: {} };
|
|
5545
|
-
}
|
|
5546
|
-
const p = params;
|
|
5547
|
-
if (!p.operation) {
|
|
5548
|
-
return { success: false, operation: "unknown", details: {} };
|
|
5549
|
-
}
|
|
5550
|
-
switch (p.operation) {
|
|
5551
|
-
case "sync_to_memory":
|
|
5552
|
-
return syncTasksToMemory();
|
|
5553
|
-
case "sync_from_memory":
|
|
5554
|
-
return syncMemoryToTasks();
|
|
5555
|
-
case "link":
|
|
5556
|
-
if (!p.beadId || !p.observationId) {
|
|
5557
|
-
return { success: false, operation: "link", details: {} };
|
|
5558
|
-
}
|
|
5559
|
-
return linkObservationToTask(p.observationId, p.beadId);
|
|
5560
|
-
case "status":
|
|
5561
|
-
return getSyncStatus();
|
|
5562
|
-
default:
|
|
5563
|
-
return { success: false, operation: p.operation, details: {} };
|
|
5564
|
-
}
|
|
5565
|
-
}
|
|
5566
|
-
function syncTasksToMemory() {
|
|
5567
|
-
const beadsDb = getBeadsDb();
|
|
5568
|
-
if (!beadsDb) {
|
|
5569
|
-
return { success: false, operation: "sync_to_memory", details: { tasksSynced: 0 } };
|
|
5570
|
-
}
|
|
5571
|
-
const memoryDb = getMemoryDb();
|
|
5572
|
-
const tasks = beadsDb.query("SELECT * FROM issues WHERE status = 'done'").all();
|
|
5573
|
-
let synced = 0;
|
|
5574
|
-
const insertStmt = memoryDb.prepare(`
|
|
5575
|
-
INSERT OR IGNORE INTO observations (type, narrative, facts, bead_id)
|
|
5576
|
-
VALUES ('progress', ?, '[]', ?)
|
|
5577
|
-
`);
|
|
5578
|
-
for (const task of tasks) {
|
|
5579
|
-
try {
|
|
5580
|
-
insertStmt.run(task.t, task.id);
|
|
5581
|
-
synced++;
|
|
5582
|
-
} catch {}
|
|
5583
|
-
}
|
|
5584
|
-
beadsDb.close();
|
|
5585
|
-
return {
|
|
5586
|
-
success: true,
|
|
5587
|
-
operation: "sync_to_memory",
|
|
5588
|
-
details: { tasksSynced: synced }
|
|
5589
|
-
};
|
|
5590
|
-
}
|
|
5591
|
-
function syncMemoryToTasks() {
|
|
5592
|
-
const beadsDb = getBeadsDb();
|
|
5593
|
-
if (!beadsDb) {
|
|
5594
|
-
return { success: false, operation: "sync_from_memory", details: {} };
|
|
5595
|
-
}
|
|
5596
|
-
const memoryDb = getMemoryDb();
|
|
5597
|
-
const observations = memoryDb.query(`
|
|
5598
|
-
SELECT * FROM observations
|
|
5599
|
-
WHERE bead_id IS NOT NULL
|
|
5600
|
-
AND type IN ('blocker', 'decision')
|
|
5601
|
-
`).all();
|
|
5602
|
-
let linked = 0;
|
|
5603
|
-
for (const obs of observations) {
|
|
5604
|
-
const existing = beadsDb.query("SELECT id FROM issues WHERE id = ?").get(obs.bead_id);
|
|
5605
|
-
if (existing) {
|
|
5606
|
-
linked++;
|
|
5607
|
-
}
|
|
5608
|
-
}
|
|
5609
|
-
beadsDb.close();
|
|
5610
|
-
return {
|
|
5611
|
-
success: true,
|
|
5612
|
-
operation: "sync_from_memory",
|
|
5613
|
-
details: { observationsLinked: linked }
|
|
5614
|
-
};
|
|
5615
|
-
}
|
|
5616
|
-
function linkObservationToTask(observationId, beadId) {
|
|
5617
|
-
const memoryDb = getMemoryDb();
|
|
5618
|
-
memoryDb.run("UPDATE observations SET bead_id = ? WHERE id = ?", [beadId, observationId]);
|
|
5619
|
-
return {
|
|
5620
|
-
success: true,
|
|
5621
|
-
operation: "link",
|
|
5622
|
-
details: { observationsLinked: 1 }
|
|
5623
|
-
};
|
|
5624
|
-
}
|
|
5625
|
-
function getSyncStatus() {
|
|
5626
|
-
const memoryDb = getMemoryDb();
|
|
5627
|
-
const memoryCount = memoryDb.query("SELECT COUNT(*) as count FROM observations").get();
|
|
5628
|
-
const beadsDb = getBeadsDb();
|
|
5629
|
-
let activeTasks = 0;
|
|
5630
|
-
if (beadsDb) {
|
|
5631
|
-
const taskCount = beadsDb.query("SELECT COUNT(*) as count FROM issues WHERE status != 'closed'").get();
|
|
5632
|
-
activeTasks = taskCount.count;
|
|
5633
|
-
beadsDb.close();
|
|
5634
|
-
}
|
|
5635
|
-
return {
|
|
5636
|
-
success: true,
|
|
5637
|
-
operation: "status",
|
|
5638
|
-
details: {
|
|
5639
|
-
memoryCount: memoryCount.count,
|
|
5640
|
-
activeTasks
|
|
5641
|
-
}
|
|
5642
|
-
};
|
|
5643
|
-
}
|
|
5644
|
-
// src/tools/quick-research.ts
|
|
5645
|
-
function quickResearch(params) {
|
|
5646
|
-
if (!params || typeof params !== "object") {
|
|
5647
|
-
return {
|
|
5648
|
-
query: "",
|
|
5649
|
-
suggestion: "Invalid params provided"
|
|
5650
|
-
};
|
|
5651
|
-
}
|
|
5652
|
-
const p = params;
|
|
5653
|
-
if (!p.query || typeof p.query !== "string") {
|
|
5654
|
-
return {
|
|
5655
|
-
query: "",
|
|
5656
|
-
suggestion: "Missing query parameter"
|
|
5657
|
-
};
|
|
5658
|
-
}
|
|
5659
|
-
const sources = p.sources || ["memory", "context7", "github"];
|
|
5660
|
-
const limit = p.limit || 5;
|
|
5661
|
-
let memoryResults;
|
|
5662
|
-
let context7Hint;
|
|
5663
|
-
let githubHint;
|
|
5664
|
-
if (sources.includes("memory")) {
|
|
5665
|
-
try {
|
|
5666
|
-
memoryResults = memorySearch({ query: p.query, limit });
|
|
5667
|
-
} catch {}
|
|
5668
|
-
}
|
|
5669
|
-
if (sources.includes("context7")) {
|
|
5670
|
-
context7Hint = `Use context7 MCP tool: context7_resolve-library-id({ libraryName: "${p.query}" }) then context7_query-docs()`;
|
|
5671
|
-
}
|
|
5672
|
-
if (sources.includes("github")) {
|
|
5673
|
-
const langHint = p.language ? ` language:${p.language}` : "";
|
|
5674
|
-
githubHint = `Use gh-grep MCP tool: gh-grep_searchGitHub({ query: "${p.query}${langHint}" })`;
|
|
5675
|
-
}
|
|
5676
|
-
const suggestion = buildSuggestion(p.query, memoryResults, sources);
|
|
5677
|
-
return {
|
|
5678
|
-
query: p.query,
|
|
5679
|
-
memory: memoryResults,
|
|
5680
|
-
context7Hint,
|
|
5681
|
-
githubHint,
|
|
5682
|
-
suggestion
|
|
5683
|
-
};
|
|
5684
|
-
}
|
|
5685
|
-
function buildSuggestion(query, memoryResults, sources) {
|
|
5686
|
-
const parts = [];
|
|
5687
|
-
if (memoryResults && memoryResults.length > 0) {
|
|
5688
|
-
parts.push(`Found ${memoryResults.length} relevant observations in memory.`);
|
|
5689
|
-
parts.push(`Check memory-get({ ids: "${memoryResults.map((r) => r.id).join(",")}" }) for details.`);
|
|
5690
|
-
}
|
|
5691
|
-
if (sources?.includes("context7")) {
|
|
5692
|
-
parts.push(`For library docs, run context7_resolve-library-id \u2192 context7_query-docs.`);
|
|
5693
|
-
}
|
|
5694
|
-
if (sources?.includes("github")) {
|
|
5695
|
-
parts.push(`For code examples, run gh-grep_searchGitHub with your query.`);
|
|
5696
|
-
}
|
|
5697
|
-
if (parts.length === 0) {
|
|
5698
|
-
parts.push(`No results found. Try broadening your query or checking different sources.`);
|
|
5699
|
-
}
|
|
5700
|
-
return parts.join(" ");
|
|
5701
|
-
}
|
|
5702
|
-
// src/tools/context-summary.ts
|
|
5703
|
-
import * as path13 from "path";
|
|
5704
|
-
import * as fs12 from "fs";
|
|
5705
|
-
import { Database as Database4 } from "bun:sqlite";
|
|
5706
|
-
var MEMORY_DIR4 = path13.join(process.cwd(), ".opencode", "memory");
|
|
5707
|
-
var MEMORY_DB4 = path13.join(MEMORY_DIR4, "memory.db");
|
|
5708
|
-
function parseStringArray3(value) {
|
|
5709
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
5710
|
-
return [];
|
|
5711
|
-
}
|
|
5712
|
-
try {
|
|
5713
|
-
const parsed = JSON.parse(value);
|
|
5714
|
-
return Array.isArray(parsed) ? parsed.filter((item) => typeof item === "string") : [];
|
|
5715
|
-
} catch {
|
|
5716
|
-
return [];
|
|
5717
|
-
}
|
|
5718
|
-
}
|
|
5719
|
-
function getMemoryDb2() {
|
|
5720
|
-
if (!fs12.existsSync(MEMORY_DIR4)) {
|
|
5721
|
-
fs12.mkdirSync(MEMORY_DIR4, { recursive: true });
|
|
5722
|
-
}
|
|
5723
|
-
const db = new Database4(MEMORY_DB4);
|
|
5724
|
-
db.run(`
|
|
5725
|
-
CREATE TABLE IF NOT EXISTS observations (
|
|
5726
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
5727
|
-
type TEXT NOT NULL,
|
|
5728
|
-
narrative TEXT NOT NULL,
|
|
5729
|
-
facts TEXT DEFAULT '[]',
|
|
5730
|
-
confidence REAL DEFAULT 1.0,
|
|
5731
|
-
files_read TEXT DEFAULT '[]',
|
|
5732
|
-
files_modified TEXT DEFAULT '[]',
|
|
5733
|
-
concepts TEXT DEFAULT '[]',
|
|
5734
|
-
bead_id TEXT,
|
|
5735
|
-
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
|
5736
|
-
expires_at TEXT
|
|
5737
|
-
)
|
|
5738
|
-
`);
|
|
5739
|
-
try {
|
|
5740
|
-
db.exec(`ALTER TABLE observations ADD COLUMN concepts TEXT DEFAULT '[]'`);
|
|
5741
|
-
} catch {}
|
|
5742
|
-
try {
|
|
5743
|
-
db.exec(`ALTER TABLE observations ADD COLUMN bead_id TEXT`);
|
|
5744
|
-
} catch {}
|
|
5745
|
-
try {
|
|
5746
|
-
db.exec(`ALTER TABLE observations ADD COLUMN expires_at TEXT`);
|
|
5747
|
-
} catch {}
|
|
5748
|
-
return db;
|
|
5749
|
-
}
|
|
5750
|
-
function contextSummary(params = {}) {
|
|
5751
|
-
const p = params && typeof params === "object" ? params : {};
|
|
5752
|
-
const db = getMemoryDb2();
|
|
5753
|
-
let whereClause = "1=1";
|
|
5754
|
-
const args = [];
|
|
5755
|
-
if (p.scope === "bead" && p.beadId) {
|
|
5756
|
-
whereClause = "bead_id = ?";
|
|
5757
|
-
args.push(p.beadId);
|
|
5758
|
-
}
|
|
5759
|
-
if (p.scope === "session") {
|
|
5760
|
-
whereClause = "created_at > datetime('now', '-1 day')";
|
|
5761
|
-
}
|
|
5762
|
-
const observations = db.query(`
|
|
5763
|
-
SELECT * FROM observations
|
|
5764
|
-
WHERE ${whereClause}
|
|
5765
|
-
ORDER BY created_at DESC
|
|
5766
|
-
LIMIT 50
|
|
5767
|
-
`).all(...args);
|
|
5768
|
-
const sections = {
|
|
5769
|
-
decisions: observations.filter((o) => o.type === "decision").map((o) => o.narrative).slice(0, 5),
|
|
5770
|
-
learnings: observations.filter((o) => o.type === "learning").map((o) => o.narrative).slice(0, 5),
|
|
5771
|
-
blockers: observations.filter((o) => o.type === "blocker").map((o) => o.narrative).slice(0, 3),
|
|
5772
|
-
progress: observations.filter((o) => o.type === "progress").map((o) => o.narrative).slice(0, 5)
|
|
5773
|
-
};
|
|
5774
|
-
const allFilesRead = new Set;
|
|
5775
|
-
const allFilesModified = new Set;
|
|
5776
|
-
for (const obs of observations) {
|
|
5777
|
-
const read = parseStringArray3(obs.files_read);
|
|
5778
|
-
const modified = parseStringArray3(obs.files_modified);
|
|
5779
|
-
read.forEach((f) => allFilesRead.add(f));
|
|
5780
|
-
modified.forEach((f) => allFilesModified.add(f));
|
|
5781
|
-
}
|
|
5782
|
-
const summary = buildSummary(sections, p.maxTokens || 2000);
|
|
5783
|
-
const tokenEstimate = Math.ceil(summary.length / 4);
|
|
5784
|
-
return {
|
|
5785
|
-
summary,
|
|
5786
|
-
sections,
|
|
5787
|
-
recentFiles: {
|
|
5788
|
-
read: Array.from(allFilesRead).slice(0, 10),
|
|
5789
|
-
modified: Array.from(allFilesModified).slice(0, 10)
|
|
5790
|
-
},
|
|
5791
|
-
tokenEstimate
|
|
5792
|
-
};
|
|
5793
|
-
}
|
|
5794
|
-
function buildSummary(sections, maxTokens) {
|
|
5795
|
-
const lines = [`## Context Summary
|
|
5796
|
-
`];
|
|
5797
|
-
if (sections.decisions.length > 0) {
|
|
5798
|
-
lines.push("### Decisions");
|
|
5799
|
-
sections.decisions.forEach((d) => lines.push(`- ${d}`));
|
|
5800
|
-
lines.push("");
|
|
5801
|
-
}
|
|
5802
|
-
if (sections.blockers.length > 0) {
|
|
5803
|
-
lines.push("### Active Blockers");
|
|
5804
|
-
sections.blockers.forEach((b) => lines.push(`- ${b}`));
|
|
5805
|
-
lines.push("");
|
|
5806
|
-
}
|
|
5807
|
-
if (sections.learnings.length > 0) {
|
|
5808
|
-
lines.push("### Key Learnings");
|
|
5809
|
-
sections.learnings.forEach((l) => lines.push(`- ${l}`));
|
|
5810
|
-
lines.push("");
|
|
5811
|
-
}
|
|
5812
|
-
if (sections.progress.length > 0) {
|
|
5813
|
-
lines.push("### Recent Progress");
|
|
5814
|
-
sections.progress.forEach((p) => lines.push(`- ${p}`));
|
|
5815
|
-
}
|
|
5816
|
-
let summary = lines.join(`
|
|
5817
|
-
`);
|
|
5818
|
-
if (summary.length > maxTokens * 4) {
|
|
5819
|
-
summary = summary.slice(0, maxTokens * 4) + `
|
|
5820
|
-
... (truncated)`;
|
|
5821
|
-
}
|
|
5822
|
-
return summary;
|
|
5823
|
-
}
|
|
5824
4912
|
// src/index.ts
|
|
5825
4913
|
var CliKitPlugin = async (ctx) => {
|
|
5826
4914
|
console.log("[CliKit] Plugin initializing...");
|
|
@@ -6067,60 +5155,5 @@ var CliKitPlugin = async (ctx) => {
|
|
|
6067
5155
|
};
|
|
6068
5156
|
var src_default = CliKitPlugin;
|
|
6069
5157
|
export {
|
|
6070
|
-
|
|
6071
|
-
swarm,
|
|
6072
|
-
shouldTruncate,
|
|
6073
|
-
shouldFormat,
|
|
6074
|
-
sendNotification,
|
|
6075
|
-
scanContentForSecrets,
|
|
6076
|
-
sanitizeContent,
|
|
6077
|
-
runTypeCheck,
|
|
6078
|
-
runFormatter,
|
|
6079
|
-
quickResearch,
|
|
6080
|
-
memoryUpdate,
|
|
6081
|
-
memoryTimeline,
|
|
6082
|
-
memorySearch,
|
|
6083
|
-
memoryRead,
|
|
6084
|
-
memoryGet,
|
|
6085
|
-
memoryAdmin,
|
|
6086
|
-
loadCliKitConfig,
|
|
6087
|
-
linkObservations,
|
|
6088
|
-
isTypeScriptFile,
|
|
6089
|
-
isSubagentTool,
|
|
6090
|
-
isSensitiveFile,
|
|
6091
|
-
isEmptyContent,
|
|
6092
|
-
hasExcessiveAIComments,
|
|
6093
|
-
getObservationsByType,
|
|
6094
|
-
getObservationsByBead,
|
|
6095
|
-
getBuiltinSkills,
|
|
6096
|
-
getBuiltinCommands,
|
|
6097
|
-
getBuiltinAgents,
|
|
6098
|
-
formatTypeCheckWarning,
|
|
6099
|
-
formatTruncationLog,
|
|
6100
|
-
formatSecurityWarning,
|
|
6101
|
-
formatNotificationLog,
|
|
6102
|
-
formatIncompleteWarning,
|
|
6103
|
-
formatEnvSummary,
|
|
6104
|
-
formatCompactionLog,
|
|
6105
|
-
formatCommentWarning,
|
|
6106
|
-
formatBlockerWarning,
|
|
6107
|
-
formatBlockedWarning,
|
|
6108
|
-
formatAutoFormatLog,
|
|
6109
|
-
findSkill,
|
|
6110
|
-
filterCommands,
|
|
6111
|
-
filterAgents,
|
|
6112
|
-
src_default as default,
|
|
6113
|
-
createObservation,
|
|
6114
|
-
contextSummary,
|
|
6115
|
-
containsQuestion,
|
|
6116
|
-
collectEnvInfo,
|
|
6117
|
-
collectCompactionPayload,
|
|
6118
|
-
checkTodoCompletion,
|
|
6119
|
-
checkDangerousCommand,
|
|
6120
|
-
checkCommentDensity,
|
|
6121
|
-
buildIdleNotification,
|
|
6122
|
-
buildErrorNotification,
|
|
6123
|
-
buildEnvBlock,
|
|
6124
|
-
buildCompactionBlock,
|
|
6125
|
-
beadsMemorySync
|
|
5158
|
+
src_default as default
|
|
6126
5159
|
};
|