@namzu/sdk 61.0.0 → 61.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -146,6 +146,9 @@ const regionSchema = z.object({
146
146
  // Left when omitted: a model asked to "click the Start button" often leaves
147
147
  // the button out, and refusing that cost a whole round trip for nothing.
148
148
  const mouseButtonSchema = z.enum(['left', 'right', 'middle']).default('left')
149
+ // One to three clicks in a row at the same point: 2 is a double-click. Absent
150
+ // means 1. How many a host can do is its `maxClickCount`.
151
+ const clickCountSchema = z.number().int().min(1).max(3).optional()
149
152
  const screenshotIdSchema = z.string().min(1).optional()
150
153
 
151
154
  const cursorPositionSchema = z.object({ type: z.literal('cursor_position') })
@@ -157,6 +160,7 @@ const mouseClickSchema = z.object({
157
160
  type: z.literal('mouse_click'),
158
161
  at: pointSchema,
159
162
  button: mouseButtonSchema,
163
+ count: clickCountSchema,
160
164
  /** Accepted only to return an explicit refusal; pointer foreground is unsafe. */
161
165
  delivery_mode: z.enum(['background', 'foreground']).optional(),
162
166
  })
@@ -597,6 +601,11 @@ function buildDescription(
597
601
  return finish(lines, caps, available)
598
602
  }
599
603
 
604
+ /** How many clicks in a row one mouse_click may make on this host. */
605
+ function maxClickCount(caps: ComputerUseCapabilities): 1 | 2 | 3 {
606
+ return caps.maxClickCount ?? 1
607
+ }
608
+
600
609
  function finish(
601
610
  lines: string[],
602
611
  caps: ComputerUseCapabilities,
@@ -604,6 +613,10 @@ function finish(
604
613
  ): string {
605
614
  if (caps.mouseClickButtons && available.includes('mouse_click'))
606
615
  lines.push(`Click buttons: ${caps.mouseClickButtons.join(', ') || 'none'}.`)
616
+ if (maxClickCount(caps) > 1 && available.includes('mouse_click'))
617
+ lines.push(
618
+ `Click count: mouse_click takes count up to ${maxClickCount(caps)} (2 is a double-click, 3 a triple-click), with the left button only; 1 when omitted.`,
619
+ )
607
620
  if (caps.mouseDragButtons && available.includes('mouse_drag'))
608
621
  lines.push(`Drag buttons: ${caps.mouseDragButtons.join(', ') || 'none'}.`)
609
622
  return lines.join(' ')
@@ -698,6 +711,17 @@ function hostModelSchema(
698
711
  enum: buttonEnum,
699
712
  description: 'Mouse button; left when omitted.',
700
713
  },
714
+ ...(actions.includes('mouse_click') && maxClickCount(caps) > 1
715
+ ? {
716
+ count: {
717
+ type: 'integer',
718
+ minimum: 1,
719
+ maximum: maxClickCount(caps),
720
+ description:
721
+ 'For mouse_click: how many clicks in a row at the point (2 is a double-click, 3 a triple-click); left button only; 1 when omitted.',
722
+ },
723
+ }
724
+ : {}),
701
725
  direction: {
702
726
  type: 'string',
703
727
  enum: ['up', 'down', 'left', 'right'],
@@ -930,7 +954,9 @@ function itemLabel(
930
954
  case 'mouse_move':
931
955
  return `Move pointer to ${pointLabel(input.to)}`
932
956
  case 'mouse_click':
933
- return `Click ${input.button} at ${pointLabel(input.at)}`
957
+ return `${
958
+ input.count === 2 ? 'Double-click' : input.count === 3 ? 'Triple-click' : 'Click'
959
+ } ${input.button} at ${pointLabel(input.at)}`
934
960
  case 'mouse_drag':
935
961
  return `Drag ${input.button} from ${pointLabel(input.from)} to ${pointLabel(input.to)}`
936
962
  case 'scroll':
@@ -1483,10 +1509,29 @@ export function createComputerUseTool(
1483
1509
  throw new StepFailure(
1484
1510
  `computer_use: action "mouse_click" does not support button "${item.button}" on this host.`,
1485
1511
  )
1512
+ const count = item.count ?? 1
1513
+ if (count > maxClickCount(caps))
1514
+ throw new StepFailure(
1515
+ maxClickCount(caps) === 1
1516
+ ? `computer_use: action "mouse_click" does not support count ${count} on this host; it clicks once per action. Click once, or repeat the click.`
1517
+ : `computer_use: action "mouse_click" does not support count ${count} on this host; it clicks at most ${maxClickCount(caps)} times in a row.`,
1518
+ )
1519
+ if (count > 1 && item.button !== 'left')
1520
+ throw new StepFailure(
1521
+ `computer_use: action "mouse_click" with count ${count} needs the left button; "${item.button}" can only be clicked once.`,
1522
+ )
1486
1523
  const frame = frameFor(frameId)
1487
1524
  const at = mapPoint(frame, item.at, 'at')
1488
1525
  return step(async () => {
1489
- const outcome = await runHost({ type: 'mouse_click', at, button: item.button }, frame)
1526
+ const outcome = await runHost(
1527
+ {
1528
+ type: 'mouse_click',
1529
+ at,
1530
+ button: item.button,
1531
+ ...(count > 1 ? { count: count as 2 | 3 } : {}),
1532
+ },
1533
+ frame,
1534
+ )
1490
1535
  const nudge = coordinateNudge(frame)
1491
1536
  if (!nudge) return outcome
1492
1537
  return typeof outcome === 'string'
@@ -36,6 +36,12 @@ export interface ComputerUseCapabilities {
36
36
  readonly mouseClickButtons?: readonly MouseButton[]
37
37
  /** Supported drag buttons; absent leaves button admission to the host. */
38
38
  readonly mouseDragButtons?: readonly MouseButton[]
39
+ /**
40
+ * The most clicks in a row one `mouse_click` may make (2 is a double-click).
41
+ * Absent means 1: the tool refuses a larger `count` before the host is
42
+ * reached, and does not offer the field to the model.
43
+ */
44
+ readonly maxClickCount?: 1 | 2 | 3
39
45
  /**
40
46
  * Why every flag above is false, when a host loaded but the desktop did
41
47
  * not answer — a WSL process with PowerShell and no interactive Windows
@@ -395,6 +401,12 @@ export type ComputerUseAction =
395
401
  readonly type: 'mouse_click'
396
402
  readonly at: Point
397
403
  readonly button: MouseButton
404
+ /**
405
+ * Clicks in a row at `at`: 2 is a double-click. Absent means 1, and the
406
+ * tool sends it only above 1, only with the left button, and only to a
407
+ * host whose {@link ComputerUseCapabilities.maxClickCount} allows it.
408
+ */
409
+ readonly count?: 1 | 2 | 3
398
410
  }
399
411
  | {
400
412
  readonly type: 'mouse_drag'