371 Commits

Author SHA1 Message Date
e9eaaa24db fix(BuiltinCommand): spill session streams to log files 2026-04-20 14:37:40 +08:00
2ec2d8e096 fix(CommandExecutionService): preserve stdout and stderr outputs 2026-04-20 14:32:25 +08:00
eea72c747c fix(DirectoryWatchSupport): isolate handler failures 2026-04-19 17:31:36 +08:00
137b1ee917 fix(CommandExecutionService): avoid persistent reader executor 2026-04-19 17:30:16 +08:00
c5aa558319 fix(McpActionExecutor): handle client call failures gracefully 2026-04-19 17:27:27 +08:00
8c8b0883bb fix(BuiltinCommand): expire finished command sessions by ttl 2026-04-19 17:26:20 +08:00
dd8e20838d fix(BuiltinCommand): apply execution policy to command tools 2026-04-19 17:23:04 +08:00
15d7eb6850 fix(DynamicActionMcp): apply execution policy to tool handler 2026-04-19 17:21:37 +08:00
657023694c fix(OriginExecution): apply execution policy to process launch 2026-04-19 17:19:39 +08:00
9b97fffc5c fix(LocalRunnerClient): unregister policy listener on close 2026-04-19 17:13:40 +08:00
14df95fc59 fix(McpConfigWatcher): clean stale actions on client removal 2026-04-19 17:13:04 +08:00
864bda95e4 refactor(action): register no blocks while no actions recovered 2026-04-19 00:51:22 +08:00
bfa3562335 refactor(exception): optimize exception report behavior 2026-04-19 00:47:31 +08:00
9b24b662da chore: add slf4j log annotation on AgentModule implementations 2026-04-19 00:36:15 +08:00
41c611cb70 refactor(framework): support inject Standalone into Standalone modules 2026-04-19 00:34:45 +08:00
6ca77bdb74 feat(perceive): add SystemStatsMonitor 2026-04-18 23:51:23 +08:00
e5ce6d6722 refactor(memory): rename MemoryUpdater into MemoryRecallProfileExtractor, and create prompt 2026-04-18 23:50:48 +08:00
a7ef9bff49 refactor(memory): enhance topic-based memory runtime on recalling and indexing 2026-04-18 22:28:40 +08:00
92c8e01000 feat(memory): create prompts for submodules of memory selector 2026-04-18 19:19:05 +08:00
e0543a8966 refactor(communication): create prompts for summarizer, and optimize message structure 2026-04-17 23:16:20 +08:00
0c079c127e chore: remove useless annotations on module 2026-04-17 18:09:40 +08:00
96301dc64a refactor(action): use synchronized lock to prevent concurrent problems in executable actions executing 2026-04-17 18:05:04 +08:00
3fd90c0f5b refactor(context): sort context blocks by descending 2026-04-17 16:01:50 +08:00
8928ec9e07 feat(action): create prompts for submodules of ActionExecutor 2026-04-17 15:01:45 +08:00
503afecbe2 refactor(action): redefine ExtractorResult structure to support openai sdk better, and make failed meta-action executing should be recorded as history normally 2026-04-16 23:27:46 +08:00
281984bb05 feat(action): redefine structure of evaluator result to support json schema of openai sdk, and create system prompt for sub-modules of ActionPlanner 2026-04-16 21:38:11 +08:00
062af4b7d2 feat(communication): update prompt 2026-04-16 21:05:39 +08:00
380c674d06 feat(communication): enrich and correct system-prompt in CommunicationProducer, and support NO_REPLY answering 2026-04-16 17:44:36 +08:00
347560d979 refactor(context): rename VisibleDomain into FocusedDomain, and optimize related context usage 2026-04-15 22:16:33 +08:00
999a6a8d7e refactor(dialog): remove legacy data class 2026-04-15 17:24:22 +08:00
f510dc5a42 refactor(context): support wait a debounce delay before executing turn 2026-04-15 16:36:23 +08:00
d8ff0b5ea4 refactor(context): simplify constructor and inputs encoding of running flow context 2026-04-15 15:45:42 +08:00
dc147000ba refactor(runtime): support collect context by source and interrupt same-source running flow by module order 2026-04-15 14:32:52 +08:00
247057e100 fix(test): fix MemoryRuntimeTest 2026-04-14 15:07:32 +08:00
33ffd782c4 refactor(cognition): remove duplicate recent chat block building logic, refresh which in cognition core uniformly 2026-04-14 12:40:56 +08:00
a847f3bff8 refactor(rolling): separate dialog rolling with memory topic binding,
now support register after-rolling consumer independently
2026-04-14 11:14:37 +08:00
28d0a43ef3 refactor(log): support advice invoke or invoke with no result via different methods to avoid unnecessary nullable check 2026-04-14 10:08:31 +08:00
cb4380eb1e feat(trace): support trace context workspace changes 2026-04-13 22:48:31 +08:00
737f9d122a feat(trace): support trace input/output information on Running/Sub AgentModule 2026-04-13 22:27:11 +08:00
e65d3302c6 feat(trace): support create advice for method with no return value 2026-04-13 21:57:10 +08:00
fece67135f feat(trace): support create loggable advice and implement common trace recorder 2026-04-13 21:39:42 +08:00
d30e58ff83 refactor(framework): centralize model exception reporting in ActivateModel and remove duplicated module-level handlers 2026-04-12 22:15:08 +08:00
93304878ad refactor(memory): migrate slice/topic/date lookup to Result flow and unify MemoryLookupException reporting 2026-04-12 20:13:11 +08:00
e37a282141 fix(test): adapt ActionExecutor tests to Result-based extractor/corrector execution flow 2026-04-12 19:19:07 +08:00
04d6ad6d80 refactor(core): normalize memory unit after adding new slice before return 2026-04-12 19:08:35 +08:00
9755672750 refactor(action-core): wrap runner submit flow with Result.runCatching and centralize action error handling 2026-04-12 18:51:33 +08:00
e0f955694d refactor(framework): wrap module execution in Result and report failures via exception handler 2026-04-12 17:33:11 +08:00
c14e6f84e7 refactor(action-core): migrate action modules to Result return flow and unify exception reporting 2026-04-12 17:29:10 +08:00
19f56d11f0 refactor(framework): add Result chain APIs and align runtime exception handling 2026-04-12 16:58:36 +08:00
94d91d9746 feat(agent): support add custom configurable object in Agent launch flow 2026-04-11 21:07:50 +08:00
fac6e24e49 feat(exception): support report necessary exception info into context 2026-04-11 18:52:53 +08:00
2aae1b1f14 refactor(action-core): return Result for meta action lookups and adapt runtime callers 2026-04-11 18:30:24 +08:00
1b48e955bd refactor(core): migrate deprecated exceptions to new hierarchy and align tests 2026-04-11 16:10:34 +08:00
b8cb2afbcf refactor(framework): unify model invocation result and exception handling 2026-04-11 14:50:12 +08:00
3732555f02 refactor(framework): migrate startup chain exceptions to AgentException hierarchy 2026-04-10 22:39:59 +08:00
ec52d64e73 refactor(exception): register exception reporters on Agent launcher 2026-04-10 19:04:11 +08:00
7b963df991 refactor(exception): establish new exception system, and move the legacy into deprecated package 2026-04-10 18:41:13 +08:00
4876d621b2 将 .java 重命名为 .kt 2026-04-10 18:37:49 +08:00
663d66fdea chore: remove legacy exception handler and adjust runtime class location 2026-04-10 14:31:56 +08:00
d29dad4691 refactor(config): adjust declared config location 2026-04-09 17:28:23 +08:00
291371f8da chore: adjust reflect related util's location 2026-04-09 16:58:24 +08:00
3e5d6ebeb4 feat(runtime): support mask assigned modules; and remove legacy module record in agent context 2026-04-09 16:13:04 +08:00
56daaf0b60 refactor(agent): normalize Agent launch flow 2026-04-09 12:26:52 +08:00
d6593c10f9 refactor(agent): support register registry shutdown hooks while agent launching 2026-04-09 12:19:20 +08:00
328befecca refactor(action): add shutdown method to ActionCore to close runner client and thread pool 2026-04-09 12:00:32 +08:00
1e46149d0a refactor(agent): remove legacy ConfigLoader and related factory; refactor agent launch flow 2026-04-09 10:35:13 +08:00
427d224f65 refactor(gateway): manage gateway implementions via related registry and interface 2026-04-08 22:24:07 +08:00
0528890d60 refactor(communication): remove channel assignment in ReplyDispatcher 2026-04-08 20:49:37 +08:00
f233c5ce32 fixup! refactor(runner): manage execution policy via ConfigCenter 2026-04-08 20:48:42 +08:00
91a595d073 chore: remove legacy utils and constant class 2026-04-08 17:36:03 +08:00
6d27e55a1e refactor(runner): manage execution policy via ConfigCenter 2026-04-08 17:21:35 +08:00
2935daeffa refactor(action): support recover schedulable executable actions together, and ActionExecutor will emit a context block to explain recovering result 2026-04-08 16:52:21 +08:00
e04b2c4fe8 refactor(memory): manage state serialization via StateCenter in MemoryRuntime 2026-04-08 14:55:37 +08:00
21a9d2114f chore(core): remove legact PartnerCore 2026-04-07 23:27:31 +08:00
3640cc2108 feat(action): support continuing executable actions after state restored 2026-04-07 23:16:12 +08:00
a114044c23 refactor(action): manage state serialization via StateCenter in ActionCore 2026-04-07 22:01:46 +08:00
874488ea79 test(memory): test with new memory behavior 2026-04-07 17:23:14 +08:00
b80ff8400c refactor(memory): compute memory slice in MemoryCore 2026-04-07 17:13:51 +08:00
6fd12cd19f fix(memory): restore normalizing logic in memory core, and fix errors in MemoryCoreTest 2026-04-07 15:02:55 +08:00
2cbaccedba refactor(cognition): manage state serialization via StateCenter in CognitionCore 2026-04-07 14:44:47 +08:00
006e7c61e5 refactor(context): remove legacy attribute coreResponse in PartnerRunningFlowContext 2026-04-07 14:42:15 +08:00
2458ea4849 refactor(memory): manage state serialization via StateCenter in MemoryUnit, and support optional loading on register in StateCenter 2026-04-07 12:27:36 +08:00
eab8eec46e chore(memory): add refactor todo in MemoryUpdater 2026-04-07 10:23:55 +08:00
a242723727 refactor(memory): manage state serialization via StateCenter in MemoryCore, and normalize slice and unit building 2026-04-07 10:21:17 +08:00
57bc63c57b refactor(perceive): manage state serialization via StateCenter in PerceiveCore 2026-04-07 10:05:35 +08:00
9aa793df8e feat(state): add StateCenter and related interface 2026-04-06 22:16:50 +08:00
8c04566243 chore(framework): reorganize Partner-Framework 2026-04-06 20:16:51 +08:00
b1ba86be57 chore(build): adjust pom.xml in Partner-Framework and fix test errors 2026-04-06 16:12:13 +08:00
f79a0521b2 refactor(vector): refactor VectorClient configuration loading method 2026-04-06 15:52:30 +08:00
332792daa2 refactor(action): make LocalRunnerClient as default runner client 2026-04-05 23:23:02 +08:00
3b236286b9 refactor(action): remove problematic action tendency cache 2026-04-05 22:32:52 +08:00
50db3fa7b2 refactor(config): adjust method init and onReload to support polymorphic config loading 2026-04-04 23:34:00 +08:00
6503ec32b4 chore(git): update gitignore 2026-04-04 17:54:25 +08:00
9771aa1de5 refactor(model): manage model registry by ConfigCenter 2026-04-04 17:53:54 +08:00
660bb01440 chore(config): add config doc to WebSocketConfig 2026-04-04 14:49:06 +08:00
188b5e8b53 refactor(config): support printing more information after init failed by ConfigDoc 2026-04-04 00:33:25 +08:00
db4dc6d040 refactor(gateway): init and load config from config center for WebSocketGateway 2026-04-03 23:07:40 +08:00
ef9d177adc fix(config): correct duplicate config checking 2026-04-03 15:35:27 +08:00
5a41e02602 fixup! refactor(config): rename watching method and remove useless covariant 2026-04-02 22:59:09 +08:00
f387c36b17 refactor(config): prevent registering Configurable after watching started 2026-04-02 22:55:53 +08:00
03532d3d97 refactor(config): run init after watching started 2026-04-02 22:19:37 +08:00
f37bef57ba refactor(config): rename watching method and remove useless covariant 2026-04-02 22:12:08 +08:00
29d6546b07 feat(config): support ConfigCenter file watching and registered json reloads 2026-04-01 23:43:19 +08:00
b9fd9bcaac refactor(mcp): switch desc.json loading to fastjson2 to avoid desc.json loading error 2026-04-01 22:57:17 +08:00
4ae65b885e refactor(watch): support configurable directory watch depth 2026-04-01 22:15:00 +08:00
632e47ec13 feat(config): add config center and runtime path resolution 2026-04-01 20:42:45 +08:00
4f200cadfc refactor(model): move model APIs from chat to agent.model 2026-03-31 21:13:57 +08:00
e4df68ea5d refactor(chat): extract model activation into provider registry
- move ActivateModel and StreamChatMessageConsumer into api.chat
- replace direct OpenAI runtime construction with ModelRuntimeRegistry
- add provider config, runtime override and OpenAI-compatible provider forking
- rename OpenAiChatRuntime to OpenAiCompatibleProvider and update imports
2026-03-31 18:37:41 +08:00
81aa4b7933 feat(chat): support streaming reply in agent turn 2026-03-31 14:44:58 +08:00
b4c44c7d98 fix(perceive): fix legacy errors 2026-03-31 12:14:52 +08:00
1301a0f8b1 refactor(event): enrich necessary attributes in InteractionEvent.Reply 2026-03-31 10:28:27 +08:00
7d82ec7238 refactor(gateway): register WebsocketGateway as response channel while launch 2026-03-31 10:15:31 +08:00
d70054cd9b refactor(interaction): decouple gateway IO from runtime response flow
- replace interaction adapter/input-output DTO flow with InputData and InteractionEvent
  - introduce ResponseChannel and default LogChannel for runtime response dispatch
  - let AgentGateway parse running context directly and submit turns asynchronously
  - update WebSocketGateway to emit serialized interaction events
  - simplify cognition turn initiation to fire-and-forget semantics
  - streamline running flow context source construction and runtime module execution
