@clawos-dev/clawd 0.2.174 → 0.2.175-beta.352.ccf86fc

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/dist/cli.cjs CHANGED
@@ -253,7 +253,11 @@ var init_events = __esm({
253
253
  "skill-hint",
254
254
  "meta-text",
255
255
  "attachment-skills",
256
- "attachment-deferred-tools"
256
+ "attachment-deferred-tools",
257
+ // clawd shift v1:scheduler fire 时 daemon 给新 cc 的首条 user message 用
258
+ // <clawd-shift-fire> wrap 起头;classifyUserMessage 识别后路由到 UserMetaLine 折叠渲染,
259
+ // 不显示成 user 气泡(避免 instruction 文本被当 owner 实时对话)。
260
+ "clawd-shift-fire"
257
261
  ];
258
262
  SKILL_SOURCE_VALUES = ["builtin", "global", "project", "plugin"];
259
263
  AGENT_SOURCE_VALUES = [
@@ -11230,6 +11234,7 @@ function classifyUserMessage(input) {
11230
11234
  if (SYSTEM_REMINDER_RE.test(text) || OPENSPEC_BLOCK_RE.test(text)) {
11231
11235
  return { meta: "system-reminder" };
11232
11236
  }
11237
+ if (CLAWD_SHIFT_FIRE_RE.test(text)) return { meta: "clawd-shift-fire" };
11233
11238
  if (SKILL_HINT_RE.test(text)) return { meta: "skill-hint" };
11234
11239
  const flags = raw;
11235
11240
  if (flags.isMeta === true || flags.isSynthetic === true) return { meta: "meta-text" };
@@ -11444,7 +11449,7 @@ function readCurrentContent(filePath) {
11444
11449
  return null;
11445
11450
  }
11446
11451
  }
11447
- var import_node_fs10, import_node_os5, import_node_path9, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11452
+ var import_node_fs10, import_node_os5, import_node_path9, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, CLAWD_SHIFT_FIRE_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11448
11453
  var init_claude_history = __esm({
11449
11454
  "src/tools/claude-history.ts"() {
11450
11455
  "use strict";
@@ -11461,6 +11466,7 @@ var init_claude_history = __esm({
11461
11466
  SYSTEM_REMINDER_RE = /^\s*<system-reminder\b/i;
11462
11467
  OPENSPEC_BLOCK_RE = /^\s*<!--\s*OPENSPEC\b/i;
11463
11468
  SKILL_HINT_RE = /^\s*Base directory for this skill:\s/;
11469
+ CLAWD_SHIFT_FIRE_RE = /^\s*<clawd-shift-fire\b/i;
11464
11470
  ATTACHMENT_SILENT_SUBTYPES = /* @__PURE__ */ new Set([
11465
11471
  "hook_additional_context",
11466
11472
  "hook_success",
@@ -41261,6 +41267,22 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
41261
41267
  return s;
41262
41268
  }
41263
41269
 
41270
+ // src/shift/wrap.ts
41271
+ function wrapShiftFirePrompt(args) {
41272
+ return [
41273
+ `<clawd-shift-fire target-persona="${escapeAttr(args.targetPersona)}">`,
41274
+ "This is a scheduled shift fire \u2014 not a live user message.",
41275
+ "Respond as an assistant turn (start your output directly).",
41276
+ "",
41277
+ "Instruction:",
41278
+ args.prompt,
41279
+ "</clawd-shift-fire>"
41280
+ ].join("\n");
41281
+ }
41282
+ function escapeAttr(v2) {
41283
+ return v2.replace(/&/g, "&amp;").replace(/"/g, "&quot;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
41284
+ }
41285
+
41264
41286
  // src/session/reducer.ts
41265
41287
  init_runtime();
41266
41288
 
@@ -43956,6 +43978,7 @@ var SessionManager = class {
43956
43978
  cwd,
43957
43979
  tool: "claude",
43958
43980
  ownerPersonaId: args.targetPersona,
43981
+ ...args.sourceSessionId ? { dispatchedFromSessionId: args.sourceSessionId } : {},
43959
43982
  createdAt: now,
43960
43983
  updatedAt: now
43961
43984
  };
@@ -43991,7 +44014,16 @@ var SessionManager = class {
43991
44014
  });
43992
44015
  const runner = this.ensureRunnerForScope(file, scope);
43993
44016
  this.deps.logger?.info("shift.createShiftSession.runner-ready", { sessionId });
43994
- runner.input({ kind: "command", command: { kind: "send", text: args.prompt } });
44017
+ runner.input({
44018
+ kind: "command",
44019
+ command: {
44020
+ kind: "send",
44021
+ text: wrapShiftFirePrompt({
44022
+ prompt: args.prompt,
44023
+ targetPersona: args.targetPersona
44024
+ })
44025
+ }
44026
+ });
43995
44027
  const kill = () => {
43996
44028
  const r = this.runners.get(sessionId);
43997
44029
  if (!r) return;
@@ -47513,7 +47545,8 @@ function createShiftScheduler(deps) {
47513
47545
  shiftId: shift.id,
47514
47546
  targetPersona: shift.targetPersona,
47515
47547
  prompt: shift.prompt,
47516
- timeoutMs
47548
+ timeoutMs,
47549
+ ...shift.createdBySessionId ? { sourceSessionId: shift.createdBySessionId } : {}
47517
47550
  });
47518
47551
  sessionId = spawned.sessionId;
47519
47552
  const startRun = {
@@ -47567,8 +47600,12 @@ function createShiftScheduler(deps) {
47567
47600
 
47568
47601
  // src/shift/spawn.ts
47569
47602
  function createShiftSpawnFn(deps) {
47570
- return async ({ targetPersona, prompt, timeoutMs }) => {
47571
- const created = deps.sessionManager.createShiftSession({ targetPersona, prompt });
47603
+ return async ({ targetPersona, prompt, timeoutMs, sourceSessionId }) => {
47604
+ const created = deps.sessionManager.createShiftSession({
47605
+ targetPersona,
47606
+ prompt,
47607
+ ...sourceSessionId ? { sourceSessionId } : {}
47608
+ });
47572
47609
  let resolveOuter = () => {
47573
47610
  };
47574
47611
  const ended = new Promise((r) => {
@@ -47622,12 +47659,14 @@ function validateSchedule(schedule) {
47622
47659
  function buildShiftInternalHandlers(deps) {
47623
47660
  const add = async (frame) => {
47624
47661
  const persona = readPersonaId(frame);
47662
+ const callerSessionId = typeof frame.sessionId === "string" ? frame.sessionId : void 0;
47625
47663
  const { type: _t, requestId: _r, personaId: _p, sessionId: _s, ...rest } = frame;
47626
47664
  const args = rest;
47627
47665
  validateSchedule(args.schedule);
47628
47666
  const shift = deps.store.add({
47629
47667
  ownerId: deps.ownerIdProvider(),
47630
47668
  createdByPersona: persona,
47669
+ ...callerSessionId ? { createdBySessionId: callerSessionId } : {},
47631
47670
  name: args.name,
47632
47671
  enabled: true,
47633
47672
  schedule: args.schedule,
@@ -55606,11 +55645,22 @@ function buildAppBuilderHandlers(deps) {
55606
55645
  }
55607
55646
 
55608
55647
  // src/handlers/shift.ts
55648
+ var UI_DEFAULT_DURATION_MS = 30 * 6e4;
55649
+ var UI_MAX_DURATION_MS = 60 * 6e4;
55650
+ function pickUiDurationMs(timeoutMs) {
55651
+ return Math.min(timeoutMs ?? UI_DEFAULT_DURATION_MS, UI_MAX_DURATION_MS);
55652
+ }
55653
+ function everyMsToCron(everyMs) {
55654
+ if (everyMs <= 6e4) return "* * * * *";
55655
+ const minutes = Math.floor(everyMs / 6e4);
55656
+ if (minutes < 60) return `*/${minutes} * * * *`;
55657
+ const hours = Math.floor(minutes / 60);
55658
+ if (hours < 24) return `0 */${hours} * * *`;
55659
+ const days = Math.max(1, Math.floor(hours / 24));
55660
+ return `0 0 */${days} * *`;
55661
+ }
55609
55662
  function daemonShiftToUiShift(d, nowMs) {
55610
- if (d.schedule.kind === "at") {
55611
- const atMs = Date.parse(d.schedule.at);
55612
- if (Number.isNaN(atMs) || atMs <= nowMs) return null;
55613
- }
55663
+ const durationMs = pickUiDurationMs(d.timeoutMs);
55614
55664
  const noteParts = [d.name];
55615
55665
  if (d.prompt && d.prompt.length > 0) {
55616
55666
  const promptPreview = d.prompt.length > 120 ? `${d.prompt.slice(0, 117)}\u2026` : d.prompt;
@@ -55618,12 +55668,49 @@ function daemonShiftToUiShift(d, nowMs) {
55618
55668
  }
55619
55669
  if (!d.enabled) noteParts.push("(disabled)");
55620
55670
  const note = noteParts.join(" \u2014 ");
55621
- return {
55622
- id: d.id,
55623
- agentId: d.targetPersona,
55624
- schedule: d.schedule,
55625
- note
55626
- };
55671
+ switch (d.schedule.kind) {
55672
+ case "at": {
55673
+ const startMs = Date.parse(d.schedule.at);
55674
+ if (Number.isNaN(startMs)) return null;
55675
+ if (startMs + durationMs <= nowMs) return null;
55676
+ return {
55677
+ id: d.id,
55678
+ agentId: d.targetPersona,
55679
+ schedule: {
55680
+ kind: "single",
55681
+ start: new Date(startMs).toISOString(),
55682
+ end: new Date(startMs + durationMs).toISOString()
55683
+ },
55684
+ note
55685
+ };
55686
+ }
55687
+ case "cron": {
55688
+ return {
55689
+ id: d.id,
55690
+ agentId: d.targetPersona,
55691
+ schedule: {
55692
+ kind: "recurring",
55693
+ cron: d.schedule.expr,
55694
+ ...d.schedule.tz ? { tz: d.schedule.tz } : {},
55695
+ durationMs
55696
+ },
55697
+ note
55698
+ };
55699
+ }
55700
+ case "every": {
55701
+ const cron = everyMsToCron(d.schedule.everyMs);
55702
+ return {
55703
+ id: d.id,
55704
+ agentId: d.targetPersona,
55705
+ schedule: {
55706
+ kind: "recurring",
55707
+ cron,
55708
+ durationMs
55709
+ },
55710
+ note
55711
+ };
55712
+ }
55713
+ }
55627
55714
  }
55628
55715
  function buildShiftHandlers(deps) {
55629
55716
  return {
@@ -21251,7 +21251,9 @@ async function main() {
21251
21251
  inputSchema: {
21252
21252
  name: external_exports.string().describe("short label shown in shift.json + future UI"),
21253
21253
  schedule: ScheduleSchema,
21254
- prompt: external_exports.string().describe("first user message injected when the new cc starts"),
21254
+ prompt: external_exports.string().describe(
21255
+ "instruction the spawned cc executes on startup (NOT a chat message from the owner). Write what you want the persona to DO or SAY at fire time, in instruction form \u2014 daemon wraps it in a <clawd-shift-fire> tag so the spawned cc treats it as a scheduled action and responds as an assistant turn (no user-bubble appears in the owner's UI)."
21256
+ ),
21255
21257
  targetPersona: external_exports.string().optional().describe("which persona to spawn; defaults to the calling persona"),
21256
21258
  timeoutMs: external_exports.number().optional().describe("hard timeout per fire; default 30 minutes")
21257
21259
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawos-dev/clawd",
3
- "version": "0.2.174",
3
+ "version": "0.2.175-beta.352.ccf86fc",
4
4
  "description": "Standalone clawd daemon — Claude Code (and future Codex) session server over WebSocket",
5
5
  "type": "module",
6
6
  "license": "MIT",