@voxslopuli/openagentsy 0.0.0-stage → 0.2.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/LICENSE +674 -0
- package/README.md +21 -2
- package/dist/adapter-dependency.test.d.ts +2 -0
- package/dist/adapter-dependency.test.d.ts.map +1 -0
- package/dist/adapter-dependency.test.js +51 -0
- package/dist/adapter-dependency.test.js.map +1 -0
- package/dist/commands/approve.d.ts +63 -0
- package/dist/commands/approve.d.ts.map +1 -0
- package/dist/commands/approve.js +218 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/approve.test.d.ts +2 -0
- package/dist/commands/approve.test.d.ts.map +1 -0
- package/dist/commands/approve.test.js +219 -0
- package/dist/commands/approve.test.js.map +1 -0
- package/dist/commands/audit.d.ts +74 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +230 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/audit.test.d.ts +2 -0
- package/dist/commands/audit.test.d.ts.map +1 -0
- package/dist/commands/audit.test.js +194 -0
- package/dist/commands/audit.test.js.map +1 -0
- package/dist/commands/board.d.ts +33 -0
- package/dist/commands/board.d.ts.map +1 -0
- package/dist/commands/board.js +65 -0
- package/dist/commands/board.js.map +1 -0
- package/dist/commands/build.d.ts +17 -0
- package/dist/commands/build.d.ts.map +1 -0
- package/dist/commands/build.js +145 -0
- package/dist/commands/build.js.map +1 -0
- package/dist/commands/conformance.d.ts +31 -0
- package/dist/commands/conformance.d.ts.map +1 -0
- package/dist/commands/conformance.js +57 -0
- package/dist/commands/conformance.js.map +1 -0
- package/dist/commands/conformance.test.d.ts +2 -0
- package/dist/commands/conformance.test.d.ts.map +1 -0
- package/dist/commands/conformance.test.js +74 -0
- package/dist/commands/conformance.test.js.map +1 -0
- package/dist/commands/doctor.d.ts +132 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +768 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/doctor.test.d.ts +2 -0
- package/dist/commands/doctor.test.d.ts.map +1 -0
- package/dist/commands/doctor.test.js +329 -0
- package/dist/commands/doctor.test.js.map +1 -0
- package/dist/commands/ledger.d.ts +109 -0
- package/dist/commands/ledger.d.ts.map +1 -0
- package/dist/commands/ledger.js +286 -0
- package/dist/commands/ledger.js.map +1 -0
- package/dist/commands/ledger.test.d.ts +2 -0
- package/dist/commands/ledger.test.d.ts.map +1 -0
- package/dist/commands/ledger.test.js +238 -0
- package/dist/commands/ledger.test.js.map +1 -0
- package/dist/commands/lessons.d.ts +73 -0
- package/dist/commands/lessons.d.ts.map +1 -0
- package/dist/commands/lessons.js +97 -0
- package/dist/commands/lessons.js.map +1 -0
- package/dist/commands/lessons.test.d.ts +2 -0
- package/dist/commands/lessons.test.d.ts.map +1 -0
- package/dist/commands/lessons.test.js +146 -0
- package/dist/commands/lessons.test.js.map +1 -0
- package/dist/commands/models.d.ts +49 -0
- package/dist/commands/models.d.ts.map +1 -0
- package/dist/commands/models.js +125 -0
- package/dist/commands/models.js.map +1 -0
- package/dist/commands/report.d.ts +57 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +164 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/report.test.d.ts +2 -0
- package/dist/commands/report.test.d.ts.map +1 -0
- package/dist/commands/report.test.js +294 -0
- package/dist/commands/report.test.js.map +1 -0
- package/dist/commands/scope.d.ts +34 -0
- package/dist/commands/scope.d.ts.map +1 -0
- package/dist/commands/scope.js +78 -0
- package/dist/commands/scope.js.map +1 -0
- package/dist/commands/scope.test.d.ts +2 -0
- package/dist/commands/scope.test.d.ts.map +1 -0
- package/dist/commands/scope.test.js +98 -0
- package/dist/commands/scope.test.js.map +1 -0
- package/dist/commands/setup.d.ts +31 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +93 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/waivers.d.ts +47 -0
- package/dist/commands/waivers.d.ts.map +1 -0
- package/dist/commands/waivers.js +68 -0
- package/dist/commands/waivers.js.map +1 -0
- package/dist/commands/waivers.test.d.ts +2 -0
- package/dist/commands/waivers.test.d.ts.map +1 -0
- package/dist/commands/waivers.test.js +64 -0
- package/dist/commands/waivers.test.js.map +1 -0
- package/dist/generate/agent.d.ts +19 -0
- package/dist/generate/agent.d.ts.map +1 -0
- package/dist/generate/agent.js +35 -0
- package/dist/generate/agent.js.map +1 -0
- package/dist/generate/agent.test.d.ts +2 -0
- package/dist/generate/agent.test.d.ts.map +1 -0
- package/dist/generate/agent.test.js +245 -0
- package/dist/generate/agent.test.js.map +1 -0
- package/dist/generate/commands.d.ts +15 -0
- package/dist/generate/commands.d.ts.map +1 -0
- package/dist/generate/commands.js +59 -0
- package/dist/generate/commands.js.map +1 -0
- package/dist/generate/lock.d.ts +18 -0
- package/dist/generate/lock.d.ts.map +1 -0
- package/dist/generate/lock.js +26 -0
- package/dist/generate/lock.js.map +1 -0
- package/dist/generate/prompt.d.ts +11 -0
- package/dist/generate/prompt.d.ts.map +1 -0
- package/dist/generate/prompt.js +114 -0
- package/dist/generate/prompt.js.map +1 -0
- package/dist/generate/prompt.test.d.ts +2 -0
- package/dist/generate/prompt.test.d.ts.map +1 -0
- package/dist/generate/prompt.test.js +59 -0
- package/dist/generate/prompt.test.js.map +1 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +448 -0
- package/dist/index.js.map +1 -0
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +237 -0
- package/dist/index.test.js.map +1 -0
- package/dist/opencode.d.ts +29 -0
- package/dist/opencode.d.ts.map +1 -0
- package/dist/opencode.js +125 -0
- package/dist/opencode.js.map +1 -0
- package/dist/plugin-bundle.test.d.ts +2 -0
- package/dist/plugin-bundle.test.d.ts.map +1 -0
- package/dist/plugin-bundle.test.js +43 -0
- package/dist/plugin-bundle.test.js.map +1 -0
- package/dist/plugin.d.ts +11 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +46 -0
- package/dist/plugin.js.map +1 -0
- package/dist/quality-skills.test.d.ts +2 -0
- package/dist/quality-skills.test.d.ts.map +1 -0
- package/dist/quality-skills.test.js +141 -0
- package/dist/quality-skills.test.js.map +1 -0
- package/dist/report/footprint.d.ts +12 -0
- package/dist/report/footprint.d.ts.map +1 -0
- package/dist/report/footprint.js +121 -0
- package/dist/report/footprint.js.map +1 -0
- package/dist/report/ledger.d.ts +27 -0
- package/dist/report/ledger.d.ts.map +1 -0
- package/dist/report/ledger.js +197 -0
- package/dist/report/ledger.js.map +1 -0
- package/dist/report/oversight.d.ts +21 -0
- package/dist/report/oversight.d.ts.map +1 -0
- package/dist/report/oversight.js +146 -0
- package/dist/report/oversight.js.map +1 -0
- package/dist/report/policy-firing.test.d.ts +2 -0
- package/dist/report/policy-firing.test.d.ts.map +1 -0
- package/dist/report/policy-firing.test.js +68 -0
- package/dist/report/policy-firing.test.js.map +1 -0
- package/dist/report/scope.d.ts +64 -0
- package/dist/report/scope.d.ts.map +1 -0
- package/dist/report/scope.js +146 -0
- package/dist/report/scope.js.map +1 -0
- package/dist/who.d.ts +9 -0
- package/dist/who.d.ts.map +1 -0
- package/dist/who.js +11 -0
- package/dist/who.js.map +1 -0
- package/package.json +54 -4
- package/plugin/openagentsy.js +39478 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { access, readFile } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { closeDatabase, listRecords, openDatabase, } from '@openagentsy/core';
|
|
4
|
+
import { createWaiverStore, listLessons, pendingLessons } from '@openagentsy/hooks';
|
|
5
|
+
/**
|
|
6
|
+
* The oversight of the scope.
|
|
7
|
+
*
|
|
8
|
+
* The counts are the board's records, the lessons that wait for a person,
|
|
9
|
+
* the waivers a person recorded, the audit log and the findings store. The
|
|
10
|
+
* two the plan names and no package keeps are carried as measurements that
|
|
11
|
+
* are not known, with the reason: a zero there would look like a
|
|
12
|
+
* measurement, and it is not one.
|
|
13
|
+
*/
|
|
14
|
+
/** How many records one page of the board holds. */
|
|
15
|
+
const PAGE_SIZE = 100;
|
|
16
|
+
/** The bean the archivist posts a candidate memory under. */
|
|
17
|
+
const MEMORY_BEAN = 'memory';
|
|
18
|
+
/** The states a decided candidate carries. */
|
|
19
|
+
const DECIDED_STATES = ['promoted', 'rejected'];
|
|
20
|
+
/**
|
|
21
|
+
* Every record on the board.
|
|
22
|
+
*
|
|
23
|
+
* The board holds more than one page of records, and a report that read
|
|
24
|
+
* only the first page would undercount a project with a long history. The
|
|
25
|
+
* pages are walked until one comes back short.
|
|
26
|
+
*/
|
|
27
|
+
async function boardRecords(stateRoot) {
|
|
28
|
+
const path = join(stateRoot, '.openagentsy', 'board.sqlite');
|
|
29
|
+
const exists = await access(path).then(() => true, () => false);
|
|
30
|
+
if (!exists)
|
|
31
|
+
return [];
|
|
32
|
+
const db = openDatabase(path);
|
|
33
|
+
try {
|
|
34
|
+
const found = [];
|
|
35
|
+
let cursor = 0;
|
|
36
|
+
for (;;) {
|
|
37
|
+
const page = listRecords(db, { cursor, limit: PAGE_SIZE });
|
|
38
|
+
found.push(...page.records);
|
|
39
|
+
if (page.records.length < PAGE_SIZE)
|
|
40
|
+
return found;
|
|
41
|
+
cursor = page.nextCursor;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
closeDatabase(db);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The memory candidates waiting for a person.
|
|
50
|
+
*
|
|
51
|
+
* A candidate is a board record under the memory bean that no person has
|
|
52
|
+
* decided on, and the decided states are the ones the memory package
|
|
53
|
+
* writes: promoted and rejected. The rule is the memory package's, and the
|
|
54
|
+
* report counts the records itself because the package sits above the
|
|
55
|
+
* adapter and the report needs nothing else of it.
|
|
56
|
+
*/
|
|
57
|
+
function memoryCandidates(records) {
|
|
58
|
+
return records.filter((record) => record.bean === MEMORY_BEAN && !DECIDED_STATES.includes(record.state)).length;
|
|
59
|
+
}
|
|
60
|
+
/** The lines of the audit log. */
|
|
61
|
+
async function auditEntries(stateRoot) {
|
|
62
|
+
const path = join(stateRoot, '.openagentsy', 'audit.jsonl');
|
|
63
|
+
let text;
|
|
64
|
+
try {
|
|
65
|
+
text = await readFile(path, 'utf8');
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
return text.split('\n').filter((line) => line.trim() !== '').length;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The findings of the scope.
|
|
74
|
+
*
|
|
75
|
+
* The findings are the store's, read through the quality package's read
|
|
76
|
+
* path. A bean scope reads the findings of that task, because the ledger
|
|
77
|
+
* reads the task of a bean the same way. Every other scope reads them all:
|
|
78
|
+
* the findings store has no session and no window, and a report that
|
|
79
|
+
* narrowed it by guesswork would be narrowing it wrongly.
|
|
80
|
+
*/
|
|
81
|
+
export function scopedFindings(findings, scope) {
|
|
82
|
+
const scoped = [];
|
|
83
|
+
for (const [taskId, entries] of Object.entries(findings)) {
|
|
84
|
+
if (scope.kind === 'bean' && taskId !== scope.id)
|
|
85
|
+
continue;
|
|
86
|
+
scoped.push(...entries);
|
|
87
|
+
}
|
|
88
|
+
return scoped;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The open floor findings of the scope.
|
|
92
|
+
*
|
|
93
|
+
* The floor tier is the one the gate refuses a ship over, so a report that
|
|
94
|
+
* counts the open floor findings is counting the things that would stop the
|
|
95
|
+
* work from shipping.
|
|
96
|
+
*/
|
|
97
|
+
function openFloor(findings, scope) {
|
|
98
|
+
const found = [];
|
|
99
|
+
for (const [taskId, entries] of Object.entries(findings)) {
|
|
100
|
+
if (scope.kind === 'bean' && taskId !== scope.id)
|
|
101
|
+
continue;
|
|
102
|
+
for (const finding of entries) {
|
|
103
|
+
if (finding.tier !== 'floor')
|
|
104
|
+
continue;
|
|
105
|
+
found.push({
|
|
106
|
+
taskId,
|
|
107
|
+
ruleId: finding.ruleId,
|
|
108
|
+
file: finding.file,
|
|
109
|
+
message: finding.message,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return found;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* The oversight of the scope.
|
|
117
|
+
*
|
|
118
|
+
* The board records of a bean scope are the records of that bean, and every
|
|
119
|
+
* other scope sees the whole board: the board has no session column and no
|
|
120
|
+
* window, so a report that narrowed it would be narrowing it by guesswork.
|
|
121
|
+
*/
|
|
122
|
+
export async function oversightFacts(stateRoot, scope, findings) {
|
|
123
|
+
const records = await boardRecords(stateRoot);
|
|
124
|
+
const scoped = scope.kind === 'bean' ? records.filter((r) => r.bean === scope.id) : records;
|
|
125
|
+
const lessons = await listLessons(stateRoot);
|
|
126
|
+
const waivers = await createWaiverStore(stateRoot).count();
|
|
127
|
+
const floor = openFloor(findings, scope);
|
|
128
|
+
return {
|
|
129
|
+
records: scoped.length,
|
|
130
|
+
lessons: pendingLessons(lessons).length,
|
|
131
|
+
memory: memoryCandidates(records),
|
|
132
|
+
waivers,
|
|
133
|
+
auditEntries: await auditEntries(stateRoot),
|
|
134
|
+
openFloor: floor.length,
|
|
135
|
+
openFloorFindings: floor,
|
|
136
|
+
mismatches: {
|
|
137
|
+
known: false,
|
|
138
|
+
reason: 'no package compares the board with a report',
|
|
139
|
+
},
|
|
140
|
+
redactions: {
|
|
141
|
+
known: false,
|
|
142
|
+
reason: 'no package keeps a counter',
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=oversight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oversight.js","sourceRoot":"","sources":["../../src/report/oversight.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-firing.test.d.ts","sourceRoot":"","sources":["../../src/report/policy-firing.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { mkdtempSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { firstPartyPolicyModules, PolicyEngine, PolicyRegistry } from '@openagentsy/hooks';
|
|
5
|
+
import { closeLedger, createPolicyFiringSink, openLedger, topPoliciesByFireCount, } from '@openagentsy/ledger';
|
|
6
|
+
import { describe, expect, it } from 'vitest';
|
|
7
|
+
/**
|
|
8
|
+
* The firing log, from the engine to the ledger and back (§21.3).
|
|
9
|
+
*
|
|
10
|
+
* The engine writes through a sink and the ledger stores the rows, so the
|
|
11
|
+
* log is a store: it is read back after the ledger was closed and opened
|
|
12
|
+
* again.
|
|
13
|
+
*/
|
|
14
|
+
describe('the policy firing log', () => {
|
|
15
|
+
it('holds the firings of a session after the ledger was reopened', () => {
|
|
16
|
+
const root = mkdtempSync(join(tmpdir(), 'openagentsy-policy-engine-'));
|
|
17
|
+
const db = openLedger(root);
|
|
18
|
+
const registry = new PolicyRegistry(firstPartyPolicyModules({ workspace: root }));
|
|
19
|
+
const engine = new PolicyEngine(registry, { sink: createPolicyFiringSink(db) });
|
|
20
|
+
engine.evaluate({
|
|
21
|
+
session: { id: 'ses_1', roleId: 'builder' },
|
|
22
|
+
response: { text: 'You are absolutely right, this is a great point.' },
|
|
23
|
+
});
|
|
24
|
+
closeLedger(db);
|
|
25
|
+
const again = openLedger(root);
|
|
26
|
+
try {
|
|
27
|
+
const counts = topPoliciesByFireCount(again, 10);
|
|
28
|
+
const flagged = counts.find((entry) => entry.policyId === 'oa.anti-sycophancy');
|
|
29
|
+
expect(flagged?.count).toBe(1);
|
|
30
|
+
expect(flagged?.flags).toBe(1);
|
|
31
|
+
expect(flagged?.versions).toEqual(['1.0.0']);
|
|
32
|
+
const stack = again
|
|
33
|
+
.query('SELECT reason, detail FROM policy_firing WHERE policy_id = ?')
|
|
34
|
+
.get('oa.policy.stack');
|
|
35
|
+
expect(stack?.reason).toBe('stack-assembled');
|
|
36
|
+
expect(stack?.detail).toContain('oa.anti-sycophancy');
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
closeLedger(again);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
it('records the stack of a session once, and the decisions of it', () => {
|
|
43
|
+
const root = mkdtempSync(join(tmpdir(), 'openagentsy-policy-engine-'));
|
|
44
|
+
const db = openLedger(root);
|
|
45
|
+
const registry = new PolicyRegistry(firstPartyPolicyModules({ workspace: root }));
|
|
46
|
+
const engine = new PolicyEngine(registry, { sink: createPolicyFiringSink(db) });
|
|
47
|
+
const context = {
|
|
48
|
+
session: { id: 'ses_1', roleId: 'builder' },
|
|
49
|
+
response: { text: 'The parser reads the file.' },
|
|
50
|
+
};
|
|
51
|
+
engine.evaluate(context);
|
|
52
|
+
engine.evaluate(context);
|
|
53
|
+
closeLedger(db);
|
|
54
|
+
const again = openLedger(root);
|
|
55
|
+
try {
|
|
56
|
+
const stack = again
|
|
57
|
+
.query('SELECT COUNT(*) AS total FROM policy_firing WHERE policy_id = ?')
|
|
58
|
+
.get('oa.policy.stack');
|
|
59
|
+
expect(stack.total).toBe(1);
|
|
60
|
+
const total = again.query('SELECT COUNT(*) AS total FROM policy_firing').get();
|
|
61
|
+
expect(total.total).toBeGreaterThan(1);
|
|
62
|
+
}
|
|
63
|
+
finally {
|
|
64
|
+
closeLedger(again);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=policy-firing.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-firing.test.js","sourceRoot":"","sources":["../../src/report/policy-firing.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ReportScope } from '@openagentsy/core';
|
|
2
|
+
import type { openLedger } from '@openagentsy/ledger';
|
|
3
|
+
/**
|
|
4
|
+
* The scope of the report, and the rows it selects.
|
|
5
|
+
*
|
|
6
|
+
* A scope is one of three things: a session, a bean or a window. The report
|
|
7
|
+
* says which one it is, and an empty scope is a fact the report prints
|
|
8
|
+
* rather than a gap it fills with zeroes.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The ledger's database, as the ledger names it.
|
|
12
|
+
*
|
|
13
|
+
* The type comes from the ledger rather than from `bun:sqlite`, so the CLI
|
|
14
|
+
* does not need the Bun type definitions to talk about the ledger it
|
|
15
|
+
* already opens.
|
|
16
|
+
*/
|
|
17
|
+
export type LedgerDb = ReturnType<typeof openLedger>;
|
|
18
|
+
/** The flags a scope is built from. */
|
|
19
|
+
export type ScopeFlags = {
|
|
20
|
+
/** The session, and the subagents that rolled up into it. */
|
|
21
|
+
session?: string | undefined;
|
|
22
|
+
/** The bean: the rows whose task is that bean. */
|
|
23
|
+
bean?: string | undefined;
|
|
24
|
+
/** The window, as a phrase: 30d, 30 days ago, 2 weeks ago. */
|
|
25
|
+
since?: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
/** The scope the flags name, or the problem with them. */
|
|
28
|
+
export type ScopeResult = {
|
|
29
|
+
ok: true;
|
|
30
|
+
scope: ReportScope;
|
|
31
|
+
} | {
|
|
32
|
+
ok: false;
|
|
33
|
+
error: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The scope the flags name.
|
|
37
|
+
*
|
|
38
|
+
* The flags name one thing. Two of them name two things, and a report of
|
|
39
|
+
* two scopes at once is a report of none of them, so the command says the
|
|
40
|
+
* scope is ambiguous and stops.
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseScope(flags: ScopeFlags): ScopeResult;
|
|
43
|
+
/**
|
|
44
|
+
* Shadow the ledger's tables with the rows the scope selects.
|
|
45
|
+
*
|
|
46
|
+
* The ledger's own queries read the tables by name, and they take no scope:
|
|
47
|
+
* the ledger holds every row it was given. So the scope is applied here,
|
|
48
|
+
* once, by putting the scoped rows into temp tables of the same names. The
|
|
49
|
+
* ledger's queries then read the scope, and the report cannot drift from
|
|
50
|
+
* the ledger, because the report never totals anything itself.
|
|
51
|
+
*
|
|
52
|
+
* The temp tables live in the connection and go with it: nothing is written
|
|
53
|
+
* to the ledger, and a report never changes what it reports on.
|
|
54
|
+
*/
|
|
55
|
+
export declare function shadowScope(db: LedgerDb, scope: ReportScope): void;
|
|
56
|
+
/**
|
|
57
|
+
* The days the ledger's own window covers.
|
|
58
|
+
*
|
|
59
|
+
* The ledger's outcome queries look at the last thirty days. A scope that
|
|
60
|
+
* names a window uses that window, and a scope that names a thing opens the
|
|
61
|
+
* ledger's window wide, so the scope alone decides what is in the report.
|
|
62
|
+
*/
|
|
63
|
+
export declare function windowDays(scope: ReportScope): number;
|
|
64
|
+
//# sourceMappingURL=scope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/report/scope.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;GAMG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAErD,uCAAuC;AACvC,MAAM,MAAM,UAAU,GAAG;IACvB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,8DAA8D;IAC9D,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AA2C1F;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAuBzD;AA+CD;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAYlE;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/** How long a unit of a window is, in milliseconds. */
|
|
2
|
+
const UNITS = {
|
|
3
|
+
h: 3_600_000,
|
|
4
|
+
hour: 3_600_000,
|
|
5
|
+
hours: 3_600_000,
|
|
6
|
+
d: 86_400_000,
|
|
7
|
+
day: 86_400_000,
|
|
8
|
+
days: 86_400_000,
|
|
9
|
+
w: 604_800_000,
|
|
10
|
+
week: 604_800_000,
|
|
11
|
+
weeks: 604_800_000,
|
|
12
|
+
m: 2_592_000_000,
|
|
13
|
+
month: 2_592_000_000,
|
|
14
|
+
months: 2_592_000_000,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* The window a phrase names.
|
|
18
|
+
*
|
|
19
|
+
* The phrase is a number and a unit, with an optional "ago": 30d, 30 days,
|
|
20
|
+
* 30 days ago. A phrase that names no window is no window, and the caller
|
|
21
|
+
* says so rather than guessing a default.
|
|
22
|
+
*/
|
|
23
|
+
function parseWindow(phrase) {
|
|
24
|
+
const trimmed = phrase
|
|
25
|
+
.trim()
|
|
26
|
+
.toLowerCase()
|
|
27
|
+
.replace(/\s+ago$/, '')
|
|
28
|
+
.trim();
|
|
29
|
+
const found = /^(\d+)\s*([a-z]+)$/.exec(trimmed);
|
|
30
|
+
if (found === null)
|
|
31
|
+
return undefined;
|
|
32
|
+
const amount = Number(found[1]);
|
|
33
|
+
const unit = found[2];
|
|
34
|
+
if (unit === undefined)
|
|
35
|
+
return undefined;
|
|
36
|
+
const millis = UNITS[unit];
|
|
37
|
+
if (millis === undefined || !Number.isFinite(amount) || amount <= 0)
|
|
38
|
+
return undefined;
|
|
39
|
+
const days = Math.round((amount * millis) / 86_400_000);
|
|
40
|
+
if (days <= 0)
|
|
41
|
+
return undefined;
|
|
42
|
+
return { days, label: `${amount} ${unit}` };
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* The scope the flags name.
|
|
46
|
+
*
|
|
47
|
+
* The flags name one thing. Two of them name two things, and a report of
|
|
48
|
+
* two scopes at once is a report of none of them, so the command says the
|
|
49
|
+
* scope is ambiguous and stops.
|
|
50
|
+
*/
|
|
51
|
+
export function parseScope(flags) {
|
|
52
|
+
const named = [
|
|
53
|
+
...(flags.session === undefined ? [] : [`session ${flags.session}`]),
|
|
54
|
+
...(flags.bean === undefined ? [] : [`bean ${flags.bean}`]),
|
|
55
|
+
...(flags.since === undefined ? [] : [`since ${flags.since}`]),
|
|
56
|
+
];
|
|
57
|
+
if (named.length > 1) {
|
|
58
|
+
return { ok: false, error: `the scope names more than one thing: ${named.join(' and ')}` };
|
|
59
|
+
}
|
|
60
|
+
if (flags.session !== undefined) {
|
|
61
|
+
return { ok: true, scope: { kind: 'session', id: flags.session } };
|
|
62
|
+
}
|
|
63
|
+
if (flags.bean !== undefined) {
|
|
64
|
+
return { ok: true, scope: { kind: 'bean', id: flags.bean } };
|
|
65
|
+
}
|
|
66
|
+
if (flags.since !== undefined) {
|
|
67
|
+
const window = parseWindow(flags.since);
|
|
68
|
+
if (window === undefined) {
|
|
69
|
+
return { ok: false, error: `the window ${flags.since} names no time` };
|
|
70
|
+
}
|
|
71
|
+
return { ok: true, scope: { kind: 'since', days: window.days, label: window.label } };
|
|
72
|
+
}
|
|
73
|
+
return { ok: true, scope: { kind: 'project' } };
|
|
74
|
+
}
|
|
75
|
+
/** The tables the scope is applied to. */
|
|
76
|
+
const TABLES = ['usage', 'waste', 'outcome', 'policy_firing'];
|
|
77
|
+
/**
|
|
78
|
+
* The rows a table holds for the scope.
|
|
79
|
+
*
|
|
80
|
+
* The predicate is the scope, and the parameters are what it names. A
|
|
81
|
+
* project scope selects every row, so the predicate is a tautology and the
|
|
82
|
+
* table is read whole.
|
|
83
|
+
*/
|
|
84
|
+
function predicate(table, scope, instant) {
|
|
85
|
+
switch (scope.kind) {
|
|
86
|
+
case 'project':
|
|
87
|
+
return { sql: '1 = 1', params: [] };
|
|
88
|
+
case 'since':
|
|
89
|
+
return { sql: 'ts >= ?', params: [instant] };
|
|
90
|
+
case 'session':
|
|
91
|
+
if (table === 'usage') {
|
|
92
|
+
return { sql: '(root_session_id = ? OR session_id = ?)', params: [scope.id, scope.id] };
|
|
93
|
+
}
|
|
94
|
+
if (table === 'policy_firing') {
|
|
95
|
+
return { sql: 'session_id = ?', params: [scope.id] };
|
|
96
|
+
}
|
|
97
|
+
return { sql: 'root_session_id = ?', params: [scope.id] };
|
|
98
|
+
case 'bean':
|
|
99
|
+
if (table === 'waste') {
|
|
100
|
+
return {
|
|
101
|
+
sql: 'message_id IN (SELECT message_id FROM main.usage WHERE task_id = ?)',
|
|
102
|
+
params: [scope.id],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
if (table === 'policy_firing') {
|
|
106
|
+
return {
|
|
107
|
+
sql: 'session_id IN (SELECT session_id FROM main.usage WHERE task_id = ?)',
|
|
108
|
+
params: [scope.id],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
return { sql: 'task_id = ?', params: [scope.id] };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Shadow the ledger's tables with the rows the scope selects.
|
|
116
|
+
*
|
|
117
|
+
* The ledger's own queries read the tables by name, and they take no scope:
|
|
118
|
+
* the ledger holds every row it was given. So the scope is applied here,
|
|
119
|
+
* once, by putting the scoped rows into temp tables of the same names. The
|
|
120
|
+
* ledger's queries then read the scope, and the report cannot drift from
|
|
121
|
+
* the ledger, because the report never totals anything itself.
|
|
122
|
+
*
|
|
123
|
+
* The temp tables live in the connection and go with it: nothing is written
|
|
124
|
+
* to the ledger, and a report never changes what it reports on.
|
|
125
|
+
*/
|
|
126
|
+
export function shadowScope(db, scope) {
|
|
127
|
+
const instant = scope.kind === 'since'
|
|
128
|
+
? new Date(Date.now() - scope.days * 86_400_000).toISOString()
|
|
129
|
+
: new Date(0).toISOString();
|
|
130
|
+
for (const table of TABLES) {
|
|
131
|
+
const { sql, params } = predicate(table, scope, instant);
|
|
132
|
+
db.exec(`DROP TABLE IF EXISTS temp.${table}`);
|
|
133
|
+
db.query(`CREATE TEMP TABLE ${table} AS SELECT * FROM main.${table} WHERE ${sql}`).run(...params);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The days the ledger's own window covers.
|
|
138
|
+
*
|
|
139
|
+
* The ledger's outcome queries look at the last thirty days. A scope that
|
|
140
|
+
* names a window uses that window, and a scope that names a thing opens the
|
|
141
|
+
* ledger's window wide, so the scope alone decides what is in the report.
|
|
142
|
+
*/
|
|
143
|
+
export function windowDays(scope) {
|
|
144
|
+
return scope.kind === 'since' ? scope.days : 36_500;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=scope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/report/scope.ts"],"names":[],"mappings":"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"}
|
package/dist/who.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who the person running a command is.
|
|
3
|
+
*
|
|
4
|
+
* A decision a person makes carries the name of the person who made it. The
|
|
5
|
+
* name comes from the environment when it is set, because a person may want
|
|
6
|
+
* the record to say who they are, and the default is "a person".
|
|
7
|
+
*/
|
|
8
|
+
export declare function deciderBy(override?: string): string;
|
|
9
|
+
//# sourceMappingURL=who.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"who.d.ts","sourceRoot":"","sources":["../src/who.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
package/dist/who.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who the person running a command is.
|
|
3
|
+
*
|
|
4
|
+
* A decision a person makes carries the name of the person who made it. The
|
|
5
|
+
* name comes from the environment when it is set, because a person may want
|
|
6
|
+
* the record to say who they are, and the default is "a person".
|
|
7
|
+
*/
|
|
8
|
+
export function deciderBy(override) {
|
|
9
|
+
return override ?? process.env.OPENAGENTSY_USER ?? 'human';
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=who.js.map
|
package/dist/who.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"who.js","sourceRoot":"","sources":["../src/who.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,QAAiB;IACzC,OAAO,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,OAAO,CAAC;AAC7D,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voxslopuli/openagentsy",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"openagentsy": "./dist/index.js",
|
|
7
|
+
"oa": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc -b tsconfig.json && chmod +x dist/index.js && node scripts/copy-plugin.mjs",
|
|
11
|
+
"typecheck": "tsc -b tsconfig.json"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@openagentsy/core": "^0.2.0",
|
|
15
|
+
"@openagentsy/footprint": "^0.2.0",
|
|
16
|
+
"@openagentsy/hooks": "^0.2.0",
|
|
17
|
+
"@openagentsy/ledger": "^0.2.0",
|
|
18
|
+
"@openagentsy/models": "^0.2.0",
|
|
19
|
+
"@openagentsy/quality": "^0.2.0",
|
|
20
|
+
"jsonc-parser": "^3.3.1",
|
|
21
|
+
"yaml": "^2.8.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/node": "^24.3.0",
|
|
25
|
+
"typescript": "^5.9.2",
|
|
26
|
+
"@openagentsy/adapter-opencode": "0.2.0"
|
|
27
|
+
},
|
|
28
|
+
"description": "The hub and spoke agent system for OpenCode: one Lead, many specialists, one writer per file.",
|
|
29
|
+
"license": "GPL-3.0-or-later",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/voxslopuli/openagentsy.git"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/voxslopuli/openagentsy#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/voxslopuli/openagentsy/issues"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"agents",
|
|
40
|
+
"opencode",
|
|
41
|
+
"coordination",
|
|
42
|
+
"leases",
|
|
43
|
+
"mcp",
|
|
44
|
+
"bun"
|
|
45
|
+
],
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=22.5.0"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"files": [
|
|
53
|
+
"dist",
|
|
54
|
+
"plugin"
|
|
55
|
+
]
|
|
56
|
+
}
|