@falai/agent 1.0.0 → 1.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 (51) hide show
  1. package/README.md +19 -4
  2. package/dist/cjs/core/Agent.d.ts +10 -0
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +21 -0
  5. package/dist/cjs/core/Agent.js.map +1 -1
  6. package/dist/cjs/core/BatchExecutor.d.ts.map +1 -1
  7. package/dist/cjs/core/BatchExecutor.js +8 -0
  8. package/dist/cjs/core/BatchExecutor.js.map +1 -1
  9. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +1 -1
  10. package/dist/cjs/core/BatchPromptBuilder.js +16 -0
  11. package/dist/cjs/core/BatchPromptBuilder.js.map +1 -1
  12. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
  13. package/dist/cjs/core/ResponseEngine.js +71 -62
  14. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  15. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  16. package/dist/cjs/core/ResponseModal.js +71 -13
  17. package/dist/cjs/core/ResponseModal.js.map +1 -1
  18. package/dist/cjs/types/agent.d.ts +4 -0
  19. package/dist/cjs/types/agent.d.ts.map +1 -1
  20. package/dist/core/Agent.d.ts +10 -0
  21. package/dist/core/Agent.d.ts.map +1 -1
  22. package/dist/core/Agent.js +21 -0
  23. package/dist/core/Agent.js.map +1 -1
  24. package/dist/core/BatchExecutor.d.ts.map +1 -1
  25. package/dist/core/BatchExecutor.js +8 -0
  26. package/dist/core/BatchExecutor.js.map +1 -1
  27. package/dist/core/BatchPromptBuilder.d.ts.map +1 -1
  28. package/dist/core/BatchPromptBuilder.js +17 -1
  29. package/dist/core/BatchPromptBuilder.js.map +1 -1
  30. package/dist/core/ResponseEngine.d.ts.map +1 -1
  31. package/dist/core/ResponseEngine.js +71 -62
  32. package/dist/core/ResponseEngine.js.map +1 -1
  33. package/dist/core/ResponseModal.d.ts.map +1 -1
  34. package/dist/core/ResponseModal.js +71 -13
  35. package/dist/core/ResponseModal.js.map +1 -1
  36. package/dist/types/agent.d.ts +4 -0
  37. package/dist/types/agent.d.ts.map +1 -1
  38. package/docs/README.md +1 -0
  39. package/docs/api/README.md +16 -0
  40. package/docs/api/overview.md +4 -0
  41. package/docs/core/agent/README.md +36 -0
  42. package/docs/core/agent/rules-and-prohibitions.md +113 -0
  43. package/docs/guides/migration/README.md +6 -2
  44. package/docs/guides/migration/multi-step-execution.md +70 -0
  45. package/package.json +1 -1
  46. package/src/core/Agent.ts +24 -0
  47. package/src/core/BatchExecutor.ts +10 -0
  48. package/src/core/BatchPromptBuilder.ts +19 -1
  49. package/src/core/ResponseEngine.ts +91 -91
  50. package/src/core/ResponseModal.ts +85 -27
  51. package/src/types/agent.ts +4 -0
@@ -1028,29 +1028,36 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
1028
1028
  * @private
1029
1029
  */
