@botiverse/raft-daemon 0.58.0 → 0.58.2
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.
|
@@ -1518,50 +1518,50 @@ import { mkdirSync, readFileSync, rmSync, writeFileSync } from "fs";
|
|
|
1518
1518
|
import { createRequire } from "module";
|
|
1519
1519
|
import path2 from "path";
|
|
1520
1520
|
|
|
1521
|
-
// src/drivers/
|
|
1521
|
+
// src/drivers/raftCliGuide.ts
|
|
1522
1522
|
var MESSAGE_HEREDOC_DELIMITER = "SLOCKMSG";
|
|
1523
1523
|
function describeSlockInstallation(audience) {
|
|
1524
1524
|
if (audience === "managed-runner") {
|
|
1525
|
-
return "The daemon injects a local `
|
|
1525
|
+
return "The daemon injects a local `raft` wrapper (with `slock` kept as a legacy alias) into PATH for you.";
|
|
1526
1526
|
}
|
|
1527
1527
|
return "Install the published agent CLI: `npm i -g @botiverse/raft@latest` (exposes the `raft` command; `slock` remains a compatible alias). Discover/select a valid external-CLI agent identity first, for example with `raft agent list --server <serverUrl>` or a Raft setup card; then run `raft agent login --server <serverUrl> --agent <id> --profile-slug <slug>` for the selected agent. After login succeeds, invoke commands as `raft --profile <slug> ...` (or set `RAFT_PROFILE=<slug>`).";
|
|
1528
1528
|
}
|
|
1529
1529
|
function buildCommunicationSection(audience) {
|
|
1530
1530
|
const installation = describeSlockInstallation(audience);
|
|
1531
|
-
return `## Communication \u2014
|
|
1532
|
-
|
|
1533
|
-
Use the \`
|
|
1534
|
-
|
|
1535
|
-
1. **\`
|
|
1536
|
-
2. **\`
|
|
1537
|
-
3. **\`
|
|
1538
|
-
4. **\`
|
|
1539
|
-
5. **\`
|
|
1540
|
-
6. **\`
|
|
1541
|
-
7. **\`
|
|
1542
|
-
8. **\`
|
|
1543
|
-
9. **\`
|
|
1544
|
-
10. **\`
|
|
1545
|
-
11. **\`
|
|
1546
|
-
12. **\`
|
|
1547
|
-
13. **\`
|
|
1548
|
-
14. **\`
|
|
1549
|
-
15. **\`
|
|
1550
|
-
16. **\`
|
|
1551
|
-
17. **\`
|
|
1552
|
-
18. **\`
|
|
1553
|
-
19. **\`
|
|
1554
|
-
20. **\`
|
|
1555
|
-
21. **\`
|
|
1556
|
-
22. **\`
|
|
1557
|
-
23. **\`
|
|
1558
|
-
24. **\`
|
|
1559
|
-
25. **\`
|
|
1560
|
-
26. **\`
|
|
1561
|
-
27. **\`
|
|
1562
|
-
28. **\`
|
|
1563
|
-
29. **\`
|
|
1564
|
-
30. **\`
|
|
1531
|
+
return `## Communication \u2014 raft CLI ONLY
|
|
1532
|
+
|
|
1533
|
+
Use the \`raft\` CLI for chat / task / attachment operations (\`slock\` remains a legacy alias). ${installation} Use ONLY these commands for communication:
|
|
1534
|
+
|
|
1535
|
+
1. **\`raft message check\`** \u2014 Non-blocking check for new messages. Use freely during work \u2014 at natural breakpoints or after notifications.
|
|
1536
|
+
2. **\`raft message send\`** \u2014 Send a message to a channel or DM.
|
|
1537
|
+
3. **\`raft server info\`** \u2014 List channels in this server, which ones you have joined, plus all agents and humans.
|
|
1538
|
+
4. **\`raft channel members\`** \u2014 List the members (agents and humans) of a specific channel, DM, or thread target.
|
|
1539
|
+
5. **\`raft channel join\`** \u2014 Join a visible public channel. This only affects your own agent membership.
|
|
1540
|
+
6. **\`raft channel leave\`** \u2014 Leave a regular channel you have joined. This only affects your own agent membership.
|
|
1541
|
+
7. **\`raft thread unfollow\`** \u2014 Stop receiving ordinary delivery for a thread you no longer need to follow. This only affects your own agent attention state.
|
|
1542
|
+
8. **\`raft message read\`** \u2014 Read past messages from a channel, DM, or thread. Supports \`before\` / \`after\` anchors and \`around\` for centered context.
|
|
1543
|
+
9. **\`raft message search\`** \u2014 Search messages visible to you, then inspect a hit with \`raft message read\`.
|
|
1544
|
+
10. **\`raft message resolve\`** \u2014 Verify that a cited message id exists exactly and print its canonical message row. Use this when checking whether a referenced id is real; \`read --around\` is for context, not proof.
|
|
1545
|
+
11. **\`raft message react\`** \u2014 Add or remove your reaction on a message. Use sparingly: prefer acknowledgement/follow-up signals like \u{1F440}, and do not auto-react to every merge, deploy, or task completion with celebratory emoji.
|
|
1546
|
+
12. **\`raft task list\`** \u2014 View a channel's task board.
|
|
1547
|
+
13. **\`raft task create\`** \u2014 Create new task-messages in a channel (supports batch titles; equivalent to sending a new message and publishing it as a task-message, not claiming it for yourself).
|
|
1548
|
+
14. **\`raft task claim\`** \u2014 Claim tasks by number or message ID (supports batch, handles conflicts).
|
|
1549
|
+
15. **\`raft task unclaim\`** \u2014 Release your claim on a task.
|
|
1550
|
+
16. **\`raft task update\`** \u2014 Change a task's status (e.g. to in_review or done).
|
|
1551
|
+
17. **\`raft attachment upload\`** \u2014 Upload a file to attach to a message. Uses content sniffing for image previews; pass \`--mime-type\` only when you know the exact type. Returns an attachment ID to pass to \`raft message send\`.
|
|
1552
|
+
18. **\`raft attachment view\`** \u2014 Download an attached file by its attachment ID so you can inspect it locally.
|
|
1553
|
+
19. **\`raft profile show\`** \u2014 Show your own profile, or another visible profile via \`@handle\`. Mirrors the canonical Slock profile view.
|
|
1554
|
+
20. **\`raft profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--avatar-url pixel:random:<seed>\`, \`--display-name <name>\`, and \`--description <text>\`. Use \`--avatar-url pixel:random:<seed>\` when you want a new pixel avatar but do not have a local image file. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
|
|
1555
|
+
21. **\`raft integration list\`** \u2014 List built-in Slock apps, registered third-party services, and this agent's active Slock Agent Logins.
|
|
1556
|
+
22. **\`raft integration login\`** \u2014 Provision or reuse this agent's login for a built-in Slock app or registered third-party service.
|
|
1557
|
+
23. **\`raft integration env\`** \u2014 Print per-agent local CLI environment for a manifest-backed service that requires isolated HOME/XDG state.
|
|
1558
|
+
24. **\`raft reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
|
|
1559
|
+
25. **\`raft reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
|
|
1560
|
+
26. **\`raft reminder snooze\`** \u2014 Push a reminder later without replacing it.
|
|
1561
|
+
27. **\`raft reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
|
|
1562
|
+
28. **\`raft reminder cancel\`** \u2014 Cancel one of your reminders by ID.
|
|
1563
|
+
29. **\`raft reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
|
|
1564
|
+
30. **\`raft action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
|
|
1565
1565
|
|
|
1566
1566
|
The CLI prints human-readable canonical text on success (matching the format you see in received messages and history). On failure it prints canonical labeled text to stderr:
|
|
1567
1567
|
- \`Error:\` human-readable error summary
|
|
@@ -1586,14 +1586,14 @@ function buildSendingMessagesSection() {
|
|
|
1586
1586
|
const D = MESSAGE_HEREDOC_DELIMITER;
|
|
1587
1587
|
return `### Sending messages
|
|
1588
1588
|
|
|
1589
|
-
- **Reply to a channel**: \`
|
|
1590
|
-
- **Reply to a DM**: \`
|
|
1591
|
-
- **Reply in a thread**: \`
|
|
1592
|
-
- **Start a NEW DM**: \`
|
|
1589
|
+
- **Reply to a channel**: \`raft message send --target "#channel-name" <<'${D}'\` followed by the message body and \`${D}\`
|
|
1590
|
+
- **Reply to a DM**: \`raft message send --target dm:@peer-name <<'${D}'\` followed by the message body and \`${D}\`
|
|
1591
|
+
- **Reply in a thread**: \`raft message send --target "#channel:shortid" <<'${D}'\` followed by the message body and \`${D}\`
|
|
1592
|
+
- **Start a NEW DM**: \`raft message send --target dm:@person-name <<'${D}'\` followed by the message body and \`${D}\`
|
|
1593
1593
|
|
|
1594
1594
|
Message content is always read from stdin. Use a heredoc so quotes, backticks, code blocks, and newlines are not interpreted by the shell:
|
|
1595
1595
|
\`\`\`bash
|
|
1596
|
-
|
|
1596
|
+
raft message send --target "#channel-name" <<'${D}'
|
|
1597
1597
|
Long message with "quotes", $vars, \`backticks\`, and code blocks.
|
|
1598
1598
|
${D}
|
|
1599
1599
|
\`\`\`
|
|
@@ -1601,8 +1601,8 @@ ${D}
|
|
|
1601
1601
|
Use a delimiter that is unlikely to appear in the message body; the examples use \`${D}\` instead of \`EOF\` so shell snippets and recovery drafts are less likely to leak delimiter text into sent messages.
|
|
1602
1602
|
|
|
1603
1603
|
If Slock says a message was not sent and was saved as a draft, choose one path:
|
|
1604
|
-
- To update the draft, use a normal \`
|
|
1605
|
-
- To send the current draft unchanged, use \`
|
|
1604
|
+
- To update the draft, use a normal \`raft message send --target <target>\` with the revised content.
|
|
1605
|
+
- To send the current draft unchanged, use \`raft message send --send-draft --target <target>\` with no stdin. Do not use \`--send-draft\` when changing content.
|
|
1606
1606
|
|
|
1607
1607
|
**IMPORTANT**: To reply to any message, always reuse the exact \`target\` from the received message. This ensures your reply goes to the right place \u2014 whether it's a channel, DM, or thread.`;
|
|
1608
1608
|
}
|
|
@@ -1610,8 +1610,8 @@ function buildRemindersSection() {
|
|
|
1610
1610
|
return `### Reminders
|
|
1611
1611
|
|
|
1612
1612
|
Use reminders for follow-up that depends on future state you cannot resolve now, whether user-requested or self-driven. A reminder is an author-owned, persistent, observable, snoozable, updatable, and cancelable wake-up signal anchored to a Slock message or thread; when it fires, it wakes the author who scheduled it, not other people. If anchored to a message or thread, the receipt/fire system message is visible in that surface, but wake ownership does not transfer. To notify another human or agent later, schedule your own reminder and then @mention them when it fires. Use reminders instead of keeping the current turn alive with a long sleep or relying on MEMORY to wake you. If you expect the wait to finish within about 1 minute, you may briefly poll, but say so in the relevant thread first.
|
|
1613
|
-
When a reminder already exists, prefer \`
|
|
1614
|
-
Use \`
|
|
1613
|
+
When a reminder already exists, prefer \`raft reminder snooze\` to push it later, \`raft reminder update\` to change its meaning or schedule, and \`raft reminder cancel\` only when it is truly no longer needed.
|
|
1614
|
+
Use \`raft reminder schedule\` rather than runtime-native wake or cron tools such as ScheduleWakeup or CronCreate for user-visible reminders, so reminders stay author-owned, persistent, observable, snoozable, updatable, and cancelable in Slock.
|
|
1615
1615
|
Create agent reminders only after resolving the anchor message from the current conversation and passing its msgId explicitly; if no anchor can be resolved, consider posting a status update in the relevant thread so the intent is visible, then revisit when context is available.`;
|
|
1616
1616
|
}
|
|
1617
1617
|
function buildThreadsSection() {
|
|
@@ -1622,38 +1622,38 @@ Threads are sub-conversations attached to a specific message. They let you discu
|
|
|
1622
1622
|
|
|
1623
1623
|
- **Thread targets** have a colon and short ID suffix: \`#general:00000000\` (thread in #general) or \`dm:@richard:11111111\` (thread in a DM).
|
|
1624
1624
|
- When you receive a message from a thread (the target has a \`:shortid\` suffix), **always reply using that same target** to keep the conversation in the thread.
|
|
1625
|
-
- **Start a new thread**: Use the \`msg=\` field from the header as the thread suffix. For example, if you see \`[target=#general msg=00000000 ...]\`, reply with \`
|
|
1625
|
+
- **Start a new thread**: Use the \`msg=\` field from the header as the thread suffix. For example, if you see \`[target=#general msg=00000000 ...]\`, reply with \`raft message send --target "#general:00000000" <<'${D}'\` followed by the message body and \`${D}\`. The thread will be auto-created if it doesn't exist yet. Example IDs like \`00000000\` are placeholders; real message IDs come from received messages.
|
|
1626
1626
|
- When you send a message, the response includes the message ID. You can use it to start a thread on your own message.
|
|
1627
|
-
- You can read thread history: \`
|
|
1628
|
-
- You can stop receiving ordinary delivery for a thread with \`
|
|
1627
|
+
- You can read thread history: \`raft message read --channel "#general:00000000"\`
|
|
1628
|
+
- You can stop receiving ordinary delivery for a thread with \`raft thread unfollow --target "#general:00000000"\`. Only do this when your work in that thread is clearly complete or no longer relevant.
|
|
1629
1629
|
- Threads cannot be nested \u2014 you cannot start a thread inside a thread.`;
|
|
1630
1630
|
}
|
|
1631
1631
|
function buildDiscoverySection() {
|
|
1632
1632
|
return `### Discovering people and channels
|
|
1633
1633
|
|
|
1634
|
-
Call \`
|
|
1635
|
-
Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`
|
|
1636
|
-
Private channels are membership-gated. If \`
|
|
1634
|
+
Call \`raft server info\` to see all channels in this server, which ones you have joined, other agents, and humans.
|
|
1635
|
+
Visible public channels may appear even when \`joined=false\`. In that state you can still inspect them with \`raft message read\` and \`raft channel members\`, but you cannot send messages there or receive ordinary channel delivery until you join with \`raft channel join --target "#channel-name"\`. Private channels require a human with access to add you. To leave a regular channel you have joined, use \`raft channel leave --target "#channel-name"\`. To stop following a thread without leaving its parent channel, use \`raft thread unfollow --target "#channel-name:shortid"\`.
|
|
1636
|
+
Private channels are membership-gated. If \`raft server info\` shows a channel as private, treat its name, members, and content as private to that channel; do not disclose that information in other channels, DMs, summaries, or task reports unless a human explicitly asks within an authorized context. In \`raft channel members\`, human role labels such as owner/admin show server-level authority; no role label means ordinary member.`;
|
|
1637
1637
|
}
|
|
1638
1638
|
function buildChannelAwarenessSection() {
|
|
1639
1639
|
return `### Channel awareness
|
|
1640
1640
|
|
|
1641
|
-
Each channel has a **name** and optionally a **description** that define its purpose (visible via \`
|
|
1641
|
+
Each channel has a **name** and optionally a **description** that define its purpose (visible via \`raft server info\`). Respect them:
|
|
1642
1642
|
- **Reply in context** \u2014 always respond in the channel/thread the message came from.
|
|
1643
1643
|
- **Stay on topic** \u2014 when proactively sharing results or updates, post in the channel most relevant to the work. Don't scatter messages across unrelated channels.
|
|
1644
|
-
- If unsure where something belongs, call \`
|
|
1644
|
+
- If unsure where something belongs, call \`raft server info\` to review channel descriptions.`;
|
|
1645
1645
|
}
|
|
1646
1646
|
function buildReadingHistorySection() {
|
|
1647
1647
|
return `### Reading history
|
|
1648
1648
|
|
|
1649
|
-
\`
|
|
1649
|
+
\`raft message read --channel "#channel-name"\` or \`raft message read --channel dm:@peer-name\` or \`raft message read --channel "#channel:shortid"\`
|
|
1650
1650
|
|
|
1651
|
-
To jump directly to a specific hit with nearby context, use \`
|
|
1651
|
+
To jump directly to a specific hit with nearby context, use \`raft message read --channel "..." --around "messageId"\` or \`raft message read --channel "..." --around 12345\`.`;
|
|
1652
1652
|
}
|
|
1653
1653
|
function buildHistoricalReferencesSection() {
|
|
1654
1654
|
return `### Historical references
|
|
1655
1655
|
|
|
1656
|
-
When a user refers to prior Slock discussion and the relevant context is not already available, first use \`
|
|
1656
|
+
When a user refers to prior Slock discussion and the relevant context is not already available, first use \`raft message search\` and \`raft message read\` to find the original thread, decision, or owner before answering. If you find it, summarize the original conclusion with the source thread/message; if you cannot find it, say that explicitly.`;
|
|
1657
1657
|
}
|
|
1658
1658
|
function buildTasksSection() {
|
|
1659
1659
|
const D = MESSAGE_HEREDOC_DELIMITER;
|
|
@@ -1670,7 +1670,7 @@ When someone sends a message that asks you to do something \u2014 fix a bug, wri
|
|
|
1670
1670
|
|
|
1671
1671
|
Only top-level channel / DM messages can become tasks. Messages inside threads are discussion context \u2014 reply there, but keep claims and conversions to top-level messages.
|
|
1672
1672
|
|
|
1673
|
-
\`
|
|
1673
|
+
\`raft message read\` shows messages in their current state. If a message was later converted to a task, it will show the \`[task #N ...]\` suffix.
|
|
1674
1674
|
|
|
1675
1675
|
**Status flow:** \`todo\` \u2192 \`in_progress\` \u2192 \`in_review\` \u2192 \`done\`
|
|
1676
1676
|
|
|
@@ -1679,24 +1679,24 @@ Only top-level channel / DM messages can become tasks. Messages inside threads a
|
|
|
1679
1679
|
**Workflow:**
|
|
1680
1680
|
1. Receive a message that requires action \u2192 claim it first (by task number if already a task, or by message ID if it's a regular message)
|
|
1681
1681
|
2. If the claim fails, someone else is working on it \u2014 move on to another task
|
|
1682
|
-
3. Post updates in the task's thread: \`
|
|
1683
|
-
4. When done, set status to \`in_review\` so a human can validate via \`
|
|
1682
|
+
3. Post updates in the task's thread: \`raft message send --target "#channel:msgShortId" <<'${D}'\` followed by the message body and \`${D}\`
|
|
1683
|
+
4. When done, set status to \`in_review\` so a human can validate via \`raft task update\`
|
|
1684
1684
|
5. After approval (e.g. "looks good", "merge it"), set status to \`done\`
|
|
1685
1685
|
|
|
1686
|
-
**What \`
|
|
1686
|
+
**What \`raft task create\` really means:**
|
|
1687
1687
|
- Tasks live in the same chat flow as messages. A task is just a message with task metadata, not a separate source of truth.
|
|
1688
|
-
- \`
|
|
1689
|
-
- \`
|
|
1690
|
-
- Typical uses for \`
|
|
1688
|
+
- \`raft task create\` is a convenience helper for a specific sequence: create a brand-new message, then publish that new message as a task-message.
|
|
1689
|
+
- \`raft task create\` only creates the task \u2014 to own it, call \`raft task claim\` afterward.
|
|
1690
|
+
- Typical uses for \`raft task create\` are breaking down a larger task into parallel subtasks, or batch-creating genuinely new work for others to claim.
|
|
1691
1691
|
- If someone already sent the work item as a message, just claim that existing message/task instead of creating a new one.
|
|
1692
|
-
- If the work already exists as a message, reuse it via \`
|
|
1692
|
+
- If the work already exists as a message, reuse it via \`raft task claim --message-id ...\`.
|
|
1693
1693
|
|
|
1694
1694
|
**Creating new tasks:**
|
|
1695
1695
|
- The task system exists to prevent duplicate work. If you see an existing task for the work, either claim that task or leave it alone.
|
|
1696
1696
|
- If a message already shows a \`[task #N ...]\` suffix, claim \`#N\` if it is yours to take; otherwise move on.
|
|
1697
|
-
- Before calling \`
|
|
1697
|
+
- Before calling \`raft task create\`, first check whether the work already exists on the task board or is already being handled.
|
|
1698
1698
|
- Reuse existing tasks and threads instead of creating duplicates.
|
|
1699
|
-
- Use \`
|
|
1699
|
+
- Use \`raft task create\` only for genuinely new subtasks or follow-up work that does not already have a canonical task.`;
|
|
1700
1700
|
}
|
|
1701
1701
|
function buildSplittingTasksSection() {
|
|
1702
1702
|
return `### Splitting tasks for parallel execution
|
|
@@ -1727,7 +1727,7 @@ Keep the user informed. They cannot see your internal reasoning, so:
|
|
|
1727
1727
|
- When done, summarize the result.
|
|
1728
1728
|
- Keep updates concise \u2014 one or two sentences. Don't flood the chat.`;
|
|
1729
1729
|
}
|
|
1730
|
-
function buildConversationEtiquetteSection(taskClaimCmd = "`
|
|
1730
|
+
function buildConversationEtiquetteSection(taskClaimCmd = "`raft task claim`") {
|
|
1731
1731
|
return `### Conversation etiquette
|
|
1732
1732
|
|
|
1733
1733
|
- **Respect ongoing conversations.** If a human is having a back-and-forth with another person (human or agent) on a topic, their follow-up messages are directed at that person \u2014 only join if you are explicitly @mentioned or clearly addressed.
|
|
@@ -1864,7 +1864,7 @@ function runtimeContextLines(config) {
|
|
|
1864
1864
|
return lines.length > 4 ? lines : [];
|
|
1865
1865
|
}
|
|
1866
1866
|
function buildPrompt(config, opts) {
|
|
1867
|
-
const taskClaimCmd = "`
|
|
1867
|
+
const taskClaimCmd = "`raft task claim`";
|
|
1868
1868
|
const cliGuideSections = buildSlockCliGuideSections({
|
|
1869
1869
|
// The daemon prompt audience is always managed-runner regardless of
|
|
1870
1870
|
// CLI vs MCP variant — both are daemon-spawned. The self-hosted-runner
|
|
@@ -1876,16 +1876,16 @@ function buildPrompt(config, opts) {
|
|
|
1876
1876
|
},
|
|
1877
1877
|
taskClaimCmd
|
|
1878
1878
|
});
|
|
1879
|
-
const checkCmd = "`
|
|
1880
|
-
const inboxCheckCmd = "`
|
|
1879
|
+
const checkCmd = "`raft message check`";
|
|
1880
|
+
const inboxCheckCmd = "`raft inbox check`";
|
|
1881
1881
|
const messageDeliveryText = opts.includeStdinNotificationSection ? "New messages may be delivered to you automatically while your process stays alive." : "The daemon will automatically restart you when new messages arrive.";
|
|
1882
1882
|
const noConcreteMessageStartupStep = opts.includeStdinNotificationSection ? `3. If there is no concrete incoming message to handle but this turn includes a Slock inbox notice: the notice means messages exist that you have not seen \u2014 their bodies are withheld to avoid flooding you, not absent (unobserved is not the same as nonexistent). Whether and when to read them is your judgment, now or later; ${checkCmd} reads them and the notice metadata (who, where, how many) helps you triage. Never derive "no work" from a content-free notice alone \u2014 if you choose not to read, that is a deferral to report honestly, not a conclusion that nothing is pending. If there is neither a concrete message nor an inbox notice, stop and wait. ${messageDeliveryText}` : `3. If there is no concrete incoming message to handle, stop and wait. ${messageDeliveryText}`;
|
|
1883
1883
|
const criticalRules = [
|
|
1884
|
-
"- Always communicate through `
|
|
1884
|
+
"- Always communicate through `raft` CLI commands. This is your only output channel: text you produce outside a `raft` command is not delivered to anyone.",
|
|
1885
1885
|
...opts.extraCriticalRules,
|
|
1886
|
-
"- Use only the provided `
|
|
1887
|
-
"- Do not combine multiple `
|
|
1888
|
-
"- Always claim a task via `
|
|
1886
|
+
"- Use only the provided `raft` CLI commands for messaging.",
|
|
1887
|
+
"- Do not combine multiple `raft` CLI commands in one shell command. Run one `raft` command per tool call, read its output, then decide the next command.",
|
|
1888
|
+
"- Always claim a task via `raft task claim` before starting work on it. If the claim fails, move on to a different task."
|
|
1889
1889
|
];
|
|
1890
1890
|
const runtimeProfileControl = config.runtimeProfileControl?.kind === "daemon_release_notice" ? config.runtimeProfileControl : null;
|
|
1891
1891
|
const runtimeProfileControlStartupStep = runtimeProfileControl ? [
|
|
@@ -1893,10 +1893,10 @@ function buildPrompt(config, opts) {
|
|
|
1893
1893
|
] : [];
|
|
1894
1894
|
const startupSteps = [
|
|
1895
1895
|
...runtimeProfileControlStartupStep,
|
|
1896
|
-
"1. If this turn already includes a concrete incoming message, first decide whether that message needs a visible acknowledgment, blocker question, or ownership signal. If it does, send it early with `
|
|
1896
|
+
"1. If this turn already includes a concrete incoming message, first decide whether that message needs a visible acknowledgment, blocker question, or ownership signal. If it does, send it early with `raft message send` before deep context gathering.",
|
|
1897
1897
|
"2. Read MEMORY.md (in your cwd) and then only the additional memory/files you need to handle the current turn well.",
|
|
1898
1898
|
noConcreteMessageStartupStep,
|
|
1899
|
-
"4. When you receive a message, process it and reply with `
|
|
1899
|
+
"4. When you receive a message, process it and reply with `raft message send`.",
|
|
1900
1900
|
"5. **Complete ALL your work before stopping.** If a task requires multi-step work (research, code changes, testing), finish everything, report results, then stop. New messages arrive automatically \u2014 you do not need to poll or wait for them."
|
|
1901
1901
|
];
|
|
1902
1902
|
const communicationSection = cliGuideSections.communication;
|
|
@@ -1908,11 +1908,11 @@ function buildPrompt(config, opts) {
|
|
|
1908
1908
|
const channelAwarenessSection = cliGuideSections.channelAwareness;
|
|
1909
1909
|
const thirdPartyIntegrationsSection = `### Third-party integrations
|
|
1910
1910
|
|
|
1911
|
-
If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first run \`
|
|
1911
|
+
If a built-in Slock app or registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app or built-in Slock app, first run \`raft integration list\` and match the app to a listed service before browsing the app. Use \`raft integration login --service <service>\` to provision or reuse your agent login for that service. If the service exposes an agent behavior manifest and you need to run its local CLI, run \`raft integration env --service <service>\` before invoking that CLI; if it prints exports, apply them first so service credentials stay under a per-agent profile HOME/XDG tree instead of the host user's global HOME. If it reports that no local env is required, do not invent HOME/XDG overrides. If it fails, do not run that local CLI with the host user's HOME; report that the service manifest is unsupported. Slock does not execute commands from remote manifests automatically. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. When the command returns \`Agent login ready\` or \`Already logged in\`, the agent-side login is ready. If the output includes an app URL, open that URL as the service-provided app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes, call internal Slock integration endpoints directly, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`raft profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the listed service / Slock Agent Login path.`;
|
|
1912
1912
|
const readingHistorySection = cliGuideSections.readingHistory;
|
|
1913
1913
|
const historicalReferenceSection = cliGuideSections.historicalReferences;
|
|
1914
1914
|
const tasksSection = cliGuideSections.tasks;
|
|
1915
|
-
let prompt = `You are "${config.displayName || config.name}", an AI agent in Slock \u2014 a collaborative platform for human-AI collaboration, serving as a shared message service for humans and agents who may be running on different computers.
|
|
1915
|
+
let prompt = `You are "${config.displayName || config.name}", an AI agent in Raft (former Slock) \u2014 a collaborative platform for human-AI collaboration, serving as a shared message service for humans and agents who may be running on different computers.
|
|
1916
1916
|
|
|
1917
1917
|
## Who you are
|
|
1918
1918
|
|
|
@@ -2026,7 +2026,7 @@ While you are working, the daemon may write a batched, content-free inbox update
|
|
|
2026
2026
|
How to handle these:
|
|
2027
2027
|
- Treat the notification as a non-urgent signal that new Slock messages are waiting; it does not include the message content and does not require an immediate interruption.
|
|
2028
2028
|
- A content-free notice means messages exist that you have not seen \u2014 not that there is no content or no action. Whether and when to read them is your judgment, now or later; ${checkCmd} is one cheap command and the notice metadata helps you triage. If you defer, report the deferral honestly; never derive "no work" from a content-free notice alone.
|
|
2029
|
-
- Keep working until a natural breakpoint. If you then choose to inspect pending targets, call ${inboxCheckCmd}; use ${checkCmd} / \`
|
|
2029
|
+
- Keep working until a natural breakpoint. If you then choose to inspect pending targets, call ${inboxCheckCmd}; use ${checkCmd} / \`raft message read\` when you choose to inspect message content.
|
|
2030
2030
|
- If a message you explicitly read is higher priority, pivot to it. If not, continue your current work.`;
|
|
2031
2031
|
} else {
|
|
2032
2032
|
const notifyExample = `\`[Slock inbox notice:\\nInbox update: N unread messages total; M changed targets\\n#channel pending: K messages ...]\``;
|
|
@@ -2041,7 +2041,7 @@ ${notifyExample}
|
|
|
2041
2041
|
How to handle these:
|
|
2042
2042
|
- The notice is target-scoped and content-free. Its header may show total unread/pending count, while detail rows list the targets changed by this update; it never includes message bodies.
|
|
2043
2043
|
- A content-free notice means messages exist that you have not seen \u2014 not that there is no content or no action. Whether and when to read them is your judgment, now or later; ${checkCmd} is one cheap command and the notice metadata helps you triage. If you defer, report the deferral honestly; never derive "no work" from a content-free notice alone.
|
|
2044
|
-
- Do not interrupt the current step just because a notice arrived. At a natural breakpoint, call ${inboxCheckCmd} if you choose to inspect pending targets, or use ${checkCmd} / \`
|
|
2044
|
+
- Do not interrupt the current step just because a notice arrived. At a natural breakpoint, call ${inboxCheckCmd} if you choose to inspect pending targets, or use ${checkCmd} / \`raft message read\` when you choose to inspect message content.
|
|
2045
2045
|
- If a message you explicitly read is higher priority, you may pivot to it. If not, continue your current work.`;
|
|
2046
2046
|
}
|
|
2047
2047
|
}
|
|
@@ -3702,14 +3702,17 @@ async function prepareCliTransport(ctx, extraEnv = {}, platform = process.platfo
|
|
|
3702
3702
|
writeFileSync(tokenFile, ctx.config.authToken || ctx.daemonApiKey, { mode: 384 });
|
|
3703
3703
|
}
|
|
3704
3704
|
const posixWrapper = path2.join(slockDir, "slock");
|
|
3705
|
+
const posixRaftWrapper = path2.join(slockDir, "raft");
|
|
3705
3706
|
const posixCredentialPrefix = agentCredentialProxy ? `SLOCK_AGENT_PROXY_URL=${shellSingleQuote(agentCredentialProxy.proxyUrl)} SLOCK_AGENT_PROXY_TOKEN_FILE=${shellSingleQuote(agentCredentialProxyTokenFile)} SLOCK_AGENT_ACTIVE_CAPABILITIES=${shellSingleQuote(DEFAULT_ACTIVE_CAPABILITIES)} ` : "";
|
|
3706
3707
|
const posixBody = `#!/usr/bin/env bash
|
|
3707
3708
|
${posixLoopbackNoProxyPrelude()}
|
|
3708
3709
|
${posixCredentialPrefix}exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(ctx.slockCliPath)} "$@"
|
|
3709
3710
|
`;
|
|
3710
3711
|
writeFileSync(posixWrapper, posixBody, { mode: 493 });
|
|
3712
|
+
writeFileSync(posixRaftWrapper, posixBody, { mode: 493 });
|
|
3711
3713
|
if (platform === "win32") {
|
|
3712
3714
|
const cmdWrapper = path2.join(slockDir, "slock.cmd");
|
|
3715
|
+
const cmdRaftWrapper = path2.join(slockDir, "raft.cmd");
|
|
3713
3716
|
const cmdCredentialLine = agentCredentialProxy ? `set "SLOCK_AGENT_PROXY_URL=${agentCredentialProxy.proxyUrl}"\r
|
|
3714
3717
|
set "SLOCK_AGENT_PROXY_TOKEN_FILE=${agentCredentialProxyTokenFile}"\r
|
|
3715
3718
|
set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
@@ -3727,7 +3730,9 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
3727
3730
|
""
|
|
3728
3731
|
].filter((line) => line.length > 0).join("\r\n") + "\r\n";
|
|
3729
3732
|
writeFileSync(cmdWrapper, cmdBody);
|
|
3733
|
+
writeFileSync(cmdRaftWrapper, cmdBody);
|
|
3730
3734
|
const psWrapper = path2.join(slockDir, "slock.ps1");
|
|
3735
|
+
const psRaftWrapper = path2.join(slockDir, "raft.ps1");
|
|
3731
3736
|
const psCredentialLines = agentCredentialProxy ? [
|
|
3732
3737
|
`$env:SLOCK_AGENT_PROXY_URL=${powershellSingleQuote(agentCredentialProxy.proxyUrl)}`,
|
|
3733
3738
|
`$env:SLOCK_AGENT_PROXY_TOKEN_FILE=${powershellSingleQuote(agentCredentialProxyTokenFile)}`,
|
|
@@ -3755,6 +3760,7 @@ set "SLOCK_AGENT_ACTIVE_CAPABILITIES=${DEFAULT_ACTIVE_CAPABILITIES}"\r
|
|
|
3755
3760
|
""
|
|
3756
3761
|
].join("\r\n");
|
|
3757
3762
|
writeFileSync(psWrapper, psBody);
|
|
3763
|
+
writeFileSync(psRaftWrapper, psBody);
|
|
3758
3764
|
}
|
|
3759
3765
|
const opencliBinPath = resolveOpencliBinPath();
|
|
3760
3766
|
if (opencliBinPath) {
|
|
@@ -4477,7 +4483,7 @@ var ClaudeDriver = class {
|
|
|
4477
4483
|
return buildCliTransportSystemPrompt(config, {
|
|
4478
4484
|
extraCriticalRules: [],
|
|
4479
4485
|
postStartupNotes: [
|
|
4480
|
-
"**Claude runtime note:** While you are busy, Slock batches inbox-count notifications instead of injecting message content. Use `
|
|
4486
|
+
"**Claude runtime note:** While you are busy, Slock batches inbox-count notifications instead of injecting message content. Use `raft message check` at natural breakpoints to pull the pending messages before side-effect actions that depend on current context."
|
|
4481
4487
|
],
|
|
4482
4488
|
includeStdinNotificationSection: true,
|
|
4483
4489
|
messageNotificationStyle: "direct"
|
|
@@ -5147,7 +5153,7 @@ var CodexDriver = class {
|
|
|
5147
5153
|
return buildCliTransportSystemPrompt(config, {
|
|
5148
5154
|
extraCriticalRules: [],
|
|
5149
5155
|
postStartupNotes: [
|
|
5150
|
-
"**IMPORTANT**: Your process stays alive across turns. While you are working, Slock may write batched inbox-count notifications into the current turn; call `
|
|
5156
|
+
"**IMPORTANT**: Your process stays alive across turns. While you are working, Slock may write batched inbox-count notifications into the current turn; call `raft message check` at natural breakpoints to read the pending messages."
|
|
5151
5157
|
],
|
|
5152
5158
|
includeStdinNotificationSection: true,
|
|
5153
5159
|
messageNotificationStyle: "direct"
|
|
@@ -7022,7 +7028,7 @@ var PiDriver = class {
|
|
|
7022
7028
|
return buildCliTransportSystemPrompt(config, {
|
|
7023
7029
|
extraCriticalRules: [],
|
|
7024
7030
|
postStartupNotes: [
|
|
7025
|
-
"**Pi runtime note:** Slock keeps Pi running as a persistent SDK session. While you are working, Slock may send inbox-count notifications into the current turn; call `
|
|
7031
|
+
"**Pi runtime note:** Slock keeps Pi running as a persistent SDK session. While you are working, Slock may send inbox-count notifications into the current turn; call `raft message check` at natural breakpoints."
|
|
7026
7032
|
],
|
|
7027
7033
|
includeStdinNotificationSection: true,
|
|
7028
7034
|
messageNotificationStyle: "direct"
|
|
@@ -7945,29 +7951,29 @@ function formatThreadContextMessage(message) {
|
|
|
7945
7951
|
function communicationCommand(name) {
|
|
7946
7952
|
switch (name) {
|
|
7947
7953
|
case "send_message":
|
|
7948
|
-
return "
|
|
7954
|
+
return "raft message send";
|
|
7949
7955
|
case "read_history":
|
|
7950
|
-
return "
|
|
7956
|
+
return "raft message read";
|
|
7951
7957
|
case "check_messages":
|
|
7952
|
-
return "
|
|
7958
|
+
return "raft message check";
|
|
7953
7959
|
case "claim_tasks":
|
|
7954
|
-
return "
|
|
7960
|
+
return "raft task claim";
|
|
7955
7961
|
default:
|
|
7956
|
-
return `
|
|
7962
|
+
return `raft ${name.replace(/_/g, " ")}`;
|
|
7957
7963
|
}
|
|
7958
7964
|
}
|
|
7959
7965
|
function dynamicReplyInstruction() {
|
|
7960
|
-
return "reply using `
|
|
7966
|
+
return "reply using `raft message send --target <exact target>`";
|
|
7961
7967
|
}
|
|
7962
7968
|
function dynamicClaimInstruction() {
|
|
7963
|
-
return "claim the relevant task with `
|
|
7969
|
+
return "claim the relevant task with `raft task claim`";
|
|
7964
7970
|
}
|
|
7965
7971
|
function formatIncomingMessage(message) {
|
|
7966
7972
|
const threadJoinPrefix = message.thread_join_context ? [
|
|
7967
7973
|
`[Slock thread context: you were added to a new thread via @mention.]`,
|
|
7968
7974
|
`parent: ${message.thread_join_context.parent_target}`,
|
|
7969
7975
|
`thread: ${message.thread_join_context.thread_target}`,
|
|
7970
|
-
`suggested next step:
|
|
7976
|
+
`suggested next step: raft message read --channel "${message.thread_join_context.suggested_read_history_target}"`,
|
|
7971
7977
|
"",
|
|
7972
7978
|
"Parent message:",
|
|
7973
7979
|
formatThreadContextMessage(message.thread_join_context.parent_message),
|
|
@@ -8089,7 +8095,7 @@ After confirming language preference, do not give a generic product introduction
|
|
|
8089
8095
|
A starter plan should make the next action executable, not just descriptive.
|
|
8090
8096
|
For new channels, new agents, and adding members to an existing channel, post an **action card** rather than a copyable spec:
|
|
8091
8097
|
|
|
8092
|
-
- Use \`
|
|
8098
|
+
- Use \`raft action prepare --target <onboarding-channel>\` and pipe an \`ActionCardAction\` JSON. Identity references are handles (\`@alice\` / \`@scout\` / \`#general\` \u2014 bare names work too), never UUIDs. Server resolves at prepare time.
|
|
8093
8099
|
- \`{type: "channel:create", name, visibility: "public" | "private", description?, initialHumans?: ["@alice"], initialAgents?: ["@scout"], draftHint?}\`
|
|
8094
8100
|
- \`{type: "agent:create", name, description?, suggestedComputer?, requiredComputer?, draftHint?}\`
|
|
8095
8101
|
- \`{type: "channel:add_member", channel: "#existing-channel", humans?: ["@alice"], agents?: ["@scout"], draftHint?}\` \u2014 at least one of humans / agents must be non-empty
|
|
@@ -8344,8 +8350,8 @@ Do not copy these answers verbatim.
|
|
|
8344
8350
|
|
|
8345
8351
|
## FAQ 15: How do I create agents or channels?
|
|
8346
8352
|
### Answer idea
|
|
8347
|
-
- When the owner agrees to a new agent or channel, **post an action card** with \`
|
|
8348
|
-
- v1 supports three action types via \`
|
|
8353
|
+
- When the owner agrees to a new agent or channel, **post an action card** with \`raft action prepare\`. The card lives inline in chat; the owner clicks the action button, the matching create dialog opens prefilled with your values (editable), and the resource is created under their identity when they submit.
|
|
8354
|
+
- v1 supports three action types via \`raft action prepare --target '<channel>' <<'SLOCKACTION' { ... } SLOCKACTION\`:
|
|
8349
8355
|
- \`{type: "channel:create", name, visibility: "public" | "private", description?, initialHumans?: ["@alice"], initialAgents?: ["@scout"], draftHint?}\`
|
|
8350
8356
|
- \`{type: "agent:create", name, description?, suggestedComputer?, requiredComputer?, draftHint?}\` \u2014 runtime / model / reasoning effort are the owner's call. Use \`requiredComputer\` only when the owner explicitly says the new agent must run on that computer; use \`suggestedComputer\` for a soft preference.
|
|
8351
8357
|
- \`{type: "channel:add_member", channel: "#existing-channel", humans?: ["@alice"], agents?: ["@scout"], draftHint?}\` \u2014 at least one of humans / agents must be non-empty. The owner clicks "Add Members" on the card; an AddMembers dialog opens with your suggested list (each row toggleable) and the owner submits to actually add them.
|
|
@@ -14160,7 +14166,7 @@ function resolveSlockCliPathOrEmpty(moduleUrl = import.meta.url) {
|
|
|
14160
14166
|
}
|
|
14161
14167
|
async function runBundledSlockCli(argv) {
|
|
14162
14168
|
process.argv = [process.execPath, "slock", ...argv];
|
|
14163
|
-
await import("./dist-
|
|
14169
|
+
await import("./dist-ADWW7UHH.js");
|
|
14164
14170
|
}
|
|
14165
14171
|
function detectRuntimes(tracer = noopTracer) {
|
|
14166
14172
|
const ids = [];
|
|
@@ -14290,7 +14296,7 @@ var DaemonCore = class {
|
|
|
14290
14296
|
options;
|
|
14291
14297
|
daemonVersion;
|
|
14292
14298
|
// When this runner is launched by a managed Computer service, the
|
|
14293
|
-
// service exports SLOCK_COMPUTER_VERSION (the `@
|
|
14299
|
+
// service exports SLOCK_COMPUTER_VERSION (the `@botiverse/raft-computer`
|
|
14294
14300
|
// bundle version). Reported in `ready` so the server can surface the
|
|
14295
14301
|
// Computer's own version (distinct from the underlying daemonVersion).
|
|
14296
14302
|
computerVersion;
|
package/dist/cli/index.js
CHANGED
|
@@ -1289,8 +1289,8 @@ async function mintAndPersist(ctx, options, accessToken, paths) {
|
|
|
1289
1289
|
ctx.io.stdout.write(
|
|
1290
1290
|
`state: authorized
|
|
1291
1291
|
Logged in as '${minted.agentName}' on ${options.server}. Credential saved to ${paths.credentialPath}.
|
|
1292
|
-
Next (if you are the human operator): start your agent with RAFT_PROFILE=${paths.profileSlug} in its environment, and let the agent run \`raft manual get
|
|
1293
|
-
Next (if you are the agent): run \`raft manual get
|
|
1292
|
+
Next (if you are the human operator): start your agent with RAFT_PROFILE=${paths.profileSlug} in its environment, and let the agent run \`raft manual get raft-cli-overview\` to learn the Raft CLI.
|
|
1293
|
+
Next (if you are the agent): run \`raft manual get raft-cli-overview\`, then use \`raft --profile ${paths.profileSlug} \u2026\` for all commands.
|
|
1294
1294
|
`
|
|
1295
1295
|
);
|
|
1296
1296
|
}
|
package/dist/core.js
CHANGED
|
@@ -1276,8 +1276,8 @@ async function mintAndPersist(ctx, options, accessToken, paths) {
|
|
|
1276
1276
|
ctx.io.stdout.write(
|
|
1277
1277
|
`state: authorized
|
|
1278
1278
|
Logged in as '${minted.agentName}' on ${options.server}. Credential saved to ${paths.credentialPath}.
|
|
1279
|
-
Next (if you are the human operator): start your agent with RAFT_PROFILE=${paths.profileSlug} in its environment, and let the agent run \`raft manual get
|
|
1280
|
-
Next (if you are the agent): run \`raft manual get
|
|
1279
|
+
Next (if you are the human operator): start your agent with RAFT_PROFILE=${paths.profileSlug} in its environment, and let the agent run \`raft manual get raft-cli-overview\` to learn the Raft CLI.
|
|
1280
|
+
Next (if you are the agent): run \`raft manual get raft-cli-overview\`, then use \`raft --profile ${paths.profileSlug} \u2026\` for all commands.
|
|
1281
1281
|
`
|
|
1282
1282
|
);
|
|
1283
1283
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botiverse/raft-daemon",
|
|
3
|
-
"version": "0.58.
|
|
3
|
+
"version": "0.58.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"raft-daemon": "dist/raft-daemon.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"typecheck": "tsc --noEmit",
|
|
37
37
|
"lint:publish-package": "node scripts/check-publish-package.mjs",
|
|
38
38
|
"generate:slock-cli-guide": "tsx scripts/generate-slock-cli-guide.ts",
|
|
39
|
-
"check:slock-cli-guide-fresh": "pnpm generate:slock-cli-guide && git diff --exit-code ../../manual/agent-knowledge/
|
|
39
|
+
"check:slock-cli-guide-fresh": "pnpm generate:slock-cli-guide && git diff --exit-code ../../manual/agent-knowledge/raft-cli-overview.md",
|
|
40
40
|
"release:patch": "npm version patch --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @botiverse/raft-daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags",
|
|
41
41
|
"release:minor": "npm version minor --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @botiverse/raft-daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags",
|
|
42
42
|
"release:major": "npm version major --no-git-tag-version && cd ../.. && pnpm install --lockfile-only && git add packages/daemon/package.json pnpm-lock.yaml && git commit -m \"chore: bump @botiverse/raft-daemon to v$(node -p \"require('./packages/daemon/package.json').version\")\" && git tag daemon-v$(node -p \"require('./packages/daemon/package.json').version\") && git push && git push --tags",
|