@mousedev/harness-core 0.1.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.
Files changed (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -0
  3. package/dist/detect.d.ts +45 -0
  4. package/dist/detect.d.ts.map +1 -0
  5. package/dist/detect.js +170 -0
  6. package/dist/detect.js.map +1 -0
  7. package/dist/engine.d.ts +33 -0
  8. package/dist/engine.d.ts.map +1 -0
  9. package/dist/engine.js +2 -0
  10. package/dist/engine.js.map +1 -0
  11. package/dist/events.d.ts +13 -0
  12. package/dist/events.d.ts.map +1 -0
  13. package/dist/events.js +2 -0
  14. package/dist/events.js.map +1 -0
  15. package/dist/exec.d.ts +9 -0
  16. package/dist/exec.d.ts.map +1 -0
  17. package/dist/exec.js +54 -0
  18. package/dist/exec.js.map +1 -0
  19. package/dist/failures.d.ts +10 -0
  20. package/dist/failures.d.ts.map +1 -0
  21. package/dist/failures.js +52 -0
  22. package/dist/failures.js.map +1 -0
  23. package/dist/git.d.ts +14 -0
  24. package/dist/git.d.ts.map +1 -0
  25. package/dist/git.js +47 -0
  26. package/dist/git.js.map +1 -0
  27. package/dist/index.d.ts +16 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +16 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/loop.d.ts +119 -0
  32. package/dist/loop.d.ts.map +1 -0
  33. package/dist/loop.js +190 -0
  34. package/dist/loop.js.map +1 -0
  35. package/dist/mea.d.ts +80 -0
  36. package/dist/mea.d.ts.map +1 -0
  37. package/dist/mea.js +156 -0
  38. package/dist/mea.js.map +1 -0
  39. package/dist/paths.d.ts +7 -0
  40. package/dist/paths.d.ts.map +1 -0
  41. package/dist/paths.js +27 -0
  42. package/dist/paths.js.map +1 -0
  43. package/dist/policy.d.ts +74 -0
  44. package/dist/policy.d.ts.map +1 -0
  45. package/dist/policy.js +179 -0
  46. package/dist/policy.js.map +1 -0
  47. package/dist/probe.d.ts +21 -0
  48. package/dist/probe.d.ts.map +1 -0
  49. package/dist/probe.js +55 -0
  50. package/dist/probe.js.map +1 -0
  51. package/dist/prompt.d.ts +33 -0
  52. package/dist/prompt.d.ts.map +1 -0
  53. package/dist/prompt.js +48 -0
  54. package/dist/prompt.js.map +1 -0
  55. package/dist/trace.d.ts +57 -0
  56. package/dist/trace.d.ts.map +1 -0
  57. package/dist/trace.js +35 -0
  58. package/dist/trace.js.map +1 -0
  59. package/dist/version.d.ts +3 -0
  60. package/dist/version.d.ts.map +1 -0
  61. package/dist/version.js +3 -0
  62. package/dist/version.js.map +1 -0
  63. package/dist/workspace.d.ts +26 -0
  64. package/dist/workspace.d.ts.map +1 -0
  65. package/dist/workspace.js +8 -0
  66. package/dist/workspace.js.map +1 -0
  67. package/package.json +39 -0
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `.mouse/policy.json`: the only thing Mouse reads from a repo.
3
+ *
4
+ * Hand-rolled parsing with defaults, no schema library, so `core` stays
5
+ * dependency-free. Unknown keys are preserved on `extra` and ignored, which
6
+ * keeps the file forward-compatible with hosts that add blocks of their own.
7
+ */
8
+ import type { DetectedCheck } from "./detect.js";
9
+ import type { Workspace } from "./workspace.js";
10
+ export type PermissionAction = "allow" | "ask" | "deny";
11
+ /** Either a single action for every call, or a pattern -> action map. */
12
+ export type PermissionToolEntry = PermissionAction | Record<string, PermissionAction>;
13
+ export interface PermissionsPolicy {
14
+ bash?: PermissionToolEntry;
15
+ write?: PermissionToolEntry;
16
+ edit?: PermissionToolEntry;
17
+ doom_loop?: PermissionAction;
18
+ }
19
+ export interface VerifyPolicy {
20
+ /** Explicit checks; `null` means detect them from the repo's manifests. */
21
+ checks: DetectedCheck[] | null;
22
+ /** Per-check wall clock. */
23
+ timeoutSec: number;
24
+ }
25
+ export interface LoopPolicy {
26
+ maxWallSec: number;
27
+ maxSteps: number;
28
+ nonProgressRounds: number;
29
+ idleTimeoutSec: number;
30
+ minRoundSec: number;
31
+ }
32
+ export interface PrunePolicy {
33
+ enabled: boolean;
34
+ thresholdChars: number;
35
+ headChars: number;
36
+ tailChars: number;
37
+ }
38
+ export interface Policy {
39
+ version: 1;
40
+ verify: VerifyPolicy;
41
+ loop: LoopPolicy;
42
+ context: {
43
+ prune: PrunePolicy;
44
+ };
45
+ permissions: PermissionsPolicy;
46
+ /** Top-level keys this version does not know, kept verbatim. */
47
+ extra: Record<string, unknown>;
48
+ }
49
+ export declare const DEFAULT_POLICY: Policy;
50
+ /**
51
+ * `verify.checks` accepts the array form `[{name, command}]` and the object
52
+ * form `{ "test": "pnpm test" }` from `.mouse/app.json`.
53
+ */
54
+ export declare function parseChecks(v: unknown): DetectedCheck[] | null;
55
+ export declare function parsePermissions(v: unknown): PermissionsPolicy;
56
+ /** Parse a policy document leniently: every block optional, every field defaulted. */
57
+ export declare function parsePolicy(raw: unknown): Policy;
58
+ /**
59
+ * Decode a single tool entry into an ordered list of `[pattern, action]`
60
+ * tuples. A single-action entry is normalized to `[["*", action]]`. Callers
61
+ * walk the list in order: first match wins. Object iteration order matches
62
+ * JSON declaration order, which is the contract users sign up for when they
63
+ * hand-edit policy.json.
64
+ */
65
+ export declare function permissionRulesForTool(entry: PermissionToolEntry | undefined): Array<[pattern: string, action: PermissionAction]>;
66
+ /** Read one file out of the workspace, or null when it is missing or unreadable. */
67
+ export declare function readWorkspaceFile(ws: Workspace, relPath: string): Promise<string | null>;
68
+ /**
69
+ * Load `.mouse/policy.json`. When it has no `verify` block, `.mouse/app.json`'s
70
+ * `verify.checks` is read as an alias so repos written for the hosted product
71
+ * keep their declared checks.
72
+ */
73
+ export declare function loadPolicy(ws: Workspace): Promise<Policy>;
74
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AACxD,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAC/B,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACrB,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE;QAAE,KAAK,EAAE,WAAW,CAAA;KAAE,CAAC;IAChC,WAAW,EAAE,iBAAiB,CAAC;IAC/B,gEAAgE;IAChE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,eAAO,MAAM,cAAc,EAAE,MAa5B,CAAC;AAiBF;;;GAGG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,aAAa,EAAE,GAAG,IAAI,CAkB9D;AAcD,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAY9D;AAED,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAgChD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,mBAAmB,GAAG,SAAS,GACrC,KAAK,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAIpD;AAED,oFAAoF;AACpF,wBAAsB,iBAAiB,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAa9F;AAWD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,EAAE,EAAE,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAa/D"}
package/dist/policy.js ADDED
@@ -0,0 +1,179 @@
1
+ import { shellPath } from "./workspace.js";
2
+ export const DEFAULT_POLICY = {
3
+ version: 1,
4
+ verify: { checks: null, timeoutSec: 900 },
5
+ loop: {
6
+ maxWallSec: 780,
7
+ maxSteps: 600,
8
+ nonProgressRounds: 3,
9
+ idleTimeoutSec: 600,
10
+ minRoundSec: 60,
11
+ },
12
+ context: { prune: { enabled: false, thresholdChars: 8192, headChars: 4096, tailChars: 1024 } },
13
+ permissions: {},
14
+ extra: {},
15
+ };
16
+ const KNOWN_KEYS = new Set(["version", "verify", "loop", "context", "permissions"]);
17
+ const ACTIONS = new Set(["allow", "ask", "deny"]);
18
+ function obj(v) {
19
+ return v && typeof v === "object" && !Array.isArray(v) ? v : null;
20
+ }
21
+ function int(v, fallback, min = 1, max = Number.MAX_SAFE_INTEGER) {
22
+ return typeof v === "number" && Number.isInteger(v) && v >= min && v <= max ? v : fallback;
23
+ }
24
+ function bool(v, fallback) {
25
+ return typeof v === "boolean" ? v : fallback;
26
+ }
27
+ /**
28
+ * `verify.checks` accepts the array form `[{name, command}]` and the object
29
+ * form `{ "test": "pnpm test" }` from `.mouse/app.json`.
30
+ */
31
+ export function parseChecks(v) {
32
+ if (Array.isArray(v)) {
33
+ const out = [];
34
+ for (const item of v) {
35
+ const o = obj(item);
36
+ if (o && typeof o.name === "string" && typeof o.command === "string" && o.command.trim()) {
37
+ out.push({ name: o.name, command: o.command });
38
+ }
39
+ }
40
+ return out;
41
+ }
42
+ const o = obj(v);
43
+ if (!o)
44
+ return null;
45
+ const out = [];
46
+ for (const [name, command] of Object.entries(o)) {
47
+ if (typeof command === "string" && command.trim())
48
+ out.push({ name, command });
49
+ }
50
+ return out;
51
+ }
52
+ function parseToolEntry(v) {
53
+ if (typeof v === "string")
54
+ return ACTIONS.has(v) ? v : undefined;
55
+ const o = obj(v);
56
+ if (!o)
57
+ return undefined;
58
+ const out = {};
59
+ for (const [pattern, action] of Object.entries(o)) {
60
+ if (typeof action === "string" && ACTIONS.has(action))
61
+ out[pattern] = action;
62
+ }
63
+ return out;
64
+ }
65
+ export function parsePermissions(v) {
66
+ const o = obj(v);
67
+ if (!o)
68
+ return {};
69
+ const out = {};
70
+ for (const tool of ["bash", "write", "edit"]) {
71
+ const entry = parseToolEntry(o[tool]);
72
+ if (entry !== undefined)
73
+ out[tool] = entry;
74
+ }
75
+ if (typeof o.doom_loop === "string" && ACTIONS.has(o.doom_loop)) {
76
+ out.doom_loop = o.doom_loop;
77
+ }
78
+ return out;
79
+ }
80
+ /** Parse a policy document leniently: every block optional, every field defaulted. */
81
+ export function parsePolicy(raw) {
82
+ const o = obj(raw) ?? {};
83
+ const d = DEFAULT_POLICY;
84
+ const verify = obj(o.verify) ?? {};
85
+ const loop = obj(o.loop) ?? {};
86
+ const prune = obj(obj(o.context)?.prune) ?? {};
87
+ const extra = {};
88
+ for (const [k, v] of Object.entries(o))
89
+ if (!KNOWN_KEYS.has(k))
90
+ extra[k] = v;
91
+ return {
92
+ version: 1,
93
+ verify: {
94
+ checks: "checks" in verify ? parseChecks(verify.checks) : d.verify.checks,
95
+ timeoutSec: int(verify.timeoutSec, d.verify.timeoutSec, 1, 86_400),
96
+ },
97
+ loop: {
98
+ maxWallSec: int(loop.maxWallSec, d.loop.maxWallSec),
99
+ maxSteps: int(loop.maxSteps, d.loop.maxSteps),
100
+ nonProgressRounds: int(loop.nonProgressRounds, d.loop.nonProgressRounds),
101
+ idleTimeoutSec: int(loop.idleTimeoutSec, d.loop.idleTimeoutSec),
102
+ minRoundSec: int(loop.minRoundSec, d.loop.minRoundSec, 0),
103
+ },
104
+ context: {
105
+ prune: {
106
+ enabled: bool(prune.enabled, d.context.prune.enabled),
107
+ thresholdChars: int(prune.thresholdChars, d.context.prune.thresholdChars),
108
+ headChars: int(prune.headChars, d.context.prune.headChars, 0),
109
+ tailChars: int(prune.tailChars, d.context.prune.tailChars, 0),
110
+ },
111
+ },
112
+ permissions: parsePermissions(o.permissions),
113
+ extra,
114
+ };
115
+ }
116
+ /**
117
+ * Decode a single tool entry into an ordered list of `[pattern, action]`
118
+ * tuples. A single-action entry is normalized to `[["*", action]]`. Callers
119
+ * walk the list in order: first match wins. Object iteration order matches
120
+ * JSON declaration order, which is the contract users sign up for when they
121
+ * hand-edit policy.json.
122
+ */
123
+ export function permissionRulesForTool(entry) {
124
+ if (!entry)
125
+ return [];
126
+ if (typeof entry === "string")
127
+ return [["*", entry]];
128
+ return Object.entries(entry);
129
+ }
130
+ /** Read one file out of the workspace, or null when it is missing or unreadable. */
131
+ export async function readWorkspaceFile(ws, relPath) {
132
+ if (relPath.includes("..") || relPath.startsWith("/"))
133
+ return null;
134
+ const abs = `${ws.root.replace(/\/+$/, "")}/${relPath}`;
135
+ try {
136
+ const res = await ws.exec(`test -f ${shellPath(abs)} && cat ${shellPath(abs)} || true`, {
137
+ cwd: ws.root,
138
+ timeoutMs: 5000,
139
+ });
140
+ if (res.code !== 0)
141
+ return null;
142
+ return res.stdout || null;
143
+ }
144
+ catch {
145
+ return null;
146
+ }
147
+ }
148
+ function parseJson(raw) {
149
+ if (!raw?.trim())
150
+ return null;
151
+ try {
152
+ return obj(JSON.parse(raw));
153
+ }
154
+ catch {
155
+ return null;
156
+ }
157
+ }
158
+ /**
159
+ * Load `.mouse/policy.json`. When it has no `verify` block, `.mouse/app.json`'s
160
+ * `verify.checks` is read as an alias so repos written for the hosted product
161
+ * keep their declared checks.
162
+ */
163
+ export async function loadPolicy(ws) {
164
+ const raw = parseJson(await readWorkspaceFile(ws, ".mouse/policy.json")) ?? {};
165
+ if (!obj(raw.verify)) {
166
+ const app = parseJson(await readWorkspaceFile(ws, ".mouse/app.json"));
167
+ const verify = obj(app?.verify);
168
+ if (verify) {
169
+ const alias = {};
170
+ if ("checks" in verify)
171
+ alias.checks = verify.checks;
172
+ if (typeof verify.timeoutSec === "number")
173
+ alias.timeoutSec = verify.timeoutSec;
174
+ raw.verify = alias;
175
+ }
176
+ }
177
+ return parsePolicy(raw);
178
+ }
179
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Workspace probe for a checkout. Prefers git for the fingerprint and tamper
3
+ * scan; a directory that is not a repo falls back to "files newer than the
4
+ * marker written before the first turn".
5
+ */
6
+ import { type DetectedCheck } from "./detect.js";
7
+ import { type CompletionProbe } from "./loop.js";
8
+ import { type Workspace } from "./workspace.js";
9
+ export interface ProbeOptions {
10
+ workspace: Workspace;
11
+ /** HEAD before the first turn; `null` when the directory is not a repo. */
12
+ runStartSha: string | null;
13
+ /** A file touched before the first turn, for the non-git fallback. */
14
+ marker: string;
15
+ signal: AbortSignal;
16
+ /** Declared checks; `null` or `undefined` detects them from the manifests. */
17
+ checks?: DetectedCheck[] | null;
18
+ checkTimeoutMs?: number;
19
+ }
20
+ export declare function makeProbe(o: ProbeOptions): CompletionProbe;
21
+ //# sourceMappingURL=probe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.d.ts","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAuB,KAAK,aAAa,EAAmB,MAAM,aAAa,CAAC;AAGvF,OAAO,EAAoB,KAAK,eAAe,EAAqB,MAAM,WAAW,CAAC;AACtF,OAAO,EAAa,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3D,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,SAAS,CAAC;IACrB,2EAA2E;IAC3E,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;IACpB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAOD,wBAAgB,SAAS,CAAC,CAAC,EAAE,YAAY,GAAG,eAAe,CAuC1D"}
package/dist/probe.js ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Workspace probe for a checkout. Prefers git for the fingerprint and tamper
3
+ * scan; a directory that is not a repo falls back to "files newer than the
4
+ * marker written before the first turn".
5
+ */
6
+ import { checksFromEcosystem, detectEcosystem } from "./detect.js";
7
+ import { LOCAL_EXEC_TIMEOUT_CODE } from "./exec.js";
8
+ import { deletedVerificationFiles, fingerprint as gitFingerprint } from "./git.js";
9
+ import { EXCERPT_MAX_CHARS } from "./loop.js";
10
+ import { shellPath } from "./workspace.js";
11
+ const DEFAULT_CHECK_TIMEOUT_MS = 900_000;
12
+ /** Ceiling on the non-git fallback listing; a larger tree still fingerprints, just coarsely. */
13
+ const FALLBACK_LIST_MAX = 2_000;
14
+ const FALLBACK_LIST_TIMEOUT_MS = 20_000;
15
+ export function makeProbe(o) {
16
+ const ws = o.workspace;
17
+ const timeoutMs = o.checkTimeoutMs ?? DEFAULT_CHECK_TIMEOUT_MS;
18
+ let checksCache = o.checks ?? null;
19
+ async function detected() {
20
+ if (checksCache)
21
+ return checksCache;
22
+ checksCache = checksFromEcosystem(await detectEcosystem(ws));
23
+ return checksCache;
24
+ }
25
+ return {
26
+ async checks() {
27
+ const out = [];
28
+ for (const check of await detected()) {
29
+ if (o.signal.aborted)
30
+ break;
31
+ const res = await ws
32
+ .exec(check.command, { cwd: ws.root, timeoutMs, signal: o.signal })
33
+ .catch((e) => ({ stdout: "", stderr: String(e), code: 1 }));
34
+ out.push({
35
+ ...check,
36
+ pass: res.code === 0,
37
+ exitCode: res.code === LOCAL_EXEC_TIMEOUT_CODE ? null : res.code,
38
+ excerpt: `${res.stdout}\n${res.stderr}`.trim().slice(-EXCERPT_MAX_CHARS),
39
+ });
40
+ }
41
+ return out;
42
+ },
43
+ tampering: () => deletedVerificationFiles(ws, o.runStartSha),
44
+ async fingerprint() {
45
+ if (o.runStartSha) {
46
+ const fp = await gitFingerprint(ws, o.runStartSha).catch(() => null);
47
+ if (fp !== null)
48
+ return fp;
49
+ }
50
+ const r = await ws.exec(`find ${shellPath(ws.root)} -xdev -type f -newer ${shellPath(o.marker)} -not -path '*/.git/*' -not -path '*/node_modules/*' 2>/dev/null | sort | head -${FALLBACK_LIST_MAX}`, { cwd: ws.root, timeoutMs: FALLBACK_LIST_TIMEOUT_MS });
51
+ return r.stdout;
52
+ },
53
+ };
54
+ }
55
+ //# sourceMappingURL=probe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe.js","sourceRoot":"","sources":["../src/probe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Mouse's system prompt for the engine.
3
+ *
4
+ * Set as the agent's `prompt`, which replaces the engine's per-model default
5
+ * (for Kimi models that default says "make MINIMAL changes", the wrong bias
6
+ * for a feature that spans five modules). The engine still appends its
7
+ * environment block, the repo's AGENTS.md / CLAUDE.md, and any skills.
8
+ *
9
+ * Static by design: the same bytes on every call of a session so the
10
+ * provider's prefix cache hits. Anything that changes per turn belongs at the
11
+ * tail of the user message, never here. Prompt bytes are cache-sensitive;
12
+ * cosmetic edits invalidate every user's cache and are not accepted.
13
+ *
14
+ * Budget: under ~600 tokens. `AGENT_PROMPT_MAX_CHARS` is the guard the test
15
+ * enforces.
16
+ */
17
+ /**
18
+ * The modes Mouse knows. `build` is the one the CLI runs; the read-only modes
19
+ * exist so a host can select a posture per turn. Hosts may add their own
20
+ * (the string escape hatch); unknown modes get the engine's default prompt.
21
+ */
22
+ export type Mode = "ask" | "plan" | "debug" | "build" | (string & {});
23
+ export type Profile = "product" | "local" | "bench";
24
+ export declare const AGENT_PROMPT_MAX_CHARS = 2600;
25
+ /**
26
+ * The prompt for a mode, or `undefined` to keep the engine's default. Only
27
+ * the writing modes carry Mouse's prompt; the read-only modes keep the engine
28
+ * default.
29
+ */
30
+ export declare function buildAgentPrompt(mode: Mode, _opts?: {
31
+ profile: Profile;
32
+ }): string | undefined;
33
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;GAIG;AACH,MAAM,MAAM,IAAI,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEtE,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAEpD,eAAO,MAAM,sBAAsB,OAAO,CAAC;AA0B3C;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,IAAI,EACV,KAAK,GAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAA2B,GACnD,MAAM,GAAG,SAAS,CAEpB"}
package/dist/prompt.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Mouse's system prompt for the engine.
3
+ *
4
+ * Set as the agent's `prompt`, which replaces the engine's per-model default
5
+ * (for Kimi models that default says "make MINIMAL changes", the wrong bias
6
+ * for a feature that spans five modules). The engine still appends its
7
+ * environment block, the repo's AGENTS.md / CLAUDE.md, and any skills.
8
+ *
9
+ * Static by design: the same bytes on every call of a session so the
10
+ * provider's prefix cache hits. Anything that changes per turn belongs at the
11
+ * tail of the user message, never here. Prompt bytes are cache-sensitive;
12
+ * cosmetic edits invalidate every user's cache and are not accepted.
13
+ *
14
+ * Budget: under ~600 tokens. `AGENT_PROMPT_MAX_CHARS` is the guard the test
15
+ * enforces.
16
+ */
17
+ export const AGENT_PROMPT_MAX_CHARS = 2600;
18
+ const BUILD_PROMPT = `You are Mouse, a coding agent working in a terminal.
19
+
20
+ Persist until the task is fully handled end to end in this turn: explore, implement, run the repo's tests, and fix what fails. Only stop when you are sure the problem is solved. Never claim done without a check you actually ran. If a tool call fails, read the error and change approach; do not repeat the same call.
21
+
22
+ Working style:
23
+ - Inspect before acting: read the relevant code and existing tests before editing. Reproduce a bug before fixing it.
24
+ - Fix the root cause. When you change a function, find every caller.
25
+ - Do the whole ask. A feature that spans several modules is done only when every module and its tests are updated.
26
+ - Prefer the simplest change that fully works: reuse what the repo has, add no dependency unless required, add no speculative abstractions.
27
+ - Validate at trust boundaries; keep internal logic plain.
28
+ - For multi-step work keep the todo list current, with exactly one item in progress.
29
+
30
+ Tools:
31
+ - Use rg for search. Batch independent reads and searches in one response.
32
+ - Prefer read/edit/write for files; use bash to build, test, and run.
33
+ - Do not re-read a file right after editing it; the edit tool fails loudly.
34
+ - Pass an explicit timeout to bash for long commands such as test suites and builds. Run long-lived servers in the background.
35
+ - Run the narrowest relevant test first, then the full suite before finishing. Never weaken, skip, or delete tests to make them pass.
36
+
37
+ Finish with a short summary: what changed, what you ran, and what it showed. Instructions in AGENTS.md or CLAUDE.md in the repo take precedence over these.`;
38
+ /** Modes that carry Mouse's prompt. `overnight` is a host mode with build's posture. */
39
+ const WRITING_MODES = new Set(["build", "overnight"]);
40
+ /**
41
+ * The prompt for a mode, or `undefined` to keep the engine's default. Only
42
+ * the writing modes carry Mouse's prompt; the read-only modes keep the engine
43
+ * default.
44
+ */
45
+ export function buildAgentPrompt(mode, _opts = { profile: "product" }) {
46
+ return WRITING_MODES.has(mode) ? BUILD_PROMPT : undefined;
47
+ }
48
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAWH,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAE3C,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;4JAmBuI,CAAC;AAE7J,wFAAwF;AACxF,MAAM,aAAa,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC;AAE3E;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAU,EACV,KAAK,GAAyB,EAAE,OAAO,EAAE,SAAS,EAAE;IAEpD,OAAO,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,57 @@
1
+ import type { TokenTotals } from "./engine.js";
2
+ import type { LoopEvent } from "./events.js";
3
+ import type { CompletionOutcome, CompletionRound } from "./loop.js";
4
+ export declare const TRACE_VERSION = 1;
5
+ export type TraceRecord = {
6
+ type: "mouse.start";
7
+ v: typeof TRACE_VERSION;
8
+ version: string;
9
+ model: string;
10
+ workspace: string;
11
+ profile: string;
12
+ runStartSha: string | null;
13
+ maxWallSec: number;
14
+ configFile?: string;
15
+ } | {
16
+ type: "mouse.attempt";
17
+ attempt: number;
18
+ steps: number;
19
+ exitCode: number | null;
20
+ timedOut: boolean;
21
+ transientError: boolean;
22
+ error: string | null;
23
+ sessionId: string | null;
24
+ } | {
25
+ type: "mouse.turn";
26
+ steps: number;
27
+ tokens: TokenTotals;
28
+ sessionId: string | null;
29
+ } | {
30
+ type: "mouse.event";
31
+ event: LoopEvent;
32
+ } | ({
33
+ type: "mouse.round";
34
+ } & CompletionRound) | {
35
+ type: "mouse.done";
36
+ outcome: CompletionOutcome;
37
+ rounds: number;
38
+ /** Names of the checks the final round ran; empty means the outcome rests on the workspace change and the model's audit alone. */
39
+ checksRun: string[];
40
+ totalSteps: number;
41
+ tokens: TokenTotals;
42
+ elapsedMs: number;
43
+ sessionId: string | null;
44
+ } | {
45
+ type: "mouse.error";
46
+ error: string;
47
+ steps: number;
48
+ elapsedMs: number;
49
+ };
50
+ export type TraceWriter = {
51
+ readonly file: string;
52
+ write(record: TraceRecord | Record<string, unknown>): void;
53
+ };
54
+ export declare function openTrace(file: string): TraceWriter;
55
+ /** Parse a trace file's lines; malformed lines are skipped. */
56
+ export declare function parseTrace(text: string): Array<Record<string, unknown>>;
57
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAEpE,eAAO,MAAM,aAAa,IAAI,CAAC;AAE/B,MAAM,MAAM,WAAW,GACnB;IACE,IAAI,EAAE,aAAa,CAAC;IACpB,CAAC,EAAE,OAAO,aAAa,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GACD;IACE,IAAI,EAAE,eAAe,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACpF;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACzC,CAAC;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GAAG,eAAe,CAAC,GAC3C;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,kIAAkI;IAClI,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,GACD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC5D,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CASnD;AAED,+DAA+D;AAC/D,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAYvE"}
package/dist/trace.js ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The JSONL trace: one record per line, `mouse.start` first. Versioned by
3
+ * `TRACE_VERSION` on the start record; readers should ignore unknown types.
4
+ */
5
+ import { appendFileSync, mkdirSync } from "node:fs";
6
+ import path from "node:path";
7
+ export const TRACE_VERSION = 1;
8
+ export function openTrace(file) {
9
+ const abs = path.resolve(file);
10
+ mkdirSync(path.dirname(abs), { recursive: true });
11
+ return {
12
+ file: abs,
13
+ write(record) {
14
+ appendFileSync(abs, `${JSON.stringify({ ts: Date.now(), ...record })}\n`);
15
+ },
16
+ };
17
+ }
18
+ /** Parse a trace file's lines; malformed lines are skipped. */
19
+ export function parseTrace(text) {
20
+ const out = [];
21
+ for (const line of text.split("\n")) {
22
+ if (!line.trim())
23
+ continue;
24
+ try {
25
+ const v = JSON.parse(line);
26
+ if (v && typeof v === "object")
27
+ out.push(v);
28
+ }
29
+ catch {
30
+ // skip
31
+ }
32
+ }
33
+ return out;
34
+ }
35
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAK7B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AA6C/B,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,OAAO;QACL,IAAI,EAAE,GAAG;QACT,KAAK,CAAC,MAAM;YACV,cAAc,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5E,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,GAAG,GAAmC,EAAE,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAS;QAC3B,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;YACtC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,GAAG,CAAC,IAAI,CAAC,CAA4B,CAAC,CAAC;QACzE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Harness version, kept in lockstep across the three packages by scripts/release.mjs. */
2
+ export declare const MOUSE_VERSION = "0.1.1";
3
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,eAAO,MAAM,aAAa,UAAU,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Harness version, kept in lockstep across the three packages by scripts/release.mjs. */
2
+ export const MOUSE_VERSION = "0.1.1";
3
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * The one thing the loop needs from the outside world: a directory and a way
3
+ * to run a shell command in it. The CLI implements it over the local machine
4
+ * (`localWorkspace`); a hosted product implements it over its sandbox.
5
+ */
6
+ export interface ExecResult {
7
+ stdout: string;
8
+ stderr: string;
9
+ code: number;
10
+ }
11
+ export interface ExecOptions {
12
+ cwd?: string;
13
+ timeoutMs?: number;
14
+ signal?: AbortSignal;
15
+ }
16
+ export interface Workspace {
17
+ /** Absolute path of the checkout the agent works in. */
18
+ readonly root: string;
19
+ exec(command: string, opts?: ExecOptions): Promise<ExecResult>;
20
+ }
21
+ /**
22
+ * Quote a path for `sh`. Plain paths stay bare so commands built for the
23
+ * conventional `/workspace` root are byte-identical to the historical ones.
24
+ */
25
+ export declare function shellPath(p: string): string;
26
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAChE;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE3C"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Quote a path for `sh`. Plain paths stay bare so commands built for the
3
+ * conventional `/workspace` root are byte-identical to the historical ones.
4
+ */
5
+ export function shellPath(p) {
6
+ return /^[A-Za-z0-9_./-]+$/.test(p) ? p : `'${p.replace(/'/g, `'\\''`)}'`;
7
+ }
8
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAuBA;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC5E,CAAC"}