@kognai/clawrouter-x402 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 +12 -0
- package/dist/clawrouter-x402/src/clawrouter-v2.d.ts +87 -0
- package/dist/clawrouter-x402/src/clawrouter-v2.js +811 -0
- package/dist/clawrouter-x402/src/index.d.ts +21 -0
- package/dist/clawrouter-x402/src/index.js +45 -0
- package/dist/orchestrator-core/src/lib/acp.d.ts +61 -0
- package/dist/orchestrator-core/src/lib/acp.js +425 -0
- package/dist/orchestrator-core/src/lib/engine-paths.d.ts +13 -0
- package/dist/orchestrator-core/src/lib/engine-paths.js +32 -0
- package/dist/orchestrator-core/src/lib/model-router-contract.d.ts +91 -0
- package/dist/orchestrator-core/src/lib/model-router-contract.js +19 -0
- package/dist/orchestrator-core/src/lib/wallet-state.d.ts +26 -0
- package/dist/orchestrator-core/src/lib/wallet-state.js +85 -0
- package/package.json +33 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* model-router-contract.ts — TICKET-215 Wave C: the engine's model-routing SEAM.
|
|
3
|
+
*
|
|
4
|
+
* This is the zero-dep interface that decouples the orchestrator from any
|
|
5
|
+
* concrete router. The orchestrator depends ONLY on this contract; the actual
|
|
6
|
+
* implementation is injected at startup (see model-router-registry.ts).
|
|
7
|
+
*
|
|
8
|
+
* WHY: ClawRouter v2 (the production router) imports `viem` for on-chain x402
|
|
9
|
+
* payments. We do NOT want `viem` in @kognai/orchestrator-core — that would make
|
|
10
|
+
* every adopter (e.g. Invoica, which never routes on-chain) carry web3. So the
|
|
11
|
+
* viem-backed router lives OUTSIDE core (Kognai injects it); products that don't
|
|
12
|
+
* route on-chain inject their own / use a local default. viem stays absent from
|
|
13
|
+
* core's dependency tree entirely.
|
|
14
|
+
*
|
|
15
|
+
* These request/response types are the canonical source of truth — clawrouter-v2
|
|
16
|
+
* imports them from here and re-exports for back-compat.
|
|
17
|
+
*/
|
|
18
|
+
export type TierClass = 'text' | 'creative';
|
|
19
|
+
export type TextComplexity = 'nano' | 'local' | 'power' | 'exec' | 'apex';
|
|
20
|
+
export type CreativeModality = 'image' | 'video' | 'speech' | 'music' | 'transcription' | 'visual_understanding';
|
|
21
|
+
export type CreativeQuality = 'fast' | 'high' | 'emotional';
|
|
22
|
+
export interface ClawRouterV2Request {
|
|
23
|
+
task_type: string;
|
|
24
|
+
tier_class: TierClass;
|
|
25
|
+
complexity?: TextComplexity;
|
|
26
|
+
modality?: CreativeModality;
|
|
27
|
+
quality?: CreativeQuality;
|
|
28
|
+
context_tokens: number;
|
|
29
|
+
constitutional_flag: boolean;
|
|
30
|
+
agent_id: string;
|
|
31
|
+
payload: {
|
|
32
|
+
system?: string;
|
|
33
|
+
prompt?: string;
|
|
34
|
+
messages?: Array<{
|
|
35
|
+
role: string;
|
|
36
|
+
content: string;
|
|
37
|
+
}>;
|
|
38
|
+
[key: string]: any;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface ClawRouterV2Response {
|
|
42
|
+
content: string;
|
|
43
|
+
model: string;
|
|
44
|
+
tier: string;
|
|
45
|
+
local: boolean;
|
|
46
|
+
cost_usd: number;
|
|
47
|
+
input_tokens: number;
|
|
48
|
+
output_tokens: number;
|
|
49
|
+
qcg_compressed: boolean;
|
|
50
|
+
tokens_saved_by_qcg: number;
|
|
51
|
+
agent_id: string;
|
|
52
|
+
task_type: string;
|
|
53
|
+
timestamp: string;
|
|
54
|
+
}
|
|
55
|
+
export interface CallLLMOptions {
|
|
56
|
+
systemPrompt?: string;
|
|
57
|
+
complexity?: TextComplexity;
|
|
58
|
+
constitutional?: boolean;
|
|
59
|
+
agentId?: string;
|
|
60
|
+
taskType?: string;
|
|
61
|
+
maxTokens?: number;
|
|
62
|
+
}
|
|
63
|
+
export interface CallLLMResult {
|
|
64
|
+
content: string;
|
|
65
|
+
model: string;
|
|
66
|
+
tier: string;
|
|
67
|
+
cost_usd: number;
|
|
68
|
+
}
|
|
69
|
+
export interface HealthCheckResult {
|
|
70
|
+
ollama: boolean;
|
|
71
|
+
gateway: boolean;
|
|
72
|
+
models: string[];
|
|
73
|
+
}
|
|
74
|
+
export interface DailyCostDigest {
|
|
75
|
+
total_usd: number;
|
|
76
|
+
by_tier: Record<string, number>;
|
|
77
|
+
by_agent: Record<string, number>;
|
|
78
|
+
tokens_saved_by_qcg: number;
|
|
79
|
+
call_count: number;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The single door every LLM call passes through (Execution Protocol §17).
|
|
83
|
+
* Implementations: Kognai's viem-backed ClawRouter v2 (injected), a future
|
|
84
|
+
* local-only default, or any product-specific router.
|
|
85
|
+
*/
|
|
86
|
+
export interface ModelRouter {
|
|
87
|
+
routeCall(req: ClawRouterV2Request): Promise<ClawRouterV2Response>;
|
|
88
|
+
callLLM(prompt: string, opts?: CallLLMOptions): Promise<CallLLMResult>;
|
|
89
|
+
healthCheck(): Promise<HealthCheckResult>;
|
|
90
|
+
getDailyCostDigest(): DailyCostDigest;
|
|
91
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* model-router-contract.ts — TICKET-215 Wave C: the engine's model-routing SEAM.
|
|
4
|
+
*
|
|
5
|
+
* This is the zero-dep interface that decouples the orchestrator from any
|
|
6
|
+
* concrete router. The orchestrator depends ONLY on this contract; the actual
|
|
7
|
+
* implementation is injected at startup (see model-router-registry.ts).
|
|
8
|
+
*
|
|
9
|
+
* WHY: ClawRouter v2 (the production router) imports `viem` for on-chain x402
|
|
10
|
+
* payments. We do NOT want `viem` in @kognai/orchestrator-core — that would make
|
|
11
|
+
* every adopter (e.g. Invoica, which never routes on-chain) carry web3. So the
|
|
12
|
+
* viem-backed router lives OUTSIDE core (Kognai injects it); products that don't
|
|
13
|
+
* route on-chain inject their own / use a local default. viem stays absent from
|
|
14
|
+
* core's dependency tree entirely.
|
|
15
|
+
*
|
|
16
|
+
* These request/response types are the canonical source of truth — clawrouter-v2
|
|
17
|
+
* imports them from here and re-exports for back-compat.
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* wallet-state.ts — CFO budget tracking for ClawRouter spend
|
|
3
|
+
*
|
|
4
|
+
* Accumulates spend from ClawRouter X-Payment-Amount headers.
|
|
5
|
+
* Enforces degraded (≥80%) and frozen (≥95%) modes to protect the wallet.
|
|
6
|
+
* Persists to logs/wallet/state.json across sprint runs.
|
|
7
|
+
*
|
|
8
|
+
* TICKET-215 Phase 3b-3 (Wave B): KOGNAI_ROOT now resolves via engine-paths
|
|
9
|
+
* (KOGNAI_ROOT / cwd) instead of `resolve(__dirname, '../..')`, so the bank
|
|
10
|
+
* state layer is location-independent and ships in @kognai/orchestrator-core.
|
|
11
|
+
* When run from a product repo root, resolveEnginePaths().root === the old
|
|
12
|
+
* __dirname/../.. — same <root>/logs/wallet/state.json, no behavior change.
|
|
13
|
+
*/
|
|
14
|
+
export interface WalletState {
|
|
15
|
+
monthlyBudget: number;
|
|
16
|
+
spentThisMonth: number;
|
|
17
|
+
callCount: number;
|
|
18
|
+
remaining: number;
|
|
19
|
+
burnPct: number;
|
|
20
|
+
isDegraded: boolean;
|
|
21
|
+
isFrozen: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function getWalletState(): WalletState;
|
|
24
|
+
export declare function recordSpend(costUsdc: number): void;
|
|
25
|
+
export declare function resetWallet(): void;
|
|
26
|
+
export declare function logWalletStatus(): void;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* wallet-state.ts — CFO budget tracking for ClawRouter spend
|
|
4
|
+
*
|
|
5
|
+
* Accumulates spend from ClawRouter X-Payment-Amount headers.
|
|
6
|
+
* Enforces degraded (≥80%) and frozen (≥95%) modes to protect the wallet.
|
|
7
|
+
* Persists to logs/wallet/state.json across sprint runs.
|
|
8
|
+
*
|
|
9
|
+
* TICKET-215 Phase 3b-3 (Wave B): KOGNAI_ROOT now resolves via engine-paths
|
|
10
|
+
* (KOGNAI_ROOT / cwd) instead of `resolve(__dirname, '../..')`, so the bank
|
|
11
|
+
* state layer is location-independent and ships in @kognai/orchestrator-core.
|
|
12
|
+
* When run from a product repo root, resolveEnginePaths().root === the old
|
|
13
|
+
* __dirname/../.. — same <root>/logs/wallet/state.json, no behavior change.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.getWalletState = getWalletState;
|
|
17
|
+
exports.recordSpend = recordSpend;
|
|
18
|
+
exports.resetWallet = resetWallet;
|
|
19
|
+
exports.logWalletStatus = logWalletStatus;
|
|
20
|
+
const fs_1 = require("fs");
|
|
21
|
+
const path_1 = require("path");
|
|
22
|
+
const engine_paths_1 = require("./engine-paths");
|
|
23
|
+
const KOGNAI_ROOT = (0, engine_paths_1.resolveEnginePaths)().root;
|
|
24
|
+
const STATE_FILE = (0, path_1.resolve)(KOGNAI_ROOT, 'logs/wallet/state.json');
|
|
25
|
+
const DEFAULT_BUDGET = parseFloat(process.env.CEO_WALLET_BUDGET_USDC || '25'); // $25/month default
|
|
26
|
+
function loadState() {
|
|
27
|
+
if ((0, fs_1.existsSync)(STATE_FILE)) {
|
|
28
|
+
try {
|
|
29
|
+
const raw = JSON.parse((0, fs_1.readFileSync)(STATE_FILE, 'utf8'));
|
|
30
|
+
// Auto-reset on new month
|
|
31
|
+
const lastReset = new Date(raw.lastReset);
|
|
32
|
+
const now = new Date();
|
|
33
|
+
if (lastReset.getMonth() !== now.getMonth() || lastReset.getFullYear() !== now.getFullYear()) {
|
|
34
|
+
return freshState();
|
|
35
|
+
}
|
|
36
|
+
return raw;
|
|
37
|
+
}
|
|
38
|
+
catch { /* fall through */ }
|
|
39
|
+
}
|
|
40
|
+
return freshState();
|
|
41
|
+
}
|
|
42
|
+
function freshState() {
|
|
43
|
+
return {
|
|
44
|
+
monthlyBudget: DEFAULT_BUDGET,
|
|
45
|
+
spentThisMonth: 0,
|
|
46
|
+
callCount: 0,
|
|
47
|
+
lastReset: new Date().toISOString(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function saveState(data) {
|
|
51
|
+
try {
|
|
52
|
+
(0, fs_1.mkdirSync)((0, path_1.resolve)(KOGNAI_ROOT, 'logs/wallet'), { recursive: true });
|
|
53
|
+
(0, fs_1.writeFileSync)(STATE_FILE, JSON.stringify(data, null, 2), 'utf8');
|
|
54
|
+
}
|
|
55
|
+
catch { /* non-fatal */ }
|
|
56
|
+
}
|
|
57
|
+
// Singleton
|
|
58
|
+
let _state = loadState();
|
|
59
|
+
function getWalletState() {
|
|
60
|
+
const remaining = Math.max(0, _state.monthlyBudget - _state.spentThisMonth);
|
|
61
|
+
const burnPct = (_state.spentThisMonth / _state.monthlyBudget) * 100;
|
|
62
|
+
return {
|
|
63
|
+
monthlyBudget: _state.monthlyBudget,
|
|
64
|
+
spentThisMonth: _state.spentThisMonth,
|
|
65
|
+
callCount: _state.callCount,
|
|
66
|
+
remaining,
|
|
67
|
+
burnPct,
|
|
68
|
+
isDegraded: burnPct >= 80,
|
|
69
|
+
isFrozen: burnPct >= 95,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function recordSpend(costUsdc) {
|
|
73
|
+
_state.spentThisMonth += costUsdc;
|
|
74
|
+
_state.callCount += 1;
|
|
75
|
+
saveState(_state);
|
|
76
|
+
}
|
|
77
|
+
function resetWallet() {
|
|
78
|
+
_state = freshState();
|
|
79
|
+
saveState(_state);
|
|
80
|
+
}
|
|
81
|
+
function logWalletStatus() {
|
|
82
|
+
const s = getWalletState();
|
|
83
|
+
const status = s.isFrozen ? '🔴 FROZEN' : s.isDegraded ? '🟡 DEGRADED' : '🟢 OK';
|
|
84
|
+
console.log(` 💳 Wallet ${status}: $${s.spentThisMonth.toFixed(4)}/$${s.monthlyBudget} (${s.burnPct.toFixed(1)}%)`);
|
|
85
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kognai/clawrouter-x402",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "ClawRouter v2 — Kognai's viem-backed x402 ModelRouter implementation. Injected into @kognai/orchestrator-core's router seam at startup, so core never depends on viem; products that don't route on-chain simply don't install this package.",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc -p tsconfig.json"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"kognai",
|
|
13
|
+
"clawrouter",
|
|
14
|
+
"x402",
|
|
15
|
+
"model-router",
|
|
16
|
+
"viem",
|
|
17
|
+
"base"
|
|
18
|
+
],
|
|
19
|
+
"license": "UNLICENSED",
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"viem": "^2.47.0"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@kognai/orchestrator-core": "*"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=18"
|
|
32
|
+
}
|
|
33
|
+
}
|