aircana 1.1.0.rc1 → 1.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64811eb3cd8c51f06884e2f4f13e9c8b95e55b1bae350e558cccde508b3076c9
4
- data.tar.gz: 61f3b8425387ada7b5f015d706d65fae1294aeb19d7b25ec35e0a22b3af6b3dc
3
+ metadata.gz: dd309e7d9e7bb2eb52d38e1e4fcc87038b37e2712aef7ccf2c66fd07d03c693e
4
+ data.tar.gz: fe066eb5c1c4dc493b711d437879c5f97c1b00be5df97a9c036b6ad9ea5a1bd9
5
5
  SHA512:
6
- metadata.gz: c7a10c4f9ec04d77d1dbc96be3aec865acde288865c837839d92d005226489e1e77031d5da2623f4d019c69a28e1855f824415fb3a2362178829e723f8acad87
7
- data.tar.gz: 234c4c2743a72b3fe899c234b94bed5e4ac964939dc77f2ba114401421ed660d8b58c18d2e4595523dd76c266dce1470563f7fa2ab53ccbe52a2192b4d28b493
6
+ metadata.gz: 2e44f4f135a4a4aa329fa708e2403e71c656fd4063b2e2e5ee74914e1f06dd2b039cafb28dbb7b64774845f463192c5b010c8131c9180a926152d297fd59f900
7
+ data.tar.gz: 4dfdf3422c2261ff41c9e4f966b14995bfe7cda36b582b4f65f8372b9a6392dca5fd3c2a230d29ac3c7d4a43f9daabffdec20667457bd75be6239d052379ea90
data/.rspec_status CHANGED
@@ -1,166 +1,204 @@
1
1
  example_id | status | run_time |
2
2
  ------------------------------------------------------------ | ------ | --------------- |
