paseo-agy-acp 2.2.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.
Files changed (107) hide show
  1. package/CHANGELOG.md +296 -0
  2. package/LICENSE +201 -0
  3. package/README.md +571 -0
  4. package/README.zh-CN.md +540 -0
  5. package/assets/official-kernel-compat/rc01/paseo_model_compat.py +172 -0
  6. package/dist/ACP Connector/acp/session/paseo-context.d.ts +6 -0
  7. package/dist/ACP Connector/acp/session/paseo-context.js +83 -0
  8. package/dist/ACP Connector/acp/session/paseo-context.js.map +1 -0
  9. package/dist/ACP Connector/acp/session/turn-scheduler.d.ts +90 -0
  10. package/dist/ACP Connector/acp/session/turn-scheduler.js +247 -0
  11. package/dist/ACP Connector/acp/session/turn-scheduler.js.map +1 -0
  12. package/dist/ACP Connector/admission/dispatch-boundary.d.ts +19 -0
  13. package/dist/ACP Connector/admission/dispatch-boundary.js +16 -0
  14. package/dist/ACP Connector/admission/dispatch-boundary.js.map +1 -0
  15. package/dist/ACP Connector/admission/errors.d.ts +18 -0
  16. package/dist/ACP Connector/admission/errors.js +46 -0
  17. package/dist/ACP Connector/admission/errors.js.map +1 -0
  18. package/dist/ACP Connector/admission/owner-instance.d.ts +31 -0
  19. package/dist/ACP Connector/admission/owner-instance.js +105 -0
  20. package/dist/ACP Connector/admission/owner-instance.js.map +1 -0
  21. package/dist/ACP Connector/admission/runtime.d.ts +20 -0
  22. package/dist/ACP Connector/admission/runtime.js +157 -0
  23. package/dist/ACP Connector/admission/runtime.js.map +1 -0
  24. package/dist/ACP Connector/admission/startup-recovery.d.ts +22 -0
  25. package/dist/ACP Connector/admission/startup-recovery.js +129 -0
  26. package/dist/ACP Connector/admission/startup-recovery.js.map +1 -0
  27. package/dist/ACP Connector/admission/turn-coordinator.d.ts +57 -0
  28. package/dist/ACP Connector/admission/turn-coordinator.js +369 -0
  29. package/dist/ACP Connector/admission/turn-coordinator.js.map +1 -0
  30. package/dist/ACP Connector/agent.d.ts +4 -0
  31. package/dist/ACP Connector/agent.js +6 -0
  32. package/dist/ACP Connector/agent.js.map +1 -0
  33. package/dist/ACP Connector/main.d.ts +2 -0
  34. package/dist/ACP Connector/main.js +31 -0
  35. package/dist/ACP Connector/main.js.map +1 -0
  36. package/dist/ACP Connector/official-kernel/admission-fence.d.ts +10 -0
  37. package/dist/ACP Connector/official-kernel/admission-fence.js +52 -0
  38. package/dist/ACP Connector/official-kernel/admission-fence.js.map +1 -0
  39. package/dist/ACP Connector/official-kernel/context.d.ts +3 -0
  40. package/dist/ACP Connector/official-kernel/context.js +52 -0
  41. package/dist/ACP Connector/official-kernel/context.js.map +1 -0
  42. package/dist/ACP Connector/official-kernel/errors.d.ts +5 -0
  43. package/dist/ACP Connector/official-kernel/errors.js +39 -0
  44. package/dist/ACP Connector/official-kernel/errors.js.map +1 -0
  45. package/dist/ACP Connector/official-kernel/identity.d.ts +3 -0
  46. package/dist/ACP Connector/official-kernel/identity.js +17 -0
  47. package/dist/ACP Connector/official-kernel/identity.js.map +1 -0
  48. package/dist/ACP Connector/official-kernel/json-rpc.d.ts +34 -0
  49. package/dist/ACP Connector/official-kernel/json-rpc.js +26 -0
  50. package/dist/ACP Connector/official-kernel/json-rpc.js.map +1 -0
  51. package/dist/ACP Connector/official-kernel/kernel-compat-lifecycle.d.ts +115 -0
  52. package/dist/ACP Connector/official-kernel/kernel-compat-lifecycle.js +1904 -0
  53. package/dist/ACP Connector/official-kernel/kernel-compat-lifecycle.js.map +1 -0
  54. package/dist/ACP Connector/official-kernel/kernel-compat-pins.d.ts +14 -0
  55. package/dist/ACP Connector/official-kernel/kernel-compat-pins.js +29 -0
  56. package/dist/ACP Connector/official-kernel/kernel-compat-pins.js.map +1 -0
  57. package/dist/ACP Connector/official-kernel/kernel-compat-rc01-recipe.d.ts +2 -0
  58. package/dist/ACP Connector/official-kernel/kernel-compat-rc01-recipe.js +32 -0
  59. package/dist/ACP Connector/official-kernel/kernel-compat-rc01-recipe.js.map +1 -0
  60. package/dist/ACP Connector/official-kernel/kernel.d.ts +3 -0
  61. package/dist/ACP Connector/official-kernel/kernel.js +12 -0
  62. package/dist/ACP Connector/official-kernel/kernel.js.map +1 -0
  63. package/dist/ACP Connector/official-kernel/login.d.ts +1 -0
  64. package/dist/ACP Connector/official-kernel/login.js +73 -0
  65. package/dist/ACP Connector/official-kernel/login.js.map +1 -0
  66. package/dist/ACP Connector/official-kernel/mcp-rewrite.d.ts +1 -0
  67. package/dist/ACP Connector/official-kernel/mcp-rewrite.js +39 -0
  68. package/dist/ACP Connector/official-kernel/mcp-rewrite.js.map +1 -0
  69. package/dist/ACP Connector/official-kernel/mode-map.d.ts +5 -0
  70. package/dist/ACP Connector/official-kernel/mode-map.js +35 -0
  71. package/dist/ACP Connector/official-kernel/mode-map.js.map +1 -0
  72. package/dist/ACP Connector/official-kernel/ndjson.d.ts +3 -0
  73. package/dist/ACP Connector/official-kernel/ndjson.js +29 -0
  74. package/dist/ACP Connector/official-kernel/ndjson.js.map +1 -0
  75. package/dist/ACP Connector/official-kernel/proxy.d.ts +14 -0
  76. package/dist/ACP Connector/official-kernel/proxy.js +197 -0
  77. package/dist/ACP Connector/official-kernel/proxy.js.map +1 -0
  78. package/dist/ACP Connector/official-kernel/run.d.ts +8 -0
  79. package/dist/ACP Connector/official-kernel/run.js +22 -0
  80. package/dist/ACP Connector/official-kernel/run.js.map +1 -0
  81. package/dist/ACP Connector/official-kernel/spawn.d.ts +5 -0
  82. package/dist/ACP Connector/official-kernel/spawn.js +33 -0
  83. package/dist/ACP Connector/official-kernel/spawn.js.map +1 -0
  84. package/dist/Admission Controller/controller.d.ts +338 -0
  85. package/dist/Admission Controller/controller.js +2089 -0
  86. package/dist/Admission Controller/controller.js.map +1 -0
  87. package/dist/Admission Controller/key-derivation.d.ts +24 -0
  88. package/dist/Admission Controller/key-derivation.js +141 -0
  89. package/dist/Admission Controller/key-derivation.js.map +1 -0
  90. package/dist/Admission Controller/key-store.d.ts +8 -0
  91. package/dist/Admission Controller/key-store.js +280 -0
  92. package/dist/Admission Controller/key-store.js.map +1 -0
  93. package/dist/Admission Controller/policy-limits.d.ts +6 -0
  94. package/dist/Admission Controller/policy-limits.js +11 -0
  95. package/dist/Admission Controller/policy-limits.js.map +1 -0
  96. package/dist/Admission Controller/process-evidence.d.ts +111 -0
  97. package/dist/Admission Controller/process-evidence.js +549 -0
  98. package/dist/Admission Controller/process-evidence.js.map +1 -0
  99. package/dist/Admission Controller/runtime-config.d.ts +23 -0
  100. package/dist/Admission Controller/runtime-config.js +86 -0
  101. package/dist/Admission Controller/runtime-config.js.map +1 -0
  102. package/dist/Admission Controller/schema.d.ts +12 -0
  103. package/dist/Admission Controller/schema.js +422 -0
  104. package/dist/Admission Controller/schema.js.map +1 -0
  105. package/package.json +72 -0
  106. package/scripts/prepare-admission-state-dir.mjs +62 -0
  107. package/scripts/prepare-official-kernel-compat.mjs +387 -0
