deveco-harness 0.1.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.en.md +71 -0
- package/README.md +71 -0
- package/deveco-harness.example.jsonc +32 -0
- package/dist/index.js +758 -0
- package/package.json +48 -0
- package/prompts/build.txt +164 -0
- package/prompts/plan.txt +118 -0
- package/skills/arkts-error-fixes/README.md +151 -0
- package/skills/arkts-error-fixes/SKILL.md +150 -0
- package/skills/arkts-error-fixes/assets/AnyTypeError.ets +269 -0
- package/skills/arkts-error-fixes/assets/AppStorageError.ets +22 -0
- package/skills/arkts-error-fixes/assets/ArrowFunctionConversionError.ets +42 -0
- package/skills/arkts-error-fixes/assets/AvoidAreaTypeError.ets +43 -0
- package/skills/arkts-error-fixes/assets/BreakpointTypeError.ets +71 -0
- package/skills/arkts-error-fixes/assets/CatchClauseTypeError.ets +54 -0
- package/skills/arkts-error-fixes/assets/ColorConsistencyError.ets +88 -0
- package/skills/arkts-error-fixes/assets/ColorPropertyError.ets +39 -0
- package/skills/arkts-error-fixes/assets/ContextTypeError.ets +105 -0
- package/skills/arkts-error-fixes/assets/DecoratorStateError.ets +64 -0
- package/skills/arkts-error-fixes/assets/DisplayListenerTypeError.ets +129 -0
- package/skills/arkts-error-fixes/assets/DuplicateEntryError.ets +35 -0
- package/skills/arkts-error-fixes/assets/ESObjectTypeError.ets +137 -0
- package/skills/arkts-error-fixes/assets/FontColorPropertyError.ets +42 -0
- package/skills/arkts-error-fixes/assets/FunctionReturnTypeError.ets +41 -0
- package/skills/arkts-error-fixes/assets/IDataSourceError.ets +79 -0
- package/skills/arkts-error-fixes/assets/ImplementationNotAllowedError.ets +38 -0
- package/skills/arkts-error-fixes/assets/InterfaceMethodSignatureError.ets +43 -0
- package/skills/arkts-error-fixes/assets/NotificationError.ets +34 -0
- package/skills/arkts-error-fixes/assets/ObjectLiteralInterfaceError.ets +49 -0
- package/skills/arkts-error-fixes/assets/ObjectLiteralTypeError.ets +54 -0
- package/skills/arkts-error-fixes/assets/ObjectSpreadError.ets +29 -0
- package/skills/arkts-error-fixes/assets/PossiblyNullError.ets +32 -0
- package/skills/arkts-error-fixes/assets/ResourceConversionError.ets +159 -0
- package/skills/arkts-error-fixes/assets/StandaloneFunctionContext.ets +116 -0
- package/skills/arkts-error-fixes/assets/StandaloneFunctionError.ets +85 -0
- package/skills/arkts-error-fixes/assets/StorageLinkDefaultError.ets +41 -0
- package/skills/arkts-error-fixes/assets/TitleButtonRectTypeError.ets +86 -0
- package/skills/arkts-error-fixes/assets/UnusedVariableWarning.ets +102 -0
- package/skills/arkts-error-fixes/assets/UtilityTypeError.ets +176 -0
- package/skills/arkts-error-fixes/assets/WindowRectSizeError.ets +65 -0
- package/skills/arkts-error-fixes/assets/WindowTypeError.ets +37 -0
- package/skills/arkts-error-fixes/reference/any_type_errors.md +433 -0
- package/skills/arkts-error-fixes/reference/appstorage_errors.md +95 -0
- package/skills/arkts-error-fixes/reference/arrow_function_conversion_errors.md +163 -0
- package/skills/arkts-error-fixes/reference/avoid_area_type_errors.md +59 -0
- package/skills/arkts-error-fixes/reference/breakpoint_type_errors.md +122 -0
- package/skills/arkts-error-fixes/reference/catch_clause_type_errors.md +89 -0
- package/skills/arkts-error-fixes/reference/color_consistency_errors.md +209 -0
- package/skills/arkts-error-fixes/reference/color_property_errors.md +136 -0
- package/skills/arkts-error-fixes/reference/context_type_errors.md +260 -0
- package/skills/arkts-error-fixes/reference/decorator_state_errors.md +109 -0
- package/skills/arkts-error-fixes/reference/display_listener_type_errors.md +149 -0
- package/skills/arkts-error-fixes/reference/duplicate_entry_errors.md +193 -0
- package/skills/arkts-error-fixes/reference/esobject_type_errors.md +110 -0
- package/skills/arkts-error-fixes/reference/fontcolor_property_errors.md +104 -0
- package/skills/arkts-error-fixes/reference/function_return_type_errors.md +194 -0
- package/skills/arkts-error-fixes/reference/idata_source_errors.md +77 -0
- package/skills/arkts-error-fixes/reference/implementation_not_allowed_errors.md +191 -0
- package/skills/arkts-error-fixes/reference/interface_method_signature_errors.md +143 -0
- package/skills/arkts-error-fixes/reference/notification_errors.md +110 -0
- package/skills/arkts-error-fixes/reference/object_literal_interface_errors.md +156 -0
- package/skills/arkts-error-fixes/reference/object_literal_type_errors.md +110 -0
- package/skills/arkts-error-fixes/reference/object_spread_errors.md +105 -0
- package/skills/arkts-error-fixes/reference/possibly_null_errors.md +156 -0
- package/skills/arkts-error-fixes/reference/resource_conversion_errors.md +154 -0
- package/skills/arkts-error-fixes/reference/standalone_function_errors.md +68 -0
- package/skills/arkts-error-fixes/reference/storage_link_default_errors.md +124 -0
- package/skills/arkts-error-fixes/reference/title_button_rect_type_errors.md +167 -0
- package/skills/arkts-error-fixes/reference/unused_variable_warnings.md +295 -0
- package/skills/arkts-error-fixes/reference/utility_type_errors.md +290 -0
- package/skills/arkts-error-fixes/reference/window_rect_size_errors.md +70 -0
- package/skills/arkts-error-fixes/reference/window_type_errors.md +95 -0
- package/skills/arkts-grammar-standards/SKILL.md +71 -0
- package/skills/arkts-grammar-standards/references/basic-syntax.md +103 -0
- package/skills/arkts-grammar-standards/references/restrictions.md +100 -0
- package/skills/arkts-grammar-standards/references/topic-aliases.json +93 -0
- package/skills/arkts-grammar-standards/references/ts-diff.md +108 -0
- package/skills/arkts-runtime-fix/SKILL.md +152 -0
- package/skills/arkts-runtime-fix/SKILL_CN.md +123 -0
- package/skills/arkts-runtime-fix/evals/evals.json +17 -0
- package/skills/arkts-runtime-fix/scripts/collect-hilog.mjs +116 -0
- package/skills/arkts-runtime-fix/scripts/collect-hilog.ts +115 -0
- package/skills/arkts-runtime-fix/scripts/fetch-faultlog.mjs +117 -0
- package/skills/arkts-runtime-fix/scripts/fetch-faultlog.ts +116 -0
- package/skills/arkts-runtime-fix/scripts/jscrash-report.mjs +149 -0
- package/skills/arkts-runtime-fix/scripts/parse-jscrash-log.mjs +126 -0
- package/skills/arkts-runtime-fix/scripts/parse-jscrash-log.ts +126 -0
- package/skills/arkts-runtime-fix/scripts/probe-faultlogger.mjs +160 -0
- package/skills/arkts-runtime-fix/scripts/probe-faultlogger.ts +160 -0
- package/skills/arkts-runtime-fix/scripts/shared/hdc.mjs +107 -0
- package/skills/arkts-runtime-fix/scripts/shared/hdc.ts +58 -0
- package/skills/arkts-runtime-fix/scripts/shared/jscrash-faultlogger.mjs +143 -0
- package/skills/arkts-runtime-fix/scripts/shared/jscrash-faultlogger.ts +148 -0
- package/skills/arkts-runtime-fix/scripts/shared/jscrash-parse.mjs +389 -0
- package/skills/arkts-runtime-fix/scripts/shared/jscrash-parse.ts +409 -0
- package/skills/arkts-runtime-fix/scripts/shared/utils.mjs +27 -0
- package/skills/arkts-runtime-fix/scripts/shared/utils.ts +27 -0
- package/skills/arkui-knowledge/SKILL.md +90 -0
- package/skills/arkui-knowledge/references/api-guardrails.md +60 -0
- package/skills/arkui-knowledge/references/common-mistakes.md +119 -0
- package/skills/arkui-knowledge/references/component-cookbook.md +135 -0
- package/skills/arkui-knowledge/references/ui-quality-checklist.md +36 -0
- package/skills/deveco-create-project/SKILL.md +144 -0
- package/skills/deveco-create-project/application/AppScope/app.json5 +10 -0
- package/skills/deveco-create-project/application/AppScope/resources/base/element/string.json +8 -0
- package/skills/deveco-create-project/application/AppScope/resources/base/media/background.png +0 -0
- package/skills/deveco-create-project/application/AppScope/resources/base/media/foreground.png +0 -0
- package/skills/deveco-create-project/application/AppScope/resources/base/media/layered_image.json +7 -0
- package/skills/deveco-create-project/application/build-profile.json5 +42 -0
- package/skills/deveco-create-project/application/code-linter.json5 +32 -0
- package/skills/deveco-create-project/application/entry/build-profile.json5 +33 -0
- package/skills/deveco-create-project/application/entry/hvigorfile.ts +7 -0
- package/skills/deveco-create-project/application/entry/obfuscation-rules.txt +23 -0
- package/skills/deveco-create-project/application/entry/oh-package.json5 +10 -0
- package/skills/deveco-create-project/application/entry/src/main/ets/entryability/EntryAbility.ets +63 -0
- package/skills/deveco-create-project/application/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets +31 -0
- package/skills/deveco-create-project/application/entry/src/main/ets/pages/Index.ets +38 -0
- package/skills/deveco-create-project/application/entry/src/main/module.json5 +50 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/element/color.json +8 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/element/float.json +8 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/element/string.json +16 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/media/background.png +0 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/media/foreground.png +0 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/media/layered_image.json +7 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/media/startIcon.png +0 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/profile/backup_config.json +3 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/base/profile/main_pages.json +5 -0
- package/skills/deveco-create-project/application/entry/src/main/resources/dark/element/color.json +8 -0
- package/skills/deveco-create-project/application/hvigor/hvigor-config.json5 +23 -0
- package/skills/deveco-create-project/application/hvigorfile.ts +7 -0
- package/skills/deveco-create-project/application/oh-package.json5 +10 -0
- package/skills/deveco-create-project/scripts/copy-template.mjs +216 -0
- package/skills/deveco-create-project/scripts/copy-template.ts +214 -0
- package/skills/deveco-create-project/scripts/detect-sdk.mjs +82 -0
- package/skills/deveco-create-project/scripts/detect-sdk.ts +95 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export type CrashReport = {
|
|
17
|
+
status: 'detected' | 'no_crash_signature';
|
|
18
|
+
source: string;
|
|
19
|
+
device: string;
|
|
20
|
+
bundle: string;
|
|
21
|
+
process: string;
|
|
22
|
+
errorType: string;
|
|
23
|
+
errorMessage: string;
|
|
24
|
+
suspectedFile: string;
|
|
25
|
+
keywords: string[];
|
|
26
|
+
topStack: string[];
|
|
27
|
+
excerpt: string[];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
type ScoredLine = {
|
|
31
|
+
line: string;
|
|
32
|
+
index: number;
|
|
33
|
+
score: number;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const ERROR_TYPE_RE =
|
|
37
|
+
/(TypeError|ReferenceError|RangeError|SyntaxError|BusinessError|ParameterError|ResourceError|SystemError|EvalError|URIError)/i;
|
|
38
|
+
const CRASH_SIGNAL_RE = /(jscrash|uncaught|exception|fatal|abort|crash|error)/i;
|
|
39
|
+
const STRONG_CRASH_SIGNAL_RE =
|
|
40
|
+
/(jscrash|uncaught|fatal|abort|crash|TypeError|ReferenceError|RangeError|SyntaxError|BusinessError|ParameterError|ResourceError|SystemError|EvalError|URIError)/i;
|
|
41
|
+
const FILE_RE = /([A-Za-z0-9_./\\-]+\.(ets|ts|js)(?::\d+:\d+)?)/i;
|
|
42
|
+
|
|
43
|
+
function trim(input: string) {
|
|
44
|
+
return input.trim();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function cleanLines(input: string) {
|
|
48
|
+
return input
|
|
49
|
+
.split(/\r?\n/)
|
|
50
|
+
.map((line) => line.trimEnd())
|
|
51
|
+
.filter((line) => line.trim().length > 0);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function unique(items: string[]) {
|
|
55
|
+
return [...new Set(items)];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function containsIgnoreCase(input: string, token: string) {
|
|
59
|
+
return input.toLowerCase().includes(token.toLowerCase());
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function firstMatch(input: string, patterns: RegExp[]) {
|
|
63
|
+
for (const pattern of patterns) {
|
|
64
|
+
const match = pattern.exec(input);
|
|
65
|
+
if (match?.[1]) {
|
|
66
|
+
return match[1].trim();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return '';
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function errorTypeFromText(input: string) {
|
|
74
|
+
const matches = input.match(new RegExp(ERROR_TYPE_RE.source, 'ig'));
|
|
75
|
+
if (!matches?.length) {
|
|
76
|
+
return '';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return matches[matches.length - 1];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function detectErrorType(lines: string[], anchor: number, focus: string) {
|
|
83
|
+
const headerText = lines.slice(0, 48).join('\n');
|
|
84
|
+
const fromHeader = errorTypeFromText(headerText);
|
|
85
|
+
if (fromHeader) {
|
|
86
|
+
return fromHeader;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (const line of lines.slice(0, 48)) {
|
|
90
|
+
const match = /^(?:Reason|Error\s+name|Error\s+type)\s*[::]\s*([A-Za-z]+Error)\s*$/i.exec(line.trim());
|
|
91
|
+
if (match?.[1] && ERROR_TYPE_RE.test(match[1])) {
|
|
92
|
+
return match[1];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (anchor >= 0) {
|
|
97
|
+
const aroundAnchor = errorTypeFromText(sliceWindow(lines, anchor, 12, 8).join('\n'));
|
|
98
|
+
if (aroundAnchor) {
|
|
99
|
+
return aroundAnchor;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const fromFocus = errorTypeFromText(focus);
|
|
104
|
+
if (fromFocus) {
|
|
105
|
+
return fromFocus;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return 'UnknownError';
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function detectBundle(input: string, bundleName: string) {
|
|
112
|
+
if (bundleName) {
|
|
113
|
+
return bundleName;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
firstMatch(input, [
|
|
118
|
+
/bundleName\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
119
|
+
/bundle\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
120
|
+
/app\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
121
|
+
]) || '(unknown)'
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function detectProcess(input: string, processHint: string) {
|
|
126
|
+
if (processHint) {
|
|
127
|
+
return processHint;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
firstMatch(input, [
|
|
132
|
+
/(?:process(?:Name)?)\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
133
|
+
/pid\s*[:=]\s*([0-9]+)/i,
|
|
134
|
+
]) || '(unknown)'
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function stackLike(line: string) {
|
|
139
|
+
return (
|
|
140
|
+
/at\s+.+:\d+:\d+/i.test(line) ||
|
|
141
|
+
/at\s+.+\(.+:\d+:\d+\)/i.test(line) ||
|
|
142
|
+
/([A-Za-z0-9_./\\-]+\.(ets|ts|js)):\d+:\d+/.test(line)
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function applicationFrameScore(line: string, bundle: string) {
|
|
147
|
+
let score = 0;
|
|
148
|
+
if (/entry[\\/].*\.ets/i.test(line)) {
|
|
149
|
+
score += 8;
|
|
150
|
+
}
|
|
151
|
+
if (/src[\\/].*\.(ets|ts|js)/i.test(line)) {
|
|
152
|
+
score += 6;
|
|
153
|
+
}
|
|
154
|
+
if (bundle !== '(unknown)' && containsIgnoreCase(line, bundle)) {
|
|
155
|
+
score += 4;
|
|
156
|
+
}
|
|
157
|
+
if (/(pages|page|feature|component|viewmodel|store|model)[\\/]/i.test(line)) {
|
|
158
|
+
score += 3;
|
|
159
|
+
}
|
|
160
|
+
if (/(framework|runtime|node_modules|oh_modules|libarkui|ets_runtime|foundation|system)[\\/]/i.test(line)) {
|
|
161
|
+
score -= 6;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return score;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function scoreCrashLine(line: string, bundle: string, processHint: string) {
|
|
168
|
+
let score = 0;
|
|
169
|
+
if (CRASH_SIGNAL_RE.test(line)) {
|
|
170
|
+
score += 5;
|
|
171
|
+
}
|
|
172
|
+
if (STRONG_CRASH_SIGNAL_RE.test(line)) {
|
|
173
|
+
score += 4;
|
|
174
|
+
}
|
|
175
|
+
if (ERROR_TYPE_RE.test(line)) {
|
|
176
|
+
score += 4;
|
|
177
|
+
}
|
|
178
|
+
if (stackLike(line)) {
|
|
179
|
+
score += 2;
|
|
180
|
+
}
|
|
181
|
+
if (bundle && bundle !== '(unknown)' && containsIgnoreCase(line, bundle)) {
|
|
182
|
+
score += 2;
|
|
183
|
+
}
|
|
184
|
+
if (processHint && processHint !== '(unknown)' && containsIgnoreCase(line, processHint)) {
|
|
185
|
+
score += 2;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return score;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function findCrashAnchor(lines: string[], bundle: string, processHint: string) {
|
|
192
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
193
|
+
const score = scoreCrashLine(lines[index], bundle, processHint);
|
|
194
|
+
if (score >= 7) {
|
|
195
|
+
return index;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
200
|
+
const score = scoreCrashLine(lines[index], bundle, processHint);
|
|
201
|
+
if (score >= 5) {
|
|
202
|
+
return index;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return -1;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function sliceWindow(lines: string[], anchor: number, before: number, after: number) {
|
|
210
|
+
if (anchor < 0) {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const start = Math.max(0, anchor - before);
|
|
215
|
+
const end = Math.min(lines.length, anchor + after + 1);
|
|
216
|
+
|
|
217
|
+
return lines.slice(start, end);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function findCrashSignal(lines: string[], start: number, end: number, step: 1 | -1) {
|
|
221
|
+
for (let index = start; step > 0 ? index < end : index >= end; index += step) {
|
|
222
|
+
if (CRASH_SIGNAL_RE.test(lines[index])) {
|
|
223
|
+
return lines[index].trim();
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return '';
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function detectErrorMessage(lines: string[], anchor: number) {
|
|
231
|
+
if (anchor >= 0) {
|
|
232
|
+
const forwardMatch = findCrashSignal(lines, anchor, Math.min(lines.length, anchor + 6), 1);
|
|
233
|
+
if (forwardMatch) {
|
|
234
|
+
return forwardMatch;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const backwardMatch = findCrashSignal(lines, anchor, Math.max(0, anchor - 3), -1);
|
|
238
|
+
if (backwardMatch) {
|
|
239
|
+
return backwardMatch;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return lines[anchor].trim();
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
246
|
+
if (CRASH_SIGNAL_RE.test(lines[index])) {
|
|
247
|
+
return lines[index].trim();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return lines[lines.length - 1] || '(not found)';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function detectTopStack(lines: string[], anchor: number) {
|
|
255
|
+
const around = anchor >= 0 ? sliceWindow(lines, anchor, 4, 18) : lines.slice(Math.max(0, lines.length - 24));
|
|
256
|
+
const frames = around.filter((line) => stackLike(line));
|
|
257
|
+
|
|
258
|
+
return unique(frames).slice(0, 8);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function detectSuspectedFile(topStack: string[], bundle: string) {
|
|
262
|
+
const candidates: ScoredLine[] = [];
|
|
263
|
+
for (let index = 0; index < topStack.length; index += 1) {
|
|
264
|
+
const line = topStack[index];
|
|
265
|
+
const match = FILE_RE.exec(line);
|
|
266
|
+
if (!match?.[1]) {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
candidates.push({
|
|
271
|
+
line: match[1],
|
|
272
|
+
index,
|
|
273
|
+
score: applicationFrameScore(match[1], bundle) - index,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (!candidates.length) {
|
|
278
|
+
return '(not found)';
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
candidates.sort((a, b) => b.score - a.score || a.index - b.index);
|
|
282
|
+
|
|
283
|
+
return candidates[0].line;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function detectKeywords(input: string) {
|
|
287
|
+
const candidates = [
|
|
288
|
+
'jscrash',
|
|
289
|
+
'uncaught',
|
|
290
|
+
'exception',
|
|
291
|
+
'fatal',
|
|
292
|
+
'typeerror',
|
|
293
|
+
'referenceerror',
|
|
294
|
+
'rangeerror',
|
|
295
|
+
'syntaxerror',
|
|
296
|
+
'businesserror',
|
|
297
|
+
'parametererror',
|
|
298
|
+
'resourceerror',
|
|
299
|
+
'systemerror',
|
|
300
|
+
'abort',
|
|
301
|
+
'crash',
|
|
302
|
+
];
|
|
303
|
+
|
|
304
|
+
return candidates.filter((item) => containsIgnoreCase(input, item));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function looksLikeCrash(input: string, anchor: number, errorType: string) {
|
|
308
|
+
if (errorType !== 'UnknownError') {
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
if (anchor >= 0) {
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return /(jscrash|uncaught|fatal|abort|crash)/i.test(input);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function pickExcerpt(lines: string[], anchor: number, bundle: string, processHint: string, limit: number) {
|
|
319
|
+
if (anchor >= 0) {
|
|
320
|
+
const around = sliceWindow(lines, anchor, 5, 18);
|
|
321
|
+
if (around.length) {
|
|
322
|
+
return around.slice(0, limit);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const scored = lines
|
|
327
|
+
.map((line, index) => ({
|
|
328
|
+
line,
|
|
329
|
+
index,
|
|
330
|
+
score: scoreCrashLine(line, bundle, processHint),
|
|
331
|
+
}))
|
|
332
|
+
.filter((item) => item.score > 0);
|
|
333
|
+
|
|
334
|
+
if (!scored.length) {
|
|
335
|
+
return lines.slice(Math.max(0, lines.length - limit));
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
const out: string[] = [];
|
|
339
|
+
for (const item of scored.slice(Math.max(0, scored.length - limit))) {
|
|
340
|
+
out.push(item.line);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return unique(out).slice(0, limit);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export function buildNextActionText(report: CrashReport) {
|
|
347
|
+
if (report.status === 'no_crash_signature') {
|
|
348
|
+
return 'Ask for a fuller crash log, a clearer repro, or optionally collect recent faultlogger or hilog evidence if needed.';
|
|
349
|
+
}
|
|
350
|
+
if (report.suspectedFile !== '(not found)') {
|
|
351
|
+
return `Inspect ${report.suspectedFile} first and make a minimal fix. Collect additional runtime evidence only if the current anchor is still too weak.`;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return 'Inspect the top stack frames first and make a minimal fix. If the stack is too weak, optionally collect more runtime evidence before broader code reading.';
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export function formatCrashReportText(report: CrashReport) {
|
|
358
|
+
return [
|
|
359
|
+
report.status === 'detected' ? 'Crash signature detected.' : 'No clear crash signature detected.',
|
|
360
|
+
`source: ${report.source}`,
|
|
361
|
+
`device: ${report.device}`,
|
|
362
|
+
`bundle: ${report.bundle}`,
|
|
363
|
+
`process: ${report.process}`,
|
|
364
|
+
`error_type: ${report.errorType}`,
|
|
365
|
+
`error_message: ${report.errorMessage}`,
|
|
366
|
+
`suspected_file: ${report.suspectedFile}`,
|
|
367
|
+
`keywords: ${report.keywords.length ? report.keywords.join(', ') : '(none)'}`,
|
|
368
|
+
'',
|
|
369
|
+
'Top stack:',
|
|
370
|
+
...(report.topStack.length ? report.topStack : ['(empty)']),
|
|
371
|
+
'',
|
|
372
|
+
'Evidence excerpt:',
|
|
373
|
+
...(report.excerpt.length ? report.excerpt : ['(empty)']),
|
|
374
|
+
'',
|
|
375
|
+
`next_action: ${buildNextActionText(report)}`,
|
|
376
|
+
].join('\n');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export function buildCrashReport(
|
|
380
|
+
input: string,
|
|
381
|
+
source: string,
|
|
382
|
+
device: string,
|
|
383
|
+
bundleName: string,
|
|
384
|
+
processHint: string,
|
|
385
|
+
): CrashReport {
|
|
386
|
+
const normalized = trim(input);
|
|
387
|
+
const lines = cleanLines(normalized);
|
|
388
|
+
const bundle = detectBundle(normalized, bundleName);
|
|
389
|
+
const process = detectProcess(normalized, processHint);
|
|
390
|
+
const anchor = findCrashAnchor(lines, bundle, process);
|
|
391
|
+
const focus = anchor >= 0 ? sliceWindow(lines, anchor, 5, 18).join('\n') : normalized;
|
|
392
|
+
const errorType = detectErrorType(lines, anchor, focus);
|
|
393
|
+
const topStack = detectTopStack(lines, anchor);
|
|
394
|
+
const excerpt = pickExcerpt(lines, anchor, bundle, process, 24);
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
status: looksLikeCrash(normalized, anchor, errorType) ? 'detected' : 'no_crash_signature',
|
|
398
|
+
source,
|
|
399
|
+
device,
|
|
400
|
+
bundle,
|
|
401
|
+
process,
|
|
402
|
+
errorType,
|
|
403
|
+
errorMessage: detectErrorMessage(lines, anchor),
|
|
404
|
+
suspectedFile: detectSuspectedFile(topStack, bundle),
|
|
405
|
+
keywords: detectKeywords(focus || normalized),
|
|
406
|
+
topStack,
|
|
407
|
+
excerpt,
|
|
408
|
+
};
|
|
409
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export function toErrorMessage(error) {
|
|
17
|
+
return error instanceof Error ? error.message : String(error);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function printKv(lines) {
|
|
21
|
+
const out = [];
|
|
22
|
+
for (const [key, value] of Object.entries(lines)) {
|
|
23
|
+
out.push(`${key}: ${value}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log(out.join('\n'));
|
|
27
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Huawei Device Co., Ltd.
|
|
3
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
* you may not use this file except in compliance with the License.
|
|
5
|
+
* You may obtain a copy of the License at
|
|
6
|
+
*
|
|
7
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
*
|
|
9
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
* See the License for the specific language governing permissions and
|
|
13
|
+
* limitations under the License.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export function toErrorMessage(error: unknown) {
|
|
17
|
+
return error instanceof Error ? error.message : String(error);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function printKv(lines: Record<string, string>) {
|
|
21
|
+
const out: string[] = [];
|
|
22
|
+
for (const [key, value] of Object.entries(lines)) {
|
|
23
|
+
out.push(`${key}: ${value}`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
console.log(out.join('\n'));
|
|
27
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: arkui-knowledge
|
|
3
|
+
description: Load this skill when answering ArkUI UI questions or when writing/modifying ArkUI components, layouts, state-driven UI, rendering control, navigation, dialogs, interactions, component APIs, or ArkUI declarative UI in .ets files.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# ArkUI Knowledge
|
|
7
|
+
|
|
8
|
+
Use this skill for ArkUI UI knowledge and implementation guidance. It helps answer ArkUI questions and helps agents write correct, polished ArkUI code on the first pass.
|
|
9
|
+
|
|
10
|
+
## When to load
|
|
11
|
+
|
|
12
|
+
Load this skill when the task involves:
|
|
13
|
+
|
|
14
|
+
- ArkUI components, component modifiers, component nesting, or declarative UI structure.
|
|
15
|
+
- Layout with `Column`, `Row`, `Stack`, `Flex`, `Grid`, `List`, `Scroll`, `Tabs`, or `TabContent`.
|
|
16
|
+
- UI state refresh with `@State`, `@Prop`, `@Link`, `@Local`, `@Param`, `@Provide`, `@Consume`, or related decorators.
|
|
17
|
+
- Rendering control with `ForEach`, `LazyForEach`, conditional UI, builders, or reusable UI blocks.
|
|
18
|
+
- Navigation, dialogs, toast prompts, menus, gestures, animation, visual styling, or UI quality.
|
|
19
|
+
- Writing or modifying `.ets` files that render visible ArkUI surfaces.
|
|
20
|
+
|
|
21
|
+
Do not load this skill for:
|
|
22
|
+
|
|
23
|
+
- Plain ArkTS syntax restrictions with no UI component concern; use `arkts-grammar-standards`.
|
|
24
|
+
- Build or type errors after compilation fails; use `arkts-error-fixes`.
|
|
25
|
+
- Runtime crashes, white screens, jscrash logs, or uncaught exceptions; use `arkts-runtime-fix`.
|
|
26
|
+
- New project creation or empty project initialization; use `deveco-create-project`.
|
|
27
|
+
|
|
28
|
+
## Responsibilities
|
|
29
|
+
|
|
30
|
+
- Explain ArkUI concepts, APIs, component choices, and correct usage.
|
|
31
|
+
- Guide page and component structure while preserving the current project style.
|
|
32
|
+
- Prevent high-frequency ArkUI mistakes before code is written.
|
|
33
|
+
- Improve UI quality: visible required text, clickable required controls, stable layout, state refresh, and minimal unrelated edits.
|
|
34
|
+
- Keep ArkUI guidance separate from ArkTS language restrictions and post-build error repair.
|
|
35
|
+
|
|
36
|
+
## Before answering or coding
|
|
37
|
+
|
|
38
|
+
1. Identify the ArkUI topic: component, layout, state, rendering, navigation, dialog, interaction, animation, or visual quality.
|
|
39
|
+
2. For questions, answer directly, then add the correct usage, common trap, and applicable boundary.
|
|
40
|
+
3. For code changes, read the target `.ets` file first. Keep the existing state-management style, navigation style, directory style, and business flow.
|
|
41
|
+
4. Check the relevant reference before using a high-risk API:
|
|
42
|
+
- `references/component-cookbook.md`
|
|
43
|
+
- `references/api-guardrails.md`
|
|
44
|
+
- `references/common-mistakes.md`
|
|
45
|
+
- `references/ui-quality-checklist.md`
|
|
46
|
+
5. If a component signature, enum, callback parameter, or modifier owner is unclear and the local references do not cover it, inspect official/project documentation or existing project usage before writing code.
|
|
47
|
+
|
|
48
|
+
## ArkUI component guardrails
|
|
49
|
+
|
|
50
|
+
- `Tabs` can contain `TabContent` directly. Build tabs with `Tabs(...) { TabContent() { ... }.tabBar(...) }`.
|
|
51
|
+
- Do not pass a `builder` object into `TabContent`; use `TabContent()` and set the label with `.tabBar(...)`.
|
|
52
|
+
- `ForEach` and `LazyForEach` key generators should return a stable string key from the item. Avoid `void` keys and index keys for business data.
|
|
53
|
+
- Place ArkUI state decorators only on component member declarations with the correct V1 or V2 decorator family. Do not mix V1 and V2 decorators in one component.
|
|
54
|
+
- Do not invent modifier names. Use full ArkUI names including `.backgroundColor()`, `.borderRadius()`, `.fontSize()`, and `.fontColor()`.
|
|
55
|
+
- Match modifiers to component owners. For example, text modifiers belong on `Text`, image fitting belongs on `Image`, and layout alignment differs by container.
|
|
56
|
+
- Prefer the existing navigation approach in the project. Do not replace router, `Navigation`, or custom app routers without a clear requirement.
|
|
57
|
+
- For dialogs, toast prompts, navigation, and animation, prefer valid UI context usage when the current project already follows that pattern.
|
|
58
|
+
|
|
59
|
+
## Common mistakes
|
|
60
|
+
|
|
61
|
+
Read `references/common-mistakes.md` before implementing UI with tabs, lists, decorators, dialogs, navigation, or custom builders.
|
|
62
|
+
|
|
63
|
+
High-risk mistakes to avoid:
|
|
64
|
+
|
|
65
|
+
- `TabContent` with a fake object parameter.
|
|
66
|
+
- `Tabs` containing direct non-`TabContent` children.
|
|
67
|
+
- `ForEach` key generator with a block body that does not return a string.
|
|
68
|
+
- `@State` on top-level variables, local variables, plain classes, or component inputs.
|
|
69
|
+
- `@ComponentV2` using V1 decorators including `@State`.
|
|
70
|
+
- Component modifiers borrowed from web, Android, other UI frameworks, or CSS shorthand.
|
|
71
|
+
- Dialog button fields with the wrong key names.
|
|
72
|
+
- Required UI text hidden by layout, overlay, tiny size, or unreachable navigation.
|
|
73
|
+
|
|
74
|
+
## UI quality checklist
|
|
75
|
+
|
|
76
|
+
Use `references/ui-quality-checklist.md` before finalizing UI work. At minimum:
|
|
77
|
+
|
|
78
|
+
- Required labels, buttons, cards, tabs, and dialog text are visible on the target screen.
|
|
79
|
+
- Required clicks update state, open the dialog, switch the tab, navigate, or show the expected response.
|
|
80
|
+
- New UI fits the current page density, spacing, color, and component style.
|
|
81
|
+
- Layout has stable dimensions where dynamic content could otherwise shift or overlap.
|
|
82
|
+
- The change is limited to files needed by the UI request.
|
|
83
|
+
|
|
84
|
+
## Boundaries with other skills
|
|
85
|
+
|
|
86
|
+
- Use `arkts-grammar-standards` for ArkTS language rules, TypeScript-to-ArkTS differences, template literals, dynamic property access, object literal typing, and syntax compliance.
|
|
87
|
+
- Use `arkts-error-fixes` only after compilation reports errors or when directly fixing build/type failures.
|
|
88
|
+
- Use `arkts-runtime-fix` for runtime stack traces, white screens, uncaught exceptions, and jscrash logs.
|
|
89
|
+
- Use `deveco-create-project` for project initialization.
|
|
90
|
+
- Do not perform state-management migration unless the user explicitly asks for that migration.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# ArkUI API Guardrails
|
|
2
|
+
|
|
3
|
+
Use these rules before writing ArkUI component constructors, modifiers, enum values, or callbacks.
|
|
4
|
+
|
|
5
|
+
## Component constructors
|
|
6
|
+
|
|
7
|
+
- `Tabs(options?)` accepts options including `barPosition`, `index`, and `controller`.
|
|
8
|
+
- `TabContent()` takes no object parameter; set the label with `.tabBar(...)`.
|
|
9
|
+
- `List({ space })` and `Grid()` contain their required item child components.
|
|
10
|
+
- `Row({ space })` and `Column({ space })` take spacing in the constructor.
|
|
11
|
+
- `Flex()` does not take a `space` option; use margins on children when needed.
|
|
12
|
+
- `Stack({ alignContent })` controls stack alignment; do not use row/column alignment methods on it.
|
|
13
|
+
|
|
14
|
+
## Modifier names
|
|
15
|
+
|
|
16
|
+
Use full ArkUI modifier names:
|
|
17
|
+
|
|
18
|
+
- `.backgroundColor(...)`
|
|
19
|
+
- `.borderRadius(...)`
|
|
20
|
+
- `.fontSize(...)`
|
|
21
|
+
- `.fontColor(...)`
|
|
22
|
+
- `.fontWeight(...)`
|
|
23
|
+
- `.textAlign(...)`
|
|
24
|
+
- `.objectFit(...)`
|
|
25
|
+
- `.textOverflow(...)`
|
|
26
|
+
|
|
27
|
+
Do not use shorthand names from other UI systems, including shortened background, radius, text size, or text color modifiers. Do not use Android layout constants for width or height.
|
|
28
|
+
|
|
29
|
+
## Modifier ownership
|
|
30
|
+
|
|
31
|
+
- `Text` owns text modifiers including `.fontSize(...)`, `.fontColor(...)`, `.fontWeight(...)`, `.textAlign(...)`, `.maxLines(...)`, and `.textOverflow(...)`.
|
|
32
|
+
- `Image` owns image modifiers including `.objectFit(...)`.
|
|
33
|
+
- `Column` and `Row` own layout alignment, but their alignment enum types differ.
|
|
34
|
+
- `Button` label styling is often clearer by placing styled `Text` inside `Button` when project style requires custom text styling.
|
|
35
|
+
- `List` owns list-level direction, edge, divider, and scroll behavior; `ListItem` owns per-row content.
|
|
36
|
+
|
|
37
|
+
## Parameters and callbacks
|
|
38
|
+
|
|
39
|
+
- `margin` and `padding` use a number, string, or object with edge names. Do not use multi-argument CSS-style shorthand.
|
|
40
|
+
- `AlertDialog` button entries use `{ value: '确定', action: () => {} }`.
|
|
41
|
+
- `ActionSheet` entries use `sheets`.
|
|
42
|
+
- Popup state-change callbacks receive an event object with visibility state.
|
|
43
|
+
- Event callback parameter types should be explicit when inference is unclear.
|
|
44
|
+
|
|
45
|
+
## Enums and resources
|
|
46
|
+
|
|
47
|
+
- Use ArkUI enum names with exact casing, for example `TextAlign.Center`, `FontWeight.Bold`, and `BarPosition.End`.
|
|
48
|
+
- Do not pass string values where an enum is expected.
|
|
49
|
+
- Do not guess system symbol or system color names. Use existing project resources or verified names.
|
|
50
|
+
|
|
51
|
+
## UIContext-sensitive APIs
|
|
52
|
+
|
|
53
|
+
When a project already uses UIContext for UI operations, follow it for:
|
|
54
|
+
|
|
55
|
+
- Toast prompts through `this.getUIContext().getPromptAction()`.
|
|
56
|
+
- Alert dialogs through `this.getUIContext().showAlertDialog(...)`.
|
|
57
|
+
- Router access through `this.getUIContext().getRouter()`.
|
|
58
|
+
- Animation through `this.getUIContext().animateTo(...)`.
|
|
59
|
+
|
|
60
|
+
If the current project has a wrapper for routing, dialog, toast, or logging, use the wrapper instead of introducing a new pattern.
|