@worca/app 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +403 -0
- package/agents/clarify.meta.json +19 -0
- package/agents/decomposer.meta.json +21 -0
- package/agents/implementer.meta.json +20 -0
- package/agents/manualTestsChecklist.meta.json +18 -0
- package/agents/manualWebUiTesting.meta.json +18 -0
- package/agents/planReviewer.meta.json +19 -0
- package/agents/planner.meta.json +20 -0
- package/agents/refiner.meta.json +19 -0
- package/agents/reviewer.meta.json +19 -0
- package/agents/worca-cc-clarify.md +67 -0
- package/agents/worca-cc-code-reviewer.md +66 -0
- package/agents/worca-cc-decomposer.md +84 -0
- package/agents/worca-cc-implementer.md +69 -0
- package/agents/worca-cc-manual-tests-checklist.md +63 -0
- package/agents/worca-cc-manual-web-ui-testing.md +64 -0
- package/agents/worca-cc-plan-refiner.md +69 -0
- package/agents/worca-cc-plan-reviewer.md +70 -0
- package/agents/worca-cc-planner.md +70 -0
- package/agents/worca-cc-workspace-reviewer.md +56 -0
- package/agents/worca-cc-workspace-scanner.md +55 -0
- package/agents/workspaceReviewer.meta.json +20 -0
- package/agents/workspaceScanner.meta.json +18 -0
- package/package.json +61 -0
- package/scripts/install.mjs +209 -0
- package/skills/worca/SKILL.md +66 -0
- package/src/cli/worca-cc.mjs +1520 -0
- package/src/core/agent-gen.mjs +206 -0
- package/src/core/agent-registry.mjs +417 -0
- package/src/core/agent-store.mjs +143 -0
- package/src/core/artifacts.mjs +2019 -0
- package/src/core/channels.mjs +302 -0
- package/src/core/chat/allowlist.mjs +27 -0
- package/src/core/chat/channel-host.mjs +562 -0
- package/src/core/chat/channel-protocol.mjs +117 -0
- package/src/core/chat/channel-worker-child.mjs +211 -0
- package/src/core/chat/chat-context.mjs +66 -0
- package/src/core/chat/command-router.mjs +343 -0
- package/src/core/chat/notifier.mjs +120 -0
- package/src/core/chat/parser.mjs +30 -0
- package/src/core/chat/rate-limiter.mjs +133 -0
- package/src/core/chat/redact.mjs +27 -0
- package/src/core/chat/renderers.mjs +136 -0
- package/src/core/claude-runner.mjs +1356 -0
- package/src/core/config.mjs +882 -0
- package/src/core/cost-budget.mjs +103 -0
- package/src/core/db.mjs +864 -0
- package/src/core/fanout.mjs +48 -0
- package/src/core/folder-dialog.mjs +138 -0
- package/src/core/fs-browse.mjs +49 -0
- package/src/core/git-info.mjs +200 -0
- package/src/core/guardrail-store.mjs +204 -0
- package/src/core/guardrails.mjs +302 -0
- package/src/core/marketplaces.mjs +267 -0
- package/src/core/migrate-fs-to-db.mjs +612 -0
- package/src/core/model-env.mjs +74 -0
- package/src/core/orchestrator.mjs +4279 -0
- package/src/core/overview-agent.mjs +124 -0
- package/src/core/phases.mjs +1279 -0
- package/src/core/pipeline-delete.mjs +428 -0
- package/src/core/plugin-api.mjs +13 -0
- package/src/core/plugin-config.mjs +100 -0
- package/src/core/plugin-inventory.mjs +50 -0
- package/src/core/plugin-manifest.mjs +447 -0
- package/src/core/plugin-models.mjs +130 -0
- package/src/core/plugin-repo.mjs +303 -0
- package/src/core/plugin-shim-child.mjs +76 -0
- package/src/core/plugin-shim.mjs +197 -0
- package/src/core/plugin-store.mjs +485 -0
- package/src/core/plugin-workflows.mjs +179 -0
- package/src/core/plugins-lock.mjs +49 -0
- package/src/core/preflight-node.mjs +122 -0
- package/src/core/preflight.mjs +341 -0
- package/src/core/projects.mjs +157 -0
- package/src/core/protocol.mjs +257 -0
- package/src/core/recoverable-error.mjs +51 -0
- package/src/core/results.mjs +188 -0
- package/src/core/run-context.mjs +1375 -0
- package/src/core/run-log.mjs +64 -0
- package/src/core/run-manifest.mjs +317 -0
- package/src/core/runners.mjs +167 -0
- package/src/core/settings.mjs +682 -0
- package/src/core/skills.mjs +210 -0
- package/src/core/sources.mjs +232 -0
- package/src/core/stats.mjs +182 -0
- package/src/core/store.mjs +67 -0
- package/src/core/title.mjs +64 -0
- package/src/core/workflow-validator.mjs +185 -0
- package/src/core/workflows.mjs +568 -0
- package/src/core/workspace-scan.mjs +420 -0
- package/src/core/workspaces.mjs +353 -0
- package/src/core/worktree.mjs +708 -0
- package/src/feature.mjs +9 -0
- package/ui/public/app.js +10647 -0
- package/ui/public/assets/worca-favicon.png +0 -0
- package/ui/public/assets/worca-logo.png +0 -0
- package/ui/public/chat-settings-view.mjs +89 -0
- package/ui/public/composer-core.mjs +211 -0
- package/ui/public/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/ui/public/fonts/poppins-latin-400-normal.woff2 +0 -0
- package/ui/public/fonts/poppins-latin-500-normal.woff2 +0 -0
- package/ui/public/fonts/poppins-latin-600-normal.woff2 +0 -0
- package/ui/public/fonts/poppins-latin-700-normal.woff2 +0 -0
- package/ui/public/guardrails-view.mjs +244 -0
- package/ui/public/index.html +1145 -0
- package/ui/public/log-filter.mjs +81 -0
- package/ui/public/log-line.mjs +86 -0
- package/ui/public/models-view.mjs +433 -0
- package/ui/public/plugins-view.mjs +430 -0
- package/ui/public/results-view.mjs +121 -0
- package/ui/public/source-pane.mjs +156 -0
- package/ui/public/stats-view.mjs +523 -0
- package/ui/public/style.css +1557 -0
- package/ui/server.mjs +3573 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// src/core/cost-budget.mjs
|
|
2
|
+
// Budget accounting for cost limits (spec docs/superpowers/specs/2026-08-07-
|
|
3
|
+
// cost-limits-stats-design.md §6.1-6.2). Window boundaries are pure functions
|
|
4
|
+
// of `now` in the LOCAL calendar — no stored anchor, no scheduler; reset means
|
|
5
|
+
// old ledger rows fall out of the SUM. Ledger rows are appended per cost event
|
|
6
|
+
// (raw floats); roundUsd applies to aggregated outputs only.
|
|
7
|
+
|
|
8
|
+
import { prepare } from './db.mjs';
|
|
9
|
+
import {
|
|
10
|
+
pipelineCostLimitUsd, totalCostLimitUsd, costLimitResetPeriod,
|
|
11
|
+
COST_RESET_PERIODS, DEFAULT_COST_RESET_PERIOD,
|
|
12
|
+
} from './settings.mjs';
|
|
13
|
+
|
|
14
|
+
export { COST_RESET_PERIODS, DEFAULT_COST_RESET_PERIOD };
|
|
15
|
+
|
|
16
|
+
/** Round a USD amount to 4 decimal places — the same grain as the orchestrator's
|
|
17
|
+
* own roundUsd, but not the same function: this one adds an EPSILON nudge (a value
|
|
18
|
+
* sitting one float-ulp below a rounding boundary goes up) and takes a number,
|
|
19
|
+
* where the orchestrator's coerces with `Number(n) || 0`. */
|
|
20
|
+
export function roundUsd(n) {
|
|
21
|
+
return Math.round((n + Number.EPSILON) * 1e4) / 1e4;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Start of the current budget window (local calendar). Calendar-component
|
|
25
|
+
* Date constructors keep boundaries at local midnight through DST. */
|
|
26
|
+
export function costWindowStart(now = new Date(), period = DEFAULT_COST_RESET_PERIOD) {
|
|
27
|
+
if (period === 'weekly') {
|
|
28
|
+
const sinceMonday = (now.getDay() + 6) % 7; // Mon=0 … Sun=6
|
|
29
|
+
return new Date(now.getFullYear(), now.getMonth(), now.getDate() - sinceMonday);
|
|
30
|
+
}
|
|
31
|
+
return new Date(now.getFullYear(), now.getMonth(), 1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Next reset boundary (exclusive end of the current window). */
|
|
35
|
+
export function costWindowEnd(now = new Date(), period = DEFAULT_COST_RESET_PERIOD) {
|
|
36
|
+
const s = costWindowStart(now, period);
|
|
37
|
+
return period === 'weekly'
|
|
38
|
+
? new Date(s.getFullYear(), s.getMonth(), s.getDate() + 7)
|
|
39
|
+
: new Date(s.getFullYear(), s.getMonth() + 1, 1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Append one cost event. No-ops on non-positive amounts (mock runs emit $0)
|
|
43
|
+
* and on a missing pipeline id. */
|
|
44
|
+
export function recordCostDelta({ pipelineId, stepKey = null, amountUsd, tsMs = Date.now() }) {
|
|
45
|
+
if (!pipelineId || !Number.isFinite(amountUsd) || amountUsd <= 0) return;
|
|
46
|
+
prepare('INSERT INTO cost_ledger (pipeline_id, step_key, amount_usd, ts) VALUES (?, ?, ?, ?)')
|
|
47
|
+
.run(pipelineId, stepKey, amountUsd, tsMs);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Windowed spend: roundUsd(SUM(amount_usd)) where ts >= windowStartMs. */
|
|
51
|
+
export function windowedSpendUsd(windowStartMs) {
|
|
52
|
+
const row = prepare('SELECT SUM(amount_usd) AS s FROM cost_ledger WHERE ts >= ?')
|
|
53
|
+
.get(windowStartMs);
|
|
54
|
+
return roundUsd(row?.s || 0);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** All-time spend + active time over ALL pipelines (archived included),
|
|
58
|
+
* falling back to per-step sums when the row total is 0. */
|
|
59
|
+
export function allTimeTotals() {
|
|
60
|
+
const row = prepare(`
|
|
61
|
+
SELECT
|
|
62
|
+
COALESCE(SUM(CASE WHEN p.total_cost_usd > 0 THEN p.total_cost_usd ELSE COALESCE(s.sc, 0) END), 0) AS spend,
|
|
63
|
+
COALESCE(SUM(CASE WHEN p.total_active_ms > 0 THEN p.total_active_ms ELSE COALESCE(s.sa, 0) END), 0) AS active
|
|
64
|
+
FROM pipelines p
|
|
65
|
+
LEFT JOIN (SELECT pipeline_id, SUM(cost_usd) sc, SUM(active_ms) sa
|
|
66
|
+
FROM pipeline_steps GROUP BY pipeline_id) s ON s.pipeline_id = p.id
|
|
67
|
+
`).get();
|
|
68
|
+
return { spendUsd: roundUsd(row?.spend || 0), activeMs: Number(row?.active || 0) };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** True when this pipeline ignores the per-pipeline cap (persistent, F7). */
|
|
72
|
+
export function readCostCapOverride(pipelineId) {
|
|
73
|
+
const row = prepare('SELECT cost_cap_override FROM pipelines WHERE id = ?').get(pipelineId);
|
|
74
|
+
return !!row?.cost_cap_override;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Set the persistent per-pipeline "disregard the cap" flag. */
|
|
78
|
+
export function setCostCapOverride(pipelineId) {
|
|
79
|
+
prepare('UPDATE pipelines SET cost_cap_override = 1 WHERE id = ?').run(pipelineId);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** One shared truth for gates, CLI, and every UI badge (spec §6.1). */
|
|
83
|
+
export function budgetStatus(now = new Date()) {
|
|
84
|
+
const resetPeriod = costLimitResetPeriod();
|
|
85
|
+
const pipelineLimitUsd = pipelineCostLimitUsd();
|
|
86
|
+
const totalLimitUsd = totalCostLimitUsd();
|
|
87
|
+
const windowStartMs = costWindowStart(now, resetPeriod).getTime();
|
|
88
|
+
const windowEndMs = costWindowEnd(now, resetPeriod).getTime();
|
|
89
|
+
const windowSpendUsd = windowedSpendUsd(windowStartMs);
|
|
90
|
+
const blocked = totalLimitUsd != null && windowSpendUsd >= totalLimitUsd;
|
|
91
|
+
return {
|
|
92
|
+
pipelineLimitUsd,
|
|
93
|
+
totalLimitUsd,
|
|
94
|
+
resetPeriod,
|
|
95
|
+
windowStartMs,
|
|
96
|
+
windowEndMs,
|
|
97
|
+
msUntilReset: windowEndMs - now.getTime(),
|
|
98
|
+
windowSpendUsd,
|
|
99
|
+
allTimeSpendUsd: allTimeTotals().spendUsd,
|
|
100
|
+
remainingUsd: totalLimitUsd == null ? null : Math.max(0, roundUsd(totalLimitUsd - windowSpendUsd)),
|
|
101
|
+
blocked,
|
|
102
|
+
};
|
|
103
|
+
}
|