@agentproto/agencies-engine 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/LICENSE +21 -0
- package/dist/index.d.ts +81 -0
- package/dist/index.mjs +330 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jeremy André and agentproto contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { GovernanceConfig } from '@agentproto/governance-engine';
|
|
2
|
+
import { AgencyOverviewSnapshot } from '@agentproto/agencies/renderers';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `computeAgencyOverview` — canonical Node implementation of the
|
|
6
|
+
* `procedures/compute-agency-overview` PROCEDURE.md.
|
|
7
|
+
*
|
|
8
|
+
* Walks the workspace (counterparties/, engagements/, invoices/), projects
|
|
9
|
+
* the aggregate into an `AgencyOverviewSnapshot`, optionally writes it to
|
|
10
|
+
* `_snapshots/agency-overview.json`. Vendor-neutral — uses the
|
|
11
|
+
* `IGovernanceFilesystem` adapter from `@agentproto/governance/runtime` so it
|
|
12
|
+
* runs against LocalFilesystem in dev and SupabaseFilesystem in prod
|
|
13
|
+
* without code changes.
|
|
14
|
+
*
|
|
15
|
+
* Designed to be called from:
|
|
16
|
+
* - A Mastra workflow (`@agentproto/agencies-mastra` codegen wraps this in suspend/
|
|
17
|
+
* resume primitives if needed).
|
|
18
|
+
* - A cron-driven routine engine (e.g. Guilde's routine-executor).
|
|
19
|
+
* - Ad-hoc by a CLI (`agencies overview compute <workspace>`).
|
|
20
|
+
*
|
|
21
|
+
* The compute is single-pass — no memoization, no incremental cache. For
|
|
22
|
+
* very large agencies (>500 engagements) this should be replaced with a
|
|
23
|
+
* watch-based incremental rebuild.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
interface ComputeAgencyOverviewInput {
|
|
27
|
+
/**
|
|
28
|
+
* Workspace root + filesystem adapter. The same `GovernanceConfig` used by
|
|
29
|
+
* the governance runtime — pass the whole config so Supabase-backed
|
|
30
|
+
* workspaces work via `MastraFilesystemGovernanceAdapter`.
|
|
31
|
+
*
|
|
32
|
+
* Only `workspaceRoot` and `filesystem` are read; secrets (genesisSeed,
|
|
33
|
+
* hmacSecret) are not used here.
|
|
34
|
+
*/
|
|
35
|
+
config: Pick<GovernanceConfig, "workspaceRoot" | "filesystem">;
|
|
36
|
+
/**
|
|
37
|
+
* If true, atomically write the snapshot to
|
|
38
|
+
* `_snapshots/agency-overview.json`. Default: true.
|
|
39
|
+
*/
|
|
40
|
+
write?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Override the `now` clock for deterministic tests.
|
|
43
|
+
*/
|
|
44
|
+
now?: Date;
|
|
45
|
+
/**
|
|
46
|
+
* Override the staleness threshold. Default: AGENCY_OVERVIEW_FRESHNESS_MS.
|
|
47
|
+
*/
|
|
48
|
+
freshnessMs?: number;
|
|
49
|
+
/**
|
|
50
|
+
* How many recent payments to include in the snapshot. Default: 5.
|
|
51
|
+
*/
|
|
52
|
+
recentPaymentsLimit?: number;
|
|
53
|
+
}
|
|
54
|
+
interface ComputeAgencyOverviewResult {
|
|
55
|
+
snapshot: AgencyOverviewSnapshot;
|
|
56
|
+
/** Workspace-relative path to the written snapshot, or null when `write: false`. */
|
|
57
|
+
snapshotPath: string | null;
|
|
58
|
+
/** Counts useful for the audit-log entry the routine writes after a successful run. */
|
|
59
|
+
walked: {
|
|
60
|
+
counterparties: number;
|
|
61
|
+
engagements: number;
|
|
62
|
+
invoices: number;
|
|
63
|
+
skipped: number;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
declare function computeAgencyOverview(input: ComputeAgencyOverviewInput): Promise<ComputeAgencyOverviewResult>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* agentagencies/v1 runtime — FS-only helpers.
|
|
70
|
+
*
|
|
71
|
+
* NO Mastra, LangChain, Temporal imports. The vendor-neutral runtime that any
|
|
72
|
+
* orchestrator can consume. Vendor adapters (e.g., @agentproto/agencies-mastra) wrap
|
|
73
|
+
* these helpers with workflow-specific suspend/resume primitives.
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
/** Workspace-relative path of the snapshot the routine writes. */
|
|
77
|
+
declare const AGENCY_OVERVIEW_SNAPSHOT_PATH: "_snapshots/agency-overview.json";
|
|
78
|
+
/** Path of the bundled rollup snippets folder (relative to the package root). */
|
|
79
|
+
declare const AGENCY_OVERVIEW_ROLLUP_SNIPPET_PATH: "src/spec/snippets/agency-overview-rollup";
|
|
80
|
+
|
|
81
|
+
export { AGENCY_OVERVIEW_ROLLUP_SNIPPET_PATH, AGENCY_OVERVIEW_SNAPSHOT_PATH, type ComputeAgencyOverviewInput, type ComputeAgencyOverviewResult, computeAgencyOverview };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
import * as path from 'path';
|
|
2
|
+
import { defaultGovernanceFilesystem, resolveFromRoot } from '@agentproto/governance-engine';
|
|
3
|
+
import matter from 'gray-matter';
|
|
4
|
+
import { AGENCY_OVERVIEW_FRESHNESS_MS, agencyOverviewSnapshotSchema, isAgencyOverviewSnapshotStale } from '@agentproto/agencies/renderers';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @agentproto/agencies-engine v0.1.0-alpha
|
|
8
|
+
* Workspace walkers + index helpers for agentagencies/v1. Vendor-neutral —
|
|
9
|
+
* routes all I/O through @agentproto/governance-engine's IGovernanceFilesystem.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
var SNAPSHOT_REL_PATH = "_snapshots/agency-overview.json";
|
|
13
|
+
async function computeAgencyOverview(input) {
|
|
14
|
+
const fs = input.config.filesystem ?? defaultGovernanceFilesystem();
|
|
15
|
+
const workspaceRoot = input.config.workspaceRoot;
|
|
16
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
17
|
+
const freshnessMs = input.freshnessMs ?? AGENCY_OVERVIEW_FRESHNESS_MS;
|
|
18
|
+
const recentPaymentsLimit = input.recentPaymentsLimit ?? 5;
|
|
19
|
+
let skipped = 0;
|
|
20
|
+
const counterpartyDirs = await listSubdirs(
|
|
21
|
+
fs,
|
|
22
|
+
workspaceRoot,
|
|
23
|
+
"counterparties"
|
|
24
|
+
);
|
|
25
|
+
const counterparties = [];
|
|
26
|
+
for (const dir of counterpartyDirs) {
|
|
27
|
+
const fmPath = resolveFromRoot(
|
|
28
|
+
workspaceRoot,
|
|
29
|
+
`counterparties/${dir}/COUNTERPARTY.md`
|
|
30
|
+
);
|
|
31
|
+
const fm = await readFrontmatter(fs, fmPath);
|
|
32
|
+
if (!fm) {
|
|
33
|
+
skipped++;
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
counterparties.push({
|
|
37
|
+
slug: dir,
|
|
38
|
+
displayName: stringField(fm, "displayName") ?? stringField(fm, "name") ?? dir,
|
|
39
|
+
status: stringField(fm, "status")
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const engagementDirs = await listSubdirs(fs, workspaceRoot, "engagements");
|
|
43
|
+
const engagements = [];
|
|
44
|
+
for (const dir of engagementDirs) {
|
|
45
|
+
const fmPath = resolveFromRoot(
|
|
46
|
+
workspaceRoot,
|
|
47
|
+
`engagements/${dir}/ENGAGEMENT.md`
|
|
48
|
+
);
|
|
49
|
+
const fm = await readFrontmatter(fs, fmPath);
|
|
50
|
+
if (!fm) {
|
|
51
|
+
skipped++;
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const counterpartyId = stringField(fm, "counterpartyId");
|
|
55
|
+
const counterparty = counterparties.find((c) => c.slug === counterpartyId);
|
|
56
|
+
const expectedValue = await readEngagementExpectedValue(
|
|
57
|
+
fs,
|
|
58
|
+
workspaceRoot,
|
|
59
|
+
dir
|
|
60
|
+
);
|
|
61
|
+
engagements.push({
|
|
62
|
+
slug: dir,
|
|
63
|
+
name: stringField(fm, "name") ?? dir,
|
|
64
|
+
status: stringField(fm, "status") ?? "unknown",
|
|
65
|
+
activeStep: stringField(fm, "activeStep"),
|
|
66
|
+
counterpartyId,
|
|
67
|
+
counterpartyDisplayName: counterparty?.displayName ?? counterpartyId ?? "\u2014",
|
|
68
|
+
expectedValue,
|
|
69
|
+
requiredSignerCount: countRequiredSignatures(fm),
|
|
70
|
+
createdAt: parseDate(stringField(fm, "createdAt"))
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
const invoices = [];
|
|
74
|
+
for (const eng of engagements) {
|
|
75
|
+
const invoiceDirs = await listSubdirs(
|
|
76
|
+
fs,
|
|
77
|
+
workspaceRoot,
|
|
78
|
+
`engagements/${eng.slug}/invoices`
|
|
79
|
+
);
|
|
80
|
+
for (const invDir of invoiceDirs) {
|
|
81
|
+
const fmPath = resolveFromRoot(
|
|
82
|
+
workspaceRoot,
|
|
83
|
+
`engagements/${eng.slug}/invoices/${invDir}/INVOICE.md`
|
|
84
|
+
);
|
|
85
|
+
const fm = await readFrontmatter(fs, fmPath);
|
|
86
|
+
if (!fm) {
|
|
87
|
+
skipped++;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
invoices.push({
|
|
91
|
+
invoiceNumber: stringField(fm, "invoiceNumber") ?? invDir,
|
|
92
|
+
amount: numberField(fm, "totalAmount") ?? numberField(fm, "amount") ?? 0,
|
|
93
|
+
currency: stringField(fm, "currency") ?? "EUR",
|
|
94
|
+
status: stringField(fm, "status") ?? "issued",
|
|
95
|
+
paidAt: parseDate(stringField(fm, "paidAt")),
|
|
96
|
+
counterpartyDisplayName: eng.counterpartyDisplayName
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const pendingPath = resolveFromRoot(
|
|
101
|
+
workspaceRoot,
|
|
102
|
+
"_index/pending-signatures.json"
|
|
103
|
+
);
|
|
104
|
+
const pendingRaw = await fs.readFile(pendingPath);
|
|
105
|
+
let pendingByEngagement = /* @__PURE__ */ new Map();
|
|
106
|
+
let pendingTotal = 0;
|
|
107
|
+
if (pendingRaw) {
|
|
108
|
+
try {
|
|
109
|
+
const parsed2 = JSON.parse(pendingRaw);
|
|
110
|
+
for (const [, list] of Object.entries(parsed2.bySigner ?? {})) {
|
|
111
|
+
for (const entry of list ?? []) {
|
|
112
|
+
pendingTotal++;
|
|
113
|
+
const m = (entry.artifactPath ?? "").match(/^engagements\/([^/]+)\//);
|
|
114
|
+
const engSlug = m?.[1];
|
|
115
|
+
if (!engSlug) continue;
|
|
116
|
+
const requested = parseDate(entry.requestedAt) ?? now;
|
|
117
|
+
const cur = pendingByEngagement.get(engSlug) ?? {
|
|
118
|
+
count: 0,
|
|
119
|
+
oldest: null
|
|
120
|
+
};
|
|
121
|
+
cur.count++;
|
|
122
|
+
if (!cur.oldest || requested < cur.oldest) cur.oldest = requested;
|
|
123
|
+
pendingByEngagement.set(engSlug, cur);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
130
|
+
"scoping",
|
|
131
|
+
"proposed",
|
|
132
|
+
"negotiating",
|
|
133
|
+
"signed",
|
|
134
|
+
"executing",
|
|
135
|
+
"in_progress",
|
|
136
|
+
"in-progress",
|
|
137
|
+
"pending_validation"
|
|
138
|
+
]);
|
|
139
|
+
const PIPELINE_STATUSES = /* @__PURE__ */ new Set(["scoping", "proposed", "negotiating"]);
|
|
140
|
+
const activeEngagements = engagements.filter(
|
|
141
|
+
(e) => ACTIVE_STATUSES.has(e.status)
|
|
142
|
+
);
|
|
143
|
+
const pipelineValue = engagements.filter((e) => PIPELINE_STATUSES.has(e.status)).reduce((sum, e) => sum + e.expectedValue, 0);
|
|
144
|
+
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
145
|
+
const activeEngagementsDelta = engagements.filter(
|
|
146
|
+
(e) => e.createdAt && e.createdAt >= monthStart
|
|
147
|
+
).length;
|
|
148
|
+
const mrr = invoices.filter((i) => i.status === "paid" && i.paidAt && i.paidAt >= monthStart).reduce((sum, i) => sum + i.amount, 0);
|
|
149
|
+
const byStatusMap = /* @__PURE__ */ new Map();
|
|
150
|
+
for (const e of engagements) {
|
|
151
|
+
const cur = byStatusMap.get(e.status) ?? { count: 0, value: 0 };
|
|
152
|
+
cur.count++;
|
|
153
|
+
cur.value += e.expectedValue;
|
|
154
|
+
byStatusMap.set(e.status, cur);
|
|
155
|
+
}
|
|
156
|
+
const byStatus = Array.from(byStatusMap.entries()).sort((a, b) => b[1].count - a[1].count).map(([status, { count, value }]) => ({
|
|
157
|
+
status,
|
|
158
|
+
pillClass: statusPillClass(status),
|
|
159
|
+
count,
|
|
160
|
+
valueFormatted: formatMoney(value)
|
|
161
|
+
}));
|
|
162
|
+
const recentPayments = invoices.filter((i) => i.status === "paid" && i.paidAt).sort((a, b) => b.paidAt.getTime() - a.paidAt.getTime()).slice(0, recentPaymentsLimit).map((i) => ({
|
|
163
|
+
invoiceNumber: i.invoiceNumber,
|
|
164
|
+
counterpartyDisplayName: i.counterpartyDisplayName,
|
|
165
|
+
amountFormatted: `${formatMoney(i.amount)} ${i.currency}`,
|
|
166
|
+
paidAt: i.paidAt.toISOString().slice(0, 10)
|
|
167
|
+
}));
|
|
168
|
+
const pendingByEngagementRows = Array.from(pendingByEngagement.entries()).map(([slug, { count, oldest }]) => {
|
|
169
|
+
const eng = engagements.find((e) => e.slug === slug);
|
|
170
|
+
const ageMs = oldest ? now.getTime() - oldest.getTime() : 0;
|
|
171
|
+
return {
|
|
172
|
+
slug,
|
|
173
|
+
name: eng?.name ?? slug,
|
|
174
|
+
requiredSigners: `${count} pending`,
|
|
175
|
+
oldestPendingAt: oldest ? oldest.toISOString().slice(0, 10) : "\u2014",
|
|
176
|
+
stalenessLabel: ageLabel(ageMs),
|
|
177
|
+
stalenessPillClass: stalenessPillClass(ageMs),
|
|
178
|
+
ageMs
|
|
179
|
+
};
|
|
180
|
+
}).sort((a, b) => b.ageMs - a.ageMs).map(({ ageMs: _ageMs, ...rest }) => rest);
|
|
181
|
+
const snapshotRaw = {
|
|
182
|
+
generatedAt: now.toISOString(),
|
|
183
|
+
isStale: false,
|
|
184
|
+
activeEngagementsCount: activeEngagements.length,
|
|
185
|
+
activeEngagementsDelta,
|
|
186
|
+
pipelineValueFormatted: formatMoney(pipelineValue),
|
|
187
|
+
mrrFormatted: formatMoney(mrr),
|
|
188
|
+
pendingSignaturesCount: pendingTotal,
|
|
189
|
+
byStatus,
|
|
190
|
+
recentPayments,
|
|
191
|
+
pendingByEngagement: pendingByEngagementRows
|
|
192
|
+
};
|
|
193
|
+
const parsed = agencyOverviewSnapshotSchema.safeParse(snapshotRaw);
|
|
194
|
+
if (!parsed.success) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
`computeAgencyOverview: produced an invalid snapshot \u2014 ${parsed.error.issues.map((i) => i.message).join("; ")}`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
const snapshot = parsed.data;
|
|
200
|
+
snapshot.isStale = isAgencyOverviewSnapshotStale(snapshot, freshnessMs, now);
|
|
201
|
+
let snapshotPath = null;
|
|
202
|
+
if (input.write !== false) {
|
|
203
|
+
const abs = resolveFromRoot(workspaceRoot, SNAPSHOT_REL_PATH);
|
|
204
|
+
await fs.ensureDir(path.dirname(abs));
|
|
205
|
+
await fs.writeFileAtomic(abs, JSON.stringify(snapshot, null, 2) + "\n");
|
|
206
|
+
snapshotPath = SNAPSHOT_REL_PATH;
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
snapshot,
|
|
210
|
+
snapshotPath,
|
|
211
|
+
walked: {
|
|
212
|
+
counterparties: counterparties.length,
|
|
213
|
+
engagements: engagements.length,
|
|
214
|
+
invoices: invoices.length,
|
|
215
|
+
skipped
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
async function listSubdirs(fs, workspaceRoot, rel) {
|
|
220
|
+
const abs = resolveFromRoot(workspaceRoot, rel);
|
|
221
|
+
const entries = await fs.listDirectory(abs);
|
|
222
|
+
return entries.filter((e) => e.isDirectory).map((e) => e.name);
|
|
223
|
+
}
|
|
224
|
+
async function readFrontmatter(fs, absPath) {
|
|
225
|
+
const content = await fs.readFile(absPath);
|
|
226
|
+
if (!content) return null;
|
|
227
|
+
try {
|
|
228
|
+
const parsed = matter(content);
|
|
229
|
+
return parsed.data;
|
|
230
|
+
} catch {
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function stringField(fm, key) {
|
|
235
|
+
const v = fm[key];
|
|
236
|
+
if (typeof v === "string") return v;
|
|
237
|
+
if (v instanceof Date) return v.toISOString();
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
function numberField(fm, key) {
|
|
241
|
+
const v = fm[key];
|
|
242
|
+
if (typeof v === "number") return v;
|
|
243
|
+
if (typeof v === "string") {
|
|
244
|
+
const n = Number(v);
|
|
245
|
+
return Number.isFinite(n) ? n : null;
|
|
246
|
+
}
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
function countRequiredSignatures(fm) {
|
|
250
|
+
const v = fm.requiredSignatures;
|
|
251
|
+
return Array.isArray(v) ? v.length : 0;
|
|
252
|
+
}
|
|
253
|
+
function parseDate(s) {
|
|
254
|
+
if (!s) return null;
|
|
255
|
+
const ms = Date.parse(s);
|
|
256
|
+
return Number.isNaN(ms) ? null : new Date(ms);
|
|
257
|
+
}
|
|
258
|
+
async function readEngagementExpectedValue(fs, workspaceRoot, engagementSlug) {
|
|
259
|
+
const agreementPath = resolveFromRoot(
|
|
260
|
+
workspaceRoot,
|
|
261
|
+
`engagements/${engagementSlug}/AGREEMENT.md`
|
|
262
|
+
);
|
|
263
|
+
const fm = await readFrontmatter(fs, agreementPath);
|
|
264
|
+
if (!fm) return 0;
|
|
265
|
+
const direct = numberField(fm, "totalAmount") ?? numberField(fm, "expectedValue");
|
|
266
|
+
if (direct != null) return direct;
|
|
267
|
+
const items = fm.lineItems;
|
|
268
|
+
if (Array.isArray(items)) {
|
|
269
|
+
return items.reduce((sum, li) => {
|
|
270
|
+
if (typeof li === "object" && li !== null && "total" in li) {
|
|
271
|
+
const t = li.total;
|
|
272
|
+
if (typeof t === "number") return sum + t;
|
|
273
|
+
}
|
|
274
|
+
return sum;
|
|
275
|
+
}, 0);
|
|
276
|
+
}
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
279
|
+
function statusPillClass(status) {
|
|
280
|
+
switch (status) {
|
|
281
|
+
case "signed":
|
|
282
|
+
case "executing":
|
|
283
|
+
case "in_progress":
|
|
284
|
+
case "in-progress":
|
|
285
|
+
return "ok";
|
|
286
|
+
case "pending_validation":
|
|
287
|
+
case "negotiating":
|
|
288
|
+
case "proposed":
|
|
289
|
+
case "scoping":
|
|
290
|
+
return "warn";
|
|
291
|
+
case "disputed":
|
|
292
|
+
case "cancelled":
|
|
293
|
+
case "void":
|
|
294
|
+
return "danger";
|
|
295
|
+
case "closed":
|
|
296
|
+
case "archived":
|
|
297
|
+
return "muted";
|
|
298
|
+
default:
|
|
299
|
+
return "";
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function stalenessPillClass(ageMs) {
|
|
303
|
+
const day = 24 * 60 * 60 * 1e3;
|
|
304
|
+
if (ageMs < 2 * day) return "ok";
|
|
305
|
+
if (ageMs < 7 * day) return "warn";
|
|
306
|
+
return "danger";
|
|
307
|
+
}
|
|
308
|
+
function ageLabel(ageMs) {
|
|
309
|
+
if (ageMs <= 0) return "just now";
|
|
310
|
+
const min = Math.round(ageMs / 6e4);
|
|
311
|
+
if (min < 60) return `${min}m`;
|
|
312
|
+
const hr = Math.round(min / 60);
|
|
313
|
+
if (hr < 48) return `${hr}h`;
|
|
314
|
+
const day = Math.round(hr / 24);
|
|
315
|
+
return `${day}d`;
|
|
316
|
+
}
|
|
317
|
+
function formatMoney(n) {
|
|
318
|
+
return n.toLocaleString("en-US", {
|
|
319
|
+
minimumFractionDigits: 2,
|
|
320
|
+
maximumFractionDigits: 2
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/index.ts
|
|
325
|
+
var AGENCY_OVERVIEW_SNAPSHOT_PATH = "_snapshots/agency-overview.json";
|
|
326
|
+
var AGENCY_OVERVIEW_ROLLUP_SNIPPET_PATH = "src/spec/snippets/agency-overview-rollup";
|
|
327
|
+
|
|
328
|
+
export { AGENCY_OVERVIEW_ROLLUP_SNIPPET_PATH, AGENCY_OVERVIEW_SNAPSHOT_PATH, computeAgencyOverview };
|
|
329
|
+
//# sourceMappingURL=index.mjs.map
|
|
330
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/compute-agency-overview.ts","../src/index.ts"],"names":["parsed"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * `computeAgencyOverview` — canonical Node implementation of the\n * `procedures/compute-agency-overview` PROCEDURE.md.\n *\n * Walks the workspace (counterparties/, engagements/, invoices/), projects\n * the aggregate into an `AgencyOverviewSnapshot`, optionally writes it to\n * `_snapshots/agency-overview.json`. Vendor-neutral — uses the\n * `IGovernanceFilesystem` adapter from `@agentproto/governance/runtime` so it\n * runs against LocalFilesystem in dev and SupabaseFilesystem in prod\n * without code changes.\n *\n * Designed to be called from:\n * - A Mastra workflow (`@agentproto/agencies-mastra` codegen wraps this in suspend/\n * resume primitives if needed).\n * - A cron-driven routine engine (e.g. Guilde's routine-executor).\n * - Ad-hoc by a CLI (`agencies overview compute <workspace>`).\n *\n * The compute is single-pass — no memoization, no incremental cache. For\n * very large agencies (>500 engagements) this should be replaced with a\n * watch-based incremental rebuild.\n */\n\nimport * as path from \"node:path\"\n\nimport {\n defaultGovernanceFilesystem,\n resolveFromRoot,\n type GovernanceConfig,\n type IGovernanceFilesystem,\n} from \"@agentproto/governance-engine\"\nimport matter from \"gray-matter\"\n\nimport {\n agencyOverviewSnapshotSchema,\n isAgencyOverviewSnapshotStale,\n type AgencyOverviewSnapshot,\n AGENCY_OVERVIEW_FRESHNESS_MS,\n} from \"@agentproto/agencies/renderers\"\n\nexport interface ComputeAgencyOverviewInput {\n /**\n * Workspace root + filesystem adapter. The same `GovernanceConfig` used by\n * the governance runtime — pass the whole config so Supabase-backed\n * workspaces work via `MastraFilesystemGovernanceAdapter`.\n *\n * Only `workspaceRoot` and `filesystem` are read; secrets (genesisSeed,\n * hmacSecret) are not used here.\n */\n config: Pick<GovernanceConfig, \"workspaceRoot\" | \"filesystem\">\n\n /**\n * If true, atomically write the snapshot to\n * `_snapshots/agency-overview.json`. Default: true.\n */\n write?: boolean\n\n /**\n * Override the `now` clock for deterministic tests.\n */\n now?: Date\n\n /**\n * Override the staleness threshold. Default: AGENCY_OVERVIEW_FRESHNESS_MS.\n */\n freshnessMs?: number\n\n /**\n * How many recent payments to include in the snapshot. Default: 5.\n */\n recentPaymentsLimit?: number\n}\n\nexport interface ComputeAgencyOverviewResult {\n snapshot: AgencyOverviewSnapshot\n /** Workspace-relative path to the written snapshot, or null when `write: false`. */\n snapshotPath: string | null\n /** Counts useful for the audit-log entry the routine writes after a successful run. */\n walked: {\n counterparties: number\n engagements: number\n invoices: number\n skipped: number\n }\n}\n\nconst SNAPSHOT_REL_PATH = \"_snapshots/agency-overview.json\"\n\nexport async function computeAgencyOverview(\n input: ComputeAgencyOverviewInput\n): Promise<ComputeAgencyOverviewResult> {\n const fs = input.config.filesystem ?? defaultGovernanceFilesystem()\n const workspaceRoot = input.config.workspaceRoot\n const now = input.now ?? new Date()\n const freshnessMs = input.freshnessMs ?? AGENCY_OVERVIEW_FRESHNESS_MS\n const recentPaymentsLimit = input.recentPaymentsLimit ?? 5\n\n let skipped = 0\n\n // ── 1. Counterparties ──────────────────────────────────────────────\n const counterpartyDirs = await listSubdirs(\n fs,\n workspaceRoot,\n \"counterparties\"\n )\n const counterparties: Array<{\n slug: string\n displayName: string\n status: string | null\n }> = []\n for (const dir of counterpartyDirs) {\n const fmPath = resolveFromRoot(\n workspaceRoot,\n `counterparties/${dir}/COUNTERPARTY.md`\n )\n const fm = await readFrontmatter(fs, fmPath)\n if (!fm) {\n skipped++\n continue\n }\n counterparties.push({\n slug: dir,\n displayName:\n stringField(fm, \"displayName\") ?? stringField(fm, \"name\") ?? dir,\n status: stringField(fm, \"status\"),\n })\n }\n\n // ── 2. Engagements ─────────────────────────────────────────────────\n const engagementDirs = await listSubdirs(fs, workspaceRoot, \"engagements\")\n type EngagementRow = {\n slug: string\n name: string\n status: string\n activeStep: string | null\n counterpartyId: string | null\n counterpartyDisplayName: string\n expectedValue: number\n requiredSignerCount: number\n createdAt: Date | null\n }\n const engagements: EngagementRow[] = []\n for (const dir of engagementDirs) {\n const fmPath = resolveFromRoot(\n workspaceRoot,\n `engagements/${dir}/ENGAGEMENT.md`\n )\n const fm = await readFrontmatter(fs, fmPath)\n if (!fm) {\n skipped++\n continue\n }\n const counterpartyId = stringField(fm, \"counterpartyId\")\n const counterparty = counterparties.find(c => c.slug === counterpartyId)\n const expectedValue = await readEngagementExpectedValue(\n fs,\n workspaceRoot,\n dir\n )\n engagements.push({\n slug: dir,\n name: stringField(fm, \"name\") ?? dir,\n status: stringField(fm, \"status\") ?? \"unknown\",\n activeStep: stringField(fm, \"activeStep\"),\n counterpartyId,\n counterpartyDisplayName:\n counterparty?.displayName ?? counterpartyId ?? \"—\",\n expectedValue,\n requiredSignerCount: countRequiredSignatures(fm),\n createdAt: parseDate(stringField(fm, \"createdAt\")),\n })\n }\n\n // ── 3. Invoices ────────────────────────────────────────────────────\n type InvoiceRow = {\n invoiceNumber: string\n amount: number\n currency: string\n status: string\n paidAt: Date | null\n counterpartyDisplayName: string\n }\n const invoices: InvoiceRow[] = []\n for (const eng of engagements) {\n const invoiceDirs = await listSubdirs(\n fs,\n workspaceRoot,\n `engagements/${eng.slug}/invoices`\n )\n for (const invDir of invoiceDirs) {\n const fmPath = resolveFromRoot(\n workspaceRoot,\n `engagements/${eng.slug}/invoices/${invDir}/INVOICE.md`\n )\n const fm = await readFrontmatter(fs, fmPath)\n if (!fm) {\n skipped++\n continue\n }\n invoices.push({\n invoiceNumber: stringField(fm, \"invoiceNumber\") ?? invDir,\n amount:\n numberField(fm, \"totalAmount\") ?? numberField(fm, \"amount\") ?? 0,\n currency: stringField(fm, \"currency\") ?? \"EUR\",\n status: stringField(fm, \"status\") ?? \"issued\",\n paidAt: parseDate(stringField(fm, \"paidAt\")),\n counterpartyDisplayName: eng.counterpartyDisplayName,\n })\n }\n }\n\n // ── 4. Pending signatures index ────────────────────────────────────\n const pendingPath = resolveFromRoot(\n workspaceRoot,\n \"_index/pending-signatures.json\"\n )\n const pendingRaw = await fs.readFile(pendingPath)\n let pendingByEngagement: Map<string, { count: number; oldest: Date | null }> =\n new Map()\n let pendingTotal = 0\n if (pendingRaw) {\n try {\n const parsed = JSON.parse(pendingRaw) as {\n bySigner?: Record<\n string,\n Array<{ artifactPath?: string; requestedAt?: string }>\n >\n }\n for (const [, list] of Object.entries(parsed.bySigner ?? {})) {\n for (const entry of list ?? []) {\n pendingTotal++\n const m = (entry.artifactPath ?? \"\").match(/^engagements\\/([^/]+)\\//)\n const engSlug = m?.[1]\n if (!engSlug) continue\n const requested = parseDate(entry.requestedAt) ?? now\n const cur = pendingByEngagement.get(engSlug) ?? {\n count: 0,\n oldest: null,\n }\n cur.count++\n if (!cur.oldest || requested < cur.oldest) cur.oldest = requested\n pendingByEngagement.set(engSlug, cur)\n }\n }\n } catch {\n // Corrupted index — leave totals at zero rather than failing the snapshot.\n }\n }\n\n // ── 5. Project the snapshot ────────────────────────────────────────\n const ACTIVE_STATUSES = new Set([\n \"scoping\",\n \"proposed\",\n \"negotiating\",\n \"signed\",\n \"executing\",\n \"in_progress\",\n \"in-progress\",\n \"pending_validation\",\n ])\n const PIPELINE_STATUSES = new Set([\"scoping\", \"proposed\", \"negotiating\"])\n\n const activeEngagements = engagements.filter(e =>\n ACTIVE_STATUSES.has(e.status)\n )\n const pipelineValue = engagements\n .filter(e => PIPELINE_STATUSES.has(e.status))\n .reduce((sum, e) => sum + e.expectedValue, 0)\n\n // Active-engagements delta = engagements created this calendar month.\n const monthStart = new Date(now.getFullYear(), now.getMonth(), 1)\n const activeEngagementsDelta = engagements.filter(\n e => e.createdAt && e.createdAt >= monthStart\n ).length\n\n // MRR — sum of paid invoices in the current calendar month.\n const mrr = invoices\n .filter(i => i.status === \"paid\" && i.paidAt && i.paidAt >= monthStart)\n .reduce((sum, i) => sum + i.amount, 0)\n\n // Group engagements by status.\n const byStatusMap = new Map<string, { count: number; value: number }>()\n for (const e of engagements) {\n const cur = byStatusMap.get(e.status) ?? { count: 0, value: 0 }\n cur.count++\n cur.value += e.expectedValue\n byStatusMap.set(e.status, cur)\n }\n const byStatus = Array.from(byStatusMap.entries())\n .sort((a, b) => b[1].count - a[1].count)\n .map(([status, { count, value }]) => ({\n status,\n pillClass: statusPillClass(status),\n count,\n valueFormatted: formatMoney(value),\n }))\n\n // Recent payments — top N most-recent paid invoices.\n const recentPayments = invoices\n .filter(i => i.status === \"paid\" && i.paidAt)\n .sort((a, b) => b.paidAt!.getTime() - a.paidAt!.getTime())\n .slice(0, recentPaymentsLimit)\n .map(i => ({\n invoiceNumber: i.invoiceNumber,\n counterpartyDisplayName: i.counterpartyDisplayName,\n amountFormatted: `${formatMoney(i.amount)} ${i.currency}`,\n paidAt: i.paidAt!.toISOString().slice(0, 10),\n }))\n\n // Pending-signature engagements — sort oldest-first.\n const pendingByEngagementRows = Array.from(pendingByEngagement.entries())\n .map(([slug, { count, oldest }]) => {\n const eng = engagements.find(e => e.slug === slug)\n const ageMs = oldest ? now.getTime() - oldest.getTime() : 0\n return {\n slug,\n name: eng?.name ?? slug,\n requiredSigners: `${count} pending`,\n oldestPendingAt: oldest ? oldest.toISOString().slice(0, 10) : \"—\",\n stalenessLabel: ageLabel(ageMs),\n stalenessPillClass: stalenessPillClass(ageMs),\n ageMs,\n }\n })\n .sort((a, b) => b.ageMs - a.ageMs)\n .map(({ ageMs: _ageMs, ...rest }) => rest)\n\n const snapshotRaw = {\n generatedAt: now.toISOString(),\n isStale: false,\n activeEngagementsCount: activeEngagements.length,\n activeEngagementsDelta,\n pipelineValueFormatted: formatMoney(pipelineValue),\n mrrFormatted: formatMoney(mrr),\n pendingSignaturesCount: pendingTotal,\n byStatus,\n recentPayments,\n pendingByEngagement: pendingByEngagementRows,\n }\n\n const parsed = agencyOverviewSnapshotSchema.safeParse(snapshotRaw)\n if (!parsed.success) {\n throw new Error(\n `computeAgencyOverview: produced an invalid snapshot — ${parsed.error.issues\n .map(i => i.message)\n .join(\"; \")}`\n )\n }\n const snapshot = parsed.data\n // Re-stamp isStale against the chosen freshness window so writers and\n // readers agree on staleness without re-checking the clock.\n snapshot.isStale = isAgencyOverviewSnapshotStale(snapshot, freshnessMs, now)\n\n // ── 6. Write the snapshot ──────────────────────────────────────────\n let snapshotPath: string | null = null\n if (input.write !== false) {\n const abs = resolveFromRoot(workspaceRoot, SNAPSHOT_REL_PATH)\n await fs.ensureDir(path.dirname(abs))\n await fs.writeFileAtomic(abs, JSON.stringify(snapshot, null, 2) + \"\\n\")\n snapshotPath = SNAPSHOT_REL_PATH\n }\n\n return {\n snapshot,\n snapshotPath,\n walked: {\n counterparties: counterparties.length,\n engagements: engagements.length,\n invoices: invoices.length,\n skipped,\n },\n }\n}\n\n// ─── Helpers ───────────────────────────────────────────────────────────\n\nasync function listSubdirs(\n fs: IGovernanceFilesystem,\n workspaceRoot: string,\n rel: string\n): Promise<string[]> {\n const abs = resolveFromRoot(workspaceRoot, rel)\n const entries = await fs.listDirectory(abs)\n return entries.filter(e => e.isDirectory).map(e => e.name)\n}\n\nasync function readFrontmatter(\n fs: IGovernanceFilesystem,\n absPath: string\n): Promise<Record<string, unknown> | null> {\n const content = await fs.readFile(absPath)\n if (!content) return null\n try {\n const parsed = matter(content)\n return parsed.data as Record<string, unknown>\n } catch {\n return null\n }\n}\n\nfunction stringField(fm: Record<string, unknown>, key: string): string | null {\n const v = fm[key]\n if (typeof v === \"string\") return v\n // YAML 1.1 auto-parses ISO date strings to Date objects (gray-matter →\n // js-yaml). Coerce back to ISO so date-shaped frontmatter fields still\n // expose a string when callers ask for one.\n if (v instanceof Date) return v.toISOString()\n return null\n}\n\nfunction numberField(fm: Record<string, unknown>, key: string): number | null {\n const v = fm[key]\n if (typeof v === \"number\") return v\n if (typeof v === \"string\") {\n const n = Number(v)\n return Number.isFinite(n) ? n : null\n }\n return null\n}\n\nfunction countRequiredSignatures(fm: Record<string, unknown>): number {\n const v = fm.requiredSignatures\n return Array.isArray(v) ? v.length : 0\n}\n\nfunction parseDate(s: string | null | undefined): Date | null {\n if (!s) return null\n const ms = Date.parse(s)\n return Number.isNaN(ms) ? null : new Date(ms)\n}\n\nasync function readEngagementExpectedValue(\n fs: IGovernanceFilesystem,\n workspaceRoot: string,\n engagementSlug: string\n): Promise<number> {\n const agreementPath = resolveFromRoot(\n workspaceRoot,\n `engagements/${engagementSlug}/AGREEMENT.md`\n )\n const fm = await readFrontmatter(fs, agreementPath)\n if (!fm) return 0\n const direct =\n numberField(fm, \"totalAmount\") ?? numberField(fm, \"expectedValue\")\n if (direct != null) return direct\n // Fall back to summing line items.\n const items = fm.lineItems\n if (Array.isArray(items)) {\n return items.reduce((sum: number, li: unknown) => {\n if (typeof li === \"object\" && li !== null && \"total\" in li) {\n const t = (li as { total: unknown }).total\n if (typeof t === \"number\") return sum + t\n }\n return sum\n }, 0)\n }\n return 0\n}\n\nfunction statusPillClass(\n status: string\n): \"\" | \"ok\" | \"warn\" | \"danger\" | \"muted\" {\n switch (status) {\n case \"signed\":\n case \"executing\":\n case \"in_progress\":\n case \"in-progress\":\n return \"ok\"\n case \"pending_validation\":\n case \"negotiating\":\n case \"proposed\":\n case \"scoping\":\n return \"warn\"\n case \"disputed\":\n case \"cancelled\":\n case \"void\":\n return \"danger\"\n case \"closed\":\n case \"archived\":\n return \"muted\"\n default:\n return \"\"\n }\n}\n\nfunction stalenessPillClass(ageMs: number): \"\" | \"ok\" | \"warn\" | \"danger\" {\n const day = 24 * 60 * 60 * 1000\n if (ageMs < 2 * day) return \"ok\"\n if (ageMs < 7 * day) return \"warn\"\n return \"danger\"\n}\n\nfunction ageLabel(ageMs: number): string {\n if (ageMs <= 0) return \"just now\"\n const min = Math.round(ageMs / 60000)\n if (min < 60) return `${min}m`\n const hr = Math.round(min / 60)\n if (hr < 48) return `${hr}h`\n const day = Math.round(hr / 24)\n return `${day}d`\n}\n\nfunction formatMoney(n: number): string {\n return n.toLocaleString(\"en-US\", {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })\n}\n","/**\n * agentagencies/v1 runtime — FS-only helpers.\n *\n * NO Mastra, LangChain, Temporal imports. The vendor-neutral runtime that any\n * orchestrator can consume. Vendor adapters (e.g., @agentproto/agencies-mastra) wrap\n * these helpers with workflow-specific suspend/resume primitives.\n */\n\nexport {\n computeAgencyOverview,\n type ComputeAgencyOverviewInput,\n type ComputeAgencyOverviewResult,\n} from \"./compute-agency-overview.js\"\n\n/** Workspace-relative path of the snapshot the routine writes. */\nexport const AGENCY_OVERVIEW_SNAPSHOT_PATH =\n \"_snapshots/agency-overview.json\" as const\n\n/** Path of the bundled rollup snippets folder (relative to the package root). */\nexport const AGENCY_OVERVIEW_ROLLUP_SNIPPET_PATH =\n \"src/spec/snippets/agency-overview-rollup\" as const\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@agentproto/agencies-engine",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "agentagencies/v1 reference engine — workspace walkers (computeAgencyOverview), index helpers, and FS-only orchestration. Routes I/O through @agentproto/governance-engine's IGovernanceFilesystem so it works against Node fs (dev) and Supabase / S3 (prod) via the same code path.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"agentagencies",
|
|
7
|
+
"agencies",
|
|
8
|
+
"engine",
|
|
9
|
+
"workspace",
|
|
10
|
+
"rollup",
|
|
11
|
+
"snapshot",
|
|
12
|
+
"filesystem-adapter",
|
|
13
|
+
"open-standard",
|
|
14
|
+
"agentic"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://agentproto.sh/docs/agp-1",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/agentproto/ts",
|
|
20
|
+
"directory": "packages/agencies/engine"
|
|
21
|
+
},
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/agentproto/ts/issues"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"type": "module",
|
|
27
|
+
"main": "dist/index.mjs",
|
|
28
|
+
"module": "dist/index.mjs",
|
|
29
|
+
"types": "dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.mjs",
|
|
34
|
+
"default": "./dist/index.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./package.json": "./package.json"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"gray-matter": "^4.0.3",
|
|
48
|
+
"@agentproto/agencies": "0.1.0-alpha.0",
|
|
49
|
+
"@agentproto/governance": "0.1.0-alpha.0",
|
|
50
|
+
"@agentproto/governance-engine": "0.1.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/node": "^25.6.2",
|
|
54
|
+
"tsup": "^8.5.1",
|
|
55
|
+
"typescript": "^5.9.3",
|
|
56
|
+
"vitest": "^3.2.4",
|
|
57
|
+
"@agentproto/tooling": "0.1.0-alpha.0"
|
|
58
|
+
},
|
|
59
|
+
"scripts": {
|
|
60
|
+
"dev": "tsup --watch",
|
|
61
|
+
"build": "tsup",
|
|
62
|
+
"clean": "rm -rf dist",
|
|
63
|
+
"check-types": "tsc --noEmit",
|
|
64
|
+
"test": "vitest run",
|
|
65
|
+
"test:watch": "vitest"
|
|
66
|
+
}
|
|
67
|
+
}
|