diff --git a/actions/ai-action/.example.env b/actions/ai-action/.example.env new file mode 100644 index 0000000..c6c7c80 --- /dev/null +++ b/actions/ai-action/.example.env @@ -0,0 +1,4 @@ +HERCULES_AUTH_TOKEN=your_hercules_auth_token_here +HERCULES_AQUILA_URL=https://aquila.hercules-ci.com +HERCULES_ACTION_ID=gls-action +HERCULES_SDK_VERSION=0.0.0 \ No newline at end of file diff --git a/actions/ai-action/Dockerfile b/actions/ai-action/Dockerfile new file mode 100644 index 0000000..3fb2319 --- /dev/null +++ b/actions/ai-action/Dockerfile @@ -0,0 +1,18 @@ +FROM node:24-alpine + +WORKDIR /app + +COPY code0-tech-* ./ + +COPY package.json package-lock.json tsconfig.base.json turbo.json ./ + +COPY actions/ai ./actions/ai-action + +RUN npm ci + +WORKDIR /app/actions/ai-action + +RUN npm run build + + +CMD ["npm", "run", "start", "-w", "@code0-tech/ai-action"] \ No newline at end of file diff --git a/actions/ai-action/package.json b/actions/ai-action/package.json new file mode 100644 index 0000000..2bc6493 --- /dev/null +++ b/actions/ai-action/package.json @@ -0,0 +1,25 @@ +{ + "name": "@code0-tech/ai-action", + "version": "0.0.0", + "private": true, + "type": "module", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "scripts": { + "build": "vite build", + "lint": "eslint .", + "test": "vitest run", + "start": "node dist/main.js", + "generate:docs": "npm run build && node dist/generateDocs.js" + }, + "dependencies": { + "@ai-sdk/anthropic": "^3.0.66", + "@ai-sdk/google": "^3.0.57", + "@ai-sdk/mcp": "^1.0.32", + "@ai-sdk/openai": "^3.0.50", + "ai": "^6.0.146", + "ai-sdk-ollama": "^3.8.2", + "ollama-ai-provider-v2": "^3.5.0", + "ts-morph": "^27.0.2" + } +} diff --git a/actions/ai-action/scripts/generateDocs.ts b/actions/ai-action/scripts/generateDocs.ts new file mode 100644 index 0000000..94cea5a --- /dev/null +++ b/actions/ai-action/scripts/generateDocs.ts @@ -0,0 +1,48 @@ +import {runStandardActionDocs, StandardActionDocsConfig} from "../../../src/standardActionDocs" +import {loadAllDefinitions, loadAllDefinitionsByModules} from "../src/helpers"; + +export function generateAIConfig(): StandardActionDocsConfig { + return { + actionName: "AI", + typePrefix: "AI_", + typesOutputPath: "../../docs/Actions/AI/types.mdx", + functionsOutputPath: "../../docs/Actions/AI/functions.mdx", + loadAllDefinitions: loadAllDefinitions, + typeLinkOverrides: {}, + typesCopy: { + title: "Datatypes", + description: "All data types registered by the AI Action.", + heading: "AI Action Types", + intro: `The AI Action registers the following data types with the Hercules platform.`, + }, + functionsCopy: { + title: "Functions", + description: "All functions registered by the AI Action.", + intro: "" + }, + functionGroups: [ + { + heading: "OpenAI Models", + loadFunctions: async (sdk) => await loadAllDefinitionsByModules(sdk, import.meta.glob("../src/functions/models/openai/common.ts")), + }, + { + heading: "Google Models", + loadFunctions: async (sdk) => await loadAllDefinitionsByModules(sdk, import.meta.glob("../src/functions/models/google/common.ts")), + }, + { + heading: "Anthropic Models", + loadFunctions: async (sdk) => await loadAllDefinitionsByModules(sdk, import.meta.glob("../src/functions/models/anthropic/common.ts")), + }, + { + heading: "Ollama", + loadFunctions: async (sdk) => await loadAllDefinitionsByModules(sdk, import.meta.glob("../src/functions/models/ollama/common.ts")), + }, + { + heading: "Tools", + loadFunctions: async (sdk) => await loadAllDefinitionsByModules(sdk, import.meta.glob("../src/functions/tools/**/*.ts")), + } + ], + } +} + +await runStandardActionDocs(generateAIConfig()) diff --git a/actions/ai-action/src/config/modelAuthConfig.ts b/actions/ai-action/src/config/modelAuthConfig.ts new file mode 100644 index 0000000..cff6c29 --- /dev/null +++ b/actions/ai-action/src/config/modelAuthConfig.ts @@ -0,0 +1,36 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {z} from "zod"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers" +import {ModelSchema} from "../types/aiModel"; + +const providers = ModelSchema.shape.provider.options; + +export const ModelAuthConfigSchema = z.object( + Object.fromEntries( + providers.map((option) => [ + option, + z.object({ + authToken: z.string(), + }) + ]) + ) +); + +export default (sdk: ActionSdk) => { + sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_MODEL_AUTH_CONFIG", ModelAuthConfigSchema), + identifier: "AI_MODEL_AUTH_CONFIG" + }) + + return sdk.registerConfigDefinitions({ + type: "AI_MODEL_AUTH_CONFIG", + identifier: "MODEL_AUTH", + linkedDataTypes: ["AI_MODEL_AUTH_CONFIG"], + name: [ + { + code: "en-US", + content: "Model auth" + } + ] + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/config/toolsAuthConfig.ts b/actions/ai-action/src/config/toolsAuthConfig.ts new file mode 100644 index 0000000..c6e5140 --- /dev/null +++ b/actions/ai-action/src/config/toolsAuthConfig.ts @@ -0,0 +1,36 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; +import {z} from "zod"; +import {ToolProviderEnum} from "../types/aiTool"; + +const providers = ToolProviderEnum.options; + +export const ToolsAuthConfigSchema = z.object( + Object.fromEntries( + providers.map((option) => [ + option, + z.object({ + authToken: z.string(), + }) + ]) + ) +); + +export default (sdk: ActionSdk) => { + sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_TOOLS_AUTH_CONFIG", ToolsAuthConfigSchema), + identifier: "AI_TOOLS_AUTH_CONFIG" + }) + + return sdk.registerConfigDefinitions({ + type: "AI_TOOLS_AUTH_CONFIG", + identifier: "TOOLS_AUTH", + linkedDataTypes: ["AI_TOOLS_AUTH_CONFIG"], + name: [ + { + code: "en-US", + content: "Model auth" + } + ] + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/generateStructuredData.ts b/actions/ai-action/src/functions/generateStructuredData.ts new file mode 100644 index 0000000..8a32b75 --- /dev/null +++ b/actions/ai-action/src/functions/generateStructuredData.ts @@ -0,0 +1,139 @@ +import {ActionSdk, HerculesFunctionContext} from "@code0-tech/hercules"; +import {Model} from "../types/aiModel"; +import {Tool} from "../types/aiTool"; +import {extractToken} from "../helpers"; +import {generateText, isLoopFinished, Output} from "ai"; +import {PlainValue} from "@code0-tech/tucana/helpers"; +import {buildProvider, buildTools} from "./helpers"; +import z from "zod"; + + +function generateZodSchema(value: PlainValue): z.ZodTypeAny { + if (value === null) { + return z.null(); + } + + if (Array.isArray(value)) { + if (value.length === 0) { + return z.array(z.unknown()); + } + + const itemSchemas = value.map((item) => generateZodSchema(item)); + const itemSchema = + itemSchemas.length === 1 + ? itemSchemas[0] + : itemSchemas.slice(1).reduce((acc, current) => z.union([acc, current]), itemSchemas[0]); + + return z.array(itemSchema); + } + + switch (typeof value) { + case "string": + return z.string(); + case "number": + return z.number(); + case "boolean": + return z.boolean(); + case "object": { + const shape: Record = {}; + for (const [key, nestedValue] of Object.entries(value as Record)) { + shape[key] = generateZodSchema(nestedValue); + } + return z.object(shape); + } + default: + return z.unknown(); + } +} + +export const handler = async (context: HerculesFunctionContext, model: Model, system: string, prompt: string, tools: Tool[], type: PlainValue): Promise => { + const apiKey = extractToken(context, model.provider) + + const provider = buildProvider(model, apiKey); + + const modelTools = await buildTools(tools, context); + + const generated = await generateText({ + model: provider.languageModel(model.model), + prompt: prompt, + system: system, + tools: modelTools, + stopWhen: isLoopFinished(), + output: Output.object({ + schema: generateZodSchema(type) + }) + }) + + return generated.output as any +}; +export default (sdk: ActionSdk) => { + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( + { + definition: { + runtimeName: "generateStructuredData", + signature: "(model: AI_MODEL, system: string, prompt: string, tools: AI_TOOL[], type: TYPE): TYPE", + linkedDataTypes: ["AI_MODEL", "AI_TOOL", "TYPE"], + name: [ + { + code: "en-US", + content: "Generate structured Data" + } + ], + displayMessage: [ + { + code: "en-US", + content: "generate structured Data" + } + ], + parameters: [ + { + runtimeName: "model", + name: [ + { + code: "en-US", + content: "Model" + } + ], + }, + { + runtimeName: "system", + name: [ + { + code: "en-US", + content: "System prompt" + } + ] + }, + { + runtimeName: "prompt", + name: [ + { + code: "en-US", + content: "Prompt" + } + ] + }, + { + runtimeName: "tools", + name: [ + { + code: "en-US", + content: "Tools" + } + ] + }, + { + runtimeName: "type", + name: [ + { + code: "en-US", + content: "Output Type" + } + ] + } + ] + }, + handler: handler + } + ) +} diff --git a/actions/ai-action/src/functions/generateText.ts b/actions/ai-action/src/functions/generateText.ts new file mode 100644 index 0000000..4ddb1e1 --- /dev/null +++ b/actions/ai-action/src/functions/generateText.ts @@ -0,0 +1,38 @@ +import {ActionSdk, HerculesFunctionContext} from "@code0-tech/hercules"; +import {Model} from "../types/aiModel"; +import {extractToken} from "../helpers"; +import {generateText, isLoopFinished} from "ai"; +import {Tool} from "../types/aiTool"; +import {buildProvider, buildTools} from "./helpers"; + + +export const handler = async (context: HerculesFunctionContext, model: Model, system: string, prompt: string, tools: Tool[]): Promise => { + const apiKey = extractToken(context, model.provider) + + const provider = buildProvider(model, apiKey); + + const modelTools = await buildTools(tools, context); + + const generated = await generateText({ + model: provider.languageModel(model.model), + prompt: prompt, + system: system, + tools: modelTools, + stopWhen: isLoopFinished(), + }) + + return generated.output +}; + +export default (sdk: ActionSdk) => { + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( + { + definition: { + runtimeName: "generateText", + signature: "(model: AI_MODEL, system: string, prompt: string, tools: AI_TOOL[]): string", + linkedDataTypes: ["AI_MODEL", "AI_TOOL"] + }, + handler: handler + } + ) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/helpers.ts b/actions/ai-action/src/functions/helpers.ts new file mode 100644 index 0000000..4015ff4 --- /dev/null +++ b/actions/ai-action/src/functions/helpers.ts @@ -0,0 +1,79 @@ +import {HerculesFunctionContext} from "@code0-tech/hercules"; +import {Model} from "../types/aiModel"; +import {Tool} from "../types/aiTool"; +import {extractToolToken} from "../helpers"; +import {ToolSet} from "ai"; +import {ProviderV3} from "@ai-sdk/provider"; +import {createGoogleGenerativeAI} from "@ai-sdk/google"; +import {createOpenAI} from "@ai-sdk/openai"; +import {createAnthropic} from "@ai-sdk/anthropic"; +import {OllamaSettings, OllamaSettingsSchema} from "./models/ollama/ollamaSettings"; +import {createOllama} from "ollama-ai-provider-v2"; +import {createMCPClient} from "@ai-sdk/mcp"; + +export function buildProvider(model: Model, apiKey: string): ProviderV3 { + switch (model.provider) { + case "google": { + return createGoogleGenerativeAI({ + apiKey: apiKey + }); + } + case "openai": { + return createOpenAI({ + apiKey: apiKey + }) + break + } + case "anthropic": { + return createAnthropic({ + apiKey: apiKey + }) + } + case "ollama": { + const settings: OllamaSettings = OllamaSettingsSchema.parse(model.settings) + return createOllama({ + baseURL: settings.baseURL + }) + } + + } +} + +export async function buildTools(tools: Tool[], context: HerculesFunctionContext) { + let modelTools: ToolSet = {} + + for (const tool of tools) { + const mcpClient = await createMCPClient({ + transport: { + type: 'http', + url: tool.url, + headers: {Authorization: `Bearer ${extractToolToken(context, tool.providerName)}`}, + redirect: 'error', + }, + }); + const tools = await mcpClient.tools() + + if (!tool.tools) { + modelTools = { + ...modelTools, + ...tools + } + continue + } + + const filteredTools: ToolSet = {} + + Object.entries(tools) + .filter(([toolName]) => tool.tools.includes(toolName)) + .forEach(([toolName, toolValue]) => { + filteredTools[toolName] = toolValue + }) + + + modelTools = { + ...modelTools, + ...filteredTools + } + } + return modelTools; +} diff --git a/actions/ai-action/src/functions/models/anthropic/anthropicSettings.ts b/actions/ai-action/src/functions/models/anthropic/anthropicSettings.ts new file mode 100644 index 0000000..042cca1 --- /dev/null +++ b/actions/ai-action/src/functions/models/anthropic/anthropicSettings.ts @@ -0,0 +1,14 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {singleZodSchemaToTypescriptDef} from "../../../../../../src/helpers"; +import z from "zod"; + +export const AnthropicSettingsSchema = z.looseObject({ + +}) + +export default (sdk: ActionSdk) => { + return sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_ANTHROPIC_SETTINGS", AnthropicSettingsSchema), + identifier: "AI_ANTHROPIC_SETTINGS" + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/models/anthropic/common.ts b/actions/ai-action/src/functions/models/anthropic/common.ts new file mode 100644 index 0000000..3fb9fff --- /dev/null +++ b/actions/ai-action/src/functions/models/anthropic/common.ts @@ -0,0 +1,8 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {Model} from "../../../types/aiModel"; +import {registerDefaultCommonAiModelFunction} from "../../../helpers"; + +export default (sdk: ActionSdk, provider: Model["provider"], model: Model["model"]) => { + if (!provider || !model) return Promise.resolve() + return registerDefaultCommonAiModelFunction(sdk, "AI_ANTHROPIC_SETTINGS", provider, model) +} diff --git a/actions/ai-action/src/functions/models/createModelFunction.ts b/actions/ai-action/src/functions/models/createModelFunction.ts new file mode 100644 index 0000000..f699402 --- /dev/null +++ b/actions/ai-action/src/functions/models/createModelFunction.ts @@ -0,0 +1,66 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {Model} from "../../types/aiModel"; + + +export default (sdk: ActionSdk) => { + return sdk.registerRuntimeFunctionDefinitions({ + definition: { + runtimeName: "createModel", + signature: "(provider: string, model: string, settings: object, maxOutputTokens?: number, temperature?: number, maxRetries?: number, stopSequences?: string[], presencePenalty?: number, frequencyPenalty?: number, seed?: number) => AI_MODEL", + parameters: [ + { + runtimeName: "provider", + }, + { + runtimeName: "model", + }, + { + runtimeName: "settings", + }, + { + runtimeName: "maxOutputTokens" + }, + { + runtimeName: "temperature" + }, + { + runtimeName: "maxRetries" + }, + { + runtimeName: "stopSequences" + }, + { + runtimeName: "presencePenalty" + }, + { + runtimeName: "frequencyPenalty" + }, + { + runtimeName: "seed" + } + ], + }, + handler: (provider: Model["provider"], + model: Model["model"], + maxOutputTokens?: Model["maxOutputTokens"], + temperature?: Model["temperature"], + maxRetries?: Model["maxRetries"], + stopSequences?: Model["stopSequences"], + presencePenalty?: Model["presencePenalty"], + frequencyPenalty?: Model["frequencyPenalty"], + seed?: Model["seed"] + ): Model => { + return { + provider: provider, + model: model, + maxOutputTokens: maxOutputTokens, + frequencyPenalty: frequencyPenalty, + presencePenalty: presencePenalty, + stopSequences: stopSequences, + temperature: temperature, + maxRetries: maxRetries, + seed: seed + } + } + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/models/google/common.ts b/actions/ai-action/src/functions/models/google/common.ts new file mode 100644 index 0000000..f6fb4bd --- /dev/null +++ b/actions/ai-action/src/functions/models/google/common.ts @@ -0,0 +1,8 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {Model} from "../../../types/aiModel"; +import {registerDefaultCommonAiModelFunction} from "../../../helpers"; + +export default (sdk: ActionSdk, provider: Model["provider"], model: Model["model"]) => { + if (!provider || !model) return Promise.resolve() + return registerDefaultCommonAiModelFunction(sdk, "AI_GOOGLE_SETTINGS", provider, model) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/models/google/googleSettings.ts b/actions/ai-action/src/functions/models/google/googleSettings.ts new file mode 100644 index 0000000..b27963f --- /dev/null +++ b/actions/ai-action/src/functions/models/google/googleSettings.ts @@ -0,0 +1,18 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {singleZodSchemaToTypescriptDef} from "../../../../../../src/helpers"; +import z from "zod"; + +export const GoogleSettingsSchema = z.looseObject({ + thinkingConfig: z.object({ + thinkingBudget: z.number().optional(), + includeThoughts: z.boolean().optional(), + thinkingLevel: z.enum(["minimal", "low", "medium", "high"]).optional() + }).optional() +}) + +export default (sdk: ActionSdk) => { + return sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_GOOGLE_SETTINGS", GoogleSettingsSchema), + identifier: "AI_GOOGLE_SETTINGS" + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/models/ollama/common.ts b/actions/ai-action/src/functions/models/ollama/common.ts new file mode 100644 index 0000000..c4b1450 --- /dev/null +++ b/actions/ai-action/src/functions/models/ollama/common.ts @@ -0,0 +1,9 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {Model} from "../../../types/aiModel"; +import {registerDefaultCommonAiModelFunction} from "../../../helpers"; + +export default (sdk: ActionSdk, provider: Model["provider"], model: Model["model"]) => { + if (!provider || !model) return Promise.resolve() + return registerDefaultCommonAiModelFunction(sdk, "AI_OLLAMA_SETTINGS", provider, model) +} + diff --git a/actions/ai-action/src/functions/models/ollama/ollamaSettings.ts b/actions/ai-action/src/functions/models/ollama/ollamaSettings.ts new file mode 100644 index 0000000..0d31ab6 --- /dev/null +++ b/actions/ai-action/src/functions/models/ollama/ollamaSettings.ts @@ -0,0 +1,16 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {singleZodSchemaToTypescriptDef} from "../../../../../../src/helpers"; +import z from "zod"; + +export const OllamaSettingsSchema = z.looseObject({ + baseURL: z.string() +}) + +export type OllamaSettings = z.infer + +export default (sdk: ActionSdk) => { + return sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_OLLAMA_SETTINGS", OllamaSettingsSchema), + identifier: "AI_OLLAMA_SETTINGS" + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/models/openai/common.ts b/actions/ai-action/src/functions/models/openai/common.ts new file mode 100644 index 0000000..0d1e096 --- /dev/null +++ b/actions/ai-action/src/functions/models/openai/common.ts @@ -0,0 +1,8 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {Model} from "../../../types/aiModel"; +import {registerDefaultCommonAiModelFunction} from "../../../helpers"; + +export default (sdk: ActionSdk, provider: Model["provider"], model: Model["model"]) => { + if (!provider || !model) return Promise.resolve() + return registerDefaultCommonAiModelFunction(sdk, "AI_OPENAI_SETTINGS", provider, model) +} diff --git a/actions/ai-action/src/functions/models/openai/openAiSettings.ts b/actions/ai-action/src/functions/models/openai/openAiSettings.ts new file mode 100644 index 0000000..ab2aaa1 --- /dev/null +++ b/actions/ai-action/src/functions/models/openai/openAiSettings.ts @@ -0,0 +1,14 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {singleZodSchemaToTypescriptDef} from "../../../../../../src/helpers"; +import z from "zod"; + +export const OpenAiSettingsSchema = z.looseObject({ + +}) + +export default (sdk: ActionSdk) => { + return sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_OPENAI_SETTINGS", OpenAiSettingsSchema), + identifier: "AI_OPENAI_SETTINGS" + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/tools/common.ts b/actions/ai-action/src/functions/tools/common.ts new file mode 100644 index 0000000..478e464 --- /dev/null +++ b/actions/ai-action/src/functions/tools/common.ts @@ -0,0 +1,31 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {TOOL_REGISTRY, ToolProvider} from "../../types/aiTool"; + + +export default (sdk: ActionSdk, tool: ToolProvider) => { + return sdk.registerFunctionDefinitions({ + runtimeName: tool, + runtimeDefinitionName: "createTool", + linkedDataTypes: ["AI_TOOL"], + signature: `(name: string, url: string, tools?: ${TOOL_REGISTRY[tool].tools.map(toolName => `"${toolName}"`).join(" | ")}): AI_TOOL`, + parameters: [ + { + runtimeName: "name", + hidden: true, + defaultValue: tool + }, + { + runtimeName: "url", + hidden: true, + defaultValue: TOOL_REGISTRY[tool].url + }, + { + runtimeName: "tools", + hidden: false, + optional: false, + defaultValue: TOOL_REGISTRY[tool].tools + } + ] + + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/functions/tools/createTool.ts b/actions/ai-action/src/functions/tools/createTool.ts new file mode 100644 index 0000000..20256d5 --- /dev/null +++ b/actions/ai-action/src/functions/tools/createTool.ts @@ -0,0 +1,36 @@ +import {ActionSdk} from "@code0-tech/hercules"; +import {Tool, ToolProvider} from "../../types/aiTool"; + + +export default (sdk: ActionSdk) => { + return sdk.registerRuntimeFunctionDefinitions({ + definition: { + runtimeName: "createTool", + linkedDataTypes: ["AI_TOOL"], + signature: "(providerName: string, url: string, tools?: string[]): AI_TOOL", + parameters: [ + { + runtimeName: "providerName" + }, + { + runtimeName: "url", + }, + { + runtimeName: "tools", + optional: true + }, + ], + }, + handler: ( + providerName: string, + url: string, + tools?: string[] + ): Tool => { + return { + providerName: providerName as ToolProvider, + url: url, + tools: tools || undefined + } + } + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/helpers.ts b/actions/ai-action/src/helpers.ts new file mode 100644 index 0000000..f9f0323 --- /dev/null +++ b/actions/ai-action/src/helpers.ts @@ -0,0 +1,224 @@ +import {ActionSdk, HerculesFunctionContext, RuntimeErrorException} from "@code0-tech/hercules"; +import {Model, MODEL_REGISTRY} from "./types/aiModel"; +import {ToolsAuthConfigSchema} from "./config/toolsAuthConfig"; +import {ToolProvider, ToolProviderEnum} from "./types/aiTool"; +import {ModelAuthConfigSchema} from "./config/modelAuthConfig"; + +export function registerDefaultCommonAiModelFunction(sdk: ActionSdk, settingsTypeName: string, provider: Model["provider"], model: Model["model"]) { + return sdk.registerFunctionDefinitions( + { + name: [ + { + code: "en-US", + content: `Create ${provider} - ${model}` + } + ], + documentation: [ + { + code: "en-US", + content: "Auto generated wrapper function to create this model" + } + ], + linkedDataTypes: [settingsTypeName, "AI_MODEL"], + runtimeDefinitionName: "createModel", + runtimeName: `${provider}/${model}`, + signature: `(provider: string, model: string, settings: ${settingsTypeName}, maxOutputTokens?: number, temperature?: number, maxRetries?: number, stopSequences?: string[], presencePenalty?: number, frequencyPenalty?: number, seed?: number): AI_MODEL`, + parameters: [ + { + runtimeName: "provider", + defaultValue: provider, + hidden: true + }, + { + runtimeName: "model", + defaultValue: model, + hidden: true, + }, + { + runtimeName: "settings", + name: [ + { + code: "en-US", + content: "Settings" + } + ], + description: [ + { + code: "en-US", + content: "The settings for this provider, for more information see the type" + } + ] + }, + { + runtimeName: "maxOutputTokens", + name: [ + { + code: "en-US", + content: "Max Output Tokens" + } + ], + description: [ + { + code: "en-US", + content: "Maximum number of tokens to generate" + } + ] + }, + { + description: [ + { + code: "en-US", + content: "temperature is a parameter that controls the randomness of the model’s outputs during text generation. Normally between 0 and 1" + } + ], + name: [ + { + code: "en-US", + content: "Temperature" + } + ], + runtimeName: "temperature" + }, + { + runtimeName: "maxRetries", + name: [ + { + code: "en-US", + content: "Maximum Retries" + } + ], + description: [ + { + code: "en-US", + content: "Maximum number of retries. Set to 0 to disable retries. Default value is 2" + } + ], + }, + { + runtimeName: "stopSequences", + name: [ + { + code: "en-US", + content: "Stop sequences" + } + ], + description: [ + { + code: "en-US", + content: "Stop sequences are specific strings (words, characters, or patterns) that tell an AI model when to stop generating text." + } + ] + }, + { + runtimeName: "presencePenalty", + name: [ + { + code: "en-US", + content: "Presence Penalty" + } + ], + description: [ + { + code: "en-US", + content: "Presence penalty pushes the model to talk about new things instead of repeating existing ones. Typical range of 0-2" + } + ] + }, + { + runtimeName: "frequencyPenalty", + name: [ + { + code: "en-US", + content: "Frequency Penalty" + } + ], + description: [ + { + code: "en-US", + content: "Frequency penalty is a parameter that reduces the likelihood of the model repeating the same words or phrases multiple times. Typical range of 0-2" + } + ] + }, + { + runtimeName: "seed", + name: [ + { + code: "en-US", + content: "Seed" + } + ], + description: [ + { + code: "en-US", + content: "Seed is a parameter used to make AI model outputs reproducible." + } + ] + } + ], + } + ); +} + +export async function loadAllDefinitions(sdk: ActionSdk) { + const modules = import.meta.glob([ + './{types,functions,config}/**/*.ts' + ]); + + await loadAllDefinitionsByModules(sdk, modules) +} + +export async function loadAllDefinitionsByModules(sdk: ActionSdk, modules: { [x: string]: () => any; }) { + for (const path in modules) { + const mod: any = await modules[path](); + + if (typeof mod.default !== 'function') continue + + if (mod.default.length === 1) { + try { + await mod.default(sdk); + } catch (error) { + console.log(`Error registering functions from ${path}:`, error); + } + } else if (mod.default.length === 3) { + const parts = path.split("/") + const provider = parts.at(-2) as Model["provider"] + + for (const model of MODEL_REGISTRY[provider]) { + try { + await mod.default(sdk, provider, model); + } catch (error) { + console.log(`Error registering functions from ${path}:`, error); + } + } + } else if (mod.default.length === 2) { + for (const toolProvider of ToolProviderEnum.options) { + try { + await mod.default(sdk, toolProvider); + } catch (error) { + console.log(`Error registering functions from ${path}:`, error); + } + } + } + } +} + +export function extractToolToken(context: HerculesFunctionContext, providerName: ToolProvider) { + const config = ToolsAuthConfigSchema.safeParse(context.matchedConfig.findConfig("TOOLS_AUTH")) + + if (!config.success) { + throw new RuntimeErrorException("Invalid tools auth") + } + + return config.data[providerName].authToken +} + +export function extractToken(context: HerculesFunctionContext, provider: Model["provider"]): string { + const config = ModelAuthConfigSchema.safeParse(context.matchedConfig.findConfig("MODEL_AUTH")); + + if (!config.success) { + throw new RuntimeErrorException("Invalid Auth config") + } + + + return config.data[provider].authToken +} \ No newline at end of file diff --git a/actions/ai-action/src/index.ts b/actions/ai-action/src/index.ts new file mode 100644 index 0000000..da4584d --- /dev/null +++ b/actions/ai-action/src/index.ts @@ -0,0 +1,42 @@ +import {createSdk} from "@code0-tech/hercules" +import { + loadAllDefinitions +} from "./helpers"; + +export const sdk = createSdk({ + authToken: process.env.HERCULES_AUTH_TOKEN || "", + aquilaUrl: process.env.HERCULES_AQUILA_URL || "127.0.0.1:50051", + actionId: process.env.HERCULES_ACTION_ID || "ai-action", + version: process.env.HERCULES_SDK_VERSION || "0.0.0", +}) + +async function main() { + try { + await loadAllDefinitions(sdk) + connectToSdk() + } catch (error) { + console.error(error) + } +} + +main().catch(err => { + console.error(err) + process.exit(1) +}) + + +function connectToSdk() { + sdk.connect().then(() => { + console.log("SDK connected successfully"); + }).catch(() => { + console.error("Error connecting SDK:"); + }) + + sdk.onError((error) => { + console.error("SDK Error occurred:", error.message); + console.log("Attempting to reconnect in 5s..."); + setTimeout(() => { + connectToSdk(); + }, 5000) + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/types/aiModel.ts b/actions/ai-action/src/types/aiModel.ts new file mode 100644 index 0000000..005c8ce --- /dev/null +++ b/actions/ai-action/src/types/aiModel.ts @@ -0,0 +1,41 @@ +import {z} from "zod"; +import {ActionSdk} from "@code0-tech/hercules"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; + +export const MODEL_REGISTRY = { + openai: ['gpt-5.1'], + google: ['gemini-2.5-flash'], + anthropic: ['claude-haiku-4-5', 'claude-sonnet-4-6', 'claude-opus-4-6'], + ollama: ['selfhosted'] +} as const + + +type Provider = keyof typeof MODEL_REGISTRY +export const ProviderEnum = z.enum(Object.keys(MODEL_REGISTRY) as [Provider, ...Provider[]]) + +export const ModelSchema = z.object({ + provider: ProviderEnum.describe(` + @description The provider, either pass in the raw provider you want to use, or use the appropriate functions to create this object + `), + model: z.string().describe(` + @description The model of the provider, either pass in the raw model you want to use, or use the appropriate functions to create this object + `), + settings: z.looseObject({}).optional(), + seed: z.number().optional(), + maxOutputTokens: z.number().optional(), + temperature: z.number().min(0).max(1).optional(), + maxRetries: z.number().optional(), + stopSequences: z.array(z.string()).optional(), + presencePenalty: z.number().min(-1).max(1).optional(), + frequencyPenalty: z.number().min(-1).max(1).optional() +}) + + +export type Model = z.infer + +export default (sdk: ActionSdk) => { + return sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_MODEL", ModelSchema), + identifier: "AI_MODEL" + }) +} \ No newline at end of file diff --git a/actions/ai-action/src/types/aiTool.ts b/actions/ai-action/src/types/aiTool.ts new file mode 100644 index 0000000..1921415 --- /dev/null +++ b/actions/ai-action/src/types/aiTool.ts @@ -0,0 +1,73 @@ +import {z} from "zod"; +import {ActionSdk} from "@code0-tech/hercules"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; + +export const TOOL_REGISTRY = { + github: { + url: "https://api.githubcopilot.com/mcp/", + tools: [ + "add_comment_to_pending_review", + "add_issue_comment", + "add_reply_to_pull_request_comment", + "assign_copilot_to_issue", + "create_branch", + "create_or_update_file", + "create_pull_request", + "create_pull_request_with_copilot", + "create_repository", + "delete_file", + "fork_repository", + "get_commit", + "get_copilot_job_status", + "get_file_contents", + "get_label", + "get_latest_release", + "get_release_by_tag", + "get_tag", + "get_team_members", + "get_teams", + "issue_read", + "issue_write", + "list_branches", + "list_commits", + "list_issue_types", + "list_issues", + "list_pull_requests", + "list_releases", + "list_tags", + "merge_pull_request", + "pull_request_read", + "pull_request_review_write", + "push_files", + "request_copilot_review", + "run_secret_scanning", + "search_code", + "search_issues", + "search_pull_requests", + "search_repositories", + "search_users", + "sub_issue_write", + "update_pull_request", + "update_pull_request_branch" + ] + } +} as const + + +export type ToolProvider = keyof typeof TOOL_REGISTRY +export const ToolProviderEnum = z.enum(Object.keys(TOOL_REGISTRY) as [ToolProvider, ...ToolProvider[]]) + +export const ToolSchema = z.object({ + providerName: ToolProviderEnum, + url: z.string(), + tools: z.array(z.string()).optional() +}) + +export type Tool = z.infer + +export default (sdk: ActionSdk) => { + return sdk.registerDataTypes({ + type: singleZodSchemaToTypescriptDef("AI_TOOL", ToolSchema), + identifier: "AI_TOOL" + }) +} \ No newline at end of file diff --git a/actions/ai-action/tsconfig.json b/actions/ai-action/tsconfig.json new file mode 100644 index 0000000..d3ec800 --- /dev/null +++ b/actions/ai-action/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": ["src", "scripts"] +} \ No newline at end of file diff --git a/actions/ai-action/vite.config.ts b/actions/ai-action/vite.config.ts new file mode 100644 index 0000000..7ab94be --- /dev/null +++ b/actions/ai-action/vite.config.ts @@ -0,0 +1,31 @@ +import {defineConfig} from 'vite'; +import {resolve} from 'path'; + +export default defineConfig({ + build: { + target: 'node18', + ssr: true, + outDir: 'dist', + emptyOutDir: true, + rollupOptions: { + input: { + main: resolve(__dirname, 'src/index.ts'), + generateDocs: resolve(__dirname, 'scripts/generateDocs.ts') + }, + external: [ + 'fs', + 'path', + 'os', + 'crypto', + 'stream', + 'util', + 'events', + 'buffer', + 'url', + 'zlib', + 'node:fs', + 'node:path' + ] + } + } +}); \ No newline at end of file diff --git a/actions/ai-action/vitest.config.ts b/actions/ai-action/vitest.config.ts new file mode 100644 index 0000000..918a608 --- /dev/null +++ b/actions/ai-action/vitest.config.ts @@ -0,0 +1,8 @@ +import baseConfig from "../../vitest.config"; +import { defineConfig, mergeConfig } from "vitest/config"; + +export default mergeConfig(baseConfig, defineConfig({ + test: { + include: ["**/*.{test,spec}.{ts,tsx}"] + } +})); \ No newline at end of file diff --git a/actions/gls-action/scripts/generateDocs.ts b/actions/gls-action/scripts/generateDocs.ts index 27f8ffb..d8886ef 100644 --- a/actions/gls-action/scripts/generateDocs.ts +++ b/actions/gls-action/scripts/generateDocs.ts @@ -1,6 +1,11 @@ -import {runStandardActionDocs, StandardActionDocsConfig} from "../../../src/standardActionDocs" +import { + loadFunctions, + runStandardActionDocs, + StandardActionDocsConfig +} from "../../../src/standardActionDocs" import {loadAllDefinitions} from "../src/helpers"; + export function createGlsDocsConfig(): StandardActionDocsConfig { return { actionName: "GLS", @@ -29,7 +34,8 @@ export function createGlsDocsConfig(): StandardActionDocsConfig { functionGroups: [ { heading: "Builder functions", - modules: import.meta.glob("../src/functions/utils/*.ts"), + loadFunctions: (sdk) => + loadFunctions(sdk, import.meta.glob("../src/functions/utils/*.ts")), }, { heading: "Shipment functions", @@ -45,11 +51,14 @@ export function createGlsDocsConfig(): StandardActionDocsConfig { | \`customContent\` | GLS_CUSTOM_CONTENT | No | Custom logo and barcode settings | ---`, - modules: import.meta.glob("../src/functions/services/*.ts"), + + loadFunctions: (sdk) => + loadFunctions(sdk, import.meta.glob("../src/functions/services/*.ts")), }, { heading: "API functions", - modules: import.meta.glob("../src/functions/*.ts"), + loadFunctions: (sdk) => + loadFunctions(sdk, import.meta.glob("../src/functions/*.ts")), }, ], } diff --git a/actions/gls-action/src/functions/cancelShipment.ts b/actions/gls-action/src/functions/cancelShipment.ts index a032f4a..26d9b1a 100644 --- a/actions/gls-action/src/functions/cancelShipment.ts +++ b/actions/gls-action/src/functions/cancelShipment.ts @@ -3,7 +3,7 @@ import {cancelShipment} from "../helpers"; import {CancelShipmentRequestData, CancelShipmentResponseData} from "../types/glsCancelShipment"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "cancelShipment", diff --git a/actions/gls-action/src/functions/getAllowedServices.ts b/actions/gls-action/src/functions/getAllowedServices.ts index 545242a..5a2ab7c 100644 --- a/actions/gls-action/src/functions/getAllowedServices.ts +++ b/actions/gls-action/src/functions/getAllowedServices.ts @@ -8,7 +8,7 @@ import { } from "../types/glsAllowedServices"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "getAllowedServices", diff --git a/actions/gls-action/src/functions/getEndOfDayReport.ts b/actions/gls-action/src/functions/getEndOfDayReport.ts index 9fe77b9..5a19fcb 100644 --- a/actions/gls-action/src/functions/getEndOfDayReport.ts +++ b/actions/gls-action/src/functions/getEndOfDayReport.ts @@ -4,7 +4,7 @@ import axios from "axios"; import {EndOfDayRequestData, EndOfDayResponseData, EndOfDayResponseDataSchema} from "../types/glsEndOfDayRequest"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "getEndOfDayReport", diff --git a/actions/gls-action/src/functions/reprintParcel.ts b/actions/gls-action/src/functions/reprintParcel.ts index ea9fc86..d42c596 100644 --- a/actions/gls-action/src/functions/reprintParcel.ts +++ b/actions/gls-action/src/functions/reprintParcel.ts @@ -8,7 +8,7 @@ import { } from "../types/glsReprintParcel"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "reprintParcel", diff --git a/actions/gls-action/src/functions/services/createAddresseeOnlyShipment.ts b/actions/gls-action/src/functions/services/createAddresseeOnlyShipment.ts index 6b9f5cb..3a6fdbc 100644 --- a/actions/gls-action/src/functions/services/createAddresseeOnlyShipment.ts +++ b/actions/gls-action/src/functions/services/createAddresseeOnlyShipment.ts @@ -11,7 +11,7 @@ import {CustomContent} from "../../types/glsCustomContent"; import {ReturnOptions} from "../../types/glsReturnOptions"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createAddresseeOnlyShipment", diff --git a/actions/gls-action/src/functions/services/createDeliveryAtWorkShipment.ts b/actions/gls-action/src/functions/services/createDeliveryAtWorkShipment.ts index 75be85b..d834d53 100644 --- a/actions/gls-action/src/functions/services/createDeliveryAtWorkShipment.ts +++ b/actions/gls-action/src/functions/services/createDeliveryAtWorkShipment.ts @@ -11,7 +11,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createDeliveryAtWorkShipment", diff --git a/actions/gls-action/src/functions/services/createDeliveryNextWorkingDayShipment.ts b/actions/gls-action/src/functions/services/createDeliveryNextWorkingDayShipment.ts index 845ddaa..e2abc19 100644 --- a/actions/gls-action/src/functions/services/createDeliveryNextWorkingDayShipment.ts +++ b/actions/gls-action/src/functions/services/createDeliveryNextWorkingDayShipment.ts @@ -11,7 +11,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createDeliveryNextWorkingDayShipment", diff --git a/actions/gls-action/src/functions/services/createDeliverySaturdayShipment.ts b/actions/gls-action/src/functions/services/createDeliverySaturdayShipment.ts index ba00235..e0b7398 100644 --- a/actions/gls-action/src/functions/services/createDeliverySaturdayShipment.ts +++ b/actions/gls-action/src/functions/services/createDeliverySaturdayShipment.ts @@ -12,7 +12,7 @@ import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createDeliverySaturdayShipment", diff --git a/actions/gls-action/src/functions/services/createDepositShipment.ts b/actions/gls-action/src/functions/services/createDepositShipment.ts index 2307cbf..2054132 100644 --- a/actions/gls-action/src/functions/services/createDepositShipment.ts +++ b/actions/gls-action/src/functions/services/createDepositShipment.ts @@ -12,7 +12,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createDepositShipment", diff --git a/actions/gls-action/src/functions/services/createExchangeShipment.ts b/actions/gls-action/src/functions/services/createExchangeShipment.ts index e9060e5..729028a 100644 --- a/actions/gls-action/src/functions/services/createExchangeShipment.ts +++ b/actions/gls-action/src/functions/services/createExchangeShipment.ts @@ -12,7 +12,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createExchangeShipment", diff --git a/actions/gls-action/src/functions/services/createFlexDeliveryShipment.ts b/actions/gls-action/src/functions/services/createFlexDeliveryShipment.ts index 9be4468..50d6a24 100644 --- a/actions/gls-action/src/functions/services/createFlexDeliveryShipment.ts +++ b/actions/gls-action/src/functions/services/createFlexDeliveryShipment.ts @@ -11,7 +11,7 @@ import {CustomContent} from "../../types/glsCustomContent"; import {PrintingOptions} from "../../types/glsPrintingOptions"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createFlexDeliveryShipment", diff --git a/actions/gls-action/src/functions/services/createGuaranteed24Shipment.ts b/actions/gls-action/src/functions/services/createGuaranteed24Shipment.ts index f4ce626..980e070 100644 --- a/actions/gls-action/src/functions/services/createGuaranteed24Shipment.ts +++ b/actions/gls-action/src/functions/services/createGuaranteed24Shipment.ts @@ -11,7 +11,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createGuaranteed24Shipment", diff --git a/actions/gls-action/src/functions/services/createIdentPinShipment.ts b/actions/gls-action/src/functions/services/createIdentPinShipment.ts index 881fe57..aea5583 100644 --- a/actions/gls-action/src/functions/services/createIdentPinShipment.ts +++ b/actions/gls-action/src/functions/services/createIdentPinShipment.ts @@ -12,7 +12,7 @@ import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createIdentPinShipment", diff --git a/actions/gls-action/src/functions/services/createIdentShipment.ts b/actions/gls-action/src/functions/services/createIdentShipment.ts index f1b99c1..a7fb416 100644 --- a/actions/gls-action/src/functions/services/createIdentShipment.ts +++ b/actions/gls-action/src/functions/services/createIdentShipment.ts @@ -12,7 +12,7 @@ import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createIdentShipment", diff --git a/actions/gls-action/src/functions/services/createPickAndShipShipment.ts b/actions/gls-action/src/functions/services/createPickAndShipShipment.ts index 0836c80..84dd64b 100644 --- a/actions/gls-action/src/functions/services/createPickAndShipShipment.ts +++ b/actions/gls-action/src/functions/services/createPickAndShipShipment.ts @@ -11,7 +11,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createPickAndShipShipment", diff --git a/actions/gls-action/src/functions/services/createShopDeliveryShipment.ts b/actions/gls-action/src/functions/services/createShopDeliveryShipment.ts index 5e241e6..5b82a63 100644 --- a/actions/gls-action/src/functions/services/createShopDeliveryShipment.ts +++ b/actions/gls-action/src/functions/services/createShopDeliveryShipment.ts @@ -10,7 +10,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import { CreateParcelsResponse } from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createShopDeliveryShipment", diff --git a/actions/gls-action/src/functions/services/createShopReturnShipment.ts b/actions/gls-action/src/functions/services/createShopReturnShipment.ts index dd86205..49c7283 100644 --- a/actions/gls-action/src/functions/services/createShopReturnShipment.ts +++ b/actions/gls-action/src/functions/services/createShopReturnShipment.ts @@ -11,7 +11,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createShopReturnShipment", diff --git a/actions/gls-action/src/functions/services/createSignatureShipment.ts b/actions/gls-action/src/functions/services/createSignatureShipment.ts index 396bb9a..e3bab1a 100644 --- a/actions/gls-action/src/functions/services/createSignatureShipment.ts +++ b/actions/gls-action/src/functions/services/createSignatureShipment.ts @@ -11,7 +11,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - sdk.registerFunctionDefinitions( + sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createSignatureShipment", diff --git a/actions/gls-action/src/functions/services/createTyreShipment.ts b/actions/gls-action/src/functions/services/createTyreShipment.ts index faf6837..a02d028 100644 --- a/actions/gls-action/src/functions/services/createTyreShipment.ts +++ b/actions/gls-action/src/functions/services/createTyreShipment.ts @@ -11,7 +11,7 @@ import {ReturnOptions} from "../../types/glsReturnOptions"; import {CreateParcelsResponse} from "../../types/glsCreateParcelsResponse"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createTyreShipment", diff --git a/actions/gls-action/src/functions/updateParcelWeight.ts b/actions/gls-action/src/functions/updateParcelWeight.ts index f1cb59b..6f7d829 100644 --- a/actions/gls-action/src/functions/updateParcelWeight.ts +++ b/actions/gls-action/src/functions/updateParcelWeight.ts @@ -8,7 +8,7 @@ import { } from "../types/glsUpdateParcelWeight"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "updateParcelWeight", diff --git a/actions/gls-action/src/functions/utils/createAddress.ts b/actions/gls-action/src/functions/utils/createAddress.ts index 10d3f7d..a6fd439 100644 --- a/actions/gls-action/src/functions/utils/createAddress.ts +++ b/actions/gls-action/src/functions/utils/createAddress.ts @@ -2,7 +2,7 @@ import {ActionSdk} from "@code0-tech/hercules"; import {AddressSchema} from "../../types/glsAddress"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createAddress", diff --git a/actions/gls-action/src/functions/utils/createConsignee.ts b/actions/gls-action/src/functions/utils/createConsignee.ts index 6f5f166..17e95e3 100644 --- a/actions/gls-action/src/functions/utils/createConsignee.ts +++ b/actions/gls-action/src/functions/utils/createConsignee.ts @@ -3,7 +3,7 @@ import {AddressSchema} from "../../types/glsAddress"; import {ConsigneeSchema} from "../../types/glsConsignee"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createConsignee", diff --git a/actions/gls-action/src/functions/utils/createCustomContent.ts b/actions/gls-action/src/functions/utils/createCustomContent.ts index 23d597b..5eb75ef 100644 --- a/actions/gls-action/src/functions/utils/createCustomContent.ts +++ b/actions/gls-action/src/functions/utils/createCustomContent.ts @@ -2,7 +2,7 @@ import {ActionSdk} from "@code0-tech/hercules"; import {CustomContent} from "../../types/glsCustomContent"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createCustomContent", diff --git a/actions/gls-action/src/functions/utils/createPrintingOptions.ts b/actions/gls-action/src/functions/utils/createPrintingOptions.ts index d4a1170..e788a2c 100644 --- a/actions/gls-action/src/functions/utils/createPrintingOptions.ts +++ b/actions/gls-action/src/functions/utils/createPrintingOptions.ts @@ -2,7 +2,7 @@ import {ActionSdk} from "@code0-tech/hercules"; import {PrintingOptions, ReturnLabels} from "../../types/glsPrintingOptions"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createPrintingOptions", diff --git a/actions/gls-action/src/functions/utils/createShipmentUnit.ts b/actions/gls-action/src/functions/utils/createShipmentUnit.ts index 75c0368..09fbab0 100644 --- a/actions/gls-action/src/functions/utils/createShipmentUnit.ts +++ b/actions/gls-action/src/functions/utils/createShipmentUnit.ts @@ -3,7 +3,7 @@ import { UnitService } from "../../types/glsUnitService"; import {ShipmentUnit} from "../../types/glsShipmentUnit"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "createShipmentUnit", diff --git a/actions/gls-action/src/functions/validateShipment.ts b/actions/gls-action/src/functions/validateShipment.ts index 153d48c..c96d200 100644 --- a/actions/gls-action/src/functions/validateShipment.ts +++ b/actions/gls-action/src/functions/validateShipment.ts @@ -8,7 +8,7 @@ import { } from "../types/glsValidateShipment"; export default (sdk: ActionSdk) => { - return sdk.registerFunctionDefinitions( + return sdk.registerRuntimeFunctionDefinitionsAndFunctionDefinitions( { definition: { runtimeName: "validateShipment", diff --git a/actions/gls-action/src/helpers.ts b/actions/gls-action/src/helpers.ts index b5a3101..604cd71 100644 --- a/actions/gls-action/src/helpers.ts +++ b/actions/gls-action/src/helpers.ts @@ -1,6 +1,4 @@ -import {ZodError, ZodObject} from "zod"; -import {createAuxiliaryTypeStore, printNode, zodToTs} from "zod-to-ts"; -import ts from "typescript"; +import {ZodError} from "zod"; import axios from "axios"; import { HerculesRuntimeFunctionDefinition, @@ -108,44 +106,7 @@ export const DEFAULT_DATA_TYPES_FOR_SERVICES = [ "GLS_CREATE_PARCELS_RESPONSE" ] -export function singleZodSchemaToTypescriptDef( - typeName: string, - zodSchema: ZodObject -) { - return zodSchemaToTypescriptDefs(typeName, zodSchema).get(typeName)!; -} - -export function zodSchemaToTypescriptDefs( - typeName: string, - zodSchema: ZodObject, - extraSchemas: Record = {} -): Map { - const store = createAuxiliaryTypeStore(); - const result = new Map(); - - for (const [name, schema] of Object.entries(extraSchemas)) { - const {node} = zodToTs(schema, {auxiliaryTypeStore: store}); - - const alias = ts.factory.createTypeAliasDeclaration( - undefined, - ts.factory.createIdentifier(name), - undefined, - node - ); - - store.definitions.set(schema, { - identifier: ts.factory.createIdentifier(name), - node: alias - }); - result.set(name, printNode(alias).replace(`type ${name} =`, ``)); - } - - const {node} = zodToTs(zodSchema, {auxiliaryTypeStore: store}); - result.set(typeName, printNode(node)); - - return result; -} let cachedToken = { token: "", diff --git a/actions/gls-action/src/types/glsAddress.ts b/actions/gls-action/src/types/glsAddress.ts index 05f5a86..a71eb8e 100644 --- a/actions/gls-action/src/types/glsAddress.ts +++ b/actions/gls-action/src/types/glsAddress.ts @@ -1,6 +1,6 @@ import {ActionSdk} from "@code0-tech/hercules"; import z from "zod" -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; export const AddressSchema = z.object({ Name1: z.string().max(40).describe(` diff --git a/actions/gls-action/src/types/glsAllowedServices.ts b/actions/gls-action/src/types/glsAllowedServices.ts index 8d4bd31..c2ca23f 100644 --- a/actions/gls-action/src/types/glsAllowedServices.ts +++ b/actions/gls-action/src/types/glsAllowedServices.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; import z from "zod"; export const AllowedServicesRequestDataSchema = z.object({ diff --git a/actions/gls-action/src/types/glsCancelShipment.ts b/actions/gls-action/src/types/glsCancelShipment.ts index e2be4ca..95c1190 100644 --- a/actions/gls-action/src/types/glsCancelShipment.ts +++ b/actions/gls-action/src/types/glsCancelShipment.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; import z from "zod"; export const CancelShipmentRequestDataSchema = z.object({ diff --git a/actions/gls-action/src/types/glsConsignee.ts b/actions/gls-action/src/types/glsConsignee.ts index b125b15..994c99c 100644 --- a/actions/gls-action/src/types/glsConsignee.ts +++ b/actions/gls-action/src/types/glsConsignee.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {zodSchemaToTypescriptDefs} from "../helpers"; +import {zodSchemaToTypescriptDefs} from "../../../../src/helpers"; import {AddressSchema} from "./glsAddress"; import {z} from "zod"; diff --git a/actions/gls-action/src/types/glsCreateParcelsResponse.ts b/actions/gls-action/src/types/glsCreateParcelsResponse.ts index 6d510bc..a2a7d98 100644 --- a/actions/gls-action/src/types/glsCreateParcelsResponse.ts +++ b/actions/gls-action/src/types/glsCreateParcelsResponse.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; import {z} from "zod"; export const CreateParcelsResponseSchema = z.object({ diff --git a/actions/gls-action/src/types/glsCustomContent.ts b/actions/gls-action/src/types/glsCustomContent.ts index df751ab..61a459b 100644 --- a/actions/gls-action/src/types/glsCustomContent.ts +++ b/actions/gls-action/src/types/glsCustomContent.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; import {z} from "zod"; export const CustomContentSchema = z.object({ diff --git a/actions/gls-action/src/types/glsEndOfDayRequest.ts b/actions/gls-action/src/types/glsEndOfDayRequest.ts index 81b62bb..9d0a2c3 100644 --- a/actions/gls-action/src/types/glsEndOfDayRequest.ts +++ b/actions/gls-action/src/types/glsEndOfDayRequest.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {singleZodSchemaToTypescriptDef, zodSchemaToTypescriptDefs} from "../helpers"; +import {singleZodSchemaToTypescriptDef, zodSchemaToTypescriptDefs} from "../../../../src/helpers"; import z from "zod"; import {AddressSchema} from "./glsAddress"; diff --git a/actions/gls-action/src/types/glsPrintingOptions.ts b/actions/gls-action/src/types/glsPrintingOptions.ts index 9d59be3..bcdb27c 100644 --- a/actions/gls-action/src/types/glsPrintingOptions.ts +++ b/actions/gls-action/src/types/glsPrintingOptions.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {singleZodSchemaToTypescriptDef, zodSchemaToTypescriptDefs} from "../helpers"; +import {singleZodSchemaToTypescriptDef, zodSchemaToTypescriptDefs} from "../../../../src/helpers"; import {z} from "zod"; export const ReturnLabelsSchema = z.object({ diff --git a/actions/gls-action/src/types/glsReprintParcel.ts b/actions/gls-action/src/types/glsReprintParcel.ts index 34d639d..e2ab096 100644 --- a/actions/gls-action/src/types/glsReprintParcel.ts +++ b/actions/gls-action/src/types/glsReprintParcel.ts @@ -1,5 +1,5 @@ import {ActionSdk} from "@code0-tech/hercules"; -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; import z from "zod"; export const ReprintParcelRequestDataSchema = z.object({ diff --git a/actions/gls-action/src/types/glsReturnOptions.ts b/actions/gls-action/src/types/glsReturnOptions.ts index b94efc5..82a2b05 100644 --- a/actions/gls-action/src/types/glsReturnOptions.ts +++ b/actions/gls-action/src/types/glsReturnOptions.ts @@ -1,4 +1,4 @@ -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; import {z} from "zod"; import {ActionSdk} from "@code0-tech/hercules"; diff --git a/actions/gls-action/src/types/glsShipment.ts b/actions/gls-action/src/types/glsShipment.ts index e245db9..c1558ae 100644 --- a/actions/gls-action/src/types/glsShipment.ts +++ b/actions/gls-action/src/types/glsShipment.ts @@ -1,4 +1,4 @@ -import {zodSchemaToTypescriptDefs} from "../helpers"; +import {zodSchemaToTypescriptDefs} from "../../../../src/helpers"; import {z} from "zod"; import {ConsigneeSchema} from "./glsConsignee"; import {AddressSchema} from "./glsAddress"; diff --git a/actions/gls-action/src/types/glsShipmentUnit.ts b/actions/gls-action/src/types/glsShipmentUnit.ts index baceb6b..21e9cc5 100644 --- a/actions/gls-action/src/types/glsShipmentUnit.ts +++ b/actions/gls-action/src/types/glsShipmentUnit.ts @@ -1,5 +1,5 @@ import {z} from "zod"; -import {zodSchemaToTypescriptDefs} from "../helpers"; +import {zodSchemaToTypescriptDefs} from "../../../../src/helpers"; import {ShipmentSchema} from "./glsShipment"; import {InternalUnitServiceSchema, UnitServiceSchema} from "./glsUnitService"; import {ActionSdk} from "@code0-tech/hercules"; diff --git a/actions/gls-action/src/types/glsShipper.ts b/actions/gls-action/src/types/glsShipper.ts index 2887d09..2435eb2 100644 --- a/actions/gls-action/src/types/glsShipper.ts +++ b/actions/gls-action/src/types/glsShipper.ts @@ -1,6 +1,6 @@ import {z} from "zod"; import {AddressSchema} from "./glsAddress"; -import {zodSchemaToTypescriptDefs} from "../helpers"; +import {zodSchemaToTypescriptDefs} from "../../../../src/helpers"; import {ActionSdk} from "@code0-tech/hercules"; export const ShipperSchema = z.object({ diff --git a/actions/gls-action/src/types/glsUnitService.ts b/actions/gls-action/src/types/glsUnitService.ts index 050fe26..dd3adc7 100644 --- a/actions/gls-action/src/types/glsUnitService.ts +++ b/actions/gls-action/src/types/glsUnitService.ts @@ -1,5 +1,5 @@ import z from "zod" -import {zodSchemaToTypescriptDefs} from "../helpers"; +import {zodSchemaToTypescriptDefs} from "../../../../src/helpers"; import {ShipmentSchema} from "./glsShipment"; import {ActionSdk} from "@code0-tech/hercules"; diff --git a/actions/gls-action/src/types/glsUpdateParcelWeight.ts b/actions/gls-action/src/types/glsUpdateParcelWeight.ts index 5a907c3..5b914cc 100644 --- a/actions/gls-action/src/types/glsUpdateParcelWeight.ts +++ b/actions/gls-action/src/types/glsUpdateParcelWeight.ts @@ -1,5 +1,5 @@ import z from "zod"; -import {singleZodSchemaToTypescriptDef} from "../helpers"; +import {singleZodSchemaToTypescriptDef} from "../../../../src/helpers"; import {ActionSdk} from "@code0-tech/hercules"; export const UpdateParcelWeightRequestDataSchema = z.object({ diff --git a/actions/gls-action/src/types/glsValidateShipment.ts b/actions/gls-action/src/types/glsValidateShipment.ts index e22874f..c199920 100644 --- a/actions/gls-action/src/types/glsValidateShipment.ts +++ b/actions/gls-action/src/types/glsValidateShipment.ts @@ -1,7 +1,7 @@ import {ActionSdk} from "@code0-tech/hercules"; import z from "zod"; import {InternalShipmentSchma, ShipmentSchema} from "./glsShipment"; -import {singleZodSchemaToTypescriptDef, zodSchemaToTypescriptDefs} from "../helpers"; +import {singleZodSchemaToTypescriptDef, zodSchemaToTypescriptDefs} from "../../../../src/helpers"; export const ValidateShipmentRequestDataSchema = z.object({ diff --git a/actions/gls-action/test/functions/reprintParcel.test.ts b/actions/gls-action/test/functions/reprintParcel.test.ts index 3f408a2..e6115e0 100644 --- a/actions/gls-action/test/functions/reprintParcel.test.ts +++ b/actions/gls-action/test/functions/reprintParcel.test.ts @@ -82,7 +82,7 @@ describe("reprintParcel.ts", () => { await withBaseFunctionMock(register.default, async (state) => { expect(state.registeredFunctionDefinitions).toHaveLength(1); - const [reprintParcel] = state.registeredFunctionDefinitions; + const [reprintParcel] = state.registeredRuntimeFunctionDefinitions; expect(reprintParcel.definition.runtimeName).toBe("reprintParcel"); diff --git a/actions/gls-action/test/helpers/withSdkMock.ts b/actions/gls-action/test/helpers/withSdkMock.ts index 6648559..306b3af 100644 --- a/actions/gls-action/test/helpers/withSdkMock.ts +++ b/actions/gls-action/test/helpers/withSdkMock.ts @@ -3,15 +3,16 @@ import { ActionSdk, HerculesActionConfigurationDefinition, HerculesDataType, - HerculesFlowType, - HerculesRegisterFunctionParameter + HerculesFlowType, HerculesRegisterFunctionDefinition, + HerculesRegisterRuntimeFunctionParameter } from "@code0-tech/hercules"; import {SdkMockState} from "../index.test"; export const withSdkMock = async (tests: (state: SdkMockState) => void) => { const state = vi.hoisted(() => { const state: SdkMockState = { - registeredFunctionDefinitions: [] as HerculesRegisterFunctionParameter[], + registeredFunctionDefinitions: [] as HerculesRegisterFunctionDefinition[], + registeredRuntimeFunctionDefinitions: [] as HerculesRegisterRuntimeFunctionParameter[], dataTypes: [] as HerculesDataType[], flowTypes: [] as HerculesFlowType[], configDefinitions: [] as HerculesActionConfigurationDefinition[], @@ -28,9 +29,36 @@ export const withSdkMock = async (tests: (state: SdkMockState) => void) => { state.configDefinitions = configDefinitions || null const mockedActionSdk: ActionSdk = { + registerFunctionDefinitions(...functionDefinitions: HerculesRegisterFunctionDefinition[]): Promise { + functionDefinitions.forEach(value => { + state.registeredFunctionDefinitions.push(value) + }) + return Promise.resolve(undefined); + }, + registerRuntimeFunctionDefinitionsAndFunctionDefinitions(...runtimeFunctionDefinitions: HerculesRegisterRuntimeFunctionParameter[]): Promise { + runtimeFunctionDefinitions.forEach(value => { + state.registeredRuntimeFunctionDefinitions.push(value) + }) + + runtimeFunctionDefinitions.forEach(value => { + state.registeredFunctionDefinitions.push({ + ...value.definition, + runtimeDefinitionName: value.definition.runtimeName, + parameters: value.definition.parameters.map(param =>{ + return { + ...param, + runtimeDefinitionName: param.runtimeName + } + }) + }) + }) + return Promise.resolve(undefined); + }, config: config, - registerFunctionDefinitions: (...defs: HerculesRegisterFunctionParameter[]) => { - state.registeredFunctionDefinitions = defs; + registerRuntimeFunctionDefinitions: (...defs: HerculesRegisterRuntimeFunctionParameter[]) => { + defs.forEach(value => { + state.registeredRuntimeFunctionDefinitions.push(value) + }) return Promise.resolve(); }, diff --git a/actions/gls-action/test/index.test.ts b/actions/gls-action/test/index.test.ts index f11dcc9..94b67b0 100644 --- a/actions/gls-action/test/index.test.ts +++ b/actions/gls-action/test/index.test.ts @@ -2,13 +2,14 @@ import {describe, expect, it, vi} from "vitest"; import { HerculesActionConfigurationDefinition, HerculesDataType, - HerculesFlowType, - HerculesRegisterFunctionParameter + HerculesFlowType, HerculesRegisterFunctionDefinition, + HerculesRegisterRuntimeFunctionParameter } from "@code0-tech/hercules"; import {withSdkMock} from "./helpers/withSdkMock"; export type SdkMockState = { - registeredFunctionDefinitions: HerculesRegisterFunctionParameter[] | null; + registeredFunctionDefinitions: HerculesRegisterFunctionDefinition[] | null; + registeredRuntimeFunctionDefinitions: HerculesRegisterRuntimeFunctionParameter[] | null; dataTypes: HerculesDataType[] | null; flowTypes: HerculesFlowType[] | null; configDefinitions: HerculesActionConfigurationDefinition[] | null; @@ -92,7 +93,7 @@ describe("withSdkMock", () => { expect(value.documentation || [], `${value.identifier}: Documentation should be set`).not.toHaveLength(0) }) - state.registeredFunctionDefinitions?.forEach(value => { + state.registeredRuntimeFunctionDefinitions?.forEach(value => { expect(value.definition.name || [], `${value.definition.runtimeName}: Name should be set`).not.toHaveLength(0) expect(value.definition.description || [], `${value.definition.runtimeName}: Description should be set`).not.toHaveLength(0) expect(value.definition.documentation || [], `${value.definition.runtimeName}: Documentation should be set`).not.toHaveLength(0) diff --git a/docker-compose.yml b/docker-compose.yml index 85b210b..0b0b992 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,4 +5,9 @@ services: build: context: . dockerfile: actions/gls-action/Dockerfile - container_name: gls-action \ No newline at end of file + container_name: gls-action + ai-action: + build: + context: . + dockerfile: actions/ai-action/Dockerfile + container_name: ai-action diff --git a/docs/Actions/AI/functions.mdx b/docs/Actions/AI/functions.mdx new file mode 100644 index 0000000..c0365da --- /dev/null +++ b/docs/Actions/AI/functions.mdx @@ -0,0 +1,1034 @@ +--- +title: Functions +description: All functions registered by the AI Action. +--- + + + +--- + +## OpenAI Models + + +### `openai/gpt-5.1` (`createModel`) + +Auto generated wrapper function to create this model + +# + +| Parameter | Name | Type | Required | Description | +| --- | --- | --- | --- | --- | +| settings | Settings | [AI_OPENAI_SETTINGS](./types.mdx#ai_openai_settings) | Yes | The settings for this provider, for more information see the type | +| maxOutputTokens | Max Output Tokens | number | No | Maximum number of tokens to generate | +| temperature | Temperature | number | No | temperature is a parameter that controls the randomness of the model’s outputs during text generation. Normally between 0 and 1 | +| maxRetries | Maximum Retries | number | No | Maximum number of retries. Set to 0 to disable retries. Default value is 2 | +| stopSequences | Stop sequences | string[] | No | Stop sequences are specific strings (words, characters, or patterns) that tell an AI model when to stop generating text. | +| presencePenalty | Presence Penalty | number | No | Presence penalty pushes the model to talk about new things instead of repeating existing ones. Typical range of 0-2 | +| frequencyPenalty | Frequency Penalty | number | No | Frequency penalty is a parameter that reduces the likelihood of the model repeating the same words or phrases multiple times. Typical range of 0-2 | +| seed | Seed | number | No | Seed is a parameter used to make AI model outputs reproducible. | + +Return Type: [AI_MODEL](./types.mdx#ai_model) + + + +--- + +## Google Models + + +### `google/gemini-2.5-flash` (`createModel`) + +Auto generated wrapper function to create this model + +# + +| Parameter | Name | Type | Required | Description | +| --- | --- | --- | --- | --- | +| settings | Settings | [AI_GOOGLE_SETTINGS](./types.mdx#ai_google_settings) | Yes | The settings for this provider, for more information see the type | +| maxOutputTokens | Max Output Tokens | number | No | Maximum number of tokens to generate | +| temperature | Temperature | number | No | temperature is a parameter that controls the randomness of the model’s outputs during text generation. Normally between 0 and 1 | +| maxRetries | Maximum Retries | number | No | Maximum number of retries. Set to 0 to disable retries. Default value is 2 | +| stopSequences | Stop sequences | string[] | No | Stop sequences are specific strings (words, characters, or patterns) that tell an AI model when to stop generating text. | +| presencePenalty | Presence Penalty | number | No | Presence penalty pushes the model to talk about new things instead of repeating existing ones. Typical range of 0-2 | +| frequencyPenalty | Frequency Penalty | number | No | Frequency penalty is a parameter that reduces the likelihood of the model repeating the same words or phrases multiple times. Typical range of 0-2 | +| seed | Seed | number | No | Seed is a parameter used to make AI model outputs reproducible. | + +Return Type: [AI_MODEL](./types.mdx#ai_model) + + + +--- + +## Anthropic Models + + +### `anthropic/claude-opus-4-6` (`createModel`) + +Auto generated wrapper function to create this model + +# + +| Parameter | Name | Type | Required | Description | +| --- | --- | --- | --- | --- | +| settings | Settings | [AI_ANTHROPIC_SETTINGS](./types.mdx#ai_anthropic_settings) | Yes | The settings for this provider, for more information see the type | +| maxOutputTokens | Max Output Tokens | number | No | Maximum number of tokens to generate | +| temperature | Temperature | number | No | temperature is a parameter that controls the randomness of the model’s outputs during text generation. Normally between 0 and 1 | +| maxRetries | Maximum Retries | number | No | Maximum number of retries. Set to 0 to disable retries. Default value is 2 | +| stopSequences | Stop sequences | string[] | No | Stop sequences are specific strings (words, characters, or patterns) that tell an AI model when to stop generating text. | +| presencePenalty | Presence Penalty | number | No | Presence penalty pushes the model to talk about new things instead of repeating existing ones. Typical range of 0-2 | +| frequencyPenalty | Frequency Penalty | number | No | Frequency penalty is a parameter that reduces the likelihood of the model repeating the same words or phrases multiple times. Typical range of 0-2 | +| seed | Seed | number | No | Seed is a parameter used to make AI model outputs reproducible. | + +Return Type: [AI_MODEL](./types.mdx#ai_model) + + + +--- + +### `anthropic/claude-sonnet-4-6` (`createModel`) + +Auto generated wrapper function to create this model + +# + +| Parameter | Name | Type | Required | Description | +| --- | --- | --- | --- | --- | +| settings | Settings | [AI_ANTHROPIC_SETTINGS](./types.mdx#ai_anthropic_settings) | Yes | The settings for this provider, for more information see the type | +| maxOutputTokens | Max Output Tokens | number | No | Maximum number of tokens to generate | +| temperature | Temperature | number | No | temperature is a parameter that controls the randomness of the model’s outputs during text generation. Normally between 0 and 1 | +| maxRetries | Maximum Retries | number | No | Maximum number of retries. Set to 0 to disable retries. Default value is 2 | +| stopSequences | Stop sequences | string[] | No | Stop sequences are specific strings (words, characters, or patterns) that tell an AI model when to stop generating text. | +| presencePenalty | Presence Penalty | number | No | Presence penalty pushes the model to talk about new things instead of repeating existing ones. Typical range of 0-2 | +| frequencyPenalty | Frequency Penalty | number | No | Frequency penalty is a parameter that reduces the likelihood of the model repeating the same words or phrases multiple times. Typical range of 0-2 | +| seed | Seed | number | No | Seed is a parameter used to make AI model outputs reproducible. | + +Return Type: [AI_MODEL](./types.mdx#ai_model) + + + +--- + +### `anthropic/claude-haiku-4-5` (`createModel`) + +Auto generated wrapper function to create this model + +# + +| Parameter | Name | Type | Required | Description | +| --- | --- | --- | --- | --- | +| settings | Settings | [AI_ANTHROPIC_SETTINGS](./types.mdx#ai_anthropic_settings) | Yes | The settings for this provider, for more information see the type | +| maxOutputTokens | Max Output Tokens | number | No | Maximum number of tokens to generate | +| temperature | Temperature | number | No | temperature is a parameter that controls the randomness of the model’s outputs during text generation. Normally between 0 and 1 | +| maxRetries | Maximum Retries | number | No | Maximum number of retries. Set to 0 to disable retries. Default value is 2 | +| stopSequences | Stop sequences | string[] | No | Stop sequences are specific strings (words, characters, or patterns) that tell an AI model when to stop generating text. | +| presencePenalty | Presence Penalty | number | No | Presence penalty pushes the model to talk about new things instead of repeating existing ones. Typical range of 0-2 | +| frequencyPenalty | Frequency Penalty | number | No | Frequency penalty is a parameter that reduces the likelihood of the model repeating the same words or phrases multiple times. Typical range of 0-2 | +| seed | Seed | number | No | Seed is a parameter used to make AI model outputs reproducible. | + +Return Type: [AI_MODEL](./types.mdx#ai_model) + + + +--- + +## Ollama + + +### `ollama/selfhosted` (`createModel`) + +Auto generated wrapper function to create this model + +# + +| Parameter | Name | Type | Required | Description | +| --- | --- | --- | --- | --- | +| settings | Settings | [AI_OLLAMA_SETTINGS](./types.mdx#ai_ollama_settings) | Yes | The settings for this provider, for more information see the type | +| maxOutputTokens | Max Output Tokens | number | No | Maximum number of tokens to generate | +| temperature | Temperature | number | No | temperature is a parameter that controls the randomness of the model’s outputs during text generation. Normally between 0 and 1 | +| maxRetries | Maximum Retries | number | No | Maximum number of retries. Set to 0 to disable retries. Default value is 2 | +| stopSequences | Stop sequences | string[] | No | Stop sequences are specific strings (words, characters, or patterns) that tell an AI model when to stop generating text. | +| presencePenalty | Presence Penalty | number | No | Presence penalty pushes the model to talk about new things instead of repeating existing ones. Typical range of 0-2 | +| frequencyPenalty | Frequency Penalty | number | No | Frequency penalty is a parameter that reduces the likelihood of the model repeating the same words or phrases multiple times. Typical range of 0-2 | +| seed | Seed | number | No | Seed is a parameter used to make AI model outputs reproducible. | + +Return Type: [AI_MODEL](./types.mdx#ai_model) + + + +--- + +## Tools + + +### `github` (`createTool`) + + + +# + +| Parameter | Name | Type | Required | Description | +| --- | --- | --- | --- | --- | +| tools | | "add_comment_to_pending_review" \| "add_issue_comment" \| "add_reply_to_pull_request_comment" \| "assign_copilot_to_issue" \| "create_branch" \| "create_or_update_file" \| "create_pull_request" \| "create_pull_request_with_copilot" \| "create_repository" \| "delete_file" \| "fork_repository" \| "get_commit" \| "get_copilot_job_status" \| "get_file_contents" \| "get_label" \| "get_latest_release" \| "get_release_by_tag" \| "get_tag" \| "get_team_members" \| "get_teams" \| "issue_read" \| "issue_write" \| "list_branches" \| "list_commits" \| "list_issue_types" \| "list_issues" \| "list_pull_requests" \| "list_releases" \| "list_tags" \| "merge_pull_request" \| "pull_request_read" \| "pull_request_review_write" \| "push_files" \| "request_copilot_review" \| "run_secret_scanning" \| "search_code" \| "search_issues" \| "search_pull_requests" \| "search_repositories" \| "search_users" \| "sub_issue_write" \| "update_pull_request" \| "update_pull_request_branch" | No | | + +Return Type: [AI_TOOL](./types.mdx#ai_tool) + + + +--- diff --git a/docs/Actions/AI/types.mdx b/docs/Actions/AI/types.mdx new file mode 100644 index 0000000..9d44675 --- /dev/null +++ b/docs/Actions/AI/types.mdx @@ -0,0 +1,284 @@ +--- +title: Datatypes +description: All data types registered by the AI Action. +--- +import {TypeTable} from "fumadocs-ui/components/type-table"; + +# AI Action Types + +The AI Action registers the following data types with the Hercules platform. + +--- + +# AI_TOOL +No documentation provided for this type. + + + +# AI_MODEL +No documentation provided for this type. + + + +# AI_OPENAI_SETTINGS +No documentation provided for this type. + + + +# AI_OLLAMA_SETTINGS +No documentation provided for this type. + + + +# AI_GOOGLE_SETTINGS +No documentation provided for this type. + + + +# AI_GOOGLE_SETTINGS$thinkingConfig +No documentation provided for this type. + + + +# AI_ANTHROPIC_SETTINGS +No documentation provided for this type. + + + +# AI_TOOLS_AUTH_CONFIG +No documentation provided for this type. + + + +# AI_TOOLS_AUTH_CONFIG$github +No documentation provided for this type. + + + +# AI_MODEL_AUTH_CONFIG +No documentation provided for this type. + + + +# AI_MODEL_AUTH_CONFIG$ollama +No documentation provided for this type. + + + +# AI_MODEL_AUTH_CONFIG$anthropic +No documentation provided for this type. + + + +# AI_MODEL_AUTH_CONFIG$google +No documentation provided for this type. + + + +# AI_MODEL_AUTH_CONFIG$openai +No documentation provided for this type. + + + \ No newline at end of file diff --git a/docs/Actions/GLS/functions.mdx b/docs/Actions/GLS/functions.mdx index 798ed9f..a31dcfc 100644 --- a/docs/Actions/GLS/functions.mdx +++ b/docs/Actions/GLS/functions.mdx @@ -16,6 +16,10 @@ The GLS Action exposes functions grouped into three categories: ### `createShipmentUnit` +Creates a GLS shipment unit (an individual parcel within a shipment). + +# + | Parameter | Name | Type | Required | Description | | --- | --- | --- | --- | --- | | weight | Weight (kg) | number | Yes | The weight of the shipment unit in kilograms. Must be a positive number and greater than 0.10 and less than 99. | @@ -27,10 +31,6 @@ The GLS Action exposes functions grouped into three categories: Return Type: [GLS_SHIPMENT_UNIT](./types.mdx#gls_shipment_unit) -# - -Creates a GLS shipment unit (an individual parcel within a shipment). - =18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/gateway": { + "version": "3.0.88", + "resolved": "https://registry.npmjs.org/@ai-sdk/gateway/-/gateway-3.0.88.tgz", + "integrity": "sha512-AFoj7xdWAtCQcy0jJ235ENSakYM8D28qBX+rB+/rX4r8qe/LXgl0e5UivOqxAlIM5E9jnQdYxIPuj3XFtGk/yg==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.22", + "@vercel/oidc": "3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/google": { + "version": "3.0.57", + "resolved": "https://registry.npmjs.org/@ai-sdk/google/-/google-3.0.57.tgz", + "integrity": "sha512-ojbYWB1loG8EGdfOWCbbtasoSwfjsGbOt2I1uPBLmoIBOa7EtUuYP4SujxHADZJFg2h08oUt4Dcw+1hJsjlF6A==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.22" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/mcp": { + "version": "1.0.32", + "resolved": "https://registry.npmjs.org/@ai-sdk/mcp/-/mcp-1.0.32.tgz", + "integrity": "sha512-WkZquZ+bPAwG1mH9yrjGVPKLycaxnUQhJkkYAAZTSAuIgENcO4k/V38+rI28AneoE995mpWn40sFiZ96fHTPgw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.22", + "pkce-challenge": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/openai": { + "version": "3.0.50", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-3.0.50.tgz", + "integrity": "sha512-7M7bklrS+gckzPdpQpC3iG5aN5aQPRJdAJQ5jt7sEgYCqDgUuef9x4Nd570+ghIfKTZvV6tSqeeTuD6De/bZig==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.22" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-3.0.8.tgz", + "integrity": "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "4.0.22", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-4.0.22.tgz", + "integrity": "sha512-B2OTFcRw/Pdka9ZTjpXv6T6qZ6RruRuLokyb8HwW+aoW9ndJ3YasA3/mVswyJw7VMBF8ofXgqvcrCt9KYvFifg==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "3.0.8", + "@standard-schema/spec": "^1.1.0", + "eventsource-parser": "^3.0.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@code0-tech/ai-action": { + "resolved": "actions/ai-action", + "link": true + }, "node_modules/@code0-tech/gls-action": { "resolved": "actions/gls-action", "link": true }, "node_modules/@code0-tech/hercules": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@code0-tech/hercules/-/hercules-0.0.2.tgz", - "integrity": "sha512-oG0N8zRNX8WJmYORhbNnAj75HXi6pzL+xclO3vOxHQiOBjb4hjqnRYIBtCTuR9xAJSXeOEqPu5rgK2hHKTsdzA==", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@code0-tech/hercules/-/hercules-0.0.3.tgz", + "integrity": "sha512-Hg/OEGvzjRBf5uQMyfQkcMZiqHdnlis8gbwC2QXm3X02N1YK2t+2QjQvAmaXG5wwxkF9OC0WJ9LSWwJU9Ro+LA==", "license": "ISC", "dependencies": { - "@code0-tech/tucana": "^0.0.65", + "@code0-tech/tucana": "0.0.67", "@grpc/grpc-js": "^1.14.3", "@protobuf-ts/grpc-backend": "^2.11.1", "@protobuf-ts/grpc-transport": "^2.11.1", "@protobuf-ts/runtime": "^2.11.1", - "@protobuf-ts/runtime-rpc": "^2.11.1" + "@protobuf-ts/runtime-rpc": "^2.11.1", + "pino": "^10.3.1", + "pino-pretty": "^13.1.3" } }, + "node_modules/@code0-tech/hercules/node_modules/@code0-tech/tucana": { + "version": "0.0.67", + "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.67.tgz", + "integrity": "sha512-3V1h3LB+iWeXnt80nsIQo+TeMgVTgbDxvDsAArbffHyU37ii1tsAAV6Ty7wAdkrCSsObyFRpdiIZgzgYVVKfzw==", + "license": "Apache-2.0" + }, "node_modules/@code0-tech/tucana": { - "version": "0.0.65", - "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.65.tgz", - "integrity": "sha512-XTNAZ+iqTEf1yLU0uqNc2+ICg6tRF0w41C6da9DePoV4qDa2aRmZwA4jJyr/1i+hohZVKRrhkY7Qaf/blsyx0g==", + "version": "0.0.68", + "resolved": "https://registry.npmjs.org/@code0-tech/tucana/-/tucana-0.0.68.tgz", + "integrity": "sha512-kbjLiKjJyZLnPmNi5JabWRNZcWZyXnfnld8jCFrUkvKbGj77CAwggR0uH8SqaxwWNWqQZlavYzCZWO/ob3+uKA==", "license": "Apache-2.0" }, "node_modules/@esbuild/aix-ppc64": { @@ -707,6 +845,21 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@pinojs/redact": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz", + "integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==", + "license": "MIT" + }, "node_modules/@protobuf-ts/grpc-backend": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/@protobuf-ts/grpc-backend/-/grpc-backend-2.11.1.tgz", @@ -1141,7 +1294,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, "license": "MIT" }, "node_modules/@ts-morph/common": { @@ -1516,6 +1668,15 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@vercel/oidc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz", + "integrity": "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20" + } + }, "node_modules/@vitest/expect": { "version": "4.0.18", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", @@ -1650,6 +1811,42 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/ai": { + "version": "6.0.146", + "resolved": "https://registry.npmjs.org/ai/-/ai-6.0.146.tgz", + "integrity": "sha512-70DE8k1rR0N3mXxyyfjYAx/FxRln/kQ5ym18lt1ys1eUklcPuoIXGbUBwdfCbmkt6YF3jCDZ5+OgkWieP/NGDw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/gateway": "3.0.88", + "@ai-sdk/provider": "3.0.8", + "@ai-sdk/provider-utils": "4.0.22", + "@opentelemetry/api": "1.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/ai-sdk-ollama": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/ai-sdk-ollama/-/ai-sdk-ollama-3.8.2.tgz", + "integrity": "sha512-0k9tLeXLhGahsjNOOBZ07KccffeZNx4gIeutuccjRT8YxxEtnIoVF/ECdgoyaPm8be6WCLDkVnmtSJmkdWHHZA==", + "license": "MIT", + "dependencies": { + "@ai-sdk/provider": "^3.0.8", + "@ai-sdk/provider-utils": "^4.0.21", + "jsonrepair": "^3.13.3", + "ollama": "^0.6.3" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "ai": "^6.0.137" + } + }, "node_modules/ajv": { "version": "6.14.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", @@ -1707,6 +1904,15 @@ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", "license": "MIT" }, + "node_modules/atomic-sleep": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz", + "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/axios": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/axios/-/axios-1.15.0.tgz", @@ -1800,6 +2006,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -1827,6 +2039,15 @@ "node": ">= 8" } }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1881,6 +2102,15 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "license": "MIT" }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -2158,6 +2388,15 @@ "node": ">=0.10.0" } }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/expect-type": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", @@ -2168,6 +2407,12 @@ "node": ">=12.0.0" } }, + "node_modules/fast-copy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.2.tgz", + "integrity": "sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2189,6 +2434,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -2439,6 +2690,12 @@ "node": ">= 0.4" } }, + "node_modules/help-me": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz", + "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==", + "license": "MIT" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2498,6 +2755,15 @@ "dev": true, "license": "ISC" }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -2505,6 +2771,12 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -2519,6 +2791,15 @@ "dev": true, "license": "MIT" }, + "node_modules/jsonrepair": { + "version": "3.13.3", + "resolved": "https://registry.npmjs.org/jsonrepair/-/jsonrepair-3.13.3.tgz", + "integrity": "sha512-BTznj0owIt2CBAH/LTo7+1I5pMvl1e1033LRl/HUowlZmJOIhzC0zbX5bxMngLkfT4WnzPP26QnW5wMr2g9tsQ==", + "license": "ISC", + "bin": { + "jsonrepair": "bin/cli.js" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2626,6 +2907,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -2669,6 +2959,50 @@ ], "license": "MIT" }, + "node_modules/ollama": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/ollama/-/ollama-0.6.3.tgz", + "integrity": "sha512-KEWEhIqE5wtfzEIZbDCLH51VFZ6Z3ZSa6sIOg/E/tBV8S51flyqBOXi+bRxlOYKDf8i327zG9eSTb8IJxvm3Zg==", + "license": "MIT", + "dependencies": { + "whatwg-fetch": "^3.6.20" + } + }, + "node_modules/ollama-ai-provider-v2": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/ollama-ai-provider-v2/-/ollama-ai-provider-v2-3.5.0.tgz", + "integrity": "sha512-+s/aYIYa91z2Vk3AkGAz3BaPAQ0flS2eFZD3BN2mD/N6W6YQbcookyu6pc2cbc8SP5VGpNB857WJ0eHDjKXsXw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "^3.0.8", + "@ai-sdk/provider-utils": "^4.0.19" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "ai": "^5.0.0 || ^6.0.0", + "zod": "^4.0.16" + } + }, + "node_modules/on-exit-leak-free": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", + "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -2770,6 +3104,76 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pino": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz", + "integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==", + "license": "MIT", + "dependencies": { + "@pinojs/redact": "^0.4.0", + "atomic-sleep": "^1.0.0", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pino-std-serializers": "^7.0.0", + "process-warning": "^5.0.0", + "quick-format-unescaped": "^4.0.3", + "real-require": "^0.2.0", + "safe-stable-stringify": "^2.3.1", + "sonic-boom": "^4.0.1", + "thread-stream": "^4.0.0" + }, + "bin": { + "pino": "bin.js" + } + }, + "node_modules/pino-abstract-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz", + "integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==", + "license": "MIT", + "dependencies": { + "split2": "^4.0.0" + } + }, + "node_modules/pino-pretty": { + "version": "13.1.3", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz", + "integrity": "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.7", + "dateformat": "^4.6.3", + "fast-copy": "^4.0.0", + "fast-safe-stringify": "^2.1.1", + "help-me": "^5.0.0", + "joycon": "^3.1.1", + "minimist": "^1.2.6", + "on-exit-leak-free": "^2.1.0", + "pino-abstract-transport": "^3.0.0", + "pump": "^3.0.0", + "secure-json-parse": "^4.0.0", + "sonic-boom": "^4.0.1", + "strip-json-comments": "^5.0.2" + }, + "bin": { + "pino-pretty": "bin.js" + } + }, + "node_modules/pino-std-serializers": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz", + "integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==", + "license": "MIT" + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/postcss": { "version": "8.5.8", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", @@ -2808,6 +3212,22 @@ "node": ">= 0.8.0" } }, + "node_modules/process-warning": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz", + "integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, "node_modules/protobufjs": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", @@ -2841,6 +3261,16 @@ "node": ">=10" } }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2851,6 +3281,21 @@ "node": ">=6" } }, + "node_modules/quick-format-unescaped": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz", + "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==", + "license": "MIT" + }, + "node_modules/real-require": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", + "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -2904,6 +3349,31 @@ "fsevents": "~2.3.2" } }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/secure-json-parse": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz", + "integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/semver": { "version": "7.7.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz", @@ -2947,6 +3417,15 @@ "dev": true, "license": "ISC" }, + "node_modules/sonic-boom": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz", + "integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==", + "license": "MIT", + "dependencies": { + "atomic-sleep": "^1.0.0" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2956,6 +3435,15 @@ "node": ">=0.10.0" } }, + "node_modules/split2": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", + "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", + "engines": { + "node": ">= 10.x" + } + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -2996,6 +3484,30 @@ "node": ">=8" } }, + "node_modules/strip-json-comments": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz", + "integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/thread-stream": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz", + "integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==", + "license": "MIT", + "dependencies": { + "real-require": "^0.2.0" + }, + "engines": { + "node": ">=20" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -3298,6 +3810,12 @@ } } }, + "node_modules/whatwg-fetch": { + "version": "3.6.20", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz", + "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==", + "license": "MIT" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -3358,6 +3876,12 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 4eb0488..fa95bcc 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,8 @@ "vitest": "^4.0.0" }, "dependencies": { - "@code0-tech/hercules": "^0.0.2", + "@code0-tech/hercules": "^0.0.3", + "@code0-tech/tucana": "^0.0.68", "axios": "^1.13.6", "vite": "^7.3.1", "zod": "^4.3.6", diff --git a/scripts/create-action.mjs b/scripts/create-action.mjs index 4dc142b..12d2a30 100644 --- a/scripts/create-action.mjs +++ b/scripts/create-action.mjs @@ -2,10 +2,10 @@ // Creates a new package inside the packages/ workspace. // Usage: npm run create-package -- -import { mkdir, writeFile, readFile } from "fs/promises"; -import { join, dirname } from "path"; -import { fileURLToPath } from "url"; -import { existsSync } from "fs"; +import {mkdir, writeFile} from "fs/promises"; +import {join, dirname} from "path"; +import {fileURLToPath} from "url"; +import {existsSync} from "fs"; const __dirname = dirname(fileURLToPath(import.meta.url)); const rootDir = join(__dirname, ".."); @@ -13,82 +13,117 @@ const rootDir = join(__dirname, ".."); const actionName = process.argv[2]; if (!actionName) { - console.error("Usage: npm run create-package -- "); - process.exit(1); + console.error("Usage: npm run create-package -- "); + process.exit(1); } if (!/^[a-z][a-z0-9-]*$/.test(actionName)) { - console.error( - "Action name must start with a lowercase letter and contain only lowercase letters, digits, and hyphens." - ); - process.exit(1); + console.error( + "Action name must start with a lowercase letter and contain only lowercase letters, digits, and hyphens." + ); + process.exit(1); } const packageDir = join(rootDir, "actions", actionName); if (existsSync(packageDir)) { - console.error( - `Action "${actionName}" already exists at actions/${actionName}` - ); - process.exit(1); + console.error( + `Action "${actionName}" already exists at actions/${actionName}` + ); + process.exit(1); } console.log(`Creating action "${actionName}"...`); // Create directory structure -await mkdir(join(packageDir, "src"), { recursive: true }); +await mkdir(join(packageDir, "src"), {recursive: true}); // package.json const packageJson = { - name: `@code0-tech/${actionName}`, - version: "0.0.0", - private: true, - type: "module", - main: "./dist/index.js", - types: "./dist/index.d.ts", - scripts: { - build: "tsc --build", - lint: "eslint .", - }, + name: `@code0-tech/${actionName}`, + version: "0.0.0", + private: true, + type: "module", + main: "./dist/index.js", + types: "./dist/index.d.ts", + scripts: { + build: "vite build", + lint: "eslint .", + test: "vitest run", + start: "node dist/main.js", + "generate:docs": "npm run build && node dist/generateDocs.js" + }, }; await writeFile( - join(packageDir, "package.json"), - JSON.stringify(packageJson, null, 2) + "\n" + join(packageDir, "package.json"), + JSON.stringify(packageJson, null, 2) + "\n" ); +await writeFile(join(packageDir, "vite.config.ts"), ` +import {defineConfig} from 'vite'; +import {resolve} from 'path'; + +export default defineConfig({ + build: { + target: 'node18', + ssr: true, + outDir: 'dist', + emptyOutDir: true, + rollupOptions: { + input: { + main: resolve(__dirname, 'src/index.ts'), + generateDocs: resolve(__dirname, 'scripts/generateDocs.ts') + }, + external: [ + 'fs', + 'path', + 'os', + 'crypto', + 'stream', + 'util', + 'events', + 'buffer', + 'url', + 'zlib', + 'node:fs', + 'node:path' + ] + } + } +}); +`); + +await writeFile(join(packageDir, "vitetest.config.ts"), ` +import baseConfig from "../../vitest.config"; +import { defineConfig, mergeConfig } from "vitest/config"; + +export default mergeConfig(baseConfig, defineConfig({ + test: { + include: ["**/*.{test,spec}.{ts,tsx}"] + } +})); +`); + + // tsconfig.json const tsconfig = { - extends: "../../tsconfig.base.json", - compilerOptions: { - rootDir: "./src", - outDir: "./dist", - composite: true, - }, - include: ["src"], - exclude: ["src/**/*.test.ts", "src/**/*.spec.ts"], + extends: "../../tsconfig.base.json", + compilerOptions: { + outDir: "dist", + }, + include: ["src"], + exclude: ["src/**/*.test.ts", "src/**/*.spec.ts"], }; await writeFile( - join(packageDir, "tsconfig.json"), - JSON.stringify(tsconfig, null, 2) + "\n" + join(packageDir, "tsconfig.json"), + JSON.stringify(tsconfig, null, 2) + "\n" ); // src/index.ts await writeFile(join(packageDir, "src", "index.ts"), `// ${actionName}\n`); -// Update root tsconfig.json references -const rootTsconfigPath = join(rootDir, "tsconfig.json"); -const rootTsconfig = JSON.parse(await readFile(rootTsconfigPath, "utf-8")); - -rootTsconfig.references = rootTsconfig.references ?? []; -rootTsconfig.references.push({ path: `actions/${actionName}` }); - -await writeFile( - rootTsconfigPath, - JSON.stringify(rootTsconfig, null, 2) + "\n" -); - console.log(`\n✅ Action "${actionName}" created successfully!`); console.log(` Location : actions/${actionName}`); console.log(` Run "npm install" to link the new workspace.`); diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..96175e3 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,42 @@ +import {ZodObject} from "zod"; +import {createAuxiliaryTypeStore, printNode, zodToTs} from "zod-to-ts"; +import * as ts from "typescript"; + +export function singleZodSchemaToTypescriptDef( + typeName: string, + zodSchema: ZodObject +) { + return zodSchemaToTypescriptDefs(typeName, zodSchema).get(typeName)!; +} + +export function zodSchemaToTypescriptDefs( + typeName: string, + zodSchema: ZodObject, + extraSchemas: Record = {} +): Map { + const store = createAuxiliaryTypeStore(); + const result = new Map(); + + for (const [name, schema] of Object.entries(extraSchemas)) { + const {node} = zodToTs(schema, {auxiliaryTypeStore: store}); + + const alias = ts.factory.createTypeAliasDeclaration( + undefined, + ts.factory.createIdentifier(name), + undefined, + node + ); + + store.definitions.set(schema, { + identifier: ts.factory.createIdentifier(name), + node: alias + }); + + result.set(name, printNode(alias).replace(`type ${name} =`, ``)); + } + + const {node} = zodToTs(zodSchema, {auxiliaryTypeStore: store}); + result.set(typeName, printNode(node)); + + return result; +} diff --git a/src/standardActionDocs.ts b/src/standardActionDocs.ts index 5d3b9ab..7734788 100644 --- a/src/standardActionDocs.ts +++ b/src/standardActionDocs.ts @@ -3,13 +3,12 @@ import { ActionSdk, HerculesActionConfigurationDefinition, HerculesDataType, - HerculesFlowType, - HerculesRegisterFunctionParameter, + HerculesFlowType, HerculesRegisterFunctionDefinition, } from "@code0-tech/hercules" import {Project, SymbolFlags, Type} from "ts-morph" interface Translation { - code?: string + code?: "en-US" | "de-DE" | string content?: string } @@ -27,16 +26,16 @@ interface FunctionDefinitionCard { } } -interface RegistryState { +export interface RegistryState { dataTypes: HerculesDataType[] actionConfigurationDefinitions: HerculesActionConfigurationDefinition[] - runtimeFunctions: HerculesRegisterFunctionParameter[] + functions: HerculesRegisterFunctionDefinition[] flowTypes: HerculesFlowType[] } interface FunctionGroup { heading: string - modules: Record Promise> + loadFunctions: (sdk: ActionSdk) => Promise, intro?: string } @@ -69,14 +68,24 @@ function createRegistry(): RegistryState { return { dataTypes: [], actionConfigurationDefinitions: [], - runtimeFunctions: [], + functions: [], flowTypes: [], } } function createMockSdk(registry: RegistryState): ActionSdk { + const registerFunctionDefinitions = (...functionDefinitions) => { + registry.functions = [...functionDefinitions.map(value => { + return { + ...value, + isFunctionDefinition: true + } + }), ...registry.functions] + return Promise.resolve() + }; return { - onError: () => {}, + onError: () => { + }, connect: () => Promise.resolve([]), dispatchEvent: () => Promise.resolve(), getProjectActionConfigurations: () => [], @@ -98,10 +107,24 @@ function createMockSdk(registry: RegistryState): ActionSdk { ] return Promise.resolve() }, - registerFunctionDefinitions: (...functionDefinitions) => { - registry.runtimeFunctions = [...functionDefinitions, ...registry.runtimeFunctions] - return Promise.resolve() + registerRuntimeFunctionDefinitionsAndFunctionDefinitions: async (...runtimeFunctionDefinitions) => { + for (const value of runtimeFunctionDefinitions) { + await registerFunctionDefinitions({ + ...value.definition, + runtimeDefinitionName: value.definition.runtimeName, + parameters: value.definition.parameters?.map(parameter => { + return { + ...parameter, + runtimeDefinitionName: parameter.runtimeName + } + }) + } as HerculesRegisterFunctionDefinition) + } + }, + registerRuntimeFunctionDefinitions: () => { + return Promise.resolve() }, + registerFunctionDefinitions: registerFunctionDefinitions, registerFlowTypes: (...flowTypes) => { registry.flowTypes = [...registry.flowTypes, ...flowTypes] return Promise.resolve() @@ -139,7 +162,7 @@ function breakDownType(typeName: string, code: string): Record { } let typeText: string - if (propType.getText().startsWith("{")) { + if (propType.getText().startsWith("{") && !(propType.getText() === "{ [key: string]: string; }" || propType.getText() === "{ [x: string]: unknown; }")) { const nestedName = `${currentName}$${name}` const nestedType = buildType(propType, nestedName) map[nestedName] = `export type ${nestedName} = ${nestedType};` @@ -262,7 +285,7 @@ ${config.typesCopy.intro} } function getParamInfo(signature: string, paramName: string): { optional: boolean; type: string | null } { - const paramsMatch = signature.match(/\((.*)\)/s) + const paramsMatch = signature.match(/\((.*)\)/) if (!paramsMatch) { return {optional: false, type: null} } @@ -289,11 +312,7 @@ function generateMarkdownTable(headers: string[], rows: string[][]): string { return [headerRow, separator, ...bodyRows].join("\n") } -async function loadFunctions( - modules: Record Promise>, - sdk: ActionSdk, - registry: RegistryState, -): Promise { +export const loadFunctions = async (sdk: ActionSdk, modules: { [x: string]: () => any; }) => { for (const path in modules) { const mod: any = await modules[path]() if (typeof mod.default !== "function") { @@ -306,8 +325,6 @@ async function loadFunctions( console.log(`Error registering functions from ${path}:`, error) } } - - registry.runtimeFunctions = [...registry.runtimeFunctions] } async function generateFunctions(config: StandardActionDocsConfig, sdk: ActionSdk, registry: RegistryState): Promise { @@ -322,16 +339,15 @@ ${config.functionsCopy.intro} ` for (const group of config.functionGroups) { - registry.runtimeFunctions = [] - await loadFunctions(group.modules, sdk, registry) + registry.functions = [] + await group.loadFunctions(sdk) generatedDoc += ` ## ${group.heading} ${group.intro ? `\n${group.intro}\n` : ""} ` - registry.runtimeFunctions.forEach(value => { - const definition = value.definition + registry.functions.forEach(definition => { const card: FunctionDefinitionCard = { descriptions: definition.description, names: definition.name, @@ -347,30 +363,33 @@ ${group.intro ? `\n${group.intro}\n` : ""} } const headers = ["Parameter", "Name", "Type", "Required", "Description"] - const rows: string[][] = definition.parameters.map(parameter => { + const rows: string[][] = definition.parameters.filter(value => !value.hidden).map(parameter => { const paramInfo = getParamInfo(definition.signature, parameter.runtimeName) const linkedType = getTypeLink(paramInfo.type, config) return [ parameter.runtimeName, - parameter.name[0].content, + parameter.name?.[0]?.content, linkedType?.replace(/\|/g, "\\|") || "Unknown", paramInfo.optional ? "No" : "Yes", - parameter.description[0].content, + parameter.description?.[0]?.content, ] }) + const formattedName = definition.runtimeName === definition.runtimeDefinitionName ? + `\`${definition.runtimeName}\`` : + `\`${definition.runtimeName}\` (\`${definition.runtimeDefinitionName}\`)` const returnType = definition.signature.split("):")[1]?.trim() generatedDoc += ` -### \`${definition.runtimeName}\` - -${generateMarkdownTable(headers, rows)} +### ${formattedName} -Return Type: ${getTypeLink(returnType || null, config) || "Unknown"} +${definition.documentation?.[0]?.content || ""} # -${definition.documentation?.at(0)?.content || ""} +${generateMarkdownTable(headers, rows)} + +Return Type: ${getTypeLink(returnType || null, config) || "Unknown"}