@aspectlylabs/mikka 0.0.129 → 0.0.131

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/cli.js CHANGED
@@ -4457,7 +4457,7 @@ import { join as join4 } from "node:path";
4457
4457
  // package.json
4458
4458
  var package_default = {
4459
4459
  name: "@mikka/daemon",
4460
- version: "0.0.129",
4460
+ version: "0.0.131",
4461
4461
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4462
4462
  type: "module",
4463
4463
  private: true,
@@ -4517,7 +4517,7 @@ var package_default = {
4517
4517
  engines: {
4518
4518
  node: ">=24"
4519
4519
  },
4520
- gitHead: "26342727de268b71e41b110fd8f4785223f3fc0f"
4520
+ gitHead: "a68a3eba7b9d42b907037a4153b9645bf525d42e"
4521
4521
  };
4522
4522
 
4523
4523
  // src/paths.ts
@@ -4981,12 +4981,15 @@ var captureCompleteResponse = z23.object({ capture: captureView });
4981
4981
  var screenCaptureRequest = z23.discriminatedUnion("action", [
4982
4982
  z23.object({ action: z23.literal("screenshot"), title }).strict(),
4983
4983
  z23.object({ action: z23.literal("start_recording"), title, maxSeconds: z23.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
4984
- z23.object({ action: z23.literal("stop_recording") }).strict()
4984
+ z23.object({ action: z23.literal("stop_recording") }).strict(),
4985
+ // A step on the recording's timeline: an action's own description, or a moment the agent marks.
4986
+ z23.object({ action: z23.literal("step"), label: title, source: z23.enum(["action", "mark"]) }).strict()
4985
4987
  ]);
4986
4988
  var screenCaptureResponse = z23.discriminatedUnion("action", [
4987
4989
  z23.object({ action: z23.literal("screenshot"), capture: captureView }),
4988
4990
  z23.object({ action: z23.literal("start_recording"), recordingId: z23.uuid(), stopsAt: z23.iso.datetime() }),
4989
- z23.object({ action: z23.literal("stop_recording"), capture: captureView })
4991
+ z23.object({ action: z23.literal("stop_recording"), capture: captureView }),
4992
+ z23.object({ action: z23.literal("step"), recorded: z23.boolean() })
4990
4993
  ]);
4991
4994
  var capturePaths = {
4992
4995
  begin: (runId) => `/v1/runs/${encodeURIComponent(runId)}/captures`,
@@ -14052,7 +14055,12 @@ async function detectComputerDriver(binary = "cua-driver") {
14052
14055
  return null;
14053
14056
  }
14054
14057
  }
14055
- var CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording" };
14058
+ var CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording", mark_recording_step: "step" };
14059
+ var cleanStep = (value) => typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
14060
+ function actionStep(value) {
14061
+ const label2 = cleanStep(value?.arguments?.step);
14062
+ return label2 && label2.length <= 200 ? label2 : null;
14063
+ }
14056
14064
  function normalizeCaptureCall(value) {
14057
14065
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid tool call");
14058
14066
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k))) throw new Error("Unknown call fields");
@@ -14062,6 +14070,10 @@ function normalizeCaptureCall(value) {
14062
14070
  const keys = Object.keys(args).sort().join(",");
14063
14071
  const title2 = typeof args.title === "string" ? args.title.replace(/\s+/g, " ").trim() : "";
14064
14072
  if (action === "stop_recording" && !keys) return { action };
14073
+ if (action === "step" && keys === "label") {
14074
+ const label2 = cleanStep(args.label);
14075
+ if (label2 && label2.length <= 200) return { action, label: label2, source: "mark" };
14076
+ }
14065
14077
  if (action === "screenshot" && keys === "title" && title2 && title2.length <= 200) return { action, title: title2 };
14066
14078
  if (action === "start_recording" && ["title", "maxSeconds,title"].includes(keys) && title2 && title2.length <= 200 && (args.maxSeconds === void 0 || Number.isInteger(args.maxSeconds) && args.maxSeconds >= 5 && args.maxSeconds <= 300))
14067
14079
  return { action, title: title2, ...args.maxSeconds === void 0 ? {} : { maxSeconds: args.maxSeconds } };
@@ -14072,9 +14084,12 @@ function normalizeCall(value) {
14072
14084
  throw new Error("Invalid tool call");
14073
14085
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k)))
14074
14086
  throw new Error("Unknown call fields");
14075
- const { name, arguments: args = {} } = value;
14076
- if (!args || typeof args !== "object" || Array.isArray(args))
14087
+ const { name, arguments: given = {} } = value;
14088
+ if (!given || typeof given !== "object" || Array.isArray(given))
14077
14089
  throw new Error("Invalid arguments");
14090
+ const { step: described, ...args } = given;
14091
+ if (Object.hasOwn(given, "step") && (name === "get_desktop_state" || !cleanStep(described) || cleanStep(described).length > 200))
14092
+ throw new Error("Unsupported tool or arguments");
14078
14093
  const keys = Object.keys(args).sort().join(",");
14079
14094
  if (name === "get_desktop_state" && !keys) return { name, arguments: {} };
14080
14095
  if (name === "click" && keys === "x,y" && [args.x, args.y].every((v2) => Number.isInteger(v2) && v2 >= 0 && v2 <= 1e5))
@@ -14201,6 +14216,8 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
14201
14216
  // src/computer/broker.mjs
