@agents-ensemble/core 0.21.0 → 0.22.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/assets/pi/pi-cli-env-wrapper.cmd +28 -0
- package/assets/pi/pi-cli-env-wrapper.sh +19 -0
- package/assets/pi/settings.json +4 -0
- package/dist/acp/acp-preset-bins.d.ts +3 -3
- package/dist/acp/acp-preset-bins.d.ts.map +1 -1
- package/dist/acp/acp-preset-bins.js +3 -3
- package/dist/acp/acp-preset-bins.js.map +1 -1
- package/dist/acp/index.d.ts +3 -1
- package/dist/acp/index.d.ts.map +1 -1
- package/dist/acp/index.js +2 -1
- package/dist/acp/index.js.map +1 -1
- package/dist/acp/pi-acp-wrapper.d.ts +3 -0
- package/dist/acp/pi-acp-wrapper.d.ts.map +1 -0
- package/dist/acp/pi-acp-wrapper.js +41 -0
- package/dist/acp/pi-acp-wrapper.js.map +1 -0
- package/dist/acp/pi-builtin-config.d.ts +10 -0
- package/dist/acp/pi-builtin-config.d.ts.map +1 -0
- package/dist/acp/pi-builtin-config.js +36 -0
- package/dist/acp/pi-builtin-config.js.map +1 -0
- package/dist/acp/pi-runtime.d.ts +23 -0
- package/dist/acp/pi-runtime.d.ts.map +1 -0
- package/dist/acp/pi-runtime.js +160 -0
- package/dist/acp/pi-runtime.js.map +1 -0
- package/dist/acp/pi-session-map.d.ts +36 -0
- package/dist/acp/pi-session-map.d.ts.map +1 -0
- package/dist/acp/pi-session-map.js +266 -0
- package/dist/acp/pi-session-map.js.map +1 -0
- package/dist/acp/resolve-acp-spawn.d.ts +9 -3
- package/dist/acp/resolve-acp-spawn.d.ts.map +1 -1
- package/dist/acp/resolve-acp-spawn.js +41 -9
- package/dist/acp/resolve-acp-spawn.js.map +1 -1
- package/dist/acp/resolve-bundled-acp-bin.d.ts +2 -2
- package/dist/acp/resolve-bundled-acp-bin.d.ts.map +1 -1
- package/dist/acp/resolve-bundled-acp-bin.js +4 -4
- package/dist/acp/resolve-bundled-acp-bin.js.map +1 -1
- package/dist/acp/validate-acp-preset-prerequisites.d.ts +1 -1
- package/dist/acp/validate-acp-preset-prerequisites.d.ts.map +1 -1
- package/dist/acp/validate-acp-preset-prerequisites.js +30 -10
- package/dist/acp/validate-acp-preset-prerequisites.js.map +1 -1
- package/dist/conductor/conductor-agent.d.ts +15 -3
- package/dist/conductor/conductor-agent.d.ts.map +1 -1
- package/dist/conductor/conductor-auth.d.ts +2 -3
- package/dist/conductor/conductor-auth.d.ts.map +1 -1
- package/dist/conductor/conductor-auth.js +5 -2
- package/dist/conductor/conductor-auth.js.map +1 -1
- package/dist/conductor/conductor-dispatch-lifecycle.d.ts +85 -0
- package/dist/conductor/conductor-dispatch-lifecycle.d.ts.map +1 -0
- package/dist/conductor/conductor-dispatch-lifecycle.js +190 -0
- package/dist/conductor/conductor-dispatch-lifecycle.js.map +1 -0
- package/dist/conductor/conductor-history.d.ts +6 -0
- package/dist/conductor/conductor-history.d.ts.map +1 -1
- package/dist/conductor/conductor-history.js +11 -6
- package/dist/conductor/conductor-history.js.map +1 -1
- package/dist/conductor/conductor-path-safety.d.ts +23 -0
- package/dist/conductor/conductor-path-safety.d.ts.map +1 -0
- package/dist/conductor/conductor-path-safety.js +319 -0
- package/dist/conductor/conductor-path-safety.js.map +1 -0
- package/dist/conductor/conductor-pi-auth.d.ts +57 -2
- package/dist/conductor/conductor-pi-auth.d.ts.map +1 -1
- package/dist/conductor/conductor-pi-auth.js +718 -40
- package/dist/conductor/conductor-pi-auth.js.map +1 -1
- package/dist/conductor/conductor-recovery-inbox.d.ts +73 -0
- package/dist/conductor/conductor-recovery-inbox.d.ts.map +1 -0
- package/dist/conductor/conductor-recovery-inbox.js +181 -0
- package/dist/conductor/conductor-recovery-inbox.js.map +1 -0
- package/dist/conductor/conductor-send-reconnect.d.ts +27 -5
- package/dist/conductor/conductor-send-reconnect.d.ts.map +1 -1
- package/dist/conductor/conductor-send-reconnect.js +88 -39
- package/dist/conductor/conductor-send-reconnect.js.map +1 -1
- package/dist/conductor/conductor-session-driver.d.ts +32 -7
- package/dist/conductor/conductor-session-driver.d.ts.map +1 -1
- package/dist/conductor/conductor-session-driver.js +474 -233
- package/dist/conductor/conductor-session-driver.js.map +1 -1
- package/dist/conductor/conductor-session.d.ts +2 -0
- package/dist/conductor/conductor-session.d.ts.map +1 -1
- package/dist/conductor/conductor-session.js +404 -156
- package/dist/conductor/conductor-session.js.map +1 -1
- package/dist/conductor/conductor-setup.d.ts +30 -0
- package/dist/conductor/conductor-setup.d.ts.map +1 -0
- package/dist/conductor/conductor-setup.js +243 -0
- package/dist/conductor/conductor-setup.js.map +1 -0
- package/dist/conductor/cursor-bootstrap-state.d.ts +9 -0
- package/dist/conductor/cursor-bootstrap-state.d.ts.map +1 -0
- package/dist/conductor/cursor-bootstrap-state.js +11 -0
- package/dist/conductor/cursor-bootstrap-state.js.map +1 -0
- package/dist/conductor/cursor-run-snapshots.d.ts +30 -0
- package/dist/conductor/cursor-run-snapshots.d.ts.map +1 -0
- package/dist/conductor/cursor-run-snapshots.js +120 -0
- package/dist/conductor/cursor-run-snapshots.js.map +1 -0
- package/dist/conductor/index.d.ts +15 -6
- package/dist/conductor/index.d.ts.map +1 -1
- package/dist/conductor/index.js +8 -4
- package/dist/conductor/index.js.map +1 -1
- package/dist/conductor/operator-command.d.ts +1 -1
- package/dist/conductor/operator-command.js +1 -1
- package/dist/conductor/operator-command.js.map +1 -1
- package/dist/conductor/operator-input-binding.d.ts +12 -0
- package/dist/conductor/operator-input-binding.d.ts.map +1 -1
- package/dist/conductor/pi-auth-recovery-snapshot-store.d.ts +4 -1
- package/dist/conductor/pi-auth-recovery-snapshot-store.d.ts.map +1 -1
- package/dist/conductor/pi-auth-recovery-snapshot-store.js +4 -1
- package/dist/conductor/pi-auth-recovery-snapshot-store.js.map +1 -1
- package/dist/conductor/pi-conductor-agent.d.ts +6 -3
- package/dist/conductor/pi-conductor-agent.d.ts.map +1 -1
- package/dist/conductor/pi-conductor-agent.js +272 -53
- package/dist/conductor/pi-conductor-agent.js.map +1 -1
- package/dist/conductor/pi-conductor-session-file.d.ts +13 -0
- package/dist/conductor/pi-conductor-session-file.d.ts.map +1 -0
- package/dist/conductor/pi-conductor-session-file.js +21 -0
- package/dist/conductor/pi-conductor-session-file.js.map +1 -0
- package/dist/conductor/pi-resource-loader.d.ts +6 -0
- package/dist/conductor/pi-resource-loader.d.ts.map +1 -1
- package/dist/conductor/pi-resource-loader.js +26 -12
- package/dist/conductor/pi-resource-loader.js.map +1 -1
- package/dist/conductor/pi-user-root-lock.d.ts +8 -0
- package/dist/conductor/pi-user-root-lock.d.ts.map +1 -0
- package/dist/conductor/pi-user-root-lock.js +53 -0
- package/dist/conductor/pi-user-root-lock.js.map +1 -0
- package/dist/conductor/recovery-inbox-command.d.ts +29 -0
- package/dist/conductor/recovery-inbox-command.d.ts.map +1 -0
- package/dist/conductor/recovery-inbox-command.js +248 -0
- package/dist/conductor/recovery-inbox-command.js.map +1 -0
- package/dist/conductor/session/events/session-event.d.ts +15 -2
- package/dist/conductor/session/events/session-event.d.ts.map +1 -1
- package/dist/conductor/session/events/session-log-event-groups.d.ts +1 -1
- package/dist/conductor/session/events/session-log-event-groups.d.ts.map +1 -1
- package/dist/conductor/session/events/session-log-event-groups.js +1 -0
- package/dist/conductor/session/events/session-log-event-groups.js.map +1 -1
- package/dist/conductor/session/events/session-log-event.d.ts +4 -0
- package/dist/conductor/session/events/session-log-event.d.ts.map +1 -1
- package/dist/conductor/session/format-session-event.js +25 -4
- package/dist/conductor/session/format-session-event.js.map +1 -1
- package/dist/conductor/session/select-dispatch-batch.d.ts +2 -0
- package/dist/conductor/session/select-dispatch-batch.d.ts.map +1 -1
- package/dist/conductor/session/select-dispatch-batch.js +31 -2
- package/dist/conductor/session/select-dispatch-batch.js.map +1 -1
- package/dist/conductor/session/session-event-queue.d.ts +5 -0
- package/dist/conductor/session/session-event-queue.d.ts.map +1 -1
- package/dist/conductor/session/session-event-queue.js +41 -4
- package/dist/conductor/session/session-event-queue.js.map +1 -1
- package/dist/conductor/session/session-event.d.ts +1 -1
- package/dist/conductor/session/session-event.d.ts.map +1 -1
- package/dist/conductor/session-policy.d.ts.map +1 -1
- package/dist/conductor/session-policy.js +4 -2
- package/dist/conductor/session-policy.js.map +1 -1
- package/dist/conductor/submit-operator-input.d.ts +3 -0
- package/dist/conductor/submit-operator-input.d.ts.map +1 -1
- package/dist/conductor/submit-operator-input.js +21 -0
- package/dist/conductor/submit-operator-input.js.map +1 -1
- package/dist/config/deep-merge.d.ts.map +1 -1
- package/dist/config/deep-merge.js +13 -3
- package/dist/config/deep-merge.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +1 -1
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/doctor-settings.d.ts +59 -0
- package/dist/config/doctor-settings.d.ts.map +1 -0
- package/dist/config/doctor-settings.js +343 -0
- package/dist/config/doctor-settings.js.map +1 -0
- package/dist/config/ensemble-config-digest.d.ts +2 -4
- package/dist/config/ensemble-config-digest.d.ts.map +1 -1
- package/dist/config/ensemble-config-digest.js +2 -4
- package/dist/config/ensemble-config-digest.js.map +1 -1
- package/dist/config/index.d.ts +3 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +1 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/load-ensemble-config.d.ts.map +1 -1
- package/dist/config/load-ensemble-config.js +8 -1
- package/dist/config/load-ensemble-config.js.map +1 -1
- package/dist/config/parse-config.d.ts.map +1 -1
- package/dist/config/parse-config.js +34 -14
- package/dist/config/parse-config.js.map +1 -1
- package/dist/config/resolve-settings.d.ts +3 -1
- package/dist/config/resolve-settings.d.ts.map +1 -1
- package/dist/config/resolve-settings.js +7 -4
- package/dist/config/resolve-settings.js.map +1 -1
- package/dist/config/types.d.ts +14 -5
- package/dist/config/types.d.ts.map +1 -1
- package/dist/dispatch/attach-worker.js +1 -1
- package/dist/dispatch/attach-worker.js.map +1 -1
- package/dist/dispatch/worker-acp-session.d.ts +21 -3
- package/dist/dispatch/worker-acp-session.d.ts.map +1 -1
- package/dist/dispatch/worker-acp-session.js +50 -13
- package/dist/dispatch/worker-acp-session.js.map +1 -1
- package/dist/ensemble-paths.d.ts +19 -19
- package/dist/ensemble-paths.d.ts.map +1 -1
- package/dist/ensemble-paths.js +40 -22
- package/dist/ensemble-paths.js.map +1 -1
- package/dist/issue/resolve-issue-url.d.ts +4 -0
- package/dist/issue/resolve-issue-url.d.ts.map +1 -1
- package/dist/issue/resolve-issue-url.js +2 -2
- package/dist/issue/resolve-issue-url.js.map +1 -1
- package/dist/operator-runtime.d.ts +17 -4
- package/dist/operator-runtime.d.ts.map +1 -1
- package/dist/operator-runtime.js +12 -3
- package/dist/operator-runtime.js.map +1 -1
- package/dist/profile/types.d.ts +4 -0
- package/dist/profile/types.d.ts.map +1 -1
- package/dist/profile/types.js +29 -12
- package/dist/profile/types.js.map +1 -1
- package/dist/representation/escape-terminal-control-characters.d.ts +9 -0
- package/dist/representation/escape-terminal-control-characters.d.ts.map +1 -0
- package/dist/representation/escape-terminal-control-characters.js +34 -0
- package/dist/representation/escape-terminal-control-characters.js.map +1 -0
- package/dist/representation/index.d.ts +1 -0
- package/dist/representation/index.d.ts.map +1 -1
- package/dist/representation/index.js +1 -0
- package/dist/representation/index.js.map +1 -1
- package/dist/runtime/types.d.ts +9 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/worker-runtime.d.ts +14 -1
- package/dist/runtime/worker-runtime.d.ts.map +1 -1
- package/dist/runtime/worker-runtime.js +197 -50
- package/dist/runtime/worker-runtime.js.map +1 -1
- package/dist/runtime/worker-session.d.ts +2 -1
- package/dist/runtime/worker-session.d.ts.map +1 -1
- package/dist/runtime/worker-session.js +1 -0
- package/dist/runtime/worker-session.js.map +1 -1
- package/dist/session/export-session-bundle.d.ts +77 -0
- package/dist/session/export-session-bundle.d.ts.map +1 -0
- package/dist/session/export-session-bundle.js +640 -0
- package/dist/session/export-session-bundle.js.map +1 -0
- package/dist/session/index.d.ts +4 -3
- package/dist/session/index.d.ts.map +1 -1
- package/dist/session/index.js +2 -1
- package/dist/session/index.js.map +1 -1
- package/dist/session/open-question-control.d.ts +9 -0
- package/dist/session/open-question-control.d.ts.map +1 -1
- package/dist/session/open-question-control.js +26 -1
- package/dist/session/open-question-control.js.map +1 -1
- package/dist/session/open-questions-store.d.ts +1 -1
- package/dist/session/open-questions-store.d.ts.map +1 -1
- package/dist/session/open-questions-store.js +3 -6
- package/dist/session/open-questions-store.js.map +1 -1
- package/dist/session/persisted-file.d.ts +5 -0
- package/dist/session/persisted-file.d.ts.map +1 -0
- package/dist/session/persisted-file.js +56 -0
- package/dist/session/persisted-file.js.map +1 -0
- package/dist/session/session-resume-store.d.ts +77 -10
- package/dist/session/session-resume-store.d.ts.map +1 -1
- package/dist/session/session-resume-store.js +346 -83
- package/dist/session/session-resume-store.js.map +1 -1
- package/dist/session/session-snapshot-paths.d.ts +7 -1
- package/dist/session/session-snapshot-paths.d.ts.map +1 -1
- package/dist/session/session-snapshot-paths.js +29 -26
- package/dist/session/session-snapshot-paths.js.map +1 -1
- package/dist/session/session-state-store.d.ts +2 -2
- package/dist/session/session-state-store.d.ts.map +1 -1
- package/dist/session/session-state-store.js +5 -16
- package/dist/session/session-state-store.js.map +1 -1
- package/dist/session/tool-call-snapshot-history.d.ts +12 -1
- package/dist/session/tool-call-snapshot-history.d.ts.map +1 -1
- package/dist/session/tool-call-snapshot-history.js +75 -70
- package/dist/session/tool-call-snapshot-history.js.map +1 -1
- package/dist/session/worker-session-history.d.ts +13 -1
- package/dist/session/worker-session-history.d.ts.map +1 -1
- package/dist/session/worker-session-history.js +171 -50
- package/dist/session/worker-session-history.js.map +1 -1
- package/dist/workspace/index.d.ts +1 -1
- package/dist/workspace/index.d.ts.map +1 -1
- package/dist/worktree/worktree.d.ts +6 -1
- package/dist/worktree/worktree.d.ts.map +1 -1
- package/dist/worktree/worktree.js +123 -2
- package/dist/worktree/worktree.js.map +1 -1
- package/package.json +9 -4
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { basename, join } from 'node:path';
|
|
2
|
+
import { chmod, mkdir } from 'node:fs/promises';
|
|
3
|
+
import { basename } from 'node:path';
|
|
5
4
|
import { getModel, getModels, getProviders, } from '@earendil-works/pi-ai/compat';
|
|
6
|
-
import { getSupportedThinkingLevels, } from '@earendil-works/pi-ai';
|
|
5
|
+
import { createAssistantMessageEventStream, getSupportedThinkingLevels, } from '@earendil-works/pi-ai';
|
|
7
6
|
import { ModelsError } from '@earendil-works/pi-ai/models';
|
|
8
7
|
import { createAgentSession, createCodemodeExtension, createMcpExtension, createToolSearchExtension, DefaultResourceLoader, SessionManager, SettingsManager, } from '@earendil-works/pi-coding-agent';
|
|
9
8
|
import { resolveEnsemblePaths } from '../ensemble-paths.js';
|
|
10
|
-
import { createPiConductorAuthContext, resolvePiConductorApiKey, } from './conductor-pi-auth.js';
|
|
9
|
+
import { createPiConductorAuthContext, hasPiConductorCommandCredential, preparePiConductorCommandAuthForRequest, resolvePiConductorApiKey, } from './conductor-pi-auth.js';
|
|
11
10
|
import { markConductorAgentFactoryCleanupIncomplete } from './conductor-agent-factory-cleanup.js';
|
|
12
11
|
import { toPiCodingAgentTools } from './conductor-tool-pi-adapter.js';
|
|
13
12
|
import { getPiHeadlessSettingsManagerOverrides, getPiHeadlessSetting, getPiSkillsDiscoverySettingsOverrides, } from './pi-headless-settings.js';
|
|
14
13
|
import { expandPiResourcePrompt, loadPiResources, } from './pi-resource-loader.js';
|
|
15
|
-
/** Project-local Pi transcript storage used by the conductor backend. */
|
|
16
|
-
export const PI_SESSION_ROOT = '.ensemble/pi/sessions';
|
|
17
14
|
export const PI_CONDUCTOR_MESSAGE_HISTORY_ENTRY_TYPE = 'agents-ensemble/conductor-message-history/v1';
|
|
18
15
|
const PI_MCP_STARTUP_OBSERVATION_MS = 2_000;
|
|
16
|
+
const PI_COMMAND_RESOLUTION_ERROR_MESSAGE = 'API key auth failed for provider: failed to resolve API key for Pi provider from the configured command.';
|
|
19
17
|
const PI_THINKING_LEVELS = [
|
|
20
18
|
'off',
|
|
21
19
|
'minimal',
|
|
@@ -31,7 +29,7 @@ export async function resolvePiModelConfig(options) {
|
|
|
31
29
|
const authContext = await createPiConductorAuthContext(options, resources);
|
|
32
30
|
return resolvePiModelConfigFromResources(options, resources, authContext);
|
|
33
31
|
}
|
|
34
|
-
async function resolvePiModelConfigFromResources(options, resources, authContext) {
|
|
32
|
+
async function resolvePiModelConfigFromResources(options, resources, authContext, commandAuthRequestGate) {
|
|
35
33
|
const env = options.env ?? process.env;
|
|
36
34
|
const settings = resources.settings;
|
|
37
35
|
const selection = resolvePiModelSelection(options.modelId, settings, resources.models);
|
|
@@ -41,19 +39,36 @@ async function resolvePiModelConfigFromResources(options, resources, authContext
|
|
|
41
39
|
const registryModel = projectDefinesModel
|
|
42
40
|
? undefined
|
|
43
41
|
: authContext.modelRegistry.find(selection.provider, selection.modelId);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
42
|
+
const commandAuthConfigured = options.apiKey === undefined &&
|
|
43
|
+
hasPiConductorCommandCredential(resources, selection.provider, env);
|
|
44
|
+
const apiKey = commandAuthConfigured
|
|
45
|
+
? undefined
|
|
46
|
+
: await resolvePiConductorApiKey({
|
|
47
|
+
modelRuntime: authContext.modelRuntime,
|
|
48
|
+
resources,
|
|
49
|
+
provider: selection.provider,
|
|
50
|
+
explicitApiKey: options.apiKey,
|
|
51
|
+
env,
|
|
52
|
+
});
|
|
51
53
|
const builtInModel = getModel(selection.provider, selection.modelId);
|
|
52
54
|
const model = resolvePiModel(selection.provider, selection.modelId, providerConfig, registryModel ?? builtInModel, registryModel);
|
|
53
55
|
if (!model) {
|
|
54
56
|
throw new Error(`Pi conductor model "${selection.provider}/${selection.modelId}" was not found in pi-ai or models.json. ` +
|
|
55
57
|
'Set defaultProvider/defaultModel in Pi settings.json or pass a built-in provider/model id.');
|
|
56
58
|
}
|
|
59
|
+
if (commandAuthConfigured) {
|
|
60
|
+
// Pi calls hasConfiguredAuth() during prompt setup and getAuth() just
|
|
61
|
+
// before sending a provider request. Keep the command out of setup and
|
|
62
|
+
// defer registration/resolution until the latter, while preserving Pi's
|
|
63
|
+
// own auth resolver and precedence.
|
|
64
|
+
installPiCommandAuthRequestGate({
|
|
65
|
+
modelRuntime: authContext.modelRuntime,
|
|
66
|
+
resources,
|
|
67
|
+
provider: selection.provider,
|
|
68
|
+
env,
|
|
69
|
+
gate: commandAuthRequestGate ?? { active: false },
|
|
70
|
+
});
|
|
71
|
+
}
|
|
57
72
|
return {
|
|
58
73
|
provider: selection.provider,
|
|
59
74
|
modelId: selection.modelId,
|
|
@@ -73,14 +88,16 @@ export class PiConductorAgent {
|
|
|
73
88
|
modelId;
|
|
74
89
|
mcpStartupState;
|
|
75
90
|
mcpLifecycleState;
|
|
91
|
+
commandAuthRequestGate;
|
|
76
92
|
piSkills;
|
|
93
|
+
piPromptResources;
|
|
77
94
|
onStreamText;
|
|
78
95
|
onContextCompaction;
|
|
79
96
|
unsubscribe;
|
|
80
97
|
activeSend;
|
|
81
98
|
closed = false;
|
|
82
99
|
closePromise;
|
|
83
|
-
constructor(session, resources, settingsManager, headlessSettingsOverrides, systemPromptRef, agentId, modelId, mcpStartupState, mcpLifecycleState, piSkills, onStreamText, onContextCompaction) {
|
|
100
|
+
constructor(session, resources, settingsManager, headlessSettingsOverrides, systemPromptRef, agentId, modelId, mcpStartupState, mcpLifecycleState, commandAuthRequestGate, piSkills, piPromptResources, onStreamText, onContextCompaction) {
|
|
84
101
|
this.session = session;
|
|
85
102
|
this.resources = resources;
|
|
86
103
|
this.settingsManager = settingsManager;
|
|
@@ -90,7 +107,9 @@ export class PiConductorAgent {
|
|
|
90
107
|
this.modelId = modelId;
|
|
91
108
|
this.mcpStartupState = mcpStartupState;
|
|
92
109
|
this.mcpLifecycleState = mcpLifecycleState;
|
|
110
|
+
this.commandAuthRequestGate = commandAuthRequestGate;
|
|
93
111
|
this.piSkills = piSkills;
|
|
112
|
+
this.piPromptResources = piPromptResources;
|
|
94
113
|
this.onStreamText = onStreamText;
|
|
95
114
|
this.onContextCompaction = onContextCompaction;
|
|
96
115
|
this.unsubscribe = this.session.subscribe((event) => this.handleEvent(event));
|
|
@@ -135,9 +154,11 @@ export class PiConductorAgent {
|
|
|
135
154
|
};
|
|
136
155
|
this.activeSend = state;
|
|
137
156
|
try {
|
|
138
|
-
await this.session.prompt(
|
|
139
|
-
|
|
140
|
-
|
|
157
|
+
await this.session.prompt(this.piPromptResources
|
|
158
|
+
? expandPiResourcePrompt(prompt, this.resources, {
|
|
159
|
+
expandSkills: !this.piSkills,
|
|
160
|
+
})
|
|
161
|
+
: prompt, {
|
|
141
162
|
expandPromptTemplates: false,
|
|
142
163
|
source: 'rpc',
|
|
143
164
|
});
|
|
@@ -147,7 +168,7 @@ export class PiConductorAgent {
|
|
|
147
168
|
runId,
|
|
148
169
|
status: 'error',
|
|
149
170
|
error: {
|
|
150
|
-
message:
|
|
171
|
+
message: piConductorErrorMessage(error),
|
|
151
172
|
...(error instanceof ModelsError ? { code: error.code } : {}),
|
|
152
173
|
},
|
|
153
174
|
modelId: this.modelId,
|
|
@@ -164,6 +185,7 @@ export class PiConductorAgent {
|
|
|
164
185
|
modelId: this.modelId,
|
|
165
186
|
};
|
|
166
187
|
}
|
|
188
|
+
sanitizePiAssistantMessageInPlace(finalMessage);
|
|
167
189
|
const status = statusFromStopReason(finalMessage.stopReason);
|
|
168
190
|
const result = assistantText(finalMessage) || undefined;
|
|
169
191
|
if (status === 'finished' &&
|
|
@@ -323,6 +345,15 @@ export class PiConductorAgent {
|
|
|
323
345
|
}
|
|
324
346
|
handleEvent(event) {
|
|
325
347
|
const activeSend = this.activeSend;
|
|
348
|
+
if ((event.type === 'message_start' ||
|
|
349
|
+
event.type === 'message_update' ||
|
|
350
|
+
event.type === 'message_end') &&
|
|
351
|
+
event.message.role === 'assistant') {
|
|
352
|
+
// AgentSession emits public listeners before appending message_end to the
|
|
353
|
+
// Pi transcript. Mutating this message keeps the event and persisted entry
|
|
354
|
+
// safe if a failure came from a nonstandard Pi stream path.
|
|
355
|
+
sanitizePiAssistantMessageInPlace(event.message);
|
|
356
|
+
}
|
|
326
357
|
if (event.type === 'compaction_end' &&
|
|
327
358
|
event.result != null &&
|
|
328
359
|
!event.aborted &&
|
|
@@ -344,6 +375,12 @@ export class PiConductorAgent {
|
|
|
344
375
|
}
|
|
345
376
|
return;
|
|
346
377
|
}
|
|
378
|
+
if (event.type === 'agent_end') {
|
|
379
|
+
for (const message of event.messages) {
|
|
380
|
+
if (message.role === 'assistant')
|
|
381
|
+
sanitizePiAssistantMessageInPlace(message);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
347
384
|
if (event.type === 'agent_end' && activeSend) {
|
|
348
385
|
activeSend.finalMessage = lastAssistantMessage(event.messages);
|
|
349
386
|
for (const message of event.messages) {
|
|
@@ -354,6 +391,135 @@ export class PiConductorAgent {
|
|
|
354
391
|
}
|
|
355
392
|
}
|
|
356
393
|
}
|
|
394
|
+
function installPiCommandAuthRequestGate(input) {
|
|
395
|
+
const originalHasConfiguredAuth = input.modelRuntime.hasConfiguredAuth.bind(input.modelRuntime);
|
|
396
|
+
input.modelRuntime.hasConfiguredAuth = (provider) => provider === input.provider || originalHasConfiguredAuth(provider);
|
|
397
|
+
const originalGetAuth = input.modelRuntime.getAuth.bind(input.modelRuntime);
|
|
398
|
+
input.modelRuntime.getAuth = (async (providerOrModel, overrides) => {
|
|
399
|
+
const provider = typeof providerOrModel === 'string'
|
|
400
|
+
? providerOrModel
|
|
401
|
+
: providerOrModel.provider;
|
|
402
|
+
if (provider !== input.provider ||
|
|
403
|
+
!input.gate.active ||
|
|
404
|
+
overrides?.apiKey !== undefined) {
|
|
405
|
+
return originalGetAuth(providerOrModel, overrides);
|
|
406
|
+
}
|
|
407
|
+
await preparePiConductorCommandAuthForRequest({
|
|
408
|
+
modelRuntime: input.modelRuntime,
|
|
409
|
+
resources: input.resources,
|
|
410
|
+
provider: input.provider,
|
|
411
|
+
env: input.env,
|
|
412
|
+
});
|
|
413
|
+
try {
|
|
414
|
+
return await originalGetAuth(providerOrModel, overrides);
|
|
415
|
+
}
|
|
416
|
+
catch (error) {
|
|
417
|
+
if (isPiCommandResolutionError(error)) {
|
|
418
|
+
throw new Error(PI_COMMAND_RESOLUTION_ERROR_MESSAGE);
|
|
419
|
+
}
|
|
420
|
+
throw error;
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
const originalStreamSimple = input.modelRuntime.streamSimple.bind(input.modelRuntime);
|
|
424
|
+
input.modelRuntime.streamSimple = ((model, context, options) => {
|
|
425
|
+
if (model.provider !== input.provider) {
|
|
426
|
+
return originalStreamSimple(model, context, options);
|
|
427
|
+
}
|
|
428
|
+
// Pi 1.2.0's lazy stream starts its setup synchronously. That setup calls
|
|
429
|
+
// prepareRequest(), which starts getAuth() before streamSimple() returns.
|
|
430
|
+
// Keep the command gate active only for that setup call: prompt hooks and
|
|
431
|
+
// the provider response stream itself must not trigger command resolution
|
|
432
|
+
// through an unrelated getAuth() lookup.
|
|
433
|
+
const output = createAssistantMessageEventStream();
|
|
434
|
+
void (async () => {
|
|
435
|
+
try {
|
|
436
|
+
const wasActive = input.gate.active;
|
|
437
|
+
let response;
|
|
438
|
+
input.gate.active = true;
|
|
439
|
+
try {
|
|
440
|
+
response = originalStreamSimple(model, context, options);
|
|
441
|
+
}
|
|
442
|
+
finally {
|
|
443
|
+
input.gate.active = wasActive;
|
|
444
|
+
}
|
|
445
|
+
let terminalEventSeen = false;
|
|
446
|
+
for await (const event of response) {
|
|
447
|
+
if (event.type === 'done' || event.type === 'error') {
|
|
448
|
+
terminalEventSeen = true;
|
|
449
|
+
}
|
|
450
|
+
output.push(sanitizePiAssistantEvent(event));
|
|
451
|
+
}
|
|
452
|
+
if (!terminalEventSeen) {
|
|
453
|
+
output.end(sanitizePiAssistantMessage(await response.result()));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
catch (error) {
|
|
457
|
+
output.push({
|
|
458
|
+
type: 'error',
|
|
459
|
+
reason: 'error',
|
|
460
|
+
error: createPiRequestFailureMessage(model, piConductorErrorMessage(error)),
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
})();
|
|
464
|
+
return output;
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
function sanitizePiAssistantEvent(event) {
|
|
468
|
+
if (event.type === 'done') {
|
|
469
|
+
return { ...event, message: sanitizePiAssistantMessage(event.message) };
|
|
470
|
+
}
|
|
471
|
+
if (event.type === 'error') {
|
|
472
|
+
return { ...event, error: sanitizePiAssistantMessage(event.error) };
|
|
473
|
+
}
|
|
474
|
+
if ('partial' in event) {
|
|
475
|
+
return { ...event, partial: sanitizePiAssistantMessage(event.partial) };
|
|
476
|
+
}
|
|
477
|
+
return event;
|
|
478
|
+
}
|
|
479
|
+
function sanitizePiAssistantMessage(message) {
|
|
480
|
+
if (!message.errorMessage)
|
|
481
|
+
return message;
|
|
482
|
+
const safeErrorMessage = sanitizePiCommandResolutionMessage(message.errorMessage);
|
|
483
|
+
return safeErrorMessage === message.errorMessage
|
|
484
|
+
? message
|
|
485
|
+
: { ...message, errorMessage: safeErrorMessage };
|
|
486
|
+
}
|
|
487
|
+
function sanitizePiAssistantMessageInPlace(message) {
|
|
488
|
+
if (!message.errorMessage)
|
|
489
|
+
return;
|
|
490
|
+
message.errorMessage = sanitizePiCommandResolutionMessage(message.errorMessage);
|
|
491
|
+
}
|
|
492
|
+
function sanitizePiCommandResolutionMessage(message) {
|
|
493
|
+
return isPiCommandResolutionError(message)
|
|
494
|
+
? PI_COMMAND_RESOLUTION_ERROR_MESSAGE
|
|
495
|
+
: message;
|
|
496
|
+
}
|
|
497
|
+
function createPiRequestFailureMessage(model, errorMessage) {
|
|
498
|
+
return {
|
|
499
|
+
role: 'assistant',
|
|
500
|
+
content: [],
|
|
501
|
+
api: model.api,
|
|
502
|
+
provider: model.provider,
|
|
503
|
+
model: model.id,
|
|
504
|
+
usage: {
|
|
505
|
+
input: 0,
|
|
506
|
+
output: 0,
|
|
507
|
+
cacheRead: 0,
|
|
508
|
+
cacheWrite: 0,
|
|
509
|
+
totalTokens: 0,
|
|
510
|
+
cost: {
|
|
511
|
+
input: 0,
|
|
512
|
+
output: 0,
|
|
513
|
+
cacheRead: 0,
|
|
514
|
+
cacheWrite: 0,
|
|
515
|
+
total: 0,
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
stopReason: 'error',
|
|
519
|
+
errorMessage: sanitizePiCommandResolutionMessage(errorMessage),
|
|
520
|
+
timestamp: Date.now(),
|
|
521
|
+
};
|
|
522
|
+
}
|
|
357
523
|
function appendPiConductorMessageHistory(sessionManager, input) {
|
|
358
524
|
const branch = sessionManager.getBranch();
|
|
359
525
|
let assistantIndex = -1;
|
|
@@ -430,55 +596,62 @@ function resolvePiConductorThinkingLevel(model, provider, modelId, value) {
|
|
|
430
596
|
}
|
|
431
597
|
return reasoning;
|
|
432
598
|
}
|
|
599
|
+
function resolvePiConductorSessionDir(options) {
|
|
600
|
+
if (options.sessionDir !== undefined)
|
|
601
|
+
return options.sessionDir;
|
|
602
|
+
if (!options.issueUrl) {
|
|
603
|
+
throw new Error('Pi conductor transcript storage requires issueUrl or an explicit sessionDir.');
|
|
604
|
+
}
|
|
605
|
+
return resolveEnsemblePaths({ repoRoot: options.cwd })
|
|
606
|
+
.canonicalPiSessionsDir(options.issueUrl);
|
|
607
|
+
}
|
|
433
608
|
async function createPiConductorSession(agentId, options, reason) {
|
|
609
|
+
const sessionDir = resolvePiConductorSessionDir(options);
|
|
610
|
+
const piInternalExtensions = options.piInternalExtensions !== false;
|
|
434
611
|
const piMcpResolution = { cwd: options.cwd };
|
|
435
612
|
const mcpLifecycleState = {
|
|
436
|
-
enabled: Object.keys(options.mcpServers ?? {}).length > 0,
|
|
613
|
+
enabled: piInternalExtensions && Object.keys(options.mcpServers ?? {}).length > 0,
|
|
437
614
|
};
|
|
438
615
|
// Validate the harness-resolved map before creating the SDK session so an
|
|
439
616
|
// unsupported transport fails with an actionable Pi-specific error.
|
|
440
|
-
if (options.mcpServers)
|
|
617
|
+
if (piInternalExtensions && options.mcpServers) {
|
|
441
618
|
loadPiMcpConfig(options.mcpServers, piMcpResolution);
|
|
619
|
+
}
|
|
442
620
|
const piSkills = options.piSkills !== false;
|
|
621
|
+
const piPromptResources = options.piPromptResources !== false;
|
|
443
622
|
const resources = await loadPiResources({
|
|
444
623
|
...options,
|
|
445
624
|
loadExtensions: options.piExtensions !== false,
|
|
625
|
+
loadPromptResources: piPromptResources,
|
|
446
626
|
loadSkillContents: !piSkills,
|
|
447
627
|
});
|
|
448
628
|
const headlessSettingsOverrides = getPiHeadlessSettingsManagerOverrides(resources.settings);
|
|
449
629
|
const authContext = await createPiConductorAuthContext(options, resources);
|
|
450
|
-
const
|
|
630
|
+
const commandAuthRequestGate = { active: false };
|
|
631
|
+
const resolved = await resolvePiModelConfigFromResources(options, resources, authContext, commandAuthRequestGate);
|
|
451
632
|
const thinkingLevel = options.reasoning !== undefined
|
|
452
633
|
? resolvePiConductorThinkingLevel(resolved.model, resolved.provider, resolved.modelId, options.reasoning)
|
|
453
634
|
: undefined;
|
|
454
635
|
if (options.apiKey !== undefined) {
|
|
455
636
|
await authContext.modelRuntime.setRuntimeApiKey(resolved.provider, options.apiKey);
|
|
456
637
|
}
|
|
457
|
-
const sessionDir = options.sessionDir ??
|
|
458
|
-
resolveEnsemblePaths({ repoRoot: options.cwd }).piSessionsDir;
|
|
459
|
-
const legacySessionDir = options.legacySessionDir ?? join(options.cwd, PI_SESSION_ROOT);
|
|
460
638
|
await mkdir(sessionDir, { recursive: true, mode: 0o700 });
|
|
461
639
|
await chmod(sessionDir, 0o700);
|
|
462
640
|
let sessionManager;
|
|
463
641
|
let previousSessionFile;
|
|
464
642
|
if (reason === 'resume') {
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
}
|
|
474
|
-
catch (error) {
|
|
475
|
-
if (!isAlreadyExists(error))
|
|
476
|
-
throw error;
|
|
477
|
-
}
|
|
478
|
-
await chmod(migratedFile, 0o600);
|
|
479
|
-
previousSessionFile = migratedFile;
|
|
643
|
+
const resumeCwds = [
|
|
644
|
+
...new Set([options.cwd, ...(options.resumeCwds ?? [])]),
|
|
645
|
+
];
|
|
646
|
+
const findSessionFile = (directory) => {
|
|
647
|
+
for (const cwd of resumeCwds) {
|
|
648
|
+
const sessionFile = SessionManager.findById(cwd, agentId, directory);
|
|
649
|
+
if (sessionFile)
|
|
650
|
+
return sessionFile;
|
|
480
651
|
}
|
|
481
|
-
|
|
652
|
+
return undefined;
|
|
653
|
+
};
|
|
654
|
+
previousSessionFile = findSessionFile(sessionDir);
|
|
482
655
|
if (!previousSessionFile) {
|
|
483
656
|
throw new Error(`Pi session not found for resume (sessionId=${agentId}, cwd=${options.cwd}, ` +
|
|
484
657
|
`sessionsRoot=${sessionDir})`);
|
|
@@ -496,7 +669,7 @@ async function createPiConductorSession(agentId, options, reason) {
|
|
|
496
669
|
// (.ensemble/pi), so use an in-memory manager and populate it only through
|
|
497
670
|
// the code-level headless settings allowlist below.
|
|
498
671
|
const settingsManager = SettingsManager.inMemory();
|
|
499
|
-
if (piSkills) {
|
|
672
|
+
if (piSkills && piPromptResources) {
|
|
500
673
|
applyPiHeadlessSettings(settingsManager, getPiSkillsDiscoverySettingsOverrides(resources.settings));
|
|
501
674
|
settingsManager.setProjectTrusted(true);
|
|
502
675
|
}
|
|
@@ -505,18 +678,22 @@ async function createPiConductorSession(agentId, options, reason) {
|
|
|
505
678
|
agentDir: authContext.agentDir,
|
|
506
679
|
settingsManager,
|
|
507
680
|
noExtensions: true,
|
|
508
|
-
noSkills: !piSkills,
|
|
509
|
-
additionalSkillPaths: piSkills ? resources.skillPaths : [],
|
|
681
|
+
noSkills: !piSkills || !piPromptResources,
|
|
682
|
+
additionalSkillPaths: piSkills && piPromptResources ? resources.skillPaths : [],
|
|
510
683
|
noPromptTemplates: true,
|
|
511
684
|
noThemes: true,
|
|
512
685
|
noContextFiles: true,
|
|
513
686
|
systemPrompt: systemPromptRef.value,
|
|
514
687
|
extensionFactories: [
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
688
|
+
...(piInternalExtensions
|
|
689
|
+
? [
|
|
690
|
+
createMcpExtension({
|
|
691
|
+
loadConfig: () => loadPiMcpConfig(mcpLifecycleState.enabled ? options.mcpServers : undefined, piMcpResolution),
|
|
692
|
+
}),
|
|
693
|
+
createCodemodeExtension({ mode: 'on' }),
|
|
694
|
+
createToolSearchExtension(),
|
|
695
|
+
]
|
|
696
|
+
: []),
|
|
520
697
|
createPiSystemPromptExtension(systemPromptRef),
|
|
521
698
|
],
|
|
522
699
|
});
|
|
@@ -555,11 +732,11 @@ async function createPiConductorSession(agentId, options, reason) {
|
|
|
555
732
|
}
|
|
556
733
|
},
|
|
557
734
|
});
|
|
558
|
-
await observePiMcpStartup(session, options.mcpServers, mcpStartupState);
|
|
735
|
+
await observePiMcpStartup(session, piInternalExtensions ? options.mcpServers : undefined, mcpStartupState);
|
|
559
736
|
if (mcpStartupState.error) {
|
|
560
737
|
throw new Error(mcpStartupState.error);
|
|
561
738
|
}
|
|
562
|
-
return new PiConductorAgent(session, resources, settingsManager, headlessSettingsOverrides, systemPromptRef, agentId, resolved.modelId, mcpStartupState, mcpLifecycleState, piSkills, options.onStreamText, options.onContextCompaction);
|
|
739
|
+
return new PiConductorAgent(session, resources, settingsManager, headlessSettingsOverrides, systemPromptRef, agentId, resolved.modelId, mcpStartupState, mcpLifecycleState, commandAuthRequestGate, piSkills, piPromptResources, options.onStreamText, options.onContextCompaction);
|
|
563
740
|
}
|
|
564
741
|
catch (error) {
|
|
565
742
|
if (!session)
|
|
@@ -969,7 +1146,49 @@ function addConductorTokenUsage(current, usage) {
|
|
|
969
1146
|
function isRecord(value) {
|
|
970
1147
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
971
1148
|
}
|
|
972
|
-
function
|
|
1149
|
+
function piConductorErrorMessage(error) {
|
|
1150
|
+
if (isPiCommandResolutionError(error)) {
|
|
1151
|
+
return PI_COMMAND_RESOLUTION_ERROR_MESSAGE;
|
|
1152
|
+
}
|
|
973
1153
|
return error instanceof Error ? error.message : String(error);
|
|
974
1154
|
}
|
|
1155
|
+
function isPiCommandResolutionError(error) {
|
|
1156
|
+
if (typeof error === 'string' &&
|
|
1157
|
+
/failed to resolve api key|from shell command/i.test(error)) {
|
|
1158
|
+
return true;
|
|
1159
|
+
}
|
|
1160
|
+
if (!error || typeof error !== 'object')
|
|
1161
|
+
return false;
|
|
1162
|
+
if (error instanceof ModelsError && error.code !== 'auth')
|
|
1163
|
+
return false;
|
|
1164
|
+
const isAuthModelsError = error instanceof ModelsError && error.code === 'auth';
|
|
1165
|
+
const errorMessage = 'message' in error && typeof error.message === 'string' ? error.message : '';
|
|
1166
|
+
if (/failed to resolve api key|from shell command/i.test(errorMessage)) {
|
|
1167
|
+
return true;
|
|
1168
|
+
}
|
|
1169
|
+
const topLevelDetails = error;
|
|
1170
|
+
if (isAuthModelsError &&
|
|
1171
|
+
(topLevelDetails.stdout !== undefined || topLevelDetails.stderr !== undefined)) {
|
|
1172
|
+
return true;
|
|
1173
|
+
}
|
|
1174
|
+
const pending = [error.cause];
|
|
1175
|
+
const seen = new Set();
|
|
1176
|
+
while (pending.length > 0) {
|
|
1177
|
+
const cause = pending.pop();
|
|
1178
|
+
if (!cause || typeof cause !== 'object' || seen.has(cause))
|
|
1179
|
+
continue;
|
|
1180
|
+
seen.add(cause);
|
|
1181
|
+
const details = cause;
|
|
1182
|
+
if (isAuthModelsError &&
|
|
1183
|
+
(details.stdout !== undefined || details.stderr !== undefined)) {
|
|
1184
|
+
return true;
|
|
1185
|
+
}
|
|
1186
|
+
if (typeof details.message === 'string' &&
|
|
1187
|
+
/failed to resolve api key|from shell command/i.test(details.message)) {
|
|
1188
|
+
return true;
|
|
1189
|
+
}
|
|
1190
|
+
pending.push(details.cause);
|
|
1191
|
+
}
|
|
1192
|
+
return false;
|
|
1193
|
+
}
|
|
975
1194
|
//# sourceMappingURL=pi-conductor-agent.js.map
|