agentboss 0.1.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/README.md +34 -0
- package/bin/aboss.js +288 -0
- package/client/dist/assets/index-C1wFD_Vo.css +1 -0
- package/client/dist/assets/index-DBj1Ujlx.js +137 -0
- package/client/dist/index.html +34 -0
- package/package.json +64 -0
- package/server/analysis/daily-aggregator.js +258 -0
- package/server/analysis/difficulty.js +129 -0
- package/server/analysis/dimensions/ai-knowledge.js +172 -0
- package/server/analysis/dimensions/ai-tools.js +161 -0
- package/server/analysis/dimensions/judgement.js +107 -0
- package/server/analysis/dimensions/llm-merge.js +57 -0
- package/server/analysis/dimensions/output-quality.js +167 -0
- package/server/analysis/dimensions/problem-definition.js +104 -0
- package/server/analysis/dimensions/system-thinking.js +225 -0
- package/server/analysis/evidence-builder.js +104 -0
- package/server/analysis/job.js +273 -0
- package/server/analysis/report-builder.js +581 -0
- package/server/analysis/scoring-v2.js +72 -0
- package/server/analysis/text-signals.js +179 -0
- package/server/analysis/thresholds-v2.js +358 -0
- package/server/api/advice.js +124 -0
- package/server/api/analysis.js +141 -0
- package/server/api/execution.js +330 -0
- package/server/api/metrics.js +277 -0
- package/server/api/overview.js +308 -0
- package/server/api/project.js +255 -0
- package/server/api/reports.js +125 -0
- package/server/api/sessions.js +118 -0
- package/server/api/settings.js +119 -0
- package/server/db/connection.js +175 -0
- package/server/db/queries.js +1051 -0
- package/server/db/schema.js +487 -0
- package/server/etl/active-time.js +150 -0
- package/server/etl/backfill-subagents.js +178 -0
- package/server/etl/claude-code.js +826 -0
- package/server/etl/detect.js +341 -0
- package/server/etl/judge-filter.js +117 -0
- package/server/etl/opencode.js +606 -0
- package/server/execution/job.js +662 -0
- package/server/execution/prompt.js +227 -0
- package/server/execution/runner.js +218 -0
- package/server/index.js +94 -0
- package/server/llm/advice-prompt.js +339 -0
- package/server/llm/advice.js +384 -0
- package/server/llm/analysis-prompt.js +162 -0
- package/server/llm/cli-runner.js +249 -0
- package/server/llm/judge-prompts.js +179 -0
- package/server/llm/judge.js +118 -0
- package/server/llm/project-advice-prompt.js +332 -0
- package/server/llm/project-advice.js +491 -0
- package/server/llm/session-analyzer.js +122 -0
- package/server/utils/project.js +80 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-shot backfill for the parent_session_id / agent_type columns on
|
|
3
|
+
* unified_session.
|
|
4
|
+
*
|
|
5
|
+
* Background
|
|
6
|
+
* ----------
|
|
7
|
+
* These columns were added after the ETL had already imported sessions
|
|
8
|
+
* from opencode.db. Existing rows have NULL values, which means the
|
|
9
|
+
* "会话列表" filters (which hide subagents via `parent_session_id IS NULL`)
|
|
10
|
+
* would still leak old subagents until the user manually re-ran ETL.
|
|
11
|
+
*
|
|
12
|
+
* What this does
|
|
13
|
+
* --------------
|
|
14
|
+
* 1. Reads every unified_session row where source = 'opencode' AND
|
|
15
|
+
* parent_session_id IS NULL.
|
|
16
|
+
* 2. Opens the user's opencode.db read-only and looks up the matching
|
|
17
|
+
* rows in its `session` table.
|
|
18
|
+
* 3. For each row whose source has a non-null parent_id (or non-null
|
|
19
|
+
* agent), updates unified_session.parent_session_id / agent_type
|
|
20
|
+
* in place.
|
|
21
|
+
*
|
|
22
|
+
* Idempotent: once a row's parent_session_id is non-NULL it's excluded
|
|
23
|
+
* from the WHERE clause, so a second invocation is a no-op (modulo
|
|
24
|
+
* sessions whose source has parent_id but agent_type was NULL and
|
|
25
|
+
* stayed NULL — we still re-update, harmless).
|
|
26
|
+
*
|
|
27
|
+
* Safe failure: opencode.db missing / locked / table renamed → log and
|
|
28
|
+
* return 0; the migration is best-effort and absolutely must not break
|
|
29
|
+
* server boot.
|
|
30
|
+
*
|
|
31
|
+
* @author Felix
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
'use strict';
|
|
35
|
+
|
|
36
|
+
const fs = require('fs');
|
|
37
|
+
const sqlite3 = require('sqlite3');
|
|
38
|
+
|
|
39
|
+
const { queryAll, queryOne } = require('../db/queries');
|
|
40
|
+
const { saveDb } = require('../db/connection');
|
|
41
|
+
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// sqlite3 promise wrappers (kept local to avoid a circular dep on opencode.js)
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
function openReadOnly(dbPath) {
|
|
47
|
+
return new Promise((resolve, reject) => {
|
|
48
|
+
const db = new sqlite3.Database(dbPath, sqlite3.OPEN_READONLY, (err) => {
|
|
49
|
+
if (err) return reject(err);
|
|
50
|
+
resolve(db);
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function closeNative(db) {
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
db.close((err) => (err ? reject(err) : resolve()));
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function dbAll(db, sql, params = []) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
db.all(sql, params, (err, rows) => (err ? reject(err) : resolve(rows || [])));
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
// Helpers
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Resolve the path to the source opencode.db from the tool_config table,
|
|
73
|
+
* which is populated by detect.js on server boot. Returns null if not
|
|
74
|
+
* configured / detected.
|
|
75
|
+
*/
|
|
76
|
+
function resolveOpenCodeDbPath(bossDb) {
|
|
77
|
+
const row = queryOne(
|
|
78
|
+
bossDb,
|
|
79
|
+
"SELECT data_path FROM tool_config WHERE tool = 'opencode'"
|
|
80
|
+
);
|
|
81
|
+
if (!row || !row.data_path) return null;
|
|
82
|
+
if (!fs.existsSync(row.data_path)) return null;
|
|
83
|
+
return row.data_path;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Chunk an array into N-element sub-arrays. Used so the WHERE IN
|
|
88
|
+
* clause stays well under SQLite's 999-parameter limit.
|
|
89
|
+
*/
|
|
90
|
+
function chunk(arr, size) {
|
|
91
|
+
const out = [];
|
|
92
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
93
|
+
out.push(arr.slice(i, i + size));
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Public
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Run the backfill. Always resolves; logs failures.
|
|
104
|
+
*
|
|
105
|
+
* @param {object} bossDb sql.js database (boss.db)
|
|
106
|
+
* @returns {Promise<{ scanned: number, updated: number, skipped: number, reason?: string }>}
|
|
107
|
+
*/
|
|
108
|
+
async function backfillSubagents(bossDb) {
|
|
109
|
+
// 1. Find candidates in boss.db.
|
|
110
|
+
const candidates = queryAll(
|
|
111
|
+
bossDb,
|
|
112
|
+
`SELECT id FROM unified_session
|
|
113
|
+
WHERE source = 'opencode'
|
|
114
|
+
AND parent_session_id IS NULL`
|
|
115
|
+
);
|
|
116
|
+
if (candidates.length === 0) {
|
|
117
|
+
return { scanned: 0, updated: 0, skipped: 0 };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 2. Resolve source db path.
|
|
121
|
+
const ocPath = resolveOpenCodeDbPath(bossDb);
|
|
122
|
+
if (!ocPath) {
|
|
123
|
+
return { scanned: candidates.length, updated: 0, skipped: candidates.length, reason: 'opencode.db not configured' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// 3. Open source db read-only.
|
|
127
|
+
let srcDb;
|
|
128
|
+
try {
|
|
129
|
+
srcDb = await openReadOnly(ocPath);
|
|
130
|
+
} catch (err) {
|
|
131
|
+
return { scanned: candidates.length, updated: 0, skipped: candidates.length, reason: `open failed: ${err.message}` };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let updated = 0;
|
|
135
|
+
try {
|
|
136
|
+
// 4. Look up parent_id / agent for each candidate, in chunks.
|
|
137
|
+
const idSet = candidates.map((r) => r.id);
|
|
138
|
+
const lookups = [];
|
|
139
|
+
for (const ids of chunk(idSet, 500)) {
|
|
140
|
+
const placeholders = ids.map(() => '?').join(',');
|
|
141
|
+
const rows = await dbAll(
|
|
142
|
+
srcDb,
|
|
143
|
+
`SELECT id, parent_id, agent FROM session WHERE id IN (${placeholders})`,
|
|
144
|
+
ids
|
|
145
|
+
);
|
|
146
|
+
lookups.push(...rows);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 5. Build patch list (only rows that actually have parent or agent).
|
|
150
|
+
const patches = lookups.filter((r) => r.parent_id || r.agent);
|
|
151
|
+
|
|
152
|
+
// 6. Apply patches. sql.js doesn't batch, so plain UPDATE-per-row
|
|
153
|
+
// is fine — boss.db is in-memory.
|
|
154
|
+
for (const p of patches) {
|
|
155
|
+
bossDb.run(
|
|
156
|
+
`UPDATE unified_session
|
|
157
|
+
SET parent_session_id = ?, agent_type = ?
|
|
158
|
+
WHERE id = ?`,
|
|
159
|
+
[p.parent_id || null, p.agent || null, p.id]
|
|
160
|
+
);
|
|
161
|
+
updated++;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (updated > 0) {
|
|
165
|
+
try { saveDb(); } catch { /* noop */ }
|
|
166
|
+
}
|
|
167
|
+
} finally {
|
|
168
|
+
try { await closeNative(srcDb); } catch { /* noop */ }
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
scanned: candidates.length,
|
|
173
|
+
updated,
|
|
174
|
+
skipped: candidates.length - updated,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
module.exports = { backfillSubagents };
|