@@ -0,0 +1,172 @@
1
+ """Local-only request compatibility profile for the RC01 official kernel."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections import deque
6
+ from typing import Any, Deque, Dict, Iterator, Optional, Set, Tuple
7
+
8
+ SUPPORTED_NON_GEMINI_MODEL_IDS = frozenset(
9
+ {
10
+ "claude-sonnet-4-6",
11
+ "claude-opus-4-6-thinking",
12
+ "gpt-oss-120b-medium",
13
+ }
14
+ )
15
+
16
+ _MAX_OUTPUT_TOKENS_BY_MODEL_ID = {
17
+ "claude-sonnet-4-6": 64000,
18
+ "claude-opus-4-6-thinking": 64000,
19
+ "gpt-oss-120b-medium": 32768,
20
+ }
21
+ _GPT_OSS_MODEL_ID = "gpt-oss-120b-medium"
22
+
23
+ __all__ = [
24
+ "SUPPORTED_NON_GEMINI_MODEL_IDS",
25
+ "is_catalog_model",
26
+ "transform_request",
27
+ ]
28
+
29
+
30
+ def is_catalog_model(model_id: str) -> bool:
31
+ """Return whether a raw catalog entry is supported by the local profile."""
32
+ return isinstance(model_id, str) and (
33
+ model_id.startswith("gemini") or model_id in SUPPORTED_NON_GEMINI_MODEL_IDS
34
+ )
35
+
36
+
37
+ def transform_request(model_id: str, body: Dict[str, Any]) -> Dict[str, Any]:
38
+ """Adapt a supported non-Gemini request in place and return the same body."""
39
+ if not isinstance(model_id, str) or not isinstance(body, dict):
40
+ return body
41
+ maximum = _MAX_OUTPUT_TOKENS_BY_MODEL_ID.get(model_id)
42
+ if maximum is None:
43
+ return body
44
+
45
+ _normalize_generation_config(body, maximum, model_id == _GPT_OSS_MODEL_ID)
46
+ _normalize_tool_schemas(body)
47
+ _normalize_tool_call_ids(body)
48
+ return body
49
+
50
+
51
+ def _normalize_generation_config(body: Dict[str, Any], maximum: int, gpt_oss: bool) -> None:
52
+ config = body.get("generationConfig")
53
+ if not isinstance(config, dict):
54
+ config = {}
55
+
56
+ max_output_tokens = _clamp_max_output_tokens(config.get("maxOutputTokens"), maximum)
57
+ if gpt_oss:
58
+ body["generationConfig"] = {"maxOutputTokens": max_output_tokens}
59
+ return
60
+
61
+ config["maxOutputTokens"] = max_output_tokens
62
+ body["generationConfig"] = config
63
+
64
+
65
+ def _clamp_max_output_tokens(value: Any, maximum: int) -> int:
66
+ if isinstance(value, int) and not isinstance(value, bool) and value > 0:
67
+ return min(value, maximum)
68
+ return maximum
69
+
70
+
71
+ def _normalize_tool_schemas(body: Dict[str, Any]) -> None:
72
+ for declaration in _function_declarations(body):
73
+ if "parameters" in declaration:
74
+ declaration["parameters"] = _strip_schema(declaration["parameters"])
75
+ declaration.pop("parametersJsonSchema", None)
76
+ elif "parametersJsonSchema" in declaration:
77
+ declaration["parameters"] = _strip_schema(declaration.pop("parametersJsonSchema"))
78
+
79
+
80
+ def _function_declarations(body: Dict[str, Any]) -> Iterator[Dict[str, Any]]:
81
+ tools = body.get("tools")
82
+ if isinstance(tools, dict):
83
+ tool_items = [tools]
84
+ elif isinstance(tools, list):
85
+ tool_items = tools
86
+ else:
87
+ return
88
+
89
+ for tool in tool_items:
90
+ if not isinstance(tool, dict):
91
+ continue
92
+ declarations = tool.get("functionDeclarations")
93
+ if isinstance(declarations, dict):
94
+ declarations = [declarations]
95
+ if not isinstance(declarations, list):
96
+ continue
97
+ for declaration in declarations:
98
+ if isinstance(declaration, dict):
99
+ yield declaration
100
+
101
+
102
+ def _strip_schema(value: Any) -> Any:
103
+ if isinstance(value, dict):
104
+ return {key: _strip_schema(child) for key, child in value.items() if key != "$schema"}
105
+ if isinstance(value, list):
106
+ return [_strip_schema(child) for child in value]
107
+ return value
108
+
109
+
110
+ def _normalize_tool_call_ids(body: Dict[str, Any]) -> None:
111
+ parts = list(_history_parts(body))
112
+ reserved_ids = {
113
+ call_id
114
+ for part in parts
115
+ for call_id in [_existing_id(part.get("functionCall"))]
116
+ if call_id is not None
117
+ }
118
+ pending_call_ids: Dict[str, Deque[str]] = {}
119
+ next_generated_call = 1
120
+
121
+ for part in parts:
122
+ function_call = part.get("functionCall")
123
+ if isinstance(function_call, dict):
124
+ call_id = _existing_id(function_call)
125
+ if call_id is None:
126
+ call_id, next_generated_call = _next_generated_call_id(reserved_ids, next_generated_call)
127
+ function_call["id"] = call_id
128
+ pending_call_ids.setdefault(_function_name(function_call), deque()).append(call_id)
129
+
130
+ function_response = part.get("functionResponse")
131
+ if not isinstance(function_response, dict):
132
+ continue
133
+ pending_for_name = pending_call_ids.get(_function_name(function_response))
134
+ if pending_for_name:
135
+ function_response["id"] = pending_for_name.popleft()
136
+
137
+
138
+ def _history_parts(body: Dict[str, Any]) -> Iterator[Dict[str, Any]]:
139
+ contents = body.get("contents")
140
+ if not isinstance(contents, list):
141
+ return
142
+
143
+ for content in contents:
144
+ if not isinstance(content, dict):
145
+ continue
146
+ parts = content.get("parts")
147
+ if not isinstance(parts, list):
148
+ continue
149
+ for part in parts:
150
+ if isinstance(part, dict):
151
+ yield part
152
+
153
+
154
+ def _existing_id(payload: Any) -> Optional[str]:
155
+ if not isinstance(payload, dict):
156
+ return None
157
+ value = payload.get("id")
158
+ return value if isinstance(value, str) and value else None
159
+
160
+
161
+ def _function_name(payload: Dict[str, Any]) -> str:
162
+ name = payload.get("name")
163
+ return name if isinstance(name, str) else ""
164
+
165
+
166
+ def _next_generated_call_id(reserved_ids: Set[str], next_index: int) -> Tuple[str, int]:
167
+ while True:
168
+ candidate = f"acp-tool-{next_index}"
169
+ next_index += 1
170
+ if candidate not in reserved_ids:
171
+ reserved_ids.add(candidate)
172
+ return candidate, next_index
@@ -0,0 +1,6 @@
1
+ export declare const PASEO_DAEMON_CONTEXT_OPEN = "[Paseo daemon system context]";
2
+ export declare const PASEO_DAEMON_CONTEXT_CLOSE = "[/Paseo daemon system context]";
3
+ export declare function resolvePaseoHome(environment?: NodeJS.ProcessEnv): string;
4
+ export declare function readPaseoDaemonAppendSystemPrompt(environment?: NodeJS.ProcessEnv): Promise<string>;
5
+ export declare function withPaseoDaemonSystemContext(promptText: string, environment?: NodeJS.ProcessEnv): Promise<string>;
6
+ export declare function wrapPaseoDaemonContextBlock(append: string): string;
@@ -0,0 +1,83 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import * as os from "node:os";
3
+ import path from "node:path";
4
+ const MAX_PASEO_APPEND_CHARS = 200_000;
5
+ const PASEO_APPEND_RETRY_ATTEMPTS = 25;
6
+ const PASEO_APPEND_RETRY_DELAY_MS = 20;
7
+ export const PASEO_DAEMON_CONTEXT_OPEN = "[Paseo daemon system context]";
8
+ export const PASEO_DAEMON_CONTEXT_CLOSE = "[/Paseo daemon system context]";
9
+ async function findPaseoAgentState(dir, fileName, depth = 4) {
10
+ if (depth < 0)
11
+ return undefined;
12
+ let entries;
13
+ try {
14
+ entries = await readdir(dir, { withFileTypes: true });
15
+ }
16
+ catch {
17
+ return undefined;
18
+ }
19
+ for (const entry of entries) {
20
+ const child = path.join(dir, entry.name);
21
+ if (entry.isFile() && entry.name === fileName)
22
+ return child;
23
+ }
24
+ for (const entry of entries) {
25
+ if (!entry.isDirectory())
26
+ continue;
27
+ const found = await findPaseoAgentState(path.join(dir, entry.name), fileName, depth - 1);
28
+ if (found)
29
+ return found;
30
+ }
31
+ return undefined;
32
+ }
33
+ function delay(ms) {
34
+ return new Promise((resolve) => setTimeout(resolve, ms));
35
+ }
36
+ export function resolvePaseoHome(environment = process.env) {
37
+ const configured = environment.PASEO_HOME?.trim();
38
+ if (configured) {
39
+ if (configured === "~")
40
+ return os.homedir();
41
+ if (configured.startsWith("~/") || configured.startsWith("~\\")) {
42
+ return path.join(os.homedir(), configured.slice(2));
43
+ }
44
+ return configured;
45
+ }
46
+ const homeDir = environment.HOME || os.homedir();
47
+ return homeDir ? path.join(homeDir, ".paseo") : "";
48
+ }
49
+ export async function readPaseoDaemonAppendSystemPrompt(environment = process.env) {
50
+ const home = resolvePaseoHome(environment);
51
+ const agentId = environment.PASEO_AGENT_ID;
52
+ if (!home || !agentId || agentId.includes("/") || agentId.includes("\\"))
53
+ return "";
54
+ for (let attempt = 0; attempt < PASEO_APPEND_RETRY_ATTEMPTS; attempt++) {
55
+ try {
56
+ const statePath = await findPaseoAgentState(path.join(home, "agents"), `${agentId}.json`);
57
+ if (statePath) {
58
+ const state = JSON.parse(await readFile(statePath, "utf8"));
59
+ const append = state.persistence?.metadata?.daemonAppendSystemPrompt;
60
+ if (typeof append === "string" && append.trim()) {
61
+ return append.trim().slice(0, MAX_PASEO_APPEND_CHARS);
62
+ }
63
+ }
64
+ }
65
+ catch {
66
+ // Paseo may still be writing the state file. Retry briefly, then fail open.
67
+ }
68
+ if (attempt < PASEO_APPEND_RETRY_ATTEMPTS - 1) {
69
+ await delay(PASEO_APPEND_RETRY_DELAY_MS);
70
+ }
71
+ }
72
+ return "";
73
+ }
74
+ export async function withPaseoDaemonSystemContext(promptText, environment = process.env) {
75
+ const append = await readPaseoDaemonAppendSystemPrompt(environment);
76
+ if (!append)
77
+ return promptText;
78
+ return [PASEO_DAEMON_CONTEXT_OPEN, append, PASEO_DAEMON_CONTEXT_CLOSE, "", promptText].join("\n");
79
+ }
80
+ export function wrapPaseoDaemonContextBlock(append) {
81
+ return [PASEO_DAEMON_CONTEXT_OPEN, append, PASEO_DAEMON_CONTEXT_CLOSE].join("\n");
82
+ }
83
+ //# sourceMappingURL=paseo-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paseo-context.js","sourceRoot":"","sources":["../../../../ACP Connector/acp/session/paseo-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /** Thrown when a claim is aborted; unwinds the turn pipeline to its reporter. */
2
+ export declare class TurnCancelled extends Error {
3
+ constructor(message?: string);
4
+ }
5
+ export declare function isTurnCancelled(error: unknown): boolean;
6
+ /**
7
+ * Run `fn` for an abort signal, now or later. Plain `addEventListener` never
8
+ * fires for a signal that is already aborted, which repeatedly produced turns
9
+ * that ran after they had been cancelled.
10
+ */
11
+ export declare function onAbort(signal: AbortSignal, fn: () => void): () => void;
12
+ export type TurnKind = "foreground" | "queued" | "steer";
13
+ /** A request's ownership of (or reservation on) the session's single turn slot. */
14
+ export declare class TurnClaim {
15
+ readonly kind: TurnKind;
16
+ /**
17
+ * For claimed queued prompts, the client-visible queue id. Lets a targeted
18
+ * `session/cancel` find the turn its queued item grew into, so it aborts
19
+ * exactly that claim instead of falling back to a session-wide abort.
20
+ */
21
+ readonly tag?: string;
22
+ private readonly controller;
23
+ private isReleased;
24
+ constructor(kind: TurnKind, parent?: AbortSignal, tag?: string);
25
+ get signal(): AbortSignal;
26
+ get aborted(): boolean;
27
+ get released(): boolean;
28
+ abort(): void;
29
+ throwIfAborted(): void;
30
+ /** @internal — the scheduler marks a claim finished exactly once. */
31
+ markReleased(): boolean;
32
+ }
33
+ /**
34
+ * Await `promise`, rejecting with `TurnCancelled` as soon as `signal` aborts.
35
+ *
36
+ * The single implementation behind invariant I4: every client-bound delivery
37
+ * goes through here (directly, or via `raceClaim` for turn claims), so a
38
+ * client transport that never settles unwinds on cancel/close instead of
39
+ * pinning the turn slot or the queue-preparation chain.
40
+ */
41
+ export declare function raceSignal<T>(promise: Promise<T>, signal: AbortSignal): Promise<T>;
42
+ /** Await `promise`, rejecting as soon as `claim` is aborted. */
43
+ export declare function raceClaim<T>(promise: Promise<T>, claim: TurnClaim): Promise<T>;
44
+ /** Lazily attach a scheduler to a session-like object. */
45
+ export declare function turnsOf(session: {
46
+ turns?: TurnScheduler;
47
+ }): TurnScheduler;
48
+ export declare class TurnScheduler {
49
+ private active?;
50
+ /** Steer reservations in FIFO order; the head is next to take the slot. */
51
+ private reservations;
52
+ private waiters;
53
+ private closed;
54
+ /** True when a turn is running or a steer has reserved the next turn. */
55
+ busy(): boolean;
56
+ get activeClaim(): TurnClaim | undefined;
57
+ /**
58
+ * Take the slot for a request that found the session idle. Synchronous by
59
+ * design: no await may separate the busy check from the claim (I1).
60
+ */
61
+ claimIdle(kind: Exclude<TurnKind, "steer">, parent?: AbortSignal, tag?: string): TurnClaim;
62
+ /**
63
+ * Reserve the next turn for a steer. Synchronous, so the claim — and its
64
+ * abort controller — exist before the first await (I1, I2). The reservation
65
+ * keeps the session `busy()`, so no queued follow-up can slip in front.
66
+ */
67
+ reserveSteer(parent?: AbortSignal): TurnClaim;
68
+ /**
69
+ * Wait for `claim` to reach the head of the reservation queue, stop whatever
70
+ * is running, and hand it the slot. Throws `TurnCancelled` if the claim is
71
+ * aborted at any point, including while the backend is being killed.
72
+ *
73
+ * A reservation stays in the queue until it is *released*, not merely until
74
+ * it is promoted. Otherwise a later steer would reach the head while an
75
+ * earlier one was running and displace it before it ever reached the backend.
76
+ */
77
+ promote(claim: TurnClaim, cancelActive: () => Promise<void>): Promise<void>;
78
+ /**
79
+ * Finish a claim. Idempotent, and safe to call from a `finally` on any exit
80
+ * path — success, cancellation, or setup failure.
81
+ */
82
+ release(claim: TurnClaim): void;
83
+ /** Abort every live claim (`session/cancel`). Queued items are untouched. */
84
+ abortAll(): void;
85
+ /** Abort everything and refuse further claims (close / delete / evict). */
86
+ close(): void;
87
+ private change;
88
+ /** Resolve on the next ownership change, or reject if `claim` is aborted. */
89
+ private nextChange;
90
+ }
@@ -0,0 +1,247 @@
1
+ // Turn ownership for a single ACP session.
2
+ //
3
+ // One session may only run one prompt turn against the agy backend at a time.
4
+ // Requests compete for that slot in three ways: an idle request claims it
5
+ // directly, a `queue` request waits in FIFO, and a `steer` request reserves it
6
+ // and displaces whatever is running.
7
+ //
8
+ // The invariants below exist because ad-hoc ownership flags spread across the
9
+ // prompt handlers made every `await` a window where the session could be
10
+ // half-owned, and every such window was a cancellation bug:
11
+ //
12
+ // I1. A claim is one object that exists from admission until the turn is fully
13
+ // finished — including a steer's wait for the previous turn to stop. There
14
+ // is no phase where a request owns the session but has no claim.
15
+ // I2. Every claim carries its AbortController from the moment it is created,
16
+ // so cancel/close/evict always have something to abort in every phase.
17
+ // I3. Cancellation unwinds by throwing (`TurnCancelled`), not by polling a
18
+ // flag after each await. Callers cannot forget to re-check.
19
+ // I4. Every client-bound delivery is raced against the turn's claim (or a
20
+ // queued item's controller). agy's prompt loop awaits each update
21
+ // callback, so a client transport that never settles would otherwise pin
22
+ // the slot forever — killing the backend cannot settle a wedged notify.
23
+ /** Thrown when a claim is aborted; unwinds the turn pipeline to its reporter. */
24
+ export class TurnCancelled extends Error {
25
+ constructor(message = "turn cancelled") {
26
+ super(message);
27
+ this.name = "TurnCancelled";
28
+ }
29
+ }
30
+ export function isTurnCancelled(error) {
31
+ const name = error?.name;
32
+ return error instanceof TurnCancelled || name === "TurnCancelled" || name === "AbortError";
33
+ }
34
+ /**
35
+ * Run `fn` for an abort signal, now or later. Plain `addEventListener` never
36
+ * fires for a signal that is already aborted, which repeatedly produced turns
37
+ * that ran after they had been cancelled.
38
+ */
39
+ export function onAbort(signal, fn) {
40
+ if (signal.aborted) {
41
+ fn();
42
+ return () => { };
43
+ }
44
+ signal.addEventListener("abort", fn, { once: true });
45
+ return () => signal.removeEventListener("abort", fn);
46
+ }
47
+ /** A request's ownership of (or reservation on) the session's single turn slot. */
48
+ export class TurnClaim {
49
+ kind;
50
+ /**
51
+ * For claimed queued prompts, the client-visible queue id. Lets a targeted
52
+ * `session/cancel` find the turn its queued item grew into, so it aborts
53
+ * exactly that claim instead of falling back to a session-wide abort.
54
+ */
55
+ tag;
56
+ controller = new AbortController();
57
+ isReleased = false;
58
+ constructor(kind, parent, tag) {
59
+ this.kind = kind;
60
+ this.tag = tag;
61
+ // A request-scoped signal (v1 `session/prompt` cancellation) folds into the
62
+ // claim, so downstream code only ever consults one signal.
63
+ if (parent)
64
+ onAbort(parent, () => this.abort());
65
+ }
66
+ get signal() {
67
+ return this.controller.signal;
68
+ }
69
+ get aborted() {
70
+ return this.controller.signal.aborted;
71
+ }
72
+ get released() {
73
+ return this.isReleased;
74
+ }
75
+ abort() {
76
+ if (!this.controller.signal.aborted)
77
+ this.controller.abort(new TurnCancelled());
78
+ }
79
+ throwIfAborted() {
80
+ if (this.aborted)
81
+ throw new TurnCancelled();
82
+ }
83
+ /** @internal — the scheduler marks a claim finished exactly once. */
84
+ markReleased() {
85
+ if (this.isReleased)
86
+ return false;
87
+ this.isReleased = true;
88
+ return true;
89
+ }
90
+ }
91
+ /**
92
+ * Await `promise`, rejecting with `TurnCancelled` as soon as `signal` aborts.
93
+ *
94
+ * The single implementation behind invariant I4: every client-bound delivery
95
+ * goes through here (directly, or via `raceClaim` for turn claims), so a
96
+ * client transport that never settles unwinds on cancel/close instead of
97
+ * pinning the turn slot or the queue-preparation chain.
98
+ */
99
+ export function raceSignal(promise, signal) {
100
+ return new Promise((resolve, reject) => {
101
+ if (signal.aborted) {
102
+ reject(new TurnCancelled());
103
+ return;
104
+ }
105
+ const off = onAbort(signal, () => reject(new TurnCancelled()));
106
+ promise.then((value) => {
107
+ off();
108
+ resolve(value);
109
+ }, (error) => {
110
+ off();
111
+ reject(error);
112
+ });
113
+ });
114
+ }
115
+ /** Await `promise`, rejecting as soon as `claim` is aborted. */
116
+ export function raceClaim(promise, claim) {
117
+ return raceSignal(promise, claim.signal);
118
+ }
119
+ /** Lazily attach a scheduler to a session-like object. */
120
+ export function turnsOf(session) {
121
+ return (session.turns ??= new TurnScheduler());
122
+ }
123
+ export class TurnScheduler {
124
+ active;
125
+ /** Steer reservations in FIFO order; the head is next to take the slot. */
126
+ reservations = [];
127
+ waiters = new Set();
128
+ closed = false;
129
+ /** True when a turn is running or a steer has reserved the next turn. */
130
+ busy() {
131
+ return this.active !== undefined || this.reservations.length > 0;
132
+ }
133
+ get activeClaim() {
134
+ return this.active;
135
+ }
136
+ /**
137
+ * Take the slot for a request that found the session idle. Synchronous by
138
+ * design: no await may separate the busy check from the claim (I1).
139
+ */
140
+ claimIdle(kind, parent, tag) {
141
+ if (this.busy()) {
142
+ // Callers must check `busy()` with no await in between; overwriting the
143
+ // slot here would silently orphan a running turn.
144
+ throw new Error("cannot claim a busy session turn slot");
145
+ }
146
+ const claim = new TurnClaim(kind, parent, tag);
147
+ this.active = claim;
148
+ if (this.closed)
149
+ claim.abort();
150
+ return claim;
151
+ }
152
+ /**
153
+ * Reserve the next turn for a steer. Synchronous, so the claim — and its
154
+ * abort controller — exist before the first await (I1, I2). The reservation
155
+ * keeps the session `busy()`, so no queued follow-up can slip in front.
156
+ */
157
+ reserveSteer(parent) {
158
+ const claim = new TurnClaim("steer", parent);
159
+ this.reservations.push(claim);
160
+ if (this.closed)
161
+ claim.abort();
162
+ return claim;
163
+ }
164
+ /**
165
+ * Wait for `claim` to reach the head of the reservation queue, stop whatever
166
+ * is running, and hand it the slot. Throws `TurnCancelled` if the claim is
167
+ * aborted at any point, including while the backend is being killed.
168
+ *
169
+ * A reservation stays in the queue until it is *released*, not merely until
170
+ * it is promoted. Otherwise a later steer would reach the head while an
171
+ * earlier one was running and displace it before it ever reached the backend.
172
+ */
173
+ async promote(claim, cancelActive) {
174
+ claim.throwIfAborted();
175
+ while (this.reservations[0] !== claim) {
176
+ if (!this.reservations.includes(claim))
177
+ throw new TurnCancelled();
178
+ await this.nextChange(claim);
179
+ }
180
+ const displaced = this.active;
181
+ if (displaced) {
182
+ displaced.abort();
183
+ // Cancellable while the backend shuts down: a stop arriving during a slow
184
+ // kill must not be swallowed and then followed by the replacement turn.
185
+ await raceClaim(cancelActive(), claim);
186
+ while (this.active)
187
+ await this.nextChange(claim);
188
+ }
189
+ claim.throwIfAborted();
190
+ if (this.reservations[0] !== claim)
191
+ throw new TurnCancelled();
192
+ this.active = claim;
193
+ this.change();
194
+ }
195
+ /**
196
+ * Finish a claim. Idempotent, and safe to call from a `finally` on any exit
197
+ * path — success, cancellation, or setup failure.
198
+ */
199
+ release(claim) {
200
+ if (!claim.markReleased())
201
+ return;
202
+ if (this.active === claim)
203
+ this.active = undefined;
204
+ const idx = this.reservations.indexOf(claim);
205
+ if (idx >= 0)
206
+ this.reservations.splice(idx, 1);
207
+ this.change();
208
+ }
209
+ /** Abort every live claim (`session/cancel`). Queued items are untouched. */
210
+ abortAll() {
211
+ this.active?.abort();
212
+ for (const reservation of [...this.reservations])
213
+ reservation.abort();
214
+ }
215
+ /** Abort everything and refuse further claims (close / delete / evict). */
216
+ close() {
217
+ this.closed = true;
218
+ this.abortAll();
219
+ this.change();
220
+ }
221
+ change() {
222
+ const pending = [...this.waiters];
223
+ this.waiters.clear();
224
+ for (const waiter of pending)
225
+ waiter();
226
+ }
227
+ /** Resolve on the next ownership change, or reject if `claim` is aborted. */
228
+ nextChange(claim) {
229
+ return new Promise((resolve, reject) => {
230
+ if (claim.aborted) {
231
+ reject(new TurnCancelled());
232
+ return;
233
+ }
234
+ let off = () => { };
235
+ const waiter = () => {
236
+ off();
237
+ resolve();
238
+ };
239
+ this.waiters.add(waiter);
240
+ off = onAbort(claim.signal, () => {
241
+ this.waiters.delete(waiter);
242
+ reject(new TurnCancelled());
243
+ });
244
+ });
245
+ }
246
+ }
247
+ //# sourceMappingURL=turn-scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"turn-scheduler.js","sourceRoot":"","sources":["../../../../ACP Connector/acp/session/turn-scheduler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Request-scoped stdin write fence used by Admission around one official
3
+ * `session/prompt` dispatch. The official kernel owns process creation; this
4
+ * boundary only sequences prepare → write → settle.
5
+ */
6
+ export interface AgyAdmissionDispatchBoundary {
7
+ prepare(processId: number): void;
8
+ beforePromptWrite(): void;
9
+ afterPromptWrite(): void;
10
+ }
11
+ export declare class AgyCliError extends Error {
12
+ readonly command: string[];
13
+ readonly exitCode: number | null;
14
+ readonly stderr: string;
15
+ constructor(message: string, command: string[], exitCode: number | null, stderr: string);
16
+ }
17
+ /** Provider failure proven terminal by the official kernel or a classified 5xx. */
18
+ export declare class AgyTerminalProviderError extends AgyCliError {
19
+ }
@@ -0,0 +1,16 @@
1
+ export class AgyCliError extends Error {
2
+ command;
3
+ exitCode;
4
+ stderr;
5
+ constructor(message, command, exitCode, stderr) {
6
+ super(message);
7
+ this.name = "AgyCliError";
8
+ this.command = command;
9
+ this.exitCode = exitCode;
10
+ this.stderr = stderr;
11
+ }
12
+ }
13
+ /** Provider failure proven terminal by the official kernel or a classified 5xx. */
14
+ export class AgyTerminalProviderError extends AgyCliError {
15
+ }
16
+ //# sourceMappingURL=dispatch-boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch-boundary.js","sourceRoot":"","sources":["../../../ACP Connector/admission/dispatch-boundary.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC3B,OAAO,CAAW;IAClB,QAAQ,CAAgB;IACxB,MAAM,CAAS;IAExB,YAAY,OAAe,EAAE,OAAiB,EAAE,QAAuB,EAAE,MAAc;QACrF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,OAAO,wBAAyB,SAAQ,WAAW;CAAG"}