@aigne/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/lib/cjs/assistant/generate-output.js +101 -0
  2. package/lib/cjs/assistant/select-agent.js +76 -0
  3. package/lib/cjs/assistant/type.js +11 -0
  4. package/lib/cjs/common/aid.js +42 -0
  5. package/lib/cjs/common/index.js +238 -0
  6. package/lib/cjs/common/resource-manager.js +199 -0
  7. package/lib/cjs/constants.js +9 -0
  8. package/lib/cjs/executor/agent.js +10 -0
  9. package/lib/cjs/executor/aigc.js +28 -0
  10. package/lib/cjs/executor/api.js +64 -0
  11. package/lib/cjs/executor/base.js +676 -0
  12. package/lib/cjs/executor/blocklet.js +25 -0
  13. package/lib/cjs/executor/call-agent.js +105 -0
  14. package/lib/cjs/executor/decision.js +478 -0
  15. package/lib/cjs/executor/image-blender.js +32 -0
  16. package/lib/cjs/executor/index.js +81 -0
  17. package/lib/cjs/executor/llm.js +379 -0
  18. package/lib/cjs/executor/logic.js +167 -0
  19. package/lib/cjs/index.js +17 -0
  20. package/lib/cjs/libs/blocklet/vc.js +92 -0
  21. package/lib/cjs/libs/openapi/request/index.js +24 -0
  22. package/lib/cjs/libs/openapi/request/util.js +146 -0
  23. package/lib/cjs/libs/openapi/types/index.js +17 -0
  24. package/lib/cjs/libs/openapi/util/call.js +15 -0
  25. package/lib/cjs/libs/openapi/util/check-schema.js +67 -0
  26. package/lib/cjs/libs/openapi/util/convert-schema.js +44 -0
  27. package/lib/cjs/libs/openapi/util/flatten-open-api.js +21 -0
  28. package/lib/cjs/libs/openapi/util/get-open-api-i18n-text.js +7 -0
  29. package/lib/cjs/logger.js +4 -0
  30. package/lib/cjs/runtime/resource-blocklet.js +5 -0
  31. package/lib/cjs/runtime/runtime.js +143 -0
  32. package/lib/cjs/types/assistant/index.js +31 -0
  33. package/lib/cjs/types/assistant/mustache/ReadableMustache.js +69 -0
  34. package/lib/cjs/types/assistant/mustache/directive.js +35 -0
  35. package/lib/cjs/types/assistant/mustache/mustache.js +688 -0
  36. package/lib/cjs/types/common/index.js +2 -0
  37. package/lib/cjs/types/index.js +20 -0
  38. package/lib/cjs/types/resource/index.js +47 -0
  39. package/lib/cjs/types/resource/project.js +35 -0
  40. package/lib/cjs/types/runtime/agent.js +2 -0
  41. package/lib/cjs/types/runtime/error.js +18 -0
  42. package/lib/cjs/types/runtime/index.js +37 -0
  43. package/lib/cjs/types/runtime/runtime-resource-blocklet-state.js +4 -0
  44. package/lib/cjs/types/runtime/schema.js +259 -0
  45. package/lib/cjs/utils/cron-job.js +48 -0
  46. package/lib/cjs/utils/extract-metadata-transform.js +58 -0
  47. package/lib/cjs/utils/extract-metadata-transform.test.js +61 -0
  48. package/lib/cjs/utils/fs.js +49 -0
  49. package/lib/cjs/utils/get-blocklet-agent.js +351 -0
  50. package/lib/cjs/utils/geti.js +37 -0
  51. package/lib/cjs/utils/is-non-nullable.js +20 -0
  52. package/lib/cjs/utils/render-message.js +23 -0
  53. package/lib/cjs/utils/resolve-secret-inputs.js +49 -0
  54. package/lib/cjs/utils/retry.js +19 -0
  55. package/lib/cjs/utils/task-id.js +7 -0
  56. package/lib/cjs/utils/tool-calls-transform.js +18 -0
  57. package/lib/esm/assistant/generate-output.js +91 -0
  58. package/lib/esm/assistant/select-agent.js +71 -0
  59. package/lib/esm/assistant/type.js +7 -0
  60. package/lib/esm/common/aid.js +38 -0
  61. package/lib/esm/common/index.js +232 -0
  62. package/lib/esm/common/resource-manager.js +192 -0
  63. package/lib/esm/constants.js +6 -0
  64. package/lib/esm/executor/agent.js +6 -0
  65. package/lib/esm/executor/aigc.js +24 -0
  66. package/lib/esm/executor/api.js +34 -0
  67. package/lib/esm/executor/base.js +668 -0
  68. package/lib/esm/executor/blocklet.js +21 -0
  69. package/lib/esm/executor/call-agent.js +98 -0
  70. package/lib/esm/executor/decision.js +471 -0
  71. package/lib/esm/executor/image-blender.js +25 -0
  72. package/lib/esm/executor/index.js +74 -0
  73. package/lib/esm/executor/llm.js +372 -0
  74. package/lib/esm/executor/logic.js +160 -0
  75. package/lib/esm/index.js +1 -0
  76. package/lib/esm/libs/blocklet/vc.js +85 -0
  77. package/lib/esm/libs/openapi/request/index.js +20 -0
  78. package/lib/esm/libs/openapi/request/util.js +136 -0
  79. package/lib/esm/libs/openapi/types/index.js +1 -0
  80. package/lib/esm/libs/openapi/util/call.js +8 -0
  81. package/lib/esm/libs/openapi/util/check-schema.js +62 -0
  82. package/lib/esm/libs/openapi/util/convert-schema.js +42 -0
  83. package/lib/esm/libs/openapi/util/flatten-open-api.js +19 -0
  84. package/lib/esm/libs/openapi/util/get-open-api-i18n-text.js +5 -0
  85. package/lib/esm/logger.js +2 -0
  86. package/lib/esm/runtime/resource-blocklet.js +2 -0
  87. package/lib/esm/runtime/runtime.js +136 -0
  88. package/lib/esm/types/assistant/index.js +9 -0
  89. package/lib/esm/types/assistant/mustache/ReadableMustache.js +63 -0
  90. package/lib/esm/types/assistant/mustache/directive.js +29 -0
  91. package/lib/esm/types/assistant/mustache/mustache.js +686 -0
  92. package/lib/esm/types/common/index.js +1 -0
  93. package/lib/esm/types/index.js +4 -0
  94. package/lib/esm/types/resource/index.js +26 -0
  95. package/lib/esm/types/resource/project.js +29 -0
  96. package/lib/esm/types/runtime/agent.js +1 -0
  97. package/lib/esm/types/runtime/error.js +14 -0
  98. package/lib/esm/types/runtime/index.js +20 -0
  99. package/lib/esm/types/runtime/runtime-resource-blocklet-state.js +1 -0
  100. package/lib/esm/types/runtime/schema.js +249 -0
  101. package/lib/esm/utils/cron-job.js +44 -0
  102. package/lib/esm/utils/extract-metadata-transform.js +54 -0
  103. package/lib/esm/utils/extract-metadata-transform.test.js +59 -0
  104. package/lib/esm/utils/fs.js +41 -0
  105. package/lib/esm/utils/get-blocklet-agent.js +344 -0
  106. package/lib/esm/utils/geti.js +30 -0
  107. package/lib/esm/utils/is-non-nullable.js +13 -0
  108. package/lib/esm/utils/render-message.js +20 -0
  109. package/lib/esm/utils/resolve-secret-inputs.js +46 -0
  110. package/lib/esm/utils/retry.js +16 -0
  111. package/lib/esm/utils/task-id.js +3 -0
  112. package/lib/esm/utils/tool-calls-transform.js +15 -0
  113. package/lib/types/assistant/generate-output.d.ts +29 -0
  114. package/lib/types/assistant/select-agent.d.ts +14 -0
  115. package/lib/types/assistant/type.d.ts +61 -0
  116. package/lib/types/common/aid.d.ts +18 -0
  117. package/lib/types/common/index.d.ts +7 -0
  118. package/lib/types/common/resource-manager.d.ts +88 -0
  119. package/lib/types/constants.d.ts +6 -0
  120. package/lib/types/executor/agent.d.ts +5 -0
  121. package/lib/types/executor/aigc.d.ts +9 -0
  122. package/lib/types/executor/api.d.ts +9 -0
  123. package/lib/types/executor/base.d.ts +209 -0
  124. package/lib/types/executor/blocklet.d.ts +9 -0
  125. package/lib/types/executor/call-agent.d.ts +12 -0
  126. package/lib/types/executor/decision.d.ts +20 -0
  127. package/lib/types/executor/image-blender.d.ts +9 -0
  128. package/lib/types/executor/index.d.ts +8 -0
  129. package/lib/types/executor/llm.d.ts +38 -0
  130. package/lib/types/executor/logic.d.ts +9 -0
  131. package/lib/types/index.d.ts +1 -0
  132. package/lib/types/libs/blocklet/vc.d.ts +17 -0
  133. package/lib/types/libs/openapi/request/index.d.ts +17 -0
  134. package/lib/types/libs/openapi/request/util.d.ts +40 -0
  135. package/lib/types/libs/openapi/types/index.d.ts +20 -0
  136. package/lib/types/libs/openapi/util/call.d.ts +2 -0
  137. package/lib/types/libs/openapi/util/check-schema.d.ts +3 -0
  138. package/lib/types/libs/openapi/util/convert-schema.d.ts +8 -0
  139. package/lib/types/libs/openapi/util/flatten-open-api.d.ts +3 -0
  140. package/lib/types/libs/openapi/util/get-open-api-i18n-text.d.ts +2 -0
  141. package/lib/types/logger.d.ts +2 -0
  142. package/lib/types/runtime/resource-blocklet.d.ts +2 -0
  143. package/lib/types/runtime/runtime.d.ts +20 -0
  144. package/lib/types/types/assistant/index.d.ts +405 -0
  145. package/lib/types/types/assistant/mustache/ReadableMustache.d.ts +2 -0
  146. package/lib/types/types/assistant/mustache/directive.d.ts +6 -0
  147. package/lib/types/types/assistant/mustache/mustache.d.ts +2 -0
  148. package/lib/types/types/common/index.d.ts +45 -0
  149. package/lib/types/types/index.d.ts +4 -0
  150. package/lib/types/types/resource/index.d.ts +17 -0
  151. package/lib/types/types/resource/project.d.ts +41 -0
  152. package/lib/types/types/runtime/agent.d.ts +33 -0
  153. package/lib/types/types/runtime/error.d.ts +10 -0
  154. package/lib/types/types/runtime/index.d.ts +116 -0
  155. package/lib/types/types/runtime/runtime-resource-blocklet-state.d.ts +5 -0
  156. package/lib/types/types/runtime/schema.d.ts +110 -0
  157. package/lib/types/utils/cron-job.d.ts +22 -0
  158. package/lib/types/utils/extract-metadata-transform.d.ts +16 -0
  159. package/lib/types/utils/extract-metadata-transform.test.d.ts +1 -0
  160. package/lib/types/utils/fs.d.ts +9 -0
  161. package/lib/types/utils/get-blocklet-agent.d.ts +219 -0
  162. package/lib/types/utils/geti.d.ts +1 -0
  163. package/lib/types/utils/is-non-nullable.d.ts +2 -0
  164. package/lib/types/utils/render-message.d.ts +6 -0
  165. package/lib/types/utils/resolve-secret-inputs.d.ts +11 -0
  166. package/lib/types/utils/retry.d.ts +1 -0
  167. package/lib/types/utils/task-id.d.ts +1 -0
  168. package/lib/types/utils/tool-calls-transform.d.ts +2 -0
  169. package/package.json +67 -0
  170. package/tsconfig.json +12 -0
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RuntimeExecutor = void 0;
7
+ const aid_1 = require("../common/aid");
8
+ const logger_1 = __importDefault(require("../logger"));
9
+ const agent_1 = require("./agent");
10
+ const aigc_1 = require("./aigc");
11
+ const api_1 = require("./api");
12
+ const base_1 = require("./base");
13
+ const blocklet_1 = require("./blocklet");
14
+ const call_agent_1 = require("./call-agent");
15
+ const decision_1 = require("./decision");
16
+ const image_blender_1 = require("./image-blender");
17
+ const llm_1 = require("./llm");
18
+ const logic_1 = require("./logic");
19
+ class RuntimeExecutor extends base_1.AgentExecutorBase {
20
+ parentAgent;
21
+ constructor(context, agent, options, parentAgent) {
22
+ super(new base_1.ExecutorContext({
23
+ ...context,
24
+ executor(agent, options) {
25
+ return new RuntimeExecutor(this, agent, options, agent);
26
+ },
27
+ }), agent, options);
28
+ this.parentAgent = parentAgent;
29
+ }
30
+ async process() {
31
+ // ignore
32
+ }
33
+ async execute() {
34
+ const { agent, options } = this;
35
+ if (this.parentAgent?.identity && agent.identity) {
36
+ const parent = (0, aid_1.parseIdentity)(this.parentAgent.identity.aid, { rejectWhenError: true });
37
+ const identity = (0, aid_1.parseIdentity)(agent.identity.aid, { rejectWhenError: true });
38
+ agent.identity.aid = (0, aid_1.stringifyIdentity)({
39
+ ...identity,
40
+ blockletDid: identity.blockletDid || parent.blockletDid,
41
+ projectId: identity.projectId || parent.projectId,
42
+ projectRef: identity.projectRef || parent.projectRef,
43
+ });
44
+ agent.identity.working ||= this.parentAgent.identity.working;
45
+ }
46
+ switch (agent.type) {
47
+ case 'agent': {
48
+ return new agent_1.AgentExecutor(this.context, agent, options).execute();
49
+ }
50
+ case 'prompt': {
51
+ return new llm_1.LLMAgentExecutor(this.context, agent, options).execute();
52
+ }
53
+ case 'image': {
54
+ return new aigc_1.AIGCAgentExecutor(this.context, agent, options).execute();
55
+ }
56
+ case 'api': {
57
+ return new api_1.APIAgentExecutor(this.context, agent, options).execute();
58
+ }
59
+ case 'function': {
60
+ return new logic_1.LogicAgentExecutor(this.context, agent, options).execute();
61
+ }
62
+ case 'router': {
63
+ return new decision_1.DecisionAgentExecutor(this.context, agent, options).execute();
64
+ }
65
+ case 'callAgent': {
66
+ return new call_agent_1.CallAgentExecutor(this.context, agent, options).execute();
67
+ }
68
+ case 'blocklet': {
69
+ return new blocklet_1.BlockletAgentExecutor(this.context, agent, options).execute();
70
+ }
71
+ case 'imageBlender': {
72
+ return new image_blender_1.ImageBlenderAgentExecutor(this.context, agent, options).execute();
73
+ }
74
+ default: {
75
+ logger_1.default.error('Unsupported agent type', { agent });
76
+ throw new Error(`Unsupported agent type: ${agent?.type}`);
77
+ }
78
+ }
79
+ }
80
+ }
81
+ exports.RuntimeExecutor = RuntimeExecutor;
@@ -0,0 +1,379 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LLMAgentExecutor = void 0;
7
+ const web_1 = require("stream/web");
8
+ const index_1 = require("@blocklet/ai-kit/api/types/index");
9
+ const config_1 = require("@blocklet/sdk/lib/config");
10
+ const generate_output_1 = require("../assistant/generate-output");
11
+ const common_1 = require("../common");
12
+ const aid_1 = require("../common/aid");
13
+ const types_1 = require("../types");
14
+ const directive_1 = require("../types/assistant/mustache/directive");
15
+ const retry_1 = __importDefault(require("../utils/retry"));
16
+ const task_id_1 = require("../utils/task-id");
17
+ const base_1 = require("./base");
18
+ class LLMAgentExecutor extends base_1.AgentExecutorBase {
19
+ retryTimes = 0;
20
+ get modelInfo() {
21
+ const { agent } = this;
22
+ const model = agent.model || agent.project.model || common_1.defaultTextModel;
23
+ const defaultModelInfo = model === agent.project.model ? agent.project : undefined;
24
+ return {
25
+ model,
26
+ temperature: agent.temperature ?? defaultModelInfo?.temperature,
27
+ topP: agent.topP ?? defaultModelInfo?.topP,
28
+ presencePenalty: agent.presencePenalty ?? defaultModelInfo?.presencePenalty,
29
+ frequencyPenalty: agent.frequencyPenalty ?? defaultModelInfo?.frequencyPenalty,
30
+ };
31
+ }
32
+ _executor;
33
+ get executor() {
34
+ this._executor ??= (async () => {
35
+ const { agent } = this;
36
+ const identity = (0, aid_1.parseIdentity)(agent.identity.aid, { rejectWhenError: true });
37
+ return agent.executor?.agent?.id
38
+ ? {
39
+ executor: await this.context.getAgent({
40
+ aid: (0, aid_1.stringifyIdentity)({
41
+ blockletDid: agent.executor.agent.blockletDid || identity.blockletDid,
42
+ projectId: agent.executor.agent.projectId || identity.projectId,
43
+ projectRef: identity.projectRef,
44
+ agentId: agent.executor.agent.id,
45
+ }),
46
+ working: agent.identity.working,
47
+ rejectOnEmpty: true,
48
+ }),
49
+ inputValues: agent.executor.inputValues,
50
+ }
51
+ : agent.project.executor?.agent?.id
52
+ ? {
53
+ executor: await this.context.getAgent({
54
+ aid: (0, aid_1.stringifyIdentity)({
55
+ blockletDid: agent.project.executor.agent.blockletDid || identity.blockletDid,
56
+ projectId: agent.project.executor.agent.projectId || identity.projectId,
57
+ projectRef: identity.projectRef,
58
+ agentId: agent.project.executor.agent.id,
59
+ }),
60
+ working: agent.identity.working,
61
+ rejectOnEmpty: true,
62
+ }),
63
+ inputValues: agent.project.executor.inputValues,
64
+ }
65
+ : undefined;
66
+ })();
67
+ return this._executor;
68
+ }
69
+ _outputsInfo;
70
+ get outputsInfo() {
71
+ this._outputsInfo ??= (async () => {
72
+ const { agent } = this;
73
+ const outputVariables = (agent.outputVariables ?? []).filter((i) => !!i.name && !i.hidden && i.from?.type !== 'callAgent') ?? [];
74
+ const schema = (0, types_1.outputVariablesToJsonSchema)(agent, {
75
+ variables: await this.context.getMemoryVariables({
76
+ ...(0, aid_1.parseIdentity)(agent.identity.aid, { rejectWhenError: true }),
77
+ working: agent.identity.working,
78
+ }),
79
+ });
80
+ const hasStreamingTextOutput = outputVariables.some((i) => i.name === types_1.RuntimeOutputVariable.text);
81
+ const hasJsonOutputs = !!schema && Object.values(schema.properties).length > 0;
82
+ return { outputs: outputVariables, schema, hasStreamingTextOutput, hasJsonOutputs };
83
+ })();
84
+ return this._outputsInfo;
85
+ }
86
+ getMessages({ inputs }) {
87
+ const { agent } = this;
88
+ const createContentStructure = async (content, variables, agent, prompt) => {
89
+ const parameters = agent.parameters ?? [];
90
+ // 没有特殊变量
91
+ if (!variables.length) {
92
+ const renderedContent = await this.renderMessage(content, { ...inputs, ...this.globalContext });
93
+ return renderedContent;
94
+ }
95
+ // 没有图片变量
96
+ const haveImageParameter = parameters.filter((i) => i.type === 'image').some((i) => variables.includes(i.key));
97
+ if (!haveImageParameter) {
98
+ const renderedContent = await this.renderMessage(content, { ...inputs, ...this.globalContext });
99
+ return renderedContent;
100
+ }
101
+ // 创建图片变量标记
102
+ const createImageMarker = (variable) => `__IMAGE_${variable}__`;
103
+ const imageVariablesMap = {};
104
+ const imageVariables = [];
105
+ // 当前参数有图片变量
106
+ parameters
107
+ .filter((i) => i.type === 'image' && i.key && variables.includes(i.key))
108
+ .forEach((param) => {
109
+ if (param.type === 'image' && param.key && inputs[param.key]) {
110
+ const marker = createImageMarker(param.key);
111
+ imageVariablesMap[param.key] = marker;
112
+ imageVariables.push({ marker, value: inputs[param.key] });
113
+ }
114
+ });
115
+ const renderedContent = await this.renderMessage(content, {
116
+ ...inputs,
117
+ ...this.globalContext,
118
+ ...imageVariablesMap,
119
+ });
120
+ const contentParts = [];
121
+ if (imageVariables.length === 0) {
122
+ return renderedContent;
123
+ }
124
+ let remainingContent = renderedContent;
125
+ for (const { marker, value } of imageVariables) {
126
+ const parts = remainingContent.split(marker);
127
+ if (parts[0]) {
128
+ contentParts.push({ type: 'text', text: parts[0] });
129
+ }
130
+ // 只有是 user 时,才处理
131
+ if (prompt.data.role === 'user') {
132
+ const list = Array.isArray(value) ? value : [value];
133
+ list.forEach((item) => contentParts.push({ type: 'image_url', imageUrl: { url: item } }));
134
+ }
135
+ remainingContent = parts[1] || '';
136
+ }
137
+ if (remainingContent) {
138
+ contentParts.push({ type: 'text', text: remainingContent });
139
+ }
140
+ config_1.logger.info('have image messages', contentParts);
141
+ return contentParts;
142
+ };
143
+ return (async () => (await Promise.all((agent.prompts ?? [])
144
+ .filter((i) => i.visibility !== 'hidden')
145
+ .map(async (prompt) => {
146
+ if (prompt.type === 'message') {
147
+ const content = prompt.data.content
148
+ ?.split('\n')
149
+ .filter((i) => !i.startsWith('//'))
150
+ .join('\n') || '';
151
+ const variables = (0, directive_1.parseDirectives)(content)
152
+ .filter((i) => i.type === 'variable')
153
+ .map((i) => i.name);
154
+ const contentStructure = await createContentStructure(content, variables, agent, prompt);
155
+ return {
156
+ role: prompt.data.role,
157
+ content: contentStructure,
158
+ };
159
+ }
160
+ console.warn('Unsupported prompt type', prompt);
161
+ return undefined;
162
+ })))
163
+ .flat()
164
+ .filter((i) => !!i?.content))();
165
+ }
166
+ async process({ inputs }) {
167
+ const { hasJsonOutputs } = await this.outputsInfo;
168
+ const messages = await this.getMessages({ inputs });
169
+ const { modelInfo } = this;
170
+ const e = await this.executor;
171
+ // NOTE: use json_schema output for models that support it
172
+ if (common_1.supportJsonSchemaModels.includes(modelInfo.model) &&
173
+ hasJsonOutputs &&
174
+ // check the llm executor is support json schema output
175
+ (!e || e.executor.parameters?.some((i) => i.type === 'llmInputResponseFormat'))) {
176
+ return this.processWithJsonSchemaFormat({ messages, inputs });
177
+ }
178
+ return this.processWithOutJsonSchemaFormatSupport({ inputs, messages });
179
+ }
180
+ async processWithOutJsonSchemaFormatSupport({ inputs, messages, }) {
181
+ const { agent, options: { taskId, parentTaskId }, } = this;
182
+ const { hasStreamingTextOutput, hasJsonOutputs, schema } = await this.outputsInfo;
183
+ const outputSchema = JSON.stringify(schema);
184
+ const messagesWithSystemPrompt = [...messages];
185
+ const lastSystemIndex = messagesWithSystemPrompt.findLastIndex((i) => i.role === 'system');
186
+ if (hasJsonOutputs) {
187
+ if (hasStreamingTextOutput) {
188
+ messagesWithSystemPrompt.splice(lastSystemIndex + 1, 0, {
189
+ role: 'system',
190
+ content: (0, generate_output_1.metadataStreamOutputFormatPrompt)(outputSchema),
191
+ });
192
+ }
193
+ else {
194
+ messagesWithSystemPrompt.splice(lastSystemIndex + 1, 0, {
195
+ role: 'system',
196
+ content: (0, generate_output_1.metadataOutputFormatPrompt)(outputSchema),
197
+ });
198
+ }
199
+ }
200
+ if (!messagesWithSystemPrompt.length)
201
+ return undefined;
202
+ this.context.callback?.({
203
+ type: types_1.AssistantResponseType.INPUT,
204
+ assistantId: agent.id,
205
+ parentTaskId,
206
+ taskId,
207
+ assistantName: agent.name,
208
+ inputParameters: this.hideSecretInputs(inputs, agent),
209
+ promptMessages: messagesWithSystemPrompt,
210
+ });
211
+ const run = async () => {
212
+ this.retryTimes += 1;
213
+ let result = '';
214
+ const metadataStrings = [];
215
+ const chatCompletionChunk = await this.callAIOrExecutor({ messages: messagesWithSystemPrompt, inputs });
216
+ const stream = (0, generate_output_1.extractMetadataFromStream)(chatCompletionChunk.pipeThrough(new web_1.TransformStream({
217
+ transform: (chunk, controller) => {
218
+ if ((0, index_1.isChatCompletionUsage)(chunk)) {
219
+ this.context.callback?.({
220
+ type: types_1.AssistantResponseType.USAGE,
221
+ taskId,
222
+ assistantId: agent.id,
223
+ usage: chunk.usage,
224
+ });
225
+ }
226
+ controller.enqueue(chunk);
227
+ },
228
+ })), hasJsonOutputs);
229
+ for await (const chunk of stream) {
230
+ if (chunk.type === 'text') {
231
+ const { text } = chunk;
232
+ result += text;
233
+ if (hasStreamingTextOutput && this.retryTimes === 1) {
234
+ this.context.callback?.({
235
+ type: types_1.AssistantResponseType.CHUNK,
236
+ taskId,
237
+ assistantId: agent.id,
238
+ delta: { content: text },
239
+ });
240
+ }
241
+ }
242
+ else if (chunk.type === 'match') {
243
+ metadataStrings.push(chunk.text);
244
+ }
245
+ }
246
+ const json = {};
247
+ for (const i of metadataStrings) {
248
+ try {
249
+ const obj = JSON.parse(i);
250
+ Object.assign(json, obj);
251
+ }
252
+ catch {
253
+ // ignore
254
+ }
255
+ }
256
+ // try to parse all text content as a json
257
+ try {
258
+ Object.assign(json, JSON.parse(result));
259
+ }
260
+ catch {
261
+ // ignore
262
+ }
263
+ try {
264
+ return await super.validateOutputs({
265
+ inputs,
266
+ outputs: { ...json, $text: result },
267
+ });
268
+ }
269
+ catch (error) {
270
+ config_1.logger.error('validate LLM outputs error', error);
271
+ throw new Error('Unexpected response format from AI');
272
+ }
273
+ };
274
+ return await (0, retry_1.default)(run, this.context.maxRetries);
275
+ }
276
+ async processWithJsonSchemaFormat({ messages, inputs, }) {
277
+ const { agent, options: { parentTaskId, taskId }, } = this;
278
+ this.context.callback?.({
279
+ type: types_1.AssistantResponseType.INPUT,
280
+ assistantId: agent.id,
281
+ parentTaskId,
282
+ taskId,
283
+ assistantName: agent.name,
284
+ inputParameters: this.hideSecretInputs(inputs, agent),
285
+ promptMessages: messages,
286
+ });
287
+ const { hasStreamingTextOutput, schema } = await this.outputsInfo;
288
+ const [json, { text }] = await Promise.all([
289
+ this.callAIGetJsonOutput({ messages, schema }),
290
+ hasStreamingTextOutput ? this.callAIGetTextStreamOutput({ messages, inputs }) : { text: undefined },
291
+ ]);
292
+ try {
293
+ return await super.validateOutputs({
294
+ inputs,
295
+ outputs: { ...json, $text: text },
296
+ });
297
+ }
298
+ catch (error) {
299
+ config_1.logger.error('validate LLM outputs error', error);
300
+ throw new Error('Unexpected response format from AI');
301
+ }
302
+ }
303
+ async callAIGetJsonOutput({ messages, schema }) {
304
+ const { modelInfo } = this;
305
+ const result = await this.context.callAI({
306
+ assistant: this.agent,
307
+ input: {
308
+ messages,
309
+ ...modelInfo,
310
+ responseFormat: {
311
+ type: 'json_schema',
312
+ jsonSchema: {
313
+ name: 'output',
314
+ schema: (0, types_1.jsonSchemaToOpenAIJsonSchema)(schema),
315
+ strict: true,
316
+ },
317
+ },
318
+ },
319
+ });
320
+ let json = '';
321
+ for await (const i of result) {
322
+ if ((0, index_1.isChatCompletionChunk)(i)) {
323
+ json += i.delta.content || '';
324
+ }
325
+ }
326
+ try {
327
+ return JSON.parse(json);
328
+ }
329
+ catch (error) {
330
+ config_1.logger.error(json, error);
331
+ throw new Error('parse ai json schema output error');
332
+ }
333
+ }
334
+ async callAIGetTextStreamOutput({ messages, inputs, }) {
335
+ const { agent, options: { taskId }, } = this;
336
+ const stream = await this.callAIOrExecutor({
337
+ messages,
338
+ inputs,
339
+ });
340
+ let text = '';
341
+ for await (const chunk of stream) {
342
+ if ((0, index_1.isChatCompletionChunk)(chunk)) {
343
+ text += chunk.delta.content || '';
344
+ this.context.callback?.({
345
+ type: types_1.AssistantResponseType.CHUNK,
346
+ taskId,
347
+ assistantId: agent.id,
348
+ delta: { content: chunk.delta.content },
349
+ });
350
+ }
351
+ }
352
+ return { text };
353
+ }
354
+ async callAIOrExecutor({ messages, inputs, }) {
355
+ const { agent, modelInfo, options: { taskId }, } = this;
356
+ const e = await this.executor;
357
+ return e
358
+ ? (await this.context
359
+ .executor(e.executor, {
360
+ inputs: {
361
+ ...inputs,
362
+ ...e.inputValues,
363
+ [e.executor.parameters?.find((i) => i.type === 'llmInputMessages' && !i.hidden)?.key]: messages,
364
+ },
365
+ taskId: (0, task_id_1.nextId)(),
366
+ parentTaskId: taskId,
367
+ })
368
+ .execute())[types_1.RuntimeOutputVariable.llmResponseStream]
369
+ : await this.context.callAI({
370
+ assistant: agent,
371
+ input: {
372
+ stream: true,
373
+ messages,
374
+ ...modelInfo,
375
+ },
376
+ });
377
+ }
378
+ }
379
+ exports.LLMAgentExecutor = LLMAgentExecutor;
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.LogicAgentExecutor = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ const quickjs_1 = require("@blocklet/quickjs");
9
+ const component_1 = require("@blocklet/sdk/lib/component");
10
+ const config_1 = __importDefault(require("@blocklet/sdk/lib/config"));
11
+ const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
12
+ const joi_1 = __importDefault(require("joi"));
13
+ const pick_1 = __importDefault(require("lodash/pick"));
14
+ const aid_1 = require("../common/aid");
15
+ const logger_1 = __importDefault(require("../logger"));
16
+ const types_1 = require("../types");
17
+ const ReadableMustache_1 = require("../types/assistant/mustache/ReadableMustache");
18
+ const geti_1 = require("../utils/geti");
19
+ const task_id_1 = require("../utils/task-id");
20
+ const base_1 = require("./base");
21
+ async function parseJSONInVM(str) {
22
+ return quickjs_1.Sandbox.callFunction({
23
+ code: `\
24
+ function parse(json) {
25
+ return eval(\`const j = \${json}; j\`)
26
+ }
27
+ `,
28
+ filename: 'parserJSONInVm.js',
29
+ functionName: 'parse',
30
+ args: [str.trim()],
31
+ });
32
+ }
33
+ class LogicAgentExecutor extends base_1.AgentExecutorBase {
34
+ async process({ inputs }) {
35
+ const { agent, options: { taskId }, } = this;
36
+ if (!agent.code)
37
+ throw new Error(`Assistant ${agent.id}'s code is empty`);
38
+ const args = Object.fromEntries(await Promise.all((agent.parameters ?? [])
39
+ .filter((i) => !!i.key && !i.hidden)
40
+ .map(async (i) => [i.key, inputs?.[i.key] ?? i.defaultValue])));
41
+ const $json = (variables, ...rest) => {
42
+ const taggedFn = async (t, ...rest) => {
43
+ const template = t.map((s, i) => `${s}${i === t.length - 1 ? '' : rest[i]}`).join('');
44
+ const renderCtx = {
45
+ ...args,
46
+ ...variables,
47
+ ...this.globalContext,
48
+ get: () => async (template, render) => {
49
+ const s = await render(template);
50
+ return (0, geti_1.geti)(renderCtx, s);
51
+ },
52
+ runAgent: () => async (template, render) => {
53
+ const t = (await parseJSONInVM(template))?.template;
54
+ const s = await render(template);
55
+ const j = await parseJSONInVM(s);
56
+ const { agentId, inputs } = await joi_1.default.object({
57
+ agentId: joi_1.default.string().required(),
58
+ inputs: joi_1.default.object().pattern(joi_1.default.string(), joi_1.default.any()).required(),
59
+ }).validateAsync(j, { stripUnknown: true });
60
+ const a = await this.context.getAgent({
61
+ aid: (0, aid_1.stringifyIdentity)({ ...(0, aid_1.parseIdentity)(agent.identity.aid, { rejectWhenError: true }), agentId }),
62
+ working: agent.identity.working,
63
+ rejectOnEmpty: true,
64
+ });
65
+ const result = await this.context.execute(a, { taskId: (0, task_id_1.nextId)(), parentTaskId: taskId, inputs });
66
+ return this.renderMessage(t, { ...renderCtx, $result: result }, { escapeJsonSymbols: true });
67
+ },
68
+ };
69
+ const result = (0, ReadableMustache_1.renderMustacheStream)(template, (enqueue) => ({
70
+ ...renderCtx,
71
+ runAgent: () => enqueue(renderCtx.runAgent()),
72
+ }));
73
+ let object;
74
+ for await (const chunk of result) {
75
+ const newObj = await parseJSONInVM(chunk);
76
+ // skip if the object is equal
77
+ // TODO: throttle the output
78
+ if ((0, fast_deep_equal_1.default)(object, newObj)) {
79
+ continue;
80
+ }
81
+ object = newObj;
82
+ try {
83
+ const obj = await this.validateOutputs({ outputs: object, partial: true });
84
+ this.context.callback?.({
85
+ type: types_1.AssistantResponseType.CHUNK,
86
+ taskId,
87
+ assistantId: agent.id,
88
+ delta: { object: obj },
89
+ });
90
+ }
91
+ catch (error) {
92
+ logger_1.default.error('validate LLM outputs error', error, object);
93
+ }
94
+ }
95
+ return object;
96
+ };
97
+ // 支持 $json({foo:"xxx"})`` 和 $json`` 两种调用方式
98
+ if (Array.isArray(variables)) {
99
+ return taggedFn(variables, ...rest);
100
+ }
101
+ return taggedFn;
102
+ };
103
+ const log = (...args) => this.context.callback({
104
+ type: types_1.AssistantResponseType.LOG,
105
+ log: JSON.stringify(args),
106
+ timestamp: Date.now(),
107
+ taskId,
108
+ assistantId: agent.id,
109
+ });
110
+ const global = {
111
+ console: {
112
+ // NOTE: do not return logger.xxx result, it will cause memory leak
113
+ log: (...args) => log(...args),
114
+ info: (...args) => log(...args),
115
+ debug: (...args) => log(...args),
116
+ warn: (...args) => log(...args),
117
+ error: (...args) => log(...args),
118
+ },
119
+ getComponentMountPoint: component_1.getComponentMountPoint,
120
+ call: (...args) => (0, component_1.call)(...args).then((res) => ({ data: res.data })),
121
+ crypto: { randomInt: crypto_1.default.randomInt },
122
+ config: { env: (0, pick_1.default)(config_1.default.env, 'appId', 'appName', 'appDescription', 'appUrl') },
123
+ };
124
+ const allArgs = {
125
+ $json,
126
+ runAgent: async ({ agentId, inputs, streaming, }) => {
127
+ const a = await this.context.getAgent({
128
+ aid: (0, aid_1.stringifyIdentity)({ ...(0, aid_1.parseIdentity)(agent.identity.aid, { rejectWhenError: true }), agentId }),
129
+ working: agent.identity.working,
130
+ rejectOnEmpty: true,
131
+ });
132
+ const { callback } = this.context;
133
+ const currentTaskId = (0, task_id_1.nextId)();
134
+ return this.context
135
+ .copy(streaming
136
+ ? {
137
+ callback: function hello(args) {
138
+ callback(args);
139
+ if (args.type === types_1.AssistantResponseType.CHUNK &&
140
+ args.delta.content &&
141
+ args.taskId === currentTaskId) {
142
+ callback({ ...args, taskId });
143
+ }
144
+ },
145
+ }
146
+ : {})
147
+ .execute(a, { taskId: currentTaskId, parentTaskId: taskId, inputs });
148
+ },
149
+ ...this.globalContext,
150
+ ...args,
151
+ };
152
+ const argKeys = Object.keys(allArgs);
153
+ const resultPromise = await quickjs_1.Sandbox.callFunction({
154
+ code: `\
155
+ async function main({${argKeys.join(', ')}) {
156
+ ${agent.code}
157
+ }
158
+ `,
159
+ filename: `${agent.name || agent.id}.js`,
160
+ global,
161
+ functionName: 'main',
162
+ args: [allArgs],
163
+ });
164
+ return resultPromise;
165
+ }
166
+ }
167
+ exports.LogicAgentExecutor = LogicAgentExecutor;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./runtime/runtime"), exports);