2026-03-30 22:46:02 +08:00
def48fd0ce refactor(context): remove legacy module context 2026-03-30 18:01:55 +08:00
0b750f8028 refactor(action): support initiate turn after evaluation 2026-03-29 22:58:55 +08:00
6e37ed032b refactor(context): support skip modules by adding specific moduleName into runningFlowContext 2026-03-29 22:26:10 +08:00
b6c86c6640 refactor(action): adjust pending action block content and make full-expanded block as SUPPLY block 2026-03-29 22:07:29 +08:00
71956b4dce refactor(action): adjust tendency evaluation to be performed asynchronously, and pass the tendency in evaluation to communication as a block of SUPPLY type. 2026-03-29 21:55:53 +08:00
c9466f4359 refactor(executor): remove legacy InteractionThreadPoolExecutor , and change related executor calling into virtual executor and CountDownLatch 2026-03-29 20:19:09 +08:00
cb09b86b23 refactor(memory): remove legacy dialogMap in MemoryRuntime and related modules 2026-03-29 18:54:23 +08:00
d4a5c5a0ed fix(memory): trim persisted overlap from chat snapshot in MemoryUpdater 2026-03-29 18:49:44 +08:00
274d007ba1 refactor(memory): add DialogRollingService to control message rolling logic 2026-03-29 18:24:38 +08:00
c7df35beb4 refactor(memory): correct memorySlice-topicPath binding behavior and adjust slice index into [startIndex,endIndex) 2026-03-29 18:11:02 +08:00
1c995923a1 refactor(context): support copy attributes on root tag into snapshot element 2026-03-29 17:28:41 +08:00
247052e318 refactor(memory): update end index of memory slice 2026-03-29 16:15:30 +08:00
eb1723de97 refactor(memory): remove legacy activated memory slice records in memory core 2026-03-29 16:08:29 +08:00
c2fbfe751f refactor(memory): add memory recalling builtin capability meta-action 2026-03-29 16:04:06 +08:00
4a1828ed94 refactor(memory): finished the context block content produced in MemorySelector 2026-03-29 00:17:14 +08:00
db20e0ca78 refactor(memory): refactor memory selector into asynchronous module 2026-03-28 22:41:48 +08:00
09f90d8ad5 refactor(memory): refactor memory extract/evaluating logic and messages building in memory modules 2026-03-28 21:52:02 +08:00
baa6870ccf chore(action): remove unused attribute 2026-03-28 21:50:17 +08:00
fd43466dd5 refactor(runner): remove useless builtin capability meta actions 2026-03-27 15:22:34 +08:00
7628d40645 refactor(communication): rename module directory 2026-03-27 15:19:36 +08:00
d806693e08 refactor(action): simplify ActionCorrectionRecognizer input and build messages with context/task block 2026-03-27 15:01:45 +08:00
dbfd0b1fc3 refactor(action): simplify corrector input and build messages with context/task block 2026-03-27 14:53:00 +08:00
f5b9f8fc58 refactor(action): simplify extractor input and switch params extraction to context/task block messages 2026-03-26 21:43:48 +08:00
7bbb7745f4 refactor(action): remove legacy additionalContext from Action state and snapshots 2026-03-26 21:22:59 +08:00
b65f5f37fb refactor(context): rename encodeToContextMessage to encodeToMessage and update usages 2026-03-26 20:43:58 +08:00
fb9b3860af refactor(common): extract shared XML Block base and reuse it in BlockContent and TaskBlock 2026-03-26 20:43:26 +08:00
c5256cbc90 refactor(module): flatten package paths from module.modules.* to module.* and remove unused ModelConstant 2026-03-26 19:59:03 +08:00
1592c876c7 refactor(action): emit full execution lifecycle/correction blocks and carry correction reason in CorrectorResult 2026-03-26 17:32:40 +08:00
453a1cfe84 refactor(build): move kotlin sourceDirs into compile/test-compile executions 2026-03-26 16:52:29 +08:00
54320dbfde refactor(context): make block activation/rendering exposure-aware and use rendered projections in aggregation 2026-03-26 16:49:56 +08:00
201addbc64 refactor(build): centralize surefire config in parent POM and default to running tests 2026-03-26 16:44:21 +08:00
5219142b5c refactor(action): add ExecutingActionBlockManager to emit execution lifecycle ContextBlocks from action snapshots 2026-03-26 15:38:01 +08:00
750bef0fd8 refactor(action): add snapshot models and snapshot builders for Action/StateAction 2026-03-26 15:18:46 +08:00
a9b925c614 refactor(context): aggregate resolved blocks by source snapshots and centralize elapsed-time activation refresh 2026-03-25 20:13:55 +08:00
264a45c85f refactor(context): adjust fading factor of pending-action block 2026-03-24 22:55:58 +08:00
155d06df45 refactor(context): add urgency attribute/label to BlockContent 2026-03-24 22:52:02 +08:00
7879836b91 refactor(action): remove the explicit PendingAction control flow and assume the confirmation semantics through a short-term, fast-decaying ContextBlock belonging to the ACTION domain. 2026-03-24 22:28:42 +08:00
82db27484c refactor(communication): adjust domains that involved in communication 2026-03-24 14:28:51 +08:00
d11a431614 refactor(action): remove the redundant fields in the prompt construction logic and data classes left in ActionEvaluator 2026-03-24 14:24:31 +08:00
50b07488a6 refactor(action): adjust ActionPlanner and related submodules to adapt to current Agent Context acquisition 2026-03-24 11:49:29 +08:00
313cea0d3b refactor(communication): register recent chat messages as context into ContextWorkspace 2026-03-24 11:28:40 +08:00
4494d58ff9 refactor(context): add ResolvedContext as response of ContextWorkspace#resolve, integrated with Message encoding 2026-03-24 11:04:03 +08:00
d7179364a1 refactor(context): forces the context of the first domain hit to be fully expanded to adapt to the context focus needs within the module 2026-03-24 10:29:15 +08:00
b05ef8683d refactor(executor): remove legacy PhaserRecord and related methods in ActionCapability 2026-03-23 23:27:37 +08:00
556b8a5348 refactor(executor): remove legacy ActionRepairer、DynamicActionGenerator and related data class 2026-03-23 23:19:16 +08:00
027ebf860e refactor(executor): Reconstruct the execution process of ExecutableAction in ActionExecutor, remove ActionRepairer, and adjust the execution timing of ActionCorrector 2026-03-23 23:16:57 +08:00
8cd12f7379 refactor(action): add resume/interrupt methods to ExecutableAction; add related definitions to support acquiring help from user 2026-03-23 17:24:19 +08:00
617daea17c refactor(context): remove legacy ContextBlock 2026-03-22 22:18:32 +08:00
61d5270625 refactor(perceive): refactor into registering context via ContextWorkspace 2026-03-22 22:17:21 +08:00
93b0199c9e refactor(communication): route messages through cognition workspace 2026-03-22 22:01:04 +08:00
977d92881c feat(cognition): add ContextWorkspace to manage context blocks 2026-03-22 21:39:25 +08:00
6aa96c33ac refactor(cognition): remove legacy user exception 2026-03-22 13:50:18 +08:00
e85094670b refactor(cognition): rename Cognation core/capability and package references to Cognition 2026-03-22 12:31:57 +08:00
21ea6a25c8 refactor(chat): remove legacy MetaMessage POJO 2026-03-22 11:02:37 +08:00
ad65cd4c09 feat(runner): add and register DynamicAction related builtin MetaAction provider 2026-03-21 23:53:13 +08:00
ff46d97eed feat(scheduler): add cancel method to ActionScheduler 2026-03-21 22:39:18 +08:00
1a83075031 refactor(runner): inline command action JSON responses and remove command response DTOs 2026-03-21 18:14:47 +08:00
809d38bd07 refactor(action): remove outdated TODO comments in ActionScheduler 2026-03-20 23:16:57 +08:00
f7d46c8ef1 refactor(action): remove legacy interventor module and move intervention entities into core action package 2026-03-20 23:09:58 +08:00
e1ee6589ef feat(runner): add and register builtin intervention action provider with intervention meta actions 2026-03-20 23:04:32 +08:00
17108f3239 fix(runner): correct actions list provided in BuiltinCapabilityActionProvider 2026-03-20 15:02:13 +08:00
59a5e22f35 refactor(runner): extract createActionKey as an abstract method in BuiltinActionProvider 2026-03-20 15:01:22 +08:00
30373cbc02 feat(runner): register builtin capability action definitions in BuiltinActionRegistry 2026-03-19 23:20:06 +08:00
0e164115c0 feat(runner): add builtin capability action provider for memory slices, initiate turn, and interaction status 2026-03-19 23:18:32 +08:00
3cc6e8df99 refactor(perceive): return Instant in showLastInteract 2026-03-19 23:16:02 +08:00
ccb7041093 refactor(perceive): remove legacy user storage in perceive core 2026-03-19 23:14:20 +08:00
e0b20ce414 refactor(runner): adjust command action response shcema in BuiltinCommandActionProvider 2026-03-19 11:31:34 +08:00
1029624dc7 refactor(cogiaiateTurnnation): support assigning reply target in method
initiateTurn
2026-03-19 10:54:36 +08:00
5b9b9c3c09 refactor(runner): add builtin action provider interface 2026-03-19 10:39:06 +08:00
67d7fd34f8 feat(runner): register builtin command action definitions in BuiltinActionRegistry 2026-03-18 23:06:06 +08:00
12368ded53 feat(runner): implement builtin command session actions with start/inspect/read/cancel/overview 2026-03-18 23:00:56 +08:00
7d9ec976e3 feat(runner): implement builtin command execute MetaAction definition 2026-03-18 17:15:47 +08:00
d8b19ebcea refactor(runner): refactor CommandExecutionService into single instance 2026-03-18 16:52:52 +08:00
7f4b82204a refactor(runner): change stdout/stderr reading thread into virtual thread in CommandExecutionService 2026-03-18 16:18:10 +08:00
664bd5a0fb refactor(runner): add typed param helper methods in BuiltinActionRegistry 2026-03-17 22:54:55 +08:00
6474eb8dc6 refactor(runner): allow object-typed params in BuiltinActionRegistry builtin actions 2026-03-17 22:51:00 +08:00
4439e5c04b feat(runner): add BuiltinCommandActionManager and command action data models scaffold 2026-03-17 22:24:23 +08:00
ef2eb909b7 refactor(runner): use string-only params and return type for BuiltinActionRegistry builtin actions 2026-03-17 22:12:22 +08:00
fd20af3e1c test(exec): add test for CommandExecutionService 2026-03-17 14:59:48 +08:00
d30ff322a2 refactor(runner): remove unused static method definition in BuiltinActionRegistry 2026-03-17 14:32:29 +08:00
cb63bbf570 feat(runner): add builtinAction defining method to BuiltinActionRegistry 2026-03-17 14:08:50 +08:00
4da4e5f161 refactor(runner): rename method buildDefinitions in BuiltinActionRegistry 2026-03-17 13:56:25 +08:00
5a717dbdda refactor(runner): load different policy provider according to os, now support bwrap sandbox in linux only 2026-03-17 12:21:31 +08:00
a6682a7719 feat(runner): implement BubbleWrap policy provider and related test 2026-03-17 12:11:54 +08:00
1465d7687b refactor(runner): add policy listener registering function and support registering McpConfigWatcher after starting 2026-03-17 10:35:35 +08:00
d31cac70a6 refactor(runner): apply execution policy wrapping in MCP transport and reload on policy changes 2026-03-16 22:45:49 +08:00
108cf9b071 refactor(runner): rename method buildFileExecutionCommands in CommandExecutionService 2026-03-16 16:52:04 +08:00
c4b8c2a858 refactor(runner): rename exec vararg parameter to commands for clarity 2026-03-15 22:41:46 +08:00
d55b849747 refactor(runner): apply execution policy wrapping before command execution in OriginExecutionService 2026-03-15 22:41:19 +08:00
a9993299a5 refactor(runner): add exec(List<String>) overload in CommandExecutionService 2026-03-15 22:41:11 +08:00
4c47cac3a5 fix(runner): repair MetaAction related logic in McpMetaRegistry and tests 2026-03-14 21:44:27 +08:00
cba9ff4f0b refactor(action): pass launcher through meta action flow instead of inferring command by file extension 2026-03-14 21:27:38 +08:00
603b0835c5 将 .java 重命名为 .kt 2026-03-14 21:27:38 +08:00
fc0d4ef03b refactor(runner): remove legacy abstract for command execution 2026-03-13 15:22:14 +08:00
97bb897407 feat(runner): add execution policy abstract for local running 2026-03-13 14:45:50 +08:00
8463eb9dae refactor(runner): remove unused method listSystemDependencies 2026-03-12 16:07:06 +08:00
9794b39572 refactor(runner): adjust the directory organization of runner 2026-03-12 15:32:28 +08:00
0506149f5f refactor(runner): separate logic of different domain in LocalRunnerClient into different class 2026-03-12 15:04:13 +08:00
9325b84d14 refactor(ActionExecutor): remove unused ActionScheduler in executor 2026-03-12 11:59:26 +08:00
6c8a1b2636 refactor(action): support built-in actions 2026-03-12 10:41:17 +08:00
3c550af33d refactor(perceive): omit user lookup when building evaluator input 2026-03-11 14:41:43 +08:00
229c7a0edb refactor(memory): remove redundant activated slice helpers 2026-03-11 13:37:18 +08:00
a067e058fb refactor(memory): remove module context and recall tracking 2026-03-10 23:09:32 +08:00
cdfae8ab1a refactor(memory): remove postprocess executor and simplify memory updater trigger 2026-03-10 23:07:58 +08:00
c1998f61b6 refactor(perceive): drop legacy perceive updater modules and remove PreProcessExecutor 2026-03-10 22:59:29 +08:00
3f6283d12a refactor(perceive): expose last interaction tracking and refresh memory sessions 2026-03-10 22:57:59 +08:00
3d1c258944 refactor(memory): drop message cleanup before summarizing 2026-03-10 21:15:35 +08:00
36dfd65046 refactor(CommunicationProducer): drop timestamp from user message 2026-03-10 21:13:12 +08:00
ee1a033c1b refactor(memory): centralize memory recording and retrieval logic 2026-03-10 20:42:46 +08:00
027e8bddc0 refactor(memory): move memory id refresh into runtime init 2026-03-10 20:17:34 +08:00
0903b8482b test(CommunicationProducer): remove CommunicationProducerTest 2026-03-10 19:54:37 +08:00
f51401e2f2 refactor(CommunicationProducer): snapshot chat history when assembling conversation 2026-03-10 19:53:20 +08:00
5ad80d8b86 refactor(memory): decouple memory storage and runtime structures 2026-03-10 19:41:05 +08:00
760ba8300b refactor(module): remove legacy prompt scaffolding 2026-03-10 17:15:50 +08:00
0f3d4659ae chore(project): remove legacy module Partner-Test-Demo 2026-03-10 15:04:16 +08:00
331d415925 refactor(CommunicationProducer): update datetime pattern and source in communicating 2026-03-10 15:01:07 +08:00
f5f64971f3 refactor(ContextBlock): return dom nodes directly 2026-03-10 14:48:14 +08:00
1cd6ba11bb refactor(CommunicationProducer): split context and supply message assembly 2026-03-10 14:31:13 +08:00
5db533f823 refactor(chat): use Message.Character enum for roles and remove unused prompt helpers 2026-03-09 22:12:35 +08:00
1b2ccaee9c refactor(chat): replace custom client with OpenAI runtime and remove file-based module prompt loading logic, prompt will be provided by each module 2026-03-09 21:51:07 +08:00
8dc7ed080b chore(build): import OpenAI dependency 2026-03-09 16:20:10 +08:00
3348557352 refactor(Action): backfill ExecutableAction result on success/failure and add immediate-action completion watcher self-talk 2026-03-08 15:42:25 +08:00
4bb83f86a8 refactor(ActionPlanner): switch pending confirmation flow to PendingActionRecord with decision parsing and reminder/expire lifecycle scheduling 2026-03-08 14:40:53 +08:00
b256af0f58 refactor(Action): remove @JvmOverloads from SchedulableExecutableAction constructor 2026-03-08 13:32:08 +08:00
ec429db4da refactor(Core): normalize preprocess user resolution from source/additional info, add Kotlin-safe AgentConfigLoader getters, and update async summary writes by index 2026-03-08 13:31:53 +08:00
145aeed600 refactor(Module): remove unused meta component POJOs from agent factory 2026-03-08 13:31:02 +08:00
5e8ef6d66f refactor(build): add kotlin-maven-plugin setup to Partner-Core and Partner-Framework poms 2026-03-08 13:30:39 +08:00
65690c65f8 refactor(MemoryUpdater): move auto-update to ActionScheduler cron and use Cognation snapshot/drain APIs for thread-safe memory refresh 2026-03-08 13:11:20 +08:00
7df0f208b5 refactor(Module): rename PostRunningAbstractAgentModuleAbstract to PostRunningAgentModule and update updater inheritance 2026-03-08 12:04:29 +08:00
4484d4a06b refactor(Context): remove finished state from flow/module context and drop MemoryUpdater finish guard 2026-03-08 11:47:44 +08:00
25ddc6f181 refactor(ActionExecutor): enforce action timeout with cancellation and move timeout defaults into Action base model 2026-03-07 20:15:41 +08:00
d905c4ace1 refactor(Action): add @JvmOverloads constructors to SchedulableExecutableAction and StateAction 2026-03-07 18:52:36 +08:00
c3c4c88c9a refactor(ActionScheduler): add timeout attribute to Schedulable, and support reschedule Schedulable content when it's fished in ActionScheduler 2026-03-07 17:05:07 +08:00
ae1b7fc033 refactor(ActionScheduler): support receiving single data that implements Schedulable and Action in ActionScheduler 2026-03-07 15:30:25 +08:00
d9e384960f refactor(action): remove ActionExecutorInput 2026-03-07 15:15:08 +08:00
2baa3971a8 refactor(action): support executing any type of Actions with virtual thread in ActionExecutor, ActionScheduler will send actionData to executor directly 2026-03-07 15:05:51 +08:00
4ee7a52f42 refactor(Action): make attribute status available for all implementations of Action, StateAction needs to present its trigger status also 2026-03-07 14:29:11 +08:00
28400545a7 chore(ActionExecutor): remove unused Void return value 2026-03-07 14:20:07 +08:00
1ce2038ab8 fix(Communication): fix Message appending logic and add refactor todo 2026-03-07 14:01:33 +08:00
0b63ec8523 fix(MemoryUpdater): fix message cleaning logic, and add refactor todo in updater 2026-03-07 13:53:34 +08:00
28a1bf8d1f refactor(chat): migrate Message from Java POJO to Kotlin data class 2026-03-06 21:04:58 +08:00
77059f84c4 将 .java 重命名为 .kt 2026-03-06 21:04:58 +08:00
d3eb5e8ee3 refactor(config): migrate ModelConfig from Java POJO to Kotlin data class 2026-03-06 17:01:03 +08:00
01cfc04dc7 将 .java 重命名为 .kt 2026-03-06 17:01:03 +08:00
6919fe656e refactor(module): rename CoreModel into CommunicationProducer 2026-03-06 15:21:36 +08:00
df25f488fa refactor(action): remove ActionDispatcher and related empty directory 2026-03-06 15:06:32 +08:00
036fd9e051 refactor(ActionPlanner): support schedule or execute actions(or
confirmed actions) immediately
2026-03-06 14:58:13 +08:00
383a49b855 refactor(ActionExecutor): refactor into Standalone module 2026-03-06 14:49:01 +08:00
7e88b8b926 chore(action): add refactor todos in ActionScheduler 2026-03-06 14:28:52 +08:00
c6c8a83dad chore(test): remove unused non-null test for ActionScheduler 2026-03-06 14:17:04 +08:00
6635d7aca2 refactor(Action): add attribute enabled status into Action, and update related collectToTrigger logic in ActionScheduler 2026-03-06 14:15:51 +08:00
facc49a799 refactor(ActionScheduler): rename entry method into schedule 2026-03-06 14:04:15 +08:00
3c6076ee0a chore(idea): update misc.xml 2026-03-06 12:49:02 +08:00
40bd2deeba feat(cognation): add initiateTurn to execute input via AgentRuntime.submit 2026-03-05 16:49:17 +08:00
839f19f15b refactor(context): add PartnerRunningFlowContext factories for user/self source and update adapter creation 2026-03-04 20:02:56 +08:00
da1abbdc88 fix(AgentRuntime): repair exception handling logic in method executeTurn 2026-03-04 17:23:14 +08:00
e6a071fc93 refactor(context): migrate running flow context to source/status/info model, and update related modules 2026-03-04 17:21:34 +08:00
56688785ba 将 .java 重命名为 .kt 2026-03-04 17:21:34 +08:00
8a9892f039 chore(core): add TODO to use RunningFlowContext for message timestamp in CoreModel 2026-03-04 13:52:19 +08:00
06f5ae9aac refactor(core): remove global running flow context map and exception context reference 2026-03-04 13:11:42 +08:00
f8d90fbcee refactor(framework): make AgentRuntime.submit blocking and remove runBlocking from AgentInteractionAdapter 2026-03-03 21:23:52 +08:00
b02f29b1b1 refactor(framework): extract interaction execution into AgentRuntime and delegate from AgentInteractionAdapter 2026-03-03 21:14:10 +08:00
f1848fece4 refactor(framework): cache running modules in AgentInteractionAdapter and add refresh method 2026-03-03 20:29:23 +08:00
85cc5cace8 chore(framework): add message queue todo in AgentGateway 2026-03-03 11:48:59 +08:00
d462f02960 refactor(framework): mv interaction in-out flow into AgentInteractionAdapter 2026-03-03 11:48:08 +08:00
5ae8b713d7 refactor(framework): correct InteractionAdapter, support loading latest modules while running 2026-03-03 11:26:36 +08:00
cf25fce09e refactor(framework): remove coordinated capability mechanism and related manager/annotations 2026-03-02 20:34:30 +08:00
868b17b56b refactor(core): use chat message user IDs for single-user check in
`MemorySelector`
2026-03-02 20:34:16 +08:00
fe8031d9ac fix(core): remove CoordinatedManager log tag from memory insert logs 2026-03-02 20:31:22 +08:00
5847b38f2b refactor(framework): remove obsolete lifecycle TODO comment in AgentModule 2026-03-01 21:35:30 +08:00
6920bc6130 refactor(core): remove redundant @NotNull type-use annotation from async resource spec builder 2026-03-01 21:34:56 +08:00
fa9512db3b refactor(framework): migrate AgentInteractionAdapter flow execution to Kotlin coroutines and remove AgentRunningFlow 2026-03-01 21:33:31 +08:00
51d51937ed 将 .java 重命名为 .kt 2026-03-01 21:33:31 +08:00
23026d6dc8 refactor(framework): move RunningFlowContext from flow.entity to flow package 2026-03-01 21:31:04 +08:00
661dd625e3 chore(maven): move coroutines dependencies into Partner-Framework 2026-03-01 20:48:41 +08:00
33fdc61eff refactor(framework): remove module enabled-status loading and persistence from config loaders 2026-02-28 21:19:58 +08:00
0870d7bc0e fix(framework): fail module registration on duplicate moduleName in AgentContext 2026-02-28 21:05:12 +08:00
baf0b05e60 doc(framework): add KDoc for factory responsibilities and agent registration lifecycle 2026-02-28 20:44:40 +08:00
51efb55259 refactor(framework): rename ComponentInitHookExecuteFactory to ComponentInitHookExecutorFactory 2026-02-28 20:38:29 +08:00
d5095359db refactor(framework): validate and collect @Shutdown hooks during agent
registration
2026-02-28 20:38:09 +08:00
1abfc729f8 fix(framework): reject @Init methods with parameters during component validation 2026-02-28 20:25:33 +08:00
528e88f613 refactor(framework): scope shutdown-only Instances and computeInstances helpers inside installShutdownHook 2026-02-27 00:34:07 +08:00
333d087979 refactor(framework): register and execute ordered @Shutdown hooks in AgentContext via JVM shutdown hook 2026-02-27 00:28:14 +08:00
a863b43563 refactor(framework): register capability core instances per capability and store cores in AgentContext 2026-02-26 22:27:43 +08:00
dde01a6253 fix(framework): reject additional components missing @AgentComponent annotation 2026-02-26 22:18:36 +08:00
fa50f4aeb7 refactor(framework): store AgentContext additional components by type and update init/injection target collection 2026-02-26 22:17:41 +08:00
b87ede0e8b refactor(framework): add @Shutdown annotation to AgentContext for ordered shutdown hook execution 2026-02-26 22:08:33 +08:00
010860de8d refactor(framework): migrate AgentRegisterFactory to Kotlin object and preserve agent registration flow 2026-02-23 23:34:54 +08:00
379cabe042 refactor(framework): replace ModuleInitHookExecuteFactory with Kotlin ComponentInitHookExecuteFactory and drive @Init execution from validated component context 2026-02-23 23:14:45 +08:00
1b164cedf1 refactor(framework): migrate capability injection to Kotlin CapabilityInjectorFactory and inject capability instances directly into components 2026-02-23 22:59:47 +08:00
7ee698768c refactor(framework): simplify AgentContext capability storage to a single implementation per capability 2026-02-23 22:59:20 +08:00
2e29e5ca7f refactor(framework): migrate CapabilityRegisterFactory to Kotlin and rebuild capability registration from validated context 2026-02-23 22:32:32 +08:00
e0a62053b5 refactor(framework): migrate AgentRegisterContext to Kotlin and store validated capability scan results in context 2026-02-23 22:12:56 +08:00
f13e45327d refactor(framework): remove legacy CapabilityFactoryContext and ModuleFactoryContext from registration flow 2026-02-23 21:58:25 +08:00
f56ff7d719 refactor(framework): rework AgentContext capability storage to group implementations by capability and include method metadata 2026-02-23 21:53:37 +08:00
fd9b376afa refactor(framework): replace CapabilityCheckFactory with Kotlin CapabilityAnnotationValidatorFactory and update capability validation flow 2026-02-23 21:41:38 +08:00
542de84640 refactor(framework): add ComponentInjectorFactory for module/additional component injection before capability registration 2026-02-23 21:16:04 +08:00
907bb626f2 chore(gitignore): update gitignore 2026-02-22 14:15:17 +08:00
2cdeaa1c30 refactor(framework): make AgentContext capabilities non-null and infer capability type on registration 2026-02-21 22:38:56 +08:00
833fe4deb3 refactor(framework): add component annotation validation before component registration 2026-02-21 19:27:17 +08:00
3c26e77b76 refactor(framework): rename AgentComponentRegisterFactory to ComponentRegisterFactory 2026-02-21 19:19:04 +08:00
2825f7f1de refactor(framework): replace legacy module check/register/proxy flow with unified AgentComponentRegisterFactory 2026-02-21 18:56:40 +08:00
86b7e5c492 refactor(framework): rename agent.factory.module to agent.factory.component and update related imports 2026-02-21 17:57:29 +08:00
b1e4d3c2e4 fixup! refactor(framework): rename AgentConfigManager to AgentConfigLoader and update agent/core wiring 2026-02-21 17:46:16 +08:00
997616e45f refactor(framework): migrate ConfigLoaderFactory to Kotlin and simplify loader metadata registration 2026-02-21 17:42:05 +08:00
6733984843 将 .java 重命名为 .kt 2026-02-21 17:42:05 +08:00
0f2052c507 refactor(framework): migrate AgentBaseFactory from Java to Kotlin and update execute signature 2026-02-21 17:22:38 +08:00
23bfb8bac1 将 .java 重命名为 .kt 2026-02-21 17:22:38 +08:00
15c11ac500 refactor(framework): type AgentContext metadata entries and add JSON-backed metadata registration 2026-02-21 17:10:46 +08:00
deffc91dd1 refactor(framework): remove obsolete Java AgentContext class 2026-02-21 16:55:31 +08:00
b2d44668da refactor(framework): rename AgentConfigManager to AgentConfigLoader and update agent/core wiring 2026-02-21 16:51:59 +08:00
f8399d2280 refactor(framework): add additional component storage and guarded registration in AgentContext 2026-02-21 16:28:20 +08:00
2870e79f79 refactor(framework): remove obsolete agent proxy and register test stubs 2026-02-21 16:19:57 +08:00
3c9ace8e56 refactor(framework): rename CapabilityHolder to AgentComponent across factory and module hooks 2026-02-21 16:19:00 +08:00
e510725e71 refactor(framework): remove legacy running/sub module base classes and module annotations 2026-02-21 16:14:46 +08:00
f963cae4ed refactor(framework): rename Context.kt to AgentContext.kt 2026-02-21 16:06:11 +08:00
45c4e8169a refactor(framework): add mutable metadata map to Context 2026-02-21 15:43:19 +08:00
6bf4d95b05 refactor(framework): encapsulate AgentContext maps and require modelInfo in module contexts 2026-02-20 21:31:20 +08:00
00ef090d2f refactor(framework): generalize AgentContext and ModuleContextData generics with wildcard bounds 2026-02-20 20:55:56 +08:00
e62cddfe44 refactor(framework): add enabled flag to ModuleContextData.Running 2026-02-20 19:00:49 +08:00
115a8d5446 refactor(framework): redesign AgentContext to store typed module contexts and runtime metadata 2026-02-20 18:57:36 +08:00
ef5d5802a7 refactor(framework): make Standalone extend AbstractAgentModule 2026-02-20 17:46:33 +08:00
87c34cc699 refactor(modules): convert ActionScheduler to Standalone and simplify async execute signature 2026-02-20 17:29:26 +08:00
bbace28d7a refactor(project): normalize formatting and reorder class members across modules 2026-02-20 17:22:54 +08:00
c47d2b2285 refactor(modules): refactor modules base class into AbstractAgentModule and remove unused @slf4j annotation 2026-02-20 17:17:49 +08:00
38c618a222 chore(gitignore): update gitignore 2026-02-20 16:30:22 +08:00
e00441faa8 refactor(framework): make AbstractAgentModule sealed with class-based module contracts and streamline ActivateModel model access 2026-02-20 16:12:35 +08:00
c3b0a9dd25 refactor(framework): make ActivateModel companion configManager private 2026-02-20 15:39:52 +08:00
6b7c9db5b1 refactor(framework): add order() to AbstractAgentModule.Running contract 2026-02-20 15:30:55 +08:00
e2ef92ce43 refactor(framework): use moduleName as modelKey for
`AbstractAgentModule` instances in ActivateModel
2026-02-20 15:29:38 +08:00
051b6450e7 refactor(framework): mark AbstractAgentModule as capability holder and consolidate module contracts within abstracts 2026-02-20 15:24:35 +08:00
2a3d33a61e refactor(framework): correct comments for ActivateModel 2026-02-20 15:02:33 +08:00
e57c03e213 refactor(framework): migrate module abstracts/ActivateModel to Kotlin and introduce shared model/context structures 2026-02-20 15:00:14 +08:00
14e6d71ac9 将 .java 重命名为 .kt 2026-02-20 15:00:14 +08:00
dc9f9417bc refactor(framework): remove @BeforeExecute/@AfterExecute hook proxy logic and use direct module instantiation 2026-02-19 22:53:49 +08:00
5051c2f662 refactor(framework): use existing model instance in
init hook `ActivateModel#modelSettings`
2026-02-19 21:46:37 +08:00
c30ec35f85 refactor(framework): rename @AgentModule to @AgentRunningModule 2026-02-19 21:39:59 +08:00
c7f113b59a refactor(framework): rename AgentRunningModule/SubModule to AbstractAgent* and migrate module inheritance usage 2026-02-19 15:04:30 +08:00
8735660830 refactor(framework): remove log hook surrounded with method execute in AgentRunningSubModule 2026-02-19 14:37:21 +08:00
18b2bb8812 refactor(framework): reorganize Module abstracts location 2026-02-19 14:09:51 +08:00
7fccea5b91 chore(agent): add todo for PartnerOutputData 2026-02-19 14:07:39 +08:00
a9bf7ca1c2 refactor(framework): correct exception names in Partner-Framework 2026-02-19 14:01:26 +08:00
1685d148c4 chore(gitignore): update gitignore 2026-02-19 14:00:35 +08:00
73ab40416d refactor(Project): rename Partner-Api/Partner-Main modules to Partner-Framework/Partner-Core and update Maven dependencies 2026-02-19 10:39:21 +08:00
1244d59fa4 chore(ActionScheduler): remove todos 2026-02-18 15:22:02 +08:00
11ea1045f4 refactor(Action): generalize ActionScheduler to Schedulable and add StateAction trigger execution path 2026-02-18 15:20:52 +08:00
a1bc784da5 refactor(Action): rename Scheduled interfaces/classes to Schedulable 2026-02-15 23:09:35 +08:00
747d3e47d6 refactor(Action): add StateAction with scheduled trigger support for state updates/callbacks 2026-02-15 21:27:11 +08:00
5f0165fa3a refactor(Action): split ActionData into Action/ExecutableAction and unify scheduled action types 2026-02-15 21:26:17 +08:00
2b0682b9e0 chore(Action): remove todo in ActionData
Context:
SYNC is like the normal reAct execution, the thread based execution model with necessary notification can cover the demands entirely
2026-02-14 12:02:03 +08:00
16a92de377 chore(Action): add TODO notes for trigger type design and executor write-back flow 2026-02-13 21:27:23 +08:00
cbba183b60 docs(README): formatted 2026-02-10 13:52:14 +08:00
8e642b07d9 docs(README): expand Action system section with architecture and execution flow details 2026-02-10 13:50:31 +08:00
66d8a95c73 docs(README): clean up section formatting and update content 2026-02-10 13:26:31 +08:00
0850f8403d docs(README): rewrite project description and adjust planning items 2026-02-10 13:17:30 +08:00
24c29a6dc6 chore(resource): remove legacy Partner prompt and module config in resources, which will be provided in config dir or other ways 2026-02-10 13:17:05 +08:00
f703cc8157 refactor(vector): make embedding URL and model fields final 2026-02-10 13:05:09 +08:00
d52f48f132 fix(AgentConfigManager): set default INSTANCE to null instead of FileAgentConfigManager, which will be set in ConfigLoaderFactory or AgentApp 2026-02-10 13:03:58 +08:00
458 changed files with 22479 additions and 13692 deletions

