@martinloop/mcp 0.5.5 → 0.5.7
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 +14 -52
- package/dist/arcade/capabilities.d.ts +36 -0
- package/dist/arcade/capabilities.js +37 -0
- package/dist/arcade/resource.d.ts +31 -0
- package/dist/arcade/resource.js +52 -0
- package/dist/arcade/status.d.ts +23 -0
- package/dist/arcade/status.js +25 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +3 -3
- package/dist/resources.js +1 -13
- package/dist/server.js +241 -75
- package/dist/tools/execution-policy.js +1 -1
- package/dist/tools/get-status.d.ts +2 -4
- package/dist/tools/get-status.js +6 -3
- package/dist/tools/preflight.d.ts +1 -1
- package/dist/tools/run-loop.d.ts +2 -3
- package/dist/tools/run-loop.js +4 -3
- package/dist/tools/run-store.js +1 -1
- package/dist/tools/tool-support.d.ts +3 -2
- package/dist/tools/tool-support.js +9 -2
- package/dist/tools/workflow-governance.d.ts +1 -1
- package/dist/tools/workflow-governance.js +1 -1
- package/dist/vendor/adapters/claude-cli.js +2 -1
- package/dist/vendor/adapters/cli-bridge.js +7 -1
- package/dist/vendor/adapters/index.d.ts +1 -0
- package/dist/vendor/adapters/index.js +1 -0
- package/dist/vendor/adapters/openai-compatible.js +6 -3
- package/dist/vendor/adapters/stub-agent-cli.d.ts +9 -0
- package/dist/vendor/adapters/stub-agent-cli.js +43 -0
- package/dist/vendor/adapters/stub-direct-provider.d.ts +8 -0
- package/dist/vendor/adapters/stub-direct-provider.js +16 -0
- package/dist/vendor/adapters/verifier-only.js +1 -1
- package/dist/vendor/contracts/execution-policy.js +1 -1
- package/dist/vendor/contracts/exits.d.ts +1 -1
- package/dist/vendor/contracts/governance.d.ts +1 -1
- package/dist/vendor/contracts/index.d.ts +1 -1
- package/dist/vendor/contracts/index.js +1 -2
- package/dist/vendor/contracts/operator.d.ts +1 -1
- package/dist/vendor/contracts/operator.js +1 -2
- package/dist/vendor/core/compiler.d.ts +2 -2
- package/dist/vendor/core/compiler.js +3 -1
- package/dist/vendor/core/exits.js +9 -4
- package/dist/vendor/core/grounding.d.ts +1 -0
- package/dist/vendor/core/grounding.js +28 -1
- package/dist/vendor/core/index.d.ts +2 -2
- package/dist/vendor/core/index.js +11 -64
- package/dist/vendor/core/policy-compiler.js +17 -1
- package/dist/vendor/core/policy.d.ts +2 -1
- package/dist/vendor/core/policy.js +15 -5
- package/dist/vendor/core/rollback.d.ts +3 -0
- package/dist/vendor/core/rollback.js +33 -20
- package/dist/vendor/core/verified-handoff.js +25 -6
- package/dist/vendor/presentation/motion.js +0 -4
- package/dist/vendor/presentation/verified-handoff.js +10 -13
- package/dist/workflow-state.js +1 -1
- package/package.json +20 -11
- package/server.json +3 -3
package/README.md
CHANGED
|
@@ -6,31 +6,11 @@ But did it actually work? Did it pass your tests? How much did it spend? What fi
|
|
|
6
6
|
|
|
7
7
|
You don't know. And that's the problem.
|
|
8
8
|
|
|
9
|
-
## One system around the coding agent
|
|
10
|
-
|
|
11
|
-
MartinLoop is the execution-control system around coding agents. The coding agent still performs the software work. MartinLoop connects the run from Definition of Done through preflight, control, verification, recovery evidence, receipts, and post-run analysis.
|
|
12
|
-
|
|
13
|
-
```text
|
|
14
|
-
DEFINE -> PREFLIGHT -> CONTROL -> VERIFY -> RECOVER -> PROVE -> ANALYZE
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
The product-level flow is **Definition of Done -> Controlled Run -> Verified Handoff**.
|
|
18
|
-
|
|
19
|
-
Through MCP, compatible hosts can use the same MartinLoop lifecycle without giving up the host's own model selection. MartinLoop does not inject a hidden fallback model.
|
|
20
|
-
|
|
21
|
-
For agent-readable product context see [`../../llms.txt`](../../llms.txt), [`../../llms-full.txt`](../../llms-full.txt), and [`../../docs/for-agents.md`](../../docs/for-agents.md).
|
|
22
|
-
|
|
23
9
|
## What This Does
|
|
24
10
|
|
|
25
|
-
MartinLoop
|
|
26
|
-
|
|
27
|
-
When it's done, you get a receipt — not a vague summary, but a structured record: dollars spent when available, attempts made, verification results, files changed, recovery state, and what the available evidence established.
|
|
28
|
-
|
|
29
|
-
The final governed outcome is one of:
|
|
11
|
+
MartinLoop is a governed loop for AI coding agents. You tell it what to do, set a budget, and point it at your test suite. It runs the agent, checks your tests after every attempt, and stops when either the tests pass or the money runs out.
|
|
30
12
|
|
|
31
|
-
|
|
32
|
-
- `STOPPED` when a configured hard boundary ends the run
|
|
33
|
-
- `NEEDS REVIEW` when completion cannot be established from the available evidence
|
|
13
|
+
When it's done, you get a receipt — not a vague summary, but a structured record: dollars spent, attempts made, verification results, files changed, and whether you got what you asked for.
|
|
34
14
|
|
|
35
15
|
**One line to connect it:**
|
|
36
16
|
|
|
@@ -38,7 +18,7 @@ The final governed outcome is one of:
|
|
|
38
18
|
claude mcp add martin-loop -- npx -y @martinloop/mcp
|
|
39
19
|
```
|
|
40
20
|
|
|
41
|
-
That's it. Your
|
|
21
|
+
That's it. Your agent now runs governed.
|
|
42
22
|
|
|
43
23
|
## Real Numbers From Real Runs
|
|
44
24
|
|
|
@@ -57,27 +37,27 @@ These aren't hypotheticals. The $28 overshoot happened in production testing. We
|
|
|
57
37
|
|
|
58
38
|
### Claude Code
|
|
59
39
|
```sh
|
|
60
|
-
claude mcp add martin-loop -- npx -y @martinloop/mcp
|
|
40
|
+
claude mcp add martin-loop -- npx -y @martinloop/mcp
|
|
61
41
|
```
|
|
62
42
|
|
|
63
43
|
Windows:
|
|
64
44
|
```sh
|
|
65
|
-
claude mcp add --transport stdio --scope user martin-loop -- cmd /c npx -y @martinloop/mcp
|
|
45
|
+
claude mcp add --transport stdio --scope user martin-loop -- cmd /c npx -y @martinloop/mcp
|
|
66
46
|
```
|
|
67
47
|
|
|
68
48
|
### Codex
|
|
69
49
|
```sh
|
|
70
|
-
codex mcp add martin-loop -- npx -y @martinloop/mcp
|
|
50
|
+
codex mcp add martin-loop -- npx -y @martinloop/mcp
|
|
71
51
|
```
|
|
72
52
|
|
|
73
53
|
### Gemini CLI
|
|
74
54
|
```sh
|
|
75
|
-
gemini mcp add martin-loop -- npx -y @martinloop/mcp
|
|
55
|
+
gemini mcp add martin-loop -- npx -y @martinloop/mcp
|
|
76
56
|
```
|
|
77
57
|
|
|
78
58
|
### Any MCP Host
|
|
79
59
|
```sh
|
|
80
|
-
npx -y @martinloop/mcp
|
|
60
|
+
npx -y @martinloop/mcp
|
|
81
61
|
```
|
|
82
62
|
|
|
83
63
|
## How a Governed Run Works
|
|
@@ -89,16 +69,14 @@ You: "Fix the auth bug. Budget $3. Verify: npm test"
|
|
|
89
69
|
martin_plan → scopes the task, sets constraints
|
|
90
70
|
martin_preflight → validates before any spend
|
|
91
71
|
martin_run → agent works inside budget + verifier gates
|
|
92
|
-
martin_dossier → receipt:
|
|
72
|
+
martin_dossier → receipt: $1.40 spent, 2 attempts, tests pass
|
|
93
73
|
```
|
|
94
74
|
|
|
95
|
-
Every attempt
|
|
75
|
+
Every attempt runs your verifier. Every dollar is tracked. If the agent drifts off-task, the scope contract catches it. If it blows the budget, the circuit breaker kills the subprocess mid-stream — not after the bill arrives.
|
|
96
76
|
|
|
97
77
|
## What Your Agent Gets
|
|
98
78
|
|
|
99
|
-
###
|
|
100
|
-
|
|
101
|
-
The exact tool set is discoverable from the running MCP server with `tools/list`; do not rely on a hard-coded count in documentation.
|
|
79
|
+
### 21 Tools
|
|
102
80
|
|
|
103
81
|
**Run the loop:**
|
|
104
82
|
`martin_doctor` `martin_plan` `martin_preflight` `martin_run` `martin_pause` `martin_continue` `martin_cancel`
|
|
@@ -109,9 +87,7 @@ The exact tool set is discoverable from the running MCP server with `tools/list`
|
|
|
109
87
|
**Ship the work:**
|
|
110
88
|
`martin_pr_summary` `martin_create_pr` `martin_review_pr`
|
|
111
89
|
|
|
112
|
-
### Read-Only Resources
|
|
113
|
-
|
|
114
|
-
The exact resource set is discoverable from the running MCP server; this documentation names the primary public resources without treating a count as a release invariant.
|
|
90
|
+
### 11 Read-Only Resources
|
|
115
91
|
|
|
116
92
|
Your agent can pull context without side effects:
|
|
117
93
|
|
|
@@ -130,33 +106,20 @@ npx martin-loop mcp print-config --host claude --profile github-review # + PR w
|
|
|
130
106
|
|
|
131
107
|
## What Happens When Things Go Wrong
|
|
132
108
|
|
|
133
|
-
MartinLoop
|
|
109
|
+
MartinLoop doesn't just report failures — it tries to fix them:
|
|
134
110
|
|
|
135
111
|
| Failure | Old behavior | Now |
|
|
136
112
|
|---|---|---|
|
|
137
113
|
| CLI not on PATH | Error message, dead stop | Searches npm global, homebrew, nvm, scoop — uses what it finds |
|
|
138
|
-
| Verifier says "command not found" | Generic "verification failed" |
|
|
114
|
+
| Verifier says "command not found" | Generic "verification failed" | Tells the next attempt: "bun is missing, install with `npm i -g bun`" |
|
|
139
115
|
| `git restore` fails mid-rollback | Throws, leaves dirty state | Retries once, falls back to `git checkout`, cleans up |
|
|
140
116
|
| Invalid `--profile` flag | Crashes | Warns, falls back to `minimal`, keeps running |
|
|
141
117
|
|
|
142
|
-
## Codex compatibility in 0.5.5
|
|
143
|
-
|
|
144
|
-
MartinLoop no longer assumes one Codex host or one fixed Codex flag set. The CLI resolves the exact Codex executable, reads its advertised capabilities, negotiates a supported write strategy, proves that strategy before reporting launch readiness, and reuses the same contract for the governed run.
|
|
145
|
-
|
|
146
|
-
That means MCP hosts can point MartinLoop at different Codex installations without requiring a documentation-specific approval or sandbox flag to exist everywhere.
|
|
147
|
-
|
|
148
|
-
## Presentation and evidence
|
|
149
|
-
|
|
150
|
-
MCP responses are Markdown-first for humans while retaining structured content for agents and automation. The presentation layer does not rewrite governed truth.
|
|
151
|
-
|
|
152
|
-
MartinLoop Arcade is a terminal-only experience. It does not run inside MCP and cannot influence MCP evidence, budgets, verification, or final outcomes.
|
|
153
|
-
|
|
154
118
|
## Who Uses This
|
|
155
119
|
|
|
156
120
|
- **Engineers running overnight agent loops** — you need a kill switch that actually works, and a receipt in the morning
|
|
157
121
|
- **Teams with shared API budgets** — you need per-task spend caps, not org-wide prayer
|
|
158
122
|
- **Anyone reviewing agent-generated PRs** — the dossier shows what the agent tried, what passed, and what didn't
|
|
159
|
-
- **Teams tired of stitching together point tools** — you want one execution-control lifecycle around coding-agent work from preflight through post-run analysis
|
|
160
123
|
|
|
161
124
|
## Requirements
|
|
162
125
|
|
|
@@ -166,7 +129,6 @@ MartinLoop Arcade is a terminal-only experience. It does not run inside MCP and
|
|
|
166
129
|
## Links
|
|
167
130
|
|
|
168
131
|
- [martin-loop](https://www.npmjs.com/package/martin-loop) — the standalone CLI
|
|
169
|
-
- [MartinLoop for AI Agents](../../docs/for-agents.md)
|
|
170
132
|
- [GitHub](https://github.com/Keesan12/martin-loop) — source and issues
|
|
171
133
|
- [martinloop.com](https://martinloop.com)
|
|
172
134
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare const MARTIN_ARCADE_UI_EXTENSION_ID = "io.modelcontextprotocol/ui";
|
|
2
|
+
export declare const MARTIN_ARCADE_MIME_TYPE = "text/html;profile=mcp-app";
|
|
3
|
+
export declare const MARTIN_ARCADE_RESOURCE_URI = "ui://martinloop/arcade/index.html";
|
|
4
|
+
export declare const MARTIN_ARCADE_FALLBACK_TEXT = "MartinLoop Arcade is available in an interactive terminal with --arcade.";
|
|
5
|
+
export declare function supportsMartinArcadeApp(capabilities: unknown): boolean;
|
|
6
|
+
export declare function buildArcadeToolDefinitions(capabilities: unknown): readonly [{
|
|
7
|
+
readonly _meta?: {
|
|
8
|
+
ui: {
|
|
9
|
+
resourceUri: string;
|
|
10
|
+
};
|
|
11
|
+
} | undefined;
|
|
12
|
+
readonly name: "martin_arcade";
|
|
13
|
+
readonly description: "Open the presentation-only MartinLoop Arcade when the host supports MCP Apps. The Arcade cannot change governed execution or evidence.";
|
|
14
|
+
readonly inputSchema: {
|
|
15
|
+
readonly type: "object";
|
|
16
|
+
readonly additionalProperties: false;
|
|
17
|
+
readonly properties: {};
|
|
18
|
+
};
|
|
19
|
+
}, {
|
|
20
|
+
readonly name: "martin_arcade_status";
|
|
21
|
+
readonly description: "Read authoritative MartinLoop evidence for the Arcade view without changing run state.";
|
|
22
|
+
readonly inputSchema: {
|
|
23
|
+
readonly type: "object";
|
|
24
|
+
readonly additionalProperties: false;
|
|
25
|
+
readonly properties: {
|
|
26
|
+
readonly loopId: {
|
|
27
|
+
readonly type: "string";
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
readonly _meta: {
|
|
32
|
+
readonly ui: {
|
|
33
|
+
readonly visibility: readonly ["app"];
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
}];
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const MARTIN_ARCADE_UI_EXTENSION_ID = "io.modelcontextprotocol/ui";
|
|
2
|
+
export const MARTIN_ARCADE_MIME_TYPE = "text/html;profile=mcp-app";
|
|
3
|
+
export const MARTIN_ARCADE_RESOURCE_URI = "ui://martinloop/arcade/index.html";
|
|
4
|
+
export const MARTIN_ARCADE_FALLBACK_TEXT = "MartinLoop Arcade is available in an interactive terminal with --arcade.";
|
|
5
|
+
export function supportsMartinArcadeApp(capabilities) {
|
|
6
|
+
if (!capabilities || typeof capabilities !== "object")
|
|
7
|
+
return false;
|
|
8
|
+
const extension = capabilities.extensions?.[MARTIN_ARCADE_UI_EXTENSION_ID];
|
|
9
|
+
return Array.isArray(extension?.mimeTypes) && extension.mimeTypes.includes(MARTIN_ARCADE_MIME_TYPE);
|
|
10
|
+
}
|
|
11
|
+
export function buildArcadeToolDefinitions(capabilities) {
|
|
12
|
+
const arcadeMeta = supportsMartinArcadeApp(capabilities)
|
|
13
|
+
? { ui: { resourceUri: MARTIN_ARCADE_RESOURCE_URI } }
|
|
14
|
+
: undefined;
|
|
15
|
+
return [
|
|
16
|
+
{
|
|
17
|
+
name: "martin_arcade",
|
|
18
|
+
description: "Open the presentation-only MartinLoop Arcade when the host supports MCP Apps. The Arcade cannot change governed execution or evidence.",
|
|
19
|
+
inputSchema: {
|
|
20
|
+
type: "object",
|
|
21
|
+
additionalProperties: false,
|
|
22
|
+
properties: {}
|
|
23
|
+
},
|
|
24
|
+
...(arcadeMeta ? { _meta: arcadeMeta } : {})
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "martin_arcade_status",
|
|
28
|
+
description: "Read authoritative MartinLoop evidence for the Arcade view without changing run state.",
|
|
29
|
+
inputSchema: {
|
|
30
|
+
type: "object",
|
|
31
|
+
additionalProperties: false,
|
|
32
|
+
properties: { loopId: { type: "string" } }
|
|
33
|
+
},
|
|
34
|
+
_meta: { ui: { visibility: ["app"] } }
|
|
35
|
+
}
|
|
36
|
+
];
|
|
37
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export declare function listArcadeResources(capabilities: unknown): {
|
|
2
|
+
resources: {
|
|
3
|
+
uri: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
mimeType: string;
|
|
7
|
+
_meta: {
|
|
8
|
+
ui: {
|
|
9
|
+
csp: {
|
|
10
|
+
connectDomains: never[];
|
|
11
|
+
resourceDomains: never[];
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
}[];
|
|
16
|
+
};
|
|
17
|
+
export declare function readArcadeResource(uri: string): Promise<{
|
|
18
|
+
contents: {
|
|
19
|
+
uri: string;
|
|
20
|
+
mimeType: string;
|
|
21
|
+
text: string;
|
|
22
|
+
_meta: {
|
|
23
|
+
ui: {
|
|
24
|
+
csp: {
|
|
25
|
+
connectDomains: never[];
|
|
26
|
+
resourceDomains: never[];
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
}[];
|
|
31
|
+
}>;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { MARTIN_ARCADE_MIME_TYPE, MARTIN_ARCADE_RESOURCE_URI, supportsMartinArcadeApp } from "./capabilities.js";
|
|
2
|
+
const ARCADE_APP_HTML = `<!doctype html>
|
|
3
|
+
<html lang="en" data-martin-arcade-app>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
7
|
+
<title>MartinLoop Arcade</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root { color-scheme: light dark; font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }
|
|
10
|
+
body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: Canvas; color: CanvasText; }
|
|
11
|
+
main { width: min(42rem, calc(100% - 2rem)); border: 1px solid currentColor; padding: 1.25rem; }
|
|
12
|
+
p { line-height: 1.5; }
|
|
13
|
+
</style>
|
|
14
|
+
</head>
|
|
15
|
+
<body>
|
|
16
|
+
<main aria-labelledby="arcade-title">
|
|
17
|
+
<h1 id="arcade-title">MartinLoop Arcade</h1>
|
|
18
|
+
<p>Presentation only. Governed run status and outcomes remain authoritative in MartinLoop.</p>
|
|
19
|
+
<p aria-live="polite" data-run-status>Waiting for authoritative run evidence.</p>
|
|
20
|
+
</main>
|
|
21
|
+
</body>
|
|
22
|
+
</html>`;
|
|
23
|
+
export function listArcadeResources(capabilities) {
|
|
24
|
+
return {
|
|
25
|
+
resources: supportsMartinArcadeApp(capabilities)
|
|
26
|
+
? [
|
|
27
|
+
{
|
|
28
|
+
uri: MARTIN_ARCADE_RESOURCE_URI,
|
|
29
|
+
name: "MartinLoop Arcade",
|
|
30
|
+
description: "Presentation-only Arcade view for a governed MartinLoop run.",
|
|
31
|
+
mimeType: MARTIN_ARCADE_MIME_TYPE,
|
|
32
|
+
_meta: { ui: { csp: { connectDomains: [], resourceDomains: [] } } }
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
: []
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export async function readArcadeResource(uri) {
|
|
39
|
+
if (uri !== MARTIN_ARCADE_RESOURCE_URI) {
|
|
40
|
+
throw new Error(`Unknown Arcade resource: ${uri}`);
|
|
41
|
+
}
|
|
42
|
+
return {
|
|
43
|
+
contents: [
|
|
44
|
+
{
|
|
45
|
+
uri: MARTIN_ARCADE_RESOURCE_URI,
|
|
46
|
+
mimeType: MARTIN_ARCADE_MIME_TYPE,
|
|
47
|
+
text: ARCADE_APP_HTML,
|
|
48
|
+
_meta: { ui: { csp: { connectDomains: [], resourceDomains: [] } } }
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type MartinRunDossierInput, type MartinRunDossierOutput } from "../tools/run-dossier.js";
|
|
2
|
+
export interface ArcadeStatusInput {
|
|
3
|
+
loopId?: string;
|
|
4
|
+
}
|
|
5
|
+
export type ArcadeDossierReader = (input: MartinRunDossierInput) => Promise<MartinRunDossierOutput>;
|
|
6
|
+
export declare function readArcadeStatus(input: ArcadeStatusInput, readDossier?: ArcadeDossierReader): Promise<{
|
|
7
|
+
loopId: string;
|
|
8
|
+
lifecycleState: string;
|
|
9
|
+
completed: boolean;
|
|
10
|
+
displayOutcome: "NEEDS_REVIEW" | "VERIFIED" | "STOPPED" | null;
|
|
11
|
+
verification: import("../tools/tool-support.js").VerificationSummary;
|
|
12
|
+
receiptIntegrity: import("../vendor/contracts/index.js").ReceiptIntegritySummary;
|
|
13
|
+
attempts: number;
|
|
14
|
+
cost: {
|
|
15
|
+
actualUsd: number;
|
|
16
|
+
provenance: import("../vendor/contracts/index.js").CostProvenance | undefined;
|
|
17
|
+
};
|
|
18
|
+
budget: {
|
|
19
|
+
maxUsd: number;
|
|
20
|
+
remainingUsd: number;
|
|
21
|
+
};
|
|
22
|
+
warnings: string[];
|
|
23
|
+
}>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { martinRunDossierTool } from "../tools/run-dossier.js";
|
|
2
|
+
const ACTIVE_LIFECYCLES = new Set(["created", "running", "verifying"]);
|
|
3
|
+
export async function readArcadeStatus(input, readDossier = martinRunDossierTool) {
|
|
4
|
+
const dossier = await readDossier(input.loopId ? { loopId: input.loopId } : { latest: true });
|
|
5
|
+
const lifecycleState = dossier.loop.lifecycleState;
|
|
6
|
+
const completed = !ACTIVE_LIFECYCLES.has(lifecycleState);
|
|
7
|
+
return {
|
|
8
|
+
loopId: dossier.loop.loopId,
|
|
9
|
+
lifecycleState,
|
|
10
|
+
completed,
|
|
11
|
+
displayOutcome: completed ? dossier.verifiedHandoff.outcome : null,
|
|
12
|
+
verification: dossier.verification,
|
|
13
|
+
receiptIntegrity: dossier.receiptIntegrity,
|
|
14
|
+
attempts: dossier.attempts.length,
|
|
15
|
+
cost: {
|
|
16
|
+
actualUsd: dossier.cost.actualUsd,
|
|
17
|
+
provenance: dossier.cost.provenance
|
|
18
|
+
},
|
|
19
|
+
budget: {
|
|
20
|
+
maxUsd: dossier.budget.maxUsd,
|
|
21
|
+
remainingUsd: dossier.loop.remainingBudgetUsd
|
|
22
|
+
},
|
|
23
|
+
warnings: dossier.warnings
|
|
24
|
+
};
|
|
25
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MARTIN_MCP_PACKAGE_VERSION = "0.
|
|
1
|
+
export declare const MARTIN_MCP_PACKAGE_VERSION = "0.5.7";
|
package/dist/package-version.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
export const MARTIN_MCP_PACKAGE_VERSION = "0.
|
|
1
|
+
// Auto-generated by build — do not edit by hand.
|
|
2
|
+
// Source of truth: packages/mcp/package.json#version
|
|
3
|
+
export const MARTIN_MCP_PACKAGE_VERSION = "0.5.7";
|
package/dist/resources.js
CHANGED
|
@@ -37,16 +37,6 @@ export const MARTIN_STATIC_RESOURCE_URIS = {
|
|
|
37
37
|
modeStatus: "martin://agent/mode-status",
|
|
38
38
|
memorySummary: "martin://agent/memory-summary"
|
|
39
39
|
};
|
|
40
|
-
function formatRecordedCost(usd, provenance) {
|
|
41
|
-
if (provenance === "unavailable")
|
|
42
|
-
return "unavailable";
|
|
43
|
-
if (provenance === "actual")
|
|
44
|
-
return `$${usd.toFixed(2)} provider-settled actual`;
|
|
45
|
-
if (provenance === "calculated") {
|
|
46
|
-
return `$${usd.toFixed(2)} calculated from observed usage`;
|
|
47
|
-
}
|
|
48
|
-
return `$${usd.toFixed(2)} estimated`;
|
|
49
|
-
}
|
|
50
40
|
export const MARTIN_RESOURCE_TEMPLATES = [
|
|
51
41
|
{
|
|
52
42
|
name: "martin_run_record",
|
|
@@ -414,7 +404,6 @@ async function buildLatestSummaryResource(runsRoot) {
|
|
|
414
404
|
budget: loop.budget,
|
|
415
405
|
cost: {
|
|
416
406
|
actualUsd: loop.cost.actualUsd,
|
|
417
|
-
provenance: loop.cost.provenance ?? "unavailable",
|
|
418
407
|
avoidedUsdEstimate: loop.cost.avoidedUsd ?? 0,
|
|
419
408
|
tokensIn: loop.cost.tokensIn,
|
|
420
409
|
tokensOut: loop.cost.tokensOut,
|
|
@@ -450,7 +439,6 @@ async function buildLatestBudgetStatusResource(runsRoot) {
|
|
|
450
439
|
budget: loop.budget,
|
|
451
440
|
cost: {
|
|
452
441
|
actualUsd: loop.cost.actualUsd,
|
|
453
|
-
provenance: loop.cost.provenance ?? "unavailable",
|
|
454
442
|
avoidedUsdEstimate: loop.cost.avoidedUsd ?? 0,
|
|
455
443
|
tokensIn: loop.cost.tokensIn,
|
|
456
444
|
tokensOut: loop.cost.tokensOut,
|
|
@@ -587,7 +575,7 @@ async function buildLatestProofCardResource(runsRoot) {
|
|
|
587
575
|
`Run: \`${loop.loopId}\``,
|
|
588
576
|
`Status: ${loop.status} / ${loop.lifecycleState}`,
|
|
589
577
|
`Attempts: ${loop.attempts.length}`,
|
|
590
|
-
`Spend:
|
|
578
|
+
`Spend: $${loop.cost.actualUsd.toFixed(2)} actual, $${(loop.cost.avoidedUsd ?? 0).toFixed(2)} avoided estimate`,
|
|
591
579
|
`Tokens: ${loop.cost.tokensIn} in / ${loop.cost.tokensOut} out`,
|
|
592
580
|
`Verifier: ${verifierStatus}`,
|
|
593
581
|
"",
|