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,18 @@
1
+ export type ProviderFailureCategory = "provider_capacity" | "quota" | "auth" | "permission" | "timeout" | "transport" | "unknown";
2
+ export interface ProviderFailureInput {
3
+ httpStatus?: number;
4
+ code?: string;
5
+ reason?: string;
6
+ timeout?: boolean;
7
+ }
8
+ export interface ClassifiedProviderFailure {
9
+ category: ProviderFailureCategory;
10
+ httpStatus: number | undefined;
11
+ code: string | undefined;
12
+ reason: string | undefined;
13
+ }
14
+ /**
15
+ * Classify the few provider signals v2 can safely retain. Unknown source text
16
+ * is deliberately discarded before an event or report can persist it.
17
+ */
18
+ export declare function classifyProviderFailure(input: ProviderFailureInput): ClassifiedProviderFailure;
@@ -0,0 +1,46 @@
1
+ const SAFE_CODES = new Set([
2
+ "UNAVAILABLE",
3
+ "MODEL_CAPACITY_EXHAUSTED",
4
+ "QUOTA_EXHAUSTED",
5
+ "UNAUTHENTICATED",
6
+ "PERMISSION_DENIED"
7
+ ]);
8
+ /**
9
+ * Classify the few provider signals v2 can safely retain. Unknown source text
10
+ * is deliberately discarded before an event or report can persist it.
11
+ */
12
+ export function classifyProviderFailure(input) {
13
+ const httpStatus = validHttpStatus(input.httpStatus);
14
+ const code = safeSignal(input.code);
15
+ const reason = safeSignal(input.reason);
16
+ if (httpStatus === 503 && (isCapacitySignal(code) || isCapacitySignal(reason))) {
17
+ return classified("provider_capacity", httpStatus, code, reason);
18
+ }
19
+ if (httpStatus === 429 && (code === "QUOTA_EXHAUSTED" || reason === "QUOTA_EXHAUSTED")) {
20
+ return classified("quota", httpStatus, code, reason);
21
+ }
22
+ if (httpStatus === 401 || code === "UNAUTHENTICATED" || reason === "UNAUTHENTICATED") {
23
+ return classified("auth", httpStatus, code, reason);
24
+ }
25
+ if (httpStatus === 403 || code === "PERMISSION_DENIED" || reason === "PERMISSION_DENIED") {
26
+ return classified("permission", httpStatus, code, reason);
27
+ }
28
+ if (httpStatus !== undefined)
29
+ return classified("transport", httpStatus, undefined, undefined);
30
+ if (input.timeout === true)
31
+ return classified("timeout", httpStatus, code, reason);
32
+ return classified("unknown", undefined, undefined, undefined);
33
+ }
34
+ function classified(category, httpStatus, code, reason) {
35
+ return { category, httpStatus, code, reason };
36
+ }
37
+ function validHttpStatus(value) {
38
+ return Number.isInteger(value) && value >= 100 && value <= 599 ? value : undefined;
39
+ }
40
+ function safeSignal(value) {
41
+ return value !== undefined && SAFE_CODES.has(value) ? value : undefined;
42
+ }
43
+ function isCapacitySignal(value) {
44
+ return value === "UNAVAILABLE" || value === "MODEL_CAPACITY_EXHAUSTED";
45
+ }
46
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../ACP Connector/admission/errors.ts"],"names":[],"mappings":"AAuBA,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,aAAa;IACb,0BAA0B;IAC1B,iBAAiB;IACjB,iBAAiB;IACjB,mBAAmB;CACpB,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAA2B;IACjE,MAAM,UAAU,GAAG,eAAe,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAExC,IAAI,UAAU,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QAC/E,OAAO,UAAU,CAAC,mBAAmB,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,UAAU,KAAK,GAAG,IAAI,CAAC,IAAI,KAAK,iBAAiB,IAAI,MAAM,KAAK,iBAAiB,CAAC,EAAE,CAAC;QACvF,OAAO,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACvD,CAAC;IACD,IAAI,UAAU,KAAK,GAAG,IAAI,IAAI,KAAK,iBAAiB,IAAI,MAAM,KAAK,iBAAiB,EAAE,CAAC;QACrF,OAAO,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,UAAU,KAAK,GAAG,IAAI,IAAI,KAAK,mBAAmB,IAAI,MAAM,KAAK,mBAAmB,EAAE,CAAC;QACzF,OAAO,UAAU,CAAC,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,UAAU,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC/F,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI;QAAE,OAAO,UAAU,CAAC,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACnF,OAAO,UAAU,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;AAChE,CAAC;AAED,SAAS,UAAU,CACjB,QAAiC,EACjC,UAA8B,EAC9B,IAAwB,EACxB,MAA0B;IAE1B,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,eAAe,CAAC,KAAyB;IAChD,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAM,IAAI,GAAG,IAAI,KAAM,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvF,CAAC;AAED,SAAS,UAAU,CAAC,KAAyB;IAC3C,OAAO,KAAK,KAAK,SAAS,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1E,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAyB;IACjD,OAAO,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,0BAA0B,CAAC;AACzE,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { type LinuxProcessEvidenceReaders, type LinuxProcessIdentity, type LinuxProcessIdentityState } from "../../Admission Controller/process-evidence.js";
2
+ /** A connector-local owner token paired with immutable Linux process evidence. */
3
+ export interface LinuxConnectorOwnerIdentity extends LinuxProcessIdentity {
4
+ readonly ownerInstanceId: string;
5
+ readonly createdAt: string;
6
+ }
7
+ /** Conservative result of checking a persisted connector owner record. */
8
+ export type LinuxConnectorOwnerIdentityState = LinuxProcessIdentityState;
9
+ /** Injectable nondeterministic dependencies keep tests away from runtime state and real processes. */
10
+ export interface OwnerInstanceDependencies {
11
+ readonly createOwnerInstanceId?: () => string;
12
+ readonly now?: () => Date;
13
+ }
14
+ export declare class ConnectorOwnerIdentityError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ /**
18
+ * Capture the current connector owner record without persisting it. Callers
19
+ * must supply process-evidence readers explicitly so the boundary is visible.
20
+ */
21
+ export declare function captureLinuxConnectorOwnerIdentity(pid: number, readers: LinuxProcessEvidenceReaders, dependencies?: OwnerInstanceDependencies): LinuxConnectorOwnerIdentity;
22
+ /**
23
+ * Re-observe the persisted record's PID and return false for every malformed,
24
+ * unavailable, or mismatched condition. It never reads or writes runtime files.
25
+ */
26
+ export declare function verifyPersistedLinuxConnectorOwnerIdentity(persisted: unknown, readers: LinuxProcessEvidenceReaders): boolean;
27
+ /**
28
+ * Re-observe a persisted connector owner without treating PID existence as
29
+ * ownership. Malformed owner records and unreadable procfs both fail closed.
30
+ */
31
+ export declare function observePersistedLinuxConnectorOwnerIdentity(persisted: unknown, readers: LinuxProcessEvidenceReaders): LinuxConnectorOwnerIdentityState;
@@ -0,0 +1,105 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { captureLinuxProcessIdentity, isSameLinuxProcessIdentity, observeLinuxProcessIdentity } from "../../Admission Controller/process-evidence.js";
3
+ const OWNER_INSTANCE_ID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
4
+ const ISO_UTC_TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
5
+ export class ConnectorOwnerIdentityError extends Error {
6
+ constructor(message) {
7
+ super(`connector owner identity error: ${message}`);
8
+ this.name = "ConnectorOwnerIdentityError";
9
+ }
10
+ }
11
+ /**
12
+ * Capture the current connector owner record without persisting it. Callers
13
+ * must supply process-evidence readers explicitly so the boundary is visible.
14
+ */
15
+ export function captureLinuxConnectorOwnerIdentity(pid, readers, dependencies = {}) {
16
+ const ownerInstanceId = createOwnerInstanceId(dependencies.createOwnerInstanceId ?? randomUUID);
17
+ const createdAt = captureTimestamp(dependencies.now ?? (() => new Date()));
18
+ const processIdentity = captureLinuxProcessIdentity(pid, readers);
19
+ return Object.freeze({
20
+ ownerInstanceId,
21
+ createdAt,
22
+ ...processIdentity
23
+ });
24
+ }
25
+ /**
26
+ * Re-observe the persisted record's PID and return false for every malformed,
27
+ * unavailable, or mismatched condition. It never reads or writes runtime files.
28
+ */
29
+ export function verifyPersistedLinuxConnectorOwnerIdentity(persisted, readers) {
30
+ return observePersistedLinuxConnectorOwnerIdentity(persisted, readers) === "same";
31
+ }
32
+ /**
33
+ * Re-observe a persisted connector owner without treating PID existence as
34
+ * ownership. Malformed owner records and unreadable procfs both fail closed.
35
+ */
36
+ export function observePersistedLinuxConnectorOwnerIdentity(persisted, readers) {
37
+ const expected = normalizePersistedOwnerIdentity(persisted);
38
+ return expected === null ? "unverifiable" : observeLinuxProcessIdentity(expected, readers);
39
+ }
40
+ function createOwnerInstanceId(factory) {
41
+ let ownerInstanceId;
42
+ try {
43
+ ownerInstanceId = factory();
44
+ }
45
+ catch {
46
+ throw new ConnectorOwnerIdentityError("owner instance ID generation failed");
47
+ }
48
+ return requireOwnerInstanceId(ownerInstanceId);
49
+ }
50
+ function captureTimestamp(now) {
51
+ let value;
52
+ try {
53
+ const date = now();
54
+ value = date instanceof Date ? date.toISOString() : undefined;
55
+ }
56
+ catch {
57
+ throw new ConnectorOwnerIdentityError("creation timestamp is unavailable");
58
+ }
59
+ return requireTimestamp(value, "creation timestamp");
60
+ }
61
+ function normalizePersistedOwnerIdentity(value) {
62
+ if (!isRecord(value))
63
+ return null;
64
+ try {
65
+ const processIdentity = {
66
+ bootId: value.bootId,
67
+ pid: value.pid,
68
+ startTimeTicks: value.startTimeTicks,
69
+ pidNamespaceInode: value.pidNamespaceInode,
70
+ ppid: value.ppid,
71
+ pgrp: value.pgrp,
72
+ session: value.session
73
+ };
74
+ if (!isSameLinuxProcessIdentity(processIdentity, processIdentity))
75
+ return null;
76
+ return Object.freeze({
77
+ ownerInstanceId: requireOwnerInstanceId(value.ownerInstanceId),
78
+ createdAt: requireTimestamp(value.createdAt, "persisted timestamp"),
79
+ ...processIdentity
80
+ });
81
+ }
82
+ catch {
83
+ return null;
84
+ }
85
+ }
86
+ function requireOwnerInstanceId(value) {
87
+ if (typeof value !== "string" || !OWNER_INSTANCE_ID_PATTERN.test(value)) {
88
+ throw new ConnectorOwnerIdentityError("owner instance ID must be a canonical UUID v4");
89
+ }
90
+ return value;
91
+ }
92
+ function requireTimestamp(value, name) {
93
+ if (typeof value !== "string" || !ISO_UTC_TIMESTAMP_PATTERN.test(value)) {
94
+ throw new ConnectorOwnerIdentityError(`${name} must be a canonical UTC timestamp`);
95
+ }
96
+ const timestamp = new Date(value);
97
+ if (!Number.isFinite(timestamp.getTime()) || timestamp.toISOString() !== value) {
98
+ throw new ConnectorOwnerIdentityError(`${name} must be a valid UTC timestamp`);
99
+ }
100
+ return value;
101
+ }
102
+ function isRecord(value) {
103
+ return typeof value === "object" && value !== null && !Array.isArray(value);
104
+ }
105
+ //# sourceMappingURL=owner-instance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-instance.js","sourceRoot":"","sources":["../../../ACP Connector/admission/owner-instance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { AdmissionController, type AdmissionRuntimeReaperReaders } from "../../Admission Controller/controller.js";
2
+ import { type AdmissionRuntimeEnvironment } from "../../Admission Controller/runtime-config.js";
3
+ export interface AdmissionRuntimeOptions {
4
+ readonly reaperReaders?: AdmissionRuntimeReaperReaders;
5
+ readonly reaperIntervalMs?: number;
6
+ readonly now?: () => number;
7
+ }
8
+ export declare class AdmissionRuntimeError extends Error {
9
+ constructor(message: string);
10
+ }
11
+ export declare class AdmissionRuntime {
12
+ #private;
13
+ constructor(controller: AdmissionController, options?: AdmissionRuntimeOptions);
14
+ get controller(): AdmissionController;
15
+ close(): void;
16
+ private assertOpen;
17
+ private reapOnce;
18
+ }
19
+ /** Build the opt-in shared queue runtime and reconcile exited local seats. */
20
+ export declare function createAdmissionRuntime(environment?: AdmissionRuntimeEnvironment, options?: AdmissionRuntimeOptions): AdmissionRuntime | null;
@@ -0,0 +1,157 @@
1
+ import { closeSync, lstatSync, openSync } from "node:fs";
2
+ import { AdmissionController } from "../../Admission Controller/controller.js";
3
+ import { loadOrCreateAdmissionKey } from "../../Admission Controller/key-store.js";
4
+ import { deriveAdmissionKeyBundle, zeroAdmissionKeyBundle } from "../../Admission Controller/key-derivation.js";
5
+ import { parseAdmissionRuntimeConfig } from "../../Admission Controller/runtime-config.js";
6
+ import { nativeAdmissionStartupRecoveryReaders, recoverExitedAdmissionSeats } from "./startup-recovery.js";
7
+ const DEFAULT_RUNTIME_REAPER_INTERVAL_MS = 1_000;
8
+ const MAX_RUNTIME_REAPER_INTERVAL_MS = 4_000;
9
+ export class AdmissionRuntimeError extends Error {
10
+ constructor(message) {
11
+ super(`admission runtime error: ${message}`);
12
+ this.name = "AdmissionRuntimeError";
13
+ }
14
+ }
15
+ export class AdmissionRuntime {
16
+ #controller;
17
+ #reaperReaders;
18
+ #readNow;
19
+ #reaperTimer;
20
+ #reaping = false;
21
+ #closed = false;
22
+ constructor(controller, options = {}) {
23
+ this.#controller = controller;
24
+ this.#reaperReaders = options.reaperReaders ?? nativeAdmissionStartupRecoveryReaders;
25
+ this.#readNow = options.now ?? Date.now;
26
+ const intervalMs = normalizeReaperIntervalMs(options.reaperIntervalMs);
27
+ this.#reaperTimer = setInterval(() => this.reapOnce(), intervalMs);
28
+ this.#reaperTimer.unref?.();
29
+ }
30
+ get controller() {
31
+ this.assertOpen();
32
+ return this.#controller;
33
+ }
34
+ close() {
35
+ if (this.#closed)
36
+ return;
37
+ this.#closed = true;
38
+ if (this.#reaperTimer !== undefined) {
39
+ clearInterval(this.#reaperTimer);
40
+ this.#reaperTimer = undefined;
41
+ }
42
+ this.#controller.close();
43
+ }
44
+ assertOpen() {
45
+ if (this.#closed)
46
+ throw new AdmissionRuntimeError("runtime is closed");
47
+ }
48
+ reapOnce() {
49
+ if (this.#closed || this.#reaping)
50
+ return;
51
+ this.#reaping = true;
52
+ try {
53
+ this.#controller.reapSuspects(readNow(this.#readNow), this.#reaperReaders);
54
+ }
55
+ catch {
56
+ // Reaper evidence is best-effort and fail-closed; startup recovery remains separate.
57
+ }
58
+ finally {
59
+ this.#reaping = false;
60
+ }
61
+ }
62
+ }
63
+ /** Build the opt-in shared queue runtime and reconcile exited local seats. */
64
+ export function createAdmissionRuntime(environment = process.env, options = {}) {
65
+ const config = parseAdmissionRuntimeConfig(environment);
66
+ if (!config.enabled)
67
+ return null;
68
+ rejectUnsafeExistingDatabase(config.databasePath);
69
+ const key = loadOrCreateAdmissionKey(config.stateDir);
70
+ let derivedKeys;
71
+ let controller;
72
+ try {
73
+ derivedKeys = deriveAdmissionKeyBundle(key);
74
+ ensureSecureDatabase(config);
75
+ controller = new AdmissionController({
76
+ databasePath: config.databasePath,
77
+ policy: config.policy,
78
+ encryptionKey: derivedKeys.encryption,
79
+ contentFingerprintKey: derivedKeys.contentFingerprint
80
+ });
81
+ controller.claimDurablePolicy(config.policy, config.agentId, Date.now());
82
+ recoverExitedAdmissionSeats(controller);
83
+ return new AdmissionRuntime(controller, options);
84
+ }
85
+ catch (error) {
86
+ try {
87
+ controller?.close();
88
+ }
89
+ catch {
90
+ // Preserve the factory failure while releasing any controller-owned copies.
91
+ }
92
+ throw error;
93
+ }
94
+ finally {
95
+ if (derivedKeys !== undefined)
96
+ zeroAdmissionKeyBundle(derivedKeys);
97
+ key.fill(0);
98
+ }
99
+ }
100
+ function normalizeReaperIntervalMs(value) {
101
+ const intervalMs = value ?? DEFAULT_RUNTIME_REAPER_INTERVAL_MS;
102
+ if (!Number.isSafeInteger(intervalMs) ||
103
+ intervalMs < 1 ||
104
+ intervalMs > MAX_RUNTIME_REAPER_INTERVAL_MS) {
105
+ throw new AdmissionRuntimeError("runtime reaper interval is invalid");
106
+ }
107
+ return intervalMs;
108
+ }
109
+ function readNow(now) {
110
+ const value = now();
111
+ if (!Number.isSafeInteger(value) || value < 0) {
112
+ throw new AdmissionRuntimeError("runtime reaper clock is invalid");
113
+ }
114
+ return value;
115
+ }
116
+ function ensureSecureDatabase(config) {
117
+ try {
118
+ const file = openSync(config.databasePath, "wx", 0o600);
119
+ closeSync(file);
120
+ }
121
+ catch (error) {
122
+ if (!hasErrorCode(error, "EEXIST")) {
123
+ throw new AdmissionRuntimeError("could not create the admission database");
124
+ }
125
+ }
126
+ assertSecureDatabase(config.databasePath);
127
+ }
128
+ function rejectUnsafeExistingDatabase(databasePath) {
129
+ try {
130
+ assertSecureDatabase(databasePath);
131
+ }
132
+ catch (error) {
133
+ if (hasErrorCode(error, "ENOENT"))
134
+ return;
135
+ throw error;
136
+ }
137
+ }
138
+ function assertSecureDatabase(databasePath) {
139
+ const stat = lstatSync(databasePath);
140
+ if (stat.isSymbolicLink() || !stat.isFile()) {
141
+ throw new AdmissionRuntimeError("admission database path must be a regular file");
142
+ }
143
+ if ((stat.mode & 0o077) !== 0) {
144
+ throw new AdmissionRuntimeError("admission database must not grant group or other access");
145
+ }
146
+ const currentUid = typeof process.getuid === "function" ? process.getuid() : undefined;
147
+ if (currentUid !== undefined && stat.uid !== currentUid) {
148
+ throw new AdmissionRuntimeError("admission database must be owned by the current user");
149
+ }
150
+ if (stat.nlink !== 1) {
151
+ throw new AdmissionRuntimeError("admission database must have exactly one link");
152
+ }
153
+ }
154
+ function hasErrorCode(error, expected) {
155
+ return typeof error === "object" && error !== null && "code" in error && error.code === expected;
156
+ }
157
+ //# sourceMappingURL=runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../ACP Connector/admission/runtime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { AdmissionController } from "../../Admission Controller/controller.js";
2
+ import { type LinuxProcessEvidenceReaders } from "../../Admission Controller/process-evidence.js";
3
+ export interface AdmissionStartupRecoveryReaders extends LinuxProcessEvidenceReaders {
4
+ listProcessIds(): readonly number[];
5
+ }
6
+ export interface AdmissionStartupRecoveryOptions {
7
+ readonly readers?: AdmissionStartupRecoveryReaders;
8
+ readonly now?: () => number;
9
+ }
10
+ export interface AdmissionStartupRecoverySummary {
11
+ readonly inspected: number;
12
+ readonly released: number;
13
+ readonly retained: number;
14
+ readonly markedRecoveryRequired: number;
15
+ }
16
+ export declare const nativeAdmissionStartupRecoveryReaders: AdmissionStartupRecoveryReaders;
17
+ /**
18
+ * Conservatively reconcile durable seats when an enabled connector starts.
19
+ * This code can only inspect process evidence and settle an existing fence; it
20
+ * cannot enqueue, start, write, replay, or deliver a business prompt.
21
+ */
22
+ export declare function recoverExitedAdmissionSeats(controller: AdmissionController, options?: AdmissionStartupRecoveryOptions): AdmissionStartupRecoverySummary;
@@ -0,0 +1,129 @@
1
+ import { readdirSync } from "node:fs";
2
+ import { captureLinuxProcessIdentity, nativeLinuxProcessEvidenceReaders, observeLinuxProcessIdentity } from "../../Admission Controller/process-evidence.js";
3
+ import { observePersistedLinuxConnectorOwnerIdentity } from "./owner-instance.js";
4
+ const MAX_PID = 2_147_483_647;
5
+ export const nativeAdmissionStartupRecoveryReaders = Object.freeze({
6
+ ...nativeLinuxProcessEvidenceReaders,
7
+ listProcessIds() {
8
+ return readdirSync("/proc", { withFileTypes: true })
9
+ .filter((entry) => entry.isDirectory() && /^[1-9][0-9]*$/.test(entry.name))
10
+ .map((entry) => Number(entry.name))
11
+ .filter((pid) => Number.isSafeInteger(pid) && pid > 0 && pid <= MAX_PID);
12
+ }
13
+ });
14
+ /**
15
+ * Conservatively reconcile durable seats when an enabled connector starts.
16
+ * This code can only inspect process evidence and settle an existing fence; it
17
+ * cannot enqueue, start, write, replay, or deliver a business prompt.
18
+ */
19
+ export function recoverExitedAdmissionSeats(controller, options = {}) {
20
+ const readers = options.readers ?? nativeAdmissionStartupRecoveryReaders;
21
+ const now = readNow(options.now ?? Date.now);
22
+ let processIds;
23
+ try {
24
+ processIds = normalizeProcessIds(readers.listProcessIds());
25
+ }
26
+ catch {
27
+ processIds = null;
28
+ }
29
+ let released = 0;
30
+ let retained = 0;
31
+ let markedRecoveryRequired = 0;
32
+ for (const queuedOwner of controller.listRecoverableQueuedOwners()) {
33
+ const owner = observePersistedLinuxConnectorOwnerIdentity(queuedOwner.owner, readers);
34
+ if (!isGoneIdentity(owner))
35
+ continue;
36
+ try {
37
+ controller.settleQueuedOwnerDeath(queuedOwner.requestId, queuedOwner.owner.ownerInstanceId, now);
38
+ }
39
+ catch {
40
+ // A concurrent owner may have admitted, cancelled, or otherwise settled the request.
41
+ }
42
+ }
43
+ const dispatches = controller.listRecoverableDispatches();
44
+ for (const dispatch of dispatches) {
45
+ const identity = dispatch.processIdentity;
46
+ if (identity === null || processIds === null) {
47
+ retained += 1;
48
+ continue;
49
+ }
50
+ const connector = observePersistedLinuxConnectorOwnerIdentity(identity.connector, readers);
51
+ if (connector === "same" || connector === "unverifiable") {
52
+ retained += 1;
53
+ continue;
54
+ }
55
+ const child = observeLinuxProcessIdentity(identity.child, readers);
56
+ const residue = inspectProcessGroup(identity.child, processIds, readers);
57
+ if (isGoneIdentity(child) && residue === "empty") {
58
+ try {
59
+ controller.releaseExitedRecoverySeat(dispatch.fence, now);
60
+ released += 1;
61
+ continue;
62
+ }
63
+ catch {
64
+ retained += 1;
65
+ continue;
66
+ }
67
+ }
68
+ if (child !== "unverifiable" && residue !== "unverifiable") {
69
+ try {
70
+ controller.markExecutionRecoveryRequired(dispatch.fence, now);
71
+ markedRecoveryRequired += 1;
72
+ }
73
+ catch {
74
+ // A concurrent owner may have advanced or settled the exact fence.
75
+ }
76
+ }
77
+ retained += 1;
78
+ }
79
+ return Object.freeze({
80
+ inspected: dispatches.length,
81
+ released,
82
+ retained,
83
+ markedRecoveryRequired
84
+ });
85
+ }
86
+ function inspectProcessGroup(expected, processIds, readers) {
87
+ let unverifiable = false;
88
+ for (const pid of processIds) {
89
+ let observed;
90
+ try {
91
+ observed = captureLinuxProcessIdentity(pid, readers);
92
+ }
93
+ catch (error) {
94
+ if (isGone(error))
95
+ continue;
96
+ unverifiable = true;
97
+ continue;
98
+ }
99
+ if (observed.bootId === expected.bootId &&
100
+ observed.pidNamespaceInode === expected.pidNamespaceInode &&
101
+ observed.pgrp === expected.pgrp &&
102
+ observed.session === expected.session) {
103
+ return "present";
104
+ }
105
+ }
106
+ return unverifiable ? "unverifiable" : "empty";
107
+ }
108
+ function normalizeProcessIds(value) {
109
+ if (!Array.isArray(value))
110
+ return null;
111
+ const ids = value.slice();
112
+ if (ids.some((pid) => !Number.isSafeInteger(pid) || pid < 1 || pid > MAX_PID))
113
+ return null;
114
+ return Object.freeze([...new Set(ids)].sort((left, right) => left - right));
115
+ }
116
+ function isGoneIdentity(value) {
117
+ return value === "gone" || value === "pid_reused";
118
+ }
119
+ function isGone(error) {
120
+ return typeof error === "object" && error !== null && "code" in error &&
121
+ (error.code === "ENOENT" || error.code === "ESRCH");
122
+ }
123
+ function readNow(now) {
124
+ const value = now();
125
+ if (!Number.isSafeInteger(value) || value < 0)
126
+ throw new Error("admission startup recovery clock is invalid");
127
+ return value;
128
+ }
129
+ //# sourceMappingURL=startup-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup-recovery.js","sourceRoot":"","sources":["../../../ACP Connector/admission/startup-recovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { type AdmissionController } from "../../Admission Controller/controller.js";
2
+ import { type LinuxConnectorOwnerIdentity } from "./owner-instance.js";
3
+ import { type AgyAdmissionDispatchBoundary } from "./dispatch-boundary.js";
4
+ import type { TurnClaim } from "../acp/session/turn-scheduler.js";
5
+ export interface AdmissionTurnProgress {
6
+ readonly state: "queued";
7
+ readonly position: number;
8
+ readonly eligiblePosition: number | null;
9
+ readonly waitedMs: number;
10
+ readonly cooldownUntil: number | null;
11
+ }
12
+ export interface AdmissionTurnExecutionResult {
13
+ readonly stopReason: "end_turn" | "cancelled";
14
+ }
15
+ export interface AdmissionTurnInput {
16
+ readonly sessionId: string;
17
+ readonly model: string;
18
+ readonly promptText: string;
19
+ readonly claim: TurnClaim;
20
+ readonly reportProgress?: (progress: AdmissionTurnProgress) => void | Promise<void>;
21
+ readonly execute: (boundary: AgyAdmissionDispatchBoundary) => Promise<AdmissionTurnExecutionResult>;
22
+ }
23
+ export interface AdmissionTurnCoordinatorOptions {
24
+ readonly controller: AdmissionController;
25
+ readonly agentId?: string;
26
+ readonly parentId?: string;
27
+ readonly connectorPid?: number;
28
+ readonly now?: () => number;
29
+ readonly createRequestId?: () => string;
30
+ readonly queuePollIntervalMs?: number;
31
+ readonly progressIntervalMs?: number;
32
+ readonly heartbeatIntervalMs?: number;
33
+ readonly wait?: (milliseconds: number, signal: AbortSignal) => Promise<void>;
34
+ }
35
+ export declare class AdmissionQueueTimeoutError extends Error {
36
+ constructor();
37
+ }
38
+ export declare class AdmissionTurnRecoveryRequiredError extends Error {
39
+ constructor();
40
+ }
41
+ /**
42
+ * Wraps the existing online ACP turn with the shared queue and one exact stdin
43
+ * write boundary. It never translates output or performs delivery replay.
44
+ */
45
+ export declare class AdmissionTurnCoordinator {
46
+ #private;
47
+ constructor(options: AdmissionTurnCoordinatorOptions);
48
+ get ownerIdentity(): LinuxConnectorOwnerIdentity;
49
+ admit(input: AdmissionTurnInput): Promise<"end_turn" | "cancelled">;
50
+ close(): void;
51
+ private waitForLease;
52
+ private settleFailure;
53
+ private cancelQueuedQuietly;
54
+ private reportProgress;
55
+ private readNow;
56
+ private assertOpen;
57
+ }