@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.
Files changed (168) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +21 -2
  3. package/dist/adapter-dependency.test.d.ts +2 -0
  4. package/dist/adapter-dependency.test.d.ts.map +1 -0
  5. package/dist/adapter-dependency.test.js +51 -0
  6. package/dist/adapter-dependency.test.js.map +1 -0
  7. package/dist/commands/approve.d.ts +63 -0
  8. package/dist/commands/approve.d.ts.map +1 -0
  9. package/dist/commands/approve.js +218 -0
  10. package/dist/commands/approve.js.map +1 -0
  11. package/dist/commands/approve.test.d.ts +2 -0
  12. package/dist/commands/approve.test.d.ts.map +1 -0
  13. package/dist/commands/approve.test.js +219 -0
  14. package/dist/commands/approve.test.js.map +1 -0
  15. package/dist/commands/audit.d.ts +74 -0
  16. package/dist/commands/audit.d.ts.map +1 -0
  17. package/dist/commands/audit.js +230 -0
  18. package/dist/commands/audit.js.map +1 -0
  19. package/dist/commands/audit.test.d.ts +2 -0
  20. package/dist/commands/audit.test.d.ts.map +1 -0
  21. package/dist/commands/audit.test.js +194 -0
  22. package/dist/commands/audit.test.js.map +1 -0
  23. package/dist/commands/board.d.ts +33 -0
  24. package/dist/commands/board.d.ts.map +1 -0
  25. package/dist/commands/board.js +65 -0
  26. package/dist/commands/board.js.map +1 -0
  27. package/dist/commands/build.d.ts +17 -0
  28. package/dist/commands/build.d.ts.map +1 -0
  29. package/dist/commands/build.js +145 -0
  30. package/dist/commands/build.js.map +1 -0
  31. package/dist/commands/conformance.d.ts +31 -0
  32. package/dist/commands/conformance.d.ts.map +1 -0
  33. package/dist/commands/conformance.js +57 -0
  34. package/dist/commands/conformance.js.map +1 -0
  35. package/dist/commands/conformance.test.d.ts +2 -0
  36. package/dist/commands/conformance.test.d.ts.map +1 -0
  37. package/dist/commands/conformance.test.js +74 -0
  38. package/dist/commands/conformance.test.js.map +1 -0
  39. package/dist/commands/doctor.d.ts +132 -0
  40. package/dist/commands/doctor.d.ts.map +1 -0
  41. package/dist/commands/doctor.js +768 -0
  42. package/dist/commands/doctor.js.map +1 -0
  43. package/dist/commands/doctor.test.d.ts +2 -0
  44. package/dist/commands/doctor.test.d.ts.map +1 -0
  45. package/dist/commands/doctor.test.js +329 -0
  46. package/dist/commands/doctor.test.js.map +1 -0
  47. package/dist/commands/ledger.d.ts +109 -0
  48. package/dist/commands/ledger.d.ts.map +1 -0
  49. package/dist/commands/ledger.js +286 -0
  50. package/dist/commands/ledger.js.map +1 -0
  51. package/dist/commands/ledger.test.d.ts +2 -0
  52. package/dist/commands/ledger.test.d.ts.map +1 -0
  53. package/dist/commands/ledger.test.js +238 -0
  54. package/dist/commands/ledger.test.js.map +1 -0
  55. package/dist/commands/lessons.d.ts +73 -0
  56. package/dist/commands/lessons.d.ts.map +1 -0
  57. package/dist/commands/lessons.js +97 -0
  58. package/dist/commands/lessons.js.map +1 -0
  59. package/dist/commands/lessons.test.d.ts +2 -0
  60. package/dist/commands/lessons.test.d.ts.map +1 -0
  61. package/dist/commands/lessons.test.js +146 -0
  62. package/dist/commands/lessons.test.js.map +1 -0
  63. package/dist/commands/models.d.ts +49 -0
  64. package/dist/commands/models.d.ts.map +1 -0
  65. package/dist/commands/models.js +125 -0
  66. package/dist/commands/models.js.map +1 -0
  67. package/dist/commands/report.d.ts +57 -0
  68. package/dist/commands/report.d.ts.map +1 -0
  69. package/dist/commands/report.js +164 -0
  70. package/dist/commands/report.js.map +1 -0
  71. package/dist/commands/report.test.d.ts +2 -0
  72. package/dist/commands/report.test.d.ts.map +1 -0
  73. package/dist/commands/report.test.js +294 -0
  74. package/dist/commands/report.test.js.map +1 -0
  75. package/dist/commands/scope.d.ts +34 -0
  76. package/dist/commands/scope.d.ts.map +1 -0
  77. package/dist/commands/scope.js +78 -0
  78. package/dist/commands/scope.js.map +1 -0
  79. package/dist/commands/scope.test.d.ts +2 -0
  80. package/dist/commands/scope.test.d.ts.map +1 -0
  81. package/dist/commands/scope.test.js +98 -0
  82. package/dist/commands/scope.test.js.map +1 -0
  83. package/dist/commands/setup.d.ts +31 -0
  84. package/dist/commands/setup.d.ts.map +1 -0
  85. package/dist/commands/setup.js +93 -0
  86. package/dist/commands/setup.js.map +1 -0
  87. package/dist/commands/waivers.d.ts +47 -0
  88. package/dist/commands/waivers.d.ts.map +1 -0
  89. package/dist/commands/waivers.js +68 -0
  90. package/dist/commands/waivers.js.map +1 -0
  91. package/dist/commands/waivers.test.d.ts +2 -0
  92. package/dist/commands/waivers.test.d.ts.map +1 -0
  93. package/dist/commands/waivers.test.js +64 -0
  94. package/dist/commands/waivers.test.js.map +1 -0
  95. package/dist/generate/agent.d.ts +19 -0
  96. package/dist/generate/agent.d.ts.map +1 -0
  97. package/dist/generate/agent.js +35 -0
  98. package/dist/generate/agent.js.map +1 -0
  99. package/dist/generate/agent.test.d.ts +2 -0
  100. package/dist/generate/agent.test.d.ts.map +1 -0
  101. package/dist/generate/agent.test.js +245 -0
  102. package/dist/generate/agent.test.js.map +1 -0
  103. package/dist/generate/commands.d.ts +15 -0
  104. package/dist/generate/commands.d.ts.map +1 -0
  105. package/dist/generate/commands.js +59 -0
  106. package/dist/generate/commands.js.map +1 -0
  107. package/dist/generate/lock.d.ts +18 -0
  108. package/dist/generate/lock.d.ts.map +1 -0
  109. package/dist/generate/lock.js +26 -0
  110. package/dist/generate/lock.js.map +1 -0
  111. package/dist/generate/prompt.d.ts +11 -0
  112. package/dist/generate/prompt.d.ts.map +1 -0
  113. package/dist/generate/prompt.js +114 -0
  114. package/dist/generate/prompt.js.map +1 -0
  115. package/dist/generate/prompt.test.d.ts +2 -0
  116. package/dist/generate/prompt.test.d.ts.map +1 -0
  117. package/dist/generate/prompt.test.js +59 -0
  118. package/dist/generate/prompt.test.js.map +1 -0
  119. package/dist/index.d.ts +40 -0
  120. package/dist/index.d.ts.map +1 -0
  121. package/dist/index.js +448 -0
  122. package/dist/index.js.map +1 -0
  123. package/dist/index.test.d.ts +2 -0
  124. package/dist/index.test.d.ts.map +1 -0
  125. package/dist/index.test.js +237 -0
  126. package/dist/index.test.js.map +1 -0
  127. package/dist/opencode.d.ts +29 -0
  128. package/dist/opencode.d.ts.map +1 -0
  129. package/dist/opencode.js +125 -0
  130. package/dist/opencode.js.map +1 -0
  131. package/dist/plugin-bundle.test.d.ts +2 -0
  132. package/dist/plugin-bundle.test.d.ts.map +1 -0
  133. package/dist/plugin-bundle.test.js +43 -0
  134. package/dist/plugin-bundle.test.js.map +1 -0
  135. package/dist/plugin.d.ts +11 -0
  136. package/dist/plugin.d.ts.map +1 -0
  137. package/dist/plugin.js +46 -0
  138. package/dist/plugin.js.map +1 -0
  139. package/dist/quality-skills.test.d.ts +2 -0
  140. package/dist/quality-skills.test.d.ts.map +1 -0
  141. package/dist/quality-skills.test.js +141 -0
  142. package/dist/quality-skills.test.js.map +1 -0
  143. package/dist/report/footprint.d.ts +12 -0
  144. package/dist/report/footprint.d.ts.map +1 -0
  145. package/dist/report/footprint.js +121 -0
  146. package/dist/report/footprint.js.map +1 -0
  147. package/dist/report/ledger.d.ts +27 -0
  148. package/dist/report/ledger.d.ts.map +1 -0
  149. package/dist/report/ledger.js +197 -0
  150. package/dist/report/ledger.js.map +1 -0
  151. package/dist/report/oversight.d.ts +21 -0
  152. package/dist/report/oversight.d.ts.map +1 -0
  153. package/dist/report/oversight.js +146 -0
  154. package/dist/report/oversight.js.map +1 -0
  155. package/dist/report/policy-firing.test.d.ts +2 -0
  156. package/dist/report/policy-firing.test.d.ts.map +1 -0
  157. package/dist/report/policy-firing.test.js +68 -0
  158. package/dist/report/policy-firing.test.js.map +1 -0
  159. package/dist/report/scope.d.ts +64 -0
  160. package/dist/report/scope.d.ts.map +1 -0
  161. package/dist/report/scope.js +146 -0
  162. package/dist/report/scope.js.map +1 -0
  163. package/dist/who.d.ts +9 -0
  164. package/dist/who.d.ts.map +1 -0
  165. package/dist/who.js +11 -0
  166. package/dist/who.js.map +1 -0
  167. package/package.json +54 -4
  168. package/plugin/openagentsy.js +39478 -0
