agentinit 1.23.0 → 1.24.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 (32) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +23 -2
  3. package/dist/agents/CodexCliAgent.js +1 -1
  4. package/dist/agents/CodexCliAgent.js.map +1 -1
  5. package/dist/cli.js +860 -42
  6. package/dist/commands/agent.d.ts.map +1 -1
  7. package/dist/commands/agent.js +88 -0
  8. package/dist/commands/agent.js.map +1 -1
  9. package/dist/core/agentSettings/adapters/claude.d.ts.map +1 -1
  10. package/dist/core/agentSettings/adapters/claude.js +140 -2
  11. package/dist/core/agentSettings/adapters/claude.js.map +1 -1
  12. package/dist/core/agentSettings/adapters/codex.d.ts +3 -0
  13. package/dist/core/agentSettings/adapters/codex.d.ts.map +1 -0
  14. package/dist/core/agentSettings/adapters/codex.js +121 -0
  15. package/dist/core/agentSettings/adapters/codex.js.map +1 -0
  16. package/dist/core/agentSettings/adapters/opencode.d.ts +3 -0
  17. package/dist/core/agentSettings/adapters/opencode.d.ts.map +1 -0
  18. package/dist/core/agentSettings/adapters/opencode.js +134 -0
  19. package/dist/core/agentSettings/adapters/opencode.js.map +1 -0
  20. package/dist/core/agentSettings/registry.d.ts.map +1 -1
  21. package/dist/core/agentSettings/registry.js +4 -0
  22. package/dist/core/agentSettings/registry.js.map +1 -1
  23. package/dist/core/agentSettings/settingsManager.d.ts +3 -1
  24. package/dist/core/agentSettings/settingsManager.d.ts.map +1 -1
  25. package/dist/core/agentSettings/settingsManager.js +221 -27
  26. package/dist/core/agentSettings/settingsManager.js.map +1 -1
  27. package/dist/core/agentSettings/types.d.ts +23 -3
  28. package/dist/core/agentSettings/types.d.ts.map +1 -1
  29. package/dist/core/agentSettings/valueParser.d.ts.map +1 -1
  30. package/dist/core/agentSettings/valueParser.js +20 -0
  31. package/dist/core/agentSettings/valueParser.js.map +1 -1
  32. package/package.json +2 -1
