@codemieai/code 0.0.40 → 0.0.42

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 (211) hide show
  1. package/README.md +5 -6
  2. package/bin/codemie-opencode.js +8 -1
  3. package/dist/agents/codemie-code/agent.d.ts.map +1 -1
  4. package/dist/agents/codemie-code/agent.js +5 -0
  5. package/dist/agents/codemie-code/agent.js.map +1 -1
  6. package/dist/agents/codemie-code/skills/index.d.ts +4 -0
  7. package/dist/agents/codemie-code/skills/index.d.ts.map +1 -1
  8. package/dist/agents/codemie-code/skills/index.js +4 -0
  9. package/dist/agents/codemie-code/skills/index.js.map +1 -1
  10. package/dist/agents/codemie-code/skills/sync/SkillSync.d.ts +52 -0
  11. package/dist/agents/codemie-code/skills/sync/SkillSync.d.ts.map +1 -0
  12. package/dist/agents/codemie-code/skills/sync/SkillSync.js +165 -0
  13. package/dist/agents/codemie-code/skills/sync/SkillSync.js.map +1 -0
  14. package/dist/agents/core/AgentCLI.d.ts.map +1 -1
  15. package/dist/agents/core/AgentCLI.js +38 -8
  16. package/dist/agents/core/AgentCLI.js.map +1 -1
  17. package/dist/agents/core/BaseAgentAdapter.d.ts +11 -1
  18. package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
  19. package/dist/agents/core/BaseAgentAdapter.js +175 -18
  20. package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
  21. package/dist/agents/core/types.d.ts +18 -0
  22. package/dist/agents/core/types.d.ts.map +1 -1
  23. package/dist/agents/plugins/claude/claude-acp.plugin.d.ts +7 -0
  24. package/dist/agents/plugins/claude/claude-acp.plugin.d.ts.map +1 -1
  25. package/dist/agents/plugins/claude/claude-acp.plugin.js +10 -0
  26. package/dist/agents/plugins/claude/claude-acp.plugin.js.map +1 -1
  27. package/dist/agents/plugins/claude/claude.plugin-installer.d.ts +11 -0
  28. package/dist/agents/plugins/claude/claude.plugin-installer.d.ts.map +1 -1
  29. package/dist/agents/plugins/claude/claude.plugin-installer.js +32 -0
  30. package/dist/agents/plugins/claude/claude.plugin-installer.js.map +1 -1
  31. package/dist/agents/plugins/claude/claude.plugin.d.ts +1 -8
  32. package/dist/agents/plugins/claude/claude.plugin.d.ts.map +1 -1
  33. package/dist/agents/plugins/claude/claude.plugin.js +96 -101
  34. package/dist/agents/plugins/claude/claude.plugin.js.map +1 -1
  35. package/dist/agents/plugins/claude/plugin/.claude-plugin/plugin.json +1 -1
  36. package/dist/agents/plugins/claude/plugin/codemie-statusline.mjs +42 -0
  37. package/dist/agents/plugins/claude/plugin/hooks/hooks.json +10 -0
  38. package/dist/agents/plugins/claude/plugin/hooks/hooks.windows.json +98 -0
  39. package/dist/agents/plugins/claude/plugin/scripts/bash/rtk-auto-wrapper.sh +81 -0
  40. package/dist/agents/plugins/claude/plugin/scripts/bash/rtk-baseline.sh +39 -0
  41. package/dist/agents/plugins/claude/sounds-installer.d.ts.map +1 -1
  42. package/dist/agents/plugins/claude/sounds-installer.js +0 -4
  43. package/dist/agents/plugins/claude/sounds-installer.js.map +1 -1
  44. package/dist/agents/plugins/codemie-code-binary.d.ts +17 -0
  45. package/dist/agents/plugins/codemie-code-binary.d.ts.map +1 -0
  46. package/dist/agents/plugins/codemie-code-binary.js +94 -0
  47. package/dist/agents/plugins/codemie-code-binary.js.map +1 -0
  48. package/dist/agents/plugins/codemie-code-hooks/index.d.ts +3 -0
  49. package/dist/agents/plugins/codemie-code-hooks/index.d.ts.map +1 -0
  50. package/dist/agents/plugins/codemie-code-hooks/index.js +3 -0
  51. package/dist/agents/plugins/codemie-code-hooks/index.js.map +1 -0
  52. package/dist/agents/plugins/codemie-code-hooks/inject-hooks.d.ts +22 -0
  53. package/dist/agents/plugins/codemie-code-hooks/inject-hooks.d.ts.map +1 -0
  54. package/dist/agents/plugins/codemie-code-hooks/inject-hooks.js +64 -0
  55. package/dist/agents/plugins/codemie-code-hooks/inject-hooks.js.map +1 -0
  56. package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.d.ts +15 -0
  57. package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.d.ts.map +1 -0
  58. package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.js +522 -0
  59. package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.js.map +1 -0
  60. package/dist/agents/plugins/codemie-code.plugin.d.ts +56 -12
  61. package/dist/agents/plugins/codemie-code.plugin.d.ts.map +1 -1
  62. package/dist/agents/plugins/codemie-code.plugin.js +502 -125
  63. package/dist/agents/plugins/codemie-code.plugin.js.map +1 -1
  64. package/dist/agents/plugins/gemini/gemini.plugin.d.ts +8 -0
  65. package/dist/agents/plugins/gemini/gemini.plugin.d.ts.map +1 -1
  66. package/dist/agents/plugins/gemini/gemini.plugin.js +45 -1
  67. package/dist/agents/plugins/gemini/gemini.plugin.js.map +1 -1
  68. package/dist/agents/plugins/opencode/opencode-message-types.d.ts +2 -0
  69. package/dist/agents/plugins/opencode/opencode-message-types.d.ts.map +1 -1
  70. package/dist/agents/plugins/opencode/opencode-message-types.js.map +1 -1
  71. package/dist/agents/plugins/opencode/opencode-model-configs.d.ts +12 -2
  72. package/dist/agents/plugins/opencode/opencode-model-configs.d.ts.map +1 -1
  73. package/dist/agents/plugins/opencode/opencode-model-configs.js +329 -24
  74. package/dist/agents/plugins/opencode/opencode-model-configs.js.map +1 -1
  75. package/dist/agents/plugins/opencode/opencode.paths.d.ts +16 -1
  76. package/dist/agents/plugins/opencode/opencode.paths.d.ts.map +1 -1
  77. package/dist/agents/plugins/opencode/opencode.paths.js +43 -5
  78. package/dist/agents/plugins/opencode/opencode.paths.js.map +1 -1
  79. package/dist/agents/plugins/opencode/opencode.plugin.d.ts.map +1 -1
  80. package/dist/agents/plugins/opencode/opencode.plugin.js +91 -25
  81. package/dist/agents/plugins/opencode/opencode.plugin.js.map +1 -1
  82. package/dist/agents/plugins/opencode/opencode.session.d.ts +5 -0
  83. package/dist/agents/plugins/opencode/opencode.session.d.ts.map +1 -1
  84. package/dist/agents/plugins/opencode/opencode.session.js +99 -2
  85. package/dist/agents/plugins/opencode/opencode.session.js.map +1 -1
  86. package/dist/agents/plugins/opencode/opencode.sqlite-reader.d.ts +59 -0
  87. package/dist/agents/plugins/opencode/opencode.sqlite-reader.d.ts.map +1 -0
  88. package/dist/agents/plugins/opencode/opencode.sqlite-reader.js +200 -0
  89. package/dist/agents/plugins/opencode/opencode.sqlite-reader.js.map +1 -0
  90. package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.d.ts +3 -0
  91. package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.d.ts.map +1 -1
  92. package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.js +35 -13
  93. package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.js.map +1 -1
  94. package/dist/agents/registry.d.ts.map +1 -1
  95. package/dist/agents/registry.js +8 -7
  96. package/dist/agents/registry.js.map +1 -1
  97. package/dist/cli/commands/analytics/data-loader.js +1 -1
  98. package/dist/cli/commands/analytics/data-loader.js.map +1 -1
  99. package/dist/cli/commands/doctor/checks/AgentsCheck.d.ts.map +1 -1
  100. package/dist/cli/commands/doctor/checks/AgentsCheck.js +5 -2
  101. package/dist/cli/commands/doctor/checks/AgentsCheck.js.map +1 -1
  102. package/dist/cli/commands/doctor/checks/FrameworksCheck.d.ts.map +1 -1
  103. package/dist/cli/commands/doctor/checks/FrameworksCheck.js +5 -2
  104. package/dist/cli/commands/doctor/checks/FrameworksCheck.js.map +1 -1
  105. package/dist/cli/commands/doctor/checks/JWTAuthCheck.d.ts +9 -0
  106. package/dist/cli/commands/doctor/checks/JWTAuthCheck.d.ts.map +1 -0
  107. package/dist/cli/commands/doctor/checks/JWTAuthCheck.js +113 -0
  108. package/dist/cli/commands/doctor/checks/JWTAuthCheck.js.map +1 -0
  109. package/dist/cli/commands/doctor/checks/index.d.ts +1 -0
  110. package/dist/cli/commands/doctor/checks/index.d.ts.map +1 -1
  111. package/dist/cli/commands/doctor/checks/index.js +1 -0
  112. package/dist/cli/commands/doctor/checks/index.js.map +1 -1
  113. package/dist/cli/commands/doctor/index.d.ts.map +1 -1
  114. package/dist/cli/commands/doctor/index.js +2 -1
  115. package/dist/cli/commands/doctor/index.js.map +1 -1
  116. package/dist/cli/commands/hook.d.ts.map +1 -1
  117. package/dist/cli/commands/hook.js +28 -5
  118. package/dist/cli/commands/hook.js.map +1 -1
  119. package/dist/cli/commands/skill.d.ts.map +1 -1
  120. package/dist/cli/commands/skill.js +80 -1
  121. package/dist/cli/commands/skill.js.map +1 -1
  122. package/dist/cli/commands/test-metrics.d.ts +17 -0
  123. package/dist/cli/commands/test-metrics.d.ts.map +1 -0
  124. package/dist/cli/commands/test-metrics.js +198 -0
  125. package/dist/cli/commands/test-metrics.js.map +1 -0
  126. package/dist/cli/index.js +9 -13
  127. package/dist/cli/index.js.map +1 -1
  128. package/dist/env/types.d.ts +12 -2
  129. package/dist/env/types.d.ts.map +1 -1
  130. package/dist/env/types.js.map +1 -1
  131. package/dist/providers/core/types.d.ts +22 -1
  132. package/dist/providers/core/types.d.ts.map +1 -1
  133. package/dist/providers/core/types.js +12 -1
  134. package/dist/providers/core/types.js.map +1 -1
  135. package/dist/providers/index.d.ts +2 -0
  136. package/dist/providers/index.d.ts.map +1 -1
  137. package/dist/providers/index.js +2 -0
  138. package/dist/providers/index.js.map +1 -1
  139. package/dist/providers/integration/setup-ui.d.ts.map +1 -1
  140. package/dist/providers/integration/setup-ui.js +3 -1
  141. package/dist/providers/integration/setup-ui.js.map +1 -1
  142. package/dist/providers/plugins/jwt/index.d.ts +9 -0
  143. package/dist/providers/plugins/jwt/index.d.ts.map +1 -0
  144. package/dist/providers/plugins/jwt/index.js +13 -0
  145. package/dist/providers/plugins/jwt/index.js.map +1 -0
  146. package/dist/providers/plugins/jwt/jwt.setup-steps.d.ts +9 -0
  147. package/dist/providers/plugins/jwt/jwt.setup-steps.d.ts.map +1 -0
  148. package/dist/providers/plugins/jwt/jwt.setup-steps.js +153 -0
  149. package/dist/providers/plugins/jwt/jwt.setup-steps.js.map +1 -0
  150. package/dist/providers/plugins/jwt/jwt.template.d.ts +12 -0
  151. package/dist/providers/plugins/jwt/jwt.template.d.ts.map +1 -0
  152. package/dist/providers/plugins/jwt/jwt.template.js +55 -0
  153. package/dist/providers/plugins/jwt/jwt.template.js.map +1 -0
  154. package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +3 -1
  155. package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
  156. package/dist/providers/plugins/sso/proxy/plugins/index.js +5 -1
  157. package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
  158. package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.d.ts +16 -0
  159. package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.d.ts.map +1 -0
  160. package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.js +53 -0
  161. package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.js.map +1 -0
  162. package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.d.ts +25 -0
  163. package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.d.ts.map +1 -0
  164. package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.js +74 -0
  165. package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.js.map +1 -0
  166. package/dist/providers/plugins/sso/proxy/plugins/sso-auth.plugin.d.ts.map +1 -1
  167. package/dist/providers/plugins/sso/proxy/plugins/sso-auth.plugin.js +13 -2
  168. package/dist/providers/plugins/sso/proxy/plugins/sso-auth.plugin.js.map +1 -1
  169. package/dist/providers/plugins/sso/proxy/plugins/sso.session-sync.plugin.d.ts.map +1 -1
  170. package/dist/providers/plugins/sso/proxy/plugins/sso.session-sync.plugin.js +6 -3
  171. package/dist/providers/plugins/sso/proxy/plugins/sso.session-sync.plugin.js.map +1 -1
  172. package/dist/providers/plugins/sso/proxy/plugins/types.d.ts +2 -2
  173. package/dist/providers/plugins/sso/proxy/plugins/types.d.ts.map +1 -1
  174. package/dist/providers/plugins/sso/proxy/proxy-types.d.ts +2 -0
  175. package/dist/providers/plugins/sso/proxy/proxy-types.d.ts.map +1 -1
  176. package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts +4 -0
  177. package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts.map +1 -1
  178. package/dist/providers/plugins/sso/proxy/sso.proxy.js +39 -10
  179. package/dist/providers/plugins/sso/proxy/sso.proxy.js.map +1 -1
  180. package/dist/providers/plugins/sso/sso.auth.d.ts +3 -1
  181. package/dist/providers/plugins/sso/sso.auth.d.ts.map +1 -1
  182. package/dist/providers/plugins/sso/sso.auth.js +70 -12
  183. package/dist/providers/plugins/sso/sso.auth.js.map +1 -1
  184. package/dist/providers/plugins/sso/sso.http-client.d.ts +38 -8
  185. package/dist/providers/plugins/sso/sso.http-client.d.ts.map +1 -1
  186. package/dist/providers/plugins/sso/sso.http-client.js +83 -85
  187. package/dist/providers/plugins/sso/sso.http-client.js.map +1 -1
  188. package/dist/providers/plugins/sso/sso.models.d.ts.map +1 -1
  189. package/dist/providers/plugins/sso/sso.models.js +3 -3
  190. package/dist/providers/plugins/sso/sso.models.js.map +1 -1
  191. package/dist/providers/plugins/sso/sso.setup-steps.d.ts.map +1 -1
  192. package/dist/providers/plugins/sso/sso.setup-steps.js +4 -1
  193. package/dist/providers/plugins/sso/sso.setup-steps.js.map +1 -1
  194. package/dist/providers/plugins/sso/sso.template.d.ts.map +1 -1
  195. package/dist/providers/plugins/sso/sso.template.js +7 -0
  196. package/dist/providers/plugins/sso/sso.template.js.map +1 -1
  197. package/dist/utils/logger.d.ts +1 -0
  198. package/dist/utils/logger.d.ts.map +1 -1
  199. package/dist/utils/logger.js +16 -1
  200. package/dist/utils/logger.js.map +1 -1
  201. package/dist/utils/native-installer.d.ts.map +1 -1
  202. package/dist/utils/native-installer.js +35 -0
  203. package/dist/utils/native-installer.js.map +1 -1
  204. package/dist/utils/paths.d.ts +1 -1
  205. package/dist/utils/paths.js +1 -1
  206. package/dist/utils/security.d.ts +18 -1
  207. package/dist/utils/security.d.ts.map +1 -1
  208. package/dist/utils/security.js +102 -0
  209. package/dist/utils/security.js.map +1 -1
  210. package/package.json +2 -1
  211. package/scripts/copy-mr-skill-to-global.ts +0 -252
