@qvac/harness 0.7.0 → 1.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -1
- package/README.md +239 -2
- package/dist-lib/index.d.ts +58 -3
- package/dist-lib/index.js +736 -239
- package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.d.ts +1 -0
- package/dist-lib/lib/capabilities/completion-engine/abort-polyfill.js +10 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/answering.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/answering.js +17 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/approval.d.ts +4 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/approval.js +29 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.d.ts +4 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/direct-search.js +73 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execute.d.ts +41 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execute.js +49 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/executing.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/executing.js +102 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.d.ts +47 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/execution-plan.js +87 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/finishing.d.ts +2 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/finishing.js +32 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspect-preload.js +75 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/inspecting.js +152 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/loading-skill.js +94 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.d.ts +9 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preload-failure.js +11 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preloading.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preloading.js +114 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preparing.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/preparing.js +198 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejecting.js +71 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejection.d.ts +18 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/rejection.js +70 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/resolving.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/resolving.js +60 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/stream.d.ts +21 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/stream.js +48 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/streaming.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/streaming.js +156 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.d.ts +7 -0
- package/dist-lib/lib/capabilities/completion-engine/actors/wrap-up.js +61 -0
- package/dist-lib/lib/capabilities/completion-engine/driver.d.ts +25 -0
- package/dist-lib/lib/capabilities/completion-engine/driver.js +553 -0
- package/dist-lib/lib/capabilities/completion-engine/durable.d.ts +61 -0
- package/dist-lib/lib/capabilities/completion-engine/durable.js +150 -0
- package/dist-lib/lib/capabilities/completion-engine/operations.d.ts +6 -0
- package/dist-lib/lib/capabilities/completion-engine/operations.js +239 -0
- package/dist-lib/lib/capabilities/completion-engine/ports.d.ts +3 -0
- package/dist-lib/lib/capabilities/completion-engine/ports.js +267 -0
- package/dist-lib/lib/capabilities/completion-engine/session.d.ts +76 -0
- package/dist-lib/lib/capabilities/completion-engine/session.js +70 -0
- package/dist-lib/lib/capabilities/completion-loop/index.d.ts +80 -0
- package/dist-lib/lib/capabilities/completion-loop/index.js +158 -0
- package/dist-lib/lib/capabilities/completion-loop/metrics.d.ts +5 -0
- package/dist-lib/lib/capabilities/completion-loop/metrics.js +29 -0
- package/dist-lib/lib/capabilities/completion-loop/round.d.ts +33 -0
- package/dist-lib/lib/capabilities/completion-loop/round.js +353 -0
- package/dist-lib/lib/capabilities/completion-loop/tool-execution.d.ts +60 -0
- package/dist-lib/lib/capabilities/completion-loop/tool-execution.js +270 -0
- package/dist-lib/lib/capabilities/completion-loop/turns.d.ts +23 -0
- package/dist-lib/lib/capabilities/completion-loop/turns.js +112 -0
- package/dist-lib/lib/capabilities/completion-runtime.d.ts +46 -0
- package/dist-lib/lib/capabilities/completion-runtime.js +74 -0
- package/dist-lib/lib/capabilities/completion.d.ts +18 -335
- package/dist-lib/lib/capabilities/completion.js +20 -1301
- package/dist-lib/lib/capabilities/download.d.ts +1 -1
- package/dist-lib/lib/capabilities/download.js +7 -2
- package/dist-lib/lib/capabilities/invoke.js +5 -3
- package/dist-lib/lib/capabilities/tool-plan.d.ts +35 -0
- package/dist-lib/lib/capabilities/tool-plan.js +66 -0
- package/dist-lib/lib/capabilities/tool-turns.d.ts +11 -2
- package/dist-lib/lib/capabilities/tool-turns.js +30 -2
- package/dist-lib/lib/capabilities/types.d.ts +287 -0
- package/dist-lib/lib/capabilities/types.js +1 -0
- package/dist-lib/lib/completion-lifecycle.d.ts +14 -0
- package/dist-lib/lib/completion-lifecycle.js +126 -0
- package/dist-lib/lib/connect.d.ts +10 -3
- package/dist-lib/lib/connect.js +329 -23
- package/dist-lib/lib/contract-types.d.ts +19 -2
- package/dist-lib/lib/harness-lifecycle.d.ts +66 -0
- package/dist-lib/lib/harness-lifecycle.js +129 -0
- package/dist-lib/lib/helpers/detach-json.d.ts +1 -0
- package/dist-lib/lib/helpers/detach-json.js +146 -0
- package/dist-lib/lib/helpers/markup-scanner.d.ts +26 -0
- package/dist-lib/lib/helpers/markup-scanner.js +156 -0
- package/dist-lib/lib/helpers/markup-stream-filter.js +138 -35
- package/dist-lib/lib/helpers/race-abort.d.ts +9 -4
- package/dist-lib/lib/helpers/race-abort.js +2 -7
- package/dist-lib/lib/helpers/recovery-required.d.ts +1 -0
- package/dist-lib/lib/helpers/recovery-required.js +1 -0
- package/dist-lib/lib/helpers/run-outcome.d.ts +10 -2
- package/dist-lib/lib/helpers/run-outcome.js +8 -5
- package/dist-lib/lib/helpers/tool-call-markup.d.ts +2 -0
- package/dist-lib/lib/helpers/tool-call-markup.js +197 -82
- package/dist-lib/lib/hooks/built-in/arg-repair.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/arg-repair.js +1 -0
- package/dist-lib/lib/hooks/built-in/egress.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/egress.js +2 -1
- package/dist-lib/lib/hooks/built-in/sandbox.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/sandbox.js +6 -1
- package/dist-lib/lib/hooks/built-in/skill-catalog.d.ts +1 -0
- package/dist-lib/lib/hooks/built-in/skill-catalog.js +2 -1
- package/dist-lib/lib/hooks/pipeline.d.ts +4 -1
- package/dist-lib/lib/hooks/pipeline.js +24 -2
- package/dist-lib/lib/hooks/run.d.ts +2 -1
- package/dist-lib/lib/hooks/run.js +19 -7
- package/dist-lib/lib/hooks/types.d.ts +17 -6
- package/dist-lib/lib/machine/completion/actions/approval.d.ts +3 -0
- package/dist-lib/lib/machine/completion/actions/approval.js +16 -0
- package/dist-lib/lib/machine/completion/actions/completion.d.ts +23 -0
- package/dist-lib/lib/machine/completion/actions/completion.js +142 -0
- package/dist-lib/lib/machine/completion/actions/skills.d.ts +9 -0
- package/dist-lib/lib/machine/completion/actions/skills.js +83 -0
- package/dist-lib/lib/machine/completion/actions/tools.d.ts +16 -0
- package/dist-lib/lib/machine/completion/actions/tools.js +173 -0
- package/dist-lib/lib/machine/completion/context.d.ts +9 -0
- package/dist-lib/lib/machine/completion/context.js +44 -0
- package/dist-lib/lib/machine/completion/contract.d.ts +6 -0
- package/dist-lib/lib/machine/completion/contract.js +1 -0
- package/dist-lib/lib/machine/completion/guards/retry.d.ts +9 -0
- package/dist-lib/lib/machine/completion/guards/retry.js +25 -0
- package/dist-lib/lib/machine/completion/implementations.d.ts +81 -0
- package/dist-lib/lib/machine/completion/implementations.js +152 -0
- package/dist-lib/lib/machine/completion/machine.d.ts +375 -0
- package/dist-lib/lib/machine/completion/machine.js +511 -0
- package/dist-lib/lib/machine/completion/ports.d.ts +65 -0
- package/dist-lib/lib/machine/completion/ports.js +224 -0
- package/dist-lib/lib/machine/completion/rules.d.ts +39 -0
- package/dist-lib/lib/machine/completion/rules.js +115 -0
- package/dist-lib/lib/machine/completion/types.d.ts +493 -0
- package/dist-lib/lib/machine/completion/types.js +1 -0
- package/dist-lib/lib/machine/engine.d.ts +93 -0
- package/dist-lib/lib/machine/engine.js +483 -0
- package/dist-lib/lib/machine/errors.d.ts +44 -0
- package/dist-lib/lib/machine/errors.js +373 -0
- package/dist-lib/lib/machine/guards.d.ts +2 -0
- package/dist-lib/lib/machine/guards.js +6 -0
- package/dist-lib/lib/machine/index.d.ts +20 -0
- package/dist-lib/lib/machine/index.js +11 -0
- package/dist-lib/lib/machine/replay-output.d.ts +24 -0
- package/dist-lib/lib/machine/replay-output.js +50 -0
- package/dist-lib/lib/machine/stable-stringify.d.ts +1 -0
- package/dist-lib/lib/machine/stable-stringify.js +11 -0
- package/dist-lib/lib/models/model-handle.d.ts +5 -1
- package/dist-lib/lib/models/model-handle.js +8 -3
- package/dist-lib/lib/models/model-list.d.ts +5 -3
- package/dist-lib/lib/models/model-pool.d.ts +18 -7
- package/dist-lib/lib/models/model-pool.js +126 -38
- package/dist-lib/lib/run-log/history-codec.d.ts +23 -0
- package/dist-lib/lib/run-log/history-codec.js +973 -0
- package/dist-lib/lib/run-log/patch.d.ts +6 -0
- package/dist-lib/lib/run-log/patch.js +93 -0
- package/dist-lib/lib/run-log/persisted-actor.d.ts +18 -0
- package/dist-lib/lib/run-log/persisted-actor.js +218 -0
- package/dist-lib/lib/run-log/protocol-types.d.ts +153 -0
- package/dist-lib/lib/run-log/protocol-types.js +1 -0
- package/dist-lib/lib/run-log/protocol.d.ts +27 -0
- package/dist-lib/lib/run-log/protocol.js +1056 -0
- package/dist-lib/lib/run-log/replay.d.ts +25 -0
- package/dist-lib/lib/run-log/replay.js +129 -0
- package/dist-lib/lib/run-log/run-journal.d.ts +125 -0
- package/dist-lib/lib/run-log/run-journal.js +783 -0
- package/dist-lib/lib/run-log-inspect.d.ts +25 -0
- package/dist-lib/lib/run-log-inspect.js +627 -0
- package/dist-lib/lib/run-log-protocol.d.ts +2 -0
- package/dist-lib/lib/run-log-protocol.js +1 -0
- package/dist-lib/lib/run-log-redact.d.ts +27 -0
- package/dist-lib/lib/run-log-redact.js +1107 -0
- package/dist-lib/lib/serve.js +308 -12
- package/dist-lib/lib/spawn.js +3 -2
- package/dist-lib/lib/tool-call-display.d.ts +1 -21
- package/dist-lib/lib/tools/exec.d.ts +2 -1
- package/dist-lib/lib/tools/exec.js +57 -2
- package/dist-lib/lib/tools/generate-image.js +1 -1
- package/dist-lib/lib/tools/generate-music.js +1 -1
- package/dist-lib/lib/tools/http-request.d.ts +2 -1
- package/dist-lib/lib/tools/http-request.js +2 -1
- package/dist-lib/lib/tools/mcp-call.js +8 -1
- package/dist-lib/lib/tools/operations/builders.d.ts +1 -0
- package/dist-lib/lib/tools/operations/builders.js +1 -0
- package/dist-lib/lib/tools/operations/compile.js +11 -1
- package/dist-lib/lib/tools/operations/manifest.js +1 -0
- package/dist-lib/lib/tools/outbound-guard.d.ts +8 -6
- package/dist-lib/lib/tools/outbound-guard.js +25 -8
- package/dist-lib/lib/tools/skills/catalog.d.ts +1 -0
- package/dist-lib/lib/tools/skills/catalog.js +35 -0
- package/dist-lib/lib/tools/skills/cli-schema-types.d.ts +1 -0
- package/dist-lib/lib/tools/skills/cli-schema.js +25 -0
- package/dist-lib/lib/wire.d.ts +5 -0
- package/dist-lib/lib/wire.js +128 -5
- package/dist-lib/schema/harness.js +22 -6
- package/dist-lib/spec/hrpc/messages.js +100 -18
- package/dist-lib/spec/hyperschema/index.js +100 -18
- package/dist-lib/spec/hyperschema/schema.json +74 -1
- package/dist-lib/spec/hyperschema/types.d.ts +11 -3
- package/package.json +19 -1
- package/patches/@qvac%2Finference@0.20.0.patch +67 -0
- package/patches/bare-stow@0.1.5.patch +68 -0
- package/patches/hypercore-blob-server@1.15.0.patch +15 -0
- package/patches/localwatch@1.4.3.patch +13 -0
- package/patches/pyodide@314.0.2.patch +144 -0
|
@@ -0,0 +1,1107 @@
|
|
|
1
|
+
import { brandCapturedRecord, isCapturedJson } from './run-log/protocol.js';
|
|
2
|
+
import { isRecord as isObject } from './guards.js';
|
|
3
|
+
import { clipRawCall, MAX_RAW_CALL_CHARS, redactBareParameterMarkup, redactToolCallMarkup, toolCallMarkup } from './helpers/tool-call-markup.js';
|
|
4
|
+
export const REDACTED = '[redacted]';
|
|
5
|
+
const CREDENTIAL_FIELDS = new Set([
|
|
6
|
+
'password',
|
|
7
|
+
'passwd',
|
|
8
|
+
'passphrase',
|
|
9
|
+
'dbpassword',
|
|
10
|
+
'githubtoken',
|
|
11
|
+
'openaiapikey',
|
|
12
|
+
'clientpassword',
|
|
13
|
+
'clientpassphrase',
|
|
14
|
+
'secret',
|
|
15
|
+
'clientsecret',
|
|
16
|
+
'token',
|
|
17
|
+
'accesstoken',
|
|
18
|
+
'refreshtoken',
|
|
19
|
+
'idtoken',
|
|
20
|
+
'authtoken',
|
|
21
|
+
'sessiontoken',
|
|
22
|
+
'bearertoken',
|
|
23
|
+
'apitoken',
|
|
24
|
+
'apikey',
|
|
25
|
+
'accesskey',
|
|
26
|
+
'accesskeyid',
|
|
27
|
+
'awsaccesskeyid',
|
|
28
|
+
'privatekey',
|
|
29
|
+
'secretaccesskey',
|
|
30
|
+
'awssecretaccesskey',
|
|
31
|
+
'credentials',
|
|
32
|
+
'authorization',
|
|
33
|
+
'proxyauthorization',
|
|
34
|
+
'cookie',
|
|
35
|
+
'setcookie',
|
|
36
|
+
'xapikey',
|
|
37
|
+
'xamzsecuritytoken',
|
|
38
|
+
'xaccesstoken',
|
|
39
|
+
'xauthtoken'
|
|
40
|
+
]);
|
|
41
|
+
const NUMERIC_CREDENTIAL_FIELDS = new Set([
|
|
42
|
+
'password',
|
|
43
|
+
'passwd',
|
|
44
|
+
'passphrase',
|
|
45
|
+
'dbpassword',
|
|
46
|
+
'githubtoken',
|
|
47
|
+
'openaiapikey',
|
|
48
|
+
'clientpassword',
|
|
49
|
+
'clientpassphrase',
|
|
50
|
+
'clientsecret',
|
|
51
|
+
'apikey',
|
|
52
|
+
'accesstoken',
|
|
53
|
+
'refreshtoken',
|
|
54
|
+
'idtoken',
|
|
55
|
+
'authtoken',
|
|
56
|
+
'sessiontoken',
|
|
57
|
+
'bearertoken',
|
|
58
|
+
'apitoken',
|
|
59
|
+
'authorization',
|
|
60
|
+
'proxyauthorization',
|
|
61
|
+
'cookie',
|
|
62
|
+
'setcookie',
|
|
63
|
+
'xapikey',
|
|
64
|
+
'xamzsecuritytoken',
|
|
65
|
+
'xaccesstoken',
|
|
66
|
+
'xauthtoken',
|
|
67
|
+
'accesskey',
|
|
68
|
+
'privatekey',
|
|
69
|
+
'credentials',
|
|
70
|
+
'secretaccesskey',
|
|
71
|
+
'awssecretaccesskey'
|
|
72
|
+
]);
|
|
73
|
+
function normalizeFieldName(name) {
|
|
74
|
+
return name.toLowerCase().replace(/[-_]/g, '');
|
|
75
|
+
}
|
|
76
|
+
function isCredentialValue(name, value) {
|
|
77
|
+
const field = normalizeFieldName(name);
|
|
78
|
+
if (!CREDENTIAL_FIELDS.has(field)) {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
return (typeof value === 'string' ||
|
|
82
|
+
isObject(value) ||
|
|
83
|
+
(typeof value === 'number' && NUMERIC_CREDENTIAL_FIELDS.has(field)));
|
|
84
|
+
}
|
|
85
|
+
function isRecord(value) {
|
|
86
|
+
return isObject(value) && !Array.isArray(value);
|
|
87
|
+
}
|
|
88
|
+
function containsRedactedMarker(value) {
|
|
89
|
+
if (value === REDACTED)
|
|
90
|
+
return true;
|
|
91
|
+
if (!value || typeof value !== 'object')
|
|
92
|
+
return false;
|
|
93
|
+
if (Array.isArray(value)) {
|
|
94
|
+
return value.some(containsRedactedMarker);
|
|
95
|
+
}
|
|
96
|
+
return Object.values(value).some(containsRedactedMarker);
|
|
97
|
+
}
|
|
98
|
+
function redactRawCall({ raw, name, args, redactArgs, isSensitiveName }) {
|
|
99
|
+
const redacted = redactArgs(name, isRecord(args) ? args : {});
|
|
100
|
+
const clipped = raw.length >= MAX_RAW_CALL_CHARS;
|
|
101
|
+
if (containsRedactedMarker(redacted) || clipped) {
|
|
102
|
+
return clipRawCall(toolCallMarkup([{ name, arguments: redacted }]));
|
|
103
|
+
}
|
|
104
|
+
return redactBareParameterMarkup(redactToolCallMarkup(raw, redactArgs), isSensitiveName);
|
|
105
|
+
}
|
|
106
|
+
function define(out, key, value) {
|
|
107
|
+
Object.defineProperty(out, key, {
|
|
108
|
+
value,
|
|
109
|
+
writable: true,
|
|
110
|
+
enumerable: true,
|
|
111
|
+
configurable: true
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function isCompletionSnapshot(value) {
|
|
115
|
+
return (isRecord(value.context) &&
|
|
116
|
+
Object.hasOwn(value, 'value') &&
|
|
117
|
+
['active', 'done', 'stopped'].includes(String(value.status)));
|
|
118
|
+
}
|
|
119
|
+
function isOperation(value) {
|
|
120
|
+
return (typeof value.id === 'string' &&
|
|
121
|
+
typeof value.name === 'string' &&
|
|
122
|
+
Object.hasOwn(value, 'args') &&
|
|
123
|
+
(value.effect === 'read' || value.effect === 'write'));
|
|
124
|
+
}
|
|
125
|
+
function isReceipt(value) {
|
|
126
|
+
return (typeof value.id === 'string' &&
|
|
127
|
+
typeof value.name === 'string' &&
|
|
128
|
+
(value.effect === 'read' || value.effect === 'write') &&
|
|
129
|
+
(value.status === 'intent' || value.status === 'retry' || value.status === 'result'));
|
|
130
|
+
}
|
|
131
|
+
function isMetadata(value) {
|
|
132
|
+
return value.version === 5 && value.type === 'metadata' && typeof value.runId === 'string';
|
|
133
|
+
}
|
|
134
|
+
function isDurableFacts(value) {
|
|
135
|
+
return (typeof value.runId === 'string' &&
|
|
136
|
+
Array.isArray(value.tools) &&
|
|
137
|
+
Array.isArray(value.bindings) &&
|
|
138
|
+
isRecord(value.runBudget) &&
|
|
139
|
+
isRecord(value.outcome));
|
|
140
|
+
}
|
|
141
|
+
function mergeSensitiveSchema(actual, prompt) {
|
|
142
|
+
const properties = {};
|
|
143
|
+
const actualProperties = actual.properties ?? {};
|
|
144
|
+
const promptProperties = prompt.properties ?? {};
|
|
145
|
+
for (const key of new Set([...Object.keys(actualProperties), ...Object.keys(promptProperties)])) {
|
|
146
|
+
const actualChild = actualProperties[key];
|
|
147
|
+
const promptChild = promptProperties[key];
|
|
148
|
+
define(properties, key, actualChild && promptChild
|
|
149
|
+
? mergeSensitiveSchema(actualChild, promptChild)
|
|
150
|
+
: (promptChild ?? actualChild));
|
|
151
|
+
}
|
|
152
|
+
const items = actual.items && prompt.items
|
|
153
|
+
? mergeSensitiveSchema(actual.items, prompt.items)
|
|
154
|
+
: (prompt.items ?? actual.items);
|
|
155
|
+
const merged = { ...actual, ...prompt };
|
|
156
|
+
if (actual.sensitive === true || prompt.sensitive === true) {
|
|
157
|
+
merged.sensitive = true;
|
|
158
|
+
}
|
|
159
|
+
if (Object.keys(properties).length > 0) {
|
|
160
|
+
merged.properties = properties;
|
|
161
|
+
}
|
|
162
|
+
if (items) {
|
|
163
|
+
merged.items = items;
|
|
164
|
+
}
|
|
165
|
+
return merged;
|
|
166
|
+
}
|
|
167
|
+
function mergeSensitiveParameters(actual, prompt) {
|
|
168
|
+
const merged = mergeSensitiveSchema(actual, prompt);
|
|
169
|
+
return { ...merged, type: 'object', properties: merged.properties ?? {} };
|
|
170
|
+
}
|
|
171
|
+
function isDoneActorType(type) {
|
|
172
|
+
return typeof type === 'string' && type.startsWith('xstate.done.actor.');
|
|
173
|
+
}
|
|
174
|
+
function isPlainRecord(value) {
|
|
175
|
+
if (!isRecord(value))
|
|
176
|
+
return false;
|
|
177
|
+
const prototype = Object.getPrototypeOf(value);
|
|
178
|
+
return prototype === Object.prototype || prototype === null;
|
|
179
|
+
}
|
|
180
|
+
function normalizeJsonHook(value, key) {
|
|
181
|
+
let prototype = value;
|
|
182
|
+
let descriptor;
|
|
183
|
+
while (prototype && !descriptor) {
|
|
184
|
+
descriptor = Object.getOwnPropertyDescriptor(prototype, 'toJSON');
|
|
185
|
+
prototype = Object.getPrototypeOf(prototype);
|
|
186
|
+
}
|
|
187
|
+
if (!descriptor || ('value' in descriptor && typeof descriptor.value !== 'function')) {
|
|
188
|
+
return { handled: false };
|
|
189
|
+
}
|
|
190
|
+
if (key === undefined) {
|
|
191
|
+
const encoded = JSON.stringify(value);
|
|
192
|
+
return { handled: true, value: encoded === undefined ? undefined : JSON.parse(encoded) };
|
|
193
|
+
}
|
|
194
|
+
const holder = {};
|
|
195
|
+
define(holder, key, value);
|
|
196
|
+
const encoded = JSON.stringify(holder);
|
|
197
|
+
if (encoded === undefined) {
|
|
198
|
+
return { handled: true, value: undefined };
|
|
199
|
+
}
|
|
200
|
+
const parsed = JSON.parse(encoded);
|
|
201
|
+
if (parsed === null || typeof parsed !== 'object') {
|
|
202
|
+
return { handled: true, value: undefined };
|
|
203
|
+
}
|
|
204
|
+
return { handled: true, value: Object.hasOwn(parsed, key) ? Reflect.get(parsed, key) : undefined };
|
|
205
|
+
}
|
|
206
|
+
function cloneStructure(value, memo = new WeakMap()) {
|
|
207
|
+
if (!value || typeof value !== 'object') {
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
const hit = memo.get(value);
|
|
211
|
+
if (hit !== undefined) {
|
|
212
|
+
return hit;
|
|
213
|
+
}
|
|
214
|
+
if (Array.isArray(value)) {
|
|
215
|
+
const out = [];
|
|
216
|
+
memo.set(value, out);
|
|
217
|
+
for (const entry of value) {
|
|
218
|
+
out.push(cloneStructure(entry, memo));
|
|
219
|
+
}
|
|
220
|
+
return out;
|
|
221
|
+
}
|
|
222
|
+
const out = {};
|
|
223
|
+
memo.set(value, out);
|
|
224
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
225
|
+
define(out, key, cloneStructure(entry, memo));
|
|
226
|
+
}
|
|
227
|
+
return out;
|
|
228
|
+
}
|
|
229
|
+
function copyPatch(patch) {
|
|
230
|
+
return isCapturedJson(patch) ? patch : cloneStructure(patch);
|
|
231
|
+
}
|
|
232
|
+
function schemaFingerprint(parameters, prompted) {
|
|
233
|
+
try {
|
|
234
|
+
return JSON.stringify([parameters, prompted]);
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return undefined;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function schemaPropertyFor(schema, key) {
|
|
241
|
+
const properties = schema.properties;
|
|
242
|
+
if (!properties) {
|
|
243
|
+
return undefined;
|
|
244
|
+
}
|
|
245
|
+
if (Object.hasOwn(properties, key)) {
|
|
246
|
+
return properties[key];
|
|
247
|
+
}
|
|
248
|
+
const lower = key.toLowerCase();
|
|
249
|
+
for (const propertyKey of Object.keys(properties)) {
|
|
250
|
+
if (propertyKey.toLowerCase() === lower) {
|
|
251
|
+
return properties[propertyKey];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
function buildRedactor(initialTools = []) {
|
|
257
|
+
const schemas = new Map();
|
|
258
|
+
const schemaFingerprints = new Map();
|
|
259
|
+
let shared = new WeakMap();
|
|
260
|
+
let schemaShared = new WeakMap();
|
|
261
|
+
const historyMemos = new WeakMap();
|
|
262
|
+
const registerTools = (tools) => {
|
|
263
|
+
let registered = false;
|
|
264
|
+
for (const tool of tools) {
|
|
265
|
+
if (!tool || typeof tool.name !== 'string' || !tool.parameters)
|
|
266
|
+
continue;
|
|
267
|
+
const prompted = tool.prompt?.parameters;
|
|
268
|
+
const fingerprint = schemaFingerprint(tool.parameters, prompted);
|
|
269
|
+
if (fingerprint !== undefined && schemaFingerprints.get(tool.name) === fingerprint) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
const parameters = prompted
|
|
273
|
+
? mergeSensitiveParameters(tool.parameters, prompted)
|
|
274
|
+
: tool.parameters;
|
|
275
|
+
schemas.set(tool.name, parameters);
|
|
276
|
+
if (fingerprint === undefined) {
|
|
277
|
+
schemaFingerprints.delete(tool.name);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
schemaFingerprints.set(tool.name, fingerprint);
|
|
281
|
+
}
|
|
282
|
+
registered = true;
|
|
283
|
+
}
|
|
284
|
+
if (registered) {
|
|
285
|
+
shared = new WeakMap();
|
|
286
|
+
schemaShared = new WeakMap();
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
const isSensitiveMarkupName = (name) => {
|
|
290
|
+
if (CREDENTIAL_FIELDS.has(normalizeFieldName(name))) {
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
const lower = name.toLowerCase();
|
|
294
|
+
for (const schema of schemas.values()) {
|
|
295
|
+
const properties = schema.properties;
|
|
296
|
+
if (!properties) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
for (const key of Object.keys(properties)) {
|
|
300
|
+
if (key.toLowerCase() === lower && properties[key]?.sensitive === true) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return false;
|
|
306
|
+
};
|
|
307
|
+
const redactProse = (text) => redactBareParameterMarkup(redactToolCallMarkup(text, redactToolArguments), isSensitiveMarkupName);
|
|
308
|
+
const walk = (value, memo, jsonKey) => {
|
|
309
|
+
if (typeof value === 'string') {
|
|
310
|
+
return jsonKey === 'response' || jsonKey === 'contentText' ? redactProse(value) : value;
|
|
311
|
+
}
|
|
312
|
+
if (!value || typeof value !== 'object')
|
|
313
|
+
return value;
|
|
314
|
+
const hit = memo?.get(value);
|
|
315
|
+
if (hit !== undefined) {
|
|
316
|
+
return hit;
|
|
317
|
+
}
|
|
318
|
+
if (Array.isArray(value)) {
|
|
319
|
+
const out = [];
|
|
320
|
+
memo?.set(value, out);
|
|
321
|
+
for (let index = 0; index < value.length; index++) {
|
|
322
|
+
out.push(walk(value[index], memo, String(index)));
|
|
323
|
+
}
|
|
324
|
+
return out;
|
|
325
|
+
}
|
|
326
|
+
if (!isPlainRecord(value)) {
|
|
327
|
+
const normalized = normalizeJsonHook(value, jsonKey);
|
|
328
|
+
if (normalized.handled) {
|
|
329
|
+
return walk(normalized.value, memo);
|
|
330
|
+
}
|
|
331
|
+
const json = JSON.stringify(value);
|
|
332
|
+
return json === undefined ? cloneStructure(value, memo) : walk(JSON.parse(json), memo);
|
|
333
|
+
}
|
|
334
|
+
const normalized = normalizeJsonHook(value, jsonKey);
|
|
335
|
+
if (normalized.handled) {
|
|
336
|
+
return walk(normalized.value, memo);
|
|
337
|
+
}
|
|
338
|
+
const out = {};
|
|
339
|
+
memo?.set(value, out);
|
|
340
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
341
|
+
define(out, key, isCredentialValue(key, entry) ? REDACTED : walk(entry, memo, key));
|
|
342
|
+
}
|
|
343
|
+
return out;
|
|
344
|
+
};
|
|
345
|
+
const walkSchema = (value, schema, { memo, jsonKey } = {}) => {
|
|
346
|
+
if (schema.sensitive === true)
|
|
347
|
+
return REDACTED;
|
|
348
|
+
if (typeof value === 'string') {
|
|
349
|
+
return redactBareParameterMarkup(value, isSensitiveMarkupName);
|
|
350
|
+
}
|
|
351
|
+
if (value && typeof value === 'object') {
|
|
352
|
+
const normalized = normalizeJsonHook(value, jsonKey);
|
|
353
|
+
if (normalized.handled) {
|
|
354
|
+
return walkSchema(normalized.value, schema, { memo });
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
const cacheSchema = memo === shared;
|
|
358
|
+
if (cacheSchema && value && typeof value === 'object') {
|
|
359
|
+
const cached = schemaShared.get(value)?.get(schema);
|
|
360
|
+
if (cached !== undefined) {
|
|
361
|
+
return cached;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
if (Array.isArray(value)) {
|
|
365
|
+
if (!schema.items) {
|
|
366
|
+
return walk(value, memo, jsonKey);
|
|
367
|
+
}
|
|
368
|
+
const out = [];
|
|
369
|
+
if (cacheSchema) {
|
|
370
|
+
cacheSchemaValue(value, schema, out);
|
|
371
|
+
}
|
|
372
|
+
for (let index = 0; index < value.length; index++) {
|
|
373
|
+
out.push(walkSchema(value[index], schema.items, { memo, jsonKey: String(index) }));
|
|
374
|
+
}
|
|
375
|
+
return out;
|
|
376
|
+
}
|
|
377
|
+
if (!isPlainRecord(value)) {
|
|
378
|
+
return walk(value, memo, jsonKey);
|
|
379
|
+
}
|
|
380
|
+
const out = {};
|
|
381
|
+
if (cacheSchema) {
|
|
382
|
+
cacheSchemaValue(value, schema, out);
|
|
383
|
+
}
|
|
384
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
385
|
+
const childSchema = schemaPropertyFor(schema, key);
|
|
386
|
+
if (isCredentialValue(key, entry)) {
|
|
387
|
+
define(out, key, REDACTED);
|
|
388
|
+
}
|
|
389
|
+
else if (childSchema) {
|
|
390
|
+
define(out, key, walkSchema(entry, childSchema, { memo, jsonKey: key }));
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
define(out, key, walk(entry, memo, key));
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return out;
|
|
397
|
+
};
|
|
398
|
+
function cacheSchemaValue(value, schema, result) {
|
|
399
|
+
let bySchema = schemaShared.get(value);
|
|
400
|
+
if (!bySchema) {
|
|
401
|
+
schemaShared.set(value, (bySchema = new WeakMap()));
|
|
402
|
+
}
|
|
403
|
+
bySchema.set(schema, result);
|
|
404
|
+
}
|
|
405
|
+
const walkCall = (value, memo) => {
|
|
406
|
+
if (!isRecord(value) || typeof value.name !== 'string') {
|
|
407
|
+
return walk(value, memo);
|
|
408
|
+
}
|
|
409
|
+
const schema = schemas.get(value.name);
|
|
410
|
+
const out = {};
|
|
411
|
+
const argsKey = Object.hasOwn(value, 'args') ? 'args' : 'arguments';
|
|
412
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
413
|
+
if (isCredentialValue(key, entry)) {
|
|
414
|
+
define(out, key, REDACTED);
|
|
415
|
+
}
|
|
416
|
+
else if (key === argsKey && schema) {
|
|
417
|
+
define(out, key, walkSchema(entry, schema, { memo, jsonKey: key }));
|
|
418
|
+
}
|
|
419
|
+
else if ((key === 'raw' || key === 'rawCall') && typeof entry === 'string') {
|
|
420
|
+
define(out, key, redactRawCall({
|
|
421
|
+
raw: entry,
|
|
422
|
+
name: value.name,
|
|
423
|
+
args: value[argsKey],
|
|
424
|
+
redactArgs: redactToolArguments,
|
|
425
|
+
isSensitiveName: isSensitiveMarkupName
|
|
426
|
+
}));
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
define(out, key, walk(entry, memo, key));
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
return out;
|
|
433
|
+
};
|
|
434
|
+
const walkSkillPreload = (value, memo) => {
|
|
435
|
+
if (!isRecord(value)) {
|
|
436
|
+
return walk(value, memo);
|
|
437
|
+
}
|
|
438
|
+
const hit = memo?.get(value);
|
|
439
|
+
if (hit !== undefined) {
|
|
440
|
+
return hit;
|
|
441
|
+
}
|
|
442
|
+
const schema = schemas.get('skill');
|
|
443
|
+
const out = {};
|
|
444
|
+
memo?.set(value, out);
|
|
445
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
446
|
+
let sanitized;
|
|
447
|
+
if (key === 'args' && schema) {
|
|
448
|
+
sanitized = walkSchema(entry, schema, { memo, jsonKey: key });
|
|
449
|
+
}
|
|
450
|
+
else if (isCredentialValue(key, entry)) {
|
|
451
|
+
sanitized = REDACTED;
|
|
452
|
+
}
|
|
453
|
+
else {
|
|
454
|
+
sanitized = walk(entry, memo, key);
|
|
455
|
+
}
|
|
456
|
+
define(out, key, sanitized);
|
|
457
|
+
}
|
|
458
|
+
return out;
|
|
459
|
+
};
|
|
460
|
+
const walkLastRound = (value, memo) => {
|
|
461
|
+
const round = {};
|
|
462
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
463
|
+
let safeEntry;
|
|
464
|
+
if (key === 'toolCalls' && Array.isArray(entry)) {
|
|
465
|
+
safeEntry = entry.map((call) => walkCall(call, memo));
|
|
466
|
+
}
|
|
467
|
+
else if (key === 'contentText' && typeof entry === 'string') {
|
|
468
|
+
safeEntry = redactProse(entry);
|
|
469
|
+
}
|
|
470
|
+
else {
|
|
471
|
+
safeEntry = walk(entry, memo, key);
|
|
472
|
+
}
|
|
473
|
+
define(round, key, safeEntry);
|
|
474
|
+
}
|
|
475
|
+
return round;
|
|
476
|
+
};
|
|
477
|
+
const walkRejectedCall = (value, memo) => {
|
|
478
|
+
const rejected = {};
|
|
479
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
480
|
+
let safeEntry;
|
|
481
|
+
if (key === 'call') {
|
|
482
|
+
safeEntry = walkCall(entry, memo);
|
|
483
|
+
}
|
|
484
|
+
else if (key === 'activity') {
|
|
485
|
+
safeEntry = walkToolActivity(entry, memo);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
safeEntry = walk(entry, memo, key);
|
|
489
|
+
}
|
|
490
|
+
define(rejected, key, safeEntry);
|
|
491
|
+
}
|
|
492
|
+
return rejected;
|
|
493
|
+
};
|
|
494
|
+
const walkHistoryOutput = (splice, memo) => {
|
|
495
|
+
const messages = splice.messages;
|
|
496
|
+
if (!Array.isArray(messages)) {
|
|
497
|
+
return cloneStructure(splice, memo);
|
|
498
|
+
}
|
|
499
|
+
const out = {};
|
|
500
|
+
for (const [key, entry] of Object.entries(splice)) {
|
|
501
|
+
define(out, key, key === 'messages' ? walkHistory(messages, memo) : cloneStructure(entry, memo));
|
|
502
|
+
}
|
|
503
|
+
return out;
|
|
504
|
+
};
|
|
505
|
+
const walkHistoryEntry = (message, memo) => {
|
|
506
|
+
if (!isRecord(message) || message.role !== 'assistant' || typeof message.content !== 'string') {
|
|
507
|
+
return cloneStructure(message, memo);
|
|
508
|
+
}
|
|
509
|
+
const hit = memo?.get(message);
|
|
510
|
+
if (hit !== undefined) {
|
|
511
|
+
return hit;
|
|
512
|
+
}
|
|
513
|
+
const out = cloneStructure(message, memo);
|
|
514
|
+
out.content = redactProse(message.content);
|
|
515
|
+
memo?.set(message, out);
|
|
516
|
+
return out;
|
|
517
|
+
};
|
|
518
|
+
const historyMemoFor = (memo) => {
|
|
519
|
+
if (!memo) {
|
|
520
|
+
return undefined;
|
|
521
|
+
}
|
|
522
|
+
let history = historyMemos.get(memo);
|
|
523
|
+
if (!history) {
|
|
524
|
+
historyMemos.set(memo, (history = new WeakMap()));
|
|
525
|
+
}
|
|
526
|
+
return history;
|
|
527
|
+
};
|
|
528
|
+
const walkHistory = (messages, memo) => {
|
|
529
|
+
const hit = memo?.get(messages);
|
|
530
|
+
if (hit !== undefined) {
|
|
531
|
+
return hit;
|
|
532
|
+
}
|
|
533
|
+
const out = messages.map((message) => walkHistoryEntry(message, memo));
|
|
534
|
+
memo?.set(messages, out);
|
|
535
|
+
return out;
|
|
536
|
+
};
|
|
537
|
+
const walkContext = (context, memo) => {
|
|
538
|
+
const out = {};
|
|
539
|
+
const handled = new Set();
|
|
540
|
+
for (const [key, entry] of Object.entries(context)) {
|
|
541
|
+
if (key === 'currentCall' || key === 'pendingCall') {
|
|
542
|
+
const safeCall = key === 'pendingCall' ? walkApprovalCall(entry, memo) : walkCall(entry, memo);
|
|
543
|
+
define(out, key, safeCall);
|
|
544
|
+
handled.add(key);
|
|
545
|
+
}
|
|
546
|
+
else if (key === 'toolQueue' && Array.isArray(entry)) {
|
|
547
|
+
define(out, key, entry.map((call) => walkCall(call, memo)));
|
|
548
|
+
handled.add(key);
|
|
549
|
+
}
|
|
550
|
+
else if (key === 'lastRound' && isRecord(entry)) {
|
|
551
|
+
define(out, key, walkLastRound(entry, memo));
|
|
552
|
+
handled.add(key);
|
|
553
|
+
}
|
|
554
|
+
else if (key === 'rejectedCall' && isRecord(entry)) {
|
|
555
|
+
define(out, key, walkRejectedCall(entry, memo));
|
|
556
|
+
handled.add(key);
|
|
557
|
+
}
|
|
558
|
+
else if (key === 'skillPreload') {
|
|
559
|
+
define(out, key, walkSkillPreload(entry, memo));
|
|
560
|
+
handled.add(key);
|
|
561
|
+
}
|
|
562
|
+
else if (key === 'history' && Array.isArray(entry)) {
|
|
563
|
+
define(out, key, walkHistory(entry, historyMemoFor(memo)));
|
|
564
|
+
handled.add(key);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
for (const [key, entry] of Object.entries(context)) {
|
|
568
|
+
if (handled.has(key))
|
|
569
|
+
continue;
|
|
570
|
+
let safeEntry;
|
|
571
|
+
if (key === 'execution') {
|
|
572
|
+
safeEntry = walkExecution(entry, memo);
|
|
573
|
+
}
|
|
574
|
+
else if (key === 'durable') {
|
|
575
|
+
safeEntry = walkFacts(entry, memo);
|
|
576
|
+
}
|
|
577
|
+
else if (isCredentialValue(key, entry)) {
|
|
578
|
+
safeEntry = REDACTED;
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
safeEntry = walk(entry, memo, key);
|
|
582
|
+
}
|
|
583
|
+
define(out, key, safeEntry);
|
|
584
|
+
}
|
|
585
|
+
return out;
|
|
586
|
+
};
|
|
587
|
+
const walkSnapshot = (snapshot, memo) => {
|
|
588
|
+
const hit = memo?.get(snapshot);
|
|
589
|
+
if (hit !== undefined) {
|
|
590
|
+
if (isRecord(hit)) {
|
|
591
|
+
return hit;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
const out = {};
|
|
595
|
+
memo?.set(snapshot, out);
|
|
596
|
+
for (const [key, entry] of Object.entries(snapshot)) {
|
|
597
|
+
let safeEntry;
|
|
598
|
+
if (key === 'context' && isRecord(entry)) {
|
|
599
|
+
safeEntry = walkContext(entry, memo);
|
|
600
|
+
}
|
|
601
|
+
else if (isCredentialValue(key, entry)) {
|
|
602
|
+
safeEntry = REDACTED;
|
|
603
|
+
}
|
|
604
|
+
else {
|
|
605
|
+
safeEntry = walk(entry, memo, key);
|
|
606
|
+
}
|
|
607
|
+
define(out, key, safeEntry);
|
|
608
|
+
}
|
|
609
|
+
return out;
|
|
610
|
+
};
|
|
611
|
+
const walkOperation = (operation, memo) => {
|
|
612
|
+
const args = isRecord(operation.args) ? operation.args : undefined;
|
|
613
|
+
const hookToolName = (operation.name === 'hook:runPreToolFold' || operation.name === 'hook:runPostToolFold') &&
|
|
614
|
+
typeof args?.toolName === 'string'
|
|
615
|
+
? args.toolName
|
|
616
|
+
: undefined;
|
|
617
|
+
const schema = typeof operation.name === 'string'
|
|
618
|
+
? (schemas.get(operation.name) ?? (hookToolName ? schemas.get(hookToolName) : undefined))
|
|
619
|
+
: undefined;
|
|
620
|
+
const out = {};
|
|
621
|
+
for (const [key, entry] of Object.entries(operation)) {
|
|
622
|
+
if (key === 'args' && schema && hookToolName) {
|
|
623
|
+
define(out, key, walkHookOperationArgs(entry, schema, memo));
|
|
624
|
+
}
|
|
625
|
+
else if (key === 'args' && schema) {
|
|
626
|
+
define(out, key, walkSchema(entry, schema, { memo, jsonKey: key }));
|
|
627
|
+
}
|
|
628
|
+
else if (key === 'facts') {
|
|
629
|
+
define(out, key, walkFacts(entry, memo));
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
define(out, key, isCredentialValue(key, entry) ? REDACTED : walk(entry, memo, key));
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return out;
|
|
636
|
+
};
|
|
637
|
+
const walkActorEvent = (event, memo) => {
|
|
638
|
+
const hit = memo?.get(event);
|
|
639
|
+
if (hit !== undefined) {
|
|
640
|
+
if (isRecord(hit)) {
|
|
641
|
+
return hit;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
const type = String(event.type);
|
|
645
|
+
const outputKind = type.slice(type.lastIndexOf('.') + 1);
|
|
646
|
+
const out = {};
|
|
647
|
+
memo?.set(event, out);
|
|
648
|
+
for (const [key, entry] of Object.entries(event)) {
|
|
649
|
+
if (key !== 'output' || !isRecord(entry)) {
|
|
650
|
+
define(out, key, isCredentialValue(key, entry) ? REDACTED : walk(entry, memo, key));
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
const output = {};
|
|
654
|
+
for (const [outputKey, outputValue] of Object.entries(entry)) {
|
|
655
|
+
if (outputKey === 'history' && isRecord(outputValue)) {
|
|
656
|
+
define(output, outputKey, walkHistoryOutput(outputValue, historyMemoFor(memo)));
|
|
657
|
+
}
|
|
658
|
+
else if ((outputKind === 'generating' || outputKind === 'resolving') &&
|
|
659
|
+
(outputKey === 'toolCalls' || outputKey === 'calls') &&
|
|
660
|
+
Array.isArray(outputValue)) {
|
|
661
|
+
define(output, outputKey, outputValue.map((call) => walkCall(call, memo)));
|
|
662
|
+
}
|
|
663
|
+
else if ((outputKind === 'inspecting' || outputKind === 'searching') &&
|
|
664
|
+
outputKey === 'directTool' &&
|
|
665
|
+
isRecord(outputValue)) {
|
|
666
|
+
define(output, outputKey, walkDirectTool(outputValue, memo));
|
|
667
|
+
}
|
|
668
|
+
else if (outputKind === 'inspecting' &&
|
|
669
|
+
(outputKey === 'rejection' || outputKey === 'rejected') &&
|
|
670
|
+
isRecord(outputValue)) {
|
|
671
|
+
define(output, outputKey, walkRejection(outputValue, memo));
|
|
672
|
+
}
|
|
673
|
+
else if (outputKey === 'execution') {
|
|
674
|
+
define(output, outputKey, walkExecution(outputValue, memo));
|
|
675
|
+
}
|
|
676
|
+
else if (outputKind === 'inspecting' && outputKey === 'call' && isRecord(outputValue)) {
|
|
677
|
+
define(output, outputKey, walkCall(outputValue, memo));
|
|
678
|
+
}
|
|
679
|
+
else if ((outputKind === 'preloadChecking' || outputKind === 'inspectPreload') &&
|
|
680
|
+
outputKey === 'args') {
|
|
681
|
+
const schema = schemas.get('skill');
|
|
682
|
+
define(output, outputKey, schema
|
|
683
|
+
? walkSchema(outputValue, schema, { memo, jsonKey: outputKey })
|
|
684
|
+
: walk(outputValue, memo, outputKey));
|
|
685
|
+
}
|
|
686
|
+
else if (outputKind === 'preparing') {
|
|
687
|
+
define(output, outputKey, walkPreparing(outputValue, memo));
|
|
688
|
+
}
|
|
689
|
+
else {
|
|
690
|
+
define(output, outputKey, walk(outputValue, memo, outputKey));
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
define(out, key, output);
|
|
694
|
+
}
|
|
695
|
+
return out;
|
|
696
|
+
};
|
|
697
|
+
const walkApprovalCall = (value, memo) => {
|
|
698
|
+
if (!isRecord(value)) {
|
|
699
|
+
return walk(value, memo);
|
|
700
|
+
}
|
|
701
|
+
const call = { name: value.name, arguments: value.arguments };
|
|
702
|
+
const sanitized = walkCall(call, memo);
|
|
703
|
+
const sanitizedArgs = isRecord(sanitized) ? sanitized.arguments : undefined;
|
|
704
|
+
const out = {};
|
|
705
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
706
|
+
define(out, key, key === 'arguments' ? sanitizedArgs : walk(entry, memo, key));
|
|
707
|
+
}
|
|
708
|
+
return out;
|
|
709
|
+
};
|
|
710
|
+
const walkExecution = (value, memo) => {
|
|
711
|
+
if (!isRecord(value)) {
|
|
712
|
+
return walk(value, memo);
|
|
713
|
+
}
|
|
714
|
+
const out = {};
|
|
715
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
716
|
+
if (key !== 'gate' || !isRecord(entry)) {
|
|
717
|
+
define(out, key, walk(entry, memo, key));
|
|
718
|
+
}
|
|
719
|
+
else {
|
|
720
|
+
const gate = {};
|
|
721
|
+
for (const [gateKey, gateValue] of Object.entries(entry)) {
|
|
722
|
+
define(gate, gateKey, gateKey === 'call' ? walkApprovalCall(gateValue, memo) : walk(gateValue, memo, gateKey));
|
|
723
|
+
}
|
|
724
|
+
define(out, key, gate);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
return out;
|
|
728
|
+
};
|
|
729
|
+
const walkToolActivity = (value, memo) => {
|
|
730
|
+
if (!isRecord(value)) {
|
|
731
|
+
return walk(value, memo);
|
|
732
|
+
}
|
|
733
|
+
const out = {};
|
|
734
|
+
const call = walkCall({ name: value.name, args: value.args }, memo);
|
|
735
|
+
const sanitizedArgs = isRecord(call) ? call.args : undefined;
|
|
736
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
737
|
+
define(out, key, key === 'args' ? sanitizedArgs : walk(entry, memo, key));
|
|
738
|
+
}
|
|
739
|
+
return out;
|
|
740
|
+
};
|
|
741
|
+
const walkTrusted = (value) => {
|
|
742
|
+
if (!value || typeof value !== 'object') {
|
|
743
|
+
return value;
|
|
744
|
+
}
|
|
745
|
+
if (Array.isArray(value)) {
|
|
746
|
+
return value.map((entry) => walkTrusted(entry));
|
|
747
|
+
}
|
|
748
|
+
if (!isPlainRecord(value)) {
|
|
749
|
+
return cloneStructure(value);
|
|
750
|
+
}
|
|
751
|
+
const out = {};
|
|
752
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
753
|
+
define(out, key, walkTrusted(entry));
|
|
754
|
+
}
|
|
755
|
+
return out;
|
|
756
|
+
};
|
|
757
|
+
const walkTrustedSchema = (schema) => {
|
|
758
|
+
if (!isPlainRecord(schema)) {
|
|
759
|
+
return walkTrusted(schema);
|
|
760
|
+
}
|
|
761
|
+
const out = {};
|
|
762
|
+
for (const [key, entry] of Object.entries(schema)) {
|
|
763
|
+
if (key === 'properties' && isRecord(entry)) {
|
|
764
|
+
const properties = {};
|
|
765
|
+
for (const [name, child] of Object.entries(entry)) {
|
|
766
|
+
define(properties, name, walkTrustedSchema(child));
|
|
767
|
+
}
|
|
768
|
+
define(out, key, properties);
|
|
769
|
+
}
|
|
770
|
+
else if (key === 'items') {
|
|
771
|
+
define(out, key, walkTrustedSchema(entry));
|
|
772
|
+
}
|
|
773
|
+
else {
|
|
774
|
+
define(out, key, walkTrusted(entry));
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return out;
|
|
778
|
+
};
|
|
779
|
+
const walkHookOperationArgs = (value, schema, memo) => {
|
|
780
|
+
if (!isRecord(value)) {
|
|
781
|
+
return walk(value, memo);
|
|
782
|
+
}
|
|
783
|
+
const out = {};
|
|
784
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
785
|
+
if (key === 'args') {
|
|
786
|
+
define(out, key, walkSchema(entry, schema, { memo, jsonKey: key }));
|
|
787
|
+
}
|
|
788
|
+
else if (key === 'parameters') {
|
|
789
|
+
define(out, key, walkTrustedSchema(entry));
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
define(out, key, isCredentialValue(key, entry) ? REDACTED : walk(entry, memo, key));
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
return out;
|
|
796
|
+
};
|
|
797
|
+
function redactHookPreToolResult(result, schema) {
|
|
798
|
+
const out = {};
|
|
799
|
+
for (const [key, entry] of Object.entries(result)) {
|
|
800
|
+
define(out, key, key === 'args'
|
|
801
|
+
? walkSchema(entry, schema, { jsonKey: key })
|
|
802
|
+
: walk(entry, new WeakMap(), key));
|
|
803
|
+
}
|
|
804
|
+
return out;
|
|
805
|
+
}
|
|
806
|
+
function redactOperationResult(operation, result) {
|
|
807
|
+
const toolName = operation.name === 'hook:runPreToolFold' && isRecord(operation.args)
|
|
808
|
+
? operation.args.toolName
|
|
809
|
+
: undefined;
|
|
810
|
+
const schema = typeof toolName === 'string' ? schemas.get(toolName) : undefined;
|
|
811
|
+
if (schema && isRecord(result)) {
|
|
812
|
+
return redactHookPreToolResult(result, schema);
|
|
813
|
+
}
|
|
814
|
+
return walk(result, new WeakMap());
|
|
815
|
+
}
|
|
816
|
+
function redactToolArguments(name, args) {
|
|
817
|
+
const schema = schemas.get(name);
|
|
818
|
+
const safe = schema
|
|
819
|
+
? walkSchema(args, schema, { memo: new WeakMap(), jsonKey: 'args' })
|
|
820
|
+
: walk(args, new WeakMap());
|
|
821
|
+
return isRecord(safe) ? safe : {};
|
|
822
|
+
}
|
|
823
|
+
const walkPrompt = (prompt, memo) => {
|
|
824
|
+
if (!isRecord(prompt)) {
|
|
825
|
+
return walk(prompt, memo);
|
|
826
|
+
}
|
|
827
|
+
const out = {};
|
|
828
|
+
for (const [key, entry] of Object.entries(prompt)) {
|
|
829
|
+
define(out, key, key === 'parameters' ? walkTrustedSchema(entry) : walk(entry, memo, key));
|
|
830
|
+
}
|
|
831
|
+
return out;
|
|
832
|
+
};
|
|
833
|
+
const walkFacts = (value, memo) => {
|
|
834
|
+
if (!isRecord(value)) {
|
|
835
|
+
return walk(value, memo);
|
|
836
|
+
}
|
|
837
|
+
const out = {};
|
|
838
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
839
|
+
if (key === 'tools' && Array.isArray(entry)) {
|
|
840
|
+
define(out, key, entry.map((tool) => {
|
|
841
|
+
if (!isRecord(tool)) {
|
|
842
|
+
return walk(tool, memo, 'tools');
|
|
843
|
+
}
|
|
844
|
+
const copy = {};
|
|
845
|
+
for (const [toolKey, toolValue] of Object.entries(tool)) {
|
|
846
|
+
define(copy, toolKey, toolKey === 'prompt' ? walkPrompt(toolValue, memo) : walk(toolValue, memo, toolKey));
|
|
847
|
+
}
|
|
848
|
+
return copy;
|
|
849
|
+
}));
|
|
850
|
+
}
|
|
851
|
+
else {
|
|
852
|
+
define(out, key, walk(entry, memo, key));
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
return out;
|
|
856
|
+
};
|
|
857
|
+
const walkResponseFormat = (value, memo) => {
|
|
858
|
+
if (!isRecord(value)) {
|
|
859
|
+
return walk(value, memo);
|
|
860
|
+
}
|
|
861
|
+
const out = {};
|
|
862
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
863
|
+
if (key !== 'json_schema' || !isRecord(entry)) {
|
|
864
|
+
define(out, key, walk(entry, memo, key));
|
|
865
|
+
continue;
|
|
866
|
+
}
|
|
867
|
+
const jsonSchema = {};
|
|
868
|
+
for (const [schemaKey, schemaValue] of Object.entries(entry)) {
|
|
869
|
+
define(jsonSchema, schemaKey, schemaKey === 'schema'
|
|
870
|
+
? walkTrustedSchema(schemaValue)
|
|
871
|
+
: walk(schemaValue, memo, schemaKey));
|
|
872
|
+
}
|
|
873
|
+
define(out, key, jsonSchema);
|
|
874
|
+
}
|
|
875
|
+
return out;
|
|
876
|
+
};
|
|
877
|
+
const walkRequest = (value, memo) => {
|
|
878
|
+
if (!isRecord(value)) {
|
|
879
|
+
return walk(value, memo);
|
|
880
|
+
}
|
|
881
|
+
const out = {};
|
|
882
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
883
|
+
define(out, key, key === 'responseFormat' ? walkResponseFormat(entry, memo) : walk(entry, memo, key));
|
|
884
|
+
}
|
|
885
|
+
return out;
|
|
886
|
+
};
|
|
887
|
+
const walkMetadata = (value, memo) => {
|
|
888
|
+
const out = {};
|
|
889
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
890
|
+
let safeEntry;
|
|
891
|
+
if (key === 'definition') {
|
|
892
|
+
safeEntry = walkTrusted(entry);
|
|
893
|
+
}
|
|
894
|
+
else if (key === 'request') {
|
|
895
|
+
safeEntry = walkRequest(entry, memo);
|
|
896
|
+
}
|
|
897
|
+
else {
|
|
898
|
+
safeEntry = walk(entry, memo, key);
|
|
899
|
+
}
|
|
900
|
+
define(out, key, safeEntry);
|
|
901
|
+
}
|
|
902
|
+
return out;
|
|
903
|
+
};
|
|
904
|
+
const walkBoundary = (value, memo) => {
|
|
905
|
+
if (!isRecord(value)) {
|
|
906
|
+
return walk(value, memo);
|
|
907
|
+
}
|
|
908
|
+
if (isDurableFacts(value)) {
|
|
909
|
+
return walkFacts(value, memo);
|
|
910
|
+
}
|
|
911
|
+
if (value.version === 5 && value.type === 'operation' && isRecord(value.receipt)) {
|
|
912
|
+
const out = {};
|
|
913
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
914
|
+
define(out, key, key === 'receipt' && isRecord(entry) ? walkOperation(entry, memo) : walk(entry, memo, key));
|
|
915
|
+
}
|
|
916
|
+
return out;
|
|
917
|
+
}
|
|
918
|
+
if (isCompletionSnapshot(value)) {
|
|
919
|
+
return walkSnapshot(value, memo);
|
|
920
|
+
}
|
|
921
|
+
if (isOperation(value) || isReceipt(value)) {
|
|
922
|
+
return walkOperation(value, memo);
|
|
923
|
+
}
|
|
924
|
+
if (isDoneActorType(value.type)) {
|
|
925
|
+
return walkActorEvent(value, memo);
|
|
926
|
+
}
|
|
927
|
+
if (value.type === 'tool-activity') {
|
|
928
|
+
return walkToolActivity(value, memo);
|
|
929
|
+
}
|
|
930
|
+
if (isMetadata(value)) {
|
|
931
|
+
return walkMetadata(value, memo);
|
|
932
|
+
}
|
|
933
|
+
return walk(value, memo);
|
|
934
|
+
};
|
|
935
|
+
const walkRunRecord = (record, memo) => {
|
|
936
|
+
if (isCapturedJson(record)) {
|
|
937
|
+
return record;
|
|
938
|
+
}
|
|
939
|
+
if (!isRecord(record)) {
|
|
940
|
+
return walk(record, memo);
|
|
941
|
+
}
|
|
942
|
+
if (isMetadata(record)) {
|
|
943
|
+
return walkMetadata(record, memo);
|
|
944
|
+
}
|
|
945
|
+
const copied = {};
|
|
946
|
+
for (const [recordKey, recordValue] of Object.entries(record)) {
|
|
947
|
+
if (isCapturedJson(recordValue)) {
|
|
948
|
+
define(copied, recordKey, recordValue);
|
|
949
|
+
}
|
|
950
|
+
else if (recordKey === 'snapshot') {
|
|
951
|
+
define(copied, recordKey, walkBoundary(recordValue, memo));
|
|
952
|
+
}
|
|
953
|
+
else if ((recordKey === 'events' || recordKey === 'patch') && isRecord(recordValue)) {
|
|
954
|
+
define(copied, recordKey, copyPatch(recordValue));
|
|
955
|
+
}
|
|
956
|
+
else if (recordKey === 'events' && Array.isArray(recordValue)) {
|
|
957
|
+
define(copied, recordKey, recordValue.map((event) => (isRecord(event) ? copyPatch(event) : walk(event, memo))));
|
|
958
|
+
}
|
|
959
|
+
else if (recordKey === 'receipt' && isRecord(recordValue)) {
|
|
960
|
+
define(copied, recordKey, walkOperation(recordValue, memo));
|
|
961
|
+
}
|
|
962
|
+
else {
|
|
963
|
+
define(copied, recordKey, walk(recordValue, memo));
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
return copied;
|
|
967
|
+
};
|
|
968
|
+
const walkEngineStep = (step, memo) => {
|
|
969
|
+
const out = {};
|
|
970
|
+
for (const [key, entry] of Object.entries(step)) {
|
|
971
|
+
if (key !== 'records' || !Array.isArray(entry)) {
|
|
972
|
+
define(out, key, walk(entry, memo, key));
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
define(out, key, entry.map((record) => walkRunRecord(record, memo)));
|
|
976
|
+
}
|
|
977
|
+
return out;
|
|
978
|
+
};
|
|
979
|
+
const walkDirectTool = (value, memo) => {
|
|
980
|
+
const out = {};
|
|
981
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
982
|
+
if (key === 'call') {
|
|
983
|
+
define(out, key, walkCall(entry, memo));
|
|
984
|
+
}
|
|
985
|
+
else if (key === 'execution') {
|
|
986
|
+
define(out, key, walkExecution(entry, memo));
|
|
987
|
+
}
|
|
988
|
+
else {
|
|
989
|
+
define(out, key, walk(entry, memo, key));
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
return out;
|
|
993
|
+
};
|
|
994
|
+
const walkRejection = (value, memo) => {
|
|
995
|
+
const out = {};
|
|
996
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
997
|
+
if (key === 'call') {
|
|
998
|
+
define(out, key, walkCall(entry, memo));
|
|
999
|
+
}
|
|
1000
|
+
else if (key === 'activity') {
|
|
1001
|
+
define(out, key, walkToolActivity(entry, memo));
|
|
1002
|
+
}
|
|
1003
|
+
else {
|
|
1004
|
+
define(out, key, walk(entry, memo, key));
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
return out;
|
|
1008
|
+
};
|
|
1009
|
+
const walkPreparing = (value, memo) => {
|
|
1010
|
+
if (!isRecord(value)) {
|
|
1011
|
+
return walk(value, memo);
|
|
1012
|
+
}
|
|
1013
|
+
const out = {};
|
|
1014
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
1015
|
+
if (key === 'directTool' && isRecord(entry)) {
|
|
1016
|
+
define(out, key, walkDirectTool(entry, memo));
|
|
1017
|
+
}
|
|
1018
|
+
else {
|
|
1019
|
+
define(out, key, walk(entry, memo, key));
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
return out;
|
|
1023
|
+
};
|
|
1024
|
+
function redactValue(value) {
|
|
1025
|
+
return walkBoundary(value, new WeakMap());
|
|
1026
|
+
}
|
|
1027
|
+
function redactShared(value) {
|
|
1028
|
+
return brandCapturedRecord(walkBoundary(value, shared));
|
|
1029
|
+
}
|
|
1030
|
+
function redactStep(step) {
|
|
1031
|
+
if (isRecord(step) &&
|
|
1032
|
+
Number.isSafeInteger(step.seq) &&
|
|
1033
|
+
Number.isSafeInteger(step.expectedLength) &&
|
|
1034
|
+
Array.isArray(step.records)) {
|
|
1035
|
+
return walkEngineStep(step, new WeakMap());
|
|
1036
|
+
}
|
|
1037
|
+
return walkBoundary(step, new WeakMap());
|
|
1038
|
+
}
|
|
1039
|
+
function redactRecord(record) {
|
|
1040
|
+
return brandCapturedRecord(walkRunRecord(record, new WeakMap()));
|
|
1041
|
+
}
|
|
1042
|
+
const redactor = Object.assign(redactValue, {
|
|
1043
|
+
registerTools,
|
|
1044
|
+
redactOperationResult,
|
|
1045
|
+
redactToolArguments,
|
|
1046
|
+
redactStep,
|
|
1047
|
+
redactShared,
|
|
1048
|
+
redactRecord
|
|
1049
|
+
});
|
|
1050
|
+
registerTools(initialTools);
|
|
1051
|
+
return redactor;
|
|
1052
|
+
}
|
|
1053
|
+
const defaultRedactor = buildRedactor();
|
|
1054
|
+
export function createRunLogRedactor(tools = []) {
|
|
1055
|
+
return buildRedactor(tools);
|
|
1056
|
+
}
|
|
1057
|
+
export function redact(value) {
|
|
1058
|
+
return defaultRedactor(value);
|
|
1059
|
+
}
|
|
1060
|
+
export function redactShared(value) {
|
|
1061
|
+
return defaultRedactor.redactShared(value);
|
|
1062
|
+
}
|
|
1063
|
+
export function redactStep(step, redactor = defaultRedactor) {
|
|
1064
|
+
return redactor.redactStep(step);
|
|
1065
|
+
}
|
|
1066
|
+
export function redactRecord(record, redactor = redact) {
|
|
1067
|
+
if (isCapturedJson(record)) {
|
|
1068
|
+
return record;
|
|
1069
|
+
}
|
|
1070
|
+
if (!isRecord(record)) {
|
|
1071
|
+
return redactor(record);
|
|
1072
|
+
}
|
|
1073
|
+
const { patch, events, ...rest } = record;
|
|
1074
|
+
const snapshot = rest.type === 'checkpoint' ? rest.snapshot : undefined;
|
|
1075
|
+
const safeRest = { ...rest };
|
|
1076
|
+
if (rest.type === 'checkpoint') {
|
|
1077
|
+
delete safeRest.snapshot;
|
|
1078
|
+
}
|
|
1079
|
+
const out = { ...redactor(safeRest) };
|
|
1080
|
+
if (rest.type === 'checkpoint' && snapshot !== undefined) {
|
|
1081
|
+
define(out, 'snapshot', isCapturedJson(snapshot) ? snapshot : redactor(snapshot));
|
|
1082
|
+
}
|
|
1083
|
+
if (patch) {
|
|
1084
|
+
define(out, 'patch', copyPatch(patch));
|
|
1085
|
+
}
|
|
1086
|
+
if (Array.isArray(events)) {
|
|
1087
|
+
define(out, 'events', events.map(copyPatch));
|
|
1088
|
+
}
|
|
1089
|
+
return out;
|
|
1090
|
+
}
|
|
1091
|
+
export function unredact(_snapshot, _request) { }
|
|
1092
|
+
export function redactingCore(core, redactor = defaultRedactor) {
|
|
1093
|
+
return new Proxy(core, {
|
|
1094
|
+
get(target, property, receiver) {
|
|
1095
|
+
if (property === 'append') {
|
|
1096
|
+
return (value) => target.append(redactRecord(value, redactor));
|
|
1097
|
+
}
|
|
1098
|
+
if (property === 'redactValue')
|
|
1099
|
+
return redactor.redactShared;
|
|
1100
|
+
const member = Reflect.get(target, property, receiver);
|
|
1101
|
+
if (typeof member !== 'function') {
|
|
1102
|
+
return member;
|
|
1103
|
+
}
|
|
1104
|
+
return member.bind(target);
|
|
1105
|
+
}
|
|
1106
|
+
});
|
|
1107
|
+
}
|