5
.gitignore vendored
View File

@@ -8,6 +8,8 @@ target/
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
.idea/db-forest-config.xml
.idea/markdown.xml
*.iws
*.iml
*.ipr
@@ -58,3 +60,6 @@ build/
/Partner-Main/data/
/AGENTS.md
/.serena/
/Partner-Core/data/
/.ai/mcp/mcp.json
/.codex

View File

@@ -1,6 +1,7 @@
<component name="ProjectDictionaryState">
<dictionary name="project">
<words>
<w>openai</w>
<w>zuper</w>
</words>
</dictionary>

12
.idea/encodings.xml generated
View File

@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/Partner-Api/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Api/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/java/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/java/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Main/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Core/src/main/java/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Core/src/main/java/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Framework/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Framework/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-SandboxRunner/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Test-Demo/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/Partner-Test-Demo/src/main/resources" charset="UTF-8" />

31
.idea/misc.xml generated
View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<list size="15">
<list size="19">
<item index="0" class="java.lang.String" itemvalue="lombok.Data" />
<item index="1" class="java.lang.String" itemvalue="net.bytebuddy.implementation.bind.annotation.RuntimeType" />
<item index="2" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.capability.annotation.Capability" />
@@ -8,18 +9,25 @@
<item index="4" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.capability.annotation.CapabilityMethod" />
<item index="5" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.capability.annotation.CoordinateManager" />
<item index="6" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.capability.annotation.Coordinated" />
<item index="7" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute" />
<item index="8" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.AgentModule" />
<item index="9" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule" />
<item index="10" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute" />
<item index="11" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.Init" />
<item index="12" class="java.lang.String" itemvalue="work.slhaf.partner.api.capability.annotation.CapabilityMethod" />
<item index="13" class="java.lang.String" itemvalue="work.slhaf.partner.api.capability.annotation.CoordinateManager" />
<item index="14" class="java.lang.String" itemvalue="work.slhaf.partner.api.register.capability.annotation.Capability" />
<item index="7" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.component.annotation.Init" />
<item index="8" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute" />
<item index="9" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.AgentRunningModule" />
<item index="10" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule" />
<item index="11" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute" />
<item index="12" class="java.lang.String" itemvalue="work.slhaf.partner.api.agent.factory.module.annotation.Init" />
<item index="13" class="java.lang.String" itemvalue="work.slhaf.partner.api.capability.annotation.CapabilityMethod" />
<item index="14" class="java.lang.String" itemvalue="work.slhaf.partner.api.capability.annotation.CoordinateManager" />
<item index="15" class="java.lang.String" itemvalue="work.slhaf.partner.api.register.capability.annotation.Capability" />
<item index="16" class="java.lang.String" itemvalue="work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityCore" />
<item index="17" class="java.lang.String" itemvalue="work.slhaf.partner.framework.agent.factory.capability.annotation.CapabilityMethod" />
<item index="18" class="java.lang.String" itemvalue="work.slhaf.partner.framework.agent.factory.component.annotation.AgentComponent" />
</list>
<writeAnnotations>
<writeAnnotation name="work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability" />
<writeAnnotation name="work.slhaf.partner.api.agent.factory.component.annotation.InjectModule" />
<writeAnnotation name="work.slhaf.partner.api.agent.factory.module.annotation.InjectModule" />
<writeAnnotation name="work.slhaf.partner.framework.agent.factory.capability.annotation.InjectCapability" />
<writeAnnotation name="work.slhaf.partner.framework.agent.factory.component.annotation.InjectModule" />
</writeAnnotations>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
@@ -30,6 +38,11 @@
<option value="$PROJECT_DIR$/PartnerExecutor/pom.xml" />
</list>
</option>
<option name="ignoredFiles">
<set>
<option value="$PROJECT_DIR$/Partner-Test-Demo/pom.xml" />
</set>
</option>
</component>
<component name="PWA">
<option name="enabled" value="true" />

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>Partner</artifactId>
<groupId>work.slhaf</groupId>
<version>0.5.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Partner-Api</artifactId>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>hamcrest-core</artifactId>
<groupId>org.hamcrest</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<properties>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>work.slhaf</groupId>
<artifactId>Partner</artifactId>
<version>0.5.0</version>
</parent>
<artifactId>Partner-Api</artifactId>
<dependencies>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.17.6</version>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.13.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.17</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.17</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.36</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.56</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@@ -1,156 +0,0 @@
package work.slhaf.partner.api.agent;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.AgentRegisterFactory;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.exception.AgentExceptionCallback;
import work.slhaf.partner.api.agent.runtime.exception.AgentLaunchFailedException;
import work.slhaf.partner.api.agent.runtime.exception.GlobalExceptionHandler;
import work.slhaf.partner.api.agent.runtime.interaction.AgentGateway;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* <h2>Agent 启动入口</h2>
* 详细启动流程请参阅{@link AgentRegisterFactory}
*/
@Slf4j
public final class Agent {
public static AgentConfigManagerStep newAgent(Class<?> clazz) {
if (clazz == null) {
throw new AgentLaunchFailedException("Agent class 和 interaction flow context 不能为 null");
}
return new AgentApp(clazz);
}
public interface AgentConfigManagerStep {
AgentGatewayStep setAgentConfigManager(Class<? extends AgentConfigManager> agentConfigManager);
}
public interface AgentGatewayStep {
AgentStep setGateway(Class<? extends AgentGateway> gateway);
}
public interface AgentStep {
AgentStep addBeforeLaunchRunners(Runnable... runners);
AgentStep addAfterLaunchRunners(Runnable... runners);
AgentStep setAgentExceptionCallback(Class<? extends AgentExceptionCallback> agentExceptionCallback);
AgentStep addScanPackage(String packageName);
AgentStep addScanDir(String externalPackagePath);
void launch();
}
public static class AgentApp implements AgentStep, AgentGatewayStep, AgentConfigManagerStep {
private final ExecutorService executorService = Executors.newVirtualThreadPerTaskExecutor();
private final List<Runnable> beforeLaunchRunners = new ArrayList<>();
private final List<Runnable> afterLaunchRunners = new ArrayList<>();
private AgentGateway gateway;
private final Class<?> applicationClass;
private Class<? extends AgentConfigManager> agentConfigManagerClass;
private Class<? extends AgentGateway> gatewayClass;
private Class<? extends AgentExceptionCallback> agentExceptionCallbackClass;
private final CountDownLatch latch = new CountDownLatch(1);
private AgentApp(Class<?> clazz) {
this.applicationClass = clazz;
}
@Override
public AgentStep setGateway(Class<? extends AgentGateway> gateway) {
this.gatewayClass = gateway;
return this;
}
@Override
public AgentStep addBeforeLaunchRunners(Runnable... runners) {
this.beforeLaunchRunners.addAll(List.of(runners));
return this;
}
@Override
public AgentStep addAfterLaunchRunners(Runnable... runners) {
this.afterLaunchRunners.addAll(List.of(runners));
return this;
}
@Override
public AgentGatewayStep setAgentConfigManager(Class<? extends AgentConfigManager> agentConfigManager) {
this.agentConfigManagerClass = agentConfigManager;
return this;
}
@Override
public AgentStep setAgentExceptionCallback(Class<? extends AgentExceptionCallback> agentExceptionCallback) {
agentExceptionCallbackClass = agentExceptionCallback;
return this;
}
@Override
public AgentStep addScanPackage(String packageName) {
AgentRegisterFactory.addScanPackage(packageName);
return this;
}
@Override
public AgentStep addScanDir(String externalPackagePath) {
AgentRegisterFactory.addScanDir(externalPackagePath);
return this;
}
@Override
public void launch() {
beforeLaunch();
AgentRegisterFactory.launch(applicationClass.getPackageName());
afterLaunch();
}
private void afterLaunch() {
try {
this.gateway = gatewayClass.getDeclaredConstructor().newInstance();
executorService.execute(() -> {
gateway.launch();
latch.countDown();
log.info("Gateway 启动完毕: {}", gatewayClass.getSimpleName());
});
latch.await();
launchRunners(afterLaunchRunners);
log.info("后置任务启动完毕");
} catch (Exception e) {
throw new AgentLaunchFailedException("Agent 后置任务启动失败", e);
}
}
private void beforeLaunch() {
try {
AgentConfigManager.setINSTANCE(agentConfigManagerClass.getDeclaredConstructor().newInstance());
log.info("配置管理器设置完毕: {}",agentConfigManagerClass.getSimpleName());
GlobalExceptionHandler.setExceptionCallback(agentExceptionCallbackClass.getDeclaredConstructor().newInstance());
log.info("异常处理回调设置完毕: {}",agentExceptionCallbackClass.getSimpleName());
launchRunners(beforeLaunchRunners);
log.info("前置任务启动完毕");
} catch (Exception e) {
throw new AgentLaunchFailedException("Agent 前置任务启动失败", e);
}
}
private void launchRunners(List<Runnable> runners) {
for (Runnable runner : runners) {
executorService.execute(runner);
}
}
}
}