@@ -0,0 +1,97 @@
1
+ import { decideLesson, LESSON_ACTIONS, listLessons, pendingLessons, readEvalResult, } from '@openagentsy/hooks';
2
+ import { deciderBy } from '../who.js';
3
+ export { deciderBy };
4
+ /**
5
+ * The inbox.
6
+ */
7
+ export async function runLessons(stateRoot) {
8
+ const all = await listLessons(stateRoot);
9
+ const pending = pendingLessons(all);
10
+ return {
11
+ root: stateRoot,
12
+ lessons: pending.map((lesson) => ({
13
+ id: lesson.id,
14
+ state: lesson.state,
15
+ summary: lesson.summary,
16
+ occurrences: lesson.occurrences,
17
+ kind: lesson.kind,
18
+ sessions: lesson.sessions.length,
19
+ updated_at: lesson.updated_at,
20
+ })),
21
+ awaiting: pending.length,
22
+ total: all.length,
23
+ };
24
+ }
25
+ /**
26
+ * The inbox, as it is read.
27
+ */
28
+ export function formatLessonsReport(report) {
29
+ const lines = [];
30
+ lines.push(`Lessons (${report.awaiting} awaiting a decision, ${report.total} in all)`);
31
+ if (report.lessons.length === 0) {
32
+ lines.push(' none');
33
+ return `${lines.join('\n')}\n`;
34
+ }
35
+ for (const lesson of report.lessons) {
36
+ const count = `${lesson.occurrences}x`.padStart(4);
37
+ lines.push(` ${lesson.id.padEnd(22)}${lesson.state.padEnd(14)}${count} ${lesson.summary}`);
38
+ }
39
+ return `${lines.join('\n')}\n`;
40
+ }
41
+ /**
42
+ * Record a decision.
43
+ */
44
+ export async function runLessonDecision(stateRoot, id, action, options = {}) {
45
+ if (!LESSON_ACTIONS.includes(action)) {
46
+ return {
47
+ ok: false,
48
+ id,
49
+ state: '',
50
+ reason: `unknown lesson action: ${action}`,
51
+ hint: `an action is one of ${LESSON_ACTIONS.join(', ')}`,
52
+ };
53
+ }
54
+ let evalResult = options.evalResult;
55
+ if (evalResult === undefined && options.evalResultPath !== undefined) {
56
+ const read = await readEvalResult(stateRoot, options.evalResultPath);
57
+ if (read.error !== undefined) {
58
+ return {
59
+ ok: false,
60
+ id,
61
+ state: '',
62
+ reason: `the proof result could not be read: ${read.error}`,
63
+ hint: 'the result file has to be there, and it has to be the JSON the runner wrote',
64
+ };
65
+ }
66
+ evalResult = read.result;
67
+ }
68
+ const outcome = await decideLesson(stateRoot, {
69
+ id,
70
+ action: action,
71
+ decidedBy: deciderBy(options.decidedBy),
72
+ reason: options.reason ?? `decided by the person running the command: ${action}`,
73
+ ...(evalResult === undefined ? {} : { evalResult }),
74
+ ...(options.changeRef === undefined ? {} : { changeRef: options.changeRef }),
75
+ ...(options.outcome === undefined ? {} : { outcome: options.outcome }),
76
+ });
77
+ if (!outcome.ok) {
78
+ return { ok: false, id, state: '', reason: outcome.reason, hint: outcome.hint };
79
+ }
80
+ return {
81
+ ok: true,
82
+ id: outcome.lesson.id,
83
+ state: outcome.lesson.state,
84
+ reason: options.reason ?? `decided by the person running the command: ${action}`,
85
+ };
86
+ }
87
+ /**
88
+ * The decision, as it is read.
89
+ */
90
+ export function formatLessonDecision(report) {
91
+ if (report.ok) {
92
+ return `${report.id} is now ${report.state}\n`;
93
+ }
94
+ const hint = report.hint === undefined ? '' : `\nNext: ${report.hint}`;
95
+ return `${report.reason}${hint}\n`;
96
+ }
97
+ //# sourceMappingURL=lessons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lessons.js","sourceRoot":"","sources":["../../src/commands/lessons.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lessons.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lessons.test.d.ts","sourceRoot":"","sources":["../../src/commands/lessons.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,146 @@
1
+ import { mkdtemp, rm } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { captureCandidate } from '@openagentsy/hooks';
5
+ import { describe, expect, it } from 'vitest';
6
+ import { deciderBy, formatLessonDecision, formatLessonsReport, runLessonDecision, runLessons, } from './lessons.js';
7
+ async function stateRoot() {
8
+ const root = await mkdtemp(join(tmpdir(), 'openagentsy-cli-lessons-'));
9
+ return { root, remove: () => rm(root, { recursive: true, force: true }) };
10
+ }
11
+ /** A candidate waiting for a decision. */
12
+ async function candidate(root, summary, session) {
13
+ const outcome = await captureCandidate(root, {
14
+ summary,
15
+ observations: [{ kind: 'missing-file', detail: 'the file was missing', session }],
16
+ explicitCorrection: true,
17
+ });
18
+ if (!outcome.ok)
19
+ throw new Error('the candidate was not created');
20
+ return outcome.lesson;
21
+ }
22
+ describe('the lessons inbox', () => {
23
+ it('lists the lessons that are waiting for a person', async () => {
24
+ const { root, remove } = await stateRoot();
25
+ try {
26
+ await candidate(root, 'the agent wrote to a file that does not exist', 'session-1');
27
+ const report = await runLessons(root);
28
+ expect(report.awaiting).toBe(1);
29
+ expect(report.lessons[0]?.summary).toBe('the agent wrote to a file that does not exist');
30
+ expect(report.lessons[0]?.occurrences).toBe(1);
31
+ }
32
+ finally {
33
+ await remove();
34
+ }
35
+ });
36
+ it('sorts the inbox by occurrences and then by recency', async () => {
37
+ const { root, remove } = await stateRoot();
38
+ try {
39
+ await candidate(root, 'the first lesson', 'session-1');
40
+ await candidate(root, 'the second lesson', 'session-2');
41
+ await captureCandidate(root, {
42
+ summary: 'the first lesson',
43
+ observations: [{ kind: 'missing-file', detail: 'the file was missing', session: 's' }],
44
+ explicitCorrection: true,
45
+ });
46
+ const report = await runLessons(root);
47
+ expect(report.lessons[0]?.summary).toBe('the first lesson');
48
+ expect(report.lessons[0]?.occurrences).toBe(2);
49
+ }
50
+ finally {
51
+ await remove();
52
+ }
53
+ });
54
+ it('says when there is nothing to decide', async () => {
55
+ const { root, remove } = await stateRoot();
56
+ try {
57
+ const report = await runLessons(root);
58
+ expect(report.awaiting).toBe(0);
59
+ expect(formatLessonsReport(report)).toContain('none');
60
+ }
61
+ finally {
62
+ await remove();
63
+ }
64
+ });
65
+ it('reads the inbox as a table', async () => {
66
+ const { root, remove } = await stateRoot();
67
+ try {
68
+ await candidate(root, 'the agent wrote to a file that does not exist', 'session-1');
69
+ const text = formatLessonsReport(await runLessons(root));
70
+ expect(text).toContain('1 awaiting a decision');
71
+ expect(text).toContain('the agent wrote to a file that does not exist');
72
+ }
73
+ finally {
74
+ await remove();
75
+ }
76
+ });
77
+ });
78
+ describe('the lesson decision', () => {
79
+ it('records the decision and names the person', async () => {
80
+ const { root, remove } = await stateRoot();
81
+ try {
82
+ const lesson = await candidate(root, 'the first lesson', 'session-1');
83
+ const report = await runLessonDecision(root, lesson.id, 'reject', {
84
+ decidedBy: 'the person',
85
+ reason: 'it is not what we want',
86
+ });
87
+ expect(report.ok).toBe(true);
88
+ expect(report.state).toBe('rejected');
89
+ expect(formatLessonDecision(report)).toContain('is now rejected');
90
+ }
91
+ finally {
92
+ await remove();
93
+ }
94
+ });
95
+ it('decides for a person when nobody says who', async () => {
96
+ const { root, remove } = await stateRoot();
97
+ try {
98
+ const lesson = await candidate(root, 'the first lesson', 'session-1');
99
+ const report = await runLessonDecision(root, lesson.id, 'reject');
100
+ expect(report.ok).toBe(true);
101
+ expect(deciderBy()).toBe('human');
102
+ }
103
+ finally {
104
+ await remove();
105
+ }
106
+ });
107
+ it('refuses an action that is not one of the four', async () => {
108
+ const { root, remove } = await stateRoot();
109
+ try {
110
+ const lesson = await candidate(root, 'the first lesson', 'session-1');
111
+ const report = await runLessonDecision(root, lesson.id, 'obliterate');
112
+ expect(report.ok).toBe(false);
113
+ expect(report.reason).toMatch(/unknown lesson action/);
114
+ expect(formatLessonDecision(report)).toContain('Next:');
115
+ }
116
+ finally {
117
+ await remove();
118
+ }
119
+ });
120
+ it('says so when the lesson is not there', async () => {
121
+ const { root, remove } = await stateRoot();
122
+ try {
123
+ const report = await runLessonDecision(root, 'oa-lesson-nosuch0', 'reject');
124
+ expect(report.ok).toBe(false);
125
+ expect(report.reason).toMatch(/not there/);
126
+ }
127
+ finally {
128
+ await remove();
129
+ }
130
+ });
131
+ it('says so when the proof result cannot be read', async () => {
132
+ const { root, remove } = await stateRoot();
133
+ try {
134
+ const lesson = await candidate(root, 'the first lesson', 'session-1');
135
+ const report = await runLessonDecision(root, lesson.id, 'validate', {
136
+ evalResultPath: join(root, 'not-there.json'),
137
+ });
138
+ expect(report.ok).toBe(false);
139
+ expect(report.reason).toMatch(/could not be read/);
140
+ }
141
+ finally {
142
+ await remove();
143
+ }
144
+ });
145
+ });
146
+ //# sourceMappingURL=lessons.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lessons.test.js","sourceRoot":"","sources":["../../src/commands/lessons.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { type FetchLike, type ModelLock, type ProviderId } from '@openagentsy/models';
2
+ export type ModelsMode = 'init' | 'refresh' | 'switch';
3
+ export type ModelsOptions = {
4
+ /** The workspace: the roles file lives here. */
5
+ workspace: string;
6
+ /** The state root: the lock file and the model cache live here. */
7
+ stateRoot: string;
8
+ mode: ModelsMode;
9
+ providers: string[];
10
+ /** Take the flash variant of the family a role would get, when it qualifies. */
11
+ preferFlash?: boolean;
12
+ allowTraining?: boolean;
13
+ allowRetention?: boolean;
14
+ yes?: boolean;
15
+ key?: string;
16
+ fetchImpl?: FetchLike;
17
+ };
18
+ export type ModelsResult = {
19
+ lock: ModelLock;
20
+ reasons: Record<string, string>;
21
+ rejected: Record<string, {
22
+ openCodeId: string;
23
+ reason: string;
24
+ }[]>;
25
+ failures: Record<string, string>;
26
+ written: boolean;
27
+ path: string;
28
+ changes: {
29
+ role: string;
30
+ from?: string;
31
+ to: string;
32
+ note: string;
33
+ }[];
34
+ mode: ModelsMode;
35
+ providers: ProviderId[];
36
+ /** What a switch touches besides the lock. */
37
+ touches?: SwitchTouches;
38
+ };
39
+ /** What a switch touches besides the lock file. */
40
+ export type SwitchTouches = {
41
+ /** The command that regenerates the agent files. */
42
+ rebuild: string;
43
+ /** The providers the lock names now. */
44
+ providers: ProviderId[];
45
+ /** The environment variables the providers read their key from. */
46
+ keys: string[];
47
+ };
48
+ export declare function runModels(options: ModelsOptions): Promise<ModelsResult>;
49
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,SAAS,EAEd,KAAK,SAAS,EACd,KAAK,UAAU,EAQhB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG;IAC1B,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,gFAAgF;IAChF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAC;IACnE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrE,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAEF,mDAAmD;AACnD,MAAM,MAAM,aAAa,GAAG;IAC1B,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAoFF,wBAAsB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAsD7E"}
@@ -0,0 +1,125 @@
1
+ import { join } from 'node:path';
2
+ import { createInterface } from 'node:readline/promises';
3
+ import { loadRoles } from '@openagentsy/core';
4
+ import { LOCK_FILE_NAME, providerAliasSummary, providerIdsFromLock, readLock, resolveProviderAlias, selectModels, writeLock, } from '@openagentsy/models';
5
+ /** The provider a command runs with when nothing else is asked for. */
6
+ const DEFAULT_PROVIDERS = ['opencode-go'];
7
+ /** The environment variable each provider reads its key from. */
8
+ const PROVIDER_KEYS = {
9
+ opencode: 'OPENCODE_API_KEY',
10
+ 'opencode-go': 'OPENCODE_API_KEY',
11
+ 'ollama-cloud': 'OLLAMA_API_KEY',
12
+ ollama: undefined,
13
+ };
14
+ /** The provider names a person may type, resolved to the provider ids. */
15
+ function parseProviders(input) {
16
+ const seen = new Set();
17
+ const selections = [];
18
+ for (const raw of input) {
19
+ for (const part of raw.split(',')) {
20
+ const name = part.trim().toLowerCase();
21
+ if (name.length === 0)
22
+ continue;
23
+ const provider = resolveProviderAlias(name);
24
+ if (!provider) {
25
+ throw new Error(`unknown provider "${name}". The names you may use: ${providerAliasSummary()}.`);
26
+ }
27
+ if (seen.has(provider))
28
+ continue;
29
+ seen.add(provider);
30
+ selections.push({ provider });
31
+ }
32
+ }
33
+ return selections;
34
+ }
35
+ /**
36
+ * The providers a command runs with.
37
+ *
38
+ * A refresh uses the providers the lock records, so a refresh cannot move
39
+ * the project back to a provider the lock no longer names. A lock that names
40
+ * no provider yet falls back to the default.
41
+ */
42
+ function resolveProviders(mode, requested, previous) {
43
+ const parsed = parseProviders(requested);
44
+ if (parsed.length > 0)
45
+ return parsed;
46
+ if (mode === 'switch') {
47
+ throw new Error('switch needs a provider: openagentsy models switch ollama-cloud');
48
+ }
49
+ if (mode === 'refresh') {
50
+ const fromLock = providerIdsFromLock(previous);
51
+ if (fromLock.length > 0)
52
+ return fromLock.map((provider) => ({ provider }));
53
+ }
54
+ return parseProviders(DEFAULT_PROVIDERS);
55
+ }
56
+ async function confirm(question, yes) {
57
+ if (yes === true)
58
+ return true;
59
+ if (!process.stdin.isTTY)
60
+ return false;
61
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
62
+ try {
63
+ const answer = await rl.question(`${question} [y/N] `);
64
+ return answer.trim().toLowerCase() === 'y';
65
+ }
66
+ finally {
67
+ rl.close();
68
+ }
69
+ }
70
+ /** What the switch touches besides the lock. */
71
+ function touchesFor(providers) {
72
+ const keys = [];
73
+ for (const provider of providers) {
74
+ const key = PROVIDER_KEYS[provider];
75
+ if (key !== undefined && !keys.includes(key))
76
+ keys.push(key);
77
+ }
78
+ return { rebuild: 'openagentsy build', providers, keys };
79
+ }
80
+ export async function runModels(options) {
81
+ const path = join(options.stateRoot, LOCK_FILE_NAME);
82
+ const roles = await loadRoles(join(options.workspace, 'roles.yaml'));
83
+ const previous = await readLock(path);
84
+ const providers = resolveProviders(options.mode, options.providers, previous);
85
+ const result = await selectModels({
86
+ root: options.stateRoot,
87
+ roles,
88
+ providers,
89
+ ...(options.preferFlash !== undefined ? { preferFlash: options.preferFlash } : {}),
90
+ ...(options.allowTraining !== undefined ? { allowTraining: options.allowTraining } : {}),
91
+ ...(options.allowRetention !== undefined ? { allowRetention: options.allowRetention } : {}),
92
+ ...(options.key !== undefined ? { benchLmKey: options.key } : {}),
93
+ ...(options.fetchImpl !== undefined ? { fetchImpl: options.fetchImpl } : {}),
94
+ });
95
+ const changes = [];
96
+ for (const [role, entry] of Object.entries(result.lock.roles)) {
97
+ const from = previous?.roles[role]?.model;
98
+ changes.push({
99
+ role,
100
+ ...(from !== undefined ? { from } : {}),
101
+ to: entry.model,
102
+ note: result.reasons[role] ?? '',
103
+ });
104
+ }
105
+ const approved = Object.keys(result.failures).length === 0
106
+ ? await confirm(`Write ${LOCK_FILE_NAME} with these ${changes.length} role assignments?`, options.yes)
107
+ : false;
108
+ if (approved) {
109
+ await writeLock(path, result.lock);
110
+ }
111
+ const providerIds = providers.map((selection) => selection.provider);
112
+ return {
113
+ lock: result.lock,
114
+ reasons: result.reasons,
115
+ rejected: result.rejected,
116
+ failures: result.failures,
117
+ written: approved,
118
+ path,
119
+ changes,
120
+ mode: options.mode,
121
+ providers: providerIds,
122
+ ...(options.mode === 'switch' ? { touches: touchesFor(providerIds) } : {}),
123
+ };
124
+ }
125
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/commands/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { type ProjectRoots, type ReportFacts } from '@openagentsy/core';
2
+ /**
3
+ * `oa report --ethical`: what the run cost, and what it was worth (§12).
4
+ *
5
+ * The report is a rendering of facts that were read from the ledger, the
6
+ * board, the stores and the conformance report. It writes nothing, it
7
+ * reaches no network, and it judges nobody: it says what happened.
8
+ *
9
+ * The `--check` flag makes the report a gate. The rule it applies is the
10
+ * quality package's own: a ship verdict with an open floor finding is a
11
+ * fabricated pass, and the gate refuses it. So the command asks the gate
12
+ * whether a ship of this work would be accepted, and the answer is the
13
+ * exit code.
14
+ */
15
+ /** The options the command takes. */
16
+ export type ReportOptions = {
17
+ /** The session, and the subagents that rolled up into it. */
18
+ session?: string | undefined;
19
+ /** The bean: the rows whose task is that bean. */
20
+ bean?: string | undefined;
21
+ /** The window, as a phrase: 30d, 30 days ago, 2 weeks ago. */
22
+ since?: string | undefined;
23
+ /** Whether the report is a gate. */
24
+ check?: boolean | undefined;
25
+ };
26
+ /** The report, and what the command returns. */
27
+ export type EthicalReport = {
28
+ /** The facts the report is rendered from. */
29
+ facts: ReportFacts;
30
+ /** The exit code the command returns. */
31
+ exitCode: number;
32
+ /** Why the gate refused, when it refused. */
33
+ refusal?: string | undefined;
34
+ /** The problem with the flags, when there is one. */
35
+ problem?: string | undefined;
36
+ };
37
+ /**
38
+ * The report.
39
+ *
40
+ * The scope names the rows the ledger is read for, the board records the
41
+ * oversight counts, and the findings store the gate. Nothing is written.
42
+ */
43
+ export declare function runEthicalReport(roots: ProjectRoots, options?: ReportOptions): Promise<EthicalReport>;
44
+ /**
45
+ * The report, as plain text.
46
+ *
47
+ * The text carries no colour, and a refusal is said in words rather than in
48
+ * an exit code alone, so a reader of the output knows what happened.
49
+ */
50
+ export declare function formatEthicalReport(report: EthicalReport): string;
51
+ /**
52
+ * The report, as JSON.
53
+ *
54
+ * The same facts the text is rendered from, so the two can never disagree.
55
+ */
56
+ export declare function ethicalReportAsJson(report: EthicalReport): string;
57
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/commands/report.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EACjB,KAAK,WAAW,EAEjB,MAAM,mBAAmB,CAAC;AAO3B;;;;;;;;;;;;GAYG;AAEH,qCAAqC;AACrC,MAAM,MAAM,aAAa,GAAG;IAC1B,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;IAC3B,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC7B,CAAC;AAEF,gDAAgD;AAChD,MAAM,MAAM,aAAa,GAAG;IAC1B,6CAA6C;IAC7C,KAAK,EAAE,WAAW,CAAC;IACnB,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B,CAAC;AAgGF;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,aAAa,CAAC,CAwCxB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAKjE;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAEjE"}