@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.
- package/README.md +5 -6
- package/bin/codemie-opencode.js +8 -1
- package/dist/agents/codemie-code/agent.d.ts.map +1 -1
- package/dist/agents/codemie-code/agent.js +5 -0
- package/dist/agents/codemie-code/agent.js.map +1 -1
- package/dist/agents/codemie-code/skills/index.d.ts +4 -0
- package/dist/agents/codemie-code/skills/index.d.ts.map +1 -1
- package/dist/agents/codemie-code/skills/index.js +4 -0
- package/dist/agents/codemie-code/skills/index.js.map +1 -1
- package/dist/agents/codemie-code/skills/sync/SkillSync.d.ts +52 -0
- package/dist/agents/codemie-code/skills/sync/SkillSync.d.ts.map +1 -0
- package/dist/agents/codemie-code/skills/sync/SkillSync.js +165 -0
- package/dist/agents/codemie-code/skills/sync/SkillSync.js.map +1 -0
- package/dist/agents/core/AgentCLI.d.ts.map +1 -1
- package/dist/agents/core/AgentCLI.js +38 -8
- package/dist/agents/core/AgentCLI.js.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.d.ts +11 -1
- package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.js +175 -18
- package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
- package/dist/agents/core/types.d.ts +18 -0
- package/dist/agents/core/types.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude-acp.plugin.d.ts +7 -0
- package/dist/agents/plugins/claude/claude-acp.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude-acp.plugin.js +10 -0
- package/dist/agents/plugins/claude/claude-acp.plugin.js.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin-installer.d.ts +11 -0
- package/dist/agents/plugins/claude/claude.plugin-installer.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin-installer.js +32 -0
- package/dist/agents/plugins/claude/claude.plugin-installer.js.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.d.ts +1 -8
- package/dist/agents/plugins/claude/claude.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/claude/claude.plugin.js +96 -101
- package/dist/agents/plugins/claude/claude.plugin.js.map +1 -1
- package/dist/agents/plugins/claude/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/agents/plugins/claude/plugin/codemie-statusline.mjs +42 -0
- package/dist/agents/plugins/claude/plugin/hooks/hooks.json +10 -0
- package/dist/agents/plugins/claude/plugin/hooks/hooks.windows.json +98 -0
- package/dist/agents/plugins/claude/plugin/scripts/bash/rtk-auto-wrapper.sh +81 -0
- package/dist/agents/plugins/claude/plugin/scripts/bash/rtk-baseline.sh +39 -0
- package/dist/agents/plugins/claude/sounds-installer.d.ts.map +1 -1
- package/dist/agents/plugins/claude/sounds-installer.js +0 -4
- package/dist/agents/plugins/claude/sounds-installer.js.map +1 -1
- package/dist/agents/plugins/codemie-code-binary.d.ts +17 -0
- package/dist/agents/plugins/codemie-code-binary.d.ts.map +1 -0
- package/dist/agents/plugins/codemie-code-binary.js +94 -0
- package/dist/agents/plugins/codemie-code-binary.js.map +1 -0
- package/dist/agents/plugins/codemie-code-hooks/index.d.ts +3 -0
- package/dist/agents/plugins/codemie-code-hooks/index.d.ts.map +1 -0
- package/dist/agents/plugins/codemie-code-hooks/index.js +3 -0
- package/dist/agents/plugins/codemie-code-hooks/index.js.map +1 -0
- package/dist/agents/plugins/codemie-code-hooks/inject-hooks.d.ts +22 -0
- package/dist/agents/plugins/codemie-code-hooks/inject-hooks.d.ts.map +1 -0
- package/dist/agents/plugins/codemie-code-hooks/inject-hooks.js +64 -0
- package/dist/agents/plugins/codemie-code-hooks/inject-hooks.js.map +1 -0
- package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.d.ts +15 -0
- package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.d.ts.map +1 -0
- package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.js +522 -0
- package/dist/agents/plugins/codemie-code-hooks/shell-hooks-source.js.map +1 -0
- package/dist/agents/plugins/codemie-code.plugin.d.ts +56 -12
- package/dist/agents/plugins/codemie-code.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/codemie-code.plugin.js +502 -125
- package/dist/agents/plugins/codemie-code.plugin.js.map +1 -1
- package/dist/agents/plugins/gemini/gemini.plugin.d.ts +8 -0
- package/dist/agents/plugins/gemini/gemini.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/gemini/gemini.plugin.js +45 -1
- package/dist/agents/plugins/gemini/gemini.plugin.js.map +1 -1
- package/dist/agents/plugins/opencode/opencode-message-types.d.ts +2 -0
- package/dist/agents/plugins/opencode/opencode-message-types.d.ts.map +1 -1
- package/dist/agents/plugins/opencode/opencode-message-types.js.map +1 -1
- package/dist/agents/plugins/opencode/opencode-model-configs.d.ts +12 -2
- package/dist/agents/plugins/opencode/opencode-model-configs.d.ts.map +1 -1
- package/dist/agents/plugins/opencode/opencode-model-configs.js +329 -24
- package/dist/agents/plugins/opencode/opencode-model-configs.js.map +1 -1
- package/dist/agents/plugins/opencode/opencode.paths.d.ts +16 -1
- package/dist/agents/plugins/opencode/opencode.paths.d.ts.map +1 -1
- package/dist/agents/plugins/opencode/opencode.paths.js +43 -5
- package/dist/agents/plugins/opencode/opencode.paths.js.map +1 -1
- package/dist/agents/plugins/opencode/opencode.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/opencode/opencode.plugin.js +91 -25
- package/dist/agents/plugins/opencode/opencode.plugin.js.map +1 -1
- package/dist/agents/plugins/opencode/opencode.session.d.ts +5 -0
- package/dist/agents/plugins/opencode/opencode.session.d.ts.map +1 -1
- package/dist/agents/plugins/opencode/opencode.session.js +99 -2
- package/dist/agents/plugins/opencode/opencode.session.js.map +1 -1
- package/dist/agents/plugins/opencode/opencode.sqlite-reader.d.ts +59 -0
- package/dist/agents/plugins/opencode/opencode.sqlite-reader.d.ts.map +1 -0
- package/dist/agents/plugins/opencode/opencode.sqlite-reader.js +200 -0
- package/dist/agents/plugins/opencode/opencode.sqlite-reader.js.map +1 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.d.ts +3 -0
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.d.ts.map +1 -1
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.js +35 -13
- package/dist/agents/plugins/opencode/session/processors/opencode.metrics-processor.js.map +1 -1
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +8 -7
- package/dist/agents/registry.js.map +1 -1
- package/dist/cli/commands/analytics/data-loader.js +1 -1
- package/dist/cli/commands/analytics/data-loader.js.map +1 -1
- package/dist/cli/commands/doctor/checks/AgentsCheck.d.ts.map +1 -1
- package/dist/cli/commands/doctor/checks/AgentsCheck.js +5 -2
- package/dist/cli/commands/doctor/checks/AgentsCheck.js.map +1 -1
- package/dist/cli/commands/doctor/checks/FrameworksCheck.d.ts.map +1 -1
- package/dist/cli/commands/doctor/checks/FrameworksCheck.js +5 -2
- package/dist/cli/commands/doctor/checks/FrameworksCheck.js.map +1 -1
- package/dist/cli/commands/doctor/checks/JWTAuthCheck.d.ts +9 -0
- package/dist/cli/commands/doctor/checks/JWTAuthCheck.d.ts.map +1 -0
- package/dist/cli/commands/doctor/checks/JWTAuthCheck.js +113 -0
- package/dist/cli/commands/doctor/checks/JWTAuthCheck.js.map +1 -0
- package/dist/cli/commands/doctor/checks/index.d.ts +1 -0
- package/dist/cli/commands/doctor/checks/index.d.ts.map +1 -1
- package/dist/cli/commands/doctor/checks/index.js +1 -0
- package/dist/cli/commands/doctor/checks/index.js.map +1 -1
- package/dist/cli/commands/doctor/index.d.ts.map +1 -1
- package/dist/cli/commands/doctor/index.js +2 -1
- package/dist/cli/commands/doctor/index.js.map +1 -1
- package/dist/cli/commands/hook.d.ts.map +1 -1
- package/dist/cli/commands/hook.js +28 -5
- package/dist/cli/commands/hook.js.map +1 -1
- package/dist/cli/commands/skill.d.ts.map +1 -1
- package/dist/cli/commands/skill.js +80 -1
- package/dist/cli/commands/skill.js.map +1 -1
- package/dist/cli/commands/test-metrics.d.ts +17 -0
- package/dist/cli/commands/test-metrics.d.ts.map +1 -0
- package/dist/cli/commands/test-metrics.js +198 -0
- package/dist/cli/commands/test-metrics.js.map +1 -0
- package/dist/cli/index.js +9 -13
- package/dist/cli/index.js.map +1 -1
- package/dist/env/types.d.ts +12 -2
- package/dist/env/types.d.ts.map +1 -1
- package/dist/env/types.js.map +1 -1
- package/dist/providers/core/types.d.ts +22 -1
- package/dist/providers/core/types.d.ts.map +1 -1
- package/dist/providers/core/types.js +12 -1
- package/dist/providers/core/types.js.map +1 -1
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/integration/setup-ui.d.ts.map +1 -1
- package/dist/providers/integration/setup-ui.js +3 -1
- package/dist/providers/integration/setup-ui.js.map +1 -1
- package/dist/providers/plugins/jwt/index.d.ts +9 -0
- package/dist/providers/plugins/jwt/index.d.ts.map +1 -0
- package/dist/providers/plugins/jwt/index.js +13 -0
- package/dist/providers/plugins/jwt/index.js.map +1 -0
- package/dist/providers/plugins/jwt/jwt.setup-steps.d.ts +9 -0
- package/dist/providers/plugins/jwt/jwt.setup-steps.d.ts.map +1 -0
- package/dist/providers/plugins/jwt/jwt.setup-steps.js +153 -0
- package/dist/providers/plugins/jwt/jwt.setup-steps.js.map +1 -0
- package/dist/providers/plugins/jwt/jwt.template.d.ts +12 -0
- package/dist/providers/plugins/jwt/jwt.template.d.ts.map +1 -0
- package/dist/providers/plugins/jwt/jwt.template.js +55 -0
- package/dist/providers/plugins/jwt/jwt.template.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +3 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js +5 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.d.ts +16 -0
- package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.d.ts.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.js +53 -0
- package/dist/providers/plugins/sso/proxy/plugins/jwt-auth.plugin.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.d.ts +25 -0
- package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.d.ts.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.js +74 -0
- package/dist/providers/plugins/sso/proxy/plugins/request-sanitizer.plugin.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/sso-auth.plugin.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/sso-auth.plugin.js +13 -2
- package/dist/providers/plugins/sso/proxy/plugins/sso-auth.plugin.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/sso.session-sync.plugin.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/sso.session-sync.plugin.js +6 -3
- package/dist/providers/plugins/sso/proxy/plugins/sso.session-sync.plugin.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/types.d.ts +2 -2
- package/dist/providers/plugins/sso/proxy/plugins/types.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/proxy-types.d.ts +2 -0
- package/dist/providers/plugins/sso/proxy/proxy-types.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts +4 -0
- package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/sso.proxy.js +39 -10
- package/dist/providers/plugins/sso/proxy/sso.proxy.js.map +1 -1
- package/dist/providers/plugins/sso/sso.auth.d.ts +3 -1
- package/dist/providers/plugins/sso/sso.auth.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.auth.js +70 -12
- package/dist/providers/plugins/sso/sso.auth.js.map +1 -1
- package/dist/providers/plugins/sso/sso.http-client.d.ts +38 -8
- package/dist/providers/plugins/sso/sso.http-client.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.http-client.js +83 -85
- package/dist/providers/plugins/sso/sso.http-client.js.map +1 -1
- package/dist/providers/plugins/sso/sso.models.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.models.js +3 -3
- package/dist/providers/plugins/sso/sso.models.js.map +1 -1
- package/dist/providers/plugins/sso/sso.setup-steps.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.setup-steps.js +4 -1
- package/dist/providers/plugins/sso/sso.setup-steps.js.map +1 -1
- package/dist/providers/plugins/sso/sso.template.d.ts.map +1 -1
- package/dist/providers/plugins/sso/sso.template.js +7 -0
- package/dist/providers/plugins/sso/sso.template.js.map +1 -1
- package/dist/utils/logger.d.ts +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +16 -1
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/native-installer.d.ts.map +1 -1
- package/dist/utils/native-installer.js +35 -0
- package/dist/utils/native-installer.js.map +1 -1
- package/dist/utils/paths.d.ts +1 -1
- package/dist/utils/paths.js +1 -1
- package/dist/utils/security.d.ts +18 -1
- package/dist/utils/security.d.ts.map +1 -1
- package/dist/utils/security.js +102 -0
- package/dist/utils/security.js.map +1 -1
- package/package.json +2 -1
- 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
|
-
*
|
|
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
|
|
20
|
-
description: '
|
|
21
|
-
npmPackage:
|
|
22
|
-
cliCommand: null,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
50
|
-
//
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
-
|
|
89
|
-
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
118
|
-
*
|
|
481
|
+
* CodeMie Code Plugin
|
|
482
|
+
* Wraps the @codemieai/codemie-opencode binary as the built-in agent
|
|
119
483
|
*/
|
|
120
|
-
export class CodeMieCodePlugin {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
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
|
-
|
|
157
|
-
|
|
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
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
|
|
179
|
-
|
|
553
|
+
/**
|
|
554
|
+
* No extension installer needed.
|
|
555
|
+
*/
|
|
556
|
+
getExtensionInstaller() {
|
|
180
557
|
return undefined;
|
|
181
558
|
}
|
|
182
559
|
}
|