@parall/claude-agent 1.36.1 → 1.37.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/dist/index.js +39 -40
- package/package.json +4 -4
- package/src/index.ts +44 -43
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as os from 'node:os';
|
|
3
|
-
import { ParallAgentGateway, createPlatformConfigManager, createLogger, createOtelLogger, childLogger,
|
|
3
|
+
import { ParallAgentGateway, createPlatformConfigManager, createLogger, createOtelLogger, childLogger, deriveModelIsPin, resolveRuntimeModel, parseShutdownDeadlineMs, parseForkDeadlineMs, parseDispatchDeadlineMs, parseProviderConfig, clearAllProviderCreds, llmSource, initAgentTelemetry, } from '@parall/agent-core';
|
|
4
4
|
import { ApiError, ParallClient, ParallWs } from '@parall/sdk';
|
|
5
5
|
import { buildClaudeRuntimeKey, contextFilePathForSession, resolveClaudeAgentConfig, resolveWsUrl, sessionStateFilePathForRuntime, stepIdFilePathForSession, } from './config.js';
|
|
6
6
|
import { ClaudeCodeAdapter } from './dispatch.js';
|
|
@@ -81,26 +81,19 @@ async function main() {
|
|
|
81
81
|
log: agentLog,
|
|
82
82
|
});
|
|
83
83
|
const platformDefaults = await configMgr.fetch();
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
// platform-managed AND not explicitly self-managed: this treats legacy hosted
|
|
91
|
-
// agents (model_management=null, resolved to platform server-side) as
|
|
92
|
-
// overrides, while excluding local self agents whose delivered model is a
|
|
93
|
-
// floor. effort stays an operator override (platform).
|
|
94
|
-
let platformModelOverride = isPlatformModelOverride(me.agent_profile);
|
|
84
|
+
// Model precedence: operator PIN (override) > env > server FLOOR. The server
|
|
85
|
+
// now says which it is via model_is_pin (deriveModelIsPin presence-gates the
|
|
86
|
+
// dual-read: old servers omit it → fall back to model_management). A PIN beats
|
|
87
|
+
// an explicit env override; a FLOOR loses to env. effort is delivered by the
|
|
88
|
+
// server only when pinned, so we no longer gate it on a local flag.
|
|
89
|
+
const platformModelOverride = deriveModelIsPin(platformDefaults, me.agent_profile);
|
|
95
90
|
const resolvedModel = resolveRuntimeModel(platformModelOverride, platformDefaults.model, config.model);
|
|
96
|
-
const resolvedEffort =
|
|
97
|
-
|
|
98
|
-
(process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || undefined))
|
|
99
|
-
: process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || undefined;
|
|
91
|
+
const resolvedEffort = platformDefaults.thinkingEffort ??
|
|
92
|
+
(process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || undefined);
|
|
100
93
|
if (platformDefaults.model)
|
|
101
|
-
agentLog.info(`platform config: model=${platformDefaults.model} → resolved=${resolvedModel ?? 'cli-default'} (${platformModelOverride ? '
|
|
94
|
+
agentLog.info(`platform config: model=${platformDefaults.model} → resolved=${resolvedModel ?? 'cli-default'} (${platformModelOverride ? 'pin/override' : 'floor'})`);
|
|
102
95
|
if (platformDefaults.thinkingEffort)
|
|
103
|
-
agentLog.info(`platform config: thinking_effort=${platformDefaults.thinkingEffort}
|
|
96
|
+
agentLog.info(`platform config: thinking_effort=${platformDefaults.thinkingEffort}`);
|
|
104
97
|
const adapter = new ClaudeCodeAdapter({
|
|
105
98
|
claudeBin: config.claudeBin,
|
|
106
99
|
claudeHome: config.claudeHome,
|
|
@@ -125,6 +118,32 @@ async function main() {
|
|
|
125
118
|
if (resolvedEffort) {
|
|
126
119
|
adapter.updateConfig({ effort: resolvedEffort });
|
|
127
120
|
}
|
|
121
|
+
// Shared by onConfigUpdate + onSessionReady. /agents/me is only consumed as
|
|
122
|
+
// deriveModelIsPin's legacy fallback when the server omits model_is_pin
|
|
123
|
+
// (old server) — skip that round trip otherwise.
|
|
124
|
+
const refreshPlatformConfig = async () => {
|
|
125
|
+
const updated = await configMgr.fetch();
|
|
126
|
+
let refreshedProfile;
|
|
127
|
+
if (updated.modelIsPin === undefined) {
|
|
128
|
+
try {
|
|
129
|
+
refreshedProfile = (await getAgentMeWithLegacyFallback(client, config.orgId))
|
|
130
|
+
.agent_profile;
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
// configMgr.fetch() degrades to cache on failure; mirror that for the
|
|
134
|
+
// legacy fallback so a transient /agents/me error doesn't reject this
|
|
135
|
+
// config-refresh callback. No profile → deriveModelIsPin treats the
|
|
136
|
+
// delivered model as a floor (safe default).
|
|
137
|
+
agentLog.warn(`platform config refresh: legacy /agents/me fallback failed: ${String(err)}`);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
const isPin = deriveModelIsPin(updated, refreshedProfile);
|
|
141
|
+
const localEffort = process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || null;
|
|
142
|
+
adapter.updateConfig({
|
|
143
|
+
model: resolveRuntimeModel(isPin, updated.model, config.model) ?? null,
|
|
144
|
+
effort: updated.thinkingEffort ?? localEffort,
|
|
145
|
+
});
|
|
146
|
+
};
|
|
128
147
|
const gateway = new ParallAgentGateway({
|
|
129
148
|
accountId: agentUserId,
|
|
130
149
|
client,
|
|
@@ -151,28 +170,8 @@ async function main() {
|
|
|
151
170
|
dispatchDeadlineMs: parseDispatchDeadlineMs(process.env.PRLL_DISPATCH_DEADLINE_MS),
|
|
152
171
|
contextFilePathForSession: (sessionKey) => contextFilePathForSession(config.stateDir, sessionKey),
|
|
153
172
|
stepIdFilePathForSession: (sessionKey) => stepIdFilePathForSession(config.stateDir, sessionKey),
|
|
154
|
-
onConfigUpdate:
|
|
155
|
-
|
|
156
|
-
platformManaged = isPlatformManagedProfile(refreshed.agent_profile);
|
|
157
|
-
platformModelOverride = isPlatformModelOverride(refreshed.agent_profile);
|
|
158
|
-
const updated = await configMgr.fetch();
|
|
159
|
-
const localEffort = process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || null;
|
|
160
|
-
adapter.updateConfig({
|
|
161
|
-
model: resolveRuntimeModel(platformModelOverride, updated.model, config.model) ?? null,
|
|
162
|
-
effort: platformManaged ? (updated.thinkingEffort ?? localEffort) : localEffort,
|
|
163
|
-
});
|
|
164
|
-
},
|
|
165
|
-
onSessionReady: async () => {
|
|
166
|
-
const refreshed = await getAgentMeWithLegacyFallback(client, config.orgId);
|
|
167
|
-
platformManaged = isPlatformManagedProfile(refreshed.agent_profile);
|
|
168
|
-
platformModelOverride = isPlatformModelOverride(refreshed.agent_profile);
|
|
169
|
-
const updated = await configMgr.fetch();
|
|
170
|
-
const localEffort = process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || null;
|
|
171
|
-
adapter.updateConfig({
|
|
172
|
-
model: resolveRuntimeModel(platformModelOverride, updated.model, config.model) ?? null,
|
|
173
|
-
effort: platformManaged ? (updated.thinkingEffort ?? localEffort) : localEffort,
|
|
174
|
-
});
|
|
175
|
-
},
|
|
173
|
+
onConfigUpdate: refreshPlatformConfig,
|
|
174
|
+
onSessionReady: refreshPlatformConfig,
|
|
176
175
|
// Long-lived `claude` subprocesses outlive a single dispatch, so the
|
|
177
176
|
// gateway's shuttingDown flag alone does not tear them down. Piggyback on
|
|
178
177
|
// onBeforeDisconnect to close stdin and SIGTERM any survivors after
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/claude-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.0",
|
|
4
4
|
"description": "Claude Code bridge runtime for self-hosted Parall agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"src"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@parall/agent-core": "1.
|
|
29
|
-
"@parall/
|
|
30
|
-
"@parall/
|
|
28
|
+
"@parall/agent-core": "1.37.0",
|
|
29
|
+
"@parall/sdk": "1.37.0",
|
|
30
|
+
"@parall/cli": "1.37.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@types/node": "^22.0.0",
|
package/src/index.ts
CHANGED
|
@@ -7,8 +7,7 @@ import {
|
|
|
7
7
|
createLogger,
|
|
8
8
|
createOtelLogger,
|
|
9
9
|
childLogger,
|
|
10
|
-
|
|
11
|
-
isPlatformModelOverride,
|
|
10
|
+
deriveModelIsPin,
|
|
12
11
|
resolveRuntimeModel,
|
|
13
12
|
parseShutdownDeadlineMs,
|
|
14
13
|
parseForkDeadlineMs,
|
|
@@ -112,34 +111,26 @@ async function main() {
|
|
|
112
111
|
log: agentLog,
|
|
113
112
|
});
|
|
114
113
|
const platformDefaults = await configMgr.fetch();
|
|
115
|
-
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
|
|
121
|
-
// platform-managed AND not explicitly self-managed: this treats legacy hosted
|
|
122
|
-
// agents (model_management=null, resolved to platform server-side) as
|
|
123
|
-
// overrides, while excluding local self agents whose delivered model is a
|
|
124
|
-
// floor. effort stays an operator override (platform).
|
|
125
|
-
let platformModelOverride = isPlatformModelOverride(me.agent_profile);
|
|
114
|
+
// Model precedence: operator PIN (override) > env > server FLOOR. The server
|
|
115
|
+
// now says which it is via model_is_pin (deriveModelIsPin presence-gates the
|
|
116
|
+
// dual-read: old servers omit it → fall back to model_management). A PIN beats
|
|
117
|
+
// an explicit env override; a FLOOR loses to env. effort is delivered by the
|
|
118
|
+
// server only when pinned, so we no longer gate it on a local flag.
|
|
119
|
+
const platformModelOverride = deriveModelIsPin(platformDefaults, me.agent_profile);
|
|
126
120
|
const resolvedModel = resolveRuntimeModel(
|
|
127
121
|
platformModelOverride,
|
|
128
122
|
platformDefaults.model,
|
|
129
123
|
config.model,
|
|
130
124
|
);
|
|
131
|
-
const resolvedEffort =
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
: process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || undefined;
|
|
125
|
+
const resolvedEffort =
|
|
126
|
+
platformDefaults.thinkingEffort ??
|
|
127
|
+
(process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || undefined);
|
|
135
128
|
if (platformDefaults.model)
|
|
136
129
|
agentLog.info(
|
|
137
|
-
`platform config: model=${platformDefaults.model} → resolved=${resolvedModel ?? 'cli-default'} (${platformModelOverride ? '
|
|
130
|
+
`platform config: model=${platformDefaults.model} → resolved=${resolvedModel ?? 'cli-default'} (${platformModelOverride ? 'pin/override' : 'floor'})`,
|
|
138
131
|
);
|
|
139
132
|
if (platformDefaults.thinkingEffort)
|
|
140
|
-
agentLog.info(
|
|
141
|
-
`platform config: thinking_effort=${platformDefaults.thinkingEffort} (${platformModelOverride ? 'applied' : 'ignored, model_management=self'})`,
|
|
142
|
-
);
|
|
133
|
+
agentLog.info(`platform config: thinking_effort=${platformDefaults.thinkingEffort}`);
|
|
143
134
|
|
|
144
135
|
const adapter = new ClaudeCodeAdapter({
|
|
145
136
|
claudeBin: config.claudeBin,
|
|
@@ -168,6 +159,36 @@ async function main() {
|
|
|
168
159
|
adapter.updateConfig({ effort: resolvedEffort });
|
|
169
160
|
}
|
|
170
161
|
|
|
162
|
+
// Shared by onConfigUpdate + onSessionReady. /agents/me is only consumed as
|
|
163
|
+
// deriveModelIsPin's legacy fallback when the server omits model_is_pin
|
|
164
|
+
// (old server) — skip that round trip otherwise.
|
|
165
|
+
const refreshPlatformConfig = async () => {
|
|
166
|
+
const updated = await configMgr.fetch();
|
|
167
|
+
let refreshedProfile:
|
|
168
|
+
| Awaited<ReturnType<typeof getAgentMeWithLegacyFallback>>['agent_profile']
|
|
169
|
+
| undefined;
|
|
170
|
+
if (updated.modelIsPin === undefined) {
|
|
171
|
+
try {
|
|
172
|
+
refreshedProfile = (await getAgentMeWithLegacyFallback(client, config.orgId))
|
|
173
|
+
.agent_profile;
|
|
174
|
+
} catch (err) {
|
|
175
|
+
// configMgr.fetch() degrades to cache on failure; mirror that for the
|
|
176
|
+
// legacy fallback so a transient /agents/me error doesn't reject this
|
|
177
|
+
// config-refresh callback. No profile → deriveModelIsPin treats the
|
|
178
|
+
// delivered model as a floor (safe default).
|
|
179
|
+
agentLog.warn(
|
|
180
|
+
`platform config refresh: legacy /agents/me fallback failed: ${String(err)}`,
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const isPin = deriveModelIsPin(updated, refreshedProfile);
|
|
185
|
+
const localEffort = process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || null;
|
|
186
|
+
adapter.updateConfig({
|
|
187
|
+
model: resolveRuntimeModel(isPin, updated.model, config.model) ?? null,
|
|
188
|
+
effort: updated.thinkingEffort ?? localEffort,
|
|
189
|
+
});
|
|
190
|
+
};
|
|
191
|
+
|
|
171
192
|
const gateway = new ParallAgentGateway({
|
|
172
193
|
accountId: agentUserId,
|
|
173
194
|
client,
|
|
@@ -196,28 +217,8 @@ async function main() {
|
|
|
196
217
|
contextFilePathForSession(config.stateDir, sessionKey),
|
|
197
218
|
stepIdFilePathForSession: (sessionKey) =>
|
|
198
219
|
stepIdFilePathForSession(config.stateDir, sessionKey),
|
|
199
|
-
onConfigUpdate:
|
|
200
|
-
|
|
201
|
-
platformManaged = isPlatformManagedProfile(refreshed.agent_profile);
|
|
202
|
-
platformModelOverride = isPlatformModelOverride(refreshed.agent_profile);
|
|
203
|
-
const updated = await configMgr.fetch();
|
|
204
|
-
const localEffort = process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || null;
|
|
205
|
-
adapter.updateConfig({
|
|
206
|
-
model: resolveRuntimeModel(platformModelOverride, updated.model, config.model) ?? null,
|
|
207
|
-
effort: platformManaged ? (updated.thinkingEffort ?? localEffort) : localEffort,
|
|
208
|
-
});
|
|
209
|
-
},
|
|
210
|
-
onSessionReady: async () => {
|
|
211
|
-
const refreshed = await getAgentMeWithLegacyFallback(client, config.orgId);
|
|
212
|
-
platformManaged = isPlatformManagedProfile(refreshed.agent_profile);
|
|
213
|
-
platformModelOverride = isPlatformModelOverride(refreshed.agent_profile);
|
|
214
|
-
const updated = await configMgr.fetch();
|
|
215
|
-
const localEffort = process.env.CLAUDE_CODE_EFFORT_LEVEL?.trim() || null;
|
|
216
|
-
adapter.updateConfig({
|
|
217
|
-
model: resolveRuntimeModel(platformModelOverride, updated.model, config.model) ?? null,
|
|
218
|
-
effort: platformManaged ? (updated.thinkingEffort ?? localEffort) : localEffort,
|
|
219
|
-
});
|
|
220
|
-
},
|
|
220
|
+
onConfigUpdate: refreshPlatformConfig,
|
|
221
|
+
onSessionReady: refreshPlatformConfig,
|
|
221
222
|
// Long-lived `claude` subprocesses outlive a single dispatch, so the
|
|
222
223
|
// gateway's shuttingDown flag alone does not tear them down. Piggyback on
|
|
223
224
|
// onBeforeDisconnect to close stdin and SIGTERM any survivors after
|