homegraph 1.1.3 → 1.2.0
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/README.md +43 -18
- package/dist/arkts/ohos-api-index.d.ts +15 -0
- package/dist/arkts/ohos-api-index.d.ts.map +1 -0
- package/dist/arkts/ohos-api-index.js +190 -0
- package/dist/arkts/ohos-api-index.js.map +1 -0
- package/dist/arkts/ohos-sdk-input.d.ts +36 -0
- package/dist/arkts/ohos-sdk-input.d.ts.map +1 -0
- package/dist/arkts/ohos-sdk-input.js +214 -0
- package/dist/arkts/ohos-sdk-input.js.map +1 -0
- package/dist/bin/command-supervision.d.ts +12 -0
- package/dist/bin/command-supervision.d.ts.map +1 -0
- package/dist/bin/command-supervision.js +86 -0
- package/dist/bin/command-supervision.js.map +1 -0
- package/dist/bin/homegraph.d.ts +1 -1
- package/dist/bin/homegraph.js +706 -168
- package/dist/bin/homegraph.js.map +1 -1
- package/dist/db/index.d.ts +20 -0
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +39 -0
- package/dist/db/index.js.map +1 -1
- package/dist/db/migrations.d.ts +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +40 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/db/queries.d.ts +14 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +174 -3
- package/dist/db/queries.js.map +1 -1
- package/dist/db/schema.sql +20 -0
- package/dist/directory.d.ts +32 -0
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +83 -0
- package/dist/directory.js.map +1 -1
- package/dist/extraction/arkts-batch-worker.d.ts +2 -0
- package/dist/extraction/arkts-batch-worker.d.ts.map +1 -0
- package/dist/extraction/arkts-batch-worker.js +28 -0
- package/dist/extraction/arkts-batch-worker.js.map +1 -0
- package/dist/extraction/context.d.ts +11 -0
- package/dist/extraction/context.d.ts.map +1 -1
- package/dist/extraction/context.js +20 -0
- package/dist/extraction/context.js.map +1 -1
- package/dist/extraction/index.d.ts +16 -2
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +619 -380
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/arkts-state-decorators.d.ts +13 -0
- package/dist/extraction/languages/arkts-state-decorators.d.ts.map +1 -0
- package/dist/extraction/languages/arkts-state-decorators.js +26 -0
- package/dist/extraction/languages/arkts-state-decorators.js.map +1 -0
- package/dist/extraction/languages/arkts-viewtree.d.ts +4 -2
- package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -1
- package/dist/extraction/languages/arkts-viewtree.js +21 -6
- package/dist/extraction/languages/arkts-viewtree.js.map +1 -1
- package/dist/extraction/languages/arkts.d.ts +98 -2
- package/dist/extraction/languages/arkts.d.ts.map +1 -1
- package/dist/extraction/languages/arkts.js +1290 -61
- package/dist/extraction/languages/arkts.js.map +1 -1
- package/dist/extraction/languages/c-cpp.d.ts +56 -0
- package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
- package/dist/extraction/languages/c-cpp.js +198 -1
- package/dist/extraction/languages/c-cpp.js.map +1 -1
- package/dist/extraction/languages/ohos-api-consumer.d.ts +34 -0
- package/dist/extraction/languages/ohos-api-consumer.d.ts.map +1 -0
- package/dist/extraction/languages/ohos-api-consumer.js +283 -0
- package/dist/extraction/languages/ohos-api-consumer.js.map +1 -0
- package/dist/extraction/parse-pool.d.ts +126 -0
- package/dist/extraction/parse-pool.d.ts.map +1 -0
- package/dist/extraction/parse-pool.js +319 -0
- package/dist/extraction/parse-pool.js.map +1 -0
- package/dist/extraction/tree-sitter-types.d.ts +17 -0
- package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.d.ts +21 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +198 -27
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +76 -17
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +78 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp/daemon-paths.d.ts +30 -3
- package/dist/mcp/daemon-paths.d.ts.map +1 -1
- package/dist/mcp/daemon-paths.js +50 -10
- package/dist/mcp/daemon-paths.js.map +1 -1
- package/dist/mcp/daemon-registry.d.ts.map +1 -1
- package/dist/mcp/daemon-registry.js +7 -3
- package/dist/mcp/daemon-registry.js.map +1 -1
- package/dist/mcp/daemon.d.ts +48 -0
- package/dist/mcp/daemon.d.ts.map +1 -1
- package/dist/mcp/daemon.js +196 -32
- package/dist/mcp/daemon.js.map +1 -1
- package/dist/mcp/engine.d.ts +17 -0
- package/dist/mcp/engine.d.ts.map +1 -1
- package/dist/mcp/engine.js +73 -1
- package/dist/mcp/engine.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +25 -43
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/ppid-watchdog.d.ts +18 -0
- package/dist/mcp/ppid-watchdog.d.ts.map +1 -1
- package/dist/mcp/ppid-watchdog.js +37 -0
- package/dist/mcp/ppid-watchdog.js.map +1 -1
- package/dist/mcp/query-cache.d.ts +25 -0
- package/dist/mcp/query-cache.d.ts.map +1 -0
- package/dist/mcp/query-cache.js +191 -0
- package/dist/mcp/query-cache.js.map +1 -0
- package/dist/mcp/query-pool.d.ts +94 -0
- package/dist/mcp/query-pool.d.ts.map +1 -0
- package/dist/mcp/query-pool.js +297 -0
- package/dist/mcp/query-pool.js.map +1 -0
- package/dist/mcp/query-worker.d.ts +24 -0
- package/dist/mcp/query-worker.d.ts.map +1 -0
- package/dist/mcp/query-worker.js +87 -0
- package/dist/mcp/query-worker.js.map +1 -0
- package/dist/mcp/server-instructions.d.ts +5 -7
- package/dist/mcp/server-instructions.d.ts.map +1 -1
- package/dist/mcp/server-instructions.js +12 -14
- package/dist/mcp/server-instructions.js.map +1 -1
- package/dist/mcp/tools.d.ts +77 -0
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +696 -60
- package/dist/mcp/tools.js.map +1 -1
- package/dist/project-config.d.ts +20 -0
- package/dist/project-config.d.ts.map +1 -1
- package/dist/project-config.js +42 -2
- package/dist/project-config.js.map +1 -1
- package/dist/reasoning/login.js +1 -1
- package/dist/reasoning/login.js.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.d.ts +0 -28
- package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
- package/dist/resolution/c-fnptr-synthesizer.js +765 -79
- package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
- package/dist/resolution/callback-synthesizer.d.ts +1 -1
- package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
- package/dist/resolution/callback-synthesizer.js +72 -11
- package/dist/resolution/callback-synthesizer.js.map +1 -1
- package/dist/resolution/cooperative-yield.d.ts +32 -0
- package/dist/resolution/cooperative-yield.d.ts.map +1 -0
- package/dist/resolution/cooperative-yield.js +42 -0
- package/dist/resolution/cooperative-yield.js.map +1 -0
- package/dist/resolution/index.d.ts +11 -2
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +72 -4
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/name-matcher.d.ts +22 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -1
- package/dist/resolution/name-matcher.js +317 -20
- package/dist/resolution/name-matcher.js.map +1 -1
- package/dist/spec/config.d.ts +7 -11
- package/dist/spec/config.d.ts.map +1 -1
- package/dist/spec/config.js +77 -48
- package/dist/spec/config.js.map +1 -1
- package/dist/spec/db/fragment-node.d.ts +1 -0
- package/dist/spec/db/fragment-node.d.ts.map +1 -1
- package/dist/spec/db/fragment-node.js +8 -0
- package/dist/spec/db/fragment-node.js.map +1 -1
- package/dist/spec/db/fts.d.ts +14 -0
- package/dist/spec/db/fts.d.ts.map +1 -1
- package/dist/spec/db/fts.js +43 -4
- package/dist/spec/db/fts.js.map +1 -1
- package/dist/spec/db/schema.d.ts +6 -3
- package/dist/spec/db/schema.d.ts.map +1 -1
- package/dist/spec/db/schema.js +36 -4
- package/dist/spec/db/schema.js.map +1 -1
- package/dist/spec/db/schema.sql +11 -1
- package/dist/spec/evolve/logic-checker.d.ts +2 -2
- package/dist/spec/evolve/logic-checker.d.ts.map +1 -1
- package/dist/spec/evolve/logic-checker.js +3 -27
- package/dist/spec/evolve/logic-checker.js.map +1 -1
- package/dist/spec/evolve/pipeline.d.ts +21 -19
- package/dist/spec/evolve/pipeline.d.ts.map +1 -1
- package/dist/spec/evolve/pipeline.js +284 -31
- package/dist/spec/evolve/pipeline.js.map +1 -1
- package/dist/spec/evolve/spec-rewriter.d.ts +2 -2
- package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -1
- package/dist/spec/evolve/spec-rewriter.js +7 -31
- package/dist/spec/evolve/spec-rewriter.js.map +1 -1
- package/dist/spec/graph/queries.d.ts +97 -0
- package/dist/spec/graph/queries.d.ts.map +1 -1
- package/dist/spec/graph/queries.js +225 -0
- package/dist/spec/graph/queries.js.map +1 -1
- package/dist/spec/llm/client.d.ts +29 -0
- package/dist/spec/llm/client.d.ts.map +1 -0
- package/dist/spec/llm/client.js +123 -0
- package/dist/spec/llm/client.js.map +1 -0
- package/dist/spec/llm/index.d.ts +3 -0
- package/dist/spec/llm/index.d.ts.map +1 -0
- package/dist/spec/llm/index.js +11 -0
- package/dist/spec/llm/index.js.map +1 -0
- package/dist/spec/llm/prompts.d.ts +13 -0
- package/dist/spec/llm/prompts.d.ts.map +1 -0
- package/dist/spec/llm/prompts.js +75 -0
- package/dist/spec/llm/prompts.js.map +1 -0
- package/dist/spec/mining/git-scanner.d.ts +12 -0
- package/dist/spec/mining/git-scanner.d.ts.map +1 -1
- package/dist/spec/mining/git-scanner.js +41 -0
- package/dist/spec/mining/git-scanner.js.map +1 -1
- package/dist/spec/mining/pipeline.d.ts.map +1 -1
- package/dist/spec/mining/pipeline.js +14 -1
- package/dist/spec/mining/pipeline.js.map +1 -1
- package/dist/spec/utils.d.ts +2 -1
- package/dist/spec/utils.d.ts.map +1 -1
- package/dist/spec/utils.js +3 -1
- package/dist/spec/utils.js.map +1 -1
- package/dist/sync/worktree.d.ts +9 -0
- package/dist/sync/worktree.d.ts.map +1 -1
- package/dist/sync/worktree.js +40 -0
- package/dist/sync/worktree.js.map +1 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.d.ts +2 -0
- package/dist/ui/shimmer-progress.d.ts.map +1 -1
- package/dist/ui/shimmer-progress.js +19 -2
- package/dist/ui/shimmer-progress.js.map +1 -1
- package/dist/upgrade/index.js +1 -1
- package/dist/upgrade/index.js.map +1 -1
- package/package.json +3 -3
- package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
- package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
- package/scripts/exp_boundary_eval/README.md +247 -0
- package/scripts/exp_boundary_eval/__pycache__/_utils.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/analyze.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/deveco_arm.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_one.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/run_session.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/__pycache__/setup.cpython-310.pyc +0 -0
- package/scripts/exp_boundary_eval/_test_mcp_chain.py +78 -0
- package/scripts/exp_boundary_eval/_test_stdin.py +8 -0
- package/scripts/exp_boundary_eval/_utils.py +1116 -0
- package/scripts/exp_boundary_eval/analyze.py +1313 -0
- package/scripts/exp_boundary_eval/data/agents.json +109 -0
- package/scripts/exp_boundary_eval/data/experiments.json +140 -0
- package/scripts/exp_boundary_eval/deveco_arm.py +519 -0
- package/scripts/exp_boundary_eval/run_all.py +378 -0
- package/scripts/exp_boundary_eval/run_one.py +165 -0
- package/scripts/exp_boundary_eval/run_session.py +158 -0
- package/scripts/exp_boundary_eval/setup.py +120 -0
- package/scripts/exp_boundary_eval/win_mcp_launcher.py +73 -0
- package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +36 -0
- package/scripts/exp_boundary_eval/win_node_launcher.py +24 -0
- package/scripts/npm-shim.js +25 -3
- package/scripts/ohos-sdk-publish.mjs +133 -0
- package/scripts/qa_eval/README.md +1 -1
- package/scripts/qa_eval/agent_runner.py +1 -1
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Run multi-turn session experiment (5). Supports multiple agents via --agent."""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import time
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional
|
|
10
|
+
|
|
11
|
+
import setup as setup_mod
|
|
12
|
+
from _utils import (OUTPUT_DIR, append_run_log, build_agent_cmd,
|
|
13
|
+
current_time_ms, find_experiment, get_agent, info, header,
|
|
14
|
+
log, parse_output, resolve_agent_model, run_monitored_subprocess,
|
|
15
|
+
subprocess_no_window_kwargs, write_json, warn)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_session(exp_id: str = "5", skip_permissions: bool = True,
|
|
19
|
+
agent_name: str = "",
|
|
20
|
+
results_dir: Optional[Path] = None,
|
|
21
|
+
state_dir: Optional[Path] = None) -> bool:
|
|
22
|
+
exp = find_experiment(exp_id)
|
|
23
|
+
if exp is None:
|
|
24
|
+
print(f"ERROR: Experiment {exp_id} not found")
|
|
25
|
+
return False
|
|
26
|
+
|
|
27
|
+
agent = get_agent(agent_name)
|
|
28
|
+
clone_path = os.environ.get("REPO_CLONE", "")
|
|
29
|
+
local_repo = os.environ.get("REPO_PATH", "")
|
|
30
|
+
if clone_path:
|
|
31
|
+
repo_root = Path(clone_path)
|
|
32
|
+
elif local_repo:
|
|
33
|
+
repo_root = Path(local_repo)
|
|
34
|
+
else:
|
|
35
|
+
print("ERROR: No repo. Use run_all.py to clone, or set REPO_PATH / REPO_CLONE.")
|
|
36
|
+
return False
|
|
37
|
+
max_turns = exp.get("max_turns_per_round", 25)
|
|
38
|
+
|
|
39
|
+
header("Experiment 5: Session Persistence & Context Decay")
|
|
40
|
+
info(f"Agent: {agent['name']} ({agent['binary']}) | Repo: {repo_root}")
|
|
41
|
+
info(f"Max turns/round: {max_turns} | Permissions: {'skip' if skip_permissions else 'ask'}")
|
|
42
|
+
|
|
43
|
+
session_id, _ = setup_mod.prepare_environment("5", "full", agent_name,
|
|
44
|
+
state_dir=state_dir)
|
|
45
|
+
log(f"Shared Session ID: {session_id}")
|
|
46
|
+
|
|
47
|
+
result_dir = results_dir / "5" if results_dir else OUTPUT_DIR / "5"
|
|
48
|
+
result_dir.mkdir(parents=True, exist_ok=True)
|
|
49
|
+
|
|
50
|
+
rounds_data = []
|
|
51
|
+
session_model = ""
|
|
52
|
+
deveco_session_id = ""
|
|
53
|
+
for round_num in range(1, 6):
|
|
54
|
+
ri = next((r for r in exp["rounds"] if r["round"] == round_num), None)
|
|
55
|
+
if not ri: continue
|
|
56
|
+
|
|
57
|
+
header(f"Round {round_num} of 5")
|
|
58
|
+
info(f"Title: {ri['title']}")
|
|
59
|
+
|
|
60
|
+
round_dir = result_dir / f"round_{round_num}"
|
|
61
|
+
round_dir.mkdir(parents=True, exist_ok=True)
|
|
62
|
+
(round_dir / "prompt.txt").write_text(ri["prompt"], encoding="utf-8")
|
|
63
|
+
|
|
64
|
+
start_ms = current_time_ms()
|
|
65
|
+
is_resume = round_num > 1
|
|
66
|
+
|
|
67
|
+
cmd = build_agent_cmd(agent, session_id, max_turns, ri["prompt"],
|
|
68
|
+
resume=is_resume, skip_permissions=skip_permissions,
|
|
69
|
+
repo_root=repo_root)
|
|
70
|
+
|
|
71
|
+
stream_path = round_dir / "stream_output.jsonl"
|
|
72
|
+
text_path = round_dir / "raw_output.txt"
|
|
73
|
+
track_hg = os.environ.get("EVAL_ARM", "") == "homegraph"
|
|
74
|
+
|
|
75
|
+
with open(stream_path, "w", encoding="utf-8") as stream_f:
|
|
76
|
+
result, mem = run_monitored_subprocess(
|
|
77
|
+
cmd, stdout=stream_f, stderr=subprocess.STDOUT, text=True,
|
|
78
|
+
track_homegraph=track_hg,
|
|
79
|
+
)
|
|
80
|
+
exit_code = result.returncode
|
|
81
|
+
|
|
82
|
+
end_ms = current_time_ms()
|
|
83
|
+
dur_ms = end_ms - start_ms
|
|
84
|
+
dur_s = f"{dur_ms / 1000:.1f}"
|
|
85
|
+
|
|
86
|
+
parser_name = agent.get("parser", "claude_stream_json")
|
|
87
|
+
stats = parse_output(stream_path, parser_name)
|
|
88
|
+
if not session_model:
|
|
89
|
+
session_model = resolve_agent_model(agent, stats)
|
|
90
|
+
if not deveco_session_id and stats.deveco_session_id:
|
|
91
|
+
deveco_session_id = stats.deveco_session_id
|
|
92
|
+
|
|
93
|
+
text_content = "\n".join(stats.text_lines)
|
|
94
|
+
text_path.write_text(text_content or "(no text output)", encoding="utf-8")
|
|
95
|
+
|
|
96
|
+
r2 = subprocess.run(
|
|
97
|
+
["git", "diff", "--name-only"], capture_output=True, text=True, cwd=repo_root,
|
|
98
|
+
**subprocess_no_window_kwargs(),
|
|
99
|
+
)
|
|
100
|
+
mod_files = len([l for l in r2.stdout.strip().split("\n") if l])
|
|
101
|
+
|
|
102
|
+
rr = {"round": round_num, "title": ri["title"], "duration_ms": dur_ms,
|
|
103
|
+
"duration_s": dur_s, "exit_code": exit_code,
|
|
104
|
+
"tool_calls": stats.tool_calls, "tool_names": stats.tool_names,
|
|
105
|
+
"files_read": list(set(stats.files_read)),
|
|
106
|
+
"files_edited": list(set(stats.files_edited)),
|
|
107
|
+
"assistant_messages": stats.assistant_messages,
|
|
108
|
+
"max_turns_hit": stats.max_turns_hit,
|
|
109
|
+
"modified_files": mod_files, "max_turns": max_turns,
|
|
110
|
+
"memory": mem.to_dict()}
|
|
111
|
+
write_json(round_dir / "round_results.json", rr)
|
|
112
|
+
rounds_data.append(rr)
|
|
113
|
+
|
|
114
|
+
info(f"Round {round_num} done: {dur_s}s | Tool calls: {stats.tool_calls} | "
|
|
115
|
+
f"Files read: {len(set(stats.files_read))} | Edited: {mod_files}")
|
|
116
|
+
if stats.max_turns_hit:
|
|
117
|
+
warn(f" Max turns ({max_turns}) hit in round {round_num}")
|
|
118
|
+
if round_num < 5:
|
|
119
|
+
time.sleep(2)
|
|
120
|
+
|
|
121
|
+
summary = {
|
|
122
|
+
"experiment_id": "5", "session_id": session_id, "agent": agent["name"],
|
|
123
|
+
"model": session_model,
|
|
124
|
+
"deveco_session_id": deveco_session_id,
|
|
125
|
+
"total_rounds": len(rounds_data),
|
|
126
|
+
"total_duration_ms": sum(r["duration_ms"] for r in rounds_data),
|
|
127
|
+
"total_tool_calls": sum(int(r["tool_calls"]) for r in rounds_data),
|
|
128
|
+
"memory_retention_curve": [
|
|
129
|
+
{"round": r["round"], "tool_calls": int(r["tool_calls"]),
|
|
130
|
+
"files_read": r.get("files_read", [])} for r in rounds_data
|
|
131
|
+
],
|
|
132
|
+
}
|
|
133
|
+
write_json(result_dir / "session_results.json", summary)
|
|
134
|
+
|
|
135
|
+
print("\nMemory Retention Curve:")
|
|
136
|
+
for r in rounds_data:
|
|
137
|
+
tc = int(r["tool_calls"])
|
|
138
|
+
fr = len(r.get("files_read", []))
|
|
139
|
+
print(f" Round {r['round']}: {'#' * (tc // 2)} ({tc} tool calls, {fr} files read)")
|
|
140
|
+
|
|
141
|
+
log(f"Results: {result_dir}/session_results.json")
|
|
142
|
+
return True
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
args = sys.argv[1:]
|
|
147
|
+
exp_id = args[0] if args else "5"
|
|
148
|
+
agent_name = ""
|
|
149
|
+
skip = True
|
|
150
|
+
i = 1
|
|
151
|
+
while i < len(args):
|
|
152
|
+
if args[i] == "--agent" and i + 1 < len(args):
|
|
153
|
+
agent_name = args[i + 1]; i += 2
|
|
154
|
+
elif args[i] == "--no-skip-permissions":
|
|
155
|
+
skip = False; i += 1
|
|
156
|
+
else:
|
|
157
|
+
i += 1
|
|
158
|
+
sys.exit(0 if run_session(exp_id, skip, agent_name) else 1)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Prepare a clean repo for an experiment run. Agent-aware."""
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
from datetime import datetime, timezone
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Optional, Tuple
|
|
10
|
+
|
|
11
|
+
from _utils import (append_run_log, error, generate_session_id,
|
|
12
|
+
get_agent, get_agent_version, git_output, git_ok, log,
|
|
13
|
+
shell_ok, verify_agent_binary, write_json)
|
|
14
|
+
from deveco_arm import git_clean_repo, write_deveco_project_config
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def prepare_environment(exp_id: str, clean_mode: str = "full",
|
|
18
|
+
agent_name: str = "",
|
|
19
|
+
state_dir: Optional[Path] = None) -> Tuple[str, str]:
|
|
20
|
+
"""Prepare repo. Returns (session_id, agent_name)."""
|
|
21
|
+
clone_path = os.environ.get("REPO_CLONE", "")
|
|
22
|
+
is_clone = bool(clone_path and Path(clone_path).is_dir())
|
|
23
|
+
local_repo = os.environ.get("REPO_PATH", "")
|
|
24
|
+
if is_clone:
|
|
25
|
+
repo_root = Path(clone_path)
|
|
26
|
+
elif local_repo and Path(local_repo).is_dir():
|
|
27
|
+
repo_root = Path(local_repo)
|
|
28
|
+
else:
|
|
29
|
+
error("No repo available. Clone via run_all.py or set REPO_PATH / REPO_CLONE.")
|
|
30
|
+
sys.exit(1)
|
|
31
|
+
|
|
32
|
+
if state_dir is not None:
|
|
33
|
+
_state_dir = state_dir
|
|
34
|
+
else:
|
|
35
|
+
from _utils import LOG_DIR
|
|
36
|
+
_state_dir = LOG_DIR
|
|
37
|
+
|
|
38
|
+
if is_clone:
|
|
39
|
+
log(f"Using cloned repo: {repo_root}")
|
|
40
|
+
else:
|
|
41
|
+
log(f"Using local repo: {repo_root}")
|
|
42
|
+
|
|
43
|
+
os.chdir(repo_root)
|
|
44
|
+
|
|
45
|
+
# Agent config
|
|
46
|
+
agent = get_agent(agent_name)
|
|
47
|
+
binary = agent["binary"]
|
|
48
|
+
|
|
49
|
+
# Step 1: Clean repo
|
|
50
|
+
arm = os.environ.get("EVAL_ARM", "baseline")
|
|
51
|
+
if clean_mode == "full":
|
|
52
|
+
log("Restoring repo to clean state...")
|
|
53
|
+
branch = os.environ.get("BRANCH", "weekly_20260601")
|
|
54
|
+
shell_ok(f"git checkout {branch}")
|
|
55
|
+
git_ok(["checkout", "."], cwd=repo_root)
|
|
56
|
+
git_clean_repo(repo_root, arm)
|
|
57
|
+
|
|
58
|
+
current_branch = git_output(["branch", "--show-current"], cwd=repo_root)
|
|
59
|
+
commit = git_output(["rev-parse", "--short", "HEAD"], cwd=repo_root)
|
|
60
|
+
log(f"Branch: {current_branch} | Commit: {commit}")
|
|
61
|
+
|
|
62
|
+
# Step 1b: DevEco A/B project config (.deveco/deveco.jsonc)
|
|
63
|
+
if agent.get("binary") == "deveco":
|
|
64
|
+
write_deveco_project_config(repo_root, arm)
|
|
65
|
+
|
|
66
|
+
# Step 1c: Index rebuilt once at homegraph suite start (run_all / prebuild).
|
|
67
|
+
# Per-experiment git reset restores the same commit — no second index here.
|
|
68
|
+
# Step 2: Clear CLAUDE.md
|
|
69
|
+
claude_md = repo_root / "CLAUDE.md"
|
|
70
|
+
if claude_md.exists() and claude_md.stat().st_size > 0:
|
|
71
|
+
backup_dir = _state_dir / "claude_md_backups"
|
|
72
|
+
backup_dir.mkdir(parents=True, exist_ok=True)
|
|
73
|
+
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
74
|
+
backup_path = backup_dir / f"CLAUDE.md.{ts}"
|
|
75
|
+
backup_path.write_text(claude_md.read_text())
|
|
76
|
+
log(f"Backed up CLAUDE.md → {backup_path}")
|
|
77
|
+
with open(claude_md, "w") as f:
|
|
78
|
+
f.write("")
|
|
79
|
+
log("Cleared CLAUDE.md")
|
|
80
|
+
|
|
81
|
+
for f in [".cursorrules", ".cursor/rules"]:
|
|
82
|
+
p = repo_root / f
|
|
83
|
+
if p.exists():
|
|
84
|
+
p.unlink()
|
|
85
|
+
|
|
86
|
+
# Step 3: Session ID
|
|
87
|
+
session_id = generate_session_id()
|
|
88
|
+
(_state_dir / f"session_{exp_id}.txt").write_text(session_id)
|
|
89
|
+
log(f"Session ID: {session_id}")
|
|
90
|
+
|
|
91
|
+
# Step 4: Verify agent binary
|
|
92
|
+
ok, resolved, err_msg = verify_agent_binary(agent)
|
|
93
|
+
if not ok:
|
|
94
|
+
error(err_msg)
|
|
95
|
+
sys.exit(1)
|
|
96
|
+
binary = resolved
|
|
97
|
+
agent_ver = get_agent_version(agent)
|
|
98
|
+
log(f"Agent: {agent['name']} ({binary}) v{agent_ver}")
|
|
99
|
+
|
|
100
|
+
# Step 5: Record state
|
|
101
|
+
write_json(_state_dir / exp_id / "state.json", {
|
|
102
|
+
"experiment_id": exp_id, "session_id": session_id,
|
|
103
|
+
"started_at": datetime.now(timezone.utc).isoformat(),
|
|
104
|
+
"clean_mode": clean_mode, "agent": agent["name"],
|
|
105
|
+
"agent_version": agent_ver, "repo_root": str(repo_root),
|
|
106
|
+
"git_branch": git_output(["branch", "--show-current"], cwd=repo_root),
|
|
107
|
+
"git_commit": git_output(["rev-parse", "HEAD"], cwd=repo_root),
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
append_run_log(_state_dir, f"Setup complete for {exp_id}: session={session_id}, agent={agent['name']}")
|
|
111
|
+
log("Setup complete.")
|
|
112
|
+
return session_id, agent["name"]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
exp_id = sys.argv[1] if len(sys.argv) > 1 else "all"
|
|
117
|
+
clean_mode = sys.argv[2] if len(sys.argv) > 2 else "full"
|
|
118
|
+
agent_name = sys.argv[3] if len(sys.argv) > 3 else ""
|
|
119
|
+
sid, _ = prepare_environment(exp_id, clean_mode, agent_name)
|
|
120
|
+
print(sid)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Windows MCP entry: pythonw (no window) → hidden node child; stdio inherited from DevEco."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import shutil
|
|
8
|
+
import subprocess
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
_CREATE_NO_WINDOW = getattr(subprocess, "CREATE_NO_WINDOW", 0x08000000)
|
|
12
|
+
|
|
13
|
+
# Applied here so MCP works even if DevEco ignores deveco.jsonc "environment".
|
|
14
|
+
_MCP_ENV_DEFAULTS = {
|
|
15
|
+
"HOMEGRAPH_NO_DAEMON": "1",
|
|
16
|
+
"HOMEGRAPH_NO_WATCHDOG": "1",
|
|
17
|
+
"HOMEGRAPH_WASM_RELAUNCHED": "1",
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _resolve_node() -> str:
|
|
22
|
+
env_node = os.environ.get("HOMEGRAPH_NODE", "").strip()
|
|
23
|
+
if env_node:
|
|
24
|
+
return env_node
|
|
25
|
+
found = shutil.which("node")
|
|
26
|
+
if not found:
|
|
27
|
+
print("node not found on PATH", file=sys.stderr)
|
|
28
|
+
sys.exit(127)
|
|
29
|
+
return found
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _node_argv(raw: list[str]) -> list[str]:
|
|
33
|
+
"""Ensure --liftoff-only is on the node command line (before homegraph.js)."""
|
|
34
|
+
node = _resolve_node()
|
|
35
|
+
args = list(raw)
|
|
36
|
+
if "--liftoff-only" not in args:
|
|
37
|
+
args.insert(0, "--liftoff-only")
|
|
38
|
+
return [node, *args]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _hidden_call(argv: list[str], env: dict) -> int:
|
|
42
|
+
si = subprocess.STARTUPINFO()
|
|
43
|
+
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
|
44
|
+
si.wShowWindow = 0
|
|
45
|
+
return subprocess.call(
|
|
46
|
+
argv,
|
|
47
|
+
env=env,
|
|
48
|
+
stdin=sys.stdin,
|
|
49
|
+
stdout=sys.stdout,
|
|
50
|
+
stderr=sys.stderr,
|
|
51
|
+
creationflags=_CREATE_NO_WINDOW,
|
|
52
|
+
startupinfo=si,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def main() -> int:
|
|
57
|
+
if len(sys.argv) < 2:
|
|
58
|
+
print(
|
|
59
|
+
"usage: win_mcp_launcher.py [--liftoff-only] [--stack-size=N] homegraph.js …",
|
|
60
|
+
file=sys.stderr,
|
|
61
|
+
)
|
|
62
|
+
return 2
|
|
63
|
+
env = os.environ.copy()
|
|
64
|
+
for key, val in _MCP_ENV_DEFAULTS.items():
|
|
65
|
+
env.setdefault(key, val)
|
|
66
|
+
argv = _node_argv(sys.argv[1:])
|
|
67
|
+
if os.name == "nt":
|
|
68
|
+
return _hidden_call(argv, env)
|
|
69
|
+
return subprocess.call(argv, env=env)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Windows MCP launcher: spawn homegraph with windowsHide while keeping stdio
|
|
4
|
+
* connected to DevEco (pythonw + Python subprocess breaks JSON-RPC pipes).
|
|
5
|
+
*
|
|
6
|
+
* Usage: node win_mcp_stdio_wrap.js [--stack-size=N] homegraph.js serve --mcp --path <repo>
|
|
7
|
+
*/
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const cp = require('child_process');
|
|
11
|
+
|
|
12
|
+
const node = process.env.HOMEGRAPH_NODE || process.execPath;
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
if (args.length === 0) {
|
|
15
|
+
process.stderr.write('usage: node win_mcp_stdio_wrap.js [--stack-size=N] homegraph.js …\n');
|
|
16
|
+
process.exit(2);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const child = cp.spawn(node, args, {
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
windowsHide: true,
|
|
22
|
+
env: process.env,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
child.on('error', (err) => {
|
|
26
|
+
process.stderr.write(String(err) + '\n');
|
|
27
|
+
process.exit(1);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
child.on('exit', (code, signal) => {
|
|
31
|
+
if (signal) {
|
|
32
|
+
process.kill(process.pid, signal);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
process.exit(code ?? 1);
|
|
36
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Windows: run node without a console window; inherit stdio (MCP / homegraph CLI)."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
_CREATE_NO_WINDOW = getattr(subprocess, "CREATE_NO_WINDOW", 0x08000000)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def main() -> int:
|
|
14
|
+
if len(sys.argv) < 2:
|
|
15
|
+
print("usage: win_node_launcher.py [--stack-size=N] script.js …", file=sys.stderr)
|
|
16
|
+
return 2
|
|
17
|
+
node = os.environ.get("HOMEGRAPH_NODE", "node")
|
|
18
|
+
cmd = [node, *sys.argv[1:]]
|
|
19
|
+
flags = _CREATE_NO_WINDOW if os.name == "nt" else 0
|
|
20
|
+
return subprocess.call(cmd, creationflags=flags)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
raise SystemExit(main())
|
package/scripts/npm-shim.js
CHANGED
|
@@ -45,7 +45,7 @@ async function main() {
|
|
|
45
45
|
// Happy path: the npm-installed optional dependency. Fall back to a download
|
|
46
46
|
// when the registry didn't deliver it.
|
|
47
47
|
var resolved = resolveInstalledBundle() || (await selfHealBundle());
|
|
48
|
-
var res = childProcess.spawnSync(resolved.command, resolved.args, { stdio: 'inherit' });
|
|
48
|
+
var res = childProcess.spawnSync(resolved.command, resolved.args, { stdio: 'inherit', windowsHide: true });
|
|
49
49
|
if (res.error) {
|
|
50
50
|
process.stderr.write('homegraph: ' + res.error.message + '\n');
|
|
51
51
|
process.exit(1);
|
|
@@ -105,7 +105,7 @@ async function selfHealBundle() {
|
|
|
105
105
|
// Already downloaded by a previous run? Use it even when downloads are
|
|
106
106
|
// disabled — HOMEGRAPH_NO_DOWNLOAD blocks fetching, not a cached bundle.
|
|
107
107
|
var cached = launcherIn(dest);
|
|
108
|
-
if (cached) return cached;
|
|
108
|
+
if (cached) { pruneOldBundles(bundlesDir, dest); return cached; }
|
|
109
109
|
|
|
110
110
|
if (process.env.HOMEGRAPH_NO_DOWNLOAD) {
|
|
111
111
|
fail('the network fallback is disabled (HOMEGRAPH_NO_DOWNLOAD is set).');
|
|
@@ -149,6 +149,7 @@ async function selfHealBundle() {
|
|
|
149
149
|
|
|
150
150
|
var ready = launcherIn(dest);
|
|
151
151
|
if (!ready) fail('downloaded bundle is missing its launcher under ' + dest + '.');
|
|
152
|
+
pruneOldBundles(bundlesDir, dest);
|
|
152
153
|
process.stderr.write('homegraph: bundle ready.\n');
|
|
153
154
|
return ready;
|
|
154
155
|
}
|
|
@@ -221,7 +222,7 @@ function extract(archive, destDir) {
|
|
|
221
222
|
var args = isWindows
|
|
222
223
|
? ['-xf', archive, '-C', destDir, '--strip-components=1']
|
|
223
224
|
: ['-xzf', archive, '-C', destDir, '--strip-components=1'];
|
|
224
|
-
var res = childProcess.spawnSync('tar', args, { stdio: 'ignore' });
|
|
225
|
+
var res = childProcess.spawnSync('tar', args, { stdio: 'ignore', windowsHide: true });
|
|
225
226
|
if (res.error) throw new Error('tar unavailable: ' + res.error.message);
|
|
226
227
|
if (res.status !== 0) throw new Error('tar exited ' + res.status);
|
|
227
228
|
}
|
|
@@ -230,6 +231,27 @@ function rmrf(p) {
|
|
|
230
231
|
try { fs.rmSync(p, { recursive: true, force: true }); } catch (e) { /* best effort */ }
|
|
231
232
|
}
|
|
232
233
|
|
|
234
|
+
// Drop sibling bundles for OTHER versions of this same platform target, keeping
|
|
235
|
+
// only keepDir. The self-heal cache otherwise accumulates a full ~50 MB bundle
|
|
236
|
+
// per version forever (issue #1074). Best-effort: a locked/busy dir (a
|
|
237
|
+
// concurrent run still mapping an older node.exe on Windows) just stays — rmrf
|
|
238
|
+
// already swallows its own errors, and the readdir is guarded — so cleanup can
|
|
239
|
+
// never break a working command. Only this target's "<target>-<version>" dirs
|
|
240
|
+
// are touched; other platforms' bundles and the ".dl-*" staging dirs are left
|
|
241
|
+
// alone.
|
|
242
|
+
function pruneOldBundles(bundlesDir, keepDir) {
|
|
243
|
+
var keep = path.basename(keepDir);
|
|
244
|
+
try {
|
|
245
|
+
var names = fs.readdirSync(bundlesDir);
|
|
246
|
+
for (var i = 0; i < names.length; i++) {
|
|
247
|
+
var name = names[i];
|
|
248
|
+
if (name === keep) continue;
|
|
249
|
+
if (name.indexOf(target + '-') !== 0) continue;
|
|
250
|
+
rmrf(path.join(bundlesDir, name));
|
|
251
|
+
}
|
|
252
|
+
} catch (e) { /* best effort — never break a working run over cleanup */ }
|
|
253
|
+
}
|
|
254
|
+
|
|
233
255
|
function fail(reason) {
|
|
234
256
|
process.stderr.write(
|
|
235
257
|
'homegraph: no prebuilt bundle for ' + target + '.\n' +
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Build and optionally publish homegraph-ohos-api-db-<version> (one npm package per API version).
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* node scripts/ohos-sdk-publish.mjs <zip-or-dir> [version] [--dry-run] [--no-publish]
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import {
|
|
12
|
+
resolveOhosSdkInput,
|
|
13
|
+
ohosApiDbFilename,
|
|
14
|
+
ohosApiDbPackageName,
|
|
15
|
+
indexOhosApiDb,
|
|
16
|
+
} from '../dist/extraction/languages/arkts.js';
|
|
17
|
+
|
|
18
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
19
|
+
|
|
20
|
+
function parseArgs(argv) {
|
|
21
|
+
const positional = [];
|
|
22
|
+
const flags = new Set();
|
|
23
|
+
for (let i = 2; i < argv.length; i++) {
|
|
24
|
+
const arg = argv[i];
|
|
25
|
+
if (arg.startsWith('--')) flags.add(arg);
|
|
26
|
+
else positional.push(arg);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
input: positional[0] ?? '',
|
|
30
|
+
version: positional[1] ?? '',
|
|
31
|
+
dryRun: flags.has('--dry-run'),
|
|
32
|
+
noPublish: flags.has('--no-publish'),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function buildNpmPackage(version, dbPath, outDir) {
|
|
37
|
+
const dbName = ohosApiDbFilename(version);
|
|
38
|
+
const pkgName = ohosApiDbPackageName(version);
|
|
39
|
+
fs.rmSync(outDir, { recursive: true, force: true });
|
|
40
|
+
fs.mkdirSync(path.join(outDir, 'scripts'), { recursive: true });
|
|
41
|
+
fs.copyFileSync(dbPath, path.join(outDir, dbName));
|
|
42
|
+
|
|
43
|
+
const postinstall = `#!/usr/bin/env node
|
|
44
|
+
'use strict';
|
|
45
|
+
const fs = require('fs');
|
|
46
|
+
const path = require('path');
|
|
47
|
+
const os = require('os');
|
|
48
|
+
const dbName = ${JSON.stringify(dbName)};
|
|
49
|
+
const src = path.join(__dirname, '..', dbName);
|
|
50
|
+
const dest = path.join(os.homedir(), '.homegraph', 'api', dbName);
|
|
51
|
+
if (!fs.existsSync(src)) process.exit(0);
|
|
52
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
53
|
+
fs.copyFileSync(src, dest);
|
|
54
|
+
`;
|
|
55
|
+
fs.writeFileSync(path.join(outDir, 'scripts', 'postinstall.js'), postinstall, { mode: 0o755 });
|
|
56
|
+
fs.writeFileSync(
|
|
57
|
+
path.join(outDir, 'package.json'),
|
|
58
|
+
JSON.stringify(
|
|
59
|
+
{
|
|
60
|
+
name: pkgName,
|
|
61
|
+
version: '1.0.0',
|
|
62
|
+
description: `Prebuilt HomeGraph OHOS API database for SDK ${version}`,
|
|
63
|
+
license: 'MIT',
|
|
64
|
+
files: [dbName, 'scripts/postinstall.js'],
|
|
65
|
+
scripts: { postinstall: 'node scripts/postinstall.js' },
|
|
66
|
+
homegraph: { ohosApiVersion: version, dbFile: dbName },
|
|
67
|
+
},
|
|
68
|
+
null,
|
|
69
|
+
2
|
|
70
|
+
) + '\n'
|
|
71
|
+
);
|
|
72
|
+
return pkgName;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const { input, version, dryRun, noPublish } = parseArgs(process.argv);
|
|
76
|
+
if (!input) {
|
|
77
|
+
console.error('Usage: node scripts/ohos-sdk-publish.mjs <zip-or-dir> [version] [--dry-run] [--no-publish]');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!fs.existsSync(path.join(ROOT, 'dist/extraction/languages/arkts.js'))) {
|
|
82
|
+
console.error('[ohos-sdk-publish] dist not built — run npm run build first');
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const resolved = resolveOhosSdkInput({
|
|
87
|
+
inputPath: path.resolve(input),
|
|
88
|
+
versionOverride: version || undefined,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const dbPath = path.join(
|
|
92
|
+
fs.mkdtempSync(path.join(path.dirname(resolved.sdkHome), '.hg-ohos-pack-')),
|
|
93
|
+
ohosApiDbFilename(resolved.version)
|
|
94
|
+
);
|
|
95
|
+
const pkgDir = path.join(path.dirname(dbPath), 'npm-package');
|
|
96
|
+
|
|
97
|
+
try {
|
|
98
|
+
process.stderr.write(`[ohos-sdk-publish] indexing ${resolved.version} …\n`);
|
|
99
|
+
const result = await indexOhosApiDb({
|
|
100
|
+
sdkHome: resolved.sdkHome,
|
|
101
|
+
version: resolved.version,
|
|
102
|
+
outputPath: dbPath,
|
|
103
|
+
onProgress: (p) => {
|
|
104
|
+
if (p.phase === 'arkts-batch') {
|
|
105
|
+
const label = p.subphase === 'scene' ? 'Scene' : 'Persist';
|
|
106
|
+
process.stderr.write(`\r${label}: ${p.current}/${p.total}`.padEnd(40));
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
process.stderr.write('\n');
|
|
111
|
+
if (!result.success) {
|
|
112
|
+
for (const err of result.errors.filter((e) => e.severity === 'error')) console.error(err.message);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const pkgName = buildNpmPackage(resolved.version, dbPath, pkgDir);
|
|
117
|
+
console.log(`[ohos-sdk-publish] package: ${pkgName} → ${pkgDir} (${result.nodesCreated} nodes)`);
|
|
118
|
+
|
|
119
|
+
if (dryRun || noPublish) {
|
|
120
|
+
console.log('[ohos-sdk-publish] skipping npm publish');
|
|
121
|
+
process.exit(0);
|
|
122
|
+
}
|
|
123
|
+
if (!process.env.NPM_TOKEN) {
|
|
124
|
+
console.error('[ohos-sdk-publish] NPM_TOKEN not set — package built, not published');
|
|
125
|
+
process.exit(0);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const { execFileSync } = await import('child_process');
|
|
129
|
+
execFileSync('npm', ['publish', '--access', 'public'], { cwd: pkgDir, stdio: 'inherit' });
|
|
130
|
+
console.log(`[ohos-sdk-publish] published ${pkgName}`);
|
|
131
|
+
} finally {
|
|
132
|
+
resolved.cleanup?.();
|
|
133
|
+
}
|
|
@@ -389,7 +389,7 @@ python scripts/qa_eval/run_pipeline.py ab --no-agent -r /path/to/repo
|
|
|
389
389
|
| DevEco `ServeError` / 端口占用 | `netstat -ano \| findstr :4096` 后结束进程,或不加 `--deveco-attach` |
|
|
390
390
|
| DevEco 凭证损坏 | `deveco providers reset` 后重新 login |
|
|
391
391
|
| `401` / Judge 全失败 | 检查 Key;智谱用 `--provider zhipu`,Key 格式 `id.secret` |
|
|
392
|
-
| `Cannot find module 'arkanalyzer'` | `npm run build
|
|
392
|
+
| `Cannot find module 'arkanalyzer'` | 发布包 < 下一版时未打进 bundle;升级 homegraph,或源码路径 `npm install && npm run build` 后用 `node dist/bin/homegraph.js sync` |
|
|
393
393
|
| `rg not found on PATH` | 安装 ripgrep(without 臂 builtin 需要) |
|
|
394
394
|
| 日志解析 0 条任务 | 确认 log 含 `Evaluate N:` 行 |
|
|
395
395
|
| 内存全为 N/A | Windows 原生无 `/proc`;用 WSL/Linux 测内存,或忽略该列 |
|
|
@@ -68,7 +68,7 @@ def find_homegraph_bin(explicit: str | None = None) -> str:
|
|
|
68
68
|
return str(p.resolve())
|
|
69
69
|
raise FileNotFoundError(f"homegraph binary not found: {explicit}")
|
|
70
70
|
|
|
71
|
-
# Prefer local dev build
|
|
71
|
+
# Prefer local dev build when testing unreleased changes
|
|
72
72
|
repo_root = Path(__file__).resolve().parents[2]
|
|
73
73
|
for local in (
|
|
74
74
|
repo_root / "dist" / "bin" / "homegraph.js",
|