explorbot 0.1.12 → 0.1.15

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.
Files changed (75) hide show
  1. package/bin/explorbot-cli.ts +21 -21
  2. package/dist/bin/explorbot-cli.js +3 -3
  3. package/dist/package.json +4 -2
  4. package/dist/rules/researcher/container-rules.md +2 -0
  5. package/dist/src/action-result.js +2 -1
  6. package/dist/src/action.js +3 -8
  7. package/dist/src/ai/captain.js +0 -2
  8. package/dist/src/ai/conversation.js +20 -4
  9. package/dist/src/ai/driller.js +1108 -0
  10. package/dist/src/ai/historian/utils.js +8 -1
  11. package/dist/src/ai/pilot.js +214 -267
  12. package/dist/src/ai/provider.js +25 -12
  13. package/dist/src/ai/quartermaster.js +2 -2
  14. package/dist/src/ai/rules.js +5 -5
  15. package/dist/src/ai/session-analyst.js +122 -0
  16. package/dist/src/ai/tester.js +69 -22
  17. package/dist/src/ai/tools.js +19 -4
  18. package/dist/src/commands/base-command.js +6 -6
  19. package/dist/src/commands/drill-command.js +3 -2
  20. package/dist/src/commands/exit-command.js +1 -0
  21. package/dist/src/commands/explore-command.js +9 -2
  22. package/dist/src/components/AddRule.js +1 -1
  23. package/dist/src/components/StatusPane.js +6 -1
  24. package/dist/src/experience-tracker.js +9 -0
  25. package/dist/src/explorbot.js +48 -8
  26. package/dist/src/explorer.js +11 -13
  27. package/dist/src/reporter.js +105 -4
  28. package/dist/src/state-manager.js +4 -3
  29. package/dist/src/stats.js +7 -1
  30. package/dist/src/test-plan.js +47 -3
  31. package/dist/src/utils/aria.js +354 -529
  32. package/dist/src/utils/hooks-runner.js +2 -8
  33. package/dist/src/utils/html.js +371 -0
  34. package/dist/src/utils/unique-names.js +12 -1
  35. package/dist/src/utils/url-matcher.js +6 -1
  36. package/dist/src/utils/web-element.js +27 -24
  37. package/dist/src/utils/xpath.js +1 -1
  38. package/package.json +4 -2
  39. package/rules/researcher/container-rules.md +2 -0
  40. package/src/action-result.ts +2 -1
  41. package/src/action.ts +3 -10
  42. package/src/ai/captain.ts +0 -2
  43. package/src/ai/conversation.ts +21 -4
  44. package/src/ai/driller.ts +1194 -0
  45. package/src/ai/historian/utils.ts +8 -1
  46. package/src/ai/pilot.ts +215 -265
  47. package/src/ai/provider.ts +24 -12
  48. package/src/ai/quartermaster.ts +2 -2
  49. package/src/ai/rules.ts +5 -5
  50. package/src/ai/session-analyst.ts +139 -0
  51. package/src/ai/tester.ts +63 -20
  52. package/src/ai/tools.ts +18 -4
  53. package/src/commands/base-command.ts +6 -6
  54. package/src/commands/drill-command.ts +3 -2
  55. package/src/commands/exit-command.ts +1 -0
  56. package/src/commands/explore-command.ts +10 -2
  57. package/src/components/AddRule.tsx +1 -1
  58. package/src/components/StatusPane.tsx +6 -3
  59. package/src/config.ts +4 -0
  60. package/src/experience-tracker.ts +9 -0
  61. package/src/explorbot.ts +55 -10
  62. package/src/explorer.ts +10 -12
  63. package/src/reporter.ts +108 -4
  64. package/src/state-manager.ts +4 -3
  65. package/src/stats.ts +10 -1
  66. package/src/test-plan.ts +62 -3
  67. package/src/utils/aria.ts +367 -537
  68. package/src/utils/hooks-runner.ts +2 -6
  69. package/src/utils/html.ts +381 -0
  70. package/src/utils/unique-names.ts +13 -0
  71. package/src/utils/url-matcher.ts +5 -1
  72. package/src/utils/web-element.ts +31 -28
  73. package/src/utils/xpath.ts +1 -1
  74. package/dist/src/ai/bosun.js +0 -456
  75. package/src/ai/bosun.ts +0 -571
