mixdog 0.9.158 → 0.9.159
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 +0 -1
- package/package.json +12 -7
- package/scripts/office-design-audit.mjs +43 -0
- package/scripts/release-paths.mjs +108 -0
- package/scripts/suite-health.mjs +102 -0
- package/src/defaults/skills/setup/SKILL.md +10 -11
- package/src/runtime/agent/orchestrator/agent-runtime/session-builder.mjs +12 -12
- package/src/runtime/agent/orchestrator/agent-trace-format.mjs +0 -4
- package/src/runtime/agent/orchestrator/config.mjs +8 -13
- package/src/runtime/agent/orchestrator/internal-tools.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +52 -2
- package/src/runtime/agent/orchestrator/providers/openai-oauth-ws.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +0 -9
- package/src/runtime/agent/orchestrator/session/compact/constants.mjs +8 -44
- package/src/runtime/agent/orchestrator/session/compact/continuation.mjs +55 -0
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +89 -4
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +227 -767
- package/src/runtime/agent/orchestrator/session/compact/summary-schema.mjs +4 -4
- package/src/runtime/agent/orchestrator/session/compact/summary.mjs +43 -50
- package/src/runtime/agent/orchestrator/session/compact.mjs +7 -21
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/loop/compact-policy.mjs +35 -73
- package/src/runtime/agent/orchestrator/session/loop/context-overflow.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +472 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec.mjs +6 -2
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +16 -5
- package/src/runtime/agent/orchestrator/session/manager/compaction-runner.mjs +66 -163
- package/src/runtime/agent/orchestrator/session/manager/context-meta.mjs +4 -20
- package/src/runtime/agent/orchestrator/session/manager/message-sanitize.mjs +8 -4
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +4 -23
- package/src/runtime/agent/orchestrator/session/manager/session-lifecycle.mjs +3 -14
- package/src/runtime/agent/orchestrator/session/manager/turn-checkpoint-context.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +64 -195
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/tool-envelope.mjs +18 -6
- package/src/runtime/browser-bridge/action-schema.mjs +19 -2
- package/src/runtime/browser-bridge/client.mjs +6 -2
- package/src/runtime/browser-bridge/tool-defs.mjs +6 -6
- package/src/runtime/computer-bridge/action-schema.mjs +85 -365
- package/src/runtime/computer-bridge/client.mjs +71 -6
- package/src/runtime/computer-bridge/core-actions.mjs +227 -0
- package/src/runtime/computer-bridge/error-recovery.mjs +105 -0
- package/src/runtime/computer-bridge/tool-defs.mjs +11 -12
- package/src/runtime/memory/index.mjs +2 -1
- package/src/runtime/memory/lib/compact-handoff.mjs +127 -0
- package/src/runtime/memory/lib/http-wire.mjs +1 -1
- package/src/runtime/memory/lib/memory-config-flags.mjs +10 -0
- package/src/runtime/memory/lib/query-handlers.mjs +16 -6
- package/src/runtime/memory/lib/recall-format.mjs +18 -41
- package/src/runtime/memory/lib/session-ingest-runtime.mjs +4 -2
- package/src/runtime/memory/lib/session-ingest.mjs +37 -9
- package/src/runtime/office/assurance-benchmark.mjs +68 -2
- package/src/runtime/office/assurance.mjs +82 -0
- package/src/runtime/office/capabilities.mjs +6 -6
- package/src/runtime/office/composition-system.mjs +5 -0
- package/src/runtime/office/content-model.mjs +1 -1
- package/src/runtime/office/design-aesthetics.mjs +460 -0
- package/src/runtime/office/design-art-direction.mjs +283 -0
- package/src/runtime/office/design-creative-director.mjs +170 -0
- package/src/runtime/office/design-deck-diversity.mjs +115 -0
- package/src/runtime/office/design-docx-components.mjs +60 -1
- package/src/runtime/office/design-docx.mjs +31 -3
- package/src/runtime/office/design-frontier-review.mjs +129 -0
- package/src/runtime/office/design-layout-grammar.mjs +134 -0
- package/src/runtime/office/design-pptx-plan.mjs +27 -2
- package/src/runtime/office/design-pptx-semantic-flow.mjs +111 -0
- package/src/runtime/office/design-pptx-semantic-visuals.mjs +885 -0
- package/src/runtime/office/design-pptx-stack.mjs +16 -8
- package/src/runtime/office/design-review.mjs +4 -0
- package/src/runtime/office/design-system.mjs +16 -4
- package/src/runtime/office/design-tokens.mjs +36 -8
- package/src/runtime/office/design-xlsx.mjs +28 -5
- package/src/runtime/office/index.mjs +2 -0
- package/src/runtime/office/office-actions.mjs +42 -3
- package/src/runtime/office/office-com-host.ps1 +99 -9
- package/src/runtime/office/office-com-session-host.ps1 +185 -2
- package/src/runtime/office/office-sessions.mjs +2 -0
- package/src/runtime/office/quality-live-benchmark.mjs +121 -67
- package/src/runtime/office/quality-pipeline.mjs +20 -0
- package/src/runtime/office/quality-score.mjs +84 -0
- package/src/runtime/office/tool-defs.mjs +1 -1
- package/src/session-runtime/config-helpers.mjs +16 -11
- package/src/session-runtime/goal-reminder.mjs +18 -0
- package/src/session-runtime/runtime-core.mjs +2 -2
- package/src/session-runtime/session-transcript.mjs +2 -2
- package/src/session-runtime/session-turn-api.mjs +5 -1
- package/src/session-runtime/settings-api.mjs +14 -12
- package/src/tui/App.jsx +1 -3
- package/src/tui/app/create-app-pickers.mjs +0 -4
- package/src/tui/app/extension-pickers.mjs +1 -56
- package/src/tui/app/input-parsers.mjs +1 -27
- package/src/tui/app/prompt-submit.mjs +2 -2
- package/src/tui/app/settings-picker.mjs +2 -43
- package/src/tui/app/slash-commands.mjs +0 -1
- package/src/tui/app/slash-dispatch.mjs +0 -4
- package/src/tui/app/usage-context-panels.mjs +0 -1
- package/src/tui/dist/index.mjs +4 -98
- package/src/tui/session/session-api.mjs +2 -3
- package/src/tui/session/session-flow.mjs +6 -11
- package/src/vendor/statusline/src/gateway/route-meta.mjs +2 -3
- package/src/runtime/agent/orchestrator/session/loop/recall-fasttrack.mjs +0 -245
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
// Shared
|
|
2
|
-
// from compact.mjs (behavior-preserving). compact.mjs re-exports the public
|
|
3
|
-
// members from here so the external surface is unchanged.
|
|
1
|
+
// Shared Compact constants. compact.mjs re-exports this small public surface.
|
|
4
2
|
import {
|
|
5
3
|
DEFAULT_COMPACTION_BUFFER_TOKENS,
|
|
6
4
|
DEFAULT_COMPACTION_BUFFER_RATIO,
|
|
@@ -19,20 +17,20 @@ export {
|
|
|
19
17
|
compactionBufferTokensForBoundary,
|
|
20
18
|
};
|
|
21
19
|
|
|
22
|
-
export const
|
|
20
|
+
export const SUMMARY_PREFIX_ANCHOR = 'A previous model worked on this task and produced the compacted handoff summary below.';
|
|
21
|
+
export const SUMMARY_PREFIX = `${SUMMARY_PREFIX_ANCHOR} Build on the work already done and avoid duplicating it; treat the summary as authoritative context for continuing the task. The summary covers the full session; only the latest real user instruction is attached after it.`;
|
|
23
22
|
export const SUMMARY_OUTPUT_TOKENS = 4_096;
|
|
24
23
|
// Unified context-share rule: every derived "how much of the model context
|
|
25
|
-
// may this budget take" ratio uses ONE number —
|
|
24
|
+
// may this budget take" ratio uses ONE number — 50%. Consumers:
|
|
26
25
|
// - compact target budget (loop/compact-policy.mjs COMPACT_TARGET_RATIO)
|
|
27
|
-
// -
|
|
26
|
+
// - fresh-context handoff injection cap
|
|
28
27
|
// Keep them in lockstep; do not fork per-consumer ratios without a decision.
|
|
29
|
-
export const CONTEXT_SHARE_RATIO = 0.
|
|
28
|
+
export const CONTEXT_SHARE_RATIO = 0.50;
|
|
30
29
|
export const DEFAULT_EFFECTIVE_CONTEXT_WINDOW_PERCENT = 90;
|
|
31
30
|
export const COMPACT_TARGET_MIN_TOKENS = 4_000;
|
|
32
31
|
export const COMPACT_SAFETY_PERCENT = 1.00;
|
|
33
|
-
// Floor for the
|
|
34
|
-
|
|
35
|
-
export const RECALL_TOKEN_CAP_FLOOR_TOKENS = 2_048;
|
|
32
|
+
// Floor for the handoff cap so small-context models still get a usable slice.
|
|
33
|
+
export const HANDOFF_TOKEN_CAP_FLOOR_TOKENS = 2_048;
|
|
36
34
|
// Minimum room the generated summary needs after the mandatory (system +
|
|
37
35
|
// preserved tail) cost is accounted for. When the configured target budget is
|
|
38
36
|
// smaller than the mandatory cost (e.g. the preserved recent turn carries a
|
|
@@ -42,40 +40,6 @@ export const RECALL_TOKEN_CAP_FLOOR_TOKENS = 2_048;
|
|
|
42
40
|
// compact failures. Floor the working budget to mandatory + this room instead.
|
|
43
41
|
export const COMPACT_SUMMARY_MIN_ROOM_TOKENS = 4_000;
|
|
44
42
|
|
|
45
|
-
export const COMPACT_TYPE_SEMANTIC = 'semantic';
|
|
46
|
-
export const COMPACT_TYPE_RECALL_FASTTRACK = 'recall-fasttrack';
|
|
47
|
-
export const DEFAULT_COMPACT_TYPE = COMPACT_TYPE_SEMANTIC;
|
|
48
|
-
export const COMPACT_TYPES = Object.freeze([
|
|
49
|
-
COMPACT_TYPE_SEMANTIC,
|
|
50
|
-
COMPACT_TYPE_RECALL_FASTTRACK,
|
|
51
|
-
]);
|
|
52
|
-
|
|
53
|
-
export function normalizeCompactType(value, fallback = DEFAULT_COMPACT_TYPE) {
|
|
54
|
-
const raw = String(value ?? '').trim().toLowerCase().replace(/_/g, '-');
|
|
55
|
-
if (!raw) return fallback;
|
|
56
|
-
if (raw === '1' || raw === 'type1' || raw === 'type-1' || raw === 'bench1' || raw === 'bench-1' || raw === 'semantic' || raw === 'summary') {
|
|
57
|
-
return COMPACT_TYPE_SEMANTIC;
|
|
58
|
-
}
|
|
59
|
-
// Recall fast-track aliases. `replace(/_/g,'-')` above already folds
|
|
60
|
-
// snake_case (fast_track -> fast-track), but list both dash/no-dash forms
|
|
61
|
-
// explicitly so callers passing either spelling resolve deterministically.
|
|
62
|
-
if (raw === '2' || raw === 'type2' || raw === 'type-2' || raw === 'recall' || raw === 'recall-fast' || raw === 'recall-fasttrack' || raw === 'recall-fast-track' || raw === 'fasttrack' || raw === 'fast-track') {
|
|
63
|
-
return COMPACT_TYPE_RECALL_FASTTRACK;
|
|
64
|
-
}
|
|
65
|
-
// Unknown / unrecognized value: fall back to the caller-provided default
|
|
66
|
-
// (semantic by default). Callers that need to detect an unknown value
|
|
67
|
-
// should compare the input against COMPACT_TYPES before normalizing.
|
|
68
|
-
return fallback;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export function compactTypeIsSemantic(value) {
|
|
72
|
-
return normalizeCompactType(value) === COMPACT_TYPE_SEMANTIC;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export function compactTypeIsRecallFastTrack(value) {
|
|
76
|
-
return normalizeCompactType(value) === COMPACT_TYPE_RECALL_FASTTRACK;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
43
|
export function compactDebugEnabled() {
|
|
80
44
|
return String(process.env.MIXDOG_COMPACT_DEBUG || '').trim() === '1';
|
|
81
45
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isProtectedContextAckMessage,
|
|
3
|
+
latestActualUserInstructionIndex,
|
|
4
|
+
} from './messages.mjs';
|
|
5
|
+
|
|
6
|
+
export const ACTIVE_TURN_CONTINUATION_SOURCE = 'compact-active-turn-continuation';
|
|
7
|
+
export const ACTIVE_TURN_CONTINUATION_ANCHOR = '<active-turn-continuation>';
|
|
8
|
+
|
|
9
|
+
function isExistingContinuation(message) {
|
|
10
|
+
return message?.role === 'user'
|
|
11
|
+
&& (
|
|
12
|
+
String(message?.meta?.source || '') === ACTIVE_TURN_CONTINUATION_SOURCE
|
|
13
|
+
|| (
|
|
14
|
+
typeof message.content === 'string'
|
|
15
|
+
&& message.content.includes(ACTIVE_TURN_CONTINUATION_ANCHOR)
|
|
16
|
+
)
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isExecutionActivity(message) {
|
|
21
|
+
if (message?.role === 'tool') return true;
|
|
22
|
+
return message?.role === 'assistant' && !isProtectedContextAckMessage(message);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function makeActiveTurnContinuationMessage() {
|
|
26
|
+
return {
|
|
27
|
+
role: 'user',
|
|
28
|
+
content: [
|
|
29
|
+
'<system-reminder>',
|
|
30
|
+
ACTIVE_TURN_CONTINUATION_ANCHOR,
|
|
31
|
+
'The latest real user request was already in progress when Compact ran.',
|
|
32
|
+
'The compacted handoff above records the assistant progress and tool outcomes completed so far.',
|
|
33
|
+
'Continue from that state without repeating progress messages or completed tool calls.',
|
|
34
|
+
'Use tools only for work that the handoff leaves incomplete or failed.',
|
|
35
|
+
'</active-turn-continuation>',
|
|
36
|
+
'</system-reminder>',
|
|
37
|
+
].join('\n'),
|
|
38
|
+
meta: {
|
|
39
|
+
source: ACTIVE_TURN_CONTINUATION_SOURCE,
|
|
40
|
+
synthetic: true,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function activeTurnContinuationMessage(messages) {
|
|
46
|
+
const list = Array.isArray(messages) ? messages : [];
|
|
47
|
+
const latestUserIndex = latestActualUserInstructionIndex(list);
|
|
48
|
+
if (latestUserIndex < 0) return null;
|
|
49
|
+
const afterLatestUser = list.slice(latestUserIndex + 1);
|
|
50
|
+
if (!afterLatestUser.some(isExistingContinuation)
|
|
51
|
+
&& !afterLatestUser.some(isExecutionActivity)) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return makeActiveTurnContinuationMessage();
|
|
55
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// Message classification, protected-context splitting, and summary-message
|
|
2
2
|
// construction helpers. Extracted verbatim from compact.mjs
|
|
3
3
|
// (behavior-preserving).
|
|
4
|
-
import { SUMMARY_PREFIX } from './constants.mjs';
|
|
4
|
+
import { SUMMARY_PREFIX, SUMMARY_PREFIX_ANCHOR } from './constants.mjs';
|
|
5
5
|
import { sha16, roleCounts } from './text-utils.mjs';
|
|
6
|
+
import {
|
|
7
|
+
isInternalRuntimeNotificationText,
|
|
8
|
+
isModelVisibleToolCompletionWrapper,
|
|
9
|
+
} from '../../../../shared/tool-execution-contract.mjs';
|
|
6
10
|
|
|
7
11
|
export function compactHeader(oldHistory) {
|
|
8
12
|
const encoded = JSON.stringify(oldHistory ?? []);
|
|
@@ -13,7 +17,7 @@ export function compactHeader(oldHistory) {
|
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
export function makeSummaryMessage(content) {
|
|
16
|
-
return { role: 'user', content };
|
|
20
|
+
return { role: 'user', content, meta: { source: 'compact-summary' } };
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
// A compact summary message is a synthetic role:'user' message carrying the
|
|
@@ -23,8 +27,14 @@ export function makeSummaryMessage(content) {
|
|
|
23
27
|
// duplicate, or fail to merge across repeated compaction.
|
|
24
28
|
export function isSummaryMessage(m) {
|
|
25
29
|
return m?.role === 'user'
|
|
26
|
-
&&
|
|
27
|
-
|
|
30
|
+
&& (
|
|
31
|
+
String(m?.meta?.source || '') === 'compact-summary'
|
|
32
|
+
|| (
|
|
33
|
+
typeof m.content === 'string'
|
|
34
|
+
&& m.content.startsWith(SUMMARY_PREFIX_ANCHOR)
|
|
35
|
+
&& /\nmessages=\d+\s+(?:sha256=|compact_type=)/.test(m.content)
|
|
36
|
+
)
|
|
37
|
+
);
|
|
28
38
|
}
|
|
29
39
|
|
|
30
40
|
export function isProtectedContextUserMessage(m) {
|
|
@@ -51,6 +61,52 @@ export function isInjectedSkillBodyMessage(m) {
|
|
|
51
61
|
return typeof m.content === 'string' && m.content.trimStart().startsWith('<skill>');
|
|
52
62
|
}
|
|
53
63
|
|
|
64
|
+
const SYNTHETIC_USER_SOURCES = new Set([
|
|
65
|
+
'compact-active-turn-continuation',
|
|
66
|
+
'max-output-recovery',
|
|
67
|
+
'refusal-recovery',
|
|
68
|
+
]);
|
|
69
|
+
const SYNTHETIC_USER_CONTROL_RE =
|
|
70
|
+
/^(?:\[mixdog-runtime\]|\[request interrupted(?: by user(?: for tool use)?| by process restart)?\])(?:\s|$)/i;
|
|
71
|
+
|
|
72
|
+
function userMessageText(message) {
|
|
73
|
+
if (typeof message?.content === 'string') return message.content;
|
|
74
|
+
if (!Array.isArray(message?.content)) return '';
|
|
75
|
+
return message.content
|
|
76
|
+
.map((block) => (typeof block === 'string' ? block : block?.text || ''))
|
|
77
|
+
.join('');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function isActualUserInstructionMessage(message) {
|
|
81
|
+
if (message?.role !== 'user'
|
|
82
|
+
|| isSummaryMessage(message)
|
|
83
|
+
|| isProtectedContextUserMessage(message)
|
|
84
|
+
|| isInjectedSkillBodyMessage(message)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
const text = userMessageText(message);
|
|
88
|
+
if (/^Reference files:\s*/i.test(text.trimStart())) return false;
|
|
89
|
+
if (SYNTHETIC_USER_CONTROL_RE.test(text.trimStart())
|
|
90
|
+
|| isInternalRuntimeNotificationText(text)
|
|
91
|
+
|| isModelVisibleToolCompletionWrapper(text)
|
|
92
|
+
|| SYNTHETIC_USER_SOURCES.has(String(message?.meta?.source || ''))) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
return text.trim().length > 0 || (Array.isArray(message.content) && message.content.length > 0);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function latestActualUserInstructionIndex(messages) {
|
|
99
|
+
for (let index = (Array.isArray(messages) ? messages.length : 0) - 1; index >= 0; index -= 1) {
|
|
100
|
+
if (isActualUserInstructionMessage(messages[index])) return index;
|
|
101
|
+
}
|
|
102
|
+
return -1;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function latestActualUserInstructionMessage(messages) {
|
|
106
|
+
const index = latestActualUserInstructionIndex(messages);
|
|
107
|
+
return index >= 0 ? { ...messages[index] } : null;
|
|
108
|
+
}
|
|
109
|
+
|
|
54
110
|
export function isProtectedContextAckMessage(m) {
|
|
55
111
|
return m?.role === 'assistant'
|
|
56
112
|
&& typeof m.content === 'string'
|
|
@@ -58,6 +114,27 @@ export function isProtectedContextAckMessage(m) {
|
|
|
58
114
|
&& !Array.isArray(m.toolCalls);
|
|
59
115
|
}
|
|
60
116
|
|
|
117
|
+
export function referenceFilesManifestMessage(message) {
|
|
118
|
+
if (message?.role !== 'user' || typeof message.content !== 'string') return null;
|
|
119
|
+
const text = message.content.trimStart();
|
|
120
|
+
if (!/^Reference files:\s*/i.test(text)) return null;
|
|
121
|
+
const paths = [...text.matchAll(/^###\s+(.+?)\s*$/gm)]
|
|
122
|
+
.map((match) => String(match[1] || '').trim())
|
|
123
|
+
.filter(Boolean);
|
|
124
|
+
if (paths.length === 0) return null;
|
|
125
|
+
const uniquePaths = [...new Set(paths)];
|
|
126
|
+
return {
|
|
127
|
+
role: 'user',
|
|
128
|
+
content: [
|
|
129
|
+
'<system-reminder>',
|
|
130
|
+
'# Reference files',
|
|
131
|
+
'These files were attached when the session started. Re-read a path when its current contents are needed; the original bodies are not re-injected after Compact.',
|
|
132
|
+
...uniquePaths.map((path) => `- ${path}`),
|
|
133
|
+
'</system-reminder>',
|
|
134
|
+
].join('\n'),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
61
138
|
export function splitProtectedContext(messages) {
|
|
62
139
|
const protectedPrefix = [];
|
|
63
140
|
const conversation = [];
|
|
@@ -74,6 +151,14 @@ export function splitProtectedContext(messages) {
|
|
|
74
151
|
previousWasProtectedContext = true;
|
|
75
152
|
continue;
|
|
76
153
|
}
|
|
154
|
+
if (prefixMode) {
|
|
155
|
+
const manifest = referenceFilesManifestMessage(m);
|
|
156
|
+
if (manifest) {
|
|
157
|
+
protectedPrefix.push(manifest);
|
|
158
|
+
previousWasProtectedContext = true;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
77
162
|
if (prefixMode && previousWasProtectedContext && isProtectedContextAckMessage(m)) {
|
|
78
163
|
protectedPrefix.push(m);
|
|
79
164
|
previousWasProtectedContext = false;
|