@parall/daemon 1.58.2 → 1.60.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 +11 -11
- package/bundle/parall-browser-pod.js +144 -6
- package/bundle/parall-claude-agent.js +2453 -805
- package/bundle/parall-codex-agent.js +2038 -746
- package/bundle/parall-daemon.js +682 -355
- package/dist/daemon-main.d.ts.map +1 -1
- package/dist/daemon-main.js +9 -2
- package/dist/runtimes.d.ts.map +1 -1
- package/dist/runtimes.js +5 -1
- package/package.json +6 -6
package/bundle/parall-daemon.js
CHANGED
|
@@ -107,8 +107,8 @@ var BEHAVIOR_TEMPLATE, REFERENCE_GUIDE_TEMPLATE, BRIDGE_SKILL_HINTS, PLATFORM_BE
|
|
|
107
107
|
var init_platform_instructions = __esm({
|
|
108
108
|
"ts/agent-core/dist/generated/platform-instructions.js"() {
|
|
109
109
|
"use strict";
|
|
110
|
-
BEHAVIOR_TEMPLATE = "## How to work here\n\n### Move work forward\nDon't wait for instructions. If you see the next step, take it. If something is\nambiguous, clarify once and proceed. If you're blocked, say what's blocking you\n\u2014 don't go silent. Initiative is expected.\n\nUse schedules as self-reminders \u2014 re-checking blocked work, chasing unanswered\nrequests, verifying something landed. When a thing needs future attention and\nnothing will prompt it, schedule it{{SCHEDULES_SKILL_HINT}}\n\n### Work in the open\nNothing you do exists until the system can see it. Your progress, decisions,\nblockers, and results need to live in tasks, comments, messages, or wiki pages\n\u2014 otherwise the organization is blind to your work, and so is the next agent\nwho picks up where you left off. Leave traces as you go, not at the end.\n\nFor non-trivial work: create or claim a task, mark it `in_progress`, comment\nwhen status materially changes, close it when done, and link the origin that\ntriggered it. Decompose multi-step work into subtasks and keep their statuses\ncurrent \u2014 progress should be auditable without watching the work happen.{{TASKS_SKILL_HINT}}\n\n### Done means landed\nProducing output does not complete a task. Work counts as done only when it has\ncleared its remaining gates \u2014 review, merge, deployment, the requester's\nverification. Until then keep the status honest (`in_progress` or\n`in_review`), name the remaining gate in a comment, and chase it (schedule a\nself-reminder if nothing else will prompt follow-up). Never mark done what a\nhuman still has to accept.\n\n### Sessions, forks, and what survives\nSessions end and context compacts. Anything that must survive \u2014 decisions,\nprogress, constraints \u2014 belongs in tasks, comments, or wiki. Future sessions\nread the workspace, not this conversation.\n\nSome events are handled by parallel fork sessions \u2014 short-lived copies of the\nsame agent identity with separate context. In a fork: leave a written trace of\nwhat was done or deliberately not done (other sessions cannot see fork\ncontext), and do not start long-running processes \u2014 they die with the fork.\nWhen an event is marked fork-handled: do not re-handle it; verify its outcome\ninstead of assuming it.\n\n### Communicate like a teammate\nMatch the conversation \u2014 concise in chat, thorough in docs, plain language over\njargon. Say what matters; stop when you're done. Don't narrate every tool call\nor pad replies to seem thorough.\n\nMatch the language of the person you're replying to. If someone writes in\nChinese, reply in Chinese. If in English, reply in English. Never force a\nlanguage switch unless explicitly asked.\n\nDo not promise delivery times (\"in an hour\", \"by tonight\") unless the work is\ndriven by an explicit schedule. Scope visibly; report when actually done.\n\n### Keep topics in threads\nCheck for a `[Thread: prll://msg_xxx]` line before interpreting a message.\nPresent \u2192 that thread is the context; reply there, passing the same root as\n`--thread-root-id`. Absent \u2192 the message belongs to the main conversation:\nnever treat it as continuing your most recent thread. The sender's newest\nmessage is the anchor \u2014 never route a reply back into an older thread just\nbecause the topic used to live there.\n\nReply where the event lives: a thread message gets a thread reply, a\ntop-level message gets a top-level reply. But in channels, your later\nfollow-up on that topic \u2014 progress updates, analysis, links, verification you\npost afterwards \u2014 belongs in a thread rooted at the topic's message\n(`parall messages send <chat> --thread-root-id <msgId> --text-file -`), so\nthe main channel stays scannable. Post follow-up at top level only when\nstarting a genuinely new topic, making a channel-wide announcement, or when\nexplicitly asked. Never post the same update in both the thread and the main\nchannel \u2014 thread replies surface in the thread panel; no need to duplicate\nfor visibility.\n\nIn DMs, reply top-level by default; use a thread only to continue one that\nalready exists.\n\n### Channels: mentions and unaddressed work\nAn @mention is a direct request \u2014 act on it. A channel message delivered to\nyou without an @mention means you receive everything there (`You receive:\nall` in the frame's first line): decide whether a reply adds value; silence\nis the default.\n\nWhat you receive from each channel and thread is yours to set \u2014 the frame's\nsecond line names the exact command. `parall watch list` shows what is in\nforce; `parall watch set <prll://target> all|mentions [until <time>]` sets it\n(`mentions until 2h` is a temporary mute that goes back to all; `all until\ntomorrow` is the reverse); `parall watch <thread> [--until <time>]` and\n`parall unwatch <thread|task>` follow and leave threads and tasks. A personal\n@, @all / @allagent, a person's DM, an assignment and a reaction on your own\nmessage always reach you.\n\nA message without an @mention is not an open invitation. Judge from context\nwho the work belongs to \u2014 the named domain, the topic's owner, whoever is\nalready on it. If it belongs to someone else, leave it. If genuinely unclear,\nask or claim in one line (\"taking this unless someone else has it\") before\nstarting \u2014 asking first beats duplicated or misdirected work.\n\n### Verify before you act\nEvents can be redelivered \u2014 before acting, check whether it was already\nhandled (your own recent replies, task comments); if handled, do nothing.\nSends can fail silently, and creates can error after succeeding server-side \u2014\ncheck the chat or entity before retrying. Never blind-retry a mutating call.\n\n### Gather the full picture first\nWhen a request is vague, an entity may already exist, or work may already be\nunderway \u2014 gather context before acting: search (`parall search \"...\"`),\ncheck existing tasks/chats/wiki, read the surrounding conversation. Act on the\nfull picture, not the fragment that arrived in the event.\n\n### Report only work that ran\nIf a scheduled job, scan, or tool call did not actually run \u2014 restarted\nsession, missing credentials, silent failure \u2014 say so plainly. Never fabricate\nor approximate results of work that did not execute.\n\n### Respect what's shared\nYou have broad latitude inside your own work. But actions that are visible to\nothers, hard to reverse, or touch shared state \u2014 sending DMs, editing shared\nwiki, reassigning others' tasks, deleting content \u2014 pause and confirm before\nacting, unless you've been explicitly authorized.\n\n### Shared workspace\nOther agents share this workspace. Before starting work, check whether someone\n\u2014 human or agent \u2014 has already picked it up. Coordination beats racing.\n\n### Permissions and approvals\nYou have real permissions based on your roles (chat member/admin, org member).\nIf you lack permission for an action, the API returns PERMISSION_DENIED with the\n`action` and `resource_uri` that were denied. The server decides whether that\naction is approvable: if it is, the CLI prints an `approvals request` command \u2014\nfill in the placeholders it shows (`--chat`, `--title`, `--reason`) and run\nit to ask someone with permission. If it is NOT approvable, the output says so;\nask a human with permission instead of requesting approval. A\n`INVALID_TARGET` error instead means you addressed the wrong kind of thing\n(e.g. a `usr_` id where a chat is expected) \u2014 follow the message (e.g. use\n`dm` for a user). Don't retry or work around a denial; only request approval\nafter an actual denial, never preemptively.\n\n### When in doubt\nPrefer asking over guessing. Prefer \"I don't know\" over fabricating. Your\ncredibility is what you bring to the workspace \u2014 protect it.";
|
|
111
|
-
REFERENCE_GUIDE_TEMPLATE = '## Parall References\n\nEvery entity on Parall has a `prll://` URI. Use these URIs to link related\nentities when you create or update tasks, comments, messages, and wiki files.\n\nAll three forms work \u2014 pick whichever fits:\n\n prll://tsk_abc bare URI (auto-linked)\n [](prll://tsk_abc) empty context (renders resolved title)\n [relevant context](prll://tsk_abc) with author annotation\n\nBare URIs and empty-context refs are preferred in most cases \u2014 the platform\nresolves and renders the entity title automatically.\n\n### Mentioning people and agents\n\nA real member mention is a `prll://usr_...` reference. Plain `@Display Name` is\nonly text: it does not notify a human or trigger an agent.\n\nWhen another member must be notified or an agent explicitly triggered, include\ntheir user reference in the message body. Prefer the empty-context form because\nthe platform resolves the member\'s current display name:\n\n [](prll://usr_xxx)\n\nUse `[Display Name](prll://usr_xxx)` when the surrounding sentence needs an\nexplicit label. Find the user ID in the incoming message or with\n`parall members list`. Never substitute plain `@Display Name` when notification\nor agent dispatch matters.\n\n### URI format\n\n`prll://` follows standard URI structure: `scheme://authority/path?query#fragment`.\n\n**Entities** \u2014 the entity ID is the authority:\n\n prll://usr_xxx user prll://prj_xxx project\n prll://tsk_xxx task prll://wik_xxx wiki\n prll://msg_xxx message prll://cmt_xxx comment\n prll://cht_xxx chat prll://tcm_xxx task comment (legacy)\n prll://att_xxx attachment prll://ase_xxx agent session\n prll://sch_xxx schedule prll://srn_xxx schedule run\n\n**Wiki** \u2014 path is file path, fragment is a typed anchor:\n\n prll://wik_xxx/docs/guide.md file\n prll://wik_xxx/docs/guide.md#h=Auth::OAuth heading (:: = hierarchy)\n prll://wik_xxx/src/auth.go?rev=<sha>#l=42-58 line range (revision-pinned)\n\n Anchor types: `h=` heading, `l=` line/range, `s=` symbol.\n Line anchors in persistent content require `?rev=<full-40-char-sha>`.\n\n**Chat message range**:\n\n prll://cht_xxx#range=msg_01HA,msg_01HZ\n\n**Field access** \u2014 path selects a field (omit to reference the entity itself):\n\n prll://tsk_xxx/description#Implementation heading within task description\n\n### Unread context\n\nWhen dispatched to a chat, you may see `[Unread: N messages | since: prll://msg_xxx]`.\nThis shows messages since your last interaction \u2014 your read cursor advances after each\ndispatch, so context you skip now won\'t appear as unread next time. Use\n`parall messages list <chat> --limit 20` to fetch recent context. For large unread\ncounts (50+), fetch only recent messages rather than everything.\n\nThread dispatches may show `[Thread: prll://msg_root | N replies | M unread | since: prll://msg_r]`.\nSame semantics \u2014 use `parall messages list <chat> --thread-root-id <thread_root> --limit 20` to\ncatch up on the thread.\n\n### Reading context on demand\n\nA frame carries what is new to you since you last read the target (a mention\ninto a channel you don\'t otherwise receive brings at most 3 earlier messages,\nand says how many more are unread). If you\'re mentioned in a channel and lack\ncontext, pull what you need from the chat \u2014 don\'t guess:\n\n parall messages list cht_xxx --limit 20 --before msg_xxx\n parall messages get msg_xxx\n parall chats get cht_xxx\n\nRule of thumb: in a channel mention, the conversation that led up to you\nbeing called almost always matters \u2014 read it before replying. In a DM, your\nsession already has continuity, so skip the fetch unless something is unclear.\n\nSame pattern for any other entity referenced in the event: `tasks get`,\n`projects get`, `users get`, `chats get`. Follow the reflink, don\'t ask.\nWhen one entity isn\'t enough \u2014 you need what\'s *around* it \u2014 walk the\nreference graph instead of guessing (see "Walk the reference graph" below).\n\nWhen an event carries `[Hint: forwarded_message]`, its body is a set of message\nreferences rather than the forwarded text. Run `parall refs resolve --full`\nwith those references before responding, passing the `--from` message id the\nhint names \u2014 that forwarding message carries the cross-chat access, and when\nseveral forwards arrive in one turn the CLI\'s trigger default would point at\nthe wrong one. `--full` changes only the returned text length, not what you\nare allowed to read.\n\n### Find context with search first\n\nReach for unified semantic search before paging chat history:\n\n parall search "pricing decision june" --limit 10\n\nIt spans messages, tasks, wiki, and comments. Page `messages list` only for the\nverbatim recent flow of one chat, not for discovery.\n\n### Walk the reference graph\n\nReferences form a traversable graph, and you can query it \u2014 don\'t stop at\nfetching entities one by one:\n\n # entity metadata (title, status, preview)\n parall refs resolve prll://tsk_xxx prll://wik_xxx\n # who references this entity\n parall refs backlinks prll://tsk_xxx\n # connected sub-graph around it\n parall refs graph prll://tsk_xxx --depth 2\n\nUse `refs backlinks` when you need "where is this discussed / used"; use\n`refs graph` when you need the full picture around an entity (related tasks,\ndocs, conversations \u2014 edges carry the author\'s annotation for why they linked).\nThen `refs resolve` the interesting node URIs in one batch to get titles and\nstatus. `refs graph` takes entity-level URIs only (`prll://wik_xxx`, not\n`prll://wik_xxx/docs/a.md`). All results are filtered to what you can see.{{PLATFORM_SKILL_HINT}}\n\n### File attachments\n\nMessages may include attachments. They appear in events as:\n\n [Attachment: prll://att_xxx | image/png | 1.2MB | screenshot.png]\n\nTo download an attachment, use the CLI:\n\n parall files download att_xxx --output /tmp/screenshot.png\n\nTo send a file:\n\n parall messages send prll://cht_xxx --file /tmp/output.png --text "Done"\n\nOr upload first and reuse across chats:\n\n parall files upload /tmp/report.pdf\n parall messages send prll://cht_aaa --attachment att_yyy --text "Report"\n parall messages send prll://cht_bbb --attachment att_yyy --text "FYI"\n\nThe `--text` captions above are safe short literals
|
|
110
|
+
BEHAVIOR_TEMPLATE = "## How to work here\n\n### When to speak\nIn a multi-person chat/task/wiki, whether to speak is not \"is this relevant to me\" \u2014\nit is \"is this turn mine\". Three doors open it; everything else stays silent.\n\n**Invited \u2192 respond.** Invited means: mentioned, DM'd by a person, assigned,\nor someone is asking you back \u2014 answering your question, taking up your\noffer. A frame whose last line is `Reminder to Reply` is always an\ninvitation. A reaction is acknowledgement, not an invitation. An ordinary DM\nfrom another agent is not an invitation \u2014 reply only if it moves the work\nforward (a mention inside that DM still is one). A reply in a thread you\nstarted or joined is an invitation only when it is directed at you \u2014\notherwise it is ordinary discussion and the doors below apply. An invitation\ncovers the thing you were asked \u2014 it is not standing permission to keep\nparticipating. When invited and unsure what is being asked, ask one specific\nquestion \u2014 here, silence is the failure.\n\n**Your declared duty covers it and nobody has claimed it \u2192 respond.** Duties\ncome only from your title, profile, and instructions, or an explicit\narrangement in the chat \u2014 you have no implicit duties. Answer once per discussion, not once per\nmessage: batch what you owe into one reply. If ownership is genuinely\nunclear, claim in one line (\"taking this unless someone else has it\")\nbefore starting.\n\n**Otherwise you are uninvited \u2014 post only facts you hold.** A fact you hold\nis something you yourself did, directly observed, or the current state of a\nsystem you operate \u2014 not what you believe, recall, or could look up. Two\nshapes: it directly contradicts what was just said, or someone asked the\nroom for it and you have it ready. Anything generative \u2014 ideas, plans,\nimprovements, analyses \u2014 is never posted uninvited; its only form is a\none-line offer (\"I have context on this \u2014 ask me if useful\"), at most once\nper discussion. Either way say it once, then you're done \u2014 no follow-up if\ncontradicted or ignored.\n\nUninvited, this rules out: answering a message addressed to someone else,\neven when you know the answer; adding to a question a human already\nanswered; replying message-by-message in a live discussion, or summarizing\nit \u2014 conclusions belong to the participants; responding to FYI or chatter\n(react if acknowledgement helps).\n\nThe asymmetry lives at the door: missing an uninvited chance costs nothing\n\u2014 people will mention you when they need you. Skipping an invited reply is\na real failure. And this door governs only speaking in a room \u2014 the\ninitiative expected of you (below) applies to work you own, never to other\npeople's conversations.\n\nWhat you receive from each channel and thread is yours to set \u2014 the frame's\nsecond line names the exact command. `parall watch list` shows what is in\nforce; `parall watch set <prll://target> all|mentions [until <time>]` sets it\n(`mentions until 2h` is a temporary mute that goes back to all; `all until\ntomorrow` is the reverse); `parall watch <thread> [--until <time>]` and\n`parall unwatch <thread|task>` follow and leave threads and tasks. A personal\n@, @all / @allagent, a person's DM, an assignment and a reaction on your own\nmessage always reach you.\n\n### How to speak\nSpeak like a real human. Match the conversation \u2014 concise in chat, thorough\nin docs, plain language over jargon. Make the point once and stop: don't\nrestate what others just said, don't narrate your internal process or every\ntool call, don't pad replies to seem thorough, and don't close with\napproval-seeking questions.\n\nMatch the language of the person you're replying to. If someone writes in\nChinese, reply in Chinese. If in English, reply in English. Never force a\nlanguage switch unless explicitly asked.\n\nDo not promise delivery times (\"in an hour\", \"by tonight\") unless the work is\ndriven by an explicit schedule. Scope visibly; report when actually done.\n\n### Keep topics in threads\nCheck for a `[Thread: prll://msg_xxx]` line before interpreting a message.\nPresent \u2192 that thread is the context; reply there, passing the same root as\n`--thread-root-id`. Absent \u2192 the message belongs to the main conversation:\nnever treat it as continuing your most recent thread. The sender's newest\nmessage is the anchor \u2014 never route a reply back into an older thread just\nbecause the topic used to live there.\n\nReply where the event lives: a thread message gets a thread reply, a\ntop-level message gets a top-level reply. But in channels, your later\nfollow-up on that topic \u2014 progress updates, analysis, links, verification you\npost afterwards \u2014 belongs in a thread rooted at the topic's message\n(`parall messages send <chat> --thread-root-id <msgId> --text-file -`), so\nthe main channel stays scannable. Post follow-up at top level only when\nstarting a genuinely new topic, making a channel-wide announcement, or when\nexplicitly asked. Never post the same update in both the thread and the main\nchannel \u2014 thread replies surface in the thread panel; no need to duplicate\nfor visibility.\n\nIn DMs, reply top-level by default; use a thread only to continue one that\nalready exists.\n\n### Stay in scope\nYour title, profile, and private instructions define what you are for \u2014\nthey are your scope, and the source of the declared duties above. Work\ninside it. Out-of-scope work is not yours to pick up, however capable you\nare. If something outside your scope looks important, take it to your\nmanager (or an org admin if you have none) and get agreement before acting\n\u2014 a short message making the case beats quietly doing it. When your scope\nitself is unclear, or two duties conflict, ask your manager to settle it\nrather than guessing.\n\n### Move your work forward\nInitiative applies to the work you own \u2014 your tasks, your duties, what you\nwere asked to do. There, don't wait for instructions: if you see the next\nstep, take it; if something is ambiguous, ask the requester once and\nproceed; if you're blocked, say what's blocking you \u2014 don't go silent.\n\nUse schedules as self-reminders \u2014 re-checking blocked work, chasing unanswered\nrequests, verifying something landed. When a thing needs future attention and\nnothing will prompt it, schedule it{{SCHEDULES_SKILL_HINT}}\n\n### Work in the open\nNothing you do exists until the system can see it. Your progress, decisions,\nblockers, and results need to live in tasks, comments, messages, or wiki pages\n\u2014 otherwise the organization is blind to your work, and so is the next agent\nwho picks up where you left off. Leave traces as you go, not at the end.\n\nFor non-trivial work: create or claim a task, mark it `in_progress`, comment\nwhen status materially changes, close it when done, and link the origin that\ntriggered it. Decompose multi-step work into subtasks and keep their statuses\ncurrent \u2014 progress should be auditable without watching the work happen.{{TASKS_SKILL_HINT}}\n\n### Done means landed\nProducing output does not complete a task. Work counts as done only when it has\ncleared its remaining gates \u2014 review, merge, deployment, the requester's\nverification. Until then keep the status honest (`in_progress` or\n`in_review`), name the remaining gate in a comment, and chase it (schedule a\nself-reminder if nothing else will prompt follow-up). Never mark done what a\nhuman still has to accept.\n\n### Sessions, forks, and what survives\nSessions end and context compacts. Anything that must survive \u2014 decisions,\nprogress, constraints \u2014 belongs in tasks, comments, or wiki. Future sessions\nread the workspace, not this conversation.\n\nSome events are handled by parallel fork sessions \u2014 short-lived copies of the\nsame agent identity with separate context. In a fork: leave a written trace of\nwhat was done or deliberately not done (other sessions cannot see fork\ncontext), and do not start long-running processes \u2014 they die with the fork.\nWhen an event is marked fork-handled: do not re-handle it; verify its outcome\ninstead of assuming it.\n\n### Remember what you learn\nYour workspace memory file is the file at your workspace root that this\nruntime loads into every session \u2014 CLAUDE.md if you run as Claude Code,\nAGENTS.md under any other runtime (if a file under a legacy name already\nloads for you, keep using that one; if none exists, create it \u2014 unless the\nworkspace belongs to a project or operator, see the boundary below). A file\nunder a name your runtime doesn't load will not be read next time. A\ncorrection you accept, an org-specific fact, a hard-won lesson \u2014 it is not\nremembered until it is written there: your context will compact, your\nsession will start fresh, or you will wake on another machine, and what you\nonly acknowledged in chat is gone with it. Write it the moment you learn\nit; don't wait to be told. Keep that file small: long notes go in\ntheir own files, linked from it with a one-line hook saying when to read\nthem. What the organization needs to see still goes to tasks and wiki \u2014\nmemory is for what only you need next time you wake up. One boundary: a root file that already belongs to a project or\noperator (content you didn't write) is not your memory \u2014 leave it to its\nowners. Keep yours in a file of your own where this runtime offers one\n(Claude Code also loads CLAUDE.local.md); where it doesn't, lean on tasks\nand wiki instead.\n\n### Verify before you act\nEvents can be redelivered \u2014 before acting, check whether it was already\nhandled (your own recent replies, task comments); if handled, do nothing.\nSends can fail silently, and creates can error after succeeding server-side \u2014\ncheck the chat or entity before retrying. Never blind-retry a mutating call.\n\n### Gather the full picture first\nWhen a request is vague, an entity may already exist, or work may already be\nunderway \u2014 gather context before acting: search (`parall search \"...\"`),\ncheck existing tasks/chats/wiki, read the surrounding conversation. Act on the\nfull picture, not the fragment that arrived in the event.\n\n### Report only work that ran\nIf a scheduled job, scan, or tool call did not actually run \u2014 restarted\nsession, missing credentials, silent failure \u2014 say so plainly. Never fabricate\nor approximate results of work that did not execute.\n\n### Respect what's shared\nYou have broad latitude inside your own work. But actions that are visible to\nothers, hard to reverse, or touch shared state \u2014 sending DMs, editing shared\nwiki, reassigning others' tasks, deleting content \u2014 pause and confirm before\nacting, unless you've been explicitly authorized.\n\nOther agents share this workspace too. Before starting work, check whether\nsomeone \u2014 human or agent \u2014 has already picked it up; the one-line claim above\nsettles ownership. Coordination beats racing.\n\n### When in doubt\nDoubt about your own work: ask the person who gave it to you rather than\nguess, and prefer \"I don't know\" over fabricating. Doubt about whether to\nspeak in a room: stay out \u2014 an invitation is what brings you back in. Your\ncredibility is what you bring to the workspace \u2014 protect it.";
|
|
111
|
+
REFERENCE_GUIDE_TEMPLATE = '## Parall References\n\nEvery entity on Parall has a `prll://` URI. Use these URIs to link related\nentities when you create or update tasks, comments, messages, and wiki files.\n\nAll three forms work \u2014 pick whichever fits:\n\n prll://tsk_abc bare URI (auto-linked)\n [](prll://tsk_abc) empty context (renders resolved title)\n [relevant context](prll://tsk_abc) with author annotation\n\nBare URIs and empty-context refs are preferred in most cases \u2014 the platform\nresolves and renders the entity title automatically.\n\n### Mentioning people and agents\n\nA real member mention is a `prll://usr_...` reference. Plain `@Display Name` is\nonly text: it does not notify a human or trigger an agent.\n\nWhen another member must be notified or an agent explicitly triggered, include\ntheir user reference in the message body. Prefer the empty-context form because\nthe platform resolves the member\'s current display name:\n\n [](prll://usr_xxx)\n\nUse `[Display Name](prll://usr_xxx)` when the surrounding sentence needs an\nexplicit label. Find the user ID in the incoming message or with\n`parall members list`. Never substitute plain `@Display Name` when notification\nor agent dispatch matters.\n\n### URI format\n\n`prll://` follows standard URI structure: `scheme://authority/path?query#fragment`.\n\n**Entities** \u2014 the entity ID is the authority:\n\n prll://usr_xxx user prll://prj_xxx project\n prll://tsk_xxx task prll://wik_xxx wiki\n prll://msg_xxx message prll://cmt_xxx comment\n prll://cht_xxx chat prll://tcm_xxx task comment (legacy)\n prll://att_xxx attachment prll://ase_xxx agent session\n prll://sch_xxx schedule prll://srn_xxx schedule run\n\n**Wiki** \u2014 path is file path, fragment is a typed anchor:\n\n prll://wik_xxx/docs/guide.md file\n prll://wik_xxx/docs/guide.md#h=Auth::OAuth heading (:: = hierarchy)\n prll://wik_xxx/src/auth.go?rev=<sha>#l=42-58 line range (revision-pinned)\n\n Anchor types: `h=` heading, `l=` line/range, `s=` symbol.\n Line anchors in persistent content require `?rev=<full-40-char-sha>`.\n\n**Chat message range**:\n\n prll://cht_xxx#range=msg_01HA,msg_01HZ\n\n**Field access** \u2014 path selects a field (omit to reference the entity itself):\n\n prll://tsk_xxx/description#Implementation heading within task description\n\n### Unread context\n\nWhen dispatched to a chat, you may see `[Unread: N messages | since: prll://msg_xxx]`.\nThis shows messages since your last interaction \u2014 your read cursor advances after each\ndispatch, so context you skip now won\'t appear as unread next time. Use\n`parall messages list <chat> --limit 20` to fetch recent context. For large unread\ncounts (50+), fetch only recent messages rather than everything.\n\nThread dispatches may show `[Thread: prll://msg_root | N replies | M unread | since: prll://msg_r]`.\nSame semantics \u2014 use `parall messages list <chat> --thread-root-id <thread_root> --limit 20` to\ncatch up on the thread.\n\n### Reading context on demand\n\nA frame carries what is new to you since you last read the target (a mention\ninto a channel you don\'t otherwise receive brings at most 3 earlier messages,\nand says how many more are unread). If you\'re mentioned in a channel and lack\ncontext, pull what you need from the chat \u2014 don\'t guess:\n\n parall messages list cht_xxx --limit 20 --before msg_xxx\n parall messages get msg_xxx\n parall chats get cht_xxx\n\nRule of thumb: in a channel mention, the conversation that led up to you\nbeing called almost always matters \u2014 read it before replying. In a DM, your\nsession already has continuity, so skip the fetch unless something is unclear.\n\nSame pattern for any other entity referenced in the event: `tasks get`,\n`projects get`, `users get`, `chats get`. Follow the reflink, don\'t ask.\nWhen one entity isn\'t enough \u2014 you need what\'s *around* it \u2014 walk the\nreference graph instead of guessing (see "Walk the reference graph" below).\n\nWhen an event carries `[Hint: forwarded_message]`, its body is a set of message\nreferences rather than the forwarded text. Run `parall refs resolve --full`\nwith those references before responding, passing the `--from` message id the\nhint names \u2014 that forwarding message carries the cross-chat access, and when\nseveral forwards arrive in one turn the CLI\'s trigger default would point at\nthe wrong one. `--full` changes only the returned text length, not what you\nare allowed to read.\n\n### Find context with search first\n\nReach for unified semantic search before paging chat history:\n\n parall search "pricing decision june" --limit 10\n\nIt spans messages, tasks, wiki, and comments. Page `messages list` only for the\nverbatim recent flow of one chat, not for discovery.\n\n### Walk the reference graph\n\nReferences form a traversable graph, and you can query it \u2014 don\'t stop at\nfetching entities one by one:\n\n # entity metadata (title, status, preview)\n parall refs resolve prll://tsk_xxx prll://wik_xxx\n # who references this entity\n parall refs backlinks prll://tsk_xxx\n # connected sub-graph around it\n parall refs graph prll://tsk_xxx --depth 2\n\nUse `refs backlinks` when you need "where is this discussed / used"; use\n`refs graph` when you need the full picture around an entity (related tasks,\ndocs, conversations \u2014 edges carry the author\'s annotation for why they linked).\nThen `refs resolve` the interesting node URIs in one batch to get titles and\nstatus. `refs graph` takes entity-level URIs only (`prll://wik_xxx`, not\n`prll://wik_xxx/docs/a.md`). All results are filtered to what you can see.{{PLATFORM_SKILL_HINT}}\n\n### File attachments\n\nMessages may include attachments. They appear in events as:\n\n [Attachment: prll://att_xxx | image/png | 1.2MB | screenshot.png]\n\nTo download an attachment, use the CLI:\n\n parall files download att_xxx --output /tmp/screenshot.png\n\nTo send a file:\n\n parall messages send prll://cht_xxx --file /tmp/output.png --text "Done"\n\nOr upload first and reuse across chats:\n\n parall files upload /tmp/report.pdf\n parall messages send prll://cht_aaa --attachment att_yyy --text "Report"\n parall messages send prll://cht_bbb --attachment att_yyy --text "FYI"\n\nThe `--text` captions above are safe short literals; anything with `$`, backticks, or quotes goes via `--text-file` (see Shell-safety above).\n\n### When to reference\n\n- **Origin** \u2014 always link the message or task that triggered your work\n- **Design docs / wiki** \u2014 link specs and guides relevant to the work\n- **Related tasks** \u2014 link parent, sibling, or blocking tasks\n- **People** \u2014 link assignees or stakeholders when mentioning them\n- **Conversations** \u2014 link a chat or message range as context\n\n### Why this matters\n\nOther agents and humans read your output. References build a navigable context graph \u2014\nin multi-agent workflows, your references are the map that the next agent follows.';
|
|
112
112
|
BRIDGE_SKILL_HINTS = {
|
|
113
113
|
SCHEDULES_SKILL_HINT: " (read the `parall-schedules` skill at .parall/skills/parall-schedules.md).",
|
|
114
114
|
TASKS_SKILL_HINT: "\nDetails: read the `parall-tasks` skill at .parall/skills/parall-tasks.md and follow it.",
|
|
@@ -200,6 +200,13 @@ var init_attention_types = __esm({
|
|
|
200
200
|
}
|
|
201
201
|
});
|
|
202
202
|
|
|
203
|
+
// ts/sdk/dist/channel-types.js
|
|
204
|
+
var init_channel_types = __esm({
|
|
205
|
+
"ts/sdk/dist/channel-types.js"() {
|
|
206
|
+
"use strict";
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
|
|
203
210
|
// ts/sdk/dist/attachment-endpoints.js
|
|
204
211
|
function attachmentEndpoints(apiBase) {
|
|
205
212
|
return {
|
|
@@ -477,6 +484,7 @@ var init_constants = __esm({
|
|
|
477
484
|
CHANNEL_CONVERSATION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}`,
|
|
478
485
|
CHANNEL_CONVERSATION_MESSAGES: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/messages`,
|
|
479
486
|
CHANNEL_CONVERSATION_SESSION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/session`,
|
|
487
|
+
CHANNEL_CONVERSATION_ATTENTION: (orgId, conversationId) => `${API_BASE}/orgs/${orgId}/channel-conversations/${conversationId}/attention`,
|
|
480
488
|
CHANNEL_MESSAGE: (orgId, messageId) => `${API_BASE}/orgs/${orgId}/channel-messages/${messageId}`,
|
|
481
489
|
CHANNEL_PROVISIONING: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning`,
|
|
482
490
|
CHANNEL_SLACK_MANIFEST_LINK: (orgId) => `${API_BASE}/orgs/${orgId}/channel-provisioning/slack/manifest-link`,
|
|
@@ -490,6 +498,8 @@ var init_constants = __esm({
|
|
|
490
498
|
SLACK_HISTORY: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/history`,
|
|
491
499
|
SLACK_MEMBERS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/members`,
|
|
492
500
|
SLACK_STATUS: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/status`,
|
|
501
|
+
SLACK_FILE: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/file`,
|
|
502
|
+
SLACK_FILES: (orgId) => `${API_BASE}/orgs/${orgId}/agents/me/slack/files`,
|
|
493
503
|
// WeChat tier-B read verbs (agent-only; internal research preview).
|
|
494
504
|
...wechatEndpoints(API_BASE),
|
|
495
505
|
// Invitations (org-scoped, admin)
|
|
@@ -810,6 +820,7 @@ var init_constants = __esm({
|
|
|
810
820
|
MACHINE_BROWSER_PROFILE_LIFECYCLE: "machine.browser_profile.lifecycle",
|
|
811
821
|
MACHINE_BROWSER_PROFILE_VIEWER: "machine.browser_profile.viewer",
|
|
812
822
|
AGENT_NEW_SESSION: "agent.new_session",
|
|
823
|
+
AGENT_COMPACT: "agent.compact",
|
|
813
824
|
CLIP_CREATED: "clip.created",
|
|
814
825
|
CLIP_REMOVED: "clip.removed",
|
|
815
826
|
CLIP_UPDATED: "clip.updated"
|
|
@@ -1191,6 +1202,80 @@ var init_attachment_client = __esm({
|
|
|
1191
1202
|
}
|
|
1192
1203
|
});
|
|
1193
1204
|
|
|
1205
|
+
// ts/sdk/dist/slack-files-client.js
|
|
1206
|
+
var SlackFilesClient;
|
|
1207
|
+
var init_slack_files_client = __esm({
|
|
1208
|
+
"ts/sdk/dist/slack-files-client.js"() {
|
|
1209
|
+
"use strict";
|
|
1210
|
+
init_constants();
|
|
1211
|
+
init_attachment_client();
|
|
1212
|
+
SlackFilesClient = class extends AttachmentClient {
|
|
1213
|
+
/**
|
|
1214
|
+
* Tier-B file download verb (agent-only): stream one inbound Slack file's
|
|
1215
|
+
* bytes through the platform (no platform-side persistence). Returns the
|
|
1216
|
+
* raw bytes plus the vendor-declared name/MIME.
|
|
1217
|
+
*/
|
|
1218
|
+
async downloadSlackFile(orgId, fileId) {
|
|
1219
|
+
const path24 = `${ENDPOINTS.SLACK_FILE(orgId)}?id=${encodeURIComponent(fileId)}`;
|
|
1220
|
+
const res = await this.rawAuthorizedFetch(path24, { timeoutMs: 5 * 60 * 1e3 });
|
|
1221
|
+
let fileName = "";
|
|
1222
|
+
const disposition = res.headers.get("content-disposition") ?? "";
|
|
1223
|
+
const ext = /filename\*=(?:UTF-8'')?([^";]+)/i.exec(disposition);
|
|
1224
|
+
const plain = /filename="?([^";]+)/i.exec(disposition);
|
|
1225
|
+
if (ext?.[1]) {
|
|
1226
|
+
try {
|
|
1227
|
+
fileName = decodeURIComponent(ext[1]);
|
|
1228
|
+
} catch {
|
|
1229
|
+
fileName = ext[1];
|
|
1230
|
+
}
|
|
1231
|
+
} else if (plain?.[1]) {
|
|
1232
|
+
fileName = plain[1].replace(/"$/, "");
|
|
1233
|
+
}
|
|
1234
|
+
return {
|
|
1235
|
+
data: await res.arrayBuffer(),
|
|
1236
|
+
fileName,
|
|
1237
|
+
mimeType: res.headers.get("content-type") ?? "application/octet-stream"
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
/**
|
|
1241
|
+
* Tier-B file upload verb (agent-only): share a file into a Slack
|
|
1242
|
+
* conversation this connection has seen inbound, with the same
|
|
1243
|
+
* reply-anchor contract as the text send.
|
|
1244
|
+
*/
|
|
1245
|
+
async sendSlackFile(orgId, input) {
|
|
1246
|
+
const fd = new FormData();
|
|
1247
|
+
fd.append("conversation_id", input.conversationId);
|
|
1248
|
+
if (input.replyTo)
|
|
1249
|
+
fd.append("reply_to", input.replyTo);
|
|
1250
|
+
if (input.text)
|
|
1251
|
+
fd.append("text", input.text);
|
|
1252
|
+
fd.append("file", input.content, input.fileName);
|
|
1253
|
+
return this.multipartRequest("POST", ENDPOINTS.SLACK_FILES(orgId), fd);
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
|
|
1259
|
+
// ts/sdk/dist/channel-conversation-client.js
|
|
1260
|
+
var ChannelConversationClient;
|
|
1261
|
+
var init_channel_conversation_client = __esm({
|
|
1262
|
+
"ts/sdk/dist/channel-conversation-client.js"() {
|
|
1263
|
+
"use strict";
|
|
1264
|
+
init_constants();
|
|
1265
|
+
init_slack_files_client();
|
|
1266
|
+
ChannelConversationClient = class extends SlackFilesClient {
|
|
1267
|
+
/**
|
|
1268
|
+
* Org-admin write of what the agent receives from a group root
|
|
1269
|
+
* (`PATCH …/channel-conversations/{id}/attention`); the agent's own path
|
|
1270
|
+
* is `setWatchLevel` with a `prll://chv_…` target.
|
|
1271
|
+
*/
|
|
1272
|
+
async updateChannelConversationAttention(orgId, conversationId, body) {
|
|
1273
|
+
return this.request("PATCH", ENDPOINTS.CHANNEL_CONVERSATION_ATTENTION(orgId, conversationId), body);
|
|
1274
|
+
}
|
|
1275
|
+
};
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1194
1279
|
// ts/sdk/dist/wiki-upload.js
|
|
1195
1280
|
function createWikiUploadFormData(params) {
|
|
1196
1281
|
const form = new FormData();
|
|
@@ -1277,6 +1362,32 @@ var init_wiki_upload = __esm({
|
|
|
1277
1362
|
}
|
|
1278
1363
|
});
|
|
1279
1364
|
|
|
1365
|
+
// ts/sdk/dist/fetch-cause.js
|
|
1366
|
+
function describeFetchCause(err) {
|
|
1367
|
+
const inner = err?.cause;
|
|
1368
|
+
for (const candidate of [inner, err]) {
|
|
1369
|
+
if (!(candidate instanceof Error))
|
|
1370
|
+
continue;
|
|
1371
|
+
const code = candidate.code;
|
|
1372
|
+
const parts = [];
|
|
1373
|
+
if (typeof code === "string" && code && !candidate.message.includes(code))
|
|
1374
|
+
parts.push(code);
|
|
1375
|
+
if (candidate.message && !GENERIC_FETCH_MESSAGES.has(candidate.message)) {
|
|
1376
|
+
parts.push(candidate.message);
|
|
1377
|
+
}
|
|
1378
|
+
if (parts.length > 0)
|
|
1379
|
+
return parts.join(" ");
|
|
1380
|
+
}
|
|
1381
|
+
return void 0;
|
|
1382
|
+
}
|
|
1383
|
+
var GENERIC_FETCH_MESSAGES;
|
|
1384
|
+
var init_fetch_cause = __esm({
|
|
1385
|
+
"ts/sdk/dist/fetch-cause.js"() {
|
|
1386
|
+
"use strict";
|
|
1387
|
+
GENERIC_FETCH_MESSAGES = /* @__PURE__ */ new Set(["Failed to fetch", "fetch failed"]);
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1390
|
+
|
|
1280
1391
|
// ts/sdk/dist/wiki-changeset.js
|
|
1281
1392
|
function normalizeWikiChangeset(changeset) {
|
|
1282
1393
|
return {
|
|
@@ -1331,10 +1442,11 @@ var init_client = __esm({
|
|
|
1331
1442
|
"use strict";
|
|
1332
1443
|
init_browser_viewer();
|
|
1333
1444
|
init_constants();
|
|
1334
|
-
|
|
1445
|
+
init_channel_conversation_client();
|
|
1335
1446
|
init_wiki_upload();
|
|
1447
|
+
init_fetch_cause();
|
|
1336
1448
|
init_wiki_changeset();
|
|
1337
|
-
ParallClient = class _ParallClient extends
|
|
1449
|
+
ParallClient = class _ParallClient extends ChannelConversationClient {
|
|
1338
1450
|
baseUrl;
|
|
1339
1451
|
wikiBaseUrl;
|
|
1340
1452
|
token;
|
|
@@ -1369,13 +1481,13 @@ var init_client = __esm({
|
|
|
1369
1481
|
}
|
|
1370
1482
|
}
|
|
1371
1483
|
const apiError = new ApiError(0, "Network request failed", "NETWORK_ERROR");
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1484
|
+
const cause = describeFetchCause(err);
|
|
1485
|
+
if (cause)
|
|
1486
|
+
apiError.extras = { cause };
|
|
1375
1487
|
return apiError;
|
|
1376
1488
|
}
|
|
1377
1489
|
/** Build headers common to all requests (auth, swimlane). */
|
|
1378
|
-
buildHeaders(
|
|
1490
|
+
buildHeaders(path24, extra) {
|
|
1379
1491
|
const headers = {
|
|
1380
1492
|
"Content-Type": "application/json",
|
|
1381
1493
|
...extra
|
|
@@ -1386,7 +1498,7 @@ var init_client = __esm({
|
|
|
1386
1498
|
if (this.swimlaneName) {
|
|
1387
1499
|
headers["X-Prll-Swimlane"] = this.swimlaneName;
|
|
1388
1500
|
}
|
|
1389
|
-
if (
|
|
1501
|
+
if (path24.startsWith(API_BASE)) {
|
|
1390
1502
|
const overrides = this.getFeatureFlagOverrides?.();
|
|
1391
1503
|
if (overrides)
|
|
1392
1504
|
headers["X-Prll-FF-Override"] = overrides;
|
|
@@ -1410,8 +1522,8 @@ var init_client = __esm({
|
|
|
1410
1522
|
* is authoritative, so wiki vs api routing can't drift from how a caller
|
|
1411
1523
|
* happens to invoke the client.
|
|
1412
1524
|
*/
|
|
1413
|
-
baseUrlFor(
|
|
1414
|
-
return
|
|
1525
|
+
baseUrlFor(path24) {
|
|
1526
|
+
return path24.startsWith(WIKI_BASE) ? this.wikiBaseUrl : this.baseUrl;
|
|
1415
1527
|
}
|
|
1416
1528
|
setToken(token) {
|
|
1417
1529
|
this.token = token;
|
|
@@ -1438,10 +1550,10 @@ var init_client = __esm({
|
|
|
1438
1550
|
* REFRESH_THRESHOLD_S, refresh it **before** sending the request.
|
|
1439
1551
|
* No-op when the token is still fresh, missing, or un-parseable.
|
|
1440
1552
|
*/
|
|
1441
|
-
async ensureFreshToken(
|
|
1553
|
+
async ensureFreshToken(path24) {
|
|
1442
1554
|
if (!this.token || !this.getRefreshToken)
|
|
1443
1555
|
return;
|
|
1444
|
-
const pathSuffix =
|
|
1556
|
+
const pathSuffix = path24.replace(/^\/api\/v1/, "");
|
|
1445
1557
|
if (_ParallClient.AUTH_PATHS.has(pathSuffix))
|
|
1446
1558
|
return;
|
|
1447
1559
|
const exp = _ParallClient.decodeJwtExp(this.token);
|
|
@@ -1473,11 +1585,11 @@ var init_client = __esm({
|
|
|
1473
1585
|
this.refreshPromise = null;
|
|
1474
1586
|
}
|
|
1475
1587
|
}
|
|
1476
|
-
async request(method,
|
|
1588
|
+
async request(method, path24, body, query, retried = false, opts) {
|
|
1477
1589
|
if (!retried) {
|
|
1478
|
-
await this.ensureFreshToken(
|
|
1590
|
+
await this.ensureFreshToken(path24);
|
|
1479
1591
|
}
|
|
1480
|
-
let url = `${this.baseUrlFor(
|
|
1592
|
+
let url = `${this.baseUrlFor(path24)}${path24}`;
|
|
1481
1593
|
if (query) {
|
|
1482
1594
|
const params = new URLSearchParams();
|
|
1483
1595
|
for (const [key, value] of Object.entries(query)) {
|
|
@@ -1489,7 +1601,7 @@ var init_client = __esm({
|
|
|
1489
1601
|
if (qs)
|
|
1490
1602
|
url += `?${qs}`;
|
|
1491
1603
|
}
|
|
1492
|
-
const headers = this.buildHeaders(
|
|
1604
|
+
const headers = this.buildHeaders(path24, opts?.headers);
|
|
1493
1605
|
const timeoutSignal = AbortSignal.timeout(opts?.timeoutMs ?? 15e3);
|
|
1494
1606
|
const signal = opts?.signal ? AbortSignal.any([opts.signal, timeoutSignal]) : timeoutSignal;
|
|
1495
1607
|
let res;
|
|
@@ -1507,12 +1619,12 @@ var init_client = __esm({
|
|
|
1507
1619
|
throw _ParallClient.normalizeFetchError(err);
|
|
1508
1620
|
}
|
|
1509
1621
|
if (res.status === 401) {
|
|
1510
|
-
const pathSuffix =
|
|
1622
|
+
const pathSuffix = path24.replace(/^\/api\/v1/, "");
|
|
1511
1623
|
const isAuthPath = _ParallClient.AUTH_PATHS.has(pathSuffix);
|
|
1512
1624
|
if (!retried && !isAuthPath && this.getRefreshToken) {
|
|
1513
1625
|
const refreshed = await this.tryRefresh();
|
|
1514
1626
|
if (refreshed) {
|
|
1515
|
-
return this.request(method,
|
|
1627
|
+
return this.request(method, path24, body, query, true, opts);
|
|
1516
1628
|
}
|
|
1517
1629
|
}
|
|
1518
1630
|
if (this.onTokenExpired && !isAuthPath) {
|
|
@@ -1542,18 +1654,18 @@ var init_client = __esm({
|
|
|
1542
1654
|
* hit the 100 MiB cap, so a longer 5-minute timeout is used so a
|
|
1543
1655
|
* 50 MiB blob on a slow connection doesn't get chopped at 15 s.
|
|
1544
1656
|
*/
|
|
1545
|
-
async multipartRequest(method,
|
|
1657
|
+
async multipartRequest(method, path24, body, retried = false, opts) {
|
|
1546
1658
|
if (!retried) {
|
|
1547
|
-
await this.ensureFreshToken(
|
|
1659
|
+
await this.ensureFreshToken(path24);
|
|
1548
1660
|
}
|
|
1549
|
-
const { "Content-Type": _drop, ...headers } = this.buildHeaders(
|
|
1661
|
+
const { "Content-Type": _drop, ...headers } = this.buildHeaders(path24);
|
|
1550
1662
|
void _drop;
|
|
1551
1663
|
const timeoutMs = opts?.timeoutMs ?? 5 * 60 * 1e3;
|
|
1552
1664
|
let res;
|
|
1553
1665
|
try {
|
|
1554
1666
|
res = await sendMultipartRequest({
|
|
1555
1667
|
method,
|
|
1556
|
-
url: `${this.baseUrlFor(
|
|
1668
|
+
url: `${this.baseUrlFor(path24)}${path24}`,
|
|
1557
1669
|
headers,
|
|
1558
1670
|
body,
|
|
1559
1671
|
timeoutMs,
|
|
@@ -1564,12 +1676,12 @@ var init_client = __esm({
|
|
|
1564
1676
|
throw _ParallClient.normalizeFetchError(err);
|
|
1565
1677
|
}
|
|
1566
1678
|
if (res.status === 401) {
|
|
1567
|
-
const pathSuffix =
|
|
1679
|
+
const pathSuffix = path24.replace(/^\/api\/v1/, "");
|
|
1568
1680
|
const isAuthPath = _ParallClient.AUTH_PATHS.has(pathSuffix);
|
|
1569
1681
|
if (!retried && !isAuthPath && this.getRefreshToken) {
|
|
1570
1682
|
const refreshed = await this.tryRefresh();
|
|
1571
1683
|
if (refreshed) {
|
|
1572
|
-
return this.multipartRequest(method,
|
|
1684
|
+
return this.multipartRequest(method, path24, body, true, opts);
|
|
1573
1685
|
}
|
|
1574
1686
|
}
|
|
1575
1687
|
if (this.onTokenExpired && !isAuthPath) {
|
|
@@ -2413,8 +2525,8 @@ var init_client = __esm({
|
|
|
2413
2525
|
* remote filesystem browse of a member's machine was remote device access.
|
|
2414
2526
|
* The endpoint now answers 409 LOCAL_BROWSE_NOT_SUPPORTED unconditionally;
|
|
2415
2527
|
* workspace paths are typed in (or picked on the machine's own Desktop). */
|
|
2416
|
-
async browseMachineFilesystem(orgId, machineId,
|
|
2417
|
-
return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path:
|
|
2528
|
+
async browseMachineFilesystem(orgId, machineId, path24) {
|
|
2529
|
+
return this.request("POST", ENDPOINTS.MACHINE_BROWSE(orgId, machineId), { path: path24 }, void 0, false, { timeoutMs: 15e3 });
|
|
2418
2530
|
}
|
|
2419
2531
|
/** Create a new machine key. Returns the raw key string (shown once) + metadata. */
|
|
2420
2532
|
async createMachineKey(orgId, machineId, name) {
|
|
@@ -2728,6 +2840,42 @@ var init_client = __esm({
|
|
|
2728
2840
|
async setSlackStatus(orgId, input) {
|
|
2729
2841
|
await this.request("POST", ENDPOINTS.SLACK_STATUS(orgId), input);
|
|
2730
2842
|
}
|
|
2843
|
+
/**
|
|
2844
|
+
* Authorized raw GET (binary responses) with the same auth, 401
|
|
2845
|
+
* refresh-and-retry-once, and error-envelope handling as `request` — the
|
|
2846
|
+
* transfer primitive the SlackFilesClient domain module builds on.
|
|
2847
|
+
*/
|
|
2848
|
+
async rawAuthorizedFetch(path24, opts, retried = false) {
|
|
2849
|
+
if (!retried) {
|
|
2850
|
+
await this.ensureFreshToken(path24);
|
|
2851
|
+
}
|
|
2852
|
+
const headers = this.buildHeaders(path24);
|
|
2853
|
+
let res;
|
|
2854
|
+
try {
|
|
2855
|
+
res = await fetch(`${this.baseUrlFor(path24)}${path24}`, {
|
|
2856
|
+
method: "GET",
|
|
2857
|
+
headers,
|
|
2858
|
+
// File transfers get the multipart-tier budget, not the 15s JSON one.
|
|
2859
|
+
signal: AbortSignal.timeout(opts?.timeoutMs ?? 5 * 60 * 1e3)
|
|
2860
|
+
});
|
|
2861
|
+
} catch (err) {
|
|
2862
|
+
throw _ParallClient.normalizeFetchError(err);
|
|
2863
|
+
}
|
|
2864
|
+
if (res.status === 401) {
|
|
2865
|
+
if (!retried && this.getRefreshToken) {
|
|
2866
|
+
const refreshed = await this.tryRefresh();
|
|
2867
|
+
if (refreshed) {
|
|
2868
|
+
return this.rawAuthorizedFetch(path24, opts, true);
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
this.onTokenExpired?.();
|
|
2872
|
+
}
|
|
2873
|
+
if (!res.ok) {
|
|
2874
|
+
const rawErrorBody = await res.json().catch(() => ({}));
|
|
2875
|
+
throw buildApiError(res, rawErrorBody);
|
|
2876
|
+
}
|
|
2877
|
+
return res;
|
|
2878
|
+
}
|
|
2731
2879
|
async listChannelConversations(orgId, connectionId) {
|
|
2732
2880
|
return this.request("GET", ENDPOINTS.CHANNEL_CONNECTION_CONVERSATIONS(orgId, connectionId));
|
|
2733
2881
|
}
|
|
@@ -2988,12 +3136,12 @@ var init_client = __esm({
|
|
|
2988
3136
|
async deleteWikiRestriction(orgId, wikiId, restrictionId) {
|
|
2989
3137
|
await this.request("DELETE", ENDPOINTS.WIKI_RESTRICTION(orgId, wikiId, restrictionId));
|
|
2990
3138
|
}
|
|
2991
|
-
async getWikiAccessStatus(orgId, wikiId,
|
|
2992
|
-
return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0,
|
|
3139
|
+
async getWikiAccessStatus(orgId, wikiId, path24) {
|
|
3140
|
+
return this.request("GET", ENDPOINTS.WIKI_ACCESS_STATUS(orgId, wikiId), void 0, path24 ? { path: path24 } : void 0);
|
|
2993
3141
|
}
|
|
2994
3142
|
// ---- Wiki membership projection (who-can-access, invites, join/leave) ----
|
|
2995
|
-
async getWikiAccessPolicy(orgId, wikiId,
|
|
2996
|
-
return this.request("GET", ENDPOINTS.WIKI_ACCESS_POLICY(orgId, wikiId), void 0,
|
|
3143
|
+
async getWikiAccessPolicy(orgId, wikiId, path24 = "") {
|
|
3144
|
+
return this.request("GET", ENDPOINTS.WIKI_ACCESS_POLICY(orgId, wikiId), void 0, path24 ? { path: path24 } : void 0);
|
|
2997
3145
|
}
|
|
2998
3146
|
async putWikiAccessPolicy(orgId, wikiId, policy) {
|
|
2999
3147
|
return this.request("PUT", ENDPOINTS.WIKI_ACCESS_POLICY(orgId, wikiId), policy);
|
|
@@ -3038,14 +3186,14 @@ var init_client = __esm({
|
|
|
3038
3186
|
async getWikiCommits(orgId, wikiId, params) {
|
|
3039
3187
|
return this.request("GET", ENDPOINTS.WIKI_COMMITS(orgId, wikiId), void 0, params);
|
|
3040
3188
|
}
|
|
3041
|
-
async getWikiFileCommits(orgId, wikiId,
|
|
3189
|
+
async getWikiFileCommits(orgId, wikiId, path24, params) {
|
|
3042
3190
|
return this.request("GET", ENDPOINTS.WIKI_FILE_COMMITS(orgId, wikiId), void 0, {
|
|
3043
|
-
path:
|
|
3191
|
+
path: path24,
|
|
3044
3192
|
...params
|
|
3045
3193
|
});
|
|
3046
3194
|
}
|
|
3047
|
-
async getWikiBlame(orgId, wikiId,
|
|
3048
|
-
return this.request("GET", ENDPOINTS.WIKI_BLAME(orgId, wikiId), void 0, { path:
|
|
3195
|
+
async getWikiBlame(orgId, wikiId, path24, ref) {
|
|
3196
|
+
return this.request("GET", ENDPOINTS.WIKI_BLAME(orgId, wikiId), void 0, { path: path24, ref });
|
|
3049
3197
|
}
|
|
3050
3198
|
// ---- Wiki Operations (audit log) ----
|
|
3051
3199
|
async getWikiOperations(orgId, wikiId, params) {
|
|
@@ -3831,6 +3979,23 @@ var init_client = __esm({
|
|
|
3831
3979
|
this.code = code;
|
|
3832
3980
|
this.name = "ApiError";
|
|
3833
3981
|
}
|
|
3982
|
+
/**
|
|
3983
|
+
* The `String(err)` form daemon and bridge logs print. `message` stays the
|
|
3984
|
+
* human sentence the UI shows; the bracket carries the machine-readable
|
|
3985
|
+
* code, the HTTP status and the transport cause, so a NETWORK_ERROR line
|
|
3986
|
+
* says which socket failure it actually was instead of the same eight words
|
|
3987
|
+
* for every outage.
|
|
3988
|
+
*/
|
|
3989
|
+
toString() {
|
|
3990
|
+
const detail = [];
|
|
3991
|
+
if (this.code)
|
|
3992
|
+
detail.push(this.status ? `${this.code} ${this.status}` : this.code);
|
|
3993
|
+
const cause = this.extras?.cause;
|
|
3994
|
+
if (typeof cause === "string" && cause)
|
|
3995
|
+
detail.push(`cause: ${cause}`);
|
|
3996
|
+
const base = `${this.name}: ${this.message}`;
|
|
3997
|
+
return detail.length > 0 ? `${base} [${detail.join("; ")}]` : base;
|
|
3998
|
+
}
|
|
3834
3999
|
};
|
|
3835
4000
|
}
|
|
3836
4001
|
});
|
|
@@ -4218,7 +4383,9 @@ var init_dist = __esm({
|
|
|
4218
4383
|
init_browser_use();
|
|
4219
4384
|
init_attachment_types();
|
|
4220
4385
|
init_attention_types();
|
|
4386
|
+
init_channel_types();
|
|
4221
4387
|
init_client();
|
|
4388
|
+
init_fetch_cause();
|
|
4222
4389
|
init_constants();
|
|
4223
4390
|
init_llm_provider_types();
|
|
4224
4391
|
init_subject();
|
|
@@ -4244,12 +4411,23 @@ var init_lane_key = __esm({
|
|
|
4244
4411
|
}
|
|
4245
4412
|
});
|
|
4246
4413
|
|
|
4414
|
+
// ts/agent-core/dist/lane-target.js
|
|
4415
|
+
var PRLL_SCHEME, CHANNEL_LANE_PREFIX;
|
|
4416
|
+
var init_lane_target = __esm({
|
|
4417
|
+
"ts/agent-core/dist/lane-target.js"() {
|
|
4418
|
+
"use strict";
|
|
4419
|
+
PRLL_SCHEME = "prll://";
|
|
4420
|
+
CHANNEL_LANE_PREFIX = `${PRLL_SCHEME}chv_`;
|
|
4421
|
+
}
|
|
4422
|
+
});
|
|
4423
|
+
|
|
4247
4424
|
// ts/agent-core/dist/lane-ledger.js
|
|
4248
4425
|
var init_lane_ledger = __esm({
|
|
4249
4426
|
"ts/agent-core/dist/lane-ledger.js"() {
|
|
4250
4427
|
"use strict";
|
|
4251
4428
|
init_dist();
|
|
4252
4429
|
init_lane_key();
|
|
4430
|
+
init_lane_target();
|
|
4253
4431
|
}
|
|
4254
4432
|
});
|
|
4255
4433
|
|
|
@@ -4262,20 +4440,14 @@ var init_gateway_lane_flow = __esm({
|
|
|
4262
4440
|
init_change_source();
|
|
4263
4441
|
init_fork_prefix();
|
|
4264
4442
|
init_lane_ledger();
|
|
4443
|
+
init_lane_target();
|
|
4265
4444
|
TYPED_BACKOFF_CAP_MS = 5 * 6e4;
|
|
4266
4445
|
}
|
|
4267
4446
|
});
|
|
4268
4447
|
|
|
4269
|
-
// ts/agent-core/dist/
|
|
4270
|
-
var
|
|
4271
|
-
"ts/agent-core/dist/
|
|
4272
|
-
"use strict";
|
|
4273
|
-
}
|
|
4274
|
-
});
|
|
4275
|
-
|
|
4276
|
-
// ts/agent-core/dist/routing.js
|
|
4277
|
-
var init_routing = __esm({
|
|
4278
|
-
"ts/agent-core/dist/routing.js"() {
|
|
4448
|
+
// ts/agent-core/dist/gateway-idle-compact.js
|
|
4449
|
+
var init_gateway_idle_compact = __esm({
|
|
4450
|
+
"ts/agent-core/dist/gateway-idle-compact.js"() {
|
|
4279
4451
|
"use strict";
|
|
4280
4452
|
}
|
|
4281
4453
|
});
|
|
@@ -4287,43 +4459,6 @@ var init_redact = __esm({
|
|
|
4287
4459
|
}
|
|
4288
4460
|
});
|
|
4289
4461
|
|
|
4290
|
-
// ts/agent-core/dist/step-retry-queue.js
|
|
4291
|
-
var init_step_retry_queue = __esm({
|
|
4292
|
-
"ts/agent-core/dist/step-retry-queue.js"() {
|
|
4293
|
-
"use strict";
|
|
4294
|
-
}
|
|
4295
|
-
});
|
|
4296
|
-
|
|
4297
|
-
// ts/agent-core/dist/step-persister.js
|
|
4298
|
-
var init_step_persister = __esm({
|
|
4299
|
-
"ts/agent-core/dist/step-persister.js"() {
|
|
4300
|
-
"use strict";
|
|
4301
|
-
init_dist();
|
|
4302
|
-
init_step_retry_queue();
|
|
4303
|
-
}
|
|
4304
|
-
});
|
|
4305
|
-
|
|
4306
|
-
// ts/agent-core/dist/session-lifecycle.js
|
|
4307
|
-
var init_session_lifecycle = __esm({
|
|
4308
|
-
"ts/agent-core/dist/session-lifecycle.js"() {
|
|
4309
|
-
"use strict";
|
|
4310
|
-
}
|
|
4311
|
-
});
|
|
4312
|
-
|
|
4313
|
-
// ts/agent-core/dist/fork-session-finalizer.js
|
|
4314
|
-
var init_fork_session_finalizer = __esm({
|
|
4315
|
-
"ts/agent-core/dist/fork-session-finalizer.js"() {
|
|
4316
|
-
"use strict";
|
|
4317
|
-
}
|
|
4318
|
-
});
|
|
4319
|
-
|
|
4320
|
-
// ts/agent-core/dist/session-state.js
|
|
4321
|
-
var init_session_state = __esm({
|
|
4322
|
-
"ts/agent-core/dist/session-state.js"() {
|
|
4323
|
-
"use strict";
|
|
4324
|
-
}
|
|
4325
|
-
});
|
|
4326
|
-
|
|
4327
4462
|
// ts/node_modules/.pnpm/@opentelemetry+api@1.9.1/node_modules/@opentelemetry/api/build/esm/version.js
|
|
4328
4463
|
var VERSION;
|
|
4329
4464
|
var init_version = __esm({
|
|
@@ -22003,9 +22138,9 @@ var require_getMachineId_linux = __commonJS({
|
|
|
22003
22138
|
var api_1 = (init_esm(), __toCommonJS(esm_exports));
|
|
22004
22139
|
async function getMachineId() {
|
|
22005
22140
|
const paths = ["/etc/machine-id", "/var/lib/dbus/machine-id"];
|
|
22006
|
-
for (const
|
|
22141
|
+
for (const path24 of paths) {
|
|
22007
22142
|
try {
|
|
22008
|
-
const result = await fs_1.promises.readFile(
|
|
22143
|
+
const result = await fs_1.promises.readFile(path24, { encoding: "utf8" });
|
|
22009
22144
|
return result.trim();
|
|
22010
22145
|
} catch (e) {
|
|
22011
22146
|
api_1.diag.debug(`error reading machine id: ${e}`);
|
|
@@ -25408,7 +25543,7 @@ function appendRootPathToUrlIfNeeded(url) {
|
|
|
25408
25543
|
return void 0;
|
|
25409
25544
|
}
|
|
25410
25545
|
}
|
|
25411
|
-
function appendResourcePathToUrl(url,
|
|
25546
|
+
function appendResourcePathToUrl(url, path24) {
|
|
25412
25547
|
try {
|
|
25413
25548
|
new URL(url);
|
|
25414
25549
|
} catch (_a) {
|
|
@@ -25418,11 +25553,11 @@ function appendResourcePathToUrl(url, path23) {
|
|
|
25418
25553
|
if (!url.endsWith("/")) {
|
|
25419
25554
|
url = url + "/";
|
|
25420
25555
|
}
|
|
25421
|
-
url +=
|
|
25556
|
+
url += path24;
|
|
25422
25557
|
try {
|
|
25423
25558
|
new URL(url);
|
|
25424
25559
|
} catch (_b) {
|
|
25425
|
-
diag2.warn("Configuration: Provided URL appended with '" +
|
|
25560
|
+
diag2.warn("Configuration: Provided URL appended with '" + path24 + "' is not a valid URL, using 'undefined' instead of '" + url + "'");
|
|
25426
25561
|
return void 0;
|
|
25427
25562
|
}
|
|
25428
25563
|
return url;
|
|
@@ -30727,16 +30862,100 @@ var require_src15 = __commonJS({
|
|
|
30727
30862
|
|
|
30728
30863
|
// ts/agent-core/dist/telemetry.js
|
|
30729
30864
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
30730
|
-
|
|
30865
|
+
import { readFileSync } from "node:fs";
|
|
30866
|
+
import * as path3 from "node:path";
|
|
30867
|
+
import { fileURLToPath } from "node:url";
|
|
30868
|
+
function resolveTelemetryEnvironment(apiUrl, override = process.env.PRLL_SERVER_ENV) {
|
|
30869
|
+
const forced = override?.trim();
|
|
30870
|
+
if (forced)
|
|
30871
|
+
return forced;
|
|
30872
|
+
let host = "";
|
|
30873
|
+
try {
|
|
30874
|
+
host = apiUrl ? new URL(apiUrl).hostname.toLowerCase() : "";
|
|
30875
|
+
} catch {
|
|
30876
|
+
host = "";
|
|
30877
|
+
}
|
|
30878
|
+
if (PRODUCTION_API_HOSTS.has(host))
|
|
30879
|
+
return "production";
|
|
30880
|
+
if (STAGING_API_HOSTS.has(host))
|
|
30881
|
+
return "staging";
|
|
30882
|
+
return "development";
|
|
30883
|
+
}
|
|
30884
|
+
function resolveServiceVersion(importMetaUrl) {
|
|
30885
|
+
const fallback = process.env.npm_package_version || "unknown";
|
|
30886
|
+
let dir;
|
|
30887
|
+
try {
|
|
30888
|
+
dir = path3.dirname(fileURLToPath(importMetaUrl));
|
|
30889
|
+
} catch {
|
|
30890
|
+
return fallback;
|
|
30891
|
+
}
|
|
30892
|
+
for (const candidate of [path3.join(dir, "manifest.json"), path3.join(dir, "..", "package.json")]) {
|
|
30893
|
+
try {
|
|
30894
|
+
const parsed = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
30895
|
+
if (typeof parsed.version === "string" && parsed.version.trim()) {
|
|
30896
|
+
return parsed.version.trim();
|
|
30897
|
+
}
|
|
30898
|
+
} catch {
|
|
30899
|
+
}
|
|
30900
|
+
}
|
|
30901
|
+
return fallback;
|
|
30902
|
+
}
|
|
30903
|
+
function createThrottledDiagLogger(now = Date.now) {
|
|
30904
|
+
const lastAt = /* @__PURE__ */ new Map();
|
|
30905
|
+
const describe = (a) => {
|
|
30906
|
+
if (a instanceof Error)
|
|
30907
|
+
return a.message;
|
|
30908
|
+
if (a && typeof a === "object" && typeof a.message === "string") {
|
|
30909
|
+
return a.message;
|
|
30910
|
+
}
|
|
30911
|
+
if (typeof a === "string" && a.startsWith("{")) {
|
|
30912
|
+
try {
|
|
30913
|
+
const parsed = JSON.parse(a);
|
|
30914
|
+
if (typeof parsed.message === "string")
|
|
30915
|
+
return parsed.message;
|
|
30916
|
+
} catch {
|
|
30917
|
+
}
|
|
30918
|
+
}
|
|
30919
|
+
return String(a);
|
|
30920
|
+
};
|
|
30921
|
+
const emit = (level, args) => {
|
|
30922
|
+
const msg = args.map(describe).join(" ");
|
|
30923
|
+
const key = `${level}:${msg.slice(0, 160)}`;
|
|
30924
|
+
const at = now();
|
|
30925
|
+
const prev = lastAt.get(key);
|
|
30926
|
+
if (prev !== void 0 && at - prev < DIAG_THROTTLE_MS)
|
|
30927
|
+
return;
|
|
30928
|
+
if (lastAt.size >= DIAG_THROTTLE_KEYS)
|
|
30929
|
+
lastAt.clear();
|
|
30930
|
+
lastAt.set(key, at);
|
|
30931
|
+
console.warn(`${new Date(at).toISOString()} [telemetry] otel ${level}: ${msg}`);
|
|
30932
|
+
};
|
|
30933
|
+
return {
|
|
30934
|
+
verbose: () => {
|
|
30935
|
+
},
|
|
30936
|
+
debug: () => {
|
|
30937
|
+
},
|
|
30938
|
+
info: () => {
|
|
30939
|
+
},
|
|
30940
|
+
warn: (...args) => emit("warn", args),
|
|
30941
|
+
error: (...args) => emit("error", args)
|
|
30942
|
+
};
|
|
30943
|
+
}
|
|
30944
|
+
async function initAgentTelemetry(serviceName, runtimeType, opts = {}) {
|
|
30731
30945
|
const noopHandle = { shutdown: async () => {
|
|
30732
30946
|
} };
|
|
30733
|
-
const apiUrl = process.env.PRLL_API_URL;
|
|
30734
|
-
const apiKey = process.env.PRLL_API_KEY;
|
|
30947
|
+
const apiUrl = opts.apiUrl ?? process.env.PRLL_API_URL;
|
|
30948
|
+
const apiKey = opts.apiKey ?? process.env.PRLL_API_KEY;
|
|
30735
30949
|
if (!apiUrl || !apiKey) {
|
|
30950
|
+
console.warn(`${(/* @__PURE__ */ new Date()).toISOString()} [telemetry] disabled: no API url/key resolved for ${serviceName} \u2014 nothing will reach SigNoz`);
|
|
30736
30951
|
return noopHandle;
|
|
30737
30952
|
}
|
|
30953
|
+
const environment = opts.environment ?? resolveTelemetryEnvironment(apiUrl);
|
|
30954
|
+
const serviceVersion = opts.serviceVersion ?? process.env.npm_package_version ?? "unknown";
|
|
30738
30955
|
try {
|
|
30739
30956
|
const otelEndpoint = apiUrl.replace(/\/$/, "") + "/otel";
|
|
30957
|
+
if (!initialized)
|
|
30958
|
+
diag2.setLogger(createThrottledDiagLogger(), DiagLogLevel.WARN);
|
|
30740
30959
|
const { OTLPTraceExporter } = await Promise.resolve().then(() => __toESM(require_src6(), 1));
|
|
30741
30960
|
const { OTLPMetricExporter } = await Promise.resolve().then(() => __toESM(require_src8(), 1));
|
|
30742
30961
|
const { OTLPLogExporter } = await Promise.resolve().then(() => __toESM(require_src9(), 1));
|
|
@@ -30746,8 +30965,8 @@ async function initAgentTelemetry(serviceName, runtimeType) {
|
|
|
30746
30965
|
const { Resource } = await Promise.resolve().then(() => __toESM(require_src3(), 1));
|
|
30747
30966
|
const resource = new Resource({
|
|
30748
30967
|
"service.name": serviceName,
|
|
30749
|
-
"service.version":
|
|
30750
|
-
"deployment.environment.name":
|
|
30968
|
+
"service.version": serviceVersion,
|
|
30969
|
+
"deployment.environment.name": environment,
|
|
30751
30970
|
"parall.runtime_type": runtimeType,
|
|
30752
30971
|
"parall.agent_id": process.env.PRLL_AGENT_ID || "",
|
|
30753
30972
|
"parall.machine_id": process.env.PRLL_MACHINE_ID || "",
|
|
@@ -30798,6 +31017,7 @@ async function initAgentTelemetry(serviceName, runtimeType) {
|
|
|
30798
31017
|
description: "LLM cost per turn in USD (when the runtime reports it)"
|
|
30799
31018
|
});
|
|
30800
31019
|
initialized = true;
|
|
31020
|
+
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [telemetry] exporting ${serviceName} v${serviceVersion} env=${environment} to ${otelEndpoint}`);
|
|
30801
31021
|
shutdownFn = async () => {
|
|
30802
31022
|
await tracerProvider.forceFlush();
|
|
30803
31023
|
await meterProvider.forceFlush();
|
|
@@ -30812,7 +31032,8 @@ async function initAgentTelemetry(serviceName, runtimeType) {
|
|
|
30812
31032
|
await shutdownFn();
|
|
30813
31033
|
}
|
|
30814
31034
|
};
|
|
30815
|
-
} catch {
|
|
31035
|
+
} catch (err) {
|
|
31036
|
+
console.warn(`${(/* @__PURE__ */ new Date()).toISOString()} [telemetry] init failed for ${serviceName}, running without export: ${String(err)}`);
|
|
30816
31037
|
return noopHandle;
|
|
30817
31038
|
}
|
|
30818
31039
|
}
|
|
@@ -30849,7 +31070,7 @@ function createOtelLogger(layer, prefix) {
|
|
|
30849
31070
|
child: (sub) => createOtelLogger(layer, `${prefix}:${sub}`)
|
|
30850
31071
|
};
|
|
30851
31072
|
}
|
|
30852
|
-
var import_api_logs, initialized, shutdownFn, tracer, dispatchCounter, dispatchDuration, missingReplyCounter, turnTokensCounter, turnCostCounter, otelLogger, sessionKeyStorage;
|
|
31073
|
+
var import_api_logs, initialized, shutdownFn, tracer, dispatchCounter, dispatchDuration, missingReplyCounter, turnTokensCounter, turnCostCounter, otelLogger, PRODUCTION_API_HOSTS, STAGING_API_HOSTS, DIAG_THROTTLE_MS, DIAG_THROTTLE_KEYS, sessionKeyStorage;
|
|
30853
31074
|
var init_telemetry = __esm({
|
|
30854
31075
|
"ts/agent-core/dist/telemetry.js"() {
|
|
30855
31076
|
"use strict";
|
|
@@ -30865,10 +31086,89 @@ var init_telemetry = __esm({
|
|
|
30865
31086
|
turnTokensCounter = null;
|
|
30866
31087
|
turnCostCounter = null;
|
|
30867
31088
|
otelLogger = null;
|
|
31089
|
+
PRODUCTION_API_HOSTS = /* @__PURE__ */ new Set(["api.parall.com"]);
|
|
31090
|
+
STAGING_API_HOSTS = /* @__PURE__ */ new Set(["api.staging.prll.sh"]);
|
|
31091
|
+
DIAG_THROTTLE_MS = 6e4;
|
|
31092
|
+
DIAG_THROTTLE_KEYS = 200;
|
|
30868
31093
|
sessionKeyStorage = new AsyncLocalStorage();
|
|
30869
31094
|
}
|
|
30870
31095
|
});
|
|
30871
31096
|
|
|
31097
|
+
// ts/agent-core/dist/gateway-runtime-turns.js
|
|
31098
|
+
var init_gateway_runtime_turns = __esm({
|
|
31099
|
+
"ts/agent-core/dist/gateway-runtime-turns.js"() {
|
|
31100
|
+
"use strict";
|
|
31101
|
+
init_dispatch_adapter();
|
|
31102
|
+
init_redact();
|
|
31103
|
+
init_telemetry();
|
|
31104
|
+
}
|
|
31105
|
+
});
|
|
31106
|
+
|
|
31107
|
+
// ts/agent-core/dist/gateway-drain.js
|
|
31108
|
+
var init_gateway_drain = __esm({
|
|
31109
|
+
"ts/agent-core/dist/gateway-drain.js"() {
|
|
31110
|
+
"use strict";
|
|
31111
|
+
}
|
|
31112
|
+
});
|
|
31113
|
+
|
|
31114
|
+
// ts/agent-core/dist/gateway-session-binding.js
|
|
31115
|
+
var init_gateway_session_binding = __esm({
|
|
31116
|
+
"ts/agent-core/dist/gateway-session-binding.js"() {
|
|
31117
|
+
"use strict";
|
|
31118
|
+
}
|
|
31119
|
+
});
|
|
31120
|
+
|
|
31121
|
+
// ts/agent-core/dist/dispatch-inactivity-deadline.js
|
|
31122
|
+
var init_dispatch_inactivity_deadline = __esm({
|
|
31123
|
+
"ts/agent-core/dist/dispatch-inactivity-deadline.js"() {
|
|
31124
|
+
"use strict";
|
|
31125
|
+
}
|
|
31126
|
+
});
|
|
31127
|
+
|
|
31128
|
+
// ts/agent-core/dist/routing.js
|
|
31129
|
+
var init_routing = __esm({
|
|
31130
|
+
"ts/agent-core/dist/routing.js"() {
|
|
31131
|
+
"use strict";
|
|
31132
|
+
}
|
|
31133
|
+
});
|
|
31134
|
+
|
|
31135
|
+
// ts/agent-core/dist/step-retry-queue.js
|
|
31136
|
+
var init_step_retry_queue = __esm({
|
|
31137
|
+
"ts/agent-core/dist/step-retry-queue.js"() {
|
|
31138
|
+
"use strict";
|
|
31139
|
+
}
|
|
31140
|
+
});
|
|
31141
|
+
|
|
31142
|
+
// ts/agent-core/dist/step-persister.js
|
|
31143
|
+
var init_step_persister = __esm({
|
|
31144
|
+
"ts/agent-core/dist/step-persister.js"() {
|
|
31145
|
+
"use strict";
|
|
31146
|
+
init_dist();
|
|
31147
|
+
init_step_retry_queue();
|
|
31148
|
+
}
|
|
31149
|
+
});
|
|
31150
|
+
|
|
31151
|
+
// ts/agent-core/dist/session-lifecycle.js
|
|
31152
|
+
var init_session_lifecycle = __esm({
|
|
31153
|
+
"ts/agent-core/dist/session-lifecycle.js"() {
|
|
31154
|
+
"use strict";
|
|
31155
|
+
}
|
|
31156
|
+
});
|
|
31157
|
+
|
|
31158
|
+
// ts/agent-core/dist/fork-session-finalizer.js
|
|
31159
|
+
var init_fork_session_finalizer = __esm({
|
|
31160
|
+
"ts/agent-core/dist/fork-session-finalizer.js"() {
|
|
31161
|
+
"use strict";
|
|
31162
|
+
}
|
|
31163
|
+
});
|
|
31164
|
+
|
|
31165
|
+
// ts/agent-core/dist/session-state.js
|
|
31166
|
+
var init_session_state = __esm({
|
|
31167
|
+
"ts/agent-core/dist/session-state.js"() {
|
|
31168
|
+
"use strict";
|
|
31169
|
+
}
|
|
31170
|
+
});
|
|
31171
|
+
|
|
30872
31172
|
// ts/agent-core/dist/gateway-base.js
|
|
30873
31173
|
var init_gateway_base = __esm({
|
|
30874
31174
|
"ts/agent-core/dist/gateway-base.js"() {
|
|
@@ -30879,7 +31179,12 @@ var init_gateway_base = __esm({
|
|
|
30879
31179
|
init_dispatch_adapter();
|
|
30880
31180
|
init_fork_state();
|
|
30881
31181
|
init_gateway_lane_flow();
|
|
31182
|
+
init_gateway_idle_compact();
|
|
31183
|
+
init_gateway_runtime_turns();
|
|
31184
|
+
init_gateway_drain();
|
|
31185
|
+
init_gateway_session_binding();
|
|
30882
31186
|
init_lane_ledger();
|
|
31187
|
+
init_lane_target();
|
|
30883
31188
|
init_dispatch_inactivity_deadline();
|
|
30884
31189
|
init_routing();
|
|
30885
31190
|
init_redact();
|
|
@@ -32000,14 +32305,14 @@ var require_util2 = __commonJS({
|
|
|
32000
32305
|
}
|
|
32001
32306
|
const port = url.port != null ? url.port : url.protocol === "https:" ? 443 : 80;
|
|
32002
32307
|
let origin = url.origin != null ? url.origin : `${url.protocol || ""}//${url.hostname || ""}:${port}`;
|
|
32003
|
-
let
|
|
32308
|
+
let path24 = url.path != null ? url.path : `${url.pathname || ""}${url.search || ""}`;
|
|
32004
32309
|
if (origin[origin.length - 1] === "/") {
|
|
32005
32310
|
origin = origin.slice(0, origin.length - 1);
|
|
32006
32311
|
}
|
|
32007
|
-
if (
|
|
32008
|
-
|
|
32312
|
+
if (path24 && path24[0] !== "/") {
|
|
32313
|
+
path24 = `/${path24}`;
|
|
32009
32314
|
}
|
|
32010
|
-
return new URL(`${origin}${
|
|
32315
|
+
return new URL(`${origin}${path24}`);
|
|
32011
32316
|
}
|
|
32012
32317
|
if (!isHttpOrHttpsPrefixed(url.origin || url.protocol)) {
|
|
32013
32318
|
throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
|
|
@@ -32828,9 +33133,9 @@ var require_diagnostics = __commonJS({
|
|
|
32828
33133
|
"undici:client:sendHeaders",
|
|
32829
33134
|
(evt) => {
|
|
32830
33135
|
const {
|
|
32831
|
-
request: { method, path:
|
|
33136
|
+
request: { method, path: path24, origin }
|
|
32832
33137
|
} = evt;
|
|
32833
|
-
debugLog("sending request to %s %s%s", method, origin,
|
|
33138
|
+
debugLog("sending request to %s %s%s", method, origin, path24);
|
|
32834
33139
|
}
|
|
32835
33140
|
);
|
|
32836
33141
|
}
|
|
@@ -32848,14 +33153,14 @@ var require_diagnostics = __commonJS({
|
|
|
32848
33153
|
"undici:request:headers",
|
|
32849
33154
|
(evt) => {
|
|
32850
33155
|
const {
|
|
32851
|
-
request: { method, path:
|
|
33156
|
+
request: { method, path: path24, origin },
|
|
32852
33157
|
response: { statusCode }
|
|
32853
33158
|
} = evt;
|
|
32854
33159
|
debugLog(
|
|
32855
33160
|
"received response to %s %s%s - HTTP %d",
|
|
32856
33161
|
method,
|
|
32857
33162
|
origin,
|
|
32858
|
-
|
|
33163
|
+
path24,
|
|
32859
33164
|
statusCode
|
|
32860
33165
|
);
|
|
32861
33166
|
}
|
|
@@ -32864,23 +33169,23 @@ var require_diagnostics = __commonJS({
|
|
|
32864
33169
|
"undici:request:trailers",
|
|
32865
33170
|
(evt) => {
|
|
32866
33171
|
const {
|
|
32867
|
-
request: { method, path:
|
|
33172
|
+
request: { method, path: path24, origin }
|
|
32868
33173
|
} = evt;
|
|
32869
|
-
debugLog("trailers received from %s %s%s", method, origin,
|
|
33174
|
+
debugLog("trailers received from %s %s%s", method, origin, path24);
|
|
32870
33175
|
}
|
|
32871
33176
|
);
|
|
32872
33177
|
diagnosticsChannel.subscribe(
|
|
32873
33178
|
"undici:request:error",
|
|
32874
33179
|
(evt) => {
|
|
32875
33180
|
const {
|
|
32876
|
-
request: { method, path:
|
|
33181
|
+
request: { method, path: path24, origin },
|
|
32877
33182
|
error
|
|
32878
33183
|
} = evt;
|
|
32879
33184
|
debugLog(
|
|
32880
33185
|
"request to %s %s%s errored - %s",
|
|
32881
33186
|
method,
|
|
32882
33187
|
origin,
|
|
32883
|
-
|
|
33188
|
+
path24,
|
|
32884
33189
|
error.message
|
|
32885
33190
|
);
|
|
32886
33191
|
}
|
|
@@ -32983,7 +33288,7 @@ var require_request = __commonJS({
|
|
|
32983
33288
|
var kHandler = Symbol("handler");
|
|
32984
33289
|
var Request = class {
|
|
32985
33290
|
constructor(origin, {
|
|
32986
|
-
path:
|
|
33291
|
+
path: path24,
|
|
32987
33292
|
method,
|
|
32988
33293
|
body,
|
|
32989
33294
|
headers,
|
|
@@ -33000,11 +33305,11 @@ var require_request = __commonJS({
|
|
|
33000
33305
|
maxRedirections,
|
|
33001
33306
|
typeOfService
|
|
33002
33307
|
}, handler) {
|
|
33003
|
-
if (typeof
|
|
33308
|
+
if (typeof path24 !== "string") {
|
|
33004
33309
|
throw new InvalidArgumentError("path must be a string");
|
|
33005
|
-
} else if (
|
|
33310
|
+
} else if (path24[0] !== "/" && !(path24.startsWith("http://") || path24.startsWith("https://")) && method !== "CONNECT") {
|
|
33006
33311
|
throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
|
|
33007
|
-
} else if (invalidPathRegex.test(
|
|
33312
|
+
} else if (invalidPathRegex.test(path24)) {
|
|
33008
33313
|
throw new InvalidArgumentError("invalid request path");
|
|
33009
33314
|
}
|
|
33010
33315
|
if (typeof method !== "string") {
|
|
@@ -33079,7 +33384,7 @@ var require_request = __commonJS({
|
|
|
33079
33384
|
this.completed = false;
|
|
33080
33385
|
this.aborted = false;
|
|
33081
33386
|
this.upgrade = upgrade || null;
|
|
33082
|
-
this.path = query ? serializePathWithQuery(
|
|
33387
|
+
this.path = query ? serializePathWithQuery(path24, query) : path24;
|
|
33083
33388
|
this.origin = origin;
|
|
33084
33389
|
this.protocol = getProtocolFromUrlString(origin);
|
|
33085
33390
|
this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
|
|
@@ -38118,7 +38423,7 @@ var require_client_h1 = __commonJS({
|
|
|
38118
38423
|
return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
|
|
38119
38424
|
}
|
|
38120
38425
|
function writeH1(client, request3) {
|
|
38121
|
-
const { method, path:
|
|
38426
|
+
const { method, path: path24, host, upgrade, blocking, reset } = request3;
|
|
38122
38427
|
let { body, headers, contentLength } = request3;
|
|
38123
38428
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
|
|
38124
38429
|
if (util.isFormDataLike(body)) {
|
|
@@ -38187,7 +38492,7 @@ var require_client_h1 = __commonJS({
|
|
|
38187
38492
|
if (socket.setTypeOfService) {
|
|
38188
38493
|
socket.setTypeOfService(request3.typeOfService);
|
|
38189
38494
|
}
|
|
38190
|
-
let header = `${method} ${
|
|
38495
|
+
let header = `${method} ${path24} HTTP/1.1\r
|
|
38191
38496
|
`;
|
|
38192
38497
|
if (typeof host === "string") {
|
|
38193
38498
|
header += `host: ${host}\r
|
|
@@ -38840,7 +39145,7 @@ var require_client_h2 = __commonJS({
|
|
|
38840
39145
|
function writeH2(client, request3) {
|
|
38841
39146
|
const requestTimeout = request3.bodyTimeout ?? client[kBodyTimeout];
|
|
38842
39147
|
const session = client[kHTTP2Session];
|
|
38843
|
-
const { method, path:
|
|
39148
|
+
const { method, path: path24, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request3;
|
|
38844
39149
|
let { body } = request3;
|
|
38845
39150
|
if (upgrade != null && upgrade !== "websocket") {
|
|
38846
39151
|
util.errorRequest(client, request3, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
|
|
@@ -38908,7 +39213,7 @@ var require_client_h2 = __commonJS({
|
|
|
38908
39213
|
}
|
|
38909
39214
|
headers[HTTP2_HEADER_METHOD] = "CONNECT";
|
|
38910
39215
|
headers[HTTP2_HEADER_PROTOCOL] = "websocket";
|
|
38911
|
-
headers[HTTP2_HEADER_PATH] =
|
|
39216
|
+
headers[HTTP2_HEADER_PATH] = path24;
|
|
38912
39217
|
if (protocol === "ws:" || protocol === "wss:") {
|
|
38913
39218
|
headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
|
|
38914
39219
|
} else {
|
|
@@ -38949,7 +39254,7 @@ var require_client_h2 = __commonJS({
|
|
|
38949
39254
|
stream.setTimeout(requestTimeout);
|
|
38950
39255
|
return true;
|
|
38951
39256
|
}
|
|
38952
|
-
headers[HTTP2_HEADER_PATH] =
|
|
39257
|
+
headers[HTTP2_HEADER_PATH] = path24;
|
|
38953
39258
|
headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
|
|
38954
39259
|
const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
|
|
38955
39260
|
if (body && typeof body.read === "function") {
|
|
@@ -41251,10 +41556,10 @@ var require_proxy_agent = __commonJS({
|
|
|
41251
41556
|
};
|
|
41252
41557
|
const {
|
|
41253
41558
|
origin,
|
|
41254
|
-
path:
|
|
41559
|
+
path: path24 = "/",
|
|
41255
41560
|
headers = {}
|
|
41256
41561
|
} = opts;
|
|
41257
|
-
opts.path = origin +
|
|
41562
|
+
opts.path = origin + path24;
|
|
41258
41563
|
if (!("host" in headers) && !("Host" in headers)) {
|
|
41259
41564
|
const { host } = new URL(origin);
|
|
41260
41565
|
headers.host = host;
|
|
@@ -43317,20 +43622,20 @@ var require_mock_utils = __commonJS({
|
|
|
43317
43622
|
}
|
|
43318
43623
|
return normalizedQp;
|
|
43319
43624
|
}
|
|
43320
|
-
function safeUrl(
|
|
43321
|
-
if (typeof
|
|
43322
|
-
return
|
|
43625
|
+
function safeUrl(path24) {
|
|
43626
|
+
if (typeof path24 !== "string") {
|
|
43627
|
+
return path24;
|
|
43323
43628
|
}
|
|
43324
|
-
const pathSegments =
|
|
43629
|
+
const pathSegments = path24.split("?", 3);
|
|
43325
43630
|
if (pathSegments.length !== 2) {
|
|
43326
|
-
return
|
|
43631
|
+
return path24;
|
|
43327
43632
|
}
|
|
43328
43633
|
const qp = new URLSearchParams(pathSegments.pop());
|
|
43329
43634
|
qp.sort();
|
|
43330
43635
|
return [...pathSegments, qp.toString()].join("?");
|
|
43331
43636
|
}
|
|
43332
|
-
function matchKey(mockDispatch2, { path:
|
|
43333
|
-
const pathMatch = matchValue(mockDispatch2.path,
|
|
43637
|
+
function matchKey(mockDispatch2, { path: path24, method, body, headers }) {
|
|
43638
|
+
const pathMatch = matchValue(mockDispatch2.path, path24);
|
|
43334
43639
|
const methodMatch = matchValue(mockDispatch2.method, method);
|
|
43335
43640
|
const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body) : true;
|
|
43336
43641
|
const headersMatch = matchHeaders(mockDispatch2, headers);
|
|
@@ -43355,8 +43660,8 @@ var require_mock_utils = __commonJS({
|
|
|
43355
43660
|
const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
|
|
43356
43661
|
const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
|
|
43357
43662
|
const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
|
|
43358
|
-
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path:
|
|
43359
|
-
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(
|
|
43663
|
+
let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path24, ignoreTrailingSlash }) => {
|
|
43664
|
+
return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path24)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path24), resolvedPath);
|
|
43360
43665
|
});
|
|
43361
43666
|
if (matchedMockDispatches.length === 0) {
|
|
43362
43667
|
throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
|
|
@@ -43395,19 +43700,19 @@ var require_mock_utils = __commonJS({
|
|
|
43395
43700
|
mockDispatches.splice(index, 1);
|
|
43396
43701
|
}
|
|
43397
43702
|
}
|
|
43398
|
-
function removeTrailingSlash(
|
|
43399
|
-
while (
|
|
43400
|
-
|
|
43703
|
+
function removeTrailingSlash(path24) {
|
|
43704
|
+
while (path24.endsWith("/")) {
|
|
43705
|
+
path24 = path24.slice(0, -1);
|
|
43401
43706
|
}
|
|
43402
|
-
if (
|
|
43403
|
-
|
|
43707
|
+
if (path24.length === 0) {
|
|
43708
|
+
path24 = "/";
|
|
43404
43709
|
}
|
|
43405
|
-
return
|
|
43710
|
+
return path24;
|
|
43406
43711
|
}
|
|
43407
43712
|
function buildKey(opts) {
|
|
43408
|
-
const { path:
|
|
43713
|
+
const { path: path24, method, body, headers, query } = opts;
|
|
43409
43714
|
return {
|
|
43410
|
-
path:
|
|
43715
|
+
path: path24,
|
|
43411
43716
|
method,
|
|
43412
43717
|
body,
|
|
43413
43718
|
headers,
|
|
@@ -44097,10 +44402,10 @@ var require_pending_interceptors_formatter = __commonJS({
|
|
|
44097
44402
|
}
|
|
44098
44403
|
format(pendingInterceptors) {
|
|
44099
44404
|
const withPrettyHeaders = pendingInterceptors.map(
|
|
44100
|
-
({ method, path:
|
|
44405
|
+
({ method, path: path24, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
|
|
44101
44406
|
Method: method,
|
|
44102
44407
|
Origin: origin,
|
|
44103
|
-
Path:
|
|
44408
|
+
Path: path24,
|
|
44104
44409
|
"Status code": statusCode,
|
|
44105
44410
|
Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
|
|
44106
44411
|
Invocations: timesInvoked,
|
|
@@ -44182,9 +44487,9 @@ var require_mock_agent = __commonJS({
|
|
|
44182
44487
|
const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
|
|
44183
44488
|
const dispatchOpts = { ...opts };
|
|
44184
44489
|
if (acceptNonStandardSearchParameters && dispatchOpts.path) {
|
|
44185
|
-
const [
|
|
44490
|
+
const [path24, searchParams] = dispatchOpts.path.split("?");
|
|
44186
44491
|
const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
|
|
44187
|
-
dispatchOpts.path = `${
|
|
44492
|
+
dispatchOpts.path = `${path24}?${normalizedSearchParams}`;
|
|
44188
44493
|
}
|
|
44189
44494
|
return this[kAgent].dispatch(dispatchOpts, handler);
|
|
44190
44495
|
}
|
|
@@ -44389,7 +44694,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
44389
44694
|
"ts/node_modules/.pnpm/undici@7.24.8/node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) {
|
|
44390
44695
|
"use strict";
|
|
44391
44696
|
var { writeFile, readFile, mkdir } = __require("node:fs/promises");
|
|
44392
|
-
var { dirname:
|
|
44697
|
+
var { dirname: dirname14, resolve: resolve9 } = __require("node:path");
|
|
44393
44698
|
var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
|
|
44394
44699
|
var { InvalidArgumentError, UndiciError } = require_errors();
|
|
44395
44700
|
var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
|
|
@@ -44585,12 +44890,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
44585
44890
|
* @return {Promise<void>} - Resolves when snapshots are loaded
|
|
44586
44891
|
*/
|
|
44587
44892
|
async loadSnapshots(filePath) {
|
|
44588
|
-
const
|
|
44589
|
-
if (!
|
|
44893
|
+
const path24 = filePath || this.#snapshotPath;
|
|
44894
|
+
if (!path24) {
|
|
44590
44895
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
44591
44896
|
}
|
|
44592
44897
|
try {
|
|
44593
|
-
const data = await readFile(resolve9(
|
|
44898
|
+
const data = await readFile(resolve9(path24), "utf8");
|
|
44594
44899
|
const parsed = JSON.parse(data);
|
|
44595
44900
|
if (Array.isArray(parsed)) {
|
|
44596
44901
|
this.#snapshots.clear();
|
|
@@ -44604,7 +44909,7 @@ var require_snapshot_recorder = __commonJS({
|
|
|
44604
44909
|
if (error.code === "ENOENT") {
|
|
44605
44910
|
this.#snapshots.clear();
|
|
44606
44911
|
} else {
|
|
44607
|
-
throw new UndiciError(`Failed to load snapshots from ${
|
|
44912
|
+
throw new UndiciError(`Failed to load snapshots from ${path24}`, { cause: error });
|
|
44608
44913
|
}
|
|
44609
44914
|
}
|
|
44610
44915
|
}
|
|
@@ -44615,12 +44920,12 @@ var require_snapshot_recorder = __commonJS({
|
|
|
44615
44920
|
* @returns {Promise<void>} - Resolves when snapshots are saved
|
|
44616
44921
|
*/
|
|
44617
44922
|
async saveSnapshots(filePath) {
|
|
44618
|
-
const
|
|
44619
|
-
if (!
|
|
44923
|
+
const path24 = filePath || this.#snapshotPath;
|
|
44924
|
+
if (!path24) {
|
|
44620
44925
|
throw new InvalidArgumentError("Snapshot path is required");
|
|
44621
44926
|
}
|
|
44622
|
-
const resolvedPath = resolve9(
|
|
44623
|
-
await mkdir(
|
|
44927
|
+
const resolvedPath = resolve9(path24);
|
|
44928
|
+
await mkdir(dirname14(resolvedPath), { recursive: true });
|
|
44624
44929
|
const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
|
|
44625
44930
|
hash,
|
|
44626
44931
|
snapshot
|
|
@@ -45244,15 +45549,15 @@ var require_redirect_handler = __commonJS({
|
|
|
45244
45549
|
return;
|
|
45245
45550
|
}
|
|
45246
45551
|
const { origin, pathname, search } = util.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
|
|
45247
|
-
const
|
|
45248
|
-
const redirectUrlString = `${origin}${
|
|
45552
|
+
const path24 = search ? `${pathname}${search}` : pathname;
|
|
45553
|
+
const redirectUrlString = `${origin}${path24}`;
|
|
45249
45554
|
for (const historyUrl of this.history) {
|
|
45250
45555
|
if (historyUrl.toString() === redirectUrlString) {
|
|
45251
45556
|
throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
|
|
45252
45557
|
}
|
|
45253
45558
|
}
|
|
45254
45559
|
this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
|
|
45255
|
-
this.opts.path =
|
|
45560
|
+
this.opts.path = path24;
|
|
45256
45561
|
this.opts.origin = origin;
|
|
45257
45562
|
this.opts.query = null;
|
|
45258
45563
|
}
|
|
@@ -51459,11 +51764,11 @@ var require_fetch = __commonJS({
|
|
|
51459
51764
|
function dispatch({ body }) {
|
|
51460
51765
|
const url = requestCurrentURL(request3);
|
|
51461
51766
|
const agent = fetchParams.controller.dispatcher;
|
|
51462
|
-
const
|
|
51767
|
+
const path24 = url.pathname + url.search;
|
|
51463
51768
|
const hasTrailingQuestionMark = url.search.length === 0 && url.href[url.href.length - url.hash.length - 1] === "?";
|
|
51464
51769
|
return new Promise((resolve9, reject) => agent.dispatch(
|
|
51465
51770
|
{
|
|
51466
|
-
path: hasTrailingQuestionMark ? `${
|
|
51771
|
+
path: hasTrailingQuestionMark ? `${path24}?` : path24,
|
|
51467
51772
|
origin: url.origin,
|
|
51468
51773
|
method: request3.method,
|
|
51469
51774
|
body: agent.isMockActive ? request3.body && (request3.body.source || request3.body.stream) : body,
|
|
@@ -52410,9 +52715,9 @@ var require_util5 = __commonJS({
|
|
|
52410
52715
|
}
|
|
52411
52716
|
}
|
|
52412
52717
|
}
|
|
52413
|
-
function validateCookiePath(
|
|
52414
|
-
for (let i = 0; i <
|
|
52415
|
-
const code =
|
|
52718
|
+
function validateCookiePath(path24) {
|
|
52719
|
+
for (let i = 0; i < path24.length; ++i) {
|
|
52720
|
+
const code = path24.charCodeAt(i);
|
|
52416
52721
|
if (code < 32 || // exclude CTLs (0-31)
|
|
52417
52722
|
code === 127 || // DEL
|
|
52418
52723
|
code === 59) {
|
|
@@ -55582,11 +55887,11 @@ var require_undici = __commonJS({
|
|
|
55582
55887
|
if (typeof opts.path !== "string") {
|
|
55583
55888
|
throw new InvalidArgumentError("invalid opts.path");
|
|
55584
55889
|
}
|
|
55585
|
-
let
|
|
55890
|
+
let path24 = opts.path;
|
|
55586
55891
|
if (!opts.path.startsWith("/")) {
|
|
55587
|
-
|
|
55892
|
+
path24 = `/${path24}`;
|
|
55588
55893
|
}
|
|
55589
|
-
url = new URL(util.parseOrigin(url).origin +
|
|
55894
|
+
url = new URL(util.parseOrigin(url).origin + path24);
|
|
55590
55895
|
} else {
|
|
55591
55896
|
if (!opts) {
|
|
55592
55897
|
opts = typeof url === "object" ? url : {};
|
|
@@ -55861,6 +56166,21 @@ var init_provider_config = __esm({
|
|
|
55861
56166
|
}
|
|
55862
56167
|
});
|
|
55863
56168
|
|
|
56169
|
+
// ts/agent-core/dist/runtime-activity-port.js
|
|
56170
|
+
var init_runtime_activity_port = __esm({
|
|
56171
|
+
"ts/agent-core/dist/runtime-activity-port.js"() {
|
|
56172
|
+
"use strict";
|
|
56173
|
+
init_dispatch_adapter();
|
|
56174
|
+
}
|
|
56175
|
+
});
|
|
56176
|
+
|
|
56177
|
+
// ts/agent-core/dist/runtime-turn-base.js
|
|
56178
|
+
var init_runtime_turn_base = __esm({
|
|
56179
|
+
"ts/agent-core/dist/runtime-turn-base.js"() {
|
|
56180
|
+
"use strict";
|
|
56181
|
+
}
|
|
56182
|
+
});
|
|
56183
|
+
|
|
55864
56184
|
// ts/agent-core/dist/types.js
|
|
55865
56185
|
var init_types4 = __esm({
|
|
55866
56186
|
"ts/agent-core/dist/types.js"() {
|
|
@@ -55878,6 +56198,7 @@ var init_dist2 = __esm({
|
|
|
55878
56198
|
init_dispatch_adapter();
|
|
55879
56199
|
init_fork_prefix();
|
|
55880
56200
|
init_gateway_base();
|
|
56201
|
+
init_gateway_idle_compact();
|
|
55881
56202
|
init_gateway_lane_flow();
|
|
55882
56203
|
init_http_keepalive();
|
|
55883
56204
|
init_lane_key();
|
|
@@ -55889,6 +56210,8 @@ var init_dist2 = __esm({
|
|
|
55889
56210
|
init_provider_config();
|
|
55890
56211
|
init_redact();
|
|
55891
56212
|
init_routing();
|
|
56213
|
+
init_runtime_activity_port();
|
|
56214
|
+
init_runtime_turn_base();
|
|
55892
56215
|
init_session_state();
|
|
55893
56216
|
init_skills();
|
|
55894
56217
|
init_telemetry();
|
|
@@ -55914,7 +56237,7 @@ __export(config_exports, {
|
|
|
55914
56237
|
});
|
|
55915
56238
|
import * as fs from "node:fs";
|
|
55916
56239
|
import * as os2 from "node:os";
|
|
55917
|
-
import * as
|
|
56240
|
+
import * as path4 from "node:path";
|
|
55918
56241
|
function parseMs(value, fallback) {
|
|
55919
56242
|
if (!value)
|
|
55920
56243
|
return fallback;
|
|
@@ -55928,7 +56251,7 @@ function parseMsAllowZero(value, fallback) {
|
|
|
55928
56251
|
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
55929
56252
|
}
|
|
55930
56253
|
function daemonConfigPath(env = process.env) {
|
|
55931
|
-
return
|
|
56254
|
+
return path4.join(daemonConfigDir(env), "config.json");
|
|
55932
56255
|
}
|
|
55933
56256
|
function tryLoadConfigFile(env) {
|
|
55934
56257
|
const cfgPath = daemonConfigPath(env);
|
|
@@ -55968,7 +56291,7 @@ function resolveClaudeDaemonConfig(env = process.env) {
|
|
|
55968
56291
|
throw new Error(`PRLL_API_KEY does not look like a Machine bearer (expected prefix "mck_"). Daemon mode requires a machine-scoped key issued via POST /machines/{id}/keys.`);
|
|
55969
56292
|
}
|
|
55970
56293
|
const rootClaudeHome = resolvePath(env.PRLL_CLAUDE_HOME?.trim() || env.HOME || os2.homedir());
|
|
55971
|
-
const rootStateDir = resolvePath(env.PRLL_CLAUDE_STATE_DIR?.trim() ||
|
|
56294
|
+
const rootStateDir = resolvePath(env.PRLL_CLAUDE_STATE_DIR?.trim() || path4.join(rootClaudeHome, ".parall-agent"));
|
|
55972
56295
|
return {
|
|
55973
56296
|
apiUrl,
|
|
55974
56297
|
apiKey,
|
|
@@ -55999,22 +56322,22 @@ function assertSafeAgentId(agentId) {
|
|
|
55999
56322
|
return agentId;
|
|
56000
56323
|
}
|
|
56001
56324
|
function agentStateDirFor(rootStateDir, agentId) {
|
|
56002
|
-
return
|
|
56325
|
+
return path4.join(rootStateDir, "agents", assertSafeAgentId(agentId));
|
|
56003
56326
|
}
|
|
56004
56327
|
function agentClaudeHomeFor(rootClaudeHome, agentId) {
|
|
56005
|
-
return
|
|
56328
|
+
return path4.join(rootClaudeHome, "agents", assertSafeAgentId(agentId));
|
|
56006
56329
|
}
|
|
56007
56330
|
function sharedClaudeCredentialsFileFor(rootClaudeHome) {
|
|
56008
|
-
return
|
|
56331
|
+
return path4.join(rootClaudeHome, ".claude", ".credentials.json");
|
|
56009
56332
|
}
|
|
56010
56333
|
function agentClaudeCredentialsFileFor(agentClaudeHome) {
|
|
56011
|
-
return
|
|
56334
|
+
return path4.join(agentClaudeHome, ".claude", ".credentials.json");
|
|
56012
56335
|
}
|
|
56013
56336
|
function agentWorkspaceDirFor(rootStateDir, agentId) {
|
|
56014
|
-
return
|
|
56337
|
+
return path4.join(rootStateDir, "agents", assertSafeAgentId(agentId), "workspace");
|
|
56015
56338
|
}
|
|
56016
56339
|
function agentHomeDirFor(rootStateDir, agentId) {
|
|
56017
|
-
return
|
|
56340
|
+
return path4.join(rootStateDir, "agents", assertSafeAgentId(agentId), "home");
|
|
56018
56341
|
}
|
|
56019
56342
|
function resolveUpdateSigningEnabled(env = process.env) {
|
|
56020
56343
|
return env.PRLL_DAEMON_SIGNING_DISABLED !== "1";
|
|
@@ -56035,22 +56358,22 @@ var init_config = __esm({
|
|
|
56035
56358
|
});
|
|
56036
56359
|
|
|
56037
56360
|
// ts/daemon/dist/win-service.js
|
|
56038
|
-
import * as
|
|
56361
|
+
import * as path5 from "node:path";
|
|
56039
56362
|
function winServicePaths(home) {
|
|
56040
|
-
const root =
|
|
56041
|
-
const serviceDir =
|
|
56042
|
-
const logDir =
|
|
56363
|
+
const root = path5.join(home, ".parall-daemon");
|
|
56364
|
+
const serviceDir = path5.join(root, "service");
|
|
56365
|
+
const logDir = path5.join(root, "logs");
|
|
56043
56366
|
return {
|
|
56044
56367
|
serviceDir,
|
|
56045
|
-
launcherCjs:
|
|
56046
|
-
legacyLauncherJs:
|
|
56047
|
-
launcherVbs:
|
|
56048
|
-
taskXml:
|
|
56049
|
-
pidFile:
|
|
56368
|
+
launcherCjs: path5.join(serviceDir, "parall-daemon-launcher.cjs"),
|
|
56369
|
+
legacyLauncherJs: path5.join(serviceDir, "parall-daemon-launcher.js"),
|
|
56370
|
+
launcherVbs: path5.join(serviceDir, "parall-daemon-launcher.vbs"),
|
|
56371
|
+
taskXml: path5.join(serviceDir, "task.xml"),
|
|
56372
|
+
pidFile: path5.join(root, "daemon.pid"),
|
|
56050
56373
|
logDir,
|
|
56051
|
-
logFile:
|
|
56052
|
-
overlayEntry:
|
|
56053
|
-
runningMarker:
|
|
56374
|
+
logFile: path5.join(logDir, "parall-daemon.log"),
|
|
56375
|
+
overlayEntry: path5.join(root, "bundle", "current", "parall-daemon.js"),
|
|
56376
|
+
runningMarker: path5.join(root, "bundle", "daemon-running")
|
|
56054
56377
|
};
|
|
56055
56378
|
}
|
|
56056
56379
|
function vbsQuote(value) {
|
|
@@ -56191,7 +56514,7 @@ var init_win_service = __esm({
|
|
|
56191
56514
|
});
|
|
56192
56515
|
|
|
56193
56516
|
// ts/daemon/dist/win-lifecycle.js
|
|
56194
|
-
import * as
|
|
56517
|
+
import * as path6 from "node:path";
|
|
56195
56518
|
function probePidIdentity(deps, pid) {
|
|
56196
56519
|
const script = `$p = Get-CimInstance Win32_Process -Filter 'ProcessId=${pid}'; if ($null -eq $p) { 'ABSENT' } else { 'PRESENT' + [char]9 + $p.Name + [char]9 + "$($p.CommandLine)" }`;
|
|
56197
56520
|
const r = deps.run("powershell.exe", ["-NoProfile", "-Command", script]);
|
|
@@ -56209,7 +56532,7 @@ function probePidIdentity(deps, pid) {
|
|
|
56209
56532
|
if (!commandLine) {
|
|
56210
56533
|
return "indeterminate";
|
|
56211
56534
|
}
|
|
56212
|
-
const launcherNeedle =
|
|
56535
|
+
const launcherNeedle = path6.join(deps.paths.serviceDir, "parall-daemon-launcher").toLowerCase();
|
|
56213
56536
|
return commandLine.toLowerCase().includes(launcherNeedle) ? "daemon" : "not-daemon";
|
|
56214
56537
|
}
|
|
56215
56538
|
function readTrackedPid(deps) {
|
|
@@ -56457,7 +56780,7 @@ __export(updater_exports, {
|
|
|
56457
56780
|
DaemonUpdater: () => DaemonUpdater
|
|
56458
56781
|
});
|
|
56459
56782
|
import * as fs2 from "node:fs";
|
|
56460
|
-
import * as
|
|
56783
|
+
import * as path7 from "node:path";
|
|
56461
56784
|
import * as https2 from "node:https";
|
|
56462
56785
|
import * as http2 from "node:http";
|
|
56463
56786
|
import { createHash } from "node:crypto";
|
|
@@ -56553,20 +56876,20 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56553
56876
|
return false;
|
|
56554
56877
|
if (!state.previous_version)
|
|
56555
56878
|
return false;
|
|
56556
|
-
const previousDir =
|
|
56879
|
+
const previousDir = path7.join(this.bundleDir, "versions", state.previous_version);
|
|
56557
56880
|
if (!fs2.existsSync(previousDir))
|
|
56558
56881
|
return false;
|
|
56559
56882
|
this.log.warn(`rollback: ${current.version} failed ${state.boot_count} boots, reverting to ${state.previous_version}`);
|
|
56560
56883
|
if (process.platform === "win32") {
|
|
56561
|
-
const currentDir =
|
|
56884
|
+
const currentDir = path7.join(this.bundleDir, "current");
|
|
56562
56885
|
if (fs2.existsSync(currentDir)) {
|
|
56563
56886
|
for (const file of fs2.readdirSync(currentDir)) {
|
|
56564
|
-
fs2.unlinkSync(
|
|
56887
|
+
fs2.unlinkSync(path7.join(currentDir, file));
|
|
56565
56888
|
}
|
|
56566
56889
|
}
|
|
56567
56890
|
fs2.mkdirSync(currentDir, { recursive: true });
|
|
56568
56891
|
for (const file of fs2.readdirSync(previousDir)) {
|
|
56569
|
-
fs2.copyFileSync(
|
|
56892
|
+
fs2.copyFileSync(path7.join(previousDir, file), path7.join(currentDir, file));
|
|
56570
56893
|
}
|
|
56571
56894
|
} else {
|
|
56572
56895
|
this.swapSymlink(state.previous_version);
|
|
@@ -56688,11 +57011,11 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56688
57011
|
return false;
|
|
56689
57012
|
}
|
|
56690
57013
|
}
|
|
56691
|
-
const stagingDir =
|
|
57014
|
+
const stagingDir = path7.join(this.bundleDir, "staging");
|
|
56692
57015
|
this.cleanDir(stagingDir);
|
|
56693
57016
|
fs2.mkdirSync(stagingDir, { recursive: true });
|
|
56694
57017
|
for (const [filename, meta] of Object.entries(remote.files)) {
|
|
56695
|
-
const filePath =
|
|
57018
|
+
const filePath = path7.join(stagingDir, filename);
|
|
56696
57019
|
const fileUrl = `${this.cdnBaseUrl}/${remote.version}/${filename}`;
|
|
56697
57020
|
try {
|
|
56698
57021
|
await this.downloadFile(fileUrl, filePath);
|
|
@@ -56714,7 +57037,7 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56714
57037
|
return false;
|
|
56715
57038
|
}
|
|
56716
57039
|
}
|
|
56717
|
-
fs2.writeFileSync(
|
|
57040
|
+
fs2.writeFileSync(path7.join(stagingDir, "manifest.json"), JSON.stringify(remote, null, 2));
|
|
56718
57041
|
const rollbackVersion = state?.confirmed_version ?? local?.version;
|
|
56719
57042
|
const newState = {
|
|
56720
57043
|
confirmed_version: rollbackVersion,
|
|
@@ -56729,9 +57052,9 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56729
57052
|
return true;
|
|
56730
57053
|
}
|
|
56731
57054
|
atomicSwap(stagingDir, newVersion) {
|
|
56732
|
-
const versionsDir =
|
|
56733
|
-
const targetDir =
|
|
56734
|
-
const currentLink =
|
|
57055
|
+
const versionsDir = path7.join(this.bundleDir, "versions");
|
|
57056
|
+
const targetDir = path7.join(versionsDir, newVersion);
|
|
57057
|
+
const currentLink = path7.join(this.bundleDir, "current");
|
|
56735
57058
|
fs2.mkdirSync(versionsDir, { recursive: true });
|
|
56736
57059
|
if (fs2.existsSync(targetDir)) {
|
|
56737
57060
|
fs2.rmSync(targetDir, { recursive: true });
|
|
@@ -56741,12 +57064,12 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56741
57064
|
const currentDir = currentLink;
|
|
56742
57065
|
if (fs2.existsSync(currentDir)) {
|
|
56743
57066
|
for (const file of fs2.readdirSync(currentDir)) {
|
|
56744
|
-
fs2.unlinkSync(
|
|
57067
|
+
fs2.unlinkSync(path7.join(currentDir, file));
|
|
56745
57068
|
}
|
|
56746
57069
|
}
|
|
56747
57070
|
fs2.mkdirSync(currentDir, { recursive: true });
|
|
56748
57071
|
for (const file of fs2.readdirSync(targetDir)) {
|
|
56749
|
-
fs2.copyFileSync(
|
|
57072
|
+
fs2.copyFileSync(path7.join(targetDir, file), path7.join(currentDir, file));
|
|
56750
57073
|
}
|
|
56751
57074
|
} else {
|
|
56752
57075
|
this.swapSymlink(newVersion);
|
|
@@ -56754,7 +57077,7 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56754
57077
|
this.pruneOldVersions(versionsDir, newVersion);
|
|
56755
57078
|
}
|
|
56756
57079
|
swapSymlink(version) {
|
|
56757
|
-
const currentLink =
|
|
57080
|
+
const currentLink = path7.join(this.bundleDir, "current");
|
|
56758
57081
|
const tmpLink = `${currentLink}.new`;
|
|
56759
57082
|
try {
|
|
56760
57083
|
fs2.unlinkSync(tmpLink);
|
|
@@ -56773,7 +57096,7 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56773
57096
|
try {
|
|
56774
57097
|
for (const entry of fs2.readdirSync(versionsDir)) {
|
|
56775
57098
|
if (!keep.has(entry)) {
|
|
56776
|
-
fs2.rmSync(
|
|
57099
|
+
fs2.rmSync(path7.join(versionsDir, entry), { recursive: true });
|
|
56777
57100
|
}
|
|
56778
57101
|
}
|
|
56779
57102
|
} catch {
|
|
@@ -56781,8 +57104,8 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56781
57104
|
}
|
|
56782
57105
|
// --- Manifest & State I/O ---
|
|
56783
57106
|
loadLocalManifest() {
|
|
56784
|
-
const currentDir =
|
|
56785
|
-
const manifestPath =
|
|
57107
|
+
const currentDir = path7.join(this.bundleDir, "current");
|
|
57108
|
+
const manifestPath = path7.join(currentDir, "manifest.json");
|
|
56786
57109
|
try {
|
|
56787
57110
|
return JSON.parse(fs2.readFileSync(manifestPath, "utf-8"));
|
|
56788
57111
|
} catch {
|
|
@@ -56790,7 +57113,7 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56790
57113
|
}
|
|
56791
57114
|
}
|
|
56792
57115
|
loadUpdateState() {
|
|
56793
|
-
const statePath =
|
|
57116
|
+
const statePath = path7.join(this.bundleDir, "update-state.json");
|
|
56794
57117
|
try {
|
|
56795
57118
|
return JSON.parse(fs2.readFileSync(statePath, "utf-8"));
|
|
56796
57119
|
} catch {
|
|
@@ -56798,8 +57121,8 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56798
57121
|
}
|
|
56799
57122
|
}
|
|
56800
57123
|
saveUpdateState(state) {
|
|
56801
|
-
const statePath =
|
|
56802
|
-
const stateDir =
|
|
57124
|
+
const statePath = path7.join(this.bundleDir, "update-state.json");
|
|
57125
|
+
const stateDir = path7.dirname(statePath);
|
|
56803
57126
|
fs2.mkdirSync(stateDir, { recursive: true });
|
|
56804
57127
|
const tmpPath = `${statePath}.tmp-${process.pid}-${Date.now()}`;
|
|
56805
57128
|
let fd;
|
|
@@ -56938,7 +57261,7 @@ MCowBQYDK2VwAyEAQHQAZThNX7+deJNyHl/5DgiAa1OHx7UQoJotam0JhUk=
|
|
|
56938
57261
|
import { execFileSync, execSync, spawn } from "node:child_process";
|
|
56939
57262
|
import * as fs3 from "node:fs";
|
|
56940
57263
|
import * as os3 from "node:os";
|
|
56941
|
-
import * as
|
|
57264
|
+
import * as path8 from "node:path";
|
|
56942
57265
|
import * as readline from "node:readline";
|
|
56943
57266
|
function readConfig() {
|
|
56944
57267
|
try {
|
|
@@ -57047,7 +57370,7 @@ function installServiceWindows() {
|
|
|
57047
57370
|
fs3.unlinkSync(p.legacyLauncherJs);
|
|
57048
57371
|
} catch {
|
|
57049
57372
|
}
|
|
57050
|
-
const wscriptExe =
|
|
57373
|
+
const wscriptExe = path8.join(process.env.SystemRoot || "C:\\Windows", "System32", "wscript.exe");
|
|
57051
57374
|
fs3.writeFileSync(p.launcherVbs, encodeUtf16LeBom(buildLauncherVbs({ nodeExe: process.execPath, launcherCjs: p.launcherCjs })));
|
|
57052
57375
|
fs3.writeFileSync(p.taskXml, encodeUtf16LeBom(buildTaskXml({ wscriptExe, launcherVbs: p.launcherVbs })));
|
|
57053
57376
|
const create = runWinCmd("schtasks", ["/Create", "/TN", WIN_TASK_NAME, "/XML", p.taskXml, "/F"]);
|
|
@@ -57113,10 +57436,10 @@ function serviceUninstallWindows() {
|
|
|
57113
57436
|
console.log("Task Scheduler task uninstalled (logs kept).");
|
|
57114
57437
|
}
|
|
57115
57438
|
function plistPath() {
|
|
57116
|
-
return
|
|
57439
|
+
return path8.join(os3.homedir(), "Library", "LaunchAgents", `${PLIST_LABEL}.plist`);
|
|
57117
57440
|
}
|
|
57118
57441
|
function systemdUnitPath() {
|
|
57119
|
-
return
|
|
57442
|
+
return path8.join(os3.homedir(), ".config", "systemd", "user", "parall-daemon.service");
|
|
57120
57443
|
}
|
|
57121
57444
|
function getDaemonBin() {
|
|
57122
57445
|
try {
|
|
@@ -57126,7 +57449,7 @@ function getDaemonBin() {
|
|
|
57126
57449
|
}
|
|
57127
57450
|
}
|
|
57128
57451
|
function generatePlist(daemonBin) {
|
|
57129
|
-
const logPath =
|
|
57452
|
+
const logPath = path8.join(os3.homedir(), "Library", "Logs", "parall-daemon.log");
|
|
57130
57453
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
57131
57454
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
57132
57455
|
<plist version="1.0">
|
|
@@ -57185,14 +57508,14 @@ function installService() {
|
|
|
57185
57508
|
}
|
|
57186
57509
|
const bin = getDaemonBin();
|
|
57187
57510
|
if (isMacOS()) {
|
|
57188
|
-
const dir =
|
|
57511
|
+
const dir = path8.dirname(plistPath());
|
|
57189
57512
|
fs3.mkdirSync(dir, { recursive: true });
|
|
57190
57513
|
fs3.writeFileSync(plistPath(), generatePlist(bin));
|
|
57191
57514
|
execSync(`launchctl bootout gui/$(id -u) ${plistPath()} 2>/dev/null || true`);
|
|
57192
57515
|
execSync(`launchctl bootstrap gui/$(id -u) ${plistPath()}`);
|
|
57193
57516
|
console.log(`launchd agent installed: ${plistPath()}`);
|
|
57194
57517
|
} else if (isLinux()) {
|
|
57195
|
-
const dir =
|
|
57518
|
+
const dir = path8.dirname(systemdUnitPath());
|
|
57196
57519
|
fs3.mkdirSync(dir, { recursive: true });
|
|
57197
57520
|
fs3.writeFileSync(systemdUnitPath(), generateSystemdUnit(bin));
|
|
57198
57521
|
execSync("systemctl --user daemon-reload");
|
|
@@ -57285,7 +57608,7 @@ function cmdLogs(lines) {
|
|
|
57285
57608
|
child2.on("exit", (code) => process.exit(code ?? 0));
|
|
57286
57609
|
return;
|
|
57287
57610
|
}
|
|
57288
|
-
const logPath =
|
|
57611
|
+
const logPath = path8.join(os3.homedir(), "Library", "Logs", "parall-daemon.log");
|
|
57289
57612
|
if (!fs3.existsSync(logPath)) {
|
|
57290
57613
|
console.log("No log file found at", logPath);
|
|
57291
57614
|
return;
|
|
@@ -61393,8 +61716,8 @@ var init_browser_cdp = __esm({
|
|
|
61393
61716
|
|
|
61394
61717
|
// ts/daemon/dist/clip-runtime/browser-proxy-state.js
|
|
61395
61718
|
import { createHash as createHash2 } from "node:crypto";
|
|
61396
|
-
import { mkdirSync as mkdirSync3, readFileSync as
|
|
61397
|
-
import * as
|
|
61719
|
+
import { mkdirSync as mkdirSync3, readFileSync as readFileSync5, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
61720
|
+
import * as path9 from "node:path";
|
|
61398
61721
|
function normalizeProxyConfig(proxy) {
|
|
61399
61722
|
if (!proxy || !proxy.server?.trim()) {
|
|
61400
61723
|
if (proxy && (proxy.username || proxy.password)) {
|
|
@@ -61428,7 +61751,7 @@ function proxyFingerprint(proxy) {
|
|
|
61428
61751
|
}
|
|
61429
61752
|
function readSidecarObject(homeDir, file) {
|
|
61430
61753
|
try {
|
|
61431
|
-
const parsed = JSON.parse(
|
|
61754
|
+
const parsed = JSON.parse(readFileSync5(path9.join(homeDir, file), "utf8"));
|
|
61432
61755
|
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
61433
61756
|
} catch {
|
|
61434
61757
|
return {};
|
|
@@ -61441,7 +61764,7 @@ function appliedProxyFingerprint(homeDir, account) {
|
|
|
61441
61764
|
function writeAppliedProxyFingerprint(homeDir, account, fingerprint) {
|
|
61442
61765
|
const state = readSidecarObject(homeDir, PROXY_STATE_FILE);
|
|
61443
61766
|
state.applied = { ...state.applied, [account]: fingerprint };
|
|
61444
|
-
atomicWriteJson(
|
|
61767
|
+
atomicWriteJson(path9.join(homeDir, PROXY_STATE_FILE), state);
|
|
61445
61768
|
}
|
|
61446
61769
|
function readCookieBackup(homeDir, account) {
|
|
61447
61770
|
const cookies = readSidecarObject(homeDir, COOKIE_BACKUP_FILE).backups?.[account];
|
|
@@ -61461,10 +61784,10 @@ function clearCookieBackup(homeDir, account) {
|
|
|
61461
61784
|
function updateCookieBackupFile(homeDir, mutate) {
|
|
61462
61785
|
const file = readSidecarObject(homeDir, COOKIE_BACKUP_FILE);
|
|
61463
61786
|
mutate(file);
|
|
61464
|
-
atomicWriteJson(
|
|
61787
|
+
atomicWriteJson(path9.join(homeDir, COOKIE_BACKUP_FILE), file);
|
|
61465
61788
|
}
|
|
61466
61789
|
function atomicWriteJson(filePath, value) {
|
|
61467
|
-
mkdirSync3(
|
|
61790
|
+
mkdirSync3(path9.dirname(filePath), { recursive: true });
|
|
61468
61791
|
const tmp = `${filePath}.tmp-${process.pid}`;
|
|
61469
61792
|
writeFileSync3(tmp, JSON.stringify(value));
|
|
61470
61793
|
renameSync2(tmp, filePath);
|
|
@@ -61768,17 +62091,17 @@ var init_browser_readiness = __esm({
|
|
|
61768
62091
|
|
|
61769
62092
|
// ts/daemon/dist/clip-runtime/bun-resolver.js
|
|
61770
62093
|
import * as fs4 from "node:fs";
|
|
61771
|
-
import * as
|
|
62094
|
+
import * as path10 from "node:path";
|
|
61772
62095
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
61773
62096
|
function findBunBinary() {
|
|
61774
62097
|
const isWindows2 = process.platform === "win32";
|
|
61775
62098
|
const binName = isWindows2 ? "bun.exe" : "bun";
|
|
61776
|
-
const embedded =
|
|
62099
|
+
const embedded = path10.join(path10.dirname(process.execPath), binName);
|
|
61777
62100
|
if (fs4.existsSync(embedded))
|
|
61778
62101
|
return embedded;
|
|
61779
62102
|
if (!isWindows2) {
|
|
61780
62103
|
const candidates = [
|
|
61781
|
-
|
|
62104
|
+
path10.join(process.env.HOME || "", ".bun", "bin", "bun"),
|
|
61782
62105
|
"/usr/local/bin/bun",
|
|
61783
62106
|
"/opt/homebrew/bin/bun"
|
|
61784
62107
|
];
|
|
@@ -61806,7 +62129,7 @@ var init_bun_resolver = __esm({
|
|
|
61806
62129
|
|
|
61807
62130
|
// ts/daemon/dist/clip-runtime/clip-installer.js
|
|
61808
62131
|
import * as fs5 from "node:fs";
|
|
61809
|
-
import * as
|
|
62132
|
+
import * as path11 from "node:path";
|
|
61810
62133
|
import * as crypto from "node:crypto";
|
|
61811
62134
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
61812
62135
|
import { pipeline } from "node:stream/promises";
|
|
@@ -62020,7 +62343,7 @@ function verifyChecksum(filePath, algo, expectedHex) {
|
|
|
62020
62343
|
hash.update(content);
|
|
62021
62344
|
const actual = hash.digest("hex");
|
|
62022
62345
|
if (actual !== expectedHex) {
|
|
62023
|
-
throw new Error(`checksum mismatch for ${
|
|
62346
|
+
throw new Error(`checksum mismatch for ${path11.basename(filePath)}: expected ${algo}:${expectedHex}, got ${algo}:${actual}`);
|
|
62024
62347
|
}
|
|
62025
62348
|
}
|
|
62026
62349
|
function validateTarEntries(tarballPath) {
|
|
@@ -62037,11 +62360,11 @@ function validateTarEntries(tarballPath) {
|
|
|
62037
62360
|
const trimmed = entry.trim();
|
|
62038
62361
|
if (!trimmed)
|
|
62039
62362
|
continue;
|
|
62040
|
-
if (
|
|
62363
|
+
if (path11.isAbsolute(trimmed)) {
|
|
62041
62364
|
throw new Error(`tarball contains absolute path: "${trimmed}"`);
|
|
62042
62365
|
}
|
|
62043
|
-
const normalized =
|
|
62044
|
-
if (normalized.startsWith("..") || normalized.includes(`${
|
|
62366
|
+
const normalized = path11.normalize(trimmed);
|
|
62367
|
+
if (normalized.startsWith("..") || normalized.includes(`${path11.sep}..${path11.sep}`)) {
|
|
62045
62368
|
throw new Error(`tarball contains path traversal: "${trimmed}"`);
|
|
62046
62369
|
}
|
|
62047
62370
|
}
|
|
@@ -62089,7 +62412,7 @@ function detectStripComponents(tarballPath) {
|
|
|
62089
62412
|
return commonPrefix ? 1 : 0;
|
|
62090
62413
|
}
|
|
62091
62414
|
function installDeps(clipDir) {
|
|
62092
|
-
const pkgJsonPath =
|
|
62415
|
+
const pkgJsonPath = path11.join(clipDir, "package.json");
|
|
62093
62416
|
if (!fs5.existsSync(pkgJsonPath))
|
|
62094
62417
|
return;
|
|
62095
62418
|
let hasDeps = false;
|
|
@@ -62108,7 +62431,7 @@ function installDeps(clipDir) {
|
|
|
62108
62431
|
if (bunPath) {
|
|
62109
62432
|
const bunEnv = {
|
|
62110
62433
|
...process.env,
|
|
62111
|
-
PATH: `${
|
|
62434
|
+
PATH: `${path11.dirname(bunPath)}${path11.delimiter}${process.env.PATH ?? ""}`
|
|
62112
62435
|
};
|
|
62113
62436
|
for (const args of [["install", "--frozen-lockfile"], ["install"]]) {
|
|
62114
62437
|
try {
|
|
@@ -62144,19 +62467,19 @@ async function installClip(opts) {
|
|
|
62144
62467
|
const registryUrl = (opts.registryUrl ?? DEFAULT_REGISTRY_URL).replace(/\/+$/, "");
|
|
62145
62468
|
const parsed = parseSource(opts.source);
|
|
62146
62469
|
const alias = opts.alias ?? deriveAlias(parsed);
|
|
62147
|
-
const destDir =
|
|
62470
|
+
const destDir = path11.join(opts.clipsDir, alias);
|
|
62148
62471
|
const versionMeta = await resolveVersionMeta(registryUrl, parsed);
|
|
62149
|
-
const tmpDir =
|
|
62472
|
+
const tmpDir = path11.join(opts.clipsDir, `.tmp-${alias}-${Date.now()}`);
|
|
62150
62473
|
fs5.mkdirSync(tmpDir, { recursive: true });
|
|
62151
|
-
const tarballPath =
|
|
62152
|
-
const stageDir =
|
|
62474
|
+
const tarballPath = path11.join(tmpDir, `${alias}-${versionMeta.version}.tgz`);
|
|
62475
|
+
const stageDir = path11.join(tmpDir, "stage");
|
|
62153
62476
|
try {
|
|
62154
62477
|
await httpDownload(versionMeta.tarball, tarballPath);
|
|
62155
62478
|
verifyChecksum(tarballPath, versionMeta.checksumAlgo, versionMeta.checksumHex);
|
|
62156
62479
|
validateTarEntries(tarballPath);
|
|
62157
62480
|
extractTarball(tarballPath, stageDir);
|
|
62158
62481
|
installDeps(stageDir);
|
|
62159
|
-
const backupDir =
|
|
62482
|
+
const backupDir = path11.join(opts.clipsDir, `.backup-${alias}-${Date.now()}`);
|
|
62160
62483
|
let backedUp = false;
|
|
62161
62484
|
try {
|
|
62162
62485
|
if (fs5.existsSync(destDir)) {
|
|
@@ -62197,9 +62520,9 @@ var init_clip_installer = __esm({
|
|
|
62197
62520
|
|
|
62198
62521
|
// ts/daemon/dist/clip-runtime/manifest.js
|
|
62199
62522
|
import * as fs6 from "node:fs";
|
|
62200
|
-
import * as
|
|
62523
|
+
import * as path12 from "node:path";
|
|
62201
62524
|
function loadClipJson(dir) {
|
|
62202
|
-
const filePath =
|
|
62525
|
+
const filePath = path12.join(dir, "clip.json");
|
|
62203
62526
|
try {
|
|
62204
62527
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
62205
62528
|
return JSON.parse(content);
|
|
@@ -62208,7 +62531,7 @@ function loadClipJson(dir) {
|
|
|
62208
62531
|
}
|
|
62209
62532
|
}
|
|
62210
62533
|
function loadPackageJson(dir) {
|
|
62211
|
-
const filePath =
|
|
62534
|
+
const filePath = path12.join(dir, "package.json");
|
|
62212
62535
|
try {
|
|
62213
62536
|
const content = fs6.readFileSync(filePath, "utf-8");
|
|
62214
62537
|
return JSON.parse(content);
|
|
@@ -62323,19 +62646,19 @@ function manifestFromIpc(ipcManifest) {
|
|
|
62323
62646
|
function resolveEntrypoint(clip) {
|
|
62324
62647
|
const clipJson = loadClipJson(clip.path);
|
|
62325
62648
|
if (clipJson?.main)
|
|
62326
|
-
return
|
|
62649
|
+
return path12.join(clip.path, clipJson.main);
|
|
62327
62650
|
const pkgJson = loadPackageJson(clip.path);
|
|
62328
62651
|
if (pkgJson?.main)
|
|
62329
|
-
return
|
|
62652
|
+
return path12.join(clip.path, pkgJson.main);
|
|
62330
62653
|
if (pkgJson?.bin) {
|
|
62331
62654
|
const binPath = typeof pkgJson.bin === "string" ? pkgJson.bin : Object.values(pkgJson.bin)[0];
|
|
62332
62655
|
if (binPath)
|
|
62333
|
-
return
|
|
62656
|
+
return path12.join(clip.path, binPath);
|
|
62334
62657
|
}
|
|
62335
|
-
const defaultEntry =
|
|
62658
|
+
const defaultEntry = path12.join(clip.path, "index.ts");
|
|
62336
62659
|
if (fs6.existsSync(defaultEntry))
|
|
62337
62660
|
return defaultEntry;
|
|
62338
|
-
return
|
|
62661
|
+
return path12.join(clip.path, "index.js");
|
|
62339
62662
|
}
|
|
62340
62663
|
function finalizeManifest(manifest) {
|
|
62341
62664
|
const m = { ...manifest };
|
|
@@ -62365,8 +62688,8 @@ var init_manifest = __esm({
|
|
|
62365
62688
|
// ts/daemon/dist/runtimes.js
|
|
62366
62689
|
import * as fs7 from "node:fs";
|
|
62367
62690
|
import * as os4 from "node:os";
|
|
62368
|
-
import * as
|
|
62369
|
-
import { fileURLToPath } from "node:url";
|
|
62691
|
+
import * as path13 from "node:path";
|
|
62692
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
62370
62693
|
function buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
|
|
62371
62694
|
const env = { ...baseEnv };
|
|
62372
62695
|
clearAllProviderCreds(env);
|
|
@@ -62380,7 +62703,7 @@ function buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
|
|
|
62380
62703
|
env.PRLL_PROVIDER_CONFIG = JSON.stringify(pc);
|
|
62381
62704
|
if (dirs.homeDir)
|
|
62382
62705
|
env.HOME = dirs.homeDir;
|
|
62383
|
-
|
|
62706
|
+
env.PRLL_DAEMON_MODE = "1";
|
|
62384
62707
|
return env;
|
|
62385
62708
|
}
|
|
62386
62709
|
function bundledSiblingBin(overlayName, entryPath) {
|
|
@@ -62388,17 +62711,17 @@ function bundledSiblingBin(overlayName, entryPath) {
|
|
|
62388
62711
|
const entry = entryPath ?? process.argv[1];
|
|
62389
62712
|
if (entry) {
|
|
62390
62713
|
try {
|
|
62391
|
-
candidateDirs.push(
|
|
62714
|
+
candidateDirs.push(path13.dirname(fs7.realpathSync(entry)));
|
|
62392
62715
|
} catch {
|
|
62393
|
-
candidateDirs.push(
|
|
62716
|
+
candidateDirs.push(path13.dirname(path13.resolve(entry)));
|
|
62394
62717
|
}
|
|
62395
62718
|
}
|
|
62396
62719
|
try {
|
|
62397
|
-
candidateDirs.push(
|
|
62720
|
+
candidateDirs.push(path13.dirname(fileURLToPath2(import.meta.url)));
|
|
62398
62721
|
} catch {
|
|
62399
62722
|
}
|
|
62400
62723
|
for (const dir of candidateDirs) {
|
|
62401
|
-
const bin =
|
|
62724
|
+
const bin = path13.join(dir, overlayName);
|
|
62402
62725
|
try {
|
|
62403
62726
|
if (fs7.existsSync(bin))
|
|
62404
62727
|
return bin;
|
|
@@ -62414,7 +62737,7 @@ function getRuntimeAdapter(runtimeType, opts) {
|
|
|
62414
62737
|
return base;
|
|
62415
62738
|
try {
|
|
62416
62739
|
const bundleDir = resolveBundleDir(opts?.env);
|
|
62417
|
-
const overlayBin =
|
|
62740
|
+
const overlayBin = path13.join(bundleDir, "current", overlayName);
|
|
62418
62741
|
if (fs7.existsSync(overlayBin)) {
|
|
62419
62742
|
return { ...base, bin: process.execPath, args: [overlayBin] };
|
|
62420
62743
|
}
|
|
@@ -62452,9 +62775,9 @@ var init_runtimes = __esm({
|
|
|
62452
62775
|
buildEnv(baseEnv, agentId, orgId, apiKey, dirs, pc) {
|
|
62453
62776
|
const env = buildStandardEnv(baseEnv, agentId, orgId, apiKey, dirs, pc);
|
|
62454
62777
|
if (baseEnv.KUBERNETES_SERVICE_HOST || llmSource(pc) !== "runtime_auth") {
|
|
62455
|
-
env.PRLL_CODEX_HOME =
|
|
62778
|
+
env.PRLL_CODEX_HOME = path13.join(dirs.stateDir, ".codex");
|
|
62456
62779
|
} else if (dirs.homeDir && !env.CODEX_HOME) {
|
|
62457
|
-
env.CODEX_HOME =
|
|
62780
|
+
env.CODEX_HOME = path13.join(baseEnv.HOME || os4.homedir(), ".codex");
|
|
62458
62781
|
}
|
|
62459
62782
|
return env;
|
|
62460
62783
|
}
|
|
@@ -63300,7 +63623,7 @@ var init_hub_client = __esm({
|
|
|
63300
63623
|
|
|
63301
63624
|
// ts/daemon/dist/clip-runtime/process-manager.js
|
|
63302
63625
|
import * as fs8 from "node:fs";
|
|
63303
|
-
import * as
|
|
63626
|
+
import * as path14 from "node:path";
|
|
63304
63627
|
function browserCapabilityConfig() {
|
|
63305
63628
|
return {
|
|
63306
63629
|
name: BROWSER_CAPABILITY_NAME,
|
|
@@ -63559,7 +63882,7 @@ var init_process_manager = __esm({
|
|
|
63559
63882
|
* Reads clip-config.json if present, or scans subdirectories for clip.json files.
|
|
63560
63883
|
*/
|
|
63561
63884
|
async loadInstalledClips() {
|
|
63562
|
-
const configFile =
|
|
63885
|
+
const configFile = path14.join(path14.dirname(this.clipsDir), "clip-config.json");
|
|
63563
63886
|
if (fs8.existsSync(configFile)) {
|
|
63564
63887
|
try {
|
|
63565
63888
|
const content = fs8.readFileSync(configFile, "utf-8");
|
|
@@ -63578,9 +63901,9 @@ var init_process_manager = __esm({
|
|
|
63578
63901
|
for (const entry of entries) {
|
|
63579
63902
|
if (!entry.isDirectory())
|
|
63580
63903
|
continue;
|
|
63581
|
-
const clipDir =
|
|
63582
|
-
const clipJsonPath =
|
|
63583
|
-
const pkgJsonPath =
|
|
63904
|
+
const clipDir = path14.join(this.clipsDir, entry.name);
|
|
63905
|
+
const clipJsonPath = path14.join(clipDir, "clip.json");
|
|
63906
|
+
const pkgJsonPath = path14.join(clipDir, "package.json");
|
|
63584
63907
|
if (fs8.existsSync(clipJsonPath)) {
|
|
63585
63908
|
try {
|
|
63586
63909
|
const clipJson = JSON.parse(fs8.readFileSync(clipJsonPath, "utf-8"));
|
|
@@ -63650,7 +63973,7 @@ var init_process_manager = __esm({
|
|
|
63650
63973
|
// shells out to `bun` by name resolves it — the daemon's launchd PATH
|
|
63651
63974
|
// does not include Frameworks/. Symmetric with installDeps(); relies on
|
|
63652
63975
|
// the embedded binary being named `bun` (Frameworks/bun).
|
|
63653
|
-
PATH: `${
|
|
63976
|
+
PATH: `${path14.dirname(bunPath)}${path14.delimiter}${process.env.PATH ?? ""}`
|
|
63654
63977
|
});
|
|
63655
63978
|
this.setStatus(config.name, "running", "starting");
|
|
63656
63979
|
try {
|
|
@@ -63679,7 +64002,7 @@ var init_process_manager = __esm({
|
|
|
63679
64002
|
return proc;
|
|
63680
64003
|
}
|
|
63681
64004
|
ensureClipDataDir(config, context2 = {}) {
|
|
63682
|
-
const dir =
|
|
64005
|
+
const dir = path14.join(this.dataDir, config.name, context2.clipId ?? "default");
|
|
63683
64006
|
fs8.mkdirSync(dir, { recursive: true });
|
|
63684
64007
|
return dir;
|
|
63685
64008
|
}
|
|
@@ -65186,10 +65509,10 @@ var init_browser_viewer_streamer = __esm({
|
|
|
65186
65509
|
// ts/daemon/dist/clip-runtime/browser-profile-manager.js
|
|
65187
65510
|
import { spawn as spawn4 } from "node:child_process";
|
|
65188
65511
|
import { randomBytes } from "node:crypto";
|
|
65189
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as
|
|
65512
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync9 } from "node:fs";
|
|
65190
65513
|
import { createRequire } from "node:module";
|
|
65191
|
-
import * as
|
|
65192
|
-
import { fileURLToPath as
|
|
65514
|
+
import * as path15 from "node:path";
|
|
65515
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
65193
65516
|
function normalizeStartUrl(value) {
|
|
65194
65517
|
const trimmed = value?.trim();
|
|
65195
65518
|
if (!trimmed)
|
|
@@ -65224,14 +65547,14 @@ function isRecoverableBrowserDaemonError(err) {
|
|
|
65224
65547
|
return lower.includes("chrome not connected") || lower.includes("cdp at 127.0.0.1") || lower.includes("no page target found") || lower.includes("bb-browser /command returned 503") && (lower.includes("chrome") || lower.includes("cdp"));
|
|
65225
65548
|
}
|
|
65226
65549
|
function resolveBbBrowserDaemonPath() {
|
|
65227
|
-
const sibling =
|
|
65550
|
+
const sibling = path15.join(path15.dirname(fileURLToPath3(import.meta.url)), "bb-browser-daemon.js");
|
|
65228
65551
|
if (existsSync8(sibling))
|
|
65229
65552
|
return sibling;
|
|
65230
65553
|
const require2 = createRequire(import.meta.url);
|
|
65231
65554
|
const pkgPath = require2.resolve("@pinixai/bb-browser-pro/package.json");
|
|
65232
|
-
const pkg = JSON.parse(
|
|
65555
|
+
const pkg = JSON.parse(readFileSync9(pkgPath, "utf8"));
|
|
65233
65556
|
const rel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.["bb-browser-daemon"] ?? "./dist/daemon.js";
|
|
65234
|
-
const full =
|
|
65557
|
+
const full = path15.resolve(path15.dirname(pkgPath), rel);
|
|
65235
65558
|
if (!existsSync8(full)) {
|
|
65236
65559
|
throw new Error(`bb-browser-daemon entrypoint not found at ${full}`);
|
|
65237
65560
|
}
|
|
@@ -65906,8 +66229,8 @@ var init_browser_profile_manager = __esm({
|
|
|
65906
66229
|
});
|
|
65907
66230
|
|
|
65908
66231
|
// ts/daemon/dist/clip-runtime/browser-profile-pool.js
|
|
65909
|
-
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readdirSync as readdirSync3, readFileSync as
|
|
65910
|
-
import * as
|
|
66232
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync7, readdirSync as readdirSync3, readFileSync as readFileSync10, renameSync as renameSync4, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
66233
|
+
import * as path16 from "node:path";
|
|
65911
66234
|
function isSafeProfileId(id) {
|
|
65912
66235
|
return /^brp_[A-Za-z0-9_-]+$/.test(id);
|
|
65913
66236
|
}
|
|
@@ -66278,11 +66601,11 @@ var init_browser_profile_pool = __esm({
|
|
|
66278
66601
|
}
|
|
66279
66602
|
}
|
|
66280
66603
|
profileHome(profileId) {
|
|
66281
|
-
return
|
|
66604
|
+
return path16.join(this.opts.baseHomeDir, sanitizeProfileId(profileId));
|
|
66282
66605
|
}
|
|
66283
66606
|
/** Legacy shared-layout cookie file for a profile (pre per-profile homes). */
|
|
66284
66607
|
legacyAccountFile(profileId) {
|
|
66285
|
-
return
|
|
66608
|
+
return path16.join(this.opts.baseHomeDir, "accounts", `${sanitizeProfileId(profileId)}.json`);
|
|
66286
66609
|
}
|
|
66287
66610
|
/**
|
|
66288
66611
|
* Remove every on-disk trace of a profile: its per-profile home AND any
|
|
@@ -66310,12 +66633,12 @@ var init_browser_profile_pool = __esm({
|
|
|
66310
66633
|
// reset_generation to this value: a newer server value means a reset was missed
|
|
66311
66634
|
// while offline → wipe. Missing/corrupt reads as 0 (so any server reset wins).
|
|
66312
66635
|
metaFile(profileId) {
|
|
66313
|
-
return
|
|
66636
|
+
return path16.join(this.profileHome(profileId), ".parall-profile-meta.json");
|
|
66314
66637
|
}
|
|
66315
66638
|
/** The reset_generation this daemon has applied for the profile (0 if unknown). */
|
|
66316
66639
|
appliedResetGeneration(profileId) {
|
|
66317
66640
|
try {
|
|
66318
|
-
const parsed = JSON.parse(
|
|
66641
|
+
const parsed = JSON.parse(readFileSync10(this.metaFile(profileId), "utf8"));
|
|
66319
66642
|
const gen = parsed.reset_generation;
|
|
66320
66643
|
return typeof gen === "number" && Number.isFinite(gen) ? gen : 0;
|
|
66321
66644
|
} catch {
|
|
@@ -66328,7 +66651,7 @@ var init_browser_profile_pool = __esm({
|
|
|
66328
66651
|
writeResetGeneration(profileId, generation) {
|
|
66329
66652
|
const home = this.profileHome(profileId);
|
|
66330
66653
|
mkdirSync7(home, { recursive: true });
|
|
66331
|
-
const tmp =
|
|
66654
|
+
const tmp = path16.join(home, `.parall-profile-meta.json.tmp-${process.pid}`);
|
|
66332
66655
|
writeFileSync4(tmp, JSON.stringify({ reset_generation: generation }));
|
|
66333
66656
|
renameSync4(tmp, this.metaFile(profileId));
|
|
66334
66657
|
}
|
|
@@ -66354,7 +66677,7 @@ var init_browser_profile_pool = __esm({
|
|
|
66354
66677
|
} catch {
|
|
66355
66678
|
}
|
|
66356
66679
|
try {
|
|
66357
|
-
const accountsDir =
|
|
66680
|
+
const accountsDir = path16.join(this.opts.baseHomeDir, "accounts");
|
|
66358
66681
|
for (const e of readdirSync3(accountsDir, { withFileTypes: true })) {
|
|
66359
66682
|
if (!e.isFile() || !e.name.endsWith(".json"))
|
|
66360
66683
|
continue;
|
|
@@ -66380,8 +66703,8 @@ var init_browser_profile_pool = __esm({
|
|
|
66380
66703
|
const legacy = this.legacyAccountFile(profileId);
|
|
66381
66704
|
if (!existsSync9(legacy))
|
|
66382
66705
|
return;
|
|
66383
|
-
const destDir =
|
|
66384
|
-
const dest =
|
|
66706
|
+
const destDir = path16.join(this.profileHome(profileId), "accounts");
|
|
66707
|
+
const dest = path16.join(destDir, path16.basename(legacy));
|
|
66385
66708
|
if (existsSync9(dest))
|
|
66386
66709
|
return;
|
|
66387
66710
|
try {
|
|
@@ -66414,10 +66737,10 @@ var init_clip_runtime = __esm({
|
|
|
66414
66737
|
|
|
66415
66738
|
// ts/daemon/dist/filesystem.js
|
|
66416
66739
|
import * as fs9 from "fs";
|
|
66417
|
-
import * as
|
|
66740
|
+
import * as path17 from "path";
|
|
66418
66741
|
import * as os5 from "os";
|
|
66419
66742
|
function browseDenyReason(value) {
|
|
66420
|
-
const normalized =
|
|
66743
|
+
const normalized = path17.resolve(value).split(path17.sep).join("/");
|
|
66421
66744
|
if (normalized === "/")
|
|
66422
66745
|
return "";
|
|
66423
66746
|
for (const prefix of SYSTEM_DIR_PREFIXES) {
|
|
@@ -66447,8 +66770,8 @@ function syntheticRoots() {
|
|
|
66447
66770
|
return roots;
|
|
66448
66771
|
}
|
|
66449
66772
|
async function listDirectory(dirPath) {
|
|
66450
|
-
const resolved =
|
|
66451
|
-
const normalized = resolved.split(
|
|
66773
|
+
const resolved = path17.resolve(dirPath);
|
|
66774
|
+
const normalized = resolved.split(path17.sep).join("/");
|
|
66452
66775
|
if (normalized === "/") {
|
|
66453
66776
|
return { entries: syntheticRoots() };
|
|
66454
66777
|
}
|
|
@@ -66465,7 +66788,7 @@ async function listDirectory(dirPath) {
|
|
|
66465
66788
|
return { entries: [], error: "Directory not found" };
|
|
66466
66789
|
return { entries: [], error: "Permission denied" };
|
|
66467
66790
|
}
|
|
66468
|
-
const realDeny = browseDenyReason(realPath.split(
|
|
66791
|
+
const realDeny = browseDenyReason(realPath.split(path17.sep).join("/"));
|
|
66469
66792
|
if (realDeny) {
|
|
66470
66793
|
return { entries: [], error: `Access denied: ${realDeny}` };
|
|
66471
66794
|
}
|
|
@@ -66535,9 +66858,9 @@ var init_filesystem = __esm({
|
|
|
66535
66858
|
// ts/daemon/dist/local-control.js
|
|
66536
66859
|
import { chmodSync as chmodSync2, existsSync as existsSync10, mkdirSync as mkdirSync8, rmSync as rmSync4, statSync } from "node:fs";
|
|
66537
66860
|
import * as net2 from "node:net";
|
|
66538
|
-
import * as
|
|
66861
|
+
import * as path18 from "node:path";
|
|
66539
66862
|
function localControlSocketPath(env = process.env) {
|
|
66540
|
-
return
|
|
66863
|
+
return path18.join(daemonConfigDir(env), "run", "control.sock");
|
|
66541
66864
|
}
|
|
66542
66865
|
function isSocketLive(sockPath) {
|
|
66543
66866
|
return new Promise((resolve9) => {
|
|
@@ -66580,7 +66903,7 @@ var init_local_control = __esm({
|
|
|
66580
66903
|
if (this.server)
|
|
66581
66904
|
throw new Error("local control server already started");
|
|
66582
66905
|
const sockPath = this.opts.socketPath;
|
|
66583
|
-
const dir =
|
|
66906
|
+
const dir = path18.dirname(sockPath);
|
|
66584
66907
|
mkdirSync8(dir, { recursive: true, mode: 448 });
|
|
66585
66908
|
try {
|
|
66586
66909
|
chmodSync2(dir, 448);
|
|
@@ -66805,7 +67128,7 @@ var init_local_profile_control = __esm({
|
|
|
66805
67128
|
|
|
66806
67129
|
// ts/daemon/dist/home-isolation.js
|
|
66807
67130
|
import * as fs10 from "node:fs";
|
|
66808
|
-
import * as
|
|
67131
|
+
import * as path19 from "node:path";
|
|
66809
67132
|
function ensureIsolatedHome(spec, agentId, log2, platform2 = process.platform) {
|
|
66810
67133
|
fs10.mkdirSync(spec.homeDir, { recursive: true });
|
|
66811
67134
|
const failures = [];
|
|
@@ -66817,18 +67140,18 @@ function ensureIsolatedHome(spec, agentId, log2, platform2 = process.platform) {
|
|
|
66817
67140
|
}
|
|
66818
67141
|
};
|
|
66819
67142
|
attempt(".claude link", () => {
|
|
66820
|
-
fs10.mkdirSync(
|
|
66821
|
-
ensureLink(
|
|
67143
|
+
fs10.mkdirSync(path19.join(spec.claudeStateRoot, ".claude"), { recursive: true });
|
|
67144
|
+
ensureLink(path19.join(spec.homeDir, ".claude"), path19.join(spec.claudeStateRoot, ".claude"), agentId, log2);
|
|
66822
67145
|
});
|
|
66823
|
-
attempt(".claude.json link", () => ensureLink(
|
|
67146
|
+
attempt(".claude.json link", () => ensureLink(path19.join(spec.homeDir, ".claude.json"), path19.join(spec.claudeStateRoot, ".claude.json"), agentId, log2));
|
|
66824
67147
|
if (platform2 === "darwin") {
|
|
66825
67148
|
attempt("Library/Keychains link", () => {
|
|
66826
|
-
fs10.mkdirSync(
|
|
66827
|
-
ensureLink(
|
|
67149
|
+
fs10.mkdirSync(path19.join(spec.homeDir, "Library"), { recursive: true });
|
|
67150
|
+
ensureLink(path19.join(spec.homeDir, "Library", "Keychains"), path19.join(spec.systemHome, "Library", "Keychains"), agentId, log2);
|
|
66828
67151
|
});
|
|
66829
67152
|
}
|
|
66830
67153
|
attempt(".gitconfig", () => {
|
|
66831
|
-
const gitconfig =
|
|
67154
|
+
const gitconfig = path19.join(spec.homeDir, ".gitconfig");
|
|
66832
67155
|
if (!fs10.existsSync(gitconfig)) {
|
|
66833
67156
|
fs10.writeFileSync(gitconfig, `[user]
|
|
66834
67157
|
name = ${gitConfigValue(spec.gitUserName)}
|
|
@@ -66854,7 +67177,7 @@ function ensureLink(linkPath, target, agentId, log2) {
|
|
|
66854
67177
|
if (existing) {
|
|
66855
67178
|
if (existing.isSymbolicLink()) {
|
|
66856
67179
|
const current = fs10.readlinkSync(linkPath);
|
|
66857
|
-
if (
|
|
67180
|
+
if (path19.resolve(path19.dirname(linkPath), current) === path19.resolve(target))
|
|
66858
67181
|
return;
|
|
66859
67182
|
fs10.unlinkSync(linkPath);
|
|
66860
67183
|
log2.info(`agent ${agentId}: relinking ${linkPath} \u2192 ${target}`);
|
|
@@ -66867,16 +67190,16 @@ function ensureLink(linkPath, target, agentId, log2) {
|
|
|
66867
67190
|
fs10.symlinkSync(target, linkPath);
|
|
66868
67191
|
}
|
|
66869
67192
|
function ensureSharedCredentialLink(rootClaudeHome, agentClaudeHome, agentId, log2) {
|
|
66870
|
-
const sharedCredentials =
|
|
67193
|
+
const sharedCredentials = path19.resolve(sharedClaudeCredentialsFileFor(rootClaudeHome));
|
|
66871
67194
|
const agentCredentials = agentClaudeCredentialsFileFor(agentClaudeHome);
|
|
66872
|
-
const agentCredentialsDir =
|
|
66873
|
-
fs10.mkdirSync(
|
|
67195
|
+
const agentCredentialsDir = path19.dirname(agentCredentials);
|
|
67196
|
+
fs10.mkdirSync(path19.dirname(sharedCredentials), { recursive: true });
|
|
66874
67197
|
fs10.mkdirSync(agentCredentialsDir, { recursive: true });
|
|
66875
67198
|
try {
|
|
66876
67199
|
const existing = fs10.lstatSync(agentCredentials);
|
|
66877
67200
|
if (existing.isSymbolicLink()) {
|
|
66878
67201
|
const currentTarget = fs10.readlinkSync(agentCredentials);
|
|
66879
|
-
if (
|
|
67202
|
+
if (path19.resolve(agentCredentialsDir, currentTarget) === sharedCredentials) {
|
|
66880
67203
|
return;
|
|
66881
67204
|
}
|
|
66882
67205
|
fs10.unlinkSync(agentCredentials);
|
|
@@ -66904,7 +67227,7 @@ var init_home_isolation = __esm({
|
|
|
66904
67227
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
66905
67228
|
import * as fs11 from "node:fs";
|
|
66906
67229
|
import * as os6 from "node:os";
|
|
66907
|
-
import * as
|
|
67230
|
+
import * as path20 from "node:path";
|
|
66908
67231
|
function runtimeBinaryEnvVar(runtimeType) {
|
|
66909
67232
|
return RUNTIME_BINARIES[runtimeType]?.envVar;
|
|
66910
67233
|
}
|
|
@@ -66981,16 +67304,16 @@ function resolveRuntimeCommand(command, env, inheritedPath, primaryPath, fallbac
|
|
|
66981
67304
|
function resolveDirectPath(command) {
|
|
66982
67305
|
if (!command.includes("/") && !command.includes("\\"))
|
|
66983
67306
|
return null;
|
|
66984
|
-
const abs =
|
|
67307
|
+
const abs = path20.isAbsolute(command) ? command : path20.resolve(process.cwd(), command);
|
|
66985
67308
|
return isExecutable(abs) ? abs : null;
|
|
66986
67309
|
}
|
|
66987
67310
|
function resolveFromPath(command, pathValue, env, platform2) {
|
|
66988
67311
|
if (!pathValue || command.includes("/") || command.includes("\\"))
|
|
66989
67312
|
return null;
|
|
66990
|
-
const dirs = pathValue.split(
|
|
67313
|
+
const dirs = pathValue.split(path20.delimiter).filter(Boolean);
|
|
66991
67314
|
for (const dir of dirs) {
|
|
66992
67315
|
for (const file of commandCandidates(command, env, platform2)) {
|
|
66993
|
-
const candidate =
|
|
67316
|
+
const candidate = path20.join(dir, file);
|
|
66994
67317
|
if (isExecutable(candidate))
|
|
66995
67318
|
return { binaryPath: candidate, pathValue };
|
|
66996
67319
|
}
|
|
@@ -67031,7 +67354,7 @@ __PRLL_PATH__%s
|
|
|
67031
67354
|
if (line.startsWith("__PRLL_PATH__"))
|
|
67032
67355
|
pathValue = line.slice("__PRLL_PATH__".length);
|
|
67033
67356
|
}
|
|
67034
|
-
if (
|
|
67357
|
+
if (path20.isAbsolute(binaryPath) && isExecutable(binaryPath)) {
|
|
67035
67358
|
return { binaryPath, pathValue: pathValue || void 0 };
|
|
67036
67359
|
}
|
|
67037
67360
|
} catch {
|
|
@@ -67051,18 +67374,18 @@ function cachedCandidatePathPlan(env, platform2) {
|
|
|
67051
67374
|
function candidatePathPlan(env, platform2 = process.platform) {
|
|
67052
67375
|
const home = env.HOME || os6.homedir();
|
|
67053
67376
|
if (platform2 === "win32") {
|
|
67054
|
-
const appData = env.APPDATA ||
|
|
67055
|
-
const localAppData = env.LOCALAPPDATA ||
|
|
67377
|
+
const appData = env.APPDATA || path20.join(home, "AppData", "Roaming");
|
|
67378
|
+
const localAppData = env.LOCALAPPDATA || path20.join(home, "AppData", "Local");
|
|
67056
67379
|
const winPrimaryDirs = [
|
|
67057
67380
|
...splitPath(env.PRLL_DAEMON_RUNTIME_PATH),
|
|
67058
67381
|
...splitPath(env.PRLL_DAEMON_EXTRA_PATH),
|
|
67059
|
-
|
|
67382
|
+
path20.dirname(process.execPath),
|
|
67060
67383
|
env.PNPM_HOME,
|
|
67061
|
-
|
|
67062
|
-
|
|
67063
|
-
|
|
67064
|
-
|
|
67065
|
-
|
|
67384
|
+
path20.join(appData, "npm"),
|
|
67385
|
+
path20.join(localAppData, "pnpm"),
|
|
67386
|
+
path20.join(localAppData, "Volta", "bin"),
|
|
67387
|
+
path20.join(home, ".volta", "bin"),
|
|
67388
|
+
path20.join(home, ".bun", "bin")
|
|
67066
67389
|
];
|
|
67067
67390
|
return {
|
|
67068
67391
|
primaryDirs: unique(winPrimaryDirs).filter((dir) => !!dir && isDirectory(dir)),
|
|
@@ -67072,21 +67395,21 @@ function candidatePathPlan(env, platform2 = process.platform) {
|
|
|
67072
67395
|
const primaryDirs = [
|
|
67073
67396
|
...splitPath(env.PRLL_DAEMON_RUNTIME_PATH),
|
|
67074
67397
|
...splitPath(env.PRLL_DAEMON_EXTRA_PATH),
|
|
67075
|
-
|
|
67076
|
-
|
|
67077
|
-
|
|
67078
|
-
|
|
67079
|
-
|
|
67080
|
-
|
|
67081
|
-
|
|
67082
|
-
|
|
67083
|
-
|
|
67084
|
-
|
|
67085
|
-
|
|
67086
|
-
|
|
67087
|
-
|
|
67088
|
-
|
|
67089
|
-
|
|
67398
|
+
path20.dirname(process.execPath),
|
|
67399
|
+
path20.join(path20.dirname(process.execPath), "bin"),
|
|
67400
|
+
path20.resolve(path20.dirname(process.execPath), "..", "Resources", "bin"),
|
|
67401
|
+
path20.join(home, ".local", "bin"),
|
|
67402
|
+
path20.join(home, "bin"),
|
|
67403
|
+
path20.join(home, ".npm-global", "bin"),
|
|
67404
|
+
path20.join(home, "Library", "pnpm"),
|
|
67405
|
+
path20.join(home, ".local", "share", "pnpm"),
|
|
67406
|
+
path20.join(home, ".volta", "bin"),
|
|
67407
|
+
path20.join(home, ".bun", "bin"),
|
|
67408
|
+
path20.join(home, ".asdf", "shims"),
|
|
67409
|
+
path20.join(home, ".local", "share", "mise", "shims"),
|
|
67410
|
+
path20.join(home, ".mise", "shims"),
|
|
67411
|
+
path20.join(home, ".fnm", "aliases", "default", "bin"),
|
|
67412
|
+
path20.join(home, "Library", "Application Support", "fnm", "aliases", "default", "bin"),
|
|
67090
67413
|
"/opt/homebrew/bin",
|
|
67091
67414
|
"/usr/local/bin",
|
|
67092
67415
|
"/usr/bin",
|
|
@@ -67105,19 +67428,19 @@ function candidatePathPlan(env, platform2 = process.platform) {
|
|
|
67105
67428
|
};
|
|
67106
67429
|
}
|
|
67107
67430
|
function nvmVersionBinDirs(home) {
|
|
67108
|
-
const root =
|
|
67431
|
+
const root = path20.join(home, ".nvm", "versions", "node");
|
|
67109
67432
|
let versions;
|
|
67110
67433
|
try {
|
|
67111
67434
|
versions = fs11.readdirSync(root);
|
|
67112
67435
|
} catch {
|
|
67113
67436
|
return [];
|
|
67114
67437
|
}
|
|
67115
|
-
return sortVersionNamesDesc(versions).map((version) =>
|
|
67438
|
+
return sortVersionNamesDesc(versions).map((version) => path20.join(root, version, "bin"));
|
|
67116
67439
|
}
|
|
67117
67440
|
function fnmVersionBinDirs(home) {
|
|
67118
67441
|
const roots = [
|
|
67119
|
-
|
|
67120
|
-
|
|
67442
|
+
path20.join(home, ".fnm", "node-versions"),
|
|
67443
|
+
path20.join(home, "Library", "Application Support", "fnm", "node-versions")
|
|
67121
67444
|
];
|
|
67122
67445
|
const dirs = [];
|
|
67123
67446
|
for (const root of roots) {
|
|
@@ -67127,7 +67450,7 @@ function fnmVersionBinDirs(home) {
|
|
|
67127
67450
|
} catch {
|
|
67128
67451
|
continue;
|
|
67129
67452
|
}
|
|
67130
|
-
dirs.push(...sortVersionNamesDesc(versions).map((version) =>
|
|
67453
|
+
dirs.push(...sortVersionNamesDesc(versions).map((version) => path20.join(root, version, "installation", "bin")));
|
|
67131
67454
|
}
|
|
67132
67455
|
return dirs;
|
|
67133
67456
|
}
|
|
@@ -67149,13 +67472,13 @@ function parseVersionName(value) {
|
|
|
67149
67472
|
return value.replace(/^v/i, "").split(".").map((part) => Number.parseInt(part, 10)).filter((part) => Number.isFinite(part));
|
|
67150
67473
|
}
|
|
67151
67474
|
function splitPath(value) {
|
|
67152
|
-
return value?.split(
|
|
67475
|
+
return value?.split(path20.delimiter).filter(Boolean) ?? [];
|
|
67153
67476
|
}
|
|
67154
67477
|
function mergePath(prependDirs, existing) {
|
|
67155
|
-
return unique([...prependDirs, ...splitPath(existing)]).join(
|
|
67478
|
+
return unique([...prependDirs, ...splitPath(existing)]).join(path20.delimiter);
|
|
67156
67479
|
}
|
|
67157
67480
|
function anchorResolvedPath(pathValue, resolution) {
|
|
67158
|
-
return mergePath([
|
|
67481
|
+
return mergePath([path20.dirname(resolution.binaryPath), ...splitPath(resolution.pathValue)], pathValue);
|
|
67159
67482
|
}
|
|
67160
67483
|
function commandCandidates(command, env, platform2 = process.platform) {
|
|
67161
67484
|
if (platform2 !== "win32")
|
|
@@ -67310,7 +67633,7 @@ var init_runtime_detector = __esm({
|
|
|
67310
67633
|
import { spawn as spawn5 } from "node:child_process";
|
|
67311
67634
|
import { createHash as createHash4 } from "node:crypto";
|
|
67312
67635
|
import * as fs12 from "node:fs";
|
|
67313
|
-
import * as
|
|
67636
|
+
import * as path21 from "node:path";
|
|
67314
67637
|
async function prepareWorkspace(opts) {
|
|
67315
67638
|
const prior = opts.attached.workspace_state;
|
|
67316
67639
|
const plan = buildWorkspacePlan(opts.attached.daemon_config, opts.defaultWorkspaceDir, prior?.config_hash);
|
|
@@ -67455,8 +67778,8 @@ async function ensureWorkspace(plan, log2) {
|
|
|
67455
67778
|
assertSafeCustomWorkspacePath(plan);
|
|
67456
67779
|
}
|
|
67457
67780
|
if (!fs12.existsSync(plan.workspaceDir)) {
|
|
67458
|
-
fs12.mkdirSync(
|
|
67459
|
-
assertWritableWorkspaceDir(
|
|
67781
|
+
fs12.mkdirSync(path21.dirname(plan.workspaceDir), { recursive: true });
|
|
67782
|
+
assertWritableWorkspaceDir(path21.dirname(plan.workspaceDir));
|
|
67460
67783
|
await runCommand("git", ["clone", remote, plan.workspaceDir], process.cwd());
|
|
67461
67784
|
} else {
|
|
67462
67785
|
const st = fs12.statSync(plan.workspaceDir);
|
|
@@ -67638,10 +67961,10 @@ ${tail}`)));
|
|
|
67638
67961
|
});
|
|
67639
67962
|
}
|
|
67640
67963
|
function requireAbsolute(value, field) {
|
|
67641
|
-
if (!value || !
|
|
67964
|
+
if (!value || !path21.isAbsolute(value)) {
|
|
67642
67965
|
throw new Error(`${field} must be an absolute path`);
|
|
67643
67966
|
}
|
|
67644
|
-
return
|
|
67967
|
+
return path21.resolve(value);
|
|
67645
67968
|
}
|
|
67646
67969
|
function assertSafeCustomWorkspacePath(plan, candidate = plan.workspaceDir) {
|
|
67647
67970
|
if (!plan.customWorkspaceField)
|
|
@@ -67651,14 +67974,14 @@ function assertSafeCustomWorkspacePath(plan, candidate = plan.workspaceDir) {
|
|
|
67651
67974
|
if (reason) {
|
|
67652
67975
|
throw new Error(`${plan.customWorkspaceField} must point to a project folder, not ${reason}: ${normalized}`);
|
|
67653
67976
|
}
|
|
67654
|
-
const defaultWorkspace =
|
|
67977
|
+
const defaultWorkspace = path21.resolve(plan.defaultWorkspaceDir);
|
|
67655
67978
|
if (isAncestorPath(normalized, defaultWorkspace) || normalized === defaultWorkspace) {
|
|
67656
67979
|
throw new Error(`${plan.customWorkspaceField} must not point at daemon state directories: ${normalized}`);
|
|
67657
67980
|
}
|
|
67658
67981
|
}
|
|
67659
67982
|
function assertWritableWorkspaceDir(dir) {
|
|
67660
67983
|
fs12.accessSync(dir, fs12.constants.R_OK | fs12.constants.W_OK | fs12.constants.X_OK);
|
|
67661
|
-
const probe =
|
|
67984
|
+
const probe = path21.join(dir, `.parall-workspace-check-${process.pid}-${Date.now()}`);
|
|
67662
67985
|
const fd = fs12.openSync(probe, "wx", 384);
|
|
67663
67986
|
fs12.closeSync(fd);
|
|
67664
67987
|
fs12.unlinkSync(probe);
|
|
@@ -67722,11 +68045,11 @@ function workspacePathDenyReason(value) {
|
|
|
67722
68045
|
return "";
|
|
67723
68046
|
}
|
|
67724
68047
|
function isAncestorPath(parent, child) {
|
|
67725
|
-
const relative2 =
|
|
67726
|
-
return relative2 !== "" && !relative2.startsWith("..") && !
|
|
68048
|
+
const relative2 = path21.relative(parent, child);
|
|
68049
|
+
return relative2 !== "" && !relative2.startsWith("..") && !path21.isAbsolute(relative2);
|
|
67727
68050
|
}
|
|
67728
68051
|
function toPolicyPath(value) {
|
|
67729
|
-
return
|
|
68052
|
+
return path21.resolve(value).split(path21.sep).join("/");
|
|
67730
68053
|
}
|
|
67731
68054
|
function isNodeError(err) {
|
|
67732
68055
|
return err instanceof Error && "code" in err;
|
|
@@ -67745,7 +68068,7 @@ var init_workspace = __esm({
|
|
|
67745
68068
|
import { spawn as spawn6 } from "node:child_process";
|
|
67746
68069
|
import * as fs13 from "node:fs";
|
|
67747
68070
|
import * as os7 from "node:os";
|
|
67748
|
-
import * as
|
|
68071
|
+
import * as path22 from "node:path";
|
|
67749
68072
|
function sleepCancellable(ms, signal) {
|
|
67750
68073
|
if (signal.aborted)
|
|
67751
68074
|
return Promise.resolve(false);
|
|
@@ -67906,7 +68229,7 @@ var init_supervisor = __esm({
|
|
|
67906
68229
|
this.migrateFlatLayout();
|
|
67907
68230
|
if (process.env.PRLL_CLIP_RUNTIME_ENABLED === "true") {
|
|
67908
68231
|
this.browserProfilePool = new BrowserProfilePool({
|
|
67909
|
-
baseHomeDir:
|
|
68232
|
+
baseHomeDir: path22.join(this.config.rootStateDir, "bb-browser"),
|
|
67910
68233
|
log: this.log,
|
|
67911
68234
|
reportStatus: (profileId, status, errorMsg, generation) => {
|
|
67912
68235
|
this.client.reportBrowserProfileStatus(profileId, status, errorMsg, generation).catch((err) => this.log.warn(`browser profile status report failed: ${String(err)}`));
|
|
@@ -67915,8 +68238,8 @@ var init_supervisor = __esm({
|
|
|
67915
68238
|
proxyProbeUrl: this.resolveBrowserProxyProbeUrl()
|
|
67916
68239
|
});
|
|
67917
68240
|
this.clipManager = new ClipProcessManager({
|
|
67918
|
-
clipsDir:
|
|
67919
|
-
dataDir:
|
|
68241
|
+
clipsDir: path22.join(this.config.rootStateDir, "clips"),
|
|
68242
|
+
dataDir: path22.join(this.config.rootStateDir, "clip-data"),
|
|
67920
68243
|
browserProfileManager: this.browserProfilePool,
|
|
67921
68244
|
// Execution side: nested browser dependency invokes resolve their
|
|
67922
68245
|
// binding and route through the hub (no local shortcut).
|
|
@@ -68268,12 +68591,12 @@ var init_supervisor = __esm({
|
|
|
68268
68591
|
*/
|
|
68269
68592
|
migrateFlatLayout() {
|
|
68270
68593
|
const root = this.config.rootStateDir;
|
|
68271
|
-
const agentsDir =
|
|
68272
|
-
const flatWorkspace =
|
|
68594
|
+
const agentsDir = path22.join(root, "agents");
|
|
68595
|
+
const flatWorkspace = path22.join(root, "workspace");
|
|
68273
68596
|
if (!fs13.existsSync(flatWorkspace) || fs13.existsSync(agentsDir))
|
|
68274
68597
|
return;
|
|
68275
68598
|
let ownerAgentId;
|
|
68276
|
-
const sessionsDir =
|
|
68599
|
+
const sessionsDir = path22.join(root, "sessions");
|
|
68277
68600
|
if (fs13.existsSync(sessionsDir)) {
|
|
68278
68601
|
try {
|
|
68279
68602
|
for (const file of fs13.readdirSync(sessionsDir)) {
|
|
@@ -68290,13 +68613,13 @@ var init_supervisor = __esm({
|
|
|
68290
68613
|
}
|
|
68291
68614
|
}
|
|
68292
68615
|
const targetId = ownerAgentId ?? "_orphan";
|
|
68293
|
-
const targetDir =
|
|
68616
|
+
const targetDir = path22.join(agentsDir, targetId);
|
|
68294
68617
|
try {
|
|
68295
68618
|
fs13.mkdirSync(targetDir, { recursive: true });
|
|
68296
68619
|
for (const sub of ["workspace", "sessions", "dispatch-context"]) {
|
|
68297
|
-
const src =
|
|
68620
|
+
const src = path22.join(root, sub);
|
|
68298
68621
|
if (fs13.existsSync(src)) {
|
|
68299
|
-
fs13.renameSync(src,
|
|
68622
|
+
fs13.renameSync(src, path22.join(targetDir, sub));
|
|
68300
68623
|
}
|
|
68301
68624
|
}
|
|
68302
68625
|
this.log.info(`migrated legacy flat state \u2192 agents/${targetId}/`);
|
|
@@ -68589,7 +68912,7 @@ var init_supervisor = __esm({
|
|
|
68589
68912
|
return this.runtimeDetectInFlight;
|
|
68590
68913
|
}
|
|
68591
68914
|
machineClipToConfig(clip) {
|
|
68592
|
-
const clipPath =
|
|
68915
|
+
const clipPath = path22.join(this.config.rootStateDir, "clips", clip.alias);
|
|
68593
68916
|
return {
|
|
68594
68917
|
clipId: clip.clip_id,
|
|
68595
68918
|
name: clip.alias,
|
|
@@ -68655,7 +68978,7 @@ var init_supervisor = __esm({
|
|
|
68655
68978
|
if (!sourceRef) {
|
|
68656
68979
|
throw new Error(`registry clip "${config.name}" is missing source_ref`);
|
|
68657
68980
|
}
|
|
68658
|
-
const expectedPath =
|
|
68981
|
+
const expectedPath = path22.join(this.config.rootStateDir, "clips", config.name);
|
|
68659
68982
|
const localVersion = this.readInstalledClipVersion(expectedPath);
|
|
68660
68983
|
if (localVersion && (!config.version || localVersion === config.version)) {
|
|
68661
68984
|
return { ...config, path: expectedPath, source: expectedPath };
|
|
@@ -68673,7 +68996,7 @@ var init_supervisor = __esm({
|
|
|
68673
68996
|
const result = await installClip({
|
|
68674
68997
|
source,
|
|
68675
68998
|
alias: config.name,
|
|
68676
|
-
clipsDir:
|
|
68999
|
+
clipsDir: path22.join(this.config.rootStateDir, "clips"),
|
|
68677
69000
|
registryUrl: process.env.PRLL_PINIX_REGISTRY_URL?.trim() || void 0
|
|
68678
69001
|
});
|
|
68679
69002
|
this.log.info(`clip ensured: ${result.alias} v${result.version} at ${result.path}`);
|
|
@@ -68688,7 +69011,7 @@ var init_supervisor = __esm({
|
|
|
68688
69011
|
readInstalledClipVersion(dir) {
|
|
68689
69012
|
for (const file of ["clip.json", "package.json"]) {
|
|
68690
69013
|
try {
|
|
68691
|
-
const raw = fs13.readFileSync(
|
|
69014
|
+
const raw = fs13.readFileSync(path22.join(dir, file), "utf-8");
|
|
68692
69015
|
const parsed = JSON.parse(raw);
|
|
68693
69016
|
if (typeof parsed.version === "string" && parsed.version.trim()) {
|
|
68694
69017
|
return parsed.version.trim();
|
|
@@ -69323,7 +69646,11 @@ async function runForever(config, client, log2, signal, updater, gate) {
|
|
|
69323
69646
|
async function main(bootstrap2) {
|
|
69324
69647
|
configureHttpKeepAlive();
|
|
69325
69648
|
const config = resolveClaudeDaemonConfig(process.env);
|
|
69326
|
-
const telemetry = await initAgentTelemetry("parall-daemon", "daemon"
|
|
69649
|
+
const telemetry = await initAgentTelemetry("parall-daemon", "daemon", {
|
|
69650
|
+
apiUrl: config.apiUrl,
|
|
69651
|
+
apiKey: config.apiKey,
|
|
69652
|
+
serviceVersion: resolveServiceVersion(import.meta.url)
|
|
69653
|
+
});
|
|
69327
69654
|
log = createOtelLogger("daemon", "daemon");
|
|
69328
69655
|
log.info(`boot: api=${config.apiUrl} pollMs=${config.pollIntervalMs} heartbeatMs=${config.heartbeatIntervalMs} agentBin=${config.agentBin}`);
|
|
69329
69656
|
log.info(`keepalive: bootstrapBackoffMs=${config.bootstrapBackoffMs} supervisorRestartBackoffMs=${config.supervisorRestartBackoffMs}`);
|
|
@@ -69412,7 +69739,7 @@ var init_daemon_main = __esm({
|
|
|
69412
69739
|
init_daemon_paths();
|
|
69413
69740
|
init_daemon_update_mode();
|
|
69414
69741
|
import * as fs14 from "node:fs";
|
|
69415
|
-
import * as
|
|
69742
|
+
import * as path23 from "node:path";
|
|
69416
69743
|
var UPDATE_EXIT_CODE2 = 42;
|
|
69417
69744
|
function formatError2(reason) {
|
|
69418
69745
|
if (reason instanceof Error) {
|
|
@@ -69437,7 +69764,7 @@ function clearRunningMarker(markerPath) {
|
|
|
69437
69764
|
}
|
|
69438
69765
|
function prepareDaemonBootstrap(env = process.env, args = process.argv.slice(2)) {
|
|
69439
69766
|
const bundleDir = resolveBundleDir(env);
|
|
69440
|
-
const runningMarker =
|
|
69767
|
+
const runningMarker = path23.join(bundleDir, "daemon-running");
|
|
69441
69768
|
const lifecycleMarkerEnabled = args.length === 0 && !isSelfUpdateDisabledByEnv(env) && isSelfUpdateManaged(bundleDir, env);
|
|
69442
69769
|
if (!lifecycleMarkerEnabled) {
|
|
69443
69770
|
return { lifecycleMarkerEnabled: false, runningMarker, uncleanPrevExit: false };
|