View File

@@ -1,21 +0,0 @@
package work.slhaf.partner.api.agent.factory;
import work.slhaf.partner.api.agent.factory.capability.exception.CapabilityFactoryExecuteFailedException;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import java.lang.reflect.InvocationTargetException;
public abstract class AgentBaseFactory {
public void execute(AgentRegisterContext context) {
try {
setVariables(context);
run();
} catch (Exception e) {
throw new CapabilityFactoryExecuteFailedException(e.getMessage(), e);
}
}
protected abstract void setVariables(AgentRegisterContext context);
protected abstract void run() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException;
}

View File

@@ -1,104 +0,0 @@
package work.slhaf.partner.api.agent.factory;
import cn.hutool.core.bean.BeanUtil;
import org.reflections.util.ClasspathHelper;
import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory;
import work.slhaf.partner.api.agent.factory.capability.CapabilityInjectFactory;
import work.slhaf.partner.api.agent.factory.capability.CapabilityRegisterFactory;
import work.slhaf.partner.api.agent.factory.config.ConfigLoaderFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.exception.ExternalModuleLoadFailedException;
import work.slhaf.partner.api.agent.factory.exception.ExternalModulePathNotExistException;
import work.slhaf.partner.api.agent.factory.module.ModuleCheckFactory;
import work.slhaf.partner.api.agent.factory.module.ModuleInitHookExecuteFactory;
import work.slhaf.partner.api.agent.factory.module.ModuleProxyFactory;
import work.slhaf.partner.api.agent.factory.module.ModuleRegisterFactory;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.data.AgentContext;
import work.slhaf.partner.api.agent.runtime.interaction.flow.AgentRunningFlow;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* <h2>Agent 注册工厂</h2>
*
* <p>
* 具体流程依次按照 {@link AgentRegisterFactory#launch(String)} 方法顺序执行,最终将执行模块列表对应实例交给 {@link AgentConfigManager} ,传递给 {@link AgentRunningFlow} 针对交互做出调用
* <p/>
*/
public class AgentRegisterFactory {
private static final List<URL> urls = new ArrayList<>();
private AgentRegisterFactory() {
}
public static void launch(String packageName) {
urls.addAll(packageNameToURL(packageName));
AgentRegisterContext registerContext = new AgentRegisterContext(urls);
//流程
//0. 加载配置
new ConfigLoaderFactory().execute(registerContext);
//1. 注册并检查Module
new ModuleCheckFactory().execute(registerContext);
new ModuleRegisterFactory().execute(registerContext);
//2. 为module通过动态代理添加PostHook逻辑并进行实例化
new ModuleProxyFactory().execute(registerContext);
//3. 加载检查Capability层内容后进行能力层的内容注册
new CapabilityCheckFactory().execute(registerContext);
new CapabilityRegisterFactory().execute(registerContext);
//. 先一步注入Capability,避免因前hook逻辑存在针对能力的引用而报错
new CapabilityInjectFactory().execute(registerContext);
//. 执行模块PreHook逻辑
new ModuleInitHookExecuteFactory().execute(registerContext);
List<MetaModule> moduleList = registerContext.getModuleFactoryContext().getAgentModuleList();
AgentConfigManager.INSTANCE.moduleEnabledStatusFilterAndRecord(moduleList);
BeanUtil.copyProperties(registerContext, AgentContext.INSTANCE);
}
/**
* 添加可扫描包
*
* @param packageName 指定的包名
*/
public static void addScanPackage(String packageName) {
urls.addAll(packageNameToURL(packageName));
}
/**
* 添加外部模块目录
*
* @param externalPackagePath 指定的外部模块目录路径
*/
public static void addScanDir(String externalPackagePath) {
File file = new File(externalPackagePath);
if (!file.exists() || !file.isDirectory()) {
throw new ExternalModulePathNotExistException("不存在的外部模块目录: " + externalPackagePath);
}
try {
File[] files = file.listFiles();
if (files == null || files.length == 0) {
throw new ExternalModulePathNotExistException("外部模块目录为空: " + externalPackagePath);
}
for (File f : files) {
if (f.getName().endsWith(".jar")) {
urls.add(f.toURI().toURL());
}
}
} catch (Exception e) {
throw new ExternalModuleLoadFailedException("外部模块URL获取失败: " + externalPackagePath, e);
}
}
private static List<URL> packageNameToURL(String packageName) {
return ClasspathHelper.forPackage(packageName).stream().toList();
}
}

View File

@@ -1,271 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability;
import cn.hutool.core.util.ClassUtil;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.capability.annotation.*;
import work.slhaf.partner.api.agent.factory.capability.exception.*;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import work.slhaf.partner.api.agent.util.AgentUtil;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.isAssignableFromAnnotation;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* <h2>Agent启动流程 4</h2>
*
* <p>负责通过反射收集 {@link Capability} 和 {@link CapabilityCore} 注解所在类,并判断是否存在被错误忽略的方法</p>
*
* <ol>
* <li>
* <p>{@link CapabilityCheckFactory#loadCoresAndCapabilities()}</p>
* 通过反射收集 {@link Capability} 和 {@link CapabilityCore} 注解所在类为对应集合
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkCountAndCapabilities()}</p>
* 检测 {@link Capability} 与 {@link CapabilityCore} 的数量、对应的能力是否相等。每一个core都将对应一个capability并通过value属性进行匹配
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkCapabilityMethods()}</p>
* 检测在 {@link Capability} 与 {@link CapabilityCore} 中是否存在对方尚未实现/注册的方法
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkCoordinatedMethods()}</p>
* 检查是否包含协调方法({@link ToCoordinated}),如果存在,则进一步检查在 {@link CoordinateManager} 所注类中是否有提供对应的实现
* </li>
* <li>
* <p>{@link CapabilityCheckFactory#checkInjectCapability()}</p>
* 检查 {@link InjectCapability} 注解是否只用在 {@link CapabilityHolder} 所标识类的字段上。{@link AgentModule} 与 {@link AgentSubModule} 已经被 {@link CapabilityHolder} 标注
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link CapabilityRegisterFactory}</p>
*/
public class CapabilityCheckFactory extends AgentBaseFactory {
private Reflections reflections;
private Set<Class<?>> cores;
private Set<Class<?>> capabilities;
@Override
protected void setVariables(AgentRegisterContext context) {
CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext();
reflections = context.getReflections();
cores = factoryContext.getCores();
capabilities = factoryContext.getCapabilities();
}
@Override
protected void run() {
loadCoresAndCapabilities();
checkCountAndCapabilities();
checkCapabilityMethods();
checkCoordinatedMethods();
checkCoordinatedManager();
checkInjectCapability();
}
private void checkCoordinatedManager() {
reflections.getTypesAnnotatedWith(CoordinateManager.class)
.stream()
.filter(ClassUtil::isNormalClass)
.forEach(managerClass -> {
try {
if (!managerClass.getDeclaredConstructor().canAccess(null)) {
throw new CapabilityCheckFailedException("CoordinateManager 所注类的无参构造方法未公开!");
}
} catch (NoSuchMethodException e) {
throw new CapabilityCheckFailedException("CoordinateManager 所注类缺少无参构造方法!");
}
});
}
private void loadCoresAndCapabilities() {
cores.addAll(reflections.getTypesAnnotatedWith(CapabilityCore.class));
capabilities.addAll(reflections.getTypesAnnotatedWith(Capability.class));
}
/**
* 检查<code>@InjectCapability</code>注解是否只用在<code>@CapabilityHolder</code>所标识类的字段上
*/
private void checkInjectCapability() {
reflections.getFieldsAnnotatedWith(InjectCapability.class).forEach(field -> {
Class<?> declaringClass = field.getDeclaringClass();
if (!isAssignableFromAnnotation(declaringClass, CapabilityHolder.class)) {
throw new UnMatchedCapabilityException("InjectCapability 注解只能用于 CapabilityHolder 注解所在类,检查该类是否使用了@CapabilityHolder注解或者受其标注的注解或父类: " + declaringClass);
}
});
}
/**
* 检查是否包含协调方法,如果存在,则进一步检查是否存在<code>@CoordinateManager</code>提供对应的实现
*/
private void checkCoordinatedMethods() {
//检查各个capability中是否含有ToCoordinated注解
//如果含有则需要查找AbstractCognationManager的子类,看这里是否有对应的Coordinated注解所在方法
Set<String> methodsToCoordinated = capabilities.stream()
.flatMap(capability -> Arrays.stream(capability.getDeclaredMethods()))
.filter(method -> method.isAnnotationPresent(ToCoordinated.class))
.map(method -> {
String capabilityValue = method.getDeclaringClass().getAnnotation(Capability.class).value();
return capabilityValue + "." + methodSignature(method);
})
.collect(Collectors.toSet());
if (!methodsToCoordinated.isEmpty()) {
Set<Class<?>> subTypesOfAbsCM = reflections.getTypesAnnotatedWith(CoordinateManager.class);
Set<String> methodsCoordinated = getMethodsCoordinated(subTypesOfAbsCM);
if (!methodsCoordinated.equals(methodsToCoordinated)) {
// 找出缺少的协调方法
Set<String> missingMethods = new HashSet<>(methodsToCoordinated);
missingMethods.removeAll(methodsCoordinated);
// 找出多余的协调方法
Set<String> extraMethods = new HashSet<>(methodsCoordinated);
extraMethods.removeAll(methodsToCoordinated);
// 抛出异常或记录错误
if (!missingMethods.isEmpty()) {
throw new UnMatchedCoordinatedMethodException("缺少协调方法: " + String.join(", ", missingMethods));
}
if (!extraMethods.isEmpty()) {
throw new UnMatchedCoordinatedMethodException("发现多余的协调方法: " + String.join(", ", extraMethods));
}
}
}
}
private Set<String> getMethodsCoordinated(Set<Class<?>> classes) {
Set<String> methodsCoordinated = new HashSet<>();
for (Class<?> cm : classes) {
Method[] methods = cm.getMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(Coordinated.class)) {
methodsCoordinated.add(method.getAnnotation(Coordinated.class).capability() + "." + methodSignature(method));
}
}
}
return methodsCoordinated;
}
/**
* 查看在<code>Capability</code>在对应的<core>CapabilityCore</core>中存在尚未实现的方法
*/
private void checkCapabilityMethods() {
HashMap<String, List<Method>> capabilitiesMethods = getCapabilityMethods(capabilities);
StringBuilder sb = new StringBuilder();
for (Class<?> core : cores) {
List<Method> methodsWithAnnotation = Arrays.stream(core.getMethods())
.filter(method -> method.isAnnotationPresent(CapabilityMethod.class))
.toList();
List<Method> capabilityMethods = capabilitiesMethods.get(core.getAnnotation(CapabilityCore.class).value());
LackRecord lackRecord = checkMethodsMatched(methodsWithAnnotation, capabilityMethods);
if (lackRecord.hasNotEmptyRecord()) {
sb.append(lackRecord.toLackErrorMsg(core.getAnnotation(CapabilityCore.class).value()));
}
}
if (!sb.isEmpty()) {
throw new UnMatchedCapabilityMethodException(sb.toString());
}
}
private LackRecord checkMethodsMatched(List<Method> methodsWithAnnotation, List<Method> capabilityMethods) {
Set<String> collectedMethodsWithAnnotation = methodsWithAnnotation.stream()
.filter(method -> !method.isAnnotationPresent(ToCoordinated.class))
.map(AgentUtil::methodSignature)
.collect(Collectors.toSet());
Set<String> collectedCapabilityMethods = capabilityMethods.stream()
.filter(method -> !method.isAnnotationPresent(ToCoordinated.class))
.map(AgentUtil::methodSignature)
.collect(Collectors.toSet());
return checkMethodsMatched(collectedMethodsWithAnnotation, collectedCapabilityMethods);
}
private LackRecord checkMethodsMatched(Set<String> collectedMethodsWithAnnotation, Set<String> collectedCapabilityMethods) {
List<String> coreLack = new ArrayList<>();
List<String> capLack = new ArrayList<>();
// 找出 core 中多余的方法
for (String coreSig : collectedMethodsWithAnnotation) {
if (!collectedCapabilityMethods.contains(coreSig)) {
capLack.add(coreSig);
}
}
// 找出 capability 中多余的方法
for (String capSig : collectedCapabilityMethods) {
if (!collectedMethodsWithAnnotation.contains(capSig)) {
coreLack.add(capSig);
}
}
return new LackRecord(coreLack, capLack);
}
private HashMap<String, List<Method>> getCapabilityMethods(Set<Class<?>> capabilities) {
HashMap<String, List<Method>> capabilityMethods = new HashMap<>();
capabilities.forEach(capability -> {
capabilityMethods.put(capability.getAnnotation(Capability.class).value(), Arrays.stream(capability.getMethods()).toList());
});
return capabilityMethods;
}
/**
* 检查<code>Capability</code>和<code>CapabilityCore</code>的数量和标识是否匹配
*/
private void checkCountAndCapabilities() {
if (cores.size() != capabilities.size()) {
throw new UnMatchedCapabilityException("Capability 注册异常: 已存在的CapabilityCore与Capability数量不匹配!");
}
if (!checkValuesMatched(cores, capabilities)) {
throw new UnMatchedCapabilityException("Capability 注册异常: 已存在的CapabilityCore与Capability不匹配!");
}
}
private boolean checkValuesMatched(Set<Class<?>> cores, Set<Class<?>> capabilities) {
Set<String> coresValues = new HashSet<>();
Set<String> capabilitiesValues = new HashSet<>();
for (Class<?> core : cores) {
CapabilityCore annotation = core.getAnnotation(CapabilityCore.class);
if (annotation != null) {
if (coresValues.contains(annotation.value())) {
throw new DuplicateCapabilityException(String.format("Capability 注册异常: 重复的Capability核心: %s", annotation.value()));
}
coresValues.add(annotation.value());
}
}
for (Class<?> capability : capabilities) {
Capability annotation = capability.getAnnotation(Capability.class);
if (annotation != null) {
if (capabilitiesValues.contains(annotation.value())) {
throw new DuplicateCapabilityException(String.format("Capability 注册异常: 重复的Capability接口: %s", annotation.value()));
}
capabilitiesValues.add(annotation.value());
}
}
return coresValues.equals(capabilitiesValues);
}
record LackRecord(List<String> coreLack, List<String> capLack) {
public boolean hasNotEmptyRecord() {
return !coreLack.isEmpty() || !capLack.isEmpty();
}
public String toLackErrorMsg(String capabilityName) {
StringBuilder sb = new StringBuilder("\n").append(capabilityName).append("\n");
if (!coreLack.isEmpty()) {
sb.append("缺少Core方法:").append("\n").append(coreLack).append("\n");
}
if (!capLack.isEmpty()) {
sb.append("缺少Capability方法:").append("\n").append(capLack).append("\n");
}
return sb.toString();
}
}
}

View File

@@ -1,88 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.capability.annotation.Capability;
import work.slhaf.partner.api.agent.factory.capability.annotation.InjectCapability;
import work.slhaf.partner.api.agent.factory.capability.annotation.ToCoordinated;
import work.slhaf.partner.api.agent.factory.capability.exception.ProxySetFailedExceptionCapability;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.module.ModuleInitHookExecuteFactory;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Set;
import java.util.function.Function;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* <h2>Agent启动流程 6</h2>
*
* <p>负责执行 {@link Capability} 的注入逻辑。</p>
*
* <p>实现方式:</p>
* <ol>
* <li>通过动态代理,为 {@link AgentModule} 与 {@link AgentSubModule} 中待注入的
* <b>能力接口</b> 类型(即 {@link Capability} 标注的接口类)生成代理对象。
* </li>
* <li>在代理对象内部,根据调用方法的签名确定路由,将调用转发至对应的具体函数。
* </li>
* <li>通过此机制,实现了 {@link Capability} 单一语义层面上普通方法与协调方法的统一入口。
* </li>
* </ol>
*
* <p>下一步流程请参阅 {@link ModuleInitHookExecuteFactory}</p>
*/public class CapabilityInjectFactory extends AgentBaseFactory {
private Reflections reflections;
private HashMap<String, Function<Object[], Object>> coordinatedMethodsRouterTable;
private HashMap<String, Function<Object[], Object>> methodsRouterTable;
private HashMap<Class<?>, Object> capabilityHolderInstances;
@Override
protected void setVariables(AgentRegisterContext context) {
CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext();
reflections = context.getReflections();
coordinatedMethodsRouterTable = factoryContext.getCoordinatedMethodsRouterTable();
methodsRouterTable = factoryContext.getMethodsRouterTable();
capabilityHolderInstances = factoryContext.getCapabilityHolderInstances();
}
@Override
protected void run() {
//获取现有的`@InjectCapability`注解所在字段,并获取对应的类,通过动态代理注入对象
Set<Field> fields = reflections.getFieldsAnnotatedWith(InjectCapability.class);
//在动态代理内部,通过函数路由表调用对应的方法
createProxy(fields);
}
private void createProxy(Set<Field> fields) {
try {
for (Field field : fields) {
field.setAccessible(true);
Class<?> fieldType = field.getType();
Object instance = Proxy.newProxyInstance(
fieldType.getClassLoader(),
new Class[]{fieldType},
(proxy, method, objects) -> {
if (method.isAnnotationPresent(ToCoordinated.class)) {
String key = method.getDeclaringClass().getAnnotation(Capability.class).value() + "." + methodSignature(method);
return coordinatedMethodsRouterTable.get(key).apply(objects);
}
String key = fieldType.getAnnotation(Capability.class).value() + "." + methodSignature(method);
return methodsRouterTable.get(key).apply(objects);
}
);
field.set(capabilityHolderInstances.get(field.getDeclaringClass()), instance);
}
} catch (Exception e) {
throw new ProxySetFailedExceptionCapability("代理设置失败", e);
}
}
}

View File

