attune-ai 2.1.1__py3-none-any.whl → 2.1.2__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.
- attune/socratic_router.py +761 -0
- attune/vscode_bridge.py +7 -4
- {attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/METADATA +179 -16
- {attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/RECORD +9 -8
- {attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/WHEEL +0 -0
- {attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/entry_points.txt +0 -0
- {attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/licenses/LICENSE +0 -0
- {attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md +0 -0
- {attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,761 @@
|
|
|
1
|
+
"""Socratic Router - Intent-based workflow discovery.
|
|
2
|
+
|
|
3
|
+
Routes user's natural language goals to AskUserQuestion options.
|
|
4
|
+
Used by the /attune command for Socratic discovery flow.
|
|
5
|
+
|
|
6
|
+
Two modes:
|
|
7
|
+
1. Quick routing: Simple intent classification → AskUserQuestion options → skill invocation
|
|
8
|
+
2. Deep discovery: Full SocraticWorkflowBuilder session for complex agent generation
|
|
9
|
+
|
|
10
|
+
Flow (Quick):
|
|
11
|
+
1. User runs /attune
|
|
12
|
+
2. Claude asks "What are you trying to accomplish?"
|
|
13
|
+
3. User responds naturally
|
|
14
|
+
4. classify_intent() detects category
|
|
15
|
+
5. AskUserQuestion presents 2-4 relevant options
|
|
16
|
+
6. User selects → routes to skill
|
|
17
|
+
|
|
18
|
+
Flow (Deep):
|
|
19
|
+
1. User needs complex workflow generation
|
|
20
|
+
2. SocraticWorkflowBuilder creates multi-round Q&A session
|
|
21
|
+
3. form_to_ask_user_question() converts Forms to AskUserQuestion
|
|
22
|
+
4. Generates custom agent workflow
|
|
23
|
+
|
|
24
|
+
Copyright 2025 Smart-AI-Memory
|
|
25
|
+
Licensed under Fair Source License 0.9
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
from dataclasses import dataclass
|
|
31
|
+
from enum import Enum
|
|
32
|
+
from typing import TYPE_CHECKING, Any
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
from attune.socratic import Form, SocraticSession
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class IntentCategory(Enum):
|
|
39
|
+
"""High-level categories of user intent."""
|
|
40
|
+
|
|
41
|
+
FIX = "fix" # Debug, fix bugs, resolve errors
|
|
42
|
+
IMPROVE = "improve" # Refactor, optimize, clean up
|
|
43
|
+
VALIDATE = "validate" # Test, review, audit
|
|
44
|
+
SHIP = "ship" # Commit, PR, release
|
|
45
|
+
UNDERSTAND = "understand" # Explain, document, explore
|
|
46
|
+
UNKNOWN = "unknown" # Needs clarification
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass
|
|
50
|
+
class WorkflowOption:
|
|
51
|
+
"""A workflow option for AskUserQuestion.
|
|
52
|
+
|
|
53
|
+
Attributes:
|
|
54
|
+
label: Short label for the option (1-5 words)
|
|
55
|
+
description: What this option does
|
|
56
|
+
skill: The skill to invoke
|
|
57
|
+
args: Arguments for the skill
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
label: str
|
|
61
|
+
description: str
|
|
62
|
+
skill: str
|
|
63
|
+
args: str = ""
|
|
64
|
+
|
|
65
|
+
def to_ask_user_option(self) -> dict[str, str]:
|
|
66
|
+
"""Convert to AskUserQuestion option format."""
|
|
67
|
+
return {"label": self.label, "description": self.description}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass
|
|
71
|
+
class IntentClassification:
|
|
72
|
+
"""Result of classifying user intent.
|
|
73
|
+
|
|
74
|
+
Attributes:
|
|
75
|
+
category: Primary intent category
|
|
76
|
+
confidence: Confidence score (0-1)
|
|
77
|
+
keywords_matched: Keywords that triggered this classification
|
|
78
|
+
suggested_question: Question to ask via AskUserQuestion
|
|
79
|
+
options: Workflow options to present
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
category: IntentCategory
|
|
83
|
+
confidence: float
|
|
84
|
+
keywords_matched: list[str]
|
|
85
|
+
suggested_question: str
|
|
86
|
+
options: list[WorkflowOption]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# Intent detection patterns
|
|
90
|
+
INTENT_PATTERNS: dict[IntentCategory, dict[str, Any]] = {
|
|
91
|
+
IntentCategory.FIX: {
|
|
92
|
+
"keywords": [
|
|
93
|
+
"fix",
|
|
94
|
+
"bug",
|
|
95
|
+
"error",
|
|
96
|
+
"broken",
|
|
97
|
+
"crash",
|
|
98
|
+
"fail",
|
|
99
|
+
"issue",
|
|
100
|
+
"problem",
|
|
101
|
+
"debug",
|
|
102
|
+
"wrong",
|
|
103
|
+
"doesn't work",
|
|
104
|
+
"not working",
|
|
105
|
+
"exception",
|
|
106
|
+
"traceback",
|
|
107
|
+
],
|
|
108
|
+
"question": "What kind of issue are you dealing with?",
|
|
109
|
+
"options": [
|
|
110
|
+
WorkflowOption(
|
|
111
|
+
label="Debug an error",
|
|
112
|
+
description="Investigate exceptions, trace execution, find root cause",
|
|
113
|
+
skill="dev",
|
|
114
|
+
args="debug",
|
|
115
|
+
),
|
|
116
|
+
WorkflowOption(
|
|
117
|
+
label="Fix failing tests",
|
|
118
|
+
description="Analyze test failures and fix the underlying code",
|
|
119
|
+
skill="testing",
|
|
120
|
+
args="run",
|
|
121
|
+
),
|
|
122
|
+
WorkflowOption(
|
|
123
|
+
label="Review for bugs",
|
|
124
|
+
description="Code review focused on finding potential bugs",
|
|
125
|
+
skill="dev",
|
|
126
|
+
args="review",
|
|
127
|
+
),
|
|
128
|
+
WorkflowOption(
|
|
129
|
+
label="Something else",
|
|
130
|
+
description="Describe your specific issue",
|
|
131
|
+
skill="attune",
|
|
132
|
+
args="",
|
|
133
|
+
),
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
IntentCategory.IMPROVE: {
|
|
137
|
+
"keywords": [
|
|
138
|
+
"refactor",
|
|
139
|
+
"improve",
|
|
140
|
+
"clean",
|
|
141
|
+
"optimize",
|
|
142
|
+
"simplify",
|
|
143
|
+
"better",
|
|
144
|
+
"performance",
|
|
145
|
+
"speed",
|
|
146
|
+
"faster",
|
|
147
|
+
"memory",
|
|
148
|
+
"too long",
|
|
149
|
+
"complex",
|
|
150
|
+
"messy",
|
|
151
|
+
"ugly",
|
|
152
|
+
],
|
|
153
|
+
"question": "What would you like to improve?",
|
|
154
|
+
"options": [
|
|
155
|
+
WorkflowOption(
|
|
156
|
+
label="Refactor code",
|
|
157
|
+
description="Improve structure, extract functions, simplify logic",
|
|
158
|
+
skill="dev",
|
|
159
|
+
args="refactor",
|
|
160
|
+
),
|
|
161
|
+
WorkflowOption(
|
|
162
|
+
label="Optimize performance",
|
|
163
|
+
description="Find bottlenecks, improve speed and memory usage",
|
|
164
|
+
skill="workflows",
|
|
165
|
+
args="run perf-audit",
|
|
166
|
+
),
|
|
167
|
+
WorkflowOption(
|
|
168
|
+
label="Code review",
|
|
169
|
+
description="Get feedback on code quality and patterns",
|
|
170
|
+
skill="dev",
|
|
171
|
+
args="review",
|
|
172
|
+
),
|
|
173
|
+
WorkflowOption(
|
|
174
|
+
label="Something else",
|
|
175
|
+
description="Describe what you want to improve",
|
|
176
|
+
skill="attune",
|
|
177
|
+
args="",
|
|
178
|
+
),
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
IntentCategory.VALIDATE: {
|
|
182
|
+
"keywords": [
|
|
183
|
+
"test",
|
|
184
|
+
"coverage",
|
|
185
|
+
"security",
|
|
186
|
+
"audit",
|
|
187
|
+
"check",
|
|
188
|
+
"verify",
|
|
189
|
+
"validate",
|
|
190
|
+
"review",
|
|
191
|
+
"safe",
|
|
192
|
+
"secure",
|
|
193
|
+
"vulnerability",
|
|
194
|
+
],
|
|
195
|
+
"question": "What would you like to validate?",
|
|
196
|
+
"options": [
|
|
197
|
+
WorkflowOption(
|
|
198
|
+
label="Run tests",
|
|
199
|
+
description="Execute test suite and see results",
|
|
200
|
+
skill="testing",
|
|
201
|
+
args="run",
|
|
202
|
+
),
|
|
203
|
+
WorkflowOption(
|
|
204
|
+
label="Check coverage",
|
|
205
|
+
description="Analyze test coverage and identify gaps",
|
|
206
|
+
skill="testing",
|
|
207
|
+
args="coverage",
|
|
208
|
+
),
|
|
209
|
+
WorkflowOption(
|
|
210
|
+
label="Security audit",
|
|
211
|
+
description="Scan for vulnerabilities and security issues",
|
|
212
|
+
skill="workflows",
|
|
213
|
+
args="run security-audit",
|
|
214
|
+
),
|
|
215
|
+
WorkflowOption(
|
|
216
|
+
label="Code review",
|
|
217
|
+
description="Quality and pattern analysis",
|
|
218
|
+
skill="dev",
|
|
219
|
+
args="review",
|
|
220
|
+
),
|
|
221
|
+
],
|
|
222
|
+
},
|
|
223
|
+
IntentCategory.SHIP: {
|
|
224
|
+
"keywords": [
|
|
225
|
+
"commit",
|
|
226
|
+
"push",
|
|
227
|
+
"pr",
|
|
228
|
+
"pull request",
|
|
229
|
+
"merge",
|
|
230
|
+
"release",
|
|
231
|
+
"deploy",
|
|
232
|
+
"ship",
|
|
233
|
+
"publish",
|
|
234
|
+
"done",
|
|
235
|
+
"ready",
|
|
236
|
+
"finished",
|
|
237
|
+
],
|
|
238
|
+
"question": "What stage are you at?",
|
|
239
|
+
"options": [
|
|
240
|
+
WorkflowOption(
|
|
241
|
+
label="Create commit",
|
|
242
|
+
description="Stage changes and create a commit with message",
|
|
243
|
+
skill="dev",
|
|
244
|
+
args="commit",
|
|
245
|
+
),
|
|
246
|
+
WorkflowOption(
|
|
247
|
+
label="Create PR",
|
|
248
|
+
description="Push branch and create pull request",
|
|
249
|
+
skill="dev",
|
|
250
|
+
args="pr",
|
|
251
|
+
),
|
|
252
|
+
WorkflowOption(
|
|
253
|
+
label="Prepare release",
|
|
254
|
+
description="Version bump, changelog, security checks",
|
|
255
|
+
skill="release",
|
|
256
|
+
args="prep",
|
|
257
|
+
),
|
|
258
|
+
WorkflowOption(
|
|
259
|
+
label="Just push",
|
|
260
|
+
description="Push current commits to remote",
|
|
261
|
+
skill="dev",
|
|
262
|
+
args="push",
|
|
263
|
+
),
|
|
264
|
+
],
|
|
265
|
+
},
|
|
266
|
+
IntentCategory.UNDERSTAND: {
|
|
267
|
+
"keywords": [
|
|
268
|
+
"explain",
|
|
269
|
+
"understand",
|
|
270
|
+
"how",
|
|
271
|
+
"what",
|
|
272
|
+
"why",
|
|
273
|
+
"document",
|
|
274
|
+
"docs",
|
|
275
|
+
"readme",
|
|
276
|
+
"learn",
|
|
277
|
+
"show",
|
|
278
|
+
"describe",
|
|
279
|
+
"overview",
|
|
280
|
+
],
|
|
281
|
+
"question": "What would you like to understand?",
|
|
282
|
+
"options": [
|
|
283
|
+
WorkflowOption(
|
|
284
|
+
label="Explain code",
|
|
285
|
+
description="Understand how specific code works",
|
|
286
|
+
skill="docs",
|
|
287
|
+
args="explain",
|
|
288
|
+
),
|
|
289
|
+
WorkflowOption(
|
|
290
|
+
label="Project overview",
|
|
291
|
+
description="High-level architecture and structure",
|
|
292
|
+
skill="docs",
|
|
293
|
+
args="overview",
|
|
294
|
+
),
|
|
295
|
+
WorkflowOption(
|
|
296
|
+
label="Generate docs",
|
|
297
|
+
description="Create or update documentation",
|
|
298
|
+
skill="docs",
|
|
299
|
+
args="generate",
|
|
300
|
+
),
|
|
301
|
+
WorkflowOption(
|
|
302
|
+
label="Something specific",
|
|
303
|
+
description="Ask about a specific part of the codebase",
|
|
304
|
+
skill="attune",
|
|
305
|
+
args="",
|
|
306
|
+
),
|
|
307
|
+
],
|
|
308
|
+
},
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def classify_intent(user_response: str) -> IntentClassification:
|
|
313
|
+
"""Classify user's natural language response into intent category.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
user_response: User's answer to "What are you trying to accomplish?"
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
IntentClassification with category, options, and metadata
|
|
320
|
+
"""
|
|
321
|
+
response_lower = user_response.lower()
|
|
322
|
+
|
|
323
|
+
best_category = IntentCategory.UNKNOWN
|
|
324
|
+
best_score = 0
|
|
325
|
+
matched_keywords: list[str] = []
|
|
326
|
+
|
|
327
|
+
# Score each category based on keyword matches
|
|
328
|
+
for category, pattern in INTENT_PATTERNS.items():
|
|
329
|
+
keywords = pattern["keywords"]
|
|
330
|
+
score = 0
|
|
331
|
+
matches = []
|
|
332
|
+
|
|
333
|
+
for keyword in keywords:
|
|
334
|
+
if keyword in response_lower:
|
|
335
|
+
score += 1
|
|
336
|
+
matches.append(keyword)
|
|
337
|
+
|
|
338
|
+
if score > best_score:
|
|
339
|
+
best_score = score
|
|
340
|
+
best_category = category
|
|
341
|
+
matched_keywords = matches
|
|
342
|
+
|
|
343
|
+
# Calculate confidence
|
|
344
|
+
if best_score == 0:
|
|
345
|
+
confidence = 0.0
|
|
346
|
+
elif best_score >= 3:
|
|
347
|
+
confidence = 0.95
|
|
348
|
+
elif best_score >= 2:
|
|
349
|
+
confidence = 0.8
|
|
350
|
+
else:
|
|
351
|
+
confidence = 0.6
|
|
352
|
+
|
|
353
|
+
# Get options for the category
|
|
354
|
+
if best_category in INTENT_PATTERNS:
|
|
355
|
+
pattern = INTENT_PATTERNS[best_category]
|
|
356
|
+
return IntentClassification(
|
|
357
|
+
category=best_category,
|
|
358
|
+
confidence=confidence,
|
|
359
|
+
keywords_matched=matched_keywords,
|
|
360
|
+
suggested_question=pattern["question"],
|
|
361
|
+
options=pattern["options"],
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
# Unknown intent - ask for clarification
|
|
365
|
+
return IntentClassification(
|
|
366
|
+
category=IntentCategory.UNKNOWN,
|
|
367
|
+
confidence=0.0,
|
|
368
|
+
keywords_matched=[],
|
|
369
|
+
suggested_question="Could you tell me more about what you're trying to do?",
|
|
370
|
+
options=[
|
|
371
|
+
WorkflowOption(
|
|
372
|
+
label="Fix something",
|
|
373
|
+
description="Debug errors, fix bugs, resolve issues",
|
|
374
|
+
skill="dev",
|
|
375
|
+
args="debug",
|
|
376
|
+
),
|
|
377
|
+
WorkflowOption(
|
|
378
|
+
label="Improve code",
|
|
379
|
+
description="Refactor, optimize, clean up",
|
|
380
|
+
skill="dev",
|
|
381
|
+
args="refactor",
|
|
382
|
+
),
|
|
383
|
+
WorkflowOption(
|
|
384
|
+
label="Validate work",
|
|
385
|
+
description="Test, review, audit for security",
|
|
386
|
+
skill="testing",
|
|
387
|
+
args="run",
|
|
388
|
+
),
|
|
389
|
+
WorkflowOption(
|
|
390
|
+
label="Ship changes",
|
|
391
|
+
description="Commit, create PR, release",
|
|
392
|
+
skill="dev",
|
|
393
|
+
args="commit",
|
|
394
|
+
),
|
|
395
|
+
],
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def get_ask_user_question_format(classification: IntentClassification) -> dict[str, Any]:
|
|
400
|
+
"""Convert classification to AskUserQuestion tool format.
|
|
401
|
+
|
|
402
|
+
Args:
|
|
403
|
+
classification: Result from classify_intent()
|
|
404
|
+
|
|
405
|
+
Returns:
|
|
406
|
+
Dict ready to pass to AskUserQuestion tool
|
|
407
|
+
"""
|
|
408
|
+
return {
|
|
409
|
+
"questions": [
|
|
410
|
+
{
|
|
411
|
+
"question": classification.suggested_question,
|
|
412
|
+
"header": classification.category.value.title(),
|
|
413
|
+
"options": [opt.to_ask_user_option() for opt in classification.options],
|
|
414
|
+
"multiSelect": False,
|
|
415
|
+
}
|
|
416
|
+
]
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
def get_skill_for_selection(
|
|
421
|
+
classification: IntentClassification, selected_label: str
|
|
422
|
+
) -> tuple[str, str]:
|
|
423
|
+
"""Get skill and args for user's selection.
|
|
424
|
+
|
|
425
|
+
Args:
|
|
426
|
+
classification: The classification that was shown to user
|
|
427
|
+
selected_label: The label the user selected
|
|
428
|
+
|
|
429
|
+
Returns:
|
|
430
|
+
Tuple of (skill, args) to invoke
|
|
431
|
+
"""
|
|
432
|
+
for option in classification.options:
|
|
433
|
+
if option.label == selected_label:
|
|
434
|
+
return option.skill, option.args
|
|
435
|
+
|
|
436
|
+
# Fallback to first option if not found
|
|
437
|
+
if classification.options:
|
|
438
|
+
return classification.options[0].skill, classification.options[0].args
|
|
439
|
+
|
|
440
|
+
return "attune", ""
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
# Convenience function for the /attune command
|
|
444
|
+
def process_socratic_response(user_response: str) -> dict[str, Any]:
|
|
445
|
+
"""Process user's response to Socratic question.
|
|
446
|
+
|
|
447
|
+
This is the main entry point for the /attune command after
|
|
448
|
+
asking "What are you trying to accomplish?"
|
|
449
|
+
|
|
450
|
+
Args:
|
|
451
|
+
user_response: User's natural language response
|
|
452
|
+
|
|
453
|
+
Returns:
|
|
454
|
+
Dict with:
|
|
455
|
+
- classification: IntentClassification object
|
|
456
|
+
- ask_user_format: Ready-to-use AskUserQuestion format
|
|
457
|
+
- confidence: How confident we are in the classification
|
|
458
|
+
"""
|
|
459
|
+
classification = classify_intent(user_response)
|
|
460
|
+
|
|
461
|
+
return {
|
|
462
|
+
"classification": classification,
|
|
463
|
+
"ask_user_format": get_ask_user_question_format(classification),
|
|
464
|
+
"confidence": classification.confidence,
|
|
465
|
+
"category": classification.category.value,
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
# =============================================================================
|
|
470
|
+
# DEEP DISCOVERY - SocraticWorkflowBuilder Integration
|
|
471
|
+
# =============================================================================
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def form_to_ask_user_question(form: Form) -> dict[str, Any]:
|
|
475
|
+
"""Convert a SocraticWorkflowBuilder Form to AskUserQuestion format.
|
|
476
|
+
|
|
477
|
+
This bridges the Socratic system's Form objects with Claude Code's
|
|
478
|
+
AskUserQuestion tool.
|
|
479
|
+
|
|
480
|
+
Args:
|
|
481
|
+
form: Form from SocraticWorkflowBuilder.get_next_questions()
|
|
482
|
+
|
|
483
|
+
Returns:
|
|
484
|
+
Dict ready to pass to AskUserQuestion tool
|
|
485
|
+
|
|
486
|
+
Example:
|
|
487
|
+
>>> from attune.socratic import SocraticWorkflowBuilder
|
|
488
|
+
>>> builder = SocraticWorkflowBuilder()
|
|
489
|
+
>>> session = builder.start_session("automate code reviews")
|
|
490
|
+
>>> form = builder.get_next_questions(session)
|
|
491
|
+
>>> ask_user_format = form_to_ask_user_question(form)
|
|
492
|
+
"""
|
|
493
|
+
from attune.socratic.forms import FieldType
|
|
494
|
+
|
|
495
|
+
questions = []
|
|
496
|
+
|
|
497
|
+
for field in form.fields:
|
|
498
|
+
# Convert field to question format
|
|
499
|
+
question_data = {
|
|
500
|
+
"question": field.label,
|
|
501
|
+
"header": field.category.title() if field.category else "Question",
|
|
502
|
+
"multiSelect": field.field_type == FieldType.MULTI_SELECT,
|
|
503
|
+
"options": [],
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
# Convert options
|
|
507
|
+
if field.options:
|
|
508
|
+
for opt in field.options[:4]: # AskUserQuestion max 4 options
|
|
509
|
+
option_data = {"label": opt.value, "description": opt.description or opt.label}
|
|
510
|
+
if opt.recommended:
|
|
511
|
+
option_data["label"] += " (Recommended)"
|
|
512
|
+
question_data["options"].append(option_data)
|
|
513
|
+
else:
|
|
514
|
+
# Text field - provide generic options
|
|
515
|
+
question_data["options"] = [
|
|
516
|
+
{"label": "Continue", "description": "Proceed with current settings"},
|
|
517
|
+
{"label": "Customize", "description": "I want to specify details"},
|
|
518
|
+
]
|
|
519
|
+
|
|
520
|
+
questions.append(question_data)
|
|
521
|
+
|
|
522
|
+
# Limit to 4 questions per AskUserQuestion call
|
|
523
|
+
return {"questions": questions[:4]}
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
def should_use_deep_discovery(user_response: str, classification: IntentClassification) -> bool:
|
|
527
|
+
"""Determine if we should use full SocraticWorkflowBuilder.
|
|
528
|
+
|
|
529
|
+
Use deep discovery when:
|
|
530
|
+
- Low confidence classification
|
|
531
|
+
- User wants to create custom agents/workflows
|
|
532
|
+
- Complex multi-step requirements
|
|
533
|
+
|
|
534
|
+
Args:
|
|
535
|
+
user_response: User's natural language response
|
|
536
|
+
classification: Result from classify_intent()
|
|
537
|
+
|
|
538
|
+
Returns:
|
|
539
|
+
True if should use SocraticWorkflowBuilder, False for quick routing
|
|
540
|
+
"""
|
|
541
|
+
# Low confidence - need more clarification
|
|
542
|
+
if classification.confidence < 0.5:
|
|
543
|
+
return True
|
|
544
|
+
|
|
545
|
+
# Explicit agent/workflow creation keywords
|
|
546
|
+
deep_keywords = [
|
|
547
|
+
"create agent",
|
|
548
|
+
"custom workflow",
|
|
549
|
+
"build workflow",
|
|
550
|
+
"automate",
|
|
551
|
+
"automation",
|
|
552
|
+
"generate agents",
|
|
553
|
+
"multi-step",
|
|
554
|
+
"pipeline",
|
|
555
|
+
]
|
|
556
|
+
|
|
557
|
+
response_lower = user_response.lower()
|
|
558
|
+
for keyword in deep_keywords:
|
|
559
|
+
if keyword in response_lower:
|
|
560
|
+
return True
|
|
561
|
+
|
|
562
|
+
return False
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
def start_deep_discovery(goal: str) -> tuple[SocraticSession, dict[str, Any]]:
|
|
566
|
+
"""Start a full SocraticWorkflowBuilder session.
|
|
567
|
+
|
|
568
|
+
Args:
|
|
569
|
+
goal: User's goal statement
|
|
570
|
+
|
|
571
|
+
Returns:
|
|
572
|
+
Tuple of (session, ask_user_format)
|
|
573
|
+
|
|
574
|
+
Example:
|
|
575
|
+
>>> session, questions = start_deep_discovery("automate security reviews")
|
|
576
|
+
>>> # Use questions with AskUserQuestion tool
|
|
577
|
+
>>> # Then call continue_deep_discovery(session, answers)
|
|
578
|
+
"""
|
|
579
|
+
from attune.socratic import SocraticWorkflowBuilder
|
|
580
|
+
|
|
581
|
+
builder = SocraticWorkflowBuilder()
|
|
582
|
+
session = builder.start_session(goal)
|
|
583
|
+
form = builder.get_next_questions(session)
|
|
584
|
+
|
|
585
|
+
if form:
|
|
586
|
+
ask_user_format = form_to_ask_user_question(form)
|
|
587
|
+
else:
|
|
588
|
+
# Session ready to generate
|
|
589
|
+
ask_user_format = {
|
|
590
|
+
"questions": [
|
|
591
|
+
{
|
|
592
|
+
"question": "Ready to generate your workflow. Proceed?",
|
|
593
|
+
"header": "Generate",
|
|
594
|
+
"options": [
|
|
595
|
+
{"label": "Generate", "description": "Create the workflow now"},
|
|
596
|
+
{"label": "Add details", "description": "I want to specify more"},
|
|
597
|
+
],
|
|
598
|
+
"multiSelect": False,
|
|
599
|
+
}
|
|
600
|
+
]
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
return session, ask_user_format
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
def continue_deep_discovery(
|
|
607
|
+
session: SocraticSession, answers: dict[str, Any]
|
|
608
|
+
) -> tuple[SocraticSession, dict[str, Any] | None]:
|
|
609
|
+
"""Continue a SocraticWorkflowBuilder session with answers.
|
|
610
|
+
|
|
611
|
+
Args:
|
|
612
|
+
session: Active session from start_deep_discovery
|
|
613
|
+
answers: User's answers to previous questions
|
|
614
|
+
|
|
615
|
+
Returns:
|
|
616
|
+
Tuple of (updated_session, next_questions_or_None)
|
|
617
|
+
"""
|
|
618
|
+
from attune.socratic import SocraticWorkflowBuilder
|
|
619
|
+
|
|
620
|
+
builder = SocraticWorkflowBuilder()
|
|
621
|
+
builder._sessions[session.session_id] = session
|
|
622
|
+
|
|
623
|
+
session = builder.submit_answers(session, answers)
|
|
624
|
+
|
|
625
|
+
if builder.is_ready_to_generate(session):
|
|
626
|
+
return session, None
|
|
627
|
+
|
|
628
|
+
form = builder.get_next_questions(session)
|
|
629
|
+
if form:
|
|
630
|
+
return session, form_to_ask_user_question(form)
|
|
631
|
+
|
|
632
|
+
return session, None
|
|
633
|
+
|
|
634
|
+
|
|
635
|
+
# =============================================================================
|
|
636
|
+
# UNIFIED ENTRY POINT
|
|
637
|
+
# =============================================================================
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
class AttuneRouter:
|
|
641
|
+
"""Unified router for /attune command.
|
|
642
|
+
|
|
643
|
+
Handles both quick routing and deep discovery modes.
|
|
644
|
+
|
|
645
|
+
Example (Claude Code /attune command):
|
|
646
|
+
>>> router = AttuneRouter()
|
|
647
|
+
>>>
|
|
648
|
+
>>> # User says: "I need to fix a bug"
|
|
649
|
+
>>> result = router.process("I need to fix a bug")
|
|
650
|
+
>>>
|
|
651
|
+
>>> if result["mode"] == "quick":
|
|
652
|
+
>>> # Use AskUserQuestion with result["ask_user_format"]
|
|
653
|
+
>>> # Then call router.route_selection(result, user_selection)
|
|
654
|
+
>>>
|
|
655
|
+
>>> elif result["mode"] == "deep":
|
|
656
|
+
>>> # Multi-round discovery session
|
|
657
|
+
>>> # Use AskUserQuestion, then router.continue_session(...)
|
|
658
|
+
"""
|
|
659
|
+
|
|
660
|
+
def __init__(self):
|
|
661
|
+
"""Initialize the router."""
|
|
662
|
+
self._sessions: dict[str, SocraticSession] = {}
|
|
663
|
+
|
|
664
|
+
def process(self, user_response: str) -> dict[str, Any]:
|
|
665
|
+
"""Process user's response and determine routing mode.
|
|
666
|
+
|
|
667
|
+
Args:
|
|
668
|
+
user_response: User's answer to "What are you trying to accomplish?"
|
|
669
|
+
|
|
670
|
+
Returns:
|
|
671
|
+
Dict with:
|
|
672
|
+
- mode: "quick" or "deep"
|
|
673
|
+
- ask_user_format: Ready for AskUserQuestion tool
|
|
674
|
+
- classification: (quick mode) IntentClassification
|
|
675
|
+
- session: (deep mode) SocraticSession
|
|
676
|
+
"""
|
|
677
|
+
classification = classify_intent(user_response)
|
|
678
|
+
|
|
679
|
+
if should_use_deep_discovery(user_response, classification):
|
|
680
|
+
session, ask_user_format = start_deep_discovery(user_response)
|
|
681
|
+
self._sessions[session.session_id] = session
|
|
682
|
+
|
|
683
|
+
return {
|
|
684
|
+
"mode": "deep",
|
|
685
|
+
"session_id": session.session_id,
|
|
686
|
+
"ask_user_format": ask_user_format,
|
|
687
|
+
"classification": classification,
|
|
688
|
+
}
|
|
689
|
+
else:
|
|
690
|
+
return {
|
|
691
|
+
"mode": "quick",
|
|
692
|
+
"ask_user_format": get_ask_user_question_format(classification),
|
|
693
|
+
"classification": classification,
|
|
694
|
+
"category": classification.category.value,
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
def route_selection(
|
|
698
|
+
self, process_result: dict[str, Any], selected_label: str
|
|
699
|
+
) -> dict[str, Any]:
|
|
700
|
+
"""Route user's selection to skill invocation.
|
|
701
|
+
|
|
702
|
+
Args:
|
|
703
|
+
process_result: Result from process()
|
|
704
|
+
selected_label: Label user selected in AskUserQuestion
|
|
705
|
+
|
|
706
|
+
Returns:
|
|
707
|
+
Dict with skill and args to invoke
|
|
708
|
+
"""
|
|
709
|
+
classification = process_result.get("classification")
|
|
710
|
+
|
|
711
|
+
if classification:
|
|
712
|
+
skill, args = get_skill_for_selection(classification, selected_label)
|
|
713
|
+
else:
|
|
714
|
+
skill, args = "attune", ""
|
|
715
|
+
|
|
716
|
+
return {
|
|
717
|
+
"skill": skill,
|
|
718
|
+
"args": args,
|
|
719
|
+
"instruction": f"Use Skill tool with skill='{skill}'"
|
|
720
|
+
+ (f", args='{args}'" if args else ""),
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
def continue_session(
|
|
724
|
+
self, session_id: str, answers: dict[str, Any]
|
|
725
|
+
) -> dict[str, Any]:
|
|
726
|
+
"""Continue a deep discovery session.
|
|
727
|
+
|
|
728
|
+
Args:
|
|
729
|
+
session_id: Session ID from process() result
|
|
730
|
+
answers: User's answers to questions
|
|
731
|
+
|
|
732
|
+
Returns:
|
|
733
|
+
Dict with next questions or generated workflow
|
|
734
|
+
"""
|
|
735
|
+
session = self._sessions.get(session_id)
|
|
736
|
+
if not session:
|
|
737
|
+
return {"error": "Session not found"}
|
|
738
|
+
|
|
739
|
+
session, next_questions = continue_deep_discovery(session, answers)
|
|
740
|
+
self._sessions[session_id] = session
|
|
741
|
+
|
|
742
|
+
if next_questions:
|
|
743
|
+
return {
|
|
744
|
+
"mode": "deep",
|
|
745
|
+
"session_id": session_id,
|
|
746
|
+
"ask_user_format": next_questions,
|
|
747
|
+
}
|
|
748
|
+
else:
|
|
749
|
+
# Ready to generate
|
|
750
|
+
from attune.socratic import SocraticWorkflowBuilder
|
|
751
|
+
|
|
752
|
+
builder = SocraticWorkflowBuilder()
|
|
753
|
+
builder._sessions[session_id] = session
|
|
754
|
+
workflow = builder.generate_workflow(session)
|
|
755
|
+
|
|
756
|
+
return {
|
|
757
|
+
"mode": "complete",
|
|
758
|
+
"session_id": session_id,
|
|
759
|
+
"workflow": workflow,
|
|
760
|
+
"summary": builder.get_session_summary(session),
|
|
761
|
+
}
|
attune/vscode_bridge.py
CHANGED
|
@@ -43,10 +43,13 @@ class CodeReviewResult:
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
def get_empathy_dir() -> Path:
|
|
46
|
-
"""Get the .
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
"""Get the .attune directory, creating if needed.
|
|
47
|
+
|
|
48
|
+
Note: Function retains 'empathy' name for backward compatibility.
|
|
49
|
+
"""
|
|
50
|
+
attune_dir = Path(".attune")
|
|
51
|
+
attune_dir.mkdir(exist_ok=True)
|
|
52
|
+
return attune_dir
|
|
50
53
|
|
|
51
54
|
|
|
52
55
|
def write_code_review_results(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: attune-ai
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: AI collaboration framework with real LLM agent execution, AskUserQuestion tool integration, Socratic agent generation, progressive tier escalation (70-85% cost savings), meta-orchestration, dynamic agent composition (10 patterns including Anthropic-inspired), intelligent caching (85% hit rate), semantic workflow discovery, visual workflow editor, MCP integration for Claude Code, and multi-agent orchestration.
|
|
5
5
|
Author-email: Patrick Roebuck <admin@smartaimemory.com>
|
|
6
6
|
Maintainer-email: Smart-AI-Memory <admin@smartaimemory.com>
|
|
@@ -421,16 +421,17 @@ Requires-Dist: aiohttp<4.0.0,>=3.10.0; extra == "all"
|
|
|
421
421
|
Requires-Dist: filelock<4.0.0,>=3.16.0; extra == "all"
|
|
422
422
|
Dynamic: license-file
|
|
423
423
|
|
|
424
|
-
#
|
|
424
|
+
# Empathy Framework
|
|
425
425
|
|
|
426
|
-
**AI-powered developer workflows with
|
|
426
|
+
**AI-powered developer workflows with cost optimization and pattern learning.**
|
|
427
427
|
|
|
428
|
-
Run code review, debugging, testing, and release workflows from Claude Code.
|
|
428
|
+
Run code review, debugging, testing, and release workflows from your terminal or Claude Code. Smart tier routing saves 34-86% on LLM costs.
|
|
429
429
|
|
|
430
430
|
[](https://pypi.org/project/attune-ai/)
|
|
431
431
|
[-brightgreen)](https://github.com/Smart-AI-Memory/attune-ai/actions)
|
|
432
432
|
[](https://www.python.org)
|
|
433
433
|
[](LICENSE)
|
|
434
|
+
[](https://github.com/Smart-AI-Memory/attune-ai/blob/main/CHANGELOG.md)
|
|
434
435
|
|
|
435
436
|
```bash
|
|
436
437
|
pip install attune-ai[developer]
|
|
@@ -438,26 +439,188 @@ pip install attune-ai[developer]
|
|
|
438
439
|
|
|
439
440
|
---
|
|
440
441
|
|
|
441
|
-
##
|
|
442
|
+
## 🎯 Transitioning to Claude-Native Architecture
|
|
442
443
|
|
|
443
|
-
|
|
444
|
+
**Empathy Framework is evolving to focus exclusively on Anthropic/Claude** to unlock features impossible with multi-provider abstraction:
|
|
445
|
+
|
|
446
|
+
- **📦 Prompt Caching:** 90% cost reduction on repeated prompts
|
|
447
|
+
- **📖 Flexible Context:** 200K via subscription for most tasks, up to 1M via API for large codebases
|
|
448
|
+
- **🧠 Extended Thinking:** See Claude's internal reasoning process
|
|
449
|
+
- **🔧 Advanced Tool Use:** Optimized for agentic workflows
|
|
450
|
+
|
|
451
|
+
**Timeline:**
|
|
452
|
+
|
|
453
|
+
- ✅ **v4.8.0 (Jan 2026):** Deprecation warnings for OpenAI/Google/Ollama providers
|
|
454
|
+
- ✅ **v5.0.0 (Jan 26, 2026):** Non-Anthropic providers removed (BREAKING - COMPLETE)
|
|
455
|
+
- ✅ **v5.0.2 (Jan 28, 2026):** Cost optimization suite with batch processing and caching monitoring
|
|
456
|
+
|
|
457
|
+
**Migration Guide:** [docs/CLAUDE_NATIVE.md](docs/CLAUDE_NATIVE.md)
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
## What's New in v5.3.0
|
|
462
|
+
|
|
463
|
+
**🎨 Dashboard Enhancements** - Improved usability and clarity:
|
|
464
|
+
|
|
465
|
+
- **Agent Display Names** - Human-readable labels for agents in dashboard (e.g., "Code Analyzer" instead of UUID)
|
|
466
|
+
- **Comprehensive Help Panel** - 5-section accordion explaining dashboard features, use cases, and Redis setup
|
|
467
|
+
- **UX Improvements** - "Source Agent:" label clarity, "Redis Requires Enabling" status message
|
|
468
|
+
- **Browser Cache Busting** - Date-based versioning ensures updates appear immediately
|
|
469
|
+
|
|
470
|
+
**📚 Documentation Improvements**:
|
|
471
|
+
|
|
472
|
+
- Clarified flexible context strategy (200K subscription + 1M API routing)
|
|
473
|
+
- Added Redis requirement documentation for dashboard
|
|
474
|
+
- Root directory cleanup (8 archived files)
|
|
475
|
+
|
|
476
|
+
**🧪 Test Infrastructure**:
|
|
477
|
+
|
|
478
|
+
- Sequential test execution to fix import timing issues
|
|
479
|
+
- All agent tracking tests passing (19/19)
|
|
480
|
+
|
|
481
|
+
[See Full Changelog](CHANGELOG.md#530---2026-01-31)
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## What's New in v5.1.0
|
|
486
|
+
|
|
487
|
+
**🤖 Multi-Agent Orchestration** - Full support for custom agents and Anthropic LLM agents:
|
|
488
|
+
|
|
489
|
+
- **Agent Coordination Dashboard** - Real-time monitoring with 6 coordination patterns:
|
|
490
|
+
- Agent heartbeats and status tracking
|
|
491
|
+
- Inter-agent coordination signals
|
|
492
|
+
- Event streaming across agent workflows
|
|
493
|
+
- Approval gates for human-in-the-loop
|
|
494
|
+
- Quality feedback and performance metrics
|
|
495
|
+
- Demo mode with test data generation
|
|
496
|
+
|
|
497
|
+
- **Custom Agents** - Build specialized agents for your workflow needs
|
|
498
|
+
- **LLM Agents from Anthropic** - Leverage Claude's advanced capabilities
|
|
499
|
+
- Dashboard accessible at `http://localhost:8000` with `python examples/dashboard_demo.py` **(Requires Redis)**
|
|
500
|
+
|
|
501
|
+
**🔐 Authentication Strategy System** - Intelligent routing between Claude subscriptions and Anthropic API:
|
|
444
502
|
|
|
445
503
|
```bash
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
504
|
+
# Interactive setup
|
|
505
|
+
python -m attune.models.auth_cli setup
|
|
506
|
+
|
|
507
|
+
# View current configuration
|
|
508
|
+
python -m attune.models.auth_cli status
|
|
509
|
+
|
|
510
|
+
# Get recommendation for a file
|
|
511
|
+
python -m attune.models.auth_cli recommend src/module.py
|
|
449
512
|
```
|
|
450
513
|
|
|
451
|
-
|
|
514
|
+
**💰 Automatic Cost Optimization** - Workflows choose the best auth method:
|
|
515
|
+
|
|
516
|
+
- Small/medium modules (<2000 LOC) → Claude subscription (free)
|
|
517
|
+
- Large modules (>2000 LOC) → Anthropic API (pay for what you need)
|
|
518
|
+
- 7 workflows integrated: document-gen, test-gen, code-review, bug-predict, security-audit, perf-audit, release-prep
|
|
519
|
+
- Auth mode tracking in all workflow outputs for telemetry
|
|
520
|
+
|
|
521
|
+
**🧪 Comprehensive Testing** - 7 new integration tests for auth strategy:
|
|
522
|
+
|
|
523
|
+
- All workflows tested with auth enabled/disabled
|
|
524
|
+
- API and subscription mode verification
|
|
525
|
+
- Cost tracking validation
|
|
526
|
+
|
|
527
|
+
**📖 Documentation** - 950+ lines across 3 guides:
|
|
528
|
+
|
|
529
|
+
- [AUTH_STRATEGY_GUIDE.md](docs/AUTH_STRATEGY_GUIDE.md) - User guide for configuration
|
|
530
|
+
- [AUTH_CLI_IMPLEMENTATION.md](docs/AUTH_CLI_IMPLEMENTATION.md) - CLI command reference
|
|
531
|
+
- [AUTH_WORKFLOW_INTEGRATIONS.md](docs/AUTH_WORKFLOW_INTEGRATIONS.md) - Integration patterns
|
|
532
|
+
|
|
533
|
+
[See Full Changelog](CHANGELOG.md#510---2026-01-29)
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
## What's New in v5.0.2
|
|
538
|
+
|
|
539
|
+
**💰 50% Cost Savings with Batch API** - Process non-urgent tasks asynchronously:
|
|
540
|
+
|
|
541
|
+
```bash
|
|
542
|
+
empathy batch submit batch_requests.json # Submit batch job
|
|
543
|
+
empathy batch status msgbatch_abc123 # Check progress
|
|
544
|
+
empathy batch results msgbatch_abc123 output.json # Download results
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Perfect for: log analysis, report generation, bulk classification, test generation
|
|
548
|
+
|
|
549
|
+
**📊 Precise Token Counting** - >98% accurate cost tracking:
|
|
550
|
+
|
|
551
|
+
- Integrated Anthropic's `count_tokens()` API for billing-accurate measurements
|
|
552
|
+
- 3-tier fallback: API → tiktoken (local) → heuristic
|
|
553
|
+
- Cache-aware cost calculation (25% write markup, 90% read discount)
|
|
554
|
+
|
|
555
|
+
**📈 Cache Performance Monitoring** - Track your 20-30% caching savings:
|
|
556
|
+
|
|
557
|
+
```bash
|
|
558
|
+
empathy cache stats # Show hit rates and cost savings
|
|
559
|
+
empathy cache stats --verbose # Detailed token metrics
|
|
560
|
+
empathy cache stats --format json # Machine-readable output
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
**🧭 Adaptive Routing Analytics** - Intelligent tier recommendations:
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
empathy routing stats <workflow> # Performance metrics
|
|
567
|
+
empathy routing check --all # Tier upgrade recommendations
|
|
568
|
+
empathy routing models --provider anthropic # Compare models
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
**🔧 Dashboard Fixes** - All 6 agent coordination patterns now operational:
|
|
572
|
+
- Agent heartbeats displaying correctly
|
|
573
|
+
- Event streaming functional
|
|
574
|
+
- Coordination signals working
|
|
575
|
+
- Approval gates operational
|
|
576
|
+
|
|
577
|
+
[See Full Changelog](CHANGELOG.md#502---2026-01-28) | [Batch API Guide](docs/BATCH_API_GUIDE.md) | [User API Docs](docs/USER_API_DOCUMENTATION.md)
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
## What's New in v4.9.0
|
|
582
|
+
|
|
583
|
+
**⚡ 18x Faster Performance** - Massive performance gains through Phase 2 optimizations:
|
|
584
|
+
|
|
585
|
+
- **Redis Two-Tier Caching:** 2x faster memory operations (37,000x for cached keys)
|
|
586
|
+
- **Generator Expressions:** 99.9% memory reduction across 27 optimizations
|
|
587
|
+
- **Parallel Scanning:** Multi-core processing enabled by default (2-4x faster)
|
|
588
|
+
- **Incremental Scanning:** Git diff-based updates (10x faster)
|
|
589
|
+
|
|
590
|
+
**🧭 Natural Language Workflows** - Use plain English instead of workflow names:
|
|
591
|
+
|
|
592
|
+
```bash
|
|
593
|
+
/workflows "find security vulnerabilities" # → security-audit
|
|
594
|
+
/workflows "check code performance" # → perf-audit
|
|
595
|
+
/workflows "predict bugs" # → bug-predict
|
|
596
|
+
/plan "review my code" # → code-review
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
**📊 Real-World Performance:**
|
|
600
|
+
|
|
601
|
+
- Combined workflow: 3.59s → 0.2s (**18x faster**)
|
|
602
|
+
- Full scan: 3,472 files in 0.98s (was 3.59s)
|
|
603
|
+
- Redis cached operations: 37ms → 0.001ms
|
|
604
|
+
|
|
605
|
+
**🎯 Improved Navigation:**
|
|
606
|
+
|
|
607
|
+
- Split `/workflow` into `/workflows` (automated analysis) and `/plan` (planning/review)
|
|
608
|
+
- Clearer hub organization with better categorization
|
|
609
|
+
- Natural language routing matches intent to workflow
|
|
610
|
+
|
|
611
|
+
[See CHANGELOG.md](CHANGELOG.md) | [Performance Docs](docs/REDIS_OPTIMIZATION_SUMMARY.md)
|
|
612
|
+
|
|
613
|
+
---
|
|
614
|
+
|
|
615
|
+
## What's New in v4.7.0
|
|
616
|
+
|
|
617
|
+
**$0 Workflows via Skills** - Multi-agent workflows run through Claude Code's Task tool instead of API calls. No additional cost with your Claude subscription.
|
|
452
618
|
|
|
453
|
-
-
|
|
454
|
-
- ✅ **Validate work** → Tests, coverage, security audit
|
|
455
|
-
- 🚀 **Ship changes** → Commit, PR, release
|
|
456
|
-
- 📚 **Understand** → Explain code, generate docs
|
|
619
|
+
**Socratic Workflows** - Interactive discovery through guided questions. Workflows ask what you need rather than requiring upfront configuration.
|
|
457
620
|
|
|
458
|
-
**
|
|
621
|
+
**Security Hardened** - Fixed critical vulnerabilities (path traversal, JWT, SSRF).
|
|
459
622
|
|
|
460
|
-
|
|
623
|
+
**Hub-Based Commands** - Organized workflows into intuitive command hubs.
|
|
461
624
|
|
|
462
625
|
---
|
|
463
626
|
|
|
@@ -23,11 +23,12 @@ attune/persistence.py,sha256=wsEJtHdjpEfIQ3-O5PaxAGiZXacON0Pft4gqt7Ui3z8,17714
|
|
|
23
23
|
attune/platform_utils.py,sha256=NsvAOOA2QgdWLd_44AY1UdQLYuclaOC7SPK-koFyi1A,7384
|
|
24
24
|
attune/redis_config.py,sha256=jDpnKXxBoAo6Cy2oBX9imbRtsUAyPKOIH6jvSlWdcbU,9742
|
|
25
25
|
attune/redis_memory.py,sha256=MYhW_M41AoWhxxh8YggWUHxZaUoQZ7XxqeBB2qDqyww,23347
|
|
26
|
+
attune/socratic_router.py,sha256=sHEPYDC88n6OaGBtnC7JquyctldBp3tSCQdrphV0BHo,23601
|
|
26
27
|
attune/templates.py,sha256=EbZmiHqS_jFZg_-lScK0fUUnw7_KpE5J3ZFTWXEKx-Q,17187
|
|
27
28
|
attune/tier_recommender.py,sha256=rBuAgGkNlX9wWcJ1QFi0ASGuZSR9RGl6PEBElxcAzMk,14297
|
|
28
29
|
attune/tools.py,sha256=YCfHTm9Es6wwh7oESt4q0mDz7AV8ecvMAB_1_0516r4,6225
|
|
29
30
|
attune/trust_building.py,sha256=z2ZsQWK5QjX6d7pxFWrFD54J1keUguTog6YztZJVPKI,19180
|
|
30
|
-
attune/vscode_bridge.py,sha256=
|
|
31
|
+
attune/vscode_bridge.py,sha256=XBKF6-YiQIRvyOtkp-4kmBrWhs5Uflo7TLUBj4ejPLU,5034
|
|
31
32
|
attune/workflow_commands.py,sha256=9Gdy3iI6LA9y7NtYBieNS3-rbOrrLRavhlbl_2yWVgU,25465
|
|
32
33
|
attune/adaptive/__init__.py,sha256=9LRWvrkitzasuGAqANEpKQMvrj5pPNtulSxz49E-Ke4,338
|
|
33
34
|
attune/adaptive/task_complexity.py,sha256=XhQgubrTxqV2V6CBD4kKZ_0kPCjchzg94HaUFIY6Q3c,3783
|
|
@@ -346,8 +347,8 @@ attune/workflows/test_gen/data_models.py,sha256=wXfef60ptiG6AvygayTxWqlL5FVOss19
|
|
|
346
347
|
attune/workflows/test_gen/report_formatter.py,sha256=RaxbDp6-9iQRfJmVwrrIReVkOkrnb668NgHrNaS-SPY,10705
|
|
347
348
|
attune/workflows/test_gen/test_templates.py,sha256=4ywqGYYaSoZxOU6Y1_E-27KEgMI5-v2a1ndia406E9c,13180
|
|
348
349
|
attune/workflows/test_gen/workflow.py,sha256=U0dhAcCKmlltPIvCSXUeFzt_Q4TodQI4tXtR6cz19MQ,25729
|
|
349
|
-
attune_ai-2.1.
|
|
350
|
-
attune_ai-2.1.
|
|
350
|
+
attune_ai-2.1.2.dist-info/licenses/LICENSE,sha256=kqe3EeGatNB79lUTHxjLnxDe7VJr0iYetThOr4_Fx7A,11348
|
|
351
|
+
attune_ai-2.1.2.dist-info/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md,sha256=JH9yAQGv_lQej5YlztI_kawbVQ2H8uVLhPGlrWnR_34,3844
|
|
351
352
|
attune_healthcare/__init__.py,sha256=4NioL1_86UXzkd-QNkQZUSZ8rKTQGSP0TC9VXP32kQs,295
|
|
352
353
|
attune_healthcare/monitors/__init__.py,sha256=Udp8qfZR504QAq5_eQjvtIaE7v06Yguc7nuF40KllQc,196
|
|
353
354
|
attune_healthcare/monitors/clinical_protocol_monitor.py,sha256=MWE5t8tW9HWZn_SNo-inx8-0nhdTNGhbcB8ZeDWyXa0,11648
|
|
@@ -449,8 +450,8 @@ workflow_scaffolding/__init__.py,sha256=UpX5vjjjPjIaAKyIV1D4GxJzLUZy5DzdzgSkePYM
|
|
|
449
450
|
workflow_scaffolding/__main__.py,sha256=0qspuNoadTDqyskXTlT8Sahqau-XIxN35NHTSGVW6z4,236
|
|
450
451
|
workflow_scaffolding/cli.py,sha256=RUVqU9SeAgm7YkM0YNd-quh8u6BNzmX8xM2y9K_p68Y,6759
|
|
451
452
|
workflow_scaffolding/generator.py,sha256=2WC02A10lzF2NQgOn66ksV17Oe72kKlU2qCQs39LIlw,8861
|
|
452
|
-
attune_ai-2.1.
|
|
453
|
-
attune_ai-2.1.
|
|
454
|
-
attune_ai-2.1.
|
|
455
|
-
attune_ai-2.1.
|
|
456
|
-
attune_ai-2.1.
|
|
453
|
+
attune_ai-2.1.2.dist-info/METADATA,sha256=4aE_g9pNuVToXXW4Zwf9ck-CJUcMG_e8MZ7jMukCkFE,45033
|
|
454
|
+
attune_ai-2.1.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
455
|
+
attune_ai-2.1.2.dist-info/entry_points.txt,sha256=GVlb04zFlpkaPtaL7X3JCZI8R0AEOZRsZjJ-wIDQvdo,1458
|
|
456
|
+
attune_ai-2.1.2.dist-info/top_level.txt,sha256=iLyjKpuOzWtwmIOZqzeBh8_SVztY2vFvhHcyo1WPtTY,73
|
|
457
|
+
attune_ai-2.1.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{attune_ai-2.1.1.dist-info → attune_ai-2.1.2.dist-info}/licenses/LICENSE_CHANGE_ANNOUNCEMENT.md
RENAMED
|
File without changes
|
|
File without changes
|