@deepstrike/wasm 0.2.74 → 0.2.76
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/dist/agent.js +5 -0
- package/dist/governance.d.ts +33 -9
- package/dist/governance.js +25 -28
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/memory/authority.d.ts +30 -0
- package/dist/memory/authority.js +34 -0
- package/dist/providers/anthropic.js +3 -2
- package/dist/providers/openai.js +2 -1
- package/dist/runtime/canonical-kernel-step.d.ts +32 -0
- package/dist/runtime/canonical-kernel-step.js +391 -141
- package/dist/runtime/execution-plane.d.ts +2 -0
- package/dist/runtime/execution-plane.js +10 -3
- package/dist/runtime/kernel-step.js +14 -3
- package/dist/runtime/replay-provider.js +4 -3
- package/dist/runtime/runner.d.ts +55 -3
- package/dist/runtime/runner.js +405 -228
- package/dist/runtime/tool-arguments.d.ts +24 -0
- package/dist/runtime/tool-arguments.js +61 -0
- package/dist/runtime/types/agent.d.ts +4 -0
- package/dist/runtime/types/agent.js +6 -55
- package/dist/types.d.ts +2 -1
- package/package.json +3 -3
package/dist/agent.js
CHANGED
|
@@ -2,6 +2,7 @@ import { RuntimeRunner } from "./runtime/runner.js";
|
|
|
2
2
|
import { LocalExecutionPlane } from "./runtime/execution-plane.js";
|
|
3
3
|
import { InMemorySessionLog } from "./runtime/session-log.js";
|
|
4
4
|
import { extractJsonValue, validateAgainstSchema } from "./runtime/output-schema.js";
|
|
5
|
+
import { checkMemoryWrite } from "./memory/authority.js";
|
|
5
6
|
function statusOf(reason) {
|
|
6
7
|
if (["completed", "success", "done"].includes(reason))
|
|
7
8
|
return "completed";
|
|
@@ -170,6 +171,10 @@ export class Agent {
|
|
|
170
171
|
created_at: now, updated_at: now, recall_count: 0, confidence: input.confidence ?? 1,
|
|
171
172
|
links: [], pinned: input.pinned ?? false, ...(input.ttlDays === undefined ? {} : { ttl_days: input.ttlDays }),
|
|
172
173
|
};
|
|
174
|
+
// §22.13 · the kernel's write rule, not a copy of it, decides whether this record may be stored.
|
|
175
|
+
const refusal = await checkMemoryWrite(undefined, record.name, record.content);
|
|
176
|
+
if (refusal)
|
|
177
|
+
throw new Error(`agent "${this.name}" memory write denied: ${refusal}`);
|
|
173
178
|
await this.memory.put(record);
|
|
174
179
|
return record;
|
|
175
180
|
}
|
package/dist/governance.d.ts
CHANGED
|
@@ -12,16 +12,11 @@ export interface GovernancePolicy {
|
|
|
12
12
|
windowMs: number;
|
|
13
13
|
}[];
|
|
14
14
|
constraints?: GovernanceConstraint[];
|
|
15
|
-
/** I5: when true (default), the
|
|
15
|
+
/** I5: when true (default), the kernel withholds statically denied tools (vetoes and `deny`
|
|
16
|
+
* rules, evaluated exactly as the call gate evaluates them) from the provider surface and names
|
|
17
|
+
* them once in the knowledge slot. Mirrors Node. */
|
|
16
18
|
surfaceDeniedInSystem?: boolean;
|
|
17
19
|
}
|
|
18
|
-
/** I5: bucket tools into allowed/denied per the policy. Pure. Mirrors Node. */
|
|
19
|
-
export declare function governanceFilterSchema<T extends {
|
|
20
|
-
name: string;
|
|
21
|
-
}>(tools: T[], policy: GovernancePolicy | undefined): {
|
|
22
|
-
allowed: T[];
|
|
23
|
-
denied: string[];
|
|
24
|
-
};
|
|
25
20
|
export type GovernanceConstraint = {
|
|
26
21
|
kind: "required";
|
|
27
22
|
tool: string;
|
|
@@ -38,5 +33,34 @@ export type GovernanceConstraint = {
|
|
|
38
33
|
min?: number;
|
|
39
34
|
max?: number;
|
|
40
35
|
};
|
|
41
|
-
export declare function governancePolicyToKernelEvent(policy: GovernancePolicy): Record<string, unknown
|
|
36
|
+
export declare function governancePolicyToKernelEvent(policy: GovernancePolicy): Record<string, unknown> & {
|
|
37
|
+
rate_limits: Array<{
|
|
38
|
+
tool: string;
|
|
39
|
+
max_calls: number;
|
|
40
|
+
window_ms: number;
|
|
41
|
+
}>;
|
|
42
|
+
};
|
|
43
|
+
/** A §13.2 live-policy patch replacing the governance posture, for `RuntimeRunner.applyPolicyPatch`. */
|
|
44
|
+
export declare function governancePolicyPatch(policy: GovernancePolicy): {
|
|
45
|
+
kind: "replace_governance_policy";
|
|
46
|
+
policy: Record<string, unknown>;
|
|
47
|
+
};
|
|
48
|
+
/** A §13.2 live policy patch in kernel vocabulary — the closed set of policies that may change
|
|
49
|
+
* while an operation runs. Use `governancePolicyPatch` to build the governance variant. */
|
|
50
|
+
export type LivePolicyPatch = {
|
|
51
|
+
kind: "replace_signal_policy";
|
|
52
|
+
policy: Record<string, unknown>;
|
|
53
|
+
} | {
|
|
54
|
+
kind: "replace_governance_policy";
|
|
55
|
+
policy: Record<string, unknown>;
|
|
56
|
+
} | {
|
|
57
|
+
kind: "replace_recovery_policy";
|
|
58
|
+
policy: Record<string, unknown>;
|
|
59
|
+
} | {
|
|
60
|
+
kind: "tighten_resource_quota";
|
|
61
|
+
max_concurrent_subagents?: number;
|
|
62
|
+
max_total_subagents?: number;
|
|
63
|
+
max_spawn_depth?: number;
|
|
64
|
+
max_workflow_nodes?: number;
|
|
65
|
+
};
|
|
42
66
|
export {};
|
package/dist/governance.js
CHANGED
|
@@ -1,29 +1,4 @@
|
|
|
1
1
|
// ─── Declarative policy (in-kernel gate) ──────────────────────────────────────
|
|
2
|
-
/** I5: bucket tools into allowed/denied per the policy. Pure. Mirrors Node. */
|
|
3
|
-
export function governanceFilterSchema(tools, policy) {
|
|
4
|
-
if (!policy)
|
|
5
|
-
return { allowed: tools, denied: [] };
|
|
6
|
-
const vetoes = new Set(policy.vetoes ?? []);
|
|
7
|
-
const allowed = [];
|
|
8
|
-
const denied = [];
|
|
9
|
-
const matches = (pat, name) => pat === name || (pat.endsWith("*") && name.startsWith(pat.slice(0, -1)));
|
|
10
|
-
for (const tool of tools) {
|
|
11
|
-
if (vetoes.has(tool.name)) {
|
|
12
|
-
denied.push(tool.name);
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
let action = policy.defaultAction ?? "allow";
|
|
16
|
-
for (const r of policy.rules ?? []) {
|
|
17
|
-
if (matches(r.pattern, tool.name))
|
|
18
|
-
action = r.action;
|
|
19
|
-
}
|
|
20
|
-
if (action === "deny")
|
|
21
|
-
denied.push(tool.name);
|
|
22
|
-
else
|
|
23
|
-
allowed.push(tool);
|
|
24
|
-
}
|
|
25
|
-
return { allowed, denied };
|
|
26
|
-
}
|
|
27
2
|
export function governancePolicyToKernelEvent(policy) {
|
|
28
3
|
return {
|
|
29
4
|
kind: "load_governance_policy",
|
|
@@ -36,9 +11,31 @@ export function governancePolicyToKernelEvent(policy) {
|
|
|
36
11
|
window_ms: rl.windowMs,
|
|
37
12
|
})),
|
|
38
13
|
constraints: (policy.constraints ?? []).map(c => c.kind === "enum"
|
|
39
|
-
? { kind: "enum", tool: c.tool,
|
|
14
|
+
? { kind: "enum", tool: c.tool, param_path: c.path, values: c.values }
|
|
40
15
|
: c.kind === "range"
|
|
41
|
-
? {
|
|
42
|
-
|
|
16
|
+
? {
|
|
17
|
+
kind: "range", tool: c.tool, param_path: c.path,
|
|
18
|
+
// The wire carries fixed-point micro-units so a bound replays byte-identically.
|
|
19
|
+
...(c.min !== undefined ? { min_micros: toMicros(c.min) } : {}),
|
|
20
|
+
...(c.max !== undefined ? { max_micros: toMicros(c.max) } : {}),
|
|
21
|
+
}
|
|
22
|
+
: { kind: "required", tool: c.tool, param_path: c.path }),
|
|
23
|
+
hide_denied_tools: policy.surfaceDeniedInSystem !== false,
|
|
43
24
|
};
|
|
44
25
|
}
|
|
26
|
+
/** A §13.2 live-policy patch replacing the governance posture, for `RuntimeRunner.applyPolicyPatch`. */
|
|
27
|
+
export function governancePolicyPatch(policy) {
|
|
28
|
+
const { kind: _kind, ...wire } = governancePolicyToKernelEvent(policy);
|
|
29
|
+
return {
|
|
30
|
+
kind: "replace_governance_policy",
|
|
31
|
+
policy: {
|
|
32
|
+
...wire,
|
|
33
|
+
rate_limits: wire.rate_limits.map(limit => ({ ...limit, window_ms: String(limit.window_ms) })),
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function toMicros(value) {
|
|
38
|
+
if (!Number.isFinite(value))
|
|
39
|
+
throw new RangeError(`governance range bound must be finite, got ${value}`);
|
|
40
|
+
return Math.round(value * 1_000_000);
|
|
41
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,8 @@ export { OpenAIProvider, qwen, deepseek, minimax, kimi } from "./providers/opena
|
|
|
22
22
|
export type { OpenAIProviderOptions, BackendProviderOptions } from "./providers/openai.js";
|
|
23
23
|
export { ProviderError, classifyProviderError } from "./providers/provider-error.js";
|
|
24
24
|
export type { ProviderErrorKind, ProviderErrorOptions } from "./providers/provider-error.js";
|
|
25
|
-
export type { GovernancePolicy, GovernanceConstraint } from "./governance.js";
|
|
25
|
+
export type { GovernancePolicy, GovernanceConstraint, LivePolicyPatch } from "./governance.js";
|
|
26
|
+
export { governancePolicyPatch } from "./governance.js";
|
|
26
27
|
export { tool, executeTools } from "./tools/index.js";
|
|
27
28
|
export type { RegisteredTool, ToolExecContext } from "./tools/index.js";
|
|
28
29
|
export { safeTool, ok, fail, ToolError, formatToolError } from "./tools/errors.js";
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export { McpExecutionPlane } from "./runtime/mcp-transport.js";
|
|
|
14
14
|
export { AnthropicProvider } from "./providers/anthropic.js";
|
|
15
15
|
export { OpenAIProvider, qwen, deepseek, minimax, kimi } from "./providers/openai.js";
|
|
16
16
|
export { ProviderError, classifyProviderError } from "./providers/provider-error.js";
|
|
17
|
+
export { governancePolicyPatch } from "./governance.js";
|
|
17
18
|
export { tool, executeTools } from "./tools/index.js";
|
|
18
19
|
export { safeTool, ok, fail, ToolError, formatToolError } from "./tools/errors.js";
|
|
19
20
|
export { WorkingMemory } from "./memory/index.js";
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { MemoryRecall, MemoryRecallLifecycle } from "./index.js";
|
|
2
|
+
/**
|
|
3
|
+
* §22.13 · the kernel's memory authority for a host with no live operation.
|
|
4
|
+
*
|
|
5
|
+
* Inside a run, every memory decision is a kernel transition (`admit_memory_write`, and the
|
|
6
|
+
* `memory_recalled` / `promotion_suggested` facts a query resolution journals). With no run — an
|
|
7
|
+
* explicit `remember`, a session extract after the run ended — the host asks the same kernel
|
|
8
|
+
* functions statelessly. The SDK keeps no copy of the validation rule and never computes a recall
|
|
9
|
+
* count itself.
|
|
10
|
+
*/
|
|
11
|
+
/** The canonical wire `MemoryPolicy` (the `u64` threshold travels as a decimal string). */
|
|
12
|
+
export interface KernelMemoryPolicyWire {
|
|
13
|
+
stale_warning_days?: number;
|
|
14
|
+
retrieval_top_k?: number;
|
|
15
|
+
validation_enabled?: boolean;
|
|
16
|
+
max_content_bytes?: number;
|
|
17
|
+
max_name_length?: number;
|
|
18
|
+
promotion_recall_threshold?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface MemoryPromotion {
|
|
21
|
+
record_id: string;
|
|
22
|
+
recall_count: number;
|
|
23
|
+
}
|
|
24
|
+
/** Would the kernel admit this write? Resolves to the refusal reason, or `undefined` when admitted. */
|
|
25
|
+
export declare function checkMemoryWrite(policy: KernelMemoryPolicyWire | undefined, name: string, content: string): Promise<string | undefined>;
|
|
26
|
+
/** Derive one recall's lifecycle from the counts the store reported it held. */
|
|
27
|
+
export declare function deriveMemoryRecall(policy: KernelMemoryPolicyWire | undefined, recalledAt: number, hits: MemoryRecall[]): Promise<{
|
|
28
|
+
recalls: MemoryRecallLifecycle[];
|
|
29
|
+
promotions: MemoryPromotion[];
|
|
30
|
+
}>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { getKernel } from "../runtime/kernel.js";
|
|
2
|
+
async function ask(request) {
|
|
3
|
+
const kernel = await getKernel();
|
|
4
|
+
return JSON.parse(kernel.memoryAuthorityJson(JSON.stringify(request)));
|
|
5
|
+
}
|
|
6
|
+
/** Would the kernel admit this write? Resolves to the refusal reason, or `undefined` when admitted. */
|
|
7
|
+
export async function checkMemoryWrite(policy, name, content) {
|
|
8
|
+
const answer = await ask({
|
|
9
|
+
op: "check_write",
|
|
10
|
+
...(policy ? { policy } : {}),
|
|
11
|
+
name,
|
|
12
|
+
content_bytes: new TextEncoder().encode(content).byteLength,
|
|
13
|
+
});
|
|
14
|
+
return answer.admitted === true ? undefined : String(answer.error ?? "memory write refused");
|
|
15
|
+
}
|
|
16
|
+
/** Derive one recall's lifecycle from the counts the store reported it held. */
|
|
17
|
+
export async function deriveMemoryRecall(policy, recalledAt, hits) {
|
|
18
|
+
if (hits.length === 0)
|
|
19
|
+
return { recalls: [], promotions: [] };
|
|
20
|
+
const answer = await ask({
|
|
21
|
+
op: "derive_recall",
|
|
22
|
+
...(policy ? { policy } : {}),
|
|
23
|
+
recalled_at: Math.max(0, Math.trunc(recalledAt)),
|
|
24
|
+
recalls: hits.map(hit => ({
|
|
25
|
+
record_id: hit.record.record_id,
|
|
26
|
+
recall_count: Math.max(0, Math.trunc(hit.record.recall_count ?? 0)),
|
|
27
|
+
...(hit.record.pinned ? { pinned: true } : {}),
|
|
28
|
+
})),
|
|
29
|
+
});
|
|
30
|
+
return {
|
|
31
|
+
recalls: (answer.recalls ?? []),
|
|
32
|
+
promotions: (answer.promotions ?? []),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { requestSnapshot } from "./prepared-request.js";
|
|
2
2
|
import { assistantReplayKey, collectStreamMessage, toAnthropicMessages } from "./base.js";
|
|
3
|
+
import { malformedToolArguments, toolArgumentsText } from "../runtime/tool-arguments.js";
|
|
3
4
|
/** Anthropic accepts at most this many cache_control breakpoints per request. */
|
|
4
5
|
const MAX_CACHE_BREAKPOINTS = 4;
|
|
5
6
|
/** Rolling cache breakpoints reserved for the message history (system uses ≤2). */
|
|
@@ -317,8 +318,8 @@ export class AnthropicProvider {
|
|
|
317
318
|
args = {};
|
|
318
319
|
}
|
|
319
320
|
nativeBlocks[idx] = { ...nativeBlocks[idx], input: args };
|
|
320
|
-
finalToolCalls.push({ id: tb.id, name: tb.name, arguments:
|
|
321
|
-
yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
|
|
321
|
+
finalToolCalls.push({ id: tb.id, name: tb.name, arguments: toolArgumentsText(tb.argsBuf) });
|
|
322
|
+
yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args, ...malformedToolArguments(tb.argsBuf) };
|
|
322
323
|
}
|
|
323
324
|
}
|
|
324
325
|
}
|
package/dist/providers/openai.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { requestSnapshot } from "./prepared-request.js";
|
|
2
2
|
import { collectStreamMessage, toOpenAIMessages } from "./base.js";
|
|
3
|
+
import { malformedToolArguments } from "../runtime/tool-arguments.js";
|
|
3
4
|
const DEEPSEEK_REASONERS = new Set(["deepseek-reasoner", "deepseek-r1"]);
|
|
4
5
|
const MINIMAX_REASONERS = new Set(["MiniMax-M1", "minimax-m1"]);
|
|
5
6
|
// OpenAI-compatible provider — works for OpenAI, Qwen (DashScope), DeepSeek, MiniMax, Kimi
|
|
@@ -107,7 +108,7 @@ export class OpenAIProvider {
|
|
|
107
108
|
catch {
|
|
108
109
|
args = {};
|
|
109
110
|
}
|
|
110
|
-
yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
|
|
111
|
+
yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args, ...malformedToolArguments(tb.argsBuf) };
|
|
111
112
|
}
|
|
112
113
|
}
|
|
113
114
|
prepareRequest(context, tools, extensions, state) {
|
|
@@ -43,6 +43,12 @@ export declare class CanonicalKernelRejectedError extends Error {
|
|
|
43
43
|
readonly fault: Record<string, unknown>;
|
|
44
44
|
constructor(faultJson: string);
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Whether a run-loop failure was the kernel refusing a malformed input (`invalid_arg`) rather than
|
|
48
|
+
* any other error. Decided by the fault the kernel named, or a binding's argument-conversion
|
|
49
|
+
* status — never by searching the message text.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isInvalidInputError(error: unknown): boolean;
|
|
46
52
|
/**
|
|
47
53
|
* A record is already authoritative once the journal append returns. A later native commit failure
|
|
48
54
|
* is therefore a rebuild boundary, never an abort boundary.
|
|
@@ -68,6 +74,13 @@ export declare class CanonicalKernelHost {
|
|
|
68
74
|
readonly journal: KernelJournal;
|
|
69
75
|
readonly operationId: string;
|
|
70
76
|
constructor(kernel: CanonicalKernelInstance, journal: KernelJournal, operationId: string);
|
|
77
|
+
/**
|
|
78
|
+
* The journal holds one outbound envelope slot per operation, so two transitions of the same
|
|
79
|
+
* operation must never overlap: the second would overwrite the first's staged bytes before its
|
|
80
|
+
* append was acknowledged. Every entry point that stages or drains goes through this queue.
|
|
81
|
+
*/
|
|
82
|
+
private exclusiveTail;
|
|
83
|
+
private exclusive;
|
|
71
84
|
transition(input: CanonicalKernelInput, options?: CanonicalTransitionOptions): Promise<CanonicalTransition>;
|
|
72
85
|
/** Restore the latest installed checkpoint and its authoritative record tail in place. */
|
|
73
86
|
restore(): Promise<CanonicalRestoreCost>;
|
|
@@ -94,6 +107,10 @@ export interface CanonicalRunnerRuntimeOptions {
|
|
|
94
107
|
preview: string;
|
|
95
108
|
}>;
|
|
96
109
|
}
|
|
110
|
+
/** Positional ids for anonymous appended nodes. A known DAG size yields `wf-node{base+i}`, the same
|
|
111
|
+
* id the kernel gives the node internally; an unknown size (after a restore) yields a batch-scoped
|
|
112
|
+
* id that cannot collide with anything already declared. */
|
|
113
|
+
export type WorkflowNodeIdBase = number | string;
|
|
97
114
|
export declare function sha256(value: string): string;
|
|
98
115
|
/**
|
|
99
116
|
* Canonical operation runtime used by the WASM host.
|
|
@@ -108,9 +125,17 @@ export declare class CanonicalRunnerRuntime {
|
|
|
108
125
|
private started;
|
|
109
126
|
private turns;
|
|
110
127
|
private lastAction;
|
|
128
|
+
/** Live policy revision (§13.2): 0 at genesis, then each `live_policy_changed`. Unknown after a
|
|
129
|
+
* restore, when a patch must name the revision it expects explicitly. */
|
|
130
|
+
private policyRevision;
|
|
131
|
+
/** Kernel-minted attempt per launched task, learned from each launch acknowledgement. */
|
|
132
|
+
private readonly taskAttempts;
|
|
111
133
|
private readonly newMessages;
|
|
112
134
|
private readonly hostObservations;
|
|
113
135
|
private spawnedTasks;
|
|
136
|
+
/** Nodes in the active workflow DAG, mirrored from committed facts so anonymous appended nodes get
|
|
137
|
+
* unique positional ids. `undefined` after a restore until the next committed submission. */
|
|
138
|
+
private workflowNodeCount;
|
|
114
139
|
private readonly memoryBindingId;
|
|
115
140
|
private payloadInlineThreshold;
|
|
116
141
|
private payloadPreviewBytes;
|
|
@@ -119,6 +144,8 @@ export declare class CanonicalRunnerRuntime {
|
|
|
119
144
|
get journal(): KernelJournal;
|
|
120
145
|
turn(): number;
|
|
121
146
|
isTerminal(): boolean;
|
|
147
|
+
/** Whether the operation has a root — the precondition for any live host control command. */
|
|
148
|
+
hasStarted(): boolean;
|
|
122
149
|
recoveryContentBytes(): number;
|
|
123
150
|
preservedRefs(): string[];
|
|
124
151
|
drainNewMessages(): ModelMessage[];
|
|
@@ -129,11 +156,16 @@ export declare class CanonicalRunnerRuntime {
|
|
|
129
156
|
resumeAction(): KernelRunnerAction | null;
|
|
130
157
|
startAgent(taskValue: Record<string, unknown>, runSpecValue?: Record<string, unknown>): Promise<KernelRunnerAction | null>;
|
|
131
158
|
startWorkflow(specValue: Record<string, unknown>): Promise<KernelRunnerAction | null>;
|
|
159
|
+
private appendBase;
|
|
132
160
|
applyHostEvent(event: Record<string, unknown>): Promise<KernelRunnerAction | null>;
|
|
133
161
|
private ensureConfigured;
|
|
134
162
|
private commit;
|
|
163
|
+
/** Record what a committed transition tells the host: its observations and published effects. */
|
|
164
|
+
private absorbTransition;
|
|
135
165
|
private currentAction;
|
|
136
166
|
private pendingEffects;
|
|
167
|
+
/** One list field of the pending effect `effectId`, which must be of kind `kind`. */
|
|
168
|
+
private pendingEffectPayload;
|
|
137
169
|
private succeededEffect;
|
|
138
170
|
private failedEffect;
|
|
139
171
|
private pageOutResolution;
|