@@ -0,0 +1,134 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { expandTilde } from '../../../utils/paths.js';
4
+ const SUPPORTED_SCOPES = ['global', 'project'];
5
+ const PERMISSION_ACTIONS = ['allow', 'ask', 'deny'];
6
+ function firstExistingPath(paths, fallback) {
7
+ return paths.find(candidate => existsSync(candidate)) ?? fallback;
8
+ }
9
+ function setting(key, valueType, title, description, options = {}) {
10
+ const definition = {
11
+ agent: 'opencode',
12
+ key,
13
+ nativePath: options.nativePath ?? key.split('.'),
14
+ title,
15
+ description,
16
+ valueType,
17
+ scopes: options.scopes ?? SUPPORTED_SCOPES,
18
+ defaultScope: options.defaultScope ?? 'global',
19
+ category: options.category ?? 'settings',
20
+ risk: options.risk ?? 'safe',
21
+ };
22
+ if (options.allowedValues) {
23
+ definition.allowedValues = options.allowedValues;
24
+ }
25
+ if (options.deprecated !== undefined) {
26
+ definition.deprecated = options.deprecated;
27
+ }
28
+ if (options.replacement) {
29
+ definition.replacement = options.replacement;
30
+ }
31
+ return definition;
32
+ }
33
+ export const opencodeSettingsAdapter = {
34
+ agent: 'opencode',
35
+ displayName: 'OpenCode',
36
+ format: 'jsonc',
37
+ definitions: [
38
+ setting('model', 'string', 'Model', 'Default model identifier in provider/model format (e.g. anthropic/claude-sonnet-4-5).', {
39
+ category: 'model',
40
+ }),
41
+ setting('small_model', 'string', 'Small model', 'Small model used for tasks such as title generation, in provider/model format.', {
42
+ category: 'model',
43
+ }),
44
+ setting('provider', 'object', 'Providers', 'Custom OpenCode provider configurations and model overrides.', {
45
+ category: 'provider',
46
+ risk: 'security-sensitive',
47
+ }),
48
+ setting('default_agent', 'string', 'Default agent', 'Default primary agent to use when none is specified.', {
49
+ category: 'agent',
50
+ }),
51
+ setting('autoupdate', 'booleanOrEnum', 'Auto update', 'Control automatic updates: true, false, or notify.', {
52
+ allowedValues: ['notify'],
53
+ scopes: ['global'],
54
+ defaultScope: 'global',
55
+ category: 'runtime',
56
+ }),
57
+ setting('shell', 'string', 'Shell', 'Default shell to use for terminal and bash tool execution.', {
58
+ category: 'runtime',
59
+ }),
60
+ setting('share', 'enum', 'Share', 'Control sharing behavior: manual, auto, or disabled.', {
61
+ allowedValues: ['manual', 'auto', 'disabled'],
62
+ category: 'sharing',
63
+ }),
64
+ setting('username', 'string', 'Username', 'Custom username displayed in conversations instead of system username.', {
65
+ category: 'ui',
66
+ }),
67
+ setting('logLevel', 'enum', 'Log level', 'Log verbosity level.', {
68
+ allowedValues: ['DEBUG', 'INFO', 'WARN', 'ERROR'],
69
+ category: 'runtime',
70
+ }),
71
+ setting('snapshot', 'boolean', 'Snapshot tracking', 'Enable or disable filesystem snapshot tracking for undo/redo.', {
72
+ category: 'runtime',
73
+ }),
74
+ setting('permission.*', 'enum', 'Default permission', 'Fallback permission rule for all tools: allow, ask, or deny.', {
75
+ nativePath: ['permission', '*'],
76
+ category: 'permissions',
77
+ risk: 'security-sensitive',
78
+ allowedValues: PERMISSION_ACTIONS,
79
+ }),
80
+ setting('permission.bash', 'enum', 'Bash permission', 'Permission rule for shell command execution.', {
81
+ category: 'permissions',
82
+ risk: 'security-sensitive',
83
+ allowedValues: PERMISSION_ACTIONS,
84
+ }),
85
+ setting('permission.read', 'enum', 'Read permission', 'Permission rule for file reads.', {
86
+ category: 'permissions',
87
+ allowedValues: PERMISSION_ACTIONS,
88
+ }),
89
+ setting('permission.edit', 'enum', 'Edit permission', 'Permission rule for editing and writing files.', {
90
+ category: 'permissions',
91
+ risk: 'risky',
92
+ allowedValues: PERMISSION_ACTIONS,
93
+ }),
94
+ setting('permission.webfetch', 'enum', 'Web fetch permission', 'Permission rule for fetching external URLs.', {
95
+ category: 'permissions',
96
+ allowedValues: PERMISSION_ACTIONS,
97
+ }),
98
+ setting('permission.task', 'enum', 'Task permission', 'Permission rule for spawning subagent tasks.', {
99
+ category: 'permissions',
100
+ allowedValues: PERMISSION_ACTIONS,
101
+ }),
102
+ setting('permission.websearch', 'enum', 'Web search permission', 'Permission rule for web search operations.', {
103
+ category: 'permissions',
104
+ allowedValues: PERMISSION_ACTIONS,
105
+ }),
106
+ setting('compaction.auto', 'boolean', 'Auto compaction', 'Enable automatic context compaction when context is full.', {
107
+ category: 'compaction',
108
+ }),
109
+ setting('tool_output.max_lines', 'positiveInteger', 'Tool output max lines', 'Maximum lines of tool output before truncation.', {
110
+ category: 'output',
111
+ }),
112
+ setting('tool_output.max_bytes', 'positiveInteger', 'Tool output max bytes', 'Maximum bytes of tool output before truncation.', {
113
+ category: 'output',
114
+ }),
115
+ ],
116
+ getSettingsPath(scope, projectPath) {
117
+ switch (scope) {
118
+ case 'global':
119
+ return firstExistingPath([
120
+ expandTilde('~/.config/opencode/opencode.jsonc'),
121
+ expandTilde('~/.config/opencode/opencode.json'),
122
+ expandTilde('~/.config/opencode/config.json'),
123
+ ], expandTilde('~/.config/opencode/opencode.json'));
124
+ case 'project':
125
+ return firstExistingPath([
126
+ join(projectPath, '.opencode', 'opencode.jsonc'),
127
+ join(projectPath, '.opencode', 'opencode.json'),
128
+ ], join(projectPath, '.opencode', 'opencode.json'));
129
+ case 'local':
130
+ throw new Error('OpenCode settings do not support local scope. Use --global or --project.');
131
+ }
132
+ },
133
+ };
134
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../../src/core/agentSettings/adapters/opencode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAGtD,MAAM,gBAAgB,GAAyB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AACrE,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;AAEpD,SAAS,iBAAiB,CAAC,KAAe,EAAE,QAAgB;IAC1D,OAAO,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,IAAI,QAAQ,CAAC;AACpE,CAAC;AAED,SAAS,OAAO,CACd,GAAW,EACX,SAA8C,EAC9C,KAAa,EACb,WAAmB,EACnB,UAA0G,EAAE;IAE5G,MAAM,UAAU,GAA2B;QACzC,KAAK,EAAE,UAAU;QACjB,GAAG;QACH,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC;QAChD,KAAK;QACL,WAAW;QACX,SAAS;QACT,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,gBAAgB;QAC1C,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,QAAQ;QAC9C,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,UAAU;QACxC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,MAAM;KAC7B,CAAC;IAEF,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,UAAU,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IACnD,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACrC,UAAU,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAC7C,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,UAAU,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IAC/C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAyB;IAC3D,KAAK,EAAE,UAAU;IACjB,WAAW,EAAE,UAAU;IACvB,MAAM,EAAE,OAAO;IACf,WAAW,EAAE;QACX,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,uFAAuF,EAAE;YAC3H,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,OAAO,CAAC,aAAa,EAAE,QAAQ,EAAE,aAAa,EAAE,gFAAgF,EAAE;YAChI,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;YACzG,QAAQ,EAAE,UAAU;YACpB,IAAI,EAAE,oBAAoB;SAC3B,CAAC;QACF,OAAO,CAAC,eAAe,EAAE,QAAQ,EAAE,eAAe,EAAE,sDAAsD,EAAE;YAC1G,QAAQ,EAAE,OAAO;SAClB,CAAC;QACF,OAAO,CAAC,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,oDAAoD,EAAE;YAC1G,aAAa,EAAE,CAAC,QAAQ,CAAC;YACzB,MAAM,EAAE,CAAC,QAAQ,CAAC;YAClB,YAAY,EAAE,QAAQ;YACtB,QAAQ,EAAE,SAAS;SACpB,CAAC;QACF,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,4DAA4D,EAAE;YAChG,QAAQ,EAAE,SAAS;SACpB,CAAC;QACF,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,sDAAsD,EAAE;YACxF,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC;YAC7C,QAAQ,EAAE,SAAS;SACpB,CAAC;QACF,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,wEAAwE,EAAE;YAClH,QAAQ,EAAE,IAAI;SACf,CAAC;QACF,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,EAAE;YAC/D,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC;YACjD,QAAQ,EAAE,SAAS;SACpB,CAAC;QACF,OAAO,CAAC,UAAU,EAAE,SAAS,EAAE,mBAAmB,EAAE,+DAA+D,EAAE;YACnH,QAAQ,EAAE,SAAS;SACpB,CAAC;QACF,OAAO,CAAC,cAAc,EAAE,MAAM,EAAE,oBAAoB,EAAE,8DAA8D,EAAE;YACpH,UAAU,EAAE,CAAC,YAAY,EAAE,GAAG,CAAC;YAC/B,QAAQ,EAAE,aAAa;YACvB,IAAI,EAAE,oBAAoB;YAC1B,aAAa,EAAE,kBAAkB;SAClC,CAAC;QACF,OAAO,CAAC,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,8CAA8C,EAAE;YACpG,QAAQ,EAAE,aAAa;YACvB,IAAI,EAAE,oBAAoB;YAC1B,aAAa,EAAE,kBAAkB;SAClC,CAAC;QACF,OAAO,CAAC,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,iCAAiC,EAAE;YACvF,QAAQ,EAAE,aAAa;YACvB,aAAa,EAAE,kBAAkB;SAClC,CAAC;QACF,OAAO,CAAC,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,gDAAgD,EAAE;YACtG,QAAQ,EAAE,aAAa;YACvB,IAAI,EAAE,OAAO;YACb,aAAa,EAAE,kBAAkB;SAClC,CAAC;QACF,OAAO,CAAC,qBAAqB,EAAE,MAAM,EAAE,sBAAsB,EAAE,6CAA6C,EAAE;YAC5G,QAAQ,EAAE,aAAa;YACvB,aAAa,EAAE,kBAAkB;SAClC,CAAC;QACF,OAAO,CAAC,iBAAiB,EAAE,MAAM,EAAE,iBAAiB,EAAE,8CAA8C,EAAE;YACpG,QAAQ,EAAE,aAAa;YACvB,aAAa,EAAE,kBAAkB;SAClC,CAAC;QACF,OAAO,CAAC,sBAAsB,EAAE,MAAM,EAAE,uBAAuB,EAAE,4CAA4C,EAAE;YAC7G,QAAQ,EAAE,aAAa;YACvB,aAAa,EAAE,kBAAkB;SAClC,CAAC;QACF,OAAO,CAAC,iBAAiB,EAAE,SAAS,EAAE,iBAAiB,EAAE,2DAA2D,EAAE;YACpH,QAAQ,EAAE,YAAY;SACvB,CAAC;QACF,OAAO,CAAC,uBAAuB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,iDAAiD,EAAE;YAC9H,QAAQ,EAAE,QAAQ;SACnB,CAAC;QACF,OAAO,CAAC,uBAAuB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,iDAAiD,EAAE;YAC9H,QAAQ,EAAE,QAAQ;SACnB,CAAC;KACH;IACD,eAAe,CAAC,KAAyB,EAAE,WAAmB;QAC5D,QAAQ,KAAK,EAAE,CAAC;YACd,KAAK,QAAQ;gBACX,OAAO,iBAAiB,CAAC;oBACvB,WAAW,CAAC,mCAAmC,CAAC;oBAChD,WAAW,CAAC,kCAAkC,CAAC;oBAC/C,WAAW,CAAC,gCAAgC,CAAC;iBAC9C,EAAE,WAAW,CAAC,kCAAkC,CAAC,CAAC,CAAC;YACtD,KAAK,SAAS;gBACZ,OAAO,iBAAiB,CAAC;oBACvB,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,gBAAgB,CAAC;oBAChD,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,eAAe,CAAC;iBAChD,EAAE,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;YACtD,KAAK,OAAO;gBACV,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAChG,CAAC;IACH,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/agentSettings/registry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAMxG,wBAAgB,wBAAwB,IAAI,oBAAoB,EAAE,CAEjE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAEvF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAExG;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,sBAAsB,GAAG,uBAAuB,CAKzF"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/agentSettings/registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAQxG,wBAAgB,wBAAwB,IAAI,oBAAoB,EAAE,CAEjE;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAEvF;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,sBAAsB,GAAG,SAAS,CAExG;AAED,wBAAgB,aAAa,CAAC,UAAU,EAAE,sBAAsB,GAAG,uBAAuB,CAKzF"}
@@ -1,6 +1,10 @@
1
1
  import { claudeSettingsAdapter } from './adapters/claude.js';
