@jinn-network/client 0.1.7-canary.d4e4e183 → 0.1.7-canary.e68c8f43
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 +67 -1
- package/dist/adapters/mech/adapter.d.ts +19 -1
- package/dist/adapters/mech/adapter.js +130 -14
- package/dist/adapters/mech/adapter.js.map +1 -1
- package/dist/adapters/mech/contracts.js +11 -2
- package/dist/adapters/mech/contracts.js.map +1 -1
- package/dist/adapters/mech/safe.d.ts +1 -1
- package/dist/adapters/mech/safe.js +5 -3
- package/dist/adapters/mech/safe.js.map +1 -1
- package/dist/adapters/mech/types.d.ts +6 -1
- package/dist/adapters/mech/types.js.map +1 -1
- package/dist/agent/operator-claude.js +8 -0
- package/dist/agent/operator-claude.js.map +1 -1
- package/dist/api/activity-events-endpoint.d.ts +14 -0
- package/dist/api/activity-events-endpoint.js +59 -0
- package/dist/api/activity-events-endpoint.js.map +1 -0
- package/dist/api/bootstrap-endpoint.d.ts +1 -2
- package/dist/api/bootstrap-endpoint.js +42 -24
- package/dist/api/bootstrap-endpoint.js.map +1 -1
- package/dist/api/codex-doctor-endpoint.d.ts +22 -5
- package/dist/api/codex-doctor-endpoint.js +136 -17
- package/dist/api/codex-doctor-endpoint.js.map +1 -1
- package/dist/api/debug-report-endpoint.d.ts +27 -0
- package/dist/api/debug-report-endpoint.js +157 -0
- package/dist/api/debug-report-endpoint.js.map +1 -0
- package/dist/api/gather-status.d.ts +33 -0
- package/dist/api/gather-status.js +210 -26
- package/dist/api/gather-status.js.map +1 -1
- package/dist/api/hermes-doctor-endpoint.d.ts +15 -7
- package/dist/api/hermes-doctor-endpoint.js +56 -19
- package/dist/api/hermes-doctor-endpoint.js.map +1 -1
- package/dist/api/launcher-status.d.ts +4 -2
- package/dist/api/launcher-status.js +11 -10
- package/dist/api/launcher-status.js.map +1 -1
- package/dist/api/launcher-tasks.d.ts +1 -1
- package/dist/api/launcher-tasks.js +12 -8
- package/dist/api/launcher-tasks.js.map +1 -1
- package/dist/api/operator-artifacts-endpoint.js +73 -6
- package/dist/api/operator-artifacts-endpoint.js.map +1 -1
- package/dist/api/server.d.ts +17 -0
- package/dist/api/server.js +40 -1
- package/dist/api/server.js.map +1 -1
- package/dist/api/setup-endpoints.d.ts +0 -9
- package/dist/api/setup-endpoints.js +11 -153
- package/dist/api/setup-endpoints.js.map +1 -1
- package/dist/api/solvernets-endpoints.js +30 -63
- package/dist/api/solvernets-endpoints.js.map +1 -1
- package/dist/api/status-build.d.ts +115 -2
- package/dist/api/status-build.js +47 -11
- package/dist/api/status-build.js.map +1 -1
- package/dist/api/status-harness-rollup.d.ts +35 -0
- package/dist/api/status-harness-rollup.js +45 -0
- package/dist/api/status-harness-rollup.js.map +1 -0
- package/dist/build-info.json +4 -4
- package/dist/build-meta.json +1 -1
- package/dist/captures/live-publisher.js +24 -4
- package/dist/captures/live-publisher.js.map +1 -1
- package/dist/captures/publish.d.ts +1 -1
- package/dist/chain-read-errors.d.ts +12 -0
- package/dist/chain-read-errors.js +26 -1
- package/dist/chain-read-errors.js.map +1 -1
- package/dist/cli/commands/codedigest-revert-check.d.ts +33 -0
- package/dist/cli/commands/codedigest-revert-check.js +249 -0
- package/dist/cli/commands/codedigest-revert-check.js.map +1 -0
- package/dist/cli/commands/solver-nets.d.ts +1 -0
- package/dist/cli/commands/solver-nets.js +170 -22
- package/dist/cli/commands/solver-nets.js.map +1 -1
- package/dist/cli/commands/solver-plugins-block.d.ts +33 -0
- package/dist/cli/commands/solver-plugins-block.js +118 -0
- package/dist/cli/commands/solver-plugins-block.js.map +1 -0
- package/dist/cli/commands/solver-plugins-feedback.d.ts +72 -0
- package/dist/cli/commands/solver-plugins-feedback.js +262 -0
- package/dist/cli/commands/solver-plugins-feedback.js.map +1 -0
- package/dist/cli/commands/solver-plugins-read.d.ts +54 -0
- package/dist/cli/commands/solver-plugins-read.js +259 -0
- package/dist/cli/commands/solver-plugins-read.js.map +1 -0
- package/dist/cli/commands/solver-plugins.d.ts +35 -0
- package/dist/cli/commands/solver-plugins.js +399 -2
- package/dist/cli/commands/solver-plugins.js.map +1 -1
- package/dist/cli/commands/tasks.js +15 -2
- package/dist/cli/commands/tasks.js.map +1 -1
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/task-native-readiness.d.ts +7 -0
- package/dist/cli/task-native-readiness.js +7 -5
- package/dist/cli/task-native-readiness.js.map +1 -1
- package/dist/config.d.ts +183 -232
- package/dist/config.js +232 -107
- package/dist/config.js.map +1 -1
- package/dist/daemon/ai-units-gate.d.ts +54 -0
- package/dist/daemon/ai-units-gate.js +82 -0
- package/dist/daemon/ai-units-gate.js.map +1 -0
- package/dist/daemon/creator.js +13 -0
- package/dist/daemon/creator.js.map +1 -1
- package/dist/daemon/daemon.d.ts +10 -0
- package/dist/daemon/daemon.js +203 -30
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/gate-logger.d.ts +9 -0
- package/dist/daemon/gate-logger.js +2 -0
- package/dist/daemon/gate-logger.js.map +1 -0
- package/dist/daemon/readiness-gate.d.ts +1 -4
- package/dist/daemon/readiness-gate.js.map +1 -1
- package/dist/daemon/spend-cap-gate.d.ts +40 -0
- package/dist/daemon/spend-cap-gate.js +46 -0
- package/dist/daemon/spend-cap-gate.js.map +1 -0
- package/dist/dashboard/assets/index-CvQbxjxy.js +351 -0
- package/dist/dashboard/assets/index-CzKxvMcU.css +32 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/discovery/http.js +328 -1
- package/dist/discovery/http.js.map +1 -1
- package/dist/discovery/onchain.js +42 -4
- package/dist/discovery/onchain.js.map +1 -1
- package/dist/discovery/types.d.ts +129 -0
- package/dist/discovery/types.js.map +1 -1
- package/dist/discovery/with-fallback.js +27 -0
- package/dist/discovery/with-fallback.js.map +1 -1
- package/dist/earning/bootstrap.d.ts +8 -3
- package/dist/earning/bootstrap.js +36 -13
- package/dist/earning/bootstrap.js.map +1 -1
- package/dist/earning/safe-adapter.js +23 -11
- package/dist/earning/safe-adapter.js.map +1 -1
- package/dist/earning/types.d.ts +6 -6
- package/dist/earning/viem-clients.d.ts +11 -4
- package/dist/earning/viem-clients.js +14 -5
- package/dist/earning/viem-clients.js.map +1 -1
- package/dist/erc8004/identity.d.ts +19 -3
- package/dist/erc8004/identity.js +21 -6
- package/dist/erc8004/identity.js.map +1 -1
- package/dist/erc8004/index.d.ts +1 -1
- package/dist/erc8004/index.js.map +1 -1
- package/dist/events/types.d.ts +2 -2
- package/dist/harnesses/cost-estimates.d.ts +10 -31
- package/dist/harnesses/cost-estimates.js +11 -43
- package/dist/harnesses/cost-estimates.js.map +1 -1
- package/dist/harnesses/engine/engine.d.ts +9 -3
- package/dist/harnesses/engine/engine.js +51 -6
- package/dist/harnesses/engine/engine.js.map +1 -1
- package/dist/harnesses/impls/hermes-agent/bootstrap.js +4 -2
- package/dist/harnesses/impls/hermes-agent/bootstrap.js.map +1 -1
- package/dist/harnesses/impls/hermes-agent/config-builder.d.ts +1 -1
- package/dist/harnesses/impls/hermes-agent/config-builder.js +4 -2
- package/dist/harnesses/impls/hermes-agent/config-builder.js.map +1 -1
- package/dist/harnesses/impls/hermes-agent/harness.js +2 -2
- package/dist/harnesses/impls/hermes-agent/harness.js.map +1 -1
- package/dist/harnesses/impls/hermes-agent/prompt.d.ts +6 -6
- package/dist/harnesses/impls/hermes-agent/prompt.js +6 -6
- package/dist/harnesses/impls/learner/adapters/claude-code.d.ts +17 -0
- package/dist/harnesses/impls/learner/adapters/claude-code.js +113 -14
- package/dist/harnesses/impls/learner/adapters/claude-code.js.map +1 -1
- package/dist/harnesses/impls/learner/adapters/codex-code.d.ts +9 -0
- package/dist/harnesses/impls/learner/adapters/codex-code.js +30 -8
- package/dist/harnesses/impls/learner/adapters/codex-code.js.map +1 -1
- package/dist/harnesses/impls/learner/harness.d.ts +9 -0
- package/dist/harnesses/impls/learner/harness.js +12 -3
- package/dist/harnesses/impls/learner/harness.js.map +1 -1
- package/dist/harnesses/impls/learner/harvest.d.ts +1 -1
- package/dist/harnesses/impls/learner/harvest.js +23 -5
- package/dist/harnesses/impls/learner/harvest.js.map +1 -1
- package/dist/harnesses/impls/learner/restoration-patch.d.ts +2 -2
- package/dist/harnesses/impls/learner/restoration-patch.js +25 -6
- package/dist/harnesses/impls/learner/restoration-patch.js.map +1 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js +21 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/eval-runner.js.map +1 -1
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.d.ts +74 -5
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js +103 -32
- package/dist/harnesses/impls/swe-rebench-v2-evaluator/hf-fetcher.js.map +1 -1
- package/dist/harnesses/readiness-registry.d.ts +7 -0
- package/dist/harnesses/readiness-registry.js +9 -0
- package/dist/harnesses/readiness-registry.js.map +1 -1
- package/dist/learner/revert-decision.d.ts +59 -0
- package/dist/learner/revert-decision.js +53 -0
- package/dist/learner/revert-decision.js.map +1 -0
- package/dist/learner/revert-stats.d.ts +24 -0
- package/dist/learner/revert-stats.js +44 -0
- package/dist/learner/revert-stats.js.map +1 -0
- package/dist/main.js +177 -104
- package/dist/main.js.map +1 -1
- package/dist/mcp/get-codedigest-reward.d.ts +13 -0
- package/dist/mcp/get-codedigest-reward.js +23 -0
- package/dist/mcp/get-codedigest-reward.js.map +1 -0
- package/dist/mcp/server.js +23 -0
- package/dist/mcp/server.js.map +1 -1
- package/dist/observability/debug-report-assemble.d.ts +43 -0
- package/dist/observability/debug-report-assemble.js +80 -0
- package/dist/observability/debug-report-assemble.js.map +1 -0
- package/dist/observability/emit-event.d.ts +9 -2
- package/dist/observability/emit-event.js +36 -2
- package/dist/observability/emit-event.js.map +1 -1
- package/dist/observability/file-logger.d.ts +69 -0
- package/dist/observability/file-logger.js +177 -0
- package/dist/observability/file-logger.js.map +1 -0
- package/dist/observability/redact-secrets.d.ts +65 -0
- package/dist/observability/redact-secrets.js +300 -0
- package/dist/observability/redact-secrets.js.map +1 -0
- package/dist/observability/tar.d.ts +30 -0
- package/dist/observability/tar.js +102 -0
- package/dist/observability/tar.js.map +1 -0
- package/dist/plugins/learner/skills/learn/consolidator-prompt.md +18 -1
- package/dist/plugins/learner/skills/learn/promoter-prompt.md +72 -1
- package/dist/preflight/pidfile-liveness.d.ts +44 -0
- package/dist/preflight/pidfile-liveness.js +103 -0
- package/dist/preflight/pidfile-liveness.js.map +1 -0
- package/dist/preflight/rpc-network.d.ts +40 -0
- package/dist/preflight/rpc-network.js +67 -1
- package/dist/preflight/rpc-network.js.map +1 -1
- package/dist/rpc/transport.d.ts +109 -0
- package/dist/rpc/transport.js +220 -0
- package/dist/rpc/transport.js.map +1 -0
- package/dist/scripts/donation-consumption-acceptance.js +7 -28
- package/dist/scripts/donation-consumption-acceptance.js.map +1 -1
- package/dist/scripts/swe-rebench-v2-pytest-missing.json +16 -0
- package/dist/solver-nets/prediction-operator-ux.d.ts +1 -2
- package/dist/solver-nets/prediction-operator-ux.js +56 -53
- package/dist/solver-nets/prediction-operator-ux.js.map +1 -1
- package/dist/solver-nets/registry.d.ts +19 -1
- package/dist/solver-nets/registry.js +37 -24
- package/dist/solver-nets/registry.js.map +1 -1
- package/dist/solver-types/_swe-rebench-v2-pool.d.ts +9 -2
- package/dist/solver-types/_swe-rebench-v2-pool.js +15 -20
- package/dist/solver-types/_swe-rebench-v2-pool.js.map +1 -1
- package/dist/solver-types/_swe-rebench-v2-state.d.ts +15 -0
- package/dist/solver-types/_swe-rebench-v2-state.js +19 -0
- package/dist/solver-types/_swe-rebench-v2-state.js.map +1 -1
- package/dist/solver-types/_swe-rebench-v2-validated-pool.d.ts +80 -2
- package/dist/solver-types/_swe-rebench-v2-validated-pool.js +242 -21
- package/dist/solver-types/_swe-rebench-v2-validated-pool.js.map +1 -1
- package/dist/solver-types/swe-rebench-v2-auto.d.ts +20 -11
- package/dist/solver-types/swe-rebench-v2-auto.js +64 -19
- package/dist/solver-types/swe-rebench-v2-auto.js.map +1 -1
- package/dist/solver-types/swe-rebench-v2.d.ts +8 -2
- package/dist/solver-types/swe-rebench-v2.js +127 -11
- package/dist/solver-types/swe-rebench-v2.js.map +1 -1
- package/dist/solvernets/launched-record-dispatcher.d.ts +4 -0
- package/dist/solvernets/launched-record-dispatcher.js +10 -4
- package/dist/solvernets/launched-record-dispatcher.js.map +1 -1
- package/dist/solvernets/registry-client-erc8004.js +11 -0
- package/dist/solvernets/registry-client-erc8004.js.map +1 -1
- package/dist/solvernets/store.d.ts +2 -2
- package/dist/spend/ai-units-config.d.ts +37 -0
- package/dist/spend/ai-units-config.js +26 -0
- package/dist/spend/ai-units-config.js.map +1 -0
- package/dist/spend/ai-units.d.ts +86 -0
- package/dist/spend/ai-units.js +163 -0
- package/dist/spend/ai-units.js.map +1 -0
- package/dist/spend/cost-surface-status.d.ts +10 -0
- package/dist/spend/cost-surface-status.js +22 -0
- package/dist/spend/cost-surface-status.js.map +1 -0
- package/dist/spend/credential.d.ts +8 -0
- package/dist/spend/credential.js +30 -0
- package/dist/spend/credential.js.map +1 -0
- package/dist/spend/daemon-config.d.ts +13 -0
- package/dist/spend/daemon-config.js +24 -0
- package/dist/spend/daemon-config.js.map +1 -0
- package/dist/spend/pricing.d.ts +16 -0
- package/dist/spend/pricing.js +26 -0
- package/dist/spend/pricing.js.map +1 -0
- package/dist/spend/record.d.ts +13 -0
- package/dist/spend/record.js +36 -0
- package/dist/spend/record.js.map +1 -0
- package/dist/spend/usage.d.ts +27 -0
- package/dist/spend/usage.js +113 -0
- package/dist/spend/usage.js.map +1 -0
- package/dist/store/store.d.ts +101 -0
- package/dist/store/store.js +304 -4
- package/dist/store/store.js.map +1 -1
- package/dist/trajectory/transcript-parsers/codex-session.d.ts +12 -6
- package/dist/trajectory/transcript-parsers/codex-session.js +114 -13
- package/dist/trajectory/transcript-parsers/codex-session.js.map +1 -1
- package/dist/trajectory/transcript-parsers/types.d.ts +8 -8
- package/dist/trajectory/transcript-session-dirs.d.ts +18 -0
- package/dist/trajectory/transcript-session-dirs.js +85 -0
- package/dist/trajectory/transcript-session-dirs.js.map +1 -0
- package/dist/trajectory/transcript-watcher.d.ts +20 -1
- package/dist/trajectory/transcript-watcher.js +98 -32
- package/dist/trajectory/transcript-watcher.js.map +1 -1
- package/dist/tx-retry.d.ts +15 -0
- package/dist/tx-retry.js +37 -7
- package/dist/tx-retry.js.map +1 -1
- package/dist/types/payloads/portfolio-v0.d.ts +3 -3
- package/dist/types/payloads/prediction-apy-v0.d.ts +3 -3
- package/dist/types/payloads/prediction-v0.d.ts +12 -12
- package/package.json +10 -3
- package/plugins/learner/skills/learn/consolidator-prompt.md +18 -1
- package/plugins/learner/skills/learn/promoter-prompt.md +72 -1
- package/plugins/swe-rebench-v2-diffmin/README.md +10 -9
- package/plugins/swe-rebench-v2-diffmin/jinn.plugin.json +1 -1
- package/plugins/swe-rebench-v2-diffmin/skills/diffmin/SKILL.md +15 -10
- package/plugins/swe-rebench-v2-diffmin/skills/test-map/SKILL.md +10 -12
- package/plugins/swe-rebench-v2-runtime/.claude-plugin/plugin.json +1 -1
- package/plugins/swe-rebench-v2-runtime/.codex-plugin/plugin.json +3 -3
- package/plugins/swe-rebench-v2-runtime/README.md +6 -6
- package/plugins/swe-rebench-v2-runtime/jinn.plugin.json +2 -3
- package/plugins/swe-rebench-v2-runtime/skills/task/SKILL.md +81 -0
- package/dist/dashboard/assets/index-BUlE8F3Y.js +0 -330
- package/dist/dashboard/assets/index-blqc7eqq.css +0 -32
- package/plugins/swe-rebench-v2-runtime/skills/orient/SKILL.md +0 -29
- package/plugins/swe-rebench-v2-runtime/skills/plan/SKILL.md +0 -53
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { CLAUDE_CODE_HARNESS, CODEX_HARNESS, canonicalHarnessName } from '../harnesses/names.js';
|
|
4
|
+
import { estimateModelCost } from '../harnesses/cost-estimates.js';
|
|
5
|
+
import { priceTokens } from './pricing.js';
|
|
6
|
+
/** USD attributed to a task whose model has no known price. */
|
|
7
|
+
export const UNKNOWN_MODEL_FALLBACK_USD = 1.0;
|
|
8
|
+
/** Parse Claude Code `--output-format stream-json` output for the terminal result. */
|
|
9
|
+
export function parseClaudeCodeUsage(stdoutJsonl) {
|
|
10
|
+
let result = null;
|
|
11
|
+
for (const line of stdoutJsonl.split('\n')) {
|
|
12
|
+
const trimmed = line.trim();
|
|
13
|
+
if (!trimmed)
|
|
14
|
+
continue;
|
|
15
|
+
let obj;
|
|
16
|
+
try {
|
|
17
|
+
obj = JSON.parse(trimmed);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (obj['type'] === 'result' && typeof obj['total_cost_usd'] === 'number') {
|
|
23
|
+
const usage = obj['usage'];
|
|
24
|
+
result = {
|
|
25
|
+
costUsd: obj['total_cost_usd'],
|
|
26
|
+
inputTokens: typeof usage?.['input_tokens'] === 'number' ? usage['input_tokens'] : undefined,
|
|
27
|
+
outputTokens: typeof usage?.['output_tokens'] === 'number' ? usage['output_tokens'] : undefined,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
/** Parse Codex `--json` output for the last turn.completed token usage. */
|
|
34
|
+
export function parseCodexUsage(stdoutJsonl) {
|
|
35
|
+
let result = null;
|
|
36
|
+
for (const line of stdoutJsonl.split('\n')) {
|
|
37
|
+
const trimmed = line.trim();
|
|
38
|
+
if (!trimmed)
|
|
39
|
+
continue;
|
|
40
|
+
let obj;
|
|
41
|
+
try {
|
|
42
|
+
obj = JSON.parse(trimmed);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (obj['type'] === 'turn.completed' && obj['usage']) {
|
|
48
|
+
const usage = obj['usage'];
|
|
49
|
+
const inT = usage['input_tokens'];
|
|
50
|
+
const outT = usage['output_tokens'];
|
|
51
|
+
if (typeof inT === 'number' && typeof outT === 'number') {
|
|
52
|
+
result = { inputTokens: inT, outputTokens: outT };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
function heuristicUsage(model) {
|
|
59
|
+
const est = model ? estimateModelCost(model) : null;
|
|
60
|
+
return {
|
|
61
|
+
model: model ?? 'unknown',
|
|
62
|
+
costUsd: est?.usd ?? UNKNOWN_MODEL_FALLBACK_USD,
|
|
63
|
+
estimated: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Determine the USD cost of a finished harness run. Reads the harness's own
|
|
68
|
+
* output file for observed usage; falls back to a heuristic on any failure.
|
|
69
|
+
* Always returns a HarnessUsage — never throws.
|
|
70
|
+
*/
|
|
71
|
+
export function harvestHarnessUsage(harness, workingDir, model) {
|
|
72
|
+
try {
|
|
73
|
+
const canonical = canonicalHarnessName(harness);
|
|
74
|
+
if (canonical === CLAUDE_CODE_HARNESS) {
|
|
75
|
+
const raw = readFileSync(join(workingDir, '.claude-code', 'stdout.jsonl'), 'utf8');
|
|
76
|
+
const parsed = parseClaudeCodeUsage(raw);
|
|
77
|
+
if (parsed) {
|
|
78
|
+
return {
|
|
79
|
+
model: model ?? 'unknown',
|
|
80
|
+
costUsd: parsed.costUsd,
|
|
81
|
+
estimated: false,
|
|
82
|
+
inputTokens: parsed.inputTokens,
|
|
83
|
+
outputTokens: parsed.outputTokens,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return heuristicUsage(model);
|
|
87
|
+
}
|
|
88
|
+
if (canonical === CODEX_HARNESS) {
|
|
89
|
+
const raw = readFileSync(join(workingDir, '.codex-code', 'stdout.jsonl'), 'utf8');
|
|
90
|
+
const parsed = parseCodexUsage(raw);
|
|
91
|
+
// When there is no model id, parsed token counts cannot be priced —
|
|
92
|
+
// discard them and fall back to the heuristic (per spec).
|
|
93
|
+
if (parsed && model) {
|
|
94
|
+
const usd = priceTokens(model, parsed);
|
|
95
|
+
if (usd != null) {
|
|
96
|
+
return {
|
|
97
|
+
model,
|
|
98
|
+
costUsd: usd,
|
|
99
|
+
estimated: false,
|
|
100
|
+
inputTokens: parsed.inputTokens,
|
|
101
|
+
outputTokens: parsed.outputTokens,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return heuristicUsage(model);
|
|
106
|
+
}
|
|
107
|
+
return heuristicUsage(model);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return heuristicUsage(model);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/spend/usage.ts"],"names":[],"mappings":"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"}
|
package/dist/store/store.d.ts
CHANGED
|
@@ -10,6 +10,17 @@ export interface ActivityEventInput {
|
|
|
10
10
|
solverType?: string | null;
|
|
11
11
|
outcome?: string | null;
|
|
12
12
|
detail?: string | null;
|
|
13
|
+
credentialId?: string | null;
|
|
14
|
+
costUsdMicros?: number | null;
|
|
15
|
+
model?: string | null;
|
|
16
|
+
/** Projected AI units debited at claim time (issue #815). Estimates are the gate input; never recomputed. */
|
|
17
|
+
aiUnits?: number | null;
|
|
18
|
+
/** Lifecycle stamp on the per-request row: 'claimed' | 'claim_failed' | 'delivered'. */
|
|
19
|
+
claimStatus?: string | null;
|
|
20
|
+
/** USD estimate captured at claim time (micros). Distinct from `actualCostUsdMicros` filled on completion. */
|
|
21
|
+
estimatedCostUsdMicros?: number | null;
|
|
22
|
+
/** USD actually billed (micros) — filled by the completion path; null until then. */
|
|
23
|
+
actualCostUsdMicros?: number | null;
|
|
13
24
|
}
|
|
14
25
|
export interface ActivityEventRow {
|
|
15
26
|
id: number;
|
|
@@ -21,6 +32,13 @@ export interface ActivityEventRow {
|
|
|
21
32
|
solverType: string | null;
|
|
22
33
|
outcome: string | null;
|
|
23
34
|
detail: string | null;
|
|
35
|
+
credentialId: string | null;
|
|
36
|
+
costUsdMicros: number | null;
|
|
37
|
+
model: string | null;
|
|
38
|
+
aiUnits: number | null;
|
|
39
|
+
claimStatus: string | null;
|
|
40
|
+
estimatedCostUsdMicros: number | null;
|
|
41
|
+
actualCostUsdMicros: number | null;
|
|
24
42
|
}
|
|
25
43
|
export interface RewardClaimInput {
|
|
26
44
|
ts: string;
|
|
@@ -148,6 +166,22 @@ export interface NetworkArtifactMetadataRow {
|
|
|
148
166
|
lastUsedAt: string;
|
|
149
167
|
peerCatalogId: string | null;
|
|
150
168
|
}
|
|
169
|
+
export interface Erc8004AnchorInput {
|
|
170
|
+
envelopeId: string;
|
|
171
|
+
envelopeCid: string;
|
|
172
|
+
contentKind: string;
|
|
173
|
+
metadataKey: string;
|
|
174
|
+
agentId: string;
|
|
175
|
+
chainId: number;
|
|
176
|
+
identityRegistryAddress: string;
|
|
177
|
+
txHash: string;
|
|
178
|
+
blockNumber: number | null;
|
|
179
|
+
payloadHex: string;
|
|
180
|
+
anchoredAt: number;
|
|
181
|
+
}
|
|
182
|
+
export interface Erc8004AnchorRow extends Erc8004AnchorInput {
|
|
183
|
+
id: number;
|
|
184
|
+
}
|
|
151
185
|
export type TaskPostingPolicyType = 'once_per_safe' | 'once_per_bucket' | 'interval';
|
|
152
186
|
type LauncherTaskProjectionState = 'open' | 'claims-in-flight' | 'fully-claimed' | 'settled' | 'failed';
|
|
153
187
|
export interface TaskPostRecord {
|
|
@@ -185,6 +219,8 @@ export declare class Store {
|
|
|
185
219
|
private ensureTaskPostsTaskCoordinatorColumns;
|
|
186
220
|
/** Older local DBs may have the projection table from before Task grouping fields landed. */
|
|
187
221
|
private ensureEnvelopeProjectionColumns;
|
|
222
|
+
/** Older local DBs predate the per-credential spend-ledger columns on activity_events. */
|
|
223
|
+
private ensureActivityEventCostColumns;
|
|
188
224
|
/**
|
|
189
225
|
* Task-native startup ignores the retired request-first `restoration_intents`
|
|
190
226
|
* table. Keep a one-time local marker when old in-flight rows are present so
|
|
@@ -194,6 +230,14 @@ export declare class Store {
|
|
|
194
230
|
/** Idempotent: older DBs before idx_reward_claims_tx may lack the unique index. */
|
|
195
231
|
private ensureRewardClaimsTxIndex;
|
|
196
232
|
recordOwnActivity(requestId: string, role: 'created' | 'claimed' | 'delivered' | 'evaluated'): void;
|
|
233
|
+
/**
|
|
234
|
+
* Membership-only variant of `recordOwnActivity`: writes the
|
|
235
|
+
* `own_activity` row but does NOT emit a generic `activity_events`
|
|
236
|
+
* row. Used by paths that emit their own enriched activity event
|
|
237
|
+
* (e.g. issue #815's claim path attaches credentialId / aiUnits /
|
|
238
|
+
* estimatedCostUsdMicros / claimStatus to the row).
|
|
239
|
+
*/
|
|
240
|
+
markOwnActivity(requestId: string, role: 'created' | 'claimed' | 'delivered' | 'evaluated'): void;
|
|
197
241
|
isOwnActivity(requestId: string): boolean;
|
|
198
242
|
setShutdownState(state: 'clean' | 'running'): void;
|
|
199
243
|
getShutdownState(): string | null;
|
|
@@ -279,8 +323,63 @@ export declare class Store {
|
|
|
279
323
|
since?: string;
|
|
280
324
|
cursor?: string;
|
|
281
325
|
}): ActivityEventRow[];
|
|
326
|
+
/**
|
|
327
|
+
* Total cost in micro-dollars recorded against a credential since the most
|
|
328
|
+
* recent UTC midnight. Backs the daily spend cap.
|
|
329
|
+
*/
|
|
330
|
+
spentTodayMicros(credentialId: string, now?: Date): number;
|
|
331
|
+
/**
|
|
332
|
+
* Sum of `ai_units` for a credential within the current 6h UTC-aligned
|
|
333
|
+
* block (00:00 / 06:00 / 12:00 / 18:00 boundaries). Reads only rows whose
|
|
334
|
+
* `claim_status = 'claimed'` or `'delivered'` so failed-claim rows
|
|
335
|
+
* (`ai_units = 0`, `claim_status = 'claim_failed'`) don't muddy the sum
|
|
336
|
+
* even though their contribution is already zero.
|
|
337
|
+
*
|
|
338
|
+
* Issue #815. Backs the per-block AI-units ceiling gate.
|
|
339
|
+
*/
|
|
340
|
+
aiUnitsThisBlock(credentialId: string, now?: Date): number;
|
|
341
|
+
/**
|
|
342
|
+
* Sum of `ai_units` for a credential within the trailing 7-day rolling
|
|
343
|
+
* window from `now`. Backs the per-week AI-units safety-net ceiling.
|
|
344
|
+
* Issue #815.
|
|
345
|
+
*/
|
|
346
|
+
aiUnitsThisWeek(credentialId: string, now?: Date): number;
|
|
347
|
+
/**
|
|
348
|
+
* True iff an `ai_units_cap_reached` row exists for the given
|
|
349
|
+
* (credentialId, window, blockId). Used by the daemon to hydrate the
|
|
350
|
+
* AI-units gate's in-memory pause memo across restarts so the
|
|
351
|
+
* "exactly one event per (credential, window, block-id)" guarantee
|
|
352
|
+
* holds across process boundaries (issue #815, finding 1).
|
|
353
|
+
*
|
|
354
|
+
* Lookup is by `credential_id` + `kind` + the `[block=...][window=...]`
|
|
355
|
+
* markers that `daemon.ts` embeds in the row's `detail` string.
|
|
356
|
+
*/
|
|
357
|
+
hasAiUnitsCapReachedFor(credentialId: string, window: 'block' | 'week', blockId: string): boolean;
|
|
358
|
+
/**
|
|
359
|
+
* Mark the per-request `claimed` row as `delivered` and record
|
|
360
|
+
* `actual_cost_usd_micros`. The `ai_units` projection captured at
|
|
361
|
+
* claim time is intentionally NOT recomputed — the issue spec says
|
|
362
|
+
* "estimates are the gate input, never recomputed". Idempotent: a
|
|
363
|
+
* no-op when no `claimed` row exists.
|
|
364
|
+
*/
|
|
365
|
+
finalizeClaimDelivered(requestId: string, actualCostUsdMicros: number): void;
|
|
282
366
|
/** Newer events first, then ascending id for `jinn logs --follow` (oldest in batch printed first in caller). */
|
|
283
367
|
getActivityEventsAfterId(afterId: number, limit: number): ActivityEventRow[];
|
|
368
|
+
/**
|
|
369
|
+
* Filtered, id-cursored page of activity events for the dedicated Events
|
|
370
|
+
* page. Newest-first.
|
|
371
|
+
*
|
|
372
|
+
* Cursors on `id` rather than `ts` so startup/shutdown rows with null
|
|
373
|
+
* timestamps remain reachable.
|
|
374
|
+
*/
|
|
375
|
+
getActivityEventsPage(opts?: {
|
|
376
|
+
kinds?: string[];
|
|
377
|
+
outcome?: string;
|
|
378
|
+
requestId?: string;
|
|
379
|
+
beforeId?: number;
|
|
380
|
+
limit?: number;
|
|
381
|
+
}): ActivityEventRow[];
|
|
382
|
+
getActivityEventById(id: number): ActivityEventRow | null;
|
|
284
383
|
getActivityCountsByKind(): Record<string, number>;
|
|
285
384
|
getLastEventAtForService(serviceIndex: number): string | null;
|
|
286
385
|
getActivityCountsForService(serviceIndex: number): Record<string, number>;
|
|
@@ -398,6 +497,8 @@ export declare class Store {
|
|
|
398
497
|
}>;
|
|
399
498
|
saveEnvelopeProjection(projection: EnvelopeProjection): void;
|
|
400
499
|
queryEnvelopeProjections(query?: EnvelopeProjectionQuery): EnvelopeProjection[];
|
|
500
|
+
saveErc8004Anchor(input: Erc8004AnchorInput): void;
|
|
501
|
+
listErc8004AnchorsByEnvelopeCids(envelopeCids: readonly string[]): Erc8004AnchorRow[];
|
|
401
502
|
close(): void;
|
|
402
503
|
}
|
|
403
504
|
export {};
|
package/dist/store/store.js
CHANGED
|
@@ -228,6 +228,23 @@ CREATE TABLE IF NOT EXISTS envelope_projection_metadata (
|
|
|
228
228
|
CREATE INDEX IF NOT EXISTS idx_envelope_projection_metadata_key_value
|
|
229
229
|
ON envelope_projection_metadata (key, value_text);
|
|
230
230
|
|
|
231
|
+
CREATE TABLE IF NOT EXISTS erc8004_anchors (
|
|
232
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
233
|
+
envelope_id TEXT NOT NULL,
|
|
234
|
+
envelope_cid TEXT NOT NULL,
|
|
235
|
+
content_kind TEXT NOT NULL,
|
|
236
|
+
metadata_key TEXT NOT NULL,
|
|
237
|
+
agent_id TEXT NOT NULL,
|
|
238
|
+
chain_id INTEGER NOT NULL,
|
|
239
|
+
identity_registry_address TEXT NOT NULL,
|
|
240
|
+
tx_hash TEXT NOT NULL,
|
|
241
|
+
block_number INTEGER,
|
|
242
|
+
payload_hex TEXT NOT NULL,
|
|
243
|
+
anchored_at INTEGER NOT NULL
|
|
244
|
+
);
|
|
245
|
+
CREATE INDEX IF NOT EXISTS idx_erc8004_anchors_envelope_cid ON erc8004_anchors(envelope_cid);
|
|
246
|
+
CREATE INDEX IF NOT EXISTS idx_erc8004_anchors_envelope_id ON erc8004_anchors(envelope_id);
|
|
247
|
+
|
|
231
248
|
CREATE TABLE IF NOT EXISTS task_post_locks (
|
|
232
249
|
creator_safe_address TEXT NOT NULL,
|
|
233
250
|
source_key TEXT NOT NULL,
|
|
@@ -299,6 +316,7 @@ export class Store {
|
|
|
299
316
|
this.ensureNetworkArtifactsPeerCatalogId();
|
|
300
317
|
this.ensureTaskPostsTaskCoordinatorColumns();
|
|
301
318
|
this.ensureEnvelopeProjectionColumns();
|
|
319
|
+
this.ensureActivityEventCostColumns();
|
|
302
320
|
this.backfillActivityEvents();
|
|
303
321
|
this.recordLegacyRestorationIntentsIgnored();
|
|
304
322
|
}
|
|
@@ -363,6 +381,30 @@ export class Store {
|
|
|
363
381
|
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_envelope_projections_solution_ref ON envelope_projections (solution_envelope_ref)`);
|
|
364
382
|
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_envelope_projections_generated ON envelope_projections (generated_at DESC)`);
|
|
365
383
|
}
|
|
384
|
+
/** Older local DBs predate the per-credential spend-ledger columns on activity_events. */
|
|
385
|
+
ensureActivityEventCostColumns() {
|
|
386
|
+
const activityCols = new Set(this.db.prepare(`PRAGMA table_info(activity_events)`).all()
|
|
387
|
+
.map(c => c.name));
|
|
388
|
+
const addActivityColumn = (name, ddl) => {
|
|
389
|
+
if (!activityCols.has(name))
|
|
390
|
+
this.db.exec(`ALTER TABLE activity_events ADD COLUMN ${ddl}`);
|
|
391
|
+
};
|
|
392
|
+
addActivityColumn('credential_id', 'credential_id TEXT');
|
|
393
|
+
addActivityColumn('cost_usd_micros', 'cost_usd_micros INTEGER');
|
|
394
|
+
addActivityColumn('model', 'model TEXT');
|
|
395
|
+
// Issue #815 — AI-units ceiling. ai_units is the gate-input projection
|
|
396
|
+
// captured at claim time; claim_status tracks the per-request lifecycle
|
|
397
|
+
// (claimed / claim_failed / delivered); the cost pair splits the
|
|
398
|
+
// estimated-at-claim-time vs actual-at-completion telemetry.
|
|
399
|
+
addActivityColumn('ai_units', 'ai_units REAL');
|
|
400
|
+
addActivityColumn('claim_status', 'claim_status TEXT');
|
|
401
|
+
addActivityColumn('estimated_cost_usd_micros', 'estimated_cost_usd_micros INTEGER');
|
|
402
|
+
addActivityColumn('actual_cost_usd_micros', 'actual_cost_usd_micros INTEGER');
|
|
403
|
+
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_activity_events_credential ON activity_events (credential_id, ts)`);
|
|
404
|
+
// Per-request lookup for the completion-time update path that fills
|
|
405
|
+
// actualCostUsdMicros / sets claim_status='delivered'.
|
|
406
|
+
this.db.exec(`CREATE INDEX IF NOT EXISTS idx_activity_events_req_claim ON activity_events (request_id, claim_status)`);
|
|
407
|
+
}
|
|
366
408
|
/**
|
|
367
409
|
* Task-native startup ignores the retired request-first `restoration_intents`
|
|
368
410
|
* table. Keep a one-time local marker when old in-flight rows are present so
|
|
@@ -417,6 +459,16 @@ export class Store {
|
|
|
417
459
|
const ts = new Date().toISOString();
|
|
418
460
|
this.recordActivityEvent({ ts, kind: role, requestId });
|
|
419
461
|
}
|
|
462
|
+
/**
|
|
463
|
+
* Membership-only variant of `recordOwnActivity`: writes the
|
|
464
|
+
* `own_activity` row but does NOT emit a generic `activity_events`
|
|
465
|
+
* row. Used by paths that emit their own enriched activity event
|
|
466
|
+
* (e.g. issue #815's claim path attaches credentialId / aiUnits /
|
|
467
|
+
* estimatedCostUsdMicros / claimStatus to the row).
|
|
468
|
+
*/
|
|
469
|
+
markOwnActivity(requestId, role) {
|
|
470
|
+
this.db.prepare(`INSERT OR REPLACE INTO own_activity (request_id, role) VALUES (?, ?)`).run(requestId, role);
|
|
471
|
+
}
|
|
420
472
|
isOwnActivity(requestId) {
|
|
421
473
|
const row = this.db.prepare('SELECT 1 FROM own_activity WHERE request_id = ?').get(requestId);
|
|
422
474
|
return row !== undefined;
|
|
@@ -746,8 +798,14 @@ export class Store {
|
|
|
746
798
|
return legacyRows.map(r => ({ requestId: r.request_id, role: r.role }));
|
|
747
799
|
}
|
|
748
800
|
recordActivityEvent(event) {
|
|
749
|
-
this.db.prepare(`INSERT INTO activity_events
|
|
750
|
-
|
|
801
|
+
this.db.prepare(`INSERT INTO activity_events
|
|
802
|
+
(ts, kind, request_id, service_index, tx_hash, solver_type, outcome, detail,
|
|
803
|
+
credential_id, cost_usd_micros, model,
|
|
804
|
+
ai_units, claim_status, estimated_cost_usd_micros, actual_cost_usd_micros)
|
|
805
|
+
VALUES
|
|
806
|
+
(@ts, @kind, @requestId, @serviceIndex, @txHash, @solverType, @outcome, @detail,
|
|
807
|
+
@credentialId, @costUsdMicros, @model,
|
|
808
|
+
@aiUnits, @claimStatus, @estimatedCostUsdMicros, @actualCostUsdMicros)`).run({
|
|
751
809
|
ts: event.ts ?? null,
|
|
752
810
|
kind: event.kind,
|
|
753
811
|
requestId: event.requestId ?? null,
|
|
@@ -756,6 +814,13 @@ export class Store {
|
|
|
756
814
|
solverType: event.solverType ?? null,
|
|
757
815
|
outcome: event.outcome ?? null,
|
|
758
816
|
detail: event.detail ?? null,
|
|
817
|
+
credentialId: event.credentialId ?? null,
|
|
818
|
+
costUsdMicros: event.costUsdMicros ?? null,
|
|
819
|
+
model: event.model ?? null,
|
|
820
|
+
aiUnits: event.aiUnits ?? null,
|
|
821
|
+
claimStatus: event.claimStatus ?? null,
|
|
822
|
+
estimatedCostUsdMicros: event.estimatedCostUsdMicros ?? null,
|
|
823
|
+
actualCostUsdMicros: event.actualCostUsdMicros ?? null,
|
|
759
824
|
});
|
|
760
825
|
}
|
|
761
826
|
getRecentActivityEvents(limit, opts = {}) {
|
|
@@ -771,7 +836,9 @@ export class Store {
|
|
|
771
836
|
params['cursor'] = opts.cursor;
|
|
772
837
|
}
|
|
773
838
|
const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
|
|
774
|
-
const rows = this.db.prepare(`SELECT id, ts, kind, request_id, service_index, tx_hash, solver_type, outcome, detail
|
|
839
|
+
const rows = this.db.prepare(`SELECT id, ts, kind, request_id, service_index, tx_hash, solver_type, outcome, detail,
|
|
840
|
+
credential_id, cost_usd_micros, model,
|
|
841
|
+
ai_units, claim_status, estimated_cost_usd_micros, actual_cost_usd_micros
|
|
775
842
|
FROM activity_events
|
|
776
843
|
${where}
|
|
777
844
|
ORDER BY id DESC
|
|
@@ -786,13 +853,106 @@ export class Store {
|
|
|
786
853
|
solverType: r.solver_type,
|
|
787
854
|
outcome: r.outcome,
|
|
788
855
|
detail: r.detail,
|
|
856
|
+
credentialId: r.credential_id,
|
|
857
|
+
costUsdMicros: r.cost_usd_micros,
|
|
858
|
+
model: r.model,
|
|
859
|
+
aiUnits: r.ai_units,
|
|
860
|
+
claimStatus: r.claim_status,
|
|
861
|
+
estimatedCostUsdMicros: r.estimated_cost_usd_micros,
|
|
862
|
+
actualCostUsdMicros: r.actual_cost_usd_micros,
|
|
789
863
|
}));
|
|
790
864
|
}
|
|
865
|
+
/**
|
|
866
|
+
* Total cost in micro-dollars recorded against a credential since the most
|
|
867
|
+
* recent UTC midnight. Backs the daily spend cap.
|
|
868
|
+
*/
|
|
869
|
+
spentTodayMicros(credentialId, now = new Date()) {
|
|
870
|
+
const midnight = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate())).toISOString();
|
|
871
|
+
const row = this.db.prepare(`SELECT COALESCE(SUM(cost_usd_micros), 0) AS total
|
|
872
|
+
FROM activity_events
|
|
873
|
+
WHERE credential_id = @cid AND ts IS NOT NULL AND ts >= @midnight`).get({ cid: credentialId, midnight });
|
|
874
|
+
return row.total;
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Sum of `ai_units` for a credential within the current 6h UTC-aligned
|
|
878
|
+
* block (00:00 / 06:00 / 12:00 / 18:00 boundaries). Reads only rows whose
|
|
879
|
+
* `claim_status = 'claimed'` or `'delivered'` so failed-claim rows
|
|
880
|
+
* (`ai_units = 0`, `claim_status = 'claim_failed'`) don't muddy the sum
|
|
881
|
+
* even though their contribution is already zero.
|
|
882
|
+
*
|
|
883
|
+
* Issue #815. Backs the per-block AI-units ceiling gate.
|
|
884
|
+
*/
|
|
885
|
+
aiUnitsThisBlock(credentialId, now = new Date()) {
|
|
886
|
+
const startOfDay = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
|
|
887
|
+
const sinceDayStart = now.getTime() - startOfDay;
|
|
888
|
+
const sixHoursMs = 6 * 60 * 60 * 1_000;
|
|
889
|
+
// Cap at 3 — there are 4 blocks per day (indices 0..3). Edge cases
|
|
890
|
+
// where sinceDayStart ≈ 24h (millisecond rounding) would otherwise
|
|
891
|
+
// overshoot into a non-existent 5th block in the *next* day.
|
|
892
|
+
const blocksIn = Math.min(Math.floor(sinceDayStart / sixHoursMs), 3);
|
|
893
|
+
const blockStart = new Date(startOfDay + blocksIn * sixHoursMs).toISOString();
|
|
894
|
+
const blockEnd = new Date(startOfDay + (blocksIn + 1) * sixHoursMs).toISOString();
|
|
895
|
+
const row = this.db.prepare(`SELECT COALESCE(SUM(ai_units), 0) AS total
|
|
896
|
+
FROM activity_events
|
|
897
|
+
WHERE credential_id = @cid
|
|
898
|
+
AND ts IS NOT NULL AND ts >= @blockStart AND ts < @blockEnd
|
|
899
|
+
AND claim_status IN ('claimed', 'delivered')`).get({ cid: credentialId, blockStart, blockEnd });
|
|
900
|
+
return row.total ?? 0;
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Sum of `ai_units` for a credential within the trailing 7-day rolling
|
|
904
|
+
* window from `now`. Backs the per-week AI-units safety-net ceiling.
|
|
905
|
+
* Issue #815.
|
|
906
|
+
*/
|
|
907
|
+
aiUnitsThisWeek(credentialId, now = new Date()) {
|
|
908
|
+
const weekStart = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1_000).toISOString();
|
|
909
|
+
const row = this.db.prepare(`SELECT COALESCE(SUM(ai_units), 0) AS total
|
|
910
|
+
FROM activity_events
|
|
911
|
+
WHERE credential_id = @cid
|
|
912
|
+
AND ts IS NOT NULL AND ts >= @weekStart
|
|
913
|
+
AND claim_status IN ('claimed', 'delivered')`).get({ cid: credentialId, weekStart });
|
|
914
|
+
return row.total ?? 0;
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* True iff an `ai_units_cap_reached` row exists for the given
|
|
918
|
+
* (credentialId, window, blockId). Used by the daemon to hydrate the
|
|
919
|
+
* AI-units gate's in-memory pause memo across restarts so the
|
|
920
|
+
* "exactly one event per (credential, window, block-id)" guarantee
|
|
921
|
+
* holds across process boundaries (issue #815, finding 1).
|
|
922
|
+
*
|
|
923
|
+
* Lookup is by `credential_id` + `kind` + the `[block=...][window=...]`
|
|
924
|
+
* markers that `daemon.ts` embeds in the row's `detail` string.
|
|
925
|
+
*/
|
|
926
|
+
hasAiUnitsCapReachedFor(credentialId, window, blockId) {
|
|
927
|
+
const marker = `[block=${blockId}][window=${window}]`;
|
|
928
|
+
const row = this.db.prepare(`SELECT 1 AS hit
|
|
929
|
+
FROM activity_events
|
|
930
|
+
WHERE kind = 'ai_units_cap_reached'
|
|
931
|
+
AND credential_id = @cid
|
|
932
|
+
AND detail LIKE @marker
|
|
933
|
+
LIMIT 1`).get({ cid: credentialId, marker: `${marker}%` });
|
|
934
|
+
return row !== undefined;
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* Mark the per-request `claimed` row as `delivered` and record
|
|
938
|
+
* `actual_cost_usd_micros`. The `ai_units` projection captured at
|
|
939
|
+
* claim time is intentionally NOT recomputed — the issue spec says
|
|
940
|
+
* "estimates are the gate input, never recomputed". Idempotent: a
|
|
941
|
+
* no-op when no `claimed` row exists.
|
|
942
|
+
*/
|
|
943
|
+
finalizeClaimDelivered(requestId, actualCostUsdMicros) {
|
|
944
|
+
this.db.prepare(`UPDATE activity_events
|
|
945
|
+
SET claim_status = 'delivered',
|
|
946
|
+
actual_cost_usd_micros = @actual
|
|
947
|
+
WHERE request_id = @req AND claim_status = 'claimed'`).run({ req: requestId, actual: actualCostUsdMicros });
|
|
948
|
+
}
|
|
791
949
|
/** Newer events first, then ascending id for `jinn logs --follow` (oldest in batch printed first in caller). */
|
|
792
950
|
getActivityEventsAfterId(afterId, limit) {
|
|
793
951
|
const effectiveLimit = Math.max(0, Math.min(limit, 1000));
|
|
794
952
|
const rows = this.db
|
|
795
|
-
.prepare(`SELECT id, ts, kind, request_id, service_index, tx_hash, solver_type, outcome, detail
|
|
953
|
+
.prepare(`SELECT id, ts, kind, request_id, service_index, tx_hash, solver_type, outcome, detail,
|
|
954
|
+
credential_id, cost_usd_micros, model,
|
|
955
|
+
ai_units, claim_status, estimated_cost_usd_micros, actual_cost_usd_micros
|
|
796
956
|
FROM activity_events
|
|
797
957
|
WHERE id > @afterId
|
|
798
958
|
ORDER BY id ASC
|
|
@@ -808,8 +968,99 @@ export class Store {
|
|
|
808
968
|
solverType: r.solver_type,
|
|
809
969
|
outcome: r.outcome,
|
|
810
970
|
detail: r.detail,
|
|
971
|
+
credentialId: r.credential_id,
|
|
972
|
+
costUsdMicros: r.cost_usd_micros,
|
|
973
|
+
model: r.model,
|
|
974
|
+
aiUnits: r.ai_units,
|
|
975
|
+
claimStatus: r.claim_status,
|
|
976
|
+
estimatedCostUsdMicros: r.estimated_cost_usd_micros,
|
|
977
|
+
actualCostUsdMicros: r.actual_cost_usd_micros,
|
|
978
|
+
}));
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Filtered, id-cursored page of activity events for the dedicated Events
|
|
982
|
+
* page. Newest-first.
|
|
983
|
+
*
|
|
984
|
+
* Cursors on `id` rather than `ts` so startup/shutdown rows with null
|
|
985
|
+
* timestamps remain reachable.
|
|
986
|
+
*/
|
|
987
|
+
getActivityEventsPage(opts = {}) {
|
|
988
|
+
const effectiveLimit = Math.max(1, Math.min(opts.limit ?? 50, 200));
|
|
989
|
+
const clauses = [];
|
|
990
|
+
const params = { limit: effectiveLimit };
|
|
991
|
+
if (opts.kinds && opts.kinds.length > 0) {
|
|
992
|
+
const placeholders = opts.kinds.map((_, i) => `@kind${i}`);
|
|
993
|
+
clauses.push(`kind IN (${placeholders.join(', ')})`);
|
|
994
|
+
opts.kinds.forEach((k, i) => {
|
|
995
|
+
params[`kind${i}`] = k;
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
if (opts.outcome) {
|
|
999
|
+
clauses.push('outcome = @outcome');
|
|
1000
|
+
params['outcome'] = opts.outcome;
|
|
1001
|
+
}
|
|
1002
|
+
if (opts.requestId) {
|
|
1003
|
+
clauses.push('request_id = @requestId');
|
|
1004
|
+
params['requestId'] = opts.requestId;
|
|
1005
|
+
}
|
|
1006
|
+
if (opts.beforeId !== undefined) {
|
|
1007
|
+
clauses.push('id < @beforeId');
|
|
1008
|
+
params['beforeId'] = opts.beforeId;
|
|
1009
|
+
}
|
|
1010
|
+
const where = clauses.length > 0 ? `WHERE ${clauses.join(' AND ')}` : '';
|
|
1011
|
+
const rows = this.db.prepare(`SELECT id, ts, kind, request_id, service_index, tx_hash, solver_type, outcome, detail,
|
|
1012
|
+
credential_id, cost_usd_micros, model,
|
|
1013
|
+
ai_units, claim_status, estimated_cost_usd_micros, actual_cost_usd_micros
|
|
1014
|
+
FROM activity_events
|
|
1015
|
+
${where}
|
|
1016
|
+
ORDER BY id DESC
|
|
1017
|
+
LIMIT @limit`).all(params);
|
|
1018
|
+
return rows.map((r) => ({
|
|
1019
|
+
id: r.id,
|
|
1020
|
+
ts: r.ts,
|
|
1021
|
+
kind: r.kind,
|
|
1022
|
+
requestId: r.request_id,
|
|
1023
|
+
serviceIndex: r.service_index,
|
|
1024
|
+
txHash: r.tx_hash,
|
|
1025
|
+
solverType: r.solver_type,
|
|
1026
|
+
outcome: r.outcome,
|
|
1027
|
+
detail: r.detail,
|
|
1028
|
+
credentialId: r.credential_id,
|
|
1029
|
+
costUsdMicros: r.cost_usd_micros,
|
|
1030
|
+
model: r.model,
|
|
1031
|
+
aiUnits: r.ai_units,
|
|
1032
|
+
claimStatus: r.claim_status,
|
|
1033
|
+
estimatedCostUsdMicros: r.estimated_cost_usd_micros,
|
|
1034
|
+
actualCostUsdMicros: r.actual_cost_usd_micros,
|
|
811
1035
|
}));
|
|
812
1036
|
}
|
|
1037
|
+
getActivityEventById(id) {
|
|
1038
|
+
const r = this.db.prepare(`SELECT id, ts, kind, request_id, service_index, tx_hash, solver_type, outcome, detail,
|
|
1039
|
+
credential_id, cost_usd_micros, model,
|
|
1040
|
+
ai_units, claim_status, estimated_cost_usd_micros, actual_cost_usd_micros
|
|
1041
|
+
FROM activity_events
|
|
1042
|
+
WHERE id = ?`).get(id);
|
|
1043
|
+
if (!r)
|
|
1044
|
+
return null;
|
|
1045
|
+
return {
|
|
1046
|
+
id: r.id,
|
|
1047
|
+
ts: r.ts,
|
|
1048
|
+
kind: r.kind,
|
|
1049
|
+
requestId: r.request_id,
|
|
1050
|
+
serviceIndex: r.service_index,
|
|
1051
|
+
txHash: r.tx_hash,
|
|
1052
|
+
solverType: r.solver_type,
|
|
1053
|
+
outcome: r.outcome,
|
|
1054
|
+
detail: r.detail,
|
|
1055
|
+
credentialId: r.credential_id,
|
|
1056
|
+
costUsdMicros: r.cost_usd_micros,
|
|
1057
|
+
model: r.model,
|
|
1058
|
+
aiUnits: r.ai_units,
|
|
1059
|
+
claimStatus: r.claim_status,
|
|
1060
|
+
estimatedCostUsdMicros: r.estimated_cost_usd_micros,
|
|
1061
|
+
actualCostUsdMicros: r.actual_cost_usd_micros,
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
813
1064
|
getActivityCountsByKind() {
|
|
814
1065
|
const rows = this.db.prepare(`SELECT kind, COUNT(*) as c FROM activity_events GROUP BY kind`).all();
|
|
815
1066
|
const out = {};
|
|
@@ -1519,6 +1770,55 @@ export class Store {
|
|
|
1519
1770
|
LIMIT @limit`).all(params);
|
|
1520
1771
|
return rows.map(rowToEnvelopeProjection);
|
|
1521
1772
|
}
|
|
1773
|
+
saveErc8004Anchor(input) {
|
|
1774
|
+
this.db.prepare(`INSERT INTO erc8004_anchors
|
|
1775
|
+
(envelope_id, envelope_cid, content_kind, metadata_key, agent_id,
|
|
1776
|
+
chain_id, identity_registry_address, tx_hash, block_number,
|
|
1777
|
+
payload_hex, anchored_at)
|
|
1778
|
+
VALUES
|
|
1779
|
+
(@envelopeId, @envelopeCid, @contentKind, @metadataKey, @agentId,
|
|
1780
|
+
@chainId, @identityRegistryAddress, @txHash, @blockNumber,
|
|
1781
|
+
@payloadHex, @anchoredAt)`).run({
|
|
1782
|
+
envelopeId: input.envelopeId,
|
|
1783
|
+
envelopeCid: input.envelopeCid,
|
|
1784
|
+
contentKind: input.contentKind,
|
|
1785
|
+
metadataKey: input.metadataKey,
|
|
1786
|
+
agentId: input.agentId,
|
|
1787
|
+
chainId: input.chainId,
|
|
1788
|
+
identityRegistryAddress: input.identityRegistryAddress,
|
|
1789
|
+
txHash: input.txHash,
|
|
1790
|
+
blockNumber: input.blockNumber,
|
|
1791
|
+
payloadHex: input.payloadHex,
|
|
1792
|
+
anchoredAt: input.anchoredAt,
|
|
1793
|
+
});
|
|
1794
|
+
}
|
|
1795
|
+
listErc8004AnchorsByEnvelopeCids(envelopeCids) {
|
|
1796
|
+
if (envelopeCids.length === 0)
|
|
1797
|
+
return [];
|
|
1798
|
+
const placeholders = envelopeCids.map((_, i) => `@cid${i}`).join(', ');
|
|
1799
|
+
const params = {};
|
|
1800
|
+
envelopeCids.forEach((cid, i) => { params[`cid${i}`] = cid; });
|
|
1801
|
+
const rows = this.db.prepare(`SELECT id, envelope_id, envelope_cid, content_kind, metadata_key, agent_id,
|
|
1802
|
+
chain_id, identity_registry_address, tx_hash, block_number,
|
|
1803
|
+
payload_hex, anchored_at
|
|
1804
|
+
FROM erc8004_anchors
|
|
1805
|
+
WHERE envelope_cid IN (${placeholders})
|
|
1806
|
+
ORDER BY anchored_at ASC, id ASC`).all(params);
|
|
1807
|
+
return rows.map((r) => ({
|
|
1808
|
+
id: r.id,
|
|
1809
|
+
envelopeId: r.envelope_id,
|
|
1810
|
+
envelopeCid: r.envelope_cid,
|
|
1811
|
+
contentKind: r.content_kind,
|
|
1812
|
+
metadataKey: r.metadata_key,
|
|
1813
|
+
agentId: r.agent_id,
|
|
1814
|
+
chainId: r.chain_id,
|
|
1815
|
+
identityRegistryAddress: r.identity_registry_address,
|
|
1816
|
+
txHash: r.tx_hash,
|
|
1817
|
+
blockNumber: r.block_number,
|
|
1818
|
+
payloadHex: r.payload_hex,
|
|
1819
|
+
anchoredAt: r.anchored_at,
|
|
1820
|
+
}));
|
|
1821
|
+
}
|
|
1522
1822
|
close() {
|
|
1523
1823
|
this.db.close();
|
|
1524
1824
|
}
|