@codemieai/code 0.11.0 → 0.13.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.
- package/README.md +109 -56
- package/bin/codemie-copilot.js +224 -0
- package/bin/codemie-pi.js +18 -0
- package/dist/agents/core/AgentCLI.d.ts.map +1 -1
- package/dist/agents/core/AgentCLI.js +16 -10
- package/dist/agents/core/AgentCLI.js.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.d.ts.map +1 -1
- package/dist/agents/core/BaseAgentAdapter.js +43 -19
- package/dist/agents/core/BaseAgentAdapter.js.map +1 -1
- package/dist/agents/core/agent-aliases.d.ts +17 -0
- package/dist/agents/core/agent-aliases.d.ts.map +1 -0
- package/dist/agents/core/agent-aliases.js +41 -0
- package/dist/agents/core/agent-aliases.js.map +1 -0
- package/dist/agents/core/session/BaseSessionAdapter.d.ts +19 -0
- package/dist/agents/core/session/BaseSessionAdapter.d.ts.map +1 -1
- package/dist/agents/core/session/session-origin-audit.d.ts +13 -0
- package/dist/agents/core/session/session-origin-audit.d.ts.map +1 -1
- package/dist/agents/core/session/session-origin-audit.js +34 -0
- package/dist/agents/core/session/session-origin-audit.js.map +1 -1
- package/dist/agents/core/session/stale-session-reconciliation.d.ts +42 -0
- package/dist/agents/core/session/stale-session-reconciliation.d.ts.map +1 -0
- package/dist/agents/core/session/stale-session-reconciliation.js +141 -0
- package/dist/agents/core/session/stale-session-reconciliation.js.map +1 -0
- package/dist/agents/core/session/types.d.ts +19 -0
- package/dist/agents/core/session/types.d.ts.map +1 -1
- package/dist/agents/core/session/types.js +17 -1
- package/dist/agents/core/session/types.js.map +1 -1
- package/dist/agents/core/types.d.ts +11 -0
- package/dist/agents/core/types.d.ts.map +1 -1
- package/dist/agents/plugins/codex/codex.reconciliation.d.ts +15 -35
- package/dist/agents/plugins/codex/codex.reconciliation.d.ts.map +1 -1
- package/dist/agents/plugins/codex/codex.reconciliation.js +8 -139
- package/dist/agents/plugins/codex/codex.reconciliation.js.map +1 -1
- package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.d.ts +146 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.js +12 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli-event-types.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.constants.d.ts +15 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.constants.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.constants.js +15 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.constants.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.models.d.ts +8 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.models.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.models.js +195 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.models.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.paths.d.ts +11 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.paths.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.paths.js +21 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.paths.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.d.ts +14 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.js +263 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.session.d.ts +43 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.session.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.session.js +343 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.session.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.d.ts +10 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.js +41 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.storage-utils.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.usage.d.ts +37 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.usage.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.usage.js +96 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.usage.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.d.ts +17 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.js +58 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.workspace.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/index.d.ts +3 -0
- package/dist/agents/plugins/copilot-cli/index.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/index.js +3 -0
- package/dist/agents/plugins/copilot-cli/index.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.d.ts +18 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.js +313 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.js.map +1 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.d.ts +16 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.d.ts.map +1 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.js +22 -0
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.metrics-processor.js.map +1 -0
- package/dist/agents/plugins/pi/__tests__/home-redirect.d.ts +12 -0
- package/dist/agents/plugins/pi/__tests__/home-redirect.d.ts.map +1 -0
- package/dist/agents/plugins/pi/__tests__/home-redirect.js +27 -0
- package/dist/agents/plugins/pi/__tests__/home-redirect.js.map +1 -0
- package/dist/agents/plugins/pi/extension/README.md +68 -0
- package/dist/agents/plugins/pi/extension/index.js +161 -0
- package/dist/agents/plugins/pi/extension/package.json +8 -0
- package/dist/agents/plugins/pi/index.d.ts +3 -0
- package/dist/agents/plugins/pi/index.d.ts.map +1 -0
- package/dist/agents/plugins/pi/index.js +3 -0
- package/dist/agents/plugins/pi/index.js.map +1 -0
- package/dist/agents/plugins/pi/pi.extension.d.ts +60 -0
- package/dist/agents/plugins/pi/pi.extension.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.extension.js +201 -0
- package/dist/agents/plugins/pi/pi.extension.js.map +1 -0
- package/dist/agents/plugins/pi/pi.incremental-sync.d.ts +63 -0
- package/dist/agents/plugins/pi/pi.incremental-sync.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.incremental-sync.js +266 -0
- package/dist/agents/plugins/pi/pi.incremental-sync.js.map +1 -0
- package/dist/agents/plugins/pi/pi.models.d.ts +20 -0
- package/dist/agents/plugins/pi/pi.models.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.models.js +201 -0
- package/dist/agents/plugins/pi/pi.models.js.map +1 -0
- package/dist/agents/plugins/pi/pi.packages.d.ts +11 -0
- package/dist/agents/plugins/pi/pi.packages.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.packages.js +35 -0
- package/dist/agents/plugins/pi/pi.packages.js.map +1 -0
- package/dist/agents/plugins/pi/pi.paths.d.ts +37 -0
- package/dist/agents/plugins/pi/pi.paths.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.paths.js +146 -0
- package/dist/agents/plugins/pi/pi.paths.js.map +1 -0
- package/dist/agents/plugins/pi/pi.plugin.d.ts +30 -0
- package/dist/agents/plugins/pi/pi.plugin.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.plugin.js +453 -0
- package/dist/agents/plugins/pi/pi.plugin.js.map +1 -0
- package/dist/agents/plugins/pi/pi.session.d.ts +114 -0
- package/dist/agents/plugins/pi/pi.session.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.session.js +388 -0
- package/dist/agents/plugins/pi/pi.session.js.map +1 -0
- package/dist/agents/plugins/pi/pi.setup.d.ts +2 -0
- package/dist/agents/plugins/pi/pi.setup.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.setup.js +33 -0
- package/dist/agents/plugins/pi/pi.setup.js.map +1 -0
- package/dist/agents/plugins/pi/pi.types.d.ts +143 -0
- package/dist/agents/plugins/pi/pi.types.d.ts.map +1 -0
- package/dist/agents/plugins/pi/pi.types.js +74 -0
- package/dist/agents/plugins/pi/pi.types.js.map +1 -0
- package/dist/agents/plugins/pi/session/pi-file-operations.d.ts +17 -0
- package/dist/agents/plugins/pi/session/pi-file-operations.d.ts.map +1 -0
- package/dist/agents/plugins/pi/session/pi-file-operations.js +98 -0
- package/dist/agents/plugins/pi/session/pi-file-operations.js.map +1 -0
- package/dist/agents/plugins/pi/session/pi-named-invocations.d.ts +52 -0
- package/dist/agents/plugins/pi/session/pi-named-invocations.d.ts.map +1 -0
- package/dist/agents/plugins/pi/session/pi-named-invocations.js +189 -0
- package/dist/agents/plugins/pi/session/pi-named-invocations.js.map +1 -0
- package/dist/agents/plugins/pi/session/pi-user-prompt.d.ts +14 -0
- package/dist/agents/plugins/pi/session/pi-user-prompt.d.ts.map +1 -0
- package/dist/agents/plugins/pi/session/pi-user-prompt.js +51 -0
- package/dist/agents/plugins/pi/session/pi-user-prompt.js.map +1 -0
- package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.d.ts +52 -0
- package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.d.ts.map +1 -0
- package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.js +716 -0
- package/dist/agents/plugins/pi/session/processors/pi.conversations-processor.js.map +1 -0
- package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.d.ts +104 -0
- package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.d.ts.map +1 -0
- package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.js +595 -0
- package/dist/agents/plugins/pi/session/processors/pi.metrics-processor.js.map +1 -0
- package/dist/agents/registry.d.ts +20 -0
- package/dist/agents/registry.d.ts.map +1 -1
- package/dist/agents/registry.js +29 -2
- package/dist/agents/registry.js.map +1 -1
- package/dist/cli/commands/analytics/agent-labels.d.ts +3 -0
- package/dist/cli/commands/analytics/agent-labels.d.ts.map +1 -0
- package/dist/cli/commands/analytics/agent-labels.js +20 -0
- package/dist/cli/commands/analytics/agent-labels.js.map +1 -0
- package/dist/cli/commands/analytics/cost/cost-enricher.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/cost-enricher.js +12 -0
- package/dist/cli/commands/analytics/cost/cost-enricher.js.map +1 -1
- package/dist/cli/commands/analytics/cost/types.d.ts +10 -0
- package/dist/cli/commands/analytics/cost/types.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/usage-readers.d.ts +24 -0
- package/dist/cli/commands/analytics/cost/usage-readers.d.ts.map +1 -1
- package/dist/cli/commands/analytics/cost/usage-readers.js +253 -54
- package/dist/cli/commands/analytics/cost/usage-readers.js.map +1 -1
- package/dist/cli/commands/analytics/formatter.d.ts.map +1 -1
- package/dist/cli/commands/analytics/formatter.js +10 -2
- package/dist/cli/commands/analytics/formatter.js.map +1 -1
- package/dist/cli/commands/analytics/index.d.ts.map +1 -1
- package/dist/cli/commands/analytics/index.js +22 -0
- package/dist/cli/commands/analytics/index.js.map +1 -1
- package/dist/cli/commands/analytics/native-loader.d.ts +21 -4
- package/dist/cli/commands/analytics/native-loader.d.ts.map +1 -1
- package/dist/cli/commands/analytics/native-loader.js +267 -88
- package/dist/cli/commands/analytics/native-loader.js.map +1 -1
- package/dist/cli/commands/analytics/report/client/app.js +77 -15
- package/dist/cli/commands/analytics/report/payload-builder.d.ts.map +1 -1
- package/dist/cli/commands/analytics/report/payload-builder.js +32 -2
- package/dist/cli/commands/analytics/report/payload-builder.js.map +1 -1
- package/dist/cli/commands/analytics/report/types.d.ts +11 -0
- package/dist/cli/commands/analytics/report/types.d.ts.map +1 -1
- package/dist/cli/commands/hook.d.ts.map +1 -1
- package/dist/cli/commands/hook.js +71 -29
- package/dist/cli/commands/hook.js.map +1 -1
- package/dist/cli/commands/install.d.ts.map +1 -1
- package/dist/cli/commands/install.js +9 -7
- package/dist/cli/commands/install.js.map +1 -1
- package/dist/cli/commands/list.d.ts.map +1 -1
- package/dist/cli/commands/list.js +4 -2
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/setup.d.ts +3 -1
- package/dist/cli/commands/setup.d.ts.map +1 -1
- package/dist/cli/commands/setup.js +87 -63
- package/dist/cli/commands/setup.js.map +1 -1
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.js +6 -4
- package/dist/cli/commands/uninstall.js.map +1 -1
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +7 -5
- package/dist/cli/commands/update.js.map +1 -1
- package/dist/cli/first-time.d.ts.map +1 -1
- package/dist/cli/first-time.js +10 -9
- package/dist/cli/first-time.js.map +1 -1
- package/dist/providers/core/auth-validation.d.ts +7 -2
- package/dist/providers/core/auth-validation.d.ts.map +1 -1
- package/dist/providers/core/auth-validation.js +11 -5
- package/dist/providers/core/auth-validation.js.map +1 -1
- package/dist/providers/core/types.d.ts +16 -0
- package/dist/providers/core/types.d.ts.map +1 -1
- package/dist/providers/core/types.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.d.ts +8 -3
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.js +46 -11
- package/dist/providers/plugins/sso/proxy/plugins/claude-request-normalizer.plugin.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.d.ts +23 -13
- package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.js +75 -18
- package/dist/providers/plugins/sso/proxy/plugins/codex-encrypted-content-sanitizer.plugin.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.d.ts +21 -0
- package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.d.ts.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.js +133 -0
- package/dist/providers/plugins/sso/proxy/plugins/copilot-encrypted-content-sanitizer.plugin.js.map +1 -0
- package/dist/providers/plugins/sso/proxy/plugins/header-injection.plugin.js +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/header-injection.plugin.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts +2 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/index.js +4 -2
- package/dist/providers/plugins/sso/proxy/plugins/index.js.map +1 -1
- package/dist/providers/plugins/sso/proxy/plugins/types.d.ts +11 -0
- package/dist/providers/plugins/sso/proxy/plugins/types.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts +2 -0
- package/dist/providers/plugins/sso/proxy/sso.proxy.d.ts.map +1 -1
- package/dist/providers/plugins/sso/proxy/sso.proxy.js +37 -1
- package/dist/providers/plugins/sso/proxy/sso.proxy.js.map +1 -1
- package/dist/providers/plugins/sso/session/SessionSyncer.d.ts.map +1 -1
- package/dist/providers/plugins/sso/session/SessionSyncer.js +13 -0
- package/dist/providers/plugins/sso/session/SessionSyncer.js.map +1 -1
- package/dist/providers/plugins/sso/session/processors/conversations/syncProcessor.js +6 -0
- package/dist/providers/plugins/sso/session/processors/conversations/syncProcessor.js.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.d.ts +0 -6
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.d.ts.map +1 -1
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.js +28 -19
- package/dist/providers/plugins/sso/session/processors/metrics/metrics-post-processor.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 +39 -22
- package/dist/providers/plugins/sso/sso.setup-steps.js.map +1 -1
- package/dist/utils/interactive.d.ts +14 -0
- package/dist/utils/interactive.d.ts.map +1 -0
- package/dist/utils/interactive.js +16 -0
- package/dist/utils/interactive.js.map +1 -0
- package/package.json +6 -5
- package/scripts/copy-plugins.js +6 -0
- package/scripts/release.sh +54 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { BaseAgentAdapter } from '../../core/BaseAgentAdapter.js';
|
|
2
|
+
import { CopilotCliSessionAdapter } from './copilot-cli.session.js';
|
|
3
|
+
import { ConfigurationError } from '../../../utils/errors.js';
|
|
4
|
+
import { commandExists, exec } from '../../../utils/processes.js';
|
|
5
|
+
import { logger } from '../../../utils/logger.js';
|
|
6
|
+
import { COPILOT_CLI_AGENT_NAME, COPILOT_CLI_CLIENT_TYPE, COPILOT_CLI_DISPLAY_NAME, } from './copilot-cli.constants.js';
|
|
7
|
+
import { assertExplicitCopilotModelAllowed, resolveCopilotModel, } from './copilot-cli.models.js';
|
|
8
|
+
export { COPILOT_CLI_AGENT_NAME, COPILOT_CLI_CLIENT_TYPE, COPILOT_CLI_DISPLAY_NAME, } from './copilot-cli.constants.js';
|
|
9
|
+
const COPILOT_SUPPORTED_VERSION = '1.0.79';
|
|
10
|
+
const COPILOT_MINIMUM_SUPPORTED_VERSION = '1.0.70';
|
|
11
|
+
const COPILOT_COMPATIBLE_PROVIDERS = ['ai-run-sso', 'litellm'];
|
|
12
|
+
const COPILOT_RECOMMENDED_MODELS = ['gpt-5.5', 'claude-sonnet-4.6', 'gpt-5.4'];
|
|
13
|
+
function buildCopilotHookConfig(env, sessionId) {
|
|
14
|
+
return {
|
|
15
|
+
agentName: env.CODEMIE_AGENT || COPILOT_CLI_AGENT_NAME,
|
|
16
|
+
sessionId,
|
|
17
|
+
provider: env.CODEMIE_PROVIDER,
|
|
18
|
+
apiBaseUrl: env.CODEMIE_BASE_URL,
|
|
19
|
+
ssoUrl: env.CODEMIE_URL,
|
|
20
|
+
syncApiUrl: env.CODEMIE_SYNC_API_URL,
|
|
21
|
+
version: env.CODEMIE_CLI_VERSION,
|
|
22
|
+
profileName: env.CODEMIE_PROFILE_NAME,
|
|
23
|
+
project: env.CODEMIE_PROJECT,
|
|
24
|
+
model: env.CODEMIE_MODEL,
|
|
25
|
+
clientType: COPILOT_CLI_CLIENT_TYPE,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function buildCopilotProviderEnv(env) {
|
|
29
|
+
if (!env.CODEMIE_BASE_URL) {
|
|
30
|
+
throw new ConfigurationError('CodeMie base URL is not configured for Copilot CLI. Run codemie setup and try again.');
|
|
31
|
+
}
|
|
32
|
+
if (!env.CODEMIE_MODEL) {
|
|
33
|
+
throw new ConfigurationError('No CodeMie model is configured for Copilot CLI. Run codemie setup or pass --model.');
|
|
34
|
+
}
|
|
35
|
+
const providerType = /^claude/i.test(env.CODEMIE_MODEL) ? 'anthropic' : 'openai';
|
|
36
|
+
const providerEnv = {
|
|
37
|
+
COPILOT_PROVIDER_BASE_URL: env.CODEMIE_BASE_URL,
|
|
38
|
+
COPILOT_PROVIDER_TYPE: providerType,
|
|
39
|
+
COPILOT_MODEL: env.CODEMIE_MODEL,
|
|
40
|
+
COPILOT_PROVIDER_MODEL_ID: env.CODEMIE_MODEL,
|
|
41
|
+
COPILOT_PROVIDER_WIRE_MODEL: env.CODEMIE_MODEL,
|
|
42
|
+
COPILOT_OFFLINE: 'true',
|
|
43
|
+
};
|
|
44
|
+
if (/^gpt[-_.]?5/i.test(env.CODEMIE_MODEL)) {
|
|
45
|
+
providerEnv.COPILOT_PROVIDER_WIRE_API = 'responses';
|
|
46
|
+
}
|
|
47
|
+
if (env.CODEMIE_API_KEY) {
|
|
48
|
+
providerEnv.COPILOT_PROVIDER_API_KEY = env.CODEMIE_API_KEY;
|
|
49
|
+
providerEnv.COPILOT_PROVIDER_BEARER_TOKEN = env.CODEMIE_API_KEY;
|
|
50
|
+
}
|
|
51
|
+
return providerEnv;
|
|
52
|
+
}
|
|
53
|
+
function assertCopilotProviderSupported(config) {
|
|
54
|
+
const provider = config.provider;
|
|
55
|
+
if (!provider || !COPILOT_COMPATIBLE_PROVIDERS.includes(provider)) {
|
|
56
|
+
throw new ConfigurationError('GitHub Copilot CLI via CodeMie currently supports only AI/Run SSO and LiteLLM profiles. ' +
|
|
57
|
+
'Run codemie setup to choose a supported provider.');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export const CopilotCliPluginMetadata = {
|
|
61
|
+
name: COPILOT_CLI_AGENT_NAME,
|
|
62
|
+
displayName: COPILOT_CLI_DISPLAY_NAME,
|
|
63
|
+
description: 'GitHub Copilot CLI - AI coding agent managed by CodeMie',
|
|
64
|
+
npmPackage: '@github/copilot',
|
|
65
|
+
cliCommand: process.env.CODEMIE_COPILOT_BIN || 'copilot',
|
|
66
|
+
supportedVersion: COPILOT_SUPPORTED_VERSION,
|
|
67
|
+
minimumSupportedVersion: COPILOT_MINIMUM_SUPPORTED_VERSION,
|
|
68
|
+
dataPaths: {
|
|
69
|
+
home: '.copilot',
|
|
70
|
+
},
|
|
71
|
+
extensionsConfig: {
|
|
72
|
+
project: '.github',
|
|
73
|
+
global: '~/.copilot',
|
|
74
|
+
skillsEntryFile: 'SKILL.md',
|
|
75
|
+
dirNames: {
|
|
76
|
+
agents: ['agents'],
|
|
77
|
+
commands: [],
|
|
78
|
+
skills: ['skills'],
|
|
79
|
+
hooks: ['hooks'],
|
|
80
|
+
rules: [],
|
|
81
|
+
},
|
|
82
|
+
extraProjectDirs: ['.github/copilot'],
|
|
83
|
+
},
|
|
84
|
+
mcpConfig: {
|
|
85
|
+
project: {
|
|
86
|
+
path: ['.mcp.json', '.github/mcp.json'],
|
|
87
|
+
jsonPath: 'mcpServers',
|
|
88
|
+
},
|
|
89
|
+
user: {
|
|
90
|
+
path: '~/.copilot/mcp-config.json',
|
|
91
|
+
jsonPath: 'mcpServers',
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
hookConfig: {
|
|
95
|
+
eventNameMapping: {
|
|
96
|
+
SessionStart: 'SessionStart',
|
|
97
|
+
SessionEnd: 'SessionEnd',
|
|
98
|
+
UserPromptSubmit: 'UserPromptSubmit',
|
|
99
|
+
PreToolUse: 'UserPromptSubmit',
|
|
100
|
+
PostToolUse: 'Stop',
|
|
101
|
+
Notification: 'PermissionRequest',
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
envMapping: {
|
|
105
|
+
baseUrl: [],
|
|
106
|
+
apiKey: [],
|
|
107
|
+
model: [],
|
|
108
|
+
},
|
|
109
|
+
supportedProviders: [...COPILOT_COMPATIBLE_PROVIDERS],
|
|
110
|
+
blockedModelPatterns: [/embedding/i, /rerank/i, /whisper/i, /tts/i, /image/i],
|
|
111
|
+
recommendedModels: [...COPILOT_RECOMMENDED_MODELS],
|
|
112
|
+
ssoConfig: {
|
|
113
|
+
enabled: true,
|
|
114
|
+
clientType: COPILOT_CLI_CLIENT_TYPE,
|
|
115
|
+
},
|
|
116
|
+
sessionAnalyticsReport: true,
|
|
117
|
+
flagMappings: {
|
|
118
|
+
'--task': { type: 'flag', target: '--prompt' },
|
|
119
|
+
},
|
|
120
|
+
lifecycle: {
|
|
121
|
+
async onSessionStart(sessionId, env) {
|
|
122
|
+
try {
|
|
123
|
+
const { processEvent } = await import('../../../cli/commands/hook.js');
|
|
124
|
+
await processEvent({
|
|
125
|
+
hook_event_name: 'SessionStart',
|
|
126
|
+
session_id: sessionId,
|
|
127
|
+
transcript_path: '',
|
|
128
|
+
permission_mode: 'default',
|
|
129
|
+
cwd: process.cwd(),
|
|
130
|
+
source: 'startup',
|
|
131
|
+
}, buildCopilotHookConfig(env, sessionId));
|
|
132
|
+
logger.info(`[copilot-cli] SessionStart hook completed for session ${sessionId}`);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
136
|
+
logger.error(`[copilot-cli] SessionStart hook failed (non-blocking): ${message}`);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
async beforeRun(env, config) {
|
|
140
|
+
assertCopilotProviderSupported(config);
|
|
141
|
+
// Prevent fallback to GitHub-native auth even when GitHub credentials exist.
|
|
142
|
+
delete env.GH_TOKEN;
|
|
143
|
+
delete env.GITHUB_TOKEN;
|
|
144
|
+
delete env.COPILOT_TOKEN;
|
|
145
|
+
if (!env.COPILOT_HOME) {
|
|
146
|
+
env.COPILOT_HOME = this.resolveDataPath();
|
|
147
|
+
}
|
|
148
|
+
await this.ensureDirectory(env.COPILOT_HOME);
|
|
149
|
+
const availableModels = (env.CODEMIE_COPILOT_AVAILABLE_MODELS || '')
|
|
150
|
+
.split(',')
|
|
151
|
+
.map((entry) => entry.trim())
|
|
152
|
+
.filter(Boolean);
|
|
153
|
+
if (env.CODEMIE_MODEL) {
|
|
154
|
+
assertExplicitCopilotModelAllowed(env.CODEMIE_MODEL, availableModels);
|
|
155
|
+
}
|
|
156
|
+
const providerEnv = buildCopilotProviderEnv(env);
|
|
157
|
+
Object.assign(env, providerEnv);
|
|
158
|
+
logger.debug('[copilot-cli] Prepared provider env for managed Copilot session', {
|
|
159
|
+
provider: config.provider,
|
|
160
|
+
model: env.CODEMIE_MODEL,
|
|
161
|
+
providerType: providerEnv.COPILOT_PROVIDER_TYPE,
|
|
162
|
+
clientType: COPILOT_CLI_CLIENT_TYPE,
|
|
163
|
+
});
|
|
164
|
+
return env;
|
|
165
|
+
},
|
|
166
|
+
enrichArgs(args, _config) {
|
|
167
|
+
const enriched = [...args];
|
|
168
|
+
const hasPrompt = enriched.includes('-p') || enriched.includes('--prompt');
|
|
169
|
+
const hasAutoApproval = enriched.includes('--allow-all') || enriched.includes('--allow-all-tools') || enriched.includes('--yolo');
|
|
170
|
+
const hasModel = enriched.includes('--model');
|
|
171
|
+
if (hasPrompt && !hasAutoApproval) {
|
|
172
|
+
enriched.push('--allow-all-tools');
|
|
173
|
+
}
|
|
174
|
+
if (!hasModel && process.env.CODEMIE_MODEL) {
|
|
175
|
+
enriched.push('--model', process.env.CODEMIE_MODEL);
|
|
176
|
+
}
|
|
177
|
+
return enriched;
|
|
178
|
+
},
|
|
179
|
+
async onSessionEnd(exitCode, env) {
|
|
180
|
+
const sessionId = env.CODEMIE_SESSION_ID;
|
|
181
|
+
if (!sessionId) {
|
|
182
|
+
logger.debug('[copilot-cli] No CODEMIE_SESSION_ID in environment, skipping session end');
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
const adapter = new CopilotCliSessionAdapter(CopilotCliPluginMetadata);
|
|
187
|
+
const sessions = await adapter.discoverSessions({
|
|
188
|
+
maxAgeDays: 1,
|
|
189
|
+
limit: 1,
|
|
190
|
+
cwd: process.cwd(),
|
|
191
|
+
});
|
|
192
|
+
const transcriptPath = sessions[0]?.filePath ?? '';
|
|
193
|
+
const agentSessionId = sessions[0]?.sessionId ?? sessionId;
|
|
194
|
+
const { processEvent } = await import('../../../cli/commands/hook.js');
|
|
195
|
+
await processEvent({
|
|
196
|
+
hook_event_name: 'SessionEnd',
|
|
197
|
+
session_id: agentSessionId,
|
|
198
|
+
transcript_path: transcriptPath,
|
|
199
|
+
permission_mode: 'default',
|
|
200
|
+
cwd: process.cwd(),
|
|
201
|
+
reason: exitCode === 0 ? 'exit' : `exit(${exitCode})`,
|
|
202
|
+
}, buildCopilotHookConfig(env, sessionId));
|
|
203
|
+
logger.info(`[copilot-cli] SessionEnd hook completed for session ${sessionId}`);
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
207
|
+
logger.error(`[copilot-cli] SessionEnd hook failed (non-blocking): ${message}`);
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
export class CopilotCliPlugin extends BaseAgentAdapter {
|
|
213
|
+
sessionAdapter = null;
|
|
214
|
+
constructor() {
|
|
215
|
+
super(CopilotCliPluginMetadata);
|
|
216
|
+
}
|
|
217
|
+
getSessionAdapter() {
|
|
218
|
+
if (!this.sessionAdapter) {
|
|
219
|
+
this.sessionAdapter = new CopilotCliSessionAdapter(this.metadata);
|
|
220
|
+
}
|
|
221
|
+
return this.sessionAdapter;
|
|
222
|
+
}
|
|
223
|
+
async setupProxy(env) {
|
|
224
|
+
if (env.CODEMIE_PROVIDER !== 'ai-run-sso' && env.CODEMIE_AUTH_METHOD !== 'jwt') {
|
|
225
|
+
await super.setupProxy(env);
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const modelSource = env.CODEMIE_MODEL_SOURCE;
|
|
229
|
+
const explicitModel = env.CODEMIE_MODEL && (modelSource === 'cli' || modelSource === 'env')
|
|
230
|
+
? env.CODEMIE_MODEL
|
|
231
|
+
: undefined;
|
|
232
|
+
const { selectedModel, availableModels } = await resolveCopilotModel(env);
|
|
233
|
+
if (explicitModel) {
|
|
234
|
+
assertExplicitCopilotModelAllowed(explicitModel, availableModels);
|
|
235
|
+
env.CODEMIE_MODEL = explicitModel;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
env.CODEMIE_MODEL = selectedModel;
|
|
239
|
+
}
|
|
240
|
+
env.CODEMIE_COPILOT_AVAILABLE_MODELS = availableModels.join(',');
|
|
241
|
+
await super.setupProxy(env);
|
|
242
|
+
}
|
|
243
|
+
async isInstalled() {
|
|
244
|
+
if (!this.metadata.cliCommand) {
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
return commandExists(this.metadata.cliCommand);
|
|
248
|
+
}
|
|
249
|
+
async getVersion() {
|
|
250
|
+
if (!this.metadata.cliCommand) {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
const result = await exec(this.metadata.cliCommand, ['--version']);
|
|
255
|
+
const match = result.stdout.trim().match(/(\d+\.\d+\.\d+)/);
|
|
256
|
+
return match ? match[1] : result.stdout.trim() || null;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=copilot-cli.plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-cli.plugin.js","sourceRoot":"","sources":["../../../../src/agents/plugins/copilot-cli/copilot-cli.plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copilot CLI Session Adapter.
|
|
3
|
+
*
|
|
4
|
+
* Sessions live at `~/.copilot/session-state/<uuid>/` (or `$COPILOT_HOME/...`), one
|
|
5
|
+
* directory per session, each holding a `workspace.yaml` manifest and — from the
|
|
6
|
+
* schema-bearing CLI versions — an `events.jsonl` transcript.
|
|
7
|
+
*
|
|
8
|
+
* Discovery reads only the manifest; transcripts are opened during parse, so a report run
|
|
9
|
+
* never pays to read a transcript it goes on to filter out.
|
|
10
|
+
*
|
|
11
|
+
* Modeled on `CodexSessionAdapter` (`src/agents/plugins/codex/codex.session.ts`), the
|
|
12
|
+
* closest analog — a natively-discovered JSONL agent. Discovery here is simpler: Codex
|
|
13
|
+
* walks `YYYY/MM/DD` directories and stats mtimes, whereas Copilot's flat layout plus the
|
|
14
|
+
* manifest's own timestamps make both unnecessary.
|
|
15
|
+
*/
|
|
16
|
+
import type { SessionAdapter, ParsedSession, AggregatedResult, SessionDiscoveryOptions, SessionDescriptor } from '../../core/session/BaseSessionAdapter.js';
|
|
17
|
+
import type { SessionProcessor, ProcessingContext } from '../../core/session/BaseProcessor.js';
|
|
18
|
+
import type { AgentMetadata } from '../../core/types.js';
|
|
19
|
+
export declare class CopilotCliSessionAdapter implements SessionAdapter {
|
|
20
|
+
private readonly metadata;
|
|
21
|
+
readonly agentName = "copilot-cli";
|
|
22
|
+
private processors;
|
|
23
|
+
constructor(metadata: AgentMetadata);
|
|
24
|
+
registerProcessor(processor: SessionProcessor): void;
|
|
25
|
+
/**
|
|
26
|
+
* Enumerate `session-state/<uuid>/` directories that carry a transcript, newest first.
|
|
27
|
+
*
|
|
28
|
+
* Directories without `events.jsonl` are pre-schema sessions with nothing to parse or
|
|
29
|
+
* price, and are skipped rather than surfaced as empty rows.
|
|
30
|
+
*/
|
|
31
|
+
discoverSessions(options?: SessionDiscoveryOptions): Promise<SessionDescriptor[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Read `events.jsonl` into the unified `ParsedSession`.
|
|
34
|
+
*
|
|
35
|
+
* `messages` carries the RAW per-model Copilot buckets — `readCopilotCli` in
|
|
36
|
+
* `usage-readers.ts` owns the conversion into `TokenUsage`, so the OpenAI/Anthropic
|
|
37
|
+
* convention mismatch lives in exactly one place.
|
|
38
|
+
*/
|
|
39
|
+
parseSessionFile(filePath: string, sessionId: string): Promise<ParsedSession>;
|
|
40
|
+
/** Parse once, then run every registered processor in priority order. */
|
|
41
|
+
processSession(filePath: string, sessionId: string, context: ProcessingContext): Promise<AggregatedResult>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=copilot-cli.session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilot-cli.session.d.ts","sourceRoot":"","sources":["../../../../src/agents/plugins/copilot-cli/copilot-cli.session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EAClB,MAAM,0CAA0C,CAAC;AAClD,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EAElB,MAAM,qCAAqC,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAmCzD,qBAAa,wBAAyB,YAAW,cAAc;IAIjD,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAHrC,QAAQ,CAAC,SAAS,iBAA0B;IAC5C,OAAO,CAAC,UAAU,CAA0B;gBAEf,QAAQ,EAAE,aAAa;IAKpD,iBAAiB,CAAC,SAAS,EAAE,gBAAgB,GAAG,IAAI;IAQpD;;;;;OAKG;IACG,gBAAgB,CAAC,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAuEvF;;;;;;OAMG;IACG,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAmMnF,yEAAyE;IACnE,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,gBAAgB,CAAC;CAwC7B"}
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copilot CLI Session Adapter.
|
|
3
|
+
*
|
|
4
|
+
* Sessions live at `~/.copilot/session-state/<uuid>/` (or `$COPILOT_HOME/...`), one
|
|
5
|
+
* directory per session, each holding a `workspace.yaml` manifest and — from the
|
|
6
|
+
* schema-bearing CLI versions — an `events.jsonl` transcript.
|
|
7
|
+
*
|
|
8
|
+
* Discovery reads only the manifest; transcripts are opened during parse, so a report run
|
|
9
|
+
* never pays to read a transcript it goes on to filter out.
|
|
10
|
+
*
|
|
11
|
+
* Modeled on `CodexSessionAdapter` (`src/agents/plugins/codex/codex.session.ts`), the
|
|
12
|
+
* closest analog — a natively-discovered JSONL agent. Discovery here is simpler: Codex
|
|
13
|
+
* walks `YYYY/MM/DD` directories and stats mtimes, whereas Copilot's flat layout plus the
|
|
14
|
+
* manifest's own timestamps make both unnecessary.
|
|
15
|
+
*/
|
|
16
|
+
import { readdirSync, existsSync } from 'fs';
|
|
17
|
+
import { join } from 'path';
|
|
18
|
+
import { getCopilotSessionStateRoot } from './copilot-cli.paths.js';
|
|
19
|
+
import { readWorkspaceManifest } from './copilot-cli.workspace.js';
|
|
20
|
+
import { COPILOT_CLI_AGENT_NAME } from './copilot-cli.constants.js';
|
|
21
|
+
import { readCopilotEventsTolerant } from './copilot-cli.storage-utils.js';
|
|
22
|
+
import { extractCopilotUsage } from './copilot-cli.usage.js';
|
|
23
|
+
import { CopilotCliMetricsProcessor } from './session/processors/copilot-cli.metrics-processor.js';
|
|
24
|
+
import { CopilotCliConversationsProcessor } from './session/processors/copilot-cli.conversations-processor.js';
|
|
25
|
+
import { logger } from '../../../utils/logger.js';
|
|
26
|
+
const DEFAULT_MAX_AGE_DAYS = 30;
|
|
27
|
+
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
28
|
+
/**
|
|
29
|
+
* Copilot tools that write to disk. `view` also carries a `path` but is a read, and the
|
|
30
|
+
* aggregator excludes reads from the changed-files metrics.
|
|
31
|
+
*/
|
|
32
|
+
const FILE_WRITE_TOOLS = new Set(['create', 'edit']);
|
|
33
|
+
/** Trailing-slash-insensitive directory comparison. */
|
|
34
|
+
function sameDir(a, b) {
|
|
35
|
+
if (!a) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return a.replace(/\/+$/, '') === b.replace(/\/+$/, '');
|
|
39
|
+
}
|
|
40
|
+
export class CopilotCliSessionAdapter {
|
|
41
|
+
metadata;
|
|
42
|
+
agentName = COPILOT_CLI_AGENT_NAME;
|
|
43
|
+
processors = [];
|
|
44
|
+
constructor(metadata) {
|
|
45
|
+
this.metadata = metadata;
|
|
46
|
+
this.registerProcessor(new CopilotCliMetricsProcessor());
|
|
47
|
+
this.registerProcessor(new CopilotCliConversationsProcessor());
|
|
48
|
+
}
|
|
49
|
+
registerProcessor(processor) {
|
|
50
|
+
this.processors.push(processor);
|
|
51
|
+
this.processors.sort((a, b) => a.priority - b.priority);
|
|
52
|
+
logger.debug(`[copilot-cli-adapter] Registered processor: ${processor.name} (priority: ${processor.priority})`);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Enumerate `session-state/<uuid>/` directories that carry a transcript, newest first.
|
|
56
|
+
*
|
|
57
|
+
* Directories without `events.jsonl` are pre-schema sessions with nothing to parse or
|
|
58
|
+
* price, and are skipped rather than surfaced as empty rows.
|
|
59
|
+
*/
|
|
60
|
+
async discoverSessions(options) {
|
|
61
|
+
const root = getCopilotSessionStateRoot();
|
|
62
|
+
if (!existsSync(root)) {
|
|
63
|
+
logger.debug(`[copilot-cli-discovery] no session-state directory at ${root}`);
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
let dirNames;
|
|
67
|
+
try {
|
|
68
|
+
dirNames = readdirSync(root, { withFileTypes: true })
|
|
69
|
+
.filter((entry) => entry.isDirectory())
|
|
70
|
+
.map((entry) => entry.name);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
logger.debug('[copilot-cli-discovery] failed to read session-state:', error);
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const maxAgeDays = options?.maxAgeDays ?? DEFAULT_MAX_AGE_DAYS;
|
|
77
|
+
const cutoffMs = Date.now() - maxAgeDays * MS_PER_DAY;
|
|
78
|
+
const results = [];
|
|
79
|
+
for (const name of dirNames) {
|
|
80
|
+
const dir = join(root, name);
|
|
81
|
+
const eventsPath = join(dir, 'events.jsonl');
|
|
82
|
+
if (!existsSync(eventsPath)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const manifest = readWorkspaceManifest(dir);
|
|
86
|
+
if (!manifest) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const { createdAt } = manifest;
|
|
90
|
+
if (createdAt === undefined) {
|
|
91
|
+
if (!options?.includeTimestampless) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (createdAt < cutoffMs) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const projectPath = manifest.cwd ?? manifest.gitRoot;
|
|
99
|
+
if (options?.cwd && !sameDir(projectPath, options.cwd)) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
results.push({
|
|
103
|
+
sessionId: manifest.id,
|
|
104
|
+
filePath: eventsPath,
|
|
105
|
+
projectPath,
|
|
106
|
+
createdAt: createdAt ?? 0,
|
|
107
|
+
updatedAt: manifest.updatedAt,
|
|
108
|
+
agentName: this.agentName,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
results.sort((a, b) => b.createdAt - a.createdAt);
|
|
112
|
+
if (options?.limit && options.limit > 0) {
|
|
113
|
+
logger.debug(`[copilot-cli-discovery] found ${results.length} session(s), returning ${options.limit}`);
|
|
114
|
+
return results.slice(0, options.limit);
|
|
115
|
+
}
|
|
116
|
+
logger.debug(`[copilot-cli-discovery] found ${results.length} session(s)`);
|
|
117
|
+
return results;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Read `events.jsonl` into the unified `ParsedSession`.
|
|
121
|
+
*
|
|
122
|
+
* `messages` carries the RAW per-model Copilot buckets — `readCopilotCli` in
|
|
123
|
+
* `usage-readers.ts` owns the conversion into `TokenUsage`, so the OpenAI/Anthropic
|
|
124
|
+
* convention mismatch lives in exactly one place.
|
|
125
|
+
*/
|
|
126
|
+
async parseSessionFile(filePath, sessionId) {
|
|
127
|
+
const events = readCopilotEventsTolerant(filePath);
|
|
128
|
+
const start = events.find((e) => e.type === 'session.start')?.data;
|
|
129
|
+
const shutdown = [...events].reverse().find((e) => e.type === 'session.shutdown')?.data;
|
|
130
|
+
const usage = extractCopilotUsage(events);
|
|
131
|
+
const tools = {};
|
|
132
|
+
const toolStatus = {};
|
|
133
|
+
const skillInvocations = {};
|
|
134
|
+
const userPrompts = [];
|
|
135
|
+
const fileOperations = [];
|
|
136
|
+
const context = start?.context;
|
|
137
|
+
const cwd = context?.cwd ?? context?.gitRoot;
|
|
138
|
+
const branch = context?.branch;
|
|
139
|
+
// Per-turn records in the Claude-shaped form `synthesizeRawSession` understands, so
|
|
140
|
+
// native synthesis derives turns, models, timestamps, cwd and branch correctly. These
|
|
141
|
+
// carry no `usage`, so `readCopilotCli` skips them; the per-model usage rows appended
|
|
142
|
+
// afterwards carry no `type`, so turn counting skips those. Orthogonal filters.
|
|
143
|
+
const turnRecords = [];
|
|
144
|
+
// tool.execution_start is the ONLY event carrying the tool name and arguments;
|
|
145
|
+
// tool.execution_complete carries just toolCallId + a boolean success. Pair by id.
|
|
146
|
+
const toolCallById = new Map();
|
|
147
|
+
// Only the newest CLI builds put `model` on each assistant.message; 1.0.17 and every
|
|
148
|
+
// 0.0.x omit it. Track the model in effect from session.model_change so those turns
|
|
149
|
+
// are still attributed, and remember which turns stayed unlabelled for the
|
|
150
|
+
// single-model backfill below.
|
|
151
|
+
let currentModel;
|
|
152
|
+
const unlabelledTurns = [];
|
|
153
|
+
for (const event of events) {
|
|
154
|
+
switch (event.type) {
|
|
155
|
+
case 'tool.execution_start': {
|
|
156
|
+
const data = (event.data ?? {});
|
|
157
|
+
if (!data.toolCallId || !data.toolName) {
|
|
158
|
+
break;
|
|
159
|
+
}
|
|
160
|
+
// Remember the name and target path; whether the write actually happened is
|
|
161
|
+
// only known at tool.execution_complete.
|
|
162
|
+
toolCallById.set(data.toolCallId, { name: data.toolName, path: data.arguments?.path });
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
case 'tool.execution_complete': {
|
|
166
|
+
const data = (event.data ?? {});
|
|
167
|
+
const call = data.toolCallId ? toolCallById.get(data.toolCallId) : undefined;
|
|
168
|
+
if (!call) {
|
|
169
|
+
break; // orphaned completion (truncated transcript) — nothing to attribute
|
|
170
|
+
}
|
|
171
|
+
tools[call.name] = (tools[call.name] ?? 0) + 1;
|
|
172
|
+
const bucket = toolStatus[call.name] ?? { success: 0, failure: 0 };
|
|
173
|
+
const failed = data.success === false || data.error !== undefined;
|
|
174
|
+
bucket[failed ? 'failure' : 'success'] += 1;
|
|
175
|
+
toolStatus[call.name] = bucket;
|
|
176
|
+
// Record the file operation only once the write is known to have SUCCEEDED.
|
|
177
|
+
// A failed edit/create (permission denied, bad old_str) must not count as a
|
|
178
|
+
// changed file, or the report inflates filesChanged and can attach the
|
|
179
|
+
// session's line totals to a file that was never written.
|
|
180
|
+
if (!failed && call.path && FILE_WRITE_TOOLS.has(call.name)) {
|
|
181
|
+
fileOperations.push({ type: call.name === 'create' ? 'write' : 'edit', path: call.path });
|
|
182
|
+
}
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
case 'skill.invoked': {
|
|
186
|
+
const data = (event.data ?? {});
|
|
187
|
+
const name = data.skill ?? data.name;
|
|
188
|
+
if (name) {
|
|
189
|
+
skillInvocations[name] = (skillInvocations[name] ?? 0) + 1;
|
|
190
|
+
}
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case 'user.message': {
|
|
194
|
+
const data = event.data ?? {};
|
|
195
|
+
const text = typeof data.text === 'string' && data.text.trim()
|
|
196
|
+
? data.text
|
|
197
|
+
: typeof data.content === 'string'
|
|
198
|
+
? data.content
|
|
199
|
+
: undefined;
|
|
200
|
+
if (typeof text === 'string' && text.trim()) {
|
|
201
|
+
userPrompts.push({ count: 1, text });
|
|
202
|
+
}
|
|
203
|
+
turnRecords.push({
|
|
204
|
+
type: 'user',
|
|
205
|
+
timestamp: event.timestamp,
|
|
206
|
+
cwd,
|
|
207
|
+
gitBranch: branch,
|
|
208
|
+
message: { role: 'user', content: typeof text === 'string' ? text : '' },
|
|
209
|
+
});
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case 'session.model_change': {
|
|
213
|
+
const next = event.data?.newModel;
|
|
214
|
+
if (next) {
|
|
215
|
+
currentModel = next;
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case 'assistant.message': {
|
|
220
|
+
const data = (event.data ?? {});
|
|
221
|
+
const record = {
|
|
222
|
+
type: 'assistant',
|
|
223
|
+
timestamp: event.timestamp,
|
|
224
|
+
cwd,
|
|
225
|
+
gitBranch: branch,
|
|
226
|
+
message: {
|
|
227
|
+
role: 'assistant',
|
|
228
|
+
model: data.model ?? currentModel,
|
|
229
|
+
content: typeof data.content === 'string'
|
|
230
|
+
? data.content
|
|
231
|
+
: '',
|
|
232
|
+
toolRequests: Array.isArray(data.toolRequests) ? data.toolRequests : [],
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
if (!record.message.model) {
|
|
236
|
+
unlabelledTurns.push(record);
|
|
237
|
+
}
|
|
238
|
+
turnRecords.push(record);
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
default:
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Last resort: if turns are still unlabelled but the shutdown rollup shows the session
|
|
246
|
+
// used exactly ONE model, every turn must have been that model. With two or more,
|
|
247
|
+
// attributing an unlabelled turn to either would be a fabrication — leave it unknown.
|
|
248
|
+
if (unlabelledTurns.length > 0) {
|
|
249
|
+
const usedModels = Object.keys(shutdown?.modelMetrics ?? {});
|
|
250
|
+
if (usedModels.length === 1) {
|
|
251
|
+
for (const turn of unlabelledTurns) {
|
|
252
|
+
turn.message.model = usedModels[0];
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
// session.shutdown.codeChanges is the authoritative churn figure, but reports only
|
|
257
|
+
// session-wide line totals plus a file list — no per-file deltas. Merge it into the
|
|
258
|
+
// per-file operations already gathered from tool arguments rather than appending a
|
|
259
|
+
// second entry for the same path, which would double-count the file.
|
|
260
|
+
const changes = shutdown?.codeChanges;
|
|
261
|
+
if (changes) {
|
|
262
|
+
for (const path of changes.filesModified ?? []) {
|
|
263
|
+
if (!fileOperations.some((op) => op.path === path)) {
|
|
264
|
+
fileOperations.push({ type: 'edit', path });
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Copilot gives no per-file split, so the session totals land on one entry. Prefer a
|
|
268
|
+
// file shutdown actually lists as modified — the first tool-derived entry may be a
|
|
269
|
+
// file that was opened but never changed, and crediting churn to it would be wrong.
|
|
270
|
+
const modified = new Set(changes.filesModified ?? []);
|
|
271
|
+
const target = fileOperations.find((op) => op.path !== undefined && modified.has(op.path)) ?? fileOperations[0];
|
|
272
|
+
if (target) {
|
|
273
|
+
target.linesAdded = changes.linesAdded ?? 0;
|
|
274
|
+
target.linesRemoved = changes.linesRemoved ?? 0;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
sessionId,
|
|
279
|
+
agentName: this.metadata.displayName,
|
|
280
|
+
agentVersion: start?.copilotVersion,
|
|
281
|
+
metadata: {
|
|
282
|
+
projectPath: cwd,
|
|
283
|
+
createdAt: start?.startTime,
|
|
284
|
+
repository: context?.repository,
|
|
285
|
+
branch,
|
|
286
|
+
gitBranch: branch,
|
|
287
|
+
},
|
|
288
|
+
messages: [...turnRecords, ...usage.messages],
|
|
289
|
+
usageMeta: {
|
|
290
|
+
premiumRequests: usage.premiumRequests,
|
|
291
|
+
usagePartial: usage.partial,
|
|
292
|
+
usageUnavailableReason: usage.unavailableReason,
|
|
293
|
+
},
|
|
294
|
+
metrics: {
|
|
295
|
+
tools,
|
|
296
|
+
toolStatus,
|
|
297
|
+
fileOperations,
|
|
298
|
+
skillInvocations,
|
|
299
|
+
userPrompts,
|
|
300
|
+
},
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/** Parse once, then run every registered processor in priority order. */
|
|
304
|
+
async processSession(filePath, sessionId, context) {
|
|
305
|
+
const parsed = await this.parseSessionFile(filePath, sessionId);
|
|
306
|
+
const processors = {};
|
|
307
|
+
const failedProcessors = [];
|
|
308
|
+
let totalRecords = 0;
|
|
309
|
+
for (const processor of this.processors) {
|
|
310
|
+
if (!processor.shouldProcess(parsed)) {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
const result = await processor.process(parsed, context);
|
|
315
|
+
const recordsProcessed = result.metadata?.recordsProcessed ?? 0;
|
|
316
|
+
totalRecords += recordsProcessed;
|
|
317
|
+
processors[processor.name] = {
|
|
318
|
+
success: result.success,
|
|
319
|
+
message: result.message,
|
|
320
|
+
recordsProcessed,
|
|
321
|
+
};
|
|
322
|
+
if (!result.success) {
|
|
323
|
+
failedProcessors.push(processor.name);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
logger.error(`[copilot-cli-adapter] Processor ${processor.name} failed:`, error);
|
|
328
|
+
processors[processor.name] = {
|
|
329
|
+
success: false,
|
|
330
|
+
message: error instanceof Error ? error.message : String(error),
|
|
331
|
+
};
|
|
332
|
+
failedProcessors.push(processor.name);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
success: failedProcessors.length === 0,
|
|
337
|
+
processors,
|
|
338
|
+
totalRecords,
|
|
339
|
+
failedProcessors,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
//# sourceMappingURL=copilot-cli.session.js.map
|