@@ -1,30 +1,239 @@
1
+ import { tmpdir } from 'os';
2
+ import { join } from 'path';
3
+ import { existsSync, writeFileSync, unlinkSync } from 'fs';
1
4
  import { logger } from '../../utils/logger.js';
5
+ import { getModelConfig, getAllOpenCodeModelConfigs } from './opencode/opencode-model-configs.js';
6
+ import { BaseAgentAdapter } from '../core/BaseAgentAdapter.js';
7
+ import { installGlobal, uninstallGlobal } from '../../utils/processes.js';
8
+ import { OpenCodeSessionAdapter } from './opencode/opencode.session.js';
9
+ import { resolveCodemieOpenCodeBinary, getPlatformPackage } from './codemie-code-binary.js';
10
+ import { getHooksPluginFileUrl, cleanupHooksPlugin } from './codemie-code-hooks/index.js';
11
+ import { getCodemieHome } from '../../utils/paths.js';
2
12
  import { CodeMieCode } from '../codemie-code/index.js';
3
13
  import { loadCodeMieConfig } from '../codemie-code/config.js';
4
- import { join } from 'path';
5
- import { readFileSync } from 'fs';
6
- import { getDirname } from '../../utils/paths.js';
7
- import { getRandomWelcomeMessage, getRandomGoodbyeMessage } from '../../utils/goodbye-messages.js';
8
- import { renderProfileInfo } from '../../utils/profile.js';
9
- import chalk from 'chalk';
10
14
  /**
11
15
  * Built-in agent name constant - single source of truth
12
16
  */