3
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:1:1] | passed | 0.00772 seconds |
4
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:2:1] | passed | 0.00102 seconds |
5
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:3:1] | passed | 0.00078 seconds |
6
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:4:1] | passed | 0.00248 seconds |
7
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:4:2:1] | passed | 0.01424 seconds |
8
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:5:1] | passed | 0.00263 seconds |
9
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:2:1] | passed | 0.00191 seconds |
10
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:2:2] | passed | 0.00177 seconds |
11
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:1] | passed | 0.00062 seconds |
12
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:2] | passed | 0.00063 seconds |
13
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:3] | passed | 0.00069 seconds |
14
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:4] | passed | 0.00063 seconds |
15
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:5] | passed | 0.00061 seconds |
16
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:6] | passed | 0.00063 seconds |
17
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:7] | passed | 0.0006 seconds |
18
- ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:8] | passed | 0.00063 seconds |
19
- ./spec/aircana/cli/commands/agents_spec.rb[1:1:1:1] | passed | 0.00042 seconds |
20
- ./spec/aircana/cli/commands/agents_spec.rb[1:1:1:2] | passed | 0.00032 seconds |
21
- ./spec/aircana/cli/commands/agents_spec.rb[1:1:1:3] | passed | 0.00044 seconds |
22
- ./spec/aircana/cli/commands/agents_spec.rb[1:1:2:1] | passed | 0.00124 seconds |
23
- ./spec/aircana/cli/commands/agents_spec.rb[1:1:3:1] | passed | 0.00035 seconds |
24
- ./spec/aircana/cli/commands/agents_spec.rb[1:1:3:2] | passed | 0.00031 seconds |
25
- ./spec/aircana/cli/commands/agents_spec.rb[1:2:1] | passed | 0.00021 seconds |
26
- ./spec/aircana/cli/commands/hooks_spec.rb[1:1:1:1] | passed | 0.00089 seconds |
27
- ./spec/aircana/cli/commands/hooks_spec.rb[1:1:2:1:1] | passed | 0.00087 seconds |
28
- ./spec/aircana/cli/commands/hooks_spec.rb[1:1:2:2:1] | passed | 0.00125 seconds |
29
- ./spec/aircana/cli/commands/hooks_spec.rb[1:2:1:1] | passed | 0.00092 seconds |
30
- ./spec/aircana/cli/commands/hooks_spec.rb[1:2:2:1] | passed | 0.00098 seconds |
31
- ./spec/aircana/cli/commands/hooks_spec.rb[1:3:1:1] | passed | 0.00079 seconds |
32
- ./spec/aircana/cli/commands/hooks_spec.rb[1:3:2:1] | passed | 0.00145 seconds |
33
- ./spec/aircana/cli/commands/hooks_spec.rb[1:4:1] | passed | 0.00411 seconds |
34
- ./spec/aircana/cli/commands/hooks_spec.rb[1:4:2:1] | passed | 0.00155 seconds |
35
- ./spec/aircana/cli/commands/hooks_spec.rb[1:5:1:1] | passed | 0.00071 seconds |
36
- ./spec/aircana/cli/commands/hooks_spec.rb[1:5:2:1] | passed | 0.00093 seconds |
37
- ./spec/aircana/cli/commands/hooks_spec.rb[1:5:3:1] | passed | 0.00124 seconds |
38
- ./spec/aircana/cli/commands/hooks_spec.rb[1:5:4:1] | passed | 0.00087 seconds |
39
- ./spec/aircana/cli/commands/hooks_spec.rb[1:6:1:1] | passed | 0.00066 seconds |
40
- ./spec/aircana/cli/commands/hooks_spec.rb[1:6:2:1] | passed | 0.00116 seconds |
41
- ./spec/aircana/cli/commands/hooks_spec.rb[1:7:1] | passed | 0.0006 seconds |
42
- ./spec/aircana/cli/commands/install_spec.rb[1:1:1:1] | passed | 0.0011 seconds |
43
- ./spec/aircana/cli/commands/install_spec.rb[1:1:2:1] | passed | 0.00182 seconds |
44
- ./spec/aircana/cli/commands/install_spec.rb[1:2:1:1] | passed | 0.00368 seconds |
45
- ./spec/aircana/cli/commands/install_spec.rb[1:2:2:1] | passed | 0.00227 seconds |
46
- ./spec/aircana/cli/commands/install_spec.rb[1:2:3:1] | passed | 0.00197 seconds |
47
- ./spec/aircana/cli/commands/install_spec.rb[1:2:4:1] | passed | 0.00264 seconds |
48
- ./spec/aircana/cli/commands/install_spec.rb[1:3:1] | passed | 0.00229 seconds |
49
- ./spec/aircana/cli/commands/install_spec.rb[1:3:2:1] | passed | 0.00228 seconds |
50
- ./spec/aircana/cli/commands/install_spec.rb[1:3:3:1] | passed | 0.00224 seconds |
51
- ./spec/aircana/cli/commands/install_spec.rb[1:3:4:1] | passed | 0.00231 seconds |
52
- ./spec/aircana/cli/commands/install_spec.rb[1:4:1] | passed | 0.00079 seconds |
53
- ./spec/aircana/cli/commands/install_spec.rb[1:4:2] | passed | 0.00076 seconds |
54
- ./spec/aircana/cli/commands/install_spec.rb[1:4:3] | passed | 0.0009 seconds |
55
- ./spec/aircana/cli/commands/install_spec.rb[1:4:4] | passed | 0.00085 seconds |
56
- ./spec/aircana/cli/commands/install_spec.rb[1:4:5] | passed | 0.00082 seconds |
57
- ./spec/aircana/cli/commands/install_spec.rb[1:5:1:1] | passed | 0.00114 seconds |
58
- ./spec/aircana/cli/commands/install_spec.rb[1:5:2:1] | passed | 0.00089 seconds |
59
- ./spec/aircana/cli/commands/install_spec.rb[1:5:3:1] | passed | 0.00136 seconds |
60
- ./spec/aircana/cli/commands/install_spec.rb[1:6:1] | passed | 0.00117 seconds |
61
- ./spec/aircana/cli/commands/plan_spec.rb[1:1:1:1] | passed | 0.00687 seconds |
62
- ./spec/aircana/cli/commands/plan_spec.rb[1:1:2:1] | passed | 0.00506 seconds |
63
- ./spec/aircana/cli/commands/plan_spec.rb[1:1:3:1] | passed | 0.00052 seconds |
64
- ./spec/aircana/cli/commands/work_spec.rb[1:1:1:1] | passed | 0.00558 seconds |
65
- ./spec/aircana/cli/commands/work_spec.rb[1:1:2:1] | passed | 0.00574 seconds |
66
- ./spec/aircana/cli/commands/work_spec.rb[1:1:3:1] | passed | 0.00056 seconds |
67
- ./spec/aircana/configuration_spec.rb[1:1:1] | passed | 0.00021 seconds |
68
- ./spec/aircana/configuration_spec.rb[1:2:1] | passed | 0.00007 seconds |
69
- ./spec/aircana/configuration_spec.rb[1:3:1] | passed | 0.0001 seconds |
70
- ./spec/aircana/configuration_spec.rb[1:4:1] | passed | 0.00019 seconds |
71
- ./spec/aircana/configuration_spec.rb[1:5:1] | passed | 0.00012 seconds |
72
- ./spec/aircana/configuration_spec.rb[1:5:2] | passed | 0.00008 seconds |
73
- ./spec/aircana/contexts/confluence_spec.rb[1:1:1:1] | passed | 0.00648 seconds |
74
- ./spec/aircana/contexts/confluence_spec.rb[1:1:1:2] | passed | 0.00066 seconds |
75
- ./spec/aircana/contexts/confluence_spec.rb[1:1:1:3] | passed | 0.00155 seconds |
76
- ./spec/aircana/contexts/confluence_spec.rb[1:1:2:1] | passed | 0.00019 seconds |
77
- ./spec/aircana/contexts/confluence_spec.rb[1:1:2:2] | passed | 0.00013 seconds |
3
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:1:1] | passed | 0.00582 seconds |
4
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:2:1] | passed | 0.00084 seconds |
5
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:3:1] | passed | 0.00108 seconds |
6
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:4:1] | passed | 0.00293 seconds |
7
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:4:2:1] | passed | 0.0156 seconds |
8
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:1:5:1] | passed | 0.00305 seconds |
9
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:2:1] | passed | 0.00206 seconds |
10
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:2:2] | passed | 0.00277 seconds |
11
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:1] | passed | 0.00082 seconds |
12
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:2] | passed | 0.0007 seconds |
13
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:3] | passed | 0.00107 seconds |
14
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:4] | passed | 0.00076 seconds |
15
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:5] | passed | 0.00076 seconds |
16
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:6] | passed | 0.00068 seconds |
17
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:7] | passed | 0.00081 seconds |
18
+ ./spec/aircana/cli/commands/add_directory_spec.rb[1:3:8] | passed | 0.0009 seconds |
19
+ ./spec/aircana/cli/commands/agents_spec.rb[1:1:1:1] | passed | 0.00553 seconds |
20
+ ./spec/aircana/cli/commands/agents_spec.rb[1:1:1:2] | passed | 0.00034 seconds |
21
+ ./spec/aircana/cli/commands/agents_spec.rb[1:1:1:3] | passed | 0.00048 seconds |
22
+ ./spec/aircana/cli/commands/agents_spec.rb[1:1:2:1] | passed | 0.00116 seconds |
23
+ ./spec/aircana/cli/commands/agents_spec.rb[1:1:3:1] | passed | 0.0004 seconds |
24
+ ./spec/aircana/cli/commands/agents_spec.rb[1:1:3:2] | passed | 0.00036 seconds |
25
+ ./spec/aircana/cli/commands/agents_spec.rb[1:2:1:1] | passed | 0.0012 seconds |
26
+ ./spec/aircana/cli/commands/agents_spec.rb[1:2:1:2] | passed | 0.0022 seconds |
27
+ ./spec/aircana/cli/commands/agents_spec.rb[1:2:1:3:1] | passed | 0.00191 seconds |
28
+ ./spec/aircana/cli/commands/agents_spec.rb[1:2:2:1] | passed | 0.00255 seconds |
29
+ ./spec/aircana/cli/commands/agents_spec.rb[1:2:3:1] | passed | 0.00113 seconds |
30
+ ./spec/aircana/cli/commands/agents_spec.rb[1:2:4:1] | passed | 0.00039 seconds |
31
+ ./spec/aircana/cli/commands/agents_spec.rb[1:3:1] | passed | 0.00096 seconds |
32
+ ./spec/aircana/cli/commands/agents_spec.rb[1:3:2] | passed | 0.00042 seconds |
33
+ ./spec/aircana/cli/commands/agents_spec.rb[1:3:3] | passed | 0.00046 seconds |
34
+ ./spec/aircana/cli/commands/agents_spec.rb[1:4:1] | passed | 0.0002 seconds |
35
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:1:1:1] | passed | 0.00083 seconds |
36
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:1:2:1:1] | passed | 0.00074 seconds |
37
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:1:2:2:1] | passed | 0.00155 seconds |
38
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:2:1:1] | passed | 0.00088 seconds |
39
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:2:2:1] | passed | 0.00088 seconds |
40
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:3:1:1] | passed | 0.00072 seconds |
41
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:3:2:1] | passed | 0.00137 seconds |
42
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:4:1] | passed | 0.00122 seconds |
43
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:4:2:1] | passed | 0.00112 seconds |
44
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:5:1:1] | passed | 0.00059 seconds |
45
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:5:2:1] | passed | 0.00072 seconds |
46
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:5:3:1] | passed | 0.00078 seconds |
47
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:5:4:1] | passed | 0.00073 seconds |
48
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:6:1:1] | passed | 0.00056 seconds |
49
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:6:2:1] | passed | 0.00092 seconds |
50
+ ./spec/aircana/cli/commands/hooks_spec.rb[1:7:1] | passed | 0.00091 seconds |
51
+ ./spec/aircana/cli/commands/install_spec.rb[1:1:1:1] | passed | 0.00107 seconds |
52
+ ./spec/aircana/cli/commands/install_spec.rb[1:1:2:1] | passed | 0.00167 seconds |
53
+ ./spec/aircana/cli/commands/install_spec.rb[1:2:1:1] | passed | 0.0033 seconds |
54
+ ./spec/aircana/cli/commands/install_spec.rb[1:2:2:1] | passed | 0.00267 seconds |
55
+ ./spec/aircana/cli/commands/install_spec.rb[1:2:3:1] | passed | 0.00505 seconds |
56
+ ./spec/aircana/cli/commands/install_spec.rb[1:2:4:1] | passed | 0.00216 seconds |
57
+ ./spec/aircana/cli/commands/install_spec.rb[1:3:1] | passed | 0.00201 seconds |
58
+ ./spec/aircana/cli/commands/install_spec.rb[1:3:2:1] | passed | 0.00198 seconds |
59
+ ./spec/aircana/cli/commands/install_spec.rb[1:3:3:1] | passed | 0.00269 seconds |
60
+ ./spec/aircana/cli/commands/install_spec.rb[1:3:4:1] | passed | 0.00248 seconds |
61
+ ./spec/aircana/cli/commands/install_spec.rb[1:4:1] | passed | 0.00099 seconds |
62
+ ./spec/aircana/cli/commands/install_spec.rb[1:4:2] | passed | 0.00128 seconds |
63
+ ./spec/aircana/cli/commands/install_spec.rb[1:4:3] | passed | 0.00112 seconds |
64
+ ./spec/aircana/cli/commands/install_spec.rb[1:4:4] | passed | 0.00082 seconds |
65
+ ./spec/aircana/cli/commands/install_spec.rb[1:4:5] | passed | 0.00083 seconds |
66
+ ./spec/aircana/cli/commands/install_spec.rb[1:5:1:1] | passed | 0.00121 seconds |
67
+ ./spec/aircana/cli/commands/install_spec.rb[1:5:2:1] | passed | 0.00081 seconds |
68
+ ./spec/aircana/cli/commands/install_spec.rb[1:5:3:1] | passed | 0.00111 seconds |
69
+ ./spec/aircana/cli/commands/install_spec.rb[1:6:1] | passed | 0.00106 seconds |
70
+ ./spec/aircana/cli/commands/plan_spec.rb[1:1:1:1] | passed | 0.01347 seconds |
71
+ ./spec/aircana/cli/commands/plan_spec.rb[1:1:2:1] | passed | 0.00625 seconds |
72
+ ./spec/aircana/cli/commands/plan_spec.rb[1:1:3:1] | passed | 0.00059 seconds |
73
+ ./spec/aircana/cli/commands/work_spec.rb[1:1:1:1] | passed | 0.0054 seconds |
74
+ ./spec/aircana/cli/commands/work_spec.rb[1:1:2:1] | passed | 0.0049 seconds |
75
+ ./spec/aircana/cli/commands/work_spec.rb[1:1:3:1] | passed | 0.0009 seconds |
76
+ ./spec/aircana/configuration_spec.rb[1:1:1] | passed | 0.00027 seconds |
77
+ ./spec/aircana/configuration_spec.rb[1:2:1] | passed | 0.00009 seconds |
78
+ ./spec/aircana/configuration_spec.rb[1:3:1] | passed | 0.00008 seconds |
79
+ ./spec/aircana/configuration_spec.rb[1:4:1] | passed | 0.00008 seconds |
80
+ ./spec/aircana/configuration_spec.rb[1:5:1] | passed | 0.00016 seconds |
81
+ ./spec/aircana/configuration_spec.rb[1:5:2] | passed | 0.00007 seconds |
82
+ ./spec/aircana/contexts/confluence_spec.rb[1:1:1:1] | passed | 0.00224 seconds |
83
+ ./spec/aircana/contexts/confluence_spec.rb[1:1:1:2] | passed | 0.00055 seconds |
84
+ ./spec/aircana/contexts/confluence_spec.rb[1:1:1:3] | passed | 0.0011 seconds |
85
+ ./spec/aircana/contexts/confluence_spec.rb[1:1:2:1] | passed | 0.00018 seconds |
86
+ ./spec/aircana/contexts/confluence_spec.rb[1:1:2:2] | passed | 0.00014 seconds |
78
87
  ./spec/aircana/contexts/confluence_spec.rb[1:1:2:3] | passed | 0.00012 seconds |
