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,389 @@
|
|
|
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
|
+
const ERROR_TYPE_RE =
|
|
17
|
+
/(TypeError|ReferenceError|RangeError|SyntaxError|BusinessError|ParameterError|ResourceError|SystemError|EvalError|URIError)/i;
|
|
18
|
+
const CRASH_SIGNAL_RE = /(jscrash|uncaught|exception|fatal|abort|crash|error)/i;
|
|
19
|
+
const STRONG_CRASH_SIGNAL_RE =
|
|
20
|
+
/(jscrash|uncaught|fatal|abort|crash|TypeError|ReferenceError|RangeError|SyntaxError|BusinessError|ParameterError|ResourceError|SystemError|EvalError|URIError)/i;
|
|
21
|
+
const FILE_RE = /([A-Za-z0-9_./\\-]+\.(ets|ts|js)(?::\d+:\d+)?)/i;
|
|
22
|
+
|
|
23
|
+
function trim(input) {
|
|
24
|
+
return input.trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function cleanLines(input) {
|
|
28
|
+
return input
|
|
29
|
+
.split(/\r?\n/)
|
|
30
|
+
.map((line) => line.trimEnd())
|
|
31
|
+
.filter((line) => line.trim().length > 0);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function unique(items) {
|
|
35
|
+
return [...new Set(items)];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function containsIgnoreCase(input, token) {
|
|
39
|
+
return input.toLowerCase().includes(token.toLowerCase());
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function firstMatch(input, patterns) {
|
|
43
|
+
for (const pattern of patterns) {
|
|
44
|
+
const match = pattern.exec(input);
|
|
45
|
+
if (match?.[1]) {
|
|
46
|
+
return match[1].trim();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function errorTypeFromText(input) {
|
|
54
|
+
const matches = input.match(new RegExp(ERROR_TYPE_RE.source, 'ig'));
|
|
55
|
+
if (!matches?.length) {
|
|
56
|
+
return '';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return matches[matches.length - 1];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function detectErrorType(lines, anchor, focus) {
|
|
63
|
+
const headerText = lines.slice(0, 48).join('\n');
|
|
64
|
+
const fromHeader = errorTypeFromText(headerText);
|
|
65
|
+
if (fromHeader) {
|
|
66
|
+
return fromHeader;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const line of lines.slice(0, 48)) {
|
|
70
|
+
const match = /^(?:Reason|Error\s+name|Error\s+type)\s*[::]\s*([A-Za-z]+Error)\s*$/i.exec(line.trim());
|
|
71
|
+
if (match?.[1] && ERROR_TYPE_RE.test(match[1])) {
|
|
72
|
+
return match[1];
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (anchor >= 0) {
|
|
77
|
+
const aroundAnchor = errorTypeFromText(sliceWindow(lines, anchor, 12, 8).join('\n'));
|
|
78
|
+
if (aroundAnchor) {
|
|
79
|
+
return aroundAnchor;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const fromFocus = errorTypeFromText(focus);
|
|
84
|
+
if (fromFocus) {
|
|
85
|
+
return fromFocus;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return 'UnknownError';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function detectBundle(input, bundleName) {
|
|
92
|
+
if (bundleName) {
|
|
93
|
+
return bundleName;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
firstMatch(input, [
|
|
98
|
+
/bundleName\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
99
|
+
/bundle\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
100
|
+
/app\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
101
|
+
]) || '(unknown)'
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function detectProcess(input, processHint) {
|
|
106
|
+
if (processHint) {
|
|
107
|
+
return processHint;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
firstMatch(input, [
|
|
112
|
+
/(?:process(?:Name)?)\s*[:=]\s*([A-Za-z0-9._-]+)/i,
|
|
113
|
+
/pid\s*[:=]\s*([0-9]+)/i,
|
|
114
|
+
]) || '(unknown)'
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function stackLike(line) {
|
|
119
|
+
return (
|
|
120
|
+
/at\s+.+:\d+:\d+/i.test(line) ||
|
|
121
|
+
/at\s+.+\(.+:\d+:\d+\)/i.test(line) ||
|
|
122
|
+
/([A-Za-z0-9_./\\-]+\.(ets|ts|js)):\d+:\d+/.test(line)
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function applicationFrameScore(line, bundle) {
|
|
127
|
+
let score = 0;
|
|
128
|
+
if (/entry[\\/].*\.ets/i.test(line)) {
|
|
129
|
+
score += 8;
|
|
130
|
+
}
|
|
131
|
+
if (/src[\\/].*\.(ets|ts|js)/i.test(line)) {
|
|
132
|
+
score += 6;
|
|
133
|
+
}
|
|
134
|
+
if (bundle !== '(unknown)' && containsIgnoreCase(line, bundle)) {
|
|
135
|
+
score += 4;
|
|
136
|
+
}
|
|
137
|
+
if (/(pages|page|feature|component|viewmodel|store|model)[\\/]/i.test(line)) {
|
|
138
|
+
score += 3;
|
|
139
|
+
}
|
|
140
|
+
if (/(framework|runtime|node_modules|oh_modules|libarkui|ets_runtime|foundation|system)[\\/]/i.test(line)) {
|
|
141
|
+
score -= 6;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return score;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function scoreCrashLine(line, bundle, processHint) {
|
|
148
|
+
let score = 0;
|
|
149
|
+
if (CRASH_SIGNAL_RE.test(line)) {
|
|
150
|
+
score += 5;
|
|
151
|
+
}
|
|
152
|
+
if (STRONG_CRASH_SIGNAL_RE.test(line)) {
|
|
153
|
+
score += 4;
|
|
154
|
+
}
|
|
155
|
+
if (ERROR_TYPE_RE.test(line)) {
|
|
156
|
+
score += 4;
|
|
157
|
+
}
|
|
158
|
+
if (stackLike(line)) {
|
|
159
|
+
score += 2;
|
|
160
|
+
}
|
|
161
|
+
if (bundle && bundle !== '(unknown)' && containsIgnoreCase(line, bundle)) {
|
|
162
|
+
score += 2;
|
|
163
|
+
}
|
|
164
|
+
if (processHint && processHint !== '(unknown)' && containsIgnoreCase(line, processHint)) {
|
|
165
|
+
score += 2;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return score;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function findCrashAnchor(lines, bundle, processHint) {
|
|
172
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
173
|
+
const score = scoreCrashLine(lines[index], bundle, processHint);
|
|
174
|
+
if (score >= 7) {
|
|
175
|
+
return index;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
180
|
+
const score = scoreCrashLine(lines[index], bundle, processHint);
|
|
181
|
+
if (score >= 5) {
|
|
182
|
+
return index;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return -1;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function sliceWindow(lines, anchor, before, after) {
|
|
190
|
+
if (anchor < 0) {
|
|
191
|
+
return [];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const start = Math.max(0, anchor - before);
|
|
195
|
+
const end = Math.min(lines.length, anchor + after + 1);
|
|
196
|
+
|
|
197
|
+
return lines.slice(start, end);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function findCrashSignal(lines, start, end, step) {
|
|
201
|
+
for (let index = start; step > 0 ? index < end : index >= end; index += step) {
|
|
202
|
+
if (CRASH_SIGNAL_RE.test(lines[index])) {
|
|
203
|
+
return lines[index].trim();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return '';
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function detectErrorMessage(lines, anchor) {
|
|
211
|
+
if (anchor >= 0) {
|
|
212
|
+
const forwardMatch = findCrashSignal(lines, anchor, Math.min(lines.length, anchor + 6), 1);
|
|
213
|
+
if (forwardMatch) {
|
|
214
|
+
return forwardMatch;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const backwardMatch = findCrashSignal(lines, anchor, Math.max(0, anchor - 3), -1);
|
|
218
|
+
if (backwardMatch) {
|
|
219
|
+
return backwardMatch;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return lines[anchor].trim();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
for (let index = lines.length - 1; index >= 0; index -= 1) {
|
|
226
|
+
if (CRASH_SIGNAL_RE.test(lines[index])) {
|
|
227
|
+
return lines[index].trim();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return lines[lines.length - 1] || '(not found)';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function detectTopStack(lines, anchor) {
|
|
235
|
+
const around = anchor >= 0 ? sliceWindow(lines, anchor, 4, 18) : lines.slice(Math.max(0, lines.length - 24));
|
|
236
|
+
const frames = around.filter((line) => stackLike(line));
|
|
237
|
+
|
|
238
|
+
return unique(frames).slice(0, 8);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function detectSuspectedFile(topStack, bundle) {
|
|
242
|
+
const candidates = [];
|
|
243
|
+
for (let index = 0; index < topStack.length; index += 1) {
|
|
244
|
+
const line = topStack[index];
|
|
245
|
+
const match = FILE_RE.exec(line);
|
|
246
|
+
if (!match?.[1]) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
candidates.push({
|
|
251
|
+
line: match[1],
|
|
252
|
+
index,
|
|
253
|
+
score: applicationFrameScore(match[1], bundle) - index,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
if (!candidates.length) {
|
|
258
|
+
return '(not found)';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
candidates.sort((a, b) => b.score - a.score || a.index - b.index);
|
|
262
|
+
|
|
263
|
+
return candidates[0].line;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function detectKeywords(input) {
|
|
267
|
+
const candidates = [
|
|
268
|
+
'jscrash',
|
|
269
|
+
'uncaught',
|
|
270
|
+
'exception',
|
|
271
|
+
'fatal',
|
|
272
|
+
'typeerror',
|
|
273
|
+
'referenceerror',
|
|
274
|
+
'rangeerror',
|
|
275
|
+
'syntaxerror',
|
|
276
|
+
'businesserror',
|
|
277
|
+
'parametererror',
|
|
278
|
+
'resourceerror',
|
|
279
|
+
'systemerror',
|
|
280
|
+
'abort',
|
|
281
|
+
'crash',
|
|
282
|
+
];
|
|
283
|
+
|
|
284
|
+
return candidates.filter((item) => containsIgnoreCase(input, item));
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function looksLikeCrash(input, anchor, errorType) {
|
|
288
|
+
if (errorType !== 'UnknownError') {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
if (anchor >= 0) {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return /(jscrash|uncaught|fatal|abort|crash)/i.test(input);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function pickExcerpt(lines, anchor, bundle, processHint, limit) {
|
|
299
|
+
if (anchor >= 0) {
|
|
300
|
+
const around = sliceWindow(lines, anchor, 5, 18);
|
|
301
|
+
if (around.length) {
|
|
302
|
+
return around.slice(0, limit);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const scored = lines
|
|
307
|
+
.map((line, index) => ({
|
|
308
|
+
line,
|
|
309
|
+
index,
|
|
310
|
+
score: scoreCrashLine(line, bundle, processHint),
|
|
311
|
+
}))
|
|
312
|
+
.filter((item) => item.score > 0);
|
|
313
|
+
|
|
314
|
+
if (!scored.length) {
|
|
315
|
+
return lines.slice(Math.max(0, lines.length - limit));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const out = [];
|
|
319
|
+
for (const item of scored.slice(Math.max(0, scored.length - limit))) {
|
|
320
|
+
out.push(item.line);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return unique(out).slice(0, limit);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export function buildNextActionText(report) {
|
|
327
|
+
if (report.status === 'no_crash_signature') {
|
|
328
|
+
return 'Ask for a fuller crash log, a clearer repro, or optionally collect recent faultlogger or hilog evidence if needed.';
|
|
329
|
+
}
|
|
330
|
+
if (report.suspectedFile !== '(not found)') {
|
|
331
|
+
return `Inspect ${report.suspectedFile} first and make a minimal fix. Collect additional runtime evidence only if the current anchor is still too weak.`;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
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.';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export function formatCrashReportText(report) {
|
|
338
|
+
return [
|
|
339
|
+
report.status === 'detected' ? 'Crash signature detected.' : 'No clear crash signature detected.',
|
|
340
|
+
`source: ${report.source}`,
|
|
341
|
+
`device: ${report.device}`,
|
|
342
|
+
`bundle: ${report.bundle}`,
|
|
343
|
+
`process: ${report.process}`,
|
|
344
|
+
`error_type: ${report.errorType}`,
|
|
345
|
+
`error_message: ${report.errorMessage}`,
|
|
346
|
+
`suspected_file: ${report.suspectedFile}`,
|
|
347
|
+
`keywords: ${report.keywords.length ? report.keywords.join(', ') : '(none)'}`,
|
|
348
|
+
'',
|
|
349
|
+
'Top stack:',
|
|
350
|
+
...(report.topStack.length ? report.topStack : ['(empty)']),
|
|
351
|
+
'',
|
|
352
|
+
'Evidence excerpt:',
|
|
353
|
+
...(report.excerpt.length ? report.excerpt : ['(empty)']),
|
|
354
|
+
'',
|
|
355
|
+
`next_action: ${buildNextActionText(report)}`,
|
|
356
|
+
].join('\n');
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export function buildCrashReport(
|
|
360
|
+
input,
|
|
361
|
+
source,
|
|
362
|
+
device,
|
|
363
|
+
bundleName,
|
|
364
|
+
processHint,
|
|
365
|
+
) {
|
|
366
|
+
const normalized = trim(input);
|
|
367
|
+
const lines = cleanLines(normalized);
|
|
368
|
+
const bundle = detectBundle(normalized, bundleName);
|
|
369
|
+
const process = detectProcess(normalized, processHint);
|
|
370
|
+
const anchor = findCrashAnchor(lines, bundle, process);
|
|
371
|
+
const focus = anchor >= 0 ? sliceWindow(lines, anchor, 5, 18).join('\n') : normalized;
|
|
372
|
+
const errorType = detectErrorType(lines, anchor, focus);
|
|
373
|
+
const topStack = detectTopStack(lines, anchor);
|
|
374
|
+
const excerpt = pickExcerpt(lines, anchor, bundle, process, 24);
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
status: looksLikeCrash(normalized, anchor, errorType) ? 'detected' : 'no_crash_signature',
|
|
378
|
+
source,
|
|
379
|
+
device,
|
|
380
|
+
bundle,
|
|
381
|
+
process,
|
|
382
|
+
errorType,
|
|
383
|
+
errorMessage: detectErrorMessage(lines, anchor),
|
|
384
|
+
suspectedFile: detectSuspectedFile(topStack, bundle),
|
|
385
|
+
keywords: detectKeywords(focus || normalized),
|
|
386
|
+
topStack,
|
|
387
|
+
excerpt,
|
|
388
|
+
};
|
|
389
|
+
}
|