@@ -19,6 +19,7 @@ export class Conversation {
19
19
  messages: ModelMessage[];
20
20
  model: any;
21
21
  telemetryFunctionId?: string;
22
+ protectedPrefixCount = 0;
22
23
  private autoTrimRules: Map<string, number>;
23
24
 
24
25
  constructor(messages: ModelMessage[] = [], model?: any, telemetryFunctionId?: string) {
@@ -29,6 +30,10 @@ export class Conversation {
29
30
  this.autoTrimRules = new Map();
30
31
  }
31
32
 
33
+ protectPrefix(count: number): void {
34
+ this.protectedPrefixCount = count;
35
+ }
36
+
32
37
  addUserText(text: string): void {
33
38
  this.messages.push({
34
39
  role: 'user',
@@ -85,9 +90,11 @@ export class Conversation {
85
90
  const escapedTag = tagName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
86
91
  const regex = new RegExp(`<${escapedTag}>[\\s\\S]*?<\\/${escapedTag}>`, 'g');
87
92
  const replacementText = `<${tagName}>${replacement}</${tagName}>`;
93
+ const start = this.protectedPrefixCount;
88
94
 
89
95
  if (keepLast === 0) {
90
- for (const message of this.messages) {
96
+ for (let i = start; i < this.messages.length; i++) {
97
+ const message = this.messages[i];
91
98
  if (typeof message.content === 'string') {
92
99
  message.content = message.content.replace(regex, replacementText);
93
100
  }
@@ -96,7 +103,7 @@ export class Conversation {
96
103
  }
97
104
 
98
105
  const allMatches: Array<{ messageIndex: number; startIndex: number; endIndex: number }> = [];
99
- for (let i = 0; i < this.messages.length; i++) {
106
+ for (let i = start; i < this.messages.length; i++) {
100
107
  const message = this.messages[i];
101
108
  if (typeof message.content === 'string') {
102
109
  const matches = [...message.content.matchAll(new RegExp(`<${escapedTag}>[\\s\\S]*?<\\/${escapedTag}>`, 'g'))];
@@ -112,7 +119,7 @@ export class Conversation {
112
119
  const keepMatches = allMatches.slice(-keepCount);
113
120
  const keepSet = new Set(keepMatches.map((m) => `${m.messageIndex}:${m.startIndex}`));
114
121
 
115
- for (let i = 0; i < this.messages.length; i++) {
122
+ for (let i = start; i < this.messages.length; i++) {
116
123
  const message = this.messages[i];
117
124
  if (typeof message.content === 'string') {
118
125
  const matches = [...message.content.matchAll(new RegExp(`<${escapedTag}>[\\s\\S]*?<\\/${escapedTag}>`, 'g'))];
@@ -137,7 +144,7 @@ export class Conversation {
137
144
 
138
145
  compactToolResults(keepLastN: number): void {
139
146
  const toolMessageIndexes: number[] = [];
140
- for (let i = 0; i < this.messages.length; i++) {
147
+ for (let i = this.protectedPrefixCount; i < this.messages.length; i++) {
141
148
  if (this.messages[i].role === 'tool') toolMessageIndexes.push(i);
142
149
  }
143
150
  const compactUpTo = toolMessageIndexes.length - Math.max(0, keepLastN);
@@ -169,6 +176,16 @@ export class Conversation {
169
176
  }
170
177
  }
171
178
 
179
+ markLastMessageCacheable(): void {
180
+ const last = this.messages[this.messages.length - 1];
181
+ if (!last) return;
182
+ (last as any).providerOptions = {
183
+ ...(last as any).providerOptions,
184
+ anthropic: { cacheControl: { type: 'ephemeral' } },
185
+ bedrock: { cachePoint: { type: 'default' } },
186
+ };
187
+ }
188
+
172
189
  hasTag(tagName: string, lastN?: number): boolean {
173
190
  const escapedTag = tagName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
174
191
  const regex = new RegExp(`<${escapedTag}>`, 'g');