13
17
  export const BUILTIN_AGENT_NAME = 'codemie-code';
18
+ const OPENCODE_SUBCOMMANDS = ['run', 'chat', 'config', 'init', 'help', 'version'];
19
+ /**
20
+ * Convert a short model ID to Bedrock inference profile format.
21
+ * Bedrock requires region-prefixed ARN-style model IDs.
22
+ *
23
+ * Examples:
24
+ * claude-sonnet-4-5-20250929 → us.anthropic.claude-sonnet-4-5-20250929-v1:0
25
+ * claude-opus-4-6 → us.anthropic.claude-opus-4-6-v1:0
26
+ *
27
+ * If the model ID already contains 'anthropic.', it's returned as-is.
28
+ */
29
+ function toBedrockModelId(modelId, region) {
30
+ if (modelId.includes('anthropic.'))
31
+ return modelId;
32
+ const regionPrefix = region?.startsWith('eu') ? 'eu'
33
+ : region?.startsWith('ap') ? 'ap'
34
+ : 'us';
35
+ return `${regionPrefix}.anthropic.${modelId}-v1:0`;
36
+ }
37
+ // Environment variable size limit (conservative - varies by platform)
38
+ // Linux: ~128KB per var, Windows: ~32KB total env block
39
+ const MAX_ENV_SIZE = 32 * 1024;
40
+ // Track temp config files for cleanup on process exit
41
+ const tempConfigFiles = [];
42
+ let cleanupRegistered = false;
43
+ /**
44
+ * Register process exit handler for temp file cleanup (best effort)
45
+ * Only registers once, even if beforeRun is called multiple times
46
+ */
47
+ function registerCleanupHandler() {
48
+ if (cleanupRegistered)
49
+ return;
50
+ cleanupRegistered = true;
51
+ process.on('exit', () => {
52
+ for (const file of tempConfigFiles) {
53
+ try {
54
+ unlinkSync(file);
55
+ logger.debug(`[codemie-code] Cleaned up temp config: ${file}`);
56
+ }
57
+ catch {
58
+ // Ignore cleanup errors - file may already be deleted
59
+ }
60
+ }
61
+ });
62
+ }
63
+ /**
64
+ * Write config to temp file as fallback when env var size exceeded
65
+ * Returns the temp file path
66
+ */
67
+ function writeConfigToTempFile(configJson) {
68
+ const configPath = join(tmpdir(), `codemie-code-config-${process.pid}-${Date.now()}.json`);
69
+ writeFileSync(configPath, configJson, 'utf-8');
70
+ tempConfigFiles.push(configPath);
71
+ registerCleanupHandler();
72
+ return configPath;
73
+ }
74
+ /**
75
+ * Ensure session metadata file exists for SessionSyncer
76
+ * Creates or updates the session file in ~/.codemie/sessions/
77
+ */
78
+ async function ensureSessionFile(sessionId, env) {
79
+ try {
80
+ const { SessionStore } = await import('../core/session/SessionStore.js');
81
+ const sessionStore = new SessionStore();
82
+ const existing = await sessionStore.loadSession(sessionId);
83
+ if (existing) {
84
+ logger.debug('[codemie-code] Session file already exists');
85
+ return;
86
+ }
87
+ const agentName = env.CODEMIE_AGENT || 'codemie-code';
88
+ const provider = env.CODEMIE_PROVIDER || 'unknown';
89
+ const project = env.CODEMIE_PROJECT;
90
+ const workingDirectory = process.cwd();
91
+ let gitBranch;
92
+ try {
93
+ const { detectGitBranch } = await import('../../utils/processes.js');
94
+ gitBranch = await detectGitBranch(workingDirectory);
95
+ }
96
+ catch {
97
+ // Git detection optional
98
+ }
99
+ const estimatedStartTime = Date.now() - 2000;
100
+ const session = {
101
+ sessionId,
102
+ agentName,
103
+ provider,
104
+ ...(project && { project }),
105
+ startTime: estimatedStartTime,
106
+ workingDirectory,
107
+ ...(gitBranch && { gitBranch }),
108
+ status: 'completed',
109
+ activeDurationMs: 0,
110
+ correlation: {
111
+ status: 'matched',
112
+ agentSessionId: 'unknown',
113
+ retryCount: 0
114
+ }
115
+ };
116
+ await sessionStore.saveSession(session);
117
+ logger.debug('[codemie-code] Created session metadata file');
118
+ }
119
+ catch (error) {
120
+ logger.warn('[codemie-code] Failed to create session file:', error);
121
+ }
122
+ }
123
+ /**
124
+ * Map user-facing provider name to OpenCode's internal provider identifier.
125
+ */
126
+ function determineActiveProvider(provider) {
127
+ if (provider === 'ollama')
128
+ return 'ollama';
129
+ if (provider === 'bedrock')
130
+ return 'amazon-bedrock';
131
+ return 'codemie-proxy';
132
+ }
133
+ /**
134
+ * Get the base storage path for OpenCode sessions.
135
+ * Used by both beforeRun (XDG_DATA_HOME) and onSessionEnd (OPENCODE_STORAGE_PATH).
136
+ */
137
+ function getOpenCodeStorageBase() {
138
+ return join(getCodemieHome(), 'opencode-storage');
139
+ }
140
+ /**
141
+ * Build a hook config object from environment variables.
142
+ * Used by both onSessionStart and onSessionEnd lifecycle hooks.
143
+ */
144
+ function buildHookConfig(env, sessionId) {
145
+ return {
146
+ agentName: env.CODEMIE_AGENT || BUILTIN_AGENT_NAME,
147
+ sessionId,
148
+ provider: env.CODEMIE_PROVIDER,
149
+ apiBaseUrl: env.CODEMIE_BASE_URL,
150
+ ssoUrl: env.CODEMIE_URL,
151
+ version: env.CODEMIE_CLI_VERSION,
152
+ profileName: env.CODEMIE_PROFILE_NAME,
153
+ project: env.CODEMIE_PROJECT,
154
+ model: env.CODEMIE_MODEL,
155
+ clientType: 'codemie-code',
156
+ };
157
+ }
158
+ /**
159
+ * Normalize the Ollama base URL to include /v1 suffix.
160
+ * Non-ollama providers get the default localhost URL.
161
+ */
162
+ function resolveOllamaBaseUrl(baseUrl, provider) {
163
+ if (provider !== 'ollama')
164
+ return 'http://localhost:11434/v1';
165
+ if (baseUrl.endsWith('/v1') || baseUrl.includes('/v1/'))
166
+ return baseUrl;
167
+ return `${baseUrl.replace(/\/$/, '')}/v1`;
168
+ }
14
169
  /**
15
- * CodeMie-Code Plugin Metadata
170
+ * Build the OpenCode config object that gets passed to the whitelabel binary.
171
+ */
172
+ function buildOpenCodeConfig(params) {
173
+ return {
174
+ enabled_providers: ['codemie-proxy', 'ollama', 'amazon-bedrock'],
175
+ share: 'disabled',
176
+ provider: {
177
+ ...(params.proxyBaseUrl && {
178
+ 'codemie-proxy': {
179
+ npm: '@ai-sdk/openai-compatible',
180
+ name: 'CodeMie SSO',
181
+ options: {
182
+ baseURL: `${params.proxyBaseUrl}/`,
183
+ apiKey: 'proxy-handled',
184
+ timeout: params.timeout,
185
+ ...(params.providerOptions?.headers && { headers: params.providerOptions.headers })
186
+ },
187
+ models: params.allModels
188
+ }
189
+ }),
190
+ ollama: {
191
+ npm: '@ai-sdk/openai-compatible',
192
+ name: 'Ollama',
193
+ options: {
194
+ baseURL: `${params.ollamaBaseUrl}/`,
195
+ apiKey: 'ollama',
196
+ timeout: params.timeout,
197
+ }
198
+ }
199
+ },
200
+ model: `${params.activeProvider}/${params.modelId}`
201
+ };
202
+ }
203
+ // Resolve binary at load time, fallback to 'codemie'
204
+ const resolvedBinary = resolveCodemieOpenCodeBinary();
205
+ /**
206
+ * Environment variable contract between the umbrella CLI and whitelabel binary.
207
+ *
208
+ * The umbrella CLI orchestrates everything (proxy, auth, metrics, session sync)
209
+ * and spawns the whitelabel binary as a child process. The whitelabel knows
210
+ * nothing about SSO, cookies, or metrics — it just sees an OpenAI-compatible
211
+ * endpoint at localhost.
212
+ *
213
+ * Flow: BaseAgentAdapter.run() → setupProxy() → beforeRun hook → spawn(binary)
214
+ *
215
+ * | Env Var | Set By | Consumed By | Purpose |
216
+ * |--------------------------|----------------------|----------------------|------------------------------------------------|
217
+ * | OPENCODE_CONFIG_CONTENT | beforeRun hook | Whitelabel config.ts | Full provider config JSON (proxy URL, models) |
218
+ * | OPENCODE_CONFIG | beforeRun (fallback) | Whitelabel config.ts | Temp file path when JSON exceeds env var limit |
219
+ * | OPENCODE_DISABLE_SHARE | beforeRun hook | Whitelabel | Disables share functionality |
220
+ * | CODEMIE_SESSION_ID | BaseAgentAdapter | onSessionEnd hook | Session ID for metrics correlation |
221
+ * | CODEMIE_AGENT | BaseAgentAdapter | Lifecycle helpers | Agent name ('codemie-code') |
222
+ * | CODEMIE_PROVIDER | Config loader | setupProxy() | Provider name (e.g., 'ai-run-sso') |
223
+ * | CODEMIE_BASE_URL | setupProxy() | beforeRun hook | Proxy URL (http://localhost:{port}) |
224
+ * | CODEMIE_MODEL | Config/CLI | beforeRun hook | Selected model ID |
225
+ * | CODEMIE_PROJECT | SSO exportEnvVars | Session metadata | CodeMie project name |
16
226
  */
