(args: unknown)
| 659 | export const COMPUTER_USE_WITHHELD_VALUE = /^<(?:text(?::\d+)?|point|value|\d+ items?)>$/; |
| 660 | |
| 661 | export function computerUseModelCallArgs(args: unknown): ComputerUseModelCallArgs { |
| 662 | const record = asRecord(args); |
| 663 | const rawAction = ownDataProperty(record, 'action'); |
| 664 | // The action the model sent, whatever it was. Collapsing an unrecognised name |
| 665 | // to `unknown` is the approval summary's job — there `knownAction` decides |
| 666 | // what a person is asked to allow. Here it erases the one thing the record is |
| 667 | // for: a model whose call was rejected for naming an action the schema does |
| 668 | // not carry reads its own history as `action: 'unknown'` and cannot connect |
| 669 | // the rejection to what it sent. |
| 670 | const action = |
| 671 | typeof rawAction === 'string' && rawAction.length > 0 |
| 672 | ? boundedDisplay(redactSecrets(rawAction), 64) |
| 673 | : 'unknown'; |
| 674 | const app = ownDataProperty(record, 'app'); |
| 675 | const windowId = ownDataProperty(record, 'window_id') ?? ownDataProperty(record, 'windowId'); |
| 676 | const observationId = |
| 677 | ownDataProperty(record, 'observation_id') ?? ownDataProperty(record, 'observationId'); |
| 678 | const elementId = ownDataProperty(record, 'element_id') ?? ownDataProperty(record, 'elementId'); |
| 679 | // Every remaining argument the model sent, as a shape. The approval summary |
| 680 | // this replaces names five keys and drops the rest, so `press_key` came back |
| 681 | // to the model as a call with no key, `set_value` as one with no value, |
| 682 | // `scroll` as one with no direction. The model reads that as the shape that |
| 683 | // worked and sends it again — and a real session refused eighteen calls for |
| 684 | // missing exactly the fields the projection had removed. The privacy boundary |
| 685 | // is about values, and only values are withheld. |
| 686 | const rest: Record< |
| 687 | string, |
| 688 | string | number | boolean | readonly number[] | readonly ComputerUseModelCallStep[] |
| 689 | > = {}; |
| 690 | const plain = MODEL_CALL_PLAIN_VALUES.get(action); |
| 691 | for (const [key, value] of Object.entries(record ?? {})) { |
| 692 | if (MODEL_CALL_NAMED_ARGS.has(key) || HOST_ONLY_ARGS.has(key)) continue; |
| 693 | if (MODEL_CALL_GEOMETRY_ARGS.has(key)) { |
| 694 | rest[key] = integerTuple(value) ?? shapeOf(value); |
| 695 | continue; |
| 696 | } |
| 697 | if (key === 'steps') { |
| 698 | const steps = projectSteps(value); |
| 699 | rest[key] = steps ?? shapeOf(value); |
| 700 | continue; |
| 701 | } |
| 702 | if (plain?.has(key)) { |
| 703 | rest[key] = |
| 704 | typeof value === 'string' |
| 705 | ? boundedDisplay(redactSecrets(value), 256) |
| 706 | : typeof value === 'number' || typeof value === 'boolean' |
| 707 | ? value |
| 708 | : shapeOf(value); |
| 709 | continue; |
| 710 | } |
| 711 | rest[key] = shapeOf(value); |
| 712 | } |
| 713 | return { |
| 714 | action, |
| 715 | ...(typeof app === 'string' && app.length > 0 |
| 716 | ? { app: boundedDisplay(redactSecrets(app), 256) } |
| 717 | : {}), |
| 718 | ...(typeof windowId === 'number' && Number.isInteger(windowId) ? { window_id: windowId } : {}), |
no test coverage detected