1030
1030
  private buildBatchResponseSchema(collectFields: string[]): Record<string, unknown> {
1031
- const properties: Record<string, unknown> = {
1032
- message: {
1033
- type: "string",
1034
- description: "Your response to the user",
1035
- },
1036
- };
1031
+ const properties: Record<string, unknown> = {
1032
+ message: {
1033
+ type: "string",
1034
+ description: "Your response to the user",
1035
+ },
1036
+ };
1037
+
1038
+ const agentSchema = this.agent.getSchema();
1039
+
1040
+ // Add collect fields to schema, using agent schema definitions when available
1041
+ for (const field of collectFields) {
1042
+ if (agentSchema?.properties && agentSchema.properties[field]) {
1043
+ properties[field] = agentSchema.properties[field];
1044
+ } else {
1045
+ // Dynamic fallback when no agent schema is defined
1046
+ properties[field] = {
1047
+ type: "string",
1048
+ description: `Collected value for ${field}`,
1049
+ };
1050
+ }
1051
+ }
1037
1052
 
1038
- // Add collect fields to schema
1039
- for (const field of collectFields) {
1040
- properties[field] = {
1041
- type: "string",
1042
- description: `Collected value for ${field}`,
1053
+ return {
1054
+ type: "object",
1055
+ properties,
1056
+ required: ["message"],
1057
+ additionalProperties: true,
1043
1058
  };
1044
1059
  }
1045
1060
 
1046
- return {
1047
- type: "object",
1048
- properties,
1049
- required: ["message"],
1050
- additionalProperties: true,
1051
- };
1052
- }
1053
-
1054
1061
  /**
1055
1062
  * Collect available tools from all steps in the batch
1056
1063
  * @private
@@ -1424,8 +1431,34 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
1424
1431
  }
1425
1432
 
1426
1433
  // Update session with next step
1427
- session = enterStep(session, nextStep.id, nextStep.description);
1428
- logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1434
+ // If the next step has requires fields that are missing, stay at the previous step
1435
+ if (nextStep.requires && nextStep.requires.length > 0) {
1436
+ const sessionData = session.data || {};
1437
+ const missingRequires = nextStep.requires.filter(
1438
+ field => (sessionData as Record<string, unknown>)[String(field)] === undefined
1439
+ );
1440
+ if (missingRequires.length > 0) {
1441
+ const warning = `[Agent] Cannot advance to step "${nextStep.description || nextStep.id}": ` +
1442
+ `missing required fields [${missingRequires.join(', ')}]. Staying at current step.`;
1443
+ logger.warn(warning);
1444
+ console.warn(warning);
1445
+ // Stay at the current step - don't enter the next one
1446
+ const currentStepId = session.currentStep?.id;
1447
+ if (currentStepId) {
1448
+ const currentStepInstance = selectedRoute.getStep(currentStepId);
1449
+ if (currentStepInstance) {
1450
+ nextStep = currentStepInstance;
1451
+ logger.debug(`[ResponseModal] Staying at current step: ${nextStep.id} due to missing requires`);
1452
+ }
1453
+ }
1454
+ } else {
1455
+ session = enterStep(session, nextStep.id, nextStep.description);
1456
+ logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1457
+ }
1458
+ } else {
1459
+ session = enterStep(session, nextStep.id, nextStep.description);
1460
+ logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1461
+ }
1429
1462
 
1430
1463
  // Build response schema for this route (with collect fields from step)
1431
1464
  const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.agent.getSchema());
@@ -1434,8 +1467,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
1434
1467
  const responsePrompt = await this.responseEngine.buildResponsePrompt({
1435
1468
  route: selectedRoute,
1436
1469
  currentStep: nextStep,
1437
- rules: selectedRoute.getRules(),
1438
- prohibitions: selectedRoute.getProhibitions(),
1470
+ rules: [...this.agent.getRules(), ...selectedRoute.getRules()],
1471
+ prohibitions: [...this.agent.getProhibitions(), ...selectedRoute.getProhibitions()],
1439
1472
  directives: responseDirectives,
1440
1473
  history: historyEvents, // Use Event[] for buildResponsePrompt
1441
1474
  lastMessage: lastMessageText, // Use string for buildResponsePrompt
@@ -1544,16 +1577,41 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
1544
1577
  }
1545
1578
 
1546
1579
  // Update session with next step
1547
- session = enterStep(session, nextStep.id, nextStep.description);
1548
- logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1580
+ // If the next step has requires fields that are missing, stay at the previous step
1581
+ if (nextStep.requires && nextStep.requires.length > 0) {
1582
+ const sessionData = session.data || {};
1583
+ const missingRequires = nextStep.requires.filter(
1584
+ field => (sessionData as Record<string, unknown>)[String(field)] === undefined
1585
+ );
1586
+ if (missingRequires.length > 0) {
1587
+ const warning = `[Agent] Cannot advance to step "${nextStep.description || nextStep.id}": ` +
1588
+ `missing required fields [${missingRequires.join(', ')}]. Staying at current step.`;
1589
+ logger.warn(warning);
1590
+ console.warn(warning);
1591
+ const currentStepId = session.currentStep?.id;
1592
+ if (currentStepId) {
1593
+ const currentStepInstance = selectedRoute.getStep(currentStepId);
1594
+ if (currentStepInstance) {
1595
+ nextStep = currentStepInstance;
1596
+ logger.debug(`[ResponseModal] Staying at current step: ${nextStep.id} due to missing requires`);
1597
+ }
1598
+ }
1599
+ } else {
1600
+ session = enterStep(session, nextStep.id, nextStep.description);
1601
+ logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1602
+ }
1603
+ } else {
1604
+ session = enterStep(session, nextStep.id, nextStep.description);
1605
+ logger.debug(`[ResponseModal] Entered step: ${nextStep.id}`);
1606
+ }
1549
1607
 
1550
1608
  // Build response schema and prompt (same as non-streaming)
1551
1609
  const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, nextStep, this.agent.getSchema());
1552
1610
  const responsePrompt = await this.responseEngine.buildResponsePrompt({
1553
1611
  route: selectedRoute,
1554
1612
  currentStep: nextStep,
1555
- rules: selectedRoute.getRules(),
1556
- prohibitions: selectedRoute.getProhibitions(),
1613
+ rules: [...this.agent.getRules(), ...selectedRoute.getRules()],
1614
+ prohibitions: [...this.agent.getProhibitions(), ...selectedRoute.getProhibitions()],
1557
1615
  directives: responseDirectives,
1558
1616
  history: historyEvents, // Use Event[] for buildResponsePrompt
1559
1617
  lastMessage: lastMessageText, // Use string for buildResponsePrompt
@@ -106,6 +106,10 @@ export interface AgentOptions<TContext = unknown, TData = unknown> {
106
106
  persistence?: PersistenceConfig<TData>;
107
107
  /** Knowledge base containing any JSON structure the AI should know */
108
108
  knowledgeBase?: Record<string, unknown>;
109
+ /** Absolute rules the agent must follow across all routes */
110
+ rules?: Template<TContext, TData>[];
111
+ /** Absolute prohibitions the agent must never do across all routes */
112
+ prohibitions?: Template<TContext, TData>[];
109
113
  /** Agent-level data schema defining the complete data structure for collection */
110
114
  schema?: StructuredSchema;
111
115
  /** Initial data to pre-populate when creating the agent */