agentic-api 2.0.31 → 2.0.491

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 (102) hide show
  1. package/dist/src/agents/agents.example.js +21 -22
  2. package/dist/src/agents/authentication.js +1 -2
  3. package/dist/src/agents/prompts.d.ts +5 -4
  4. package/dist/src/agents/prompts.js +44 -87
  5. package/dist/src/agents/reducer.core.d.ts +24 -2
  6. package/dist/src/agents/reducer.core.js +125 -35
  7. package/dist/src/agents/reducer.loaders.d.ts +55 -1
  8. package/dist/src/agents/reducer.loaders.js +114 -1
  9. package/dist/src/agents/reducer.types.d.ts +45 -2
  10. package/dist/src/agents/semantic.js +1 -2
  11. package/dist/src/agents/simulator.d.ts +11 -3
  12. package/dist/src/agents/simulator.executor.d.ts +14 -4
  13. package/dist/src/agents/simulator.executor.js +81 -23
  14. package/dist/src/agents/simulator.js +128 -42
  15. package/dist/src/agents/simulator.prompts.d.ts +9 -7
  16. package/dist/src/agents/simulator.prompts.js +66 -86
  17. package/dist/src/agents/simulator.types.d.ts +23 -5
  18. package/dist/src/agents/simulator.utils.d.ts +7 -2
  19. package/dist/src/agents/simulator.utils.js +31 -11
  20. package/dist/src/agents/system.js +1 -2
  21. package/dist/src/execute/helpers.d.ts +75 -0
  22. package/dist/src/execute/helpers.js +139 -0
  23. package/dist/src/execute/index.d.ts +11 -0
  24. package/dist/src/execute/index.js +44 -0
  25. package/dist/src/execute/legacy.d.ts +46 -0
  26. package/dist/src/execute/legacy.js +460 -0
  27. package/dist/src/execute/modelconfig.d.ts +19 -0
  28. package/dist/src/execute/modelconfig.js +56 -0
  29. package/dist/src/execute/responses.d.ts +55 -0
  30. package/dist/src/execute/responses.js +594 -0
  31. package/dist/src/execute/shared.d.ts +83 -0
  32. package/dist/src/execute/shared.js +188 -0
  33. package/dist/src/index.d.ts +1 -1
  34. package/dist/src/index.js +2 -2
  35. package/dist/src/{princing.openai.d.ts → pricing.llm.d.ts} +6 -0
  36. package/dist/src/pricing.llm.js +255 -0
  37. package/dist/src/prompts.d.ts +13 -4
  38. package/dist/src/prompts.js +221 -114
  39. package/dist/src/rag/embeddings.d.ts +36 -18
  40. package/dist/src/rag/embeddings.js +131 -128
  41. package/dist/src/rag/index.d.ts +5 -5
  42. package/dist/src/rag/index.js +14 -17
  43. package/dist/src/rag/parser.d.ts +2 -1
  44. package/dist/src/rag/parser.js +11 -14
  45. package/dist/src/rag/rag.examples.d.ts +27 -0
  46. package/dist/src/rag/rag.examples.js +151 -0
  47. package/dist/src/rag/rag.manager.d.ts +383 -0
  48. package/dist/src/rag/rag.manager.js +1390 -0
  49. package/dist/src/rag/types.d.ts +128 -12
  50. package/dist/src/rag/types.js +100 -1
  51. package/dist/src/rag/usecase.d.ts +37 -0
  52. package/dist/src/rag/usecase.js +96 -7
  53. package/dist/src/rules/git/git.e2e.helper.js +22 -2
  54. package/dist/src/rules/git/git.health.d.ts +61 -2
  55. package/dist/src/rules/git/git.health.js +333 -11
  56. package/dist/src/rules/git/index.d.ts +2 -2
  57. package/dist/src/rules/git/index.js +13 -1
  58. package/dist/src/rules/git/repo.d.ts +160 -0
  59. package/dist/src/rules/git/repo.js +777 -0
  60. package/dist/src/rules/git/repo.pr.js +117 -13
  61. package/dist/src/rules/git/repo.tools.d.ts +22 -1
  62. package/dist/src/rules/git/repo.tools.js +50 -1
  63. package/dist/src/rules/types.d.ts +27 -14
  64. package/dist/src/rules/utils.matter.d.ts +0 -4
  65. package/dist/src/rules/utils.matter.js +35 -7
  66. package/dist/src/scrapper.d.ts +15 -22
  67. package/dist/src/scrapper.js +58 -110
  68. package/dist/src/stategraph/index.d.ts +1 -1
  69. package/dist/src/stategraph/stategraph.d.ts +56 -2
  70. package/dist/src/stategraph/stategraph.js +134 -6
  71. package/dist/src/stategraph/stategraph.storage.js +8 -0
  72. package/dist/src/stategraph/types.d.ts +27 -0
  73. package/dist/src/types.d.ts +46 -9
  74. package/dist/src/types.js +8 -7
  75. package/dist/src/usecase.d.ts +11 -2
  76. package/dist/src/usecase.js +27 -35
  77. package/dist/src/utils.d.ts +32 -18
  78. package/dist/src/utils.js +87 -129
  79. package/package.json +10 -3
  80. package/dist/src/agents/digestor.test.d.ts +0 -1
  81. package/dist/src/agents/digestor.test.js +0 -45
  82. package/dist/src/agents/reducer.example.d.ts +0 -28
  83. package/dist/src/agents/reducer.example.js +0 -118
  84. package/dist/src/agents/reducer.process.d.ts +0 -16
  85. package/dist/src/agents/reducer.process.js +0 -143
  86. package/dist/src/agents/reducer.tools.d.ts +0 -29
  87. package/dist/src/agents/reducer.tools.js +0 -157
  88. package/dist/src/agents/simpleExample.d.ts +0 -3
  89. package/dist/src/agents/simpleExample.js +0 -38
  90. package/dist/src/agents/system-review.d.ts +0 -5
  91. package/dist/src/agents/system-review.js +0 -181
  92. package/dist/src/agents/systemReview.d.ts +0 -4
  93. package/dist/src/agents/systemReview.js +0 -22
  94. package/dist/src/execute.d.ts +0 -49
  95. package/dist/src/execute.js +0 -564
  96. package/dist/src/princing.openai.js +0 -54
  97. package/dist/src/rag/tools.d.ts +0 -76
  98. package/dist/src/rag/tools.js +0 -196
  99. package/dist/src/rules/user.mapper.d.ts +0 -61
  100. package/dist/src/rules/user.mapper.js +0 -160
  101. package/dist/src/rules/utils/slug.d.ts +0 -22
  102. package/dist/src/rules/utils/slug.js +0 -35