79
- ./spec/aircana/contexts/confluence_spec.rb[1:1:3:1] | passed | 0.00047 seconds |
80
- ./spec/aircana/contexts/confluence_spec.rb[1:1:3:2] | passed | 0.00047 seconds |
81
- ./spec/aircana/contexts/local_spec.rb[1:1:1] | passed | 0.0013 seconds |
82
- ./spec/aircana/contexts/local_spec.rb[1:1:2] | passed | 0.00106 seconds |
83
- ./spec/aircana/contexts/local_spec.rb[1:1:3] | passed | 0.00102 seconds |
84
- ./spec/aircana/contexts/local_spec.rb[1:1:4] | passed | 0.00096 seconds |
85
- ./spec/aircana/contexts/local_spec.rb[1:1:5] | passed | 0.00101 seconds |
86
- ./spec/aircana/contexts/local_spec.rb[1:1:6] | passed | 0.00136 seconds |
87
- ./spec/aircana/contexts/local_spec.rb[1:1:7] | passed | 0.00158 seconds |
88
- ./spec/aircana/contexts/local_spec.rb[1:1:8] | passed | 0.00126 seconds |
89
- ./spec/aircana/contexts/manifest_spec.rb[1:1:1] | passed | 0.00096 seconds |
90
- ./spec/aircana/contexts/manifest_spec.rb[1:1:2] | passed | 0.00084 seconds |
91
- ./spec/aircana/contexts/manifest_spec.rb[1:2:1] | passed | 1.02 seconds |
92
- ./spec/aircana/contexts/manifest_spec.rb[1:2:2] | passed | 0.00189 seconds |
93
- ./spec/aircana/contexts/manifest_spec.rb[1:3:1] | passed | 0.00188 seconds |
94
- ./spec/aircana/contexts/manifest_spec.rb[1:3:2] | passed | 0.00039 seconds |
95
- ./spec/aircana/contexts/manifest_spec.rb[1:3:3] | passed | 0.0015 seconds |
96
- ./spec/aircana/contexts/manifest_spec.rb[1:3:4] | passed | 0.00208 seconds |
97
- ./spec/aircana/contexts/manifest_spec.rb[1:4:1] | passed | 0.00217 seconds |
98
- ./spec/aircana/contexts/manifest_spec.rb[1:4:2] | passed | 0.00051 seconds |
99
- ./spec/aircana/contexts/manifest_spec.rb[1:5:1] | passed | 0.00185 seconds |
100
- ./spec/aircana/contexts/manifest_spec.rb[1:5:2] | passed | 0.00046 seconds |
88
+ ./spec/aircana/contexts/confluence_spec.rb[1:1:3:1] | passed | 0.00041 seconds |
89
+ ./spec/aircana/contexts/confluence_spec.rb[1:1:3:2] | passed | 0.00043 seconds |
90
+ ./spec/aircana/contexts/local_spec.rb[1:1:1] | passed | 0.00148 seconds |
91
+ ./spec/aircana/contexts/local_spec.rb[1:1:2] | passed | 0.00123 seconds |
92
+ ./spec/aircana/contexts/local_spec.rb[1:1:3] | passed | 0.00144 seconds |
93
+ ./spec/aircana/contexts/local_spec.rb[1:1:4] | passed | 0.00112 seconds |
94
+ ./spec/aircana/contexts/local_spec.rb[1:1:5] | passed | 0.00135 seconds |
95
+ ./spec/aircana/contexts/local_spec.rb[1:1:6] | passed | 0.00118 seconds |
96
+ ./spec/aircana/contexts/local_spec.rb[1:1:7] | passed | 0.00203 seconds |
97
+ ./spec/aircana/contexts/local_spec.rb[1:1:8] | passed | 0.00123 seconds |
98
+ ./spec/aircana/contexts/manifest_spec.rb[1:1:1] | passed | 0.00088 seconds |
99
+ ./spec/aircana/contexts/manifest_spec.rb[1:1:2] | passed | 0.00086 seconds |
100
+ ./spec/aircana/contexts/manifest_spec.rb[1:2:1] | passed | 1.01 seconds |
101
+ ./spec/aircana/contexts/manifest_spec.rb[1:2:2] | passed | 0.00168 seconds |
102
+ ./spec/aircana/contexts/manifest_spec.rb[1:3:1] | passed | 0.00153 seconds |
103
+ ./spec/aircana/contexts/manifest_spec.rb[1:3:2] | passed | 0.00052 seconds |
104
+ ./spec/aircana/contexts/manifest_spec.rb[1:3:3] | passed | 0.00152 seconds |
105
+ ./spec/aircana/contexts/manifest_spec.rb[1:3:4] | passed | 0.00156 seconds |
106
+ ./spec/aircana/contexts/manifest_spec.rb[1:4:1] | passed | 0.00142 seconds |
107
+ ./spec/aircana/contexts/manifest_spec.rb[1:4:2] | passed | 0.00058 seconds |
108
+ ./spec/aircana/contexts/manifest_spec.rb[1:5:1] | passed | 0.00214 seconds |
109
+ ./spec/aircana/contexts/manifest_spec.rb[1:5:2] | passed | 0.00039 seconds |
101
110
  ./spec/aircana/contexts/manifest_spec.rb[1:6:1] | passed | 0.00046 seconds |
