@superblocksteam/vite-plugin-file-sync 2.0.43-next.13 → 2.0.43-next.15
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/ai-service/agent/subagents/apis/api-executor.d.ts +57 -0
- package/dist/ai-service/agent/subagents/apis/api-executor.d.ts.map +1 -0
- package/dist/ai-service/agent/subagents/apis/api-executor.js +284 -0
- package/dist/ai-service/agent/subagents/apis/api-executor.js.map +1 -0
- package/dist/ai-service/agent/subagents/apis/context.d.ts +12 -0
- package/dist/ai-service/agent/subagents/apis/context.d.ts.map +1 -0
- package/dist/ai-service/agent/subagents/apis/context.js +18 -0
- package/dist/ai-service/agent/subagents/apis/context.js.map +1 -0
- package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts +37 -31
- package/dist/ai-service/agent/subagents/apis/generate-api-source.d.ts.map +1 -1
- package/dist/ai-service/agent/subagents/apis/generate-api-source.js +355 -479
- package/dist/ai-service/agent/subagents/apis/generate-api-source.js.map +1 -1
- package/dist/ai-service/agent/subagents/apis/state.d.ts +40 -0
- package/dist/ai-service/agent/subagents/apis/state.d.ts.map +1 -0
- package/dist/ai-service/agent/subagents/apis/state.js +25 -0
- package/dist/ai-service/agent/subagents/apis/state.js.map +1 -0
- package/dist/ai-service/agent/subagents/apis/types.d.ts +5 -0
- package/dist/ai-service/agent/subagents/apis/types.d.ts.map +1 -0
- package/dist/ai-service/agent/subagents/apis/types.js +2 -0
- package/dist/ai-service/agent/subagents/apis/types.js.map +1 -0
- package/dist/ai-service/agent/tool-message-utils.d.ts.map +1 -1
- package/dist/ai-service/agent/tool-message-utils.js +8 -24
- package/dist/ai-service/agent/tool-message-utils.js.map +1 -1
- package/dist/ai-service/agent/tools/apis/build-api.d.ts +20 -0
- package/dist/ai-service/agent/tools/apis/build-api.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/build-api.js +168 -0
- package/dist/ai-service/agent/tools/apis/build-api.js.map +1 -0
- package/dist/ai-service/agent/tools/apis/finalize-api.d.ts +15 -0
- package/dist/ai-service/agent/tools/apis/finalize-api.d.ts.map +1 -0
- package/dist/ai-service/agent/tools/apis/finalize-api.js +103 -0
- package/dist/ai-service/agent/tools/apis/finalize-api.js.map +1 -0
- package/dist/ai-service/agent/tools/build-finalize.d.ts +1 -22
- package/dist/ai-service/agent/tools/build-finalize.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/build-finalize.js +27 -18
- package/dist/ai-service/agent/tools/build-finalize.js.map +1 -1
- package/dist/ai-service/agent/tools/integrations/execute-request.d.ts +1 -1
- package/dist/ai-service/agent/tools/integrations/execute-request.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/integrations/index.d.ts +1 -1
- package/dist/ai-service/agent/tools/integrations/index.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/integrations/index.js +1 -1
- package/dist/ai-service/agent/tools/integrations/index.js.map +1 -1
- package/dist/ai-service/agent/tools/integrations/internal.d.ts +1 -1
- package/dist/ai-service/agent/tools/integrations/internal.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/integrations/internal.js +12 -1
- package/dist/ai-service/agent/tools/integrations/internal.js.map +1 -1
- package/dist/ai-service/agent/tools/integrations/metadata.d.ts +1 -1
- package/dist/ai-service/agent/tools/integrations/metadata.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/integrations/metadata.js +1 -1
- package/dist/ai-service/agent/tools/integrations/metadata.js.map +1 -1
- package/dist/ai-service/agent/tools/integrations/run-code.d.ts +1 -1
- package/dist/ai-service/agent/tools/integrations/run-code.d.ts.map +1 -1
- package/dist/ai-service/agent/tools/study-current-app-state.d.ts +1 -0
- package/dist/ai-service/agent/tools/study-current-app-state.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/access-control.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/access-control.js +5 -2
- package/dist/ai-service/agent/tools2/access-control.js.map +1 -1
- package/dist/ai-service/agent/tools2/registry.d.ts +2 -1
- package/dist/ai-service/agent/tools2/registry.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/registry.js +4 -4
- package/dist/ai-service/agent/tools2/registry.js.map +1 -1
- package/dist/ai-service/agent/tools2/types.d.ts +17 -3
- package/dist/ai-service/agent/tools2/types.d.ts.map +1 -1
- package/dist/ai-service/agent/tools2/types.js +21 -0
- package/dist/ai-service/agent/tools2/types.js.map +1 -1
- package/dist/ai-service/agent/utils.d.ts +1 -0
- package/dist/ai-service/agent/utils.d.ts.map +1 -1
- package/dist/ai-service/agent/utils.js +1 -0
- package/dist/ai-service/agent/utils.js.map +1 -1
- package/dist/ai-service/integrations/metadata/database.d.ts.map +1 -1
- package/dist/ai-service/integrations/metadata/database.js +61 -20
- package/dist/ai-service/integrations/metadata/database.js.map +1 -1
- package/dist/ai-service/integrations/metadata/databricks.d.ts.map +1 -1
- package/dist/ai-service/integrations/metadata/databricks.js +5 -5
- package/dist/ai-service/integrations/metadata/databricks.js.map +1 -1
- package/dist/ai-service/integrations/metadata/graphql-based.d.ts +2 -0
- package/dist/ai-service/integrations/metadata/graphql-based.d.ts.map +1 -1
- package/dist/ai-service/integrations/metadata/graphql-based.js +95 -14
- package/dist/ai-service/integrations/metadata/graphql-based.js.map +1 -1
- package/dist/ai-service/integrations/metadata/llm-utils.d.ts +24 -0
- package/dist/ai-service/integrations/metadata/llm-utils.d.ts.map +1 -0
- package/dist/ai-service/integrations/metadata/llm-utils.js +45 -0
- package/dist/ai-service/integrations/metadata/llm-utils.js.map +1 -0
- package/dist/ai-service/integrations/store.d.ts +5 -5
- package/dist/ai-service/integrations/store.d.ts.map +1 -1
- package/dist/ai-service/integrations/store.js +52 -53
- package/dist/ai-service/integrations/store.js.map +1 -1
- package/dist/ai-service/llm/context/constants.d.ts +7 -6
- package/dist/ai-service/llm/context/constants.d.ts.map +1 -1
- package/dist/ai-service/llm/context/constants.js +7 -6
- package/dist/ai-service/llm/context/constants.js.map +1 -1
- package/dist/ai-service/llm/context/context-handle.d.ts +106 -0
- package/dist/ai-service/llm/context/context-handle.d.ts.map +1 -0
- package/dist/ai-service/llm/context/context-handle.js +134 -0
- package/dist/ai-service/llm/context/context-handle.js.map +1 -0
- package/dist/ai-service/llm/context/context-lock.d.ts +144 -0
- package/dist/ai-service/llm/context/context-lock.d.ts.map +1 -0
- package/dist/ai-service/llm/context/context-lock.js +221 -0
- package/dist/ai-service/llm/context/context-lock.js.map +1 -0
- package/dist/ai-service/llm/context/context.d.ts +18 -19
- package/dist/ai-service/llm/context/context.d.ts.map +1 -1
- package/dist/ai-service/llm/context/context.js +78 -129
- package/dist/ai-service/llm/context/context.js.map +1 -1
- package/dist/ai-service/llm/context/index.d.ts +4 -0
- package/dist/ai-service/llm/context/index.d.ts.map +1 -1
- package/dist/ai-service/llm/context/index.js +5 -0
- package/dist/ai-service/llm/context/index.js.map +1 -1
- package/dist/ai-service/llm/context/internal-types.d.ts +0 -2
- package/dist/ai-service/llm/context/internal-types.d.ts.map +1 -1
- package/dist/ai-service/llm/context/internal-types.js.map +1 -1
- package/dist/ai-service/llm/context/levels/l1.d.ts.map +1 -1
- package/dist/ai-service/llm/context/levels/l1.js +3 -5
- package/dist/ai-service/llm/context/levels/l1.js.map +1 -1
- package/dist/ai-service/llm/context/manager.d.ts +60 -11
- package/dist/ai-service/llm/context/manager.d.ts.map +1 -1
- package/dist/ai-service/llm/context/manager.js +113 -37
- package/dist/ai-service/llm/context/manager.js.map +1 -1
- package/dist/ai-service/llm/context/utils/content-compaction.d.ts +2 -2
- package/dist/ai-service/llm/context/utils/content-compaction.d.ts.map +1 -1
- package/dist/ai-service/llm/context/utils/content-compaction.js +6 -3
- package/dist/ai-service/llm/context/utils/content-compaction.js.map +1 -1
- package/dist/ai-service/llm/context/utils/index.d.ts +1 -1
- package/dist/ai-service/llm/context/utils/index.d.ts.map +1 -1
- package/dist/ai-service/llm/context/utils/index.js +1 -1
- package/dist/ai-service/llm/context/utils/index.js.map +1 -1
- package/dist/ai-service/llm/context/utils/message-utils.d.ts +17 -7
- package/dist/ai-service/llm/context/utils/message-utils.d.ts.map +1 -1
- package/dist/ai-service/llm/context/utils/message-utils.js +31 -18
- package/dist/ai-service/llm/context/utils/message-utils.js.map +1 -1
- package/dist/ai-service/llmobs/middleware/stream-text.d.ts.map +1 -1
- package/dist/ai-service/llmobs/middleware/stream-text.js +1 -0
- package/dist/ai-service/llmobs/middleware/stream-text.js.map +1 -1
- package/dist/ai-service/llmobs/tracer.d.ts +4 -0
- package/dist/ai-service/llmobs/tracer.d.ts.map +1 -1
- package/dist/ai-service/llmobs/tracer.js +11 -0
- package/dist/ai-service/llmobs/tracer.js.map +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ButtonPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/CheckboxPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ColumnPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ContainerPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/DatePickerPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/DropdownPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/IconPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ImagePropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/InputPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/ModalPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/PagePropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/SectionPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/SlideoutPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/SwitchPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/TablePropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-components/TextPropsDocs.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-typedefs/Dim.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-typedefs/EventFlow.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/library-typedefs/TextStyleWithVariant.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/full-examples.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-api.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-components-rules.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-custom-components.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-data-filtering.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-event-flow.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-forms.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-layouts.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-page.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-rbac.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-routes.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-state.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/superblocks-theming-chakra-new.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/system-base.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/system-incremental.js +1 -1
- package/dist/ai-service/prompt-builder-service/static-fragments/platform-parts/system-specific-edit.js +1 -1
- package/dist/ai-service/state-machine/clark-fsm.d.ts +2 -0
- package/dist/ai-service/state-machine/clark-fsm.d.ts.map +1 -1
- package/dist/ai-service/state-machine/clark-fsm.js.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.d.ts.map +1 -1
- package/dist/ai-service/state-machine/handlers/llm-generating.js +363 -336
- package/dist/ai-service/state-machine/handlers/llm-generating.js.map +1 -1
- package/dist/ai-service/util/stop-condition.d.ts +4 -1
- package/dist/ai-service/util/stop-condition.d.ts.map +1 -1
- package/dist/ai-service/util/stop-condition.js +14 -2
- package/dist/ai-service/util/stop-condition.js.map +1 -1
- package/dist/sync-service/download.d.ts.map +1 -1
- package/dist/sync-service/download.js +28 -7
- package/dist/sync-service/download.js.map +1 -1
- package/dist/util/logger.d.ts +13 -0
- package/dist/util/logger.d.ts.map +1 -1
- package/dist/util/logger.js +21 -0
- package/dist/util/logger.js.map +1 -1
- package/package.json +11 -9
- package/dist/ai-service/llm/context/logger.d.ts +0 -17
- package/dist/ai-service/llm/context/logger.d.ts.map +0 -1
- package/dist/ai-service/llm/context/logger.js +0 -26
- package/dist/ai-service/llm/context/logger.js.map +0 -1
|
@@ -1,198 +1,35 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { smoothStream } from "ai";
|
|
4
4
|
import z from "zod";
|
|
5
|
-
import { getErrorMeta, getLogger } from "../../../../util/logger.js";
|
|
5
|
+
import { getErrorMeta, getLogger, getPrefixedLogger, } from "../../../../util/logger.js";
|
|
6
6
|
import { datasourceSdkClassByType, Paths } from "../../../const.js";
|
|
7
7
|
import { tracedStreamText } from "../../../llmobs/helpers.js";
|
|
8
8
|
import { getContextId } from "../../../state-machine/helpers/context-id.js";
|
|
9
|
-
import { ApiBuilderTypeScriptError } from "../../../transform/api-builder/shared.js";
|
|
10
9
|
import { YamlToApiBuilderTransformer } from "../../../transform/api-builder/to-sdk-transformer.js";
|
|
11
|
-
import { ApiBuilderToYamlTransformer } from "../../../transform/api-builder/to-yaml-transformer.js";
|
|
12
10
|
import { applyFileTransformations, renderPath, } from "../../../transform/shared.js";
|
|
13
11
|
import { processLLMConfig } from "../../../util/llm-config-utils.js";
|
|
12
|
+
import { safeJsonStringify } from "../../../util/safe-stringify.js";
|
|
13
|
+
import { hasToolSuccess } from "../../../util/stop-condition.js";
|
|
14
14
|
import { getToolCallArguments } from "../../tool-message-utils.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
15
|
+
import { buildApiToolFactory } from "../../tools/apis/build-api.js";
|
|
16
|
+
import { finalizeApiToolFactory } from "../../tools/apis/finalize-api.js";
|
|
17
|
+
import { executeRequestToIntegrationToolFactory, searchIntegrationsToolFactory, readIntegrationMetadataToolFactory, } from "../../tools/index.js";
|
|
18
|
+
import { getPageEntitiesFiltered, processStreamChunk } from "../../utils.js";
|
|
17
19
|
import { createToolFactory } from "./../../tools2/types.js";
|
|
20
|
+
import { ApiGenerationContext } from "./context.js";
|
|
18
21
|
import { selectExamplesByTags, formatSelectedExamples, } from "./example-selector.js";
|
|
19
22
|
import { VALID_TAGS } from "./examples.js";
|
|
20
23
|
import { buildApiPrompt } from "./prompt-builder.js";
|
|
21
|
-
import {
|
|
24
|
+
import { ApiGenerationStateMap } from "./state.js";
|
|
22
25
|
import systemPrompt from "./system-prompt.js";
|
|
23
|
-
export const buildApiTools = (
|
|
24
|
-
// TODO(colin): find a better way to do this
|
|
25
|
-
onFinalized) => {
|
|
26
|
-
const { apiName, pageName, prompt } = input;
|
|
27
|
-
const integrationById = new Map();
|
|
28
|
-
let apiYaml;
|
|
29
|
-
let buildApiAttempts = 0;
|
|
30
|
-
for (const integration of promptContext?.integrations ?? []) {
|
|
31
|
-
integrationById.set(integration.id, integration);
|
|
32
|
-
}
|
|
33
|
-
const readIntegrationMetadata = tool({
|
|
34
|
-
description: "Read the metadata for a given integration configuration ID. REQUIRED before using database integrations (PostgreSQL, MySQL, Databricks, Snowflake, etc.) to get the correct schema/table structure. Call this first when working with any integration to avoid making up column names or table structures.",
|
|
35
|
-
inputSchema: z.object({ integrationId: z.string() }),
|
|
36
|
-
execute: async ({ integrationId }) => {
|
|
37
|
-
const integration = integrationById.get(integrationId);
|
|
38
|
-
if (!integration) {
|
|
39
|
-
throw new Error(`Integration with ID ${integrationId} not found`);
|
|
40
|
-
}
|
|
41
|
-
const integrationWithOptimizedMetadata = await services.integrationStore.getIntegrationForPromptContext(integration, prompt, clark, services);
|
|
42
|
-
return integrationWithOptimizedMetadata?.metadata ?? {};
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
const fetchIntegration = tool({
|
|
46
|
-
description: "Fetch the integration configuration for a given integration ID",
|
|
47
|
-
inputSchema: z.object({ integrationId: z.string() }),
|
|
48
|
-
execute: async ({ integrationId }) => {
|
|
49
|
-
const integration = await clark.context.peer?.call.aiGetIntegration({
|
|
50
|
-
integrationId,
|
|
51
|
-
});
|
|
52
|
-
if (integration) {
|
|
53
|
-
const existing = integrationById.get(integrationId);
|
|
54
|
-
const mergedMetadata = {
|
|
55
|
-
...(integration?.metadata ?? {}),
|
|
56
|
-
...(existing?.metadata ?? {}),
|
|
57
|
-
};
|
|
58
|
-
integrationById.set(integrationId, {
|
|
59
|
-
...integration,
|
|
60
|
-
metadata: mergedMetadata,
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
return integration;
|
|
64
|
-
},
|
|
65
|
-
});
|
|
66
|
-
const buildApi = tool({
|
|
67
|
-
description: "Compile the API source code.",
|
|
68
|
-
inputSchema: z.object({
|
|
69
|
-
apiSource: z.string().describe("The source code of the API"),
|
|
70
|
-
apiName: z.string().describe("The name of the API"),
|
|
71
|
-
}),
|
|
72
|
-
execute: async ({ apiSource }) => {
|
|
73
|
-
buildApiAttempts++;
|
|
74
|
-
if (buildApiAttempts > 5) {
|
|
75
|
-
throw new Error("Fatal error: Too many attempts to build the API");
|
|
76
|
-
}
|
|
77
|
-
const generatedArtifact = {
|
|
78
|
-
type: "file",
|
|
79
|
-
filePath: renderPath(Paths.GeneratedApis, {
|
|
80
|
-
pageName,
|
|
81
|
-
apiName,
|
|
82
|
-
}) + ".ts",
|
|
83
|
-
content: apiSource,
|
|
84
|
-
};
|
|
85
|
-
try {
|
|
86
|
-
[apiYaml] = await applyFileTransformations([generatedArtifact], [
|
|
87
|
-
new ApiBuilderToYamlTransformer({
|
|
88
|
-
templateRenderer: services.templateRenderer,
|
|
89
|
-
skipCleanup: true,
|
|
90
|
-
}),
|
|
91
|
-
]);
|
|
92
|
-
// At this point we know the apiSource is valid TypeScript.
|
|
93
|
-
// Now do some static analysis to ensure it's semantically valid
|
|
94
|
-
// We do this against the TS source instead of the YAML because
|
|
95
|
-
// it's easier to provide better errors to the LLM, which is dealing in TS
|
|
96
|
-
const analysisWarnings = apiStaticAnalysis(apiSource);
|
|
97
|
-
if (analysisWarnings.length > 0) {
|
|
98
|
-
throw new Error(`Static analysis detected potential issues in the API:\n\n${analysisWarnings.join("\n\n")}`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
if (error instanceof ApiBuilderTypeScriptError) {
|
|
103
|
-
throw new Error(`There were issues compiling the apiSource to TypeScript. Correct the errors below and try again.
|
|
104
|
-
|
|
105
|
-
${error.message.replace(/src\/to-yaml/g, "")}
|
|
106
|
-
`);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
message: "API compiled successfully",
|
|
114
|
-
apiName,
|
|
115
|
-
pageName,
|
|
116
|
-
};
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
const finalizeApi = tool({
|
|
120
|
-
description: "Finalize. Create a summary of the work completed and a TypeScript interface describing the expected response from the API.",
|
|
121
|
-
inputSchema: z.object({
|
|
122
|
-
responseInterface: z
|
|
123
|
-
.string()
|
|
124
|
-
.describe("A TypeScript interface describing the expected response from the API"),
|
|
125
|
-
inputInterface: z
|
|
126
|
-
.string()
|
|
127
|
-
.describe("A TypeScript interface describing the expected input to the API"),
|
|
128
|
-
summary: z.string().describe("A summary of the API"),
|
|
129
|
-
apiName: z.string().describe("The name of the API"),
|
|
130
|
-
givingUpDueToFatalError: z
|
|
131
|
-
.boolean()
|
|
132
|
-
.optional()
|
|
133
|
-
.describe("Whether to give up due to a fatal error"),
|
|
134
|
-
}),
|
|
135
|
-
execute: async ({ responseInterface, inputInterface, summary, givingUpDueToFatalError, }) => {
|
|
136
|
-
if (givingUpDueToFatalError) {
|
|
137
|
-
const message = "Giving up due to a fatal error. No API was created.";
|
|
138
|
-
onFinalized(message);
|
|
139
|
-
return {
|
|
140
|
-
message,
|
|
141
|
-
apiName,
|
|
142
|
-
pageName,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
if (!apiYaml) {
|
|
146
|
-
throw new Error("Unexpected state: Was the buildApi tool called successfully?");
|
|
147
|
-
}
|
|
148
|
-
if (isNewApi) {
|
|
149
|
-
// if it's a new API, the scope will be touched
|
|
150
|
-
await scopeUpdateQueue.enqueue(async () => {
|
|
151
|
-
await ensureScopeFileDraft({
|
|
152
|
-
identifier: pageName,
|
|
153
|
-
type: "name",
|
|
154
|
-
}, services);
|
|
155
|
-
await services.draftInterface.createDraftFile(apiYaml.filePath, apiYaml.content);
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
await services.draftInterface.createDraftFile(apiYaml.filePath, apiYaml.content);
|
|
160
|
-
}
|
|
161
|
-
let message = `${summary}
|
|
162
|
-
|
|
163
|
-
The API response corresponds to the following TypeScript interface:
|
|
164
|
-
|
|
165
|
-
\`\`\`typescript
|
|
166
|
-
${responseInterface}
|
|
167
|
-
\`\`\`
|
|
168
|
-
|
|
169
|
-
The API input corresponds to the following TypeScript interface:
|
|
170
|
-
|
|
171
|
-
\`\`\`typescript
|
|
172
|
-
${inputInterface}
|
|
173
|
-
\`\`\`
|
|
174
|
-
`;
|
|
175
|
-
if (isNewApi) {
|
|
176
|
-
message = `${message}
|
|
177
|
-
|
|
178
|
-
The ${pageName} scope was updated to include the ${apiName} entity.
|
|
179
|
-
`;
|
|
180
|
-
}
|
|
181
|
-
onFinalized(message);
|
|
182
|
-
return {
|
|
183
|
-
message: summary,
|
|
184
|
-
apiName,
|
|
185
|
-
pageName,
|
|
186
|
-
};
|
|
187
|
-
},
|
|
188
|
-
});
|
|
26
|
+
export const buildApiTools = (clark, services, scopeUpdateQueue) => {
|
|
189
27
|
return {
|
|
190
|
-
readIntegrationMetadata,
|
|
191
|
-
fetchIntegration,
|
|
28
|
+
readIntegrationMetadata: readIntegrationMetadataToolFactory.create(clark, services),
|
|
192
29
|
searchIntegrations: searchIntegrationsToolFactory.create(clark, services),
|
|
193
30
|
executeRequestToIntegration: executeRequestToIntegrationToolFactory.create(clark, services),
|
|
194
|
-
buildApi,
|
|
195
|
-
finalizeApi,
|
|
31
|
+
buildApi: buildApiToolFactory.create(clark, services),
|
|
32
|
+
finalizeApi: finalizeApiToolFactory.create(clark, services, scopeUpdateQueue),
|
|
196
33
|
};
|
|
197
34
|
};
|
|
198
35
|
export const readApiSource = async (pageName, apiName, pageEntityNames, services) => {
|
|
@@ -225,6 +62,7 @@ export const readApiSource = async (pageName, apiName, pageEntityNames, services
|
|
|
225
62
|
return sdkArtifact;
|
|
226
63
|
};
|
|
227
64
|
export const generateApiSourceSubagentToolFactory = createToolFactory("build_generateApiSource", (clark, services, scopeUpdateQueue, promptContext, logRef) => {
|
|
65
|
+
const logger = getPrefixedLogger("[api-subagent]");
|
|
228
66
|
const model = services.llmProvider.modelForClassification("broad_edit");
|
|
229
67
|
const llmConfig = clark.context.llmConfig;
|
|
230
68
|
return {
|
|
@@ -233,8 +71,14 @@ export const generateApiSourceSubagentToolFactory = createToolFactory("build_gen
|
|
|
233
71
|
When calling this tool, analyze the user's requirements and provide 2-4 relevant exampleHints tags.
|
|
234
72
|
`,
|
|
235
73
|
inputSchema: z.object({
|
|
236
|
-
|
|
237
|
-
|
|
74
|
+
id: z
|
|
75
|
+
.object({
|
|
76
|
+
apiName: z.string().describe("The name of the API"),
|
|
77
|
+
pageName: z
|
|
78
|
+
.string()
|
|
79
|
+
.describe("The name of the page the API belongs to"), // this could be an enum from app context
|
|
80
|
+
})
|
|
81
|
+
.describe("The reference ID of the API being finalized"),
|
|
238
82
|
action: z.enum(["create", "edit"]).describe("The action to take"),
|
|
239
83
|
prompt: z
|
|
240
84
|
.string()
|
|
@@ -245,330 +89,362 @@ When calling this tool, analyze the user's requirements and provide 2-4 relevant
|
|
|
245
89
|
.describe(`Optional tags to help select relevant examples to guide the API subagent. Provide 2-4 most relevant tags based on the task requirements.`),
|
|
246
90
|
}),
|
|
247
91
|
execute: async (input) => {
|
|
248
|
-
const {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
const
|
|
252
|
-
const
|
|
253
|
-
const existingSdkApiArtifact = await readApiSource(pageName, apiName, pageEntityNames, services);
|
|
254
|
-
if (existingSdkApiArtifact) {
|
|
255
|
-
const existingIntegrationIds = services.appContextStore.apiSemanticsByName[apiName]?.blocks
|
|
256
|
-
.map((block) => block.id)
|
|
257
|
-
.filter((id) => id !== undefined) ?? [];
|
|
258
|
-
eligibleIntegrations = existingIntegrationIds
|
|
259
|
-
.map((id) => promptContext?.integrations?.find((integration) => integration.id === id))
|
|
260
|
-
.filter((x) => x !== undefined);
|
|
261
|
-
const promptContextIntegrationIds = new Set(promptContext?.integrations?.map((integration) => integration.id) ??
|
|
262
|
-
[]);
|
|
263
|
-
missingIntegrationIds = existingIntegrationIds.filter((id) => !promptContextIntegrationIds.has(id));
|
|
264
|
-
}
|
|
265
|
-
else {
|
|
266
|
-
eligibleIntegrations = promptContext?.integrations;
|
|
267
|
-
}
|
|
268
|
-
let finalizedMessage = "";
|
|
269
|
-
const tools = buildApiTools(input, !existingSdkApiArtifact, promptContext, clark, services, scopeUpdateQueue, (message) => {
|
|
270
|
-
finalizedMessage = message;
|
|
271
|
-
});
|
|
272
|
-
// Build API prompt using shared helper
|
|
273
|
-
const apiPrompt = buildApiPrompt({
|
|
274
|
-
apiName,
|
|
275
|
-
userPrompt: prompt,
|
|
276
|
-
pageEntities: pageEntities.map((e) => ({
|
|
277
|
-
name: e.name,
|
|
278
|
-
type: e.type,
|
|
279
|
-
componentType: e.componentType,
|
|
280
|
-
})),
|
|
281
|
-
availableIntegrations: eligibleIntegrations?.map((integration) => ({
|
|
282
|
-
name: integration.name,
|
|
283
|
-
id: integration.id,
|
|
284
|
-
type: datasourceSdkClassByType[integration.type] || integration.type,
|
|
285
|
-
})),
|
|
286
|
-
existingApiSource: existingSdkApiArtifact?.content,
|
|
287
|
-
missingIntegrationIds,
|
|
288
|
-
isEdit: !!existingSdkApiArtifact,
|
|
289
|
-
});
|
|
290
|
-
// Select relevant examples based on hints provided by upstream LLM
|
|
291
|
-
const selectedExampleMetadata = selectExamplesByTags(exampleHints, {
|
|
292
|
-
maxExamples: 6,
|
|
293
|
-
includeNegative: true,
|
|
294
|
-
maxTokenBudget: 7000,
|
|
295
|
-
});
|
|
296
|
-
const examplesContent = formatSelectedExamples(selectedExampleMetadata);
|
|
297
|
-
// Log selected examples for debugging
|
|
298
|
-
if (exampleHints && exampleHints.length > 0) {
|
|
299
|
-
logRef.content += `[EXAMPLE SELECTION] Hints: ${exampleHints.join(", ")}\n`;
|
|
300
|
-
logRef.content += `[EXAMPLE SELECTION] Selected: ${selectedExampleMetadata.map((e) => e.id).join(", ")}\n\n`;
|
|
301
|
-
}
|
|
302
|
-
// Set up context for the API subagent
|
|
303
|
-
const contextId = getContextId(clark, services);
|
|
92
|
+
const { id, prompt, exampleHints } = input;
|
|
93
|
+
const { pageName, apiName } = id;
|
|
94
|
+
// Set up context for the API subagent with thread-safe ownership
|
|
95
|
+
const subagentName = `api-subagent-${pageName}-${apiName}`;
|
|
96
|
+
const contextId = getContextId(clark, services, subagentName);
|
|
304
97
|
const contextOptions = clark.context.llmConfig?.contextOptions;
|
|
305
|
-
|
|
306
|
-
const
|
|
307
|
-
//
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
:
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
context.startTurn({
|
|
316
|
-
role: "user",
|
|
317
|
-
content: apiPrompt,
|
|
98
|
+
// Generate a unique owner ID for this subagent execution
|
|
99
|
+
const ownerId = `${subagentName}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
100
|
+
// Acquire exclusive context access with retries
|
|
101
|
+
const contextHandle = await services.contextManager.acquireContext(contextId, ownerId, {
|
|
102
|
+
contextOptions,
|
|
103
|
+
acquireOptions: {
|
|
104
|
+
waitTimeoutMs: 10000, // Wait up to 10 seconds for context
|
|
105
|
+
lockTimeoutMs: 300000, // Hold lock for up to 5 minutes
|
|
106
|
+
retryIntervalMs: 100,
|
|
107
|
+
},
|
|
318
108
|
});
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
.
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
109
|
+
try {
|
|
110
|
+
const context = contextHandle.context;
|
|
111
|
+
const mainSystemPrompt = context.getSystemPrompt();
|
|
112
|
+
let eligibleIntegrations;
|
|
113
|
+
let missingIntegrationIds;
|
|
114
|
+
const pageEntities = getPageEntitiesFiltered(pageName, ["StateVar", "Component"], services);
|
|
115
|
+
const pageEntityNames = pageEntities.map((entity) => entity.name);
|
|
116
|
+
const existingSdkApiArtifact = await readApiSource(pageName, apiName, pageEntityNames, services);
|
|
117
|
+
if (existingSdkApiArtifact) {
|
|
118
|
+
const existingIntegrationIds = services.appContextStore.apiSemanticsByName[apiName]?.blocks
|
|
119
|
+
.map((block) => block.id)
|
|
120
|
+
.filter((id) => id !== undefined) ?? [];
|
|
121
|
+
eligibleIntegrations = existingIntegrationIds
|
|
122
|
+
.map((id) => promptContext?.integrations?.find((integration) => integration.id === id))
|
|
123
|
+
.filter((x) => x !== undefined);
|
|
124
|
+
const promptContextIntegrationIds = new Set(promptContext?.integrations?.map((integration) => integration.id) ?? []);
|
|
125
|
+
missingIntegrationIds = existingIntegrationIds.filter((id) => !promptContextIntegrationIds.has(id));
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
eligibleIntegrations = promptContext?.integrations;
|
|
129
|
+
}
|
|
130
|
+
if (!clark.context.apiGenStateMap) {
|
|
131
|
+
logger.info("Initializing API generation state map");
|
|
132
|
+
clark.context.apiGenStateMap = new ApiGenerationStateMap();
|
|
133
|
+
}
|
|
134
|
+
const apiGenStateMap = clark.context.apiGenStateMap;
|
|
135
|
+
apiGenStateMap.set(id, {
|
|
136
|
+
status: "ready",
|
|
137
|
+
isNewApi: !existingSdkApiArtifact,
|
|
138
|
+
});
|
|
139
|
+
logger.info(`API generation started for ${pageName}/${apiName} (existing: ${existingSdkApiArtifact ? "yes" : "no"})`);
|
|
140
|
+
const tools = buildApiTools(clark, services, scopeUpdateQueue);
|
|
141
|
+
// Build API prompt using shared helper
|
|
142
|
+
const apiPrompt = buildApiPrompt({
|
|
339
143
|
apiName,
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
144
|
+
userPrompt: prompt,
|
|
145
|
+
pageEntities: pageEntities.map((e) => ({
|
|
146
|
+
name: e.name,
|
|
147
|
+
type: e.type,
|
|
148
|
+
componentType: e.componentType,
|
|
149
|
+
})),
|
|
150
|
+
availableIntegrations: eligibleIntegrations?.map((integration) => ({
|
|
151
|
+
name: integration.name,
|
|
152
|
+
id: integration.id,
|
|
153
|
+
type: datasourceSdkClassByType[integration.type] || integration.type,
|
|
154
|
+
})),
|
|
155
|
+
existingApiSource: existingSdkApiArtifact?.content,
|
|
156
|
+
missingIntegrationIds,
|
|
157
|
+
isEdit: !!existingSdkApiArtifact,
|
|
158
|
+
});
|
|
159
|
+
// Select relevant examples based on hints provided by upstream LLM
|
|
160
|
+
const selectedExampleMetadata = selectExamplesByTags(exampleHints, {
|
|
161
|
+
maxExamples: 6,
|
|
162
|
+
includeNegative: true,
|
|
163
|
+
maxTokenBudget: 7000,
|
|
164
|
+
});
|
|
165
|
+
const examplesContent = formatSelectedExamples(selectedExampleMetadata);
|
|
166
|
+
// Log selected examples for debugging
|
|
167
|
+
if (exampleHints && exampleHints.length > 0) {
|
|
168
|
+
logRef.content += `[EXAMPLE SELECTION] Hints: ${exampleHints.join(", ")}\n`;
|
|
169
|
+
logRef.content += `[EXAMPLE SELECTION] Selected: ${selectedExampleMetadata.map((e) => e.id).join(", ")}\n\n`;
|
|
170
|
+
}
|
|
171
|
+
// Combine system prompt with examples
|
|
172
|
+
const fullSystemPrompt = examplesContent
|
|
173
|
+
? `${systemPrompt}\n\n${examplesContent}`
|
|
174
|
+
: systemPrompt;
|
|
175
|
+
context.setSystemPrompt({
|
|
176
|
+
role: "system",
|
|
177
|
+
content: fullSystemPrompt,
|
|
178
|
+
});
|
|
179
|
+
context.startTurn({
|
|
180
|
+
role: "user",
|
|
181
|
+
content: apiPrompt,
|
|
182
|
+
});
|
|
183
|
+
// Process LLM configuration
|
|
184
|
+
const { providerOptions, headers } = processLLMConfig(llmConfig, 5000, // default budget tokens
|
|
185
|
+
`API Subagent (model=${model.modelId})`);
|
|
186
|
+
const apiSubagentTrack = "api_subagent";
|
|
187
|
+
services.clarkProfiler
|
|
188
|
+
.getProfiler()
|
|
189
|
+
.createTrack(apiSubagentTrack, "API Subagent", "tool");
|
|
190
|
+
return await services.clarkProfiler.getProfiler().timeAsync(`generateApiSource:${apiName}`, async () => {
|
|
191
|
+
let stepCount = 0;
|
|
192
|
+
let thinkingSpanActive = false;
|
|
193
|
+
let textSpanActive = false;
|
|
194
|
+
const allReasoningDeltas = [];
|
|
195
|
+
let currentStepReasoningDeltas = [];
|
|
196
|
+
let currentStepTextDeltas = [];
|
|
197
|
+
// Step accumulators for accurate token counting
|
|
198
|
+
const startTime = new Date().toISOString();
|
|
199
|
+
let totalInputTokens = 0;
|
|
200
|
+
let totalOutputTokens = 0;
|
|
201
|
+
let totalCachedTokens = 0;
|
|
202
|
+
const response = tracedStreamText({
|
|
203
|
+
model,
|
|
204
|
+
messages: context.getMessages(),
|
|
205
|
+
abortSignal: clark.context.abortController?.signal,
|
|
206
|
+
providerOptions,
|
|
207
|
+
headers,
|
|
208
|
+
experimental_transform: [smoothStream({ chunking: "line" })],
|
|
209
|
+
tools,
|
|
210
|
+
prepareStep: async (step) => {
|
|
211
|
+
context.startStep();
|
|
212
|
+
const messages = context.getMessages();
|
|
213
|
+
return { ...step, messages };
|
|
214
|
+
},
|
|
215
|
+
stopWhen: hasToolSuccess("finalizeApi"),
|
|
216
|
+
onChunk: (chunkData) => {
|
|
217
|
+
if (chunkData.chunk.type === "reasoning-delta") {
|
|
218
|
+
allReasoningDeltas.push(chunkData.chunk.text);
|
|
219
|
+
currentStepReasoningDeltas.push(chunkData.chunk.text);
|
|
220
|
+
if (!thinkingSpanActive) {
|
|
221
|
+
thinkingSpanActive = true;
|
|
222
|
+
services.clarkProfiler
|
|
223
|
+
.getProfiler()
|
|
224
|
+
.startFrame(`API Thinking Step ${stepCount + 1}`, apiSubagentTrack, {
|
|
225
|
+
stepNumber: stepCount + 1,
|
|
226
|
+
chunkType: chunkData.chunk.type,
|
|
227
|
+
apiName,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (chunkData.chunk.type === "text-delta") {
|
|
232
|
+
currentStepTextDeltas.push(chunkData.chunk.text);
|
|
233
|
+
if (!textSpanActive) {
|
|
234
|
+
textSpanActive = true;
|
|
235
|
+
services.clarkProfiler
|
|
236
|
+
.getProfiler()
|
|
237
|
+
.startFrame(`API Text Generation Step ${stepCount + 1}`, apiSubagentTrack, {
|
|
238
|
+
stepNumber: stepCount + 1,
|
|
239
|
+
firstTextDelta: chunkData.chunk.text.slice(0, 50) +
|
|
240
|
+
(chunkData.chunk.text.length > 50 ? "..." : ""),
|
|
241
|
+
apiName,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
// Clark often gets the id wrong across tool calls, so we put it in context
|
|
247
|
+
experimental_context: new ApiGenerationContext(id),
|
|
248
|
+
onStepFinish: async (step) => {
|
|
249
|
+
stepCount++;
|
|
250
|
+
const stepTimestamp = new Date().toISOString();
|
|
251
|
+
context.endStep(step.response.messages, step.usage);
|
|
252
|
+
logRef.content += `--- OUTPUT STEP (API subagent) [${stepTimestamp}] ---\n`;
|
|
253
|
+
totalInputTokens += step.usage?.inputTokens ?? 0;
|
|
254
|
+
if (step.reasoning && thinkingSpanActive) {
|
|
364
255
|
services.clarkProfiler
|
|
365
256
|
.getProfiler()
|
|
366
|
-
.
|
|
367
|
-
|
|
368
|
-
|
|
257
|
+
.updateActiveFrameArgs(apiSubagentTrack, {
|
|
258
|
+
completeReasoningText: currentStepReasoningDeltas.join(" "),
|
|
259
|
+
reasoningLength: step.reasoning.length,
|
|
260
|
+
stepComplete: true,
|
|
369
261
|
apiName,
|
|
370
262
|
});
|
|
263
|
+
services.clarkProfiler
|
|
264
|
+
.getProfiler()
|
|
265
|
+
.endFrame(apiSubagentTrack);
|
|
266
|
+
thinkingSpanActive = false;
|
|
267
|
+
currentStepReasoningDeltas = [];
|
|
371
268
|
}
|
|
372
|
-
|
|
373
|
-
if (chunkData.chunk.type === "text-delta") {
|
|
374
|
-
currentStepTextDeltas.push(chunkData.chunk.text);
|
|
375
|
-
if (!textSpanActive) {
|
|
376
|
-
textSpanActive = true;
|
|
269
|
+
if (step.text && textSpanActive) {
|
|
377
270
|
services.clarkProfiler
|
|
378
271
|
.getProfiler()
|
|
379
|
-
.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
272
|
+
.updateActiveFrameArgs(apiSubagentTrack, {
|
|
273
|
+
completeTextContent: currentStepTextDeltas.join(""),
|
|
274
|
+
finalText: step.text,
|
|
275
|
+
textLength: step.text.length,
|
|
276
|
+
stepComplete: true,
|
|
383
277
|
apiName,
|
|
384
278
|
});
|
|
279
|
+
services.clarkProfiler
|
|
280
|
+
.getProfiler()
|
|
281
|
+
.endFrame(apiSubagentTrack);
|
|
282
|
+
textSpanActive = false;
|
|
283
|
+
currentStepTextDeltas = [];
|
|
385
284
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
.
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
stepComplete: true,
|
|
401
|
-
apiName,
|
|
402
|
-
});
|
|
403
|
-
services.clarkProfiler
|
|
404
|
-
.getProfiler()
|
|
405
|
-
.endFrame(apiSubagentTrack);
|
|
406
|
-
thinkingSpanActive = false;
|
|
407
|
-
currentStepReasoningDeltas = [];
|
|
408
|
-
}
|
|
409
|
-
if (step.text && textSpanActive) {
|
|
410
|
-
services.clarkProfiler
|
|
411
|
-
.getProfiler()
|
|
412
|
-
.updateActiveFrameArgs(apiSubagentTrack, {
|
|
413
|
-
completeTextContent: currentStepTextDeltas.join(""),
|
|
414
|
-
finalText: step.text,
|
|
415
|
-
textLength: step.text.length,
|
|
416
|
-
stepComplete: true,
|
|
417
|
-
apiName,
|
|
418
|
-
});
|
|
419
|
-
services.clarkProfiler
|
|
420
|
-
.getProfiler()
|
|
421
|
-
.endFrame(apiSubagentTrack);
|
|
422
|
-
textSpanActive = false;
|
|
423
|
-
currentStepTextDeltas = [];
|
|
424
|
-
}
|
|
425
|
-
if (step.reasoning) {
|
|
426
|
-
const reasoningLines = [
|
|
427
|
-
"[REASONING]",
|
|
428
|
-
...step.reasoning.map(({ text }) => text),
|
|
429
|
-
"",
|
|
430
|
-
];
|
|
431
|
-
logRef.content += reasoningLines.join("\n");
|
|
432
|
-
const reasoningText = step.reasoning
|
|
433
|
-
.map(({ text }) => text)
|
|
434
|
-
.join(" ");
|
|
435
|
-
if (reasoningText.trim()) {
|
|
436
|
-
void services.chatSessionStore.recordAssistant({
|
|
437
|
-
type: "reasoning",
|
|
438
|
-
text: reasoningText,
|
|
439
|
-
group: `api-${apiName}`,
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
if (step.toolCalls.length > 0) {
|
|
444
|
-
try {
|
|
445
|
-
await Promise.all(step.toolCalls.map(async (toolCall) => {
|
|
446
|
-
const args = await getToolCallArguments(toolCall.toolName, toolCall.input, clark);
|
|
447
|
-
await services.chatSessionStore.recordAssistant({
|
|
448
|
-
type: "tool",
|
|
449
|
-
tool: toolCall.toolName,
|
|
450
|
-
args: args,
|
|
285
|
+
if (step.reasoning) {
|
|
286
|
+
const reasoningLines = [
|
|
287
|
+
"[REASONING]",
|
|
288
|
+
...step.reasoning.map(({ text }) => text),
|
|
289
|
+
"",
|
|
290
|
+
];
|
|
291
|
+
logRef.content += reasoningLines.join("\n");
|
|
292
|
+
const reasoningText = step.reasoning
|
|
293
|
+
.map(({ text }) => text)
|
|
294
|
+
.join(" ");
|
|
295
|
+
if (reasoningText.trim()) {
|
|
296
|
+
void services.chatSessionStore.recordAssistant({
|
|
297
|
+
type: "reasoning",
|
|
298
|
+
text: reasoningText,
|
|
451
299
|
group: `api-${apiName}`,
|
|
452
300
|
});
|
|
453
|
-
}));
|
|
454
|
-
}
|
|
455
|
-
catch (error) {
|
|
456
|
-
getLogger().error("Failed to record subagent tool calls", getErrorMeta(error));
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
// Record text messages AFTER tool calls
|
|
460
|
-
if (step.text) {
|
|
461
|
-
logRef.content += `[ASSISTANT TEXT] ${step.text}\n`;
|
|
462
|
-
void services.chatSessionStore.recordAssistant({
|
|
463
|
-
type: "text",
|
|
464
|
-
text: step.text,
|
|
465
|
-
group: `api-${apiName}`,
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
// Accumulate token usage for this step
|
|
469
|
-
if (step.usage) {
|
|
470
|
-
const stepInputTokens = step.usage.inputTokens ?? 0;
|
|
471
|
-
const stepOutputTokens = step.usage.outputTokens ?? 0;
|
|
472
|
-
const stepCachedTokens = step.usage.cachedInputTokens ?? 0;
|
|
473
|
-
// Accumulate tokens across all steps
|
|
474
|
-
totalInputTokens += stepInputTokens;
|
|
475
|
-
totalOutputTokens += stepOutputTokens;
|
|
476
|
-
totalCachedTokens += stepCachedTokens;
|
|
477
|
-
}
|
|
478
|
-
const finalizeApiResult = step.toolResults.find((r) => r.toolName === "finalizeApi");
|
|
479
|
-
if (finalizeApiResult) {
|
|
480
|
-
finalizeApiData = finalizeApiResult.input;
|
|
481
|
-
}
|
|
482
|
-
const toolsCalled = step.content
|
|
483
|
-
.filter((c) => c.type === "tool-result")
|
|
484
|
-
.map((c) => ({
|
|
485
|
-
toolName: c.toolName,
|
|
486
|
-
input: JSON.stringify(c.input),
|
|
487
|
-
output: JSON.stringify(c.output, null, 2),
|
|
488
|
-
}));
|
|
489
|
-
if (toolsCalled.length > 0) {
|
|
490
|
-
logRef.content += `[TOOLS CALLED]\n`;
|
|
491
|
-
toolsCalled.forEach((tool, idx) => {
|
|
492
|
-
logRef.content += ` Tool ${idx + 1}: ${tool.toolName}\n`;
|
|
493
|
-
logRef.content += ` Input: ${tool.input}\n`;
|
|
494
|
-
logRef.content += ` Output: ${tool.output}\n`;
|
|
495
|
-
});
|
|
496
|
-
toolsCalled.forEach((tool, idx) => {
|
|
497
|
-
let parsedInput, parsedOutput;
|
|
498
|
-
try {
|
|
499
|
-
parsedInput = JSON.parse(tool.input);
|
|
500
|
-
}
|
|
501
|
-
catch {
|
|
502
|
-
parsedInput = tool.input;
|
|
503
301
|
}
|
|
302
|
+
}
|
|
303
|
+
if (step.toolCalls.length > 0) {
|
|
504
304
|
try {
|
|
505
|
-
|
|
305
|
+
await Promise.all(step.toolCalls.map(async (toolCall) => {
|
|
306
|
+
const args = await getToolCallArguments(toolCall.toolName, toolCall.input, clark);
|
|
307
|
+
await services.chatSessionStore.recordAssistant({
|
|
308
|
+
type: "tool",
|
|
309
|
+
tool: toolCall.toolName,
|
|
310
|
+
args: args,
|
|
311
|
+
group: `api-${apiName}`,
|
|
312
|
+
});
|
|
313
|
+
}));
|
|
506
314
|
}
|
|
507
|
-
catch {
|
|
508
|
-
|
|
315
|
+
catch (error) {
|
|
316
|
+
getLogger().error("Failed to record subagent tool calls", getErrorMeta(error));
|
|
509
317
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
318
|
+
}
|
|
319
|
+
// Record text messages AFTER tool calls
|
|
320
|
+
if (step.text) {
|
|
321
|
+
logRef.content += `[ASSISTANT TEXT] ${step.text}\n`;
|
|
322
|
+
void services.chatSessionStore.recordAssistant({
|
|
323
|
+
type: "text",
|
|
324
|
+
text: step.text,
|
|
325
|
+
group: `api-${apiName}`,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
// Accumulate token usage for this step
|
|
329
|
+
if (step.usage) {
|
|
330
|
+
const stepInputTokens = step.usage.inputTokens ?? 0;
|
|
331
|
+
const stepOutputTokens = step.usage.outputTokens ?? 0;
|
|
332
|
+
const stepCachedTokens = step.usage.cachedInputTokens ?? 0;
|
|
333
|
+
// Accumulate tokens across all steps
|
|
334
|
+
totalInputTokens += stepInputTokens;
|
|
335
|
+
totalOutputTokens += stepOutputTokens;
|
|
336
|
+
totalCachedTokens += stepCachedTokens;
|
|
337
|
+
}
|
|
338
|
+
const toolsCalled = step.content
|
|
339
|
+
.filter((c) => c.type === "tool-result")
|
|
340
|
+
.map((c) => ({
|
|
341
|
+
toolName: c.toolName,
|
|
342
|
+
input: JSON.stringify(c.input),
|
|
343
|
+
output: JSON.stringify(c.output, null, 2),
|
|
344
|
+
}));
|
|
345
|
+
if (toolsCalled.length > 0) {
|
|
346
|
+
logRef.content += `[TOOLS CALLED]\n`;
|
|
347
|
+
toolsCalled.forEach((tool, idx) => {
|
|
348
|
+
logRef.content += ` Tool ${idx + 1}: ${tool.toolName}\n`;
|
|
349
|
+
logRef.content += ` Input: ${tool.input}\n`;
|
|
350
|
+
logRef.content += ` Output: ${tool.output}\n`;
|
|
351
|
+
});
|
|
352
|
+
toolsCalled.forEach((tool, idx) => {
|
|
353
|
+
let parsedInput, parsedOutput;
|
|
354
|
+
try {
|
|
355
|
+
parsedInput = JSON.parse(tool.input);
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
parsedInput = tool.input;
|
|
359
|
+
}
|
|
360
|
+
try {
|
|
361
|
+
parsedOutput = JSON.parse(tool.output);
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
parsedOutput = tool.output;
|
|
365
|
+
}
|
|
366
|
+
services.clarkProfiler
|
|
367
|
+
.getProfiler()
|
|
368
|
+
.addInstantEvent(`API Tool Call: ${tool.toolName}`, apiSubagentTrack, {
|
|
369
|
+
step: stepCount,
|
|
370
|
+
toolIndex: idx + 1,
|
|
371
|
+
toolName: tool.toolName,
|
|
372
|
+
input: parsedInput,
|
|
373
|
+
output: parsedOutput,
|
|
374
|
+
inputSize: tool.input.length,
|
|
375
|
+
outputSize: tool.output.length,
|
|
376
|
+
apiName,
|
|
377
|
+
});
|
|
521
378
|
});
|
|
522
|
-
}
|
|
379
|
+
}
|
|
380
|
+
logRef.content += `\n`;
|
|
381
|
+
},
|
|
382
|
+
onFinish: (result) => {
|
|
383
|
+
context.endTurn(result.totalUsage);
|
|
384
|
+
if (mainSystemPrompt) {
|
|
385
|
+
// restore main system prompt
|
|
386
|
+
context.setSystemPrompt(mainSystemPrompt);
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
}, clark.tracer, clark.logger);
|
|
390
|
+
for await (const chunk of response.fullStream) {
|
|
391
|
+
await processStreamChunk(chunk, clark, logRef, `api-${apiName}`);
|
|
392
|
+
}
|
|
393
|
+
if (thinkingSpanActive) {
|
|
394
|
+
services.clarkProfiler.getProfiler().endFrame(apiSubagentTrack);
|
|
395
|
+
}
|
|
396
|
+
if (textSpanActive) {
|
|
397
|
+
services.clarkProfiler.getProfiler().endFrame(apiSubagentTrack);
|
|
398
|
+
}
|
|
399
|
+
try {
|
|
400
|
+
const requestTokenData = {
|
|
401
|
+
requestId: `api-subagent-${apiName}-${Date.now()}`,
|
|
402
|
+
inputTokens: totalInputTokens,
|
|
403
|
+
outputTokens: totalOutputTokens,
|
|
404
|
+
totalTokens: totalInputTokens + totalOutputTokens,
|
|
405
|
+
cachedInputTokens: totalCachedTokens,
|
|
406
|
+
model: model.modelId,
|
|
407
|
+
startTime: startTime,
|
|
408
|
+
endTime: new Date().toISOString(),
|
|
409
|
+
};
|
|
410
|
+
await clark.context.peer?.call.aiPushTokenUsage(requestTokenData);
|
|
411
|
+
}
|
|
412
|
+
catch (error) {
|
|
413
|
+
// Token tracking is non-critical - log error but don't fail the API generation
|
|
414
|
+
getLogger().warn("Failed to send token usage data for API generation", error instanceof Error ? error.message : String(error));
|
|
415
|
+
}
|
|
416
|
+
const stateMap = clark.context.apiGenStateMap;
|
|
417
|
+
if (!stateMap) {
|
|
418
|
+
throw new Error("No API generation state map found in context");
|
|
419
|
+
}
|
|
420
|
+
const finalState = stateMap.get(id);
|
|
421
|
+
if (!finalState) {
|
|
422
|
+
throw new Error("No state found for API ${pageName}/${apiName} after generation");
|
|
423
|
+
}
|
|
424
|
+
try {
|
|
425
|
+
if (finalState.status === "finalized") {
|
|
426
|
+
logger.info(`API generation succeeded for ${pageName}/${apiName}`);
|
|
427
|
+
return finalState;
|
|
523
428
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
context.endTurn(result.totalUsage);
|
|
528
|
-
if (mainSystemPrompt) {
|
|
529
|
-
// restore main system prompt
|
|
530
|
-
context.setSystemPrompt(mainSystemPrompt);
|
|
429
|
+
else {
|
|
430
|
+
logger.error(`API generation failed for ${pageName}/${apiName}: final status: ${finalState.status}`);
|
|
431
|
+
throw new Error(`API generation failed, final state: ${safeJsonStringify(finalState)}`);
|
|
531
432
|
}
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
if (thinkingSpanActive) {
|
|
538
|
-
services.clarkProfiler.getProfiler().endFrame(apiSubagentTrack);
|
|
539
|
-
}
|
|
540
|
-
if (textSpanActive) {
|
|
541
|
-
services.clarkProfiler.getProfiler().endFrame(apiSubagentTrack);
|
|
542
|
-
}
|
|
543
|
-
try {
|
|
544
|
-
const requestTokenData = {
|
|
545
|
-
requestId: `api-subagent-${apiName}-${Date.now()}`,
|
|
546
|
-
inputTokens: totalInputTokens,
|
|
547
|
-
outputTokens: totalOutputTokens,
|
|
548
|
-
totalTokens: totalInputTokens + totalOutputTokens,
|
|
549
|
-
cachedInputTokens: totalCachedTokens,
|
|
550
|
-
model: model.modelId,
|
|
551
|
-
startTime: startTime,
|
|
552
|
-
endTime: new Date().toISOString(),
|
|
553
|
-
};
|
|
554
|
-
await clark.context.peer?.call.aiPushTokenUsage(requestTokenData);
|
|
555
|
-
}
|
|
556
|
-
catch (error) {
|
|
557
|
-
// Token tracking is non-critical - log error but don't fail the API generation
|
|
558
|
-
getLogger().warn("Failed to send token usage data for API generation", error instanceof Error ? error.message : String(error));
|
|
559
|
-
}
|
|
560
|
-
return {
|
|
561
|
-
message: finalizedMessage,
|
|
433
|
+
}
|
|
434
|
+
finally {
|
|
435
|
+
stateMap.delete(id);
|
|
436
|
+
}
|
|
437
|
+
}, apiSubagentTrack, {
|
|
562
438
|
apiName,
|
|
563
439
|
pageName,
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
}
|
|
440
|
+
promptLength: apiPrompt.length,
|
|
441
|
+
model: model.modelId,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
finally {
|
|
445
|
+
// Always release the context lock when done
|
|
446
|
+
contextHandle.release();
|
|
447
|
+
}
|
|
572
448
|
},
|
|
573
449
|
};
|
|
574
450
|
});
|