edsger 0.35.0 → 0.35.2
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/api/app-store.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
1
3
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
2
4
|
import { DEFAULT_MODEL } from '../../constants.js';
|
|
3
5
|
import { logDebug, logError, logInfo } from '../../utils/logger.js';
|
|
@@ -8,12 +10,33 @@ function parseAppStoreResult(responseText) {
|
|
|
8
10
|
try {
|
|
9
11
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
10
12
|
let jsonResult = null;
|
|
11
|
-
// Try to extract JSON from markdown code block
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
// Try to extract JSON from markdown code block (check all occurrences, prefer last)
|
|
14
|
+
const jsonBlockMatches = [...responseText.matchAll(/```json\s*\n([\s\S]*?)\n\s*```/g)];
|
|
15
|
+
for (let i = jsonBlockMatches.length - 1; i >= 0; i--) {
|
|
16
|
+
try {
|
|
17
|
+
const candidate = JSON.parse(jsonBlockMatches[i][1]);
|
|
18
|
+
if (candidate && candidate.app_store) {
|
|
19
|
+
jsonResult = candidate;
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Try next match
|
|
25
|
+
}
|
|
15
26
|
}
|
|
16
|
-
|
|
27
|
+
if (!jsonResult) {
|
|
28
|
+
// Try to find a JSON object containing "app_store" anywhere in the text
|
|
29
|
+
const appStoreMatch = responseText.match(/\{[\s\S]*"app_store"\s*:\s*\{[\s\S]*\}/);
|
|
30
|
+
if (appStoreMatch) {
|
|
31
|
+
try {
|
|
32
|
+
jsonResult = JSON.parse(appStoreMatch[0]);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Not valid JSON
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!jsonResult) {
|
|
17
40
|
// Try to parse the entire response as JSON
|
|
18
41
|
jsonResult = JSON.parse(responseText);
|
|
19
42
|
}
|
|
@@ -80,8 +103,22 @@ export async function executeAppStoreQuery(currentPrompt, systemPrompt, config,
|
|
|
80
103
|
const responseText = message.result || lastAssistantResponse;
|
|
81
104
|
const parsed = parseAppStoreResult(responseText);
|
|
82
105
|
if (parsed.error) {
|
|
83
|
-
|
|
84
|
-
|
|
106
|
+
// Fallback: try accumulated assistant responses (may contain JSON code blocks)
|
|
107
|
+
if (lastAssistantResponse && responseText !== lastAssistantResponse) {
|
|
108
|
+
const fallback = parseAppStoreResult(lastAssistantResponse);
|
|
109
|
+
if (!fallback.error) {
|
|
110
|
+
logInfo('Parsed result from accumulated responses');
|
|
111
|
+
structuredResult = fallback.appStore;
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
logError(`Failed to parse result: ${parsed.error}`);
|
|
115
|
+
structuredResult = null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
logError(`Failed to parse result: ${parsed.error}`);
|
|
120
|
+
structuredResult = null;
|
|
121
|
+
}
|
|
85
122
|
}
|
|
86
123
|
else {
|
|
87
124
|
structuredResult = parsed.appStore;
|
|
@@ -98,5 +135,36 @@ export async function executeAppStoreQuery(currentPrompt, systemPrompt, config,
|
|
|
98
135
|
}
|
|
99
136
|
}
|
|
100
137
|
}
|
|
138
|
+
// File-based fallback: the agent may have written JSON to a file in the cwd
|
|
139
|
+
if (!structuredResult && cwd) {
|
|
140
|
+
structuredResult = tryParseJsonFilesInDir(cwd);
|
|
141
|
+
if (structuredResult) {
|
|
142
|
+
logInfo('Parsed result from JSON file written by agent');
|
|
143
|
+
}
|
|
144
|
+
}
|
|
101
145
|
return structuredResult;
|
|
102
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Search for JSON files in the given directory that contain an app_store key.
|
|
149
|
+
*/
|
|
150
|
+
function tryParseJsonFilesInDir(dir) {
|
|
151
|
+
try {
|
|
152
|
+
const files = readdirSync(dir).filter((f) => f.endsWith('.json'));
|
|
153
|
+
for (const file of files) {
|
|
154
|
+
try {
|
|
155
|
+
const content = readFileSync(join(dir, file), 'utf-8');
|
|
156
|
+
const parsed = parseAppStoreResult(content);
|
|
157
|
+
if (!parsed.error && parsed.appStore) {
|
|
158
|
+
return parsed.appStore;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Skip unreadable files
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
// Directory not readable
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
@@ -42,6 +42,7 @@ ${hasCodebase ? '5' : '4'}. **Write Store Listings**: Generate optimized app nam
|
|
|
42
42
|
**Store Listing Standards**:
|
|
43
43
|
- App name: max 30 characters, compelling and searchable
|
|
44
44
|
- Subtitle: max 30 characters (Apple), punchy value proposition
|
|
45
|
+
- Promotional text: max 170 characters (Apple), highlights current promotions or features — can be updated without a new app version
|
|
45
46
|
- Short description: max 80 characters (Google Play)
|
|
46
47
|
- Description: max 4000 characters, benefit-focused with feature bullets
|
|
47
48
|
- Keywords: max 100 characters (Apple), comma-separated, no spaces after commas
|
|
@@ -59,6 +60,7 @@ Return ONLY a JSON object. No text before or after.
|
|
|
59
60
|
"en-US": {
|
|
60
61
|
"app_name": "Product Name",
|
|
61
62
|
"subtitle": "Short value proposition",
|
|
63
|
+
"promotional_text": "Highlight a current promotion, new feature, or seasonal message (170 chars max)",
|
|
62
64
|
"short_description": "One-liner for Google Play (80 chars max)",
|
|
63
65
|
"description": "Full store description with features and benefits",
|
|
64
66
|
"keywords": "keyword1,keyword2,keyword3",
|