102
- ./spec/aircana/contexts/manifest_spec.rb[1:6:2] | passed | 0.00054 seconds |
103
- ./spec/aircana/contexts/manifest_spec.rb[1:6:3] | passed | 0.00051 seconds |
104
- ./spec/aircana/fzf_helper_spec.rb[1:1:1:1] | passed | 0.0006 seconds |
105
- ./spec/aircana/fzf_helper_spec.rb[1:1:1:2] | passed | 0.00043 seconds |
106
- ./spec/aircana/fzf_helper_spec.rb[1:1:1:3] | passed | 0.00068 seconds |
107
- ./spec/aircana/fzf_helper_spec.rb[1:1:2:1] | passed | 0.00075 seconds |
108
- ./spec/aircana/fzf_helper_spec.rb[1:1:3:1] | passed | 0.00084 seconds |
109
- ./spec/aircana/fzf_helper_spec.rb[1:2:1:1] | passed | 0.00032 seconds |
110
- ./spec/aircana/fzf_helper_spec.rb[1:2:1:2] | passed | 0.0003 seconds |
111
- ./spec/aircana/fzf_helper_spec.rb[1:2:1:3] | passed | 0.00029 seconds |
112
- ./spec/aircana/fzf_helper_spec.rb[1:2:2:1] | passed | 0.0003 seconds |
113
- ./spec/aircana/fzf_helper_spec.rb[1:2:2:2] | passed | 0.00022 seconds |
114
- ./spec/aircana/generators/agents_generator_spec.rb[1:1:1] | passed | 0.00009 seconds |
115
- ./spec/aircana/generators/agents_generator_spec.rb[1:2:1] | passed | 0.00096 seconds |
116
- ./spec/aircana/generators/agents_generator_spec.rb[1:2:2] | passed | 0.00032 seconds |
117
- ./spec/aircana/generators/agents_generator_spec.rb[1:3:1:1] | passed | 0.00011 seconds |
118
- ./spec/aircana/generators/agents_generator_spec.rb[1:3:1:2] | passed | 0.00008 seconds |
119
- ./spec/aircana/generators/agents_generator_spec.rb[1:3:2:1] | passed | 0.00008 seconds |
120
- ./spec/aircana/generators/agents_generator_spec.rb[1:3:2:2] | passed | 0.00008 seconds |
121
- ./spec/aircana/generators/agents_generator_spec.rb[1:4:1:1] | passed | 0.00009 seconds |
122
- ./spec/aircana/generators/agents_generator_spec.rb[1:4:2:1] | passed | 0.00008 seconds |
111
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:2] | passed | 0.00042 seconds |
112
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:3] | passed | 0.00042 seconds |
113
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:4] | passed | 0.00038 seconds |
114
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:5] | passed | 0.00038 seconds |
115
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:6] | passed | 0.00036 seconds |
116
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:7] | passed | 0.00036 seconds |
117
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:8] | passed | 0.00036 seconds |
118
+ ./spec/aircana/contexts/manifest_spec.rb[1:6:9] | passed | 0.00151 seconds |
119
+ ./spec/aircana/contexts/web_spec.rb[1:1:1] | passed | 0.00033 seconds |
120
+ ./spec/aircana/contexts/web_spec.rb[1:2:1] | passed | 0.00032 seconds |
121
+ ./spec/aircana/contexts/web_spec.rb[1:3:1:1] | passed | 0.00022 seconds |
122
+ ./spec/aircana/contexts/web_spec.rb[1:3:1:2] | passed | 0.00019 seconds |
123
+ ./spec/aircana/contexts/web_spec.rb[1:3:1:3] | passed | 0.00018 seconds |
124
+ ./spec/aircana/contexts/web_spec.rb[1:3:2:1] | passed | 0.00041 seconds |
125
+ ./spec/aircana/contexts/web_spec.rb[1:3:2:2] | passed | 0.00033 seconds |
126
+ ./spec/aircana/contexts/web_spec.rb[1:3:3:1] | passed | 0.00029 seconds |
127
+ ./spec/aircana/contexts/web_spec.rb[1:3:3:2] | passed | 0.0004 seconds |
128
+ ./spec/aircana/contexts/web_spec.rb[1:3:3:3] | passed | 0.00036 seconds |
129
+ ./spec/aircana/contexts/web_spec.rb[1:3:3:4] | passed | 0.00022 seconds |
130
+ ./spec/aircana/contexts/web_spec.rb[1:3:3:5] | passed | 0.00394 seconds |
131
+ ./spec/aircana/contexts/web_spec.rb[1:3:4:1] | passed | 0.00022 seconds |
132
+ ./spec/aircana/contexts/web_spec.rb[1:3:4:2] | passed | 0.00017 seconds |
133
+ ./spec/aircana/contexts/web_spec.rb[1:3:4:3] | passed | 0.00017 seconds |
134
+ ./spec/aircana/contexts/web_spec.rb[1:3:5:1] | passed | 0.0006 seconds |
135
+ ./spec/aircana/contexts/web_spec.rb[1:3:5:2] | passed | 0.00017 seconds |
136
+ ./spec/aircana/contexts/web_spec.rb[1:3:5:3] | passed | 0.00092 seconds |
137
+ ./spec/aircana/contexts/web_spec.rb[1:3:6:1] | passed | 0.00036 seconds |
138
+ ./spec/aircana/contexts/web_spec.rb[1:3:6:2] | passed | 0.00035 seconds |
139
+ ./spec/aircana/contexts/web_spec.rb[1:3:6:3] | passed | 0.00033 seconds |
140
+ ./spec/aircana/contexts/web_spec.rb[1:3:7:1] | passed | 0.00016 seconds |
141
+ ./spec/aircana/contexts/web_spec.rb[1:3:7:2] | passed | 0.00042 seconds |
142
+ ./spec/aircana/fzf_helper_spec.rb[1:1:1:1] | passed | 0.00024 seconds |
143
+ ./spec/aircana/fzf_helper_spec.rb[1:1:1:2] | passed | 0.00021 seconds |
144
+ ./spec/aircana/fzf_helper_spec.rb[1:1:1:3] | passed | 0.00026 seconds |
145
+ ./spec/aircana/fzf_helper_spec.rb[1:1:2:1] | passed | 0.00042 seconds |
146
+ ./spec/aircana/fzf_helper_spec.rb[1:1:3:1] | passed | 0.00054 seconds |
147
+ ./spec/aircana/fzf_helper_spec.rb[1:2:1:1] | passed | 0.00017 seconds |
148
+ ./spec/aircana/fzf_helper_spec.rb[1:2:1:2] | passed | 0.00014 seconds |
149
+ ./spec/aircana/fzf_helper_spec.rb[1:2:1:3] | passed | 0.00014 seconds |
150
+ ./spec/aircana/fzf_helper_spec.rb[1:2:2:1] | passed | 0.00014 seconds |
151
+ ./spec/aircana/fzf_helper_spec.rb[1:2:2:2] | passed | 0.00011 seconds |
152
+ ./spec/aircana/generators/agents_generator_spec.rb[1:1:1] | passed | 0.00005 seconds |
153
+ ./spec/aircana/generators/agents_generator_spec.rb[1:2:1] | passed | 0.00041 seconds |
154
+ ./spec/aircana/generators/agents_generator_spec.rb[1:2:2] | passed | 0.00042 seconds |
155
+ ./spec/aircana/generators/agents_generator_spec.rb[1:3:1:1] | passed | 0.00009 seconds |
156
+ ./spec/aircana/generators/agents_generator_spec.rb[1:3:1:2] | passed | 0.00005 seconds |
157
+ ./spec/aircana/generators/agents_generator_spec.rb[1:3:2:1] | passed | 0.00005 seconds |
158
+ ./spec/aircana/generators/agents_generator_spec.rb[1:3:2:2] | passed | 0.00005 seconds |
159
+ ./spec/aircana/generators/agents_generator_spec.rb[1:4:1:1] | passed | 0.00006 seconds |
160
+ ./spec/aircana/generators/agents_generator_spec.rb[1:4:2:1] | passed | 0.00016 seconds |
123
161
  ./spec/aircana/generators/hooks_generator_spec.rb[1:1:1] | passed | 0.00006 seconds |
