@harmonyos-arkts/opencode-plugin 0.0.12 → 0.0.13
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/dist/index.js +153 -47
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5052,32 +5052,32 @@ var require_URL = __commonJS({
|
|
|
5052
5052
|
else
|
|
5053
5053
|
return basepath.substring(0, lastslash + 1) + refpath;
|
|
5054
5054
|
}
|
|
5055
|
-
function remove_dot_segments(
|
|
5056
|
-
if (!
|
|
5055
|
+
function remove_dot_segments(path9) {
|
|
5056
|
+
if (!path9) return path9;
|
|
5057
5057
|
var output = "";
|
|
5058
|
-
while (
|
|
5059
|
-
if (
|
|
5060
|
-
|
|
5058
|
+
while (path9.length > 0) {
|
|
5059
|
+
if (path9 === "." || path9 === "..") {
|
|
5060
|
+
path9 = "";
|
|
5061
5061
|
break;
|
|
5062
5062
|
}
|
|
5063
|
-
var twochars =
|
|
5064
|
-
var threechars =
|
|
5065
|
-
var fourchars =
|
|
5063
|
+
var twochars = path9.substring(0, 2);
|
|
5064
|
+
var threechars = path9.substring(0, 3);
|
|
5065
|
+
var fourchars = path9.substring(0, 4);
|
|
5066
5066
|
if (threechars === "../") {
|
|
5067
|
-
|
|
5067
|
+
path9 = path9.substring(3);
|
|
5068
5068
|
} else if (twochars === "./") {
|
|
5069
|
-
|
|
5069
|
+
path9 = path9.substring(2);
|
|
5070
5070
|
} else if (threechars === "/./") {
|
|
5071
|
-
|
|
5072
|
-
} else if (twochars === "/." &&
|
|
5073
|
-
|
|
5074
|
-
} else if (fourchars === "/../" || threechars === "/.." &&
|
|
5075
|
-
|
|
5071
|
+
path9 = "/" + path9.substring(3);
|
|
5072
|
+
} else if (twochars === "/." && path9.length === 2) {
|
|
5073
|
+
path9 = "/";
|
|
5074
|
+
} else if (fourchars === "/../" || threechars === "/.." && path9.length === 3) {
|
|
5075
|
+
path9 = "/" + path9.substring(4);
|
|
5076
5076
|
output = output.replace(/\/?[^\/]*$/, "");
|
|
5077
5077
|
} else {
|
|
5078
|
-
var segment =
|
|
5078
|
+
var segment = path9.match(/(\/?([^\/]*))/)[0];
|
|
5079
5079
|
output += segment;
|
|
5080
|
-
|
|
5080
|
+
path9 = path9.substring(segment.length);
|
|
5081
5081
|
}
|
|
5082
5082
|
}
|
|
5083
5083
|
return output;
|
|
@@ -18304,10 +18304,10 @@ function mergeDefs(...defs) {
|
|
|
18304
18304
|
function cloneDef(schema) {
|
|
18305
18305
|
return mergeDefs(schema._zod.def);
|
|
18306
18306
|
}
|
|
18307
|
-
function getElementAtPath(obj,
|
|
18308
|
-
if (!
|
|
18307
|
+
function getElementAtPath(obj, path9) {
|
|
18308
|
+
if (!path9)
|
|
18309
18309
|
return obj;
|
|
18310
|
-
return
|
|
18310
|
+
return path9.reduce((acc, key) => acc?.[key], obj);
|
|
18311
18311
|
}
|
|
18312
18312
|
function promiseAllObject(promisesObj) {
|
|
18313
18313
|
const keys = Object.keys(promisesObj);
|
|
@@ -18690,11 +18690,11 @@ function aborted(x, startIndex = 0) {
|
|
|
18690
18690
|
}
|
|
18691
18691
|
return false;
|
|
18692
18692
|
}
|
|
18693
|
-
function prefixIssues(
|
|
18693
|
+
function prefixIssues(path9, issues) {
|
|
18694
18694
|
return issues.map((iss) => {
|
|
18695
18695
|
var _a2;
|
|
18696
18696
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
18697
|
-
iss.path.unshift(
|
|
18697
|
+
iss.path.unshift(path9);
|
|
18698
18698
|
return iss;
|
|
18699
18699
|
});
|
|
18700
18700
|
}
|
|
@@ -18877,7 +18877,7 @@ function formatError(error92, mapper = (issue3) => issue3.message) {
|
|
|
18877
18877
|
}
|
|
18878
18878
|
function treeifyError(error92, mapper = (issue3) => issue3.message) {
|
|
18879
18879
|
const result = { errors: [] };
|
|
18880
|
-
const processError = (error93,
|
|
18880
|
+
const processError = (error93, path9 = []) => {
|
|
18881
18881
|
var _a2, _b;
|
|
18882
18882
|
for (const issue3 of error93.issues) {
|
|
18883
18883
|
if (issue3.code === "invalid_union" && issue3.errors.length) {
|
|
@@ -18887,7 +18887,7 @@ function treeifyError(error92, mapper = (issue3) => issue3.message) {
|
|
|
18887
18887
|
} else if (issue3.code === "invalid_element") {
|
|
18888
18888
|
processError({ issues: issue3.issues }, issue3.path);
|
|
18889
18889
|
} else {
|
|
18890
|
-
const fullpath = [...
|
|
18890
|
+
const fullpath = [...path9, ...issue3.path];
|
|
18891
18891
|
if (fullpath.length === 0) {
|
|
18892
18892
|
result.errors.push(mapper(issue3));
|
|
18893
18893
|
continue;
|
|
@@ -18919,8 +18919,8 @@ function treeifyError(error92, mapper = (issue3) => issue3.message) {
|
|
|
18919
18919
|
}
|
|
18920
18920
|
function toDotPath(_path) {
|
|
18921
18921
|
const segs = [];
|
|
18922
|
-
const
|
|
18923
|
-
for (const seg of
|
|
18922
|
+
const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
18923
|
+
for (const seg of path9) {
|
|
18924
18924
|
if (typeof seg === "number")
|
|
18925
18925
|
segs.push(`[${seg}]`);
|
|
18926
18926
|
else if (typeof seg === "symbol")
|
|
@@ -30897,13 +30897,13 @@ function resolveRef(ref, ctx) {
|
|
|
30897
30897
|
if (!ref.startsWith("#")) {
|
|
30898
30898
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
30899
30899
|
}
|
|
30900
|
-
const
|
|
30901
|
-
if (
|
|
30900
|
+
const path9 = ref.slice(1).split("/").filter(Boolean);
|
|
30901
|
+
if (path9.length === 0) {
|
|
30902
30902
|
return ctx.rootSchema;
|
|
30903
30903
|
}
|
|
30904
30904
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
30905
|
-
if (
|
|
30906
|
-
const key =
|
|
30905
|
+
if (path9[0] === defsKey) {
|
|
30906
|
+
const key = path9[1];
|
|
30907
30907
|
if (!key || !ctx.defs[key]) {
|
|
30908
30908
|
throw new Error(`Reference not found: ${ref}`);
|
|
30909
30909
|
}
|
|
@@ -31572,6 +31572,7 @@ var HM_DESIGN = `
|
|
|
31572
31572
|
- Use the \`harmonyos-prd-design\` skill to create prd desgin documents
|
|
31573
31573
|
- Reference design patterns and best practices from the skill documentation
|
|
31574
31574
|
- Design documents should be stored in the project's \`.harmonyos/\` directory
|
|
31575
|
+
- After UX renders the prototype, write it as \`prototype.html\`, then call \`html_preview\` with \`filePath\` set to that file's local path so the frontend can open it reliably
|
|
31575
31576
|
`;
|
|
31576
31577
|
var HM_DEVELOP = `
|
|
31577
31578
|
### Development Phase
|
|
@@ -32938,10 +32939,10 @@ function mergeDefs2(...defs) {
|
|
|
32938
32939
|
function cloneDef2(schema) {
|
|
32939
32940
|
return mergeDefs2(schema._zod.def);
|
|
32940
32941
|
}
|
|
32941
|
-
function getElementAtPath2(obj,
|
|
32942
|
-
if (!
|
|
32942
|
+
function getElementAtPath2(obj, path9) {
|
|
32943
|
+
if (!path9)
|
|
32943
32944
|
return obj;
|
|
32944
|
-
return
|
|
32945
|
+
return path9.reduce((acc, key) => acc?.[key], obj);
|
|
32945
32946
|
}
|
|
32946
32947
|
function promiseAllObject2(promisesObj) {
|
|
32947
32948
|
const keys = Object.keys(promisesObj);
|
|
@@ -33302,11 +33303,11 @@ function aborted2(x, startIndex = 0) {
|
|
|
33302
33303
|
}
|
|
33303
33304
|
return false;
|
|
33304
33305
|
}
|
|
33305
|
-
function prefixIssues2(
|
|
33306
|
+
function prefixIssues2(path9, issues) {
|
|
33306
33307
|
return issues.map((iss) => {
|
|
33307
33308
|
var _a2;
|
|
33308
33309
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
33309
|
-
iss.path.unshift(
|
|
33310
|
+
iss.path.unshift(path9);
|
|
33310
33311
|
return iss;
|
|
33311
33312
|
});
|
|
33312
33313
|
}
|
|
@@ -33474,7 +33475,7 @@ function treeifyError2(error92, _mapper) {
|
|
|
33474
33475
|
return issue3.message;
|
|
33475
33476
|
};
|
|
33476
33477
|
const result = { errors: [] };
|
|
33477
|
-
const processError = (error93,
|
|
33478
|
+
const processError = (error93, path9 = []) => {
|
|
33478
33479
|
var _a2, _b;
|
|
33479
33480
|
for (const issue3 of error93.issues) {
|
|
33480
33481
|
if (issue3.code === "invalid_union" && issue3.errors.length) {
|
|
@@ -33484,7 +33485,7 @@ function treeifyError2(error92, _mapper) {
|
|
|
33484
33485
|
} else if (issue3.code === "invalid_element") {
|
|
33485
33486
|
processError({ issues: issue3.issues }, issue3.path);
|
|
33486
33487
|
} else {
|
|
33487
|
-
const fullpath = [...
|
|
33488
|
+
const fullpath = [...path9, ...issue3.path];
|
|
33488
33489
|
if (fullpath.length === 0) {
|
|
33489
33490
|
result.errors.push(mapper(issue3));
|
|
33490
33491
|
continue;
|
|
@@ -33516,8 +33517,8 @@ function treeifyError2(error92, _mapper) {
|
|
|
33516
33517
|
}
|
|
33517
33518
|
function toDotPath2(_path) {
|
|
33518
33519
|
const segs = [];
|
|
33519
|
-
const
|
|
33520
|
-
for (const seg of
|
|
33520
|
+
const path9 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
33521
|
+
for (const seg of path9) {
|
|
33521
33522
|
if (typeof seg === "number")
|
|
33522
33523
|
segs.push(`[${seg}]`);
|
|
33523
33524
|
else if (typeof seg === "symbol")
|
|
@@ -45341,22 +45342,22 @@ var HEADERS = {
|
|
|
45341
45342
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36"
|
|
45342
45343
|
};
|
|
45343
45344
|
var REQUEST_TIMEOUT_MS = 1e4;
|
|
45344
|
-
async function post(
|
|
45345
|
+
async function post(path9, body) {
|
|
45345
45346
|
const controller = new AbortController();
|
|
45346
45347
|
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
45347
45348
|
try {
|
|
45348
|
-
const res = await fetch(BASE_URL +
|
|
45349
|
+
const res = await fetch(BASE_URL + path9, {
|
|
45349
45350
|
method: "POST",
|
|
45350
45351
|
headers: HEADERS,
|
|
45351
45352
|
body: JSON.stringify(body),
|
|
45352
45353
|
signal: controller.signal
|
|
45353
45354
|
});
|
|
45354
45355
|
if (!res.ok) {
|
|
45355
|
-
throw new Error(`API request failed: ${res.status} ${res.statusText} for ${
|
|
45356
|
+
throw new Error(`API request failed: ${res.status} ${res.statusText} for ${path9}`);
|
|
45356
45357
|
}
|
|
45357
45358
|
const data = await res.json();
|
|
45358
45359
|
if (data.code && data.code !== 0 && data.code !== "0") {
|
|
45359
|
-
throw new Error(`API error [${data.code}]: ${data.message} for ${
|
|
45360
|
+
throw new Error(`API error [${data.code}]: ${data.message} for ${path9}`);
|
|
45360
45361
|
}
|
|
45361
45362
|
return data;
|
|
45362
45363
|
} finally {
|
|
@@ -45613,6 +45614,82 @@ Use harmony-doc-view with a URL above to read any official document in full.`
|
|
|
45613
45614
|
});
|
|
45614
45615
|
}
|
|
45615
45616
|
|
|
45617
|
+
// src/tools/html-preview/html-preview-tool.ts
|
|
45618
|
+
import { access } from "fs/promises";
|
|
45619
|
+
import path7 from "path";
|
|
45620
|
+
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
45621
|
+
var PROTOTYPE_HTML_FILENAME = "prototype.html";
|
|
45622
|
+
function toFileUrl(filePath) {
|
|
45623
|
+
return pathToFileURL(path7.resolve(filePath)).href;
|
|
45624
|
+
}
|
|
45625
|
+
async function fileExists(filePath) {
|
|
45626
|
+
try {
|
|
45627
|
+
await access(filePath);
|
|
45628
|
+
return true;
|
|
45629
|
+
} catch {
|
|
45630
|
+
return false;
|
|
45631
|
+
}
|
|
45632
|
+
}
|
|
45633
|
+
function resolvePrototypePath(directory, input) {
|
|
45634
|
+
const trimmed = input.trim();
|
|
45635
|
+
if (!trimmed) {
|
|
45636
|
+
throw new Error("filePath is required");
|
|
45637
|
+
}
|
|
45638
|
+
if (trimmed.startsWith("file://")) {
|
|
45639
|
+
return fileURLToPath2(trimmed);
|
|
45640
|
+
}
|
|
45641
|
+
return path7.isAbsolute(trimmed) ? trimmed : path7.resolve(directory, trimmed);
|
|
45642
|
+
}
|
|
45643
|
+
async function resolvePrototypePreview(directory, filePathInput) {
|
|
45644
|
+
const filePath = resolvePrototypePath(directory, filePathInput);
|
|
45645
|
+
if (!await fileExists(filePath)) {
|
|
45646
|
+
throw new Error(
|
|
45647
|
+
`Prototype HTML not found: ${filePath}. Pass the exact local path where ${PROTOTYPE_HTML_FILENAME} was written.`
|
|
45648
|
+
);
|
|
45649
|
+
}
|
|
45650
|
+
return { url: toFileUrl(filePath), filePath };
|
|
45651
|
+
}
|
|
45652
|
+
function htmlPreviewTool(_managers) {
|
|
45653
|
+
return tool({
|
|
45654
|
+
description: "Send the UX prototype preview to the frontend. Call this immediately after writing prototype.html. You MUST pass filePath with the exact local path of the written file so the frontend can locate and preview it.",
|
|
45655
|
+
args: {
|
|
45656
|
+
filePath: tool.schema.string(
|
|
45657
|
+
"Local path to prototype.html. Use the same path from the write step, e.g. prototype.html, /Users/yanqing/coding/your-project/prototype.html, or file:///.../prototype.html."
|
|
45658
|
+
),
|
|
45659
|
+
title: tool.schema.optional(
|
|
45660
|
+
tool.schema.string("Optional title shown in the preview panel")
|
|
45661
|
+
)
|
|
45662
|
+
},
|
|
45663
|
+
execute: async (args, context) => {
|
|
45664
|
+
try {
|
|
45665
|
+
log("[html_preview]", { filePath: args.filePath, title: args.title });
|
|
45666
|
+
const { url: url3, filePath } = await resolvePrototypePreview(context.directory, args.filePath);
|
|
45667
|
+
const title = args.title?.trim() || "Prototype Preview";
|
|
45668
|
+
const metadata = {
|
|
45669
|
+
url: url3,
|
|
45670
|
+
filePath,
|
|
45671
|
+
fileName: path7.basename(filePath),
|
|
45672
|
+
title
|
|
45673
|
+
};
|
|
45674
|
+
context.metadata({
|
|
45675
|
+
title,
|
|
45676
|
+
metadata: {
|
|
45677
|
+
htmlPreview: metadata
|
|
45678
|
+
}
|
|
45679
|
+
});
|
|
45680
|
+
return [
|
|
45681
|
+
"Prototype preview sent to frontend.",
|
|
45682
|
+
`Title: ${title}`,
|
|
45683
|
+
`Local path: ${filePath}`,
|
|
45684
|
+
`Preview URL: ${url3}`
|
|
45685
|
+
].join("\n");
|
|
45686
|
+
} catch (e) {
|
|
45687
|
+
return `Error: ${e instanceof Error ? e.message : String(e)}`;
|
|
45688
|
+
}
|
|
45689
|
+
}
|
|
45690
|
+
});
|
|
45691
|
+
}
|
|
45692
|
+
|
|
45616
45693
|
// node_modules/turndown/lib/turndown.es.js
|
|
45617
45694
|
function extend3(destination) {
|
|
45618
45695
|
for (var i = 1; i < arguments.length; i++) {
|
|
@@ -46786,6 +46863,7 @@ function createBuiltinTools(managers) {
|
|
|
46786
46863
|
return {
|
|
46787
46864
|
createHmTemplate: createHmTemplateTool(managers),
|
|
46788
46865
|
skillSearch: skillSearchTool(managers),
|
|
46866
|
+
html_preview: htmlPreviewTool(managers),
|
|
46789
46867
|
"harmony-doc-view": harmonyDocViewTool(managers)
|
|
46790
46868
|
};
|
|
46791
46869
|
}
|
|
@@ -46910,11 +46988,11 @@ Diff.prototype = {
|
|
|
46910
46988
|
}
|
|
46911
46989
|
}
|
|
46912
46990
|
},
|
|
46913
|
-
addToPath: function addToPath(
|
|
46914
|
-
var last =
|
|
46991
|
+
addToPath: function addToPath(path9, added, removed, oldPosInc, options) {
|
|
46992
|
+
var last = path9.lastComponent;
|
|
46915
46993
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
46916
46994
|
return {
|
|
46917
|
-
oldPos:
|
|
46995
|
+
oldPos: path9.oldPos + oldPosInc,
|
|
46918
46996
|
lastComponent: {
|
|
46919
46997
|
count: last.count + 1,
|
|
46920
46998
|
added,
|
|
@@ -46924,7 +47002,7 @@ Diff.prototype = {
|
|
|
46924
47002
|
};
|
|
46925
47003
|
} else {
|
|
46926
47004
|
return {
|
|
46927
|
-
oldPos:
|
|
47005
|
+
oldPos: path9.oldPos + oldPosInc,
|
|
46928
47006
|
lastComponent: {
|
|
46929
47007
|
count: 1,
|
|
46930
47008
|
added,
|
|
@@ -47361,6 +47439,9 @@ arrayDiff.join = arrayDiff.removeEmpty = function(value) {
|
|
|
47361
47439
|
return value;
|
|
47362
47440
|
};
|
|
47363
47441
|
|
|
47442
|
+
// src/hooks/tool-hooks.ts
|
|
47443
|
+
import path8 from "path";
|
|
47444
|
+
|
|
47364
47445
|
// src/compress/compile-hvigorw.ts
|
|
47365
47446
|
function processHvigorwCompileInfo(input, output) {
|
|
47366
47447
|
if (input.tool !== "bash") return;
|
|
@@ -47402,6 +47483,7 @@ function createToolHooks(sessionManager, projectDir) {
|
|
|
47402
47483
|
"tool.execute.after": async (input, output) => {
|
|
47403
47484
|
processHvigorwCompileInfo(input, output);
|
|
47404
47485
|
injectAiCodeChange(input, output);
|
|
47486
|
+
await injectHtmlPreview(input, output, projectDir);
|
|
47405
47487
|
await updateEtsCount(sessionManager, projectDir, input);
|
|
47406
47488
|
}
|
|
47407
47489
|
};
|
|
@@ -47427,6 +47509,30 @@ async function updateEtsCount(sessionManager, projectDir, input) {
|
|
|
47427
47509
|
}
|
|
47428
47510
|
}
|
|
47429
47511
|
}
|
|
47512
|
+
async function injectHtmlPreview(input, output, projectDir) {
|
|
47513
|
+
if (input.tool !== "html_preview") return;
|
|
47514
|
+
try {
|
|
47515
|
+
const existing = output.metadata.htmlPreview;
|
|
47516
|
+
if (existing?.url) {
|
|
47517
|
+
output.title = existing.title?.trim() || "Prototype Preview";
|
|
47518
|
+
return;
|
|
47519
|
+
}
|
|
47520
|
+
const filePathArg = input.args?.filePath;
|
|
47521
|
+
if (!filePathArg) return;
|
|
47522
|
+
const title = input.args?.title?.trim() || "Prototype Preview";
|
|
47523
|
+
const { url: url3, filePath } = await resolvePrototypePreview(projectDir, filePathArg);
|
|
47524
|
+
output.title = title;
|
|
47525
|
+
output.metadata.htmlPreview = {
|
|
47526
|
+
url: url3,
|
|
47527
|
+
filePath,
|
|
47528
|
+
fileName: path8.basename(filePath),
|
|
47529
|
+
title
|
|
47530
|
+
};
|
|
47531
|
+
log("htmlPreview injected", { url: url3, title });
|
|
47532
|
+
} catch (e) {
|
|
47533
|
+
log("htmlPreview after hook error", { tool: input.tool, error: String(e) });
|
|
47534
|
+
}
|
|
47535
|
+
}
|
|
47430
47536
|
function injectAiCodeChange(input, output) {
|
|
47431
47537
|
try {
|
|
47432
47538
|
if (input.tool === "write") {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "@harmonyos-arkts/opencode-plugin",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.13",
|
|
5
5
|
"description": "HarmonyOS Full-Lifecycle Development Assistant. Specialized in the complete development lifecycle of HarmonyOS applications, including project creation, UI development, state management, network requests, data storage, permission requests, performance optimization, testing, and release.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|