@agentproto/runtime 5.1.0 → 5.3.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/README.md +18 -0
- package/dist/bundles.d.ts +67 -0
- package/dist/bundles.mjs +173 -0
- package/dist/bundles.mjs.map +1 -0
- package/dist/catalog-models.d.ts +2 -3
- package/dist/config-DcESQDmZ.d.ts +748 -0
- package/dist/config-schema.d.ts +9 -3
- package/dist/config-schema.mjs +198 -47
- package/dist/config-schema.mjs.map +1 -1
- package/dist/config.d.ts +2 -589
- package/dist/config.mjs +205 -49
- package/dist/config.mjs.map +1 -1
- package/dist/index.d.ts +3774 -9286
- package/dist/index.mjs +12070 -4494
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-imports.d.ts +73 -1
- package/dist/mcp-imports.mjs +146 -4
- package/dist/mcp-imports.mjs.map +1 -1
- package/dist/resume-strategies.mjs.map +1 -1
- package/dist/{session-config-ByfVeEQJ.d.ts → session-config-DxIIuJFY.d.ts} +1 -1
- package/dist/session-presence.mjs +196 -46
- package/dist/session-presence.mjs.map +1 -1
- package/dist/session-story.mjs +1 -0
- package/dist/session-story.mjs.map +1 -1
- package/dist/sessions-DKm6Wqro.d.ts +6866 -0
- package/dist/{spawn-defaults-wQV9AeiG.d.ts → spawn-defaults-Cp9SGZex.d.ts} +103 -2
- package/dist/user-presets.d.ts +8 -99
- package/dist/user-presets.mjs +35 -4
- package/dist/user-presets.mjs.map +1 -1
- package/package.json +49 -34
- package/dist/context-continuity-Bn99UtVC.d.ts +0 -104
|
@@ -1,6 +1,107 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AcpMcpServer } from '@agentproto/acp';
|
|
2
|
+
import { SandboxMode } from '@agentproto/command-sandbox';
|
|
2
3
|
import { CatalogProvider } from '@agentproto/model-catalog';
|
|
3
4
|
|
|
5
|
+
/**
|
|
6
|
+
* `agent_start({ browser: "headless" })` — an isolated headless Chrome for
|
|
7
|
+
* one spawned agent, mounted as a per-session stdio MCP server
|
|
8
|
+
* (`chrome-devtools-mcp --headless --isolated`, see
|
|
9
|
+
* `@agentproto/plugin-local-browser`'s `buildHeadlessBrowserMcpEntry`).
|
|
10
|
+
*
|
|
11
|
+
* The server is a child of the adapter process, so it inherits the session's
|
|
12
|
+
* `commandSandbox` confinement and normally dies with the adapter (stdin EOF,
|
|
13
|
+
* and Chrome exits when its pipe closes). On `session:exited`,
|
|
14
|
+
* `sweepSessionBrowser` does two things:
|
|
15
|
+
* - kills anything still carrying the session's `--agentproto-session=<id>`
|
|
16
|
+
* Chrome marker, in case an adapter never exited or never closed its MCP
|
|
17
|
+
* children;
|
|
18
|
+
* - deletes the session's profile dir, `$TMPDIR/agentproto-browser/<id>`.
|
|
19
|
+
* The profile is caller-owned rather than `--isolated`, because `--isolated`
|
|
20
|
+
* only cleans up on a graceful `browser.close()`; observed live, a killed
|
|
21
|
+
* session left its puppeteer temp profile behind.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** `agent_start.browser`. `false` (the default) mounts nothing. */
|
|
25
|
+
type SpawnBrowserMode = "headless" | false;
|
|
26
|
+
interface HeadlessBrowserMount {
|
|
27
|
+
entry: AcpMcpServer;
|
|
28
|
+
/** Read grants the adapter's `commandSandbox` needs for the MCP server +
|
|
29
|
+
* Chrome (threaded as `additionalReadPaths`). */
|
|
30
|
+
readPaths: string[];
|
|
31
|
+
}
|
|
32
|
+
interface ResolveHeadlessBrowserInput {
|
|
33
|
+
sessionId: string;
|
|
34
|
+
cwd: string;
|
|
35
|
+
/** The spawn's explicit `commandSandbox`; `undefined` falls back to the
|
|
36
|
+
* workspace's `adapterSpawn` config, like the driver does. */
|
|
37
|
+
commandSandbox?: SandboxMode;
|
|
38
|
+
}
|
|
39
|
+
type ResolveHeadlessBrowser = (input: ResolveHeadlessBrowserInput) => Promise<HeadlessBrowserMount>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Canonical context-continuity policy for long-running agent sessions.
|
|
43
|
+
*
|
|
44
|
+
* Provides a deterministic, testable policy engine with safe defaults and a
|
|
45
|
+
* clear override order: global defaults → per-harness defaults →
|
|
46
|
+
* per-model defaults → session override. The policy drives warnings,
|
|
47
|
+
* opportunistic compaction, fresh continuation, and hard-stop decisions at
|
|
48
|
+
* turn boundaries so sessions never silently run into the model context
|
|
49
|
+
* limit.
|
|
50
|
+
*/
|
|
51
|
+
/**
|
|
52
|
+
* `manual` suppresses every automatic *nudge* (warn/compact/continue-fresh —
|
|
53
|
+
* see `contextContinuityNextAction`) so the session is left alone until the
|
|
54
|
+
* caller acts. It does NOT suppress `hard-stop`: that state is an
|
|
55
|
+
* unconditional safety floor, independent of mode, by design — its whole
|
|
56
|
+
* purpose is to stop a session from silently running past the model's real
|
|
57
|
+
* context window (further prompts would be truncated/rejected by the
|
|
58
|
+
* provider, or corrupt the conversation) even when nothing is watching.
|
|
59
|
+
* `manual` means "don't nag me", not "let me drive off the window's edge".
|
|
60
|
+
* A session that wants to opt out of the hard stop should set
|
|
61
|
+
* `hardStopAtPct` above what it will ever reach, not rely on mode.
|
|
62
|
+
*/
|
|
63
|
+
type ContextContinuityMode = "manual" | "ask" | "auto";
|
|
64
|
+
interface ContextContinuityThresholds {
|
|
65
|
+
/** Percentage at which the UI first warns that context is filling. */
|
|
66
|
+
warnAtPct: number;
|
|
67
|
+
/** Percentage at which an opportunistic compact may be attempted. */
|
|
68
|
+
compactAtPct: number;
|
|
69
|
+
/** Percentage at which a fresh continuation session is created. */
|
|
70
|
+
continueFreshAtPct: number;
|
|
71
|
+
/** Percentage above which no new prompt may be admitted. */
|
|
72
|
+
hardStopAtPct: number;
|
|
73
|
+
}
|
|
74
|
+
interface ContextContinuityCheckpointSections {
|
|
75
|
+
goal: boolean;
|
|
76
|
+
plan: boolean;
|
|
77
|
+
decisions: boolean;
|
|
78
|
+
changedFiles: boolean;
|
|
79
|
+
gitStatus: boolean;
|
|
80
|
+
tests: boolean;
|
|
81
|
+
errors: boolean;
|
|
82
|
+
risks: boolean;
|
|
83
|
+
nextStep: boolean;
|
|
84
|
+
config: boolean;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* User-supplied policy fragment. Every field optional; missing values are
|
|
88
|
+
* filled from the next precedence layer or from safe defaults.
|
|
89
|
+
*/
|
|
90
|
+
interface ContextContinuityPolicy extends Partial<ContextContinuityThresholds>, Partial<ContextContinuityCheckpointSections> {
|
|
91
|
+
mode?: ContextContinuityMode;
|
|
92
|
+
/** Optional display label for UIs. */
|
|
93
|
+
label?: string;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Fully-resolved, validated policy. This is the shape stored on a session
|
|
97
|
+
* descriptor and returned by status queries.
|
|
98
|
+
*/
|
|
99
|
+
interface ResolvedContextContinuityPolicy extends ContextContinuityThresholds, Required<ContextContinuityCheckpointSections> {
|
|
100
|
+
mode: ContextContinuityMode;
|
|
101
|
+
/** Effective label (falls back to mode when absent). */
|
|
102
|
+
label: string;
|
|
103
|
+
}
|
|
104
|
+
|
|
4
105
|
/**
|
|
5
106
|
* Deferred/lazy MCP tool loading (harness-parity item 3).
|
|
6
107
|
*
|
|
@@ -589,4 +690,4 @@ interface DeclaredAdapterOption {
|
|
|
589
690
|
*/
|
|
590
691
|
declare function normalizeSkillsOption(skills: string[], options: Record<string, boolean | number | string>, declaredOptions: readonly DeclaredAdapterOption[] | undefined): Record<string, boolean | number | string>;
|
|
591
692
|
|
|
592
|
-
export { type AdapterAuthDescriptor as A,
|
|
693
|
+
export { type AdapterAuthDescriptor as A, type ContextContinuityPolicy as C, type DefaultsAdapterAuthConfig as D, type ResolvedContextContinuityPolicy as R, type SpawnDefaultsConfig as S, type SpawnBrowserMode as a, type ResolveHeadlessBrowser as b, type ResolvedAuthSpec as c, type DeclaredAdapterOption as d, type AuthEcho as e, AuthResolutionError as f, CLAUDE_CODE_OAUTH_SOURCE as g, type CredentialSource as h, type DefaultsAdapterConfig as i, type DeferredToolsConfig as j, type ResolveSubscriptionCredentialInput as k, type ResolvedSpawnAuthMaterial as l, type ResolvedSpawnDefaults as m, type SubscriptionCredentialResolution as n, SubscriptionSourceError as o, credentialFingerprint as p, normalizeSkillsOption as q, resolveAuthSpec as r, resolveDeferredToolsGatewayOption as s, resolveSpawnDefaults as t, resolveSubscriptionCredential as u };
|
package/dist/user-presets.d.ts
CHANGED
|
@@ -1,102 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
1
|
+
import 'zod';
|
|
2
|
+
import './session-config-DxIIuJFY.js';
|
|
3
|
+
import './spawn-defaults-Cp9SGZex.js';
|
|
4
|
+
export { c5 as RecentSpawnConfig, U as UserPreset, b8 as UserPresetsFile, bp as deleteUserPreset, c6 as deriveRecentSpawnConfigs, bw as getUserPreset, bC as listUserPresets, bE as loadUserPresets, c0 as saveUserPreset, c7 as touchUserPreset, c8 as userPresetSchema, c3 as userPresetsPath } from './sessions-DKm6Wqro.js';
|
|
4
5
|
import '@agentproto/auth';
|
|
5
6
|
import '@agentproto/acp';
|
|
6
7
|
import '@agentproto/command-sandbox';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* This is deliberately separate from `preset-tools.ts`: provider presets are
|
|
12
|
-
* static gateway definitions shipped by packages, while a UserPreset is a
|
|
13
|
-
* private saved combination of the orthogonal session-config axes.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/** A reusable, user-scoped subset of the spawn/session config axes. */
|
|
17
|
-
interface UserPreset extends Partial<SessionConfig> {
|
|
18
|
-
/** Stable machine-local id, e.g. `fast-deepseek`. */
|
|
19
|
-
id: string;
|
|
20
|
-
/** Human-readable name shown by CLI and editor pickers. */
|
|
21
|
-
label: string;
|
|
22
|
-
/** Adapter harness to use. Omitted means the caller selects one. */
|
|
23
|
-
adapter?: string;
|
|
24
|
-
/** Canonical harness slug — alias for `adapter`. */
|
|
25
|
-
harness?: string;
|
|
26
|
-
model?: string;
|
|
27
|
-
route?: RouteSpec;
|
|
28
|
-
access?: {
|
|
29
|
-
profileRef?: string;
|
|
30
|
-
};
|
|
31
|
-
posture?: Posture;
|
|
32
|
-
effort?: EffortLevel;
|
|
33
|
-
contextProfile?: ContextProfile;
|
|
34
|
-
/** Working directory the favorite pins to. When set, a spawn from this
|
|
35
|
-
* preset lands here regardless of the caller's active folder — the axis
|
|
36
|
-
* that makes a favorite fully location-pinned (true zero-input). Omitted
|
|
37
|
-
* means the caller's cwd ladder resolves it as before. */
|
|
38
|
-
cwd?: string;
|
|
39
|
-
/** Skills to preload for a spawn from this preset — the same axis as
|
|
40
|
-
* `SpawnAgentSessionInput.skills`. Omitted means the adapter/defaults
|
|
41
|
-
* decide. */
|
|
42
|
-
skills?: string[];
|
|
43
|
-
/** Capability bundle ids (`bundle_list`) for a spawn from this preset — the
|
|
44
|
-
* same axis as `SpawnAgentSessionInput.bundles`. Omitted means the
|
|
45
|
-
* adapter/defaults decide. */
|
|
46
|
-
bundles?: string[];
|
|
47
|
-
/** `agent_start.browser` for spawns from this preset. Ranks below the
|
|
48
|
-
* role's own default (see `resolveBrowserMode`). */
|
|
49
|
-
browser?: SpawnBrowserMode;
|
|
50
|
-
}
|
|
51
|
-
declare const userPresetsFileSchema: z.ZodObject<{
|
|
52
|
-
version: z.ZodLiteral<1>;
|
|
53
|
-
presets: z.ZodArray<z.ZodObject<{
|
|
54
|
-
id: z.ZodString;
|
|
55
|
-
label: z.ZodString;
|
|
56
|
-
adapter: z.ZodOptional<z.ZodString>;
|
|
57
|
-
harness: z.ZodOptional<z.ZodString>;
|
|
58
|
-
model: z.ZodOptional<z.ZodString>;
|
|
59
|
-
route: z.ZodOptional<z.ZodObject<{
|
|
60
|
-
gateway: z.ZodString;
|
|
61
|
-
baseUrl: z.ZodOptional<z.ZodString>;
|
|
62
|
-
}, z.core.$strip>>;
|
|
63
|
-
access: z.ZodOptional<z.ZodObject<{
|
|
64
|
-
profileRef: z.ZodOptional<z.ZodString>;
|
|
65
|
-
}, z.core.$strip>>;
|
|
66
|
-
posture: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
|
|
67
|
-
default: "default";
|
|
68
|
-
plan: "plan";
|
|
69
|
-
"accept-edits": "accept-edits";
|
|
70
|
-
bypass: "bypass";
|
|
71
|
-
"read-only": "read-only";
|
|
72
|
-
}>, z.ZodObject<{
|
|
73
|
-
harnessModeId: z.ZodString;
|
|
74
|
-
}, z.core.$strip>]>>;
|
|
75
|
-
effort: z.ZodOptional<z.ZodEnum<{
|
|
76
|
-
low: "low";
|
|
77
|
-
medium: "medium";
|
|
78
|
-
high: "high";
|
|
79
|
-
xhigh: "xhigh";
|
|
80
|
-
max: "max";
|
|
81
|
-
ultracode: "ultracode";
|
|
82
|
-
}>>;
|
|
83
|
-
contextProfile: z.ZodOptional<z.ZodString>;
|
|
84
|
-
cwd: z.ZodOptional<z.ZodString>;
|
|
85
|
-
skills: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
86
|
-
bundles: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
87
|
-
browser: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"headless">, z.ZodLiteral<false>]>>;
|
|
88
|
-
}, z.core.$strip>>;
|
|
89
|
-
}, z.core.$strip>;
|
|
90
|
-
type UserPresetsFile = z.infer<typeof userPresetsFileSchema>;
|
|
91
|
-
declare function userPresetsPath(): string;
|
|
92
|
-
/** Missing or malformed user config is treated as empty — a bad preset must
|
|
93
|
-
* never prevent the daemon from starting. Writes always restore valid JSON. */
|
|
94
|
-
declare function loadUserPresets(): Promise<UserPresetsFile>;
|
|
95
|
-
declare function listUserPresets(): Promise<UserPreset[]>;
|
|
96
|
-
declare function getUserPreset(id: string): Promise<UserPreset | undefined>;
|
|
97
|
-
/** Add or replace a preset by id. The parser makes this the single validation
|
|
98
|
-
* boundary for CLI, MCP and editor callers. */
|
|
99
|
-
declare function saveUserPreset(preset: UserPreset): Promise<void>;
|
|
100
|
-
declare function deleteUserPreset(id: string): Promise<boolean>;
|
|
101
|
-
|
|
102
|
-
export { type UserPreset, type UserPresetsFile, deleteUserPreset, getUserPreset, listUserPresets, loadUserPresets, saveUserPreset, userPresetsPath };
|
|
8
|
+
import '@agentproto/model-catalog';
|
|
9
|
+
import '@agentproto/acp/client';
|
|
10
|
+
import 'node:child_process';
|
|
11
|
+
import './config-DcESQDmZ.js';
|
package/dist/user-presets.mjs
CHANGED
|
@@ -31,7 +31,8 @@ var userPresetSchema = z.object({
|
|
|
31
31
|
cwd: z.string().min(1).optional(),
|
|
32
32
|
skills: z.array(z.string().min(1)).optional(),
|
|
33
33
|
bundles: z.array(z.string().min(1)).optional(),
|
|
34
|
-
browser: z.union([z.literal("headless"), z.literal(false)]).optional()
|
|
34
|
+
browser: z.union([z.literal("headless"), z.literal(false)]).optional(),
|
|
35
|
+
lastUsedAt: z.string().min(1).optional()
|
|
35
36
|
});
|
|
36
37
|
var userPresetsFileSchema = z.object({
|
|
37
38
|
version: z.literal(1),
|
|
@@ -68,8 +69,10 @@ async function saveUserPreset(preset) {
|
|
|
68
69
|
const validated = userPresetSchema.parse(preset);
|
|
69
70
|
const file = await loadUserPresets();
|
|
70
71
|
const index = file.presets.findIndex((existing) => existing.id === validated.id);
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
const lastUsedAt = validated.lastUsedAt ?? (index === -1 ? void 0 : file.presets[index]?.lastUsedAt);
|
|
73
|
+
const next = { ...validated, ...lastUsedAt ? { lastUsedAt } : {} };
|
|
74
|
+
if (index === -1) file.presets.push(next);
|
|
75
|
+
else file.presets[index] = next;
|
|
73
76
|
await writeUserPresets(file);
|
|
74
77
|
}
|
|
75
78
|
async function deleteUserPreset(id) {
|
|
@@ -80,7 +83,35 @@ async function deleteUserPreset(id) {
|
|
|
80
83
|
await writeUserPresets(file);
|
|
81
84
|
return true;
|
|
82
85
|
}
|
|
86
|
+
async function touchUserPreset(id) {
|
|
87
|
+
const file = await loadUserPresets();
|
|
88
|
+
const index = file.presets.findIndex((preset) => preset.id === id);
|
|
89
|
+
if (index === -1) return;
|
|
90
|
+
file.presets[index] = { ...file.presets[index], lastUsedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
91
|
+
await writeUserPresets(file);
|
|
92
|
+
}
|
|
93
|
+
function deriveRecentSpawnConfigs(descriptors, limit = 5) {
|
|
94
|
+
const seen = /* @__PURE__ */ new Set();
|
|
95
|
+
const out = [];
|
|
96
|
+
for (const desc of descriptors) {
|
|
97
|
+
if (out.length >= limit) break;
|
|
98
|
+
if (desc.kind !== "agent-cli") continue;
|
|
99
|
+
const adapter = desc.harness ?? desc.adapterSlug;
|
|
100
|
+
if (!adapter) continue;
|
|
101
|
+
const config = {
|
|
102
|
+
adapter,
|
|
103
|
+
...desc.model ? { model: desc.model } : {},
|
|
104
|
+
...desc.accessProfile?.profileRef ? { profileRef: desc.accessProfile.profileRef } : {},
|
|
105
|
+
...desc.cwd ? { cwd: desc.cwd } : {}
|
|
106
|
+
};
|
|
107
|
+
const key = JSON.stringify(config);
|
|
108
|
+
if (seen.has(key)) continue;
|
|
109
|
+
seen.add(key);
|
|
110
|
+
out.push({ ...config, recent: true });
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
83
114
|
|
|
84
|
-
export { deleteUserPreset, getUserPreset, listUserPresets, loadUserPresets, saveUserPreset, userPresetsPath };
|
|
115
|
+
export { deleteUserPreset, deriveRecentSpawnConfigs, getUserPreset, listUserPresets, loadUserPresets, saveUserPreset, touchUserPreset, userPresetSchema, userPresetsPath };
|
|
85
116
|
//# sourceMappingURL=user-presets.mjs.map
|
|
86
117
|
//# sourceMappingURL=user-presets.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/user-presets.ts"],"names":[],"mappings":"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","file":"user-presets.mjs","sourcesContent":["/**\n * User-owned spawn presets.\n *\n * This is deliberately separate from `preset-tools.ts`: provider presets are\n * static gateway definitions shipped by packages, while a UserPreset is a\n * private saved combination of the orthogonal session-config axes.\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\nimport { z } from \"zod\"\nimport type {\n ContextProfile,\n EffortLevel,\n Posture,\n RouteSpec,\n SessionConfig,\n} from \"./session-config.js\"\nimport type { SpawnBrowserMode } from \"./browser-mount.js\"\n\nconst effortSchema = z.enum([\"low\", \"medium\", \"high\", \"xhigh\", \"max\", \"ultracode\"])\nconst postureSchema = z.union([\n z.enum([\"default\", \"plan\", \"accept-edits\", \"bypass\", \"read-only\"]),\n z.object({ harnessModeId: z.string().min(1) }),\n])\nconst routeSchema = z.object({\n gateway: z.string().min(1),\n baseUrl: z.string().url().optional(),\n})\n\n/** A reusable, user-scoped subset of the spawn/session config axes. */\nexport interface UserPreset extends Partial<SessionConfig> {\n /** Stable machine-local id, e.g. `fast-deepseek`. */\n id: string\n /** Human-readable name shown by CLI and editor pickers. */\n label: string\n /** Adapter harness to use. Omitted means the caller selects one. */\n adapter?: string\n /** Canonical harness slug — alias for `adapter`. */\n harness?: string\n model?: string\n route?: RouteSpec\n access?: { profileRef?: string }\n posture?: Posture\n effort?: EffortLevel\n contextProfile?: ContextProfile\n /** Working directory the favorite pins to. When set, a spawn from this\n * preset lands here regardless of the caller's active folder — the axis\n * that makes a favorite fully location-pinned (true zero-input). Omitted\n * means the caller's cwd ladder resolves it as before. */\n cwd?: string\n /** Skills to preload for a spawn from this preset — the same axis as\n * `SpawnAgentSessionInput.skills`. Omitted means the adapter/defaults\n * decide. */\n skills?: string[]\n /** Capability bundle ids (`bundle_list`) for a spawn from this preset — the\n * same axis as `SpawnAgentSessionInput.bundles`. Omitted means the\n * adapter/defaults decide. */\n bundles?: string[]\n /** `agent_start.browser` for spawns from this preset. Ranks below the\n * role's own default (see `resolveBrowserMode`). */\n browser?: SpawnBrowserMode\n}\n\nconst userPresetSchema = z.object({\n id: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n label: z.string().min(1),\n adapter: z.string().min(1).optional(),\n harness: z.string().min(1).optional(),\n model: z.string().min(1).optional(),\n route: routeSchema.optional(),\n access: z.object({ profileRef: z.string().min(1).optional() }).optional(),\n posture: postureSchema.optional(),\n effort: effortSchema.optional(),\n contextProfile: z.string().min(1).optional(),\n cwd: z.string().min(1).optional(),\n skills: z.array(z.string().min(1)).optional(),\n bundles: z.array(z.string().min(1)).optional(),\n browser: z.union([z.literal(\"headless\"), z.literal(false)]).optional(),\n}) satisfies z.ZodType<UserPreset>\n\nconst userPresetsFileSchema = z.object({\n version: z.literal(1),\n presets: z.array(userPresetSchema),\n})\n\nexport type UserPresetsFile = z.infer<typeof userPresetsFileSchema>\n\nfunction emptyFile(): UserPresetsFile {\n return { version: 1, presets: [] }\n}\n\nexport function userPresetsPath(): string {\n return resolve(homedir(), \".agentproto\", \"presets.json\")\n}\n\n/** Missing or malformed user config is treated as empty — a bad preset must\n * never prevent the daemon from starting. Writes always restore valid JSON. */\nexport async function loadUserPresets(): Promise<UserPresetsFile> {\n try {\n return userPresetsFileSchema.parse(JSON.parse(await readFile(userPresetsPath(), \"utf8\")))\n } catch {\n return emptyFile()\n }\n}\n\nasync function writeUserPresets(file: UserPresetsFile): Promise<void> {\n const dir = join(homedir(), \".agentproto\")\n await mkdir(dir, { recursive: true })\n await writeFile(userPresetsPath(), JSON.stringify(file, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n })\n}\n\nexport async function listUserPresets(): Promise<UserPreset[]> {\n return (await loadUserPresets()).presets\n}\n\nexport async function getUserPreset(id: string): Promise<UserPreset | undefined> {\n return (await loadUserPresets()).presets.find(preset => preset.id === id)\n}\n\n/** Add or replace a preset by id. The parser makes this the single validation\n * boundary for CLI, MCP and editor callers. */\nexport async function saveUserPreset(preset: UserPreset): Promise<void> {\n const validated = userPresetSchema.parse(preset)\n const file = await loadUserPresets()\n const index = file.presets.findIndex(existing => existing.id === validated.id)\n if (index === -1) file.presets.push(validated)\n else file.presets[index] = validated\n await writeUserPresets(file)\n}\n\nexport async function deleteUserPreset(id: string): Promise<boolean> {\n const file = await loadUserPresets()\n const index = file.presets.findIndex(preset => preset.id === id)\n if (index === -1) return false\n file.presets.splice(index, 1)\n await writeUserPresets(file)\n return true\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/user-presets.ts"],"names":[],"mappings":"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","file":"user-presets.mjs","sourcesContent":["/**\n * User-owned spawn presets.\n *\n * This is deliberately separate from `preset-tools.ts`: provider presets are\n * static gateway definitions shipped by packages, while a UserPreset is a\n * private saved combination of the orthogonal session-config axes.\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { join, resolve } from \"node:path\"\nimport { z } from \"zod\"\nimport type {\n ContextProfile,\n EffortLevel,\n Posture,\n RouteSpec,\n SessionConfig,\n} from \"./session-config.js\"\nimport type { SpawnBrowserMode } from \"./browser-mount.js\"\nimport type { SessionDescriptor } from \"./sessions.js\"\n\nconst effortSchema = z.enum([\"low\", \"medium\", \"high\", \"xhigh\", \"max\", \"ultracode\"])\nconst postureSchema = z.union([\n z.enum([\"default\", \"plan\", \"accept-edits\", \"bypass\", \"read-only\"]),\n z.object({ harnessModeId: z.string().min(1) }),\n])\nconst routeSchema = z.object({\n gateway: z.string().min(1),\n baseUrl: z.string().url().optional(),\n})\n\n/** A reusable, user-scoped subset of the spawn/session config axes. */\nexport interface UserPreset extends Partial<SessionConfig> {\n /** Stable machine-local id, e.g. `fast-deepseek`. */\n id: string\n /** Human-readable name shown by CLI and editor pickers. */\n label: string\n /** Adapter harness to use. Omitted means the caller selects one. */\n adapter?: string\n /** Canonical harness slug — alias for `adapter`. */\n harness?: string\n model?: string\n route?: RouteSpec\n access?: { profileRef?: string }\n posture?: Posture\n effort?: EffortLevel\n contextProfile?: ContextProfile\n /** Working directory the favorite pins to. When set, a spawn from this\n * preset lands here regardless of the caller's active folder — the axis\n * that makes a favorite fully location-pinned (true zero-input). Omitted\n * means the caller's cwd ladder resolves it as before. */\n cwd?: string\n /** Skills to preload for a spawn from this preset — the same axis as\n * `SpawnAgentSessionInput.skills`. Omitted means the adapter/defaults\n * decide. */\n skills?: string[]\n /** Capability bundle ids (`bundle_list`) for a spawn from this preset — the\n * same axis as `SpawnAgentSessionInput.bundles`. Omitted means the\n * adapter/defaults decide. */\n bundles?: string[]\n /** `agent_start.browser` for spawns from this preset. Ranks below the\n * role's own default (see `resolveBrowserMode`). */\n browser?: SpawnBrowserMode\n /** ISO 8601 timestamp of the last spawn that resolved a `presetId` to this\n * preset (agent_start, `/sessions/agent`, `/sessions/chat` — stamped once\n * in `spawnAgentSession`, the shared core all three route through). Never\n * set by a caller directly; `saveUserPreset` preserves the existing value\n * across an edit unless the write explicitly overrides it. Absent for a\n * preset that has never been used to spawn. */\n lastUsedAt?: string\n}\n\nexport const userPresetSchema = z.object({\n id: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n label: z.string().min(1),\n adapter: z.string().min(1).optional(),\n harness: z.string().min(1).optional(),\n model: z.string().min(1).optional(),\n route: routeSchema.optional(),\n access: z.object({ profileRef: z.string().min(1).optional() }).optional(),\n posture: postureSchema.optional(),\n effort: effortSchema.optional(),\n contextProfile: z.string().min(1).optional(),\n cwd: z.string().min(1).optional(),\n skills: z.array(z.string().min(1)).optional(),\n bundles: z.array(z.string().min(1)).optional(),\n browser: z.union([z.literal(\"headless\"), z.literal(false)]).optional(),\n lastUsedAt: z.string().min(1).optional(),\n}) satisfies z.ZodType<UserPreset>\n\nconst userPresetsFileSchema = z.object({\n version: z.literal(1),\n presets: z.array(userPresetSchema),\n})\n\nexport type UserPresetsFile = z.infer<typeof userPresetsFileSchema>\n\nfunction emptyFile(): UserPresetsFile {\n return { version: 1, presets: [] }\n}\n\nexport function userPresetsPath(): string {\n return resolve(homedir(), \".agentproto\", \"presets.json\")\n}\n\n/** Missing or malformed user config is treated as empty — a bad preset must\n * never prevent the daemon from starting. Writes always restore valid JSON. */\nexport async function loadUserPresets(): Promise<UserPresetsFile> {\n try {\n return userPresetsFileSchema.parse(JSON.parse(await readFile(userPresetsPath(), \"utf8\")))\n } catch {\n return emptyFile()\n }\n}\n\nasync function writeUserPresets(file: UserPresetsFile): Promise<void> {\n const dir = join(homedir(), \".agentproto\")\n await mkdir(dir, { recursive: true })\n await writeFile(userPresetsPath(), JSON.stringify(file, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n })\n}\n\nexport async function listUserPresets(): Promise<UserPreset[]> {\n return (await loadUserPresets()).presets\n}\n\nexport async function getUserPreset(id: string): Promise<UserPreset | undefined> {\n return (await loadUserPresets()).presets.find(preset => preset.id === id)\n}\n\n/** Add or replace a preset by id. The parser makes this the single validation\n * boundary for CLI, MCP and editor callers. An edit that doesn't name its own\n * `lastUsedAt` keeps the existing preset's stamp rather than wiping it — a\n * rename/retune of a favorite must not erase its recency. */\nexport async function saveUserPreset(preset: UserPreset): Promise<void> {\n const validated = userPresetSchema.parse(preset)\n const file = await loadUserPresets()\n const index = file.presets.findIndex(existing => existing.id === validated.id)\n const lastUsedAt = validated.lastUsedAt ?? (index === -1 ? undefined : file.presets[index]?.lastUsedAt)\n const next: UserPreset = { ...validated, ...(lastUsedAt ? { lastUsedAt } : {}) }\n if (index === -1) file.presets.push(next)\n else file.presets[index] = next\n await writeUserPresets(file)\n}\n\nexport async function deleteUserPreset(id: string): Promise<boolean> {\n const file = await loadUserPresets()\n const index = file.presets.findIndex(preset => preset.id === id)\n if (index === -1) return false\n file.presets.splice(index, 1)\n await writeUserPresets(file)\n return true\n}\n\n/** Stamp `lastUsedAt` on the preset a spawn just resolved `presetId` to.\n * Best-effort: an unknown id is a no-op, and a write failure here must never\n * fail the spawn it's timestamping — callers should await it inside a\n * `.catch(() => {})`. */\nexport async function touchUserPreset(id: string): Promise<void> {\n const file = await loadUserPresets()\n const index = file.presets.findIndex(preset => preset.id === id)\n if (index === -1) return\n file.presets[index] = { ...file.presets[index]!, lastUsedAt: new Date().toISOString() }\n await writeUserPresets(file)\n}\n\n/** One de-duplicated recent spawn configuration, derived from session\n * history rather than persisted — the `user_preset_list({ includeRecent:\n * true })` / `GET /user-presets?includeRecent=1` companion view to actual\n * favorites, so a caller can \"save as favorite\" something they've spawned\n * before without retyping it. */\nexport interface RecentSpawnConfig {\n adapter?: string\n model?: string\n profileRef?: string\n cwd?: string\n /** Always true — the marker that distinguishes a derived row from a\n * persisted {@link UserPreset} when the two are rendered in one list. */\n recent: true\n}\n\n/** Derive up to `limit` distinct recent spawn configurations (adapter,\n * model, profileRef, cwd) from the registry's own newest-first session\n * list. Only `agent-cli` sessions carry a spawn config; a session that\n * named neither `harness` nor `adapterSlug` is skipped (nothing to offer\n * as a favorite). Distinctness is by the exact (adapter, model, profileRef,\n * cwd) tuple, keeping only the most recent occurrence of each. */\nexport function deriveRecentSpawnConfigs(\n descriptors: readonly SessionDescriptor[],\n limit = 5,\n): RecentSpawnConfig[] {\n const seen = new Set<string>()\n const out: RecentSpawnConfig[] = []\n for (const desc of descriptors) {\n if (out.length >= limit) break\n if (desc.kind !== \"agent-cli\") continue\n const adapter = desc.harness ?? desc.adapterSlug\n if (!adapter) continue\n const config: Omit<RecentSpawnConfig, \"recent\"> = {\n adapter,\n ...(desc.model ? { model: desc.model } : {}),\n ...(desc.accessProfile?.profileRef ? { profileRef: desc.accessProfile.profileRef } : {}),\n ...(desc.cwd ? { cwd: desc.cwd } : {}),\n }\n const key = JSON.stringify(config)\n if (seen.has(key)) continue\n seen.add(key)\n out.push({ ...config, recent: true })\n }\n return out\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentproto/runtime",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"description": "@agentproto/runtime — long-running gateway that turns an agentproto workspace into a live runtime. Composes @agentproto/mcp-server (CRUD verbs) with HTTP transport, HEARTBEAT.md autonomy loop, and append-only conversation persistence. Drop a workspace dir, point your MCP client at it, and the agent ticks on its own.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentproto",
|
|
7
|
+
"aip-46",
|
|
8
|
+
"aip-58",
|
|
7
9
|
"runtime",
|
|
8
10
|
"gateway",
|
|
9
11
|
"mcp",
|
|
@@ -91,6 +93,11 @@
|
|
|
91
93
|
"import": "./dist/release-check.mjs",
|
|
92
94
|
"default": "./dist/release-check.mjs"
|
|
93
95
|
},
|
|
96
|
+
"./bundles": {
|
|
97
|
+
"types": "./dist/bundles.d.ts",
|
|
98
|
+
"import": "./dist/bundles.mjs",
|
|
99
|
+
"default": "./dist/bundles.mjs"
|
|
100
|
+
},
|
|
94
101
|
"./mcp-imports": {
|
|
95
102
|
"types": "./dist/mcp-imports.d.ts",
|
|
96
103
|
"import": "./dist/mcp-imports.mjs",
|
|
@@ -148,44 +155,51 @@
|
|
|
148
155
|
},
|
|
149
156
|
"dependencies": {
|
|
150
157
|
"@modelcontextprotocol/ext-apps": "1.7.5",
|
|
151
|
-
"@modelcontextprotocol/sdk": "^1.30.
|
|
158
|
+
"@modelcontextprotocol/sdk": "^1.30.1",
|
|
152
159
|
"ai": "^6.0.277",
|
|
153
160
|
"croner": "^9.1.0",
|
|
154
161
|
"gray-matter": "^4.0.3",
|
|
155
162
|
"ws": "^8.21.3",
|
|
156
163
|
"zod": "^4.6.5",
|
|
157
|
-
"@agentproto/
|
|
158
|
-
"@agentproto/
|
|
159
|
-
"@agentproto/
|
|
160
|
-
"@agentproto/
|
|
161
|
-
"@agentproto/
|
|
162
|
-
"@agentproto/apps": "0.
|
|
163
|
-
"@agentproto/
|
|
164
|
-
"@agentproto/
|
|
165
|
-
"@agentproto/driver
|
|
166
|
-
"@agentproto/driver-
|
|
167
|
-
"@agentproto/
|
|
168
|
-
"@agentproto/
|
|
169
|
-
"@agentproto/
|
|
170
|
-
"@agentproto/
|
|
171
|
-
"@agentproto/
|
|
172
|
-
"@agentproto/
|
|
164
|
+
"@agentproto/a2a": "0.1.0",
|
|
165
|
+
"@agentproto/adapter-browser": "0.2.0",
|
|
166
|
+
"@agentproto/agent": "0.2.5",
|
|
167
|
+
"@agentproto/acp": "0.9.1",
|
|
168
|
+
"@agentproto/app-kit": "1.4.0",
|
|
169
|
+
"@agentproto/apps": "0.17.0",
|
|
170
|
+
"@agentproto/auth": "1.1.1",
|
|
171
|
+
"@agentproto/app-client": "0.4.1",
|
|
172
|
+
"@agentproto/driver": "0.2.5",
|
|
173
|
+
"@agentproto/driver-agent-cli": "2.6.0",
|
|
174
|
+
"@agentproto/command-sandbox": "0.3.0",
|
|
175
|
+
"@agentproto/driver-browser": "0.1.0",
|
|
176
|
+
"@agentproto/driver-http": "0.1.9",
|
|
177
|
+
"@agentproto/eval-reporters": "0.2.19",
|
|
178
|
+
"@agentproto/governance-engine": "0.1.9",
|
|
179
|
+
"@agentproto/llm-endpoint": "0.11.2",
|
|
180
|
+
"@agentproto/manifest": "0.2.3",
|
|
181
|
+
"@agentproto/model-catalog": "0.11.3",
|
|
182
|
+
"@agentproto/governance": "0.1.5",
|
|
183
|
+
"@agentproto/mcp-server": "0.4.1",
|
|
184
|
+
"@agentproto/pairing-host": "0.1.0",
|
|
185
|
+
"@agentproto/plugin-local-browser": "0.3.1",
|
|
173
186
|
"@agentproto/provider-presets": "0.7.0",
|
|
174
|
-
"@agentproto/
|
|
175
|
-
"@agentproto/
|
|
176
|
-
"@agentproto/
|
|
177
|
-
"@agentproto/
|
|
178
|
-
"@agentproto/
|
|
179
|
-
"@agentproto/secrets": "1.1.
|
|
180
|
-
"@agentproto/telemetry-langfuse": "0.2.
|
|
181
|
-
"@agentproto/
|
|
182
|
-
"@agentproto/workflow": "0.7.
|
|
183
|
-
"@agentproto/workflow-loader": "0.2.
|
|
184
|
-
"@agentproto/
|
|
185
|
-
"@agentproto/
|
|
187
|
+
"@agentproto/provider-kit": "0.4.6",
|
|
188
|
+
"@agentproto/providers-store": "0.3.21",
|
|
189
|
+
"@agentproto/routine": "0.3.1",
|
|
190
|
+
"@agentproto/sandbox": "0.7.2",
|
|
191
|
+
"@agentproto/review": "0.4.0",
|
|
192
|
+
"@agentproto/secrets": "1.1.1",
|
|
193
|
+
"@agentproto/telemetry-langfuse": "0.2.17",
|
|
194
|
+
"@agentproto/redaction": "0.2.3",
|
|
195
|
+
"@agentproto/workflow": "0.7.1",
|
|
196
|
+
"@agentproto/workflow-loader": "0.2.5",
|
|
197
|
+
"@agentproto/tool": "0.3.2",
|
|
198
|
+
"@agentproto/workflow-runtime": "0.15.0",
|
|
199
|
+
"@agentproto/workspace-brain": "0.4.9"
|
|
186
200
|
},
|
|
187
201
|
"optionalDependencies": {
|
|
188
|
-
"@agentproto/sandbox-e2b": "0.5.
|
|
202
|
+
"@agentproto/sandbox-e2b": "0.5.9"
|
|
189
203
|
},
|
|
190
204
|
"devDependencies": {
|
|
191
205
|
"@types/node": "^25.9.5",
|
|
@@ -194,9 +208,9 @@
|
|
|
194
208
|
"typescript": "^5.9.3",
|
|
195
209
|
"vite-node": "^3.2.4",
|
|
196
210
|
"vitest": "^3.2.7",
|
|
197
|
-
"@agentproto/
|
|
211
|
+
"@agentproto/rendezvous": "0.2.3",
|
|
198
212
|
"@agentproto/transcript-fixtures": "0.3.0",
|
|
199
|
-
"@agentproto/
|
|
213
|
+
"@agentproto/tooling": "0.1.0"
|
|
200
214
|
},
|
|
201
215
|
"scripts": {
|
|
202
216
|
"dev": "tsup --watch",
|
|
@@ -206,6 +220,7 @@
|
|
|
206
220
|
"test": "vitest run --passWithNoTests",
|
|
207
221
|
"test:watch": "vitest",
|
|
208
222
|
"sim:inbound": "vite-node scripts/simulate-inbound.mjs",
|
|
209
|
-
"telegram:proxy": "vite-node scripts/telegram-proxy.mjs"
|
|
223
|
+
"telegram:proxy": "vite-node scripts/telegram-proxy.mjs",
|
|
224
|
+
"bench:review-ledger": "vite-node scripts/bench-review-ledger.mjs"
|
|
210
225
|
}
|
|
211
226
|
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { AcpMcpServer } from '@agentproto/acp';
|
|
2
|
-
import { SandboxMode } from '@agentproto/command-sandbox';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* `agent_start({ browser: "headless" })` — an isolated headless Chrome for
|
|
6
|
-
* one spawned agent, mounted as a per-session stdio MCP server
|
|
7
|
-
* (`chrome-devtools-mcp --headless --isolated`, see
|
|
8
|
-
* `@agentproto/plugin-local-browser`'s `buildHeadlessBrowserMcpEntry`).
|
|
9
|
-
*
|
|
10
|
-
* The server is a child of the adapter process, so it inherits the session's
|
|
11
|
-
* `commandSandbox` confinement and normally dies with the adapter (stdin EOF,
|
|
12
|
-
* and Chrome exits when its pipe closes). On `session:exited`,
|
|
13
|
-
* `sweepSessionBrowser` does two things:
|
|
14
|
-
* - kills anything still carrying the session's `--agentproto-session=<id>`
|
|
15
|
-
* Chrome marker, in case an adapter never exited or never closed its MCP
|
|
16
|
-
* children;
|
|
17
|
-
* - deletes the session's profile dir, `$TMPDIR/agentproto-browser/<id>`.
|
|
18
|
-
* The profile is caller-owned rather than `--isolated`, because `--isolated`
|
|
19
|
-
* only cleans up on a graceful `browser.close()`; observed live, a killed
|
|
20
|
-
* session left its puppeteer temp profile behind.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
/** `agent_start.browser`. `false` (the default) mounts nothing. */
|
|
24
|
-
type SpawnBrowserMode = "headless" | false;
|
|
25
|
-
interface HeadlessBrowserMount {
|
|
26
|
-
entry: AcpMcpServer;
|
|
27
|
-
/** Read grants the adapter's `commandSandbox` needs for the MCP server +
|
|
28
|
-
* Chrome (threaded as `additionalReadPaths`). */
|
|
29
|
-
readPaths: string[];
|
|
30
|
-
}
|
|
31
|
-
interface ResolveHeadlessBrowserInput {
|
|
32
|
-
sessionId: string;
|
|
33
|
-
cwd: string;
|
|
34
|
-
/** The spawn's explicit `commandSandbox`; `undefined` falls back to the
|
|
35
|
-
* workspace's `adapterSpawn` config, like the driver does. */
|
|
36
|
-
commandSandbox?: SandboxMode;
|
|
37
|
-
}
|
|
38
|
-
type ResolveHeadlessBrowser = (input: ResolveHeadlessBrowserInput) => Promise<HeadlessBrowserMount>;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Canonical context-continuity policy for long-running agent sessions.
|
|
42
|
-
*
|
|
43
|
-
* Provides a deterministic, testable policy engine with safe defaults and a
|
|
44
|
-
* clear override order: global defaults → per-harness defaults →
|
|
45
|
-
* per-model defaults → session override. The policy drives warnings,
|
|
46
|
-
* opportunistic compaction, fresh continuation, and hard-stop decisions at
|
|
47
|
-
* turn boundaries so sessions never silently run into the model context
|
|
48
|
-
* limit.
|
|
49
|
-
*/
|
|
50
|
-
/**
|
|
51
|
-
* `manual` suppresses every automatic *nudge* (warn/compact/continue-fresh —
|
|
52
|
-
* see `contextContinuityNextAction`) so the session is left alone until the
|
|
53
|
-
* caller acts. It does NOT suppress `hard-stop`: that state is an
|
|
54
|
-
* unconditional safety floor, independent of mode, by design — its whole
|
|
55
|
-
* purpose is to stop a session from silently running past the model's real
|
|
56
|
-
* context window (further prompts would be truncated/rejected by the
|
|
57
|
-
* provider, or corrupt the conversation) even when nothing is watching.
|
|
58
|
-
* `manual` means "don't nag me", not "let me drive off the window's edge".
|
|
59
|
-
* A session that wants to opt out of the hard stop should set
|
|
60
|
-
* `hardStopAtPct` above what it will ever reach, not rely on mode.
|
|
61
|
-
*/
|
|
62
|
-
type ContextContinuityMode = "manual" | "ask" | "auto";
|
|
63
|
-
interface ContextContinuityThresholds {
|
|
64
|
-
/** Percentage at which the UI first warns that context is filling. */
|
|
65
|
-
warnAtPct: number;
|
|
66
|
-
/** Percentage at which an opportunistic compact may be attempted. */
|
|
67
|
-
compactAtPct: number;
|
|
68
|
-
/** Percentage at which a fresh continuation session is created. */
|
|
69
|
-
continueFreshAtPct: number;
|
|
70
|
-
/** Percentage above which no new prompt may be admitted. */
|
|
71
|
-
hardStopAtPct: number;
|
|
72
|
-
}
|
|
73
|
-
interface ContextContinuityCheckpointSections {
|
|
74
|
-
goal: boolean;
|
|
75
|
-
plan: boolean;
|
|
76
|
-
decisions: boolean;
|
|
77
|
-
changedFiles: boolean;
|
|
78
|
-
gitStatus: boolean;
|
|
79
|
-
tests: boolean;
|
|
80
|
-
errors: boolean;
|
|
81
|
-
risks: boolean;
|
|
82
|
-
nextStep: boolean;
|
|
83
|
-
config: boolean;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* User-supplied policy fragment. Every field optional; missing values are
|
|
87
|
-
* filled from the next precedence layer or from safe defaults.
|
|
88
|
-
*/
|
|
89
|
-
interface ContextContinuityPolicy extends Partial<ContextContinuityThresholds>, Partial<ContextContinuityCheckpointSections> {
|
|
90
|
-
mode?: ContextContinuityMode;
|
|
91
|
-
/** Optional display label for UIs. */
|
|
92
|
-
label?: string;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Fully-resolved, validated policy. This is the shape stored on a session
|
|
96
|
-
* descriptor and returned by status queries.
|
|
97
|
-
*/
|
|
98
|
-
interface ResolvedContextContinuityPolicy extends ContextContinuityThresholds, Required<ContextContinuityCheckpointSections> {
|
|
99
|
-
mode: ContextContinuityMode;
|
|
100
|
-
/** Effective label (falls back to mode when absent). */
|
|
101
|
-
label: string;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
export type { ContextContinuityPolicy as C, ResolveHeadlessBrowser as R, SpawnBrowserMode as S, ResolvedContextContinuityPolicy as a };
|