124
- ./spec/aircana/generators/hooks_generator_spec.rb[1:2:1] | passed | 0.00006 seconds |
125
- ./spec/aircana/generators/hooks_generator_spec.rb[1:3:1] | passed | 0.00077 seconds |
126
- ./spec/aircana/generators/hooks_generator_spec.rb[1:3:2] | passed | 0.0005 seconds |
127
- ./spec/aircana/generators/hooks_generator_spec.rb[1:4:1] | passed | 0.00018 seconds |
128
- ./spec/aircana/generators/hooks_generator_spec.rb[1:5:1:1] | passed | 0.0002 seconds |
129
- ./spec/aircana/generators/hooks_generator_spec.rb[1:5:2:1] | passed | 0.00008 seconds |
130
- ./spec/aircana/generators/hooks_generator_spec.rb[1:6:1] | passed | 0.00134 seconds |
131
- ./spec/aircana/generators/hooks_generator_spec.rb[1:7:1] | passed | 0.00048 seconds |
132
- ./spec/aircana/human_logger_spec.rb[1:1:1] | passed | 0.00014 seconds |
133
- ./spec/aircana/human_logger_spec.rb[1:2:1] | passed | 0.00009 seconds |
134
- ./spec/aircana/human_logger_spec.rb[1:3:1] | passed | 0.00009 seconds |
135
- ./spec/aircana/human_logger_spec.rb[1:4:1] | passed | 0.00009 seconds |
136
- ./spec/aircana/human_logger_spec.rb[1:5:1] | passed | 0.00007 seconds |
137
- ./spec/aircana/human_logger_spec.rb[1:5:2] | passed | 0.00008 seconds |
138
- ./spec/aircana/human_logger_spec.rb[1:5:3] | passed | 0.00007 seconds |
139
- ./spec/aircana/human_logger_spec.rb[1:5:4] | passed | 0.00007 seconds |
140
- ./spec/aircana/human_logger_spec.rb[1:5:5] | passed | 0.00007 seconds |
141
- ./spec/aircana/human_logger_spec.rb[1:5:6] | passed | 0.00007 seconds |
142
- ./spec/aircana/human_logger_spec.rb[1:5:7] | passed | 0.00008 seconds |
143
- ./spec/aircana/human_logger_spec.rb[1:6:1] | passed | 0.00006 seconds |
144
- ./spec/aircana/llm/claude_client_spec.rb[1:1:1:1] | passed | 0.00086 seconds |
145
- ./spec/aircana/llm/claude_client_spec.rb[1:1:1:2] | passed | 0.00072 seconds |
146
- ./spec/aircana/llm/claude_client_spec.rb[1:1:1:3] | passed | 0.0006 seconds |
147
- ./spec/aircana/llm/claude_client_spec.rb[1:1:1:4] | passed | 0.0006 seconds |
148
- ./spec/aircana/llm/claude_client_spec.rb[1:1:2:1] | passed | 0.00068 seconds |
149
- ./spec/aircana/llm/claude_client_spec.rb[1:1:2:2] | passed | 0.00061 seconds |
150
- ./spec/aircana/llm/claude_client_spec.rb[1:1:3:1] | passed | 0.00066 seconds |
151
- ./spec/aircana/llm/claude_client_spec.rb[1:2:1] | passed | 0.00074 seconds |
152
- ./spec/aircana/llm/claude_client_spec.rb[1:2:2] | passed | 0.00058 seconds |
153
- ./spec/aircana/llm/claude_client_spec.rb[1:3:1:1] | passed | 0.00043 seconds |
154
- ./spec/aircana/llm/claude_client_spec.rb[1:3:1:2] | passed | 0.00076 seconds |
155
- ./spec/aircana/system_checker_spec.rb[1:1:1:1] | passed | 0.00064 seconds |
156
- ./spec/aircana/system_checker_spec.rb[1:1:2:1] | passed | 0.00077 seconds |
157
- ./spec/aircana/system_checker_spec.rb[1:1:3:1] | passed | 0.00098 seconds |
158
- ./spec/aircana/system_checker_spec.rb[1:2:1] | passed | 0.00038 seconds |
159
- ./spec/aircana/system_checker_spec.rb[1:2:2] | passed | 0.0004 seconds |
160
- ./spec/aircana/system_checker_spec.rb[1:3:1] | passed | 0.00035 seconds |
161
- ./spec/aircana/system_checker_spec.rb[1:3:2] | passed | 0.00039 seconds |
162
- ./spec/aircana/system_checker_spec.rb[1:3:3] | passed | 0.00044 seconds |
163
- ./spec/aircana/system_checker_spec.rb[1:3:4] | passed | 0.00049 seconds |
164
- ./spec/aircana/system_checker_spec.rb[1:3:5] | passed | 0.00028 seconds |
165
- ./spec/aircana_spec.rb[1:1] | passed | 0.0001 seconds |
166
- ./spec/aircana_spec.rb[1:2] | passed | 0.0012 seconds |
162
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:2:1] | passed | 0.00004 seconds |
163
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:3:1] | passed | 0.00065 seconds |
164
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:3:2] | passed | 0.00027 seconds |
165
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:4:1] | passed | 0.00012 seconds |
166
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:5:1:1] | passed | 0.00013 seconds |
167
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:5:2:1] | passed | 0.00005 seconds |
168
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:6:1] | passed | 0.00074 seconds |
169
+ ./spec/aircana/generators/hooks_generator_spec.rb[1:7:1] | passed | 0.00022 seconds |
170
+ ./spec/aircana/human_logger_spec.rb[1:1:1] | passed | 0.00008 seconds |
171
+ ./spec/aircana/human_logger_spec.rb[1:2:1] | passed | 0.00017 seconds |
172
+ ./spec/aircana/human_logger_spec.rb[1:3:1] | passed | 0.00005 seconds |
173
+ ./spec/aircana/human_logger_spec.rb[1:4:1] | passed | 0.00005 seconds |
174
+ ./spec/aircana/human_logger_spec.rb[1:5:1] | passed | 0.00004 seconds |
175
+ ./spec/aircana/human_logger_spec.rb[1:5:2] | passed | 0.00004 seconds |
176
+ ./spec/aircana/human_logger_spec.rb[1:5:3] | passed | 0.00004 seconds |
177
+ ./spec/aircana/human_logger_spec.rb[1:5:4] | passed | 0.00004 seconds |
178
+ ./spec/aircana/human_logger_spec.rb[1:5:5] | passed | 0.00004 seconds |
179
+ ./spec/aircana/human_logger_spec.rb[1:5:6] | passed | 0.00004 seconds |
180
+ ./spec/aircana/human_logger_spec.rb[1:5:7] | passed | 0.00004 seconds |
181
+ ./spec/aircana/human_logger_spec.rb[1:6:1] | passed | 0.00004 seconds |
182
+ ./spec/aircana/llm/claude_client_spec.rb[1:1:1:1] | passed | 0.00064 seconds |
183
+ ./spec/aircana/llm/claude_client_spec.rb[1:1:1:2] | passed | 0.00068 seconds |
184
+ ./spec/aircana/llm/claude_client_spec.rb[1:1:1:3] | passed | 0.00048 seconds |
185
+ ./spec/aircana/llm/claude_client_spec.rb[1:1:1:4] | passed | 0.00044 seconds |
186
+ ./spec/aircana/llm/claude_client_spec.rb[1:1:2:1] | passed | 0.00066 seconds |
187
+ ./spec/aircana/llm/claude_client_spec.rb[1:1:2:2] | passed | 0.0004 seconds |
188
+ ./spec/aircana/llm/claude_client_spec.rb[1:1:3:1] | passed | 0.00041 seconds |
189
+ ./spec/aircana/llm/claude_client_spec.rb[1:2:1] | passed | 0.00037 seconds |
190
+ ./spec/aircana/llm/claude_client_spec.rb[1:2:2] | passed | 0.00037 seconds |
191
+ ./spec/aircana/llm/claude_client_spec.rb[1:3:1:1] | passed | 0.00026 seconds |
192
+ ./spec/aircana/llm/claude_client_spec.rb[1:3:1:2] | passed | 0.00024 seconds |
193
+ ./spec/aircana/system_checker_spec.rb[1:1:1:1] | passed | 0.00034 seconds |
194
+ ./spec/aircana/system_checker_spec.rb[1:1:2:1] | passed | 0.0005 seconds |
195
+ ./spec/aircana/system_checker_spec.rb[1:1:3:1] | passed | 0.00062 seconds |
196
+ ./spec/aircana/system_checker_spec.rb[1:2:1] | passed | 0.00025 seconds |
197
+ ./spec/aircana/system_checker_spec.rb[1:2:2] | passed | 0.00025 seconds |
198
+ ./spec/aircana/system_checker_spec.rb[1:3:1] | passed | 0.00025 seconds |
199
+ ./spec/aircana/system_checker_spec.rb[1:3:2] | passed | 0.00025 seconds |
200
+ ./spec/aircana/system_checker_spec.rb[1:3:3] | passed | 0.0003 seconds |
201
+ ./spec/aircana/system_checker_spec.rb[1:3:4] | passed | 0.00041 seconds |
202
+ ./spec/aircana/system_checker_spec.rb[1:3:5] | passed | 0.0002 seconds |
203
+ ./spec/aircana_spec.rb[1:1] | passed | 0.00004 seconds |
204
+ ./spec/aircana_spec.rb[1:2] | passed | 0.0009 seconds |
data/CLAUDE.md CHANGED
@@ -36,7 +36,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
36
36
  - `aircana plan` - Launch Claude Code with planner agent (experimental)
37
37
  - `aircana work` - Launch Claude Code with worker agent (experimental)
38
38
  - `aircana agents create` - Create a new agent interactively
39
- - `aircana agents refresh <agent>` - Refresh agent knowledge from Confluence
39
+ - `aircana agents refresh <agent>` - Refresh agent knowledge from Confluence and web sources
40
+ - `aircana agents add-url <agent> <url>` - Add a web URL to an agent's knowledge base
40
41
  - `aircana hooks list` - List all available hooks
41
42
  - `aircana hooks enable <hook>` - Enable a specific hook
42
43
  - `aircana hooks disable <hook>` - Disable a specific hook
@@ -57,6 +58,7 @@ Aircana is a Ruby gem that provides context management and workflow utilities fo
57
58
  - `relevant_files.rb`: Manages current working file set
58
59
  - `confluence.rb`: Handles Confluence page fetching and caching
59
60
  - `confluence_content.rb`: Processes Confluence content
61
+ - `web.rb`: Handles web URL fetching and HTML to Markdown conversion
60
62
  - `local.rb`: Local file context management
61
63
  - **Generators** (`lib/aircana/generators/`): Template generation system
62
64
  - `base_generator.rb`: Base class for all generators
@@ -95,9 +97,21 @@ Aircana is a Ruby gem that provides context management and workflow utilities fo
95
97
  - Rubocop configured with custom rules in `.rubocop.yml`