@@ -1,211 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability;
import cn.hutool.core.util.ClassUtil;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.capability.annotation.*;
import work.slhaf.partner.api.agent.factory.capability.exception.CapabilityFactoryExecuteFailedException;
import work.slhaf.partner.api.agent.factory.capability.exception.CoreInstancesCreateFailedExceptionCapability;
import work.slhaf.partner.api.agent.factory.capability.exception.DuplicateMethodException;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* <h2>Agent启动流程 5</h2>
*
* <p>
* 负责收集注解 {@link Capability} 和 {@link CapabilityCore} 标识的类并生成函数路由表、创建core、capability实例以及放入instanceMap供后续进行注入操作
* </p>
*
* <ol>
* <li>
* <p>{@link CapabilityRegisterFactory#setCoreInstances()}</p>
* 通过反射调用无参构造函数创建core实例并将实例放入instanceMap供后续使用
* </li>
* <li>
* <p>{@link CapabilityRegisterFactory#generateRouterTable()}</p>
* 生成函数路由表:
* <ul>
* <li>
* <p>{@link CapabilityRegisterFactory#generateMethodsRouterTable()}</p>
* 生成普通方法对应的函数路由表
* </li>
* <li>
* <p>{@link CapabilityRegisterFactory#generateCoordinatedMethodsRouterTable()}</p>
* 生成协调方法对应的函数路由表
* </li>
* </ul>
* </li>
* <li>
* 函数路由表生成完毕、core实例创建完毕之后将交由下一工厂完成能力(Capability)注入操作,注入到 {@link AgentModule} 与 {@link AgentSubModule} 对应的实例中
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link CapabilityInjectFactory}</p>
*/
public class CapabilityRegisterFactory extends AgentBaseFactory {
private Reflections reflections;
private HashMap<String, Function<Object[], Object>> methodsRouterTable;
private HashMap<String, Function<Object[], Object>> coordinatedMethodsRouterTable;
private HashMap<Class<?>, Object> coreInstances;
private HashMap<Class<?>, Object> capabilityHolderInstances;
private Set<Class<?>> cores;
private Set<Class<?>> capabilities;
@Override
protected void setVariables(AgentRegisterContext context) {
CapabilityFactoryContext factoryContext = context.getCapabilityFactoryContext();
reflections = context.getReflections();
methodsRouterTable = factoryContext.getMethodsRouterTable();
coordinatedMethodsRouterTable = factoryContext.getCoordinatedMethodsRouterTable();
coreInstances = factoryContext.getCapabilityCoreInstances();
cores = factoryContext.getCores();
capabilities = factoryContext.getCapabilities();
capabilityHolderInstances = factoryContext.getCapabilityHolderInstances();
}
@Override
protected void run() {
setCapabilityHolderInstances();
setCoreInstances();
generateRouterTable();
}
private void setCapabilityHolderInstances() {
Set<Class<?>> collect = reflections.getTypesAnnotatedWith(CapabilityHolder.class).stream()
.filter(ClassUtil::isNormalClass)
.filter(clazz -> !capabilityHolderInstances.containsKey(clazz))
.collect(Collectors.toSet());
for (Class<?> clazz : collect) {
try {
Constructor<?> constructor = clazz.getDeclaredConstructor();
if (constructor.canAccess(null)) {
throw new CapabilityFactoryExecuteFailedException("缺少无参构造方法的类: " + clazz);
}
Object o = constructor.newInstance();
capabilityHolderInstances.put(clazz, o);
} catch (Exception e) {
throw new CapabilityFactoryExecuteFailedException("创建代理对象失败: " + clazz, e);
}
}
}
/**
* 生成函数路由表
*/
private void generateRouterTable() {
generateMethodsRouterTable();
generateCoordinatedMethodsRouterTable();
}
/**
* 生成协调函数对应的函数路由表
*/
private void generateCoordinatedMethodsRouterTable() {
Set<Method> methodsAnnotatedWith = reflections.getMethodsAnnotatedWith(Coordinated.class);
if (methodsAnnotatedWith.isEmpty()) {
return;
}
try {
//获取所有CM实例
HashMap<String, Object> coordinateManagerInstances = getCoordinateManagerInstances();
methodsAnnotatedWith.forEach(method -> {
String key = method.getAnnotation(Coordinated.class).capability() + "." + methodSignature(method);
Function<Object[], Object> function = args -> {
try {
return method.invoke(coordinateManagerInstances.get(key), args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
coordinatedMethodsRouterTable.put(key, function);
});
} catch (Exception e) {
throw new CapabilityFactoryExecuteFailedException("创建协调方法路由表出错", e);
}
}
/**
* 获取<code>CoordinateManager</code>子类实例
*/
private HashMap<String, Object> getCoordinateManagerInstances() throws InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
HashMap<String, Object> map = new HashMap<>();
for (Class<?> c : reflections.getTypesAnnotatedWith(CoordinateManager.class)) {
Constructor<?> constructor = c.getDeclaredConstructor();
Object instance = constructor.newInstance();
setCores(instance, c);
Arrays.stream(c.getMethods())
.filter(method -> method.isAnnotationPresent(Coordinated.class))
.forEach(method -> {
String key = method.getAnnotation(Coordinated.class).capability() + "." + methodSignature(method);
map.put(key, instance);
});
}
return map;
}
private void setCores(Object cmInstance, Class<?> cmClazz) throws IllegalAccessException {
for (Field field : cmClazz.getFields()) {
if (field.getType().isAnnotationPresent(CapabilityCore.class)) {
field.setAccessible(true);
field.set(cmInstance, coreInstances.get(field.getType()));
}
}
}
/**
* 扫描`@Capability`与`@CapabilityMethod`注解的类与方法
* 将`capabilityValue.methodSignature`作为key,函数对象为通过反射拿到的core实例对应的方法
*/
private void generateMethodsRouterTable() {
cores.forEach(core -> Arrays.stream(core.getMethods())
.filter(method -> method.isAnnotationPresent(CapabilityMethod.class))
.forEach(method -> {
Function<Object[], Object> function = args -> {
try {
return method.invoke(coreInstances.get(core), args);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
};
String key = core.getAnnotation(CapabilityCore.class).value() + "." + methodSignature(method);
if (methodsRouterTable.containsKey(key)) {
throw new DuplicateMethodException("重复注册能力方法: " + core.getPackage().getName() + "." + core.getSimpleName() + "#" + method.getName());
}
methodsRouterTable.put(key, function);
}));
}
/**
* 反射获取<code>CapabilityCore</code>实例
*/
private void setCoreInstances() {
try {
for (Class<?> core : cores) {
Constructor<?> constructor = core.getDeclaredConstructor();
constructor.setAccessible(true);
coreInstances.put(core, constructor.newInstance());
}
} catch (InvocationTargetException | NoSuchMethodException | InstantiationException |
IllegalAccessException e) {
throw new CoreInstancesCreateFailedExceptionCapability("core实例创建失败");
}
}
}

View File

@@ -1,14 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Core的协调类该注解的实现类中如果存在任何{@link CapabilityCore}实例的引用,都将被自动注入
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CoordinateManager {
}

View File

@@ -1,15 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 用于标注协调方法,`value`值需与对应的`@ToCoordinated`保持一致
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Coordinated {
String capability();
}

View File

@@ -1,15 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 当`@Capability`所注接口中如果存在方法需要协调多个Core服务的调用可以通过该注解进行排除
* value值为方法对应标识需与协调实现处的方法标识保持一致
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ToCoordinated {
}

View File

@@ -1,13 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
import work.slhaf.partner.api.agent.runtime.exception.AgentLaunchFailedException;
public class CapabilityCheckFailedException extends AgentLaunchFailedException {
public CapabilityCheckFailedException(String message) {
super("Capability注册失败: " + message);
}
public CapabilityCheckFailedException(String message, Throwable cause) {
super("Capability注册失败: " + message, cause);
}
}

View File

@@ -1,13 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
import work.slhaf.partner.api.agent.runtime.exception.AgentLaunchFailedException;
public class CapabilityFactoryExecuteFailedException extends AgentLaunchFailedException {
public CapabilityFactoryExecuteFailedException(String message) {
super("CapabilityRegisterFactory 执行失败: " + message);
}
public CapabilityFactoryExecuteFailedException(String message, Throwable cause) {
super("CapabilityRegisterFactory 执行失败: " + message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class CoreInstancesCreateFailedExceptionCapability extends CapabilityFactoryExecuteFailedException {
public CoreInstancesCreateFailedExceptionCapability(String message) {
super(message);
}
public CoreInstancesCreateFailedExceptionCapability(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class DuplicateCapabilityException extends CapabilityCheckFailedException {
public DuplicateCapabilityException(String message) {
super(message);
}
public DuplicateCapabilityException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class DuplicateMethodException extends CapabilityCheckFailedException{
public DuplicateMethodException(String message) {
super(message);
}
public DuplicateMethodException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class EmptyCapabilityHolderException extends CapabilityCheckFailedException{
public EmptyCapabilityHolderException(String message) {
super(message);
}
public EmptyCapabilityHolderException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class ProxySetFailedExceptionCapability extends CapabilityFactoryExecuteFailedException {
public ProxySetFailedExceptionCapability(String message) {
super(message);
}
public ProxySetFailedExceptionCapability(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class UnMatchedCapabilityException extends CapabilityCheckFailedException{
public UnMatchedCapabilityException(String message) {
super(message);
}
public UnMatchedCapabilityException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class UnMatchedCapabilityMethodException extends CapabilityCheckFailedException {
public UnMatchedCapabilityMethodException(String message) {
super(message);
}
public UnMatchedCapabilityMethodException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.capability.exception;
public class UnMatchedCoordinatedMethodException extends CapabilityCheckFailedException {
public UnMatchedCoordinatedMethodException(String message) {
super(message);
}
public UnMatchedCoordinatedMethodException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,77 +0,0 @@
package work.slhaf.partner.api.agent.factory.config;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.config.exception.ConfigNotExistException;
import work.slhaf.partner.api.agent.factory.config.exception.PromptNotExistException;
import work.slhaf.partner.api.agent.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.ConfigFactoryContext;
import work.slhaf.partner.api.agent.factory.module.ModuleCheckFactory;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.config.FileAgentConfigManager;
import work.slhaf.partner.api.chat.pojo.Message;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* <h2>Agent启动流程 0</h2>
* <p>
* 通过指定的 {@link AgentConfigManager} 或者默认的 {@link FileAgentConfigManager} 加载配置文件
* <p/>
*
* <p>下一步流程请参阅{@link ModuleCheckFactory}</p>
*/
@Slf4j
public class ConfigLoaderFactory extends AgentBaseFactory {
private AgentConfigManager agentConfigManager;
private HashMap<String, ModelConfig> modelConfigMap;
private HashMap<String, List<Message>> modelPromptMap;
@Override
protected void setVariables(AgentRegisterContext context) {
ConfigFactoryContext factoryContext = context.getConfigFactoryContext();
modelConfigMap = factoryContext.getModelConfigMap();
modelPromptMap = factoryContext.getModelPromptMap();
if (AgentConfigManager.INSTANCE == null) {
AgentConfigManager.setINSTANCE(new FileAgentConfigManager());
}
agentConfigManager = AgentConfigManager.INSTANCE;
}
@Override
protected void run() {
agentConfigManager.load();
modelConfigMap.putAll(agentConfigManager.getModelConfigMap());
modelPromptMap.putAll(agentConfigManager.getModelPromptMap());
check();
}
/**
* 对模型Config与Prompt分别进行检验,除了都必须包含default外还需要确保数量、key一致毕竟是模型配置与提示词
*/
private void check() {
log.info("执行config与prompt检测...");
if (!modelConfigMap.containsKey("default")) {
throw new ConfigNotExistException("缺少默认配置! 需确保存在一个模型配置的key为`default`");
}
if (!modelPromptMap.containsKey("basic")) {
throw new PromptNotExistException("缺少基础Prompt! 需要确保存在key为basic的Prompt文件它将与其他Prompt共同作用于模块节点。");
}
Set<String> configKeySet = new HashSet<>(modelConfigMap.keySet());
configKeySet.remove("default");
Set<String> promptKeySet = new HashSet<>(modelPromptMap.keySet());
promptKeySet.remove("basic");
if (!promptKeySet.containsAll(configKeySet)) {
log.warn("存在未被提示词包含的模型配置,该配置将无法生效!");
}
//检查提示词数量与`ActivateModel`的实现数量是否一致
log.info("检测完毕.");
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
public class ConfigDirNotExistException extends ConfigFactoryInitFailedException {
public ConfigDirNotExistException(String message, Throwable cause) {
super(message, cause);
}
public ConfigDirNotExistException(String message) {
super(message);
}
}

View File

@@ -1,13 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
import work.slhaf.partner.api.agent.runtime.exception.AgentLaunchFailedException;
public class ConfigFactoryInitFailedException extends AgentLaunchFailedException {
public ConfigFactoryInitFailedException(String message, Throwable cause) {
super("AgentConfigManager 执行失败: " + message, cause);
}
public ConfigFactoryInitFailedException(String message) {
super("AgentConfigManager 执行失败: " + message);
}
}

View File

@@ -1,13 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
import work.slhaf.partner.api.agent.runtime.exception.AgentRuntimeException;
public class ConfigFactoryRuntimeException extends AgentRuntimeException {
public ConfigFactoryRuntimeException(String message, Throwable cause) {
super("ConfigFactory 运行出错: " + message, cause);
}
public ConfigFactoryRuntimeException(String message) {
super("ConfigFactory 运行出错: " + message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
public class ConfigGenerateFailedException extends ConfigFactoryInitFailedException {
public ConfigGenerateFailedException(String message, Throwable cause) {
super(message, cause);
}
public ConfigGenerateFailedException(String message) {
super(message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
public class ConfigNotExistException extends ConfigFactoryInitFailedException {
public ConfigNotExistException(String message, Throwable e) {
super(message, e);
}
public ConfigNotExistException(String message) {
super(message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
public class ConfigUpdateFailedException extends ConfigFactoryRuntimeException{
public ConfigUpdateFailedException(String message, Throwable cause) {
super(message, cause);
}
public ConfigUpdateFailedException(String message) {
super(message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
public class PromptDirNotExistException extends ConfigFactoryInitFailedException {
public PromptDirNotExistException(String message, Throwable cause) {
super(message, cause);
}
public PromptDirNotExistException(String message) {
super(message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.exception;
public class PromptNotExistException extends ConfigFactoryInitFailedException {
public PromptNotExistException(String message) {
super(message);
}
public PromptNotExistException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,10 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.pojo;
import lombok.Data;
@Data
public class ModelConfig {
private String baseUrl;
private String apikey;
private String model;
}

View File

@@ -1,9 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.pojo;
import lombok.Data;
@Data
public class PrimaryModelConfig {
private String key;
private ModelConfig modelConfig;
}

View File

@@ -1,12 +0,0 @@
package work.slhaf.partner.api.agent.factory.config.pojo;
import lombok.Data;
import work.slhaf.partner.api.chat.pojo.Message;
import java.util.List;
@Data
public class PrimaryModelPrompt {
private String key;
private List<Message> messages;
}

View File

@@ -1,28 +0,0 @@
package work.slhaf.partner.api.agent.factory.context;
import lombok.Data;
import org.reflections.Reflections;
import org.reflections.scanners.Scanners;
import org.reflections.util.ConfigurationBuilder;
import java.net.URL;
import java.util.List;
@Data
public class AgentRegisterContext {
private Reflections reflections;
private CapabilityFactoryContext capabilityFactoryContext = new CapabilityFactoryContext();
private ConfigFactoryContext configFactoryContext = new ConfigFactoryContext();
private ModuleFactoryContext moduleFactoryContext = new ModuleFactoryContext();
public AgentRegisterContext(List<URL> urls) {
reflections = new Reflections(new ConfigurationBuilder().setScanners(
Scanners.FieldsAnnotated,
Scanners.SubTypes,
Scanners.MethodsAnnotated,
Scanners.TypesAnnotated
)
.setUrls(urls)
);
}
}

View File

@@ -1,18 +0,0 @@
package work.slhaf.partner.api.agent.factory.context;
import lombok.Data;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
@Data
public class CapabilityFactoryContext {
private final HashMap<String, Function<Object[], Object>> methodsRouterTable = new HashMap<>();
private final HashMap<String, Function<Object[], Object>> coordinatedMethodsRouterTable = new HashMap<>();
private final HashMap<Class<?>, Object> capabilityCoreInstances = new HashMap<>();
private final HashMap<Class<?>, Object> capabilityHolderInstances = new HashMap<>();
private Set<Class<?>> cores = new HashSet<>();
private Set<Class<?>> capabilities = new HashSet<>();
}

View File

@@ -1,14 +0,0 @@
package work.slhaf.partner.api.agent.factory.context;
import lombok.Data;
import work.slhaf.partner.api.agent.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.chat.pojo.Message;
import java.util.HashMap;
import java.util.List;
@Data
public class ConfigFactoryContext {
private HashMap<String, List<Message>> modelPromptMap = new HashMap<>();
private HashMap<String, ModelConfig> modelConfigMap = new HashMap<>();
}

View File

@@ -1,14 +0,0 @@
package work.slhaf.partner.api.agent.factory.context;
import lombok.Data;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaSubModule;
import java.util.ArrayList;
import java.util.List;
@Data
public class ModuleFactoryContext {
private List<MetaModule> agentModuleList = new ArrayList<>();
private List<MetaSubModule> agentSubModuleList = new ArrayList<>();
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.exception;
public class AgentRegisterFactoryFailedException extends RuntimeException {
public AgentRegisterFactoryFailedException(String message, Throwable cause) {
super("AgentRegisterFactory 执行失败: " + message, cause);
}
public AgentRegisterFactoryFailedException(String message) {
super("AgentRegisterFactory 执行失败: " + message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.exception;
public class ExternalModuleLoadFailedException extends AgentRegisterFactoryFailedException{
public ExternalModuleLoadFailedException(String message, Throwable cause) {
super(message, cause);
}
public ExternalModuleLoadFailedException(String message) {
super(message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.exception;
public class ExternalModulePathNotExistException extends AgentRegisterFactoryFailedException {
public ExternalModulePathNotExistException(String message) {
super(message);
}
public ExternalModulePathNotExistException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,227 +0,0 @@
package work.slhaf.partner.api.agent.factory.module;
import cn.hutool.core.util.ClassUtil;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute;
import work.slhaf.partner.api.agent.factory.module.exception.ModuleCheckException;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.ActivateModel;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.getMethodAnnotationTypeSet;
/**
* <h2>Agent启动流程 1</h2>
*
* <p>
* 检查模块部分抽象类与注解、接口的使用方式
* </p>
*
* <ol>
* <li>
* <p>{@link ModuleCheckFactory#annotationAbstractCheck(Set, Class)}</p>
* 所有添加了 {@link AgentModule} 注解的类都将作为Agent的执行模块为规范模块入口都必须实现抽象类: {@link AgentRunningModule}; {@link AgentSubModule} 注解所在类则必须实现 {@link AgentRunningSubModule}
* </li>
* <li>
* <p>{@link ModuleCheckFactory#moduleConstructorsCheck(Set)}</p>
* 所有 {@link AgentModule} 与 {@link AgentSubModule} 注解所在类都必须具备空参构造方法,初始化逻辑可放在 @Init 注解所处方法中,将在 Capability 与 subModules 注入后才会执行
* </li>
* <li>
* <p>{@link ModuleCheckFactory#activateModelImplCheck()}</p>
* 检查实现了 {@link ActivateModel} 的模块数量、名称与prompt是否一致
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link ModuleRegisterFactory}</p>
*/
public class ModuleCheckFactory extends AgentBaseFactory {
private Reflections reflections;
@Override
protected void setVariables(AgentRegisterContext context) {
reflections = context.getReflections();
}
@Override
protected void run() {
AnnotatedModules annotatedModules = getAnnotatedModules();
ExtendedModules extendedModules = getExtendedModules();
checkIfClassCorresponds(annotatedModules, extendedModules);
//检查注解AgentModule或AgentSubModule所在类是否继承了对应的抽象类
annotationAbstractCheck(annotatedModules.moduleTypes(), AgentRunningModule.class);
annotationAbstractCheck(annotatedModules.subModuleTypes(), AgentRunningSubModule.class);
//检查AgentModule是否具备无参构造方法
moduleConstructorsCheck(annotatedModules.moduleTypes());
moduleConstructorsCheck(annotatedModules.subModuleTypes());
//检查实现了ActivateModel的模块数量、名称与prompt是否一致
activateModelImplCheck();
//检查hook注解所在位置是否正确
hookLocationCheck();
}
private ExtendedModules getExtendedModules() {
Set<Class<?>> moduleTypes = reflections.getSubTypesOf(AgentRunningModule.class)
.stream()
.filter(ClassUtil::isNormalClass)
.collect(Collectors.toSet());
Set<Class<?>> subModuleTypes = reflections.getSubTypesOf(AgentRunningSubModule.class)
.stream()
.filter(ClassUtil::isNormalClass)
.collect(Collectors.toSet());
return new ExtendedModules(moduleTypes, subModuleTypes);
}
private AnnotatedModules getAnnotatedModules() {
Set<Class<?>> moduleTypes = reflections.getTypesAnnotatedWith(AgentModule.class)
.stream()
.filter(ClassUtil::isNormalClass)
.collect(Collectors.toSet());
Set<Class<?>> subModuleTypes = reflections.getTypesAnnotatedWith(AgentSubModule.class)
.stream()
.filter(ClassUtil::isNormalClass)
.collect(Collectors.toSet());
return new AnnotatedModules(moduleTypes, subModuleTypes);
}
private void moduleConstructorsCheck(Set<Class<?>> types) {
for (Class<?> type : types) {
try {
type.getConstructor();
} catch (NoSuchMethodException e) {
throw new ModuleCheckException("缺少无参构造方法的模块: " + type.getSimpleName(), e);
}
}
}
private void activateModelImplCheck() {
try {
Set<Class<? extends ActivateModel>> types = reflections.getSubTypesOf(ActivateModel.class);
Set<String> modelKeySet = new HashSet<>();
for (Class<? extends ActivateModel> type : types) {
ActivateModel instance = type.getConstructor().newInstance();
modelKeySet.add(instance.modelKey());
}
Set<String> promptKeySet = AgentConfigManager.INSTANCE.getModelPromptMap().keySet();
if (!promptKeySet.containsAll(modelKeySet)) {
modelKeySet.removeAll(promptKeySet);
throw new ModuleCheckException("存在未配置Prompt的ActivateModel实现! 缺少Prompt的ModelKey列表: " + modelKeySet);
}
} catch (Exception e) {
throw new ModuleCheckException("ActivateModel 检测出错", e);
}
}
private void hookLocationCheck() {
//检查@AfterExecute注解
postHookLocationCheck();
//检查@BeforeExecute注解
preHookLocationCheck();
//检查@Init注解
initHookLocationCheck();
}
private void initHookLocationCheck() {
Set<Class<?>> types = getMethodAnnotationTypeSet(AgentModule.class, reflections);
checkLocation(types);
}
private void preHookLocationCheck() {
Set<Method> methods = reflections.getMethodsAnnotatedWith(BeforeExecute.class);
Set<Class<?>> types = methods.stream()
.map(Method::getDeclaringClass)
.collect(Collectors.toSet());
checkLocation(types);
}
private void postHookLocationCheck() {
Set<Method> methods = reflections.getMethodsAnnotatedWith(AfterExecute.class);
Set<Class<?>> types = methods.stream()
.map(Method::getDeclaringClass)
.collect(Collectors.toSet());
checkLocation(types);
}
private void checkLocation(Set<Class<?>> types) {
for (Class<?> type : types) {
if (AgentRunningModule.class.isAssignableFrom(type)) {
continue;
}
if (AgentRunningSubModule.class.isAssignableFrom(type)) {
continue;
}
if (ActivateModel.class.isAssignableFrom(type)) {
continue;
}
throw new ModuleCheckException("在不支持的类中使用了hook注解: " + type.getSimpleName());
}
}
private void annotationAbstractCheck(Set<Class<?>> types, Class<?> clazz) {
for (Class<?> type : types) {
if (type.isAnnotation()) {
continue;
}
if (clazz.isAssignableFrom(type) && ClassUtil.isNormalClass(type)) {
continue;
}
throw new ModuleCheckException("存在未继承AgentInteractionModule.class的AgentModule实现: " + type.getSimpleName());
}
}
private void checkIfClassCorresponds(AnnotatedModules annotatedModules, ExtendedModules extendedModules) {
// 检查是否有被@AgentModule注解但没有继承AgentRunningModule的类
checkSets(annotatedModules.moduleTypes(), extendedModules.moduleTypes(),
"存在被@AgentModule注解但未继承AgentRunningModule的类");
// 检查是否有继承AgentRunningModule但没有被@AgentModule注解的类
checkSets(extendedModules.moduleTypes(), annotatedModules.moduleTypes(),
"存在继承AgentRunningModule但未被@AgentModule注解的类");
// 检查是否有被@AgentSubModule注解但没有继承AgentRunningSubModule的类
checkSets(annotatedModules.subModuleTypes(), extendedModules.subModuleTypes(),
"存在被@AgentSubModule注解但未继承AgentRunningSubModule的类");
// 检查是否有继承AgentRunningSubModule但没有被@AgentSubModule注解的类
checkSets(extendedModules.subModuleTypes(), annotatedModules.subModuleTypes(),
"存在继承AgentRunningSubModule但未被@AgentSubModule注解的类");
}
/**
* 检查源集合中是否有不在目标集合中的元素
* @param source 源集合
* @param target 目标集合
* @param errorMessage 错误信息前缀
*/
private void checkSets(Set<Class<?>> source, Set<Class<?>> target, String errorMessage) {
// 只有在需要时才创建HashSet以节省内存
if (!target.containsAll(source)) {
// 使用流式处理找出差异部分,避免创建完整的中间集合
String classNames = source.stream()
.filter(clazz -> !target.contains(clazz))
.map(Class::getSimpleName)
.limit(10) // 限制显示数量,避免信息泄露
.collect(Collectors.joining(", ", "[", "]"));
throw new ModuleCheckException(errorMessage + ": " + classNames);
}
}
private record AnnotatedModules(Set<Class<?>> moduleTypes, Set<Class<?>> subModuleTypes) {
}
private record ExtendedModules(Set<Class<?>> moduleTypes, Set<Class<?>> subModuleTypes) {
}
}

View File

@@ -1,97 +0,0 @@
package work.slhaf.partner.api.agent.factory.module;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.AgentRegisterFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.ModuleFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.Init;
import work.slhaf.partner.api.agent.factory.module.exception.ModuleInitHookExecuteFailedException;
import work.slhaf.partner.api.agent.factory.module.pojo.BaseMetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaMethod;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.Module;
import work.slhaf.partner.api.agent.util.AgentUtil;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.collectExtendedClasses;
import static work.slhaf.partner.api.agent.util.AgentUtil.methodSignature;
/**
* <h2>Agent启动流程 7</h2>
*
* <p>负责执行初始化hook逻辑即 {@link Init} 注解所在方法</p>
*
* <ol>
* <li>
* <p>{@link ModuleInitHookExecuteFactory#collectInitHookMethods(Class, Class)}</p>
* 分别遍历前置模块拿到的模块列表({@link ModuleInitHookExecuteFactory#moduleList}, {@link ModuleInitHookExecuteFactory#subModuleList}),通过 {@link AgentUtil#collectExtendedClasses(Class, Class)} 收集到当前模块类的继承链上的所有类后,收集其所有带有 {@link Init} 注解的方法
* </li>
* <li>
* <p>{@link ModuleInitHookExecuteFactory#proceedInitMethods(BaseMetaModule, List)}</p>
* 收集好初始化方法后,将通过反射执行该方法,所用实例即为前置模块中收集到的执行模块与子模块的 {@link MetaModule} 与 {@link MetaSubModule} 内容
* </li>
* </ol>
*
* <p>Agent启动流程到此进行完毕。整个工厂执行链中均为针对 {@link AgentRegisterContext} 进行的操作,在 {@link AgentRegisterFactory} 中,将进行最终处理以及将必要内容进行传递。</p>
*/
public class ModuleInitHookExecuteFactory extends AgentBaseFactory {
private List<MetaModule> moduleList;
private List<MetaSubModule> subModuleList;
@Override
protected void setVariables(AgentRegisterContext context) {
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
moduleList = factoryContext.getAgentModuleList();
subModuleList = factoryContext.getAgentSubModuleList();
}
@Override
protected void run() {
//遍历模块列表,并向上查找@Init注解
for (MetaSubModule metaSubModule : subModuleList) {
List<MetaMethod> initHookMethods = collectInitHookMethods(metaSubModule.getClazz(),AgentRunningModule.class);
proceedInitMethods(metaSubModule, initHookMethods);
}
for (MetaModule metaModule : moduleList) {
List<MetaMethod> initHookMethods = collectInitHookMethods(metaModule.getClazz(), AgentRunningSubModule.class);
proceedInitMethods(metaModule, initHookMethods);
}
}
private void proceedInitMethods(BaseMetaModule metaModule, List<MetaMethod> initHookMethods) {
for (MetaMethod metaMethod : initHookMethods) {
try {
metaMethod.getMethod().invoke(metaModule.getInstance());
} catch (IllegalAccessException | InvocationTargetException e) {
throw new ModuleInitHookExecuteFailedException("模块的init hook方法执行失败! 模块: " + metaModule.getClazz().getSimpleName() + " 方法签名: " + methodSignature(metaMethod.getMethod()), e);
}
}
}
private List<MetaMethod> collectInitHookMethods(Class<?> clazz, Class<? extends Module> target) {
Set<Class<?>> classes = collectExtendedClasses(clazz, target);
return classes.stream()
.map(Class::getDeclaredMethods)
.flatMap(Arrays::stream)
.filter(method -> method.isAnnotationPresent(Init.class))
.map(method -> {
MetaMethod metaMethod = new MetaMethod();
metaMethod.setMethod(method);
metaMethod.setOrder(method.getAnnotation(Init.class).order());
return metaMethod;
})
.sorted(Comparator.comparing(MetaMethod::getOrder))
.collect(Collectors.toList());
}
}

View File

@@ -1,259 +0,0 @@
package work.slhaf.partner.api.agent.factory.module;
import lombok.Getter;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.implementation.bind.annotation.*;
import net.bytebuddy.matcher.ElementMatchers;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.capability.CapabilityCheckFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.CapabilityFactoryContext;
import work.slhaf.partner.api.agent.factory.context.ModuleFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.InjectModule;
import work.slhaf.partner.api.agent.factory.module.exception.ModuleInstanceGenerateFailedException;
import work.slhaf.partner.api.agent.factory.module.exception.ModuleProxyGenerateFailedException;
import work.slhaf.partner.api.agent.factory.module.exception.ProxiedModuleRunningException;
import work.slhaf.partner.api.agent.factory.module.pojo.BaseMetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaMethod;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.Module;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.stream.Collectors;
import static work.slhaf.partner.api.agent.util.AgentUtil.collectExtendedClasses;
/**
* <h2>Agent启动流程 3</h2>
*
* <p>
* 扫描前置模块各个hook注解生成代理对象放入对应的list中并按照类型为键放入 {@link ModuleProxyFactory#capabilityHolderInstances} 中供后续完成能力(capability)注入
* <p/>
*
* <ol>
*
* <li>
* <p>{@link ModuleProxyFactory#createProxiedInstances()}</p>
* 根据moduleList中的类型信息向上查找继承链获取所有hook方法收集为{@link MethodsListRecord}然后通过ByteBuddy根据收集到的preHook与postHook生成代理对象放入对应的 {@link MetaModule} 对象以及 instanceMap 中
* </li>
* <li>
* <p>{@link ModuleProxyFactory#injectSubModule()}</p>
* 通过反射将子模块实例注入到执行模块中带有注解 {@link InjectModule} 的字段
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link CapabilityCheckFactory}</p>
*/
public class ModuleProxyFactory extends AgentBaseFactory {
private List<MetaModule> moduleList;
private List<MetaSubModule> subModuleList;
private HashMap<Class<?>, Object> capabilityHolderInstances;
private final HashMap<Class<?>, Object> subModuleInstances = new HashMap<>();
private final HashMap<Class<?>, Object> moduleInstances = new HashMap<>();
@Override
protected void setVariables(AgentRegisterContext context) {
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
CapabilityFactoryContext capabilityFactoryContext = context.getCapabilityFactoryContext();
moduleList = factoryContext.getAgentModuleList();
subModuleList = factoryContext.getAgentSubModuleList();
capabilityHolderInstances = capabilityFactoryContext.getCapabilityHolderInstances();
}
@Override
protected void run() {
createProxiedInstances();
injectSubModule();
}
private void injectSubModule() {
for (MetaModule module : moduleList) {
//因为实际上ByteBuddy生成的是module.getClazz()的子类所以应当使用getDeclaredFields()获取字段
Arrays.stream(module.getClazz().getDeclaredFields())
.filter(field -> field.isAnnotationPresent(InjectModule.class))
.forEach(field -> {
try {
field.setAccessible(true);
field.set(
moduleInstances.get(module.getClazz()),
subModuleInstances.get(field.getType())
);
} catch (IllegalAccessException e) {
throw new ModuleInstanceGenerateFailedException("模块实例注入失败", e);
}
});
}
}
private void createProxiedInstances() {
generateModuleProxy(moduleList, AgentRunningModule.class);
generateModuleProxy(subModuleList, AgentRunningSubModule.class);
updateInstanceMap(moduleInstances, moduleList);
updateInstanceMap(subModuleInstances, subModuleList);
updateCapabilityHolderInstances();
}
private void updateCapabilityHolderInstances() {
capabilityHolderInstances.putAll(moduleInstances);
capabilityHolderInstances.putAll(subModuleInstances);
}
private void updateInstanceMap(HashMap<Class<?>, Object> instanceMap, List<? extends BaseMetaModule> list) {
for (BaseMetaModule baseMetaModule : list) {
instanceMap.put(baseMetaModule.getClazz(), baseMetaModule.getInstance());
}
}
private void generateModuleProxy(List<? extends BaseMetaModule> list, Class<? extends Module> overrideSource) {
for (BaseMetaModule module : list) {
Class<?> clazz = module.getClazz();
try {
MethodsListRecord record = collectHookMethods(clazz);
//生成实例
generateProxiedInstances(record, module, overrideSource);
} catch (Exception e) {
throw new ModuleProxyGenerateFailedException("创建代理对象失败: " + clazz.getSimpleName(), e);
}
}
}
private void generateProxiedInstances(MethodsListRecord record, BaseMetaModule module, Class<? extends Module> overrideSource) {
try {
Class<? extends Module> clazz = module.getClazz();
Class<? extends Module> proxyClass = new ByteBuddy()
.subclass(clazz)
.method(ElementMatchers.isOverriddenFrom(overrideSource))
.intercept(MethodDelegation.to(new ModuleProxyInterceptor(record.post, record.pre)))
.make()
.load(ModuleProxyFactory.class.getClassLoader())
.getLoaded();
// new ByteBuddy()
// .subclass(clazz)
// .method(ElementMatchers.isOverriddenFrom(overrideSource))
// .intercept(MethodDelegation.to(new ModuleProxyInterceptor(record.post, record.pre)))
//
// .make()
// .saveIn(new File("./generated-classes"));
module.setInstance(proxyClass.getConstructor().newInstance());
} catch (Exception e) {
throw new ModuleProxyGenerateFailedException("模块Hook代理生成失败! 代理失败的模块名: " + module.getClazz().getSimpleName(), e);
}
}
private MethodsListRecord collectHookMethods(Class<?> clazz) {
List<MetaMethod> post = new ArrayList<>();
List<MetaMethod> pre = new ArrayList<>();
//获取该类本身的hook逻辑
collectHookMethods(post, pre, clazz);
//获取它所继承、实现的抽象类或接口, 以Module为终点收集继承链上所有父类和接口
Set<Class<?>> classes = collectExtendedClasses(clazz, Module.class);
//获取这些类中的hook逻辑
collectHookMethods(post, pre, classes);
return new MethodsListRecord(post, pre);
}
private void collectHookMethods(List<MetaMethod> post, List<MetaMethod> pre, Set<Class<?>> classes) {
for (Class<?> type : classes) {
collectPreHookMethods(pre, type);
collectPostHookMethods(post, type);
}
}
private void collectPostHookMethods(List<MetaMethod> post, Class<?> type) {
Set<MetaMethod> collectedPostHookMethod = Arrays.stream(type.getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(AfterExecute.class))
.map(method -> {
MetaMethod metaMethod = new MetaMethod();
metaMethod.setMethod(method);
metaMethod.setOrder(method.getAnnotation(AfterExecute.class).order());
return metaMethod;
})
.collect(Collectors.toSet());
post.addAll(collectedPostHookMethod);
}
private void collectPreHookMethods(List<MetaMethod> pre, Class<?> type) {
Set<MetaMethod> collectedPreHookMethods = Arrays.stream(type.getDeclaredMethods())
.filter(method -> method.isAnnotationPresent(BeforeExecute.class))
.map(method -> {
MetaMethod metaMethod = new MetaMethod();
metaMethod.setMethod(method);
metaMethod.setOrder(method.getAnnotation(BeforeExecute.class).order());
return metaMethod;
})
.collect(Collectors.toSet());
pre.addAll(collectedPreHookMethods);
}
private void collectHookMethods(List<MetaMethod> post, List<MetaMethod> pre, Class<?> clazz) {
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(BeforeExecute.class)) {
MetaMethod metaMethod = new MetaMethod();
metaMethod.setOrder(method.getAnnotation(BeforeExecute.class).order());
pre.add(metaMethod);
metaMethod.setMethod(method);
} else if (method.isAnnotationPresent(AfterExecute.class)) {
MetaMethod metaMethod = new MetaMethod();
metaMethod.setOrder(method.getAnnotation(AfterExecute.class).order());
post.add(metaMethod);
metaMethod.setMethod(method);
}
}
}
@Getter
@SuppressWarnings("ClassCanBeRecord")
public static class ModuleProxyInterceptor {
private final List<MetaMethod> postHookMethods;
private final List<MetaMethod> preHookMethods;
public ModuleProxyInterceptor(List<MetaMethod> postHookMethods, List<MetaMethod> preHookMethods) {
this.postHookMethods = postHookMethods;
this.preHookMethods = preHookMethods;
}
@RuntimeType
public Object intercept(@Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper, @This Object proxy) throws Exception {
executeHookMethods(preHookMethods, proxy);
Object res = zuper.call();
executeHookMethods(postHookMethods, proxy);
return res;
}
private void executeHookMethods(List<MetaMethod> hookMethods, Object proxy) {
for (MetaMethod metaMethod : hookMethods) {
Method m = metaMethod.getMethod();
try {
m.setAccessible(true);
m.invoke(proxy);
} catch (Exception e) {
throw new ProxiedModuleRunningException("hook方法执行异常: " + m.getDeclaringClass() + "#" + m.getName(), e);
}
}
}
}
record MethodsListRecord(List<MetaMethod> post, List<MetaMethod> pre) {
public MethodsListRecord {
post.sort(Comparator.comparingInt(MetaMethod::getOrder));
pre.sort(Comparator.comparingInt(MetaMethod::getOrder));
}
}
}

View File

@@ -1,104 +0,0 @@
package work.slhaf.partner.api.agent.factory.module;
import cn.hutool.core.util.ClassUtil;
import org.reflections.Reflections;
import work.slhaf.partner.api.agent.factory.AgentBaseFactory;
import work.slhaf.partner.api.agent.factory.context.AgentRegisterContext;
import work.slhaf.partner.api.agent.factory.context.ModuleFactoryContext;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentSubModule;
import work.slhaf.partner.api.agent.factory.module.annotation.CoreModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaSubModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
/**
* <h2>Agent启动流程 2</h2>
*
* <p>
* 负责收集 {@link AgentModule} 与 {@link AgentSubModule} 注解所在类的信息,供后续工厂完成动态代理、模块与能力注入
* <p/>
*
* <ol>
* <li>
* <p>{@link ModuleRegisterFactory#setModuleList()}</p>
* 扫描 {@link AgentModule} 注解,获取执行模块信息: 类型、模块名称({@link AgentModule#name()}),执行顺序。并按照注解的 {@link AgentModule#order()} 字段进行排序
* </li>
* <li>
* <p>{@link ModuleRegisterFactory#setSubModuleList()}</p>
* 扫描 {@link AgentSubModule} 注册,获取子模块类型信息
* </li>
* <li>
* 两种模块都将存入各自的list中供后续模块完成注册与注入
* </li>
* </ol>
*
* <p>下一步流程请参阅{@link ModuleProxyFactory}</p>
*/
public class ModuleRegisterFactory extends AgentBaseFactory {
private Reflections reflections;
private List<MetaModule> moduleList;
private List<MetaSubModule> subModuleList;
@Override
protected void setVariables(AgentRegisterContext context) {
ModuleFactoryContext factoryContext = context.getModuleFactoryContext();
reflections = context.getReflections();
moduleList = factoryContext.getAgentModuleList();
subModuleList = factoryContext.getAgentSubModuleList();
}
@Override
protected void run() {
setModuleList();
setSubModuleList();
}
private void setSubModuleList() {
Set<Class<?>> subModules = reflections.getTypesAnnotatedWith(AgentSubModule.class);
for (Class<?> subModule : subModules) {
if (!ClassUtil.isNormalClass(subModule)) {
continue;
}
Class<? extends AgentRunningSubModule> clazz = subModule.asSubclass(AgentRunningSubModule.class);
MetaSubModule metaSubModule = new MetaSubModule();
metaSubModule.setClazz(clazz);
subModuleList.add(metaSubModule);
}
}
private void setModuleList() {
//反射扫描获取@AgentModule所在类, 该部分为Agent流程执行模块
Set<Class<?>> modules = reflections.getTypesAnnotatedWith(AgentModule.class);
for (Class<?> module : modules) {
if (!ClassUtil.isNormalClass(module)) {
continue;
}
Class<? extends AgentRunningModule> clazz = module.asSubclass(AgentRunningModule.class);
MetaModule metaModule = getMetaModule(clazz);
moduleList.add(metaModule);
}
moduleList.sort(Comparator.comparing(MetaModule::getOrder));
}
private static MetaModule getMetaModule(Class<? extends AgentRunningModule> clazz) {
MetaModule metaModule = new MetaModule();
AgentModule agentModule;
if (clazz.isAnnotationPresent(CoreModule.class)){
agentModule = CoreModule.class.getAnnotation(AgentModule.class);
}else{
agentModule = clazz.getAnnotation(AgentModule.class);
}
metaModule.setName(agentModule.name());
metaModule.setOrder(agentModule.order());
metaModule.setClazz(clazz);
return metaModule;
}
}

View File

@@ -1,20 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 仅适用于以下类中的方法:
* 1. <code>@AgentModule</code>注解所在类
* 2. <code>ActivateModel</code>子类
* 3. <code>AgentRunningModule</code>或者<code>AgentRunningSubModule</code>子类
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterExecute {
int order() default 0;
}

View File

@@ -1,26 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.annotation;
import work.slhaf.partner.api.agent.factory.capability.annotation.CapabilityHolder;
import java.lang.annotation.*;
/**
* 用于注解执行模块
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@CapabilityHolder
@Inherited
public @interface AgentModule {
/**
* 模块名称
*/
String name();
/**
* 模块执行顺序,数字越小执行越靠前
*/
int order();
}

View File

@@ -1,14 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.annotation;
import work.slhaf.partner.api.agent.factory.capability.annotation.CapabilityHolder;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@CapabilityHolder
public @interface AgentSubModule {
}

View File

@@ -1,18 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 仅适用于以下类中的方法:
* 1. <code>@AgentModule</code>注解所在类
* 2. <code>ActivateModel</code>子类
* 3. <code>AgentRunningModule</code>或者<code>AgentRunningSubModule</code>子类
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeforeExecute {
int order() default 0;
}

View File

@@ -1,9 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@AgentModule(name = "core",order = 5)
public @interface CoreModule {
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.exception;
public class ModuleCheckException extends ModuleFactoryInitFailedException {
public ModuleCheckException(String message) {
super(message);
}
public ModuleCheckException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.exception;
public class ModuleFactoryInitFailedException extends RuntimeException {
public ModuleFactoryInitFailedException(String message) {
super("ModuleFactory 执行失败: "+message);
}
public ModuleFactoryInitFailedException(String message, Throwable cause) {
super("ModuleFactory 执行失败: "+message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.exception;
public class ModuleInitHookExecuteFailedException extends ModuleFactoryInitFailedException {
public ModuleInitHookExecuteFailedException(String message) {
super(message);
}
public ModuleInitHookExecuteFailedException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.exception;
public class ModuleInstanceGenerateFailedException extends ModuleFactoryInitFailedException {
public ModuleInstanceGenerateFailedException(String message) {
super(message);
}
public ModuleInstanceGenerateFailedException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.exception;
public class ModuleProxyGenerateFailedException extends ModuleFactoryInitFailedException {
public ModuleProxyGenerateFailedException(String message) {
super(message);
}
public ModuleProxyGenerateFailedException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,13 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.exception;
import work.slhaf.partner.api.agent.runtime.exception.AgentRuntimeException;
public class ProxiedModuleRunningException extends AgentRuntimeException {
public ProxiedModuleRunningException(String message) {
super(message);
}
public ProxiedModuleRunningException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,10 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.pojo;
import lombok.Data;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.Module;
@Data
public abstract class BaseMetaModule <C extends Module> {
private Class<? extends C> clazz;
private C instance;
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.pojo;
import lombok.Data;
import java.lang.reflect.Method;
@Data
public class MetaMethod {
private int order;
private Method method;
}

View File

@@ -1,13 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
@EqualsAndHashCode(callSuper = true)
@Data
public class MetaModule extends BaseMetaModule<AgentRunningModule>{
private String name;
private int order;
private boolean enabled = true;
}

View File

@@ -1,10 +0,0 @@
package work.slhaf.partner.api.agent.factory.module.pojo;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningSubModule;
@EqualsAndHashCode(callSuper = true)
@Data
public class MetaSubModule extends BaseMetaModule<AgentRunningSubModule>{
}

View File

@@ -1,103 +0,0 @@
package work.slhaf.partner.api.agent.runtime.config;
import lombok.Data;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.config.exception.ConfigUpdateFailedException;
import work.slhaf.partner.api.agent.factory.config.exception.PromptNotExistException;
import work.slhaf.partner.api.agent.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.chat.pojo.Message;
import java.util.*;
@Slf4j
@Data
public abstract class AgentConfigManager {
@Setter
public static AgentConfigManager INSTANCE = new FileAgentConfigManager();
private static final String DEFAULT_KEY = "default";
protected HashMap<String, ModelConfig> modelConfigMap;
protected HashMap<String, List<Message>> modelPromptMap;
protected HashMap<String, Boolean> moduleEnabledStatus;
protected Map<Integer, List<MetaModule>> moduleOrderedMap = new LinkedHashMap<>();
protected Map<String, MetaModule> moduleMap = new HashMap<>();
public void load() {
modelConfigMap = loadModelConfig();
modelPromptMap = loadModelPrompt();
}
protected abstract HashMap<String, List<Message>> loadModelPrompt();
protected abstract HashMap<String, ModelConfig> loadModelConfig();
public abstract void dumpModelConfig(String key);
protected abstract void dumpModuleEnabledStatus();
protected abstract HashMap<String, Boolean> loadModuleEnabledStatusMap(List<MetaModule> moduleList);
public void moduleEnabledStatusFilterAndRecord(List<MetaModule> moduleList) {
updateModuleMap(moduleList);
updateModuleEnabledStatus(moduleList);
}
private void updateModuleMap(List<MetaModule> moduleList) {
//在ModuleRegisterFactory已进行过排序操作
for (MetaModule module : moduleList) {
int k = module.getOrder();
moduleOrderedMap.computeIfAbsent(k, order -> new ArrayList<>()).add(module);
moduleMap.put(module.getName(), module);
}
}
private void updateModuleEnabledStatus(List<MetaModule> moduleList) {
this.moduleEnabledStatus = loadModuleEnabledStatusMap(moduleList);
boolean unmatch = false;
for (MetaModule metaModule : moduleList) {
String moduleName = metaModule.getName();
if (moduleEnabledStatus.containsKey(moduleName)) {
metaModule.setEnabled(moduleEnabledStatus.get(moduleName));
} else {
log.warn("缺少Module {} 启用配置! 将触发更新操作!", moduleName);
unmatch = true;
}
}
if (unmatch) {
dumpModuleEnabledStatus();
}
}
public List<Message> loadModelPrompt(String modelKey) {
if (!modelPromptMap.containsKey(modelKey)) {
throw new PromptNotExistException("不存在的modelPrompt: " + modelKey);
}
return modelPromptMap.get(modelKey);
}
public ModelConfig loadModelConfig(String modelKey) {
if (!modelConfigMap.containsKey(modelKey)) {
return modelConfigMap.get(DEFAULT_KEY);
}
return modelConfigMap.get(modelKey);
}
public void updateModelConfig(String modelKey, ModelConfig config) {
modelConfigMap.put(modelKey, config);
dumpModelConfig(modelKey);
}
public void updateModuleEnabledStatus(String key, boolean status) {
if (!moduleEnabledStatus.containsKey(key)) {
throw new ConfigUpdateFailedException("模块状态更新失败! 不存在的ModuleKey: " + key);
}
moduleEnabledStatus.put(key, status);
dumpModuleEnabledStatus();
moduleMap.get(key).setEnabled(status);
}
}

View File

@@ -1,122 +0,0 @@
package work.slhaf.partner.api.agent.runtime.config;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import work.slhaf.partner.api.agent.factory.config.exception.*;
import work.slhaf.partner.api.agent.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.agent.factory.config.pojo.PrimaryModelConfig;
import work.slhaf.partner.api.agent.factory.config.pojo.PrimaryModelPrompt;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.chat.pojo.Message;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
/**
* 默认配置工厂
* 将从当前运行目录的config文件夹下创建并读取配置
*/
@Slf4j
public class FileAgentConfigManager extends AgentConfigManager {
protected static final String CONFIG_DIR = "./config/";
protected static final String MODEL_CONFIG_DIR = "./config/model/";
protected static final String PROMPT_CONFIG_DIR = "./config/prompt/";
protected static final String MODULE_ENABLED_STATUS_CONFIG_FILE = CONFIG_DIR + "module_enabled_status.json";
@Override
protected HashMap<String, List<Message>> loadModelPrompt() {
File file = new File(PROMPT_CONFIG_DIR);
if (!file.exists() && !file.isDirectory()) {
throw new PromptDirNotExistException("未找到提示词目录: " + PROMPT_CONFIG_DIR + " 请手动创建!");
}
File[] files = file.listFiles();
if (files == null || files.length == 0) {
throw new PromptNotExistException("在目录 " + PROMPT_CONFIG_DIR + " 中未找到提示词配置!");
}
HashMap<String, List<Message>> promptMap = new HashMap<>();
for (File f : files) {
if (f.isDirectory()) {
continue;
}
PrimaryModelPrompt primaryModelPrompt = JSONUtil.readJSONObject(f, StandardCharsets.UTF_8).toBean(PrimaryModelPrompt.class);
promptMap.put(primaryModelPrompt.getKey(), primaryModelPrompt.getMessages());
}
return promptMap;
}
@Override
protected HashMap<String, ModelConfig> loadModelConfig() {
File file = new File(MODEL_CONFIG_DIR);
if (!file.exists() || !file.isDirectory()) {
throw new ConfigDirNotExistException("未找到配置目录: " + MODEL_CONFIG_DIR + " 请手动创建!");
}
File[] files = file.listFiles();
if (files == null || files.length == 0) {
throw new ConfigNotExistException("在目录" + MODEL_CONFIG_DIR + "中未找到配置文件!");
}
//遍历文件获取所有配置文件并返回
HashMap<String, ModelConfig> configMap = new HashMap<>();
for (File f : files) {
if (f.isDirectory()) {
continue;
}
PrimaryModelConfig primaryModelConfig = JSONUtil.readJSONObject(f, StandardCharsets.UTF_8).toBean(PrimaryModelConfig.class);
configMap.put(primaryModelConfig.getKey(), primaryModelConfig.getModelConfig());
}
return configMap;
}
@Override
protected HashMap<String, Boolean> loadModuleEnabledStatusMap(List<MetaModule> moduleList) {
File file = new File(MODULE_ENABLED_STATUS_CONFIG_FILE);
try {
moduleEnabledStatus = new HashMap<>();
if (!file.exists()) {
file.createNewFile();
for (MetaModule module : moduleList) {
moduleEnabledStatus.put(module.getName(), module.isEnabled());
}
dumpModuleEnabledStatus();
} else {
JSONObject obj = JSONUtil.readJSONObject(file, StandardCharsets.UTF_8);
for (String s : obj.keySet()) {
moduleEnabledStatus.put(s, obj.getBool(s));
}
log.info("ModuleEnabledStatusConfig 配置文件已成功读取!");
}
return moduleEnabledStatus;
} catch (Exception e) {
throw new ConfigGenerateFailedException("ModuleEnabledStatusConfig 配置文件创建失败!", e);
}
}
@Override
public void dumpModelConfig(String key) {
try {
File file = new File(MODEL_CONFIG_DIR + key + ".json");
if (!file.exists()) {
file.createNewFile();
}
FileUtils.writeStringToFile(file, JSONUtil.toJsonPrettyStr(modelConfigMap.get(key)), StandardCharsets.UTF_8, false);
} catch (Exception e) {
throw new ConfigUpdateFailedException("ModelConfig 配置文件更新失败!");
}
}
@Override
protected void dumpModuleEnabledStatus() {
try {
File file = new File(MODULE_ENABLED_STATUS_CONFIG_FILE);
FileUtils.writeStringToFile(file, JSONUtil.toJsonPrettyStr(moduleEnabledStatus), StandardCharsets.UTF_8, false);
} catch (IOException e) {
throw new ConfigGenerateFailedException("ModuleEnabledStatus 配置文件更新失败!");
}
}
}

View File

@@ -1,23 +0,0 @@
package work.slhaf.partner.api.agent.runtime.data;
import lombok.Data;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
@Data
public class AgentContext {
public static AgentContext INSTANCE = new AgentContext();
private HashMap<String, Function<Object[], Object>> methodsRouterTable;
private HashMap<String, Function<Object[], Object>> coordinatedMethodsRouterTable;
private HashMap<Class<?>, Object> capabilityCoreInstances;
private HashMap<Class<?>, Object> capabilityHolderInstances;
private Set<Class<?>> cores;
private Set<Class<?>> capabilities;
private List<MetaModule> moduleList;
}

View File

@@ -1,6 +0,0 @@
package work.slhaf.partner.api.agent.runtime.exception;
public interface AgentExceptionCallback {
void onRuntimeException(AgentRuntimeException e);
void onFailedException(AgentLaunchFailedException e);
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.runtime.exception;
public class AgentLaunchFailedException extends RuntimeException {
public AgentLaunchFailedException(String message, Throwable cause) {
super("Agent 启动失败 " + message, cause);
}
public AgentLaunchFailedException(String message) {
super("Agent 启动失败 " + message);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.runtime.exception;
public class AgentRunningFailedException extends AgentRuntimeException{
public AgentRunningFailedException(String message) {
super(message);
}
public AgentRunningFailedException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,11 +0,0 @@
package work.slhaf.partner.api.agent.runtime.exception;
public class AgentRuntimeException extends RuntimeException {
public AgentRuntimeException(String message) {
super("Agent 执行出错 " + message);
}
public AgentRuntimeException(String message, Throwable cause) {
super("Agent 执行出错 " + message, cause);
}
}

View File

@@ -1,39 +0,0 @@
package work.slhaf.partner.api.agent.runtime.exception;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class GlobalExceptionHandler {
public static GlobalExceptionHandler INSTANCE = new GlobalExceptionHandler();
private AgentExceptionCallback exceptionCallback = new LogAgentExceptionCallback();
public boolean handle(Throwable e) {
boolean exit;
Throwable cause = e.getCause();
switch (cause) {
case AgentRunningFailedException arfe -> {
exit = true;
exceptionCallback.onRuntimeException((AgentRuntimeException) cause);
}
case AgentRuntimeException are -> {
exit = false;
exceptionCallback.onRuntimeException((AgentRuntimeException) cause);
}
case AgentLaunchFailedException alfe -> {
exit = true;
exceptionCallback.onFailedException((AgentLaunchFailedException) cause);
}
default -> {
exit = true;
log.error("意外异常: ", cause);
}
}
return exit;
}
public static void setExceptionCallback(AgentExceptionCallback callback) {
INSTANCE.exceptionCallback = callback;
}
}

View File

@@ -1,17 +0,0 @@
package work.slhaf.partner.api.agent.runtime.exception;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LogAgentExceptionCallback implements AgentExceptionCallback {
@Override
public void onRuntimeException(AgentRuntimeException e) {
log.error("Agent 运行异常: ", e);
}
@Override
public void onFailedException(AgentLaunchFailedException e) {
throw e;
}
}

View File

@@ -1,26 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction;
import work.slhaf.partner.api.agent.runtime.interaction.data.AgentInputData;
import work.slhaf.partner.api.agent.runtime.interaction.data.AgentOutputData;
import work.slhaf.partner.api.agent.runtime.interaction.flow.entity.RunningFlowContext;
public interface AgentGateway <I extends AgentInputData, O extends AgentOutputData, C extends RunningFlowContext>{
void launch();
default void receive(I inputData){
C finalInputData = adapter().parseInputData(inputData);
C outputContext = adapter().call(finalInputData);
O outputData = adapter().parseOutputData(outputContext);
send(outputData);
}
void send(O outputData);
/**
* 通过adapter提供的receive、send方法进行与客户端的交互行为
*
* @return adapter实例
*/
AgentInteractionAdapter<I, O, C> adapter();
}

View File

@@ -1,26 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.interaction.data.AgentInputData;
import work.slhaf.partner.api.agent.runtime.interaction.data.AgentOutputData;
import work.slhaf.partner.api.agent.runtime.interaction.flow.AgentRunningFlow;
import work.slhaf.partner.api.agent.runtime.interaction.flow.entity.RunningFlowContext;
import java.util.List;
import java.util.Map;
public abstract class AgentInteractionAdapter<I extends AgentInputData, O extends AgentOutputData, C extends RunningFlowContext> {
protected AgentRunningFlow<C> agentRunningFlow = new AgentRunningFlow<>();
protected Map<Integer, List<MetaModule>> moduleOrderedMap = AgentConfigManager.INSTANCE.getModuleOrderedMap();
public C call(C finalInputData){
return agentRunningFlow.launch(moduleOrderedMap, finalInputData);
}
protected abstract O parseOutputData(C outputContext);
protected abstract C parseInputData(I inputData);
}

View File

@@ -1,9 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public abstract class AgentInputData extends InteractionData{
}

View File

@@ -1,16 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.data;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public abstract class AgentOutputData extends InteractionData{
protected int code;
public static class StatusCode {
public static final int SUCCESS = 1;
public static final int FAILED = 0;
}
}

View File

@@ -1,12 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.data;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public abstract class InteractionData {
protected String userInfo;
protected String content;
protected LocalDateTime dateTime;
}

View File

@@ -1,49 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.flow;
import work.slhaf.partner.api.agent.factory.module.pojo.MetaModule;
import work.slhaf.partner.api.agent.runtime.exception.AgentRuntimeException;
import work.slhaf.partner.api.agent.runtime.exception.GlobalExceptionHandler;
import work.slhaf.partner.api.agent.runtime.interaction.flow.entity.RunningFlowContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Agent执行流程
*/
public class AgentRunningFlow<C extends RunningFlowContext> {
public C launch(Map<Integer, List<MetaModule>> modules, C interactionContext) {
try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
//流程执行启动
for (Map.Entry<Integer, List<MetaModule>> entry : modules.entrySet()) {
List<Future<?>> futures = new ArrayList<>();
List<MetaModule> moduleList = entry.getValue();
for (MetaModule module : moduleList) {
Future<?> future = executor.submit(() -> {
module.getInstance().execute(interactionContext);
});
futures.add(future);
}
for (Future<?> future : futures) {
try {
future.get();
} catch (Exception e) {
boolean exit = GlobalExceptionHandler.INSTANCE.handle(e);
if (exit) throw new AgentRuntimeException("Agent执行出错!", e);
interactionContext.getErrMsg().add(e.getLocalizedMessage());
}
}
}
interactionContext.setOk(1);
} catch (Exception e) {
interactionContext.setOk(0);
interactionContext.getErrMsg().add(e.getLocalizedMessage());
}
return interactionContext;
}
}

View File

@@ -1,97 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts;
import cn.hutool.core.bean.BeanUtil;
import work.slhaf.partner.api.agent.factory.config.pojo.ModelConfig;
import work.slhaf.partner.api.agent.factory.module.annotation.Init;
import work.slhaf.partner.api.agent.runtime.config.AgentConfigManager;
import work.slhaf.partner.api.agent.runtime.interaction.flow.entity.Model;
import work.slhaf.partner.api.chat.ChatClient;
import work.slhaf.partner.api.chat.constant.ChatConstant;
import work.slhaf.partner.api.chat.pojo.ChatResponse;
import work.slhaf.partner.api.chat.pojo.Message;
import java.util.ArrayList;
import java.util.List;
public interface ActivateModel {
AgentConfigManager AGENT_CONFIG_MANAGER = AgentConfigManager.INSTANCE;
@Init(order = -1)
default void modelSettings() {
Model model = new Model();
ModelConfig modelConfig = AgentConfigManager.INSTANCE.loadModelConfig(modelKey());
model.setBaseMessages(withBasicPrompt() ? loadSpecificPromptAndBasicPrompt(modelKey()) : loadSpecificPrompt(modelKey()));
model.setChatClient(new ChatClient(modelConfig.getBaseUrl(), modelConfig.getApikey(), modelConfig.getModel()));
setModel(model);
}
default void updateModelSettings(ChatClient newChatClient) {
BeanUtil.copyProperties(newChatClient, chatClient());
}
private List<Message> loadSpecificPrompt(String modelKey) {
return AGENT_CONFIG_MANAGER.loadModelPrompt(modelKey);
}
private List<Message> loadSpecificPromptAndBasicPrompt(String modelKey) {
List<Message> messages = new ArrayList<>();
messages.addAll(AGENT_CONFIG_MANAGER.loadModelPrompt("basic"));
messages.addAll(AGENT_CONFIG_MANAGER.loadModelPrompt(modelKey));
return messages;
}
default ChatResponse chat() {
Model model = getModel();
List<Message> temp = new ArrayList<>();
temp.addAll(model.getBaseMessages());
temp.addAll(model.getChatMessages());
return model.getChatClient().runChat(temp);
}
default ChatResponse singleChat(String input) {
Model model = getModel();
List<Message> temp = new ArrayList<>(model.getBaseMessages());
temp.add(new Message(ChatConstant.Character.USER, input));
return model.getChatClient().runChat(temp);
}
default void updateChatClientSettings() {
Model model = getModel();
model.getChatClient().setTemperature(0.4);
model.getChatClient().setTop_p(0.8);
}
default List<Message> chatMessages() {
return getModel().getChatMessages();
}
default List<Message> baseMessages() {
return getModel().getBaseMessages();
}
default ChatClient chatClient() {
return getModel().getChatClient();
}
/**
* 仅适用Module子类否则需要重写
*
* @return 持有的model实例
*/
default Model getModel() {
return ((Module) this).getModel();
}
default void setModel(Model model) {
((Module) this).setModel(model);
}
/**
* 对应调用的模型配置名称
*/
String modelKey();
boolean withBasicPrompt();
}

View File

@@ -1,36 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.CoreModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.entity.RunningFlowContext;
/**
* 流程执行模块基类
*/
@Slf4j
public abstract class AgentRunningModule<C extends RunningFlowContext> extends Module {
public abstract void execute(C context);
@BeforeExecute
private void beforeLog() {
log.debug("[{}] 模块执行开始...", getModuleName());
}
@AfterExecute
private void afterLog() {
log.debug("[{}] 模块执行结束...", getModuleName());
}
private String getModuleName(){
if (this.getClass().isAnnotationPresent(AgentModule.class)) {
return this.getClass().getAnnotation(AgentModule.class).name();
} else if (this.getClass().isAnnotationPresent(CoreModule.class)) {
return CoreModule.class.getAnnotation(AgentModule.class).name();
}else {
return "Unknown Module";
}
}
}

View File

@@ -1,35 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.agent.factory.module.annotation.AfterExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.AgentModule;
import work.slhaf.partner.api.agent.factory.module.annotation.BeforeExecute;
import work.slhaf.partner.api.agent.factory.module.annotation.CoreModule;
@Slf4j
public abstract class AgentRunningSubModule<I, O> extends Module {
public abstract O execute(I data);
@BeforeExecute
private void beforeLog() {
log.debug("[{}] 模块执行开始...", getModuleName());
}
@AfterExecute
private void afterLog() {
log.debug("[{}] 模块执行结束...", getModuleName());
}
private String getModuleName(){
if (this.getClass().isAnnotationPresent(AgentModule.class)) {
return this.getClass().getAnnotation(AgentModule.class).name();
} else if (this.getClass().isAnnotationPresent(CoreModule.class)) {
return CoreModule.class.getAnnotation(AgentModule.class).name();
}else {
return "Unknown Module";
}
}
}

View File

@@ -1,16 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts;
import lombok.Getter;
import lombok.Setter;
import work.slhaf.partner.api.agent.runtime.interaction.flow.entity.Model;
/**
* 模块基类
*/
public abstract class Module {
@Getter
@Setter
protected Model model = new Model();
}

View File

@@ -1,16 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.flow.entity;
import lombok.Data;
import work.slhaf.partner.api.chat.ChatClient;
import work.slhaf.partner.api.chat.pojo.Message;
import java.util.List;
@Data
public class Model {
protected ChatClient chatClient;
protected List<Message> chatMessages;
protected List<Message> baseMessages;
}

View File

@@ -1,18 +0,0 @@
package work.slhaf.partner.api.agent.runtime.interaction.flow.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.partner.api.common.entity.PersistableObject;
import java.util.ArrayList;
import java.util.List;
/**
* 流程上下文
*/
@EqualsAndHashCode(callSuper = true)
@Data
public abstract class RunningFlowContext extends PersistableObject {
protected int ok;
protected List<String> errMsg = new ArrayList<>();
}

View File

@@ -1,84 +0,0 @@
package work.slhaf.partner.api.chat;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import work.slhaf.partner.api.chat.constant.ChatConstant;
import work.slhaf.partner.api.chat.pojo.ChatBody;
import work.slhaf.partner.api.chat.pojo.ChatResponse;
import work.slhaf.partner.api.chat.pojo.Message;
import work.slhaf.partner.api.chat.pojo.PrimaryChatResponse;
import java.util.List;
@Slf4j
@Data
@NoArgsConstructor
public class ChatClient {
private String clientId;
private String url;
private String apikey;
private String model;
private double top_p;
private double temperature;
private int max_tokens;
public ChatClient(String url, String apikey, String model) {
this.url = url;
this.apikey = apikey;
this.model = model;
}
public ChatResponse runChat(List<Message> messages) {
HttpRequest request = HttpRequest.post(url);
request.setConnectionTimeout(2000);
request.setReadTimeout(15000);
request.header("Content-Type", "application/json");
request.header("Authorization", "Bearer " + apikey);
ChatBody body;
if (top_p > 0) {
body = ChatBody.builder()
.model(model)
.messages(messages)
.top_p(top_p)
.temperature(temperature)
.max_tokens(max_tokens)
.build();
} else {
body = ChatBody.builder()
.model(model)
.messages(messages)
.build();
}
ChatResponse finalResponse;
try {
HttpResponse response = request.body(JSONUtil.toJsonStr(body)).execute();
PrimaryChatResponse primaryChatResponse = JSONUtil.toBean(response.body(), PrimaryChatResponse.class);
finalResponse = ChatResponse.builder()
.status(ChatConstant.ResponseStatus.SUCCESS)
.message(primaryChatResponse.getChoices().get(0).getMessage().getContent())
.usageBean(primaryChatResponse.getUsage())
.build();
response.close();
} catch (IORuntimeException e) {
log.error("请求超时", e);
finalResponse = ChatResponse.builder()
.message("连接超时")
.status(ChatConstant.ResponseStatus.FAILED)
.usageBean(null)
.build();
}
return finalResponse;
}
}

View File

@@ -1,14 +0,0 @@
package work.slhaf.partner.api.chat.constant;
public class ChatConstant {
public static class Character {
public static final String USER = "user";
public static final String SYSTEM = "system";
public static final String ASSISTANT = "assistant";
}
public enum ResponseStatus {
SUCCESS, FAILED
}
}

View File

@@ -1,25 +0,0 @@
package work.slhaf.partner.api.chat.pojo;
import lombok.*;
import java.util.List;
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ChatBody {
@NonNull
private String model;
@NonNull
private List<Message> messages;
@Builder.Default
private double temperature = 1;
@Builder.Default
private double top_p = 1;
private boolean stream;
@Builder.Default
private int max_tokens = 1024;
private int presence_penalty;
private int frequency_penalty;
}

View File

@@ -1,17 +0,0 @@
package work.slhaf.partner.api.chat.pojo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import work.slhaf.partner.api.chat.constant.ChatConstant;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ChatResponse {
private ChatConstant.ResponseStatus status;
private String message;
private PrimaryChatResponse.UsageBean usageBean;
}

View File

@@ -1,22 +0,0 @@
package work.slhaf.partner.api.chat.pojo;
import lombok.*;
import work.slhaf.partner.api.common.entity.PersistableObject;
import java.io.Serial;
@EqualsAndHashCode(callSuper = true)
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Message extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
@NonNull
private String role;
@NonNull
private String content;
}

View File

@@ -1,20 +0,0 @@
package work.slhaf.partner.api.chat.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import work.slhaf.partner.api.common.entity.PersistableObject;
import java.io.Serial;
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
public class MetaMessage extends PersistableObject {
@Serial
private static final long serialVersionUID = 1L;
private Message userMessage;
private Message assistantMessage;
}

View File

@@ -1,111 +0,0 @@
package work.slhaf.partner.api.chat.pojo;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class PrimaryChatResponse {
/**
* id
*/
private String id;
/**
* object
*/
private String object;
/**
* created
*/
private int created;
/**
* model
*/
private String model;
/**
* choices
*/
private List<ChoicesBean> choices;
/**
* usage
*/
private UsageBean usage;
/**
* system_fingerprint
*/
private String system_fingerprint;
@Setter
@Getter
public static class UsageBean {
/**
* prompt_tokens
*/
private int prompt_tokens;
/**
* completion_tokens
*/
private int completion_tokens;
/**
* total_tokens
*/
private int total_tokens;
/**
* prompt_cache_hit_tokens
*/
private int prompt_cache_hit_tokens;
/**
* prompt_cache_miss_tokens
*/
private int prompt_cache_miss_tokens;
@Override
public String toString() {
return "UsageBean{" +
"prompt_tokens=" + prompt_tokens +
", completion_tokens=" + completion_tokens +
", total_tokens=" + total_tokens +
", prompt_cache_hit_tokens=" + prompt_cache_hit_tokens +
", prompt_cache_miss_tokens=" + prompt_cache_miss_tokens +
'}';
}
}
@Setter
@Getter
public static class ChoicesBean {
/**
* index
*/
private int index;
/**
* message
*/
private MessageBean message;
/**
* logprobs
*/
private Object logprobs;
/**
* finish_reason
*/
private String finish_reason;
@Setter
@Getter
public static class MessageBean {
/**
* role
*/
private String role;
/**
* content
*/
private String content;
}
}
}

View File

@@ -1,6 +0,0 @@
package work.slhaf.partner.api.common.entity;
import java.io.Serializable;
public abstract class PersistableObject implements Serializable {
}

View File

@@ -1,7 +0,0 @@
package factory;
public class AgentRegisterTest {
public static void main(String[] args) {
}
}

View File

@@ -1,25 +0,0 @@
package module;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;
import org.junit.jupiter.api.Test;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
public class ModuleProxyTest {
@Test
public void test() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
Class<? extends AgentRunningModule> clazz = new ByteBuddy().subclass(MyAgentRunningModule.class)
.method(ElementMatchers.isOverriddenFrom(AgentRunningModule.class))
.intercept(MethodDelegation.to(
new MyModuleProxyInterceptor()
))
.make()
.load(ModuleProxyTest.class.getClassLoader())
.getLoaded();
clazz.getConstructor().newInstance().execute(null);
}
}

View File

@@ -1,11 +0,0 @@
package module;
import work.slhaf.partner.api.agent.runtime.interaction.flow.abstracts.AgentRunningModule;
import work.slhaf.partner.api.agent.runtime.interaction.flow.entity.RunningFlowContext;
public class MyAgentRunningModule extends AgentRunningModule {
@Override
public void execute(RunningFlowContext context) {
System.out.println("MyAgentRunningModule");
}
}

View File

@@ -1,18 +0,0 @@
package module;
import net.bytebuddy.implementation.bind.annotation.*;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
public class MyModuleProxyInterceptor {
public MyModuleProxyInterceptor() {}
@RuntimeType
public Object intercept(@Origin Method method, @AllArguments Object[] allArguments, @SuperCall Callable<?> zuper, @This Object proxy) throws Exception {
System.out.println("22222");
Object res = zuper.call();
System.out.println("11111");
return res;
}
}

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>

View File

@@ -31,9 +31,6 @@ public final class InProcessMcpTransport implements McpClientTransport, McpState
private volatile McpStatelessServerHandler serverHandler;
public record Pair(InProcessMcpTransport clientSide, InProcessMcpTransport serverSide) {
}
public static Pair pair() {
InProcessMcpTransport client = new InProcessMcpTransport();
InProcessMcpTransport server = new InProcessMcpTransport();
@@ -126,15 +123,15 @@ public final class InProcessMcpTransport implements McpClientTransport, McpState
return Mono.empty();
}
/* ======================================================
* other boilerplate
* ====================================================== */
@Override
public void close() {
McpClientTransport.super.close();
}
/* ======================================================
* other boilerplate
* ====================================================== */
@Override
public Mono<Void> closeGracefully() {
inbound.tryEmitComplete();
@@ -152,4 +149,7 @@ public final class InProcessMcpTransport implements McpClientTransport, McpState
public List<String> protocolVersions() {
return McpClientTransport.super.protocolVersions();
}
public record Pair(InProcessMcpTransport clientSide, InProcessMcpTransport serverSide) {
}
}

View File

@@ -1,49 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>work.slhaf</groupId>
<artifactId>Partner</artifactId>
<groupId>work.slhaf</groupId>
<version>0.5.0</version>
</parent>
<artifactId>Partner-Test-Demo</artifactId>
<dependencies>
<dependency>
<groupId>work.slhaf</groupId>
<artifactId>Partner-Api</artifactId>
<version>0.5.0</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modelVersion>4.0.0</modelVersion>
<artifactId>Partner-Main</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>work.slhaf.demo.AgentDemoApplication</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- 添加 maven-shade-plugin 插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
@@ -52,8 +20,8 @@
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>work.slhaf.demo.AgentDemoApplication</mainClass>
<transformer>
<mainClass>work.slhaf.partner.Main</mainClass>
</transformer>
</transformers>
</configuration>
@@ -61,7 +29,6 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
@@ -69,5 +36,9 @@
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -9,7 +9,7 @@
<version>0.5.0</version>
</parent>
<artifactId>Partner-Main</artifactId>
<artifactId>Partner-Core</artifactId>
<dependencies>
<dependency>
@@ -19,19 +19,9 @@
</dependency>
<dependency>
<groupId>work.slhaf</groupId>
<artifactId>Partner-Api</artifactId>
<artifactId>Partner-Framework</artifactId>
<version>0.5.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>1.10.2</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-test</artifactId>
<version>1.10.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.nd4j/nd4j-api -->
<dependency>
<groupId>org.nd4j</groupId>
@@ -111,10 +101,37 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<skipTests>true</skipTests>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
<configuration>
<jvmTarget>${maven.compiler.target}</jvmTarget>
</configuration>
</plugin>
</plugins>

Some files were not shown because too many files have changed in this diff Show More