2
+ import { codexSettingsAdapter } from './adapters/codex.js';
3
+ import { opencodeSettingsAdapter } from './adapters/opencode.js';
2
4
  const ADAPTERS = [
3
5
  claudeSettingsAdapter,
6
+ codexSettingsAdapter,
7
+ opencodeSettingsAdapter,
4
8
  ];
5
9
  export function getAgentSettingsAdapters() {
6
10
  return [...ADAPTERS];
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/agentSettings/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,MAAM,QAAQ,GAA2B;IACvC,qBAAqB;CACtB,CAAC;AAEF,MAAM,UAAU,wBAAwB;IACtC,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAa,EAAE,GAAW;IAClE,OAAO,uBAAuB,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAkC;IAC9D,OAAO;QACL,GAAG,UAAU;QACb,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;KAC5C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/agentSettings/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,MAAM,QAAQ,GAA2B;IACvC,qBAAqB;IACrB,oBAAoB;IACpB,uBAAuB;CACxB,CAAC;AAEF,MAAM,UAAU,wBAAwB;IACtC,OAAO,CAAC,GAAG,QAAQ,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAa,EAAE,GAAW;IAClE,OAAO,uBAAuB,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,UAAkC;IAC9D,OAAO;QACL,GAAG,UAAU;QACb,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;KAC5C,CAAC;AACJ,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { AgentHookAddOptions, AgentHookMatcher, AgentHookRemoveOptions, AgentHookWriteResult, AgentSettingReadOptions, AgentSettingsSchema, AgentSettingSetOptions, AgentSettingsWriteResult } from './types.js';
1
+ import type { AgentApiKeyAction, AgentApiKeyOptions, AgentApiKeyResult, AgentHookAddOptions, AgentHookMatcher, AgentHookRemoveOptions, AgentHookWriteResult, AgentSettingReadOptions, AgentSettingsSchema, AgentSettingSetOptions, AgentSettingsWriteResult } from './types.js';
2
2
  export declare class AgentSettingsManager {
3
3
  getSupportedAgents(): string[];
4
4
  getSchema(agent: string): AgentSettingsSchema;
@@ -8,5 +8,7 @@ export declare class AgentSettingsManager {
8
8
  listHooks(agent: string, event?: string, options?: AgentSettingReadOptions): Promise<Record<string, AgentHookMatcher[]> | AgentHookMatcher[]>;
9
9
  addHook(agent: string, event: string, command: string, options?: AgentHookAddOptions): Promise<AgentHookWriteResult>;
10
10
  removeHook(agent: string, event: string, commandOrName: string, options?: AgentHookRemoveOptions): Promise<AgentHookWriteResult>;
11
+ getApiKeyStatus(agent: string, apiKey: string, options?: AgentApiKeyOptions): Promise<AgentApiKeyResult>;
12
+ updateApiKeyTrust(agent: string, action: AgentApiKeyAction, apiKey: string, options?: AgentApiKeyOptions): Promise<AgentApiKeyResult>;
11
13
  }
12
14
  //# sourceMappingURL=settingsManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"settingsManager.d.ts","sourceRoot":"","sources":["../../../src/core/agentSettings/settingsManager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,mBAAmB,EAInB,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EAEnB,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAoOpB,qBAAa,oBAAoB;IAC/B,kBAAkB,IAAI,MAAM,EAAE;IAI9B,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB;IAcvC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,OAAO,CAAC;IAuBzF,GAAG,CACP,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,wBAAwB,CAAC;IAkC9B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAgC1G,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,GAAG,gBAAgB,EAAE,CAAC;IAgCjJ,OAAO,CACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,oBAAoB,CAAC;IA2C1B,UAAU,CACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,oBAAoB,CAAC;CAiDjC"}
1
+ {"version":3,"file":"settingsManager.d.ts","sourceRoot":"","sources":["../../../src/core/agentSettings/settingsManager.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAEV,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EAEjB,mBAAmB,EAInB,gBAAgB,EAChB,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EAEnB,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAiWpB,qBAAa,oBAAoB;IAC/B,kBAAkB,IAAI,MAAM,EAAE;IAI9B,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB;IAcvC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,OAAO,CAAC;IA4CzF,GAAG,CACP,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,wBAAwB,CAAC;IAkC9B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAgC1G,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,uBAA4B,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,GAAG,gBAAgB,EAAE,CAAC;IAoCjJ,OAAO,CACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,oBAAoB,CAAC;IA4C1B,UAAU,CACd,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,oBAAoB,CAAC;IAmD1B,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAuB5G,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA4ChJ"}
@@ -1,3 +1,5 @@
1
+ import * as TOML from '@iarna/toml';
2
+ import { parse as parseJsonc } from 'jsonc-parser';
1
3
  import { readFileIfExists, writeFile } from '../../utils/fs.js';
2
4
  import { getEffectiveAgentSettingsDefaultScopeSync } from '../userConfig.js';
3
5
  import { parseAgentSettingValue } from './valueParser.js';
@@ -13,8 +15,22 @@ const HOOK_EVENT_ALIASES = {
13
15
  stop: 'Stop',
14
16
  'session-start': 'SessionStart',
15
17
  'session-end': 'SessionEnd',
18
+ 'user-prompt-submit': 'UserPromptSubmit',
16
19
  };
17
20
  const HOOK_EVENTS = new Set(Object.values(HOOK_EVENT_ALIASES));
21
+ const CLAUDE_API_KEY_RESPONSES_DEFINITION = {
22
+ agent: 'claude',
23
+ key: 'customApiKeyResponses',
24
+ nativePath: ['customApiKeyResponses'],
25
+ title: 'Custom API key responses',
26
+ description: 'Remembered custom API key trust responses.',
27
+ valueType: 'object',
28
+ scopes: ['global'],
29
+ defaultScope: 'global',
30
+ category: 'auth',
31
+ risk: 'security-sensitive',
32
+ store: 'globalConfig',
33
+ };
18
34
  function assertObject(value, path) {
19
35
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
20
36
  throw new Error(`${path} contains JSON that is not an object.`);
@@ -144,6 +160,50 @@ function buildHookCommand(command, name) {
144
160
  ...(name ? { name } : {}),
145
161
  };
146
162
  }
163
+ function normalizeApiKeyForConfig(apiKey) {
164
+ const trimmed = apiKey.trim();
165
+ if (!trimmed) {
166
+ throw new Error('API key cannot be empty.');
167
+ }
168
+ return trimmed.slice(-20);
169
+ }
170
+ function getApiKeyResponses(config) {
171
+ const current = config.customApiKeyResponses;
172
+ if (current !== undefined && (!current || typeof current !== 'object' || Array.isArray(current))) {
173
+ throw new Error('Existing customApiKeyResponses value is not an object.');
174
+ }
175
+ const responses = (current ?? {});
176
+ const approved = responses.approved ?? [];
177
+ const rejected = responses.rejected ?? [];
178
+ if (!Array.isArray(approved) || !approved.every(value => typeof value === 'string')) {
179
+ throw new Error('Existing customApiKeyResponses.approved value must be an array of strings.');
180
+ }
181
+ if (!Array.isArray(rejected) || !rejected.every(value => typeof value === 'string')) {
182
+ throw new Error('Existing customApiKeyResponses.rejected value must be an array of strings.');
183
+ }
184
+ return {
185
+ approved,
186
+ rejected,
187
+ };
188
+ }
189
+ function getApiKeyStatusFromResponses(responses, fingerprint) {
190
+ if (responses.approved.includes(fingerprint)) {
191
+ return 'approved';
192
+ }
193
+ if (responses.rejected.includes(fingerprint)) {
194
+ return 'rejected';
195
+ }
196
+ return 'unknown';
197
+ }
198
+ function setApiKeyResponses(config, approved, rejected) {
199
+ config.customApiKeyResponses = {
200
+ ...(config.customApiKeyResponses && typeof config.customApiKeyResponses === 'object' && !Array.isArray(config.customApiKeyResponses)
201
+ ? config.customApiKeyResponses
202
+ : {}),
203
+ approved,
204
+ rejected,
205
+ };
206
+ }
147
207
  function deleteNestedValue(config, path) {
148
208
  const parents = [];
149
209
  let current = config;
@@ -178,27 +238,79 @@ function resolveProjectPath(projectPath) {
178
238
  return projectPath ?? process.cwd();
179
239
  }
180
240
  function resolveScope(definition, scope) {
181
- const resolvedScope = scope ?? getEffectiveAgentSettingsDefaultScopeSync();
241
+ const defaultScope = getEffectiveAgentSettingsDefaultScopeSync();
242
+ const resolvedScope = scope ?? (definition.store === 'globalConfig' && !definition.scopes.includes(defaultScope) ? definition.defaultScope : defaultScope);
182
243
  if (!definition.scopes.includes(resolvedScope)) {
183
244
  throw new Error(`"${definition.key}" does not support ${resolvedScope} scope. Supported scopes: ${definition.scopes.join(', ')}.`);
184
245
  }
185
246
  return resolvedScope;
186
247
  }
187
- async function readJsonObject(path) {
248
+ function getSupportedSettingScopes(adapter) {
249
+ return [...new Set(adapter.definitions.flatMap(definition => definition.scopes))];
250
+ }
251
+ function resolveFullReadScope(adapter, scope) {
252
+ const resolvedScope = scope ?? getEffectiveAgentSettingsDefaultScopeSync();
253
+ const supportedScopes = getSupportedSettingScopes(adapter);
254
+ if (!supportedScopes.includes(resolvedScope)) {
255
+ throw new Error(`Agent ${adapter.agent} settings do not support ${resolvedScope} scope. Supported scopes: ${supportedScopes.join(', ')}.`);
256
+ }
257
+ return resolvedScope;
258
+ }
259
+ async function readConfigObject(adapter, path) {
188
260
  const content = await readFileIfExists(path);
189
261
  if (!content) {
190
262
  return {};
191
263
  }
264
+ if (adapter.format === 'toml') {
265
+ try {
266
+ return assertObject(TOML.parse(content), path);
267
+ }
268
+ catch (error) {
269
+ if (error instanceof SyntaxError || error instanceof Error) {
270
+ throw new Error(`${path} contains invalid TOML.`);
271
+ }
272
+ throw error;
273
+ }
274
+ }
192
275
  try {
193
- return assertObject(JSON.parse(content), path);
276
+ const errors = [];
277
+ const value = adapter.format === 'jsonc'
278
+ ? parseJsonc(content, errors, { allowTrailingComma: true })
279
+ : JSON.parse(content);
280
+ if (errors.length > 0) {
281
+ throw new SyntaxError('Invalid JSONC');
282
+ }
283
+ return assertObject(value, path);
194
284
  }
195
285
  catch (error) {
196
286
  if (error instanceof SyntaxError) {
197
- throw new Error(`${path} contains invalid JSON.`);
287
+ throw new Error(`${path} contains invalid ${adapter.format === 'jsonc' ? 'JSONC' : 'JSON'}.`);
198
288
  }
199
289
  throw error;
200
290
  }
201
291
  }
292
+ function stringifyConfigObject(adapter, config) {
293
+ if (adapter.format === 'toml') {
294
+ return TOML.stringify(config);
295
+ }
296
+ return `${JSON.stringify(config, null, 2)}\n`;
297
+ }
298
+ async function writeConfigObject(adapter, path, config) {
299
+ await writeFile(path, stringifyConfigObject(adapter, config));
300
+ }
301
+ function assertHookEventSupported(adapter, event) {
302
+ if (adapter.hookEvents && !adapter.hookEvents.includes(event)) {
303
+ throw new Error(`Agent ${adapter.agent} does not support ${event} hooks. Supported: ${adapter.hookEvents.join(', ')}.`);
304
+ }
305
+ }
306
+ function resolveHookScope(adapter, scope) {
307
+ const resolvedScope = scope ?? getEffectiveAgentSettingsDefaultScopeSync();
308
+ const supportedScopes = adapter.hookScopes ?? ['global', 'project', 'local'];
309
+ if (!supportedScopes.includes(resolvedScope)) {
310
+ throw new Error(`Agent ${adapter.agent} hooks do not support ${resolvedScope} scope. Supported scopes: ${supportedScopes.join(', ')}.`);
311
+ }
312
+ return resolvedScope;
313
+ }
202
314
  export class AgentSettingsManager {
203
315
  getSupportedAgents() {
204
316
  return getAgentSettingsAdapters().map(adapter => adapter.agent);
@@ -221,17 +333,34 @@ export class AgentSettingsManager {
221
333
  throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(', ')}`);
222
334
  }
223
335
  if (!key) {
224
- const scope = options.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
336
+ const scope = resolveFullReadScope(adapter, options.scope);
225
337
  const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath));
226
- return await readJsonObject(path);
338
+ const config = await readConfigObject(adapter, path);
339
+ if (scope !== 'global') {
340
+ return config;
341
+ }
342
+ const globalConfigDefinitions = adapter.definitions.filter(definition => definition.store === 'globalConfig' && definition.scopes.includes('global'));
343
+ if (globalConfigDefinitions.length === 0) {
344
+ return config;
345
+ }
346
+ const globalConfigPath = adapter.getSettingsPath('global', resolveProjectPath(options.projectPath), globalConfigDefinitions[0]);
347
+ const globalConfig = await readConfigObject(adapter, globalConfigPath);
348
+ const result = { ...config };
349
+ for (const definition of globalConfigDefinitions) {
350
+ const value = getNestedValue(globalConfig, definition.nativePath);
351
+ if (value !== undefined) {
352
+ setNestedValue(result, definition.nativePath, value);
353
+ }
354
+ }
355
+ return result;
227
356
  }
228
357
  const definition = getAgentSettingDefinition(agent, key);
229
358
  if (!definition) {
230
359
  throw new Error(`Unknown ${agent} setting: ${key}.`);
231
360
  }
232
361
  const scope = resolveScope(definition, options.scope);
233
- const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath));
234
- const config = await readJsonObject(path);
362
+ const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath), definition);
363
+ const config = await readConfigObject(adapter, path);
235
364
  return getNestedValue(config, definition.nativePath);
236
365
  }
237
366
  async set(agent, key, rawValue, options = {}) {
@@ -244,13 +373,13 @@ export class AgentSettingsManager {
244
373
  throw new Error(`Unknown ${agent} setting: ${key}.`);
245
374
  }
246
375
  const scope = resolveScope(definition, options.scope);
247
- const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath));
248
- const config = await readJsonObject(path);
376
+ const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath), definition);
377
+ const config = await readConfigObject(adapter, path);
249
378
  const previousValue = getNestedValue(config, definition.nativePath);
250
379
  const value = parseAgentSettingValue(definition, rawValue, options.parseJson);
251
380
  setNestedValue(config, definition.nativePath, value);
252
381
  if (!options.dryRun) {
253
- await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
382
+ await writeConfigObject(adapter, path, config);
254
383
  }
255
384
  return {
256
385
  agent,
@@ -272,12 +401,12 @@ export class AgentSettingsManager {
272
401
  throw new Error(`Unknown ${agent} setting: ${key}.`);
273
402
  }
274
403
  const scope = resolveScope(definition, options.scope);
275
- const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath));
276
- const config = await readJsonObject(path);
404
+ const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath), definition);
405
+ const config = await readConfigObject(adapter, path);
277
406
  const previousValue = getNestedValue(config, definition.nativePath);
278
407
  deleteNestedValue(config, definition.nativePath);
279
408
  if (!options.dryRun) {
280
- await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
409
+ await writeConfigObject(adapter, path, config);
281
410
  }
282
411
  return {
283
412
  agent,
@@ -293,14 +422,18 @@ export class AgentSettingsManager {
293
422
  if (!adapter) {
294
423
  throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(', ')}`);
295
424
  }
296
- if (agent !== 'claude') {
425
+ if (!adapter.hookEvents) {
297
426
  throw new Error(`Agent ${agent} does not support hook management.`);
298
427
  }
299
- const scope = options.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
428
+ const hookEvent = event ? normalizeHookEvent(event) : undefined;
429
+ if (hookEvent) {
430
+ assertHookEventSupported(adapter, hookEvent);
431
+ }
432
+ const scope = resolveHookScope(adapter, options.scope);
300
433
  const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath));
301
- const config = await readJsonObject(path);
302
- if (event) {
303
- return getHookMatchers(config, normalizeHookEvent(event));
434
+ const config = await readConfigObject(adapter, path);
435
+ if (hookEvent) {
436
+ return getHookMatchers(config, hookEvent);
304
437
  }
305
438
  const hooks = getNestedValue(config, ['hooks']);
306
439
  if (hooks === undefined) {
@@ -320,13 +453,14 @@ export class AgentSettingsManager {
320
453
  if (!adapter) {
321
454
  throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(', ')}`);
322
455
  }
323
- if (agent !== 'claude') {
456
+ if (!adapter.hookEvents) {
324
457
  throw new Error(`Agent ${agent} does not support hook management.`);
325
458
  }
326
459
  const hookEvent = normalizeHookEvent(event);
327
- const scope = options.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
460
+ assertHookEventSupported(adapter, hookEvent);
461
+ const scope = resolveHookScope(adapter, options.scope);
328
462
  const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath));
329
- const config = await readJsonObject(path);
463
+ const config = await readConfigObject(adapter, path);
330
464
  const hook = buildHookCommand(command, options.name);
331
465
  const matchers = getHookMatchers(config, hookEvent);
332
466
  const matcher = options.matcher ?? '*';
@@ -342,7 +476,7 @@ export class AgentSettingsManager {
342
476
  }
343
477
  setHookMatchers(config, hookEvent, matchers);
344
478
  if (!options.dryRun) {
345
- await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
479
+ await writeConfigObject(adapter, path, config);
346
480
  }
347
481
  return {
348
482
  agent,
@@ -358,13 +492,14 @@ export class AgentSettingsManager {
358
492
  if (!adapter) {
359
493
  throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(', ')}`);
360
494
  }
361
- if (agent !== 'claude') {
495
+ if (!adapter.hookEvents) {
362
496
  throw new Error(`Agent ${agent} does not support hook management.`);
363
497
  }
364
498
  const hookEvent = normalizeHookEvent(event);
365
- const scope = options.scope ?? getEffectiveAgentSettingsDefaultScopeSync();
499
+ assertHookEventSupported(adapter, hookEvent);
500
+ const scope = resolveHookScope(adapter, options.scope);
366
501
  const path = adapter.getSettingsPath(scope, resolveProjectPath(options.projectPath));
367
- const config = await readJsonObject(path);
502
+ const config = await readConfigObject(adapter, path);
368
503
  const matchers = getHookMatchers(config, hookEvent);
369
504
  let removed = 0;
370
505
  const nextMatchers = matchers
@@ -384,7 +519,7 @@ export class AgentSettingsManager {
384
519
  .filter(entry => entry.hooks.length > 0);
385
520
  setHookMatchers(config, hookEvent, nextMatchers);
386
521
  if (!options.dryRun) {
387
- await writeFile(path, `${JSON.stringify(config, null, 2)}\n`);
522
+ await writeConfigObject(adapter, path, config);
388
523
  }
389
524
  return {
390
525
  agent,
@@ -395,5 +530,64 @@ export class AgentSettingsManager {
395
530
  dryRun: Boolean(options.dryRun),
396
531
  };
397
532
  }
533
+ async getApiKeyStatus(agent, apiKey, options = {}) {
534
+ const adapter = getAgentSettingsAdapter(agent);
535
+ if (!adapter) {
536
+ throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(', ')}`);
537
+ }
538
+ if (agent !== 'claude') {
539
+ throw new Error(`Agent ${agent} does not support API key trust management.`);
540
+ }
541
+ const path = adapter.getSettingsPath('global', resolveProjectPath(options.projectPath), CLAUDE_API_KEY_RESPONSES_DEFINITION);
542
+ const config = await readConfigObject(adapter, path);
543
+ const fingerprint = normalizeApiKeyForConfig(apiKey);
544
+ const responses = getApiKeyResponses(config);
545
+ return {
546
+ agent,
547
+ path,
548
+ fingerprint,
549
+ status: getApiKeyStatusFromResponses(responses, fingerprint),
550
+ dryRun: false,
551
+ };
552
+ }
553
+ async updateApiKeyTrust(agent, action, apiKey, options = {}) {
554
+ const adapter = getAgentSettingsAdapter(agent);
555
+ if (!adapter) {
556
+ throw new Error(`Unsupported agent settings adapter: ${agent}. Supported: ${this.getSupportedAgents().join(', ')}`);
557
+ }
558
+ if (agent !== 'claude') {
559
+ throw new Error(`Agent ${agent} does not support API key trust management.`);
560
+ }
561
+ const path = adapter.getSettingsPath('global', resolveProjectPath(options.projectPath), CLAUDE_API_KEY_RESPONSES_DEFINITION);
562
+ const config = await readConfigObject(adapter, path);
563
+ const fingerprint = normalizeApiKeyForConfig(apiKey);
564
+ const responses = getApiKeyResponses(config);
565
+ const previousStatus = getApiKeyStatusFromResponses(responses, fingerprint);
566
+ let approved = responses.approved.filter(value => value !== fingerprint);
567
+ let rejected = responses.rejected.filter(value => value !== fingerprint);
568
+ if (action === 'approve') {
569
+ approved = [...approved, fingerprint];
570
+ }
571
+ else if (action === 'reject') {
572
+ rejected = [...rejected, fingerprint];
573
+ }
574
+ const status = action === 'approve'
575
+ ? 'approved'
576
+ : action === 'reject'
577
+ ? 'rejected'
578
+ : 'unknown';
579
+ setApiKeyResponses(config, approved, rejected);
580
+ if (!options.dryRun) {
581
+ await writeConfigObject(adapter, path, config);
582
+ }
583
+ return {
584
+ agent,
585
+ path,
586
+ fingerprint,
587
+ status,
588
+ previousStatus,
589
+ dryRun: Boolean(options.dryRun),
590
+ };
591
+ }
398
592
  }
399
593
  //# sourceMappingURL=settingsManager.js.map