96
98
  - String style enforced as double quotes
97
99
 
98
- ### Confluence Integration
99
- When configured, agents can sync knowledge from Confluence:
100
+ ### Knowledge Sources
101
+ Agents can sync knowledge from multiple sources:
102
+
103
+ **Confluence Integration:**
100
104
  - Set environment variables: `CONFLUENCE_BASE_URL`, `CONFLUENCE_USERNAME`, `CONFLUENCE_API_TOKEN`
101
105
  - Pages are fetched based on agent name as label
102
106
  - Content cached locally for offline access
103
- - Refresh with `aircana agents refresh <agent>`
107
+
108
+ **Web URL Integration:**
109
+ - Add URLs directly to agent knowledge bases
110
+ - HTML content is automatically converted to Markdown
111
+ - Interactive URL collection during agent creation
112
+ - Add individual URLs: `aircana agents add-url <agent> <url>`
113
+
114
+ **Unified Management:**
115
+ - Both sources tracked in manifest.json for each agent
116
+ - Refresh all sources with `aircana agents refresh <agent>`
117
+ - Content stored as Markdown files in `.aircana/agents/<agent>/knowledge/`
@@ -88,6 +88,11 @@ module Aircana
88
88
  def list
89
89
  Agents.list
90
90
  end
91
+
92
+ desc "add-url AGENT URL", "Add a web URL to an agent's knowledge base"
93
+ def add_url(agent, url)
94
+ Agents.add_url(agent, url)
95
+ end
91
96
  end
92
97
 
93
98
  class HooksSubcommand < Subcommand
@@ -4,6 +4,7 @@ require "json"
4
4
  require "tty-prompt"
5
5
  require_relative "../../generators/agents_generator"
6
6
  require_relative "../../contexts/manifest"
7
+ require_relative "../../contexts/web"
7
8
 
8
9
  module Aircana
9
10
  module CLI
@@ -43,6 +44,9 @@ module Aircana
43
44
  # Prompt for knowledge fetching
44
45
  prompt_for_knowledge_fetch(prompt, normalized_agent_name)
45
46
 
47
+ # Prompt for web URL fetching
48
+ prompt_for_url_fetch(prompt, normalized_agent_name)
49
+
46
50
  # Prompt for agent file review
47
51
  prompt_for_agent_review(prompt, file)
48
52
 
@@ -59,6 +63,44 @@ module Aircana
59
63
  print_agents_list(agent_folders)
60
64
  end
61
65
 
66
+ def add_url(agent, url) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/PerceivedComplexity
67
+ normalized_agent = normalize_string(agent)
68
+
69
+ unless agent_exists?(normalized_agent)
70
+ Aircana.human_logger.error "Agent '#{agent}' not found. Use 'aircana agents list' to see available agents."
71
+ exit 1
72
+ end
73
+
74
+ web = Aircana::Contexts::Web.new
75
+ result = web.fetch_url_for(agent: normalized_agent, url: url)
76
+
77
+ if result
78
+ # Update manifest with the new URL
79
+ existing_sources = Aircana::Contexts::Manifest.sources_from_manifest(normalized_agent)
80
+ web_sources = existing_sources.select { |s| s["type"] == "web" }
81
+ other_sources = existing_sources.reject { |s| s["type"] == "web" }
82
+
83
+ if web_sources.any?
84
+ # Add to existing web source
85
+ web_sources.first["urls"] << result
86
+ else
87
+ # Create new web source
88
+ web_sources = [{ "type" => "web", "urls" => [result] }]
89
+ end
90
+
91
+ all_sources = other_sources + web_sources
92
+ Aircana::Contexts::Manifest.update_manifest(normalized_agent, all_sources)
93
+
94
+ Aircana.human_logger.success "Successfully added URL to agent '#{agent}'"
95
+ else
96
+ Aircana.human_logger.error "Failed to fetch URL: #{url}"
97
+ exit 1
98
+ end
99
+ rescue Aircana::Error => e
100
+ Aircana.human_logger.error "Failed to add URL: #{e.message}"
101
+ exit 1
102
+ end
103
+
62
104
  private
63
105
 
64
106
  def perform_refresh(normalized_agent)
@@ -77,20 +119,38 @@ module Aircana
77
119
  end
78
120
  end
79
121
 
80
- def perform_manifest_aware_refresh(normalized_agent)
81
- confluence = Aircana::Contexts::Confluence.new
122
+ def perform_manifest_aware_refresh(normalized_agent) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
123
+ total_pages = 0
124
+ all_sources = []
82
125
 
83
126
  # Try manifest-based refresh first
84
127
  if Aircana::Contexts::Manifest.manifest_exists?(normalized_agent)
85
128
  Aircana.human_logger.info "Refreshing from knowledge manifest..."
86
- result = confluence.refresh_from_manifest(agent: normalized_agent)
129
+
130
+ # Refresh Confluence sources
131
+ confluence = Aircana::Contexts::Confluence.new
132
+ confluence_result = confluence.refresh_from_manifest(agent: normalized_agent)
133
+ total_pages += confluence_result[:pages_count]
134
+ all_sources.concat(confluence_result[:sources])
135
+
136
+ # Refresh web sources
137
+ web = Aircana::Contexts::Web.new
138
+ web_result = web.refresh_web_sources(agent: normalized_agent)
139
+ total_pages += web_result[:pages_count]
140
+ all_sources.concat(web_result[:sources])
87
141
  else
88
142
  Aircana.human_logger.info "No manifest found, falling back to label-based search..."
89
- result = confluence.fetch_pages_for(agent: normalized_agent)
143
+ confluence = Aircana::Contexts::Confluence.new
144
+ confluence_result = confluence.fetch_pages_for(agent: normalized_agent)
145
+ total_pages += confluence_result[:pages_count]
146
+ all_sources.concat(confluence_result[:sources])
90
147
  end
91
148
 
92
- log_refresh_result(normalized_agent, result[:pages_count])
93
- result
149
+ # Update manifest with all sources combined
150
+ Aircana::Contexts::Manifest.update_manifest(normalized_agent, all_sources) if all_sources.any?
151
+
152
+ log_refresh_result(normalized_agent, total_pages)
153
+ { pages_count: total_pages, sources: all_sources }
94
154
  end
95
155
 
96
156
  def show_gitignore_recommendation
@@ -153,6 +213,43 @@ module Aircana
153
213
  Aircana.human_logger.info "You can try again later with 'aircana agents refresh #{normalized_agent_name}'"
154
214
  end
155
215
 
216
+ def prompt_for_url_fetch(prompt, normalized_agent_name) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
217
+ return unless prompt.yes?("Would you like to add web URLs for this agent's knowledge base?")
218
+
219
+ urls = []
220
+ loop do
221
+ url = prompt.ask("Enter URL (or press Enter to finish):")
222
+ break if url.nil? || url.strip.empty?
223
+
224
+ url = url.strip
225
+ if valid_url?(url)
226
+ urls << url
227
+ else
228
+ Aircana.human_logger.warn "Invalid URL format: #{url}. Please enter a valid HTTP or HTTPS URL."
229
+ end
230
+ end
231
+
232
+ return if urls.empty?
233
+
234
+ begin
235
+ Aircana.human_logger.info "Fetching #{urls.size} URL(s)..."
236
+ web = Aircana::Contexts::Web.new
237
+ result = web.fetch_urls_for(agent: normalized_agent_name, urls: urls)
238
+
239
+ if result[:pages_count].positive?
240
+ Aircana.human_logger.success "Successfully fetched #{result[:pages_count]} URL(s)"
241
+ show_gitignore_recommendation
242
+ else
243
+ Aircana.human_logger.warn "No URLs were successfully fetched"
244
+ end
245
+ rescue Aircana::Error => e
246
+ Aircana.human_logger.warn "Failed to fetch URLs: #{e.message}"
247
+ Aircana.human_logger.info(
248
+ "You can add URLs later with 'aircana agents add-url #{normalized_agent_name} <URL>'"
249
+ )
250
+ end
251
+ end
252
+
156
253
  def prompt_for_agent_review(prompt, file_path)
157
254
  Aircana.human_logger.info "Agent file created at: #{file_path}"
158
255
 
@@ -214,6 +311,18 @@ module Aircana
214
311
  config["description"] || "No description available"
215
312
  end
216
313
 