17
227
  export const CodeMieCodePluginMetadata = {
18
228
  name: BUILTIN_AGENT_NAME,
19
- displayName: 'CodeMie Native',
20
- description: 'Built-in LangGraph-based coding assistant',
21
- npmPackage: null, // Built-in
22
- cliCommand: null, // No external CLI
23
- envMapping: {},
24
- supportedProviders: ['ollama', 'litellm', 'ai-run-sso'],
25
- blockedModelPatterns: [],
26
- // Built-in agent doesn't use proxy (handles auth internally)
27
- ssoConfig: undefined,
229
+ displayName: 'CodeMie Code',
230
+ description: 'CodeMie Code - AI coding assistant',
231
+ npmPackage: '@codemieai/codemie-opencode',
232
+ cliCommand: resolvedBinary || null,
233
+ dataPaths: {
234
+ home: '.opencode'
235
+ },
236
+ ownedSubcommands: OPENCODE_SUBCOMMANDS,
28
237
  customOptions: [
29
238
  { flags: '--task <task>', description: 'Execute a single task and exit' },
30
239
  { flags: '--debug', description: 'Enable debug logging' },
@@ -32,66 +241,57 @@ export const CodeMieCodePluginMetadata = {
32
241
  { flags: '--plan-only', description: 'Plan without execution' }
33
242
  ],
34
243
  isBuiltIn: true,
35
- // Custom handler for built-in agent
36
- customRunHandler: async (args, options) => {
244
+ // Custom handler for built-in agent.
245
+ // Receives the original (pre-enrichArgs) args from BaseAgentAdapter so that
246
+ // --task, --debug, --plan, --plan-only can be parsed reliably.
247
+ // The `options` parameter is always {} (reserved); args parsing is authoritative.
248
+ customRunHandler: async (args, _options, agentConfig) => {
37
249
  try {
38
250
  // Check if we have a valid configuration first
39
251
  const workingDir = process.cwd();
40
- let config;
252
+ // Use profile from AgentConfig (set by BaseAgentAdapter from CODEMIE_PROFILE_NAME)
253
+ // or fall back to environment variable set by AgentCLI
254
+ const profileName = agentConfig?.profileName || process.env.CODEMIE_PROFILE_NAME;
41
255
  try {
42
- config = await loadCodeMieConfig(workingDir);
256
+ await loadCodeMieConfig(workingDir, profileName ? { name: profileName } : undefined);
43
257
  }
44
258
  catch (error) {
45
259
  const errorMessage = error instanceof Error ? error.message : String(error);
46
260
  logger.error('Configuration loading failed:', errorMessage);
47
261
  throw new Error(`CodeMie configuration required: ${errorMessage}. Please run: codemie setup`);
48
262
  }
49
- // Show welcome message with session info
50
- // Read from environment variables (same as BaseAgentAdapter)
51
- const profileName = process.env.CODEMIE_PROFILE_NAME || config.name || 'default';
52
- const provider = process.env.CODEMIE_PROVIDER || config.displayProvider || config.provider;
53
- const model = process.env.CODEMIE_MODEL || config.model;
54
- const codeMieUrl = process.env.CODEMIE_URL || config.codeMieUrl;
55
- const sessionId = process.env.CODEMIE_SESSION_ID || 'n/a';
56
- const cliVersion = process.env.CODEMIE_CLI_VERSION || 'unknown';
57
- console.log(renderProfileInfo({
58
- profile: profileName,
59
- provider,
60
- model,
61
- codeMieUrl,
62
- agent: BUILTIN_AGENT_NAME,
63
- cliVersion,
64
- sessionId
65
- }));
66
- // Show random welcome message
67
- console.log(chalk.cyan.bold(getRandomWelcomeMessage()));
68
- console.log(''); // Empty line for spacing
263
+ // Welcome/goodbye messages are shown by BaseAgentAdapter (which invokes this handler).
264
+ // Parse agent-specific flags from original args (--debug, --task, --plan, --plan-only).
265
+ const debug = args.includes('--debug');
266
+ const taskIdx = args.indexOf('--task');
267
+ const task = taskIdx !== -1 && taskIdx < args.length - 1 ? args[taskIdx + 1] : undefined;
268
+ const plan = args.includes('--plan');
269
+ const planOnly = args.includes('--plan-only');
270
+ // Remaining args (excluding known flags and --task value) are treated as a prompt
271
+ const knownFlags = new Set(['--debug', '--task', '--plan', '--plan-only']);
272
+ const promptArgs = args.filter((a, i) => {
273
+ if (knownFlags.has(a))
274
+ return false;
275
+ if (i > 0 && args[i - 1] === '--task')
276
+ return false;
277
+ return true;
278
+ });
69
279
  const codeMie = new CodeMieCode(workingDir);
70
- await codeMie.initialize({ debug: options.debug });
71
- try {
72
- if (options.task) {
73
- await codeMie.executeTaskWithUI(options.task, {
74
- planMode: (options.plan || options.planOnly),
75
- planOnly: options.planOnly
76
- });
77
- }
78
- else if (args.length > 0) {
79
- await codeMie.executeTaskWithUI(args.join(' '));
80
- if (!options.planOnly) {
81
- await codeMie.startInteractive();
82
- }
83
- }
84
- else {
280
+ await codeMie.initialize({ debug: debug });
281
+ if (task) {
282
+ await codeMie.executeTaskWithUI(task, {
283
+ planMode: (plan || planOnly),
284
+ planOnly: planOnly
285
+ });
286
+ }
287
+ else if (promptArgs.length > 0) {
288
+ await codeMie.executeTaskWithUI(promptArgs.join(' '));
289
+ if (!planOnly) {
85
290
  await codeMie.startInteractive();
86
291
  }
87
292
  }
88
- finally {
89
- // Show goodbye message
90
- console.log(''); // Empty line for spacing
91
- console.log(chalk.cyan.bold(getRandomGoodbyeMessage()));
92
- console.log(''); // Spacing before powered by
93
- console.log(chalk.cyan('Powered by AI/Run CodeMie CLI'));
94
- console.log(''); // Empty line for spacing
293
+ else {
294
+ await codeMie.startInteractive();
95
295
  }
96
296
  }
97
297
  catch (error) {
@@ -99,84 +299,261 @@ export const CodeMieCodePluginMetadata = {
99
299
  throw new Error(`Failed to run CodeMie Native: ${errorMessage}`);
100
300
  }
101
301
  },
102
- customHealthCheck: async () => {
103
- const result = await CodeMieCode.testConnection(process.cwd());
104
- if (result.success) {
105
- logger.success('CodeMie Native is healthy');
106
- console.log(`Provider: ${result.provider || 'unknown'}`);
107
- console.log(`Model: ${result.model || 'unknown'}`);
108
- return true;
109
- }
110
- else {
111
- logger.error('Health check failed:', result.error);
112
- return false;
302
+ envMapping: {
303
+ baseUrl: [],
304
+ apiKey: [],
305
+ model: []
306
+ },
307
+ supportedProviders: ['litellm', 'ai-run-sso', 'ollama', 'bedrock', 'bearer-auth'],
308
+ ssoConfig: { enabled: true, clientType: 'codemie-code' },
309
+ lifecycle: {
310
+ async onSessionStart(sessionId, env) {
311
+ try {
312
+ const { processEvent } = await import('../../cli/commands/hook.js');
313
+ const event = {
314
+ hook_event_name: 'SessionStart',
315
+ session_id: sessionId,
316
+ transcript_path: '',
317
+ permission_mode: 'default',
318
+ cwd: process.cwd(),
319
+ source: 'startup',
320
+ };
321
+ await processEvent(event, buildHookConfig(env, sessionId));
322
+ logger.info(`[codemie-code] SessionStart hook completed for session ${sessionId}`);
323
+ }
324
+ catch (error) {
325
+ const msg = error instanceof Error ? error.message : String(error);
326
+ logger.error(`[codemie-code] SessionStart hook failed (non-blocking): ${msg}`);
327
+ }
328
+ },
329
+ async beforeRun(env, config) {
330
+ const sessionId = env.CODEMIE_SESSION_ID;
331
+ if (sessionId) {
332
+ // ensureSessionFile handles its own errors internally
333
+ await ensureSessionFile(sessionId, env);
334
+ }
335
+ const provider = env.CODEMIE_PROVIDER;
336
+ const baseUrl = env.CODEMIE_BASE_URL;
337
+ if (!baseUrl) {
338
+ return env;
339
+ }
340
+ if (!baseUrl.startsWith('http://') && !baseUrl.startsWith('https://')) {
341
+ logger.warn(`Invalid CODEMIE_BASE_URL format: ${baseUrl}`, { agent: 'codemie-code' });
342
+ return env;
343
+ }
344
+ const selectedModel = env.CODEMIE_MODEL || config?.model || 'gpt-5-2-2025-12-11';
345
+ const modelConfig = getModelConfig(selectedModel);
346
+ const { providerOptions } = modelConfig;
347
+ const allModels = getAllOpenCodeModelConfigs();
348
+ const isBedrock = provider === 'bedrock';
349
+ const proxyBaseUrl = provider !== 'ollama' && !isBedrock ? baseUrl : undefined;
350
+ const ollamaBaseUrl = resolveOllamaBaseUrl(baseUrl, provider);
351
+ const activeProvider = determineActiveProvider(provider);
352
+ const timeout = providerOptions?.timeout ?? parseInt(env.CODEMIE_TIMEOUT || '600') * 1000;
353
+ const modelId = isBedrock
354
+ ? toBedrockModelId(modelConfig.id, env.AWS_REGION || env.CODEMIE_AWS_REGION)
355
+ : modelConfig.id;
356
+ const openCodeConfig = buildOpenCodeConfig({
357
+ proxyBaseUrl, ollamaBaseUrl, activeProvider, modelId, timeout, providerOptions, allModels
358
+ });
359
+ // --- Hooks injection ---
360
+ // 1. Build default hooks (always present for session tracking + metrics)
361
+ const defaultHooks = {
362
+ SessionStart: [{ hooks: [{ type: 'command', command: 'codemie hook', timeout: 5 }] }],
363
+ SessionEnd: [{ hooks: [{ type: 'command', command: 'codemie hook', timeout: 10 }] }],
364
+ };
365
+ // 2. Merge profile hooks on top of defaults
366
+ let mergedHooks = { ...defaultHooks };
367
+ if (env.CODEMIE_PROFILE_CONFIG) {
368
+ try {
369
+ const profileConfig = JSON.parse(env.CODEMIE_PROFILE_CONFIG);
370
+ if (profileConfig.hooks && typeof profileConfig.hooks === 'object') {
371
+ mergedHooks = { ...defaultHooks, ...profileConfig.hooks };
372
+ logger.debug('[codemie-code] Merged profile hooks with defaults');
373
+ }
374
+ }
375
+ catch {
376
+ // Non-critical — profile config parse failure doesn't block startup
377
+ }
378
+ }
379
+ env.OPENCODE_HOOKS = JSON.stringify({ hooks: mergedHooks });
380
+ // 3. Always inject shell-hooks plugin
381
+ const pluginUrl = getHooksPluginFileUrl();
382
+ openCodeConfig.plugin = openCodeConfig.plugin || [];
383
+ openCodeConfig.plugin.push(pluginUrl);
384
+ logger.debug(`[codemie-code] Injected hooks plugin: ${pluginUrl}`);
385
+ // --- Storage path configuration ---
386
+ // Configure storage path for OpenCode sessions
387
+ // This ensures codemie-opencode writes sessions to a location we can discover
388
+ // OpenCode will use: ${XDG_DATA_HOME}/opencode/storage/
389
+ // Which becomes: ~/.codemie/opencode-storage/opencode/storage/
390
+ env.XDG_DATA_HOME = getOpenCodeStorageBase();
391
+ logger.debug(`[codemie-code] Setting XDG_DATA_HOME=${env.XDG_DATA_HOME} for OpenCode sessions`);
392
+ env.OPENCODE_DISABLE_SHARE = 'true';
393
+ const configJson = JSON.stringify(openCodeConfig);
394
+ if (configJson.length > MAX_ENV_SIZE) {
395
+ logger.warn(`Config size (${configJson.length} bytes) exceeds env var limit (${MAX_ENV_SIZE}), using temp file fallback`, {
396
+ agent: 'codemie-code'
397
+ });
398
+ const configPath = writeConfigToTempFile(configJson);
399
+ logger.debug(`[codemie-code] Wrote config to temp file: ${configPath}`);
400
+ env.OPENCODE_CONFIG = configPath;
401
+ return env;
402
+ }
403
+ env.OPENCODE_CONFIG_CONTENT = configJson;
404
+ return env;
405
+ },
406
+ enrichArgs: (args, _config) => {
407
+ if (args.length > 0 && OPENCODE_SUBCOMMANDS.includes(args[0])) {
408
+ return args;
409
+ }
410
+ const taskIndex = args.indexOf('--task');
411
+ if (taskIndex !== -1 && taskIndex < args.length - 1) {
412
+ const taskValue = args[taskIndex + 1];
413
+ const otherArgs = args.filter((arg, i, arr) => {
414
+ if (i === taskIndex || i === taskIndex + 1)
415
+ return false;
416
+ if (arg === '-m' || arg === '--message')
417
+ return false;
418
+ if (i > 0 && (arr[i - 1] === '-m' || arr[i - 1] === '--message'))
419
+ return false;
420
+ return true;
421
+ });
422
+ return ['run', ...otherArgs, taskValue];
423
+ }
424
+ return args;
425
+ },
426
+ async onSessionEnd(exitCode, env) {
427
+ const sessionId = env.CODEMIE_SESSION_ID;
428
+ if (!sessionId) {
429
+ logger.debug('[codemie-code] No CODEMIE_SESSION_ID in environment, skipping session end');
430
+ return;
431
+ }
432
+ try {
433
+ // 1. Discover OpenCode session for transcript_path (best effort)
434
+ // Set OPENCODE_STORAGE_PATH so getOpenCodeStoragePath() resolves to the
435
+ // same location that beforeRun configured via XDG_DATA_HOME on the child process.
436
+ const expectedStoragePath = join(getOpenCodeStorageBase(), 'opencode', 'storage');
437
+ process.env.OPENCODE_STORAGE_PATH = expectedStoragePath;
438
+ let transcriptPath = '';
439
+ try {
440
+ const adapter = new OpenCodeSessionAdapter(CodeMieCodePluginMetadata);
441
+ const sessions = await adapter.discoverSessions({ maxAgeDays: 1 });
442
+ if (sessions.length > 0) {
443
+ transcriptPath = sessions[0].filePath;
444
+ logger.debug(`[codemie-code] Discovered OpenCode session: ${sessions[0].sessionId}`);
445
+ }
446
+ else {
447
+ logger.debug('[codemie-code] No recent OpenCode sessions found');
448
+ }
449
+ }
450
+ catch (discoverError) {
451
+ const msg = discoverError instanceof Error ? discoverError.message : String(discoverError);
452
+ logger.debug(`[codemie-code] Session discovery failed (non-blocking): ${msg}`);
453
+ }
454
+ // 2. Route through processEvent for full SessionEnd pipeline:
455
+ // accumulateActiveDuration → incrementalSync → syncToAPI →
456
+ // sendSessionEndMetrics → updateStatus → renameFiles
457
+ const { processEvent } = await import('../../cli/commands/hook.js');
458
+ const event = {
459
+ hook_event_name: 'SessionEnd',
460
+ session_id: sessionId,
461
+ transcript_path: transcriptPath,
462
+ permission_mode: 'default',
463
+ cwd: process.cwd(),
464
+ reason: exitCode === 0 ? 'exit' : `exit(${exitCode})`,
465
+ };
466
+ await processEvent(event, buildHookConfig(env, sessionId));
467
+ logger.info(`[codemie-code] SessionEnd hook completed for session ${sessionId}`);
468
+ }
469
+ catch (error) {
470
+ const errorMessage = error instanceof Error ? error.message : String(error);
471
+ logger.error(`[codemie-code] SessionEnd hook failed (non-blocking): ${errorMessage}`);
472
+ }
473
+ finally {
474
+ delete process.env.OPENCODE_STORAGE_PATH;
475
+ cleanupHooksPlugin();
476
+ }
113
477
  }
114
478
  }
115
479
  };
116
480
  /**
117
- * CodeMie-Code Adapter
118
- * Custom implementation for built-in agent
481
+ * CodeMie Code Plugin
482
+ * Wraps the @codemieai/codemie-opencode binary as the built-in agent
119
483
  */
120
- export class CodeMieCodePlugin {
121
- name = BUILTIN_AGENT_NAME;
122
- displayName = 'CodeMie Native';
123
- description = 'CodeMie Native Agent - Built-in LangGraph-based coding assistant';
124
- async install() {
125
- logger.info('CodeMie Native is built-in and already available');
126
- }
127
- async uninstall() {
128
- logger.info('CodeMie Native is built-in and cannot be uninstalled');
484
+ export class CodeMieCodePlugin extends BaseAgentAdapter {
485
+ sessionAdapter;
486
+ constructor() {
487
+ super(CodeMieCodePluginMetadata);
488
+ this.sessionAdapter = new OpenCodeSessionAdapter(CodeMieCodePluginMetadata);
129
489
  }
490
+ /**
491
+ * Check if the agent is available.
492
+ * Returns true if the whitelabel binary is present, OR if only the built-in
493
+ * CodeMieCode handler is available (always the case when isBuiltIn: true).
494
+ * Warns at log level when the binary is absent so the condition is surfaced
495
+ * by doctor checks and debug sessions rather than silently swallowed.
496
+ */
130
497
  async isInstalled() {
498
+ const binaryPath = resolveCodemieOpenCodeBinary();
499
+ if (!binaryPath) {
500
+ // Binary not found in node_modules — falling back to built-in CodeMieCode handler
501
+ logger.warn('[codemie-code] Whitelabel binary not found — running built-in CodeMieCode handler as fallback');
502
+ logger.warn('[codemie-code] Install the binary with: npm i -g @codemieai/codemie-opencode');
503
+ return true; // Built-in handler is always available
504
+ }
505
+ const installed = existsSync(binaryPath);
506
+ if (!installed) {
507
+ // Binary path resolved at load time but the file is now missing
508
+ logger.warn('[codemie-code] Binary path resolved but file not found — running built-in CodeMieCode handler as fallback');
509
+ logger.warn('[codemie-code] Reinstall with: codemie install codemie-code');
510
+ }
511
+ // Binary present (use it) or absent (fall back to built-in handler)
131
512
  return true;
132
513
  }
133
- async run(args, envOverrides) {
134
- // Set environment variables if provided
135
- if (envOverrides) {
136
- Object.assign(process.env, envOverrides);
137
- }
138
- // Parse options from args
139
- const options = {};
140
- const filteredArgs = [];
141
- for (let i = 0; i < args.length; i++) {
142
- const arg = args[i];
143
- if (arg === '--task' && args[i + 1]) {
144
- options.task = args[i + 1];
145
- i++; // Skip next arg
146
- }
147
- else if (arg === '--debug') {
148
- options.debug = true;
149
- }
150
- else if (arg === '--plan') {
151
- options.plan = true;
152
- }
153
- else if (arg === '--plan-only') {
154
- options.planOnly = true;
514
+ /**
515
+ * Install the whitelabel package globally.
516
+ */
517
+ async install() {
518
+ await installGlobal('@codemieai/codemie-opencode');
519
+ }
520
+ /**
521
+ * Uninstall the whitelabel package and its platform-specific binary.
522
+ *
523
+ * npm hoists the platform-specific binary package (e.g.
524
+ * @codemieai/codemie-opencode-darwin-arm64) to the top-level global
525
+ * node_modules. `npm uninstall -g @codemieai/codemie-opencode` only removes
526
+ * the wrapper, leaving the binary as an orphan. We explicitly remove both.
527
+ */
528
+ async uninstall() {
529
+ await uninstallGlobal('@codemieai/codemie-opencode');
530
+ const platformPkg = getPlatformPackage();
531
+ if (platformPkg) {
532
+ try {
533
+ await uninstallGlobal(platformPkg);
155
534
  }
156
- else {
157
- filteredArgs.push(arg);
535
+ catch {
536
+ // Platform package may not be hoisted separately — ignore
537
+ logger.debug(`[codemie-code] Platform package ${platformPkg} was not installed separately`);
158
538
  }
159
539
  }
160
- if (!options.debug && logger.isDebugMode()) {
161
- options.debug = true;
162
- }
163
- if (CodeMieCodePluginMetadata.customRunHandler) {
164
- await CodeMieCodePluginMetadata.customRunHandler(filteredArgs, options, {});
540
+ // Verify the binary is actually gone
541
+ const remaining = resolveCodemieOpenCodeBinary();
542
+ if (remaining) {
543
+ logger.warn(`[codemie-code] Binary still found after uninstall: ${remaining}`);
544
+ logger.warn('[codemie-code] You may need to manually remove it');
165
545
  }
166
546
  }
167
- async getVersion() {
168
- try {
169
- const packageJsonPath = join(getDirname(import.meta.url), '../../../package.json');
170
- const packageJsonContent = readFileSync(packageJsonPath, 'utf-8');
171
- const packageJson = JSON.parse(packageJsonContent);
172
- return `v${packageJson.version} (built-in)`;
173
- }
174
- catch {
175
- return 'unknown (built-in)';
176
- }
547
+ /**
548
+ * Return session adapter for analytics.
549
+ */
550
+ getSessionAdapter() {
551
+ return this.sessionAdapter;
177
552
  }
178
- getMetricsConfig() {
179
- // Built-in agent doesn't have specific metrics config
553
+ /**
554
+ * No extension installer needed.
555
+ */
556
+ getExtensionInstaller() {
180
557
  return undefined;
181
558
  }
182
559
  }