fix: drop default task_logs; process in log, progress in task center (v1.0.81)
All checks were successful
技能自动化发布 / release (push) Successful in 7s
All checks were successful
技能自动化发布 / release (push) Successful in 7s
This commit is contained in:
@@ -13,8 +13,6 @@ from service.task_service import (
|
||||
cmd_config_path,
|
||||
cmd_health,
|
||||
cmd_init_db,
|
||||
cmd_log_get,
|
||||
cmd_logs,
|
||||
cmd_run,
|
||||
cmd_version,
|
||||
)
|
||||
@@ -58,8 +56,6 @@ def _handle_run(args: argparse.Namespace) -> int:
|
||||
def _print_full_usage() -> None:
|
||||
print("通用业务技能模板(main.py)可用命令:")
|
||||
print(" python main.py run [target [input_id]] [-t target] [-i input_id]")
|
||||
print(" python main.py logs [--limit N] [--status s] [--task-type t] [--target-id tid]")
|
||||
print(" python main.py log-get <log_id>")
|
||||
print(" python main.py health")
|
||||
print(" python main.py config-path")
|
||||
print(" python main.py version")
|
||||
@@ -69,7 +65,7 @@ def _print_full_usage() -> None:
|
||||
def build_parser() -> ZhArgumentParser:
|
||||
p = ZhArgumentParser(
|
||||
prog="main.py",
|
||||
description="通用业务技能模板:任务执行命令骨架、日志查询、健康检查、版本输出。",
|
||||
description="通用业务技能模板:任务执行命令骨架、健康检查、版本输出。",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
)
|
||||
sub = p.add_subparsers(dest="cmd", required=True, parser_class=ZhArgumentParser)
|
||||
@@ -80,19 +76,6 @@ def build_parser() -> ZhArgumentParser:
|
||||
sp.add_argument("run_tail", nargs="*", metavar="位置参数")
|
||||
sp.set_defaults(handler=_handle_run)
|
||||
|
||||
sp = sub.add_parser("logs", help="查看任务日志")
|
||||
sp.add_argument("--limit", type=int, default=10)
|
||||
sp.add_argument("--status", default=None)
|
||||
sp.add_argument("--task-type", default=None, dest="task_type")
|
||||
sp.add_argument("--target-id", default=None, dest="target_id")
|
||||
sp.set_defaults(handler=lambda a: cmd_logs(
|
||||
limit=a.limit, status=a.status, task_type=a.task_type, target_id=a.target_id
|
||||
))
|
||||
|
||||
sp = sub.add_parser("log-get", help="按 log_id 查看单条任务日志(JSON)")
|
||||
sp.add_argument("log_id")
|
||||
sp.set_defaults(handler=lambda a: cmd_log_get(a.log_id))
|
||||
|
||||
sp = sub.add_parser("health", help="健康检查")
|
||||
sp.set_defaults(handler=lambda _a: cmd_health())
|
||||
|
||||
@@ -116,7 +99,7 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
_print_full_usage()
|
||||
return 1
|
||||
if len(argv) == 2 and argv[0] not in {
|
||||
"run", "logs", "log-get", "health", "config-path", "version", "init-db",
|
||||
"run", "health", "config-path", "version", "init-db",
|
||||
"-h", "--help",
|
||||
}:
|
||||
return cmd_run(target=argv[0], input_id=argv[1])
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
"""SQLite 连接与任务日志表迁移模板。"""
|
||||
"""SQLite 连接与幂等初始化模板。
|
||||
|
||||
模板默认只建数据管理元数据表。业务表由复制后的技能自行 CREATE,并同步展示元数据。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sqlite3
|
||||
|
||||
from db.display_metadata import init_display_metadata
|
||||
from db.timestamp_columns import init_task_logs_timestamp_maintenance
|
||||
from util.runtime_paths import get_db_path
|
||||
|
||||
|
||||
@@ -17,23 +19,6 @@ def init_db() -> None:
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS task_logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
task_type TEXT NOT NULL,
|
||||
target_id TEXT,
|
||||
input_id TEXT,
|
||||
input_title TEXT,
|
||||
status TEXT NOT NULL,
|
||||
error_msg TEXT,
|
||||
result_summary TEXT,
|
||||
created_at INTEGER NOT NULL DEFAULT (unixepoch()),
|
||||
updated_at INTEGER NOT NULL DEFAULT (unixepoch())
|
||||
)
|
||||
"""
|
||||
)
|
||||
init_task_logs_timestamp_maintenance(cur)
|
||||
init_display_metadata(cur)
|
||||
conn.commit()
|
||||
finally:
|
||||
|
||||
@@ -13,7 +13,6 @@ INTERNAL_METADATA_TABLES = frozenset({"_jiangchang_tables", "_jiangchang_columns
|
||||
LEGACY_METADATA_TABLES = frozenset({"_schema_meta"})
|
||||
METADATA_TABLES = INTERNAL_METADATA_TABLES | LEGACY_METADATA_TABLES
|
||||
|
||||
TASK_LOGS_TABLE = "task_logs"
|
||||
DATETIME_UNIX_SECONDS = "datetime_unix_seconds"
|
||||
STANDARD_TIMESTAMP_COLUMNS = frozenset({"created_at", "updated_at"})
|
||||
|
||||
@@ -46,44 +45,6 @@ CREATE TABLE IF NOT EXISTS _jiangchang_columns (
|
||||
)
|
||||
"""
|
||||
|
||||
TASK_LOGS_TABLE_METADATA = {
|
||||
"table_name": TASK_LOGS_TABLE,
|
||||
"display_name": "任务日志",
|
||||
"description": "记录技能任务的执行状态和结果(系统自动写入,宿主数据管理只读展示)",
|
||||
"visible": 1,
|
||||
"readonly": 1,
|
||||
}
|
||||
|
||||
TASK_LOGS_COLUMN_METADATA: tuple[dict[str, object], ...] = (
|
||||
{"column_name": "id", "display_name": "编号", "description": "任务日志唯一编号", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{"column_name": "task_type", "display_name": "任务类型", "description": "任务的业务类型", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{"column_name": "target_id", "display_name": "目标编号", "description": "任务目标对象编号", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{"column_name": "input_id", "display_name": "输入编号", "description": "输入对象编号", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{"column_name": "input_title", "display_name": "输入标题", "description": "输入对象标题", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{"column_name": "status", "display_name": "状态", "description": "任务当前状态", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{"column_name": "error_msg", "display_name": "错误信息", "description": "任务失败时的错误说明", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{"column_name": "result_summary", "display_name": "结果摘要", "description": "任务执行结果摘要", "visible": 1, "searchable": 1, "editable": 0},
|
||||
{
|
||||
"column_name": "created_at",
|
||||
"display_name": "创建时间",
|
||||
"description": "记录创建时间(Unix 秒级时间戳,数据库自动生成)",
|
||||
"visible": 1,
|
||||
"searchable": 0,
|
||||
"editable": 0,
|
||||
"display_type": DATETIME_UNIX_SECONDS,
|
||||
},
|
||||
{
|
||||
"column_name": "updated_at",
|
||||
"display_name": "更新时间",
|
||||
"description": "记录最后更新时间(Unix 秒级时间戳,自动维护)",
|
||||
"visible": 1,
|
||||
"searchable": 0,
|
||||
"editable": 0,
|
||||
"display_type": DATETIME_UNIX_SECONDS,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def _ensure_jiangchang_tables_columns(cursor) -> None:
|
||||
"""旧库补列:CREATE IF NOT EXISTS 不会给已有表加新字段。"""
|
||||
cursor.execute("PRAGMA table_info('_jiangchang_tables')")
|
||||
@@ -195,24 +156,6 @@ def upsert_column_metadata(
|
||||
)
|
||||
|
||||
|
||||
def seed_task_logs_display_metadata(cursor) -> None:
|
||||
meta = TASK_LOGS_TABLE_METADATA
|
||||
upsert_table_metadata(
|
||||
cursor,
|
||||
table_name=str(meta["table_name"]),
|
||||
display_name=str(meta["display_name"]),
|
||||
description=str(meta["description"]) if meta.get("description") else None,
|
||||
visible=int(meta["visible"]),
|
||||
readonly=int(meta["readonly"]),
|
||||
)
|
||||
seed_column_metadata_batch(
|
||||
cursor,
|
||||
table_name=TASK_LOGS_TABLE,
|
||||
columns=TASK_LOGS_COLUMN_METADATA,
|
||||
valid_column_names=[str(column["column_name"]) for column in TASK_LOGS_COLUMN_METADATA],
|
||||
)
|
||||
|
||||
|
||||
def seed_column_metadata_batch(
|
||||
cursor,
|
||||
*,
|
||||
@@ -307,7 +250,6 @@ def table_allows_manual_create(cursor, table_name: str) -> bool:
|
||||
|
||||
def init_display_metadata(cursor) -> None:
|
||||
init_display_metadata_tables(cursor)
|
||||
seed_task_logs_display_metadata(cursor)
|
||||
|
||||
|
||||
def iter_user_tables(cursor) -> Iterable[str]:
|
||||
|
||||
@@ -12,8 +12,6 @@ from db.display_metadata import (
|
||||
DATETIME_UNIX_SECONDS,
|
||||
METADATA_TABLES,
|
||||
STANDARD_TIMESTAMP_COLUMNS,
|
||||
TASK_LOGS_COLUMN_METADATA,
|
||||
TASK_LOGS_TABLE,
|
||||
iter_user_tables,
|
||||
list_editable_business_columns,
|
||||
list_physical_column_names,
|
||||
@@ -516,11 +514,5 @@ def validate_display_metadata(conn: sqlite3.Connection, *, check_column_order: b
|
||||
|
||||
|
||||
def validate_template_database(conn: sqlite3.Connection) -> ValidationReport:
|
||||
report = validate_display_metadata(conn)
|
||||
physical = list_physical_column_names(conn.cursor(), TASK_LOGS_TABLE)
|
||||
expected = [str(item["column_name"]) for item in TASK_LOGS_COLUMN_METADATA]
|
||||
if physical != expected:
|
||||
report.errors.append(
|
||||
f"task_logs 物理字段顺序应为 {expected},当前为 {physical}"
|
||||
)
|
||||
return report
|
||||
"""模板自检入口:校验展示元数据完整性。模板默认无业务表。"""
|
||||
return validate_display_metadata(conn)
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
"""task_logs 表读写模板。
|
||||
|
||||
通用业务日志仓储:记录每次任务执行的 task_type / target / input / 状态 / 结果摘要。
|
||||
不假设任何特定业务(发布、对账、审核等都可复用)。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
from db.connection import get_conn, init_db
|
||||
|
||||
|
||||
def save_task_log(
|
||||
task_type: str,
|
||||
target_id: Optional[str] = None,
|
||||
input_id: Optional[str] = None,
|
||||
input_title: Optional[str] = None,
|
||||
status: str = "success",
|
||||
error_msg: Optional[str] = None,
|
||||
result_summary: Optional[str] = None,
|
||||
) -> int:
|
||||
init_db()
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
"""
|
||||
INSERT INTO task_logs
|
||||
(task_type, target_id, input_id, input_title, status, error_msg, result_summary)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
(task_type, target_id, input_id, input_title or "", status, error_msg, result_summary),
|
||||
)
|
||||
new_id = int(cur.lastrowid)
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
return new_id
|
||||
|
||||
|
||||
def list_task_logs(
|
||||
limit: int,
|
||||
status: Optional[str] = None,
|
||||
task_type: Optional[str] = None,
|
||||
target_id: Optional[str] = None,
|
||||
) -> List[Tuple[Any, ...]]:
|
||||
init_db()
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
sql = (
|
||||
"SELECT id, task_type, target_id, input_id, input_title, status, error_msg, result_summary, "
|
||||
"created_at, updated_at FROM task_logs WHERE 1=1 "
|
||||
)
|
||||
params: List[Any] = []
|
||||
if status:
|
||||
sql += "AND status = ? "
|
||||
params.append(status)
|
||||
if task_type:
|
||||
sql += "AND task_type = ? "
|
||||
params.append(task_type)
|
||||
if target_id:
|
||||
sql += "AND target_id = ? "
|
||||
params.append(target_id)
|
||||
sql += "ORDER BY created_at DESC, id DESC LIMIT ?"
|
||||
params.append(int(limit))
|
||||
cur.execute(sql, tuple(params))
|
||||
return list(cur.fetchall())
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_task_log_by_id(log_id: int) -> Optional[Tuple[Any, ...]]:
|
||||
init_db()
|
||||
conn = get_conn()
|
||||
try:
|
||||
cur = conn.cursor()
|
||||
cur.execute(
|
||||
"SELECT id, task_type, target_id, input_id, input_title, status, error_msg, result_summary, "
|
||||
"created_at, updated_at FROM task_logs WHERE id = ?",
|
||||
(int(log_id),),
|
||||
)
|
||||
return cur.fetchone()
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -1,30 +1,44 @@
|
||||
"""标准时间字段:Unix 秒级时间戳、默认值与 updated_at 自动维护。"""
|
||||
"""标准时间字段:Unix 秒级时间戳、默认值与 updated_at 自动维护。
|
||||
|
||||
业务表若包含 created_at / updated_at,在 CREATE TABLE 后调用
|
||||
``init_updated_at_trigger(cursor, table_name)``。模板默认不建业务表。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
STANDARD_TIMESTAMP_COLUMNS = frozenset({"created_at", "updated_at"})
|
||||
DATETIME_UNIX_SECONDS = "datetime_unix_seconds"
|
||||
TASK_LOGS_UPDATED_AT_TRIGGER = "task_logs_set_updated_at"
|
||||
|
||||
_TASK_LOGS_UPDATED_AT_TRIGGER_DDL = f"""
|
||||
CREATE TRIGGER IF NOT EXISTS {TASK_LOGS_UPDATED_AT_TRIGGER}
|
||||
AFTER UPDATE ON task_logs
|
||||
|
||||
def updated_at_trigger_name(table_name: str) -> str:
|
||||
return f"{table_name}_set_updated_at"
|
||||
|
||||
|
||||
def _quote_identifier(name: str) -> str:
|
||||
return '"' + name.replace('"', '""') + '"'
|
||||
|
||||
|
||||
def init_updated_at_trigger(cursor, table_name: str) -> None:
|
||||
"""幂等创建 {table}_set_updated_at:业务字段 UPDATE 后刷新 updated_at。"""
|
||||
trigger = updated_at_trigger_name(table_name)
|
||||
quoted = _quote_identifier(table_name)
|
||||
quoted_trigger = _quote_identifier(trigger)
|
||||
cursor.execute(
|
||||
f"""
|
||||
CREATE TRIGGER IF NOT EXISTS {quoted_trigger}
|
||||
AFTER UPDATE ON {quoted}
|
||||
FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE task_logs
|
||||
UPDATE {quoted}
|
||||
SET updated_at = unixepoch()
|
||||
WHERE id = NEW.id AND updated_at = OLD.updated_at;
|
||||
END
|
||||
"""
|
||||
|
||||
|
||||
def init_task_logs_timestamp_maintenance(cursor) -> None:
|
||||
"""幂等创建 task_logs.updated_at 自动维护 trigger。"""
|
||||
cursor.execute(_TASK_LOGS_UPDATED_AT_TRIGGER_DDL)
|
||||
)
|
||||
|
||||
|
||||
def has_updated_at_trigger(cursor, table_name: str) -> bool:
|
||||
trigger_name = f"{table_name}_set_updated_at"
|
||||
trigger_name = updated_at_trigger_name(table_name)
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT 1 FROM sqlite_master
|
||||
|
||||
@@ -10,7 +10,7 @@ def build_video_info(
|
||||
compose_context_before: Optional[dict[str, Any]] = None,
|
||||
compose_context_after: Optional[dict[str, Any]] = None,
|
||||
) -> dict[str, Any]:
|
||||
"""将 RpaVideoSession.summary() 转为 task log / CLI 可用的 video 块。"""
|
||||
"""将 RpaVideoSession.summary() 转为 finish() / CLI 可用的 video 块。"""
|
||||
return {
|
||||
"enabled": video_summary.get("enabled", False),
|
||||
"path": video_summary.get("path"),
|
||||
@@ -31,7 +31,7 @@ def merge_video_into_result_summary(
|
||||
payload: dict[str, Any],
|
||||
video_info: Optional[dict[str, Any]],
|
||||
) -> dict[str, Any]:
|
||||
"""把 video artifact 字段写入 result_summary JSON 对象。"""
|
||||
"""把 video artifact 字段写入 finish() 结果对象(video / video_path 等)。"""
|
||||
if not video_info:
|
||||
return payload
|
||||
payload = dict(payload)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""任务编排、日志查询模板。
|
||||
"""任务编排模板。
|
||||
|
||||
编排层:job_context / emit / checkpoint / finish、鉴权、任务日志与错误转换。
|
||||
编排层:job_context / emit / checkpoint / finish、鉴权与错误转换。
|
||||
过程看统一文件日志;进度/终态看任务中心;业务结果写入业务表(有才建)。
|
||||
领域业务请放在 ``service/<domain>_service.py``,由本模块调用;多入口(CLI/Action/cron)复用同一内核。
|
||||
复制后在 cmd_run(或 cmd_sync_*)中接线到真实 domain service,勿按 toolbar/cron/agent 分叉业务。
|
||||
"""
|
||||
@@ -11,12 +12,11 @@ import asyncio
|
||||
import json
|
||||
import os
|
||||
import uuid
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Optional
|
||||
|
||||
from jiangchang_skill_core import collect_runtime_diagnostics, config, format_runtime_health_lines
|
||||
from jiangchang_skill_core.activity import JobStopped, emit, finish, job_context
|
||||
|
||||
from db import task_logs_repository as tlr
|
||||
from jiangchang_skill_core.rpa.video_session import RpaVideoSession
|
||||
from service.entitlement_service import check_entitlement
|
||||
from service.task_run_support import (
|
||||
@@ -27,7 +27,6 @@ from service.task_run_support import (
|
||||
from util.constants import LOG_LOGGER_NAME, PLATFORM_KIT_MIN_VERSION, SKILL_SLUG, SKILL_VERSION
|
||||
from util.logging_config import get_skill_logger, setup_skill_logging
|
||||
from util.runtime_paths import get_db_path, get_skill_data_dir, get_skill_root
|
||||
from util.timeutil import unix_to_iso
|
||||
from db.connection import init_db
|
||||
|
||||
|
||||
@@ -84,21 +83,6 @@ def cmd_run(target: Optional[str] = None, input_id: Optional[str] = None) -> int
|
||||
task_type,
|
||||
)
|
||||
emit("鉴权失败,已记录诊断信息", type="warn", skill=SKILL_SLUG, stage="auth")
|
||||
tlr.save_task_log(
|
||||
task_type=task_type,
|
||||
target_id=target,
|
||||
input_id=input_id,
|
||||
input_title="模板示例任务",
|
||||
status="failed",
|
||||
error_msg=reason,
|
||||
result_summary=json.dumps({"stage": "auth", "error": reason}, ensure_ascii=False),
|
||||
)
|
||||
log.info(
|
||||
"task_log_saved task_type=%s target_id=%s input_id=%s stage=auth status=failed",
|
||||
task_type,
|
||||
target,
|
||||
input_id,
|
||||
)
|
||||
finish(
|
||||
status="failed",
|
||||
message=reason,
|
||||
@@ -129,21 +113,6 @@ def cmd_run(target: Optional[str] = None, input_id: Optional[str] = None) -> int
|
||||
},
|
||||
video_info,
|
||||
)
|
||||
tlr.save_task_log(
|
||||
task_type=task_type,
|
||||
target_id=target,
|
||||
input_id=input_id,
|
||||
input_title="模板示例任务",
|
||||
status="failed",
|
||||
error_msg="模板仓库未实现真实业务",
|
||||
result_summary=json.dumps(summary_payload, ensure_ascii=False),
|
||||
)
|
||||
log.info(
|
||||
"task_log_saved task_type=%s target_id=%s input_id=%s status=failed",
|
||||
task_type,
|
||||
target,
|
||||
input_id,
|
||||
)
|
||||
|
||||
log.warning(
|
||||
"task_failed task_type=%s stage=demo_finish error_code=TEMPLATE_STUB",
|
||||
@@ -153,10 +122,8 @@ def cmd_run(target: Optional[str] = None, input_id: Optional[str] = None) -> int
|
||||
status="failed",
|
||||
message="模板仓库未实现真实业务",
|
||||
skill=SKILL_SLUG,
|
||||
template_demo=True,
|
||||
target=target,
|
||||
input_id=input_id,
|
||||
error_code="TEMPLATE_STUB",
|
||||
**summary_payload,
|
||||
)
|
||||
print("ERROR:TEMPLATE_STUB 这是模板仓库,请复制后在 scripts/service/task_service.py 中实现 cmd_run 的真实业务逻辑。")
|
||||
return rc
|
||||
@@ -170,32 +137,6 @@ def cmd_run(target: Optional[str] = None, input_id: Optional[str] = None) -> int
|
||||
input_id,
|
||||
)
|
||||
emit("任务失败,已记录诊断信息", type="warn", skill=SKILL_SLUG, stage="run")
|
||||
try:
|
||||
tlr.save_task_log(
|
||||
task_type=task_type,
|
||||
target_id=target,
|
||||
input_id=input_id,
|
||||
input_title="模板示例任务",
|
||||
status="failed",
|
||||
error_msg="任务执行异常,详见统一日志",
|
||||
result_summary=json.dumps(
|
||||
{"stage": "run", "error": "unexpected_exception"},
|
||||
ensure_ascii=False,
|
||||
),
|
||||
)
|
||||
log.info(
|
||||
"task_log_saved task_type=%s target_id=%s input_id=%s stage=run status=failed",
|
||||
task_type,
|
||||
target,
|
||||
input_id,
|
||||
)
|
||||
except Exception:
|
||||
log.exception(
|
||||
"task_log_save_failed task_type=%s target_id=%s input_id=%s",
|
||||
task_type,
|
||||
target,
|
||||
input_id,
|
||||
)
|
||||
finish(
|
||||
status="failed",
|
||||
message="任务执行异常,详见统一日志",
|
||||
@@ -205,67 +146,6 @@ def cmd_run(target: Optional[str] = None, input_id: Optional[str] = None) -> int
|
||||
return 1
|
||||
|
||||
|
||||
def cmd_logs(
|
||||
limit: int = 10,
|
||||
status: Optional[str] = None,
|
||||
task_type: Optional[str] = None,
|
||||
target_id: Optional[str] = None,
|
||||
) -> int:
|
||||
if limit <= 0:
|
||||
limit = 10
|
||||
rows = tlr.list_task_logs(limit, status, task_type, target_id)
|
||||
if not rows:
|
||||
print("暂无任务日志")
|
||||
return 0
|
||||
|
||||
sep_line = "_" * 39
|
||||
for idx, r in enumerate(rows):
|
||||
rid, ttype, tid, iid, ititle, st, err, rsum, cat, uat = r
|
||||
print(f"id:{rid}")
|
||||
print(f"task_type:{ttype or ''}")
|
||||
print(f"target_id:{tid or ''}")
|
||||
print(f"input_id:{iid or ''}")
|
||||
print(f"input_title:{ititle or ''}")
|
||||
print(f"status:{st or ''}")
|
||||
print(f"error_msg:{err or ''}")
|
||||
print(f"result_summary:{rsum or ''}")
|
||||
print(f"created_at:{unix_to_iso(cat) or str(cat or '')}")
|
||||
print(f"updated_at:{unix_to_iso(uat) or str(uat or '')}")
|
||||
if idx != len(rows) - 1:
|
||||
print(sep_line)
|
||||
print()
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_log_get(log_id: str) -> int:
|
||||
if not str(log_id).isdigit():
|
||||
print("❌ log_id 必须是数字")
|
||||
return 1
|
||||
row = tlr.get_task_log_by_id(int(log_id))
|
||||
if not row:
|
||||
print("❌ 没有这条任务日志")
|
||||
return 1
|
||||
rid, ttype, tid, iid, ititle, st, err, rsum, cat, uat = row
|
||||
print(
|
||||
json.dumps(
|
||||
{
|
||||
"id": int(rid),
|
||||
"task_type": ttype,
|
||||
"target_id": tid,
|
||||
"input_id": iid,
|
||||
"input_title": ititle,
|
||||
"status": st,
|
||||
"error_msg": err,
|
||||
"result_summary": rsum,
|
||||
"created_at": unix_to_iso(cat),
|
||||
"updated_at": unix_to_iso(uat),
|
||||
},
|
||||
ensure_ascii=False,
|
||||
)
|
||||
)
|
||||
return 0
|
||||
|
||||
|
||||
def cmd_config_path() -> int:
|
||||
example_path = os.path.join(get_skill_root(), ".env.example")
|
||||
env_path = config.get_env_file_path() or ""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""技能标识、版本与平台公共库约束(复制后请修改 slug/version/logger)。"""
|
||||
|
||||
SKILL_SLUG = "your-skill-slug"
|
||||
SKILL_VERSION = "1.0.80"
|
||||
SKILL_VERSION = "1.0.81"
|
||||
LOG_LOGGER_NAME = "openclaw.skill.your_skill_slug"
|
||||
PLATFORM_KIT_MIN_VERSION = "1.2.11"
|
||||
|
||||
Reference in New Issue
Block a user