aircana 1.5.0 → 2.0.0.rc1
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.
- checksums.yaml +4 -4
- data/.rspec_status +175 -186
- data/CLAUDE.md +1 -7
- data/README.md +91 -81
- data/lib/aircana/cli/app.rb +5 -29
- data/lib/aircana/cli/commands/agents.rb +78 -0
- data/lib/aircana/cli/commands/doctor_checks.rb +0 -12
- data/lib/aircana/cli/commands/dump_context.rb +2 -3
- data/lib/aircana/cli/commands/generate.rb +3 -5
- data/lib/aircana/configuration.rb +1 -2
- data/lib/aircana/contexts/confluence.rb +1 -3
- data/lib/aircana/contexts/manifest.rb +1 -10
- data/lib/aircana/contexts/web.rb +1 -3
- data/lib/aircana/generators/agents_generator.rb +2 -6
- data/lib/aircana/generators/{relevant_files_command_generator.rb → ask_expert_command_generator.rb} +3 -13
- data/lib/aircana/generators.rb +0 -2
- data/lib/aircana/templates/agents/defaults/sub-agent-coordinator.erb +90 -0
- data/lib/aircana/templates/commands/ask_expert.erb +44 -0
- data/lib/aircana/version.rb +1 -1
- data/lib/aircana.rb +0 -2
- metadata +5 -11
- data/lib/aircana/cli/commands/add_directory.rb +0 -148
- data/lib/aircana/cli/commands/add_files.rb +0 -26
- data/lib/aircana/cli/commands/clear_files.rb +0 -16
- data/lib/aircana/cli/commands/files.rb +0 -65
- data/lib/aircana/contexts/relevant_files.rb +0 -78
- data/lib/aircana/generators/relevant_files_verbose_results_generator.rb +0 -34
- data/lib/aircana/templates/commands/add_relevant_files.erb +0 -3
- data/lib/aircana/templates/relevant_files_verbose_results.erb +0 -18
data/README.md
CHANGED
@@ -1,11 +1,27 @@
|
|
1
1
|
# Aircana
|
2
2
|
|
3
|
-
A Ruby CLI utility for context management and Claude Code integration. Aircana helps manage relevant files for development sessions, create specialized Claude Code agents, and optionally sync knowledge from Confluence.
|
4
|
-
|
5
3
|
[](https://github.com/westonkd/aircana/actions/workflows/main.yml)
|
6
4
|
[](https://badge.fury.io/rb/aircana)
|
7
5
|
|
8
|
-
##
|
6
|
+
## Intro
|
7
|
+
|
8
|
+
Aircana aims to be a "batteries-included" CLI for common needs of Instructure Engineering teams using agents in development. It provides:
|
9
|
+
|
10
|
+
Consistent artifact generation and updating of agent, slash command, and hook ERB templates.
|
11
|
+
|
12
|
+
Subagent generation for improved context window management.
|
13
|
+
|
14
|
+
Agent-accessible knowledge bases sourced from Confluence or public websites, backed by manifest files.
|
15
|
+
|
16
|
+
Development workflow with plan, record, and execute phases (record and execute phases are in progress).
|
17
|
+
|
18
|
+
SQS integration for features like Slack notifications and messages.
|
19
|
+
|
20
|
+
While Aircana includes features beneficial in many agentic contexts (like knowledge base syncing), its primary tools are built on "human-in-the-loop" principles.
|
21
|
+
|
22
|
+
## How can I try it?
|
23
|
+
|
24
|
+
### Installation
|
9
25
|
|
10
26
|
Install the gem:
|
11
27
|
|
@@ -13,106 +29,108 @@ Install the gem:
|
|
13
29
|
gem install aircana
|
14
30
|
```
|
15
31
|
|
16
|
-
|
32
|
+
Verify installation and dependency setup:
|
17
33
|
|
18
|
-
```
|
19
|
-
|
34
|
+
```bash
|
35
|
+
aircana doctor
|
20
36
|
```
|
21
37
|
|
22
|
-
|
38
|
+
Install Aircana files into your repo:
|
23
39
|
|
24
40
|
```bash
|
25
|
-
|
41
|
+
cd ~/my/repo
|
42
|
+
aircana install # This is a no-op if the repo already uses .aircana
|
26
43
|
```
|
27
44
|
|
28
|
-
|
45
|
+
### Take it for a spin
|
46
|
+
|
47
|
+
If your project previously had Aircana agents set up, run the following to populate each defined agent's knowledge base:
|
29
48
|
|
30
49
|
```bash
|
31
|
-
aircana
|
50
|
+
aircana agents refresh-all
|
32
51
|
```
|
33
52
|
|
34
|
-
|
53
|
+
To start using your agents with domain-specific knowledge, follow the agent workflow tutorial.
|
54
|
+
|
55
|
+
### Things to try
|
56
|
+
|
57
|
+
- Configure the Confluence integration and create your own domain-specific subagent
|
58
|
+
|
59
|
+
- Launch Claude Code and view the hooks installed by Aircana (prefixed with air). The /air-ask-expert command is pretty handy once you set up some agents with knowledbases.
|
60
|
+
|
61
|
+
- Set up the SQS integration to receive Slack messages when Claude Code needs your attention (documentation coming soon).
|
35
62
|
|
36
|
-
|
37
|
-
- Ruby >= 3.3.0
|
38
|
-
- `git` (version control operations)
|
39
|
-
- `fzf` (interactive file selection)
|
63
|
+
- Explore other tools by running `aircana --help`
|
40
64
|
|
41
|
-
|
42
|
-
- `bat` (enhanced file previews, falls back to `cat`)
|
43
|
-
- `fd` (faster file searching, falls back to `find`)
|
65
|
+
## Key Concepts
|
44
66
|
|
45
|
-
###
|
46
|
-
- Access to a Confluence instance
|
47
|
-
- Confluence API token
|
48
|
-
- Appropriate permissions to read pages and labels
|
67
|
+
### Subagents
|
49
68
|
|
50
|
-
|
69
|
+
Subagents are domain-specific agents to whom the primary Claude Code agent can delegate tasks and questions.
|
51
70
|
|
52
|
-
|
71
|
+
Each subagent has its own context window. Effectively using subagents can keep the main context window and per-agent context windows smaller for longer, leading to much more usable results and reducing the need to remind agents of core principles and tasks.
|
53
72
|
|
54
|
-
|
55
|
-
Track and manage a curated set of "relevant files" - the current working set of important files for your development session. This context is automatically available to Claude Code sessions.
|
73
|
+
Claude Code can also run subagents in parallel. A "swarm" of appropriately designed subagents can expedite planning and execution tasks while considering a broader context.
|
56
74
|
|
57
|
-
|
75
|
+
Aircana allows easy generation of subagents and binds each to an agent-specific knowledge base with documents from Confluence or websites.
|
58
76
|
|
59
|
-
###
|
60
|
-
Create Claude Code agents with:
|
61
|
-
- **Domain Knowledge**: Focused expertise in specific areas
|
62
|
-
- **Confluence Integration**: Knowledge sync from labeled pages (requires Confluence setup)
|
63
|
-
- **Customizable Models**: Choose from different Claude models and interface colors
|
77
|
+
### Knowledge Bases
|
64
78
|
|
65
|
-
|
79
|
+
Aircana provides each subagent access to a human-curated knowledge base. This access enables Aircana-managed subagents to yield more relevant results, minimizing back-and-forth between the human operator and the agent.
|
66
80
|
|
67
|
-
|
68
|
-
- **Relevant Files**: Current working set managed by Aircana (independent feature)
|
69
|
-
- **Confluence Pages**: Fetched based on agent labels (agent feature, requires setup)
|
70
|
-
- **Web URLs**: Any web content added to agent knowledge bases (HTML converted to Markdown)
|
71
|
-
- **Local Context**: Project-specific files and configurations
|
81
|
+
After initial agent creation, Aircana supports refreshing agents' knowledge bases with the latest versions of each source.
|
72
82
|
|
73
|
-
|
83
|
+
#### Confluence
|
74
84
|
|
75
|
-
|
76
|
-
- **Agent Configuration**: Create and configure specialized Claude Code agents
|
77
|
-
- **Confluence Integration**: Sync knowledge from Confluence pages to agents (optional)
|
78
|
-
- **Claude Code Shortcuts**: Quick-launch Claude Code with pre-configured agents
|
79
|
-
- **System Health Checks**: Validate dependencies and configuration
|
85
|
+
To add a Confluence page to an agent's knowledge base, label the desired page in Confluence, then run `aircana agent refresh <AGENT>`.
|
80
86
|
|
81
|
-
|
87
|
+
Aircana will also pull any Confluence pages labeled with a matching agent name during initial agent creation (`aircana agent create`).
|
82
88
|
|
83
|
-
|
84
|
-
```bash
|
85
|
-
gem install aircana
|
86
|
-
aircana doctor
|
87
|
-
```
|
89
|
+
See the Confluence setup guide or run `aircana doctor` for instructions on setting up Confluence integration.
|
88
90
|
|
89
|
-
|
90
|
-
```bash
|
91
|
-
cd your-project
|
92
|
-
aircana generate
|
93
|
-
aircana install # Set up Aircana integration in this project
|
94
|
-
```
|
91
|
+
#### Websites
|
95
92
|
|
96
|
-
|
97
|
-
```bash
|
98
|
-
aircana files add # Interactive selection
|
99
|
-
```
|
93
|
+
In addition to Confluence sources, Aircana allows adding arbitrary public websites to a knowledge base.
|
100
94
|
|
101
|
-
|
102
|
-
```
|
103
|
-
/add-relevant-files
|
104
|
-
```
|
95
|
+
Websites are also refreshed when `aircana agent refresh <AGENT>` is used.
|
105
96
|
|
106
|
-
|
107
|
-
```bash
|
108
|
-
aircana agents create # Tag Confluence pages with the agent's name before or after creation to pull that knowledge into the agent's knowledge base.
|
109
|
-
```
|
97
|
+
#### Structure
|
110
98
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
99
|
+
Knowledge bases are stored in the .aircana directory of each project. For example:
|
100
|
+
|
101
|
+
```
|
102
|
+
.aircana
|
103
|
+
├── agents
|
104
|
+
│ ├── canvas-backend-account-expert
|
105
|
+
│ │ ├── knowledge
|
106
|
+
│ │ │ ├── Accounts.md
|
107
|
+
│ │ │ └── Subdomains-&-Request-Routing.md
|
108
|
+
│ │ └── manifest.json
|
109
|
+
```
|
110
|
+
|
111
|
+
Agent files in the .claude/agents directory reference these files.
|
112
|
+
|
113
|
+
In many cases, adding the actual knowledge base to version control is undesirable because:
|
114
|
+
|
115
|
+
There may be numerous files in the knowledge base, bloating repository size.
|
116
|
+
|
117
|
+
Knowledge bases may contain sensitive information that should not be public in an open-source project.
|
118
|
+
|
119
|
+
Aircana manages a per-agent manifest.json file to address these concerns.
|
120
|
+
|
121
|
+
### Consistent Artifacts
|
122
|
+
|
123
|
+
Aircana maintains a set of ERB templates for generating Claude Code agents, hooks, and slash commands consistently.
|
124
|
+
|
125
|
+
These templates promote best practices and help new users quickly create effective artifacts without extensive trial and error.
|
126
|
+
|
127
|
+
### SQS Integration (Slack Integration at Instructure)
|
128
|
+
|
129
|
+
Aircana uses the "Notification" Claude Code hook to send messages to SQS.
|
130
|
+
|
131
|
+
At Instructure this means you can easily configure Claude Code to send you slack messages when it needs your attention via Aircana
|
132
|
+
|
133
|
+
(Instructions coming soon, send a message if you want help with this)
|
116
134
|
|
117
135
|
## Configuration (Optional)
|
118
136
|
|
@@ -257,14 +275,6 @@ This refreshes both Confluence pages and web URLs associated with the agent.
|
|
257
275
|
|
258
276
|
## All Commands
|
259
277
|
|
260
|
-
### File Management
|
261
|
-
```bash
|
262
|
-
aircana files add # Interactively select files to add to context
|
263
|
-
aircana files add-dir [PATH] # Add all files from directory to context
|
264
|
-
aircana files clear # Clear current file context
|
265
|
-
aircana files list # Show current relevant files
|
266
|
-
```
|
267
|
-
|
268
278
|
### Agent Management
|
269
279
|
```bash
|
270
280
|
aircana agents create # Create new agent interactively
|
data/lib/aircana/cli/app.rb
CHANGED
@@ -2,9 +2,6 @@
|
|
2
2
|
|
3
3
|
require "thor"
|
4
4
|
|
5
|
-
require_relative "commands/add_files"
|
6
|
-
require_relative "commands/add_directory"
|
7
|
-
require_relative "commands/clear_files"
|
8
5
|
require_relative "commands/doctor"
|
9
6
|
require_relative "commands/dump_context"
|
10
7
|
require_relative "commands/generate"
|
@@ -15,7 +12,6 @@ require_relative "help_formatter"
|
|
15
12
|
require_relative "commands/agents"
|
16
13
|
require_relative "commands/hooks"
|
17
14
|
require_relative "commands/project"
|
18
|
-
require_relative "commands/files"
|
19
15
|
|
20
16
|
module Aircana
|
21
17
|
module CLI
|
@@ -49,28 +45,6 @@ module Aircana
|
|
49
45
|
Install.run
|
50
46
|
end
|
51
47
|
|
52
|
-
class FilesSubcommand < Subcommand
|
53
|
-
desc "add", "Interactively add files to current context"
|
54
|
-
def add
|
55
|
-
Files.add
|
56
|
-
end
|
57
|
-
|
58
|
-
desc "add-dir [DIRECTORY_PATH]", "Add all files from directory to context"
|
59
|
-
def add_dir(directory_path)
|
60
|
-
Files.add_dir(directory_path)
|
61
|
-
end
|
62
|
-
|
63
|
-
desc "clear", "Remove all files from current context"
|
64
|
-
def clear
|
65
|
-
Files.clear
|
66
|
-
end
|
67
|
-
|
68
|
-
desc "list", "Show current relevant files"
|
69
|
-
def list
|
70
|
-
Files.list
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
48
|
class AgentsSubcommand < Subcommand
|
75
49
|
desc "create", "Create a new agent"
|
76
50
|
def create
|
@@ -91,6 +65,11 @@ module Aircana
|
|
91
65
|
def add_url(agent, url)
|
92
66
|
Agents.add_url(agent, url)
|
93
67
|
end
|
68
|
+
|
69
|
+
desc "refresh-all", "Refresh knowledge for all configured agents"
|
70
|
+
def refresh_all
|
71
|
+
Agents.refresh_all
|
72
|
+
end
|
94
73
|
end
|
95
74
|
|
96
75
|
class HooksSubcommand < Subcommand
|
@@ -147,9 +126,6 @@ module Aircana
|
|
147
126
|
end
|
148
127
|
end
|
149
128
|
|
150
|
-
desc "files", "Manage relevant files for context"
|
151
|
-
subcommand "files", FilesSubcommand
|
152
|
-
|
153
129
|
desc "agents", "Create and manage agents and their knowledgebases"
|
154
130
|
subcommand "agents", AgentsSubcommand
|
155
131
|
|
@@ -101,6 +101,38 @@ module Aircana
|
|
101
101
|
exit 1
|
102
102
|
end
|
103
103
|
|
104
|
+
def refresh_all # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
105
|
+
agent_names = all_agents
|
106
|
+
|
107
|
+
if agent_names.empty?
|
108
|
+
Aircana.human_logger.info "No agents found to refresh."
|
109
|
+
return
|
110
|
+
end
|
111
|
+
|
112
|
+
Aircana.human_logger.info "Starting refresh for #{agent_names.size} agent(s)..."
|
113
|
+
|
114
|
+
results = {
|
115
|
+
total: agent_names.size,
|
116
|
+
successful: 0,
|
117
|
+
failed: 0,
|
118
|
+
total_pages: 0,
|
119
|
+
failed_agents: []
|
120
|
+
}
|
121
|
+
|
122
|
+
agent_names.each do |agent_name|
|
123
|
+
result = refresh_single_agent(agent_name)
|
124
|
+
if result[:success]
|
125
|
+
results[:successful] += 1
|
126
|
+
results[:total_pages] += result[:pages_count]
|
127
|
+
else
|
128
|
+
results[:failed] += 1
|
129
|
+
results[:failed_agents] << { name: agent_name, error: result[:error] }
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
print_refresh_all_summary(results)
|
134
|
+
end
|
135
|
+
|
104
136
|
private
|
105
137
|
|
106
138
|
def perform_refresh(normalized_agent)
|
@@ -329,6 +361,52 @@ module Aircana
|
|
329
361
|
def find_available_editor
|
330
362
|
%w[code subl atom nano vim vi].find { |cmd| system("which #{cmd} > /dev/null 2>&1") }
|
331
363
|
end
|
364
|
+
|
365
|
+
def all_agents
|
366
|
+
agent_dir = Aircana.configuration.agent_knowledge_dir
|
367
|
+
return [] unless Dir.exist?(agent_dir)
|
368
|
+
|
369
|
+
find_agent_folders(agent_dir)
|
370
|
+
end
|
371
|
+
|
372
|
+
def refresh_single_agent(agent_name) # rubocop:disable Metrics/MethodLength
|
373
|
+
Aircana.human_logger.info "Refreshing agent '#{agent_name}'..."
|
374
|
+
|
375
|
+
begin
|
376
|
+
result = perform_manifest_aware_refresh(agent_name)
|
377
|
+
{
|
378
|
+
success: true,
|
379
|
+
pages_count: result[:pages_count],
|
380
|
+
sources: result[:sources]
|
381
|
+
}
|
382
|
+
rescue Aircana::Error => e
|
383
|
+
Aircana.human_logger.error "Failed to refresh agent '#{agent_name}': #{e.message}"
|
384
|
+
{
|
385
|
+
success: false,
|
386
|
+
pages_count: 0,
|
387
|
+
sources: [],
|
388
|
+
error: e.message
|
389
|
+
}
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
def print_refresh_all_summary(results) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
394
|
+
Aircana.human_logger.info ""
|
395
|
+
Aircana.human_logger.info "=== Refresh All Summary ==="
|
396
|
+
Aircana.human_logger.success "✓ Successful: #{results[:successful]}/#{results[:total]} agents"
|
397
|
+
Aircana.human_logger.success "✓ Total pages refreshed: #{results[:total_pages]}"
|
398
|
+
|
399
|
+
if results[:failed].positive?
|
400
|
+
Aircana.human_logger.error "✗ Failed: #{results[:failed]} agents"
|
401
|
+
Aircana.human_logger.info ""
|
402
|
+
Aircana.human_logger.info "Failed agents:"
|
403
|
+
results[:failed_agents].each do |failed_agent|
|
404
|
+
Aircana.human_logger.error " - #{failed_agent[:name]}: #{failed_agent[:error]}"
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
Aircana.human_logger.info ""
|
409
|
+
end
|
332
410
|
end
|
333
411
|
end
|
334
412
|
end
|
@@ -59,7 +59,6 @@ module Aircana
|
|
59
59
|
check_directory("~/.aircana", "Global Aircana directory")
|
60
60
|
check_directory(".aircana", "Project Aircana directory")
|
61
61
|
check_agents_status
|
62
|
-
check_relevant_files_status
|
63
62
|
end
|
64
63
|
|
65
64
|
def check_agents_status
|
@@ -74,17 +73,6 @@ module Aircana
|
|
74
73
|
log_remedy("Create agents with: aircana agents create")
|
75
74
|
end
|
76
75
|
end
|
77
|
-
|
78
|
-
def check_relevant_files_status
|
79
|
-
relevant_files_dir = File.join(Dir.pwd, ".aircana", "relevant_files")
|
80
|
-
if Dir.exist?(relevant_files_dir) && !Dir.empty?(relevant_files_dir)
|
81
|
-
file_count = Dir.glob(File.join(relevant_files_dir, "*")).size
|
82
|
-
log_success("relevant_files", "#{file_count} file(s) in context")
|
83
|
-
else
|
84
|
-
log_info("relevant_files", "No relevant files added yet")
|
85
|
-
log_remedy("Add files with: aircana add-files")
|
86
|
-
end
|
87
|
-
end
|
88
76
|
end
|
89
77
|
|
90
78
|
module OptionalIntegrations
|
@@ -1,15 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "../shell_command"
|
4
|
-
require_relative "../../contexts/relevant_files"
|
5
4
|
|
6
5
|
module Aircana
|
7
6
|
module CLI
|
8
7
|
module DumpContext
|
9
8
|
class << self
|
10
|
-
def run(_agent_name:,
|
9
|
+
def run(_agent_name:, _verbose: true)
|
11
10
|
Aircana.logger.level = Logger::ERROR
|
12
|
-
|
11
|
+
Aircana.human_logger.info("Context dumping functionality has been removed.")
|
13
12
|
end
|
14
13
|
|
15
14
|
private
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "../../generators/relevant_files_command_generator"
|
4
|
-
require_relative "../../generators/relevant_files_verbose_results_generator"
|
5
3
|
require_relative "../../generators/plan_command_generator"
|
6
4
|
require_relative "../../generators/write_plan_command_generator"
|
5
|
+
require_relative "../../generators/ask_expert_command_generator"
|
7
6
|
require_relative "../../generators/agents_generator"
|
8
7
|
require_relative "../../generators/hooks_generator"
|
9
8
|
require_relative "../../generators/project_config_generator"
|
@@ -14,10 +13,9 @@ module Aircana
|
|
14
13
|
class << self
|
15
14
|
def generators
|
16
15
|
@generators ||= [
|
17
|
-
Aircana::Generators::RelevantFilesVerboseResultsGenerator.new,
|
18
|
-
Aircana::Generators::RelevantFilesCommandGenerator.new,
|
19
16
|
Aircana::Generators::PlanCommandGenerator.new,
|
20
|
-
Aircana::Generators::WritePlanCommandGenerator.new
|
17
|
+
Aircana::Generators::WritePlanCommandGenerator.new,
|
18
|
+
Aircana::Generators::AskExpertCommandGenerator.new
|
21
19
|
]
|
22
20
|
end
|
23
21
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module Aircana
|
4
4
|
class Configuration
|
5
|
-
attr_accessor :global_dir, :project_dir, :
|
5
|
+
attr_accessor :global_dir, :project_dir, :stream, :output_dir,
|
6
6
|
:claude_code_config_path, :claude_code_project_config_path, :agent_knowledge_dir,
|
7
7
|
:hooks_dir, :confluence_base_url, :confluence_username, :confluence_api_token
|
8
8
|
|
@@ -18,7 +18,6 @@ module Aircana
|
|
18
18
|
def setup_directory_paths
|
19
19
|
@global_dir = File.join(Dir.home, ".aircana")
|
20
20
|
@project_dir = Dir.pwd
|
21
|
-
@relevant_project_files_dir = File.join(@project_dir, ".aircana", "relevant_files")
|
22
21
|
@output_dir = File.join(@global_dir, "aircana.out")
|
23
22
|
@agent_knowledge_dir = File.join(@project_dir, ".aircana", "agents")
|
24
23
|
@hooks_dir = File.join(@project_dir, ".aircana", "hooks")
|
@@ -27,10 +27,7 @@ module Aircana
|
|
27
27
|
|
28
28
|
if File.exist?(manifest_path)
|
29
29
|
existing_data = JSON.parse(File.read(manifest_path))
|
30
|
-
manifest_data = existing_data.merge({
|
31
|
-
"last_updated" => Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
32
|
-
"sources" => sources
|
33
|
-
})
|
30
|
+
manifest_data = existing_data.merge({ "sources" => sources })
|
34
31
|
else
|
35
32
|
manifest_data = build_manifest_data(agent, sources)
|
36
33
|
end
|
@@ -87,13 +84,9 @@ module Aircana
|
|
87
84
|
end
|
88
85
|
|
89
86
|
def build_manifest_data(agent, sources)
|
90
|
-
timestamp = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
91
|
-
|
92
87
|
{
|
93
88
|
"version" => "1.0",
|
94
89
|
"agent" => agent,
|
95
|
-
"created" => timestamp,
|
96
|
-
"last_updated" => timestamp,
|
97
90
|
"sources" => sources
|
98
91
|
}
|
99
92
|
end
|
@@ -157,8 +150,6 @@ module Aircana
|
|
157
150
|
raise ManifestError, "Each URL entry must be a hash" unless url_entry.is_a?(Hash)
|
158
151
|
|
159
152
|
raise ManifestError, "URL entry missing required field: url" unless url_entry.key?("url")
|
160
|
-
|
161
|
-
raise ManifestError, "URL entry missing required field: title" unless url_entry.key?("title")
|
162
153
|
end
|
163
154
|
end
|
164
155
|
end
|
data/lib/aircana/contexts/web.rb
CHANGED
@@ -7,7 +7,7 @@ module Aircana
|
|
7
7
|
class AgentsGenerator < BaseGenerator
|
8
8
|
attr_reader :agent_name, :short_description, :description, :model, :color, :default_agent
|
9
9
|
|
10
|
-
AVAILABLE_DEFAULT_AGENTS = %w[planner jira].freeze
|
10
|
+
AVAILABLE_DEFAULT_AGENTS = %w[planner jira sub-agent-coordinator].freeze
|
11
11
|
|
12
12
|
class << self
|
13
13
|
def create_default_agent(agent_name)
|
@@ -44,7 +44,7 @@ module Aircana
|
|
44
44
|
|
45
45
|
def locals
|
46
46
|
super.merge({
|
47
|
-
|
47
|
+
agent_name:, short_description:, description:,
|
48
48
|
model:, color:, knowledge_path:
|
49
49
|
})
|
50
50
|
end
|
@@ -63,10 +63,6 @@ module Aircana
|
|
63
63
|
File.join(Aircana.configuration.claude_code_project_config_path, "agents", "#{agent_name}.md")
|
64
64
|
end
|
65
65
|
|
66
|
-
def relevant_project_files_path
|
67
|
-
File.join(Aircana.configuration.relevant_project_files_dir, "relevant_files.md")
|
68
|
-
end
|
69
|
-
|
70
66
|
def knowledge_path
|
71
67
|
".aircana/agents/#{agent_name}/knowledge/"
|
72
68
|
end
|
data/lib/aircana/generators/{relevant_files_command_generator.rb → ask_expert_command_generator.rb}
RENAMED
@@ -4,7 +4,7 @@ require_relative "../generators"
|
|
4
4
|
|
5
5
|
module Aircana
|
6
6
|
module Generators
|
7
|
-
class
|
7
|
+
class AskExpertCommandGenerator < BaseGenerator
|
8
8
|
def initialize(file_in: nil, file_out: nil)
|
9
9
|
super(
|
10
10
|
file_in: file_in || default_template_path,
|
@@ -12,24 +12,14 @@ module Aircana
|
|
12
12
|
)
|
13
13
|
end
|
14
14
|
|
15
|
-
protected
|
16
|
-
|
17
|
-
def locals
|
18
|
-
super.merge({ relevant_project_files_path: })
|
19
|
-
end
|
20
|
-
|
21
15
|
private
|
22
16
|
|
23
17
|
def default_template_path
|
24
|
-
File.join(File.dirname(__FILE__), "..", "templates", "commands", "
|
18
|
+
File.join(File.dirname(__FILE__), "..", "templates", "commands", "ask_expert.erb")
|
25
19
|
end
|
26
20
|
|
27
21
|
def default_output_path
|
28
|
-
File.join(Aircana.configuration.output_dir, "commands", "air-
|
29
|
-
end
|
30
|
-
|
31
|
-
def relevant_project_files_path
|
32
|
-
File.join(Aircana.configuration.relevant_project_files_dir, "relevant_files.md")
|
22
|
+
File.join(Aircana.configuration.output_dir, "commands", "air-ask-expert.md")
|
33
23
|
end
|
34
24
|
end
|
35
25
|
end
|
data/lib/aircana/generators.rb
CHANGED