@@ -9,12 +9,20 @@ export interface ToolParameterProperty {
9
9
  required?: string[];
10
10
  additionalProperties?: boolean;
11
11
  items?: ToolParameterProperty;
12
+ minLength?: number;
13
+ maxLength?: number;
14
+ format?: string;
15
+ minimum?: number;
16
+ maximum?: number;
17
+ default?: any;
18
+ [key: string]: any;
12
19
  }
13
20
  export interface ToolParameters {
14
21
  type: string;
15
22
  properties: Record<string, ToolParameterProperty>;
16
23
  required?: string[];
17
24
  additionalProperties?: boolean;
25
+ [key: string]: any;
18
26
  }
19
27
  export interface Tool {
20
28
  type: "function";
@@ -25,6 +33,17 @@ export interface Tool {
25
33
  strict: boolean;
26
34
  };
27
35
  }
36
+ export type ToolContractOutput<T> = {
37
+ status: "ok" | "success" | "empty" | "error" | "transfer_required" | "multiple_results";
38
+ items?: T[];
39
+ meta?: Record<string, any>;
40
+ control?: {
41
+ next_hint?: string;
42
+ can_retry: boolean;
43
+ error_code?: string;
44
+ transfer_message?: string;
45
+ };
46
+ };
28
47
  export interface AgentModelMapping {
29
48
  [key: string]: string;
30
49
  }
@@ -33,21 +52,37 @@ export interface AgentModel {
33
52
  temperature: null;
34
53
  maxTokens: number;
35
54
  topP?: number;
55
+ stream?: boolean;
36
56
  parallel_tool_calls: boolean;
37
- frequencyPenalty?: number;
38
- presencePenalty?: number;
39
57
  stop?: string[] | string;
40
58
  tool_choice?: "auto" | "none" | "required";
41
59
  /**
42
60
  * Timeout in milliseconds for a query.
43
- * If not specified, the default (10 minutes).
61
+ * If not specified, the default (10 minutes).
44
62
  * https://platform.openai.com/docs/guides/flex-processing#api-request-timeouts
45
63
  */
46
64
  timeout?: number;
65
+ verbosity?: string;
66
+ reasoning_effort?: string;
67
+ frequencyPenalty?: number;
68
+ presencePenalty?: number;
69
+ text?: {
70
+ verbosity?: string;
71
+ format?: {
72
+ type: string;
73
+ name?: string;
74
+ schema?: any;
75
+ strict?: boolean;
76
+ };
77
+ };
78
+ reasoning?: {
79
+ effort: string;
80
+ };
47
81
  }
