@amaster.ai/pi-lark 0.1.2-beta.52 → 0.1.2-beta.53
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/package.json +2 -2
- package/skills/lark-apps/SKILL.md +10 -4
- package/skills/lark-apps/references/lark-apps-cloud-dev.md +5 -4
- package/skills/lark-apps/references/lark-apps-create.md +6 -3
- package/skills/lark-apps/references/lark-apps-get.md +1 -1
- package/skills/lark-apps/references/lark-apps-list.md +1 -1
- package/skills/lark-apps/references/lark-apps-local-dev.md +27 -1
- package/skills/lark-apps/references/lark-apps-release-create.md +1 -1
- package/skills/lark-drive/SKILL.md +7 -5
- package/skills/lark-drive/references/lark-drive-copy.md +87 -0
- package/skills/lark-drive/references/lark-drive-update-title.md +78 -0
- package/skills/lark-im/references/lark-im-message-enrichment.md +1 -1
- package/skills/lark-im/references/lark-im-messages-search.md +1 -3
- package/skills/lark-sheets/SKILL.md +83 -82
- package/skills/lark-sheets/references/lark-sheets-batch-update.md +13 -58
- package/skills/lark-sheets/references/lark-sheets-chart.md +2 -1
- package/skills/lark-sheets/references/lark-sheets-conditional-format.md +1 -1
- package/skills/lark-sheets/references/lark-sheets-range-operations.md +5 -5
- package/skills/lark-sheets/references/lark-sheets-read-data.md +80 -6
- package/skills/lark-sheets/references/lark-sheets-sheet-structure.md +21 -10
- package/skills/lark-sheets/references/lark-sheets-styles-put.md +93 -0
- package/skills/lark-sheets/references/lark-sheets-visual-standards.md +2 -2
- package/skills/lark-sheets/references/lark-sheets-workbook.md +4 -3
- package/skills/lark-sheets/references/lark-sheets-write-cells.md +40 -12
- package/skills/lark-sheets/scripts/lark_detect_subtables.py +593 -0
- package/skills/lark-sheets/scripts/lark_inspect_workbook.py +188 -0
- package/skills/lark-sheets/scripts/lark_profile_table.py +614 -0
- package/skills/lark-sheets/scripts/lark_sheet_range.py +176 -0
- package/skills/lark-sheets/scripts/lark_sheet_read_cli.py +184 -0
- package/skills/lark-sheets/scripts/sheets_df.py +21 -3
- package/skills/lark-whiteboard/SKILL.md +15 -8
- package/skills/lark-whiteboard/references/lark-whiteboard-export.md +4 -3
- package/skills/lark-whiteboard/references/lark-whiteboard-update.md +4 -4
- package/skills/lark-whiteboard/references/lark-whiteboard-workflow.md +19 -17
- package/skills/lark-whiteboard/routes/dsl.md +8 -2
- package/skills/lark-whiteboard/routes/mermaid.md +1 -1
- package/skills/lark-whiteboard/routes/svg-edit.md +5 -2
- package/skills/lark-whiteboard/routes/svg.md +3 -1
- package/skills/lark-whiteboard/scenes/mention.md +71 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Copyright (c) 2026 Lark Technologies Pte. Ltd.
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""Inspect a Lark spreadsheet and emit a compact workbook profile."""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import argparse
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from lark_sheet_range import index_to_col
|
|
12
|
+
from lark_sheet_read_cli import (
|
|
13
|
+
LarkCliError,
|
|
14
|
+
add_spreadsheet_args,
|
|
15
|
+
emit_error,
|
|
16
|
+
emit_success,
|
|
17
|
+
envelope_data,
|
|
18
|
+
resolve_target_sheets,
|
|
19
|
+
run_sheets,
|
|
20
|
+
sheet_identifier,
|
|
21
|
+
sheet_locator,
|
|
22
|
+
sheet_title,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
ACTION = "inspect_workbook"
|
|
26
|
+
LAYOUT_INCLUDE = "merges,row_heights,col_widths,hidden_rows,hidden_cols,groups,frozen"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _sheet_summary(sheet: dict[str, Any]) -> dict[str, Any]:
|
|
30
|
+
return {
|
|
31
|
+
"sheet_id": sheet_identifier(sheet),
|
|
32
|
+
"title": sheet_title(sheet),
|
|
33
|
+
"index": sheet.get("index"),
|
|
34
|
+
"row_count": sheet.get("row_count"),
|
|
35
|
+
"column_count": sheet.get("column_count"),
|
|
36
|
+
"is_hidden": sheet.get("is_hidden"),
|
|
37
|
+
"merged_cells_count": sheet.get("merged_cells_count"),
|
|
38
|
+
"chart_count": sheet.get("chart_count"),
|
|
39
|
+
"pivot_table_count": sheet.get("pivot_table_count"),
|
|
40
|
+
"float_image_count": sheet.get("float_image_count"),
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _list_count(value: Any) -> int:
|
|
45
|
+
return len(value) if isinstance(value, list) else 0
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _layout_summary(layout: dict[str, Any]) -> dict[str, Any]:
|
|
49
|
+
"""Retain layout signals without serializing unbounded per-cell metadata."""
|
|
50
|
+
merges = layout.get("merged_cells") or layout.get("merges") or []
|
|
51
|
+
groups = layout.get("groups") if isinstance(layout.get("groups"), dict) else {}
|
|
52
|
+
row_groups = layout.get("row_groups") or groups.get("rows", [])
|
|
53
|
+
col_groups = layout.get("column_groups") or groups.get("columns", [])
|
|
54
|
+
return {
|
|
55
|
+
"merge_count": _list_count(merges),
|
|
56
|
+
"row_heights_count": _list_count(layout.get("row_heights")),
|
|
57
|
+
"column_widths_count": _list_count(layout.get("col_widths")),
|
|
58
|
+
"hidden_rows_count": _list_count(layout.get("hidden_rows")),
|
|
59
|
+
"hidden_columns_count": _list_count(
|
|
60
|
+
layout.get("hidden_cols") or layout.get("hidden_columns")
|
|
61
|
+
),
|
|
62
|
+
"row_groups_count": _list_count(row_groups),
|
|
63
|
+
"column_groups_count": _list_count(col_groups),
|
|
64
|
+
"frozen": layout.get("frozen"),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def inspect_workbook(args) -> tuple[dict[str, Any], list[str]]:
|
|
69
|
+
warnings: list[str] = []
|
|
70
|
+
workbook = envelope_data(
|
|
71
|
+
run_sheets(
|
|
72
|
+
"+workbook-info",
|
|
73
|
+
url=args.url,
|
|
74
|
+
spreadsheet_token=args.spreadsheet_token,
|
|
75
|
+
timeout=args.timeout,
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
# An explicit selector must resolve: without require_one a typo'd
|
|
79
|
+
# --sheet-id/--sheet-name silently yields sheet_count 0, which reads as
|
|
80
|
+
# "empty workbook" instead of a locator error.
|
|
81
|
+
target_sheets = resolve_target_sheets(
|
|
82
|
+
workbook,
|
|
83
|
+
sheet_id=args.sheet_id,
|
|
84
|
+
sheet_name=args.sheet_name,
|
|
85
|
+
require_one=bool(args.sheet_id or args.sheet_name),
|
|
86
|
+
)
|
|
87
|
+
if args.max_sheets < 1:
|
|
88
|
+
raise LarkCliError("--max-sheets must be at least 1")
|
|
89
|
+
inspect_count = len(target_sheets)
|
|
90
|
+
if not args.sheet_id and not args.sheet_name:
|
|
91
|
+
inspect_count = min(len(target_sheets), args.max_sheets)
|
|
92
|
+
if inspect_count < len(target_sheets):
|
|
93
|
+
warnings.append(
|
|
94
|
+
f"layout and preview skipped for {len(target_sheets) - inspect_count} sheets; "
|
|
95
|
+
f"pass --sheet-id or --sheet-name to inspect one"
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
profiles = []
|
|
99
|
+
for position, sheet in enumerate(target_sheets):
|
|
100
|
+
sid = sheet_identifier(sheet)
|
|
101
|
+
title = sheet_title(sheet)
|
|
102
|
+
profile = _sheet_summary(sheet)
|
|
103
|
+
if position >= inspect_count:
|
|
104
|
+
profiles.append(profile)
|
|
105
|
+
continue
|
|
106
|
+
locator = sheet_locator(sheet)
|
|
107
|
+
col_count = int(sheet.get("column_count") or args.max_preview_cols)
|
|
108
|
+
preview_cols = min(col_count, args.max_preview_cols)
|
|
109
|
+
if col_count > args.max_preview_cols:
|
|
110
|
+
warnings.append(
|
|
111
|
+
f"{title or sid}: preview clipped to first {args.max_preview_cols} columns"
|
|
112
|
+
)
|
|
113
|
+
end_col = index_to_col(max(1, preview_cols))
|
|
114
|
+
preview_range = f"A1:{end_col}{args.preview_rows}"
|
|
115
|
+
|
|
116
|
+
# Per-sheet, not fail-the-run: this is the first-step pre-flight, and
|
|
117
|
+
# one unreadable sheet (odd type, transient error, a locator that does
|
|
118
|
+
# not resolve) must not throw away the summaries already collected for
|
|
119
|
+
# every other sheet. The basic summary comes from +workbook-info and is
|
|
120
|
+
# already in hand, so a failure here degrades detail, not correctness —
|
|
121
|
+
# same call the sibling profile_table downgrades to a warning.
|
|
122
|
+
try:
|
|
123
|
+
layout = envelope_data(
|
|
124
|
+
run_sheets(
|
|
125
|
+
"+sheet-info",
|
|
126
|
+
url=args.url,
|
|
127
|
+
spreadsheet_token=args.spreadsheet_token,
|
|
128
|
+
**locator,
|
|
129
|
+
flags={"include": LAYOUT_INCLUDE},
|
|
130
|
+
timeout=args.timeout,
|
|
131
|
+
)
|
|
132
|
+
)
|
|
133
|
+
preview = envelope_data(
|
|
134
|
+
run_sheets(
|
|
135
|
+
"+csv-get",
|
|
136
|
+
url=args.url,
|
|
137
|
+
spreadsheet_token=args.spreadsheet_token,
|
|
138
|
+
**locator,
|
|
139
|
+
flags={"range": preview_range, "max_chars": args.max_chars},
|
|
140
|
+
timeout=args.timeout,
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
except LarkCliError as exc:
|
|
144
|
+
warnings.append(
|
|
145
|
+
f"{title or sid}: layout/preview unavailable ({exc}); "
|
|
146
|
+
"re-read this sheet on its own with --sheet-name, or use +sheet-info / +csv-get directly"
|
|
147
|
+
)
|
|
148
|
+
profiles.append(profile)
|
|
149
|
+
continue
|
|
150
|
+
if preview.get("has_more"):
|
|
151
|
+
warnings.append(f"{title or sid}: preview range {preview_range} was truncated")
|
|
152
|
+
|
|
153
|
+
profiles.append(
|
|
154
|
+
{
|
|
155
|
+
**profile,
|
|
156
|
+
"layout": _layout_summary(layout),
|
|
157
|
+
"preview": {
|
|
158
|
+
"range": preview_range,
|
|
159
|
+
"current_region": preview.get("current_region"),
|
|
160
|
+
"row_indices": preview.get("row_indices"),
|
|
161
|
+
"col_indices": preview.get("col_indices"),
|
|
162
|
+
"annotated_csv": preview.get("annotated_csv"),
|
|
163
|
+
"has_more": preview.get("has_more"),
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
return {"sheet_count": len(target_sheets), "sheets": profiles}, warnings
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def main() -> None:
|
|
172
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
173
|
+
add_spreadsheet_args(parser, require_sheet=False, allow_sheet=True)
|
|
174
|
+
parser.add_argument("--preview-rows", type=int, default=15)
|
|
175
|
+
parser.add_argument("--max-preview-cols", type=int, default=100)
|
|
176
|
+
parser.add_argument("--max-chars", type=int, default=8000)
|
|
177
|
+
parser.add_argument("--max-sheets", type=int, default=3)
|
|
178
|
+
parser.add_argument("--timeout", type=int, default=60)
|
|
179
|
+
args = parser.parse_args()
|
|
180
|
+
try:
|
|
181
|
+
data, warnings = inspect_workbook(args)
|
|
182
|
+
except (LarkCliError, ValueError, TypeError) as exc:
|
|
183
|
+
emit_error(ACTION, str(exc))
|
|
184
|
+
emit_success(ACTION, data, warnings)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
if __name__ == "__main__":
|
|
188
|
+
main()
|