14202
14217
  var ComputerBroker = class {
14203
14218
  grants = /* @__PURE__ */ new Map();
14219
+ // runId → when its screen recording stops by itself; only set while one runs.
14220
+ recordingUntil = /* @__PURE__ */ new Map();
14204
14221
  pending = /* @__PURE__ */ new Map();
14205
14222
  sockets = /* @__PURE__ */ new Set();
14206
14223
  suspended = false;
@@ -14279,6 +14296,24 @@ var ComputerBroker = class {
14279
14296
  if (!grant || signal?.aborted || !this.permitted(grant.runId))
14280
14297
  return Promise.reject(new Error("Not permitted"));
14281
14298
  const call = normalizeCall(value);
14299
+ const step = actionStep(value);
14300
+ return this.requestCall(token, grant, call, signal).then((result) => {
14301
+ this.markStep(grant.runId, step);
14302
+ return result;
14303
+ });
14304
+ }
14305
+ /** While this run records, a done action's description becomes a step on the recording (best effort; never fails the action). */
14306
+ markStep(runId, label2) {
14307
+ const until = this.recordingUntil.get(runId);
14308
+ if (!label2 || !this.capture || until === void 0) return;
14309
+ if (this.now() > until) {
14310
+ this.recordingUntil.delete(runId);
14311
+ return;
14312
+ }
14313
+ void Promise.resolve().then(() => this.capture(runId, { action: "step", label: label2, source: "action" })).catch(() => {
14314
+ });
14315
+ }
14316
+ requestCall(token, grant, call, signal) {
14282
14317
  const actionId = randomUUID9();
14283
14318
  const assertLive = () => {
14284
14319
  if (this.suspended || signal?.aborted || this.grants.get(token) !== grant || this.driver?.fingerprint !== grant.fingerprint || !this.permitted(grant.runId))
@@ -14331,7 +14366,10 @@ var ComputerBroker = class {
14331
14366
  return { error: "Not permitted" };
14332
14367
  const call = normalizeCaptureCall(value);
14333
14368
  try {
14334
- return { result: await this.capture(grant.runId, call, signal) };
14369
+ const result = await this.capture(grant.runId, call, signal);
14370
+ if (call.action === "start_recording" && typeof result?.stopsAt === "string") this.recordingUntil.set(grant.runId, Date.parse(result.stopsAt));
14371
+ if (call.action === "stop_recording") this.recordingUntil.delete(grant.runId);
14372
+ return { result };
14335
14373
  } catch (error) {
14336
14374
  const detail = typeof error?.safeMessage === "string" ? error.safeMessage.slice(0, 300) : void 0;
14337
14375
  return { error: "Capture failed", ...detail ? { detail } : {} };
package/client.js CHANGED
@@ -3719,7 +3719,7 @@ import { join } from "node:path";
3719
3719
  // package.json
3720
3720
  var package_default = {
3721
3721
  name: "@mikka/daemon",
3722
- version: "0.0.129",
3722
+ version: "0.0.131",
3723
3723
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3724
3724
  type: "module",
3725
3725
  private: true,
@@ -3779,7 +3779,7 @@ var package_default = {
3779
3779
  engines: {
3780
3780
  node: ">=24"
3781
3781
  },
3782
- gitHead: "26342727de268b71e41b110fd8f4785223f3fc0f"
3782
+ gitHead: "a68a3eba7b9d42b907037a4153b9645bf525d42e"
3783
3783
  };
3784
3784
 
3785
3785
  // src/paths.ts
@@ -28,6 +28,13 @@ export async function detectComputerDriver(binary = "cua-driver") {
28
28
  return null;
29
29
  }
30
30
  }
31
+ // What an action does, in the person's words. While a screen recording runs it
32
+ // becomes a step on the recording's timeline (Figma 13), so it is never
33
+ // coordinates, keys or a tool name.
34
+ const step = {
35
+ type: "string", minLength: 1, maxLength: 200,
36
+ description: "What this action does, in plain words for the person watching (e.g. \"Click Sign in\", \"点击登录按钮\"). Shown on the screen recording's timeline; never coordinates or tool names.",
37
+ };
31
38
  export const TOOLS = [
32
39
  {
33
40
  name: "get_desktop_state",
@@ -47,8 +54,9 @@ export const TOOLS = [
47
54
  properties: {
48
55
  x: { type: "integer", minimum: 0, maximum: 100000 },
49
56
  y: { type: "integer", minimum: 0, maximum: 100000 },
57
+ step,
50
58
  },
51
- required: ["x", "y"],
59
+ required: ["x", "y", "step"],
52
60
  additionalProperties: false,
53
61
  },
54
62
  },
@@ -58,8 +66,8 @@ export const TOOLS = [
58
66
  "Type exactly the requested text into the focused desktop control, subject to the computer permission policy.",
59
67
  inputSchema: {
60
68
  type: "object",
61
- properties: { text: { type: "string", minLength: 1, maxLength: 8000 } },
62
- required: ["text"],
69
+ properties: { text: { type: "string", minLength: 1, maxLength: 8000 }, step },
70
+ required: ["text", "step"],
63
71
  additionalProperties: false,
64
72
  },
65
73
  },
@@ -68,8 +76,8 @@ export const TOOLS = [
68
76
  description: "Press the requested key and modifiers on the focused desktop, subject to the computer permission policy.",
69
77
  inputSchema: {
70
78
  type: "object",
71
- properties: { key: { type: "string" }, modifiers: { type: "array", items: { type: "string", enum: ["ctrl", "shift", "alt", "super"] }, maxItems: 4, uniqueItems: true } },
72
- required: ["key"], additionalProperties: false,
79
+ properties: { key: { type: "string" }, modifiers: { type: "array", items: { type: "string", enum: ["ctrl", "shift", "alt", "super"] }, maxItems: 4, uniqueItems: true }, step },
80
+ required: ["key", "step"], additionalProperties: false,
73
81
  },
74
82
  },
75
83
  {
@@ -77,8 +85,8 @@ export const TOOLS = [
77
85
  description: "Scroll the requested amount at a desktop coordinate, subject to the computer permission policy.",
78
86
  inputSchema: {
79
87
  type: "object",
80
- properties: { direction: { type: "string", enum: ["up", "down", "left", "right"] }, amount: { type: "integer", minimum: 1, maximum: 50 }, x: { type: "integer", minimum: 0, maximum: 100000 }, y: { type: "integer", minimum: 0, maximum: 100000 } },
81
- required: ["direction", "amount", "x", "y"], additionalProperties: false,
88
+ properties: { direction: { type: "string", enum: ["up", "down", "left", "right"] }, amount: { type: "integer", minimum: 1, maximum: 50 }, x: { type: "integer", minimum: 0, maximum: 100000 }, y: { type: "integer", minimum: 0, maximum: 100000 }, step },
89
+ required: ["direction", "amount", "x", "y", "step"], additionalProperties: false,
82
90
  },
83
91
  },
84
92
  ];
@@ -108,8 +116,20 @@ export const CAPTURE_TOOLS = [
108
116
  description: "Stop the screen recording and keep it with the thread.",
109
117
  inputSchema: { type: "object", properties: {}, additionalProperties: false },
110
118
  },
119
+ {
120
+ name: "mark_recording_step",
121
+ description:
122
+ "While recording, mark a moment that is not one of your actions (e.g. \"The first screen appears\", \"首屏出现\") on the recording's timeline. Each action's `step` is marked by itself.",
123
+ inputSchema: { type: "object", properties: { label: step }, required: ["label"], additionalProperties: false },
124
+ },
111
125
  ];
112
- const CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording" };
126
+ const CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording", mark_recording_step: "step" };
127
+ const cleanStep = (value) => (typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "");
128
+ /** The action's own description for the recording timeline, or null. */
129
+ export function actionStep(value) {
130
+ const label = cleanStep(value?.arguments?.step);
131
+ return label && label.length <= 200 ? label : null;
132
+ }
113
133
  export function normalizeCaptureCall(value) {
114
134
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid tool call");
115
135
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k))) throw new Error("Unknown call fields");
@@ -119,6 +139,10 @@ export function normalizeCaptureCall(value) {
119
139
  const keys = Object.keys(args).sort().join(",");
120
140
  const title = typeof args.title === "string" ? args.title.replace(/\s+/g, " ").trim() : "";
121
141
  if (action === "stop_recording" && !keys) return { action };
142
+ if (action === "step" && keys === "label") {
143
+ const label = cleanStep(args.label);
144
+ if (label && label.length <= 200) return { action, label, source: "mark" };
145
+ }
122
146
  if (action === "screenshot" && keys === "title" && title && title.length <= 200) return { action, title };
123
147
  if (action === "start_recording" && ["title", "maxSeconds,title"].includes(keys) && title && title.length <= 200 && (args.maxSeconds === undefined || (Number.isInteger(args.maxSeconds) && args.maxSeconds >= 5 && args.maxSeconds <= 300)))
124
148
  return { action, title, ...(args.maxSeconds === undefined ? {} : { maxSeconds: args.maxSeconds }) };
@@ -130,9 +154,14 @@ export function normalizeCall(value) {
130
154
  throw new Error("Invalid tool call");
131
155
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k)))
132
156
  throw new Error("Unknown call fields");
133
- const { name, arguments: args = {} } = value;
134
- if (!args || typeof args !== "object" || Array.isArray(args))
157
+ const { name, arguments: given = {} } = value;
158
+ if (!given || typeof given !== "object" || Array.isArray(given))
135
159
  throw new Error("Invalid arguments");
160
+ // `step` is the person's description, kept by the broker for the recording
161
+ // timeline; it never reaches the driver or a review.
162
+ const { step: described, ...args } = given;
163
+ if (Object.hasOwn(given, "step") && (name === "get_desktop_state" || !cleanStep(described) || cleanStep(described).length > 200))
164
+ throw new Error("Unsupported tool or arguments");
136
165
  const keys = Object.keys(args).sort().join(",");
137
166
  if (name === "get_desktop_state" && !keys) return { name, arguments: {} };
138
167
  if (
package/http-link.js CHANGED
@@ -2727,12 +2727,15 @@ var captureCompleteResponse = z9.object({ capture: captureView });
2727
2727
  var screenCaptureRequest = z9.discriminatedUnion("action", [
2728
2728
  z9.object({ action: z9.literal("screenshot"), title }).strict(),
2729
2729
  z9.object({ action: z9.literal("start_recording"), title, maxSeconds: z9.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
2730
- z9.object({ action: z9.literal("stop_recording") }).strict()
2730
+ z9.object({ action: z9.literal("stop_recording") }).strict(),
2731
+ // A step on the recording's timeline: an action's own description, or a moment the agent marks.
2732
+ z9.object({ action: z9.literal("step"), label: title, source: z9.enum(["action", "mark"]) }).strict()
2731
2733
  ]);
2732
2734
  var screenCaptureResponse = z9.discriminatedUnion("action", [
2733
2735
  z9.object({ action: z9.literal("screenshot"), capture: captureView }),
2734
2736
  z9.object({ action: z9.literal("start_recording"), recordingId: z9.uuid(), stopsAt: z9.iso.datetime() }),
2735
- z9.object({ action: z9.literal("stop_recording"), capture: captureView })
2737
+ z9.object({ action: z9.literal("stop_recording"), capture: captureView }),
2738
+ z9.object({ action: z9.literal("step"), recorded: z9.boolean() })
2736
2739
  ]);
2737
2740
  var capturePaths = {
2738
2741
  begin: (runId) => `/v1/runs/${encodeURIComponent(runId)}/captures`,
@@ -4118,7 +4121,7 @@ var InvalidIdError = class extends DaemonError {
4118
4121
  // package.json
4119
4122
  var package_default = {
4120
4123
  name: "@mikka/daemon",
4121
- version: "0.0.129",
4124
+ version: "0.0.131",
4122
4125
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4123
4126
  type: "module",
4124
4127
  private: true,
@@ -4178,7 +4181,7 @@ var package_default = {
4178
4181
  engines: {
4179
4182
  node: ">=24"
4180
4183
  },
4181
- gitHead: "26342727de268b71e41b110fd8f4785223f3fc0f"
4184
+ gitHead: "a68a3eba7b9d42b907037a4153b9645bf525d42e"
4182
4185
  };
4183
4186
 
4184
4187
  // src/paths.ts
package/login.js CHANGED
@@ -3726,7 +3726,7 @@ var ServerUnreachableError = class extends DaemonError {
3726
3726
  // package.json
3727
3727
  var package_default = {
3728
3728
  name: "@mikka/daemon",
3729
- version: "0.0.129",
3729
+ version: "0.0.131",
3730
3730
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3731
3731
  type: "module",
3732
3732
  private: true,
@@ -3786,7 +3786,7 @@ var package_default = {
3786
3786
  engines: {
3787
3787
  node: ">=24"
3788
3788
  },
3789
- gitHead: "26342727de268b71e41b110fd8f4785223f3fc0f"
3789
+ gitHead: "a68a3eba7b9d42b907037a4153b9645bf525d42e"
3790
3790
  };
3791
3791
 
3792
3792
  // src/paths.ts
@@ -3844,12 +3844,15 @@ var captureCompleteResponse = z23.object({ capture: captureView });
3844
3844
  var screenCaptureRequest = z23.discriminatedUnion("action", [
3845
3845
  z23.object({ action: z23.literal("screenshot"), title }).strict(),
3846
3846
  z23.object({ action: z23.literal("start_recording"), title, maxSeconds: z23.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
3847
- z23.object({ action: z23.literal("stop_recording") }).strict()
3847
+ z23.object({ action: z23.literal("stop_recording") }).strict(),
3848
+ // A step on the recording's timeline: an action's own description, or a moment the agent marks.
3849
+ z23.object({ action: z23.literal("step"), label: title, source: z23.enum(["action", "mark"]) }).strict()
3848
3850
  ]);
3849
3851
  var screenCaptureResponse = z23.discriminatedUnion("action", [
3850
3852
  z23.object({ action: z23.literal("screenshot"), capture: captureView }),
3851
3853
  z23.object({ action: z23.literal("start_recording"), recordingId: z23.uuid(), stopsAt: z23.iso.datetime() }),
3852
- z23.object({ action: z23.literal("stop_recording"), capture: captureView })
3854
+ z23.object({ action: z23.literal("stop_recording"), capture: captureView }),
3855
+ z23.object({ action: z23.literal("step"), recorded: z23.boolean() })
3853
3856
  ]);
3854
3857
 
3855
3858
  // src/run-mailbox.ts
package/main.js CHANGED
@@ -3773,7 +3773,7 @@ import { join as join5 } from "node:path";
3773
3773
  // package.json
3774
3774
  var package_default = {
3775
3775
  name: "@mikka/daemon",
3776
- version: "0.0.129",
3776
+ version: "0.0.131",
3777
3777
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
3778
3778
  type: "module",
3779
3779
  private: true,
@@ -3833,7 +3833,7 @@ var package_default = {
3833
3833
  engines: {
3834
3834
  node: ">=24"
3835
3835
  },
3836
- gitHead: "26342727de268b71e41b110fd8f4785223f3fc0f"
3836
+ gitHead: "a68a3eba7b9d42b907037a4153b9645bf525d42e"
3837
3837
  };
3838
3838
 
3839
3839
  // src/paths.ts
@@ -4120,12 +4120,15 @@ var captureCompleteResponse = z7.object({ capture: captureView });
4120
4120
  var screenCaptureRequest = z7.discriminatedUnion("action", [
4121
4121
  z7.object({ action: z7.literal("screenshot"), title }).strict(),
4122
4122
  z7.object({ action: z7.literal("start_recording"), title, maxSeconds: z7.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
4123
- z7.object({ action: z7.literal("stop_recording") }).strict()
4123
+ z7.object({ action: z7.literal("stop_recording") }).strict(),
4124
+ // A step on the recording's timeline: an action's own description, or a moment the agent marks.
4125
+ z7.object({ action: z7.literal("step"), label: title, source: z7.enum(["action", "mark"]) }).strict()
4124
4126
  ]);
4125
4127
  var screenCaptureResponse = z7.discriminatedUnion("action", [
4126
4128
  z7.object({ action: z7.literal("screenshot"), capture: captureView }),
4127
4129
  z7.object({ action: z7.literal("start_recording"), recordingId: z7.uuid(), stopsAt: z7.iso.datetime() }),
4128
- z7.object({ action: z7.literal("stop_recording"), capture: captureView })
4130
+ z7.object({ action: z7.literal("stop_recording"), capture: captureView }),
4131
+ z7.object({ action: z7.literal("step"), recorded: z7.boolean() })
4129
4132
  ]);
4130
4133
 
4131
4134
  // ../protocol/src/accounts.ts
@@ -13127,7 +13130,12 @@ async function detectComputerDriver(binary = "cua-driver") {
13127
13130
  return null;
13128
13131
  }
13129
13132
  }
13130
- var CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording" };
13133
+ var CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording", mark_recording_step: "step" };
13134
+ var cleanStep = (value) => typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
13135
+ function actionStep(value) {
13136
+ const label2 = cleanStep(value?.arguments?.step);
13137
+ return label2 && label2.length <= 200 ? label2 : null;
13138
+ }
13131
13139
  function normalizeCaptureCall(value) {
13132
13140
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid tool call");
13133
13141
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k))) throw new Error("Unknown call fields");
@@ -13137,6 +13145,10 @@ function normalizeCaptureCall(value) {
13137
13145
  const keys = Object.keys(args).sort().join(",");
13138
13146
  const title2 = typeof args.title === "string" ? args.title.replace(/\s+/g, " ").trim() : "";
13139
13147
  if (action === "stop_recording" && !keys) return { action };
13148
+ if (action === "step" && keys === "label") {
13149
+ const label2 = cleanStep(args.label);
13150
+ if (label2 && label2.length <= 200) return { action, label: label2, source: "mark" };
13151
+ }
13140
13152
  if (action === "screenshot" && keys === "title" && title2 && title2.length <= 200) return { action, title: title2 };
13141
13153
  if (action === "start_recording" && ["title", "maxSeconds,title"].includes(keys) && title2 && title2.length <= 200 && (args.maxSeconds === void 0 || Number.isInteger(args.maxSeconds) && args.maxSeconds >= 5 && args.maxSeconds <= 300))
13142
13154
  return { action, title: title2, ...args.maxSeconds === void 0 ? {} : { maxSeconds: args.maxSeconds } };
@@ -13147,9 +13159,12 @@ function normalizeCall(value) {
13147
13159
  throw new Error("Invalid tool call");
13148
13160
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k)))
13149
13161
  throw new Error("Unknown call fields");
13150
- const { name, arguments: args = {} } = value;
13151
- if (!args || typeof args !== "object" || Array.isArray(args))
13162
+ const { name, arguments: given = {} } = value;
13163
+ if (!given || typeof given !== "object" || Array.isArray(given))
13152
13164
  throw new Error("Invalid arguments");
13165
+ const { step: described, ...args } = given;
13166
+ if (Object.hasOwn(given, "step") && (name === "get_desktop_state" || !cleanStep(described) || cleanStep(described).length > 200))
13167
+ throw new Error("Unsupported tool or arguments");
13153
13168
  const keys = Object.keys(args).sort().join(",");
13154
13169
  if (name === "get_desktop_state" && !keys) return { name, arguments: {} };
13155
13170
  if (name === "click" && keys === "x,y" && [args.x, args.y].every((v2) => Number.isInteger(v2) && v2 >= 0 && v2 <= 1e5))
@@ -13276,6 +13291,8 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
13276
13291
  // src/computer/broker.mjs
13277
13292
  var ComputerBroker = class {
13278
13293
  grants = /* @__PURE__ */ new Map();
13294
+ // runId → when its screen recording stops by itself; only set while one runs.
13295
+ recordingUntil = /* @__PURE__ */ new Map();
13279
13296
  pending = /* @__PURE__ */ new Map();
13280
13297
  sockets = /* @__PURE__ */ new Set();
13281
13298
  suspended = false;
@@ -13354,6 +13371,24 @@ var ComputerBroker = class {
13354
13371
  if (!grant || signal?.aborted || !this.permitted(grant.runId))
13355
13372
  return Promise.reject(new Error("Not permitted"));
13356
13373
  const call = normalizeCall(value);
13374
+ const step = actionStep(value);
13375
+ return this.requestCall(token, grant, call, signal).then((result) => {
13376
+ this.markStep(grant.runId, step);
13377
+ return result;
13378
+ });
13379
+ }
13380
+ /** While this run records, a done action's description becomes a step on the recording (best effort; never fails the action). */
13381
+ markStep(runId, label2) {
13382
+ const until = this.recordingUntil.get(runId);
13383
+ if (!label2 || !this.capture || until === void 0) return;
13384
+ if (this.now() > until) {
13385
+ this.recordingUntil.delete(runId);
13386
+ return;
13387
+ }
13388
+ void Promise.resolve().then(() => this.capture(runId, { action: "step", label: label2, source: "action" })).catch(() => {
13389
+ });
13390
+ }
13391
+ requestCall(token, grant, call, signal) {
13357
13392
  const actionId = randomUUID8();
13358
13393
  const assertLive = () => {
13359
13394
  if (this.suspended || signal?.aborted || this.grants.get(token) !== grant || this.driver?.fingerprint !== grant.fingerprint || !this.permitted(grant.runId))
@@ -13406,7 +13441,10 @@ var ComputerBroker = class {
13406
13441
  return { error: "Not permitted" };
13407
13442
  const call = normalizeCaptureCall(value);
13408
13443
  try {
13409
- return { result: await this.capture(grant.runId, call, signal) };
13444
+ const result = await this.capture(grant.runId, call, signal);
13445
+ if (call.action === "start_recording" && typeof result?.stopsAt === "string") this.recordingUntil.set(grant.runId, Date.parse(result.stopsAt));
13446
+ if (call.action === "stop_recording") this.recordingUntil.delete(grant.runId);
13447
+ return { result };
13410
13448
  } catch (error) {
13411
13449
  const detail = typeof error?.safeMessage === "string" ? error.safeMessage.slice(0, 300) : void 0;
13412
13450
  return { error: "Capture failed", ...detail ? { detail } : {} };
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "version": 1,
3
- "sourceSha": "26342727de268b71e41b110fd8f4785223f3fc0f",
3
+ "sourceSha": "a68a3eba7b9d42b907037a4153b9645bf525d42e",
4
4
  "repository": "alexj11324/Mikka",
5
- "buildRunId": "41271312573",
5
+ "buildRunId": "41271551957",
6
6
  "buildKind": "github-actions-main",
7
7
  "sourceLockSha256": "c99f1e4f641d8e004cfe807653478e10f91e53fcf47102add5f4c154cdc1cb57",
8
- "createdAt": "2026-11-01T04:13:48.510Z",
8
+ "createdAt": "2026-11-01T04:21:10.976Z",
9
9
  "sbom": "sbom.cdx.json",
10
10
  "files": [
11
11
  {
@@ -40,18 +40,18 @@
40
40
  },
41
41
  {
42
42
  "path": "cli.js",
43
- "size": 632263,
44
- "sha256": "824332a07fb39e1619afc8eec9bb9cbdb3f22ac0c967b5ca7bdf30aab708394f"
43
+ "size": 634339,
44
+ "sha256": "8cf0737bcd96d7bae0e0323c447ebf36c20a5055ca3d4b7f4bf8695222e5e59d"
45
45
  },
46
46
  {
47
47
  "path": "client.js",
48
48
  "size": 139865,
49
- "sha256": "6943ec6ee05c36ad686e70a0e8732bb119c8c949aa65c871819dd9dccbfab50d"
49
+ "sha256": "68007a12a73fa1215ea5d593d8120b24cefdb33b9fe2138623ef88443777e71a"
50
50
  },
51
51
  {
52
52
  "path": "computer/driver.mjs",
53
- "size": 12788,
54
- "sha256": "ce40e50779ef36e3f5f333b1315e7c53c4746f5ac60c0ffa4aae16a03bcf39ad"
53
+ "size": 14571,
54
+ "sha256": "7368022aad90b87836a9bcebe726a9e683ff12fdc6a9ab4d98fd2aa641a3910d"
55
55
  },
56
56
  {
57
57
  "path": "computer/proxy.mjs",
@@ -170,8 +170,8 @@
170
170
  },
171
171
  {
172
172
  "path": "http-link.js",
173
- "size": 180835,
174
- "sha256": "1861df72990fc61cc0273195a0e980317cd9eb54c7c8b85b10cd6443851e42c5"
173
+ "size": 181108,
174
+ "sha256": "1af0389f07f1e7aa4056b486ffd60c822a37546be7cf108a4a33e02be60653d0"
175
175
  },
176
176
  {
177
177
  "path": "log.js",
@@ -180,13 +180,13 @@
180
180
  },
181
181
  {
182
182
  "path": "login.js",
183
- "size": 144321,
184
- "sha256": "49d0f568d4f8e7831da15829fd378f71303268ea304dc4a25b5ea92f759192ea"
183
+ "size": 144600,
184
+ "sha256": "f5b8598376e3b23eab57eb70c41c863bf1358b7e768fd4729092567048a7ac01"
185
185
  },
186
186
  {
187
187
  "path": "main.js",
188
- "size": 577894,
189
- "sha256": "9b586babcb211d961af4af4191cd01d4d62d441e92c2f5b09eb7d4949247e9cd"
188
+ "size": 579964,
189
+ "sha256": "5be5fc8581af42706093ca65ce0de1fd961d76673380768a6bc2a7fac34edea4"
190
190
  },
191
191
  {
192
192
  "path": "mikka-mcp.mjs",
@@ -195,23 +195,23 @@
195
195
  },
196
196
  {
197
197
  "path": "mikka.js",
198
- "size": 632279,
199
- "sha256": "7122bb354a1934d030e790c21475d28d073913e849760f438490d70383ae7868"
198
+ "size": 634355,
199
+ "sha256": "788edc531b7f16387a1cd3f2cc8dab27d03a6f6fad271ec5ee564f332e4944a1"
200
200
  },
201
201
  {
202
202
  "path": "npm-shrinkwrap.json",
203
203
  "size": 78117,
204
- "sha256": "3a284d1dd1504b12df16f1b565241876c9b61a66b773951963e84639c098d38e"
204
+ "sha256": "1c43cf0a8e20bb34317f6381bf570cd6c6eba5f350d440c24bbfd09efce71317"
205
205
  },
206
206
  {
207
207
  "path": "package.json",
208
208
  "size": 1247,
209
- "sha256": "e69306bbc9c91693108a3ec4cf5e4fe4fb0649bffaa8d28f47281ce5e5218186"
209
+ "sha256": "604e8853d5e7ca66fb6a54b8b7b40f82344980fbae6d186194f2ffc3f03c0c06"
210
210
  },
211
211
  {
212
212
  "path": "paths.js",
213
213
  "size": 4138,
214
- "sha256": "88fcd6109465c92368a3e623e9a2f30e676cbbf7e243b0a6f991fcddc06a6965"
214
+ "sha256": "94aa27c86f3c655d5aa9eeed1394d717fa1ef561f61d45cfe0751cf2db517a89"
215
215
  },
216
216
  {
217
217
  "path": "sandbox.js",
@@ -221,7 +221,7 @@
221
221
  {
222
222
  "path": "sbom.cdx.json",
223
223
  "size": 144314,
224
- "sha256": "a89a2a7e97091f6f3f146c939ca4cd704417f4b4d004db7ef91e6c668c5e5081"
224
+ "sha256": "179f9e93f8adf35ba423e33efaed40e8b385528a2b1f7c41bccd46ad1fba53b7"
225
225
  }
226
226
  ]
227
227
  }
package/mikka.js CHANGED
@@ -4458,7 +4458,7 @@ import { join as join4 } from "node:path";
4458
4458
  // package.json
4459
4459
  var package_default = {
4460
4460
  name: "@mikka/daemon",
4461
- version: "0.0.129",
4461
+ version: "0.0.131",
4462
4462
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
4463
4463
  type: "module",
4464
4464
  private: true,
@@ -4518,7 +4518,7 @@ var package_default = {
4518
4518
  engines: {
4519
4519
  node: ">=24"
4520
4520
  },
4521
- gitHead: "26342727de268b71e41b110fd8f4785223f3fc0f"
4521
+ gitHead: "a68a3eba7b9d42b907037a4153b9645bf525d42e"
4522
4522
  };
4523
4523
 
4524
4524
  // src/paths.ts
@@ -4982,12 +4982,15 @@ var captureCompleteResponse = z23.object({ capture: captureView });
4982
4982
  var screenCaptureRequest = z23.discriminatedUnion("action", [
4983
4983
  z23.object({ action: z23.literal("screenshot"), title }).strict(),
4984
4984
  z23.object({ action: z23.literal("start_recording"), title, maxSeconds: z23.number().int().min(5).max(RECORDING_MAX_SECONDS).optional() }).strict(),
4985
- z23.object({ action: z23.literal("stop_recording") }).strict()
4985
+ z23.object({ action: z23.literal("stop_recording") }).strict(),
4986
+ // A step on the recording's timeline: an action's own description, or a moment the agent marks.
4987
+ z23.object({ action: z23.literal("step"), label: title, source: z23.enum(["action", "mark"]) }).strict()
4986
4988
  ]);
4987
4989
  var screenCaptureResponse = z23.discriminatedUnion("action", [
4988
4990
  z23.object({ action: z23.literal("screenshot"), capture: captureView }),
4989
4991
  z23.object({ action: z23.literal("start_recording"), recordingId: z23.uuid(), stopsAt: z23.iso.datetime() }),
4990
- z23.object({ action: z23.literal("stop_recording"), capture: captureView })
4992
+ z23.object({ action: z23.literal("stop_recording"), capture: captureView }),
4993
+ z23.object({ action: z23.literal("step"), recorded: z23.boolean() })
4991
4994
  ]);
4992
4995
  var capturePaths = {
4993
4996
  begin: (runId) => `/v1/runs/${encodeURIComponent(runId)}/captures`,
@@ -14053,7 +14056,12 @@ async function detectComputerDriver(binary = "cua-driver") {
14053
14056
  return null;
14054
14057
  }
14055
14058
  }
14056
- var CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording" };
14059
+ var CAPTURE_ACTIONS = { capture_screenshot: "screenshot", start_screen_recording: "start_recording", stop_screen_recording: "stop_recording", mark_recording_step: "step" };
14060
+ var cleanStep = (value) => typeof value === "string" ? value.replace(/\s+/g, " ").trim() : "";
14061
+ function actionStep(value) {
14062
+ const label2 = cleanStep(value?.arguments?.step);
14063
+ return label2 && label2.length <= 200 ? label2 : null;
14064
+ }
14057
14065
  function normalizeCaptureCall(value) {
14058
14066
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid tool call");
14059
14067
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k))) throw new Error("Unknown call fields");
@@ -14063,6 +14071,10 @@ function normalizeCaptureCall(value) {
14063
14071
  const keys = Object.keys(args).sort().join(",");
14064
14072
  const title2 = typeof args.title === "string" ? args.title.replace(/\s+/g, " ").trim() : "";
14065
14073
  if (action === "stop_recording" && !keys) return { action };
14074
+ if (action === "step" && keys === "label") {
14075
+ const label2 = cleanStep(args.label);
14076
+ if (label2 && label2.length <= 200) return { action, label: label2, source: "mark" };
14077
+ }
14066
14078
  if (action === "screenshot" && keys === "title" && title2 && title2.length <= 200) return { action, title: title2 };
14067
14079
  if (action === "start_recording" && ["title", "maxSeconds,title"].includes(keys) && title2 && title2.length <= 200 && (args.maxSeconds === void 0 || Number.isInteger(args.maxSeconds) && args.maxSeconds >= 5 && args.maxSeconds <= 300))
14068
14080
  return { action, title: title2, ...args.maxSeconds === void 0 ? {} : { maxSeconds: args.maxSeconds } };
@@ -14073,9 +14085,12 @@ function normalizeCall(value) {
14073
14085
  throw new Error("Invalid tool call");
14074
14086
  if (Object.keys(value).some((k) => !["name", "arguments"].includes(k)))
14075
14087
  throw new Error("Unknown call fields");
14076
- const { name, arguments: args = {} } = value;
14077
- if (!args || typeof args !== "object" || Array.isArray(args))
14088
+ const { name, arguments: given = {} } = value;
14089
+ if (!given || typeof given !== "object" || Array.isArray(given))
14078
14090
  throw new Error("Invalid arguments");
14091
+ const { step: described, ...args } = given;
14092
+ if (Object.hasOwn(given, "step") && (name === "get_desktop_state" || !cleanStep(described) || cleanStep(described).length > 200))
14093
+ throw new Error("Unsupported tool or arguments");
14079
14094
  const keys = Object.keys(args).sort().join(",");
14080
14095
  if (name === "get_desktop_state" && !keys) return { name, arguments: {} };
14081
14096
  if (name === "click" && keys === "x,y" && [args.x, args.y].every((v2) => Number.isInteger(v2) && v2 >= 0 && v2 <= 1e5))
@@ -14202,6 +14217,8 @@ async function executeDriver(driver, input, display, leaseGuard, assertLive = ()
14202
14217
  // src/computer/broker.mjs
14203
14218
  var ComputerBroker = class {
14204
14219
  grants = /* @__PURE__ */ new Map();
14220
+ // runId → when its screen recording stops by itself; only set while one runs.
14221
+ recordingUntil = /* @__PURE__ */ new Map();
14205
14222
  pending = /* @__PURE__ */ new Map();
14206
14223
  sockets = /* @__PURE__ */ new Set();
14207
14224
  suspended = false;
@@ -14280,6 +14297,24 @@ var ComputerBroker = class {
14280
14297
  if (!grant || signal?.aborted || !this.permitted(grant.runId))
14281
14298
  return Promise.reject(new Error("Not permitted"));
14282
14299
  const call = normalizeCall(value);
14300
+ const step = actionStep(value);
14301
+ return this.requestCall(token, grant, call, signal).then((result) => {
14302
+ this.markStep(grant.runId, step);
14303
+ return result;
14304
+ });
14305
+ }
14306
+ /** While this run records, a done action's description becomes a step on the recording (best effort; never fails the action). */
14307
+ markStep(runId, label2) {
14308
+ const until = this.recordingUntil.get(runId);
14309
+ if (!label2 || !this.capture || until === void 0) return;
14310
+ if (this.now() > until) {
14311
+ this.recordingUntil.delete(runId);
14312
+ return;
14313
+ }
14314
+ void Promise.resolve().then(() => this.capture(runId, { action: "step", label: label2, source: "action" })).catch(() => {
14315
+ });
14316
+ }
14317
+ requestCall(token, grant, call, signal) {
14283
14318
  const actionId = randomUUID9();
14284
14319
  const assertLive = () => {
14285
14320
  if (this.suspended || signal?.aborted || this.grants.get(token) !== grant || this.driver?.fingerprint !== grant.fingerprint || !this.permitted(grant.runId))
@@ -14332,7 +14367,10 @@ var ComputerBroker = class {
14332
14367
  return { error: "Not permitted" };
14333
14368
  const call = normalizeCaptureCall(value);
14334
14369
  try {
14335
- return { result: await this.capture(grant.runId, call, signal) };
14370
+ const result = await this.capture(grant.runId, call, signal);
14371
+ if (call.action === "start_recording" && typeof result?.stopsAt === "string") this.recordingUntil.set(grant.runId, Date.parse(result.stopsAt));
14372
+ if (call.action === "stop_recording") this.recordingUntil.delete(grant.runId);
14373
+ return { result };
14336
14374
  } catch (error) {
14337
14375
  const detail = typeof error?.safeMessage === "string" ? error.safeMessage.slice(0, 300) : void 0;
14338
14376
  return { error: "Capture failed", ...detail ? { detail } : {} };
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@aspectlylabs/mikka",
3
- "version": "0.0.129",
3
+ "version": "0.0.131",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@aspectlylabs/mikka",
9
- "version": "0.0.129",
9
+ "version": "0.0.131",
10
10
  "license": "AGPL-3.0-only",
11
11
  "dependencies": {
12
12
  "@agentclientprotocol/sdk": "1.9.0",
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@aspectlylabs/mikka",
3
- "version": "0.0.129",
3
+ "version": "0.0.131",
4
4
  "description": "Local Mikka daemon: runs agents through the user's own CLIs",
5
- "gitHead": "26342727de268b71e41b110fd8f4785223f3fc0f",
5
+ "gitHead": "a68a3eba7b9d42b907037a4153b9645bf525d42e",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "license": "AGPL-3.0-only",
package/paths.js CHANGED
@@ -6,7 +6,7 @@ import { join } from "node:path";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "@mikka/daemon",
9
- version: "0.0.129",
9
+ version: "0.0.131",
10
10
  description: "Local Mikka daemon: runs agents through the user's own CLIs",
11
11
  type: "module",
12
12
  private: true,
@@ -66,7 +66,7 @@ var package_default = {
66
66
  engines: {
67
67
  node: ">=24"
68
68
  },
69
- gitHead: "26342727de268b71e41b110fd8f4785223f3fc0f"
69
+ gitHead: "a68a3eba7b9d42b907037a4153b9645bf525d42e"
70
70
  };
71
71
 
72
72
  // src/paths.ts
package/sbom.cdx.json CHANGED
@@ -2,10 +2,10 @@
2
2
  "$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
3
3
  "bomFormat": "CycloneDX",
4
4
  "specVersion": "1.5",
5
- "serialNumber": "urn:uuid:d1ad240d-c3cb-4f21-8cad-19b6a2bf9c13",
5
+ "serialNumber": "urn:uuid:e9d594f9-d36a-4c7d-8b05-f4828a4faf2d",
6
6
  "version": 1,
7
7
  "metadata": {
8
- "timestamp": "2026-11-01T04:13:47.699Z",
8
+ "timestamp": "2026-11-01T04:21:10.240Z",
9
9
  "lifecycles": [
10
10
  {
11
11
  "phase": "pre-build"
@@ -19,13 +19,13 @@
19
19
  }
20
20
  ],
21
21
  "component": {
22
- "bom-ref": "@aspectlylabs/mikka@0.0.129",
22
+ "bom-ref": "@aspectlylabs/mikka@0.0.131",
23
23
  "type": "library",
24
- "name": ".retained-build-5ZBjN5",
25
- "version": "0.0.129",
24
+ "name": ".retained-build-c6MmNJ",
25
+ "version": "0.0.131",
26
26
  "scope": "required",
27
27
  "description": "Local Mikka daemon: runs agents through the user's own CLIs",
28
- "purl": "pkg:npm/%40aspectlylabs/mikka@0.0.129",
28
+ "purl": "pkg:npm/%40aspectlylabs/mikka@0.0.131",
29
29
  "properties": [],
30
30
  "externalReferences": [
31
31
  {
@@ -4627,7 +4627,7 @@
4627
4627
  ],
4628
4628
  "dependencies": [
4629
4629
  {
4630
- "ref": "@aspectlylabs/mikka@0.0.129",
4630
+ "ref": "@aspectlylabs/mikka@0.0.131",
4631
4631
  "dependsOn": [
4632
4632
  "@agentclientprotocol/sdk@1.9.0",
4633
4633
  "@anthropic-ai/claude-agent-sdk@0.3.305",