48
82
  export interface AgentConfig {
49
83
  name: string;
50
- model: AgentModel;
84
+ groupName?: string;
85
+ model: string;
51
86
  human?: boolean;
52
87
  publicDescription: string;
53
88
  instructions: string;
@@ -65,8 +100,8 @@ export interface AgentConfig {
65
100
  export interface UserNano {
66
101
  id: string;
67
102
  isAnonymous?: boolean;
68
- role: string;
69
103
  uid?: string;
104
+ [key: string]: any;
70
105
  }
71
106
  export type AgenticCache = {
72
107
  get: <T>(key: string) => Promise<T | null>;
@@ -83,6 +118,7 @@ export interface AgenticContext {
83
118
  session: any;
84
119
  [key: string]: any;
85
120
  currentAgent?: AgentConfig;
121
+ discussionRootAgent?: string;
86
122
  }
87
123
  export type AllAgentConfigsType = Record<string, AgentConfig[]>;
88
124
  export interface Usage {
@@ -128,7 +164,8 @@ export interface ExecutionAction {
128
164
  * - `lastMessage`: The final assistant message content after execution.
129
165
  * - `usage`: Token usage/cost snapshot for the whole execution.
130
166
  * - `error`: Optional error message if something went wrong (non-fatal).
131
- * - `moreThinkin`: When true, caller should continue the execution loop (retro-compat flag).
167
+ *
168
+ * NOTE: `moreThinkin` was removed (obsolete) - reasoning_effort in modelConfig handles this natively
132
169
  */
133
170
  export interface ExecutionResult {
134
171
  runId: string;
@@ -138,7 +175,6 @@ export interface ExecutionResult {
138
175
  lastMessage: string;
139
176
  usage: Usage;
140
177
  error?: string;
141
- moreThinkin: boolean;
142
178
  /**
143
179
  * Human-readable summary formatter. Optional to preserve backward compatibility.
144
180
  */
@@ -150,10 +186,11 @@ export interface ExecutionResult {
150
186
  * Merge strategy:
151
187
  * - `runId`: preserved from the primary accumulator `a`.
152
188
  * - `actions`: appended in order (a.actions then b.actions).
153
- * - `lastMessage`: preserved from `a` unless set elsewhere later in the workflow.
189
+ * - `lastMessage`: prioritize more recent (b) over older (a).
154
190
  * - `usage`: summed field-by-field to accumulate totals across steps.
155
191
  * - `error`: keep the latest non-undefined error (prefer `b`).
156
- * - `moreThinkin`: true if either `a` or `b` requests continued thinking.
192
+ *
193
+ * NOTE: moreThinkin removed (obsolete) - always returns false
157
194
  */
158
195
  export declare function enrichExecutionResult(result: ExecutionResult): ExecutionResult;
159
196
  export declare function executionResultMerge(a: ExecutionResult, b: ExecutionResult): ExecutionResult;
package/dist/src/types.js CHANGED
@@ -8,10 +8,11 @@ exports.executionResultMerge = executionResultMerge;
8
8
  * Merge strategy:
9
9
  * - `runId`: preserved from the primary accumulator `a`.
10
10
  * - `actions`: appended in order (a.actions then b.actions).
11
- * - `lastMessage`: preserved from `a` unless set elsewhere later in the workflow.
11
+ * - `lastMessage`: prioritize more recent (b) over older (a).
12
12
  * - `usage`: summed field-by-field to accumulate totals across steps.
13
13
  * - `error`: keep the latest non-undefined error (prefer `b`).
14
- * - `moreThinkin`: true if either `a` or `b` requests continued thinking.
14
+ *
15
+ * NOTE: moreThinkin removed (obsolete) - always returns false
15
16
  */
16
17
  function enrichExecutionResult(result) {
17
18
  const formatAction = (action, index) => {
@@ -29,7 +30,7 @@ function enrichExecutionResult(result) {
29
30
  if (result.error) {
30
31
  lines.push(`error: ${result.error}`);
31
32
  }
32
- lines.push(`moreThinkin: ${Boolean(result.moreThinkin)}`);
33
+ // moreThinkin removed (obsolete) - reasoning_effort fait le job
33
34
  const actions = result.actions || [];
34
35
  lines.push(`actions (${actions.length}):`);
35
36
  actions.forEach((a, i) => lines.push(` - ${formatAction(a, i)}`));
@@ -42,16 +43,16 @@ function executionResultMerge(a, b) {
42
43
  const merged = {
43
44
  runId: a.runId && a.runId.length > 0 ? a.runId : b.runId,
44
45
  startQuery: a.startQuery || b.startQuery || '',
45
- actions: [...(a.actions || []), ...(b.actions || [])],
46
- lastMessage: a.lastMessage || '',
46
+ actions: [...(a.actions || []), ...(b.actions || [])], // ✅ BUG FIX: Fusionner les actions
47
+ lastMessage: b.lastMessage || a.lastMessage || '', // ✅ BUG FIX: Prioriser le plus récent (b)
47
48
  usage: {
48
49
  prompt: (a.usage?.prompt || 0) + (b.usage?.prompt || 0),
49
50
  completion: (a.usage?.completion || 0) + (b.usage?.completion || 0),
50
51
  total: (a.usage?.total || 0) + (b.usage?.total || 0),
51
52
  cost: (a.usage?.cost || 0) + (b.usage?.cost || 0),
52
53
  },
53
- error: b.error ?? a.error,
54
- moreThinkin: Boolean(a.moreThinkin || b.moreThinkin),
54
+ error: b.error ?? a.error
55
+ // moreThinkin removed (obsolete) - reasoning_effort fait le job
55
56
  };
56
57
  return enrichExecutionResult(merged);
57
58
  }
@@ -1,4 +1,13 @@
1
- export declare function callGPTToExtractUserQueries(inputsection: string, file: string): Promise<{
2
- json: any;
1
+ import { UsecaseExtractionOptions } from "./prompts";
2
+ /**
3
+ * Extrait les use cases d'une section de document en utilisant un LLM via executeQuery
4
+ *
5
+ * @param inputsection - Le contenu de la section à analyser
6
+ * @param file - Le nom du fichier source
7
+ * @param options - Options d'extraction (optionnel)
8
+ * @returns Promise avec le JSON des queries et le coût
9
+ */
10
+ export declare function llmExtractUserQueries(inputsection: string, file: string, options?: UsecaseExtractionOptions): Promise<{
11
+ json: string;
3
12
  cost: number;
4
13
  }>;
@@ -1,44 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.callGPTToExtractUserQueries = callGPTToExtractUserQueries;
4
- const princing_openai_1 = require("./princing.openai");
3
+ exports.llmExtractUserQueries = llmExtractUserQueries;
5
4
  const prompts_1 = require("./prompts");
6
- const utils_1 = require("./utils");
7
- async function callGPTToExtractUserQueries(inputsection, file) {
8
- const openai = (0, utils_1.openaiInstance)();
5
+ const execute_1 = require("./execute");
6
+ /**
7
+ * Extrait les use cases d'une section de document en utilisant un LLM via executeQuery
8
+ *
9
+ * @param inputsection - Le contenu de la section à analyser
10
+ * @param file - Le nom du fichier source
11
+ * @param options - Options d'extraction (optionnel)
12
+ * @returns Promise avec le JSON des queries et le coût
13
+ */
14
+ async function llmExtractUserQueries(inputsection, file, options = { model: "LOW-fast" }) {
9
15
  // Format: YYYY-MM-DD
10
16
  const today = new Date().toISOString().substring(0, 10);
11
- // Créer le prompt pour décrire la tâche au LLM
12
- const messages = [
13
- {
14
- role: "system",
15
- content: (0, prompts_1.usecaseExtractionPrompt)(file)
16
- },
17
- {
18
- role: "user",
19
- content: `Nous sommes le ${today}.\nVoici le document à analyser :\n${inputsection}`
20
- }
21
- ];
22
- // WARNING: o3-mini is buggy with "Marche à suivre nouveau bail.pdf"
23
- //const model = "o3-mini";// "gpt-4o-mini";
24
- const model = "gpt-5-mini";
25
- const response = await openai.chat.completions.create({
26
- model: model,
27
- reasoning_effort: "low",
28
- verbosity: "low",
29
- messages,
30
- //reasoning_effort:"low",
31
- response_format: { type: "json_object" }
32
- });
17
+ // Construire le prompt complet en combinant système et utilisateur
18
+ const systemPrompt = (0, prompts_1.usecaseExtractionPrompt)(file);
19
+ const userContent = `Nous sommes le ${today}.\nVoici le document à analyser :\n${inputsection}`;
20
+ // Combiner les prompts pour executeQuery (qui prend un seul message utilisateur)
21
+ const query = `${systemPrompt}\n\n---\n\n${userContent}`;
22
+ //
23
+ // Utiliser executeQuery pour exécuter la requête
33
24
  // response_format: { type: "json_object" }
34
- const cost = (0, princing_openai_1.calculateCost)(model, response.usage);
35
- // Récupérer la réponse markdown
36
- const json = response.choices[0].message.content;
25
+ const result = await (0, execute_1.executeQuery)({
26
+ query,
27
+ model: options.model,
28
+ stdout: execute_1.DummyWritable,
29
+ verbose: false,
30
+ json: true
31
+ });
32
+ const json = result.content;
33
+ const cost = result.usage.cost;
37
34
  console.log(`Markdown 💰 cost: ${cost}`);
38
- //
39
- // add a regex to extract the markdown content between <thinking></thinking> tags
40
- // const thinking = markdown.match(/<thinking>[\s\S]*?<\/thinking>/)?.[0];
41
- // const markdownWithoutThinking = markdown.replace(/<thinking>[\s\S]*?<\/thinking>/g, '');
42
- // return markdownWithoutThinking;
43
35
  return { json, cost };
44
36
  }
@@ -1,6 +1,13 @@
1
1
  import { ParsedFunctionToolCall } from "openai/resources/beta/chat/completions";
2
2
  import { AgentConfig, AgenticContext } from "./types";
3
- export declare const openaiInstance: (openai?: any) => any;
3
+ import OpenAI from "openai";
4
+ /**
5
+ * global openai instance
6
+ */
7
+ declare global {
8
+ var _openaiInstance_: OpenAI | undefined;
9
+ }
10
+ export declare const openaiInstance: (envKey?: string, baseUrl?: string) => OpenAI;
4
11
  /**
5
12
  * Converts a string to a URL-friendly slug
6
13
  * @param text The text to convert to a slug
@@ -8,27 +15,34 @@ export declare const openaiInstance: (openai?: any) => any;
8
15
  * @returns A URL-friendly slug
9
16
  */
10
17
  export declare const toSlug: (text: string, whitespace?: string) => string;
18
+ /**
19
+ * Contrat standard JSON pour le transfert (handoff) entre agents.
20
+ *
21
+ * Ce contrat décrit le format attendu lors d'un transfert via l'outil "transferAgents".
22
+ * Il doit être inclut dans la documentation de l'outil pour garantir l'interopérabilité.
23
+ *
24
+ * Exemple de contrat (format JSON) :
25
+ *
26
+ * ```json
27
+ * {
28
+ * "subject_id": "sha1(intention_normalisee_id|bien|acteur)", // Identifiant unique du sujet
29
+ * "intention": "<string>", // Intention normalisée de la demande
30
+ * "decision_preliminaire": "S1|S2|S3", // Décision préliminaire prise (catégorisation)
31
+ * "meme_sujet_bons_ouverts": "string", // Identifiants ou liens vers dossiers ouverts liés au même sujet
32
+ * "urgency": "standard|prioritaire|urgent", // Niveau d'urgence de la demande
33
+ * "mood": "<string>", // État émotionnel détecté ou exprimé
34
+ * "next_action": "<string>", // Prochaine action préconisée ou à effectuer
35
+ * "multiple_subjects": "string" // Autres sujets/discussions associés (optionnel)
36
+ * }
37
+ * ```
38
+ *
39
+ * À intégrer dans la définition des outils de transfert pour chaque agent métier impliqué dans un handoff.
40
+ */
11
41
  /**
12
42
  * This defines and adds "transferAgents" tool dynamically based on the specified downstreamAgents on each agent.
43
+ * https://github.com/openai/openai-realtime-agents/blob/without-agents-sdk/src/app/agentConfigs/utils.ts
13
44
  */
14
45
  export declare function injectTransferTools(agentDefs: AgentConfig[]): AgentConfig[];
15
46
  export declare function handleTransferCall(discussion: any, currentAgentRef: {
16
47
  name: string;
17
48
  }, agents: AgentConfig[], functionCallParams: ParsedFunctionToolCall, context: AgenticContext): Promise<any>;
18
- /**
19
- * Calls the system review agent to analyze a prompt
20
- *
21
- * This function sends a prompt to the system review agent and returns its analysis.
22
- * The system review agent evaluates prompts based on various criteria like clarity,
23
- * identity, scope, decision logic, etc.
24
- *
25
- * @param {string} prompt - The prompt text to be analyzed by the system review agent
26
- * @param {Object} params - Parameters for the API call
27
- * @param {Object} params.openai - The OpenAI client instance
28
- * @param {Object} params.defaultOptions - Default options to be merged with agent model options
29
- * @returns {Promise<string>} The analysis response from the system review agent
30
- */
31
- export declare function callForSystemReview(prompt: string, params: any): Promise<{
32
- content: any;
33
- cost: number;
34
- }>;
package/dist/src/utils.js CHANGED
@@ -1,21 +1,34 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.toSlug = exports.openaiInstance = void 0;
4
7
  exports.injectTransferTools = injectTransferTools;
5
8
  exports.handleTransferCall = handleTransferCall;
6
- exports.callForSystemReview = callForSystemReview;
7
9
  const prompts_1 = require("./prompts");
8
- const system_1 = require("./agents/system");
9
- const princing_openai_1 = require("./princing.openai");
10
- let _openaiInstance;
11
- const openaiInstance = function (openai) {
12
- if (openai) {
13
- _openaiInstance = openai;
10
+ const openai_1 = __importDefault(require("openai"));
11
+ const openaiInstance = function (envKey, baseUrl) {
12
+ if (globalThis._openaiInstance_) {
13
+ return globalThis._openaiInstance_;
14
+ }
15
+ if (!envKey) {
16
+ throw new Error('AI API key is missing');
17
+ }
18
+ //
19
+ // use multiple fallback if envKey is not set
20
+ const options = {
21
+ apiKey: process.env[envKey] || envKey || process.env.API_LLM_KEY || process.env.OPENAI_API_KEY,
22
+ timeout: 60000 * 15
23
+ };
24
+ if (baseUrl) {
25
+ options.baseURL = baseUrl;
14
26
  }
15
- if (!_openaiInstance) {
27
+ globalThis._openaiInstance_ = new openai_1.default(options);
28
+ if (!globalThis._openaiInstance_) {
16
29
  throw new Error('OpenAI instance has not been initialized');
17
30
  }
18
- return _openaiInstance;
31
+ return globalThis._openaiInstance_;
19
32
  };
20
33
  exports.openaiInstance = openaiInstance;
21
34
  /**
@@ -40,8 +53,32 @@ const toSlug = (text, whitespace = '-') => {
40
53
  .replace(new RegExp(`^\\${whitespace}+|\\${whitespace}+$`, 'g'), ''); // Trim whitespace char (escape for regex)
41
54
  };
42
55
  exports.toSlug = toSlug;
56
+ /**
57
+ * Contrat standard JSON pour le transfert (handoff) entre agents.
58
+ *
59
+ * Ce contrat décrit le format attendu lors d'un transfert via l'outil "transferAgents".
60
+ * Il doit être inclut dans la documentation de l'outil pour garantir l'interopérabilité.
61
+ *
62
+ * Exemple de contrat (format JSON) :
63
+ *
64
+ * ```json
65
+ * {
66
+ * "subject_id": "sha1(intention_normalisee_id|bien|acteur)", // Identifiant unique du sujet
67
+ * "intention": "<string>", // Intention normalisée de la demande
68
+ * "decision_preliminaire": "S1|S2|S3", // Décision préliminaire prise (catégorisation)
69
+ * "meme_sujet_bons_ouverts": "string", // Identifiants ou liens vers dossiers ouverts liés au même sujet
70
+ * "urgency": "standard|prioritaire|urgent", // Niveau d'urgence de la demande
71
+ * "mood": "<string>", // État émotionnel détecté ou exprimé
72
+ * "next_action": "<string>", // Prochaine action préconisée ou à effectuer
73
+ * "multiple_subjects": "string" // Autres sujets/discussions associés (optionnel)
74
+ * }
75
+ * ```
76
+ *
77
+ * À intégrer dans la définition des outils de transfert pour chaque agent métier impliqué dans un handoff.
78
+ */
43
79
  /**
44
80
  * This defines and adds "transferAgents" tool dynamically based on the specified downstreamAgents on each agent.
81
+ * https://github.com/openai/openai-realtime-agents/blob/without-agents-sdk/src/app/agentConfigs/utils.ts
45
82
  */
46
83
  function injectTransferTools(agentDefs) {
47
84
  // Iterate over each agent definition
@@ -50,67 +87,18 @@ function injectTransferTools(agentDefs) {
50
87
  return;
51
88
  }
52
89
  const downstreamAgents = agentDef.downstreamAgents || [];
53
- //
54
- // Add the think tool if maxSteps is set
55
- // https://www.aihero.dev/implementing-anthropics-think-tool-in-typescript
56
- if (agentDef.maxSteps && agentDef.maxSteps > 0) {
57
- const description = `
58
- Use the tool as a helper to think about something with a plan of multiple steps.
59
- It will not obtain new information or change the database, but just append the thought to the log.
60
- Use it when complex reasoning or some cache memory is needed.
61
- To avoid infinite thinking, the tool is limited to ${agentDef.maxSteps} calls.
62
-
63
- It takes two arguments:
64
- - thought (str): A thought to think about.
65
- - step (int): The incremented step number that constrains the global thinking with a limitation of ${agentDef.maxSteps} calls.
66
- `;
67
- const think = {
68
- type: "function",
69
- function: {
70
- name: "thinking",
71
- description,
72
- strict: true,
73
- parameters: {
74
- type: "object",
75
- properties: {
76
- justification: {
77
- type: "string",
78
- description: "The reasoning why this thinking is needed.",
79
- },
80
- thought: {
81
- type: "string",
82
- description: "A thought to think about.",
83
- },
84
- step: {
85
- type: "number",
86
- description: "The incremented step number that constrains the global thinking.",
87
- },
88
- },
89
- required: ["justification", "thought", "step"],
90
- additionalProperties: false,
91
- },
92
- }
93
- };
94
- // Ensure the agent has a tools array
95
- if (!agentDef.tools) {
96
- agentDef.tools = [];
97
- }
98
- console.log('--- DBG addTools', agentDef.name, 'with think step', agentDef.maxSteps);
99
- // Add the newly created tool to the current agent's tools
100
- agentDef.tools.push(think);
101
- }
102
90
  // Only proceed if there are downstream agents
103
91
  if (downstreamAgents.length > 0) {
104
92
  // Build a list of downstream agents and their descriptions for the prompt
105
93
  const availableAgentsList = downstreamAgents
106
- .map((dAgent) => `- ${dAgent.name}: ${dAgent.publicDescription ?? "No description"} ${dAgent.human ? '(human agent, less specialized)' : ''}`)
94
+ .map((dAgent) => `- ${dAgent.name}: ${dAgent.publicDescription ?? "No description"} ${dAgent.human ? '(⚠️ root agent for orientation)' : ''}`)
107
95
  .join("\n");
108
96
  // Create the transfer_agent tool specific to this agent
109
97
  const transferAgentTool = {
110
98
  type: "function",
111
99
  function: {
112
100
  name: "transferAgents",
113
- description: `${prompts_1.transferAgentPrompt.replace('__AGENT_NAME__', agentDef.name)}
101
+ description: `${prompts_1.transferAgentPromptStructured.replace('__AGENT_NAME__', agentDef.name)}
114
102
  ${availableAgentsList}
115
103
  `,
116
104
  parameters: {
@@ -126,7 +114,7 @@ ${availableAgentsList}
126
114
  },
127
115
  destination_agent: {
128
116
  type: "string",
129
- description: "The more specialized destination_agent that should handle the users intended request.",
117
+ description: "The more specialized destination_agent that should handle the user's intended request.",
130
118
  enum: downstreamAgents.map((dAgent) => dAgent.name),
131
119
  },
132
120
  confidence: {
@@ -151,7 +139,7 @@ ${availableAgentsList}
151
139
  }
152
140
  // Add the newly created tool to the current agent's tools
153
141
  agentDef.tools.push(transferAgentTool);
154
- // console.log('--- DBG injectTransferTools',agentDef.name,'with new transfer',JSON.stringify(transferAgentTool.function.parameters,null,2 ));
142
+ // console.log('--- DBG injectTransferTools',agentDef.name,transferAgentTool.function.description);
155
143
  }
156
144
  // so .stringify doesn't break with circular dependencies
157
145
  agentDef.downstreamAgents = agentDef.downstreamAgents?.map(({ name, publicDescription, human }) => ({
@@ -166,6 +154,14 @@ ${availableAgentsList}
166
154
  //
167
155
  // Fonction pour gérer un appel de fonction retourné par OpenAI
168
156
  // le contexte est un objet qui contient des informations supplémentaires de session
157
+ //
158
+ // TODO [Phase 2 - openai-agents-js]:
159
+ // Cette logique de handleTransferCall sera remplacée par le handoff natif
160
+ // de openai-agents-js (https://openai.github.io/openai-agents-js/)
161
+ // qui gère les transferts via policies et router intégrés.
162
+ // Les concepts de downstreamAgents et confidence seront mappés
163
+ // vers les primitives de l'Agent SDK (swarm.run, handoff strategies).
164
+ // Le stateGraph restera compatible car il utilise AgentMessage générique.
169
165
  async function handleTransferCall(discussion, currentAgentRef, agents, functionCallParams, context) {
170
166
  const currentAgentName = currentAgentRef.name;
171
167
  const args = JSON.parse(functionCallParams?.function?.arguments || '{}');
@@ -194,18 +190,26 @@ async function handleTransferCall(discussion, currentAgentRef, agents, functionC
194
190
  if (destinationAgent) {
195
191
  //console.log(`🤖 Agent "${destinationAgent.name}" en préparation`);
196
192
  currentAgentRef.name = destinationAgent.name;
193
+ //
194
+ // Generate ID for CONTEXT TRAIL (loop detection)
195
+ const transferId = (0, exports.toSlug)(args.rationale_for_transfer);
197
196
  return {
198
- feedback: args.rationale_for_transfer,
197
+ name: functionCallParams.function.name, // ← tool pour addStep
198
+ feedback: args.rationale_for_transfer, // ← reason pour addStep
199
+ context: `${currentAgentName} → ${destinationAgentName}`, // ← context pour addStep
200
+ id: transferId, // ← ID optionnel pour addStep
199
201
  destination_agent: destinationAgentName,
200
202
  source_agent: currentAgentName,
201
- did_transfer: true,
202
- name: functionCallParams.function.name
203
+ content: '', // ✅ Transfert silencieux
204
+ did_transfer: true
203
205
  };
204
206
  }
205
207
  else {
206
- console.log(" Agent non trouvé !");
208
+ console.log(`❌L'agent destination "${destinationAgentName}" n'a pas été trouvé.`);
207
209
  return {
208
- feedback: "L'agent destination n'a pas été trouvé.",
210
+ feedback: `❌ L'agent destination "${destinationAgentName}" n'a pas été trouvé.`,
211
+ content: `❌L'agent destination "${destinationAgentName}" n'a pas été trouvé.`,
212
+ context: `❌L'agent destination "${destinationAgentName}" n'a pas été trouvé.`,
209
213
  did_transfer: false,
210
214
  name: functionCallParams.function.name
211
215
  };
@@ -226,11 +230,24 @@ async function handleTransferCall(discussion, currentAgentRef, agents, functionC
226
230
  // ⚠️ ALWAYS inject context in tool logic, ALWAYS!
227
231
  const agent = agents.find(a => a.name === currentAgentRef.name);
228
232
  if (agent?.toolLogic && agent.toolLogic[functionCallParams.function.name]) {
229
- const { content, usage } = await agent.toolLogic[functionCallParams.function.name](args, context);
233
+ const rawResult = await agent.toolLogic[functionCallParams.function.name](args, context);
234
+ //
235
+ // ✅ Le tool peut retourner { content, context, id, usage? } OU ToolContractOutput
236
+ // - Si content existe → utiliser le texte formaté
237
+ // - Sinon → préserver rawResult pour sérialisation (ToolContractOutput)
238
+ // - context: identifiant sémantique unique pour le trail (ex: "intention_123", "daily-events")
239
+ // - id: slug unique pour détection de boucles (généralement dérivé du context)
240
+ // Si le tool ne fournit pas context/id, on utilise le nom du tool comme fallback
241
+ const toolContext = rawResult.context || 'Null';
242
+ const toolId = rawResult.id || args.justification || JSON.stringify(args);
230
243
  return {
231
- content,
244
+ content: rawResult.content, // ✅ Peut être undefined pour ToolContractOutput
232
245
  name: functionCallParams.function.name,
233
- usage
246
+ context: toolContext,
247
+ id: toolId,
248
+ usage: rawResult.usage,
249
+ feedback: rawResult.feedback,
250
+ rawResult: rawResult // ✅ Préserver le résultat brut pour sérialisation
234
251
  };
235
252
  }
236
253
  else {
@@ -244,62 +261,3 @@ async function handleTransferCall(discussion, currentAgentRef, agents, functionC
244
261
  };
245
262
  }
246
263
  }
247
- /**
248
- * Calls the system review agent to analyze a prompt
249
- *
250
- * This function sends a prompt to the system review agent and returns its analysis.
251
- * The system review agent evaluates prompts based on various criteria like clarity,
252
- * identity, scope, decision logic, etc.
253
- *
254
- * @param {string} prompt - The prompt text to be analyzed by the system review agent
255
- * @param {Object} params - Parameters for the API call
256
- * @param {Object} params.openai - The OpenAI client instance
257
- * @param {Object} params.defaultOptions - Default options to be merged with agent model options
258
- * @returns {Promise<string>} The analysis response from the system review agent
259
- */
260
- async function callForSystemReview(prompt, params) {
261
- const { openai, defaultOptions } = params;
262
- const agent = system_1.system;
263
- const options = Object.assign({}, agent.model, defaultOptions || {});
264
- const jsonOptions = `
265
- - L'option JSON a été activée, tu dois respecter le format brut suivant \`
266
- {
267
- directives: [
268
- {"directive": "...","criteria": [{"criterion": "...","score": "...","comment": "..."}]},
269
- ...
270
- ]
271
- }
272
- \``;
273
- //
274
- // add the initial agent to his memory
275
- // Handle two-shot prompting: if instructions is an array, use the first part as a system message
276
- const instructions = agent.instructions;
277
- options.messages = [
278
- { role: "system", content: instructions }
279
- ];
280
- if (options.response_format?.type == "json_object") {
281
- options.messages.push({ role: "user", content: jsonOptions });
282
- }
283
- options.messages.push({ role: "user", content: `tu dois analyser toutes les directives:\n ${prompt}` });
284
- let thinking = 1;
285
- //
286
- // loop until the agent has finished thinking
287
- do {
288
- const response = await openai.chat.completions.create(options);
289
- const cost = (0, princing_openai_1.calculateCost)(options.model, response.usage);
290
- if (options.response_format?.type == "json_object") {
291
- const content = JSON.parse(response.choices[0].message.content || '{}');
292
- return { content, cost };
293
- }
294
- // Handle two-shot prompting: if instructions is an array, send the second part as a user message
295
- // This allows for more complex agent behavior by providing additional context or instructions
296
- // after the initial response, similar to chain-of-thought prompting
297
- if (!Array.isArray(agent.instructions) || thinking >= agent.instructions.length) {
298
- const content = response.choices[0].message.content;
299
- return { content, cost };
300
- }
301
- const instructions = agent.instructions[thinking];
302
- options.messages.push({ role: "user", content: instructions });
303
- thinking++;
304
- } while (true);
305
- }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-api",
3
- "version": "2.0.31",
3
+ "version": "2.0.491",
4
4
  "description": "API pour l'orchestration d'agents intelligents avec séquences et escalades automatiques",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -10,7 +10,13 @@
10
10
  "scripts": {
11
11
  "prebuild": "npm version patch --no-git-tag-version",
12
12
  "build": "tsc",
13
- "test": "jest",
13
+ "test": "jest --silent",
14
+ "test:quiet": "jest --testPathIgnorePatterns=agent* --silent tests",
15
+ "test:verbose": "jest --testPathIgnorePatterns=agent* --verbose tests",
16
+ "test:simulator": "jest --testNamePattern=simulator.* --silent tests",
17
+ "test:simulator:quiet": "jest --testNamePattern=simulator.* --silent tests",
18
+ "test:merge-recovery": "jest --testPathPattern=merge-recovery --verbose",
19
+ "test:merge-recovery:single": "jest --testPathPattern=merge-recovery --testNamePattern=corrupted-index-from-previous-pr --verbose",
14
20
  "lint": "eslint 'src/**/*.ts'",
15
21
  "prepublishOnly": "npm run build",
16
22
  "extract:pdf": "texttopdf ",
@@ -21,12 +27,13 @@
21
27
  },
22
28
  "dependencies": {
23
29
  "@mozilla/readability": "^0.6.0",
30
+ "async-mutex": "^0.5.0",
24
31
  "dotenv": "^16.4.7",
25
32
  "hnswlib-node": "^3.0.0",
26
33
  "jsdom": "^26.0.0",
27
34
  "minisearch": "^7.1.0",
28
35
  "natural": "^8.1.0",
29
- "openai": "^4.102.0",
36
+ "openai": "^5.23.2",
30
37
  "simple-git": "^3.27.0",
31
38
  "stopwords-fr": "^0.3.0"
32
39
  },