314
+ def agent_exists?(agent_name)
315
+ agent_dir = File.join(Aircana.configuration.agent_knowledge_dir, agent_name)
316
+ Dir.exist?(agent_dir)
317
+ end
318
+
319
+ def valid_url?(url)
320
+ uri = URI.parse(url)
321
+ %w[http https].include?(uri.scheme) && !uri.host.nil?
322
+ rescue URI::InvalidURIError
323
+ false
324
+ end
325
+
217
326
  def find_available_editor
218
327
  %w[code subl atom nano vim vi].find { |cmd| system("which #{cmd} > /dev/null 2>&1") }
219
328
  end
@@ -56,7 +56,6 @@ module Aircana
56
56
  return { pages_count: 0, sources: [] } if all_pages.empty?
57
57
 
58
58
  updated_sources = process_pages_with_manifest(all_pages, agent)
59
- Manifest.update_manifest(agent, updated_sources)
60
59
 
61
60
  { pages_count: all_pages.size, sources: updated_sources }
62
61
  end
@@ -128,6 +128,8 @@ module Aircana
128
128
  case source["type"]
129
129
  when "confluence"
130
130
  validate_confluence_source(source)
131
+ when "web"
132
+ validate_web_source(source)
131
133
  else
132
134
  raise ManifestError, "Unknown source type: #{source["type"]}"
133
135
  end
@@ -140,6 +142,24 @@ module Aircana
140
142
 
141
143
  raise ManifestError, "Confluence pages must be an array"
142
144
  end
145
+
146
+ def validate_web_source(source)
147
+ raise ManifestError, "Web source missing required field: urls" unless source.key?("urls")
148
+
149
+ raise ManifestError, "Web urls must be an array" unless source["urls"].is_a?(Array)
150
+
151
+ source["urls"].each do |url_entry|
152
+ validate_web_url_entry(url_entry)
153
+ end
154
+ end
155
+
156
+ def validate_web_url_entry(url_entry)
157
+ raise ManifestError, "Each URL entry must be a hash" unless url_entry.is_a?(Hash)
158
+
159
+ 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
+ end
143
163
  end
144
164
  end
145
165
 
