@monoes/monomindcli 2.9.21 → 2.9.22
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/.claude/skills/mastermind-createorg/SKILL.md +26 -3
- package/dist/src/commands/events.d.ts +9 -0
- package/dist/src/commands/events.d.ts.map +1 -0
- package/dist/src/commands/events.js +89 -0
- package/dist/src/commands/events.js.map +1 -0
- package/dist/src/commands/index.d.ts +1 -1
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +2 -1
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/org-observe.d.ts +21 -0
- package/dist/src/commands/org-observe.d.ts.map +1 -1
- package/dist/src/commands/org-observe.js +79 -0
- package/dist/src/commands/org-observe.js.map +1 -1
- package/dist/src/commands/org.d.ts.map +1 -1
- package/dist/src/commands/org.js +20 -0
- package/dist/src/commands/org.js.map +1 -1
- package/dist/src/orgrt/approvals.d.ts +16 -1
- package/dist/src/orgrt/approvals.d.ts.map +1 -1
- package/dist/src/orgrt/approvals.js +39 -2
- package/dist/src/orgrt/approvals.js.map +1 -1
- package/dist/src/orgrt/copilot-runner.d.ts +14 -0
- package/dist/src/orgrt/copilot-runner.d.ts.map +1 -0
- package/dist/src/orgrt/copilot-runner.js +250 -0
- package/dist/src/orgrt/copilot-runner.js.map +1 -0
- package/dist/src/orgrt/crush-runner.d.ts +24 -0
- package/dist/src/orgrt/crush-runner.d.ts.map +1 -0
- package/dist/src/orgrt/crush-runner.js +251 -0
- package/dist/src/orgrt/crush-runner.js.map +1 -0
- package/dist/src/orgrt/daemon.d.ts +40 -1
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +63 -2
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/grok-runner.d.ts +18 -0
- package/dist/src/orgrt/grok-runner.d.ts.map +1 -0
- package/dist/src/orgrt/grok-runner.js +323 -0
- package/dist/src/orgrt/grok-runner.js.map +1 -0
- package/dist/src/orgrt/pi-rpc-runner.d.ts +68 -0
- package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -0
- package/dist/src/orgrt/pi-rpc-runner.js +400 -0
- package/dist/src/orgrt/pi-rpc-runner.js.map +1 -0
- package/dist/src/orgrt/pi-runner.d.ts +16 -0
- package/dist/src/orgrt/pi-runner.d.ts.map +1 -0
- package/dist/src/orgrt/pi-runner.js +264 -0
- package/dist/src/orgrt/pi-runner.js.map +1 -0
- package/dist/src/orgrt/qwen-runner.d.ts +18 -0
- package/dist/src/orgrt/qwen-runner.d.ts.map +1 -0
- package/dist/src/orgrt/qwen-runner.js +267 -0
- package/dist/src/orgrt/qwen-runner.js.map +1 -0
- package/dist/src/orgrt/types.d.ts +18 -0
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +2 -2
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/orgrt/usage-proxy.d.ts +32 -0
- package/dist/src/orgrt/usage-proxy.d.ts.map +1 -0
- package/dist/src/orgrt/usage-proxy.js +226 -0
- package/dist/src/orgrt/usage-proxy.js.map +1 -0
- package/dist/src/ui/dashboard.html +63 -0
- package/dist/src/ui/orgs.html +8 -1
- package/dist/src/ui/routes-org.mjs +26 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
package/dist/src/orgrt/types.js
CHANGED
|
@@ -96,7 +96,7 @@ export const RoleSchema = z.object({
|
|
|
96
96
|
* agent runtime regardless of the org-level `runtime` field or the
|
|
97
97
|
* MONOMIND_RUNTIME env var ('claude' explicitly forces the Claude default).
|
|
98
98
|
* Enables mixed-runtime orgs — e.g. a Claude coordinator with opencode workers. */
|
|
99
|
-
runtime: z.enum(['claude', 'kimicode', 'opencode', 'vercel', 'codex', 'antigravity']).optional(),
|
|
99
|
+
runtime: z.enum(['claude', 'kimicode', 'opencode', 'vercel', 'codex', 'antigravity', 'grok', 'qwen', 'crush', 'copilot', 'pi', 'pi-rpc']).optional(),
|
|
100
100
|
/** Per-role override of run_config.max_turns_per_message — roles that legitimately
|
|
101
101
|
* need many more turns per message (e.g. a developer doing sequential build/fix/verify
|
|
102
102
|
* cycles) than others (e.g. docs, pm) shouldn't be forced onto one global budget. */
|
|
@@ -155,7 +155,7 @@ export const OrgDefSchema = z.object({
|
|
|
155
155
|
* MONOMIND_RUNTIME env var is honored, falling back to the default Claude
|
|
156
156
|
* runner. Per-org values override the env var, and a role's own `runtime`
|
|
157
157
|
* field (see RoleSchema) overrides this per role. */
|
|
158
|
-
runtime: z.enum(['claude', 'kimicode', 'opencode', 'vercel', 'codex', 'antigravity']).optional(),
|
|
158
|
+
runtime: z.enum(['claude', 'kimicode', 'opencode', 'vercel', 'codex', 'antigravity', 'grok', 'qwen', 'crush', 'copilot', 'pi', 'pi-rpc']).optional(),
|
|
159
159
|
}).passthrough();
|
|
160
160
|
export const ORG_DIR = '.monomind/orgs';
|
|
161
161
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/orgrt/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/orgrt/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export interface UsageTotals {
|
|
2
|
+
inputTokens: number;
|
|
3
|
+
outputTokens: number;
|
|
4
|
+
}
|
|
5
|
+
export type UsageApiStyle = 'openai' | 'anthropic';
|
|
6
|
+
export interface UsageProxyOptions {
|
|
7
|
+
/** The real API base URL requests are relayed to, e.g. https://api.openai.com. */
|
|
8
|
+
upstreamBaseUrl: string;
|
|
9
|
+
/** Which response-body shape to look for usage in. */
|
|
10
|
+
apiStyle: UsageApiStyle;
|
|
11
|
+
}
|
|
12
|
+
/** Parse a (possibly SSE) response body buffer for the usage it carries,
|
|
13
|
+
* merging per-field across every JSON document / SSE chunk found (not
|
|
14
|
+
* "last chunk wins" as a whole object — see mergeUsage). Handles both a
|
|
15
|
+
* single JSON document and `data: {...}\n\n` SSE framing. Exported for unit
|
|
16
|
+
* testing without spinning up a real server. */
|
|
17
|
+
export declare function parseUsageFromResponseBody(body: string, apiStyle: UsageApiStyle): UsageTotals | undefined;
|
|
18
|
+
export declare class UsageProxyServer {
|
|
19
|
+
private opts;
|
|
20
|
+
private server;
|
|
21
|
+
private boundPort;
|
|
22
|
+
private totalsAcc;
|
|
23
|
+
private readonly upstream;
|
|
24
|
+
constructor(opts: UsageProxyOptions);
|
|
25
|
+
start(): Promise<void>;
|
|
26
|
+
url(): string;
|
|
27
|
+
totals(): UsageTotals;
|
|
28
|
+
reset(): void;
|
|
29
|
+
stop(): Promise<void>;
|
|
30
|
+
private handle;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=usage-proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-proxy.d.ts","sourceRoot":"","sources":["../../../src/orgrt/usage-proxy.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEnD,MAAM,WAAW,iBAAiB;IAChC,kFAAkF;IAClF,eAAe,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,QAAQ,EAAE,aAAa,CAAC;CACzB;AAoDD;;;;iDAIiD;AACjD,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,WAAW,GAAG,SAAS,CAyCzG;AAED,qBAAa,gBAAgB;IAMf,OAAO,CAAC,IAAI;IALxB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,SAAS,CAAoD;IACrE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAM;IAE/B,YAAoB,IAAI,EAAE,iBAAiB,EAE1C;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAS3B;IAED,GAAG,IAAI,MAAM,CAEZ;IAED,MAAM,IAAI,WAAW,CAEpB;IAED,KAAK,IAAI,IAAI,CAEZ;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAI1B;IAED,OAAO,CAAC,MAAM;CAuDf"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// packages/@monomind/cli/src/orgrt/usage-proxy.ts
|
|
2
|
+
/**
|
|
3
|
+
* UsageProxyServer — a loopback HTTP reverse proxy that sits between a
|
|
4
|
+
* subprocess CLI and its configured LLM API base URL, purely to observe
|
|
5
|
+
* token usage. It is NOT part of the request/response path functionally —
|
|
6
|
+
* every request/response is relayed byte-for-byte unchanged; usage parsing
|
|
7
|
+
* is a side-channel that never affects what the CLI sees.
|
|
8
|
+
*
|
|
9
|
+
* Why this exists: some subprocess-backed AgentRunners (CrushAgentRunner,
|
|
10
|
+
* CopilotAgentRunner) drive CLIs whose non-interactive output doesn't
|
|
11
|
+
* self-report token usage the way codex/kimi/qwen/grok's JSON event streams
|
|
12
|
+
* do. Those CLIs DO support pointing at a custom OpenAI-compatible (or
|
|
13
|
+
* Anthropic-compatible) base URL for BYOK/self-hosted use — this proxy uses
|
|
14
|
+
* that existing knob rather than needing any CLI-side cooperation: the
|
|
15
|
+
* runner starts a UsageProxyServer pointed at the real upstream, sets the
|
|
16
|
+
* CLI's base-url env var to `proxy.url()`, and reads `proxy.totals()` after
|
|
17
|
+
* each turn.
|
|
18
|
+
*
|
|
19
|
+
* Deliberately generic — not tied to crush/copilot specifically. Any future
|
|
20
|
+
* subprocess runner whose CLI doesn't self-report usage can reuse this.
|
|
21
|
+
*/
|
|
22
|
+
import { createServer as createHttpServer, request as httpRequest } from 'node:http';
|
|
23
|
+
import { request as httpsRequest } from 'node:https';
|
|
24
|
+
import { URL } from 'node:url';
|
|
25
|
+
/** Extract usage tokens from a single parsed JSON body (a plain
|
|
26
|
+
* chat-completion response, or one SSE `data:` chunk). Returns undefined
|
|
27
|
+
* when the body has no usage field — callers accumulate across chunks.
|
|
28
|
+
*
|
|
29
|
+
* Anthropic-specific: input_tokens arrives on the `message_start` SSE event
|
|
30
|
+
* under `message.usage` (NOT top-level `usage`), while output_tokens
|
|
31
|
+
* arrives on later `message_delta` events under top-level `usage` — the two
|
|
32
|
+
* fields legitimately arrive in DIFFERENT chunks of the same stream. Fields
|
|
33
|
+
* are OPTIONAL in the return value (omitted, not defaulted to 0) precisely
|
|
34
|
+
* so the caller can merge per-field across chunks instead of the last
|
|
35
|
+
* chunk's presence/absence clobbering an earlier chunk's value — a body
|
|
36
|
+
* shape returning always-present-defaulted-to-0 fields made that merge
|
|
37
|
+
* impossible to do correctly upstream. */
|
|
38
|
+
function extractUsageFromBody(body, apiStyle) {
|
|
39
|
+
if (!body || typeof body !== 'object')
|
|
40
|
+
return undefined;
|
|
41
|
+
const record = body;
|
|
42
|
+
const topUsage = record.usage;
|
|
43
|
+
const nestedMessageUsage = apiStyle === 'anthropic' && record.message && typeof record.message === 'object'
|
|
44
|
+
? record.message.usage
|
|
45
|
+
: undefined;
|
|
46
|
+
if (apiStyle === 'anthropic') {
|
|
47
|
+
const topU = (topUsage && typeof topUsage === 'object') ? topUsage : undefined;
|
|
48
|
+
const nestedU = (nestedMessageUsage && typeof nestedMessageUsage === 'object') ? nestedMessageUsage : undefined;
|
|
49
|
+
if (!topU && !nestedU)
|
|
50
|
+
return undefined;
|
|
51
|
+
const input = nestedU?.input_tokens ?? topU?.input_tokens;
|
|
52
|
+
const output = topU?.output_tokens ?? nestedU?.output_tokens;
|
|
53
|
+
const result = {};
|
|
54
|
+
if (typeof input === 'number')
|
|
55
|
+
result.inputTokens = input;
|
|
56
|
+
if (typeof output === 'number')
|
|
57
|
+
result.outputTokens = output;
|
|
58
|
+
return (result.inputTokens !== undefined || result.outputTokens !== undefined) ? result : undefined;
|
|
59
|
+
}
|
|
60
|
+
// openai style
|
|
61
|
+
if (!topUsage || typeof topUsage !== 'object')
|
|
62
|
+
return undefined;
|
|
63
|
+
const u = topUsage;
|
|
64
|
+
const result = {};
|
|
65
|
+
if (typeof u.prompt_tokens === 'number')
|
|
66
|
+
result.inputTokens = u.prompt_tokens;
|
|
67
|
+
if (typeof u.completion_tokens === 'number')
|
|
68
|
+
result.outputTokens = u.completion_tokens;
|
|
69
|
+
return (result.inputTokens !== undefined || result.outputTokens !== undefined) ? result : undefined;
|
|
70
|
+
}
|
|
71
|
+
/** Merge a newly-seen partial usage reading into an accumulator, per field —
|
|
72
|
+
* a later chunk that doesn't report a field must not erase an earlier
|
|
73
|
+
* chunk's value for that field (see extractUsageFromBody's header). */
|
|
74
|
+
function mergeUsage(acc, next) {
|
|
75
|
+
if (next.inputTokens !== undefined)
|
|
76
|
+
acc.inputTokens = next.inputTokens;
|
|
77
|
+
if (next.outputTokens !== undefined)
|
|
78
|
+
acc.outputTokens = next.outputTokens;
|
|
79
|
+
}
|
|
80
|
+
/** Parse a (possibly SSE) response body buffer for the usage it carries,
|
|
81
|
+
* merging per-field across every JSON document / SSE chunk found (not
|
|
82
|
+
* "last chunk wins" as a whole object — see mergeUsage). Handles both a
|
|
83
|
+
* single JSON document and `data: {...}\n\n` SSE framing. Exported for unit
|
|
84
|
+
* testing without spinning up a real server. */
|
|
85
|
+
export function parseUsageFromResponseBody(body, apiStyle) {
|
|
86
|
+
const trimmed = body.trim();
|
|
87
|
+
if (!trimmed)
|
|
88
|
+
return undefined;
|
|
89
|
+
const merged = {};
|
|
90
|
+
if (trimmed.startsWith('{') || trimmed.startsWith('[')) {
|
|
91
|
+
try {
|
|
92
|
+
const parsed = JSON.parse(trimmed);
|
|
93
|
+
if (Array.isArray(parsed)) {
|
|
94
|
+
for (const item of parsed) {
|
|
95
|
+
const u = extractUsageFromBody(item, apiStyle);
|
|
96
|
+
if (u)
|
|
97
|
+
mergeUsage(merged, u);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
const u = extractUsageFromBody(parsed, apiStyle);
|
|
102
|
+
if (u)
|
|
103
|
+
mergeUsage(merged, u);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|
|
109
|
+
return (merged.inputTokens !== undefined || merged.outputTokens !== undefined)
|
|
110
|
+
? { inputTokens: merged.inputTokens ?? 0, outputTokens: merged.outputTokens ?? 0 }
|
|
111
|
+
: undefined;
|
|
112
|
+
}
|
|
113
|
+
// SSE framing: scan every `data: ` line, merging per field across chunks.
|
|
114
|
+
for (const rawLine of trimmed.split('\n')) {
|
|
115
|
+
const line = rawLine.trim();
|
|
116
|
+
if (!line.startsWith('data:'))
|
|
117
|
+
continue;
|
|
118
|
+
const payload = line.slice(5).trim();
|
|
119
|
+
if (!payload || payload === '[DONE]')
|
|
120
|
+
continue;
|
|
121
|
+
try {
|
|
122
|
+
const u = extractUsageFromBody(JSON.parse(payload), apiStyle);
|
|
123
|
+
if (u)
|
|
124
|
+
mergeUsage(merged, u);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// ignore malformed SSE chunk — best-effort side-channel
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return (merged.inputTokens !== undefined || merged.outputTokens !== undefined)
|
|
131
|
+
? { inputTokens: merged.inputTokens ?? 0, outputTokens: merged.outputTokens ?? 0 }
|
|
132
|
+
: undefined;
|
|
133
|
+
}
|
|
134
|
+
export class UsageProxyServer {
|
|
135
|
+
opts;
|
|
136
|
+
server;
|
|
137
|
+
boundPort = 0;
|
|
138
|
+
totalsAcc = { inputTokens: 0, outputTokens: 0 };
|
|
139
|
+
upstream;
|
|
140
|
+
constructor(opts) {
|
|
141
|
+
this.opts = opts;
|
|
142
|
+
this.upstream = new URL(opts.upstreamBaseUrl);
|
|
143
|
+
}
|
|
144
|
+
async start() {
|
|
145
|
+
if (this.server)
|
|
146
|
+
return;
|
|
147
|
+
this.server = createHttpServer((req, res) => this.handle(req, res));
|
|
148
|
+
await new Promise((resolve, reject) => {
|
|
149
|
+
this.server.once('error', reject);
|
|
150
|
+
this.server.listen(0, '127.0.0.1', () => resolve());
|
|
151
|
+
});
|
|
152
|
+
const addr = this.server.address();
|
|
153
|
+
this.boundPort = typeof addr === 'object' && addr ? addr.port : 0;
|
|
154
|
+
}
|
|
155
|
+
url() {
|
|
156
|
+
return `http://127.0.0.1:${this.boundPort}`;
|
|
157
|
+
}
|
|
158
|
+
totals() {
|
|
159
|
+
return { ...this.totalsAcc };
|
|
160
|
+
}
|
|
161
|
+
reset() {
|
|
162
|
+
this.totalsAcc = { inputTokens: 0, outputTokens: 0 };
|
|
163
|
+
}
|
|
164
|
+
async stop() {
|
|
165
|
+
if (!this.server)
|
|
166
|
+
return;
|
|
167
|
+
await new Promise((resolve) => this.server.close(() => resolve()));
|
|
168
|
+
this.server = undefined;
|
|
169
|
+
}
|
|
170
|
+
handle(clientReq, clientRes) {
|
|
171
|
+
const isHttps = this.upstream.protocol === 'https:';
|
|
172
|
+
const upstreamPath = (clientReq.url ?? '/');
|
|
173
|
+
// Force identity encoding: parseUsageFromResponseBody reads the response
|
|
174
|
+
// body as raw utf8 text. If the CLI's HTTP client sends its own
|
|
175
|
+
// Accept-Encoding and the upstream honors it with a compressed (gzip)
|
|
176
|
+
// response, that read silently produces garbage — JSON.parse fails,
|
|
177
|
+
// usage extraction returns undefined, and accounting stays at 0 with no
|
|
178
|
+
// error surfaced anywhere. Stripping it here means the upstream always
|
|
179
|
+
// sends plain text, which this proxy can actually parse.
|
|
180
|
+
const headers = { ...clientReq.headers, host: this.upstream.host };
|
|
181
|
+
delete headers['accept-encoding'];
|
|
182
|
+
const upstreamReq = (isHttps ? httpsRequest : httpRequest)({
|
|
183
|
+
protocol: this.upstream.protocol,
|
|
184
|
+
hostname: this.upstream.hostname,
|
|
185
|
+
port: this.upstream.port || (isHttps ? 443 : 80),
|
|
186
|
+
path: upstreamPath,
|
|
187
|
+
method: clientReq.method,
|
|
188
|
+
headers,
|
|
189
|
+
}, (upstreamRes) => {
|
|
190
|
+
clientRes.writeHead(upstreamRes.statusCode ?? 502, upstreamRes.headers);
|
|
191
|
+
const chunks = [];
|
|
192
|
+
upstreamRes.on('data', (chunk) => {
|
|
193
|
+
chunks.push(chunk);
|
|
194
|
+
clientRes.write(chunk);
|
|
195
|
+
});
|
|
196
|
+
upstreamRes.on('end', () => {
|
|
197
|
+
clientRes.end();
|
|
198
|
+
try {
|
|
199
|
+
const body = Buffer.concat(chunks).toString('utf8');
|
|
200
|
+
const usage = parseUsageFromResponseBody(body, this.opts.apiStyle);
|
|
201
|
+
if (usage) {
|
|
202
|
+
this.totalsAcc.inputTokens += usage.inputTokens;
|
|
203
|
+
this.totalsAcc.outputTokens += usage.outputTokens;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// usage extraction is a side-channel — never let it break the proxied response
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
upstreamRes.on('error', () => { try {
|
|
211
|
+
clientRes.end();
|
|
212
|
+
}
|
|
213
|
+
catch { /* already closed */ } });
|
|
214
|
+
});
|
|
215
|
+
upstreamReq.on('error', () => {
|
|
216
|
+
try {
|
|
217
|
+
if (!clientRes.headersSent)
|
|
218
|
+
clientRes.writeHead(502);
|
|
219
|
+
clientRes.end();
|
|
220
|
+
}
|
|
221
|
+
catch { /* client already gone */ }
|
|
222
|
+
});
|
|
223
|
+
clientReq.pipe(upstreamReq);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=usage-proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage-proxy.js","sourceRoot":"","sources":["../../../src/orgrt/usage-proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -2098,6 +2098,9 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
|
|
|
2098
2098
|
<button class="odt-btn secondary" data-tab="costs" onclick="v2SwitchOrgTab('costs')">Costs</button>
|
|
2099
2099
|
<button class="odt-btn secondary" data-tab="config" onclick="v2SwitchOrgTab('config')">Config</button>
|
|
2100
2100
|
<button class="odt-btn secondary" data-tab="files" onclick="v2SwitchOrgTab('files')">Files</button>
|
|
2101
|
+
<button class="odt-btn secondary" data-tab="approvals" onclick="v2SwitchOrgTab('approvals')">Approvals</button>
|
|
2102
|
+
<button class="odt-btn secondary" data-tab="budgets" onclick="v2SwitchOrgTab('budgets')">Budgets</button>
|
|
2103
|
+
<button class="odt-btn secondary" data-tab="decisions" onclick="v2SwitchOrgTab('decisions')">Decisions</button>
|
|
2101
2104
|
</div>
|
|
2102
2105
|
<div id="org-detail-body">
|
|
2103
2106
|
<div class="odt-pane active" id="odt-chart"></div>
|
|
@@ -2108,6 +2111,9 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
|
|
|
2108
2111
|
<div class="odt-pane" id="odt-costs"></div>
|
|
2109
2112
|
<div class="odt-pane" id="odt-config" style="overflow-y:auto"></div>
|
|
2110
2113
|
<div class="odt-pane" id="odt-files" style="overflow-y:auto"></div>
|
|
2114
|
+
<div class="odt-pane" id="odt-approvals"></div>
|
|
2115
|
+
<div class="odt-pane" id="odt-budgets"></div>
|
|
2116
|
+
<div class="odt-pane" id="odt-decisions"></div>
|
|
2111
2117
|
</div>
|
|
2112
2118
|
</div>
|
|
2113
2119
|
<div id="org-copy-dialog" style="display:none;position:absolute;inset:0;background:rgba(0,0,0,0.72);z-index:90;align-items:center;justify-content:center">
|
|
@@ -5863,6 +5869,7 @@ function v2RenderOrgTab(tab) {
|
|
|
5863
5869
|
else if (tab === 'routines') v2RenderOrgRoutines();
|
|
5864
5870
|
else if (tab === 'myissues') v2RenderOrgMyIssues();
|
|
5865
5871
|
else if (tab === 'budgets') v2RenderOrgBudgets();
|
|
5872
|
+
else if (tab === 'decisions') v2RenderOrgDecisions();
|
|
5866
5873
|
else if (tab === 'plugins') v2RenderOrgPlugins();
|
|
5867
5874
|
else if (tab === 'charts') v2RenderOrgCharts();
|
|
5868
5875
|
else if (tab === 'projects') v2RenderOrgProjects();
|
|
@@ -7171,6 +7178,62 @@ async function orgApprovalAction(id, action) {
|
|
|
7171
7178
|
} catch (e) { showToast('Error', e.message, 'err'); }
|
|
7172
7179
|
}
|
|
7173
7180
|
|
|
7181
|
+
// ── DECISIONS ──────────────────────────────────────────────
|
|
7182
|
+
let _v2DecisionsCache = [];
|
|
7183
|
+
let _v2DecisionsStatusFilter = 'all';
|
|
7184
|
+
let _v2DecisionsRoleFilter = 'all';
|
|
7185
|
+
|
|
7186
|
+
async function v2RenderOrgDecisions() {
|
|
7187
|
+
const el = document.getElementById('odt-decisions');
|
|
7188
|
+
if (!el || !_v2SelOrg) return;
|
|
7189
|
+
const _rendOrg = _v2SelOrg;
|
|
7190
|
+
el.innerHTML = '<div class="loading-txt">Loading…</div>';
|
|
7191
|
+
try {
|
|
7192
|
+
const _enc = encodeURIComponent(_rendOrg);
|
|
7193
|
+
const data = await fetch(`/api/org/${_enc}/gates${DIR ? '?dir=' + encodeURIComponent(DIR) : ''}`).then(r => r.ok ? r.json() : { gates: [] }).catch(() => ({ gates: [] }));
|
|
7194
|
+
if (_v2SelOrg !== _rendOrg) return;
|
|
7195
|
+
_v2DecisionsCache = Array.isArray(data) ? data : (data.gates || []);
|
|
7196
|
+
_v2DecisionsStatusFilter = 'all';
|
|
7197
|
+
_v2DecisionsRoleFilter = 'all';
|
|
7198
|
+
v2RenderDecisionsTable();
|
|
7199
|
+
} catch (e) { el.innerHTML = '<div class="empty">Failed: ' + esc(e.message) + '</div>'; }
|
|
7200
|
+
}
|
|
7201
|
+
|
|
7202
|
+
function v2RenderDecisionsTable() {
|
|
7203
|
+
const el = document.getElementById('odt-decisions');
|
|
7204
|
+
if (!el) return;
|
|
7205
|
+
const gates = _v2DecisionsCache;
|
|
7206
|
+
const roles = [...new Set(gates.map(g => g.roleId || '—'))].sort();
|
|
7207
|
+
const filtered = gates.filter(g =>
|
|
7208
|
+
(_v2DecisionsStatusFilter === 'all' || (g.status || 'pending') === _v2DecisionsStatusFilter) &&
|
|
7209
|
+
(_v2DecisionsRoleFilter === 'all' || (g.roleId || '—') === _v2DecisionsRoleFilter)
|
|
7210
|
+
);
|
|
7211
|
+
const filterBar = `<div style="display:flex;gap:10px;margin-bottom:10px">
|
|
7212
|
+
<select class="filter-input" style="width:auto" onchange="_v2DecisionsStatusFilter=this.value;v2RenderDecisionsTable()">
|
|
7213
|
+
${['all', 'pending', 'approved', 'rejected'].map(s => `<option value="${s}" ${_v2DecisionsStatusFilter===s?'selected':''}>${s === 'all' ? 'All statuses' : s}</option>`).join('')}
|
|
7214
|
+
</select>
|
|
7215
|
+
<select class="filter-input" style="width:auto" onchange="_v2DecisionsRoleFilter=this.value;v2RenderDecisionsTable()">
|
|
7216
|
+
<option value="all" ${_v2DecisionsRoleFilter==='all'?'selected':''}>All roles</option>
|
|
7217
|
+
${roles.map(r => `<option value="${esc(r)}" ${_v2DecisionsRoleFilter===r?'selected':''}>${esc(r)}</option>`).join('')}
|
|
7218
|
+
</select>
|
|
7219
|
+
</div>`;
|
|
7220
|
+
if (!filtered.length) { el.innerHTML = filterBar + '<div class="empty">No decision gates match</div>'; return; }
|
|
7221
|
+
el.innerHTML = filterBar + `<table style="width:100%;border-collapse:collapse;font-size:12px">
|
|
7222
|
+
<thead><tr style="color:var(--text-xs);text-align:left">
|
|
7223
|
+
<th style="padding:6px 8px">Role</th><th>Gate</th><th>Status</th><th>Resolution</th><th>Date</th>
|
|
7224
|
+
</tr></thead><tbody>` +
|
|
7225
|
+
filtered.slice(0, 100).map(g => {
|
|
7226
|
+
const cls = g.status === 'approved' ? 'on' : g.status === 'rejected' ? 'warn' : '';
|
|
7227
|
+
return `<tr style="border-top:1px solid var(--border)">
|
|
7228
|
+
<td style="padding:6px 8px;color:var(--text-hi)">${esc(g.roleId || '—')}</td>
|
|
7229
|
+
<td style="padding:6px 8px;color:var(--text-lo);max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap" title="${esc(g.description || '')}">${esc(g.name || '—')}</td>
|
|
7230
|
+
<td style="padding:6px 8px"><span class="ss-pill ${cls}">${esc(g.status || 'pending')}</span></td>
|
|
7231
|
+
<td style="padding:6px 8px;color:var(--text-lo);max-width:180px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${esc(g.resolution || '—')}</td>
|
|
7232
|
+
<td style="padding:6px 8px;color:var(--text-xs);font-size:11px;font-family:var(--mono)">${relTime(g.resolvedAt || g.createdAt)}</td>
|
|
7233
|
+
</tr>`;
|
|
7234
|
+
}).join('') + '</tbody></table>';
|
|
7235
|
+
}
|
|
7236
|
+
|
|
7174
7237
|
// ── SECRETS ────────────────────────────────────────────────
|
|
7175
7238
|
async function v2RenderOrgSecrets() {
|
|
7176
7239
|
const el = document.getElementById('odt-secrets');
|
package/dist/src/ui/orgs.html
CHANGED
|
@@ -1406,7 +1406,14 @@ function renderTab(tab) {
|
|
|
1406
1406
|
function renderChart() {
|
|
1407
1407
|
const d = orgDetailData;
|
|
1408
1408
|
const roles = Array.isArray(d.roles) ? d.roles : [];
|
|
1409
|
-
|
|
1409
|
+
// Structural report lines come straight from each role's reports_to (the
|
|
1410
|
+
// authoritative chain also shown in the Roles tab) — declared communication
|
|
1411
|
+
// edges (command/feedback/handoff busses) don't reflect who actually reports
|
|
1412
|
+
// to whom, e.g. a hierarchical topology's queen commanding every worker directly.
|
|
1413
|
+
const reportEdges = roles
|
|
1414
|
+
.filter(r => r.reports_to && r.reports_to !== r.id)
|
|
1415
|
+
.map(r => ({ from: r.id, to: r.reports_to, type: 'report' }));
|
|
1416
|
+
const comms = reportEdges.concat(Array.isArray(d.communication) ? d.communication : []);
|
|
1410
1417
|
const running = !!(allOrgs.find(o => o.name === selectedOrg) || {}).running;
|
|
1411
1418
|
|
|
1412
1419
|
// Meta bar
|
|
@@ -878,6 +878,32 @@ if (req.method === 'GET' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/ap
|
|
|
878
878
|
return true;
|
|
879
879
|
}
|
|
880
880
|
|
|
881
|
+
// GET /api/org/:name/gates — decision gate log (read-only explorer; resolving stays
|
|
882
|
+
// CLI-only via `org gate-approve`/`gate-reject`, which needs the daemon's
|
|
883
|
+
// x-monomind-cred auth header for live delivery — out of scope for a read-only view)
|
|
884
|
+
if (req.method === 'GET' && url.match(/^\/api\/org\/[a-z0-9][a-z0-9_-]{0,63}\/gates(\?.*)?$/i)) {
|
|
885
|
+
try {
|
|
886
|
+
const orgName = decodeURIComponent(url.split('/')[3].split('?')[0]);
|
|
887
|
+
if (orgName.length > 64 || !/^[a-z0-9][a-z0-9_-]*$/i.test(orgName)) { res.writeHead(400); res.end('Invalid org name'); return true; }
|
|
888
|
+
const _gatesQs = new URL(req.url, 'http://localhost').searchParams;
|
|
889
|
+
const base = path.join(path.resolve(_gatesQs.get('dir') || ctx.projectDir || process.cwd()), '.monomind', 'orgs');
|
|
890
|
+
const readJsonSafe = (f) => { try { return JSON.parse(fs.readFileSync(f, 'utf8')); } catch(_) { return null; } };
|
|
891
|
+
const data = readJsonSafe(path.join(base, orgName, 'gates.json')) || { gates: [] };
|
|
892
|
+
const gates = (data.gates || [])
|
|
893
|
+
.sort((a, b) => (b.createdAt || 0) - (a.createdAt || 0))
|
|
894
|
+
.map(g => ({
|
|
895
|
+
id: g.id, name: g.name, description: g.description, roleId: g.roleId,
|
|
896
|
+
status: g.status || 'pending', createdAt: g.createdAt || null,
|
|
897
|
+
resolvedBy: g.resolvedBy || null, resolvedAt: g.resolvedAt || null,
|
|
898
|
+
resolution: g.resolution || null,
|
|
899
|
+
}));
|
|
900
|
+
const pending = gates.filter(g => g.status === 'pending').length;
|
|
901
|
+
res.writeHead(200, { 'Content-Type': 'application/json', ...(corsOrigin ? { 'Access-Control-Allow-Origin': corsOrigin } : {}) });
|
|
902
|
+
res.end(JSON.stringify({ gates, pending }));
|
|
903
|
+
} catch(_) { res.writeHead(500); res.end('{"gates":[],"pending":0}'); }
|
|
904
|
+
return true;
|
|
905
|
+
}
|
|
906
|
+
|
|
881
907
|
// GET /api/questions?dir=<ctx.projectDir> — list ask_human questions (pending and
|
|
882
908
|
// answered) for every org in one project. Mirrors the existing -approvals.json
|
|
883
909
|
// sidecar convention, but reads this feature's .monomind/orgs/<org>/questions.json
|