devsquad 3.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- devsquad-3.6.0.dist-info/METADATA +944 -0
- devsquad-3.6.0.dist-info/RECORD +95 -0
- devsquad-3.6.0.dist-info/WHEEL +5 -0
- devsquad-3.6.0.dist-info/entry_points.txt +2 -0
- devsquad-3.6.0.dist-info/licenses/LICENSE +21 -0
- devsquad-3.6.0.dist-info/top_level.txt +2 -0
- scripts/__init__.py +0 -0
- scripts/ai_semantic_matcher.py +512 -0
- scripts/alert_manager.py +505 -0
- scripts/api/__init__.py +43 -0
- scripts/api/models.py +386 -0
- scripts/api/routes/__init__.py +20 -0
- scripts/api/routes/dispatch.py +348 -0
- scripts/api/routes/lifecycle.py +330 -0
- scripts/api/routes/metrics_gates.py +347 -0
- scripts/api_server.py +318 -0
- scripts/auth.py +451 -0
- scripts/cli/__init__.py +1 -0
- scripts/cli/cli_visual.py +642 -0
- scripts/cli.py +1094 -0
- scripts/collaboration/__init__.py +212 -0
- scripts/collaboration/_version.py +1 -0
- scripts/collaboration/agent_briefing.py +656 -0
- scripts/collaboration/ai_semantic_matcher.py +260 -0
- scripts/collaboration/anchor_checker.py +281 -0
- scripts/collaboration/anti_rationalization.py +470 -0
- scripts/collaboration/async_integration_example.py +255 -0
- scripts/collaboration/batch_scheduler.py +149 -0
- scripts/collaboration/checkpoint_manager.py +561 -0
- scripts/collaboration/ci_feedback_adapter.py +351 -0
- scripts/collaboration/code_map_generator.py +247 -0
- scripts/collaboration/concern_pack_loader.py +352 -0
- scripts/collaboration/confidence_score.py +496 -0
- scripts/collaboration/config_loader.py +188 -0
- scripts/collaboration/consensus.py +244 -0
- scripts/collaboration/context_compressor.py +533 -0
- scripts/collaboration/coordinator.py +668 -0
- scripts/collaboration/dispatcher.py +1636 -0
- scripts/collaboration/dual_layer_context.py +128 -0
- scripts/collaboration/enhanced_worker.py +539 -0
- scripts/collaboration/feature_usage_tracker.py +206 -0
- scripts/collaboration/five_axis_consensus.py +334 -0
- scripts/collaboration/input_validator.py +401 -0
- scripts/collaboration/integration_example.py +287 -0
- scripts/collaboration/intent_workflow_mapper.py +350 -0
- scripts/collaboration/language_parsers.py +269 -0
- scripts/collaboration/lifecycle_protocol.py +1446 -0
- scripts/collaboration/llm_backend.py +453 -0
- scripts/collaboration/llm_cache.py +448 -0
- scripts/collaboration/llm_cache_async.py +347 -0
- scripts/collaboration/llm_retry.py +387 -0
- scripts/collaboration/llm_retry_async.py +389 -0
- scripts/collaboration/mce_adapter.py +597 -0
- scripts/collaboration/memory_bridge.py +1607 -0
- scripts/collaboration/models.py +537 -0
- scripts/collaboration/null_providers.py +297 -0
- scripts/collaboration/operation_classifier.py +289 -0
- scripts/collaboration/output_slicer.py +225 -0
- scripts/collaboration/performance_monitor.py +462 -0
- scripts/collaboration/permission_guard.py +865 -0
- scripts/collaboration/prompt_assembler.py +756 -0
- scripts/collaboration/prompt_variant_generator.py +483 -0
- scripts/collaboration/protocols.py +267 -0
- scripts/collaboration/report_formatter.py +352 -0
- scripts/collaboration/retrospective.py +279 -0
- scripts/collaboration/role_matcher.py +92 -0
- scripts/collaboration/role_template_market.py +352 -0
- scripts/collaboration/rule_collector.py +678 -0
- scripts/collaboration/scratchpad.py +346 -0
- scripts/collaboration/skill_registry.py +151 -0
- scripts/collaboration/skillifier.py +878 -0
- scripts/collaboration/standardized_role_template.py +317 -0
- scripts/collaboration/task_completion_checker.py +237 -0
- scripts/collaboration/test_quality_guard.py +695 -0
- scripts/collaboration/unified_gate_engine.py +598 -0
- scripts/collaboration/usage_tracker.py +309 -0
- scripts/collaboration/user_friendly_error.py +176 -0
- scripts/collaboration/verification_gate.py +312 -0
- scripts/collaboration/warmup_manager.py +635 -0
- scripts/collaboration/worker.py +513 -0
- scripts/collaboration/workflow_engine.py +684 -0
- scripts/dashboard.py +1088 -0
- scripts/generate_benchmark_report.py +786 -0
- scripts/history_manager.py +604 -0
- scripts/mcp_server.py +289 -0
- skills/__init__.py +32 -0
- skills/dispatch/handler.py +52 -0
- skills/intent/handler.py +59 -0
- skills/registry.py +67 -0
- skills/retrospective/__init__.py +0 -0
- skills/retrospective/handler.py +125 -0
- skills/review/handler.py +356 -0
- skills/security/handler.py +454 -0
- skills/test/__init__.py +0 -0
- skills/test/handler.py +78 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
devsquad-3.6.0.dist-info/licenses/LICENSE,sha256=Nx7tqYDkj_hkw6VQEEBkqOscdLFzt4BCaRu8xqOzCuU,1067
|
|
2
|
+
scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
scripts/ai_semantic_matcher.py,sha256=BxTPazglCSz52BRqbf2us2_z8yvV-Gy6OqDAMwH2v6A,17242
|
|
4
|
+
scripts/alert_manager.py,sha256=T0iAo128_JkHypHFFrzBFRRw747lmRxcDVn8RBS4XoI,16613
|
|
5
|
+
scripts/api_server.py,sha256=S4TMICnVG-QxsBy581wEwUpUU9bUqD2wDBvzTgGyfm8,10064
|
|
6
|
+
scripts/auth.py,sha256=ILGg2V8lOp-hw_cwsA7-5S5yynA5ZxyCQYYrOtjrZfg,14352
|
|
7
|
+
scripts/cli.py,sha256=Oi_lmmr5UzbwP6m5y8B5ZoDARUahxUFEfd7YQ_PBce4,48328
|
|
8
|
+
scripts/dashboard.py,sha256=vtdw6EytkqFz0iFQ6v07686HvA--sLB1gy0RQOVu-48,35539
|
|
9
|
+
scripts/generate_benchmark_report.py,sha256=k1OscgXkyf690GjDDuywUGo83DMF3btYs2Z44qdoHew,29191
|
|
10
|
+
scripts/history_manager.py,sha256=X3kqA2YJy1M2cLA34yHk5fKtwkhPonveljicgBlujzE,20504
|
|
11
|
+
scripts/mcp_server.py,sha256=NEL6NbIEWyYp2z8BFrB-iBRPz5RQi82Yjr-lw1K2SpM,10690
|
|
12
|
+
scripts/api/__init__.py,sha256=hDZnDkeQcFmpWYMgNNZE4Mlox9DYBD9Ze0o_tOJ2cbk,926
|
|
13
|
+
scripts/api/models.py,sha256=p1VTLYT9CHBVrgs3gXGrBlgOW9oILdwuSdMUp9BdhZ4,17955
|
|
14
|
+
scripts/api/routes/__init__.py,sha256=IDOWCj3p2t4eNibr9cH1nYV1PnP0LwufGJMSoVrz6OM,539
|
|
15
|
+
scripts/api/routes/dispatch.py,sha256=jnfRtqDoBfFD93cYYrgry5WwcmwagjWt3cIvJv-N3fk,11177
|
|
16
|
+
scripts/api/routes/lifecycle.py,sha256=yOKuFyfIRFF4WLU-nxq_EwIP7EaM86mmsBUl4w6E38M,11568
|
|
17
|
+
scripts/api/routes/metrics_gates.py,sha256=5e3ysJV9bx_WSDpt4ySqGYcLUabdT4egZ-y8SOqoxA4,11368
|
|
18
|
+
scripts/cli/__init__.py,sha256=ceO6s2CvYTDDSggDKLTdgVWqQqcNNM-F55Bmbn-JMb4,14
|
|
19
|
+
scripts/cli/cli_visual.py,sha256=pqyDIemY0t8u57dg-GR5LGTOnXEJ9BXMCWr33pEAsPk,21614
|
|
20
|
+
scripts/collaboration/__init__.py,sha256=jL3ppFqE_fIGdpwGFyW1w-rEdpSjZ23lbTJ-LAuAOzU,5922
|
|
21
|
+
scripts/collaboration/_version.py,sha256=pnBAJI_5J7ByFo6sxUkzCfK3L9wcGJP7yeF7OJLugqk,22
|
|
22
|
+
scripts/collaboration/agent_briefing.py,sha256=BtvCX21JsipfRiJ6QUbBBDcTA51W7I0MdEprx3IF8LA,24065
|
|
23
|
+
scripts/collaboration/ai_semantic_matcher.py,sha256=yt7t9GraRAGLYh68JyJzpV1--mphCX_CVb2bsZblbyA,10351
|
|
24
|
+
scripts/collaboration/anchor_checker.py,sha256=YwDqepTQG-8EY0QhNM2deO1LwnWWYnoPpUbx7jh_3SI,10100
|
|
25
|
+
scripts/collaboration/anti_rationalization.py,sha256=29btejWWgx-zsQWr5cgy7_0YLljeAES4JyYzRNcefjQ,17796
|
|
26
|
+
scripts/collaboration/async_integration_example.py,sha256=lwHkA54zY8-C-EyDxJENeQ7lTZ2aqvt6IrLMDG3SUGY,7959
|
|
27
|
+
scripts/collaboration/batch_scheduler.py,sha256=IPbj6y_8x6qgXzsh0L4wtqebXqOw0oDQANWeC4ThUIU,4831
|
|
28
|
+
scripts/collaboration/checkpoint_manager.py,sha256=X9n1PP-2KVW8IO8dRkRBW8YPRcJZWa4n9OGmA0J3o1A,21666
|
|
29
|
+
scripts/collaboration/ci_feedback_adapter.py,sha256=iYpSifV3wbtPBpfjmxJdQ1IAML_XGUuItiEIfDUdIi4,12159
|
|
30
|
+
scripts/collaboration/code_map_generator.py,sha256=0srNkAhBkMVngaR7sniYXtZppgBvWiuBMErP1y1Gu0o,10063
|
|
31
|
+
scripts/collaboration/concern_pack_loader.py,sha256=zpRmbH4jhYbvGVktGyxGp7DPxO31X26cIuEkxLhD33Y,11720
|
|
32
|
+
scripts/collaboration/confidence_score.py,sha256=_aX3U_5ny5_YQVaUgB5vhWL7XUvQNpR7sG2kCriRpgU,16965
|
|
33
|
+
scripts/collaboration/config_loader.py,sha256=4eZ2iZ0NyHBTrqmdUWPvSfZG7d7R8iv5J5aTWuDfDOA,6920
|
|
34
|
+
scripts/collaboration/consensus.py,sha256=kpSg_u_Xqk2RobhJjhV846nGYjAd-9b9iW6z8XCsMr4,8814
|
|
35
|
+
scripts/collaboration/context_compressor.py,sha256=S4SY291ix9-8AOB3cFDawCcYvKKtzePepwep0rQ8Stg,20824
|
|
36
|
+
scripts/collaboration/coordinator.py,sha256=A8zZPAOOcKIk12DEx0Yt-vq3C185YGMXC5IyHN8hZMc,26718
|
|
37
|
+
scripts/collaboration/dispatcher.py,sha256=OWbfT00vs9pK3HuTPRRbR6OhcIgMG2UszeYfOOuRY8M,70722
|
|
38
|
+
scripts/collaboration/dual_layer_context.py,sha256=P0ZI4yd6WnPkApQEATAdqqjKQNdmEqq8Ia-sXy68Q9w,4912
|
|
39
|
+
scripts/collaboration/enhanced_worker.py,sha256=y4Iv494jk-10AG90g_gb0uaAThWN8m8a6zyPzjvKJwI,19291
|
|
40
|
+
scripts/collaboration/feature_usage_tracker.py,sha256=og01psDkUV3MoGa-wYKNhpzmSqTg6NKkt24uT0_o1zk,7315
|
|
41
|
+
scripts/collaboration/five_axis_consensus.py,sha256=klfzVMhHEy64Bk2CjbMxUUGEa9QQ8b5HuBTPyyJ0oU8,11203
|
|
42
|
+
scripts/collaboration/input_validator.py,sha256=0QWeH6hKoPOa3dq6uTU17aIVihF-h6k6dvanQZr0UtI,12724
|
|
43
|
+
scripts/collaboration/integration_example.py,sha256=TLKuBbnGq3kwpyACvxFtJuXB5em6uvqUeqvEnKX2cRA,8500
|
|
44
|
+
scripts/collaboration/intent_workflow_mapper.py,sha256=LEeWJTXJkSj5t768EPV3WdgCztqMnL1T2D8y93GgfQo,13181
|
|
45
|
+
scripts/collaboration/language_parsers.py,sha256=1XY-64QBctufmhiw3rCOgkXxIMV84jg9R2ucw2JPJsg,9383
|
|
46
|
+
scripts/collaboration/lifecycle_protocol.py,sha256=E1gLZ0wC6jDfzA3hrxTwdBaM_Ps56KltiHwuhiKwiCM,55193
|
|
47
|
+
scripts/collaboration/llm_backend.py,sha256=U04THXrfiHpizNAdAXnRh8wo1UO3q25QL_2nsPUKtJ8,16548
|
|
48
|
+
scripts/collaboration/llm_cache.py,sha256=wv4u7TU-6_NxsRiygqm4OAxVlOxhHKUhj6IirMQ-UDM,14012
|
|
49
|
+
scripts/collaboration/llm_cache_async.py,sha256=4qk_C6wwgRu_ltxYIcKf61LgSsOt24upbeb-FoVyEzE,11445
|
|
50
|
+
scripts/collaboration/llm_retry.py,sha256=Xoi72wEntbmSJ0a0Mp9R_N26kPOYPFd1pa5LFAuZdXI,12480
|
|
51
|
+
scripts/collaboration/llm_retry_async.py,sha256=hK-DFTTalZ8xsMMf5k4MZku-z7xXTgtKv8FE3uEryCo,13394
|
|
52
|
+
scripts/collaboration/mce_adapter.py,sha256=0DeaPiFO6724Ie2Nukk9bl-7HlcgKs0Gq_6vk5NYVRI,22913
|
|
53
|
+
scripts/collaboration/memory_bridge.py,sha256=g5ylSrzm8liPc0Kej2oT5rc9n5ecvIpQYFoOntihgaA,63098
|
|
54
|
+
scripts/collaboration/models.py,sha256=qTVyRgP76oijjYccKApbEBmBqhOGU7J0vi1CZxlSMlY,18912
|
|
55
|
+
scripts/collaboration/null_providers.py,sha256=CNh04uDMphUliEx0F6YVduATmBRkMjdEIKKY1q2ZHPI,9951
|
|
56
|
+
scripts/collaboration/operation_classifier.py,sha256=HqGVpYI6eJvTAMdJKrxFDZ-Hkh_uJPhTitLn-zPYu3o,10251
|
|
57
|
+
scripts/collaboration/output_slicer.py,sha256=ka_Qcr5rjahmeu0k5vALcICI_K91x5jvfki6x6_28oE,7148
|
|
58
|
+
scripts/collaboration/performance_monitor.py,sha256=3mGkWwaMA1ezhz1wqeab5ExDEgox_47bAW1ZG9nBrhw,15156
|
|
59
|
+
scripts/collaboration/permission_guard.py,sha256=oJZWCNLLCEZ_SqxfhDhOvTH0dbKVGn9F36cD746N7NM,35234
|
|
60
|
+
scripts/collaboration/prompt_assembler.py,sha256=MGAGA3tv9Bdedcbb51PA7XRiN6ablFa33zrBgF9wuOY,32016
|
|
61
|
+
scripts/collaboration/prompt_variant_generator.py,sha256=GbYZbVfvGJ2Yv4VWXbpv3nzR46ChMDm4dxke9IzSHmE,16800
|
|
62
|
+
scripts/collaboration/protocols.py,sha256=10tCUPaC53peJLHmfXWPELANecEkzjtAx9cX1paj8V0,7772
|
|
63
|
+
scripts/collaboration/report_formatter.py,sha256=mDDTz-ZroKdGsXbh3Qq6Z70oWcI-fJq1_ZGeRp3anpM,14976
|
|
64
|
+
scripts/collaboration/retrospective.py,sha256=FZIMeHY6tUZQ_kDj8jscr-NP70YMbsRXDtvEMkKAv2c,10782
|
|
65
|
+
scripts/collaboration/role_matcher.py,sha256=edS7wtq3o1ZYDV4AvjDRFJlXLRYYBeKDJsrtSjba7P8,3265
|
|
66
|
+
scripts/collaboration/role_template_market.py,sha256=D6q0PyWbpYZrIHFViBaSQpdyRVUPWcrEoWKkIIJUaT0,12065
|
|
67
|
+
scripts/collaboration/rule_collector.py,sha256=QnAsOrh4SLn1HtfGnONOFAt-eDDWCmiE6iV1zKfAr9E,28170
|
|
68
|
+
scripts/collaboration/scratchpad.py,sha256=aQxD56KeGz2QPNoOYNTByYp_ge2gTYMLxSwo9F9_g20,13239
|
|
69
|
+
scripts/collaboration/skill_registry.py,sha256=jxmWnQ5-MVnDB3k7TjF5fz0yqu5I01iKAGoZDixZPak,5759
|
|
70
|
+
scripts/collaboration/skillifier.py,sha256=2IysxrloDkN9V6ZAUeXGB8r8DoFl3QFDGuBOWAEh_Oc,34544
|
|
71
|
+
scripts/collaboration/standardized_role_template.py,sha256=01NB3SRaiZrx6dK-vHIIQDpOpCzs1dPUMRbsZvayCmg,12482
|
|
72
|
+
scripts/collaboration/task_completion_checker.py,sha256=W1G6Ai0O5Hi8kSOOTCbNqbDKpl7J2jv32aQm--oJG-g,8797
|
|
73
|
+
scripts/collaboration/test_quality_guard.py,sha256=0kQmEahTKPoAE5elwJpipKzEc_Im4ePkw3lY9EuPPOI,27240
|
|
74
|
+
scripts/collaboration/unified_gate_engine.py,sha256=Jreycht9bMwmSGA5KI9ck-4pwOxXyvDZWGX7yZl6TeA,20743
|
|
75
|
+
scripts/collaboration/usage_tracker.py,sha256=Jz01Nq1rn8TIAJeWttowP3m_x-WbFE7vES9UpMISJqw,10161
|
|
76
|
+
scripts/collaboration/user_friendly_error.py,sha256=RPKDdx9iqx3HB9gLbS1ftkUDWWClrURJlO517xaQ2yU,6822
|
|
77
|
+
scripts/collaboration/verification_gate.py,sha256=0hVSQE_O3UWZJ3NEMGs-R7IhrHld39Bno-vcTXgjcUs,10675
|
|
78
|
+
scripts/collaboration/warmup_manager.py,sha256=MTM1Ny-dvXqxPTrAspToKobW9Ejhz3txCQARspzhMZg,22924
|
|
79
|
+
scripts/collaboration/worker.py,sha256=yJSLvgh-rrF5vXzVPcAkTU9s_uR9OHD9-sZFbV2Asnk,19054
|
|
80
|
+
scripts/collaboration/workflow_engine.py,sha256=HuyFe7zJCFSsHmyL9Aijrama4n3mwvt85y4awlaFehw,27168
|
|
81
|
+
skills/__init__.py,sha256=rMCK3-GkjvYe5vfL834daHjSPZHJCWit2Deq7XrEnQE,1250
|
|
82
|
+
skills/registry.py,sha256=ghZBXqBahez0B4IanaW99EyQ0SEpSXfew6jLGs8RYPA,2034
|
|
83
|
+
skills/dispatch/handler.py,sha256=GuEotcNnlK_ubvyjxQT8UzEDocr4CpsqUJI4Hv-8EVg,1824
|
|
84
|
+
skills/intent/handler.py,sha256=z3cELpXXHY0zgIm5JG5nfDsDYTTG-tSgbVOXWA1CpjY,2242
|
|
85
|
+
skills/retrospective/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
86
|
+
skills/retrospective/handler.py,sha256=CDgdwVFphk_4LQORbWTsFBS6tZDSFWdnQN29Ncwe5g8,5288
|
|
87
|
+
skills/review/handler.py,sha256=-OIy-M2V_f9IYXdNdt1GiuFo1N0WI46RRgLvS2KEf0g,13539
|
|
88
|
+
skills/security/handler.py,sha256=yAJGHSktFppPQHF0qCRLNuEDtIfR7OYPgBPz1XMx6Hw,17217
|
|
89
|
+
skills/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
90
|
+
skills/test/handler.py,sha256=imWEJtswp7aOWeQ1fupwbk5qyJNYS5lBvuyXvdoTWck,3310
|
|
91
|
+
devsquad-3.6.0.dist-info/METADATA,sha256=QRFK1sMIrsBKI3pm4UUool1q8QMM8lgNN1ywFQ8rP-Y,45435
|
|
92
|
+
devsquad-3.6.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
93
|
+
devsquad-3.6.0.dist-info/entry_points.txt,sha256=9h61tKPkQeHCn2jCkXSkhPU7iWrb7dhj9Tshg1YDwLk,46
|
|
94
|
+
devsquad-3.6.0.dist-info/top_level.txt,sha256=KmkXcHcHyHTs335-6-kswfgudjHF25nFPQIMILfMJWM,15
|
|
95
|
+
devsquad-3.6.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Weiransoft
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
scripts/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,512 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
AI 语义匹配器
|
|
5
|
+
|
|
6
|
+
⚠️ 已弃用:此模块为 V2 遗留,V3 请使用 scripts.collaboration.ai_semantic_matcher
|
|
7
|
+
|
|
8
|
+
基于大模型 AI 助手的语义理解能力,实现智能角色匹配。
|
|
9
|
+
|
|
10
|
+
核心功能:
|
|
11
|
+
1. 使用大模型理解任务需求的深层语义
|
|
12
|
+
2. 基于角色能力描述进行智能匹配
|
|
13
|
+
3. 提供匹配原因和置信度解释
|
|
14
|
+
4. 支持多轮对话优化匹配结果
|
|
15
|
+
|
|
16
|
+
技术优势:
|
|
17
|
+
- 超越简单文本相似度,理解语义关联
|
|
18
|
+
- 支持上下文感知的匹配
|
|
19
|
+
- 可解释的匹配结果
|
|
20
|
+
- 持续学习和优化
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
import json
|
|
25
|
+
from typing import Dict, List, Any, Optional, Tuple
|
|
26
|
+
from dataclasses import dataclass, field
|
|
27
|
+
from datetime import datetime
|
|
28
|
+
import hashlib
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class SemanticMatchResult:
|
|
33
|
+
"""语义匹配结果"""
|
|
34
|
+
role_id: str
|
|
35
|
+
role_name: str
|
|
36
|
+
confidence: float # 置信度 (0-1)
|
|
37
|
+
reasoning: str # 匹配推理过程
|
|
38
|
+
matched_capabilities: List[str] = field(default_factory=list)
|
|
39
|
+
relevance_score: float = 0.0 # 相关性评分
|
|
40
|
+
explanation: str = "" # 详细解释
|
|
41
|
+
metadata: Dict[str, Any] = field(default_factory=dict)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class AISemanticMatcher:
|
|
45
|
+
"""
|
|
46
|
+
AI 语义匹配器
|
|
47
|
+
|
|
48
|
+
利用大模型 AI 助手的语义理解能力,实现智能角色匹配。
|
|
49
|
+
|
|
50
|
+
工作原理:
|
|
51
|
+
1. 分析任务需求,提取关键语义信息
|
|
52
|
+
2. 理解角色能力和职责
|
|
53
|
+
3. 基于语义相似度进行匹配
|
|
54
|
+
4. 生成可解释的匹配结果
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
def __init__(self, ai_client: Any = None):
|
|
58
|
+
"""
|
|
59
|
+
初始化 AI 语义匹配器
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
ai_client: AI 客户端实例(如 Trae AI 助手)
|
|
63
|
+
"""
|
|
64
|
+
self.ai_client = ai_client
|
|
65
|
+
self.match_cache: Dict[str, SemanticMatchResult] = {}
|
|
66
|
+
self.match_history: List[Dict[str, Any]] = []
|
|
67
|
+
|
|
68
|
+
# 匹配提示词模板
|
|
69
|
+
self.match_prompt_template = """
|
|
70
|
+
你是一个智能角色匹配专家。请分析以下任务需求,并匹配最适合的角色。
|
|
71
|
+
|
|
72
|
+
## 任务需求
|
|
73
|
+
**标题**: {task_title}
|
|
74
|
+
**描述**: {task_description}
|
|
75
|
+
**所需能力**: {required_capabilities}
|
|
76
|
+
**偏好技能**: {preferred_skills}
|
|
77
|
+
|
|
78
|
+
## 可用角色
|
|
79
|
+
{role_descriptions}
|
|
80
|
+
|
|
81
|
+
## 匹配要求
|
|
82
|
+
1. 分析任务的核心需求和关键能力要求
|
|
83
|
+
2. 评估每个角色与任务的匹配度
|
|
84
|
+
3. 考虑角色的专业能力和经验
|
|
85
|
+
4. 提供匹配原因和置信度评分
|
|
86
|
+
|
|
87
|
+
请以 JSON 格式返回匹配结果:
|
|
88
|
+
{{
|
|
89
|
+
"matches": [
|
|
90
|
+
{{
|
|
91
|
+
"role_id": "角色 ID",
|
|
92
|
+
"role_name": "角色名称",
|
|
93
|
+
"confidence": 0.0-1.0,
|
|
94
|
+
"reasoning": "匹配推理过程",
|
|
95
|
+
"matched_capabilities": ["匹配的能力列表"],
|
|
96
|
+
"relevance_score": 0.0-1.0,
|
|
97
|
+
"explanation": "详细解释"
|
|
98
|
+
}}
|
|
99
|
+
],
|
|
100
|
+
"best_match": "最佳匹配角色 ID",
|
|
101
|
+
"analysis": "整体分析"
|
|
102
|
+
}}
|
|
103
|
+
"""
|
|
104
|
+
|
|
105
|
+
def match(self,
|
|
106
|
+
task_title: str,
|
|
107
|
+
task_description: str,
|
|
108
|
+
roles: List[Dict[str, Any]],
|
|
109
|
+
required_capabilities: List[str] = None,
|
|
110
|
+
preferred_skills: List[str] = None,
|
|
111
|
+
use_cache: bool = True) -> List[SemanticMatchResult]:
|
|
112
|
+
"""
|
|
113
|
+
使用 AI 进行智能角色匹配
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
task_title: 任务标题
|
|
117
|
+
task_description: 任务描述
|
|
118
|
+
roles: 角色列表,每个角色包含 id, name, description, capabilities
|
|
119
|
+
required_capabilities: 必需能力列表
|
|
120
|
+
preferred_skills: 偏好技能列表
|
|
121
|
+
use_cache: 是否使用缓存
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
List[SemanticMatchResult]: 匹配结果列表
|
|
125
|
+
"""
|
|
126
|
+
# 生成缓存键
|
|
127
|
+
cache_key = self._generate_cache_key(
|
|
128
|
+
task_title, task_description, roles
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# 检查缓存
|
|
132
|
+
if use_cache and cache_key in self.match_cache:
|
|
133
|
+
print(f"✅ 使用缓存的匹配结果")
|
|
134
|
+
return [self.match_cache[cache_key]]
|
|
135
|
+
|
|
136
|
+
# 构建角色描述
|
|
137
|
+
role_descriptions = self._build_role_descriptions(roles)
|
|
138
|
+
|
|
139
|
+
# 构建提示词
|
|
140
|
+
prompt = self.match_prompt_template.format(
|
|
141
|
+
task_title=task_title,
|
|
142
|
+
task_description=task_description,
|
|
143
|
+
required_capabilities=required_capabilities or [],
|
|
144
|
+
preferred_skills=preferred_skills or [],
|
|
145
|
+
role_descriptions=role_descriptions
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# 调用 AI 助手
|
|
149
|
+
try:
|
|
150
|
+
ai_response = self._call_ai_assistant(prompt)
|
|
151
|
+
|
|
152
|
+
# 解析 AI 响应
|
|
153
|
+
results = self._parse_ai_response(ai_response, roles)
|
|
154
|
+
|
|
155
|
+
# 缓存结果
|
|
156
|
+
if results and use_cache:
|
|
157
|
+
self.match_cache[cache_key] = results[0]
|
|
158
|
+
|
|
159
|
+
# 记录历史
|
|
160
|
+
self._record_match(task_title, roles, results)
|
|
161
|
+
|
|
162
|
+
return results
|
|
163
|
+
|
|
164
|
+
except Exception as e:
|
|
165
|
+
print(f"❌ AI 匹配失败:{e}")
|
|
166
|
+
# 降级到传统匹配
|
|
167
|
+
return self._fallback_match(task_description, roles)
|
|
168
|
+
|
|
169
|
+
def _build_role_descriptions(self, roles: List[Dict[str, Any]]) -> str:
|
|
170
|
+
"""构建角色描述文本"""
|
|
171
|
+
descriptions = []
|
|
172
|
+
|
|
173
|
+
for i, role in enumerate(roles, 1):
|
|
174
|
+
desc = f"""
|
|
175
|
+
{i}. **{role.get('name', 'Unknown')}** ({role.get('id', 'unknown')})
|
|
176
|
+
- 职责:{role.get('description', '')}
|
|
177
|
+
- 能力:{', '.join(role.get('capabilities', []))}
|
|
178
|
+
- 技能:{', '.join(role.get('skills', []))}
|
|
179
|
+
"""
|
|
180
|
+
descriptions.append(desc)
|
|
181
|
+
|
|
182
|
+
return "\n".join(descriptions)
|
|
183
|
+
|
|
184
|
+
def _call_ai_assistant(self, prompt: str) -> str:
|
|
185
|
+
"""
|
|
186
|
+
调用 AI 助手
|
|
187
|
+
|
|
188
|
+
Args:
|
|
189
|
+
prompt: 提示词
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
str: AI 响应
|
|
193
|
+
"""
|
|
194
|
+
# 如果提供了 AI 客户端,使用真实 AI 调用
|
|
195
|
+
if self.ai_client:
|
|
196
|
+
try:
|
|
197
|
+
response = self.ai_client.complete(prompt)
|
|
198
|
+
return response
|
|
199
|
+
except Exception as e:
|
|
200
|
+
print(f"⚠️ AI 调用失败,使用模拟响应:{e}")
|
|
201
|
+
|
|
202
|
+
# 模拟 AI 响应(用于测试和降级)
|
|
203
|
+
return self._simulate_ai_response(prompt)
|
|
204
|
+
|
|
205
|
+
def _simulate_ai_response(self, prompt: str) -> str:
|
|
206
|
+
"""
|
|
207
|
+
模拟 AI 响应
|
|
208
|
+
|
|
209
|
+
在实际 AI 客户端不可用时使用
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
prompt: 提示词
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
str: 模拟的 AI 响应
|
|
216
|
+
"""
|
|
217
|
+
# 基于关键词的简单规则匹配
|
|
218
|
+
prompt_lower = prompt.lower()
|
|
219
|
+
|
|
220
|
+
# 检测角色相关关键词
|
|
221
|
+
role_keywords = {
|
|
222
|
+
'architect': ['架构', '设计', '系统', '技术选型', '模块', '接口'],
|
|
223
|
+
'product-manager': ['需求', '产品', '用户', '功能', 'prd'],
|
|
224
|
+
'developer': ['开发', '实现', '代码', '功能', '编程'],
|
|
225
|
+
'tester': ['测试', '质量', 'bug', '用例', '验证'],
|
|
226
|
+
'ui-designer': ['ui', '设计', '界面', '交互', '视觉', '原型'],
|
|
227
|
+
'devops': ['部署', '运维', 'ci/cd', '监控', '容器']
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
matches = []
|
|
231
|
+
for role_id, keywords in role_keywords.items():
|
|
232
|
+
score = sum(1 for kw in keywords if kw in prompt_lower)
|
|
233
|
+
if score > 0:
|
|
234
|
+
matches.append({
|
|
235
|
+
'role_id': role_id,
|
|
236
|
+
'score': score
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
# 排序
|
|
240
|
+
matches.sort(key=lambda x: x['score'], reverse=True)
|
|
241
|
+
|
|
242
|
+
# 构建响应
|
|
243
|
+
if matches:
|
|
244
|
+
best_match = matches[0]
|
|
245
|
+
response = {
|
|
246
|
+
"matches": [
|
|
247
|
+
{
|
|
248
|
+
"role_id": best_match['role_id'],
|
|
249
|
+
"role_name": best_match['role_id'].replace('-', ' ').title(),
|
|
250
|
+
"confidence": min(0.5 + best_match['score'] * 0.1, 0.95),
|
|
251
|
+
"reasoning": f"基于关键词匹配,任务描述中包含 {best_match['score']} 个相关关键词",
|
|
252
|
+
"matched_capabilities": ["相关能力"],
|
|
253
|
+
"relevance_score": best_match['score'] / 10.0,
|
|
254
|
+
"explanation": "任务需求与该角色职责高度相关"
|
|
255
|
+
}
|
|
256
|
+
],
|
|
257
|
+
"best_match": best_match['role_id'],
|
|
258
|
+
"analysis": f"通过分析任务描述,推荐 {best_match['role_id']} 角色"
|
|
259
|
+
}
|
|
260
|
+
else:
|
|
261
|
+
response = {
|
|
262
|
+
"matches": [],
|
|
263
|
+
"best_match": None,
|
|
264
|
+
"analysis": "未找到明确匹配的角色"
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return json.dumps(response, ensure_ascii=False)
|
|
268
|
+
|
|
269
|
+
def _parse_ai_response(self, response: str,
|
|
270
|
+
roles: List[Dict[str, Any]]) -> List[SemanticMatchResult]:
|
|
271
|
+
"""
|
|
272
|
+
解析 AI 响应
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
response: AI 响应
|
|
276
|
+
roles: 角色列表
|
|
277
|
+
|
|
278
|
+
Returns:
|
|
279
|
+
List[SemanticMatchResult]: 匹配结果
|
|
280
|
+
"""
|
|
281
|
+
try:
|
|
282
|
+
# 尝试解析 JSON
|
|
283
|
+
if isinstance(response, str):
|
|
284
|
+
data = json.loads(response)
|
|
285
|
+
else:
|
|
286
|
+
data = response
|
|
287
|
+
|
|
288
|
+
results = []
|
|
289
|
+
for match_data in data.get('matches', []):
|
|
290
|
+
result = SemanticMatchResult(
|
|
291
|
+
role_id=match_data.get('role_id', ''),
|
|
292
|
+
role_name=match_data.get('role_name', ''),
|
|
293
|
+
confidence=float(match_data.get('confidence', 0.0)),
|
|
294
|
+
reasoning=match_data.get('reasoning', ''),
|
|
295
|
+
matched_capabilities=match_data.get('matched_capabilities', []),
|
|
296
|
+
relevance_score=float(match_data.get('relevance_score', 0.0)),
|
|
297
|
+
explanation=match_data.get('explanation', ''),
|
|
298
|
+
metadata={
|
|
299
|
+
'best_match': data.get('best_match'),
|
|
300
|
+
'analysis': data.get('analysis')
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
results.append(result)
|
|
304
|
+
|
|
305
|
+
# 按置信度排序
|
|
306
|
+
results.sort(key=lambda r: r.confidence, reverse=True)
|
|
307
|
+
|
|
308
|
+
return results
|
|
309
|
+
|
|
310
|
+
except Exception as e:
|
|
311
|
+
print(f"❌ 解析 AI 响应失败:{e}")
|
|
312
|
+
return []
|
|
313
|
+
|
|
314
|
+
def _fallback_match(self, task_description: str,
|
|
315
|
+
roles: List[Dict[str, Any]]) -> List[SemanticMatchResult]:
|
|
316
|
+
"""
|
|
317
|
+
降级匹配策略
|
|
318
|
+
|
|
319
|
+
当 AI 匹配失败时使用
|
|
320
|
+
|
|
321
|
+
Args:
|
|
322
|
+
task_description: 任务描述
|
|
323
|
+
roles: 角色列表
|
|
324
|
+
|
|
325
|
+
Returns:
|
|
326
|
+
List[SemanticMatchResult]: 匹配结果
|
|
327
|
+
"""
|
|
328
|
+
print("⚠️ 使用降级匹配策略")
|
|
329
|
+
|
|
330
|
+
# 简单的关键词匹配
|
|
331
|
+
results = []
|
|
332
|
+
task_lower = task_description.lower()
|
|
333
|
+
|
|
334
|
+
for role in roles:
|
|
335
|
+
# 计算关键词匹配度
|
|
336
|
+
keywords = role.get('keywords', [])
|
|
337
|
+
match_count = sum(1 for kw in keywords if kw.lower() in task_lower)
|
|
338
|
+
|
|
339
|
+
if match_count > 0:
|
|
340
|
+
confidence = min(match_count / 5.0, 0.8)
|
|
341
|
+
result = SemanticMatchResult(
|
|
342
|
+
role_id=role.get('id', ''),
|
|
343
|
+
role_name=role.get('name', ''),
|
|
344
|
+
confidence=confidence,
|
|
345
|
+
reasoning=f"关键词匹配:{match_count} 个关键词匹配",
|
|
346
|
+
matched_capabilities=role.get('capabilities', [])[:3],
|
|
347
|
+
relevance_score=match_count / 10.0,
|
|
348
|
+
explanation="基于关键词的简单匹配"
|
|
349
|
+
)
|
|
350
|
+
results.append(result)
|
|
351
|
+
|
|
352
|
+
results.sort(key=lambda r: r.confidence, reverse=True)
|
|
353
|
+
return results
|
|
354
|
+
|
|
355
|
+
def _generate_cache_key(self, task_title: str,
|
|
356
|
+
task_description: str,
|
|
357
|
+
roles: List[Dict[str, Any]]) -> str:
|
|
358
|
+
"""生成缓存键"""
|
|
359
|
+
content = f"{task_title}|{task_description}|{len(roles)}"
|
|
360
|
+
return hashlib.md5(content.encode('utf-8')).hexdigest()
|
|
361
|
+
|
|
362
|
+
def _record_match(self, task_title: str,
|
|
363
|
+
roles: List[Dict[str, Any]],
|
|
364
|
+
results: List[SemanticMatchResult]):
|
|
365
|
+
"""记录匹配历史"""
|
|
366
|
+
record = {
|
|
367
|
+
'task_title': task_title,
|
|
368
|
+
'timestamp': datetime.now().isoformat(),
|
|
369
|
+
'roles_count': len(roles),
|
|
370
|
+
'results': [
|
|
371
|
+
{
|
|
372
|
+
'role_id': r.role_id,
|
|
373
|
+
'confidence': r.confidence,
|
|
374
|
+
'reasoning': r.reasoning
|
|
375
|
+
} for r in results
|
|
376
|
+
]
|
|
377
|
+
}
|
|
378
|
+
self.match_history.append(record)
|
|
379
|
+
|
|
380
|
+
def get_match_history(self, limit: int = 10) -> List[Dict]:
|
|
381
|
+
"""获取匹配历史"""
|
|
382
|
+
return self.match_history[-limit:]
|
|
383
|
+
|
|
384
|
+
def clear_cache(self):
|
|
385
|
+
"""清除缓存"""
|
|
386
|
+
self.match_cache.clear()
|
|
387
|
+
print("✅ 缓存已清除")
|
|
388
|
+
|
|
389
|
+
def explain_match(self, result: SemanticMatchResult) -> str:
|
|
390
|
+
"""
|
|
391
|
+
解释匹配结果
|
|
392
|
+
|
|
393
|
+
Args:
|
|
394
|
+
result: 匹配结果
|
|
395
|
+
|
|
396
|
+
Returns:
|
|
397
|
+
str: 解释文本
|
|
398
|
+
"""
|
|
399
|
+
explanation = f"""
|
|
400
|
+
🎯 匹配结果:{result.role_name} ({result.role_id})
|
|
401
|
+
置信度:{result.confidence:.1%}
|
|
402
|
+
相关性:{result.relevance_score:.1%}
|
|
403
|
+
|
|
404
|
+
匹配原因:
|
|
405
|
+
{result.reasoning}
|
|
406
|
+
|
|
407
|
+
详细说明:
|
|
408
|
+
{result.explanation}
|
|
409
|
+
|
|
410
|
+
匹配的能力:
|
|
411
|
+
{', '.join(result.matched_capabilities) if result.matched_capabilities else '无'}
|
|
412
|
+
"""
|
|
413
|
+
return explanation.strip()
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def main():
|
|
417
|
+
"""示例用法"""
|
|
418
|
+
# 创建匹配器
|
|
419
|
+
matcher = AISemanticMatcher()
|
|
420
|
+
|
|
421
|
+
# 定义角色
|
|
422
|
+
roles = [
|
|
423
|
+
{
|
|
424
|
+
'id': 'architect',
|
|
425
|
+
'name': '架构师',
|
|
426
|
+
'description': '负责系统架构设计和技术选型',
|
|
427
|
+
'capabilities': ['系统架构设计', '技术选型', '架构评审'],
|
|
428
|
+
'skills': ['架构设计', '系统设计'],
|
|
429
|
+
'keywords': ['架构', '设计', '系统', '选型']
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
'id': 'product-manager',
|
|
433
|
+
'name': '产品经理',
|
|
434
|
+
'description': '负责需求分析和产品规划',
|
|
435
|
+
'capabilities': ['需求分析', '产品规划', '用户研究'],
|
|
436
|
+
'skills': ['需求挖掘', '文档编写'],
|
|
437
|
+
'keywords': ['需求', '产品', '用户', '功能']
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
'id': 'developer',
|
|
441
|
+
'name': '开发工程师',
|
|
442
|
+
'description': '负责代码实现和功能开发',
|
|
443
|
+
'capabilities': ['代码实现', '功能开发', '代码优化'],
|
|
444
|
+
'skills': ['编程', '调试'],
|
|
445
|
+
'keywords': ['开发', '实现', '代码', '编程']
|
|
446
|
+
}
|
|
447
|
+
]
|
|
448
|
+
|
|
449
|
+
# 测试任务
|
|
450
|
+
tasks = [
|
|
451
|
+
{
|
|
452
|
+
'title': '设计微服务架构',
|
|
453
|
+
'description': '设计一个高可用的微服务架构,需要考虑服务拆分、通信机制和部署方案',
|
|
454
|
+
'required_capabilities': ['系统架构设计'],
|
|
455
|
+
'preferred_skills': ['架构设计']
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
'title': '实现用户管理功能',
|
|
459
|
+
'description': '实现用户注册、登录、权限管理等功能',
|
|
460
|
+
'required_capabilities': ['代码实现'],
|
|
461
|
+
'preferred_skills': ['编程']
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
'title': '分析用户需求',
|
|
465
|
+
'description': '分析用户需求,编写 PRD 文档,定义产品功能',
|
|
466
|
+
'required_capabilities': ['需求分析'],
|
|
467
|
+
'preferred_skills': ['文档编写']
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
|
|
471
|
+
# 执行匹配
|
|
472
|
+
print("="*80)
|
|
473
|
+
print("AI 语义匹配测试")
|
|
474
|
+
print("="*80)
|
|
475
|
+
|
|
476
|
+
for task in tasks:
|
|
477
|
+
print(f"\n📋 任务:{task['title']}")
|
|
478
|
+
print("-" * 80)
|
|
479
|
+
|
|
480
|
+
results = matcher.match(
|
|
481
|
+
task_title=task['title'],
|
|
482
|
+
task_description=task['description'],
|
|
483
|
+
roles=roles,
|
|
484
|
+
required_capabilities=task.get('required_capabilities'),
|
|
485
|
+
preferred_skills=task.get('preferred_skills')
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
if results:
|
|
489
|
+
best = results[0]
|
|
490
|
+
print(f"✅ 最佳匹配:{best.role_name} ({best.role_id})")
|
|
491
|
+
print(f" 置信度:{best.confidence:.1%}")
|
|
492
|
+
print(f" 相关性:{best.relevance_score:.1%}")
|
|
493
|
+
print(f" 原因:{best.reasoning}")
|
|
494
|
+
print(f"\n📝 详细说明:")
|
|
495
|
+
print(f" {best.explanation}")
|
|
496
|
+
else:
|
|
497
|
+
print("❌ 未找到匹配的角色")
|
|
498
|
+
|
|
499
|
+
# 显示匹配历史
|
|
500
|
+
print("\n" + "="*80)
|
|
501
|
+
print("匹配历史")
|
|
502
|
+
print("="*80)
|
|
503
|
+
history = matcher.get_match_history()
|
|
504
|
+
for record in history:
|
|
505
|
+
print(f"任务:{record['task_title']}")
|
|
506
|
+
print(f"时间:{record['timestamp']}")
|
|
507
|
+
print(f"结果:{len(record['results'])} 个匹配")
|
|
508
|
+
print()
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
if __name__ == "__main__":
|
|
512
|
+
main()
|