@@ -0,0 +1,341 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "httparty"
4
+ require "reverse_markdown"
5
+ require "uri"
6
+ require_relative "local"
7
+ require_relative "manifest"
8
+ require_relative "../progress_tracker"
9
+ require_relative "../version"
10
+ require_relative "../llm/claude_client"
11
+
12
+ module Aircana
13
+ module Contexts
14
+ class Web # rubocop:disable Metrics/ClassLength
15
+ include HTTParty
16
+
17
+ headers "User-Agent" => "Aircana/#{Aircana::VERSION} (+https://github.com/westonkd/aircana)"
18
+ default_timeout 30
19
+ follow_redirects true
20
+
21
+ def initialize
22
+ @local_storage = Local.new
23
+ end
24
+
25
+ def fetch_url_for(agent:, url:)
26
+ validate_url!(url)
27
+
28
+ page_data = fetch_and_process_url(url)
29
+ store_page_as_markdown(page_data, agent)
30
+
31
+ build_url_metadata(page_data)
32
+ rescue StandardError => e
33
+ handle_fetch_error(url, e)
34
+ nil
35
+ end
36
+
37
+ def fetch_urls_for(agent:, urls:) # rubocop:disable Metrics/MethodLength
38
+ return { pages_count: 0, sources: [] } if urls.empty?
39
+
40
+ pages_metadata = []
41
+ successful_urls = []
42
+
43
+ ProgressTracker.with_batch_progress(urls, "Fetching URLs") do |url, _index|
44
+ metadata = fetch_url_for(agent: agent, url: url)
45
+ if metadata
46
+ pages_metadata << metadata
47
+ successful_urls << url
48
+ end
49
+ end
50
+
51
+ if successful_urls.any?
52
+ sources = build_sources_metadata(successful_urls, pages_metadata)
53
+ update_or_create_manifest(agent, sources)
54
+ { pages_count: successful_urls.size, sources: sources }
55
+ else
56
+ { pages_count: 0, sources: [] }
57
+ end
58
+ end
59
+
60
+ def refresh_web_sources(agent:) # rubocop:disable Metrics/CyclomaticComplexity
61
+ sources = Manifest.sources_from_manifest(agent)
62
+ web_sources = sources.select { |s| s["type"] == "web" }
63
+
64
+ return { pages_count: 0, sources: [] } if web_sources.empty?
65
+
66
+ all_urls = web_sources.flat_map { |source| source["urls"]&.map { |u| u["url"] } || [] }
67
+ return { pages_count: 0, sources: [] } if all_urls.empty?
68
+
69
+ fetch_urls_for(agent: agent, urls: all_urls)
70
+ end
71
+
72
+ private
73
+
74
+ def validate_url!(url)
75
+ uri = URI.parse(url)
76
+ raise Error, "URL must use HTTP or HTTPS protocol" unless %w[http https].include?(uri.scheme)
77
+ raise Error, "Invalid URL format" unless uri.host
78
+ rescue URI::InvalidURIError
79
+ raise Error, "Invalid URL format"
80
+ end
81
+
82
+ def fetch_and_process_url(url) # rubocop:disable Metrics/MethodLength
83
+ Aircana.human_logger.info("Fetching #{url}")
84
+
85
+ response = self.class.get(url)
86
+
87
+ raise Error, "Failed to fetch URL (#{response.code})" unless response.success?
88
+
89
+ html_title = extract_title(response.body)
90
+ content = convert_to_markdown(response.body)
91
+ title = generate_meaningful_title(html_title, content, url)
92
+
93
+ {
94
+ url: url,
95
+ title: title,
96
+ content: content,
97
+ last_fetched: Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
98
+ }
99
+ end
100
+
101
+ def extract_title(html) # rubocop:disable Metrics/MethodLength
102
+ title_match = html.match(%r{<title[^>]*>(.*?)</title>}im)
103
+ return nil unless title_match
104
+
105
+ title = title_match[1].strip
106
+ # Decode HTML entities
107
+ title.gsub(/&([a-zA-Z]+|#\d+);/) do |match|
108
+ case match
109
+ when "&amp;" then "&"
110
+ when "&lt;" then "<"
111
+ when "&gt;" then ">"
112
+ when "&quot;" then '"'
113
+ when "&#39;", "&apos;" then "'"
114
+ else match
115
+ end
116
+ end
117
+ end
118
+
119
+ def extract_title_from_url(url)
120
+ uri = URI.parse(url)
121
+ # Use the last path segment or host as fallback title
122
+ path_segments = uri.path.split("/").reject(&:empty?)
123
+ if path_segments.any?
124
+ path_segments.last.gsub(/[-_]/, " ").split.map(&:capitalize).join(" ")
125
+ else
126
+ uri.host
127
+ end
128
+ end
129
+
130
+ def generate_meaningful_title(html_title, content, url) # rubocop:disable Metrics/CyclomaticComplexity
131
+ # If we have a good HTML title that's descriptive, use it
132
+ return html_title if html_title && html_title.length > 10 && !generic_title?(html_title)
133
+
134
+ # If content is too short, use fallback
135
+ return html_title || extract_title_from_url(url) if content.length < 50
136
+
137
+ # Use Claude to generate a meaningful title based on content
138
+ begin
139
+ generate_title_with_claude(content, url)
140
+ rescue StandardError => e
141
+ Aircana.human_logger.warn("Failed to generate title with Claude: #{e.message}")
142
+ html_title || extract_title_from_url(url)
143
+ end
144
+ end
145
+
146
+ def generic_title?(title)
147
+ generic_patterns = [
148
+ /^(home|index|welcome|untitled|document)$/i,
149
+ /^(page|default)$/i,
150
+ /^\s*$/,
151
+ # Truncated titles (contain ellipsis)
152
+ /\.\.\./,
153
+ # Titles with excessive metadata (site names, IDs, etc.)
154
+ / - .+ - \d+$/,
155
+ # Question titles that are truncated
156
+ /^how do i .+\.\.\./i,
157
+ /^what is .+\.\.\./i
158
+ ]
159
+
160
+ generic_patterns.any? { |pattern| title.match?(pattern) }
161
+ end
162
+
163
+ def generate_title_with_claude(content, url)
164
+ prompt = build_title_generation_prompt(content, url)
165
+ claude_client = LLM::ClaudeClient.new
166
+ claude_client.prompt(prompt).strip
167
+ end
168
+
169
+ def build_title_generation_prompt(content, url) # rubocop:disable Metrics/MethodLength
170
+ # Truncate content to avoid overly long prompts
171
+ truncated_content = content.length > 1000 ? "#{content[0..1000]}..." : content
172
+
173
+ <<~PROMPT
174
+ Based on the following web page content from #{url}, generate a concise, descriptive title
175
+ that would help an AI agent understand what this document contains and when it would be useful.
176
+
177
+ The title should be:
178
+ - 3-8 words long
179
+ - Focused on the main topic or purpose
180
+ - Helpful for knowledge retrieval
181
+ - Professional and clear
182
+
183
+ Content:
184
+ #{truncated_content}
185
+
186
+ Respond with only the title, no additional text or explanation.
187
+ PROMPT
188
+ end
189
+
190
+ def convert_to_markdown(html)
191
+ return "" if html.nil? || html.empty?
192
+
193
+ # Extract meaningful content by removing unwanted elements
194
+ cleaned_html = extract_main_content(html)
195
+
196
+ ReverseMarkdown.convert(cleaned_html, github_flavored: true)
197
+ rescue StandardError => e
198
+ Aircana.human_logger.warn "Failed to convert HTML to markdown: #{e.message}"
199
+ # Fallback to plain text extraction
200
+ extract_text_content(html)
201
+ end
202
+
203
+ def store_page_as_markdown(page_data, agent)
204
+ @local_storage.store_content(
205
+ title: page_data[:title],
206
+ content: page_data[:content],
207
+ agent: agent
208
+ )
209
+ end
210
+
211
+ def build_url_metadata(page_data)
212
+ {
213
+ "url" => page_data[:url],
214
+ "title" => page_data[:title],
215
+ "last_fetched" => page_data[:last_fetched]
216
+ }
217
+ end
218
+
219
+ def build_sources_metadata(_urls, pages_metadata)
220
+ [
221
+ {
222
+ "type" => "web",
223
+ "urls" => pages_metadata
224
+ }
225
+ ]
226
+ end
227
+
228
+ def update_or_create_manifest(agent, new_sources)
229
+ existing_sources = Manifest.sources_from_manifest(agent)
230
+
231
+ # Remove existing web sources and add new ones
232
+ other_sources = existing_sources.reject { |s| s["type"] == "web" }
233
+ all_sources = other_sources + new_sources
234
+
235
+ if Manifest.manifest_exists?(agent)
236
+ Manifest.update_manifest(agent, all_sources)
237
+ else
238
+ Manifest.create_manifest(agent, all_sources)
239
+ end
240
+ end
241
+
242
+ def handle_fetch_error(url, error)
243
+ case error
244
+ when URI::InvalidURIError
245
+ Aircana.human_logger.error "Invalid URL format: #{url}"
246
+ when HTTParty::Error
247
+ Aircana.human_logger.error "HTTP error fetching #{url}: #{error.message}"
248
+ when Error
249
+ Aircana.human_logger.error "Error fetching #{url}: #{error.message}"
250
+ else
251
+ Aircana.human_logger.error "Unexpected error fetching #{url}: #{error.message}"
252
+ end
253
+ end
254
+
255
+ def extract_main_content(html) # rubocop:disable Metrics/MethodLength
256
+ # Try to find the main content area using common selectors
257
+ content_patterns = [
258
+ # Common main content selectors
259
+ %r{<main[^>]*>(.*?)</main>}mi,
260
+ %r{<article[^>]*>(.*?)</article>}mi,
261
+ %r{<div[^>]*class="[^"]*content[^"]*"[^>]*>(.*?)</div>}mi,
262
+ %r{<div[^>]*id="content"[^>]*>(.*?)</div>}mi,
263
+ %r{<div[^>]*class="[^"]*post[^"]*"[^>]*>(.*?)</div>}mi,
264
+ # Documentation specific
265
+ %r{<div[^>]*class="[^"]*docs[^"]*"[^>]*>(.*?)</div>}mi,
266
+ %r{<div[^>]*class="[^"]*documentation[^"]*"[^>]*>(.*?)</div>}mi,
267
+ # Body content as fallback
268
+ %r{<body[^>]*>(.*?)</body>}mi
269
+ ]
270
+
271
+ extracted_content = nil
272
+ content_patterns.each do |pattern|
273
+ match = html.match(pattern)
274
+ if match && match[1].strip.length > 100 # Ensure meaningful content
275
+ extracted_content = match[1]
276
+ break
277
+ end
278
+ end
279
+
280
+ # If no pattern matched or content is too short, use the full HTML
281
+ content_to_clean = extracted_content || html
282
+
283
+ # Remove unwanted elements
284
+ clean_html_content(content_to_clean)
285
+ end
286
+
287
+ def clean_html_content(html) # rubocop:disable Metrics/MethodLength
288
+ cleaned = html.dup
289
+
290
+ # Remove script and style tags completely
291
+ cleaned = cleaned.gsub(%r{<script[^>]*>.*?</script>}mi, "")
292
+ cleaned = cleaned.gsub(%r{<style[^>]*>.*?</style>}mi, "")
293
+
294
+ # Remove navigation, header, footer, sidebar elements
295
+ navigation_selectors = %w[nav header footer aside sidebar menu breadcrumb]
296
+ navigation_selectors.each do |selector|
297
+ # Remove by tag name
298
+ cleaned = cleaned.gsub(%r{<#{selector}[^>]*>.*?</#{selector}>}mi, "")
299
+ # Remove by class name (common patterns)
300
+ cleaned = cleaned.gsub(%r{<[^>]+class="[^"]*#{selector}[^"]*"[^>]*>.*?</[^>]+>}mi, "")
301
+ cleaned = cleaned.gsub(%r{<[^>]+id="#{selector}"[^>]*>.*?</[^>]+>}mi, "")
302
+ end
303
+
304
+ # Remove common non-content elements
305
+ unwanted_patterns = [
306
+ %r{<div[^>]*class="[^"]*comment[^"]*"[^>]*>.*?</div>}mi,
307
+ %r{<div[^>]*class="[^"]*social[^"]*"[^>]*>.*?</div>}mi,
308
+ %r{<div[^>]*class="[^"]*share[^"]*"[^>]*>.*?</div>}mi,
309
+ %r{<div[^>]*class="[^"]*ad[^"]*"[^>]*>.*?</div>}mi,
310
+ %r{<div[^>]*class="[^"]*advertisement[^"]*"[^>]*>.*?</div>}mi,
311
+ %r{<div[^>]*class="[^"]*popup[^"]*"[^>]*>.*?</div>}mi,
312
+ %r{<div[^>]*class="[^"]*modal[^"]*"[^>]*>.*?</div>}mi
313
+ ]
314
+
315
+ unwanted_patterns.each do |pattern|
316
+ cleaned = cleaned.gsub(pattern, "")
317
+ end
318
+
319
+ # Clean up whitespace
320
+ cleaned.gsub(/\n\s*\n\s*\n+/, "\n\n").strip
321
+ end
322
+
323
+ def extract_text_content(html) # rubocop:disable Metrics/MethodLength
324
+ # Fallback method for plain text extraction
325
+ text = html.gsub(%r{<script[^>]*>.*?</script>}mi, "")
326
+ .gsub(%r{<style[^>]*>.*?</style>}mi, "")
327
+ .gsub(/<[^>]+>/, "")
328
+ .gsub("&nbsp;", " ")
329
+ .gsub("&amp;", "&")
330
+ .gsub("&lt;", "<")
331
+ .gsub("&gt;", ">")
332
+ .gsub("&quot;", '"')
333
+ .gsub(/\s+/, " ")
334
+ .strip
335
+
336
+ # If the extracted text is very short, it might not be useful
337
+ text.length < 20 ? "Content could not be extracted from this page." : text
338
+ end
339
+ end
340
+ end
341
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Aircana
4
- VERSION = "1.1.0.rc1"
4
+ VERSION = "1.2.0"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aircana
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0.rc1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Weston Dransfield
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
10
+ date: 2025-09-26 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: httparty
@@ -145,6 +145,7 @@ files:
145
145
  - lib/aircana/contexts/local.rb
146
146
  - lib/aircana/contexts/manifest.rb
147
147
  - lib/aircana/contexts/relevant_files.rb
148
+ - lib/aircana/contexts/web.rb
148
149
  - lib/aircana/fzf_helper.rb
149
150
  - lib/aircana/generators.rb
150
151
  - lib/aircana/generators/agents_generator.rb
@@ -197,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
198
  - !ruby/object:Gem::Version
198
199
  version: '0'
199
200
  requirements: []
200
- rubygems_version: 3.6.9
201
+ rubygems_version: 3.6.2
201
202
  specification_version: 4
202
203
  summary: Humble workflow and context utilities for engineering with agents
203
204
  test_files: []