@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.
@@ -1,22 +1,23 @@
1
1
  {
2
- "version": "1.30.0",
3
- "built_at": "2026-05-21T12:46:24.454Z",
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": "4e11b293fffa8cd05cbc3f06cf31e19024ec44d5830ba68e645bc0697b6c23c2",
7
- "size": 233525
6
+ "sha256": "99e0829cda93f0ad208c9e017f0210203498a4be1c9077eb60f8e94ac24238db",
7
+ "size": 238575
8
8
  },
9
9
  "parall-codex-agent.js": {
10
- "sha256": "65f489157cb660c029ae17fd882b052dfdd3e1273295ef5f1d6da4ede92cada5",
11
- "size": 264796
10
+ "sha256": "809852713ed2d62fd65a1f050977c7ef44b0e568cd85fe66965ac671040db7b2",
11
+ "size": 269586
12
12
  },
13
13
  "parall-daemon.js": {
14
- "sha256": "57a97577de50b9afc4af7f1bc786412b9b8b05bf0e9b3b9add4085733ccbb56d",
15
- "size": 140056
14
+ "sha256": "d0de188d62e7e274f6eb52e50aca0926cd0e25d82031f56f24ef5c3e56e87786",
15
+ "size": 164213
16
16
  },
17
17
  "parall-openclaw-agent.js": {
18
- "sha256": "d2128b5a15c37c9fe624ed6ba6f1dc15c32235d98795e6171716d9776014aedf",
19
- "size": 8475
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 + one-shot
1403
- * mck_ token. The UI uses this when the user clicks "Create Workspace".
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 only daemon_mode=true machines (non-terminated). Backs the
1410
- * "Workspaces" UI list. Legacy 1:1 machines are excluded.
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, llmSource) {
1435
- return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source: llmSource });
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
- return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH);
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.PRLL_CLAUDE_STATE_DIR?.trim() || path4.join(claudeHome, ".parall-agent"));
4288
- const workspaceDir = resolvePath(env.PRLL_CLAUDE_WORKSPACE_DIR?.trim() || path4.join(stateDir, "workspace"));
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
- async shutdown() {
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
- await adapter.shutdown();
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 + one-shot
1403
- * mck_ token. The UI uses this when the user clicks "Create Workspace".
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 only daemon_mode=true machines (non-terminated). Backs the
1410
- * "Workspaces" UI list. Legacy 1:1 machines are excluded.
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, llmSource) {
1435
- return this.request("PATCH", ENDPOINTS.MACHINE_LLM_SOURCE(orgId, machineId), { llm_source: llmSource });
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
- return this.request("POST", ENDPOINTS.MACHINES_ME_HEALTH);
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.PRLL_CODEX_STATE_DIR?.trim() || path4.join(env.HOME || os2.homedir(), ".parall-agent"));
4283
- const workspaceDir = resolvePath(env.PRLL_CODEX_WORKSPACE_DIR?.trim() || path4.join(stateDir, "workspace"));
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();