@almadar/agent 1.3.1 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/index.d.ts +730 -2
- package/dist/agent/index.js +2057 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/{firestore-checkpointer-CkNKXoun.d.ts → firestore-checkpointer-BkFR-sZM.d.ts} +1 -1
- package/dist/index.d.ts +767 -5
- package/dist/index.js +3311 -1801
- package/dist/index.js.map +1 -1
- package/dist/{index-BN4d3ObG.d.ts → interrupt-config-Bib_RCTB.d.ts} +2 -3
- package/dist/persistence/index.d.ts +2 -2
- package/package.json +4 -4
package/dist/agent/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { AgentDomainCategorySchema, isOrbitalDefinition, isEntityReference, getT
|
|
|
2
2
|
import { getFullOrbitalPrompt, getRequirementsTraitPrompt, getKeyBehaviorsReference, getSExprQuickRef, getCommonErrorsSection, getArchitectureSection } from '@almadar/skills';
|
|
3
3
|
import { tool } from '@langchain/core/tools';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { LLMClient, ANTHROPIC_MODELS, createAnthropicClient, OPENROUTER_MODELS, createOpenRouterClient, KIMI_MODELS, createKimiClient, OPENAI_MODELS, createOpenAIClient, DEEPSEEK_MODELS, createDeepSeekClient } from '@almadar/llm';
|
|
5
|
+
import { LLMClient, ANTHROPIC_MODELS, createAnthropicClient, OPENROUTER_MODELS, createOpenRouterClient, KIMI_MODELS, createKimiClient, OPENAI_MODELS, createOpenAIClient, DEEPSEEK_MODELS, createDeepSeekClient, createRequirementsClient } from '@almadar/llm';
|
|
6
6
|
import { FilesystemBackend, createDeepAgent } from 'deepagents';
|
|
7
7
|
import { MemorySaver } from '@langchain/langgraph';
|
|
8
8
|
export { Command } from '@langchain/langgraph';
|
|
@@ -4692,6 +4692,2061 @@ function getBudgetWarningMessage(eventCount, budget) {
|
|
|
4692
4692
|
return null;
|
|
4693
4693
|
}
|
|
4694
4694
|
|
|
4695
|
-
|
|
4695
|
+
// src/agent/react-reflection.ts
|
|
4696
|
+
var ReActEngine = class {
|
|
4697
|
+
constructor(options = {}) {
|
|
4698
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
4699
|
+
this.options = {
|
|
4700
|
+
maxIterations: options.maxIterations ?? 10,
|
|
4701
|
+
enableReflection: options.enableReflection ?? true,
|
|
4702
|
+
enableAutoCorrect: options.enableAutoCorrect ?? true,
|
|
4703
|
+
memoryManager: options.memoryManager,
|
|
4704
|
+
onStep: options.onStep ?? (() => {
|
|
4705
|
+
}),
|
|
4706
|
+
onError: options.onError ?? (() => {
|
|
4707
|
+
})
|
|
4708
|
+
};
|
|
4709
|
+
}
|
|
4710
|
+
/**
|
|
4711
|
+
* Start a new ReAct session
|
|
4712
|
+
*/
|
|
4713
|
+
startSession(userRequest) {
|
|
4714
|
+
const sessionId = `react_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
4715
|
+
const session = {
|
|
4716
|
+
sessionId,
|
|
4717
|
+
userRequest,
|
|
4718
|
+
currentStep: 0,
|
|
4719
|
+
steps: [],
|
|
4720
|
+
maxIterations: this.options.maxIterations,
|
|
4721
|
+
state: "REASONING"
|
|
4722
|
+
};
|
|
4723
|
+
this.sessions.set(sessionId, session);
|
|
4724
|
+
return session;
|
|
4725
|
+
}
|
|
4726
|
+
/**
|
|
4727
|
+
* Execute REASON step
|
|
4728
|
+
*/
|
|
4729
|
+
async reason(sessionId, context) {
|
|
4730
|
+
const session = this.getSession(sessionId);
|
|
4731
|
+
const thought = await this.generateThought(context);
|
|
4732
|
+
const step = {
|
|
4733
|
+
stepNumber: ++session.currentStep,
|
|
4734
|
+
state: "REASONING",
|
|
4735
|
+
thought,
|
|
4736
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
4737
|
+
};
|
|
4738
|
+
session.steps.push(step);
|
|
4739
|
+
session.state = "ACTING";
|
|
4740
|
+
this.options.onStep(step);
|
|
4741
|
+
return step;
|
|
4742
|
+
}
|
|
4743
|
+
/**
|
|
4744
|
+
* Execute ACT step
|
|
4745
|
+
*/
|
|
4746
|
+
async act(sessionId, action, actionInput) {
|
|
4747
|
+
const session = this.getSession(sessionId);
|
|
4748
|
+
const previousStep = session.steps[session.steps.length - 1];
|
|
4749
|
+
const step = {
|
|
4750
|
+
stepNumber: ++session.currentStep,
|
|
4751
|
+
state: "ACTING",
|
|
4752
|
+
thought: previousStep?.thought ?? "",
|
|
4753
|
+
action,
|
|
4754
|
+
actionInput,
|
|
4755
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
4756
|
+
};
|
|
4757
|
+
session.steps.push(step);
|
|
4758
|
+
session.state = "OBSERVING";
|
|
4759
|
+
this.options.onStep(step);
|
|
4760
|
+
return step;
|
|
4761
|
+
}
|
|
4762
|
+
/**
|
|
4763
|
+
* Execute OBSERVE step
|
|
4764
|
+
*/
|
|
4765
|
+
async observe(sessionId, observation) {
|
|
4766
|
+
const session = this.getSession(sessionId);
|
|
4767
|
+
const previousStep = session.steps[session.steps.length - 1];
|
|
4768
|
+
const step = {
|
|
4769
|
+
stepNumber: ++session.currentStep,
|
|
4770
|
+
state: "OBSERVING",
|
|
4771
|
+
thought: previousStep?.thought ?? "",
|
|
4772
|
+
action: previousStep?.action,
|
|
4773
|
+
actionInput: previousStep?.actionInput,
|
|
4774
|
+
observation,
|
|
4775
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
4776
|
+
};
|
|
4777
|
+
session.steps.push(step);
|
|
4778
|
+
session.state = this.options.enableReflection ? "REFLECTING" : "COMPLETE";
|
|
4779
|
+
this.options.onStep(step);
|
|
4780
|
+
return step;
|
|
4781
|
+
}
|
|
4782
|
+
/**
|
|
4783
|
+
* Execute REFLECT step
|
|
4784
|
+
*/
|
|
4785
|
+
async reflect(sessionId, result) {
|
|
4786
|
+
const session = this.getSession(sessionId);
|
|
4787
|
+
const previousStep = session.steps[session.steps.length - 1];
|
|
4788
|
+
const reflection = await this.performReflection(session, result);
|
|
4789
|
+
const step = {
|
|
4790
|
+
stepNumber: ++session.currentStep,
|
|
4791
|
+
state: "REFLECTING",
|
|
4792
|
+
thought: previousStep?.thought ?? "",
|
|
4793
|
+
action: previousStep?.action,
|
|
4794
|
+
actionInput: previousStep?.actionInput,
|
|
4795
|
+
observation: previousStep?.observation,
|
|
4796
|
+
reflection: reflection.notes,
|
|
4797
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
4798
|
+
};
|
|
4799
|
+
session.steps.push(step);
|
|
4800
|
+
if (reflection.shouldCorrect && this.options.enableAutoCorrect) {
|
|
4801
|
+
session.state = "CORRECTING";
|
|
4802
|
+
} else {
|
|
4803
|
+
session.state = "COMPLETE";
|
|
4804
|
+
}
|
|
4805
|
+
this.options.onStep(step);
|
|
4806
|
+
return { step, reflection };
|
|
4807
|
+
}
|
|
4808
|
+
/**
|
|
4809
|
+
* Execute CORRECT step (auto-correction)
|
|
4810
|
+
*/
|
|
4811
|
+
async correct(sessionId, correctionAction, correctionInput) {
|
|
4812
|
+
const session = this.getSession(sessionId);
|
|
4813
|
+
const previousStep = session.steps[session.steps.length - 1];
|
|
4814
|
+
const step = {
|
|
4815
|
+
stepNumber: ++session.currentStep,
|
|
4816
|
+
state: "CORRECTING",
|
|
4817
|
+
thought: `Correcting: ${previousStep?.reflection}`,
|
|
4818
|
+
action: correctionAction,
|
|
4819
|
+
actionInput: correctionInput,
|
|
4820
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
4821
|
+
};
|
|
4822
|
+
session.steps.push(step);
|
|
4823
|
+
session.state = "OBSERVING";
|
|
4824
|
+
this.options.onStep(step);
|
|
4825
|
+
if (this.options.memoryManager) {
|
|
4826
|
+
await this.storeCorrection(session, step);
|
|
4827
|
+
}
|
|
4828
|
+
return step;
|
|
4829
|
+
}
|
|
4830
|
+
/**
|
|
4831
|
+
* Handle errors with context preservation
|
|
4832
|
+
*/
|
|
4833
|
+
async handleError(sessionId, error, context) {
|
|
4834
|
+
const session = this.getSession(sessionId);
|
|
4835
|
+
const step = {
|
|
4836
|
+
stepNumber: ++session.currentStep,
|
|
4837
|
+
state: "REFLECTING",
|
|
4838
|
+
thought: "",
|
|
4839
|
+
error: error.message,
|
|
4840
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
4841
|
+
};
|
|
4842
|
+
session.steps.push(step);
|
|
4843
|
+
this.options.onError(error, step);
|
|
4844
|
+
if (this.options.memoryManager) {
|
|
4845
|
+
await this.storeError(session, error, context);
|
|
4846
|
+
}
|
|
4847
|
+
return step;
|
|
4848
|
+
}
|
|
4849
|
+
/**
|
|
4850
|
+
* Get session by ID
|
|
4851
|
+
*/
|
|
4852
|
+
getSession(sessionId) {
|
|
4853
|
+
const session = this.sessions.get(sessionId);
|
|
4854
|
+
if (!session) {
|
|
4855
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
4856
|
+
}
|
|
4857
|
+
return session;
|
|
4858
|
+
}
|
|
4859
|
+
/**
|
|
4860
|
+
* Get reflection metrics
|
|
4861
|
+
*/
|
|
4862
|
+
getReflectionMetrics(sessionId) {
|
|
4863
|
+
const session = this.getSession(sessionId);
|
|
4864
|
+
const reflections = session.steps.filter((s) => s.state === "REFLECTING");
|
|
4865
|
+
const corrections = session.steps.filter((s) => s.state === "CORRECTING").length;
|
|
4866
|
+
const errors = session.steps.filter((s) => s.error).length;
|
|
4867
|
+
return {
|
|
4868
|
+
totalSteps: session.currentStep,
|
|
4869
|
+
corrections,
|
|
4870
|
+
errors,
|
|
4871
|
+
averageConfidence: reflections.length > 0 ? 0.8 : 0
|
|
4872
|
+
// Simplified
|
|
4873
|
+
};
|
|
4874
|
+
}
|
|
4875
|
+
// ============================================================================
|
|
4876
|
+
// Private Helpers
|
|
4877
|
+
// ============================================================================
|
|
4878
|
+
async generateThought(context) {
|
|
4879
|
+
return `I need to analyze the request: "${context.request}". Previous attempts: ${context.previousSteps?.length ?? 0}.`;
|
|
4880
|
+
}
|
|
4881
|
+
async performReflection(session, result) {
|
|
4882
|
+
const hasErrors = result === null || typeof result === "object" && result !== null && "error" in result;
|
|
4883
|
+
if (hasErrors) {
|
|
4884
|
+
return {
|
|
4885
|
+
shouldCorrect: true,
|
|
4886
|
+
correctionStrategy: "retry_with_validation",
|
|
4887
|
+
confidence: 0.3,
|
|
4888
|
+
notes: "Result contains errors, correction needed"
|
|
4889
|
+
};
|
|
4890
|
+
}
|
|
4891
|
+
if (session.currentStep >= session.maxIterations) {
|
|
4892
|
+
return {
|
|
4893
|
+
shouldCorrect: false,
|
|
4894
|
+
confidence: 0.9,
|
|
4895
|
+
notes: "Max iterations reached, completing task"
|
|
4896
|
+
};
|
|
4897
|
+
}
|
|
4898
|
+
return {
|
|
4899
|
+
shouldCorrect: false,
|
|
4900
|
+
confidence: 0.9,
|
|
4901
|
+
notes: "Result looks good"
|
|
4902
|
+
};
|
|
4903
|
+
}
|
|
4904
|
+
async storeCorrection(session, step) {
|
|
4905
|
+
if (!this.options.memoryManager) return;
|
|
4906
|
+
console.log(`[ReAct] Storing correction for session ${session.sessionId}`);
|
|
4907
|
+
}
|
|
4908
|
+
async storeError(session, error, context) {
|
|
4909
|
+
if (!this.options.memoryManager) return;
|
|
4910
|
+
console.log(`[ReAct] Storing error for session ${session.sessionId}: ${error.message}`);
|
|
4911
|
+
}
|
|
4912
|
+
};
|
|
4913
|
+
function createReActEngine(options) {
|
|
4914
|
+
return new ReActEngine(options);
|
|
4915
|
+
}
|
|
4916
|
+
|
|
4917
|
+
// src/agent/hitl-v2.ts
|
|
4918
|
+
var HITLv2Manager = class {
|
|
4919
|
+
constructor(options = {}) {
|
|
4920
|
+
this.pendingInterrupts = /* @__PURE__ */ new Map();
|
|
4921
|
+
this.responses = /* @__PURE__ */ new Map();
|
|
4922
|
+
this.checkpoints = /* @__PURE__ */ new Map();
|
|
4923
|
+
this.options = {
|
|
4924
|
+
defaultTimeoutMs: options.defaultTimeoutMs ?? 3e5,
|
|
4925
|
+
// 5 minutes
|
|
4926
|
+
memoryManager: options.memoryManager,
|
|
4927
|
+
onInterrupt: options.onInterrupt,
|
|
4928
|
+
onResponse: options.onResponse
|
|
4929
|
+
};
|
|
4930
|
+
}
|
|
4931
|
+
// ============================================================================
|
|
4932
|
+
// Interrupt Creation
|
|
4933
|
+
// ============================================================================
|
|
4934
|
+
/**
|
|
4935
|
+
* Create a confirmation interrupt
|
|
4936
|
+
*/
|
|
4937
|
+
async confirm(sessionId, question, options = {}) {
|
|
4938
|
+
const payload = {
|
|
4939
|
+
question,
|
|
4940
|
+
severity: options.severity ?? "info",
|
|
4941
|
+
defaultValue: options.defaultValue
|
|
4942
|
+
};
|
|
4943
|
+
const request = await this.createInterrupt(
|
|
4944
|
+
sessionId,
|
|
4945
|
+
"confirm",
|
|
4946
|
+
"Confirmation Required",
|
|
4947
|
+
question,
|
|
4948
|
+
payload,
|
|
4949
|
+
options.timeoutMs,
|
|
4950
|
+
options.context
|
|
4951
|
+
);
|
|
4952
|
+
return this.waitForResponse(request);
|
|
4953
|
+
}
|
|
4954
|
+
/**
|
|
4955
|
+
* Create an edit interrupt
|
|
4956
|
+
*/
|
|
4957
|
+
async edit(sessionId, content, options = {}) {
|
|
4958
|
+
const payload = {
|
|
4959
|
+
content,
|
|
4960
|
+
format: options.format ?? "text",
|
|
4961
|
+
schema: options.schema
|
|
4962
|
+
};
|
|
4963
|
+
const request = await this.createInterrupt(
|
|
4964
|
+
sessionId,
|
|
4965
|
+
"edit",
|
|
4966
|
+
options.title ?? "Edit Content",
|
|
4967
|
+
options.description ?? "Please review and edit the content",
|
|
4968
|
+
payload,
|
|
4969
|
+
options.timeoutMs,
|
|
4970
|
+
options.context
|
|
4971
|
+
);
|
|
4972
|
+
return this.waitForResponse(request);
|
|
4973
|
+
}
|
|
4974
|
+
/**
|
|
4975
|
+
* Create a selection interrupt
|
|
4976
|
+
*/
|
|
4977
|
+
async select(sessionId, options, config = {}) {
|
|
4978
|
+
const payload = {
|
|
4979
|
+
options,
|
|
4980
|
+
multiple: config.multiple
|
|
4981
|
+
};
|
|
4982
|
+
const request = await this.createInterrupt(
|
|
4983
|
+
sessionId,
|
|
4984
|
+
"select",
|
|
4985
|
+
config.title ?? "Make a Selection",
|
|
4986
|
+
config.description ?? "Please select an option",
|
|
4987
|
+
payload,
|
|
4988
|
+
config.timeoutMs,
|
|
4989
|
+
config.context
|
|
4990
|
+
);
|
|
4991
|
+
return this.waitForResponse(request);
|
|
4992
|
+
}
|
|
4993
|
+
/**
|
|
4994
|
+
* Create a text input interrupt
|
|
4995
|
+
*/
|
|
4996
|
+
async text(sessionId, options = {}) {
|
|
4997
|
+
const payload = {
|
|
4998
|
+
placeholder: options.placeholder,
|
|
4999
|
+
multiline: options.multiline,
|
|
5000
|
+
maxLength: options.maxLength
|
|
5001
|
+
};
|
|
5002
|
+
const request = await this.createInterrupt(
|
|
5003
|
+
sessionId,
|
|
5004
|
+
"text",
|
|
5005
|
+
options.title ?? "Input Required",
|
|
5006
|
+
options.description ?? "Please provide input",
|
|
5007
|
+
payload,
|
|
5008
|
+
options.timeoutMs,
|
|
5009
|
+
options.context
|
|
5010
|
+
);
|
|
5011
|
+
return this.waitForResponse(request);
|
|
5012
|
+
}
|
|
5013
|
+
// ============================================================================
|
|
5014
|
+
// Response Handling
|
|
5015
|
+
// ============================================================================
|
|
5016
|
+
/**
|
|
5017
|
+
* Submit a response to an interrupt
|
|
5018
|
+
*/
|
|
5019
|
+
async submitResponse(interruptId, response, userId) {
|
|
5020
|
+
const request = this.pendingInterrupts.get(interruptId);
|
|
5021
|
+
if (!request) {
|
|
5022
|
+
throw new Error(`Interrupt not found or expired: ${interruptId}`);
|
|
5023
|
+
}
|
|
5024
|
+
const responseRecord = {
|
|
5025
|
+
interruptId,
|
|
5026
|
+
response,
|
|
5027
|
+
respondedAt: /* @__PURE__ */ new Date(),
|
|
5028
|
+
userId
|
|
5029
|
+
};
|
|
5030
|
+
this.responses.set(interruptId, responseRecord);
|
|
5031
|
+
this.pendingInterrupts.delete(interruptId);
|
|
5032
|
+
if (this.options.memoryManager) {
|
|
5033
|
+
await this.storeInteraction(request, responseRecord);
|
|
5034
|
+
}
|
|
5035
|
+
this.options.onResponse?.(request, responseRecord);
|
|
5036
|
+
}
|
|
5037
|
+
/**
|
|
5038
|
+
* Cancel an interrupt
|
|
5039
|
+
*/
|
|
5040
|
+
cancelInterrupt(interruptId, reason) {
|
|
5041
|
+
const request = this.pendingInterrupts.get(interruptId);
|
|
5042
|
+
if (!request) return;
|
|
5043
|
+
this.pendingInterrupts.delete(interruptId);
|
|
5044
|
+
console.log(`[HITLv2] Interrupt ${interruptId} cancelled: ${reason ?? "No reason"}`);
|
|
5045
|
+
}
|
|
5046
|
+
// ============================================================================
|
|
5047
|
+
// Time-Travel Debugging
|
|
5048
|
+
// ============================================================================
|
|
5049
|
+
/**
|
|
5050
|
+
* Save a checkpoint for time-travel
|
|
5051
|
+
*/
|
|
5052
|
+
saveCheckpoint(checkpointId, state) {
|
|
5053
|
+
this.checkpoints.set(checkpointId, JSON.parse(JSON.stringify(state)));
|
|
5054
|
+
}
|
|
5055
|
+
/**
|
|
5056
|
+
* Restore a checkpoint
|
|
5057
|
+
*/
|
|
5058
|
+
restoreCheckpoint(checkpointId) {
|
|
5059
|
+
const checkpoint = this.checkpoints.get(checkpointId);
|
|
5060
|
+
if (!checkpoint) return null;
|
|
5061
|
+
return JSON.parse(JSON.stringify(checkpoint));
|
|
5062
|
+
}
|
|
5063
|
+
/**
|
|
5064
|
+
* List available checkpoints
|
|
5065
|
+
*/
|
|
5066
|
+
listCheckpoints() {
|
|
5067
|
+
return Array.from(this.checkpoints.keys());
|
|
5068
|
+
}
|
|
5069
|
+
/**
|
|
5070
|
+
* Rewind to checkpoint and continue
|
|
5071
|
+
*/
|
|
5072
|
+
async rewindToCheckpoint(checkpointId, sessionId, modifyFn) {
|
|
5073
|
+
let state = this.restoreCheckpoint(checkpointId);
|
|
5074
|
+
if (!state) return null;
|
|
5075
|
+
if (modifyFn) {
|
|
5076
|
+
state = modifyFn(state);
|
|
5077
|
+
}
|
|
5078
|
+
console.log(`[HITLv2] Session ${sessionId} rewound to checkpoint ${checkpointId}`);
|
|
5079
|
+
return state;
|
|
5080
|
+
}
|
|
5081
|
+
// ============================================================================
|
|
5082
|
+
// Analytics
|
|
5083
|
+
// ============================================================================
|
|
5084
|
+
/**
|
|
5085
|
+
* Get interrupt statistics
|
|
5086
|
+
*/
|
|
5087
|
+
getStats() {
|
|
5088
|
+
const responses = Array.from(this.responses.values());
|
|
5089
|
+
const totalResponseTime = responses.reduce((sum, r) => {
|
|
5090
|
+
const request = this.pendingInterrupts.get(r.interruptId);
|
|
5091
|
+
if (!request) return sum;
|
|
5092
|
+
return sum + (r.respondedAt.getTime() - request.createdAt.getTime());
|
|
5093
|
+
}, 0);
|
|
5094
|
+
return {
|
|
5095
|
+
pendingCount: this.pendingInterrupts.size,
|
|
5096
|
+
totalHandled: this.responses.size,
|
|
5097
|
+
checkpointsCount: this.checkpoints.size,
|
|
5098
|
+
averageResponseTimeMs: responses.length > 0 ? totalResponseTime / responses.length : 0
|
|
5099
|
+
};
|
|
5100
|
+
}
|
|
5101
|
+
/**
|
|
5102
|
+
* Get pending interrupts for a session
|
|
5103
|
+
*/
|
|
5104
|
+
getPendingForSession(sessionId) {
|
|
5105
|
+
return Array.from(this.pendingInterrupts.values()).filter((req) => req.sessionId === sessionId);
|
|
5106
|
+
}
|
|
5107
|
+
// ============================================================================
|
|
5108
|
+
// Private Helpers
|
|
5109
|
+
// ============================================================================
|
|
5110
|
+
async createInterrupt(sessionId, type, title, description, payload, timeoutMs, partialContext) {
|
|
5111
|
+
const interruptId = `int_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
5112
|
+
const checkpointId = `chk_${interruptId}`;
|
|
5113
|
+
const request = {
|
|
5114
|
+
interruptId,
|
|
5115
|
+
sessionId,
|
|
5116
|
+
type,
|
|
5117
|
+
title,
|
|
5118
|
+
description,
|
|
5119
|
+
context: {
|
|
5120
|
+
checkpointId,
|
|
5121
|
+
currentState: partialContext?.currentState ?? "unknown",
|
|
5122
|
+
previousActions: partialContext?.previousActions ?? [],
|
|
5123
|
+
relevantMemory: partialContext?.relevantMemory
|
|
5124
|
+
},
|
|
5125
|
+
payload,
|
|
5126
|
+
timeoutMs: timeoutMs ?? this.options.defaultTimeoutMs,
|
|
5127
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
5128
|
+
};
|
|
5129
|
+
this.pendingInterrupts.set(interruptId, request);
|
|
5130
|
+
setTimeout(() => {
|
|
5131
|
+
if (this.pendingInterrupts.has(interruptId)) {
|
|
5132
|
+
this.cancelInterrupt(interruptId, "Timeout");
|
|
5133
|
+
}
|
|
5134
|
+
}, request.timeoutMs);
|
|
5135
|
+
this.options.onInterrupt?.(request);
|
|
5136
|
+
return request;
|
|
5137
|
+
}
|
|
5138
|
+
async waitForResponse(request) {
|
|
5139
|
+
return new Promise((resolve2, reject) => {
|
|
5140
|
+
const checkInterval = setInterval(() => {
|
|
5141
|
+
const response = this.responses.get(request.interruptId);
|
|
5142
|
+
if (response) {
|
|
5143
|
+
clearInterval(checkInterval);
|
|
5144
|
+
resolve2(response.response);
|
|
5145
|
+
this.responses.delete(request.interruptId);
|
|
5146
|
+
}
|
|
5147
|
+
if (!this.pendingInterrupts.has(request.interruptId)) {
|
|
5148
|
+
clearInterval(checkInterval);
|
|
5149
|
+
reject(new Error("Interrupt cancelled or expired"));
|
|
5150
|
+
}
|
|
5151
|
+
}, 100);
|
|
5152
|
+
});
|
|
5153
|
+
}
|
|
5154
|
+
async storeInteraction(request, response) {
|
|
5155
|
+
if (!this.options.memoryManager) return;
|
|
5156
|
+
console.log(`[HITLv2] Storing interaction: ${request.type} \u2192 ${JSON.stringify(response.response).slice(0, 50)}`);
|
|
5157
|
+
}
|
|
5158
|
+
};
|
|
5159
|
+
function createHITLv2Manager(options) {
|
|
5160
|
+
return new HITLv2Manager(options);
|
|
5161
|
+
}
|
|
5162
|
+
|
|
5163
|
+
// src/memory/agentic-search.ts
|
|
5164
|
+
var AgenticSearchEngine = class {
|
|
5165
|
+
constructor(memoryManager) {
|
|
5166
|
+
this.memoryManager = memoryManager;
|
|
5167
|
+
}
|
|
5168
|
+
/**
|
|
5169
|
+
* Perform agentic search through memory
|
|
5170
|
+
*/
|
|
5171
|
+
async search(params) {
|
|
5172
|
+
const startTime = Date.now();
|
|
5173
|
+
const strategy = params.strategy ?? "hybrid";
|
|
5174
|
+
const depth = params.depth ?? 3;
|
|
5175
|
+
const limit = params.limit ?? 10;
|
|
5176
|
+
let results = [];
|
|
5177
|
+
switch (strategy) {
|
|
5178
|
+
case "temporal":
|
|
5179
|
+
results = await this.temporalSearch(params, depth, limit);
|
|
5180
|
+
break;
|
|
5181
|
+
case "semantic":
|
|
5182
|
+
results = await this.semanticSearch(params, depth, limit);
|
|
5183
|
+
break;
|
|
5184
|
+
case "pattern":
|
|
5185
|
+
results = await this.patternSearch(params, depth, limit);
|
|
5186
|
+
break;
|
|
5187
|
+
case "hybrid":
|
|
5188
|
+
default:
|
|
5189
|
+
results = await this.hybridSearch(params, depth, limit);
|
|
5190
|
+
break;
|
|
5191
|
+
}
|
|
5192
|
+
results.sort((a, b) => b.relevance - a.relevance);
|
|
5193
|
+
const insights = this.generateInsights(results, params.query);
|
|
5194
|
+
const duration = Date.now() - startTime;
|
|
5195
|
+
return {
|
|
5196
|
+
results: results.slice(0, limit),
|
|
5197
|
+
insights,
|
|
5198
|
+
metadata: {
|
|
5199
|
+
strategy,
|
|
5200
|
+
depth,
|
|
5201
|
+
duration,
|
|
5202
|
+
totalResults: results.length
|
|
5203
|
+
}
|
|
5204
|
+
};
|
|
5205
|
+
}
|
|
5206
|
+
// ============================================================================
|
|
5207
|
+
// Search Strategies
|
|
5208
|
+
// ============================================================================
|
|
5209
|
+
/**
|
|
5210
|
+
* Temporal search - "What did I do last week?"
|
|
5211
|
+
* Navigates memory by time relationships
|
|
5212
|
+
*/
|
|
5213
|
+
async temporalSearch(params, _depth, limit) {
|
|
5214
|
+
const results = [];
|
|
5215
|
+
const isRecentQuery = /recent|last|latest|newest/i.test(params.query);
|
|
5216
|
+
/week|month|day|ago/i.test(params.query);
|
|
5217
|
+
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit * 2);
|
|
5218
|
+
for (const session of sessions) {
|
|
5219
|
+
let relevance = 0.5;
|
|
5220
|
+
let reasoning = "Recent generation session";
|
|
5221
|
+
if (isRecentQuery) {
|
|
5222
|
+
const daysAgo = (Date.now() - session.createdAt.getTime()) / (1e3 * 60 * 60 * 24);
|
|
5223
|
+
relevance = Math.max(0.1, 1 - daysAgo / 30);
|
|
5224
|
+
reasoning = `Created ${Math.round(daysAgo)} days ago`;
|
|
5225
|
+
}
|
|
5226
|
+
const sessionText = `${session.prompt} ${session.entities.join(" ")} ${session.patterns.join(" ")}`.toLowerCase();
|
|
5227
|
+
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
5228
|
+
const termMatches = queryTerms.filter((term) => sessionText.includes(term)).length;
|
|
5229
|
+
relevance += termMatches * 0.1;
|
|
5230
|
+
if (relevance > 0.3) {
|
|
5231
|
+
results.push({
|
|
5232
|
+
type: "session",
|
|
5233
|
+
data: session,
|
|
5234
|
+
relevance: Math.min(1, relevance),
|
|
5235
|
+
reasoning,
|
|
5236
|
+
source: "generation_history",
|
|
5237
|
+
timestamp: session.createdAt
|
|
5238
|
+
});
|
|
5239
|
+
}
|
|
5240
|
+
}
|
|
5241
|
+
return results;
|
|
5242
|
+
}
|
|
5243
|
+
/**
|
|
5244
|
+
* Semantic search - "How did I handle user roles?"
|
|
5245
|
+
* Reasoning-based understanding of structure
|
|
5246
|
+
*/
|
|
5247
|
+
async semanticSearch(params, _depth, limit) {
|
|
5248
|
+
const results = [];
|
|
5249
|
+
const concepts = this.extractConcepts(params.query);
|
|
5250
|
+
const prefs = await this.memoryManager.getUserPreferences(params.userId);
|
|
5251
|
+
if (prefs) {
|
|
5252
|
+
let relevance = 0.3;
|
|
5253
|
+
const matchedConcepts = [];
|
|
5254
|
+
if (concepts.naming && prefs.namingConvention) {
|
|
5255
|
+
relevance += 0.2;
|
|
5256
|
+
matchedConcepts.push(`uses ${prefs.namingConvention}`);
|
|
5257
|
+
}
|
|
5258
|
+
if (concepts.patterns && prefs.preferredPatterns.length > 0) {
|
|
5259
|
+
const matched = prefs.preferredPatterns.filter(
|
|
5260
|
+
(p) => concepts.patterns?.some((cp) => p.toLowerCase().includes(cp.toLowerCase()))
|
|
5261
|
+
);
|
|
5262
|
+
relevance += matched.length * 0.1;
|
|
5263
|
+
matchedConcepts.push(`patterns: ${matched.join(", ")}`);
|
|
5264
|
+
}
|
|
5265
|
+
if (concepts.entities && prefs.commonEntities.length > 0) {
|
|
5266
|
+
const matched = prefs.commonEntities.filter(
|
|
5267
|
+
(e) => concepts.entities?.some((ce) => e.toLowerCase().includes(ce.toLowerCase()))
|
|
5268
|
+
);
|
|
5269
|
+
relevance += matched.length * 0.1;
|
|
5270
|
+
matchedConcepts.push(`entities: ${matched.join(", ")}`);
|
|
5271
|
+
}
|
|
5272
|
+
if (relevance > 0.4) {
|
|
5273
|
+
results.push({
|
|
5274
|
+
type: "preference",
|
|
5275
|
+
data: prefs,
|
|
5276
|
+
relevance: Math.min(1, relevance),
|
|
5277
|
+
reasoning: `User preferences match query concepts: ${matchedConcepts.join("; ")}`,
|
|
5278
|
+
source: "user_preferences",
|
|
5279
|
+
timestamp: prefs.learnedAt
|
|
5280
|
+
});
|
|
5281
|
+
}
|
|
5282
|
+
}
|
|
5283
|
+
if (params.appId) {
|
|
5284
|
+
const project = await this.memoryManager.getProjectContext(params.appId);
|
|
5285
|
+
if (project) {
|
|
5286
|
+
let relevance = 0.3;
|
|
5287
|
+
const projectText = `${project.projectName ?? ""} ${project.description ?? ""} ${project.existingEntities.join(" ")}`.toLowerCase();
|
|
5288
|
+
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
5289
|
+
const termMatches = queryTerms.filter((term) => projectText.includes(term)).length;
|
|
5290
|
+
relevance += termMatches * 0.15;
|
|
5291
|
+
if (relevance > 0.4) {
|
|
5292
|
+
results.push({
|
|
5293
|
+
type: "project",
|
|
5294
|
+
data: project,
|
|
5295
|
+
relevance: Math.min(1, relevance),
|
|
5296
|
+
reasoning: `Project context contains ${termMatches} matching terms`,
|
|
5297
|
+
source: "project_context",
|
|
5298
|
+
timestamp: project.lastUpdatedAt
|
|
5299
|
+
});
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5302
|
+
}
|
|
5303
|
+
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit);
|
|
5304
|
+
for (const session of sessions) {
|
|
5305
|
+
const sessionText = `${session.prompt} ${session.entities.join(" ")}`.toLowerCase();
|
|
5306
|
+
let relevance = 0.3;
|
|
5307
|
+
if (concepts.entities) {
|
|
5308
|
+
const entityMatches = session.entities.filter(
|
|
5309
|
+
(e) => concepts.entities?.some((ce) => e.toLowerCase().includes(ce.toLowerCase()))
|
|
5310
|
+
);
|
|
5311
|
+
relevance += entityMatches.length * 0.15;
|
|
5312
|
+
}
|
|
5313
|
+
if (concepts.patterns) {
|
|
5314
|
+
const patternMatches = session.patterns.filter(
|
|
5315
|
+
(p) => concepts.patterns?.some((cp) => p.toLowerCase().includes(cp.toLowerCase()))
|
|
5316
|
+
);
|
|
5317
|
+
relevance += patternMatches.length * 0.1;
|
|
5318
|
+
}
|
|
5319
|
+
const queryTerms = params.query.toLowerCase().split(/\s+/);
|
|
5320
|
+
const termMatches = queryTerms.filter((term) => sessionText.includes(term)).length;
|
|
5321
|
+
relevance += termMatches * 0.05;
|
|
5322
|
+
if (relevance > 0.4) {
|
|
5323
|
+
results.push({
|
|
5324
|
+
type: "session",
|
|
5325
|
+
data: session,
|
|
5326
|
+
relevance: Math.min(1, relevance),
|
|
5327
|
+
reasoning: `Session contains relevant entities, patterns, or keywords`,
|
|
5328
|
+
source: "generation_history",
|
|
5329
|
+
timestamp: session.createdAt
|
|
5330
|
+
});
|
|
5331
|
+
}
|
|
5332
|
+
}
|
|
5333
|
+
return results;
|
|
5334
|
+
}
|
|
5335
|
+
/**
|
|
5336
|
+
* Pattern search - "Show me all list views I've built"
|
|
5337
|
+
* Searches for specific patterns and effects
|
|
5338
|
+
*/
|
|
5339
|
+
async patternSearch(params, _depth, limit) {
|
|
5340
|
+
const results = [];
|
|
5341
|
+
const patternTerms = ["list", "form", "detail", "card", "table", "chart", "map", "calendar"];
|
|
5342
|
+
const matchedTerms = patternTerms.filter(
|
|
5343
|
+
(term) => params.query.toLowerCase().includes(term)
|
|
5344
|
+
);
|
|
5345
|
+
const patterns = await this.memoryManager.getUserPatterns(params.userId);
|
|
5346
|
+
for (const pattern of patterns) {
|
|
5347
|
+
let relevance = 0.3;
|
|
5348
|
+
let reasoning = `Pattern usage: ${pattern.usageCount} times`;
|
|
5349
|
+
if (matchedTerms.some((term) => pattern.patternId.toLowerCase().includes(term))) {
|
|
5350
|
+
relevance += 0.3;
|
|
5351
|
+
reasoning += ", matches query pattern type";
|
|
5352
|
+
}
|
|
5353
|
+
const successRate = pattern.usageCount > 0 ? pattern.successCount / pattern.usageCount : 0;
|
|
5354
|
+
relevance += successRate * 0.2;
|
|
5355
|
+
if (relevance > 0.4) {
|
|
5356
|
+
results.push({
|
|
5357
|
+
type: "pattern",
|
|
5358
|
+
data: pattern,
|
|
5359
|
+
relevance: Math.min(1, relevance),
|
|
5360
|
+
reasoning: `${reasoning}, ${Math.round(successRate * 100)}% success rate`,
|
|
5361
|
+
source: "pattern_affinity",
|
|
5362
|
+
timestamp: pattern.lastUsedAt
|
|
5363
|
+
});
|
|
5364
|
+
}
|
|
5365
|
+
}
|
|
5366
|
+
const sessions = await this.memoryManager.getUserGenerationHistory(params.userId, limit);
|
|
5367
|
+
for (const session of sessions) {
|
|
5368
|
+
const matchingPatterns = session.patterns.filter(
|
|
5369
|
+
(p) => matchedTerms.some((term) => p.toLowerCase().includes(term))
|
|
5370
|
+
);
|
|
5371
|
+
if (matchingPatterns.length > 0) {
|
|
5372
|
+
results.push({
|
|
5373
|
+
type: "session",
|
|
5374
|
+
data: session,
|
|
5375
|
+
relevance: 0.5 + matchingPatterns.length * 0.1,
|
|
5376
|
+
reasoning: `Session uses patterns: ${matchingPatterns.join(", ")}`,
|
|
5377
|
+
source: "generation_history",
|
|
5378
|
+
timestamp: session.createdAt
|
|
5379
|
+
});
|
|
5380
|
+
}
|
|
5381
|
+
}
|
|
5382
|
+
return results;
|
|
5383
|
+
}
|
|
5384
|
+
/**
|
|
5385
|
+
* Hybrid search - combines all strategies
|
|
5386
|
+
*/
|
|
5387
|
+
async hybridSearch(params, depth, limit) {
|
|
5388
|
+
const [temporal, semantic, pattern] = await Promise.all([
|
|
5389
|
+
this.temporalSearch(params, depth, Math.ceil(limit / 2)),
|
|
5390
|
+
this.semanticSearch(params, depth, Math.ceil(limit / 2)),
|
|
5391
|
+
this.patternSearch(params, depth, Math.ceil(limit / 2))
|
|
5392
|
+
]);
|
|
5393
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5394
|
+
const combined = [];
|
|
5395
|
+
for (const result of [...temporal, ...semantic, ...pattern]) {
|
|
5396
|
+
const key = `${result.type}-${JSON.stringify(result.data)}`;
|
|
5397
|
+
if (!seen.has(key)) {
|
|
5398
|
+
seen.add(key);
|
|
5399
|
+
combined.push(result);
|
|
5400
|
+
}
|
|
5401
|
+
}
|
|
5402
|
+
return combined;
|
|
5403
|
+
}
|
|
5404
|
+
// ============================================================================
|
|
5405
|
+
// Helpers
|
|
5406
|
+
// ============================================================================
|
|
5407
|
+
/**
|
|
5408
|
+
* Extract semantic concepts from query
|
|
5409
|
+
*/
|
|
5410
|
+
extractConcepts(query) {
|
|
5411
|
+
const lower = query.toLowerCase();
|
|
5412
|
+
return {
|
|
5413
|
+
naming: /naming|case|pascal|camel|snake/i.test(lower),
|
|
5414
|
+
validation: /validat|schema|required|optional/i.test(lower),
|
|
5415
|
+
patterns: ["entity", "list", "form", "detail", "card"].filter((p) => lower.includes(p)),
|
|
5416
|
+
entities: this.extractEntityNames(lower),
|
|
5417
|
+
actions: ["create", "update", "delete", "list", "view"].filter((a) => lower.includes(a))
|
|
5418
|
+
};
|
|
5419
|
+
}
|
|
5420
|
+
/**
|
|
5421
|
+
* Extract potential entity names from query
|
|
5422
|
+
*/
|
|
5423
|
+
extractEntityNames(query) {
|
|
5424
|
+
const words = query.split(/\s+/);
|
|
5425
|
+
const entities = [];
|
|
5426
|
+
for (const word of words) {
|
|
5427
|
+
const clean = word.replace(/[^a-zA-Z]/g, "");
|
|
5428
|
+
if (clean.length > 2 && clean[0] === clean[0].toUpperCase()) {
|
|
5429
|
+
entities.push(clean);
|
|
5430
|
+
}
|
|
5431
|
+
}
|
|
5432
|
+
return entities;
|
|
5433
|
+
}
|
|
5434
|
+
/**
|
|
5435
|
+
* Generate insights from search results
|
|
5436
|
+
*/
|
|
5437
|
+
generateInsights(results, query) {
|
|
5438
|
+
const summary = `Found ${results.length} relevant memory items for "${query}"`;
|
|
5439
|
+
const patternResults = results.filter((r) => r.type === "pattern");
|
|
5440
|
+
const patterns = patternResults.length > 0 ? patternResults.slice(0, 3).map((r) => r.data.patternId) : ["No dominant patterns identified"];
|
|
5441
|
+
const sessions = results.filter((r) => r.type === "session");
|
|
5442
|
+
const trends = [];
|
|
5443
|
+
if (sessions.length > 0) {
|
|
5444
|
+
const timestamps = sessions.filter((s) => s.timestamp).map((s) => s.timestamp.getTime()).sort((a, b) => b - a);
|
|
5445
|
+
if (timestamps.length >= 2) {
|
|
5446
|
+
const avgGap = (timestamps[0] - timestamps[timestamps.length - 1]) / (timestamps.length - 1);
|
|
5447
|
+
const daysGap = avgGap / (1e3 * 60 * 60 * 24);
|
|
5448
|
+
if (daysGap < 7) {
|
|
5449
|
+
trends.push("High activity - multiple sessions per week");
|
|
5450
|
+
} else if (daysGap > 30) {
|
|
5451
|
+
trends.push("Sporadic usage - sessions spread out over time");
|
|
5452
|
+
}
|
|
5453
|
+
}
|
|
5454
|
+
}
|
|
5455
|
+
const suggestions = [];
|
|
5456
|
+
if (patterns.length > 0 && !patterns[0].includes("No dominant")) {
|
|
5457
|
+
suggestions.push(`Consider reusing pattern: ${patterns[0]}`);
|
|
5458
|
+
}
|
|
5459
|
+
const projectResults = results.filter((r) => r.type === "project");
|
|
5460
|
+
if (projectResults.length > 0) {
|
|
5461
|
+
suggestions.push("Review existing project conventions for consistency");
|
|
5462
|
+
}
|
|
5463
|
+
const interruptResults = results.filter((r) => r.type === "interrupt");
|
|
5464
|
+
if (interruptResults.length > 3) {
|
|
5465
|
+
suggestions.push("High interrupt frequency - consider adjusting auto-approval settings");
|
|
5466
|
+
}
|
|
5467
|
+
if (suggestions.length === 0) {
|
|
5468
|
+
suggestions.push("No specific suggestions based on current memory");
|
|
5469
|
+
}
|
|
5470
|
+
return { summary, patterns, trends, suggestions };
|
|
5471
|
+
}
|
|
5472
|
+
};
|
|
5473
|
+
function createAgenticSearchEngine(memoryManager) {
|
|
5474
|
+
return new AgenticSearchEngine(memoryManager);
|
|
5475
|
+
}
|
|
5476
|
+
var PreferenceLearner = class {
|
|
5477
|
+
constructor(options) {
|
|
5478
|
+
this.llmClient = options.llmClient ?? createRequirementsClient();
|
|
5479
|
+
this.memoryManager = options.memoryManager;
|
|
5480
|
+
this.confidenceThreshold = options.confidenceThreshold ?? 0.7;
|
|
5481
|
+
}
|
|
5482
|
+
/**
|
|
5483
|
+
* Analyze a session and infer user preferences
|
|
5484
|
+
*/
|
|
5485
|
+
async analyzeSession(session) {
|
|
5486
|
+
const prompt = this.buildAnalysisPrompt(session);
|
|
5487
|
+
const content = await this.llmClient.call({
|
|
5488
|
+
systemPrompt: "You analyze generation sessions and infer user preferences. Respond with JSON.",
|
|
5489
|
+
userPrompt: prompt
|
|
5490
|
+
});
|
|
5491
|
+
return this.parseAnalysisResponse(content);
|
|
5492
|
+
}
|
|
5493
|
+
/**
|
|
5494
|
+
* Learn from a session and update preferences if confidence is high
|
|
5495
|
+
*/
|
|
5496
|
+
async learnFromSession(session) {
|
|
5497
|
+
let preferences = await this.memoryManager.getUserPreferences(session.userId);
|
|
5498
|
+
if (!preferences) {
|
|
5499
|
+
preferences = {
|
|
5500
|
+
id: session.userId,
|
|
5501
|
+
userId: session.userId,
|
|
5502
|
+
namingConvention: "PascalCase",
|
|
5503
|
+
validationStyle: "strict",
|
|
5504
|
+
preferredPatterns: [],
|
|
5505
|
+
commonEntities: [],
|
|
5506
|
+
commonTraits: [],
|
|
5507
|
+
learnedAt: /* @__PURE__ */ new Date(),
|
|
5508
|
+
confidence: 0.5
|
|
5509
|
+
};
|
|
5510
|
+
}
|
|
5511
|
+
const analysis = await this.analyzeSession(session);
|
|
5512
|
+
let updated = false;
|
|
5513
|
+
for (const inference of analysis.inferences) {
|
|
5514
|
+
if (inference.confidence >= this.confidenceThreshold) {
|
|
5515
|
+
switch (inference.field) {
|
|
5516
|
+
case "namingConvention":
|
|
5517
|
+
if (this.isValidNamingConvention(inference.value)) {
|
|
5518
|
+
preferences.namingConvention = inference.value;
|
|
5519
|
+
updated = true;
|
|
5520
|
+
}
|
|
5521
|
+
break;
|
|
5522
|
+
case "validationStyle":
|
|
5523
|
+
if (this.isValidValidationStyle(inference.value)) {
|
|
5524
|
+
preferences.validationStyle = inference.value;
|
|
5525
|
+
updated = true;
|
|
5526
|
+
}
|
|
5527
|
+
break;
|
|
5528
|
+
case "preferredPatterns":
|
|
5529
|
+
if (Array.isArray(inference.value)) {
|
|
5530
|
+
preferences.preferredPatterns = [
|
|
5531
|
+
.../* @__PURE__ */ new Set([...preferences.preferredPatterns, ...inference.value])
|
|
5532
|
+
].slice(0, 10);
|
|
5533
|
+
updated = true;
|
|
5534
|
+
}
|
|
5535
|
+
break;
|
|
5536
|
+
case "commonEntities":
|
|
5537
|
+
if (Array.isArray(inference.value)) {
|
|
5538
|
+
preferences.commonEntities = [
|
|
5539
|
+
.../* @__PURE__ */ new Set([...preferences.commonEntities, ...inference.value])
|
|
5540
|
+
].slice(0, 20);
|
|
5541
|
+
updated = true;
|
|
5542
|
+
}
|
|
5543
|
+
break;
|
|
5544
|
+
}
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5547
|
+
if (updated) {
|
|
5548
|
+
preferences.confidence = Math.min(1, preferences.confidence + 0.05);
|
|
5549
|
+
await this.memoryManager.updateUserPreferences(session.userId, preferences);
|
|
5550
|
+
}
|
|
5551
|
+
return updated ? preferences : null;
|
|
5552
|
+
}
|
|
5553
|
+
/**
|
|
5554
|
+
* Batch learn from multiple sessions
|
|
5555
|
+
*/
|
|
5556
|
+
async batchLearn(sessions) {
|
|
5557
|
+
if (sessions.length === 0) return null;
|
|
5558
|
+
const userId = sessions[0].userId;
|
|
5559
|
+
let preferences = await this.memoryManager.getUserPreferences(userId);
|
|
5560
|
+
if (!preferences) {
|
|
5561
|
+
preferences = {
|
|
5562
|
+
id: userId,
|
|
5563
|
+
userId,
|
|
5564
|
+
namingConvention: "PascalCase",
|
|
5565
|
+
validationStyle: "strict",
|
|
5566
|
+
preferredPatterns: [],
|
|
5567
|
+
commonEntities: [],
|
|
5568
|
+
commonTraits: [],
|
|
5569
|
+
learnedAt: /* @__PURE__ */ new Date(),
|
|
5570
|
+
confidence: 0.5
|
|
5571
|
+
};
|
|
5572
|
+
}
|
|
5573
|
+
const allPatterns = /* @__PURE__ */ new Set();
|
|
5574
|
+
const allEntities = /* @__PURE__ */ new Set();
|
|
5575
|
+
for (const session of sessions) {
|
|
5576
|
+
session.patterns.forEach((p) => allPatterns.add(p));
|
|
5577
|
+
session.entities.forEach((e) => allEntities.add(e));
|
|
5578
|
+
}
|
|
5579
|
+
preferences.preferredPatterns = [...allPatterns].slice(0, 10);
|
|
5580
|
+
preferences.commonEntities = [...allEntities].slice(0, 20);
|
|
5581
|
+
preferences.confidence = Math.min(1, 0.5 + sessions.length * 0.05);
|
|
5582
|
+
const aggregatePrompt = this.buildAggregatePrompt(sessions);
|
|
5583
|
+
const content = await this.llmClient.call({
|
|
5584
|
+
systemPrompt: "You analyze generation sessions and infer user preferences. Respond with JSON.",
|
|
5585
|
+
userPrompt: aggregatePrompt
|
|
5586
|
+
});
|
|
5587
|
+
const analysis = this.parseAnalysisResponse(content);
|
|
5588
|
+
for (const inference of analysis.inferences) {
|
|
5589
|
+
if (inference.confidence >= this.confidenceThreshold) {
|
|
5590
|
+
if (inference.field === "namingConvention" && this.isValidNamingConvention(inference.value)) {
|
|
5591
|
+
preferences.namingConvention = inference.value;
|
|
5592
|
+
}
|
|
5593
|
+
if (inference.field === "validationStyle" && this.isValidValidationStyle(inference.value)) {
|
|
5594
|
+
preferences.validationStyle = inference.value;
|
|
5595
|
+
}
|
|
5596
|
+
}
|
|
5597
|
+
}
|
|
5598
|
+
await this.memoryManager.updateUserPreferences(userId, preferences);
|
|
5599
|
+
return preferences;
|
|
5600
|
+
}
|
|
5601
|
+
// ==========================================================================
|
|
5602
|
+
// Prompt Building
|
|
5603
|
+
// ==========================================================================
|
|
5604
|
+
buildAnalysisPrompt(session) {
|
|
5605
|
+
return `Analyze this generation session and infer the user's preferences.
|
|
5606
|
+
|
|
5607
|
+
Session Details:
|
|
5608
|
+
- Prompt: "${session.prompt}"
|
|
5609
|
+
- Generated Entities: ${session.entities.join(", ")}
|
|
5610
|
+
- Used Patterns: ${session.patterns.join(", ")}
|
|
5611
|
+
- Skill: ${session.skill}
|
|
5612
|
+
|
|
5613
|
+
Schema Excerpt:
|
|
5614
|
+
${JSON.stringify(session.generatedSchema, null, 2).slice(0, 2e3)}
|
|
5615
|
+
|
|
5616
|
+
Analyze and infer:
|
|
5617
|
+
1. Naming convention preference (PascalCase, camelCase, snake_case)
|
|
5618
|
+
2. Validation style (strict, minimal, none)
|
|
5619
|
+
3. Preferred UI patterns
|
|
5620
|
+
4. Common entity types
|
|
5621
|
+
|
|
5622
|
+
Respond in JSON format:
|
|
5623
|
+
{
|
|
5624
|
+
"inferences": [
|
|
5625
|
+
{
|
|
5626
|
+
"field": "namingConvention",
|
|
5627
|
+
"value": "PascalCase",
|
|
5628
|
+
"confidence": 0.85,
|
|
5629
|
+
"reasoning": "User consistently uses PascalCase for entity names"
|
|
5630
|
+
}
|
|
5631
|
+
],
|
|
5632
|
+
"isHighConfidence": true
|
|
5633
|
+
}`;
|
|
5634
|
+
}
|
|
5635
|
+
buildAggregatePrompt(sessions) {
|
|
5636
|
+
const summaries = sessions.slice(0, 10).map((s) => ({
|
|
5637
|
+
prompt: s.prompt.slice(0, 100),
|
|
5638
|
+
entities: s.entities,
|
|
5639
|
+
patterns: s.patterns
|
|
5640
|
+
}));
|
|
5641
|
+
return `Analyze these ${sessions.length} generation sessions and infer the user's aggregate preferences.
|
|
5642
|
+
|
|
5643
|
+
Session Summaries:
|
|
5644
|
+
${JSON.stringify(summaries, null, 2)}
|
|
5645
|
+
|
|
5646
|
+
Infer the user's overall:
|
|
5647
|
+
1. Naming convention preference (PascalCase, camelCase, snake_case)
|
|
5648
|
+
2. Validation style (strict, minimal, none)
|
|
5649
|
+
|
|
5650
|
+
Respond in JSON format:
|
|
5651
|
+
{
|
|
5652
|
+
"inferences": [
|
|
5653
|
+
{
|
|
5654
|
+
"field": "namingConvention",
|
|
5655
|
+
"value": "PascalCase",
|
|
5656
|
+
"confidence": 0.9,
|
|
5657
|
+
"reasoning": "Used PascalCase in 8 out of 10 sessions"
|
|
5658
|
+
}
|
|
5659
|
+
],
|
|
5660
|
+
"isHighConfidence": true
|
|
5661
|
+
}`;
|
|
5662
|
+
}
|
|
5663
|
+
// ==========================================================================
|
|
5664
|
+
// Response Parsing
|
|
5665
|
+
// ==========================================================================
|
|
5666
|
+
parseAnalysisResponse(content) {
|
|
5667
|
+
try {
|
|
5668
|
+
const jsonMatch = content.match(/\{[\s\S]*\}/);
|
|
5669
|
+
if (!jsonMatch) {
|
|
5670
|
+
return { inferences: [], isHighConfidence: false };
|
|
5671
|
+
}
|
|
5672
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
5673
|
+
if (Array.isArray(parsed.inferences)) {
|
|
5674
|
+
return {
|
|
5675
|
+
inferences: parsed.inferences.filter(
|
|
5676
|
+
(inf) => inf.field && inf.value !== void 0 && typeof inf.confidence === "number"
|
|
5677
|
+
),
|
|
5678
|
+
isHighConfidence: parsed.isHighConfidence ?? false
|
|
5679
|
+
};
|
|
5680
|
+
}
|
|
5681
|
+
return { inferences: [], isHighConfidence: false };
|
|
5682
|
+
} catch {
|
|
5683
|
+
return { inferences: [], isHighConfidence: false };
|
|
5684
|
+
}
|
|
5685
|
+
}
|
|
5686
|
+
// ==========================================================================
|
|
5687
|
+
// Validation Helpers
|
|
5688
|
+
// ==========================================================================
|
|
5689
|
+
isValidNamingConvention(value) {
|
|
5690
|
+
return typeof value === "string" && ["PascalCase", "camelCase", "snake_case"].includes(value);
|
|
5691
|
+
}
|
|
5692
|
+
isValidValidationStyle(value) {
|
|
5693
|
+
return typeof value === "string" && ["strict", "minimal", "none"].includes(value);
|
|
5694
|
+
}
|
|
5695
|
+
};
|
|
5696
|
+
function createPreferenceLearner(options) {
|
|
5697
|
+
return new PreferenceLearner(options);
|
|
5698
|
+
}
|
|
5699
|
+
|
|
5700
|
+
// src/agent/memory-integration.ts
|
|
5701
|
+
var MemoryIntegrationEngine = class {
|
|
5702
|
+
constructor(options) {
|
|
5703
|
+
this.metrics = { queries: 0, hits: 0, totalLatencyMs: 0 };
|
|
5704
|
+
this.options = {
|
|
5705
|
+
enableEpisodic: true,
|
|
5706
|
+
enableSemantic: true,
|
|
5707
|
+
enableProcedural: true,
|
|
5708
|
+
...options
|
|
5709
|
+
};
|
|
5710
|
+
this.searchEngine = createAgenticSearchEngine(options.memoryManager);
|
|
5711
|
+
this.preferenceLearner = createPreferenceLearner({
|
|
5712
|
+
memoryManager: options.memoryManager
|
|
5713
|
+
});
|
|
5714
|
+
if (!options.memoryManager) {
|
|
5715
|
+
throw new Error("MemoryManager is required for MemoryIntegrationEngine");
|
|
5716
|
+
}
|
|
5717
|
+
}
|
|
5718
|
+
// ============================================================================
|
|
5719
|
+
// Episodic Memory: Past Sessions
|
|
5720
|
+
// ============================================================================
|
|
5721
|
+
/**
|
|
5722
|
+
* Retrieve similar past generation sessions
|
|
5723
|
+
*/
|
|
5724
|
+
async retrieveSimilarSessions(request, limit = 5) {
|
|
5725
|
+
if (!this.options.enableEpisodic) return [];
|
|
5726
|
+
const start = Date.now();
|
|
5727
|
+
try {
|
|
5728
|
+
const results = await this.searchEngine.search({
|
|
5729
|
+
userId: this.options.userId,
|
|
5730
|
+
query: request,
|
|
5731
|
+
strategy: "semantic",
|
|
5732
|
+
limit
|
|
5733
|
+
});
|
|
5734
|
+
const sessions = results.results.filter((r) => r.type === "session").map((r) => {
|
|
5735
|
+
const session = r.data;
|
|
5736
|
+
return {
|
|
5737
|
+
sessionId: session.id ?? "unknown",
|
|
5738
|
+
request: session.request ?? "",
|
|
5739
|
+
schema: session.schemaSnapshot ? JSON.parse(session.schemaSnapshot) : null,
|
|
5740
|
+
success: session.success ?? false,
|
|
5741
|
+
similarity: r.relevance
|
|
5742
|
+
};
|
|
5743
|
+
});
|
|
5744
|
+
this.recordMetrics(true, Date.now() - start);
|
|
5745
|
+
return sessions;
|
|
5746
|
+
} catch (error) {
|
|
5747
|
+
this.recordMetrics(false, Date.now() - start);
|
|
5748
|
+
console.warn("[Memory] Failed to retrieve similar sessions:", error);
|
|
5749
|
+
return [];
|
|
5750
|
+
}
|
|
5751
|
+
}
|
|
5752
|
+
/**
|
|
5753
|
+
* Record a new generation session to episodic memory
|
|
5754
|
+
*/
|
|
5755
|
+
async recordSession(request, result) {
|
|
5756
|
+
if (!this.options.enableEpisodic) return;
|
|
5757
|
+
await this.options.memoryManager.recordGeneration(
|
|
5758
|
+
this.options.userId,
|
|
5759
|
+
{
|
|
5760
|
+
threadId: `thread_${Date.now()}`,
|
|
5761
|
+
prompt: request,
|
|
5762
|
+
skill: "kflow-orbitals",
|
|
5763
|
+
generatedSchema: result.schema,
|
|
5764
|
+
entities: [],
|
|
5765
|
+
patterns: [],
|
|
5766
|
+
success: result.success,
|
|
5767
|
+
validationResult: result.validationResult
|
|
5768
|
+
}
|
|
5769
|
+
);
|
|
5770
|
+
}
|
|
5771
|
+
// ============================================================================
|
|
5772
|
+
// Semantic Memory: Patterns & Preferences
|
|
5773
|
+
// ============================================================================
|
|
5774
|
+
/**
|
|
5775
|
+
* Get learned user preferences
|
|
5776
|
+
*/
|
|
5777
|
+
async getUserPreferences() {
|
|
5778
|
+
if (!this.options.enableSemantic) {
|
|
5779
|
+
return {
|
|
5780
|
+
namingConvention: "PascalCase",
|
|
5781
|
+
preferredPatterns: [],
|
|
5782
|
+
commonEntities: []
|
|
5783
|
+
};
|
|
5784
|
+
}
|
|
5785
|
+
try {
|
|
5786
|
+
const prefs = await this.options.memoryManager.getUserPreferences(
|
|
5787
|
+
this.options.userId
|
|
5788
|
+
);
|
|
5789
|
+
if (!prefs) {
|
|
5790
|
+
return {
|
|
5791
|
+
namingConvention: "PascalCase",
|
|
5792
|
+
preferredPatterns: [],
|
|
5793
|
+
commonEntities: []
|
|
5794
|
+
};
|
|
5795
|
+
}
|
|
5796
|
+
return {
|
|
5797
|
+
namingConvention: prefs.namingConvention ?? "PascalCase",
|
|
5798
|
+
preferredPatterns: prefs.preferredPatterns ?? [],
|
|
5799
|
+
commonEntities: prefs.commonEntities ?? []
|
|
5800
|
+
};
|
|
5801
|
+
} catch (error) {
|
|
5802
|
+
console.warn("[Memory] Failed to get user preferences:", error);
|
|
5803
|
+
return {
|
|
5804
|
+
namingConvention: "PascalCase",
|
|
5805
|
+
preferredPatterns: [],
|
|
5806
|
+
commonEntities: []
|
|
5807
|
+
};
|
|
5808
|
+
}
|
|
5809
|
+
}
|
|
5810
|
+
/**
|
|
5811
|
+
* Learn from user feedback
|
|
5812
|
+
*/
|
|
5813
|
+
async learnFromFeedback(feedback) {
|
|
5814
|
+
if (!this.options.enableSemantic) return;
|
|
5815
|
+
await this.options.memoryManager.updatePatternAffinity(
|
|
5816
|
+
this.options.userId,
|
|
5817
|
+
feedback.pattern,
|
|
5818
|
+
feedback.outcome,
|
|
5819
|
+
{ entityType: feedback.entityType }
|
|
5820
|
+
);
|
|
5821
|
+
}
|
|
5822
|
+
/**
|
|
5823
|
+
* Infer preferences from usage patterns
|
|
5824
|
+
*/
|
|
5825
|
+
async inferPreferences() {
|
|
5826
|
+
if (!this.options.enableSemantic) {
|
|
5827
|
+
return { confidence: 0 };
|
|
5828
|
+
}
|
|
5829
|
+
try {
|
|
5830
|
+
const sessions = await this.options.memoryManager.getUserGenerationHistory(
|
|
5831
|
+
this.options.userId,
|
|
5832
|
+
5
|
|
5833
|
+
);
|
|
5834
|
+
if (sessions.length === 0) {
|
|
5835
|
+
return { confidence: 0 };
|
|
5836
|
+
}
|
|
5837
|
+
const analysis = await this.preferenceLearner.analyzeSession(sessions[0]);
|
|
5838
|
+
const namingInference = analysis.inferences.find((i) => i.field === "namingConvention");
|
|
5839
|
+
const validationInference = analysis.inferences.find((i) => i.field === "validationStyle");
|
|
5840
|
+
return {
|
|
5841
|
+
namingConvention: namingInference?.value,
|
|
5842
|
+
validationStyle: validationInference?.value,
|
|
5843
|
+
confidence: analysis.isHighConfidence ? 0.8 : 0.5
|
|
5844
|
+
};
|
|
5845
|
+
} catch (error) {
|
|
5846
|
+
console.warn("[Memory] Failed to infer preferences:", error);
|
|
5847
|
+
return { confidence: 0 };
|
|
5848
|
+
}
|
|
5849
|
+
}
|
|
5850
|
+
// ============================================================================
|
|
5851
|
+
// Procedural Memory: Domain Workflows
|
|
5852
|
+
// ============================================================================
|
|
5853
|
+
/**
|
|
5854
|
+
* Get project context (domain-specific knowledge)
|
|
5855
|
+
*/
|
|
5856
|
+
async getProjectContext() {
|
|
5857
|
+
if (!this.options.enableProcedural || !this.options.projectId) {
|
|
5858
|
+
return void 0;
|
|
5859
|
+
}
|
|
5860
|
+
try {
|
|
5861
|
+
const context = await this.options.memoryManager.getProjectContext(
|
|
5862
|
+
this.options.projectId
|
|
5863
|
+
);
|
|
5864
|
+
if (!context) return void 0;
|
|
5865
|
+
return {
|
|
5866
|
+
domain: context.domain ?? "business",
|
|
5867
|
+
existingEntities: context.existingEntities ?? [],
|
|
5868
|
+
conventions: context.conventions ?? []
|
|
5869
|
+
};
|
|
5870
|
+
} catch (error) {
|
|
5871
|
+
console.warn("[Memory] Failed to get project context:", error);
|
|
5872
|
+
return void 0;
|
|
5873
|
+
}
|
|
5874
|
+
}
|
|
5875
|
+
/**
|
|
5876
|
+
* Update project context with new conventions
|
|
5877
|
+
*/
|
|
5878
|
+
async updateProjectContext(update) {
|
|
5879
|
+
if (!this.options.enableProcedural || !this.options.projectId) return;
|
|
5880
|
+
await this.options.memoryManager.updateProjectContext(
|
|
5881
|
+
this.options.projectId,
|
|
5882
|
+
{
|
|
5883
|
+
userId: this.options.userId,
|
|
5884
|
+
domain: update.domain,
|
|
5885
|
+
conventions: update.conventions,
|
|
5886
|
+
existingEntities: update.existingEntities
|
|
5887
|
+
}
|
|
5888
|
+
);
|
|
5889
|
+
}
|
|
5890
|
+
// ============================================================================
|
|
5891
|
+
// Combined Memory Context
|
|
5892
|
+
// ============================================================================
|
|
5893
|
+
/**
|
|
5894
|
+
* Build complete memory context for a generation request
|
|
5895
|
+
*/
|
|
5896
|
+
async buildContext(request) {
|
|
5897
|
+
const start = Date.now();
|
|
5898
|
+
const [
|
|
5899
|
+
userPreferences,
|
|
5900
|
+
similarSessions,
|
|
5901
|
+
projectContext,
|
|
5902
|
+
inferredPrefs
|
|
5903
|
+
] = await Promise.all([
|
|
5904
|
+
this.getUserPreferences(),
|
|
5905
|
+
this.retrieveSimilarSessions(request, 3),
|
|
5906
|
+
this.getProjectContext(),
|
|
5907
|
+
this.inferPreferences()
|
|
5908
|
+
]);
|
|
5909
|
+
if (inferredPrefs.confidence > 0.7) {
|
|
5910
|
+
if (inferredPrefs.namingConvention) {
|
|
5911
|
+
userPreferences.namingConvention = inferredPrefs.namingConvention;
|
|
5912
|
+
}
|
|
5913
|
+
}
|
|
5914
|
+
const latencyMs = Date.now() - start;
|
|
5915
|
+
console.log(`[Memory] Context built in ${latencyMs}ms:`, {
|
|
5916
|
+
similarSessions: similarSessions.length,
|
|
5917
|
+
hasProjectContext: !!projectContext,
|
|
5918
|
+
userPreferences: Object.keys(userPreferences).length
|
|
5919
|
+
});
|
|
5920
|
+
return {
|
|
5921
|
+
userPreferences,
|
|
5922
|
+
similarSessions,
|
|
5923
|
+
projectContext,
|
|
5924
|
+
learnedPatterns: []
|
|
5925
|
+
// Would be populated from pattern affinity
|
|
5926
|
+
};
|
|
5927
|
+
}
|
|
5928
|
+
// ============================================================================
|
|
5929
|
+
// Metrics
|
|
5930
|
+
// ============================================================================
|
|
5931
|
+
/**
|
|
5932
|
+
* Get memory quality metrics
|
|
5933
|
+
*/
|
|
5934
|
+
getMetrics() {
|
|
5935
|
+
const totalQueries = this.metrics.queries;
|
|
5936
|
+
const hits = this.metrics.hits;
|
|
5937
|
+
return {
|
|
5938
|
+
recallAccuracy: totalQueries > 0 ? hits / totalQueries : 0,
|
|
5939
|
+
precision: 0.85,
|
|
5940
|
+
// Simplified metric
|
|
5941
|
+
latencyMs: totalQueries > 0 ? this.metrics.totalLatencyMs / totalQueries : 0,
|
|
5942
|
+
cacheHitRate: 0.3
|
|
5943
|
+
// Simplified metric
|
|
5944
|
+
};
|
|
5945
|
+
}
|
|
5946
|
+
recordMetrics(hit, latencyMs) {
|
|
5947
|
+
this.metrics.queries++;
|
|
5948
|
+
if (hit) this.metrics.hits++;
|
|
5949
|
+
this.metrics.totalLatencyMs += latencyMs;
|
|
5950
|
+
}
|
|
5951
|
+
};
|
|
5952
|
+
function createMemoryIntegration(options) {
|
|
5953
|
+
return new MemoryIntegrationEngine(options);
|
|
5954
|
+
}
|
|
5955
|
+
|
|
5956
|
+
// src/tools/composition.ts
|
|
5957
|
+
var WorkflowEngine = class {
|
|
5958
|
+
constructor(executor) {
|
|
5959
|
+
this.workflows = /* @__PURE__ */ new Map();
|
|
5960
|
+
this.executor = executor;
|
|
5961
|
+
}
|
|
5962
|
+
/**
|
|
5963
|
+
* Register a workflow definition
|
|
5964
|
+
*/
|
|
5965
|
+
registerWorkflow(definition) {
|
|
5966
|
+
this.workflows.set(definition.name, definition);
|
|
5967
|
+
}
|
|
5968
|
+
/**
|
|
5969
|
+
* Execute a workflow by name
|
|
5970
|
+
*/
|
|
5971
|
+
async executeWorkflow(workflowName, inputs) {
|
|
5972
|
+
const definition = this.workflows.get(workflowName);
|
|
5973
|
+
if (!definition) {
|
|
5974
|
+
throw new Error(`Workflow not found: ${workflowName}`);
|
|
5975
|
+
}
|
|
5976
|
+
return this.runWorkflow(definition, inputs);
|
|
5977
|
+
}
|
|
5978
|
+
/**
|
|
5979
|
+
* Execute a workflow definition directly
|
|
5980
|
+
*/
|
|
5981
|
+
async runWorkflow(definition, inputs) {
|
|
5982
|
+
const workflowId = `wf_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
5983
|
+
const startTime = Date.now();
|
|
5984
|
+
const context = {
|
|
5985
|
+
workflowId,
|
|
5986
|
+
inputs,
|
|
5987
|
+
outputs: {},
|
|
5988
|
+
stepResults: /* @__PURE__ */ new Map(),
|
|
5989
|
+
metadata: {
|
|
5990
|
+
startTime,
|
|
5991
|
+
stepsCompleted: 0,
|
|
5992
|
+
stepsFailed: 0
|
|
5993
|
+
}
|
|
5994
|
+
};
|
|
5995
|
+
const steps = definition.steps.map((s) => ({ ...s, status: "pending" }));
|
|
5996
|
+
try {
|
|
5997
|
+
const executionOrder = this.resolveDependencies(steps);
|
|
5998
|
+
for (const stepId of executionOrder) {
|
|
5999
|
+
const step = steps.find((s) => s.id === stepId);
|
|
6000
|
+
if (step.condition && !step.condition(context)) {
|
|
6001
|
+
step.status = "skipped";
|
|
6002
|
+
continue;
|
|
6003
|
+
}
|
|
6004
|
+
await this.executeStep(step, context, definition);
|
|
6005
|
+
if (step.status === "error" && definition.onError === "stop") {
|
|
6006
|
+
break;
|
|
6007
|
+
}
|
|
6008
|
+
}
|
|
6009
|
+
const durationMs = Date.now() - startTime;
|
|
6010
|
+
return {
|
|
6011
|
+
success: context.metadata.stepsFailed === 0,
|
|
6012
|
+
workflowId,
|
|
6013
|
+
context,
|
|
6014
|
+
steps,
|
|
6015
|
+
durationMs
|
|
6016
|
+
};
|
|
6017
|
+
} catch (error) {
|
|
6018
|
+
return {
|
|
6019
|
+
success: false,
|
|
6020
|
+
workflowId,
|
|
6021
|
+
context,
|
|
6022
|
+
steps,
|
|
6023
|
+
durationMs: Date.now() - startTime,
|
|
6024
|
+
error: error instanceof Error ? error.message : String(error)
|
|
6025
|
+
};
|
|
6026
|
+
}
|
|
6027
|
+
}
|
|
6028
|
+
/**
|
|
6029
|
+
* Execute independent steps in parallel
|
|
6030
|
+
*/
|
|
6031
|
+
async executeParallel(steps, context) {
|
|
6032
|
+
const promises = steps.map(async (step) => {
|
|
6033
|
+
const startTime = Date.now();
|
|
6034
|
+
try {
|
|
6035
|
+
const input = typeof step.input === "function" ? step.input(context) : step.input;
|
|
6036
|
+
const output = await this.executor.execute(step.tool, input);
|
|
6037
|
+
return {
|
|
6038
|
+
stepId: step.id,
|
|
6039
|
+
success: true,
|
|
6040
|
+
output,
|
|
6041
|
+
durationMs: Date.now() - startTime
|
|
6042
|
+
};
|
|
6043
|
+
} catch (error) {
|
|
6044
|
+
return {
|
|
6045
|
+
stepId: step.id,
|
|
6046
|
+
success: false,
|
|
6047
|
+
error: error instanceof Error ? error.message : String(error),
|
|
6048
|
+
durationMs: Date.now() - startTime
|
|
6049
|
+
};
|
|
6050
|
+
}
|
|
6051
|
+
});
|
|
6052
|
+
return Promise.all(promises);
|
|
6053
|
+
}
|
|
6054
|
+
/**
|
|
6055
|
+
* Create a workflow builder for fluent API
|
|
6056
|
+
*/
|
|
6057
|
+
createWorkflow(name, description) {
|
|
6058
|
+
return new WorkflowBuilder(this, name, description);
|
|
6059
|
+
}
|
|
6060
|
+
// ============================================================================
|
|
6061
|
+
// Private Helpers
|
|
6062
|
+
// ============================================================================
|
|
6063
|
+
async executeStep(step, context, definition) {
|
|
6064
|
+
step.status = "running";
|
|
6065
|
+
step.startTime = Date.now();
|
|
6066
|
+
const maxRetries = definition.maxRetries ?? 0;
|
|
6067
|
+
let attempt = 0;
|
|
6068
|
+
while (attempt <= maxRetries) {
|
|
6069
|
+
try {
|
|
6070
|
+
const input = typeof step.input === "function" ? step.input(context) : step.input;
|
|
6071
|
+
const output = await this.executor.execute(step.tool, input);
|
|
6072
|
+
step.output = output;
|
|
6073
|
+
step.status = "success";
|
|
6074
|
+
step.endTime = Date.now();
|
|
6075
|
+
context.stepResults.set(step.id, { success: true, output });
|
|
6076
|
+
context.outputs[step.id] = output;
|
|
6077
|
+
context.metadata.stepsCompleted++;
|
|
6078
|
+
return;
|
|
6079
|
+
} catch (error) {
|
|
6080
|
+
attempt++;
|
|
6081
|
+
if (attempt > maxRetries) {
|
|
6082
|
+
step.error = error instanceof Error ? error.message : String(error);
|
|
6083
|
+
step.status = "error";
|
|
6084
|
+
step.endTime = Date.now();
|
|
6085
|
+
context.stepResults.set(step.id, { success: false, error: step.error });
|
|
6086
|
+
context.metadata.stepsFailed++;
|
|
6087
|
+
return;
|
|
6088
|
+
}
|
|
6089
|
+
await new Promise((r) => setTimeout(r, 1e3 * attempt));
|
|
6090
|
+
}
|
|
6091
|
+
}
|
|
6092
|
+
}
|
|
6093
|
+
resolveDependencies(steps) {
|
|
6094
|
+
const visited = /* @__PURE__ */ new Set();
|
|
6095
|
+
const result = [];
|
|
6096
|
+
const visit = (stepId) => {
|
|
6097
|
+
if (visited.has(stepId)) return;
|
|
6098
|
+
visited.add(stepId);
|
|
6099
|
+
const step = steps.find((s) => s.id === stepId);
|
|
6100
|
+
if (!step) return;
|
|
6101
|
+
if (step.dependsOn) {
|
|
6102
|
+
for (const dep of step.dependsOn) {
|
|
6103
|
+
visit(dep);
|
|
6104
|
+
}
|
|
6105
|
+
}
|
|
6106
|
+
result.push(stepId);
|
|
6107
|
+
};
|
|
6108
|
+
for (const step of steps) {
|
|
6109
|
+
visit(step.id);
|
|
6110
|
+
}
|
|
6111
|
+
return result;
|
|
6112
|
+
}
|
|
6113
|
+
};
|
|
6114
|
+
var WorkflowBuilder = class {
|
|
6115
|
+
constructor(engine, name, description) {
|
|
6116
|
+
this.engine = engine;
|
|
6117
|
+
this.definition = {
|
|
6118
|
+
name,
|
|
6119
|
+
description,
|
|
6120
|
+
inputs: {},
|
|
6121
|
+
steps: [],
|
|
6122
|
+
onError: "stop",
|
|
6123
|
+
maxRetries: 0
|
|
6124
|
+
};
|
|
6125
|
+
}
|
|
6126
|
+
input(name, type, required = true, defaultValue) {
|
|
6127
|
+
this.definition.inputs[name] = { type, required, default: defaultValue };
|
|
6128
|
+
return this;
|
|
6129
|
+
}
|
|
6130
|
+
step(id, tool12, input, options = {}) {
|
|
6131
|
+
this.definition.steps.push({
|
|
6132
|
+
id,
|
|
6133
|
+
name: id,
|
|
6134
|
+
tool: tool12,
|
|
6135
|
+
input,
|
|
6136
|
+
dependsOn: options.dependsOn,
|
|
6137
|
+
condition: options.condition,
|
|
6138
|
+
status: "pending"
|
|
6139
|
+
});
|
|
6140
|
+
return this;
|
|
6141
|
+
}
|
|
6142
|
+
parallel(steps) {
|
|
6143
|
+
for (const step of steps) {
|
|
6144
|
+
this.definition.steps.push({
|
|
6145
|
+
id: step.id,
|
|
6146
|
+
name: step.id,
|
|
6147
|
+
tool: step.tool,
|
|
6148
|
+
input: step.input,
|
|
6149
|
+
status: "pending"
|
|
6150
|
+
});
|
|
6151
|
+
}
|
|
6152
|
+
return this;
|
|
6153
|
+
}
|
|
6154
|
+
onError(policy) {
|
|
6155
|
+
this.definition.onError = policy;
|
|
6156
|
+
return this;
|
|
6157
|
+
}
|
|
6158
|
+
retry(maxRetries) {
|
|
6159
|
+
this.definition.maxRetries = maxRetries;
|
|
6160
|
+
return this;
|
|
6161
|
+
}
|
|
6162
|
+
build() {
|
|
6163
|
+
return this.definition;
|
|
6164
|
+
}
|
|
6165
|
+
async execute(inputs) {
|
|
6166
|
+
return this.engine.runWorkflow(this.definition, inputs);
|
|
6167
|
+
}
|
|
6168
|
+
};
|
|
6169
|
+
|
|
6170
|
+
// src/agent/react-workflow-integration.ts
|
|
6171
|
+
var ReActWorkflowExecutor = class {
|
|
6172
|
+
constructor(options) {
|
|
6173
|
+
this.telemetry = [];
|
|
6174
|
+
this.options = {
|
|
6175
|
+
...options,
|
|
6176
|
+
enableTelemetry: options.enableTelemetry ?? true,
|
|
6177
|
+
maxExecutionMs: options.maxExecutionMs ?? 6e4
|
|
6178
|
+
};
|
|
6179
|
+
this.workflowEngine = new WorkflowEngine(options.toolExecutor);
|
|
6180
|
+
}
|
|
6181
|
+
/**
|
|
6182
|
+
* Execute a workflow action within a ReAct session
|
|
6183
|
+
* This replaces simple tool calls with full workflows
|
|
6184
|
+
*/
|
|
6185
|
+
async executeWorkflowAction(session, action, context) {
|
|
6186
|
+
const startTime = Date.now();
|
|
6187
|
+
const errors = [];
|
|
6188
|
+
let totalRetries = 0;
|
|
6189
|
+
this.workflowEngine.registerWorkflow({
|
|
6190
|
+
name: action.name,
|
|
6191
|
+
description: `Workflow for ${action.name}`,
|
|
6192
|
+
inputs: Object.keys(context).reduce((acc, key) => {
|
|
6193
|
+
acc[key] = { type: "unknown", required: false };
|
|
6194
|
+
return acc;
|
|
6195
|
+
}, {}),
|
|
6196
|
+
steps: action.workflow.steps.map((step) => ({
|
|
6197
|
+
id: step.id,
|
|
6198
|
+
name: step.id,
|
|
6199
|
+
tool: step.tool,
|
|
6200
|
+
input: step.input,
|
|
6201
|
+
dependsOn: step.dependsOn,
|
|
6202
|
+
status: "pending"
|
|
6203
|
+
})),
|
|
6204
|
+
onError: "retry",
|
|
6205
|
+
maxRetries: 3
|
|
6206
|
+
});
|
|
6207
|
+
try {
|
|
6208
|
+
const result = await this.executeWithTimeout(
|
|
6209
|
+
action.name,
|
|
6210
|
+
context,
|
|
6211
|
+
this.options.maxExecutionMs
|
|
6212
|
+
);
|
|
6213
|
+
const stepsExecuted = result.steps.filter(
|
|
6214
|
+
(s) => s.status === "success" || s.status === "error"
|
|
6215
|
+
).length;
|
|
6216
|
+
totalRetries = this.telemetry.filter(
|
|
6217
|
+
(t) => t.sessionId === session.sessionId && t.actionName === action.name
|
|
6218
|
+
).reduce((sum, t) => sum + t.retryCount, 0);
|
|
6219
|
+
if (result.success && this.options.memoryManager) {
|
|
6220
|
+
await this.storeWorkflowResult(session, action.name, result);
|
|
6221
|
+
}
|
|
6222
|
+
return {
|
|
6223
|
+
success: result.success,
|
|
6224
|
+
output: result.context.outputs,
|
|
6225
|
+
stepsExecuted,
|
|
6226
|
+
durationMs: result.durationMs || Date.now() - startTime,
|
|
6227
|
+
retries: totalRetries,
|
|
6228
|
+
errors: result.error ? [result.error] : errors
|
|
6229
|
+
};
|
|
6230
|
+
} catch (error) {
|
|
6231
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
6232
|
+
errors.push(errorMessage);
|
|
6233
|
+
return {
|
|
6234
|
+
success: false,
|
|
6235
|
+
output: null,
|
|
6236
|
+
stepsExecuted: 0,
|
|
6237
|
+
durationMs: Date.now() - startTime,
|
|
6238
|
+
retries: totalRetries,
|
|
6239
|
+
errors
|
|
6240
|
+
};
|
|
6241
|
+
}
|
|
6242
|
+
}
|
|
6243
|
+
/**
|
|
6244
|
+
* Execute workflow with timeout
|
|
6245
|
+
*/
|
|
6246
|
+
async executeWithTimeout(workflowName, inputs, timeoutMs) {
|
|
6247
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
6248
|
+
setTimeout(() => reject(new Error("Workflow execution timeout")), timeoutMs);
|
|
6249
|
+
});
|
|
6250
|
+
const executionPromise = this.workflowEngine.executeWorkflow(workflowName, inputs);
|
|
6251
|
+
return Promise.race([executionPromise, timeoutPromise]);
|
|
6252
|
+
}
|
|
6253
|
+
/**
|
|
6254
|
+
* Store workflow result in memory for learning
|
|
6255
|
+
*/
|
|
6256
|
+
async storeWorkflowResult(session, actionName, result) {
|
|
6257
|
+
if (!this.options.memoryManager) return;
|
|
6258
|
+
await this.options.memoryManager.recordGeneration(
|
|
6259
|
+
session.sessionId,
|
|
6260
|
+
// Use session ID as user ID proxy
|
|
6261
|
+
{
|
|
6262
|
+
threadId: session.sessionId,
|
|
6263
|
+
prompt: `Workflow: ${actionName}`,
|
|
6264
|
+
skill: "react-workflow",
|
|
6265
|
+
generatedSchema: result.context.outputs,
|
|
6266
|
+
entities: [],
|
|
6267
|
+
patterns: [],
|
|
6268
|
+
success: result.success
|
|
6269
|
+
}
|
|
6270
|
+
);
|
|
6271
|
+
}
|
|
6272
|
+
/**
|
|
6273
|
+
* Record telemetry for a workflow step
|
|
6274
|
+
*/
|
|
6275
|
+
recordTelemetry(event) {
|
|
6276
|
+
if (!this.options.enableTelemetry) return;
|
|
6277
|
+
this.telemetry.push(event);
|
|
6278
|
+
if (this.telemetry.length > 1e3) {
|
|
6279
|
+
this.telemetry = this.telemetry.slice(-500);
|
|
6280
|
+
}
|
|
6281
|
+
}
|
|
6282
|
+
/**
|
|
6283
|
+
* Get telemetry for analysis
|
|
6284
|
+
*/
|
|
6285
|
+
getTelemetry(sessionId) {
|
|
6286
|
+
if (sessionId) {
|
|
6287
|
+
return this.telemetry.filter((t) => t.sessionId === sessionId);
|
|
6288
|
+
}
|
|
6289
|
+
return [...this.telemetry];
|
|
6290
|
+
}
|
|
6291
|
+
/**
|
|
6292
|
+
* Get workflow performance metrics
|
|
6293
|
+
*/
|
|
6294
|
+
getMetrics() {
|
|
6295
|
+
const events = this.telemetry;
|
|
6296
|
+
const uniqueWorkflows = new Set(events.map((e) => e.actionName)).size;
|
|
6297
|
+
const successCount = events.filter((e) => e.success).length;
|
|
6298
|
+
const successRate = events.length > 0 ? successCount / events.length : 0;
|
|
6299
|
+
const avgDuration = events.length > 0 ? events.reduce((sum, e) => sum + e.durationMs, 0) / events.length : 0;
|
|
6300
|
+
const avgRetries = events.length > 0 ? events.reduce((sum, e) => sum + e.retryCount, 0) / events.length : 0;
|
|
6301
|
+
const toolUsage = events.reduce((acc, e) => {
|
|
6302
|
+
acc[e.tool] = (acc[e.tool] || 0) + 1;
|
|
6303
|
+
return acc;
|
|
6304
|
+
}, {});
|
|
6305
|
+
return {
|
|
6306
|
+
totalWorkflows: uniqueWorkflows,
|
|
6307
|
+
successRate,
|
|
6308
|
+
avgDurationMs: avgDuration,
|
|
6309
|
+
avgRetries,
|
|
6310
|
+
toolUsage
|
|
6311
|
+
};
|
|
6312
|
+
}
|
|
6313
|
+
};
|
|
6314
|
+
var ReActWorkflowEngine = class {
|
|
6315
|
+
constructor(options) {
|
|
6316
|
+
this.reactEngine = new ReActEngine(options.reactOptions);
|
|
6317
|
+
this.workflowExecutor = new ReActWorkflowExecutor(options.workflowOptions);
|
|
6318
|
+
}
|
|
6319
|
+
/**
|
|
6320
|
+
* Start a new session
|
|
6321
|
+
*/
|
|
6322
|
+
startSession(userRequest) {
|
|
6323
|
+
return this.reactEngine.startSession(userRequest);
|
|
6324
|
+
}
|
|
6325
|
+
/**
|
|
6326
|
+
* Execute REASON step
|
|
6327
|
+
*/
|
|
6328
|
+
async reason(sessionId, context) {
|
|
6329
|
+
return this.reactEngine.reason(sessionId, context);
|
|
6330
|
+
}
|
|
6331
|
+
/**
|
|
6332
|
+
* Execute ACT step with workflow support
|
|
6333
|
+
*
|
|
6334
|
+
* This is the key integration point - replaces simple tool calls
|
|
6335
|
+
* with full workflows that have retry, parallel execution, etc.
|
|
6336
|
+
*/
|
|
6337
|
+
async act(sessionId, action, actionInput, workflowAction) {
|
|
6338
|
+
const session = this.reactEngine.getSession(sessionId);
|
|
6339
|
+
if (!workflowAction) {
|
|
6340
|
+
const step2 = await this.reactEngine.act(sessionId, action, actionInput);
|
|
6341
|
+
return { step: step2 };
|
|
6342
|
+
}
|
|
6343
|
+
const workflowResult = await this.workflowExecutor.executeWorkflowAction(
|
|
6344
|
+
session,
|
|
6345
|
+
workflowAction,
|
|
6346
|
+
actionInput
|
|
6347
|
+
);
|
|
6348
|
+
const step = {
|
|
6349
|
+
stepNumber: ++session.currentStep,
|
|
6350
|
+
state: "ACTING",
|
|
6351
|
+
thought: `Executing workflow: ${workflowAction.name}`,
|
|
6352
|
+
action: workflowAction.name,
|
|
6353
|
+
actionInput,
|
|
6354
|
+
observation: workflowResult.success ? `Workflow completed successfully (${workflowResult.stepsExecuted} steps)` : `Workflow failed: ${workflowResult.errors.join(", ")}`,
|
|
6355
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
6356
|
+
};
|
|
6357
|
+
session.steps.push(step);
|
|
6358
|
+
session.state = workflowResult.success ? "OBSERVING" : "REFLECTING";
|
|
6359
|
+
return { step, workflowResult };
|
|
6360
|
+
}
|
|
6361
|
+
/**
|
|
6362
|
+
* Execute OBSERVE step
|
|
6363
|
+
*/
|
|
6364
|
+
async observe(sessionId, observation) {
|
|
6365
|
+
return this.reactEngine.observe(sessionId, observation);
|
|
6366
|
+
}
|
|
6367
|
+
/**
|
|
6368
|
+
* Execute REFLECT step
|
|
6369
|
+
*/
|
|
6370
|
+
async reflect(sessionId, result) {
|
|
6371
|
+
return this.reactEngine.reflect(sessionId, result);
|
|
6372
|
+
}
|
|
6373
|
+
/**
|
|
6374
|
+
* Execute CORRECT step
|
|
6375
|
+
*/
|
|
6376
|
+
async correct(sessionId, correctionAction, correctionInput) {
|
|
6377
|
+
return this.reactEngine.correct(sessionId, correctionAction, correctionInput);
|
|
6378
|
+
}
|
|
6379
|
+
/**
|
|
6380
|
+
* Get session
|
|
6381
|
+
*/
|
|
6382
|
+
getSession(sessionId) {
|
|
6383
|
+
return this.reactEngine.getSession(sessionId);
|
|
6384
|
+
}
|
|
6385
|
+
/**
|
|
6386
|
+
* Get workflow metrics
|
|
6387
|
+
*/
|
|
6388
|
+
getWorkflowMetrics() {
|
|
6389
|
+
return this.workflowExecutor.getMetrics();
|
|
6390
|
+
}
|
|
6391
|
+
};
|
|
6392
|
+
function createReActWorkflowExecutor(options) {
|
|
6393
|
+
return new ReActWorkflowExecutor(options);
|
|
6394
|
+
}
|
|
6395
|
+
function createReActWorkflowEngine(options) {
|
|
6396
|
+
return new ReActWorkflowEngine(options);
|
|
6397
|
+
}
|
|
6398
|
+
|
|
6399
|
+
// src/agent/hitl-workflow-integration.ts
|
|
6400
|
+
var HITLWorkflowEngine = class {
|
|
6401
|
+
constructor(options) {
|
|
6402
|
+
this.gateHistory = /* @__PURE__ */ new Map();
|
|
6403
|
+
this.options = {
|
|
6404
|
+
...options,
|
|
6405
|
+
defaultTimeoutMs: options.defaultTimeoutMs ?? 3e5,
|
|
6406
|
+
// 5 minutes
|
|
6407
|
+
enableAutoApprove: options.enableAutoApprove ?? true
|
|
6408
|
+
};
|
|
6409
|
+
this.hitlManager = options.hitlManager;
|
|
6410
|
+
this.workflowEngine = new WorkflowEngine(options.toolExecutor);
|
|
6411
|
+
}
|
|
6412
|
+
/**
|
|
6413
|
+
* Execute a workflow with human gates
|
|
6414
|
+
*/
|
|
6415
|
+
async executeWorkflow(sessionId, workflow, initialContext) {
|
|
6416
|
+
const startTime = Date.now();
|
|
6417
|
+
const gatesPassed = [];
|
|
6418
|
+
const branchesTaken = [];
|
|
6419
|
+
let wasInterrupted = false;
|
|
6420
|
+
try {
|
|
6421
|
+
let context = await this.executeInitialSteps(
|
|
6422
|
+
workflow.initialSteps,
|
|
6423
|
+
initialContext
|
|
6424
|
+
);
|
|
6425
|
+
for (const gate of workflow.gates) {
|
|
6426
|
+
if (gate.condition && !gate.condition(context)) {
|
|
6427
|
+
continue;
|
|
6428
|
+
}
|
|
6429
|
+
if (this.options.enableAutoApprove && gate.autoApprove) {
|
|
6430
|
+
if (gate.autoApprove.condition(context)) {
|
|
6431
|
+
const autoResult = {
|
|
6432
|
+
gateId: gate.id,
|
|
6433
|
+
approved: true,
|
|
6434
|
+
response: { autoApproved: true, reason: gate.autoApprove.reason },
|
|
6435
|
+
respondedAt: Date.now(),
|
|
6436
|
+
autoApproved: true
|
|
6437
|
+
};
|
|
6438
|
+
gatesPassed.push(autoResult);
|
|
6439
|
+
continue;
|
|
6440
|
+
}
|
|
6441
|
+
}
|
|
6442
|
+
wasInterrupted = true;
|
|
6443
|
+
const gateResult = await this.executeHumanGate(sessionId, gate);
|
|
6444
|
+
gatesPassed.push(gateResult);
|
|
6445
|
+
if (!gateResult.approved) {
|
|
6446
|
+
return {
|
|
6447
|
+
success: false,
|
|
6448
|
+
output: null,
|
|
6449
|
+
gatesPassed,
|
|
6450
|
+
branchesTaken,
|
|
6451
|
+
durationMs: Date.now() - startTime,
|
|
6452
|
+
wasInterrupted
|
|
6453
|
+
};
|
|
6454
|
+
}
|
|
6455
|
+
context = {
|
|
6456
|
+
...context,
|
|
6457
|
+
[`gate_${gate.id}`]: gateResult.response
|
|
6458
|
+
};
|
|
6459
|
+
}
|
|
6460
|
+
let branchExecuted = false;
|
|
6461
|
+
for (const branch of workflow.branches) {
|
|
6462
|
+
if (branch.condition(context)) {
|
|
6463
|
+
branchesTaken.push(branch.id);
|
|
6464
|
+
if (branch.gate) {
|
|
6465
|
+
wasInterrupted = true;
|
|
6466
|
+
const branchGateResult = await this.executeHumanGate(
|
|
6467
|
+
sessionId,
|
|
6468
|
+
branch.gate
|
|
6469
|
+
);
|
|
6470
|
+
gatesPassed.push(branchGateResult);
|
|
6471
|
+
if (!branchGateResult.approved) {
|
|
6472
|
+
continue;
|
|
6473
|
+
}
|
|
6474
|
+
}
|
|
6475
|
+
context = await this.executeBranchSteps(branch.steps, context);
|
|
6476
|
+
branchExecuted = true;
|
|
6477
|
+
break;
|
|
6478
|
+
}
|
|
6479
|
+
}
|
|
6480
|
+
if (!branchExecuted && workflow.fallbackBranch) {
|
|
6481
|
+
branchesTaken.push(workflow.fallbackBranch.id);
|
|
6482
|
+
context = await this.executeBranchSteps(
|
|
6483
|
+
workflow.fallbackBranch.steps,
|
|
6484
|
+
context
|
|
6485
|
+
);
|
|
6486
|
+
}
|
|
6487
|
+
this.gateHistory.set(sessionId, gatesPassed);
|
|
6488
|
+
return {
|
|
6489
|
+
success: true,
|
|
6490
|
+
output: context,
|
|
6491
|
+
gatesPassed,
|
|
6492
|
+
branchesTaken,
|
|
6493
|
+
durationMs: Date.now() - startTime,
|
|
6494
|
+
wasInterrupted
|
|
6495
|
+
};
|
|
6496
|
+
} catch (error) {
|
|
6497
|
+
return {
|
|
6498
|
+
success: false,
|
|
6499
|
+
output: error instanceof Error ? error.message : String(error),
|
|
6500
|
+
gatesPassed,
|
|
6501
|
+
branchesTaken,
|
|
6502
|
+
durationMs: Date.now() - startTime,
|
|
6503
|
+
wasInterrupted
|
|
6504
|
+
};
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
/**
|
|
6508
|
+
* Execute initial workflow steps
|
|
6509
|
+
*/
|
|
6510
|
+
async executeInitialSteps(steps, context) {
|
|
6511
|
+
let result = { ...context };
|
|
6512
|
+
for (const step of steps) {
|
|
6513
|
+
const output = await this.options.toolExecutor.execute(
|
|
6514
|
+
step.tool,
|
|
6515
|
+
this.interpolateInput(step.input, result)
|
|
6516
|
+
);
|
|
6517
|
+
result = { ...result, [step.tool]: output };
|
|
6518
|
+
}
|
|
6519
|
+
return result;
|
|
6520
|
+
}
|
|
6521
|
+
/**
|
|
6522
|
+
* Execute a human gate
|
|
6523
|
+
*/
|
|
6524
|
+
async executeHumanGate(sessionId, gate) {
|
|
6525
|
+
const timeoutMs = gate.timeoutMs ?? this.options.defaultTimeoutMs;
|
|
6526
|
+
switch (gate.type) {
|
|
6527
|
+
case "approval":
|
|
6528
|
+
return this.executeApprovalGate(sessionId, gate, timeoutMs);
|
|
6529
|
+
case "edit":
|
|
6530
|
+
return this.executeEditGate(sessionId, gate, timeoutMs);
|
|
6531
|
+
case "select":
|
|
6532
|
+
return this.executeSelectGate(sessionId, gate, timeoutMs);
|
|
6533
|
+
case "custom":
|
|
6534
|
+
return this.executeCustomGate(sessionId, gate, timeoutMs);
|
|
6535
|
+
default:
|
|
6536
|
+
throw new Error(`Unknown gate type: ${gate.type}`);
|
|
6537
|
+
}
|
|
6538
|
+
}
|
|
6539
|
+
/**
|
|
6540
|
+
* Execute approval gate
|
|
6541
|
+
*/
|
|
6542
|
+
async executeApprovalGate(sessionId, gate, timeoutMs) {
|
|
6543
|
+
const approved = await this.hitlManager.confirm(sessionId, gate.description, {
|
|
6544
|
+
severity: "info",
|
|
6545
|
+
timeoutMs,
|
|
6546
|
+
context: {
|
|
6547
|
+
checkpointId: `gate_${gate.id}`,
|
|
6548
|
+
currentState: "awaiting_approval",
|
|
6549
|
+
previousActions: []
|
|
6550
|
+
}
|
|
6551
|
+
});
|
|
6552
|
+
return {
|
|
6553
|
+
gateId: gate.id,
|
|
6554
|
+
approved,
|
|
6555
|
+
response: { approved },
|
|
6556
|
+
respondedAt: Date.now(),
|
|
6557
|
+
autoApproved: false
|
|
6558
|
+
};
|
|
6559
|
+
}
|
|
6560
|
+
/**
|
|
6561
|
+
* Execute edit gate
|
|
6562
|
+
*/
|
|
6563
|
+
async executeEditGate(sessionId, gate, timeoutMs) {
|
|
6564
|
+
const content = gate.payload?.content || "";
|
|
6565
|
+
const edited = await this.hitlManager.edit(sessionId, content, {
|
|
6566
|
+
format: gate.payload?.format || "text",
|
|
6567
|
+
title: gate.title,
|
|
6568
|
+
description: gate.description,
|
|
6569
|
+
timeoutMs
|
|
6570
|
+
});
|
|
6571
|
+
return {
|
|
6572
|
+
gateId: gate.id,
|
|
6573
|
+
approved: true,
|
|
6574
|
+
response: { edited, content: edited },
|
|
6575
|
+
respondedAt: Date.now(),
|
|
6576
|
+
autoApproved: false
|
|
6577
|
+
};
|
|
6578
|
+
}
|
|
6579
|
+
/**
|
|
6580
|
+
* Execute select gate
|
|
6581
|
+
*/
|
|
6582
|
+
async executeSelectGate(sessionId, gate, timeoutMs) {
|
|
6583
|
+
const options = gate.payload?.options || [];
|
|
6584
|
+
const selected = await this.hitlManager.select(sessionId, options, {
|
|
6585
|
+
multiple: gate.payload?.multiple || false,
|
|
6586
|
+
timeoutMs
|
|
6587
|
+
});
|
|
6588
|
+
return {
|
|
6589
|
+
gateId: gate.id,
|
|
6590
|
+
approved: true,
|
|
6591
|
+
response: { selected },
|
|
6592
|
+
respondedAt: Date.now(),
|
|
6593
|
+
autoApproved: false
|
|
6594
|
+
};
|
|
6595
|
+
}
|
|
6596
|
+
/**
|
|
6597
|
+
* Execute custom gate
|
|
6598
|
+
*/
|
|
6599
|
+
async executeCustomGate(sessionId, gate, timeoutMs) {
|
|
6600
|
+
const request = {
|
|
6601
|
+
interruptId: `custom_${gate.id}_${Date.now()}`,
|
|
6602
|
+
sessionId,
|
|
6603
|
+
type: "text",
|
|
6604
|
+
title: gate.title,
|
|
6605
|
+
description: gate.description,
|
|
6606
|
+
context: {
|
|
6607
|
+
checkpointId: `gate_${gate.id}`,
|
|
6608
|
+
currentState: "custom_gate",
|
|
6609
|
+
previousActions: []
|
|
6610
|
+
},
|
|
6611
|
+
payload: gate.payload || {},
|
|
6612
|
+
timeoutMs,
|
|
6613
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
6614
|
+
};
|
|
6615
|
+
const response = await this.waitForResponse(request);
|
|
6616
|
+
return {
|
|
6617
|
+
gateId: gate.id,
|
|
6618
|
+
approved: true,
|
|
6619
|
+
response,
|
|
6620
|
+
respondedAt: Date.now(),
|
|
6621
|
+
autoApproved: false
|
|
6622
|
+
};
|
|
6623
|
+
}
|
|
6624
|
+
/**
|
|
6625
|
+
* Execute branch steps
|
|
6626
|
+
*/
|
|
6627
|
+
async executeBranchSteps(steps, context) {
|
|
6628
|
+
return this.executeInitialSteps(steps, context);
|
|
6629
|
+
}
|
|
6630
|
+
/**
|
|
6631
|
+
* Wait for interrupt response
|
|
6632
|
+
*/
|
|
6633
|
+
async waitForResponse(request) {
|
|
6634
|
+
return new Promise((resolve2) => {
|
|
6635
|
+
setTimeout(() => {
|
|
6636
|
+
resolve2({ timeout: true });
|
|
6637
|
+
}, request.timeoutMs || 3e5);
|
|
6638
|
+
});
|
|
6639
|
+
}
|
|
6640
|
+
/**
|
|
6641
|
+
* Interpolate input with context
|
|
6642
|
+
*/
|
|
6643
|
+
interpolateInput(input, context) {
|
|
6644
|
+
const result = {};
|
|
6645
|
+
for (const [key, value] of Object.entries(input)) {
|
|
6646
|
+
if (typeof value === "string" && value.startsWith("{{") && value.endsWith("}}")) {
|
|
6647
|
+
const path6 = value.slice(2, -2).trim();
|
|
6648
|
+
result[key] = this.getValueFromPath(context, path6);
|
|
6649
|
+
} else {
|
|
6650
|
+
result[key] = value;
|
|
6651
|
+
}
|
|
6652
|
+
}
|
|
6653
|
+
return result;
|
|
6654
|
+
}
|
|
6655
|
+
/**
|
|
6656
|
+
* Get value from path
|
|
6657
|
+
*/
|
|
6658
|
+
getValueFromPath(obj, path6) {
|
|
6659
|
+
const parts = path6.split(".");
|
|
6660
|
+
let current = obj;
|
|
6661
|
+
for (const part of parts) {
|
|
6662
|
+
if (current && typeof current === "object") {
|
|
6663
|
+
current = current[part];
|
|
6664
|
+
} else {
|
|
6665
|
+
return void 0;
|
|
6666
|
+
}
|
|
6667
|
+
}
|
|
6668
|
+
return current;
|
|
6669
|
+
}
|
|
6670
|
+
/**
|
|
6671
|
+
* Get gate history for a session
|
|
6672
|
+
*/
|
|
6673
|
+
getGateHistory(sessionId) {
|
|
6674
|
+
return this.gateHistory.get(sessionId) || [];
|
|
6675
|
+
}
|
|
6676
|
+
/**
|
|
6677
|
+
* Clear gate history
|
|
6678
|
+
*/
|
|
6679
|
+
clearGateHistory(sessionId) {
|
|
6680
|
+
if (sessionId) {
|
|
6681
|
+
this.gateHistory.delete(sessionId);
|
|
6682
|
+
} else {
|
|
6683
|
+
this.gateHistory.clear();
|
|
6684
|
+
}
|
|
6685
|
+
}
|
|
6686
|
+
};
|
|
6687
|
+
function createSchemaGenerationHITLWorkflow(complexity) {
|
|
6688
|
+
const needsReview = complexity === "complex";
|
|
6689
|
+
return {
|
|
6690
|
+
name: "schema-generation-with-review",
|
|
6691
|
+
initialSteps: [
|
|
6692
|
+
{ tool: "analyzeRequirements", input: { text: "{{requirements}}" } },
|
|
6693
|
+
{ tool: "extractEntities", input: { from: "{{analyzeRequirements}}" } }
|
|
6694
|
+
],
|
|
6695
|
+
gates: [
|
|
6696
|
+
{
|
|
6697
|
+
id: "complexity-check",
|
|
6698
|
+
type: "approval",
|
|
6699
|
+
title: "Complex Schema Detected",
|
|
6700
|
+
description: `This appears to be a ${complexity} schema. Review before proceeding?`,
|
|
6701
|
+
condition: () => needsReview,
|
|
6702
|
+
autoApprove: {
|
|
6703
|
+
condition: () => !needsReview,
|
|
6704
|
+
reason: "Simple schema, auto-approved"
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
],
|
|
6708
|
+
branches: [
|
|
6709
|
+
{
|
|
6710
|
+
id: "generate-full",
|
|
6711
|
+
condition: () => true,
|
|
6712
|
+
steps: [
|
|
6713
|
+
{ tool: "generateOrbital", input: { entities: "{{extractEntities}}" } },
|
|
6714
|
+
{ tool: "validateSchema", input: { schema: "{{generateOrbital}}" } }
|
|
6715
|
+
],
|
|
6716
|
+
gate: needsReview ? {
|
|
6717
|
+
id: "schema-review",
|
|
6718
|
+
type: "edit",
|
|
6719
|
+
title: "Review Generated Schema",
|
|
6720
|
+
description: "Please review and edit the generated schema if needed.",
|
|
6721
|
+
payload: { format: "json" }
|
|
6722
|
+
} : void 0
|
|
6723
|
+
}
|
|
6724
|
+
]
|
|
6725
|
+
};
|
|
6726
|
+
}
|
|
6727
|
+
function createMultiStageApprovalWorkflow(stages) {
|
|
6728
|
+
return {
|
|
6729
|
+
name: "multi-stage-approval",
|
|
6730
|
+
initialSteps: [],
|
|
6731
|
+
gates: stages.map((stage, index) => ({
|
|
6732
|
+
id: `approval-${index}`,
|
|
6733
|
+
type: "approval",
|
|
6734
|
+
title: `${stage.name} Approval Required`,
|
|
6735
|
+
description: `Waiting for approval from ${stage.approver}`
|
|
6736
|
+
})),
|
|
6737
|
+
branches: [
|
|
6738
|
+
{
|
|
6739
|
+
id: "approved",
|
|
6740
|
+
condition: () => true,
|
|
6741
|
+
steps: [{ tool: "finalize", input: {} }]
|
|
6742
|
+
}
|
|
6743
|
+
]
|
|
6744
|
+
};
|
|
6745
|
+
}
|
|
6746
|
+
function createHITLWorkflowEngine(options) {
|
|
6747
|
+
return new HITLWorkflowEngine(options);
|
|
6748
|
+
}
|
|
6749
|
+
|
|
6750
|
+
export { EVENT_BUDGETS, HITLWorkflowEngine, HITLv2Manager, MemoryIntegrationEngine, ReActEngine, ReActWorkflowEngine, ReActWorkflowExecutor, SessionManager, createHITLWorkflowEngine, createHITLv2Manager, createMemoryIntegration, createMultiStageApprovalWorkflow, createReActEngine, createReActWorkflowEngine, createReActWorkflowExecutor, createSchemaGenerationHITLWorkflow, createSkillAgent, getBudgetWarningMessage, getEventBudget, getInterruptConfig, resumeSkillAgent };
|
|
4696
6751
|
//# sourceMappingURL=index.js.map
|
|
4697
6752
|
//# sourceMappingURL=index.js.map
|