@fancyboi999/open-tag-daemon 0.6.1 → 0.7.1

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.
@@ -3156,7 +3156,7 @@ message.command("check").description("non-blocking check for new messages").acti
3156
3156
  for (const m of d.messages) console.log(m.text);
3157
3157
  console.log("No more new messages.");
3158
3158
  });
3159
- message.command("send").description("send a message (body read from stdin); if new messages arrived since last read the message is freshness-held as a draft \u2014 revise it or use --send-draft to submit as-is").requiredOption("--target <target>", "#channel / dm:@name / #channel:shortid").option("--attach <ids>", "attachment ids, comma-separated").option("--send-draft", "submit the held draft as-is, bypassing freshness check").action(async (opts) => {
3159
+ message.command("send").description("send a message (body read from stdin); if new messages arrived since last read the message is freshness-held as a draft \u2014 revise it or use --send-draft to submit as-is").requiredOption("--target <target>", "#channel / dm:@name / #channel:shortid / thread:shortid").option("--attach <ids>", "attachment ids, comma-separated").option("--send-draft", "submit the held draft as-is, bypassing freshness check").action(async (opts) => {
3160
3160
  const sendDraft = !!opts.sendDraft;
3161
3161
  const content = sendDraft ? "" : (await readStdin()).trim();
3162
3162
  const attachmentIds = opts.attach ? String(opts.attach).split(",").map((s) => s.trim()).filter(Boolean) : [];
@@ -3232,6 +3232,16 @@ task.command("update").description("update task status (--message-id, or --chann
3232
3232
  await api("POST", "/agent-api/task/update", body);
3233
3233
  console.log(`Updated -> ${opts.status}`);
3234
3234
  });
3235
+ task.command("assign").description("hand off a task to another agent (--message-id, or --channel #ch --number N)").option("--message-id <id>").option("--channel <ch>", "#name / dm:@name (used with --number)").option("--number <n>", "task number #N").requiredOption("--to <agent>", "@agent handle").action(async (opts) => {
3236
+ const body = { to: opts.to };
3237
+ if (opts.number != null) {
3238
+ body.channel = opts.channel;
3239
+ body.number = Number(opts.number);
3240
+ } else body.messageId = opts.messageId;
3241
+ const d = await api("POST", "/agent-api/task/assign", body);
3242
+ console.log(`Assigned task #${d.number ?? "?"} -> @${d.to}`);
3243
+ if (d.followUp) console.log(d.followUp);
3244
+ });
3235
3245
  var taskCreate = async (opts) => {
3236
3246
  const d = await api("POST", "/agent-api/task/new", { target: opts.channel, title: opts.title });
3237
3247
  for (const t of d.tasks ?? []) console.log(`Created task #${t.number ?? "-"} ${String(t.id).slice(0, 8)}: ${t.content}`);
@@ -3256,7 +3266,7 @@ thread.command("reply").description("start or reply to a thread under a message
3256
3266
  const d = await api("POST", "/agent-api/thread/reply", { parent: opts.parent, channel: opts.channel, content });
3257
3267
  console.log(`Replied in thread (thread ${String(d.threadChannelId).slice(0, 8)}, msg ${String(d.id).slice(0, 8)})`);
3258
3268
  });
3259
- thread.command("unfollow").description("stop receiving deliveries from a thread").requiredOption("--target <thread>", "#channel:shortid").action(async (opts) => {
3269
+ thread.command("unfollow").description("stop receiving deliveries from a thread").requiredOption("--target <thread>", "#channel:shortid or thread:shortid").action(async (opts) => {
3260
3270
  await api("POST", "/agent-api/thread/unfollow", { target: opts.target });
3261
3271
  console.log(`Unfollowed ${opts.target}`);
3262
3272
  });
package/dist/cli.mjs CHANGED
@@ -3937,8 +3937,8 @@ A local \`open-tag\` command is on your PATH. Use ONLY it to communicate, via yo
3937
3937
  - \`open-tag message read --channel <t> [--limit N]\` \u2014 read history.
3938
3938
  - \`open-tag server info\` \u2014 list channels / agents / humans.
3939
3939
  - \`open-tag channel join --target "#name"\` \u2014 join a public channel.
3940
- - \`open-tag task list --channel <t>\` \xB7 \`open-tag task claim --message-id <id>\` \xB7 \`open-tag task update --message-id <id> --status <todo|in_progress|in_review|done>\` \xB7 \`open-tag task create --channel <t> --title <t>\`(delegate a task)
3941
- - **Threads (no dedicated thread command \u2014 use message send/read with a thread-suffix target)**: reply to / open a thread = \`open-tag message send --target "#channel:shortid"\` (suffix shortid = the 8-char short id from the \`msg=\` field in the message header; if it does not exist, a thread is created automatically); read a thread = \`open-tag message read --channel "#channel:shortid"\`; stop receiving deliveries for a thread = \`open-tag thread unfollow --target "#channel:shortid"\` (only when work in that thread is clearly done or irrelevant). Threads cannot be nested.
3940
+ - \`open-tag task list --channel <t>\` \xB7 \`open-tag task claim --message-id <id>\` \xB7 \`open-tag task assign --message-id <id> --to @agent\`(handoff to another agent) \xB7 \`open-tag task update --message-id <id> --status <todo|in_progress|in_review|done>\` \xB7 \`open-tag task create --channel <t> --title <t>\`(delegate a task)
3941
+ - **Threads (no dedicated thread command \u2014 use a thread target)**: reply to / open a thread = \`open-tag message send --target "#channel:shortid"\` or the stable \`thread:shortid\` form (where \`shortid\` is the 8-char parent message id from the message header; if the thread does not exist yet, the target creates it automatically when the parent channel is accessible); read a thread = \`open-tag message read --channel "thread:shortid"\`; stop receiving deliveries for a thread = \`open-tag thread unfollow --target "thread:shortid"\` (or the older \`#channel:shortid\` form) when work there is clearly done or irrelevant. Threads cannot be nested.
3942
3942
  - \`open-tag message react --message-id <id> --emoji <e> [--remove]\`(emoji reaction) \xB7 \`open-tag message search --query <q>\`(search channels you are in)
3943
3943
  - \`open-tag attachment upload --file <path> --channel <t>\`(upload a file, returns an id; then use \`message send --attach <id>\`) \xB7 \`open-tag attachment view --id <id>\`(downloads the attachment to the local \`attachments/\` directory and prints its local path for inspection \u2014 this command only handles the download and path; how you open it is up to your local tools)
3944
3944
  - \`open-tag message resolve --id <id>\`(verify that a cited message id is real \u2014 always resolve before referencing, never invent ids from memory) \xB7 \`open-tag channel members --channel <t>\` \xB7 \`open-tag channel leave --target "#name"\` \xB7 \`open-tag task unclaim --message-id <id>\`
@@ -3946,7 +3946,7 @@ A local \`open-tag\` command is on your PATH. Use ONLY it to communicate, via yo
3946
3946
  - \`open-tag reminder schedule --content <t> --in <seconds> [--anchor <msgId>] [--recurring <seconds>]\`(schedule a future wakeup for yourself \u2014 at the scheduled time the system will @-mention you to wake you up) \xB7 \`open-tag reminder list/cancel/snooze\`. For anything that depends on a future state, use a reminder instead of busy-waiting.
3947
3947
  - \`open-tag action prepare --target <t>\` \u2014 prepare an action card for a human to commit (B-mode quick-commit). You do NOT have permission to create channels/agents yourself; instead pipe the action JSON on STDIN and post a card the human clicks to execute under their own identity. Variants: \`channel:create\` (\`{"type":"channel:create","name":"x","description":"...","visibility":"public"}\`), \`agent:create\` (\`{"type":"agent:create","name":"y","description":"..."}\`). Use when a human asks you to set up a channel/agent \u2014 propose it as a card, don't ask them to do it manually.
3948
3948
 
3949
- Targets: \`#channel\`, \`dm:@name\`, thread \`#channel:shortid\`. Send the body via stdin heredoc:
3949
+ Targets: \`#channel\`, \`dm:@name\`, thread \`#channel:shortid\` or \`thread:shortid\`. Prefer \`thread:shortid\` when reusing a thread target across different agents, private channels, or DMs because it is stable across actor viewpoints. Send the body via stdin heredoc:
3950
3950
  \`\`\`bash
3951
3951
  open-tag message send --target "#all" <<'MSG'
3952
3952
  Your reply. Quotes, $vars, \`backticks\`, code blocks are all safe here.
@@ -3958,11 +3958,11 @@ FRESHNESS HOLD (collaboration safety): if new messages arrived in that target si
3958
3958
 
3959
3959
  ## Received message format
3960
3960
  \`[target=<id> msg=<shortid> time=<iso> type=human|agent|system] @sender: content\`
3961
- Reuse the \`target=\` value when replying so it lands in the right channel/DM/thread. @mention people by their @handle. \`msg=\` is the 8-char short id \u2014 use it as a thread suffix (\`#channel:shortid\`) to start/reply in a thread, and pass it to \`open-tag message resolve\` to verify a cited id is real. \`type=system\` messages announce state changes (task events, reminders) \u2014 don't reply unless they clearly ask you to act.
3961
+ Reuse the \`target=\` value when replying so it lands in the right channel/DM/thread. @mention people by their @handle. \`msg=\` is the 8-char short id \u2014 use it as a thread suffix (\`#channel:shortid\`) or as the stable form \`thread:shortid\` to start/reply in a thread, and pass it to \`open-tag message resolve\` to verify a cited id is real. \`type=system\` messages announce state changes (task events, reminders) \u2014 don't reply unless they clearly ask you to act.
3962
3962
 
3963
3963
  ### Formatting \u2014 so refs/links render
3964
3964
  open-tag auto-renders these **bare-text** tokens into clickable refs; write them as plain words, NOT wrapped in backticks (code spans are literal, won't render):
3965
- - \`@handle\` \u2192 user/agent \xB7 \`#channel\` \u2192 channel \xB7 \`#channel:shortid\` \u2192 thread \xB7 \`task #N\` \u2192 task (write "task #N", not bare "#N").
3965
+ - \`@handle\` \u2192 user/agent \xB7 \`#channel\` \u2192 channel \xB7 \`#channel:shortid\` or \`thread:shortid\` \u2192 thread \xB7 \`task #N\` \u2192 task (write "task #N", not bare "#N").
3966
3966
  - **URL next to CJK/non-ASCII punctuation**: wrap it in \`<url>\` or \`[text](url)\`, else the punctuation gets swallowed into the link. Wrong: \`env:http://x:3000,see\` \u2192 Right: \`env:<http://x:3000>,see\`.
3967
3967
 
3968
3968
  ### Citing prior discussion
@@ -4139,6 +4139,29 @@ function summarize(tool, input) {
4139
4139
  if (["Read", "Write", "Edit"].includes(tool)) return input.file_path ?? input.path ?? "";
4140
4140
  return "";
4141
4141
  }
4142
+ var CLAUDE_EFFORTS = /* @__PURE__ */ new Set(["low", "medium", "high", "xhigh", "max"]);
4143
+ function buildClaudeArgs(p) {
4144
+ const args2 = [
4145
+ "-p",
4146
+ "--output-format",
4147
+ "stream-json",
4148
+ "--input-format",
4149
+ "stream-json",
4150
+ "--verbose",
4151
+ "--dangerously-skip-permissions",
4152
+ "--permission-mode",
4153
+ "bypassPermissions",
4154
+ "--include-partial-messages",
4155
+ "--disallowed-tools",
4156
+ "EnterPlanMode,ExitPlanMode,ScheduleWakeup,CronCreate,CronList,CronDelete,AskUserQuestion",
4157
+ ...p.promptFileFlag
4158
+ ];
4159
+ if (p.model) args2.push("--model", p.model);
4160
+ const effort = typeof p.reasoningEffort === "string" && CLAUDE_EFFORTS.has(p.reasoningEffort) ? p.reasoningEffort : null;
4161
+ if (effort) args2.push("--effort", effort);
4162
+ if (p.sessionId) args2.push("--resume", p.sessionId);
4163
+ return args2;
4164
+ }
4142
4165
  var claudeRuntime = {
4143
4166
  name: "claude",
4144
4167
  start(opts, cb) {
@@ -4149,24 +4172,13 @@ var claudeRuntime = {
4149
4172
  promptFlag = ["--append-system-prompt-file", pf];
4150
4173
  } catch {
4151
4174
  }
4152
- const args2 = [
4153
- "-p",
4154
- "--output-format",
4155
- "stream-json",
4156
- "--input-format",
4157
- "stream-json",
4158
- "--verbose",
4159
- "--dangerously-skip-permissions",
4160
- "--permission-mode",
4161
- "bypassPermissions",
4162
- "--include-partial-messages",
4163
- "--disallowed-tools",
4164
- "EnterPlanMode,ExitPlanMode,ScheduleWakeup,CronCreate,CronList,CronDelete,AskUserQuestion",
4165
- ...promptFlag,
4166
- "--model",
4167
- opts.model ?? "sonnet"
4168
- ];
4169
- if (opts.sessionId) args2.push("--resume", opts.sessionId);
4175
+ const rc = opts.runtimeConfig;
4176
+ const args2 = buildClaudeArgs({
4177
+ promptFileFlag: promptFlag,
4178
+ model: opts.model,
4179
+ reasoningEffort: rc && typeof rc.reasoningEffort === "string" ? rc.reasoningEffort : null,
4180
+ sessionId: opts.sessionId
4181
+ });
4170
4182
  const proc = spawn("claude", args2, { cwd: opts.cwd, stdio: ["pipe", "pipe", "pipe"], env: opts.env });
4171
4183
  let sessionId = opts.sessionId ?? null;
4172
4184
  const writeUser = (text) => {
@@ -5991,7 +6003,7 @@ conn = new Connection(serverUrl, apiKey, (msg) => {
5991
6003
  runningAgents: mgr.running(),
5992
6004
  hostname: os4.hostname(),
5993
6005
  os: `${os4.platform()} ${os4.arch()}`,
5994
- daemonVersion: "0.6.1",
6006
+ daemonVersion: "0.7.1",
5995
6007
  machineId: readMachineId()
5996
6008
  // Stable identity: empty on first connection; server sends it back via ready:ack for persistence.
5997
6009
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fancyboi999/open-tag-daemon",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "open-tag compute-plane daemon — connect any machine to an open-tag server so its agents run there. No repo clone needed.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",