@agimon-ai/po-computer-use 0.0.0-alpha.73 → 0.0.0-alpha.75

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.
@@ -1,7 +1,7 @@
1
- import { createApiClient, defineActivityGroup, defineChannelFile, defineFill, defineNativePlugin, defineSessionStore, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
1
+ import { createApiClient, defineActivityGroup, defineChannelFile, defineFill, defineNativePlugin, defineSessionStore, defineToolRenderer, nativeApiTransport, sessionApiAddress } from "@agimon-ai/po-core/native";
2
2
  import { View } from "react-native-unistyles/components/native/View";
3
3
  import { Text } from "react-native-unistyles/components/native/Text";
4
- import { Button, CheckIcon, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, SegmentedControl, fontOf } from "@agimon-ai/po-native-components";
4
+ import { Badge, Button, CheckIcon, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, MessageItem, MessageItemBody, MessageItemHeader, MessageItemStatus, SegmentedControl, fontOf, toolTone } from "@agimon-ai/po-native-components";
5
5
  import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
6
6
  import { StyleSheet } from "react-native-unistyles";
7
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -204,7 +204,7 @@ createApiClient(routes, {
204
204
  });
205
205
  //#endregion
206
206
  //#region src/extensions/workspaces/sessions/(frontend)/fill/_components/ComputerUsePanel.native.tsx
207
- function text(value, fallback) {
207
+ function text$1(value, fallback) {
208
208
  return typeof value === "string" || typeof value === "number" ? String(value) : fallback;
209
209
  }
210
210
  function remaining(ms) {
@@ -222,7 +222,7 @@ function ComputerUseView({ state, targets = [], busy = false, error, submitting
222
222
  label: "Whole desktop",
223
223
  target: { scope: "desktop" }
224
224
  }, ...targets.map((target) => ({
225
- label: `${text(target.applicationName, "Application")}: ${text(target.windowTitle, text(target.windowId, "Window"))}`,
225
+ label: `${text$1(target.applicationName, "Application")}: ${text$1(target.windowTitle, text$1(target.windowId, "Window"))}`,
226
226
  target
227
227
  }))];
228
228
  const chosen = choices[selected] ?? choices[0];
@@ -240,41 +240,41 @@ function ComputerUseView({ state, targets = [], busy = false, error, submitting
240
240
  const total = state.durationMs ?? 3e5;
241
241
  const controlled = state.target?.scope === "desktop" ? "your whole desktop" : typeof state.target?.applicationName === "string" ? state.target.applicationName : "the chosen window";
242
242
  return /* @__PURE__ */ jsxs(View, {
243
- style: styles.panel,
243
+ style: styles$4.panel,
244
244
  children: [
245
245
  /* @__PURE__ */ jsx(Text, {
246
- style: styles.title,
246
+ style: styles$4.title,
247
247
  accessibilityRole: "header",
248
248
  children: "Computer use"
249
249
  }),
250
250
  busy ? /* @__PURE__ */ jsx(Text, {
251
- style: styles.detail,
251
+ style: styles$4.detail,
252
252
  children: "Computer use is busy in another session."
253
253
  }) : null,
254
254
  failure ? /* @__PURE__ */ jsx(Text, {
255
- style: styles.error,
255
+ style: styles$4.error,
256
256
  accessibilityRole: "alert",
257
257
  children: failure
258
258
  }) : null,
259
259
  state.artifact?.status === "ready" ? /* @__PURE__ */ jsxs(View, {
260
- style: styles.row,
260
+ style: styles$4.row,
261
261
  children: [/* @__PURE__ */ jsx(View, {
262
- style: styles.check,
262
+ style: styles$4.check,
263
263
  children: /* @__PURE__ */ jsx(CheckIcon, {
264
264
  size: 12,
265
265
  color: "rail"
266
266
  })
267
267
  }), /* @__PURE__ */ jsx(Text, {
268
- style: styles.text,
268
+ style: styles$4.text,
269
269
  children: "Recording saved to session artifacts."
270
270
  })]
271
271
  }) : null,
272
272
  state.artifact?.failure ? /* @__PURE__ */ jsx(Text, {
273
- style: styles.error,
273
+ style: styles$4.error,
274
274
  children: state.artifact.failure.message
275
275
  }) : null,
276
276
  pending ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text, {
277
- style: styles.text,
277
+ style: styles$4.text,
278
278
  children: "Desktop activation is pending."
279
279
  }), /* @__PURE__ */ jsx(Button, {
280
280
  variant: "outline",
@@ -283,17 +283,17 @@ function ComputerUseView({ state, targets = [], busy = false, error, submitting
283
283
  children: "Cancel activation"
284
284
  })] }) : active ? /* @__PURE__ */ jsxs(Fragment, { children: [
285
285
  /* @__PURE__ */ jsxs(View, {
286
- style: styles.row,
286
+ style: styles$4.row,
287
287
  accessibilityLiveRegion: "polite",
288
- children: [/* @__PURE__ */ jsx(View, { style: styles.dot }), /* @__PURE__ */ jsx(Text, {
289
- style: styles.live,
288
+ children: [/* @__PURE__ */ jsx(View, { style: styles$4.dot }), /* @__PURE__ */ jsx(Text, {
289
+ style: styles$4.live,
290
290
  children: state.phase === "stopping" ? "Po is handing control back" : `Po is controlling ${controlled}`
291
291
  })]
292
292
  }),
293
293
  left === void 0 ? null : /* @__PURE__ */ jsxs(View, {
294
- style: styles.row,
294
+ style: styles$4.row,
295
295
  children: [/* @__PURE__ */ jsx(View, {
296
- style: styles.track,
296
+ style: styles$4.track,
297
297
  accessibilityRole: "progressbar",
298
298
  accessibilityLabel: "Time left",
299
299
  accessibilityValue: {
@@ -301,9 +301,9 @@ function ComputerUseView({ state, targets = [], busy = false, error, submitting
301
301
  max: total,
302
302
  now: Math.max(0, left)
303
303
  },
304
- children: /* @__PURE__ */ jsx(View, { style: [styles.fill, { width: `${Math.min(100, Math.max(0, left / total * 100))}%` }] })
304
+ children: /* @__PURE__ */ jsx(View, { style: [styles$4.fill, { width: `${Math.min(100, Math.max(0, left / total * 100))}%` }] })
305
305
  }), /* @__PURE__ */ jsx(Text, {
306
- style: styles.detail,
306
+ style: styles$4.detail,
307
307
  children: remaining(left)
308
308
  })]
309
309
  }),
@@ -315,7 +315,7 @@ function ComputerUseView({ state, targets = [], busy = false, error, submitting
315
315
  })
316
316
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
317
317
  /* @__PURE__ */ jsx(Text, {
318
- style: styles.detail,
318
+ style: styles$4.detail,
319
319
  children: "Po asks before it takes control. You can stop at any time."
320
320
  }),
321
321
  /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
@@ -442,7 +442,7 @@ function SessionPanel({ sessionId, sendSessionFrame }) {
442
442
  }
443
443
  function ComputerUsePanel(props) {
444
444
  return props.sessionId === null ? /* @__PURE__ */ jsx(Text, {
445
- style: styles.detail,
445
+ style: styles$4.detail,
446
446
  children: "Select a session."
447
447
  }) : /* @__PURE__ */ jsx(SessionPanel, {
448
448
  ...props,
@@ -461,9 +461,9 @@ function ComputerUseConfirmation({ target, durationMs, onConfirm, onCancel }) {
461
461
  desktop ? "your whole desktop" : "this window",
462
462
  "?"
463
463
  ] }) }), /* @__PURE__ */ jsxs(DialogBody, { children: [
464
- /* @__PURE__ */ jsx(DialogDescription, { children: desktop ? "Every app window on the main display, except Po and system security windows." : `${text(target.applicationName, "Application")}: ${text(target.windowTitle, text(target.windowId, "Window"))}` }),
464
+ /* @__PURE__ */ jsx(DialogDescription, { children: desktop ? "Every app window on the main display, except Po and system security windows." : `${text$1(target.applicationName, "Application")}: ${text$1(target.windowTitle, text$1(target.windowId, "Window"))}` }),
465
465
  /* @__PURE__ */ jsxs(Text, {
466
- style: styles.text,
466
+ style: styles$4.text,
467
467
  children: [
468
468
  "For ",
469
469
  durationMs / 6e4,
@@ -471,7 +471,7 @@ function ComputerUseConfirmation({ target, durationMs, onConfirm, onCancel }) {
471
471
  ]
472
472
  }),
473
473
  /* @__PURE__ */ jsxs(Text, {
474
- style: styles.detail,
474
+ style: styles$4.detail,
475
475
  children: [
476
476
  "Po records ",
477
477
  desktop ? "the main display" : "this window",
@@ -479,7 +479,7 @@ function ComputerUseConfirmation({ target, durationMs, onConfirm, onCancel }) {
479
479
  ]
480
480
  }),
481
481
  /* @__PURE__ */ jsx(Text, {
482
- style: styles.detail,
482
+ style: styles$4.detail,
483
483
  children: "Only this session and its approved device receive control."
484
484
  }),
485
485
  /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx(Button, {
@@ -494,7 +494,7 @@ function ComputerUseConfirmation({ target, durationMs, onConfirm, onCancel }) {
494
494
  ] })] })
495
495
  });
496
496
  }
497
- const styles = StyleSheet.create((theme) => ({
497
+ const styles$4 = StyleSheet.create((theme) => ({
498
498
  panel: {
499
499
  gap: theme.spacing(3),
500
500
  uni__dependencies: [0]
@@ -581,6 +581,740 @@ var ComputerUse_activity_computer_use_native_default = defineFill({
581
581
  slot: "activity.computer-use",
582
582
  component: ComputerUsePanel
583
583
  });
584
+ const MS_PER_SECOND = 1e3;
585
+ /** The computer_state call's summary: it always observes the one authorized window. */
586
+ function computerStateCallSummary(_args) {
587
+ return "authorized window";
588
+ }
589
+ /**
590
+ * The computer_action call as its two pieces: the action kind first, the element
591
+ * it targets second. Either may be missing; the empty ones are dropped.
592
+ */
593
+ function computerActionCallParts(args) {
594
+ return [typeof args.kind === "string" ? args.kind : "", typeof args.elementRef === "string" ? args.elementRef : ""].filter(Boolean);
595
+ }
596
+ /** The computer_exec call's summary: the script it ran. */
597
+ function computerExecCallSummary(args) {
598
+ return typeof args.scriptPath === "string" ? args.scriptPath : "";
599
+ }
600
+ /**
601
+ * The script path as its folder and its file name, so a phone header can let the
602
+ * folder truncate while the script name stays whole.
603
+ */
604
+ function computerExecPathParts(path) {
605
+ const cut = path.lastIndexOf("/");
606
+ return cut < 0 ? {
607
+ folder: "",
608
+ name: path
609
+ } : {
610
+ folder: path.slice(0, cut + 1),
611
+ name: path.slice(cut + 1)
612
+ };
613
+ }
614
+ function record(value) {
615
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
616
+ }
617
+ const text = (value) => typeof value === "string" ? value : "";
618
+ const count = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
619
+ /** The result's text blocks joined; images (the screenshot) are dropped, as the web cards drop them. */
620
+ function computerResultText(content) {
621
+ return content.flatMap((block) => {
622
+ const entry = record(block);
623
+ return entry?.type === "text" && typeof entry.text === "string" ? [entry.text] : [];
624
+ }).join("\n");
625
+ }
626
+ /** `AXTextField` as `text field`; a role without the AX prefix is kept as it came. */
627
+ function computerRoleWords(role) {
628
+ if (!role.startsWith("AX")) return role;
629
+ return role.slice(2).replace(/([a-z])([A-Z])/gu, "$1 $2").toLowerCase();
630
+ }
631
+ function element(value) {
632
+ const entry = record(value);
633
+ if (entry === void 0 || typeof entry.ref !== "string") return [];
634
+ return [{
635
+ ref: entry.ref,
636
+ role: computerRoleWords(text(entry.role)),
637
+ label: text(entry.label) || text(entry.value),
638
+ enabled: entry.enabled !== false,
639
+ secure: entry.secure === true
640
+ }];
641
+ }
642
+ /** An observation when the value is one: an application name and an element list. */
643
+ function computerObservationView(value) {
644
+ const entry = record(value);
645
+ if (entry === void 0 || typeof entry.applicationName !== "string" || !Array.isArray(entry.elements)) return void 0;
646
+ const nextOffset = count(entry.nextOffset);
647
+ const artifact = text(entry.screenshotArtifact);
648
+ return {
649
+ applicationName: entry.applicationName,
650
+ windowTitle: text(entry.windowTitle),
651
+ elements: entry.elements.flatMap(element),
652
+ truncated: entry.truncated === true || nextOffset !== void 0,
653
+ ...nextOffset === void 0 ? {} : { nextOffset },
654
+ ...artifact.length > 0 ? { screenshotArtifact: artifact } : {}
655
+ };
656
+ }
657
+ /** One value of a script result as a short phrase: scalars as they read, collections by their size. */
658
+ function phrase(value) {
659
+ if (value === null || value === void 0) return "none";
660
+ if (typeof value === "string") return value;
661
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
662
+ if (Array.isArray(value)) return `${String(value.length)} item${value.length === 1 ? "" : "s"}`;
663
+ const size = Object.keys(value).length;
664
+ return `${String(size)} field${size === 1 ? "" : "s"}`;
665
+ }
666
+ /** A script's return value as fields: an object's own keys, or one `result` field for anything else. */
667
+ function computerResultFields(value) {
668
+ if (value === void 0) return [];
669
+ const entry = record(value);
670
+ if (entry === void 0) return [{
671
+ key: "result",
672
+ value: phrase(value)
673
+ }];
674
+ return Object.entries(entry).map(([key, field]) => ({
675
+ key,
676
+ value: phrase(field)
677
+ }));
678
+ }
679
+ function run(entry) {
680
+ if (!Array.isArray(entry.logs)) return void 0;
681
+ const observation = computerObservationView(entry.observation);
682
+ const metrics = record(entry.metrics);
683
+ const actions = count(metrics?.actions);
684
+ const observations = count(metrics?.observations);
685
+ const durationMs = count(metrics?.durationMs);
686
+ return {
687
+ fields: computerResultFields(entry.result),
688
+ logs: entry.logs.filter((line) => typeof line === "string"),
689
+ ...actions === void 0 ? {} : { actions },
690
+ ...observations === void 0 ? {} : { observations },
691
+ ...durationMs === void 0 ? {} : { duration: `${(durationMs / MS_PER_SECOND).toFixed(1)}s` },
692
+ ...observation === void 0 ? {} : { observation }
693
+ };
694
+ }
695
+ function failure(entry) {
696
+ if (typeof entry.error !== "string") return void 0;
697
+ const completedActions = count(entry.completedActions);
698
+ return {
699
+ reason: entry.error,
700
+ ...completedActions === void 0 ? {} : { completedActions },
701
+ outcomeUncertain: entry.outcomeUncertain === true
702
+ };
703
+ }
704
+ /** The text as lines a card can count: CRLF folded, tabs widened, trailing blank lines dropped. */
705
+ function lines(value) {
706
+ if (value.length === 0) return [];
707
+ const split = value.replaceAll("\r\n", "\n").replaceAll(" ", " ").split("\n");
708
+ while (split.length > 0 && split.at(-1)?.trim() === "") split.pop();
709
+ return split;
710
+ }
711
+ /**
712
+ * A computer tool result as the card lays it out. The tools answer in JSON (an
713
+ * observation, an action's outcome, a script run, a script failure) or in a
714
+ * plain sentence when they fail early; anything that does not parse as a shape
715
+ * the card knows falls back to its text lines.
716
+ */
717
+ function computerResultView(content) {
718
+ const raw = computerResultText(content);
719
+ let parsed;
720
+ try {
721
+ parsed = JSON.parse(raw);
722
+ } catch {
723
+ return {
724
+ kind: "text",
725
+ lines: lines(raw)
726
+ };
727
+ }
728
+ const entry = record(parsed);
729
+ const observation = computerObservationView(parsed);
730
+ if (observation !== void 0) return {
731
+ kind: "observation",
732
+ observation
733
+ };
734
+ const ran = entry === void 0 ? void 0 : run(entry);
735
+ if (ran !== void 0) return {
736
+ kind: "run",
737
+ run: ran
738
+ };
739
+ const failed = entry === void 0 ? void 0 : failure(entry);
740
+ if (failed !== void 0) return {
741
+ kind: "failure",
742
+ failure: failed
743
+ };
744
+ if (entry?.launched === true && typeof entry.applicationName === "string") return {
745
+ kind: "launched",
746
+ applicationName: entry.applicationName,
747
+ bundleId: text(entry.bundleId)
748
+ };
749
+ if (entry?.applied === true) return { kind: "applied" };
750
+ return {
751
+ kind: "text",
752
+ lines: lines(raw)
753
+ };
754
+ }
755
+ /** How many rows the view holds back while collapsed, so the card offers expand only when it reveals something. */
756
+ function computerResultHidden(view) {
757
+ switch (view.kind) {
758
+ case "observation": return Math.max(0, view.observation.elements.length - 5);
759
+ case "run": return Math.max(0, view.run.logs.length - 3);
760
+ case "text": return Math.max(0, view.lines.length - 8);
761
+ default: return 0;
762
+ }
763
+ }
764
+ //#endregion
765
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/_components/ComputerResultBody.native.tsx
766
+ /** The parsed result, or none before the tool answers. */
767
+ function computerResult(props) {
768
+ return props.result === null ? void 0 : computerResultView(props.result.content);
769
+ }
770
+ /** Whether the card has rows to reveal: the header offers expand only then, and never on a failure. */
771
+ function computerResultExpandable(props) {
772
+ const view = computerResult(props);
773
+ return !props.isError && view !== void 0 && computerResultHidden(view) > 0;
774
+ }
775
+ /**
776
+ * The body the three computer tool cards share on native. The web cards print
777
+ * the result's text; the tools answer in JSON, so this lays the parsed result
778
+ * out instead: the window and its elements, a script's figures and logs, an
779
+ * action's outcome. A preview shows while collapsed, as the web's first lines
780
+ * do. A failure shows only its reason in red, with a quiet note of any actions
781
+ * that already ran; the header's edge and outcome already say it failed.
782
+ */
783
+ function ComputerResultBody({ props, expanded }) {
784
+ const { toolName, output, running, isError } = props;
785
+ const view = computerResult(props);
786
+ const testID = `tool-result-${toolName}`;
787
+ if (isError) {
788
+ const failure = view?.kind === "failure" ? view.failure : {
789
+ reason: view?.kind === "text" ? view.lines.join("\n") : output.trim(),
790
+ outcomeUncertain: false
791
+ };
792
+ return failure.reason.length === 0 ? null : /* @__PURE__ */ jsx(MessageItemBody, {
793
+ testID,
794
+ children: /* @__PURE__ */ jsx(FailureBlock, { failure })
795
+ });
796
+ }
797
+ if (view === void 0) return running ? /* @__PURE__ */ jsx(MessageItemBody, {
798
+ testID,
799
+ children: /* @__PURE__ */ jsx(MessageItemStatus, {
800
+ tone: "running",
801
+ children: "running"
802
+ })
803
+ }) : null;
804
+ if (view.kind === "text" && view.lines.length === 0) return null;
805
+ return /* @__PURE__ */ jsx(MessageItemBody, {
806
+ testID,
807
+ children: /* @__PURE__ */ jsxs(View, {
808
+ style: styles$3.stack,
809
+ children: [
810
+ view.kind === "observation" ? /* @__PURE__ */ jsx(ObservationBlock, {
811
+ observation: view.observation,
812
+ expanded
813
+ }) : null,
814
+ view.kind === "run" ? /* @__PURE__ */ jsx(RunBlock, {
815
+ run: view.run,
816
+ expanded
817
+ }) : null,
818
+ view.kind === "applied" ? /* @__PURE__ */ jsx(Text, {
819
+ style: [styles$3.sans, styles$3.text],
820
+ children: "Applied to the element."
821
+ }) : null,
822
+ view.kind === "launched" ? /* @__PURE__ */ jsxs(View, {
823
+ style: styles$3.figure,
824
+ children: [/* @__PURE__ */ jsxs(Text, {
825
+ numberOfLines: 1,
826
+ style: [
827
+ styles$3.sans,
828
+ styles$3.strong,
829
+ styles$3.keep
830
+ ],
831
+ children: ["Opened ", view.applicationName]
832
+ }), /* @__PURE__ */ jsx(Text, {
833
+ numberOfLines: 1,
834
+ style: [
835
+ styles$3.mono,
836
+ styles$3.faint,
837
+ styles$3.yield
838
+ ],
839
+ children: view.bundleId
840
+ })]
841
+ }) : null,
842
+ view.kind === "text" ? /* @__PURE__ */ jsx(TextLines, {
843
+ lines: view.lines,
844
+ expanded
845
+ }) : null,
846
+ running ? /* @__PURE__ */ jsx(MessageItemStatus, {
847
+ tone: "running",
848
+ children: "running"
849
+ }) : null
850
+ ]
851
+ })
852
+ });
853
+ }
854
+ function FailureBlock({ failure }) {
855
+ const done = failure.completedActions;
856
+ const note = [done === void 0 ? "" : `${String(done)} action${done === 1 ? "" : "s"} already ran`, failure.outcomeUncertain ? "the last outcome is uncertain" : ""].filter(Boolean);
857
+ return /* @__PURE__ */ jsxs(View, {
858
+ style: styles$3.stack,
859
+ children: [/* @__PURE__ */ jsx(Text, {
860
+ selectable: true,
861
+ style: [styles$3.sans, styles$3.error],
862
+ children: failure.reason
863
+ }), note.length > 0 ? /* @__PURE__ */ jsxs(Text, {
864
+ style: [styles$3.small, styles$3.faint],
865
+ children: [note.join(", "), "."]
866
+ }) : null]
867
+ });
868
+ }
869
+ function WindowLine({ observation, lead }) {
870
+ return /* @__PURE__ */ jsxs(View, {
871
+ style: styles$3.figure,
872
+ children: [/* @__PURE__ */ jsxs(Text, {
873
+ numberOfLines: 1,
874
+ style: [
875
+ styles$3.sans,
876
+ styles$3.strong,
877
+ styles$3.keep
878
+ ],
879
+ children: [lead === void 0 ? "" : `${lead} `, observation.applicationName]
880
+ }), observation.windowTitle.length > 0 ? /* @__PURE__ */ jsx(Text, {
881
+ numberOfLines: 1,
882
+ style: [
883
+ styles$3.sans,
884
+ styles$3.dim,
885
+ styles$3.yield
886
+ ],
887
+ children: observation.windowTitle
888
+ }) : null]
889
+ });
890
+ }
891
+ function ElementRow({ element }) {
892
+ const secure = element.secure && !element.role.includes("secure");
893
+ const traits = [
894
+ element.role,
895
+ element.enabled ? "" : "disabled",
896
+ secure ? "secure" : ""
897
+ ].filter(Boolean);
898
+ return /* @__PURE__ */ jsxs(View, {
899
+ style: styles$3.row,
900
+ accessibilityLabel: `${element.label} ${traits.join(" ")} ${element.ref}`,
901
+ children: [
902
+ /* @__PURE__ */ jsx(Text, {
903
+ numberOfLines: 1,
904
+ style: [
905
+ styles$3.sans,
906
+ element.enabled ? styles$3.text : styles$3.faint,
907
+ styles$3.yield
908
+ ],
909
+ children: element.label.length > 0 ? element.label : element.role
910
+ }),
911
+ /* @__PURE__ */ jsx(Text, {
912
+ numberOfLines: 1,
913
+ style: [
914
+ styles$3.small,
915
+ styles$3.faint,
916
+ styles$3.keep
917
+ ],
918
+ children: traits.join(" · ")
919
+ }),
920
+ /* @__PURE__ */ jsx(Text, {
921
+ numberOfLines: 1,
922
+ style: [
923
+ styles$3.mono,
924
+ styles$3.faint,
925
+ styles$3.ref
926
+ ],
927
+ children: element.ref
928
+ })
929
+ ]
930
+ });
931
+ }
932
+ function ObservationBlock({ observation, expanded }) {
933
+ const { elements } = observation;
934
+ const shown = expanded ? elements : elements.slice(0, 5);
935
+ const hidden = elements.length - shown.length;
936
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
937
+ /* @__PURE__ */ jsx(WindowLine, { observation }),
938
+ /* @__PURE__ */ jsxs(View, {
939
+ style: styles$3.chips,
940
+ children: [/* @__PURE__ */ jsx(Badge, {
941
+ size: "xs",
942
+ children: `${String(elements.length)} element${elements.length === 1 ? "" : "s"}`
943
+ }), observation.truncated ? /* @__PURE__ */ jsx(Badge, {
944
+ size: "xs",
945
+ tone: "yellow",
946
+ children: observation.nextOffset === void 0 ? "more not shown" : `more from offset ${String(observation.nextOffset)}`
947
+ }) : null]
948
+ }),
949
+ shown.length > 0 ? /* @__PURE__ */ jsx(View, {
950
+ style: styles$3.list,
951
+ children: shown.map((element) => /* @__PURE__ */ jsx(ElementRow, { element }, element.ref))
952
+ }) : null,
953
+ hidden > 0 ? /* @__PURE__ */ jsxs(MessageItemStatus, {
954
+ expands: true,
955
+ children: [hidden, " more elements"]
956
+ }) : null,
957
+ observation.screenshotArtifact === void 0 ? null : /* @__PURE__ */ jsxs(Text, {
958
+ numberOfLines: 2,
959
+ style: [styles$3.small, styles$3.faint],
960
+ children: ["Screenshot saved to ", observation.screenshotArtifact]
961
+ })
962
+ ] });
963
+ }
964
+ function RunBlock({ run, expanded }) {
965
+ const figures = [
966
+ run.actions === void 0 ? "" : `${String(run.actions)} action${run.actions === 1 ? "" : "s"}`,
967
+ run.observations === void 0 ? "" : `${String(run.observations)} observation${run.observations === 1 ? "" : "s"}`,
968
+ run.duration ?? ""
969
+ ].filter(Boolean);
970
+ const logs = expanded ? run.logs : run.logs.slice(0, 3);
971
+ const hidden = run.logs.length - logs.length;
972
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
973
+ figures.length > 0 ? /* @__PURE__ */ jsx(View, {
974
+ style: styles$3.chips,
975
+ children: figures.map((figure) => /* @__PURE__ */ jsx(Badge, {
976
+ size: "xs",
977
+ children: figure
978
+ }, figure))
979
+ }) : null,
980
+ run.fields.length > 0 ? /* @__PURE__ */ jsx(View, {
981
+ style: styles$3.list,
982
+ children: run.fields.map((field) => /* @__PURE__ */ jsxs(View, {
983
+ style: styles$3.row,
984
+ children: [/* @__PURE__ */ jsx(Text, {
985
+ numberOfLines: 1,
986
+ style: [
987
+ styles$3.small,
988
+ styles$3.faint,
989
+ styles$3.key
990
+ ],
991
+ children: field.key
992
+ }), /* @__PURE__ */ jsx(Text, {
993
+ numberOfLines: 1,
994
+ selectable: true,
995
+ style: [
996
+ styles$3.sans,
997
+ styles$3.text,
998
+ styles$3.yield
999
+ ],
1000
+ children: field.value
1001
+ })]
1002
+ }, field.key))
1003
+ }) : null,
1004
+ logs.length > 0 ? /* @__PURE__ */ jsx(View, {
1005
+ style: styles$3.list,
1006
+ children: logs.map((line, index) => /* @__PURE__ */ jsx(Text, {
1007
+ numberOfLines: 1,
1008
+ selectable: true,
1009
+ style: [styles$3.mono, styles$3.dim],
1010
+ children: line
1011
+ }, `${String(index)}-${line}`))
1012
+ }) : null,
1013
+ hidden > 0 ? /* @__PURE__ */ jsxs(MessageItemStatus, {
1014
+ expands: true,
1015
+ children: [hidden, " more log lines"]
1016
+ }) : null,
1017
+ run.observation === void 0 ? null : /* @__PURE__ */ jsx(WindowLine, {
1018
+ observation: run.observation,
1019
+ lead: "Ended on"
1020
+ })
1021
+ ] });
1022
+ }
1023
+ function TextLines({ lines, expanded }) {
1024
+ const shown = expanded ? lines : lines.slice(0, 8);
1025
+ const hidden = lines.length - shown.length;
1026
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(View, {
1027
+ style: styles$3.list,
1028
+ children: shown.map((line, index) => /* @__PURE__ */ jsx(Text, {
1029
+ selectable: true,
1030
+ style: [styles$3.sans, styles$3.dim],
1031
+ children: line
1032
+ }, `${String(index)}-${line}`))
1033
+ }), hidden > 0 ? /* @__PURE__ */ jsxs(MessageItemStatus, {
1034
+ expands: true,
1035
+ children: [hidden, " more line(s)"]
1036
+ }) : null] });
1037
+ }
1038
+ const styles$3 = StyleSheet.create((theme) => ({
1039
+ stack: {
1040
+ gap: theme.spacing(2),
1041
+ uni__dependencies: [0]
1042
+ },
1043
+ list: {
1044
+ gap: theme.spacing(1),
1045
+ uni__dependencies: [0]
1046
+ },
1047
+ chips: {
1048
+ flexDirection: "row",
1049
+ flexWrap: "wrap",
1050
+ gap: theme.spacing(1.5),
1051
+ uni__dependencies: [0]
1052
+ },
1053
+ figure: {
1054
+ flexDirection: "row",
1055
+ alignItems: "baseline",
1056
+ gap: theme.spacing(2),
1057
+ minWidth: 0,
1058
+ uni__dependencies: [0]
1059
+ },
1060
+ row: {
1061
+ flexDirection: "row",
1062
+ alignItems: "baseline",
1063
+ gap: theme.spacing(2),
1064
+ minWidth: 0,
1065
+ uni__dependencies: [0]
1066
+ },
1067
+ sans: {
1068
+ fontFamily: fontOf(theme.fontFamily.sans),
1069
+ fontSize: theme.fontSize.base,
1070
+ lineHeight: theme.lineHeight.base,
1071
+ uni__dependencies: [0]
1072
+ },
1073
+ small: {
1074
+ fontFamily: fontOf(theme.fontFamily.sans),
1075
+ fontSize: theme.fontSize.sm,
1076
+ lineHeight: theme.lineHeight.sm,
1077
+ uni__dependencies: [0]
1078
+ },
1079
+ mono: {
1080
+ fontFamily: fontOf(theme.fontFamily.mono),
1081
+ fontSize: theme.fontSize.sm,
1082
+ lineHeight: theme.lineHeight.sm,
1083
+ uni__dependencies: [0]
1084
+ },
1085
+ strong: {
1086
+ color: theme.colors.text,
1087
+ fontWeight: theme.fontWeight.semibold,
1088
+ uni__dependencies: [0]
1089
+ },
1090
+ text: {
1091
+ color: theme.colors.text,
1092
+ uni__dependencies: [0]
1093
+ },
1094
+ dim: {
1095
+ color: theme.colors.dim,
1096
+ uni__dependencies: [0]
1097
+ },
1098
+ faint: {
1099
+ color: theme.colors.faint,
1100
+ uni__dependencies: [0]
1101
+ },
1102
+ error: {
1103
+ color: theme.colors.red,
1104
+ uni__dependencies: [0]
1105
+ },
1106
+ keep: {
1107
+ flexShrink: 0,
1108
+ maxWidth: "60%"
1109
+ },
1110
+ yield: {
1111
+ flexShrink: 1,
1112
+ minWidth: 0
1113
+ },
1114
+ key: {
1115
+ flexShrink: 0,
1116
+ maxWidth: "40%"
1117
+ },
1118
+ ref: {
1119
+ flexShrink: 0,
1120
+ marginLeft: "auto"
1121
+ }
1122
+ }));
1123
+ //#endregion
1124
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/_components/ComputerActionToolCard.native.tsx
1125
+ /**
1126
+ * The computer_action tool's timeline item on native, as the web's: the action
1127
+ * and the element it targets in the header, the outcome's first lines beneath.
1128
+ */
1129
+ function ComputerActionToolCard(props) {
1130
+ const { toolName, args, running, isError } = props;
1131
+ const [kind, ...target] = computerActionCallParts(args);
1132
+ return /* @__PURE__ */ jsx(MessageItem, {
1133
+ tone: toolTone({
1134
+ running,
1135
+ isError
1136
+ }),
1137
+ expandable: computerResultExpandable(props),
1138
+ children: ({ expanded }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MessageItemHeader, {
1139
+ title: toolName,
1140
+ children: /* @__PURE__ */ jsxs(View, {
1141
+ testID: `tool-call-${toolName}`,
1142
+ style: styles$2.summary,
1143
+ children: [kind === void 0 ? null : /* @__PURE__ */ jsx(Text, {
1144
+ numberOfLines: 1,
1145
+ style: [styles$2.sans, styles$2.primary],
1146
+ children: kind
1147
+ }), target.length > 0 ? /* @__PURE__ */ jsx(Text, {
1148
+ numberOfLines: 1,
1149
+ style: [styles$2.sans, styles$2.detail],
1150
+ children: target.join(" ")
1151
+ }) : null]
1152
+ })
1153
+ }), /* @__PURE__ */ jsx(ComputerResultBody, {
1154
+ props,
1155
+ expanded
1156
+ })] })
1157
+ });
1158
+ }
1159
+ const styles$2 = StyleSheet.create((theme) => ({
1160
+ summary: {
1161
+ flex: 1,
1162
+ flexDirection: "row",
1163
+ alignItems: "center",
1164
+ gap: theme.spacing(2),
1165
+ minWidth: 0,
1166
+ uni__dependencies: [0]
1167
+ },
1168
+ sans: {
1169
+ fontFamily: fontOf(theme.fontFamily.sans),
1170
+ fontSize: theme.fontSize.base,
1171
+ lineHeight: theme.lineHeight.base,
1172
+ uni__dependencies: [0]
1173
+ },
1174
+ primary: {
1175
+ flexShrink: 0,
1176
+ maxWidth: "45%",
1177
+ color: theme.colors.text,
1178
+ uni__dependencies: [0]
1179
+ },
1180
+ detail: {
1181
+ flexShrink: 1,
1182
+ color: theme.colors.dim,
1183
+ uni__dependencies: [0]
1184
+ }
1185
+ }));
1186
+ //#endregion
1187
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/computer-action.native.tsx
1188
+ var computer_action_native_default = defineToolRenderer({
1189
+ tools: ["computer_action"],
1190
+ message: ComputerActionToolCard
1191
+ });
1192
+ //#endregion
1193
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/_components/ComputerExecToolCard.native.tsx
1194
+ /**
1195
+ * The computer_exec tool's timeline item on native, as the web's: the script
1196
+ * path in the header, the run's first lines beneath it.
1197
+ */
1198
+ function ComputerExecToolCard(props) {
1199
+ const { toolName, args, running, isError } = props;
1200
+ const path = computerExecPathParts(computerExecCallSummary(args));
1201
+ return /* @__PURE__ */ jsx(MessageItem, {
1202
+ tone: toolTone({
1203
+ running,
1204
+ isError
1205
+ }),
1206
+ expandable: computerResultExpandable(props),
1207
+ children: ({ expanded }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MessageItemHeader, {
1208
+ title: toolName,
1209
+ children: /* @__PURE__ */ jsxs(View, {
1210
+ testID: `tool-call-${toolName}`,
1211
+ style: styles$1.summary,
1212
+ children: [path.folder.length > 0 ? /* @__PURE__ */ jsx(Text, {
1213
+ numberOfLines: 1,
1214
+ style: [styles$1.sans, styles$1.folder],
1215
+ children: path.folder
1216
+ }) : null, /* @__PURE__ */ jsx(Text, {
1217
+ numberOfLines: 1,
1218
+ style: [styles$1.sans, styles$1.primary],
1219
+ children: path.name
1220
+ })]
1221
+ })
1222
+ }), /* @__PURE__ */ jsx(ComputerResultBody, {
1223
+ props,
1224
+ expanded
1225
+ })] })
1226
+ });
1227
+ }
1228
+ const styles$1 = StyleSheet.create((theme) => ({
1229
+ summary: {
1230
+ flex: 1,
1231
+ flexDirection: "row",
1232
+ alignItems: "center",
1233
+ minWidth: 0
1234
+ },
1235
+ sans: {
1236
+ fontFamily: fontOf(theme.fontFamily.sans),
1237
+ fontSize: theme.fontSize.base,
1238
+ lineHeight: theme.lineHeight.base,
1239
+ uni__dependencies: [0]
1240
+ },
1241
+ folder: {
1242
+ flexShrink: 1,
1243
+ minWidth: 0,
1244
+ color: theme.colors.dim,
1245
+ uni__dependencies: [0]
1246
+ },
1247
+ primary: {
1248
+ flexShrink: 0,
1249
+ maxWidth: "100%",
1250
+ color: theme.colors.text,
1251
+ uni__dependencies: [0]
1252
+ }
1253
+ }));
1254
+ //#endregion
1255
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/computer-exec.native.tsx
1256
+ var computer_exec_native_default = defineToolRenderer({
1257
+ tools: ["computer_exec"],
1258
+ message: ComputerExecToolCard
1259
+ });
1260
+ //#endregion
1261
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/_components/ComputerStateToolCard.native.tsx
1262
+ /**
1263
+ * The computer_state tool's timeline item on native, as the web's: the observed
1264
+ * window in the header, the observation's first lines beneath it.
1265
+ */
1266
+ function ComputerStateToolCard(props) {
1267
+ const { toolName, args, running, isError } = props;
1268
+ return /* @__PURE__ */ jsx(MessageItem, {
1269
+ tone: toolTone({
1270
+ running,
1271
+ isError
1272
+ }),
1273
+ expandable: computerResultExpandable(props),
1274
+ children: ({ expanded }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MessageItemHeader, {
1275
+ title: toolName,
1276
+ children: /* @__PURE__ */ jsx(View, {
1277
+ testID: `tool-call-${toolName}`,
1278
+ style: styles.summary,
1279
+ children: /* @__PURE__ */ jsx(Text, {
1280
+ numberOfLines: 1,
1281
+ style: [styles.sans, styles.primary],
1282
+ children: computerStateCallSummary(args)
1283
+ })
1284
+ })
1285
+ }), /* @__PURE__ */ jsx(ComputerResultBody, {
1286
+ props,
1287
+ expanded
1288
+ })] })
1289
+ });
1290
+ }
1291
+ const styles = StyleSheet.create((theme) => ({
1292
+ summary: {
1293
+ flex: 1,
1294
+ flexDirection: "row",
1295
+ alignItems: "center",
1296
+ gap: theme.spacing(2),
1297
+ minWidth: 0,
1298
+ uni__dependencies: [0]
1299
+ },
1300
+ sans: {
1301
+ fontFamily: fontOf(theme.fontFamily.sans),
1302
+ fontSize: theme.fontSize.base,
1303
+ lineHeight: theme.lineHeight.base,
1304
+ uni__dependencies: [0]
1305
+ },
1306
+ primary: {
1307
+ flexShrink: 1,
1308
+ color: theme.colors.text,
1309
+ uni__dependencies: [0]
1310
+ }
1311
+ }));
1312
+ //#endregion
1313
+ //#region src/extensions/workspaces/sessions/(frontend)/tool/computer-state.native.tsx
1314
+ var computer_state_native_default = defineToolRenderer({
1315
+ tools: ["computer_state"],
1316
+ message: ComputerStateToolCard
1317
+ });
584
1318
  //#endregion
585
1319
  //#region generated/native.ts
586
1320
  const via = (identity, value) => value === void 0 ? void 0 : {
@@ -601,6 +1335,13 @@ const nativePlugin = defineNativePlugin({
601
1335
  slot: "activity.computer-use",
602
1336
  id: "computer-use"
603
1337
  }, ComputerUse_activity_computer_use_native_default)];
1338
+ },
1339
+ get toolRenderers() {
1340
+ return [
1341
+ via({ tools: ["computer_action"] }, computer_action_native_default),
1342
+ via({ tools: ["computer_exec"] }, computer_exec_native_default),
1343
+ via({ tools: ["computer_state"] }, computer_state_native_default)
1344
+ ];
604
1345
  }
605
1346
  }
606
1347
  });