@codemieai/code 0.12.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/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 +1 -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.constants.d.ts +4 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.constants.d.ts.map +1 -1
- package/dist/agents/plugins/copilot-cli/copilot-cli.constants.js +4 -0
- package/dist/agents/plugins/copilot-cli/copilot-cli.constants.js.map +1 -1
- 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.plugin.d.ts +4 -20
- package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.d.ts.map +1 -1
- package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.js +237 -38
- package/dist/agents/plugins/copilot-cli/copilot-cli.plugin.js.map +1 -1
- package/dist/agents/plugins/copilot-cli/copilot-cli.session.d.ts.map +1 -1
- package/dist/agents/plugins/copilot-cli/copilot-cli.session.js +14 -2
- package/dist/agents/plugins/copilot-cli/copilot-cli.session.js.map +1 -1
- package/dist/agents/plugins/copilot-cli/index.d.ts +2 -1
- package/dist/agents/plugins/copilot-cli/index.d.ts.map +1 -1
- package/dist/agents/plugins/copilot-cli/index.js +2 -1
- package/dist/agents/plugins/copilot-cli/index.js.map +1 -1
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.d.ts +6 -3
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.d.ts.map +1 -1
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.js +298 -5
- package/dist/agents/plugins/copilot-cli/session/processors/copilot-cli.conversations-processor.js.map +1 -1
- 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.map +1 -1
- package/dist/agents/registry.js +2 -2
- package/dist/agents/registry.js.map +1 -1
- package/dist/cli/commands/analytics/agent-labels.d.ts.map +1 -1
- package/dist/cli/commands/analytics/agent-labels.js +1 -0
- package/dist/cli/commands/analytics/agent-labels.js.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 +199 -54
- package/dist/cli/commands/analytics/cost/usage-readers.js.map +1 -1
- package/dist/cli/commands/analytics/index.js +1 -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 +250 -96
- package/dist/cli/commands/analytics/native-loader.js.map +1 -1
- package/dist/cli/commands/analytics/report/client/app.js +47 -3
- package/dist/cli/commands/analytics/report/payload-builder.d.ts.map +1 -1
- package/dist/cli/commands/analytics/report/payload-builder.js +25 -2
- package/dist/cli/commands/analytics/report/payload-builder.js.map +1 -1
- package/dist/cli/commands/analytics/report/types.d.ts +1 -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 +7 -5
- 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 +3 -1
- package/dist/cli/commands/list.js.map +1 -1
- package/dist/cli/commands/uninstall.d.ts.map +1 -1
- package/dist/cli/commands/uninstall.js +5 -3
- 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 +5 -3
- 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 +7 -6
- 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/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/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 -4
- package/scripts/copy-plugins.js +6 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pi Incremental Sync Timer
|
|
3
|
+
*
|
|
4
|
+
* Pi has no hook surface that fires mid-run, so without this timer a session's
|
|
5
|
+
* metrics exist only in memory until `onSessionEnd` flushes them. A SIGKILL, a
|
|
6
|
+
* closed terminal, or an OS shutdown therefore loses the entire run. Ticking every
|
|
7
|
+
* ~30 s writes per-record metric deltas to JSONL and uploads whatever is PENDING,
|
|
8
|
+
* so at most one interval's worth of work is ever at risk.
|
|
9
|
+
*
|
|
10
|
+
* Which transcripts to process is read from the run ledger the CodeMie extension
|
|
11
|
+
* writes from inside Pi — never inferred from the session directory. A directory
|
|
12
|
+
* listing cannot tell this run's transcripts from a concurrent `pi`'s, and claiming
|
|
13
|
+
* one uploads a stranger's prompts under this user's identity.
|
|
14
|
+
*
|
|
15
|
+
* @see pi.extension.ts
|
|
16
|
+
*/
|
|
17
|
+
import { resolve } from 'path';
|
|
18
|
+
import { logger } from '../../../utils/logger.js';
|
|
19
|
+
import { readPiRunLedger } from './pi.extension.js';
|
|
20
|
+
import { PiSessionAdapter } from './pi.session.js';
|
|
21
|
+
/** Set to `false` to run Pi without the mid-run flush. */
|
|
22
|
+
const DISABLE_ENV = 'CODEMIE_PI_SYNC_ENABLED';
|
|
23
|
+
const INTERVAL_ENV = 'CODEMIE_PI_SYNC_INTERVAL_MS';
|
|
24
|
+
const DEFAULT_INTERVAL_MS = 30_000;
|
|
25
|
+
/**
|
|
26
|
+
* How long `stop` waits for a tick that is already running before abandoning it.
|
|
27
|
+
*
|
|
28
|
+
* It is a backstop, not the mechanism: `stop` first tells the tick to skip its upload, so
|
|
29
|
+
* what it normally waits for is a local transcript parse. The bound only matters when the
|
|
30
|
+
* tick was already inside the upload, which no signal can interrupt.
|
|
31
|
+
*/
|
|
32
|
+
const STOP_DRAIN_TIMEOUT_MS = 5_000;
|
|
33
|
+
const activeTimers = new Map();
|
|
34
|
+
const inFlightTicks = new Map();
|
|
35
|
+
export function startPiIncrementalSync(options) {
|
|
36
|
+
if (process.env[DISABLE_ENV] === 'false') {
|
|
37
|
+
logger.debug(`[pi-incremental-sync] Disabled by ${DISABLE_ENV}=false`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (activeTimers.has(options.sessionId)) {
|
|
41
|
+
logger.debug(`[pi-incremental-sync] Already running for session ${options.sessionId}`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const intervalMs = resolveIntervalMs(options.intervalMs);
|
|
45
|
+
const timer = setInterval(() => {
|
|
46
|
+
scheduleTick(options);
|
|
47
|
+
}, intervalMs);
|
|
48
|
+
// Don't pin the Node event loop alive solely on this timer; when Pi finishes, the
|
|
49
|
+
// parent must be free to exit rather than wait out an interval.
|
|
50
|
+
if (typeof timer.unref === 'function') {
|
|
51
|
+
timer.unref();
|
|
52
|
+
}
|
|
53
|
+
activeTimers.set(options.sessionId, timer);
|
|
54
|
+
logger.debug(`[pi-incremental-sync] Started (session=${options.sessionId}, intervalMs=${intervalMs})`);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Stop ticking and wait — for a bounded time — on a tick that is already running.
|
|
58
|
+
*
|
|
59
|
+
* The wait is the point. `clearInterval` cancels the *schedule*, not the tick already
|
|
60
|
+
* executing, and the caller's next move is the end-of-session flush over the same
|
|
61
|
+
* `{sessionId}_metrics.jsonl`. Both read the file's record ids before either appends, so
|
|
62
|
+
* an overlap appends the same deltas twice — and the sync path uploads pending records
|
|
63
|
+
* without deduplicating them by record id.
|
|
64
|
+
*
|
|
65
|
+
* The bound is the point too. This runs on the way out of the CLI, and the tick's upload
|
|
66
|
+
* is a 30 s API timeout over three attempts *per batch*: waiting it out would hang the
|
|
67
|
+
* exit for minutes whenever the sync host black-holes traffic. So the tick is first told
|
|
68
|
+
* to skip its upload — the phase that can take minutes and that appends nothing — and only
|
|
69
|
+
* the remainder is awaited, under {@link STOP_DRAIN_TIMEOUT_MS}.
|
|
70
|
+
*
|
|
71
|
+
* If the bound expires the tick was already mid-upload, and the hazard accepted is the
|
|
72
|
+
* inverse of the double-append: `MetricsSyncProcessor` finishes by rewriting the whole
|
|
73
|
+
* metrics file from the snapshot it read, so deltas the session-end flush appends in the
|
|
74
|
+
* meantime can be dropped. One truncated shutdown is the price of never hanging every
|
|
75
|
+
* user whose network is down.
|
|
76
|
+
*/
|
|
77
|
+
export async function stopPiIncrementalSync(sessionId,
|
|
78
|
+
/** Overrides {@link STOP_DRAIN_TIMEOUT_MS}. Injected by tests. */
|
|
79
|
+
drainTimeoutMs = STOP_DRAIN_TIMEOUT_MS) {
|
|
80
|
+
const timer = activeTimers.get(sessionId);
|
|
81
|
+
if (timer) {
|
|
82
|
+
clearInterval(timer);
|
|
83
|
+
activeTimers.delete(sessionId);
|
|
84
|
+
}
|
|
85
|
+
const inFlight = inFlightTicks.get(sessionId);
|
|
86
|
+
if (inFlight) {
|
|
87
|
+
inFlight.stopping.abort();
|
|
88
|
+
await drainTick(sessionId, inFlight.done, drainTimeoutMs);
|
|
89
|
+
}
|
|
90
|
+
if (timer || inFlight) {
|
|
91
|
+
logger.debug(`[pi-incremental-sync] Stopped (session=${sessionId})`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** Await the tick, giving up after `timeoutMs` so a stuck upload cannot hold the CLI open. */
|
|
95
|
+
async function drainTick(sessionId, done, timeoutMs) {
|
|
96
|
+
let timer;
|
|
97
|
+
const expiry = new Promise((resolveExpiry) => {
|
|
98
|
+
timer = setTimeout(() => resolveExpiry('expired'), timeoutMs);
|
|
99
|
+
});
|
|
100
|
+
try {
|
|
101
|
+
const outcome = await Promise.race([done.then(() => 'drained'), expiry]);
|
|
102
|
+
if (outcome === 'expired') {
|
|
103
|
+
logger.warn(`[pi-incremental-sync] Gave up waiting for the in-flight tick after ${timeoutMs} ms `
|
|
104
|
+
+ `(session=${sessionId}); it is most likely still uploading`);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
clearTimeout(timer);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function resolveIntervalMs(override) {
|
|
112
|
+
if (override !== undefined && override > 0)
|
|
113
|
+
return override;
|
|
114
|
+
// A non-positive delay is not "use the default" to Node: it clamps to 1 ms, so a
|
|
115
|
+
// mistyped env var turns the timer into a hot loop that re-parses every transcript.
|
|
116
|
+
const fromEnv = Number(process.env[INTERVAL_ENV]);
|
|
117
|
+
return Number.isFinite(fromEnv) && fromEnv > 0 ? fromEnv : DEFAULT_INTERVAL_MS;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Run a tick unless one is already running, and publish it so `stop` can await it.
|
|
121
|
+
*
|
|
122
|
+
* Re-entrancy is guarded rather than queued: a tick that outruns the interval means
|
|
123
|
+
* the transcripts are large, and stacking another parse on top would only compound
|
|
124
|
+
* that. The skipped work is picked up by the next tick, which re-reads the ledger.
|
|
125
|
+
*/
|
|
126
|
+
function scheduleTick(options) {
|
|
127
|
+
const { sessionId } = options;
|
|
128
|
+
if (inFlightTicks.has(sessionId)) {
|
|
129
|
+
logger.debug(`[pi-incremental-sync] Tick still running, skipping (session=${sessionId})`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
const stopping = new AbortController();
|
|
133
|
+
const done = runTick(options, stopping.signal).finally(() => {
|
|
134
|
+
// Only retract our own entry: a stop/start cycle may have published a newer tick.
|
|
135
|
+
if (inFlightTicks.get(sessionId)?.done === done) {
|
|
136
|
+
inFlightTicks.delete(sessionId);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
inFlightTicks.set(sessionId, { done, stopping });
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Process every transcript the ledger attributes to this run, then push what the
|
|
143
|
+
* processors wrote.
|
|
144
|
+
*/
|
|
145
|
+
async function runTick(options, stopping) {
|
|
146
|
+
try {
|
|
147
|
+
const ledger = await readPiRunLedger(options.sessionId);
|
|
148
|
+
if (ledger.transcripts.length === 0) {
|
|
149
|
+
logger.debug(`[pi-incremental-sync] No transcripts yet for session ${options.sessionId}`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const adapter = options.adapter ?? new PiSessionAdapter(options.metadata);
|
|
153
|
+
const gitBranch = await resolveRunGitBranch(options.sessionId, ledger.cwd);
|
|
154
|
+
for (const transcript of ledger.transcripts) {
|
|
155
|
+
try {
|
|
156
|
+
const result = await adapter.processSession(transcript, options.sessionId, buildTickContext(options, gitBranch));
|
|
157
|
+
logger.debug(`[pi-incremental-sync] tick ok session=${options.sessionId} `
|
|
158
|
+
+ `transcript=${transcript} records=${result.totalRecords}`);
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
// One unreadable transcript must not strand the others in the same run.
|
|
162
|
+
logger.error(`[pi-incremental-sync] processSession failed for ${transcript}:`, error);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Everything above appends to the metrics JSONL, so it is drained in full; the upload
|
|
166
|
+
// only reads and rewrites it, and it is the phase that can take minutes. A stop that
|
|
167
|
+
// lands before it starts skips it outright — the session-end flush that follows syncs
|
|
168
|
+
// exactly what this upload would have.
|
|
169
|
+
if (stopping.aborted) {
|
|
170
|
+
logger.debug(`[pi-incremental-sync] Stopping, so this tick skips its upload (session=${options.sessionId})`);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
await uploadPending(options);
|
|
174
|
+
}
|
|
175
|
+
catch (error) {
|
|
176
|
+
logger.error('[pi-incremental-sync] tick failed:', error);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* The processing context for one mid-run tick.
|
|
181
|
+
*
|
|
182
|
+
* Two things separate it from the end-of-session context: the branch, which the metrics
|
|
183
|
+
* aggregator emits one record per, so deltas written without it land in a second,
|
|
184
|
+
* unattributed bucket for the same session; and the terminality of a missing tool result,
|
|
185
|
+
* which mid-run means "still running" rather than "never finished".
|
|
186
|
+
*
|
|
187
|
+
* The resolved branch outranks any the caller's context carries, because the caller can
|
|
188
|
+
* only know the branch CodeMie was launched on — which is the wrong one precisely when the
|
|
189
|
+
* two differ. See {@link resolveRunGitBranch}.
|
|
190
|
+
*/
|
|
191
|
+
function buildTickContext(options, gitBranch) {
|
|
192
|
+
return {
|
|
193
|
+
...options.buildContext(),
|
|
194
|
+
...(gitBranch && { gitBranch }),
|
|
195
|
+
emitUnresolvedToolCalls: false,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The branch this run's deltas belong under — the one the end-of-run correlation settles on.
|
|
200
|
+
*
|
|
201
|
+
* `correlateRunToSession` rewrites the session record's branch at session end whenever the
|
|
202
|
+
* ledger's cwd is a different checkout than the one CodeMie was launched from, which is
|
|
203
|
+
* what `codemie pi --session /other/repo/x.jsonl` does. The aggregator emits one record per
|
|
204
|
+
* distinct branch, so a tick that stamped the launch branch would split a single session
|
|
205
|
+
* across two branch records. Reading the cwd the ledger records about itself is identity,
|
|
206
|
+
* not attribution.
|
|
207
|
+
*/
|
|
208
|
+
async function resolveRunGitBranch(sessionId, ledgerCwd) {
|
|
209
|
+
try {
|
|
210
|
+
const { SessionStore } = await import('../../../agents/core/session/SessionStore.js');
|
|
211
|
+
const session = await new SessionStore().loadSession(sessionId);
|
|
212
|
+
if (ledgerCwd &&
|
|
213
|
+
session?.workingDirectory &&
|
|
214
|
+
resolve(ledgerCwd) !== resolve(session.workingDirectory)) {
|
|
215
|
+
const { detectGitBranch } = await import('../../../utils/processes.js');
|
|
216
|
+
return (await detectGitBranch(ledgerCwd)) ?? session.gitBranch;
|
|
217
|
+
}
|
|
218
|
+
return session?.gitBranch;
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
logger.debug('[pi-incremental-sync] Could not resolve the run git branch:', error);
|
|
222
|
+
return undefined;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
async function uploadPending(options) {
|
|
226
|
+
if (!options.ssoUrl || !options.syncApiUrl)
|
|
227
|
+
return;
|
|
228
|
+
try {
|
|
229
|
+
const uploadContext = await buildUploadContext(options.sessionId, options.ssoUrl, options.syncApiUrl, options.cliVersion);
|
|
230
|
+
if (!uploadContext)
|
|
231
|
+
return;
|
|
232
|
+
const { SessionSyncer } = await import('../../../providers/plugins/sso/session/SessionSyncer.js');
|
|
233
|
+
const result = await new SessionSyncer().sync(options.sessionId, uploadContext);
|
|
234
|
+
logger.debug(`[pi-incremental-sync] upload ${result.success ? 'ok' : 'partial'}: ${result.message}`);
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
// An upload failure leaves the payloads PENDING; the next tick retries them.
|
|
238
|
+
logger.error('[pi-incremental-sync] upload failed:', error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async function buildUploadContext(sessionId, ssoUrl, syncApiUrl, version = '0.0.0') {
|
|
242
|
+
try {
|
|
243
|
+
const { CodeMieSSO } = await import('../../../providers/plugins/sso/sso.auth.js');
|
|
244
|
+
const credentials = await new CodeMieSSO().getStoredCredentials(ssoUrl);
|
|
245
|
+
if (!credentials?.cookies) {
|
|
246
|
+
logger.debug('[pi-incremental-sync] No SSO credentials available, skipping upload');
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
const cookies = Object.entries(credentials.cookies)
|
|
250
|
+
.map(([name, value]) => `${name}=${value}`)
|
|
251
|
+
.join('; ');
|
|
252
|
+
return {
|
|
253
|
+
apiBaseUrl: syncApiUrl,
|
|
254
|
+
cookies,
|
|
255
|
+
clientType: 'codemie-pi',
|
|
256
|
+
version,
|
|
257
|
+
dryRun: false,
|
|
258
|
+
sessionId,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
logger.debug('[pi-incremental-sync] Failed to build upload context:', error);
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
//# sourceMappingURL=pi.incremental-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.incremental-sync.js","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.incremental-sync.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { LlmModel } from '../../../providers/plugins/sso/sso.http-client.js';
|
|
2
|
+
export interface PiModelClassification {
|
|
3
|
+
provider: 'codemie-proxy' | 'codemie-anthropic';
|
|
4
|
+
api?: 'openai-responses';
|
|
5
|
+
}
|
|
6
|
+
export declare function classifyPiModel(modelId: string): PiModelClassification;
|
|
7
|
+
export interface PiModelEntry {
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
api?: 'openai-responses';
|
|
11
|
+
reasoning?: boolean;
|
|
12
|
+
thinkingLevelMap?: Record<string, string | null>;
|
|
13
|
+
input: ('text' | 'image')[];
|
|
14
|
+
contextWindow: number;
|
|
15
|
+
maxTokens: number;
|
|
16
|
+
compat?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export declare function convertLlmModelToPiEntry(model: LlmModel): PiModelEntry;
|
|
19
|
+
export declare function fetchAndBuildPiModels(env: NodeJS.ProcessEnv, cwd?: string): Promise<void>;
|
|
20
|
+
//# sourceMappingURL=pi.models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.models.d.ts","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.models.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mDAAmD,CAAC;AAMlF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,eAAe,GAAG,mBAAmB,CAAC;IAChD,GAAG,CAAC,EAAE,kBAAkB,CAAC;CAC1B;AAiBD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,CAQtE;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,kBAAkB,CAAC;IACzB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACjD,KAAK,EAAE,CAAC,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AA0CD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,QAAQ,GAAG,YAAY,CAgCtE;AAqGD,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAgCf"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { mkdir, writeFile } from 'fs/promises';
|
|
2
|
+
import { fetchCodeMieLlmModels } from '../../../providers/plugins/sso/sso.http-client.js';
|
|
3
|
+
import { CodeMieSSO } from '../../../providers/plugins/sso/sso.auth.js';
|
|
4
|
+
import { logger } from '../../../utils/logger.js';
|
|
5
|
+
import { getPiAgentDir, getPiModelsPath } from './pi.paths.js';
|
|
6
|
+
const RESPONSES_API_PATTERNS = [
|
|
7
|
+
/^gpt-5-2-/,
|
|
8
|
+
/^gpt-5\.2-/,
|
|
9
|
+
/^gpt-5-1-codex/,
|
|
10
|
+
/^gpt-5\.1-codex/,
|
|
11
|
+
/^gpt-5-3-codex/,
|
|
12
|
+
/^gpt-5\.3-codex/,
|
|
13
|
+
/^gpt-5\.4-/,
|
|
14
|
+
/^gpt-5-4-/,
|
|
15
|
+
/^gpt-5\.5-/,
|
|
16
|
+
/^gpt-5-5-/,
|
|
17
|
+
/^gpt-5\.6-/,
|
|
18
|
+
/^gpt-5-6-/,
|
|
19
|
+
];
|
|
20
|
+
export function classifyPiModel(modelId) {
|
|
21
|
+
if (modelId.startsWith('claude')) {
|
|
22
|
+
return { provider: 'codemie-anthropic' };
|
|
23
|
+
}
|
|
24
|
+
if (RESPONSES_API_PATTERNS.some(pattern => pattern.test(modelId))) {
|
|
25
|
+
return { provider: 'codemie-proxy', api: 'openai-responses' };
|
|
26
|
+
}
|
|
27
|
+
return { provider: 'codemie-proxy' };
|
|
28
|
+
}
|
|
29
|
+
function detectLimits(id) {
|
|
30
|
+
if (id.startsWith('claude'))
|
|
31
|
+
return { contextWindow: 200000, maxTokens: 64000 };
|
|
32
|
+
if (id.startsWith('gemini'))
|
|
33
|
+
return { contextWindow: 1048576, maxTokens: 65536 };
|
|
34
|
+
if (id.startsWith('gpt-4.1'))
|
|
35
|
+
return { contextWindow: 1048576, maxTokens: 32768 };
|
|
36
|
+
if (/^gpt-5\.5-/.test(id) || /^gpt-5-5-/.test(id))
|
|
37
|
+
return { contextWindow: 1050000, maxTokens: 128000 };
|
|
38
|
+
if (/^gpt-5\.6-/.test(id) || /^gpt-5-6-/.test(id))
|
|
39
|
+
return { contextWindow: 1050000, maxTokens: 128000 };
|
|
40
|
+
if (id.startsWith('gpt-5'))
|
|
41
|
+
return { contextWindow: 400000, maxTokens: 128000 };
|
|
42
|
+
if (/^o[134]-/.test(id) || id === 'o1')
|
|
43
|
+
return { contextWindow: 200000, maxTokens: 100000 };
|
|
44
|
+
if (id.startsWith('qwen') || id.startsWith('moonshotai') || id.startsWith('kimi')) {
|
|
45
|
+
return { contextWindow: 262144, maxTokens: 131072 };
|
|
46
|
+
}
|
|
47
|
+
if (id.startsWith('deepseek'))
|
|
48
|
+
return { contextWindow: 65536, maxTokens: 65536 };
|
|
49
|
+
return { contextWindow: 128000, maxTokens: 4096 };
|
|
50
|
+
}
|
|
51
|
+
function defaultThinkingLevelMap() {
|
|
52
|
+
return {
|
|
53
|
+
off: null,
|
|
54
|
+
minimal: 'minimal',
|
|
55
|
+
low: 'low',
|
|
56
|
+
medium: 'medium',
|
|
57
|
+
high: 'high',
|
|
58
|
+
xhigh: 'high',
|
|
59
|
+
max: 'high',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function isReasoningModel(id) {
|
|
63
|
+
return (id.startsWith('claude') ||
|
|
64
|
+
id.startsWith('gemini') ||
|
|
65
|
+
id.startsWith('gpt-5') ||
|
|
66
|
+
/^o[134]-/.test(id) ||
|
|
67
|
+
id === 'o1' ||
|
|
68
|
+
id.startsWith('deepseek') ||
|
|
69
|
+
id.startsWith('moonshotai') ||
|
|
70
|
+
id.startsWith('kimi'));
|
|
71
|
+
}
|
|
72
|
+
export function convertLlmModelToPiEntry(model) {
|
|
73
|
+
const id = model.deployment_name || model.base_name || model.label;
|
|
74
|
+
const limits = detectLimits(id);
|
|
75
|
+
const entry = {
|
|
76
|
+
id,
|
|
77
|
+
name: model.label || id,
|
|
78
|
+
input: model.multimodal ? ['text', 'image'] : ['text'],
|
|
79
|
+
contextWindow: limits.contextWindow,
|
|
80
|
+
maxTokens: limits.maxTokens,
|
|
81
|
+
};
|
|
82
|
+
const classification = classifyPiModel(id);
|
|
83
|
+
if (classification.api) {
|
|
84
|
+
entry.api = classification.api;
|
|
85
|
+
}
|
|
86
|
+
if (isReasoningModel(id)) {
|
|
87
|
+
entry.reasoning = true;
|
|
88
|
+
entry.thinkingLevelMap = defaultThinkingLevelMap();
|
|
89
|
+
}
|
|
90
|
+
if (id.startsWith('claude-sonnet-4-6') ||
|
|
91
|
+
id.startsWith('claude-sonnet-5') ||
|
|
92
|
+
/^claude-opus-4-[6-8]/.test(id) ||
|
|
93
|
+
id.startsWith('claude-opus-5')) {
|
|
94
|
+
entry.compat = { forceAdaptiveThinking: true };
|
|
95
|
+
}
|
|
96
|
+
return entry;
|
|
97
|
+
}
|
|
98
|
+
async function fetchCodeMieModels(env) {
|
|
99
|
+
const jwtToken = env.CODEMIE_JWT_TOKEN;
|
|
100
|
+
const baseUrl = env.CODEMIE_BASE_URL;
|
|
101
|
+
if (jwtToken && baseUrl) {
|
|
102
|
+
logger.debug('[pi-models] Fetching CodeMie model list via JWT auth');
|
|
103
|
+
return fetchCodeMieLlmModels(baseUrl, jwtToken);
|
|
104
|
+
}
|
|
105
|
+
const codeMieUrl = env.CODEMIE_URL;
|
|
106
|
+
if (codeMieUrl) {
|
|
107
|
+
const sso = new CodeMieSSO();
|
|
108
|
+
const credentials = await sso.getStoredCredentials(codeMieUrl);
|
|
109
|
+
if (!credentials) {
|
|
110
|
+
throw new Error(`SSO credentials not found for ${codeMieUrl}. Run: codemie profile login --url ${codeMieUrl}`);
|
|
111
|
+
}
|
|
112
|
+
logger.debug('[pi-models] Fetching CodeMie model list via SSO auth');
|
|
113
|
+
return fetchCodeMieLlmModels(credentials.apiUrl, credentials.cookies);
|
|
114
|
+
}
|
|
115
|
+
throw new Error('No CodeMie authentication available. Run codemie setup or set CODEMIE_JWT_TOKEN.');
|
|
116
|
+
}
|
|
117
|
+
function buildModelsConfig(entries, baseUrl, apiKey) {
|
|
118
|
+
const proxyModels = [];
|
|
119
|
+
const anthropicModels = [];
|
|
120
|
+
for (const entry of entries) {
|
|
121
|
+
const classification = classifyPiModel(entry.id);
|
|
122
|
+
if (classification.provider === 'codemie-anthropic') {
|
|
123
|
+
anthropicModels.push(entry);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
proxyModels.push(entry);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const providers = {};
|
|
130
|
+
if (proxyModels.length > 0) {
|
|
131
|
+
providers['codemie-proxy'] = {
|
|
132
|
+
baseUrl: `${baseUrl.replace(/\/$/, '')}/v1`,
|
|
133
|
+
api: 'openai-completions',
|
|
134
|
+
apiKey,
|
|
135
|
+
compat: {
|
|
136
|
+
supportsReasoningEffort: true,
|
|
137
|
+
thinkingFormat: 'reasoning_effort',
|
|
138
|
+
},
|
|
139
|
+
models: proxyModels,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
if (anthropicModels.length > 0) {
|
|
143
|
+
providers['codemie-anthropic'] = {
|
|
144
|
+
baseUrl: baseUrl.replace(/\/$/, ''),
|
|
145
|
+
api: 'anthropic-messages',
|
|
146
|
+
apiKey,
|
|
147
|
+
authHeader: true,
|
|
148
|
+
compat: {
|
|
149
|
+
supportsReasoningEffort: true,
|
|
150
|
+
thinkingFormat: 'reasoning_effort',
|
|
151
|
+
},
|
|
152
|
+
models: anthropicModels,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
return { providers };
|
|
156
|
+
}
|
|
157
|
+
function createSyntheticLlmModel(modelId) {
|
|
158
|
+
return {
|
|
159
|
+
base_name: modelId,
|
|
160
|
+
deployment_name: modelId,
|
|
161
|
+
label: modelId,
|
|
162
|
+
enabled: true,
|
|
163
|
+
multimodal: false,
|
|
164
|
+
features: {},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function buildStaticFallbackModel(modelId, baseUrl, apiKey) {
|
|
168
|
+
const entry = convertLlmModelToPiEntry(createSyntheticLlmModel(modelId));
|
|
169
|
+
return buildModelsConfig([entry], baseUrl, apiKey);
|
|
170
|
+
}
|
|
171
|
+
export async function fetchAndBuildPiModels(env, cwd = process.cwd()) {
|
|
172
|
+
const agentDir = getPiAgentDir(cwd);
|
|
173
|
+
await mkdir(agentDir, { recursive: true });
|
|
174
|
+
const baseUrl = env.CODEMIE_BASE_URL || '';
|
|
175
|
+
const apiKey = env.CODEMIE_API_KEY || 'proxy-handled';
|
|
176
|
+
let entries = [];
|
|
177
|
+
try {
|
|
178
|
+
const rawModels = await fetchCodeMieModels(env);
|
|
179
|
+
entries = rawModels
|
|
180
|
+
.filter(model => model.enabled)
|
|
181
|
+
.map(convertLlmModelToPiEntry);
|
|
182
|
+
logger.debug(`[pi-models] Loaded ${entries.length} models from CodeMie API`);
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
186
|
+
logger.warn(`[pi-models] Failed to fetch live models, falling back to static model: ${message}`);
|
|
187
|
+
const configuredModel = env.CODEMIE_MODEL;
|
|
188
|
+
if (!configuredModel) {
|
|
189
|
+
throw new Error('No CodeMie model configured and live model fetch failed.');
|
|
190
|
+
}
|
|
191
|
+
const fallback = buildStaticFallbackModel(configuredModel, baseUrl, apiKey);
|
|
192
|
+
await writeFile(getPiModelsPath(cwd), JSON.stringify(fallback, null, 2), 'utf-8');
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (entries.length === 0) {
|
|
196
|
+
throw new Error('CodeMie returned no enabled models for codemie-pi.');
|
|
197
|
+
}
|
|
198
|
+
const config = buildModelsConfig(entries, baseUrl, apiKey);
|
|
199
|
+
await writeFile(getPiModelsPath(cwd), JSON.stringify(config, null, 2), 'utf-8');
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=pi.models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.models.js","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const REQUIRED_PI_PACKAGES: readonly string[];
|
|
2
|
+
export interface InstallPiPackagesOptions {
|
|
3
|
+
/** Pi CLI command name or path (default: 'pi') */
|
|
4
|
+
cliCommand?: string | null;
|
|
5
|
+
/** Working directory for the install commands (default: process.cwd()) */
|
|
6
|
+
cwd?: string;
|
|
7
|
+
/** Per-package timeout in milliseconds (default: 300000) */
|
|
8
|
+
timeout?: number;
|
|
9
|
+
}
|
|
10
|
+
export declare function installRequiredPiPackages(options?: InstallPiPackagesOptions): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=pi.packages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.packages.d.ts","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.packages.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAIjD,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,kDAAkD;IAClD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAID,wBAAsB,yBAAyB,CAC7C,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,IAAI,CAAC,CAkCf"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { exec } from '../../../utils/exec.js';
|
|
2
|
+
import { logger } from '../../../utils/logger.js';
|
|
3
|
+
import { AgentInstallationError } from '../../../utils/errors.js';
|
|
4
|
+
export const REQUIRED_PI_PACKAGES = [
|
|
5
|
+
'git:github.com/obra/superpowers',
|
|
6
|
+
'npm:pi-subagents',
|
|
7
|
+
'npm:pi-mcp-adapter',
|
|
8
|
+
];
|
|
9
|
+
const DEFAULT_TIMEOUT_MS = 300_000;
|
|
10
|
+
export async function installRequiredPiPackages(options = {}) {
|
|
11
|
+
const cliCommand = options.cliCommand || 'pi';
|
|
12
|
+
const cwd = options.cwd ?? process.cwd();
|
|
13
|
+
const timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
14
|
+
logger.info(`[pi] Installing required Pi packages using ${cliCommand}`);
|
|
15
|
+
for (const pkg of REQUIRED_PI_PACKAGES) {
|
|
16
|
+
logger.info(`[pi] Installing package: ${pkg}`);
|
|
17
|
+
let result;
|
|
18
|
+
try {
|
|
19
|
+
result = await exec(cliCommand, ['install', pkg], {
|
|
20
|
+
cwd,
|
|
21
|
+
timeout,
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
26
|
+
throw new AgentInstallationError('pi', `Failed to install Pi package "${pkg}": ${message}`);
|
|
27
|
+
}
|
|
28
|
+
if (result.code !== 0) {
|
|
29
|
+
const output = [result.stdout, result.stderr].filter(Boolean).join('\n');
|
|
30
|
+
throw new AgentInstallationError('pi', `Failed to install Pi package "${pkg}": ${output}`);
|
|
31
|
+
}
|
|
32
|
+
logger.success(`[pi] Installed package: ${pkg}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=pi.packages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.packages.js","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.packages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,CAAC,MAAM,oBAAoB,GAAsB;IACrD,iCAAiC;IACjC,kBAAkB;IAClB,oBAAoB;CACrB,CAAC;AAWF,MAAM,kBAAkB,GAAG,OAAO,CAAC;AAEnC,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,UAAoC,EAAE;IAEtC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,kBAAkB,CAAC;IAEtD,MAAM,CAAC,IAAI,CAAC,8CAA8C,UAAU,EAAE,CAAC,CAAC;IAExE,KAAK,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,4BAA4B,GAAG,EAAE,CAAC,CAAC;QAE/C,IAAI,MAAkB,CAAC;QACvB,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,GAAG,CAAC,EAAE;gBAChD,GAAG;gBACH,OAAO;aACR,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,sBAAsB,CAC9B,IAAI,EACJ,iCAAiC,GAAG,MAAM,OAAO,EAAE,CACpD,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACzE,MAAM,IAAI,sBAAsB,CAC9B,IAAI,EACJ,iCAAiC,GAAG,MAAM,MAAM,EAAE,CACnD,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,OAAO,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export declare function getUserPiAgentDir(): string;
|
|
2
|
+
export declare function getPiAgentDir(cwd?: string): string;
|
|
3
|
+
export declare function getPiModelsPath(cwd?: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* Compute the default Pi session storage directory for a given cwd.
|
|
6
|
+
*
|
|
7
|
+
* Pi encodes the cwd as `--<cwd with leading slash removed and path
|
|
8
|
+
* separators/colons replaced by dashes>--` under the agent dir's `sessions/`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getPiSessionDir(cwd?: string): string;
|
|
11
|
+
export interface PiSessionDirResolution {
|
|
12
|
+
/**
|
|
13
|
+
* Where Pi keeps this project's transcripts. Always an absolute path, so every caller
|
|
14
|
+
* may hand it to Pi and to the filesystem without a further check.
|
|
15
|
+
*/
|
|
16
|
+
sessionDir: string;
|
|
17
|
+
/** Whether the user configured a usable directory of their own. */
|
|
18
|
+
isCustom: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the effective Pi session directory: the configured one when it has a path form,
|
|
22
|
+
* the default per-cwd encoded directory from {@link getPiSessionDir} otherwise.
|
|
23
|
+
*
|
|
24
|
+
* Falling back is not a substitute directory handed to Pi. `isCustom` is false with it, so
|
|
25
|
+
* no caller injects `PI_CODING_AGENT_SESSION_DIR`, and Pi still reads the user's own value
|
|
26
|
+
* from the flag, the environment, or `settings.json` and aborts on it exactly as a bare
|
|
27
|
+
* `pi` would — the wrapper neither rescues the run nor relocates the transcripts of one
|
|
28
|
+
* that works.
|
|
29
|
+
*
|
|
30
|
+
* What the fallback does prevent is a value with no path form reaching the filesystem.
|
|
31
|
+
* Every unresolvable value is a `file://` URL, and to `existsSync` those are RELATIVE
|
|
32
|
+
* paths: `file://bad` is `<cwd>/file:/bad`, an ordinary directory any working tree may
|
|
33
|
+
* happen to contain. Returning one would have discovery list whatever `.jsonl` files live
|
|
34
|
+
* there and upload them as this session's transcripts.
|
|
35
|
+
*/
|
|
36
|
+
export declare function resolvePiSessionDir(cwd?: string, env?: NodeJS.ProcessEnv): PiSessionDirResolution;
|
|
37
|
+
//# sourceMappingURL=pi.paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pi.paths.d.ts","sourceRoot":"","sources":["../../../../src/agents/plugins/pi/pi.paths.ts"],"names":[],"mappings":"AAMA,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,aAAa,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAEjE;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAInE;AAED,MAAM,WAAW,sBAAsB;IACrC;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAC;CACnB;AAqGD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAsB,EAC3B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,sBAAsB,CAaxB"}
|