@oh-my-pi/pi-coding-agent 16.1.11 → 16.1.12
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 +14 -0
- package/dist/cli.js +2770 -2770
- package/dist/types/export/share.d.ts +10 -5
- package/dist/types/secrets/index.d.ts +1 -1
- package/dist/types/secrets/obfuscator.d.ts +43 -9
- package/dist/types/utils/image-loading.d.ts +3 -4
- package/package.json +12 -12
- package/src/export/share.ts +198 -8
- package/src/main.ts +8 -0
- package/src/sdk.ts +2 -1
- package/src/secrets/index.ts +1 -1
- package/src/secrets/obfuscator.ts +220 -71
- package/src/session/agent-session.ts +19 -29
- package/src/utils/image-loading.ts +3 -6
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AgentState } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import { DEFAULT_SHARE_URL } from "@oh-my-pi/pi-wire";
|
|
3
|
-
import type
|
|
3
|
+
import { type SecretObfuscator } from "../secrets/obfuscator";
|
|
4
4
|
import type { SessionManager } from "../session/session-manager";
|
|
5
5
|
import { type SessionData } from "./html";
|
|
6
6
|
export { DEFAULT_SHARE_URL };
|
|
@@ -12,10 +12,15 @@ export interface ShareSessionOptions {
|
|
|
12
12
|
/** Agent state for system prompt + tool descriptions in the snapshot. */
|
|
13
13
|
state?: AgentState;
|
|
14
14
|
/**
|
|
15
|
-
* Redacts the snapshot before sealing
|
|
16
|
-
* header, system prompt, tool descriptions
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* Redacts the snapshot before sealing via a typed, per-field walk over the
|
|
16
|
+
* session (header title/cwd, system prompt, tool descriptions, entry summaries,
|
|
17
|
+
* labels, and message text — including tool-result output and `@file` mentions),
|
|
18
|
+
* so secrets that landed in persisted entries (tool outputs reading .env, etc.)
|
|
19
|
+
* never leave the machine. Inline image bytes are preserved (size-trimmed
|
|
20
|
+
* separately); opaque provider-replay blobs (`providerPayload`,
|
|
21
|
+
* `redactedThinking`, `compaction.preserveData`) and untyped extension payloads
|
|
22
|
+
* (`details`/`data`/`outputSchema`) are dropped rather than walked. Pass
|
|
23
|
+
* undefined to skip redaction entirely.
|
|
19
24
|
*/
|
|
20
25
|
obfuscator?: SecretObfuscator;
|
|
21
26
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SecretEntry } from "./obfuscator";
|
|
2
|
-
export { deobfuscateSessionContext, obfuscateMessages, obfuscateProviderContext,
|
|
2
|
+
export { deobfuscateSessionContext, deobfuscateToolArguments, obfuscateMessages, obfuscateProviderContext, type SecretEntry, SecretObfuscator, } from "./obfuscator";
|
|
3
3
|
/**
|
|
4
4
|
* Load secrets from project-local and global secrets.yml files.
|
|
5
5
|
* Project-local entries override global entries with matching content.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import type { AssistantMessage, Context, Message } from "@oh-my-pi/pi-ai";
|
|
2
3
|
import type { SessionContext } from "../session/session-context";
|
|
3
4
|
export interface SecretEntry {
|
|
4
5
|
type: "plain" | "regex";
|
|
@@ -7,6 +8,12 @@ export interface SecretEntry {
|
|
|
7
8
|
replacement?: string;
|
|
8
9
|
flags?: string;
|
|
9
10
|
}
|
|
11
|
+
export type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
12
|
+
[key: string]: JsonValue | undefined;
|
|
13
|
+
};
|
|
14
|
+
export type JsonRecord = {
|
|
15
|
+
[key: string]: JsonValue | undefined;
|
|
16
|
+
};
|
|
10
17
|
export declare class SecretObfuscator {
|
|
11
18
|
#private;
|
|
12
19
|
constructor(entries: SecretEntry[]);
|
|
@@ -15,15 +22,42 @@ export declare class SecretObfuscator {
|
|
|
15
22
|
obfuscate(text: string): string;
|
|
16
23
|
/** Deobfuscate obfuscate-mode placeholders back to original secrets. Replace-mode is NOT reversed. */
|
|
17
24
|
deobfuscate(text: string): string;
|
|
18
|
-
/** Deep-walk an object, deobfuscating all string values. */
|
|
19
|
-
deobfuscateObject<T>(obj: T): T;
|
|
20
|
-
/** Deep-walk an object, obfuscating all string values. */
|
|
21
|
-
obfuscateObject<T>(obj: T): T;
|
|
22
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* Restore secret placeholders for local display. Only message kinds the model
|
|
28
|
+
* itself authored from obfuscated context carry placeholders — assistant
|
|
29
|
+
* content and the LLM-written branch/compaction summaries. User, developer, and
|
|
30
|
+
* tool-result messages are persisted with their literal text, so a literal
|
|
31
|
+
* `#ABCD#` the operator typed must survive untouched; those roles are never
|
|
32
|
+
* walked.
|
|
33
|
+
*/
|
|
23
34
|
export declare function deobfuscateSessionContext(sessionContext: SessionContext, obfuscator: SecretObfuscator | undefined): SessionContext;
|
|
24
|
-
|
|
35
|
+
export declare function deobfuscateAgentMessages(obfuscator: SecretObfuscator, messages: AgentMessage[]): AgentMessage[];
|
|
36
|
+
/**
|
|
37
|
+
* Restore placeholders in assistant content: visible text, thinking text, and
|
|
38
|
+
* tool-call arguments/intent/rawBlock. Signatures and redacted-thinking bytes
|
|
39
|
+
* are opaque provider-replay data and pass through byte-identical.
|
|
40
|
+
*/
|
|
41
|
+
export declare function deobfuscateAssistantContent(obfuscator: SecretObfuscator, content: AssistantMessage["content"]): AssistantMessage["content"];
|
|
42
|
+
/**
|
|
43
|
+
* Restore placeholders inside a tool call's arguments. Arguments are arbitrary
|
|
44
|
+
* model-authored JSON, so tool-call arguments are the ONLY place a recursive
|
|
45
|
+
* JSON walk runs.
|
|
46
|
+
*/
|
|
47
|
+
export declare function deobfuscateToolArguments(obfuscator: SecretObfuscator, args: Record<string, unknown>): Record<string, unknown>;
|
|
48
|
+
/** Redact secrets inside a tool call's arguments (same JSON-walk exception as {@link deobfuscateToolArguments}). */
|
|
49
|
+
export declare function obfuscateToolArguments(obfuscator: SecretObfuscator, args: Record<string, unknown>): Record<string, unknown>;
|
|
50
|
+
/**
|
|
51
|
+
* Redact secrets from outbound messages. Opt-in by origin: only user messages,
|
|
52
|
+
* tool results, and user-authored developer messages (e.g. `@file` mentions)
|
|
53
|
+
* can carry operator secrets. System prompts, tool schemas, and assistant
|
|
54
|
+
* output are author-controlled or model-generated and pass through untouched.
|
|
55
|
+
* Within a targeted message only `text` blocks are rewritten — inline image
|
|
56
|
+
* bytes are never walked.
|
|
57
|
+
*/
|
|
25
58
|
export declare function obfuscateMessages(obfuscator: SecretObfuscator, messages: Message[]): Message[];
|
|
26
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Redact outbound provider context. Only conversation messages are rewritten;
|
|
61
|
+
* the static system prompt and tool schemas pass through unchanged.
|
|
62
|
+
*/
|
|
27
63
|
export declare function obfuscateProviderContext(obfuscator: SecretObfuscator | undefined, context: Context): Context;
|
|
28
|
-
/** Convert tool schemas to wire JSON Schema before obfuscating provider-visible strings. */
|
|
29
|
-
export declare function obfuscateProviderTools(obfuscator: SecretObfuscator | undefined, tools: Tool[] | undefined): Tool[] | undefined;
|
|
@@ -4,10 +4,9 @@ export declare const MAX_IMAGE_INPUT_BYTES: number;
|
|
|
4
4
|
export declare const SUPPORTED_INPUT_IMAGE_MIME_TYPES: Set<string>;
|
|
5
5
|
/**
|
|
6
6
|
* Ollama and its local-backend family decode image input through llama.cpp /
|
|
7
|
-
* `stb_image`, which is compiled without WebP support
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* automatic equivalent of `OMP_NO_WEBP=1`.
|
|
7
|
+
* `stb_image`, which is compiled without WebP support, so a WebP upload fails
|
|
8
|
+
* with an opaque HTTP 400. Detect those models so the resize pipeline encodes
|
|
9
|
+
* to PNG/JPEG instead — the automatic equivalent of `OMP_NO_WEBP=1`.
|
|
11
10
|
*/
|
|
12
11
|
export declare function modelLacksWebpSupport(model: Pick<Model, "provider" | "api" | "imageInputDecoder"> | undefined): boolean;
|
|
13
12
|
/**
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
4
|
-
"version": "16.1.
|
|
4
|
+
"version": "16.1.12",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -48,17 +48,17 @@
|
|
|
48
48
|
"@agentclientprotocol/sdk": "0.25.0",
|
|
49
49
|
"@babel/parser": "^7.29.7",
|
|
50
50
|
"@mozilla/readability": "^0.6.0",
|
|
51
|
-
"@oh-my-pi/hashline": "16.1.
|
|
52
|
-
"@oh-my-pi/omp-stats": "16.1.
|
|
53
|
-
"@oh-my-pi/pi-agent-core": "16.1.
|
|
54
|
-
"@oh-my-pi/pi-ai": "16.1.
|
|
55
|
-
"@oh-my-pi/pi-catalog": "16.1.
|
|
56
|
-
"@oh-my-pi/pi-mnemopi": "16.1.
|
|
57
|
-
"@oh-my-pi/pi-natives": "16.1.
|
|
58
|
-
"@oh-my-pi/pi-tui": "16.1.
|
|
59
|
-
"@oh-my-pi/pi-utils": "16.1.
|
|
60
|
-
"@oh-my-pi/pi-wire": "16.1.
|
|
61
|
-
"@oh-my-pi/snapcompact": "16.1.
|
|
51
|
+
"@oh-my-pi/hashline": "16.1.12",
|
|
52
|
+
"@oh-my-pi/omp-stats": "16.1.12",
|
|
53
|
+
"@oh-my-pi/pi-agent-core": "16.1.12",
|
|
54
|
+
"@oh-my-pi/pi-ai": "16.1.12",
|
|
55
|
+
"@oh-my-pi/pi-catalog": "16.1.12",
|
|
56
|
+
"@oh-my-pi/pi-mnemopi": "16.1.12",
|
|
57
|
+
"@oh-my-pi/pi-natives": "16.1.12",
|
|
58
|
+
"@oh-my-pi/pi-tui": "16.1.12",
|
|
59
|
+
"@oh-my-pi/pi-utils": "16.1.12",
|
|
60
|
+
"@oh-my-pi/pi-wire": "16.1.12",
|
|
61
|
+
"@oh-my-pi/snapcompact": "16.1.12",
|
|
62
62
|
"@opentelemetry/api": "^1.9.1",
|
|
63
63
|
"@opentelemetry/context-async-hooks": "^2.7.1",
|
|
64
64
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
|
package/src/export/share.ts
CHANGED
|
@@ -19,13 +19,16 @@
|
|
|
19
19
|
import * as fs from "node:fs/promises";
|
|
20
20
|
import * as os from "node:os";
|
|
21
21
|
import * as path from "node:path";
|
|
22
|
-
import type { AgentState } from "@oh-my-pi/pi-agent-core";
|
|
22
|
+
import type { AgentMessage, AgentState } from "@oh-my-pi/pi-agent-core";
|
|
23
|
+
import type { AssistantMessage, ImageContent, TextContent } from "@oh-my-pi/pi-ai";
|
|
23
24
|
import { $which, logger } from "@oh-my-pi/pi-utils";
|
|
24
25
|
import { DEFAULT_SHARE_URL } from "@oh-my-pi/pi-wire";
|
|
25
26
|
import { $ } from "bun";
|
|
26
|
-
import type
|
|
27
|
+
import { obfuscateToolArguments, type SecretObfuscator } from "../secrets/obfuscator";
|
|
28
|
+
import type { SessionEntry, SessionHeader } from "../session/session-entries";
|
|
27
29
|
import type { SessionManager } from "../session/session-manager";
|
|
28
|
-
import {
|
|
30
|
+
import type { OutputMeta } from "../tools/output-meta";
|
|
31
|
+
import { buildSessionData, type SessionData, type SubSession } from "./html";
|
|
29
32
|
|
|
30
33
|
export { DEFAULT_SHARE_URL };
|
|
31
34
|
|
|
@@ -53,10 +56,15 @@ export interface ShareSessionOptions {
|
|
|
53
56
|
/** Agent state for system prompt + tool descriptions in the snapshot. */
|
|
54
57
|
state?: AgentState;
|
|
55
58
|
/**
|
|
56
|
-
* Redacts the snapshot before sealing
|
|
57
|
-
* header, system prompt, tool descriptions
|
|
58
|
-
*
|
|
59
|
-
*
|
|
59
|
+
* Redacts the snapshot before sealing via a typed, per-field walk over the
|
|
60
|
+
* session (header title/cwd, system prompt, tool descriptions, entry summaries,
|
|
61
|
+
* labels, and message text — including tool-result output and `@file` mentions),
|
|
62
|
+
* so secrets that landed in persisted entries (tool outputs reading .env, etc.)
|
|
63
|
+
* never leave the machine. Inline image bytes are preserved (size-trimmed
|
|
64
|
+
* separately); opaque provider-replay blobs (`providerPayload`,
|
|
65
|
+
* `redactedThinking`, `compaction.preserveData`) and untyped extension payloads
|
|
66
|
+
* (`details`/`data`/`outputSchema`) are dropped rather than walked. Pass
|
|
67
|
+
* undefined to skip redaction entirely.
|
|
60
68
|
*/
|
|
61
69
|
obfuscator?: SecretObfuscator;
|
|
62
70
|
}
|
|
@@ -75,7 +83,189 @@ export interface ShareSessionResult {
|
|
|
75
83
|
/** Build the snapshot that gets sealed and uploaded, redacted when an obfuscator is provided. */
|
|
76
84
|
export function buildShareSnapshot(sm: SessionManager, options?: ShareSessionOptions): SessionData {
|
|
77
85
|
const data = buildSessionData(sm, options?.state);
|
|
78
|
-
return options?.obfuscator?.hasSecrets() ? options.obfuscator
|
|
86
|
+
return options?.obfuscator?.hasSecrets() ? redactSessionDataForShare(options.obfuscator, data) : data;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Redact secrets from a share snapshot. A share blob leaves the machine, so
|
|
91
|
+
* every text-bearing field is rewritten through the obfuscator. The walk is
|
|
92
|
+
* typed end-to-end (no generic object traversal): inline image bytes are left
|
|
93
|
+
* intact (size-trimmed later by {@link stripImagePayloads}) and opaque,
|
|
94
|
+
* untyped payloads we cannot redact field-by-field (`compaction.preserveData`,
|
|
95
|
+
* extension `details`/`data`, `mode_change.data`, structured output schemas)
|
|
96
|
+
* are dropped so they cannot leak.
|
|
97
|
+
*/
|
|
98
|
+
function redactShareHeader(o: SecretObfuscator, header: SessionHeader | null): SessionHeader | null {
|
|
99
|
+
if (!header) return header;
|
|
100
|
+
return {
|
|
101
|
+
...header,
|
|
102
|
+
title: header.title === undefined ? undefined : o.obfuscate(header.title),
|
|
103
|
+
cwd: o.obfuscate(header.cwd),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function redactSessionDataForShare(o: SecretObfuscator, data: SessionData): SessionData {
|
|
108
|
+
return {
|
|
109
|
+
...data,
|
|
110
|
+
header: redactShareHeader(o, data.header),
|
|
111
|
+
systemPrompt: data.systemPrompt === undefined ? undefined : o.obfuscate(data.systemPrompt),
|
|
112
|
+
tools: data.tools?.map(tool => ({ ...tool, description: o.obfuscate(tool.description) })),
|
|
113
|
+
entries: data.entries.map(entry => redactShareEntry(o, entry)),
|
|
114
|
+
subSessions: data.subSessions
|
|
115
|
+
? Object.fromEntries(
|
|
116
|
+
Object.entries(data.subSessions).map(([key, sub]) => [key, redactShareSubSession(o, sub)]),
|
|
117
|
+
)
|
|
118
|
+
: data.subSessions,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function redactShareSubSession(o: SecretObfuscator, sub: SubSession): SubSession {
|
|
123
|
+
return {
|
|
124
|
+
...sub,
|
|
125
|
+
header: redactShareHeader(o, sub.header),
|
|
126
|
+
entries: sub.entries.map(entry => redactShareEntry(o, entry)),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function redactShareEntry(o: SecretObfuscator, entry: SessionEntry): SessionEntry {
|
|
131
|
+
switch (entry.type) {
|
|
132
|
+
case "message":
|
|
133
|
+
return { ...entry, message: redactShareMessage(o, entry.message) };
|
|
134
|
+
case "compaction":
|
|
135
|
+
return {
|
|
136
|
+
...entry,
|
|
137
|
+
summary: o.obfuscate(entry.summary),
|
|
138
|
+
shortSummary: entry.shortSummary === undefined ? undefined : o.obfuscate(entry.shortSummary),
|
|
139
|
+
details: undefined,
|
|
140
|
+
preserveData: undefined,
|
|
141
|
+
};
|
|
142
|
+
case "branch_summary":
|
|
143
|
+
return { ...entry, summary: o.obfuscate(entry.summary), details: undefined };
|
|
144
|
+
case "custom_message":
|
|
145
|
+
return { ...entry, content: redactShareContent(o, entry.content), details: undefined };
|
|
146
|
+
case "custom":
|
|
147
|
+
return { ...entry, data: undefined };
|
|
148
|
+
case "mode_change":
|
|
149
|
+
return { ...entry, data: undefined };
|
|
150
|
+
case "session_init":
|
|
151
|
+
return {
|
|
152
|
+
...entry,
|
|
153
|
+
systemPrompt: o.obfuscate(entry.systemPrompt),
|
|
154
|
+
task: o.obfuscate(entry.task),
|
|
155
|
+
outputSchema: undefined,
|
|
156
|
+
};
|
|
157
|
+
case "label":
|
|
158
|
+
return { ...entry, label: entry.label === undefined ? undefined : o.obfuscate(entry.label) };
|
|
159
|
+
default:
|
|
160
|
+
return entry;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function redactShareContent(
|
|
165
|
+
o: SecretObfuscator,
|
|
166
|
+
content: string | (TextContent | ImageContent)[],
|
|
167
|
+
): string | (TextContent | ImageContent)[] {
|
|
168
|
+
if (typeof content === "string") return o.obfuscate(content);
|
|
169
|
+
return content.map(block => (block.type === "text" ? { ...block, text: o.obfuscate(block.text) } : block));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Redact freeform strings in tool output metadata (source path/URL, diagnostics); numeric truncation info is preserved. */
|
|
173
|
+
function redactShareOutputMeta(o: SecretObfuscator, meta: OutputMeta | undefined): OutputMeta | undefined {
|
|
174
|
+
if (!meta) return meta;
|
|
175
|
+
return {
|
|
176
|
+
...meta,
|
|
177
|
+
source: meta.source ? { ...meta.source, value: o.obfuscate(meta.source.value) } : meta.source,
|
|
178
|
+
diagnostics: meta.diagnostics
|
|
179
|
+
? {
|
|
180
|
+
summary: o.obfuscate(meta.diagnostics.summary),
|
|
181
|
+
messages: meta.diagnostics.messages.map(message => o.obfuscate(message)),
|
|
182
|
+
}
|
|
183
|
+
: meta.diagnostics,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function redactShareMessage(o: SecretObfuscator, message: AgentMessage): AgentMessage {
|
|
188
|
+
switch (message.role) {
|
|
189
|
+
case "user":
|
|
190
|
+
case "developer":
|
|
191
|
+
return {
|
|
192
|
+
...message,
|
|
193
|
+
providerPayload: undefined,
|
|
194
|
+
content: redactShareContent(o, message.content),
|
|
195
|
+
} as AgentMessage;
|
|
196
|
+
case "custom":
|
|
197
|
+
case "hookMessage":
|
|
198
|
+
return { ...message, details: undefined, content: redactShareContent(o, message.content) } as AgentMessage;
|
|
199
|
+
case "toolResult":
|
|
200
|
+
return {
|
|
201
|
+
...message,
|
|
202
|
+
details: undefined,
|
|
203
|
+
content: redactShareContent(o, message.content) as (TextContent | ImageContent)[],
|
|
204
|
+
};
|
|
205
|
+
case "assistant":
|
|
206
|
+
// Drop opaque provider-replay state (encrypted reasoning / native history) the viewer
|
|
207
|
+
// never reads and we cannot redact field-by-field: `providerPayload` and any
|
|
208
|
+
// `redactedThinking` blocks.
|
|
209
|
+
return {
|
|
210
|
+
...message,
|
|
211
|
+
providerPayload: undefined,
|
|
212
|
+
errorMessage: message.errorMessage === undefined ? undefined : o.obfuscate(message.errorMessage),
|
|
213
|
+
content: message.content.flatMap((block): AssistantMessage["content"] => {
|
|
214
|
+
if (block.type === "redactedThinking") return [];
|
|
215
|
+
if (block.type === "text") return [{ ...block, text: o.obfuscate(block.text) }];
|
|
216
|
+
if (block.type === "thinking") return [{ ...block, thinking: o.obfuscate(block.thinking) }];
|
|
217
|
+
if (block.type === "toolCall") {
|
|
218
|
+
return [
|
|
219
|
+
{
|
|
220
|
+
...block,
|
|
221
|
+
arguments: obfuscateToolArguments(o, block.arguments),
|
|
222
|
+
intent: block.intent === undefined ? undefined : o.obfuscate(block.intent),
|
|
223
|
+
rawBlock: block.rawBlock === undefined ? undefined : o.obfuscate(block.rawBlock),
|
|
224
|
+
},
|
|
225
|
+
];
|
|
226
|
+
}
|
|
227
|
+
return [block];
|
|
228
|
+
}),
|
|
229
|
+
};
|
|
230
|
+
case "bashExecution":
|
|
231
|
+
return {
|
|
232
|
+
...message,
|
|
233
|
+
command: o.obfuscate(message.command),
|
|
234
|
+
output: o.obfuscate(message.output),
|
|
235
|
+
meta: redactShareOutputMeta(o, message.meta),
|
|
236
|
+
};
|
|
237
|
+
case "pythonExecution":
|
|
238
|
+
return {
|
|
239
|
+
...message,
|
|
240
|
+
code: o.obfuscate(message.code),
|
|
241
|
+
output: o.obfuscate(message.output),
|
|
242
|
+
meta: redactShareOutputMeta(o, message.meta),
|
|
243
|
+
};
|
|
244
|
+
case "branchSummary":
|
|
245
|
+
return { ...message, summary: o.obfuscate(message.summary) };
|
|
246
|
+
case "compactionSummary":
|
|
247
|
+
return {
|
|
248
|
+
...message,
|
|
249
|
+
providerPayload: undefined,
|
|
250
|
+
summary: o.obfuscate(message.summary),
|
|
251
|
+
shortSummary: message.shortSummary === undefined ? undefined : o.obfuscate(message.shortSummary),
|
|
252
|
+
blocks:
|
|
253
|
+
message.blocks === undefined
|
|
254
|
+
? undefined
|
|
255
|
+
: (redactShareContent(o, message.blocks) as (TextContent | ImageContent)[]),
|
|
256
|
+
};
|
|
257
|
+
case "fileMention":
|
|
258
|
+
return {
|
|
259
|
+
...message,
|
|
260
|
+
files: message.files.map(file => ({
|
|
261
|
+
...file,
|
|
262
|
+
path: o.obfuscate(file.path),
|
|
263
|
+
content: o.obfuscate(file.content),
|
|
264
|
+
})),
|
|
265
|
+
};
|
|
266
|
+
default:
|
|
267
|
+
return message;
|
|
268
|
+
}
|
|
79
269
|
}
|
|
80
270
|
|
|
81
271
|
/** Share the session; tries a secret gist first, then the share server. */
|
package/src/main.ts
CHANGED
|
@@ -149,8 +149,16 @@ const RPC_BACKGROUND_DEFAULTED_SETTING_PATHS: SettingPath[] = [
|
|
|
149
149
|
"bash.autoBackground.thresholdMs",
|
|
150
150
|
];
|
|
151
151
|
|
|
152
|
+
// Protocol-mode hosts opt into a small set of paths whose host-default we
|
|
153
|
+
// re-apply at startup so embedders inherit OMP's neutral defaults instead of
|
|
154
|
+
// the local user's globally-persisted preferences for interactive use. The
|
|
155
|
+
// guard preserves any explicit configuration — caller `Settings.isolated`
|
|
156
|
+
// overrides, project `.claude/settings.yml`, `--config` overlays, or global
|
|
157
|
+
// `config.yml` — so the host default only kicks in when nothing is set. Without
|
|
158
|
+
// it the override clobbers every caller/host choice (#2598, #3207).
|
|
152
159
|
function applyDefaultSettingOverrides(settingPaths: SettingPath[], targetSettings: Settings): void {
|
|
153
160
|
for (const settingPath of settingPaths) {
|
|
161
|
+
if (targetSettings.isConfigured(settingPath)) continue;
|
|
154
162
|
targetSettings.override(settingPath, getDefault(settingPath));
|
|
155
163
|
}
|
|
156
164
|
}
|
package/src/sdk.ts
CHANGED
|
@@ -97,6 +97,7 @@ import { AgentRegistry, MAIN_AGENT_ID } from "./registry/agent-registry";
|
|
|
97
97
|
import {
|
|
98
98
|
collectEnvSecrets,
|
|
99
99
|
deobfuscateSessionContext,
|
|
100
|
+
deobfuscateToolArguments,
|
|
100
101
|
loadSecrets,
|
|
101
102
|
obfuscateMessages,
|
|
102
103
|
obfuscateProviderContext,
|
|
@@ -2535,7 +2536,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2535
2536
|
result = { ...result, timeout: Math.min(result.timeout, maxTimeout) };
|
|
2536
2537
|
}
|
|
2537
2538
|
if (obfuscator?.hasSecrets()) {
|
|
2538
|
-
result = obfuscator
|
|
2539
|
+
result = deobfuscateToolArguments(obfuscator, result);
|
|
2539
2540
|
}
|
|
2540
2541
|
return result;
|
|
2541
2542
|
},
|
package/src/secrets/index.ts
CHANGED
|
@@ -6,9 +6,9 @@ import { compileSecretRegex } from "./regex";
|
|
|
6
6
|
|
|
7
7
|
export {
|
|
8
8
|
deobfuscateSessionContext,
|
|
9
|
+
deobfuscateToolArguments,
|
|
9
10
|
obfuscateMessages,
|
|
10
11
|
obfuscateProviderContext,
|
|
11
|
-
obfuscateProviderTools,
|
|
12
12
|
type SecretEntry,
|
|
13
13
|
SecretObfuscator,
|
|
14
14
|
} from "./obfuscator";
|