nolo-cli 0.1.10 โ 0.1.11
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 +0 -32
- package/agentRuntimeCommands.ts +3 -3
- package/commandRegistry.ts +2 -2
- package/machineCommands.ts +31 -6
- package/package.json +6 -22
- package/ai/agent/_executeModel.ts +0 -118
- package/ai/agent/agentSlice.ts +0 -525
- package/ai/agent/appWorkingMemory.ts +0 -126
- package/ai/agent/avatarUtils.ts +0 -24
- package/ai/agent/buildEditingContext.ts +0 -373
- package/ai/agent/buildSystemPrompt.ts +0 -532
- package/ai/agent/cleanAgentMessages.ts +0 -140
- package/ai/agent/cliChatClient.ts +0 -119
- package/ai/agent/cliExecutor.ts +0 -733
- package/ai/agent/cliPrompt.ts +0 -10
- package/ai/agent/contextCompiler.ts +0 -107
- package/ai/agent/contextLayerContract.ts +0 -44
- package/ai/agent/createAgentSchema.ts +0 -234
- package/ai/agent/executeToolCall.ts +0 -58
- package/ai/agent/fetchAgentContexts.ts +0 -42
- package/ai/agent/generatePrompt.ts +0 -3
- package/ai/agent/getFullChatContextKeys.ts +0 -168
- package/ai/agent/hooks/fetchPublicAgents.ts +0 -133
- package/ai/agent/hooks/useAgentConfig.ts +0 -61
- package/ai/agent/hooks/useAgentDialog.ts +0 -35
- package/ai/agent/hooks/useAgentFormValidation.ts +0 -202
- package/ai/agent/hooks/usePublicAgents.ts +0 -473
- package/ai/agent/machineRunPermissions.ts +0 -95
- package/ai/agent/persistMessageWithFixedId.ts +0 -37
- package/ai/agent/planSlice.ts +0 -259
- package/ai/agent/referenceUtils.ts +0 -229
- package/ai/agent/runAgentBackground.ts +0 -238
- package/ai/agent/runAgentClientLoop.ts +0 -138
- package/ai/agent/runtimeGuidance.ts +0 -97
- package/ai/agent/runtimeServerBase.ts +0 -37
- package/ai/agent/server/fetchPublicAgents.ts +0 -128
- package/ai/agent/startParallelAgentStreams.ts +0 -424
- package/ai/agent/startupProtocol.ts +0 -53
- package/ai/agent/streamAgentChatTurn.ts +0 -1278
- package/ai/agent/streamAgentChatTurnUtils.ts +0 -738
- package/ai/agent/types.ts +0 -71
- package/ai/agent/utils/imageOutput.ts +0 -33
- package/ai/agent/utils/sortUtils.ts +0 -250
- package/ai/agent/web/referencePickerUtils.ts +0 -146
- package/ai/ai.locale.ts +0 -1079
- package/ai/chat/accumulateToolCallChunks.ts +0 -95
- package/ai/chat/fetchUtils.native.ts +0 -276
- package/ai/chat/fetchUtils.ts +0 -153
- package/ai/chat/parseApiError.ts +0 -64
- package/ai/chat/parseMultilineSSE.ts +0 -95
- package/ai/chat/sendOpenAICompletionsRequest.native.ts +0 -682
- package/ai/chat/sendOpenAICompletionsRequest.ts +0 -703
- package/ai/chat/sendOpenAIResponseRequest.ts +0 -491
- package/ai/chat/shouldUseServerProxy.ts +0 -18
- package/ai/chat/sseClient.native.ts +0 -91
- package/ai/chat/sseClient.ts +0 -67
- package/ai/chat/streamReader.native.ts +0 -31
- package/ai/chat/streamReader.ts +0 -62
- package/ai/chat/updateTotalUsage.ts +0 -72
- package/ai/context/buildReferenceContext.ts +0 -437
- package/ai/context/calculateContextUsage.ts +0 -133
- package/ai/context/retention.ts +0 -165
- package/ai/context/tokenUtils.ts +0 -78
- package/ai/index.ts +0 -1
- package/ai/llm/calculateGeminiImageTokens.ts +0 -57
- package/ai/llm/deepinfra.ts +0 -28
- package/ai/llm/fireworks.ts +0 -50
- package/ai/llm/generateRequestBody.ts +0 -165
- package/ai/llm/getModelContextWindow.ts +0 -84
- package/ai/llm/getNoloKey.ts +0 -31
- package/ai/llm/getPricing.ts +0 -199
- package/ai/llm/hooks/useModelPricing.ts +0 -75
- package/ai/llm/imagePricing.ts +0 -40
- package/ai/llm/isResponseAPIModel.ts +0 -13
- package/ai/llm/mimo.ts +0 -71
- package/ai/llm/mistral.ts +0 -22
- package/ai/llm/modelAvatar.ts +0 -427
- package/ai/llm/models.ts +0 -45
- package/ai/llm/openrouterModels.ts +0 -269
- package/ai/llm/providers.ts +0 -306
- package/ai/llm/reasoningModels.ts +0 -28
- package/ai/llm/types.ts +0 -59
- package/ai/llm/usageRequestOptions.ts +0 -59
- package/ai/memory/capture.ts +0 -148
- package/ai/memory/consolidate.ts +0 -104
- package/ai/memory/delete.ts +0 -147
- package/ai/memory/overlay.ts +0 -84
- package/ai/memory/query.ts +0 -38
- package/ai/memory/queryShared.ts +0 -160
- package/ai/memory/rank.ts +0 -105
- package/ai/memory/recentRelationshipRecap.ts +0 -249
- package/ai/memory/remember.ts +0 -167
- package/ai/memory/runtime.ts +0 -76
- package/ai/memory/store.ts +0 -20
- package/ai/memory/storeShared.ts +0 -76
- package/ai/memory/types.ts +0 -46
- package/ai/memory/understanding.ts +0 -349
- package/ai/memory/understandingGreeting.ts +0 -264
- package/ai/messages/type.ts +0 -20
- package/ai/policy/personalizationDialog.ts +0 -333
- package/ai/policy/runtimePolicy.ts +0 -440
- package/ai/policy/selfUpdateFields.ts +0 -48
- package/ai/policy/types.ts +0 -64
- package/ai/skills/referenceRuntime.ts +0 -274
- package/ai/skills/skillDiagnostics.ts +0 -251
- package/ai/skills/skillDocBuilder.ts +0 -139
- package/ai/skills/skillDocProtocol.ts +0 -434
- package/ai/skills/skillReferenceSummary.ts +0 -63
- package/ai/skills/skillSummaryMarker.ts +0 -26
- package/ai/token/calculatePrice.ts +0 -544
- package/ai/token/db.ts +0 -98
- package/ai/token/externalToolCost.ts +0 -330
- package/ai/token/hooks/useRecords.ts +0 -65
- package/ai/token/missingUsageEstimate.ts +0 -42
- package/ai/token/modelUsageQuery.ts +0 -252
- package/ai/token/normalizeUsage.ts +0 -84
- package/ai/token/openaiImageGenerationUsage.ts +0 -56
- package/ai/token/prepareTokenUsageData.ts +0 -88
- package/ai/token/query.ts +0 -88
- package/ai/token/queryUserTokens.ts +0 -59
- package/ai/token/resolveBillingTarget.ts +0 -52
- package/ai/token/saveTokenRecord.ts +0 -53
- package/ai/token/serverDialogProjection.ts +0 -78
- package/ai/token/serverTokenWriter.ts +0 -143
- package/ai/token/stats.ts +0 -21
- package/ai/token/tokenThunks.ts +0 -24
- package/ai/token/types.ts +0 -93
- package/ai/tools/agent/agentTools.ts +0 -176
- package/ai/tools/agent/agentUpdateShared.ts +0 -311
- package/ai/tools/agent/callAgentTool.ts +0 -139
- package/ai/tools/agent/createAgentTool.ts +0 -512
- package/ai/tools/agent/createDialogTool.ts +0 -69
- package/ai/tools/agent/createSkillAgentTool.ts +0 -62
- package/ai/tools/agent/parallelBudget.ts +0 -221
- package/ai/tools/agent/presets/appBuilderPreset.ts +0 -145
- package/ai/tools/agent/runLlmTool.ts +0 -96
- package/ai/tools/agent/runStreamingAgentTool.ts +0 -73
- package/ai/tools/agent/skillAgentArgs.ts +0 -106
- package/ai/tools/agent/skillAgentPreset.ts +0 -89
- package/ai/tools/agent/streamParallelAgentsTool.ts +0 -122
- package/ai/tools/agent/updateAgentTool.ts +0 -96
- package/ai/tools/agent/updateSelfTool.ts +0 -113
- package/ai/tools/amazonProductScraperTool.ts +0 -86
- package/ai/tools/apifyActorClient.ts +0 -45
- package/ai/tools/appEditGuard.ts +0 -372
- package/ai/tools/appReadSnapshot.ts +0 -153
- package/ai/tools/appTools.ts +0 -1549
- package/ai/tools/applyEditTool.ts +0 -256
- package/ai/tools/applyLineEditsTool.ts +0 -312
- package/ai/tools/browserTools/click.ts +0 -33
- package/ai/tools/browserTools/closeSession.ts +0 -29
- package/ai/tools/browserTools/common.ts +0 -27
- package/ai/tools/browserTools/openSession.ts +0 -48
- package/ai/tools/browserTools/readContent.ts +0 -38
- package/ai/tools/browserTools/selectOption.ts +0 -46
- package/ai/tools/browserTools/typeText.ts +0 -42
- package/ai/tools/category/createCategoryTool.ts +0 -66
- package/ai/tools/category/queryContentsByCategoryTool.ts +0 -69
- package/ai/tools/category/updateContentCategoryTool.ts +0 -75
- package/ai/tools/cfBrowserTools.ts +0 -319
- package/ai/tools/cfSpeechToTextTool.ts +0 -49
- package/ai/tools/checkEnvTool.ts +0 -65
- package/ai/tools/cloudflareCrawlTool.ts +0 -289
- package/ai/tools/codeSearchTool.ts +0 -111
- package/ai/tools/codeTools.ts +0 -101
- package/ai/tools/createDocTool.ts +0 -132
- package/ai/tools/createPlanTool.ts +0 -999
- package/ai/tools/createSkillDocTool.ts +0 -155
- package/ai/tools/createWorkflowTool.ts +0 -154
- package/ai/tools/deepseekOcrTool.ts +0 -34
- package/ai/tools/delayTool.ts +0 -31
- package/ai/tools/deleteSpacesTool.ts +0 -325
- package/ai/tools/deleteSpacesToolModel.ts +0 -159
- package/ai/tools/devReloadUtils.ts +0 -29
- package/ai/tools/dialogMessageSearch.ts +0 -137
- package/ai/tools/doctorSkillTool.ts +0 -72
- package/ai/tools/ecommerceScraperTool.ts +0 -86
- package/ai/tools/emailTools.ts +0 -549
- package/ai/tools/evalSkillTool.ts +0 -92
- package/ai/tools/exaSearchTool.ts +0 -64
- package/ai/tools/execBashTool.ts +0 -379
- package/ai/tools/executeSqlTool.ts +0 -192
- package/ai/tools/fetchWebpageSupport.ts +0 -309
- package/ai/tools/fetchWebpageTool.ts +0 -84
- package/ai/tools/geminiImagePreviewTool.ts +0 -361
- package/ai/tools/generateDocxTool.ts +0 -215
- package/ai/tools/googleSearchScraperTool.ts +0 -106
- package/ai/tools/importDataTool.ts +0 -133
- package/ai/tools/importSkillTool.ts +0 -162
- package/ai/tools/index.ts +0 -1858
- package/ai/tools/listFilesTool.ts +0 -82
- package/ai/tools/listUserSpacesTool.ts +0 -113
- package/ai/tools/modelUsageTools.ts +0 -142
- package/ai/tools/olmOcrTool.ts +0 -34
- package/ai/tools/openaiImageTool.ts +0 -218
- package/ai/tools/paddleOcrTool.ts +0 -34
- package/ai/tools/prepareTools.ts +0 -23
- package/ai/tools/readDocTool.ts +0 -84
- package/ai/tools/readFileTool.ts +0 -211
- package/ai/tools/readTool.ts +0 -163
- package/ai/tools/readXPostTool.ts +0 -233
- package/ai/tools/rememberMemoryTool.ts +0 -84
- package/ai/tools/remotionVideoTool.ts +0 -151
- package/ai/tools/searchDialogMessagesTool.ts +0 -222
- package/ai/tools/searchRepoTool.ts +0 -115
- package/ai/tools/searchWorkspaceTool.ts +0 -259
- package/ai/tools/skillFollowup.ts +0 -86
- package/ai/tools/surfWeatherTool.ts +0 -169
- package/ai/tools/table/addTableRowTool.ts +0 -217
- package/ai/tools/table/createTableTool.ts +0 -315
- package/ai/tools/table/rowTools.ts +0 -366
- package/ai/tools/table/schemaTools.ts +0 -244
- package/ai/tools/table/shareTableTool.ts +0 -148
- package/ai/tools/table/toolShared.ts +0 -129
- package/ai/tools/toolApiClient.ts +0 -198
- package/ai/tools/toolNameAliases.ts +0 -57
- package/ai/tools/toolResultError.ts +0 -42
- package/ai/tools/toolRunSlice.ts +0 -303
- package/ai/tools/toolSchemaCompatibility.ts +0 -53
- package/ai/tools/toolVisibility.ts +0 -4
- package/ai/tools/types.ts +0 -20
- package/ai/tools/uiAskChoiceTool.ts +0 -104
- package/ai/tools/updateContentTitleTool.ts +0 -84
- package/ai/tools/updateDocTool.ts +0 -105
- package/ai/tools/updateUserPreferenceProfileTool.ts +0 -145
- package/ai/tools/whisperTool.ts +0 -77
- package/ai/tools/writeFileTool.ts +0 -210
- package/ai/tools/youtubeScraperTool.ts +0 -116
- package/ai/tools/ziweiChartTool.ts +0 -678
- package/ai/types.ts +0 -55
- package/ai/workflow/workflowExecutor.ts +0 -323
- package/ai/workflow/workflowSlice.ts +0 -73
- package/ai/workflow/workflowTypes.ts +0 -106
- package/client/compactDialog.ts +0 -222
- package/connector-experimental/capabilities.ts +0 -73
- package/connector-experimental/codexBinary.ts +0 -41
- package/connector-experimental/heartbeatLoop.ts +0 -22
- package/connector-experimental/index.ts +0 -5
- package/connector-experimental/machineInfo.ts +0 -46
- package/connector-experimental/protocol.ts +0 -54
package/ai/tools/appTools.ts
DELETED
|
@@ -1,1549 +0,0 @@
|
|
|
1
|
-
// packages/ai/tools/appTools.ts
|
|
2
|
-
// Web ๅบ็จ้จ็ฝฒ/็ฎก็ๅทฅๅ
ท
|
|
3
|
-
// ๅฝๅ็ปไธๅๅธๅฐๅนณๅฐๆ็ฎก่ฟ่กๆถ
|
|
4
|
-
|
|
5
|
-
import { toolRunUpdated, type ToolRunStep } from "./toolRunSlice";
|
|
6
|
-
import { callToolApi, getToolRequestContext } from "./toolApiClient";
|
|
7
|
-
import { syncAppRecord } from "app/actions/syncAppRecord";
|
|
8
|
-
import { deleteDbKey } from "app/hooks/deleteDbKey";
|
|
9
|
-
import { selectAllMsgs, selectCurrentDialogId } from "chat/messages/messageSlice";
|
|
10
|
-
import { ToolResultError } from "./toolResultError";
|
|
11
|
-
import {
|
|
12
|
-
analyzeAppStyleSystem,
|
|
13
|
-
buildAppReadSnapshotWarning,
|
|
14
|
-
buildAppStyleSystemHint,
|
|
15
|
-
classifyAppReadSnapshot,
|
|
16
|
-
} from "./appReadSnapshot";
|
|
17
|
-
import { evaluateSmallVisualEditGuard } from "./appEditGuard";
|
|
18
|
-
|
|
19
|
-
type AppSourceFile = { name: string; code: string };
|
|
20
|
-
type AppDeployFramework = "worker" | "react-spa";
|
|
21
|
-
|
|
22
|
-
interface AppDeployArgs {
|
|
23
|
-
name?: string;
|
|
24
|
-
code?: string;
|
|
25
|
-
files?: AppSourceFile[];
|
|
26
|
-
pages?: AppSourceFile[];
|
|
27
|
-
appId?: string;
|
|
28
|
-
framework?: AppDeployFramework;
|
|
29
|
-
spaceId?: string;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
interface AppDeployApiResult {
|
|
33
|
-
success: boolean;
|
|
34
|
-
url: string;
|
|
35
|
-
customUrl?: string;
|
|
36
|
-
routeRegistered?: boolean;
|
|
37
|
-
previewReady?: boolean;
|
|
38
|
-
modifiedOn?: string;
|
|
39
|
-
userFriendlyName: string;
|
|
40
|
-
appId?: string;
|
|
41
|
-
appKey?: string;
|
|
42
|
-
appRecord?: Record<string, any> | null;
|
|
43
|
-
bundleWarnings?: string[];
|
|
44
|
-
deployMode?: "platform";
|
|
45
|
-
framework?: AppDeployFramework;
|
|
46
|
-
previewCheck?: {
|
|
47
|
-
attempted: boolean;
|
|
48
|
-
ready: boolean;
|
|
49
|
-
status?: number;
|
|
50
|
-
attempts: number;
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface AppDeployStartResult {
|
|
55
|
-
success: boolean;
|
|
56
|
-
jobId: string;
|
|
57
|
-
eventChannel?: string;
|
|
58
|
-
status: "pending" | "running";
|
|
59
|
-
summary?: string;
|
|
60
|
-
steps?: ToolRunStep[];
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
interface AppDeployStatusResult {
|
|
64
|
-
success: boolean;
|
|
65
|
-
jobId: string;
|
|
66
|
-
status: "pending" | "running" | "succeeded" | "failed";
|
|
67
|
-
summary?: string;
|
|
68
|
-
steps?: ToolRunStep[];
|
|
69
|
-
result?: AppDeployApiResult;
|
|
70
|
-
error?: {
|
|
71
|
-
message?: string;
|
|
72
|
-
code?: string;
|
|
73
|
-
details?: unknown;
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
interface AppPreflightIssue {
|
|
78
|
-
code: string;
|
|
79
|
-
message: string;
|
|
80
|
-
file?: string;
|
|
81
|
-
importSpecifier?: string;
|
|
82
|
-
symbol?: string;
|
|
83
|
-
suggestion?: string;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
interface AppPreflightResult {
|
|
87
|
-
success: boolean;
|
|
88
|
-
ok: boolean;
|
|
89
|
-
framework: AppDeployFramework;
|
|
90
|
-
summary: string;
|
|
91
|
-
issues: AppPreflightIssue[];
|
|
92
|
-
warnings: string[];
|
|
93
|
-
entryFile?: string;
|
|
94
|
-
externalImports?: string[];
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
interface AppRepairPlanStep {
|
|
98
|
-
action: string;
|
|
99
|
-
reason: string;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
interface AppRepairPlan {
|
|
103
|
-
strategy: "targeted-repair";
|
|
104
|
-
scope: "existing-files";
|
|
105
|
-
mode: "preflight-first";
|
|
106
|
-
summary: string;
|
|
107
|
-
steps: AppRepairPlanStep[];
|
|
108
|
-
issueCodes: string[];
|
|
109
|
-
suggestedFiles?: string[];
|
|
110
|
-
keepFiles?: string[];
|
|
111
|
-
revertFiles?: string[];
|
|
112
|
-
preferTokenFiles?: string[];
|
|
113
|
-
targetStyleFields?: string[];
|
|
114
|
-
targetElements?: string[];
|
|
115
|
-
rerun: ["appPreflight", "appDeploy"];
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
interface AppStoplossPayload {
|
|
119
|
-
success: false;
|
|
120
|
-
ok: false;
|
|
121
|
-
error: true;
|
|
122
|
-
code:
|
|
123
|
-
| "DEPLOY_TRANSPORT_FAILURE"
|
|
124
|
-
| "PREFLIGHT_TRANSPORT_FAILURE";
|
|
125
|
-
summary: string;
|
|
126
|
-
framework: AppDeployFramework;
|
|
127
|
-
stopReason: "invalid-json-response" | "html-response";
|
|
128
|
-
retryable: false;
|
|
129
|
-
responsePreview?: string;
|
|
130
|
-
nextAction: string;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const normalizeOptionalString = (value: unknown): string | undefined => {
|
|
134
|
-
if (typeof value !== "string") return undefined;
|
|
135
|
-
const trimmed = value.trim();
|
|
136
|
-
return trimmed ? trimmed : undefined;
|
|
137
|
-
};
|
|
138
|
-
|
|
139
|
-
export function decideAppDeploySpaceId(params: {
|
|
140
|
-
explicitSpaceId?: string | null;
|
|
141
|
-
currentSpaceId?: string | null;
|
|
142
|
-
existingAppSpaceId?: string | null;
|
|
143
|
-
}): string | undefined {
|
|
144
|
-
const existingAppSpaceId = normalizeOptionalString(params.existingAppSpaceId);
|
|
145
|
-
if (existingAppSpaceId) {
|
|
146
|
-
return undefined;
|
|
147
|
-
}
|
|
148
|
-
return (
|
|
149
|
-
normalizeOptionalString(params.explicitSpaceId) ??
|
|
150
|
-
normalizeOptionalString(params.currentSpaceId)
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export async function resolveAppDeploySpaceId(
|
|
155
|
-
args: AppDeployArgs,
|
|
156
|
-
thunkApi: any
|
|
157
|
-
): Promise<string | undefined> {
|
|
158
|
-
const currentSpaceId = normalizeOptionalString(
|
|
159
|
-
thunkApi?.getState?.()?.space?.currentSpaceId
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
if (!args.appId) {
|
|
163
|
-
return decideAppDeploySpaceId({
|
|
164
|
-
explicitSpaceId: args.spaceId,
|
|
165
|
-
currentSpaceId,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
try {
|
|
170
|
-
const existing = await callToolApi<{
|
|
171
|
-
success: boolean;
|
|
172
|
-
spaceId?: string | null;
|
|
173
|
-
}>(thunkApi, "/api/app/get", { appId: args.appId }, { withAuth: true });
|
|
174
|
-
|
|
175
|
-
return decideAppDeploySpaceId({
|
|
176
|
-
explicitSpaceId: args.spaceId,
|
|
177
|
-
currentSpaceId,
|
|
178
|
-
existingAppSpaceId: existing.spaceId,
|
|
179
|
-
});
|
|
180
|
-
} catch {
|
|
181
|
-
return decideAppDeploySpaceId({
|
|
182
|
-
explicitSpaceId: args.spaceId,
|
|
183
|
-
currentSpaceId,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const TOOL_STEP_STATUS_RANK: Record<ToolRunStep["status"], number> = {
|
|
189
|
-
pending: 0,
|
|
190
|
-
running: 1,
|
|
191
|
-
succeeded: 2,
|
|
192
|
-
failed: 3,
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
function parseSseChunk(chunk: string): Array<Record<string, unknown>> {
|
|
196
|
-
const results: Array<Record<string, unknown>> = [];
|
|
197
|
-
for (const line of chunk.split("\n")) {
|
|
198
|
-
const trimmed = line.trim();
|
|
199
|
-
if (!trimmed.startsWith("data:")) continue;
|
|
200
|
-
const json = trimmed.slice(5).trim();
|
|
201
|
-
if (!json) continue;
|
|
202
|
-
try {
|
|
203
|
-
results.push(JSON.parse(json));
|
|
204
|
-
} catch {
|
|
205
|
-
// ignore malformed lines / heartbeat
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
return results;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const APP_DEPLOY_STEP_LABELS: Record<string, string> = {
|
|
212
|
-
prepare: "ๆด็้จ็ฝฒๅๆฐ",
|
|
213
|
-
preflight: "้ขๆฃไปฃ็ ",
|
|
214
|
-
build: "ๆๅ
ๅบ็จ",
|
|
215
|
-
deploy: "ๅๅธ็ซ็น",
|
|
216
|
-
verify: "้ช่ฏ่ฎฟ้ฎ",
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
function buildDeploySteps(
|
|
220
|
-
currentStepId: keyof typeof APP_DEPLOY_STEP_LABELS,
|
|
221
|
-
currentStatus: ToolRunStep["status"],
|
|
222
|
-
detail?: string
|
|
223
|
-
): ToolRunStep[] {
|
|
224
|
-
const ids = Object.keys(APP_DEPLOY_STEP_LABELS) as Array<
|
|
225
|
-
keyof typeof APP_DEPLOY_STEP_LABELS
|
|
226
|
-
>;
|
|
227
|
-
const currentIndex = ids.indexOf(currentStepId);
|
|
228
|
-
return ids.map((id, index) => ({
|
|
229
|
-
id,
|
|
230
|
-
label: APP_DEPLOY_STEP_LABELS[id],
|
|
231
|
-
status:
|
|
232
|
-
index < currentIndex
|
|
233
|
-
? "succeeded"
|
|
234
|
-
: index === currentIndex
|
|
235
|
-
? currentStatus
|
|
236
|
-
: "pending",
|
|
237
|
-
...(index === currentIndex && detail ? { detail } : {}),
|
|
238
|
-
}));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function updateDeployProgress(
|
|
242
|
-
thunkApi: any,
|
|
243
|
-
toolRunId: string | undefined,
|
|
244
|
-
stepIdOrSteps: keyof typeof APP_DEPLOY_STEP_LABELS | ToolRunStep[],
|
|
245
|
-
summary: string,
|
|
246
|
-
currentStatus: ToolRunStep["status"] = "running",
|
|
247
|
-
detail?: string
|
|
248
|
-
) {
|
|
249
|
-
if (!toolRunId) return;
|
|
250
|
-
thunkApi.dispatch(
|
|
251
|
-
toolRunUpdated({
|
|
252
|
-
id: toolRunId,
|
|
253
|
-
outputSummary: summary,
|
|
254
|
-
steps: Array.isArray(stepIdOrSteps)
|
|
255
|
-
? stepIdOrSteps
|
|
256
|
-
: buildDeploySteps(stepIdOrSteps, currentStatus, detail),
|
|
257
|
-
})
|
|
258
|
-
);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function normalizeAppDeployArgs(args: AppDeployArgs) {
|
|
262
|
-
const normalizedFiles = Array.isArray(args.files) && args.files.length > 0
|
|
263
|
-
? args.files
|
|
264
|
-
: Array.isArray(args.pages) && args.pages.length > 0
|
|
265
|
-
? args.pages
|
|
266
|
-
: undefined;
|
|
267
|
-
return {
|
|
268
|
-
...args,
|
|
269
|
-
files: normalizedFiles,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
function isLikelyReactWorkerMisuse(code: string | undefined): boolean {
|
|
274
|
-
if (!code) return false;
|
|
275
|
-
return /from\s+["']react["']|from\s+["']react-dom|react-icons\/lu|createRoot\s*\(|<\w+[^>]*>/.test(
|
|
276
|
-
code
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
function rewriteAppDeployError(errorMessage: string, args: AppDeployArgs): string {
|
|
281
|
-
if (errorMessage.includes("React SPA ๆจกๅผๅฟ
้กปๆไพ files ๅๆฐ")) {
|
|
282
|
-
return 'React SPA ้่ฆไผ `files`๏ผ่ณๅฐ `main.tsx` + `App.tsx`๏ผ๏ผไธ่ฝๅชไผ `code`ใๅฆๆไฝ ็ฐๅจๆฟๅฐ็ๆฏๅคๆไปถๆบ็ ๏ผไนๅฏไปฅ็ดๆฅไผ `pages`๏ผ็ณป็ปไผ่ชๅจๅ
ผๅฎนไธบ `files`ใ';
|
|
283
|
-
}
|
|
284
|
-
if (errorMessage.includes("้่ฆๆไพ code ๆ files ๅๆฐ")) {
|
|
285
|
-
return "็ผบๅฐๅฏ้จ็ฝฒๆบ็ ใ่ฏทไผ `code`๏ผๅๆไปถ Worker๏ผๆ `files`๏ผๅคๆไปถ้กน็ฎ๏ผ๏ผๅฆๆไฝ ๆไธๅญๆฎตๅๆฏ `pages`๏ผ็ฐๅจไนๅฏไปฅ็ดๆฅไผ ใ";
|
|
286
|
-
}
|
|
287
|
-
if (
|
|
288
|
-
errorMessage.includes("Bundle failed") &&
|
|
289
|
-
args.framework !== "react-spa" &&
|
|
290
|
-
isLikelyReactWorkerMisuse(args.code)
|
|
291
|
-
) {
|
|
292
|
-
return 'ๆฃๆตๅฐไฝ ๆ React ็ปไปถไปฃ็ ๅฝๆๅๆไปถ Worker ๅป้จ็ฝฒไบใ่ฆๅไบคไบ็ฝ้กต๏ผ่ฏทๆน็จ `framework: "react-spa"` ๅนถไผ `files`๏ผ้ๅธธๆฏ `main.tsx` + `App.tsx`๏ผ๏ผๅฆๆไฝ ๅชๆณ่ฟๅ้ๆ HTML๏ผ่ฏทๅปๆ `react` / `react-dom` / `react-icons` importใ';
|
|
293
|
-
}
|
|
294
|
-
return errorMessage;
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
function messageContentToText(content: unknown): string {
|
|
298
|
-
if (typeof content === "string") return content;
|
|
299
|
-
if (Array.isArray(content)) {
|
|
300
|
-
return content
|
|
301
|
-
.map((part) =>
|
|
302
|
-
part && typeof part === "object" && "text" in part
|
|
303
|
-
? String((part as { text?: unknown }).text ?? "")
|
|
304
|
-
: ""
|
|
305
|
-
)
|
|
306
|
-
.join("\n");
|
|
307
|
-
}
|
|
308
|
-
return "";
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function getLatestUserInputFromThunk(thunkApi: any): string | undefined {
|
|
312
|
-
try {
|
|
313
|
-
const state = thunkApi?.getState?.();
|
|
314
|
-
if (!state) return undefined;
|
|
315
|
-
const dialogId = selectCurrentDialogId(state);
|
|
316
|
-
const messages = selectAllMsgs(state, dialogId);
|
|
317
|
-
for (let i = messages.length - 1; i >= 0; i -= 1) {
|
|
318
|
-
const message = messages[i];
|
|
319
|
-
if (message?.role !== "user") continue;
|
|
320
|
-
const text = messageContentToText(message.content).trim();
|
|
321
|
-
if (text) return text;
|
|
322
|
-
}
|
|
323
|
-
} catch {
|
|
324
|
-
return undefined;
|
|
325
|
-
}
|
|
326
|
-
return undefined;
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
function formatPreflightIssues(issues: AppPreflightIssue[] | undefined): string {
|
|
330
|
-
if (!Array.isArray(issues) || issues.length === 0) return "";
|
|
331
|
-
return issues
|
|
332
|
-
.slice(0, 6)
|
|
333
|
-
.map((issue) => {
|
|
334
|
-
const parts = [`- ${issue.message}`];
|
|
335
|
-
if (issue.suggestion) parts.push(`ๅปบ่ฎฎๆนไธบ๏ผ${issue.suggestion}`);
|
|
336
|
-
return parts.join("๏ผ");
|
|
337
|
-
})
|
|
338
|
-
.join("\n");
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
function inferRepairSuggestedFiles(issues: AppPreflightIssue[] | undefined): string[] {
|
|
342
|
-
const files = new Set<string>();
|
|
343
|
-
for (const issue of issues ?? []) {
|
|
344
|
-
if (issue.file) files.add(issue.file);
|
|
345
|
-
if (issue.code === "missing-entry-file") {
|
|
346
|
-
files.add("main.tsx");
|
|
347
|
-
files.add("App.tsx");
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
return [...files];
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
function buildRepairSteps(
|
|
354
|
-
issues: AppPreflightIssue[] | undefined,
|
|
355
|
-
framework: AppDeployFramework
|
|
356
|
-
): AppRepairPlanStep[] {
|
|
357
|
-
const steps: AppRepairPlanStep[] = [];
|
|
358
|
-
const seen = new Set<string>();
|
|
359
|
-
|
|
360
|
-
const push = (action: string, reason: string) => {
|
|
361
|
-
const key = `${action}::${reason}`;
|
|
362
|
-
if (seen.has(key)) return;
|
|
363
|
-
seen.add(key);
|
|
364
|
-
steps.push({ action, reason });
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
for (const issue of issues ?? []) {
|
|
368
|
-
switch (issue.code) {
|
|
369
|
-
case "missing-files":
|
|
370
|
-
push(
|
|
371
|
-
framework === "react-spa"
|
|
372
|
-
? "่กฅ้ฝ React SPA ็ files ๆฐ็ป๏ผไธ่ฆๅชไผ code"
|
|
373
|
-
: "่กฅ้ฝๅฏ้จ็ฝฒๆบ็ ๏ผ็กฎไฟ่ณๅฐไผ code ๆ files",
|
|
374
|
-
issue.message
|
|
375
|
-
);
|
|
376
|
-
break;
|
|
377
|
-
case "missing-entry-file":
|
|
378
|
-
push("ๆฐๅขๅนถไฟ็็จณๅฎๅ
ฅๅฃๆไปถ main.tsx ไธ App.tsx", issue.message);
|
|
379
|
-
break;
|
|
380
|
-
case "invalid-file":
|
|
381
|
-
case "invalid-file-path":
|
|
382
|
-
push("ไฟฎๆญฃ้ๆณๆไปถๅๆ็ฉบๆไปถๅ
ๅฎน๏ผๅชๆนๅบ้ฎ้ข็ๆไปถ", issue.message);
|
|
383
|
-
break;
|
|
384
|
-
case "css-import-disallowed":
|
|
385
|
-
push("็งป้ค CSS import๏ผๆนๆๅ
่ๆ ทๅผใstyle ๅฏน่ฑกๆ็ปไปถๅ
style ๆ ็ญพ", issue.message);
|
|
386
|
-
break;
|
|
387
|
-
case "unsupported-import":
|
|
388
|
-
push(
|
|
389
|
-
issue.importSpecifier
|
|
390
|
-
? `็งป้คๆๆฟๆขๆชๆฏๆไพ่ต ${issue.importSpecifier}๏ผๅชไฟ็ๅนณๅฐ็ฝๅๅไพ่ต`
|
|
391
|
-
: "็งป้คๆๆฟๆขๆชๆฏๆไพ่ต๏ผๅชไฟ็ๅนณๅฐ็ฝๅๅไพ่ต",
|
|
392
|
-
issue.message
|
|
393
|
-
);
|
|
394
|
-
break;
|
|
395
|
-
case "invalid-icon-import":
|
|
396
|
-
push(
|
|
397
|
-
issue.suggestion
|
|
398
|
-
? `ๆๆ ๆๅพๆ ๆฟๆขๆ ${issue.suggestion}`
|
|
399
|
-
: "ๆๆ ๆๅพๆ ๆฟๆขๆ react-icons/lu ไธญ็ๅฎๅญๅจ็ๅพๆ ๅ",
|
|
400
|
-
issue.message
|
|
401
|
-
);
|
|
402
|
-
break;
|
|
403
|
-
default:
|
|
404
|
-
push("ๆ นๆฎ้ขๆฃ้ฎ้ขๅๅฑ้จไฟฎๅค๏ผไธ่ฆๆด้กต้ๅ", issue.message);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
push("ไฟฎๅฎๅๅ
้ๆฐ่ฐ็จ appPreflight", "็กฎ่ฎคๅฝๅ issues ๅทฒๆถ้ค");
|
|
409
|
-
push("ๅชๆ preflight ้่ฟๅๅ่ฐ็จ appDeploy", "้ฟๅ
้ๅค่ฟๅ
ฅๅคฑ่ดฅ้จ็ฝฒ");
|
|
410
|
-
return steps;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
function buildAppRepairPlan(args: {
|
|
414
|
-
summary: string;
|
|
415
|
-
framework: AppDeployFramework;
|
|
416
|
-
issues?: AppPreflightIssue[];
|
|
417
|
-
}): AppRepairPlan {
|
|
418
|
-
return {
|
|
419
|
-
strategy: "targeted-repair",
|
|
420
|
-
scope: "existing-files",
|
|
421
|
-
mode: "preflight-first",
|
|
422
|
-
summary: args.summary,
|
|
423
|
-
steps: buildRepairSteps(args.issues, args.framework),
|
|
424
|
-
issueCodes: [...new Set((args.issues ?? []).map((issue) => issue.code))],
|
|
425
|
-
suggestedFiles: inferRepairSuggestedFiles(args.issues),
|
|
426
|
-
rerun: ["appPreflight", "appDeploy"],
|
|
427
|
-
};
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
function buildAppRepairPayload(args: {
|
|
431
|
-
summary: string;
|
|
432
|
-
framework: AppDeployFramework;
|
|
433
|
-
issues?: AppPreflightIssue[];
|
|
434
|
-
warnings?: string[];
|
|
435
|
-
entryFile?: string;
|
|
436
|
-
externalImports?: string[];
|
|
437
|
-
code?: string;
|
|
438
|
-
}): {
|
|
439
|
-
success: false;
|
|
440
|
-
ok: false;
|
|
441
|
-
error: true;
|
|
442
|
-
code: "PREFLIGHT_FAILED" | "DEPLOY_FAILED";
|
|
443
|
-
summary: string;
|
|
444
|
-
framework: AppDeployFramework;
|
|
445
|
-
issues: AppPreflightIssue[];
|
|
446
|
-
warnings?: string[];
|
|
447
|
-
entryFile?: string;
|
|
448
|
-
externalImports?: string[];
|
|
449
|
-
repairPlan: AppRepairPlan;
|
|
450
|
-
nextAction: string;
|
|
451
|
-
} {
|
|
452
|
-
const issues = args.issues ?? [];
|
|
453
|
-
return {
|
|
454
|
-
success: false,
|
|
455
|
-
ok: false,
|
|
456
|
-
error: true,
|
|
457
|
-
code: issues.length > 0 ? "PREFLIGHT_FAILED" : "DEPLOY_FAILED",
|
|
458
|
-
summary: args.summary,
|
|
459
|
-
framework: args.framework,
|
|
460
|
-
issues,
|
|
461
|
-
...(args.warnings?.length ? { warnings: args.warnings } : {}),
|
|
462
|
-
...(args.entryFile ? { entryFile: args.entryFile } : {}),
|
|
463
|
-
...(args.externalImports?.length ? { externalImports: args.externalImports } : {}),
|
|
464
|
-
repairPlan: buildAppRepairPlan({
|
|
465
|
-
summary: args.summary,
|
|
466
|
-
framework: args.framework,
|
|
467
|
-
issues,
|
|
468
|
-
}),
|
|
469
|
-
nextAction:
|
|
470
|
-
"ๅชไฟฎๅคๅฝๅ issues ๅฝไธญ็ๆไปถๅไพ่ต๏ผ็ถๅ้ๆฐ่ฐ็จ appPreflight๏ผๅชๆ้่ฟๅๅ appDeployใ",
|
|
471
|
-
};
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
function formatRepairPlan(plan: AppRepairPlan | undefined): string {
|
|
475
|
-
if (!plan) return "";
|
|
476
|
-
return [
|
|
477
|
-
"ไฟฎๅคๅปบ่ฎฎ๏ผ",
|
|
478
|
-
...plan.steps.slice(0, 6).map((step, index) => `${index + 1}. ${step.action}๏ผ${step.reason}๏ผ`),
|
|
479
|
-
...(plan.keepFiles?.length ? [`- ไฟ็ๆไปถ๏ผ${plan.keepFiles.join(", ")}`] : []),
|
|
480
|
-
...(plan.revertFiles?.length ? [`- ๅ้ๆไปถ๏ผ${plan.revertFiles.join(", ")}`] : []),
|
|
481
|
-
...(plan.preferTokenFiles?.length
|
|
482
|
-
? [`- ไผๅ
ๆ่ง่งไฟฎๆนๆถๆๅฐ่ฟไบ token ๆไปถ๏ผ${plan.preferTokenFiles.join(", ")}`]
|
|
483
|
-
: []),
|
|
484
|
-
...(plan.targetStyleFields?.length
|
|
485
|
-
? [`- ไป
็ปง็ปญ่ฐๆด่ฟไบ่ง่งๅญๆฎต๏ผ${plan.targetStyleFields.join(", ")}`]
|
|
486
|
-
: []),
|
|
487
|
-
...(plan.targetElements?.length
|
|
488
|
-
? [`- ไป
็ปง็ปญ่ฐๆด่ฟไบๅ
็ด ๏ผ${plan.targetElements.join(", ")}`]
|
|
489
|
-
: []),
|
|
490
|
-
"ไฟฎๅฎๅ๏ผๅ
appPreflight๏ผๅ appDeployใ",
|
|
491
|
-
].join("\n");
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
function isTransportStoplossError(error: {
|
|
495
|
-
code?: string;
|
|
496
|
-
message?: string;
|
|
497
|
-
details?: unknown;
|
|
498
|
-
} | null | undefined): boolean {
|
|
499
|
-
const code = error?.code ?? "";
|
|
500
|
-
if (
|
|
501
|
-
code === "HTML_RESPONSE" ||
|
|
502
|
-
code === "INVALID_JSON_RESPONSE" ||
|
|
503
|
-
code === "HTML_ERROR_RESPONSE" ||
|
|
504
|
-
code === "NON_JSON_ERROR_RESPONSE"
|
|
505
|
-
) {
|
|
506
|
-
return true;
|
|
507
|
-
}
|
|
508
|
-
const message = error?.message ?? "";
|
|
509
|
-
return message.includes("Unexpected token '<'") || message.includes("<!DOCTYPE");
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
function buildAppStoplossPayload(args: {
|
|
513
|
-
summary: string;
|
|
514
|
-
framework: AppDeployFramework;
|
|
515
|
-
stage: "deploy" | "preflight";
|
|
516
|
-
error?: {
|
|
517
|
-
code?: string;
|
|
518
|
-
details?: unknown;
|
|
519
|
-
message?: string;
|
|
520
|
-
} | null;
|
|
521
|
-
}): AppStoplossPayload {
|
|
522
|
-
const details =
|
|
523
|
-
args.error?.details && typeof args.error.details === "object"
|
|
524
|
-
? (args.error.details as { responsePreview?: string })
|
|
525
|
-
: null;
|
|
526
|
-
const errorCode = args.error?.code ?? "";
|
|
527
|
-
const stopReason =
|
|
528
|
-
errorCode.includes("HTML") || (args.error?.message ?? "").includes("<!DOCTYPE")
|
|
529
|
-
? "html-response"
|
|
530
|
-
: "invalid-json-response";
|
|
531
|
-
return {
|
|
532
|
-
success: false,
|
|
533
|
-
ok: false,
|
|
534
|
-
error: true,
|
|
535
|
-
code:
|
|
536
|
-
args.stage === "preflight"
|
|
537
|
-
? "PREFLIGHT_TRANSPORT_FAILURE"
|
|
538
|
-
: "DEPLOY_TRANSPORT_FAILURE",
|
|
539
|
-
summary: args.summary,
|
|
540
|
-
framework: args.framework,
|
|
541
|
-
stopReason,
|
|
542
|
-
retryable: false,
|
|
543
|
-
...(details?.responsePreview ? { responsePreview: details.responsePreview } : {}),
|
|
544
|
-
nextAction:
|
|
545
|
-
"่ฟไธๆฏไปฃ็ ็บง issues๏ผ่ๆฏ้จ็ฝฒ้้่ฟๅไบๅผๅธธๅๅบใๅๆญข่ชๅจ deploy / preflight ้่ฏ๏ผๅ็จๆท่ฏดๆๅฝๅๅนณๅฐๆฅๅฃๅผๅธธ๏ผ็ญๅพ
ๆๅกๆขๅคๅๅ็ปง็ปญใ",
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
function formatStoplossPlan(payload: AppStoplossPayload): string {
|
|
550
|
-
return [
|
|
551
|
-
payload.summary,
|
|
552
|
-
payload.responsePreview ? `ๅๅบ้ข่ง: ${payload.responsePreview}` : "",
|
|
553
|
-
"ๅคๆญ: ๅฝๅๆฏ้จ็ฝฒ/้ขๆฃ้้ๅผๅธธ๏ผไธๆฏๅบ็จไปฃ็ ้ฎ้ขใ",
|
|
554
|
-
"ไธไธๆญฅ: ๅๆญข่ชๅจ้่ฏ๏ผๅ่ฏ็จๆทๅฝๅๅนณๅฐๆฅๅฃ่ฟๅๅผๅธธ๏ผ็จๅๅ่ฏใ",
|
|
555
|
-
]
|
|
556
|
-
.filter(Boolean)
|
|
557
|
-
.join("\n");
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
561
|
-
|
|
562
|
-
async function pollAppDeployJob(
|
|
563
|
-
thunkApi: any,
|
|
564
|
-
args: AppDeployArgs,
|
|
565
|
-
toolRunId: string | undefined,
|
|
566
|
-
jobId: string,
|
|
567
|
-
options?: {
|
|
568
|
-
sharedState?: {
|
|
569
|
-
done: boolean;
|
|
570
|
-
result?: AppDeployApiResult;
|
|
571
|
-
failure?: Error;
|
|
572
|
-
error?: string;
|
|
573
|
-
lastSteps: ToolRunStep[];
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
): Promise<AppDeployApiResult> {
|
|
577
|
-
const sharedState = options?.sharedState;
|
|
578
|
-
let lastSteps: ToolRunStep[] = sharedState?.lastSteps ?? [];
|
|
579
|
-
try {
|
|
580
|
-
for (let attempt = 0; attempt < 180; attempt += 1) {
|
|
581
|
-
if (sharedState?.done) {
|
|
582
|
-
if (sharedState.result) return sharedState.result;
|
|
583
|
-
if (sharedState.failure) throw sharedState.failure;
|
|
584
|
-
throw new Error(sharedState.error || "้จ็ฝฒๅคฑ่ดฅ");
|
|
585
|
-
}
|
|
586
|
-
const statusData = await callToolApi<AppDeployStatusResult>(
|
|
587
|
-
thunkApi,
|
|
588
|
-
"/api/app/deploy/status",
|
|
589
|
-
{ jobId },
|
|
590
|
-
{ withAuth: true }
|
|
591
|
-
);
|
|
592
|
-
|
|
593
|
-
const nextSteps = Array.isArray(statusData.steps)
|
|
594
|
-
? statusData.steps.map((step) => {
|
|
595
|
-
const previous = lastSteps.find((item) => item.id === step.id);
|
|
596
|
-
if (
|
|
597
|
-
previous &&
|
|
598
|
-
TOOL_STEP_STATUS_RANK[step.status] < TOOL_STEP_STATUS_RANK[previous.status]
|
|
599
|
-
) {
|
|
600
|
-
return previous;
|
|
601
|
-
}
|
|
602
|
-
return step;
|
|
603
|
-
})
|
|
604
|
-
: lastSteps;
|
|
605
|
-
// Only advance lastSteps when server returns a non-empty steps array; this
|
|
606
|
-
// preserves the last known UI state if the server briefly returns empty steps.
|
|
607
|
-
if (nextSteps.length > 0) {
|
|
608
|
-
lastSteps = nextSteps;
|
|
609
|
-
if (sharedState) {
|
|
610
|
-
sharedState.lastSteps = nextSteps;
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
updateDeployProgress(
|
|
615
|
-
thunkApi,
|
|
616
|
-
toolRunId,
|
|
617
|
-
lastSteps.length > 0 ? lastSteps : "prepare",
|
|
618
|
-
statusData.summary ?? "ๆญฃๅจๅๆญฅๆๅก็ซฏ้จ็ฝฒ็ถๆโฆ",
|
|
619
|
-
statusData.status === "failed" ? "failed" : "running"
|
|
620
|
-
);
|
|
621
|
-
|
|
622
|
-
if (statusData.status === "succeeded" && statusData.result) {
|
|
623
|
-
if (sharedState) {
|
|
624
|
-
sharedState.done = true;
|
|
625
|
-
sharedState.result = statusData.result;
|
|
626
|
-
}
|
|
627
|
-
return statusData.result;
|
|
628
|
-
}
|
|
629
|
-
if (statusData.status === "failed") {
|
|
630
|
-
if (
|
|
631
|
-
isTransportStoplossError({
|
|
632
|
-
code: statusData.error?.code,
|
|
633
|
-
details: statusData.error?.details,
|
|
634
|
-
message: statusData.error?.message || statusData.summary,
|
|
635
|
-
})
|
|
636
|
-
) {
|
|
637
|
-
const payload = buildAppStoplossPayload({
|
|
638
|
-
summary: "้จ็ฝฒ็ถๆๆฅๅฃ่ฟๅไบๅผๅธธๅๅบ๏ผๅทฒๅๆญข่ชๅจ้่ฏใ",
|
|
639
|
-
framework: args.framework ?? "worker",
|
|
640
|
-
stage: "deploy",
|
|
641
|
-
error: {
|
|
642
|
-
code: statusData.error?.code,
|
|
643
|
-
details: statusData.error?.details,
|
|
644
|
-
message: statusData.error?.message || statusData.summary,
|
|
645
|
-
},
|
|
646
|
-
});
|
|
647
|
-
const displayMessage = formatStoplossPlan(payload);
|
|
648
|
-
const stoplossError = new ToolResultError(payload.summary, {
|
|
649
|
-
code: payload.code,
|
|
650
|
-
rawData: payload,
|
|
651
|
-
displayData: displayMessage,
|
|
652
|
-
retryable: false,
|
|
653
|
-
});
|
|
654
|
-
if (sharedState) {
|
|
655
|
-
sharedState.done = true;
|
|
656
|
-
sharedState.failure = stoplossError;
|
|
657
|
-
sharedState.error = displayMessage;
|
|
658
|
-
}
|
|
659
|
-
updateDeployProgress(
|
|
660
|
-
thunkApi,
|
|
661
|
-
toolRunId,
|
|
662
|
-
statusData.steps ?? "prepare",
|
|
663
|
-
displayMessage,
|
|
664
|
-
"failed"
|
|
665
|
-
);
|
|
666
|
-
throw stoplossError;
|
|
667
|
-
}
|
|
668
|
-
const rewrittenBase = rewriteAppDeployError(
|
|
669
|
-
statusData.error?.message || statusData.summary || "้จ็ฝฒๅคฑ่ดฅ",
|
|
670
|
-
args
|
|
671
|
-
);
|
|
672
|
-
const issues =
|
|
673
|
-
statusData.error?.code === "PREFLIGHT_FAILED"
|
|
674
|
-
? ((statusData.error?.details as { issues?: AppPreflightIssue[] } | undefined)?.issues ?? [])
|
|
675
|
-
: [];
|
|
676
|
-
const repairPayload = buildAppRepairPayload({
|
|
677
|
-
summary: rewrittenBase,
|
|
678
|
-
framework: args.framework ?? "worker",
|
|
679
|
-
issues,
|
|
680
|
-
});
|
|
681
|
-
const rewritten = [
|
|
682
|
-
rewrittenBase,
|
|
683
|
-
formatPreflightIssues(issues),
|
|
684
|
-
formatRepairPlan(repairPayload.repairPlan),
|
|
685
|
-
]
|
|
686
|
-
.filter(Boolean)
|
|
687
|
-
.join("\n");
|
|
688
|
-
const repairError = new ToolResultError(rewrittenBase, {
|
|
689
|
-
code: statusData.error?.code ?? repairPayload.code,
|
|
690
|
-
rawData: repairPayload,
|
|
691
|
-
displayData: rewritten,
|
|
692
|
-
retryable: true,
|
|
693
|
-
});
|
|
694
|
-
if (sharedState) {
|
|
695
|
-
sharedState.done = true;
|
|
696
|
-
sharedState.failure = repairError;
|
|
697
|
-
sharedState.error = rewritten;
|
|
698
|
-
}
|
|
699
|
-
updateDeployProgress(
|
|
700
|
-
thunkApi,
|
|
701
|
-
toolRunId,
|
|
702
|
-
statusData.steps ?? "prepare",
|
|
703
|
-
rewritten,
|
|
704
|
-
"failed"
|
|
705
|
-
);
|
|
706
|
-
throw repairError;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
await sleep(Math.min(400 + attempt * 50, 2000));
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
throw new Error("้จ็ฝฒไปปๅกไปๅจๆๅก็ซฏๆง่ก๏ผ่ฏท็จๅ้่ฏๆฅ็็ปๆใ");
|
|
713
|
-
} finally {
|
|
714
|
-
// Ensure SSE subscriber always sees done=true so it can cancel the reader,
|
|
715
|
-
// even when polling times out or throws an unexpected error.
|
|
716
|
-
if (sharedState && !sharedState.done) {
|
|
717
|
-
sharedState.done = true;
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
async function subscribeToDeployEvents(args: {
|
|
723
|
-
thunkApi: any;
|
|
724
|
-
deployArgs: AppDeployArgs;
|
|
725
|
-
toolRunId?: string;
|
|
726
|
-
jobId: string;
|
|
727
|
-
eventChannel: string;
|
|
728
|
-
sharedState: {
|
|
729
|
-
done: boolean;
|
|
730
|
-
result?: AppDeployApiResult;
|
|
731
|
-
failure?: Error;
|
|
732
|
-
error?: string;
|
|
733
|
-
lastSteps: ToolRunStep[];
|
|
734
|
-
};
|
|
735
|
-
}): Promise<void> {
|
|
736
|
-
const { thunkApi, deployArgs, toolRunId, jobId, eventChannel, sharedState } = args;
|
|
737
|
-
const { baseUrl, token } = getToolRequestContext(thunkApi);
|
|
738
|
-
if (!token) return;
|
|
739
|
-
|
|
740
|
-
const res = await fetch(`${baseUrl}/api/events/${encodeURIComponent(eventChannel)}`, {
|
|
741
|
-
method: "GET",
|
|
742
|
-
headers: {
|
|
743
|
-
Accept: "text/event-stream",
|
|
744
|
-
Authorization: `Bearer ${token}`,
|
|
745
|
-
},
|
|
746
|
-
});
|
|
747
|
-
if (!res.ok || !res.body) return;
|
|
748
|
-
|
|
749
|
-
const reader = res.body.getReader();
|
|
750
|
-
const decoder = new TextDecoder();
|
|
751
|
-
|
|
752
|
-
try {
|
|
753
|
-
while (true) {
|
|
754
|
-
if (sharedState.done) {
|
|
755
|
-
return;
|
|
756
|
-
}
|
|
757
|
-
const { done, value } = await reader.read();
|
|
758
|
-
if (done) return;
|
|
759
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
760
|
-
for (const event of parseSseChunk(chunk)) {
|
|
761
|
-
if (event.type !== "app-deploy-progress" || event.jobId !== jobId) continue;
|
|
762
|
-
const eventSteps = Array.isArray(event.steps)
|
|
763
|
-
? (event.steps as ToolRunStep[]).map((step) => {
|
|
764
|
-
const previous = sharedState.lastSteps.find((item) => item.id === step.id);
|
|
765
|
-
if (
|
|
766
|
-
previous &&
|
|
767
|
-
TOOL_STEP_STATUS_RANK[step.status] < TOOL_STEP_STATUS_RANK[previous.status]
|
|
768
|
-
) {
|
|
769
|
-
return previous;
|
|
770
|
-
}
|
|
771
|
-
return step;
|
|
772
|
-
})
|
|
773
|
-
: sharedState.lastSteps;
|
|
774
|
-
sharedState.lastSteps = eventSteps;
|
|
775
|
-
const status = typeof event.status === "string" ? event.status : "running";
|
|
776
|
-
const summary =
|
|
777
|
-
typeof event.summary === "string" ? event.summary : "ๆญฃๅจๆฅๆถๆๅก็ซฏ้จ็ฝฒไบไปถโฆ";
|
|
778
|
-
|
|
779
|
-
updateDeployProgress(
|
|
780
|
-
thunkApi,
|
|
781
|
-
toolRunId,
|
|
782
|
-
eventSteps.length > 0 ? eventSteps : "prepare",
|
|
783
|
-
summary,
|
|
784
|
-
status === "failed" ? "failed" : status === "succeeded" ? "succeeded" : "running"
|
|
785
|
-
);
|
|
786
|
-
|
|
787
|
-
if (status === "succeeded" && event.result) {
|
|
788
|
-
sharedState.done = true;
|
|
789
|
-
sharedState.result = event.result as AppDeployApiResult;
|
|
790
|
-
return;
|
|
791
|
-
}
|
|
792
|
-
if (status === "failed") {
|
|
793
|
-
if (
|
|
794
|
-
isTransportStoplossError({
|
|
795
|
-
code: (event.error as { code?: string } | undefined)?.code,
|
|
796
|
-
details: (event.error as { details?: unknown } | undefined)?.details,
|
|
797
|
-
message: (event.error as { message?: string } | undefined)?.message || summary,
|
|
798
|
-
})
|
|
799
|
-
) {
|
|
800
|
-
const payload = buildAppStoplossPayload({
|
|
801
|
-
summary: "้จ็ฝฒไบไปถๆต่ฟๅไบๅผๅธธๅๅบ๏ผๅทฒๅๆญข่ชๅจ้่ฏใ",
|
|
802
|
-
framework: deployArgs.framework ?? "worker",
|
|
803
|
-
stage: "deploy",
|
|
804
|
-
error: {
|
|
805
|
-
code: (event.error as { code?: string } | undefined)?.code,
|
|
806
|
-
details: (event.error as { details?: unknown } | undefined)?.details,
|
|
807
|
-
message: (event.error as { message?: string } | undefined)?.message || summary,
|
|
808
|
-
},
|
|
809
|
-
});
|
|
810
|
-
const displayMessage = formatStoplossPlan(payload);
|
|
811
|
-
const stoplossError = new ToolResultError(payload.summary, {
|
|
812
|
-
code: payload.code,
|
|
813
|
-
rawData: payload,
|
|
814
|
-
displayData: displayMessage,
|
|
815
|
-
retryable: false,
|
|
816
|
-
});
|
|
817
|
-
sharedState.done = true;
|
|
818
|
-
sharedState.failure = stoplossError;
|
|
819
|
-
sharedState.error = displayMessage;
|
|
820
|
-
updateDeployProgress(
|
|
821
|
-
thunkApi,
|
|
822
|
-
toolRunId,
|
|
823
|
-
eventSteps.length > 0 ? eventSteps : "prepare",
|
|
824
|
-
displayMessage,
|
|
825
|
-
"failed"
|
|
826
|
-
);
|
|
827
|
-
return;
|
|
828
|
-
}
|
|
829
|
-
const rewrittenBase = rewriteAppDeployError(
|
|
830
|
-
(event.error as { message?: string } | undefined)?.message || summary || "้จ็ฝฒๅคฑ่ดฅ",
|
|
831
|
-
deployArgs
|
|
832
|
-
);
|
|
833
|
-
const issues =
|
|
834
|
-
(event.error as { code?: string; details?: { issues?: AppPreflightIssue[] } } | undefined)?.code === "PREFLIGHT_FAILED"
|
|
835
|
-
? (((event.error as { details?: { issues?: AppPreflightIssue[] } } | undefined)?.details)
|
|
836
|
-
?.issues ?? [])
|
|
837
|
-
: [];
|
|
838
|
-
const repairPayload = buildAppRepairPayload({
|
|
839
|
-
summary: rewrittenBase,
|
|
840
|
-
framework: deployArgs.framework ?? "worker",
|
|
841
|
-
issues,
|
|
842
|
-
});
|
|
843
|
-
const rewritten = [
|
|
844
|
-
rewrittenBase,
|
|
845
|
-
formatPreflightIssues(issues),
|
|
846
|
-
formatRepairPlan(repairPayload.repairPlan),
|
|
847
|
-
]
|
|
848
|
-
.filter(Boolean)
|
|
849
|
-
.join("\n");
|
|
850
|
-
const repairError = new ToolResultError(rewrittenBase, {
|
|
851
|
-
code: (event.error as { code?: string } | undefined)?.code ?? repairPayload.code,
|
|
852
|
-
rawData: repairPayload,
|
|
853
|
-
displayData: rewritten,
|
|
854
|
-
retryable: true,
|
|
855
|
-
});
|
|
856
|
-
sharedState.done = true;
|
|
857
|
-
sharedState.failure = repairError;
|
|
858
|
-
sharedState.error = rewritten;
|
|
859
|
-
updateDeployProgress(
|
|
860
|
-
thunkApi,
|
|
861
|
-
toolRunId,
|
|
862
|
-
eventSteps.length > 0 ? eventSteps : "prepare",
|
|
863
|
-
rewritten,
|
|
864
|
-
"failed"
|
|
865
|
-
);
|
|
866
|
-
return;
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
} finally {
|
|
871
|
-
// Cancel the SSE reader on every exit path (success, failure, external done,
|
|
872
|
-
// natural stream end) so the underlying HTTP connection is always released.
|
|
873
|
-
try {
|
|
874
|
-
await reader.cancel();
|
|
875
|
-
} catch {}
|
|
876
|
-
try {
|
|
877
|
-
reader.releaseLock();
|
|
878
|
-
} catch {}
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
883
|
-
// appDeploy โ ้จ็ฝฒๆๆดๆฐไธไธช Web ๅบ็จ
|
|
884
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
885
|
-
export const appDeployFunctionSchema = {
|
|
886
|
-
name: "appDeploy",
|
|
887
|
-
description:
|
|
888
|
-
"ๅฐ JavaScript/TypeScript ไปฃ็ ้จ็ฝฒไธบ Web ๅบ็จใ" +
|
|
889
|
-
"้ป่ฎค้จ็ฝฒๅฐๅนณๅฐๆๅกๅจ๏ผnolo.chat/apps/{appId}/๏ผ๏ผๆ ้็จๆท้
็ฝฎไปปไฝ้ขๅค่ดฆๅท๏ผ็ซๅณๅฏ่ฎฟ้ฎใ" +
|
|
890
|
-
"ไปฃ็ ๅฟ
้กปๆฏ ES Module ๆ ผๅผ๏ผexport default { fetch(req) {} }๏ผใ" +
|
|
891
|
-
"ๆฏๆๅคๆไปถ้กน็ฎ๏ผ้่ฟ files ๆฐ็ปไผ ๅ
ฅ๏ผๆๅก็ซฏ่ชๅจๆๅ
ใ" +
|
|
892
|
-
"ๆฐๅปบๅบ็จๆถไฝฟ็จ name๏ผๆดๆฐๅทฒๆๅบ็จๆถๅฟ
้กปไผๅ
ไผ appId๏ผ้ฟๅ
ๅ ไธบๅ็งฐ้ๅค่่ฏฏๅปบๆฐๅบ็จใ",
|
|
893
|
-
parameters: {
|
|
894
|
-
type: "object",
|
|
895
|
-
properties: {
|
|
896
|
-
name: {
|
|
897
|
-
type: "string",
|
|
898
|
-
description: "ๅบ็จๅ็งฐ๏ผๅชๅ
่ฎธๅญๆฏใๆฐๅญใ่ฟๅญ็ฌฆ๏ผไพๅฆ 'my-app' ๆ 'bmi-calculator'ใไป
็จไบๆฐๅปบๅบ็จ๏ผๆดๆฐๅทฒๆๅบ็จๆถๅบไผๅ
ไผ appId๏ผๆๅก็ซฏไผ่ชๅจๆฒฟ็จๅๅฒๅ็งฐใ",
|
|
899
|
-
},
|
|
900
|
-
code: {
|
|
901
|
-
type: "string",
|
|
902
|
-
description:
|
|
903
|
-
"ๅๆไปถๅบ็จไปฃ็ ๏ผๅฟ
้กปๆฏ ES Module ๆ ผๅผใไธ files ไบ้ไธใ" +
|
|
904
|
-
"็คบไพ๏ผ\n" +
|
|
905
|
-
"export default {\n" +
|
|
906
|
-
" async fetch(request, env, ctx) {\n" +
|
|
907
|
-
" return new Response('Hello World!');\n" +
|
|
908
|
-
" }\n" +
|
|
909
|
-
"};",
|
|
910
|
-
},
|
|
911
|
-
files: {
|
|
912
|
-
type: "array",
|
|
913
|
-
description: "ๅคๆไปถ้กน็ฎ๏ผไธ code ไบ้ไธใๆๅก็ซฏ่ชๅจๆๅ
ใๆฎ้ Worker ๅ
ฅๅฃ็จ index.ts/main.ts/worker.ts๏ผReact SPA ๆจ่ main.tsx + App.tsxใ",
|
|
914
|
-
items: {
|
|
915
|
-
type: "object",
|
|
916
|
-
properties: {
|
|
917
|
-
name: { type: "string", description: "ๆไปถๅ๏ผๅฆ 'index.ts' ๆ 'utils/helper.ts'" },
|
|
918
|
-
code: { type: "string", description: "ๆไปถๅ
ๅฎน" },
|
|
919
|
-
},
|
|
920
|
-
required: ["name", "code"],
|
|
921
|
-
},
|
|
922
|
-
},
|
|
923
|
-
pages: {
|
|
924
|
-
type: "array",
|
|
925
|
-
description: "ๅ
ผๅฎนๅซๅ๏ผ็ญๅไบ filesใ่ฅไธๆธธ็ๆ็ๆฏ pages ๅญๆฎต๏ผ็ณป็ปไผ่ชๅจๆ files ๅค็ใ",
|
|
926
|
-
items: {
|
|
927
|
-
type: "object",
|
|
928
|
-
properties: {
|
|
929
|
-
name: { type: "string", description: "ๆไปถๅ๏ผๅฆ 'App.tsx'" },
|
|
930
|
-
code: { type: "string", description: "ๆไปถๅ
ๅฎน" },
|
|
931
|
-
},
|
|
932
|
-
required: ["name", "code"],
|
|
933
|
-
},
|
|
934
|
-
},
|
|
935
|
-
appId: {
|
|
936
|
-
type: "string",
|
|
937
|
-
description:
|
|
938
|
-
"ๅบ็จ ID๏ผๆๅกๅจ่ฟๅ็ ULID๏ผใ" +
|
|
939
|
-
"ๅๅปบๆฐๅบ็จๆถไธ่ฆไผ ๆญคๅญๆฎต๏ผๆๅกๅจไผ่ชๅจ็ๆๅนถๅจๅๅบไธญ่ฟๅใ" +
|
|
940
|
-
"ๆดๆฐๅทฒๆๅบ็จๆถ๏ผๅกซๅ
ฅไธๆฌก้จ็ฝฒๅๅบไธญ่ฟๅ็ appId๏ผๅฎ็ฐ่ฆ็ๆดๆฐ่้ๆฐๅปบใ",
|
|
941
|
-
},
|
|
942
|
-
framework: {
|
|
943
|
-
type: "string",
|
|
944
|
-
enum: ["worker", "react-spa"],
|
|
945
|
-
description:
|
|
946
|
-
"ๅบ็จๆกๆถใ" +
|
|
947
|
-
"'worker'๏ผ้ป่ฎค๏ผ๏ผ็ดๆฅ้จ็ฝฒ export default { fetch } ไปฃ็ ใ" +
|
|
948
|
-
"'react-spa'๏ผ้จ็ฝฒๅคๆไปถ React ๅ้กตๅบ็จ๏ผ้ๅๅคๆไบคไบใๅพ่กจๅ็ปไปถๅ้กต้ขใReact SPA ๆจกๅผๅฟ
้กป้
ๅ files ไฝฟ็จใ",
|
|
949
|
-
},
|
|
950
|
-
spaceId: {
|
|
951
|
-
type: "string",
|
|
952
|
-
description:
|
|
953
|
-
"ๅฏ้็ Space IDใ้ป่ฎคไผไผๅ
ไฝฟ็จๅฝๅๆญฃๅจ็ผ่พ/ๅฏน่ฏ็็ฉบ้ดใ" +
|
|
954
|
-
"ๅฆๆๆฏๅฐๆช็ปๅฎ็ฉบ้ด็ๆงๅบ็จ๏ผ้ๆฐ้จ็ฝฒๆถไผๆๅฎ็ปๅฎๅฐ่ฏฅ็ฉบ้ด๏ผ" +
|
|
955
|
-
"ๅทฒ็ป็ปๅฎ็ฉบ้ด็ๅบ็จไธไผๅ ไธบ่ฟไธชๅญๆฎต่ขซ่ฟ็งปใ",
|
|
956
|
-
},
|
|
957
|
-
},
|
|
958
|
-
anyOf: [
|
|
959
|
-
{ required: ["name"] },
|
|
960
|
-
{ required: ["appId"] },
|
|
961
|
-
],
|
|
962
|
-
// note: ๆฐๅปบๅบ็จๆถๅฟ
้กปๆพๅผๆไพ name๏ผๆดๆฐๅทฒๆๅบ็จๆถๅ
่ฎธไป
ไผ appId
|
|
963
|
-
},
|
|
964
|
-
};
|
|
965
|
-
|
|
966
|
-
export const appPreflightFunctionSchema = {
|
|
967
|
-
name: "appPreflight",
|
|
968
|
-
description:
|
|
969
|
-
"ๅจ็ๆญฃ้จ็ฝฒๅๅ
ๅๅบ็จ้ขๆฃ๏ผๆฃๆฅ React SPA / Worker ็ๅ
ฅๅฃๆไปถใ็ฝๅๅไพ่ตใๅพๆ ๅใCSS import ๅๅธธ่ง้จ็ฝฒ้่ฏฏใ",
|
|
970
|
-
parameters: {
|
|
971
|
-
type: "object",
|
|
972
|
-
properties: {
|
|
973
|
-
name: {
|
|
974
|
-
type: "string",
|
|
975
|
-
description: "ๅบ็จๅ็งฐใๆฐๅปบๅบ็จๅปบ่ฎฎไผ ๏ผๆดๆฐๅทฒๆๅบ็จๆถๅฏ้
ๅ appId ไธ่ตทไผ ใ",
|
|
976
|
-
},
|
|
977
|
-
code: {
|
|
978
|
-
type: "string",
|
|
979
|
-
description: "ๅๆไปถ Worker ไปฃ็ ๏ผไธ files ไบ้ไธใ",
|
|
980
|
-
},
|
|
981
|
-
files: {
|
|
982
|
-
type: "array",
|
|
983
|
-
description: "ๅคๆไปถๆบ็ ๏ผไธ code ไบ้ไธใReact SPA ๆจ่ main.tsx + App.tsxใ",
|
|
984
|
-
items: {
|
|
985
|
-
type: "object",
|
|
986
|
-
properties: {
|
|
987
|
-
name: { type: "string" },
|
|
988
|
-
code: { type: "string" },
|
|
989
|
-
},
|
|
990
|
-
required: ["name", "code"],
|
|
991
|
-
},
|
|
992
|
-
},
|
|
993
|
-
pages: {
|
|
994
|
-
type: "array",
|
|
995
|
-
description: "ๅ
ผๅฎนๅซๅ๏ผ็ญๅไบ filesใ",
|
|
996
|
-
items: {
|
|
997
|
-
type: "object",
|
|
998
|
-
properties: {
|
|
999
|
-
name: { type: "string" },
|
|
1000
|
-
code: { type: "string" },
|
|
1001
|
-
},
|
|
1002
|
-
required: ["name", "code"],
|
|
1003
|
-
},
|
|
1004
|
-
},
|
|
1005
|
-
appId: {
|
|
1006
|
-
type: "string",
|
|
1007
|
-
description: "ๅทฒๅญๅจๅบ็จ็ appId๏ผ็จไบๆดๆฐๅๆ ก้ชใ",
|
|
1008
|
-
},
|
|
1009
|
-
framework: {
|
|
1010
|
-
type: "string",
|
|
1011
|
-
enum: ["worker", "react-spa"],
|
|
1012
|
-
},
|
|
1013
|
-
spaceId: {
|
|
1014
|
-
type: "string",
|
|
1015
|
-
description: "ๅฏ้ Space IDใ",
|
|
1016
|
-
},
|
|
1017
|
-
},
|
|
1018
|
-
anyOf: [{ required: ["name"] }, { required: ["appId"] }],
|
|
1019
|
-
},
|
|
1020
|
-
};
|
|
1021
|
-
|
|
1022
|
-
export async function appPreflightFunc(
|
|
1023
|
-
rawArgs: AppDeployArgs,
|
|
1024
|
-
thunkApi: any
|
|
1025
|
-
): Promise<{ rawData: any; displayData: string }> {
|
|
1026
|
-
const args = normalizeAppDeployArgs(rawArgs);
|
|
1027
|
-
const deploySpaceId = await resolveAppDeploySpaceId(args, thunkApi);
|
|
1028
|
-
const data = await callToolApi<AppPreflightResult>(
|
|
1029
|
-
thunkApi,
|
|
1030
|
-
"/api/app/preflight",
|
|
1031
|
-
{
|
|
1032
|
-
name: args.name,
|
|
1033
|
-
code: args.code,
|
|
1034
|
-
files: args.files,
|
|
1035
|
-
appId: args.appId,
|
|
1036
|
-
framework: args.framework,
|
|
1037
|
-
...(deploySpaceId ? { spaceId: deploySpaceId } : {}),
|
|
1038
|
-
},
|
|
1039
|
-
{ withAuth: true }
|
|
1040
|
-
);
|
|
1041
|
-
|
|
1042
|
-
const lines = [
|
|
1043
|
-
data.ok ? "โ
้ขๆฃ้่ฟ" : "โ ้ขๆฃๅคฑ่ดฅ",
|
|
1044
|
-
`- ๆกๆถ: ${data.framework}`,
|
|
1045
|
-
`- ๆ่ฆ: ${data.summary}`,
|
|
1046
|
-
];
|
|
1047
|
-
const repairPayload = data.ok
|
|
1048
|
-
? null
|
|
1049
|
-
: buildAppRepairPayload({
|
|
1050
|
-
summary: data.summary,
|
|
1051
|
-
framework: data.framework,
|
|
1052
|
-
issues: data.issues,
|
|
1053
|
-
warnings: data.warnings,
|
|
1054
|
-
entryFile: data.entryFile,
|
|
1055
|
-
externalImports: data.externalImports,
|
|
1056
|
-
});
|
|
1057
|
-
if (data.entryFile) lines.push(`- ๅ
ฅๅฃๆไปถ: ${data.entryFile}`);
|
|
1058
|
-
if (data.issues?.length) {
|
|
1059
|
-
lines.push(`\n้ฎ้ข:\n${formatPreflightIssues(data.issues)}`);
|
|
1060
|
-
}
|
|
1061
|
-
if (repairPayload?.repairPlan) {
|
|
1062
|
-
lines.push(`\n${formatRepairPlan(repairPayload.repairPlan)}`);
|
|
1063
|
-
}
|
|
1064
|
-
if (data.warnings?.length) {
|
|
1065
|
-
lines.push(`\n่ญฆๅ:\n${data.warnings.map((warning) => `- ${warning}`).join("\n")}`);
|
|
1066
|
-
}
|
|
1067
|
-
|
|
1068
|
-
return {
|
|
1069
|
-
rawData: repairPayload ?? data,
|
|
1070
|
-
displayData: lines.join("\n"),
|
|
1071
|
-
};
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
export async function appDeployFunc(
|
|
1075
|
-
rawArgs: AppDeployArgs,
|
|
1076
|
-
thunkApi: any,
|
|
1077
|
-
context?: { parentMessageId: string; toolRunId?: string; userInput?: string }
|
|
1078
|
-
): Promise<{ rawData: any; displayData: string }> {
|
|
1079
|
-
const args = normalizeAppDeployArgs(rawArgs);
|
|
1080
|
-
const { name, code, files, appId, framework } = args;
|
|
1081
|
-
const deploySpaceId = await resolveAppDeploySpaceId(args, thunkApi);
|
|
1082
|
-
const toolRunId = context?.toolRunId;
|
|
1083
|
-
if (!name && !appId) throw new Error("ๅฟ
้กปๆไพ name ๅๆฐ๏ผๆฐๅปบๅบ็จๆถๅฟ
ๅกซ๏ผๆดๆฐๅทฒๆๅบ็จๆถๅฏ็็ฅ๏ผๆๅก็ซฏไป appId ่ฎฐๅฝไธญ่ชๅจ่กฅๅ
๏ผ");
|
|
1084
|
-
if (framework === "react-spa" && code && (!files || files.length === 0)) {
|
|
1085
|
-
throw new Error('React SPA ้่ฆไผ `files`๏ผ่ณๅฐ `main.tsx` + `App.tsx`๏ผ๏ผไธ่ฝๅชไผ `code`ใ');
|
|
1086
|
-
}
|
|
1087
|
-
if (!code && (!files || files.length === 0)) throw new Error("ๅฟ
้กปๆไพ code ๆ files ๅๆฐ");
|
|
1088
|
-
if ((rawArgs as { deployTarget?: string }).deployTarget && (rawArgs as { deployTarget?: string }).deployTarget !== "platform") {
|
|
1089
|
-
throw new Error("ๅทฒไธๅๆฏๆ Cloudflare ้จ็ฝฒ็ฎๆ ๏ผ่ฏทไฝฟ็จๅนณๅฐๆ็ฎกใ");
|
|
1090
|
-
}
|
|
1091
|
-
|
|
1092
|
-
updateDeployProgress(
|
|
1093
|
-
thunkApi,
|
|
1094
|
-
toolRunId,
|
|
1095
|
-
"prepare",
|
|
1096
|
-
"ๆญฃๅจๆด็้จ็ฝฒๅๆฐโฆ",
|
|
1097
|
-
"running",
|
|
1098
|
-
framework === "react-spa" ? "ๅๅค React SPA ๅคๆไปถๆๅปบ" : "ๅๅคๅๆไปถ Worker / ๅคๆไปถ Worker ้จ็ฝฒ"
|
|
1099
|
-
);
|
|
1100
|
-
|
|
1101
|
-
const guardUserInput = context?.userInput ?? getLatestUserInputFromThunk(thunkApi);
|
|
1102
|
-
if (appId && (code || (files && files.length > 0)) && guardUserInput) {
|
|
1103
|
-
try {
|
|
1104
|
-
const previousSource = await callToolApi<{
|
|
1105
|
-
code?: string;
|
|
1106
|
-
files?: AppSourceFile[];
|
|
1107
|
-
}>(thunkApi, "/api/app/prepare-edit", { appId }, { withAuth: true });
|
|
1108
|
-
const guardResult = evaluateSmallVisualEditGuard({
|
|
1109
|
-
userInput: guardUserInput,
|
|
1110
|
-
previousSource,
|
|
1111
|
-
nextSource: { code, files },
|
|
1112
|
-
});
|
|
1113
|
-
if (!guardResult.ok) {
|
|
1114
|
-
updateDeployProgress(
|
|
1115
|
-
thunkApi,
|
|
1116
|
-
toolRunId,
|
|
1117
|
-
"prepare",
|
|
1118
|
-
guardResult.summary,
|
|
1119
|
-
"failed",
|
|
1120
|
-
"ๆฃๆตๅฐๅฐ่ง่งไฟฎๆน่ถ
ๅบ่ๅด๏ผ่ฆๆฑๅ
ๆถๆๆนๅจ"
|
|
1121
|
-
);
|
|
1122
|
-
throw new ToolResultError(guardResult.summary, {
|
|
1123
|
-
code: guardResult.rawData.code,
|
|
1124
|
-
rawData: guardResult.rawData,
|
|
1125
|
-
displayData: guardResult.displayData,
|
|
1126
|
-
retryable: true,
|
|
1127
|
-
});
|
|
1128
|
-
}
|
|
1129
|
-
} catch (error: any) {
|
|
1130
|
-
if (
|
|
1131
|
-
error instanceof ToolResultError ||
|
|
1132
|
-
error?.name === "ToolResultError" ||
|
|
1133
|
-
error?.code === "SMALL_VISUAL_SCOPE_EXCEEDED"
|
|
1134
|
-
) {
|
|
1135
|
-
throw error;
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
let preflightData: AppPreflightResult;
|
|
1141
|
-
try {
|
|
1142
|
-
preflightData = await callToolApi<AppPreflightResult>(
|
|
1143
|
-
thunkApi,
|
|
1144
|
-
"/api/app/preflight",
|
|
1145
|
-
{
|
|
1146
|
-
name,
|
|
1147
|
-
code,
|
|
1148
|
-
files,
|
|
1149
|
-
appId,
|
|
1150
|
-
framework,
|
|
1151
|
-
...(deploySpaceId ? { spaceId: deploySpaceId } : {}),
|
|
1152
|
-
},
|
|
1153
|
-
{ withAuth: true }
|
|
1154
|
-
);
|
|
1155
|
-
} catch (error: any) {
|
|
1156
|
-
if (isTransportStoplossError(error)) {
|
|
1157
|
-
const payload = buildAppStoplossPayload({
|
|
1158
|
-
summary: "้ขๆฃๆฅๅฃ่ฟๅไบๅผๅธธๅๅบ๏ผๆๆถๆ ๆณๅคๆญไปฃ็ ้ฎ้ขใ",
|
|
1159
|
-
framework: framework ?? "worker",
|
|
1160
|
-
stage: "preflight",
|
|
1161
|
-
error,
|
|
1162
|
-
});
|
|
1163
|
-
const displayMessage = formatStoplossPlan(payload);
|
|
1164
|
-
updateDeployProgress(
|
|
1165
|
-
thunkApi,
|
|
1166
|
-
toolRunId,
|
|
1167
|
-
"preflight",
|
|
1168
|
-
displayMessage,
|
|
1169
|
-
"failed",
|
|
1170
|
-
"ๆฃๆตๅฐ้ขๆฃ้้ๅผๅธธ๏ผๅทฒๅๆญข่ชๅจ้่ฏ"
|
|
1171
|
-
);
|
|
1172
|
-
throw new ToolResultError(payload.summary, {
|
|
1173
|
-
code: payload.code,
|
|
1174
|
-
rawData: payload,
|
|
1175
|
-
displayData: displayMessage,
|
|
1176
|
-
retryable: false,
|
|
1177
|
-
});
|
|
1178
|
-
}
|
|
1179
|
-
const rewritten = rewriteAppDeployError(error?.message || String(error), args);
|
|
1180
|
-
const issues = (error?.details as { issues?: AppPreflightIssue[] } | undefined)?.issues ?? [];
|
|
1181
|
-
const repairPayload = buildAppRepairPayload({
|
|
1182
|
-
summary: rewritten,
|
|
1183
|
-
framework: framework ?? "worker",
|
|
1184
|
-
issues,
|
|
1185
|
-
});
|
|
1186
|
-
const displayMessage = [
|
|
1187
|
-
rewritten,
|
|
1188
|
-
formatPreflightIssues(issues),
|
|
1189
|
-
formatRepairPlan(repairPayload.repairPlan),
|
|
1190
|
-
]
|
|
1191
|
-
.filter(Boolean)
|
|
1192
|
-
.join("\n");
|
|
1193
|
-
updateDeployProgress(
|
|
1194
|
-
thunkApi,
|
|
1195
|
-
toolRunId,
|
|
1196
|
-
"preflight",
|
|
1197
|
-
displayMessage,
|
|
1198
|
-
"failed",
|
|
1199
|
-
"้ขๆฃๆฅๅฃๆง่กๅคฑ่ดฅ"
|
|
1200
|
-
);
|
|
1201
|
-
throw new ToolResultError(rewritten, {
|
|
1202
|
-
code: error?.code ?? repairPayload.code,
|
|
1203
|
-
rawData: repairPayload,
|
|
1204
|
-
displayData: displayMessage,
|
|
1205
|
-
retryable: true,
|
|
1206
|
-
});
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
if (!preflightData.ok) {
|
|
1210
|
-
const repairPayload = buildAppRepairPayload({
|
|
1211
|
-
summary: preflightData.summary,
|
|
1212
|
-
framework: preflightData.framework,
|
|
1213
|
-
issues: preflightData.issues,
|
|
1214
|
-
warnings: preflightData.warnings,
|
|
1215
|
-
entryFile: preflightData.entryFile,
|
|
1216
|
-
externalImports: preflightData.externalImports,
|
|
1217
|
-
});
|
|
1218
|
-
const displayMessage = [
|
|
1219
|
-
preflightData.summary,
|
|
1220
|
-
formatPreflightIssues(preflightData.issues),
|
|
1221
|
-
formatRepairPlan(repairPayload.repairPlan),
|
|
1222
|
-
]
|
|
1223
|
-
.filter(Boolean)
|
|
1224
|
-
.join("\n");
|
|
1225
|
-
updateDeployProgress(
|
|
1226
|
-
thunkApi,
|
|
1227
|
-
toolRunId,
|
|
1228
|
-
"preflight",
|
|
1229
|
-
displayMessage,
|
|
1230
|
-
"failed",
|
|
1231
|
-
"่ฏทๅ
ไฟฎๅค้ขๆฃ้ฎ้ข๏ผๅ้ๆฐ้จ็ฝฒ"
|
|
1232
|
-
);
|
|
1233
|
-
throw new ToolResultError(preflightData.summary, {
|
|
1234
|
-
code: "PREFLIGHT_FAILED",
|
|
1235
|
-
rawData: repairPayload,
|
|
1236
|
-
displayData: displayMessage,
|
|
1237
|
-
retryable: true,
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
updateDeployProgress(
|
|
1242
|
-
thunkApi,
|
|
1243
|
-
toolRunId,
|
|
1244
|
-
"preflight",
|
|
1245
|
-
preflightData.summary || "้ขๆฃ้่ฟ",
|
|
1246
|
-
"succeeded",
|
|
1247
|
-
preflightData.entryFile
|
|
1248
|
-
? `ๅ
ฅๅฃๆไปถ๏ผ${preflightData.entryFile}`
|
|
1249
|
-
: framework === "react-spa"
|
|
1250
|
-
? "React SPA ็บฆๆๆฃๆฅ้่ฟ"
|
|
1251
|
-
: "Worker ็บฆๆๆฃๆฅ้่ฟ"
|
|
1252
|
-
);
|
|
1253
|
-
|
|
1254
|
-
let startData: AppDeployStartResult;
|
|
1255
|
-
try {
|
|
1256
|
-
startData = await callToolApi<AppDeployStartResult>(
|
|
1257
|
-
thunkApi,
|
|
1258
|
-
"/api/app/deploy",
|
|
1259
|
-
{
|
|
1260
|
-
name,
|
|
1261
|
-
code,
|
|
1262
|
-
files,
|
|
1263
|
-
appId,
|
|
1264
|
-
framework,
|
|
1265
|
-
...(deploySpaceId ? { spaceId: deploySpaceId } : {}),
|
|
1266
|
-
},
|
|
1267
|
-
{ withAuth: true }
|
|
1268
|
-
);
|
|
1269
|
-
} catch (error: any) {
|
|
1270
|
-
if (isTransportStoplossError(error)) {
|
|
1271
|
-
const payload = buildAppStoplossPayload({
|
|
1272
|
-
summary: "้จ็ฝฒๆฅๅฃ่ฟๅไบๅผๅธธๅๅบ๏ผๅฝๅไธ่ฝ็ปง็ปญ่ชๅจ้จ็ฝฒใ",
|
|
1273
|
-
framework: framework ?? "worker",
|
|
1274
|
-
stage: "deploy",
|
|
1275
|
-
error,
|
|
1276
|
-
});
|
|
1277
|
-
const displayMessage = formatStoplossPlan(payload);
|
|
1278
|
-
updateDeployProgress(
|
|
1279
|
-
thunkApi,
|
|
1280
|
-
toolRunId,
|
|
1281
|
-
framework === "react-spa" ? "build" : "prepare",
|
|
1282
|
-
displayMessage,
|
|
1283
|
-
"failed",
|
|
1284
|
-
"ๆฃๆตๅฐ้จ็ฝฒ้้ๅผๅธธ๏ผๅทฒๅๆญข่ชๅจ้่ฏ"
|
|
1285
|
-
);
|
|
1286
|
-
throw new ToolResultError(payload.summary, {
|
|
1287
|
-
code: payload.code,
|
|
1288
|
-
rawData: payload,
|
|
1289
|
-
displayData: displayMessage,
|
|
1290
|
-
retryable: false,
|
|
1291
|
-
});
|
|
1292
|
-
}
|
|
1293
|
-
const rewritten = rewriteAppDeployError(error?.message || String(error), args);
|
|
1294
|
-
const issues = (error?.details as { issues?: AppPreflightIssue[] } | undefined)?.issues ?? [];
|
|
1295
|
-
const repairPayload = buildAppRepairPayload({
|
|
1296
|
-
summary: rewritten,
|
|
1297
|
-
framework: framework ?? "worker",
|
|
1298
|
-
issues,
|
|
1299
|
-
});
|
|
1300
|
-
const displayMessage = [
|
|
1301
|
-
rewritten,
|
|
1302
|
-
formatPreflightIssues(issues),
|
|
1303
|
-
formatRepairPlan(repairPayload.repairPlan),
|
|
1304
|
-
]
|
|
1305
|
-
.filter(Boolean)
|
|
1306
|
-
.join("\n");
|
|
1307
|
-
updateDeployProgress(
|
|
1308
|
-
thunkApi,
|
|
1309
|
-
toolRunId,
|
|
1310
|
-
framework === "react-spa" ? "build" : "prepare",
|
|
1311
|
-
displayMessage,
|
|
1312
|
-
"failed",
|
|
1313
|
-
"่ฏทๆ นๆฎๆ็คบ่ฐๆดๅๆฐๆไปฃ็ ๅ้่ฏ"
|
|
1314
|
-
);
|
|
1315
|
-
throw new ToolResultError(rewritten, {
|
|
1316
|
-
code: error?.code ?? repairPayload.code,
|
|
1317
|
-
rawData: repairPayload,
|
|
1318
|
-
displayData: displayMessage,
|
|
1319
|
-
retryable: true,
|
|
1320
|
-
});
|
|
1321
|
-
}
|
|
1322
|
-
|
|
1323
|
-
updateDeployProgress(
|
|
1324
|
-
thunkApi,
|
|
1325
|
-
toolRunId,
|
|
1326
|
-
startData.steps ?? "prepare",
|
|
1327
|
-
startData.summary ?? "้จ็ฝฒ่ฏทๆฑๅทฒๅ้ๅฐๆๅก็ซฏโฆ",
|
|
1328
|
-
"running"
|
|
1329
|
-
);
|
|
1330
|
-
const sharedState = {
|
|
1331
|
-
done: false,
|
|
1332
|
-
result: undefined as AppDeployApiResult | undefined,
|
|
1333
|
-
failure: undefined as Error | undefined,
|
|
1334
|
-
error: undefined as string | undefined,
|
|
1335
|
-
lastSteps: Array.isArray(startData.steps) ? startData.steps : [],
|
|
1336
|
-
};
|
|
1337
|
-
const ssePromise = startData.eventChannel
|
|
1338
|
-
? subscribeToDeployEvents({
|
|
1339
|
-
thunkApi,
|
|
1340
|
-
deployArgs: args,
|
|
1341
|
-
toolRunId,
|
|
1342
|
-
jobId: startData.jobId,
|
|
1343
|
-
eventChannel: startData.eventChannel,
|
|
1344
|
-
sharedState,
|
|
1345
|
-
}).catch(() => {
|
|
1346
|
-
// SSE ไป
ไฝไธบๅ ้้้๏ผๅคฑ่ดฅๅ็ฑ่ฝฎ่ฏขๅ
ๅบ
|
|
1347
|
-
})
|
|
1348
|
-
: Promise.resolve();
|
|
1349
|
-
|
|
1350
|
-
const data = await pollAppDeployJob(thunkApi, args, toolRunId, startData.jobId, {
|
|
1351
|
-
sharedState,
|
|
1352
|
-
});
|
|
1353
|
-
void ssePromise;
|
|
1354
|
-
const primaryUrl = data.customUrl ?? data.url;
|
|
1355
|
-
const previewCheck = data.previewCheck;
|
|
1356
|
-
const previewReady = data.previewReady ?? previewCheck?.ready;
|
|
1357
|
-
|
|
1358
|
-
// ้จ็ฝฒๆๅๅๅฐ appRecord ๅๆญฅๅฐๆฌๅฐ DB ๅๆๆ syncServers
|
|
1359
|
-
if (data.appKey && data.appRecord) {
|
|
1360
|
-
void thunkApi.dispatch(syncAppRecord(data.appKey, data.appRecord));
|
|
1361
|
-
}
|
|
1362
|
-
|
|
1363
|
-
const lines = [
|
|
1364
|
-
`๐ ๅบ็จ้จ็ฝฒๆๅ๏ผ`,
|
|
1365
|
-
`- ๅ็งฐ: ${data.userFriendlyName}`,
|
|
1366
|
-
...(data.appId ? [`- appId: ${data.appId}`] : []),
|
|
1367
|
-
`- ่ฎฟ้ฎๅฐๅ: ${primaryUrl}`,
|
|
1368
|
-
`- ๆดๆฐๆถ้ด: ${data.modifiedOn ?? "ๅๅ"}`,
|
|
1369
|
-
];
|
|
1370
|
-
|
|
1371
|
-
if (data.bundleWarnings?.length) {
|
|
1372
|
-
lines.push(`\nโ ๏ธ ๆๅ
่ญฆๅ:\n${data.bundleWarnings.join("\n")}`);
|
|
1373
|
-
}
|
|
1374
|
-
if (previewCheck?.attempted && previewReady === false) {
|
|
1375
|
-
lines.push("\nโณ ็ซ็นๅทฒๅๅธ๏ผไฝ้ฆๆฌกๅ ่ฝฝๅฏ่ฝ็จๆ
ข๏ผ่ๅคฉๅก็้ไผ็ปง็ปญๆพ็คบ้ข่งๅ ่ฝฝ็ถๆใ");
|
|
1376
|
-
}
|
|
1377
|
-
lines.push(`\nๅฏไปฅ็ดๆฅ่ฎฟ้ฎ ${primaryUrl} ๆต่ฏๆๆใ`);
|
|
1378
|
-
|
|
1379
|
-
return {
|
|
1380
|
-
rawData: { ...data, appUrl: primaryUrl, previewCheck },
|
|
1381
|
-
displayData: lines.join("\n"),
|
|
1382
|
-
};
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1386
|
-
// appList โ ๅๅบ็จๆทๅทฒ้จ็ฝฒ็ๆๆๅบ็จ
|
|
1387
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1388
|
-
export const appListFunctionSchema = {
|
|
1389
|
-
name: "appList",
|
|
1390
|
-
description: "ๅๅบๅบ็จๅ่กจใไธไผ spaceId ๆถๅๅบๅฝๅ็จๆท่ชๅทฑ็ๅบ็จ๏ผไผ ๅ
ฅ spaceId ๆถๅๅบ่ฏฅ Space ไธ็ๅบ็จใ",
|
|
1391
|
-
parameters: {
|
|
1392
|
-
type: "object",
|
|
1393
|
-
properties: {
|
|
1394
|
-
spaceId: {
|
|
1395
|
-
type: "string",
|
|
1396
|
-
description: "ๅฏ้ใ่ฅๆไพ๏ผๅๅชๅๅบ่ฏฅ Space ไธ็ๅบ็จใ",
|
|
1397
|
-
},
|
|
1398
|
-
},
|
|
1399
|
-
},
|
|
1400
|
-
};
|
|
1401
|
-
|
|
1402
|
-
export async function appListFunc(
|
|
1403
|
-
args: { spaceId?: string },
|
|
1404
|
-
thunkApi: any
|
|
1405
|
-
): Promise<{ rawData: any; displayData: string }> {
|
|
1406
|
-
const data = await callToolApi<{
|
|
1407
|
-
success: boolean;
|
|
1408
|
-
workers: Array<{
|
|
1409
|
-
userFriendlyName: string;
|
|
1410
|
-
url: string;
|
|
1411
|
-
customUrl?: string;
|
|
1412
|
-
appId?: string;
|
|
1413
|
-
modifiedOn: string;
|
|
1414
|
-
}>;
|
|
1415
|
-
}>(thunkApi, "/api/app/list", args?.spaceId ? { spaceId: args.spaceId } : {}, { withAuth: true });
|
|
1416
|
-
|
|
1417
|
-
if (!data.workers.length) {
|
|
1418
|
-
return {
|
|
1419
|
-
rawData: data,
|
|
1420
|
-
displayData: "๐ญ ไฝ ่ฟๆฒกๆ้จ็ฝฒไปปไฝๅบ็จใ",
|
|
1421
|
-
};
|
|
1422
|
-
}
|
|
1423
|
-
|
|
1424
|
-
const list = data.workers
|
|
1425
|
-
.map((w) => {
|
|
1426
|
-
const url = w.customUrl ?? w.url;
|
|
1427
|
-
const id = w.appId ? ` (appId: ${w.appId})` : "";
|
|
1428
|
-
return `- **${w.userFriendlyName}**${id}: ${url} (ๆดๆฐ: ${w.modifiedOn?.slice(0, 10) ?? "-"})`;
|
|
1429
|
-
})
|
|
1430
|
-
.join("\n");
|
|
1431
|
-
|
|
1432
|
-
return {
|
|
1433
|
-
rawData: data,
|
|
1434
|
-
displayData: `๐ ๅทฒ้จ็ฝฒ็ๅบ็จ (${data.workers.length} ไธช):\n${list}`,
|
|
1435
|
-
};
|
|
1436
|
-
}
|
|
1437
|
-
|
|
1438
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1439
|
-
// appDelete โ ๅ ้คไธไธชๅบ็จ
|
|
1440
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1441
|
-
export const appDeleteFunctionSchema = {
|
|
1442
|
-
name: "appDelete",
|
|
1443
|
-
description: "ๅ ้คไธไธชๅทฒ้จ็ฝฒ็ๅบ็จใๅ ้คๅ URL ็ซๅณๅคฑๆ๏ผไธๅฏๆขๅคใ",
|
|
1444
|
-
parameters: {
|
|
1445
|
-
type: "object",
|
|
1446
|
-
properties: {
|
|
1447
|
-
appId: {
|
|
1448
|
-
type: "string",
|
|
1449
|
-
description: "ๅบ็จ IDใๅฟ
้กปๅ
็จ appList / appDeploy / appRead ๆฟๅฐๅฎ๏ผๅๆ appId ๅ ้คใ",
|
|
1450
|
-
},
|
|
1451
|
-
},
|
|
1452
|
-
required: ["appId"],
|
|
1453
|
-
},
|
|
1454
|
-
};
|
|
1455
|
-
|
|
1456
|
-
export async function appDeleteFunc(
|
|
1457
|
-
args: { appId: string },
|
|
1458
|
-
thunkApi: any
|
|
1459
|
-
): Promise<{ rawData: any; displayData: string }> {
|
|
1460
|
-
const { appId } = args;
|
|
1461
|
-
if (!appId) throw new Error("ๅฟ
้กปๆไพ appId ๅๆฐ๏ผ่ฏทๅ
่ฐ็จ appList ๆ appRead ่ทๅ็ฎๆ ๅบ็จ ID");
|
|
1462
|
-
|
|
1463
|
-
// ๅ
่ทๅ appKey๏ผๅ่ตฐๅ
จ server ๅ ้ค่ทฏๅพ
|
|
1464
|
-
const appInfo = await callToolApi<{
|
|
1465
|
-
appKey?: string;
|
|
1466
|
-
appId?: string;
|
|
1467
|
-
name?: string;
|
|
1468
|
-
}>(thunkApi, "/api/app/get", { appId }, { withAuth: true });
|
|
1469
|
-
|
|
1470
|
-
if (!appInfo.appKey) {
|
|
1471
|
-
throw new Error("ๆ ๆณ่งฃๆ appKey๏ผๆ ๆณๆง่ก็ปไธๅ ้ค");
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
await thunkApi.dispatch(deleteDbKey(appInfo.appKey));
|
|
1475
|
-
|
|
1476
|
-
return {
|
|
1477
|
-
rawData: { deleted: true },
|
|
1478
|
-
displayData: `๐๏ธ ๅบ็จ "${appInfo.name ?? appId}" ๅทฒๆๅๅ ้คใ`,
|
|
1479
|
-
};
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1483
|
-
// appRead โ ่ฏปๅๅบ็จๅฝๅไปฃ็ ๏ผ็จไบไฟฎๆนๅ่ทๅ็ฐๆๅ
ๅฎน๏ผ
|
|
1484
|
-
// โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
1485
|
-
export const appReadFunctionSchema = {
|
|
1486
|
-
name: "appRead",
|
|
1487
|
-
description:
|
|
1488
|
-
"่ฏปๅๅทฒ้จ็ฝฒๅบ็จ็ๅฝๅไปฃ็ ใๅจไฟฎๆนๅบ็จ๏ผๅขๅ ๅ่ฝใ่ฐๆดๆ ทๅผ็ญ๏ผไนๅ๏ผๅฟ
้กปๅ
่ฐ็จๆญคๅทฅๅ
ท่ทๅ็ฐๆไปฃ็ ๏ผๅๅบไบ็ฐๆไปฃ็ ่ฟ่กไฟฎๆนๅ้ๆฐ้จ็ฝฒใๅฟ
้กปไผ appId๏ผๅฆ่ฟไธ็ฅ้ appId๏ผ่ฏทๅ
่ฐ็จ appListใ",
|
|
1489
|
-
parameters: {
|
|
1490
|
-
type: "object",
|
|
1491
|
-
properties: {
|
|
1492
|
-
appId: {
|
|
1493
|
-
type: "string",
|
|
1494
|
-
description: "ๅบ็จ ID๏ผไป appList ๆไนๅ็ appRead/appDeploy ่ฟๅ็ปๆไธญ่ทๅ๏ผใๆฏ name ๆด็ฒพ็กฎ๏ผๅ็ปญๆดๆฐ/ๅ ้ค้ฝๅบไผๅ
ไฝฟ็จใ",
|
|
1495
|
-
},
|
|
1496
|
-
},
|
|
1497
|
-
required: ["appId"],
|
|
1498
|
-
},
|
|
1499
|
-
};
|
|
1500
|
-
|
|
1501
|
-
export async function appReadFunc(
|
|
1502
|
-
args: { appId: string },
|
|
1503
|
-
thunkApi: any
|
|
1504
|
-
): Promise<{ rawData: any; displayData: string }> {
|
|
1505
|
-
const { appId } = args;
|
|
1506
|
-
if (!appId) throw new Error("ๅฟ
้กปๆไพ appId ๅๆฐ๏ผ่ฏทๅ
่ฐ็จ appList ่ทๅ็ฎๆ ๅบ็จ ID");
|
|
1507
|
-
|
|
1508
|
-
const data = await callToolApi<{
|
|
1509
|
-
success: boolean;
|
|
1510
|
-
appId: string;
|
|
1511
|
-
userFriendlyName: string;
|
|
1512
|
-
url: string;
|
|
1513
|
-
customUrl?: string;
|
|
1514
|
-
code: string;
|
|
1515
|
-
files?: Array<{ name: string; code: string }>;
|
|
1516
|
-
framework?: "worker" | "react-spa";
|
|
1517
|
-
}>(thunkApi, "/api/app/prepare-edit", { appId }, { withAuth: true });
|
|
1518
|
-
|
|
1519
|
-
const primaryUrl = data.customUrl ?? data.url;
|
|
1520
|
-
const displayBody = Array.isArray(data.files) && data.files.length > 0
|
|
1521
|
-
? data.files
|
|
1522
|
-
.map((file) => `### ${file.name}\n\`\`\`${file.name.endsWith(".tsx") || file.name.endsWith(".ts") ? "typescript" : "javascript"}\n${file.code}\n\`\`\``)
|
|
1523
|
-
.join("\n\n")
|
|
1524
|
-
: "```javascript\n" + data.code + "\n```";
|
|
1525
|
-
const snapshotWarning = buildAppReadSnapshotWarning(
|
|
1526
|
-
classifyAppReadSnapshot(data)
|
|
1527
|
-
);
|
|
1528
|
-
const styleSystemAnalysis = analyzeAppStyleSystem(data);
|
|
1529
|
-
const styleSystemHint = buildAppStyleSystemHint(styleSystemAnalysis);
|
|
1530
|
-
|
|
1531
|
-
return {
|
|
1532
|
-
rawData: {
|
|
1533
|
-
...data,
|
|
1534
|
-
styleSystemStatus: styleSystemAnalysis.status,
|
|
1535
|
-
legacyMigrationRecommended:
|
|
1536
|
-
styleSystemAnalysis.legacyMigrationRecommended,
|
|
1537
|
-
styleSystemEvidence: styleSystemAnalysis.evidence,
|
|
1538
|
-
...(styleSystemHint ? { styleSystemHint } : {}),
|
|
1539
|
-
},
|
|
1540
|
-
displayData:
|
|
1541
|
-
`๐ ๅบ็จ "${data.userFriendlyName}" ๅฝๅไปฃ็ ๏ผ\n` +
|
|
1542
|
-
`- appId: ${data.appId}\n` +
|
|
1543
|
-
`- ่ฎฟ้ฎๅฐๅ: ${primaryUrl}\n` +
|
|
1544
|
-
(snapshotWarning ? `\n${snapshotWarning}\n` : "\n") +
|
|
1545
|
-
(styleSystemHint ? `\n${styleSystemHint}\n` : "") +
|
|
1546
|
-
"\n" +
|
|
1547
|
-
displayBody,
|
|
1548
|
-
};
|
|
1549
|
-
}
|