@11agents/cli 0.1.27 → 0.1.29
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.
|
@@ -319,7 +319,13 @@ class XiaohongshuAdbPublisher:
|
|
|
319
319
|
)
|
|
320
320
|
status = "published"
|
|
321
321
|
if copy_link_after_publish:
|
|
322
|
-
link_result = self.copy_current_note_link(
|
|
322
|
+
link_result = self.copy_current_note_link(
|
|
323
|
+
device,
|
|
324
|
+
prepare=False,
|
|
325
|
+
run_dir=run_dir / "link",
|
|
326
|
+
expected_title=title,
|
|
327
|
+
expected_caption=composed_caption,
|
|
328
|
+
)
|
|
323
329
|
|
|
324
330
|
ended_epoch = int(time.time())
|
|
325
331
|
if status == "published":
|
|
@@ -757,6 +763,7 @@ class XiaohongshuAdbPublisher:
|
|
|
757
763
|
expected_caption: str,
|
|
758
764
|
) -> Path:
|
|
759
765
|
self._wait_for_publish_exit_after_confirm(device, run_dir)
|
|
766
|
+
self._restart_xiaohongshu_for_link_recovery(device, run_dir)
|
|
760
767
|
return self._open_latest_own_note_for_link(
|
|
761
768
|
device,
|
|
762
769
|
run_dir,
|
|
@@ -797,7 +804,13 @@ class XiaohongshuAdbPublisher:
|
|
|
797
804
|
|
|
798
805
|
self._open_me_tab(device, run_dir)
|
|
799
806
|
self._dismiss_link_recovery_prompts(device, run_dir)
|
|
800
|
-
self._tap_latest_profile_note(
|
|
807
|
+
self._tap_latest_profile_note(
|
|
808
|
+
device,
|
|
809
|
+
run_dir,
|
|
810
|
+
expected_title=expected_title,
|
|
811
|
+
require_expected_match=bool(expected_title or expected_caption),
|
|
812
|
+
allow_first_card_fallback=bool(expected_title or expected_caption),
|
|
813
|
+
)
|
|
801
814
|
self._wait_for_detail_screen(device, run_dir)
|
|
802
815
|
return self._verify_current_note_detail(
|
|
803
816
|
device,
|
|
@@ -807,6 +820,13 @@ class XiaohongshuAdbPublisher:
|
|
|
807
820
|
prefix="published-note-detail",
|
|
808
821
|
)
|
|
809
822
|
|
|
823
|
+
def _restart_xiaohongshu_for_link_recovery(self, device: Device, run_dir: Path) -> None:
|
|
824
|
+
self._close_xiaohongshu(device)
|
|
825
|
+
time.sleep(self._wait("after_prompt_dismiss"))
|
|
826
|
+
self.adb.screenshot(device.adb_serial, run_dir / "after-publish-app-closed.png")
|
|
827
|
+
self._launch_xiaohongshu(device)
|
|
828
|
+
self.adb.screenshot(device.adb_serial, run_dir / "after-publish-relaunch.png")
|
|
829
|
+
|
|
810
830
|
def _dismiss_link_recovery_prompts(self, device: Device, run_dir: Path) -> None:
|
|
811
831
|
for idx in range(2):
|
|
812
832
|
try:
|
|
@@ -844,7 +864,22 @@ class XiaohongshuAdbPublisher:
|
|
|
844
864
|
self._tap_coord_or_default(device, "bottom_me", self._relative_coord(0.9, 0.93), self._wait("after_me_tab"))
|
|
845
865
|
self.adb.screenshot(device.adb_serial, run_dir / "profile.png")
|
|
846
866
|
|
|
847
|
-
def _tap_latest_profile_note(
|
|
867
|
+
def _tap_latest_profile_note(
|
|
868
|
+
self,
|
|
869
|
+
device: Device,
|
|
870
|
+
run_dir: Path,
|
|
871
|
+
*,
|
|
872
|
+
expected_title: str = "",
|
|
873
|
+
require_expected_match: bool = False,
|
|
874
|
+
allow_first_card_fallback: bool = False,
|
|
875
|
+
) -> None:
|
|
876
|
+
if require_expected_match and not expected_title:
|
|
877
|
+
not_identifiable_shot = run_dir / "expected-profile-note-not-identifiable.png"
|
|
878
|
+
self.adb.screenshot(device.adb_serial, not_identifiable_shot)
|
|
879
|
+
raise XiaohongshuAutomationError(
|
|
880
|
+
"expected Xiaohongshu profile note cannot be selected safely without a title",
|
|
881
|
+
not_identifiable_shot,
|
|
882
|
+
)
|
|
848
883
|
attempts = 8 if expected_title else 3
|
|
849
884
|
for attempt in range(attempts):
|
|
850
885
|
root = ui.dump_ui(self.adb, device, run_dir / f"profile-before-latest-note-{attempt + 1}.xml")
|
|
@@ -857,7 +892,14 @@ class XiaohongshuAdbPublisher:
|
|
|
857
892
|
self._scroll_profile_notes_down_half_screen(device)
|
|
858
893
|
self.adb.screenshot(device.adb_serial, run_dir / f"profile-after-scroll-{attempt + 1}.png")
|
|
859
894
|
time.sleep(2 if expected_title else 1)
|
|
860
|
-
if
|
|
895
|
+
if allow_first_card_fallback:
|
|
896
|
+
root = ui.dump_ui(self.adb, device, run_dir / "profile-before-first-card-fallback.xml")
|
|
897
|
+
node = self._find_latest_profile_note_node(root, expected_title="")
|
|
898
|
+
if node is not None:
|
|
899
|
+
ui.tap_node(self.adb, device, node, sleep_s=self._wait("after_latest_note_tap"))
|
|
900
|
+
self.adb.screenshot(device.adb_serial, run_dir / "first-card-fallback-opened.png")
|
|
901
|
+
return
|
|
902
|
+
if expected_title or require_expected_match:
|
|
861
903
|
not_found_shot = run_dir / "expected-profile-note-not-found.png"
|
|
862
904
|
self.adb.screenshot(device.adb_serial, not_found_shot)
|
|
863
905
|
raise XiaohongshuAutomationError(
|
|
@@ -966,7 +1008,8 @@ class XiaohongshuAdbPublisher:
|
|
|
966
1008
|
continue
|
|
967
1009
|
note_text = f"{text}\n{desc}"
|
|
968
1010
|
if expected:
|
|
969
|
-
|
|
1011
|
+
note_match = _normalize_match_text(note_text)
|
|
1012
|
+
if not _looks_like_profile_note_card(node) or not _profile_card_matches_expected_title(note_match, expected):
|
|
970
1013
|
continue
|
|
971
1014
|
return node
|
|
972
1015
|
item = (top, left, node)
|
|
@@ -1462,7 +1505,7 @@ def _note_text_matches_expected(visible_text: str, expected_title: str, expected
|
|
|
1462
1505
|
title = _normalize_match_text(expected_title)
|
|
1463
1506
|
caption_fragment = _verification_fragment(expected_caption)
|
|
1464
1507
|
|
|
1465
|
-
if title and title not in haystack:
|
|
1508
|
+
if title and title not in haystack and not _visible_text_matches_truncated_title(haystack, title):
|
|
1466
1509
|
return False, f"title not visible: {expected_title!r}"
|
|
1467
1510
|
if caption_fragment and caption_fragment not in haystack:
|
|
1468
1511
|
return False, f"caption fragment not visible: {caption_fragment!r}"
|
|
@@ -1471,6 +1514,13 @@ def _note_text_matches_expected(visible_text: str, expected_title: str, expected
|
|
|
1471
1514
|
return True, ""
|
|
1472
1515
|
|
|
1473
1516
|
|
|
1517
|
+
def _visible_text_matches_truncated_title(visible_text: str, expected_title: str) -> bool:
|
|
1518
|
+
if not visible_text or not expected_title:
|
|
1519
|
+
return False
|
|
1520
|
+
min_prefix = min(18, len(expected_title))
|
|
1521
|
+
return len(expected_title) >= min_prefix and expected_title[:min_prefix] in visible_text
|
|
1522
|
+
|
|
1523
|
+
|
|
1474
1524
|
def _looks_like_profile_note_card(node) -> bool:
|
|
1475
1525
|
text = node.attrib.get("text", "")
|
|
1476
1526
|
desc = node.attrib.get("content-desc", "")
|
|
@@ -1570,6 +1620,19 @@ def _verification_fragment(text: str) -> str:
|
|
|
1570
1620
|
return normalized[:18]
|
|
1571
1621
|
|
|
1572
1622
|
|
|
1623
|
+
def _profile_card_matches_expected_title(card_text: str, expected_title: str) -> bool:
|
|
1624
|
+
if not card_text or not expected_title:
|
|
1625
|
+
return False
|
|
1626
|
+
if expected_title in card_text:
|
|
1627
|
+
return True
|
|
1628
|
+
min_prefix = min(18, len(expected_title))
|
|
1629
|
+
if len(card_text) >= min_prefix and card_text in expected_title:
|
|
1630
|
+
return True
|
|
1631
|
+
if len(card_text) >= min_prefix and expected_title.startswith(card_text):
|
|
1632
|
+
return True
|
|
1633
|
+
return expected_title[:min_prefix] in card_text
|
|
1634
|
+
|
|
1635
|
+
|
|
1573
1636
|
def _strip_hashtags(text: str) -> str:
|
|
1574
1637
|
return re.sub(r"#[^\s#]+", "", text or "").strip()
|
|
1575
1638
|
|
package/package.json
CHANGED
package/src/commands/runtime.js
CHANGED
|
@@ -103,6 +103,9 @@ async function writeCurrentClaim(deps, task, machineKey) {
|
|
|
103
103
|
task_id: String(task.id || ''),
|
|
104
104
|
runtime_id: String(task.runtime_id || task.runtime?.id || ''),
|
|
105
105
|
machine_key: String(task.runtime?.machine_key || machineKey || ''),
|
|
106
|
+
project_id: String(task.workspace?.id || ''),
|
|
107
|
+
project_slug: String(task.workspace?.slug || task.workspace_slug || ''),
|
|
108
|
+
agent_name: String(task.agent?.name || ''),
|
|
106
109
|
}
|
|
107
110
|
await mkdir(claimsDirPath(deps.homeDir), { recursive: true })
|
|
108
111
|
await writeFile(claimFilePath(deps.homeDir, task.id), JSON.stringify(payload))
|
|
@@ -1079,6 +1082,14 @@ function buildCodexPrompt(task) {
|
|
|
1079
1082
|
'- aspect alternatives: "1:1", "16:9", "9:16", "4:3", "3:4". Choose the closest ratio to the final placement.',
|
|
1080
1083
|
'- image_size alternatives: "1K", "2K". For a specific output size, pass aspect and image_size; pass size only when the MCP tool/provider explicitly supports the requested exact dimensions.',
|
|
1081
1084
|
'- Use model="gpt" with model_id only when the task or current project notes confirm that GPT image generation is available for the hosted MCP key.',
|
|
1085
|
+
'- MCP authentication (agent_planning, database_sync, knowledge_sync, image_generate, etc.):',
|
|
1086
|
+
' 1. Find your project_slug from the task context (task.workspace.slug).',
|
|
1087
|
+
' 2. Open ~/.11agents/credentials.yaml and read the value under tokens.<project_slug>.',
|
|
1088
|
+
' 3. Use that value as the Bearer token in the Authorization header for the 11agents hosted MCP endpoint.',
|
|
1089
|
+
' 4. If the key is missing from credentials.yaml, add it:',
|
|
1090
|
+
' tokens:',
|
|
1091
|
+
' <project_slug>: <your-token>',
|
|
1092
|
+
' Get the token from the 11agents platform → open your project → Tokens menu.',
|
|
1082
1093
|
'',
|
|
1083
1094
|
'Final task comment requirements:',
|
|
1084
1095
|
'> [!IMPORTANT]',
|
|
@@ -1397,6 +1408,7 @@ async function runOneRuntimeTaskSlot(runtime, config, machineKey, registration,
|
|
|
1397
1408
|
task_id: runtimeTask.id,
|
|
1398
1409
|
task_title: String(runtimeTask.issue?.title || runtimeTask.title || ''),
|
|
1399
1410
|
project_slug: String(runtimeTask.workspace?.slug || runtimeTask.workspace_slug || ''),
|
|
1411
|
+
agent_name: String(runtimeTask.agent?.name || ''),
|
|
1400
1412
|
runtime_id: runtime.id,
|
|
1401
1413
|
}, null, 2))
|
|
1402
1414
|
await writeCurrentClaim(deps, runtimeTask, machineKey)
|
package/src/credentials.js
CHANGED
|
@@ -47,7 +47,7 @@ export function parseCredentials(content = '') {
|
|
|
47
47
|
|
|
48
48
|
export async function readCredentials({ homeDir = os.homedir() } = {}) {
|
|
49
49
|
try {
|
|
50
|
-
return parseCredentials(await readFile(path.join(homeDir, '.11agents', 'credentials'), 'utf8'))
|
|
50
|
+
return parseCredentials(await readFile(path.join(homeDir, '.11agents', 'credentials.yaml'), 'utf8'))
|
|
51
51
|
} catch (error) {
|
|
52
52
|
if (error?.code === 'ENOENT') return { tokens: {} }
|
|
53
53
|
throw error
|