rehydra 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +41 -3
  2. package/dist/browser.d.ts +1 -1
  3. package/dist/browser.d.ts.map +1 -1
  4. package/dist/browser.js +1 -1
  5. package/dist/browser.js.map +1 -1
  6. package/dist/cli/commands/anonymize.d.ts.map +1 -1
  7. package/dist/cli/commands/anonymize.js.map +1 -1
  8. package/dist/cli/utils/color.d.ts.map +1 -1
  9. package/dist/cli/utils/color.js +1 -0
  10. package/dist/cli/utils/color.js.map +1 -1
  11. package/dist/core/anonymizer.d.ts.map +1 -1
  12. package/dist/core/anonymizer.js +4 -1
  13. package/dist/core/anonymizer.js.map +1 -1
  14. package/dist/index.d.ts +1 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +1 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/opencode-plugin/git-identity.d.ts +3 -0
  19. package/dist/opencode-plugin/git-identity.d.ts.map +1 -0
  20. package/dist/opencode-plugin/git-identity.js +37 -0
  21. package/dist/opencode-plugin/git-identity.js.map +1 -0
  22. package/dist/opencode-plugin/github-username.d.ts +3 -0
  23. package/dist/opencode-plugin/github-username.d.ts.map +1 -0
  24. package/dist/opencode-plugin/github-username.js +41 -0
  25. package/dist/opencode-plugin/github-username.js.map +1 -0
  26. package/dist/opencode-plugin/identity-recognizer.d.ts +5 -0
  27. package/dist/opencode-plugin/identity-recognizer.d.ts.map +1 -0
  28. package/dist/opencode-plugin/identity-recognizer.js +21 -0
  29. package/dist/opencode-plugin/identity-recognizer.js.map +1 -0
  30. package/dist/opencode-plugin/index.d.ts +10 -1
  31. package/dist/opencode-plugin/index.d.ts.map +1 -1
  32. package/dist/opencode-plugin/index.js +32 -1
  33. package/dist/opencode-plugin/index.js.map +1 -1
  34. package/dist/opencode-plugin/plugin-v2.d.ts +92 -0
  35. package/dist/opencode-plugin/plugin-v2.d.ts.map +1 -0
  36. package/dist/opencode-plugin/plugin-v2.js +385 -0
  37. package/dist/opencode-plugin/plugin-v2.js.map +1 -0
  38. package/dist/opencode-plugin/plugin.d.ts +12 -3
  39. package/dist/opencode-plugin/plugin.d.ts.map +1 -1
  40. package/dist/opencode-plugin/plugin.js +102 -9
  41. package/dist/opencode-plugin/plugin.js.map +1 -1
  42. package/dist/opencode-plugin/types.d.ts +4 -1
  43. package/dist/opencode-plugin/types.d.ts.map +1 -1
  44. package/dist/opencode-plugin/vcs-command.d.ts +3 -0
  45. package/dist/opencode-plugin/vcs-command.d.ts.map +1 -0
  46. package/dist/opencode-plugin/vcs-command.js +34 -0
  47. package/dist/opencode-plugin/vcs-command.js.map +1 -0
  48. package/dist/pipeline/tagger.d.ts +6 -6
  49. package/dist/pipeline/tagger.d.ts.map +1 -1
  50. package/dist/pipeline/tagger.js +32 -11
  51. package/dist/pipeline/tagger.js.map +1 -1
  52. package/dist/pipeline/validator.d.ts.map +1 -1
  53. package/dist/pipeline/validator.js +8 -1
  54. package/dist/pipeline/validator.js.map +1 -1
  55. package/dist/proxy/providers/anthropic.d.ts +1 -0
  56. package/dist/proxy/providers/anthropic.d.ts.map +1 -1
  57. package/dist/proxy/providers/anthropic.js +2 -4
  58. package/dist/proxy/providers/anthropic.js.map +1 -1
  59. package/dist/proxy/providers/openai.d.ts +1 -0
  60. package/dist/proxy/providers/openai.d.ts.map +1 -1
  61. package/dist/proxy/providers/openai.js +3 -4
  62. package/dist/proxy/providers/openai.js.map +1 -1
  63. package/dist/proxy/providers/streaming-tool-loop.d.ts +12 -0
  64. package/dist/proxy/providers/streaming-tool-loop.d.ts.map +1 -0
  65. package/dist/proxy/providers/streaming-tool-loop.js +223 -0
  66. package/dist/proxy/providers/streaming-tool-loop.js.map +1 -0
  67. package/dist/proxy/providers/types.d.ts +3 -0
  68. package/dist/proxy/providers/types.d.ts.map +1 -1
  69. package/dist/proxy/providers/types.js +0 -4
  70. package/dist/proxy/providers/types.js.map +1 -1
  71. package/dist/proxy/rehydra-fetch.d.ts.map +1 -1
  72. package/dist/proxy/rehydra-fetch.js +68 -6
  73. package/dist/proxy/rehydra-fetch.js.map +1 -1
  74. package/dist/proxy/tool-loop-stream.d.ts +7 -0
  75. package/dist/proxy/tool-loop-stream.d.ts.map +1 -0
  76. package/dist/proxy/tool-loop-stream.js +65 -0
  77. package/dist/proxy/tool-loop-stream.js.map +1 -0
  78. package/dist/proxy/types.d.ts +6 -2
  79. package/dist/proxy/types.d.ts.map +1 -1
  80. package/dist/recognizers/address.d.ts +2 -0
  81. package/dist/recognizers/address.d.ts.map +1 -0
  82. package/dist/recognizers/address.js +23 -0
  83. package/dist/recognizers/address.js.map +1 -0
  84. package/dist/recognizers/custom-id.d.ts.map +1 -1
  85. package/dist/recognizers/custom-id.js +4 -2
  86. package/dist/recognizers/custom-id.js.map +1 -1
  87. package/dist/recognizers/index.d.ts +2 -0
  88. package/dist/recognizers/index.d.ts.map +1 -1
  89. package/dist/recognizers/index.js +6 -0
  90. package/dist/recognizers/index.js.map +1 -1
  91. package/dist/recognizers/postal-code.d.ts +16 -0
  92. package/dist/recognizers/postal-code.d.ts.map +1 -0
  93. package/dist/recognizers/postal-code.js +42 -0
  94. package/dist/recognizers/postal-code.js.map +1 -0
  95. package/dist/types/index.d.ts +15 -3
  96. package/dist/types/index.d.ts.map +1 -1
  97. package/dist/types/index.js +2 -0
  98. package/dist/types/index.js.map +1 -1
  99. package/dist/types/pii-types.d.ts +2 -0
  100. package/dist/types/pii-types.d.ts.map +1 -1
  101. package/dist/types/pii-types.js +7 -0
  102. package/dist/types/pii-types.js.map +1 -1
  103. package/dist/utils/storage-node.d.ts +1 -0
  104. package/dist/utils/storage-node.d.ts.map +1 -1
  105. package/dist/utils/storage-node.js +22 -0
  106. package/dist/utils/storage-node.js.map +1 -1
  107. package/dist/utils/storage.d.ts +3 -0
  108. package/dist/utils/storage.d.ts.map +1 -1
  109. package/dist/utils/storage.js.map +1 -1
  110. package/package.json +4 -1
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Rehydra OpenCode Plugin — OpenCode 2 (V2 plugin API) implementation.
3
+ *
4
+ * OpenCode 2 replaces the V1 hooks-object entrypoint with a plugin definition
5
+ * that exposes a stable `id` and registers hooks through a plugin context.
6
+ * Mapping from the V1 hooks:
7
+ *
8
+ * V1 hook V2 registration
9
+ * -------------------------------------- -----------------------------------------------------
10
+ * experimental.chat.messages.transform ctx.session.hook("context" | "compaction" | "generate" | "title")
11
+ * experimental.chat.system.transform same hooks — event.system.push({ type: "text", text })
12
+ * tool.execute.before ctx.tool.hook("execute.before") — mutate event.input in place
13
+ * tool.execute.after ctx.tool.hook("execute.after") — event.result / event.status
14
+ * experimental.text.complete no V2 equivalent (documented gap — see README)
15
+ * client.app.log console.* (captured by OpenCode's log service)
16
+ *
17
+ * The V2 session-request event shape (@opencode/ai SessionRequest) differs from
18
+ * V1: { sessionID, system, messages: Message[] } where each Message has a role
19
+ * and content parts. Text/reasoning parts carry `text`; tool-call parts carry
20
+ * `input`; tool-result parts carry `result`. Tool calls and results share the
21
+ * same `id` across messages, which is used to pair VCS commands with outputs.
22
+ *
23
+ * Registering the scrubber on all four session-request kinds also protects the
24
+ * session-title request, closing the V1 title leak (OpenCode issue #46115)
25
+ * without disabling the title agent.
26
+ *
27
+ * Structural types only: the plugin declares its own minimal shapes for the
28
+ * OpenCode plugin context, so there is no runtime (or build) dependency on
29
+ * OpenCode packages.
30
+ */
31
+ import type { RehydraPluginOptions } from "./types.js";
32
+ /**
33
+ * The part of the OpenCode 2 plugin context this plugin uses. The real context
34
+ * (@opencode/plugin Context) satisfies this structurally.
35
+ */
36
+ export interface RehydraV2PluginContext {
37
+ readonly app: {
38
+ readonly name: string;
39
+ readonly version: string;
40
+ };
41
+ readonly location: {
42
+ readonly directory: string;
43
+ readonly project?: unknown;
44
+ };
45
+ readonly options: Record<string, unknown>;
46
+ readonly session: {
47
+ hook(name: string, callback: (event: unknown) => void | Promise<void>): Promise<unknown>;
48
+ };
49
+ readonly tool: {
50
+ hook(name: string, callback: (event: unknown) => void | Promise<void>): Promise<unknown>;
51
+ };
52
+ }
53
+ export type RehydraCleanup = () => void | Promise<void>;
54
+ /** Default-exported plugin definition consumed by OpenCode 2. */
55
+ export interface RehydraV2Plugin {
56
+ readonly id: string;
57
+ readonly setup: (context: RehydraV2PluginContext) => Promise<RehydraCleanup | void>;
58
+ }
59
+ export declare function isVcsEnabled(options: RehydraPluginOptions | undefined): boolean;
60
+ /**
61
+ * Creates a Rehydra plugin definition for OpenCode 2.
62
+ *
63
+ * @example
64
+ * ```json
65
+ * // opencode.json — published npm package with default options
66
+ * { "plugins": ["@rehydra/opencode"] }
67
+ * ```
68
+ *
69
+ * @example
70
+ * ```json
71
+ * // opencode.json — npm package with custom options
72
+ * {
73
+ * "plugins": [{
74
+ * "package": "@rehydra/opencode",
75
+ * "options": { "envFiles": [".env", ".env.local"] }
76
+ * }]
77
+ * }
78
+ * ```
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * // .opencode/plugins/rehydra.ts — local plugin with custom options
83
+ * import { createRehydraPluginV2 } from "@rehydra/opencode";
84
+ * export default createRehydraPluginV2({
85
+ * envFiles: [".env", ".env.local"],
86
+ * });
87
+ * ```
88
+ */
89
+ export declare function createRehydraPluginV2(options?: RehydraPluginOptions): RehydraV2Plugin;
90
+ declare const _default: RehydraV2Plugin;
91
+ export default _default;
92
+ //# sourceMappingURL=plugin-v2.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-v2.d.ts","sourceRoot":"","sources":["../../src/opencode-plugin/plugin-v2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAeH,OAAO,KAAK,EAAe,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAwDpE;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE;QAChB,IAAI,CACF,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACjD,OAAO,CAAC,OAAO,CAAC,CAAC;KACrB,CAAC;IACF,QAAQ,CAAC,IAAI,EAAE;QACb,IAAI,CACF,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACjD,OAAO,CAAC,OAAO,CAAC,CAAC;KACrB,CAAC;CACH;AAED,MAAM,MAAM,cAAc,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAExD,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,CACd,OAAO,EAAE,sBAAsB,KAC5B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC;CACrC;AAED,wBAAgB,YAAY,CAC1B,OAAO,EAAE,oBAAoB,GAAG,SAAS,GACxC,OAAO,CAET;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,CAAC,EAAE,oBAAoB,GAC7B,eAAe,CAyWjB;;AAED,wBAAuC"}
@@ -0,0 +1,385 @@
1
+ /**
2
+ * Rehydra OpenCode Plugin — OpenCode 2 (V2 plugin API) implementation.
3
+ *
4
+ * OpenCode 2 replaces the V1 hooks-object entrypoint with a plugin definition
5
+ * that exposes a stable `id` and registers hooks through a plugin context.
6
+ * Mapping from the V1 hooks:
7
+ *
8
+ * V1 hook V2 registration
9
+ * -------------------------------------- -----------------------------------------------------
10
+ * experimental.chat.messages.transform ctx.session.hook("context" | "compaction" | "generate" | "title")
11
+ * experimental.chat.system.transform same hooks — event.system.push({ type: "text", text })
12
+ * tool.execute.before ctx.tool.hook("execute.before") — mutate event.input in place
13
+ * tool.execute.after ctx.tool.hook("execute.after") — event.result / event.status
14
+ * experimental.text.complete no V2 equivalent (documented gap — see README)
15
+ * client.app.log console.* (captured by OpenCode's log service)
16
+ *
17
+ * The V2 session-request event shape (@opencode/ai SessionRequest) differs from
18
+ * V1: { sessionID, system, messages: Message[] } where each Message has a role
19
+ * and content parts. Text/reasoning parts carry `text`; tool-call parts carry
20
+ * `input`; tool-result parts carry `result`. Tool calls and results share the
21
+ * same `id` across messages, which is used to pair VCS commands with outputs.
22
+ *
23
+ * Registering the scrubber on all four session-request kinds also protects the
24
+ * session-title request, closing the V1 title leak (OpenCode issue #46115)
25
+ * without disabling the title agent.
26
+ *
27
+ * Structural types only: the plugin declares its own minimal shapes for the
28
+ * OpenCode plugin context, so there is no runtime (or build) dependency on
29
+ * OpenCode packages.
30
+ */
31
+ /* eslint-disable no-console */
32
+ import { createAnonymizer } from "../core/anonymizer.js";
33
+ import { AnonymizerSessionImpl } from "../storage/session-base.js";
34
+ import { InMemoryPIIStorageProvider } from "../storage/in-memory.js";
35
+ import { InMemoryKeyProvider } from "../crypto/index.js";
36
+ import { PIIType, createDefaultPolicy, SECRET_PII_TYPES, DEFAULT_TAG_FORMAT, } from "../types/index.js";
37
+ import { buildPIISystemInstruction } from "../proxy/system-instruction.js";
38
+ import { buildTagPrefix } from "../utils/regex.js";
39
+ import { githubUsernameRecognizer } from "./github-username.js";
40
+ import { protectIdentityTags } from "./identity-recognizer.js";
41
+ import { vcsCommandTypes } from "./vcs-command.js";
42
+ import { gitIdentityRecognizer } from "./git-identity.js";
43
+ import { deepRehydrate } from "./plugin.js";
44
+ /** Session request kinds that can be hooked in OpenCode 2. */
45
+ const REQUEST_KINDS = [
46
+ "context",
47
+ "compaction",
48
+ "generate",
49
+ "title",
50
+ ];
51
+ export function isVcsEnabled(options) {
52
+ return options?.vcsIdentities === true;
53
+ }
54
+ /**
55
+ * Creates a Rehydra plugin definition for OpenCode 2.
56
+ *
57
+ * @example
58
+ * ```json
59
+ * // opencode.json — published npm package with default options
60
+ * { "plugins": ["@rehydra/opencode"] }
61
+ * ```
62
+ *
63
+ * @example
64
+ * ```json
65
+ * // opencode.json — npm package with custom options
66
+ * {
67
+ * "plugins": [{
68
+ * "package": "@rehydra/opencode",
69
+ * "options": { "envFiles": [".env", ".env.local"] }
70
+ * }]
71
+ * }
72
+ * ```
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * // .opencode/plugins/rehydra.ts — local plugin with custom options
77
+ * import { createRehydraPluginV2 } from "@rehydra/opencode";
78
+ * export default createRehydraPluginV2({
79
+ * envFiles: [".env", ".env.local"],
80
+ * });
81
+ * ```
82
+ */
83
+ export function createRehydraPluginV2(options) {
84
+ return {
85
+ id: "rehydra",
86
+ async setup(ctx) {
87
+ const SERVICE = "rehydra";
88
+ // OpenCode 2 removes client.app.log from the plugin context. Plain console
89
+ // output is captured by OpenCode's log service, so the structured
90
+ // "service=rehydra …" entries survive in the log directory.
91
+ function log(level, message, extra) {
92
+ const payload = {
93
+ service: SERVICE,
94
+ level,
95
+ message,
96
+ };
97
+ if (extra !== undefined) {
98
+ for (const [key, value] of Object.entries(extra)) {
99
+ payload[key] = value;
100
+ }
101
+ }
102
+ if (level === "error") {
103
+ console.error(payload);
104
+ }
105
+ else if (level === "warn") {
106
+ console.warn(payload);
107
+ }
108
+ else {
109
+ console.log(payload);
110
+ }
111
+ }
112
+ const keyProvider = new InMemoryKeyProvider();
113
+ const piiStorage = new InMemoryPIIStorageProvider();
114
+ // Factory options take precedence over options from opencode.json
115
+ // (ctx.options). Both feed the same RehydraPluginOptions shape.
116
+ const runtimeOptions = ctx.options;
117
+ const opts = {
118
+ ...(runtimeOptions ?? {}),
119
+ ...(options ?? {}),
120
+ };
121
+ // Build anonymizer config from options, sharing key and storage providers
122
+ const baseConfig = opts.anonymizer ?? {
123
+ secrets: {
124
+ enabled: true,
125
+ envFiles: opts.envFiles ?? ["**/.env*"],
126
+ redactValues: opts.redactValues,
127
+ minValueLength: opts.minValueLength,
128
+ },
129
+ };
130
+ const anonymizerConfig = {
131
+ ...baseConfig,
132
+ secrets: baseConfig.secrets === undefined
133
+ ? undefined
134
+ : {
135
+ ...baseConfig.secrets,
136
+ envBaseDirectory: baseConfig.secrets.envBaseDirectory ?? ctx.location.directory,
137
+ },
138
+ };
139
+ const tagFormat = anonymizerConfig.tagFormat ?? opts.tagFormat ?? DEFAULT_TAG_FORMAT;
140
+ const tagPrefix = buildTagPrefix(tagFormat);
141
+ const rehydraInstruction = `<rehydra>\n${buildPIISystemInstruction(tagFormat)}\n</rehydra>`;
142
+ const anonymizer = createAnonymizer({
143
+ ...anonymizerConfig,
144
+ tagFormat,
145
+ keyProvider,
146
+ piiStorageProvider: piiStorage,
147
+ });
148
+ if (opts.vcsIdentities === true) {
149
+ anonymizer
150
+ .getRegistry()
151
+ .register(protectIdentityTags(githubUsernameRecognizer, tagFormat));
152
+ anonymizer
153
+ .getRegistry()
154
+ .register(protectIdentityTags(gitIdentityRecognizer, tagFormat));
155
+ }
156
+ await anonymizer.initialize();
157
+ // Build policy with disabled types (URL and IP_ADDRESS disabled by default)
158
+ const disableTypes = opts.disableTypes ?? [
159
+ "URL",
160
+ "IP_ADDRESS",
161
+ ];
162
+ let policy = opts.policy;
163
+ if (disableTypes.length > 0) {
164
+ const base = createDefaultPolicy();
165
+ const disableSet = new Set(disableTypes);
166
+ const regexEnabledTypes = new Set(base.regexEnabledTypes);
167
+ const nerEnabledTypes = new Set(base.nerEnabledTypes);
168
+ // createDefaultPolicy() excludes secret types (they're opt-in via
169
+ // AnonymizerConfig.secrets). Add them back so that passing this
170
+ // partial policy to mergePolicyWithBase doesn't accidentally drop
171
+ // the secret types the anonymizer added to its internal default.
172
+ for (const secretType of SECRET_PII_TYPES) {
173
+ regexEnabledTypes.add(secretType);
174
+ }
175
+ for (const t of disableSet) {
176
+ const piiType = t;
177
+ regexEnabledTypes.delete(piiType);
178
+ nerEnabledTypes.delete(piiType);
179
+ }
180
+ policy = {
181
+ ...policy,
182
+ regexEnabledTypes,
183
+ nerEnabledTypes,
184
+ };
185
+ }
186
+ log("info", "plugin initialized", {
187
+ envFiles: anonymizerConfig.secrets?.envFiles,
188
+ redactValueCount: opts.redactValues?.length ?? 0,
189
+ disableTypes,
190
+ opencode: `${ctx.app.name} ${ctx.app.version}`,
191
+ });
192
+ const locale = opts.locale;
193
+ const identityPolicy = (types) => {
194
+ const defaults = createDefaultPolicy();
195
+ const configPolicy = anonymizerConfig.defaultPolicy;
196
+ const enabledTypes = new Set(policy?.enabledTypes ??
197
+ configPolicy?.enabledTypes ??
198
+ defaults.enabledTypes);
199
+ const regexEnabledTypes = new Set(policy?.regexEnabledTypes ??
200
+ configPolicy?.regexEnabledTypes ??
201
+ defaults.regexEnabledTypes);
202
+ if (anonymizerConfig.secrets?.enabled === true) {
203
+ for (const type of SECRET_PII_TYPES) {
204
+ if (!disableTypes.includes(type)) {
205
+ enabledTypes.add(type);
206
+ regexEnabledTypes.add(type);
207
+ }
208
+ }
209
+ }
210
+ for (const type of types) {
211
+ if (!disableTypes.includes(type)) {
212
+ enabledTypes.add(type);
213
+ regexEnabledTypes.add(type);
214
+ }
215
+ }
216
+ return {
217
+ ...policy,
218
+ enabledTypes,
219
+ regexEnabledTypes,
220
+ reuseIdsForRepeatedPII: true,
221
+ };
222
+ };
223
+ // One session per OpenCode session, keyed by sessionID
224
+ const sessions = new Map();
225
+ function getSession(sessionID) {
226
+ let session = sessions.get(sessionID);
227
+ if (session === undefined) {
228
+ session = new AnonymizerSessionImpl(anonymizer, sessionID, piiStorage, keyProvider);
229
+ sessions.set(sessionID, session);
230
+ }
231
+ return session;
232
+ }
233
+ // Track whether any anonymization occurred (to conditionally inject instruction)
234
+ let hasAnonymized = false;
235
+ /**
236
+ * Scrubs one outgoing model request. OpenCode 2 delivers the same request
237
+ * shape to the `context` (agent loop), `compaction`, `generate`, and
238
+ * `title` session hooks, so one implementation covers every kind.
239
+ */
240
+ async function scrubRequest(event) {
241
+ let totalScrubbed = 0;
242
+ const scrubbedByType = {};
243
+ const session = getSession(event.sessionID);
244
+ // VCS commands by tool-call id, captured before scrubbing so detection
245
+ // tokens survive anonymization. Tool results pair with their call by id.
246
+ const commandsByCallId = new Map();
247
+ // OpenCode retains the rehydrated arguments after tool execution and
248
+ // serializes them into later model requests. Copy and scrub values so
249
+ // the execution arguments and JSON property names stay intact.
250
+ const scrubValue = async (value, activePolicy) => {
251
+ if (typeof value === "string") {
252
+ const result = await session.anonymize(value, locale, activePolicy ?? policy);
253
+ if (result.stats.totalEntities > 0) {
254
+ hasAnonymized = true;
255
+ totalScrubbed += result.stats.totalEntities;
256
+ for (const [type, count] of Object.entries(result.stats.countsByType)) {
257
+ scrubbedByType[type] = (scrubbedByType[type] ?? 0) + count;
258
+ }
259
+ }
260
+ return result.anonymizedText;
261
+ }
262
+ if (Array.isArray(value)) {
263
+ const result = [];
264
+ for (const item of value)
265
+ result.push(await scrubValue(item, activePolicy));
266
+ return result;
267
+ }
268
+ if (value !== null && typeof value === "object") {
269
+ const entries = [];
270
+ for (const [key, item] of Object.entries(value)) {
271
+ entries.push([key, await scrubValue(item, activePolicy)]);
272
+ }
273
+ return Object.fromEntries(entries);
274
+ }
275
+ return value;
276
+ };
277
+ for (const msg of event.messages) {
278
+ const content = msg.content;
279
+ if (!Array.isArray(content))
280
+ continue;
281
+ for (const part of content) {
282
+ if (part.type === "tool-call") {
283
+ const rawInput = part.input;
284
+ if (isVcsEnabled(opts) &&
285
+ rawInput !== null &&
286
+ typeof rawInput === "object" &&
287
+ typeof rawInput.command ===
288
+ "string" &&
289
+ typeof part.id === "string") {
290
+ commandsByCallId.set(part.id, rawInput.command);
291
+ }
292
+ part.input = await scrubValue(part.input);
293
+ }
294
+ else if (part.type === "text" || part.type === "reasoning") {
295
+ if (typeof part.text === "string") {
296
+ part.text = (await scrubValue(part.text));
297
+ }
298
+ }
299
+ else if (part.type === "tool-result" &&
300
+ part.result !== undefined &&
301
+ part.result !== null) {
302
+ let outputPolicy;
303
+ if (isVcsEnabled(opts) &&
304
+ typeof part.id === "string" &&
305
+ commandsByCallId.has(part.id)) {
306
+ const command = commandsByCallId.get(part.id) ?? "";
307
+ const commands = vcsCommandTypes(command);
308
+ const types = [];
309
+ if (commands.has("github"))
310
+ types.push(PIIType.GITHUB_USERNAME);
311
+ if (commands.has("git"))
312
+ types.push(PIIType.PERSON);
313
+ if (types.length > 0)
314
+ outputPolicy = identityPolicy(types);
315
+ }
316
+ part.result = await scrubValue(part.result, outputPolicy);
317
+ }
318
+ }
319
+ }
320
+ if (totalScrubbed > 0) {
321
+ // Only include types that actually had hits
322
+ const nonZero = {};
323
+ for (const [type, count] of Object.entries(scrubbedByType)) {
324
+ if (count > 0)
325
+ nonZero[type] = count;
326
+ }
327
+ log("info", `scrubbed ${totalScrubbed} secret(s) from messages`, {
328
+ scrubbed: nonZero,
329
+ messageCount: event.messages.length,
330
+ });
331
+ }
332
+ else {
333
+ log("debug", "no secrets found in messages", {
334
+ messageCount: event.messages.length,
335
+ });
336
+ }
337
+ if (hasAnonymized) {
338
+ log("debug", "injected rehydra instruction into system prompt");
339
+ event.system.push({ type: "text", text: rehydraInstruction });
340
+ }
341
+ }
342
+ // Register the scrubber on every model-request kind OpenCode 2 can issue:
343
+ // agent loop, checkpoint compaction, transient generates, session titles.
344
+ for (const kind of REQUEST_KINDS) {
345
+ await ctx.session.hook(kind, (event) => scrubRequest(event));
346
+ }
347
+ await ctx.tool.hook("execute.before", async (event) => {
348
+ const toolEvent = event;
349
+ const session = getSession(toolEvent.sessionID);
350
+ const before = JSON.stringify(toolEvent.input);
351
+ toolEvent.input = await deepRehydrate(toolEvent.input, session, tagPrefix);
352
+ if (before !== JSON.stringify(toolEvent.input)) {
353
+ log("info", "rehydrated PII tags in tool args", {
354
+ tool: toolEvent.tool,
355
+ callID: toolEvent.id,
356
+ });
357
+ }
358
+ });
359
+ // Result shape varies by tool type: native tools return their result
360
+ // object while MCP tools return the raw CallToolResult
361
+ // ({ content: [{type,text}], … }). deepRehydrate handles any shape.
362
+ await ctx.tool.hook("execute.after", async (event) => {
363
+ if (event.status === "error")
364
+ return;
365
+ const toolEvent = event;
366
+ const session = getSession(toolEvent.sessionID);
367
+ const before = JSON.stringify(toolEvent.result);
368
+ toolEvent.result = await deepRehydrate(toolEvent.result, session, tagPrefix);
369
+ if (JSON.stringify(toolEvent.result) !== before) {
370
+ log("info", "rehydrated PII tags in tool result", {
371
+ tool: toolEvent.tool,
372
+ callID: toolEvent.id,
373
+ });
374
+ }
375
+ });
376
+ // Drop the PII maps when the plugin unloads.
377
+ return () => {
378
+ sessions.clear();
379
+ piiStorage.clear();
380
+ };
381
+ },
382
+ };
383
+ }
384
+ export default createRehydraPluginV2();
385
+ //# sourceMappingURL=plugin-v2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-v2.js","sourceRoot":"","sources":["../../src/opencode-plugin/plugin-v2.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@
10
10
  * - tool.execute.before — rehydrate PII tags in tool args
11
11
  * - experimental.text.complete — rehydrate PII tags in LLM response
12
12
  */
13
+ import { AnonymizerSessionImpl } from "../storage/session-base.js";
13
14
  import type { RehydraPluginOptions } from "./types.js";
14
15
  /**
15
16
  * OpenCode Plugin types — matches signatures from @opencode-ai/plugin.
@@ -34,10 +35,18 @@ interface OpencodeClient {
34
35
  };
35
36
  [key: string]: unknown;
36
37
  }
37
- type Plugin = (input: PluginInput) => Promise<Hooks>;
38
+ type Plugin = (input: PluginInput, options?: Record<string, unknown>) => Promise<Hooks>;
38
39
  interface Hooks {
39
40
  [key: string]: unknown;
40
41
  }
42
+ /**
43
+ * Recursively rehydrate all string values containing PII tags.
44
+ * Returns a new value (for strings/arrays) or the same object mutated in-place
45
+ * (for plain objects). The in-place mutation is required because OpenCode's
46
+ * tool.execute.before hook uses the original args reference for execution —
47
+ * replacing the object wholesale has no effect.
48
+ */
49
+ export declare function deepRehydrate(value: unknown, session: AnonymizerSessionImpl, tagPrefix: string): Promise<unknown>;
41
50
  /**
42
51
  * Creates a Rehydra plugin for OpenCode.
43
52
  *
@@ -53,10 +62,10 @@ interface Hooks {
53
62
  * @example
54
63
  * ```json
55
64
  * // opencode.json — when published as npm package
56
- * { "plugin": ["@rehydra/opencode-plugin"] }
65
+ * { "plugin": [["@rehydra/opencode", { "disableTypes": ["DATE"] }]] }
57
66
  * ```
58
67
  */
59
- export declare function createRehydraPlugin(options?: RehydraPluginOptions): Plugin;
68
+ export declare function createRehydraPlugin(factoryOptions?: RehydraPluginOptions): Plugin;
60
69
  declare const _default: Plugin;
61
70
  export default _default;
62
71
  //# sourceMappingURL=plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/opencode-plugin/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAe,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAIpE;;;GAGG;AACH,UAAU,WAAW;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,cAAc;IACtB,GAAG,EAAE;QACH,GAAG,CAAC,KAAK,EAAE;YACT,IAAI,EAAE;gBACJ,OAAO,EAAE,MAAM,CAAC;gBAChB,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;gBAC3C,OAAO,EAAE,MAAM,CAAC;gBAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;aACjC,CAAC;SACH,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACtB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,KAAK,MAAM,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;AAErD,UAAU,KAAK;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAoCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAG,MAAM,CA+O1E;;AAED,wBAAqC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../src/opencode-plugin/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAKnE,OAAO,KAAK,EAAe,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAQpE;;;GAGG;AACH,UAAU,WAAW;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,UAAU,cAAc;IACtB,GAAG,EAAE;QACH,GAAG,CAAC,KAAK,EAAE;YACT,IAAI,EAAE;gBACJ,OAAO,EAAE,MAAM,CAAC;gBAChB,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;gBAC3C,OAAO,EAAE,MAAM,CAAC;gBAChB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;aACjC,CAAC;SACH,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KACtB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,KAAK,MAAM,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC;AAExF,UAAU,KAAK;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,qBAAqB,EAC9B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAqBlB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAoUjF;;AAED,wBAAqC"}