@parall/daemon 1.30.0 → 1.31.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/bundle/manifest.json +12 -11
- package/bundle/parall-claude-agent.js +131 -14
- package/bundle/parall-codex-agent.js +120 -11
- package/bundle/parall-daemon.js +895 -273
- package/bundle/parall-openclaw-agent.js +2 -2
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +52 -2
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -0
- package/dist/index.js +30 -3
- package/dist/runtimes.d.ts +9 -8
- package/dist/runtimes.d.ts.map +1 -1
- package/dist/runtimes.js +47 -83
- package/dist/supervisor.d.ts +4 -0
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +33 -0
- package/dist/updater-manifest.d.ts +39 -0
- package/dist/updater-manifest.d.ts.map +1 -0
- package/dist/updater-manifest.js +94 -0
- package/dist/updater.d.ts +60 -0
- package/dist/updater.d.ts.map +1 -0
- package/dist/updater.js +409 -0
- package/package.json +6 -6
package/bundle/manifest.json
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
3
|
-
"built_at": "2026-05-
|
|
2
|
+
"version": "1.31.0",
|
|
3
|
+
"built_at": "2026-05-25T09:46:03.818Z",
|
|
4
4
|
"files": {
|
|
5
5
|
"parall-claude-agent.js": {
|
|
6
|
-
"sha256": "
|
|
7
|
-
"size":
|
|
6
|
+
"sha256": "99e0829cda93f0ad208c9e017f0210203498a4be1c9077eb60f8e94ac24238db",
|
|
7
|
+
"size": 238575
|
|
8
8
|
},
|
|
9
9
|
"parall-codex-agent.js": {
|
|
10
|
-
"sha256": "
|
|
11
|
-
"size":
|
|
10
|
+
"sha256": "809852713ed2d62fd65a1f050977c7ef44b0e568cd85fe66965ac671040db7b2",
|
|
11
|
+
"size": 269586
|
|
12
12
|
},
|
|
13
13
|
"parall-daemon.js": {
|
|
14
|
-
"sha256": "
|
|
15
|
-
"size":
|
|
14
|
+
"sha256": "d0de188d62e7e274f6eb52e50aca0926cd0e25d82031f56f24ef5c3e56e87786",
|
|
15
|
+
"size": 164213
|
|
16
16
|
},
|
|
17
17
|
"parall-openclaw-agent.js": {
|
|
18
|
-
"sha256": "
|
|
19
|
-
"size":
|
|
18
|
+
"sha256": "e876fa06665655a342b11de264896be7f64dc5d4635dee497f73f9984e95f651",
|
|
19
|
+
"size": 8457
|
|
20
20
|
}
|
|
21
|
-
}
|
|
21
|
+
},
|
|
22
|
+
"signature": "rb+Dn/DCALZ7cTEWj+ta6bL2I9OcmFlyrUPoC299ey6FmZn2CgnDhdfq3uguwVnBRAvmTD1YjQJMFXm9wMe/AQ=="
|
|
22
23
|
}
|
|
@@ -3,6 +3,34 @@
|
|
|
3
3
|
// ts/claude-agent/dist/index.js
|
|
4
4
|
import * as os3 from "node:os";
|
|
5
5
|
|
|
6
|
+
// ts/agent-core/dist/provider-config.js
|
|
7
|
+
function llmSource(pc) {
|
|
8
|
+
if (pc?.llm_source)
|
|
9
|
+
return pc.llm_source;
|
|
10
|
+
if (pc?.openai_api_key || pc?.openai_base_url || pc?.anthropic_auth_token || pc?.anthropic_base_url) {
|
|
11
|
+
return "custom";
|
|
12
|
+
}
|
|
13
|
+
return "parall";
|
|
14
|
+
}
|
|
15
|
+
function clearAllProviderCreds(env) {
|
|
16
|
+
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
17
|
+
delete env.ANTHROPIC_BASE_URL;
|
|
18
|
+
delete env.ANTHROPIC_API_KEY;
|
|
19
|
+
delete env.OPENAI_API_KEY;
|
|
20
|
+
delete env.OPENAI_BASE_URL;
|
|
21
|
+
delete env.PRLL_CLAUDE_ALLOW_API_KEY;
|
|
22
|
+
}
|
|
23
|
+
function parseProviderConfig(env) {
|
|
24
|
+
const raw = env.PRLL_PROVIDER_CONFIG?.trim();
|
|
25
|
+
if (!raw)
|
|
26
|
+
return void 0;
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(raw);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
throw new Error(`Invalid PRLL_PROVIDER_CONFIG JSON: ${String(err)}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
6
34
|
// ts/agent-core/dist/session-state.js
|
|
7
35
|
function normalizeSessionKey(sessionKey) {
|
|
8
36
|
return sessionKey.toLowerCase();
|
|
@@ -474,6 +502,7 @@ var ENDPOINTS = {
|
|
|
474
502
|
ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
|
|
475
503
|
ORG_MEMBER_CHATS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/chats`,
|
|
476
504
|
ORG_MEMBER_TASKS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/tasks`,
|
|
505
|
+
REF_SEARCH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/search`,
|
|
477
506
|
// Direct messages (org-scoped, atomic find-or-create + send)
|
|
478
507
|
DM: (orgId) => `${API_BASE}/orgs/${orgId}/dm`,
|
|
479
508
|
// Onboarding
|
|
@@ -556,6 +585,7 @@ var ENDPOINTS = {
|
|
|
556
585
|
MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
|
|
557
586
|
MACHINE_RUNTIME_AUTH_SESSIONS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions`,
|
|
558
587
|
MACHINE_RUNTIME_AUTH_SESSION_COMPLETE: (orgId, machineId, sessionId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions/${sessionId}/complete`,
|
|
588
|
+
MACHINE_REQUEST_UPDATE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/request-update`,
|
|
559
589
|
MACHINE_BROWSE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/browse`,
|
|
560
590
|
// Machine self-control-plane (mck_-scoped). The bearer token implicitly
|
|
561
591
|
// identifies the Machine, so there is no `:mid` URL parameter — these are
|
|
@@ -601,6 +631,12 @@ var ENDPOINTS = {
|
|
|
601
631
|
INVITATION_ACCEPT: (id) => `${API_BASE}/invitations/${id}/accept`,
|
|
602
632
|
INVITATION_DECLINE: (id) => `${API_BASE}/invitations/${id}/decline`,
|
|
603
633
|
INVITATION_BY_TOKEN: (token) => `${API_BASE}/invitations/by-token/${token}`,
|
|
634
|
+
// Org-level shareable invite link
|
|
635
|
+
ORG_INVITE_LINK: (orgId) => `${API_BASE}/orgs/${orgId}/invite-link`,
|
|
636
|
+
ORG_INVITE_LINK_REGENERATE: (orgId) => `${API_BASE}/orgs/${orgId}/invite-link/regenerate`,
|
|
637
|
+
ORG_INVITE_LINK_JOIN_REQUESTS: (orgId) => `${API_BASE}/orgs/${orgId}/invite-link/join-requests`,
|
|
638
|
+
ORG_INVITE_LINK_JOIN_REQUEST_DECIDE: (orgId, jrId) => `${API_BASE}/orgs/${orgId}/invite-link/join-requests/${jrId}/decide`,
|
|
639
|
+
INVITE_LINK_JOIN: `${API_BASE}/invite-link/join`,
|
|
604
640
|
// Wikis (org-scoped, served by wiki-service)
|
|
605
641
|
WIKIS: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wikis`,
|
|
606
642
|
WIKI: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}`,
|
|
@@ -720,6 +756,8 @@ var WS_EVENTS = {
|
|
|
720
756
|
INVITATION_ACCEPTED: "invitation.accepted",
|
|
721
757
|
INVITATION_DECLINED: "invitation.declined",
|
|
722
758
|
INVITATION_REVOKED: "invitation.revoked",
|
|
759
|
+
ORG_JOIN_REQUEST_NEW: "org.join_request.new",
|
|
760
|
+
ORG_INVITE_LINK_JOINED: "org.invite_link.joined",
|
|
723
761
|
AGENT_CONFIG_UPDATE: "agent_config.update",
|
|
724
762
|
PRESENCE_UPDATE: "presence.update",
|
|
725
763
|
WIKI_CHANGESET_CREATED: "wiki.changeset.created",
|
|
@@ -748,6 +786,8 @@ var WS_EVENTS = {
|
|
|
748
786
|
MACHINE_STOP: "machine.stop",
|
|
749
787
|
MACHINE_WORKSPACE_SETUP_REQUESTED: "machine.workspace.setup.requested",
|
|
750
788
|
MACHINE_FILESYSTEM_BROWSE: "machine.filesystem.browse",
|
|
789
|
+
MACHINE_UPDATE: "machine.update",
|
|
790
|
+
MACHINE_CONFIG_UPDATED: "machine.config.updated",
|
|
751
791
|
AGENT_NEW_SESSION: "agent.new_session"
|
|
752
792
|
};
|
|
753
793
|
|
|
@@ -1077,6 +1117,9 @@ var ParallClient = class _ParallClient {
|
|
|
1077
1117
|
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS_ONLINE(orgId));
|
|
1078
1118
|
return res.user_ids ?? [];
|
|
1079
1119
|
}
|
|
1120
|
+
async searchRefs(orgId, params) {
|
|
1121
|
+
return this.request("GET", ENDPOINTS.REF_SEARCH(orgId), void 0, params);
|
|
1122
|
+
}
|
|
1080
1123
|
async removeOrgMember(orgId, userId) {
|
|
1081
1124
|
return this.request("DELETE", ENDPOINTS.ORG_MEMBER(orgId, userId));
|
|
1082
1125
|
}
|
|
@@ -1130,6 +1173,34 @@ var ParallClient = class _ParallClient {
|
|
|
1130
1173
|
async getInvitationByToken(token) {
|
|
1131
1174
|
return this.request("GET", ENDPOINTS.INVITATION_BY_TOKEN(token));
|
|
1132
1175
|
}
|
|
1176
|
+
// ---- Org-level shareable invite link ----
|
|
1177
|
+
/** Fetch the org's current invite link. Auto-creates on first call
|
|
1178
|
+
* so the settings UI never sees an empty state. */
|
|
1179
|
+
async getOrgInviteLink(orgId) {
|
|
1180
|
+
return this.request("GET", ENDPOINTS.ORG_INVITE_LINK(orgId));
|
|
1181
|
+
}
|
|
1182
|
+
/** Rotate the token in place. The old token stops resolving immediately. */
|
|
1183
|
+
async regenerateOrgInviteLink(orgId) {
|
|
1184
|
+
return this.request("POST", ENDPOINTS.ORG_INVITE_LINK_REGENERATE(orgId));
|
|
1185
|
+
}
|
|
1186
|
+
/** Toggle the require-approval flag on the org's invite link. */
|
|
1187
|
+
async updateOrgInviteLink(orgId, data) {
|
|
1188
|
+
return this.request("PATCH", ENDPOINTS.ORG_INVITE_LINK(orgId), data);
|
|
1189
|
+
}
|
|
1190
|
+
/** Redeem an invite-link token. Caller must be authenticated; the
|
|
1191
|
+
* token is the lookup key so this endpoint is NOT org-scoped. */
|
|
1192
|
+
async joinByInviteLink(token) {
|
|
1193
|
+
return this.request("POST", ENDPOINTS.INVITE_LINK_JOIN, { token });
|
|
1194
|
+
}
|
|
1195
|
+
/** Admin: list pending invite-link join requests for an org. */
|
|
1196
|
+
async listOrgJoinRequests(orgId) {
|
|
1197
|
+
const res = await this.request("GET", ENDPOINTS.ORG_INVITE_LINK_JOIN_REQUESTS(orgId));
|
|
1198
|
+
return res.data;
|
|
1199
|
+
}
|
|
1200
|
+
/** Admin: approve or reject a pending invite-link join request. */
|
|
1201
|
+
async decideOrgJoinRequest(orgId, jrId, decision) {
|
|
1202
|
+
return this.request("POST", ENDPOINTS.ORG_INVITE_LINK_JOIN_REQUEST_DECIDE(orgId, jrId), { decision });
|
|
1203
|
+
}
|
|
1133
1204
|
// ---- Direct Messages (org-scoped) ----
|
|
1134
1205
|
async sendDirectMessage(orgId, req) {
|
|
1135
1206
|
return this.request("POST", ENDPOINTS.DM(orgId), req);
|
|
@@ -1399,19 +1470,20 @@ var ParallClient = class _ParallClient {
|
|
|
1399
1470
|
}
|
|
1400
1471
|
// ---- Daemon-mode Machine management (org-scoped, user auth) ----
|
|
1401
1472
|
/**
|
|
1402
|
-
* Create a new daemon-mode Machine. Returns the Machine row +
|
|
1403
|
-
* mck_ token.
|
|
1473
|
+
* Create a new self-hosted daemon-mode Machine. Returns the Machine row +
|
|
1474
|
+
* one-shot mck_ token.
|
|
1404
1475
|
*/
|
|
1405
1476
|
async createMachine(orgId, opts) {
|
|
1406
1477
|
return this.request("POST", ENDPOINTS.MACHINES(orgId), opts);
|
|
1407
1478
|
}
|
|
1408
1479
|
/**
|
|
1409
|
-
* Returns
|
|
1410
|
-
* "Workspaces" UI list. Legacy 1:1 machines are
|
|
1480
|
+
* Returns local daemon_mode=true machines (non-terminated). Backs the
|
|
1481
|
+
* "Workspaces" UI list. Legacy 1:1 and retired hosted daemon machines are
|
|
1482
|
+
* excluded.
|
|
1411
1483
|
*/
|
|
1412
1484
|
async getDaemonMachines(orgId) {
|
|
1413
1485
|
const all = await this.getMachines(orgId);
|
|
1414
|
-
return all.filter((m) => m.daemon_mode && m.status !== "terminated");
|
|
1486
|
+
return all.filter((m) => m.daemon_mode && m.compute_mode === "local" && m.status !== "terminated");
|
|
1415
1487
|
}
|
|
1416
1488
|
/** Attach an agent to a daemon-mode Machine. */
|
|
1417
1489
|
async attachAgent(orgId, machineId, agentId, opts) {
|
|
@@ -1431,8 +1503,8 @@ var ParallClient = class _ParallClient {
|
|
|
1431
1503
|
async retryAgentWorkspaceSetup(orgId, machineId, agentId) {
|
|
1432
1504
|
return this.request("POST", ENDPOINTS.MACHINE_AGENT_WORKSPACE_SETUP(orgId, machineId, agentId));
|
|
1433
1505
|
}
|
|
1434
|
-
async patchMachineLLMSource(orgId, machineId,
|
|
1435
|
-
return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source:
|
|
1506
|
+
async patchMachineLLMSource(orgId, machineId, llmSource2) {
|
|
1507
|
+
return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source: llmSource2 });
|
|
1436
1508
|
}
|
|
1437
1509
|
/** Get machine-level runtime auth state. */
|
|
1438
1510
|
async getMachineRuntimeAuth(orgId, machineId) {
|
|
@@ -1473,8 +1545,9 @@ var ParallClient = class _ParallClient {
|
|
|
1473
1545
|
* daemon should call this on a fixed cadence (e.g. every 30s) so an
|
|
1474
1546
|
* external observer can detect a wedged supervisor.
|
|
1475
1547
|
*/
|
|
1476
|
-
async postMachineHeartbeat() {
|
|
1477
|
-
|
|
1548
|
+
async postMachineHeartbeat(daemonVersion) {
|
|
1549
|
+
const body = daemonVersion ? { daemon_version: daemonVersion } : void 0;
|
|
1550
|
+
return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, body);
|
|
1478
1551
|
}
|
|
1479
1552
|
async reportAgentWorkspaceState(agentId, state) {
|
|
1480
1553
|
const res = await this.request("PUT", ENDPOINTS.MACHINES_ME_AGENT_WORKSPACE_STATE(agentId), state);
|
|
@@ -1502,6 +1575,10 @@ var ParallClient = class _ParallClient {
|
|
|
1502
1575
|
async resizeMachine(orgId, machineId, spec) {
|
|
1503
1576
|
return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
|
|
1504
1577
|
}
|
|
1578
|
+
/** Signal a local daemon-mode Machine to check for and apply an update. */
|
|
1579
|
+
async requestMachineUpdate(orgId, machineId, mandatory = false) {
|
|
1580
|
+
await this.request("POST", ENDPOINTS.MACHINE_REQUEST_UPDATE(orgId, machineId), { mandatory });
|
|
1581
|
+
}
|
|
1505
1582
|
async browseMachineFilesystem(orgId, machineId, path9) {
|
|
1506
1583
|
return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path9 }, void 0, false, { timeoutMs: 15e3 });
|
|
1507
1584
|
}
|
|
@@ -2352,6 +2429,7 @@ var ParallWs = class {
|
|
|
2352
2429
|
};
|
|
2353
2430
|
|
|
2354
2431
|
// ts/agent-core/dist/gateway-base.js
|
|
2432
|
+
var LIVE_SESSION_STATUSES = /* @__PURE__ */ new Set(["open", "active", "idle"]);
|
|
2355
2433
|
function parseShutdownDeadlineMs(raw) {
|
|
2356
2434
|
if (!raw)
|
|
2357
2435
|
return void 0;
|
|
@@ -2821,6 +2899,17 @@ var ParallAgentGateway = class {
|
|
|
2821
2899
|
parent_session_id: parentSessionId,
|
|
2822
2900
|
runtime_ref: Object.keys(runtimeRef).length > 0 ? runtimeRef : void 0
|
|
2823
2901
|
});
|
|
2902
|
+
if (!LIVE_SESSION_STATUSES.has(session.status)) {
|
|
2903
|
+
this.opts.log?.warn?.(`createAgentSession returned terminal session ${session.id} (${session.status}), resetting runtime for ${sessionKey}`);
|
|
2904
|
+
this.sessionBindings.delete(sessionKey);
|
|
2905
|
+
try {
|
|
2906
|
+
await this.opts.onSessionStale?.(sessionKey);
|
|
2907
|
+
} catch (e) {
|
|
2908
|
+
this.opts.log?.warn?.(`onSessionStale failed: ${e}`);
|
|
2909
|
+
}
|
|
2910
|
+
this.opts.log?.info?.(`stale session self-heal complete for ${sessionKey} \u2014 next dispatch will create a fresh session`);
|
|
2911
|
+
throw new Error(`Agent session ${session.id} is terminal (${session.status})`);
|
|
2912
|
+
}
|
|
2824
2913
|
const binding = {
|
|
2825
2914
|
sessionKey,
|
|
2826
2915
|
agentSessionId: session.id,
|
|
@@ -4284,8 +4373,8 @@ function resolveClaudeAgentConfig(env = process.env) {
|
|
|
4284
4373
|
const apiKey = requireEnv(env, "PRLL_API_KEY");
|
|
4285
4374
|
const orgId = requireEnv(env, "PRLL_ORG_ID");
|
|
4286
4375
|
const claudeHome = resolvePath(env.PRLL_CLAUDE_HOME?.trim() || env.HOME || os2.homedir());
|
|
4287
|
-
const stateDir = resolvePath(env.
|
|
4288
|
-
const workspaceDir = resolvePath(env.
|
|
4376
|
+
const stateDir = resolvePath(env.PRLL_STATE_DIR?.trim() || path4.join(claudeHome, ".parall-agent"));
|
|
4377
|
+
const workspaceDir = resolvePath(env.PRLL_WORKSPACE_DIR?.trim() || path4.join(stateDir, "workspace"));
|
|
4289
4378
|
const additionalDirs = parseList(env.PRLL_CLAUDE_ADD_DIRS).map(resolvePath);
|
|
4290
4379
|
return {
|
|
4291
4380
|
apiUrl,
|
|
@@ -5231,12 +5320,16 @@ var ClaudeCodeAdapter = class _ClaudeCodeAdapter {
|
|
|
5231
5320
|
}
|
|
5232
5321
|
this.opts.sessionManager.cleanupFork(fork.sessionKey);
|
|
5233
5322
|
}
|
|
5234
|
-
|
|
5235
|
-
this.shuttingDown = true;
|
|
5323
|
+
resetProcesses() {
|
|
5236
5324
|
for (const [sessionKey, state] of this.processes) {
|
|
5237
5325
|
this.killProcess(sessionKey, state);
|
|
5238
5326
|
}
|
|
5239
5327
|
this.processes.clear();
|
|
5328
|
+
this.pendingInjections.clear();
|
|
5329
|
+
}
|
|
5330
|
+
async shutdown() {
|
|
5331
|
+
this.shuttingDown = true;
|
|
5332
|
+
this.resetProcesses();
|
|
5240
5333
|
await this.opts.sessionManager.shutdownAll();
|
|
5241
5334
|
}
|
|
5242
5335
|
static STEER_TURN_TIMEOUT_MS = 1e4;
|
|
@@ -5728,7 +5821,27 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
|
|
|
5728
5821
|
return { ...user, agent_profile: null };
|
|
5729
5822
|
}
|
|
5730
5823
|
}
|
|
5824
|
+
function resolveProviderEnv() {
|
|
5825
|
+
const pc = parseProviderConfig(process.env);
|
|
5826
|
+
if (!pc)
|
|
5827
|
+
return;
|
|
5828
|
+
clearAllProviderCreds(process.env);
|
|
5829
|
+
const source = llmSource(pc);
|
|
5830
|
+
if (source === "parall") {
|
|
5831
|
+
process.env.ANTHROPIC_AUTH_TOKEN = process.env.PRLL_API_KEY;
|
|
5832
|
+
process.env.ANTHROPIC_BASE_URL = `${process.env.PRLL_API_URL}/api/llm`;
|
|
5833
|
+
process.env.PRLL_CLAUDE_ALLOW_API_KEY = "1";
|
|
5834
|
+
} else if (source === "custom") {
|
|
5835
|
+
if (pc.anthropic_auth_token) {
|
|
5836
|
+
process.env.ANTHROPIC_AUTH_TOKEN = pc.anthropic_auth_token;
|
|
5837
|
+
process.env.PRLL_CLAUDE_ALLOW_API_KEY = "1";
|
|
5838
|
+
}
|
|
5839
|
+
if (pc.anthropic_base_url)
|
|
5840
|
+
process.env.ANTHROPIC_BASE_URL = pc.anthropic_base_url;
|
|
5841
|
+
}
|
|
5842
|
+
}
|
|
5731
5843
|
async function main() {
|
|
5844
|
+
resolveProviderEnv();
|
|
5732
5845
|
const config = resolveClaudeAgentConfig(process.env);
|
|
5733
5846
|
if (config.allowApiKey && (process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_AUTH_TOKEN)) {
|
|
5734
5847
|
log.warn("PRLL_CLAUDE_ALLOW_API_KEY=1 \u2014 ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKEN will reach the Claude CLI; billing routes through Anthropic API pay-per-use instead of Claude.ai OAuth.");
|
|
@@ -5839,7 +5952,11 @@ async function main() {
|
|
|
5839
5952
|
onBeforeDisconnect: () => adapter.shutdown(),
|
|
5840
5953
|
onNewSession: async () => {
|
|
5841
5954
|
sessionManager.clearMainSession();
|
|
5842
|
-
|
|
5955
|
+
adapter.resetProcesses();
|
|
5956
|
+
},
|
|
5957
|
+
onSessionStale: () => {
|
|
5958
|
+
sessionManager.clearMainSession();
|
|
5959
|
+
adapter.resetProcesses();
|
|
5843
5960
|
}
|
|
5844
5961
|
});
|
|
5845
5962
|
const abortController = new AbortController();
|
|
@@ -3,6 +3,34 @@
|
|
|
3
3
|
// ts/codex-agent/dist/index.js
|
|
4
4
|
import * as os3 from "node:os";
|
|
5
5
|
|
|
6
|
+
// ts/agent-core/dist/provider-config.js
|
|
7
|
+
function llmSource(pc) {
|
|
8
|
+
if (pc?.llm_source)
|
|
9
|
+
return pc.llm_source;
|
|
10
|
+
if (pc?.openai_api_key || pc?.openai_base_url || pc?.anthropic_auth_token || pc?.anthropic_base_url) {
|
|
11
|
+
return "custom";
|
|
12
|
+
}
|
|
13
|
+
return "parall";
|
|
14
|
+
}
|
|
15
|
+
function clearAllProviderCreds(env) {
|
|
16
|
+
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
17
|
+
delete env.ANTHROPIC_BASE_URL;
|
|
18
|
+
delete env.ANTHROPIC_API_KEY;
|
|
19
|
+
delete env.OPENAI_API_KEY;
|
|
20
|
+
delete env.OPENAI_BASE_URL;
|
|
21
|
+
delete env.PRLL_CLAUDE_ALLOW_API_KEY;
|
|
22
|
+
}
|
|
23
|
+
function parseProviderConfig(env) {
|
|
24
|
+
const raw = env.PRLL_PROVIDER_CONFIG?.trim();
|
|
25
|
+
if (!raw)
|
|
26
|
+
return void 0;
|
|
27
|
+
try {
|
|
28
|
+
return JSON.parse(raw);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
throw new Error(`Invalid PRLL_PROVIDER_CONFIG JSON: ${String(err)}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
6
34
|
// ts/agent-core/dist/session-state.js
|
|
7
35
|
function normalizeSessionKey(sessionKey) {
|
|
8
36
|
return sessionKey.toLowerCase();
|
|
@@ -474,6 +502,7 @@ var ENDPOINTS = {
|
|
|
474
502
|
ORG_MEMBER: (orgId, userId) => `${API_BASE}/orgs/${orgId}/members/${userId}`,
|
|
475
503
|
ORG_MEMBER_CHATS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/chats`,
|
|
476
504
|
ORG_MEMBER_TASKS: (orgId, memberId) => `${API_BASE}/orgs/${orgId}/members/${memberId}/tasks`,
|
|
505
|
+
REF_SEARCH: (orgId) => `${API_BASE}/orgs/${orgId}/refs/search`,
|
|
477
506
|
// Direct messages (org-scoped, atomic find-or-create + send)
|
|
478
507
|
DM: (orgId) => `${API_BASE}/orgs/${orgId}/dm`,
|
|
479
508
|
// Onboarding
|
|
@@ -556,6 +585,7 @@ var ENDPOINTS = {
|
|
|
556
585
|
MACHINE_KEY: (orgId, machineId, keyId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/keys/${keyId}`,
|
|
557
586
|
MACHINE_RUNTIME_AUTH_SESSIONS: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions`,
|
|
558
587
|
MACHINE_RUNTIME_AUTH_SESSION_COMPLETE: (orgId, machineId, sessionId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/runtime-auth-sessions/${sessionId}/complete`,
|
|
588
|
+
MACHINE_REQUEST_UPDATE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/request-update`,
|
|
559
589
|
MACHINE_BROWSE: (orgId, machineId) => `${API_BASE}/orgs/${orgId}/machines/${machineId}/browse`,
|
|
560
590
|
// Machine self-control-plane (mck_-scoped). The bearer token implicitly
|
|
561
591
|
// identifies the Machine, so there is no `:mid` URL parameter — these are
|
|
@@ -601,6 +631,12 @@ var ENDPOINTS = {
|
|
|
601
631
|
INVITATION_ACCEPT: (id) => `${API_BASE}/invitations/${id}/accept`,
|
|
602
632
|
INVITATION_DECLINE: (id) => `${API_BASE}/invitations/${id}/decline`,
|
|
603
633
|
INVITATION_BY_TOKEN: (token) => `${API_BASE}/invitations/by-token/${token}`,
|
|
634
|
+
// Org-level shareable invite link
|
|
635
|
+
ORG_INVITE_LINK: (orgId) => `${API_BASE}/orgs/${orgId}/invite-link`,
|
|
636
|
+
ORG_INVITE_LINK_REGENERATE: (orgId) => `${API_BASE}/orgs/${orgId}/invite-link/regenerate`,
|
|
637
|
+
ORG_INVITE_LINK_JOIN_REQUESTS: (orgId) => `${API_BASE}/orgs/${orgId}/invite-link/join-requests`,
|
|
638
|
+
ORG_INVITE_LINK_JOIN_REQUEST_DECIDE: (orgId, jrId) => `${API_BASE}/orgs/${orgId}/invite-link/join-requests/${jrId}/decide`,
|
|
639
|
+
INVITE_LINK_JOIN: `${API_BASE}/invite-link/join`,
|
|
604
640
|
// Wikis (org-scoped, served by wiki-service)
|
|
605
641
|
WIKIS: (orgId) => `${WIKI_BASE}/orgs/${orgId}/wikis`,
|
|
606
642
|
WIKI: (orgId, wikiId) => `${WIKI_BASE}/orgs/${orgId}/wikis/${wikiId}`,
|
|
@@ -720,6 +756,8 @@ var WS_EVENTS = {
|
|
|
720
756
|
INVITATION_ACCEPTED: "invitation.accepted",
|
|
721
757
|
INVITATION_DECLINED: "invitation.declined",
|
|
722
758
|
INVITATION_REVOKED: "invitation.revoked",
|
|
759
|
+
ORG_JOIN_REQUEST_NEW: "org.join_request.new",
|
|
760
|
+
ORG_INVITE_LINK_JOINED: "org.invite_link.joined",
|
|
723
761
|
AGENT_CONFIG_UPDATE: "agent_config.update",
|
|
724
762
|
PRESENCE_UPDATE: "presence.update",
|
|
725
763
|
WIKI_CHANGESET_CREATED: "wiki.changeset.created",
|
|
@@ -748,6 +786,8 @@ var WS_EVENTS = {
|
|
|
748
786
|
MACHINE_STOP: "machine.stop",
|
|
749
787
|
MACHINE_WORKSPACE_SETUP_REQUESTED: "machine.workspace.setup.requested",
|
|
750
788
|
MACHINE_FILESYSTEM_BROWSE: "machine.filesystem.browse",
|
|
789
|
+
MACHINE_UPDATE: "machine.update",
|
|
790
|
+
MACHINE_CONFIG_UPDATED: "machine.config.updated",
|
|
751
791
|
AGENT_NEW_SESSION: "agent.new_session"
|
|
752
792
|
};
|
|
753
793
|
|
|
@@ -1077,6 +1117,9 @@ var ParallClient = class _ParallClient {
|
|
|
1077
1117
|
const res = await this.request("GET", ENDPOINTS.ORG_MEMBERS_ONLINE(orgId));
|
|
1078
1118
|
return res.user_ids ?? [];
|
|
1079
1119
|
}
|
|
1120
|
+
async searchRefs(orgId, params) {
|
|
1121
|
+
return this.request("GET", ENDPOINTS.REF_SEARCH(orgId), void 0, params);
|
|
1122
|
+
}
|
|
1080
1123
|
async removeOrgMember(orgId, userId) {
|
|
1081
1124
|
return this.request("DELETE", ENDPOINTS.ORG_MEMBER(orgId, userId));
|
|
1082
1125
|
}
|
|
@@ -1130,6 +1173,34 @@ var ParallClient = class _ParallClient {
|
|
|
1130
1173
|
async getInvitationByToken(token) {
|
|
1131
1174
|
return this.request("GET", ENDPOINTS.INVITATION_BY_TOKEN(token));
|
|
1132
1175
|
}
|
|
1176
|
+
// ---- Org-level shareable invite link ----
|
|
1177
|
+
/** Fetch the org's current invite link. Auto-creates on first call
|
|
1178
|
+
* so the settings UI never sees an empty state. */
|
|
1179
|
+
async getOrgInviteLink(orgId) {
|
|
1180
|
+
return this.request("GET", ENDPOINTS.ORG_INVITE_LINK(orgId));
|
|
1181
|
+
}
|
|
1182
|
+
/** Rotate the token in place. The old token stops resolving immediately. */
|
|
1183
|
+
async regenerateOrgInviteLink(orgId) {
|
|
1184
|
+
return this.request("POST", ENDPOINTS.ORG_INVITE_LINK_REGENERATE(orgId));
|
|
1185
|
+
}
|
|
1186
|
+
/** Toggle the require-approval flag on the org's invite link. */
|
|
1187
|
+
async updateOrgInviteLink(orgId, data) {
|
|
1188
|
+
return this.request("PATCH", ENDPOINTS.ORG_INVITE_LINK(orgId), data);
|
|
1189
|
+
}
|
|
1190
|
+
/** Redeem an invite-link token. Caller must be authenticated; the
|
|
1191
|
+
* token is the lookup key so this endpoint is NOT org-scoped. */
|
|
1192
|
+
async joinByInviteLink(token) {
|
|
1193
|
+
return this.request("POST", ENDPOINTS.INVITE_LINK_JOIN, { token });
|
|
1194
|
+
}
|
|
1195
|
+
/** Admin: list pending invite-link join requests for an org. */
|
|
1196
|
+
async listOrgJoinRequests(orgId) {
|
|
1197
|
+
const res = await this.request("GET", ENDPOINTS.ORG_INVITE_LINK_JOIN_REQUESTS(orgId));
|
|
1198
|
+
return res.data;
|
|
1199
|
+
}
|
|
1200
|
+
/** Admin: approve or reject a pending invite-link join request. */
|
|
1201
|
+
async decideOrgJoinRequest(orgId, jrId, decision) {
|
|
1202
|
+
return this.request("POST", ENDPOINTS.ORG_INVITE_LINK_JOIN_REQUEST_DECIDE(orgId, jrId), { decision });
|
|
1203
|
+
}
|
|
1133
1204
|
// ---- Direct Messages (org-scoped) ----
|
|
1134
1205
|
async sendDirectMessage(orgId, req) {
|
|
1135
1206
|
return this.request("POST", ENDPOINTS.DM(orgId), req);
|
|
@@ -1399,19 +1470,20 @@ var ParallClient = class _ParallClient {
|
|
|
1399
1470
|
}
|
|
1400
1471
|
// ---- Daemon-mode Machine management (org-scoped, user auth) ----
|
|
1401
1472
|
/**
|
|
1402
|
-
* Create a new daemon-mode Machine. Returns the Machine row +
|
|
1403
|
-
* mck_ token.
|
|
1473
|
+
* Create a new self-hosted daemon-mode Machine. Returns the Machine row +
|
|
1474
|
+
* one-shot mck_ token.
|
|
1404
1475
|
*/
|
|
1405
1476
|
async createMachine(orgId, opts) {
|
|
1406
1477
|
return this.request("POST", ENDPOINTS.MACHINES(orgId), opts);
|
|
1407
1478
|
}
|
|
1408
1479
|
/**
|
|
1409
|
-
* Returns
|
|
1410
|
-
* "Workspaces" UI list. Legacy 1:1 machines are
|
|
1480
|
+
* Returns local daemon_mode=true machines (non-terminated). Backs the
|
|
1481
|
+
* "Workspaces" UI list. Legacy 1:1 and retired hosted daemon machines are
|
|
1482
|
+
* excluded.
|
|
1411
1483
|
*/
|
|
1412
1484
|
async getDaemonMachines(orgId) {
|
|
1413
1485
|
const all = await this.getMachines(orgId);
|
|
1414
|
-
return all.filter((m) => m.daemon_mode && m.status !== "terminated");
|
|
1486
|
+
return all.filter((m) => m.daemon_mode && m.compute_mode === "local" && m.status !== "terminated");
|
|
1415
1487
|
}
|
|
1416
1488
|
/** Attach an agent to a daemon-mode Machine. */
|
|
1417
1489
|
async attachAgent(orgId, machineId, agentId, opts) {
|
|
@@ -1431,8 +1503,8 @@ var ParallClient = class _ParallClient {
|
|
|
1431
1503
|
async retryAgentWorkspaceSetup(orgId, machineId, agentId) {
|
|
1432
1504
|
return this.request("POST", ENDPOINTS.MACHINE_AGENT_WORKSPACE_SETUP(orgId, machineId, agentId));
|
|
1433
1505
|
}
|
|
1434
|
-
async patchMachineLLMSource(orgId, machineId,
|
|
1435
|
-
return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source:
|
|
1506
|
+
async patchMachineLLMSource(orgId, machineId, llmSource2) {
|
|
1507
|
+
return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source: llmSource2 });
|
|
1436
1508
|
}
|
|
1437
1509
|
/** Get machine-level runtime auth state. */
|
|
1438
1510
|
async getMachineRuntimeAuth(orgId, machineId) {
|
|
@@ -1473,8 +1545,9 @@ var ParallClient = class _ParallClient {
|
|
|
1473
1545
|
* daemon should call this on a fixed cadence (e.g. every 30s) so an
|
|
1474
1546
|
* external observer can detect a wedged supervisor.
|
|
1475
1547
|
*/
|
|
1476
|
-
async postMachineHeartbeat() {
|
|
1477
|
-
|
|
1548
|
+
async postMachineHeartbeat(daemonVersion) {
|
|
1549
|
+
const body = daemonVersion ? { daemon_version: daemonVersion } : void 0;
|
|
1550
|
+
return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH, body);
|
|
1478
1551
|
}
|
|
1479
1552
|
async reportAgentWorkspaceState(agentId, state) {
|
|
1480
1553
|
const res = await this.request("PUT", ENDPOINTS.MACHINES_ME_AGENT_WORKSPACE_STATE(agentId), state);
|
|
@@ -1502,6 +1575,10 @@ var ParallClient = class _ParallClient {
|
|
|
1502
1575
|
async resizeMachine(orgId, machineId, spec) {
|
|
1503
1576
|
return this.request("PATCH", ENDPOINTS.MACHINE_SPEC(orgId, machineId), spec);
|
|
1504
1577
|
}
|
|
1578
|
+
/** Signal a local daemon-mode Machine to check for and apply an update. */
|
|
1579
|
+
async requestMachineUpdate(orgId, machineId, mandatory = false) {
|
|
1580
|
+
await this.request("POST", ENDPOINTS.MACHINE_REQUEST_UPDATE(orgId, machineId), { mandatory });
|
|
1581
|
+
}
|
|
1505
1582
|
async browseMachineFilesystem(orgId, machineId, path8) {
|
|
1506
1583
|
return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path8 }, void 0, false, { timeoutMs: 15e3 });
|
|
1507
1584
|
}
|
|
@@ -2352,6 +2429,7 @@ var ParallWs = class {
|
|
|
2352
2429
|
};
|
|
2353
2430
|
|
|
2354
2431
|
// ts/agent-core/dist/gateway-base.js
|
|
2432
|
+
var LIVE_SESSION_STATUSES = /* @__PURE__ */ new Set(["open", "active", "idle"]);
|
|
2355
2433
|
function parseShutdownDeadlineMs(raw) {
|
|
2356
2434
|
if (!raw)
|
|
2357
2435
|
return void 0;
|
|
@@ -2821,6 +2899,17 @@ var ParallAgentGateway = class {
|
|
|
2821
2899
|
parent_session_id: parentSessionId,
|
|
2822
2900
|
runtime_ref: Object.keys(runtimeRef).length > 0 ? runtimeRef : void 0
|
|
2823
2901
|
});
|
|
2902
|
+
if (!LIVE_SESSION_STATUSES.has(session.status)) {
|
|
2903
|
+
this.opts.log?.warn?.(`createAgentSession returned terminal session ${session.id} (${session.status}), resetting runtime for ${sessionKey}`);
|
|
2904
|
+
this.sessionBindings.delete(sessionKey);
|
|
2905
|
+
try {
|
|
2906
|
+
await this.opts.onSessionStale?.(sessionKey);
|
|
2907
|
+
} catch (e) {
|
|
2908
|
+
this.opts.log?.warn?.(`onSessionStale failed: ${e}`);
|
|
2909
|
+
}
|
|
2910
|
+
this.opts.log?.info?.(`stale session self-heal complete for ${sessionKey} \u2014 next dispatch will create a fresh session`);
|
|
2911
|
+
throw new Error(`Agent session ${session.id} is terminal (${session.status})`);
|
|
2912
|
+
}
|
|
2824
2913
|
const binding = {
|
|
2825
2914
|
sessionKey,
|
|
2826
2915
|
agentSessionId: session.id,
|
|
@@ -4279,8 +4368,8 @@ function resolveCodexAgentConfig(env = process.env) {
|
|
|
4279
4368
|
const apiKey = requireEnv(env, "PRLL_API_KEY");
|
|
4280
4369
|
const orgId = requireEnv(env, "PRLL_ORG_ID");
|
|
4281
4370
|
const codexHome = resolvePath(env.PRLL_CODEX_HOME?.trim() || env.CODEX_HOME?.trim() || path4.join(env.HOME || os2.homedir(), ".codex"));
|
|
4282
|
-
const stateDir = resolvePath(env.
|
|
4283
|
-
const workspaceDir = resolvePath(env.
|
|
4371
|
+
const stateDir = resolvePath(env.PRLL_STATE_DIR?.trim() || path4.join(env.HOME || os2.homedir(), ".parall-agent"));
|
|
4372
|
+
const workspaceDir = resolvePath(env.PRLL_WORKSPACE_DIR?.trim() || path4.join(stateDir, "workspace"));
|
|
4284
4373
|
return {
|
|
4285
4374
|
apiUrl,
|
|
4286
4375
|
apiKey,
|
|
@@ -6733,7 +6822,24 @@ async function getAgentMeWithLegacyFallback(client, orgId) {
|
|
|
6733
6822
|
return { ...user, agent_profile: null };
|
|
6734
6823
|
}
|
|
6735
6824
|
}
|
|
6825
|
+
function resolveProviderEnv() {
|
|
6826
|
+
const pc = parseProviderConfig(process.env);
|
|
6827
|
+
if (!pc)
|
|
6828
|
+
return;
|
|
6829
|
+
clearAllProviderCreds(process.env);
|
|
6830
|
+
const source = llmSource(pc);
|
|
6831
|
+
if (source === "parall") {
|
|
6832
|
+
process.env.OPENAI_API_KEY = process.env.PRLL_API_KEY;
|
|
6833
|
+
process.env.OPENAI_BASE_URL = `${process.env.PRLL_API_URL}/api/llm/v1`;
|
|
6834
|
+
} else if (source === "custom") {
|
|
6835
|
+
if (pc.openai_api_key)
|
|
6836
|
+
process.env.OPENAI_API_KEY = pc.openai_api_key;
|
|
6837
|
+
if (pc.openai_base_url)
|
|
6838
|
+
process.env.OPENAI_BASE_URL = pc.openai_base_url;
|
|
6839
|
+
}
|
|
6840
|
+
}
|
|
6736
6841
|
async function main() {
|
|
6842
|
+
resolveProviderEnv();
|
|
6737
6843
|
const config = resolveCodexAgentConfig(process.env);
|
|
6738
6844
|
const client = new ParallClient({
|
|
6739
6845
|
baseUrl: config.apiUrl,
|
|
@@ -6831,6 +6937,9 @@ async function main() {
|
|
|
6831
6937
|
},
|
|
6832
6938
|
onNewSession: () => {
|
|
6833
6939
|
sessionManager.clearMainThread();
|
|
6940
|
+
},
|
|
6941
|
+
onSessionStale: () => {
|
|
6942
|
+
sessionManager.clearMainThread();
|
|
6834
6943
|
}
|
|
6835
6944
|
});
|
|
6836
6945
|
const abortController = new AbortController();
|