open-agents-ai 0.72.0 → 0.72.1

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 (2) hide show
  1. package/dist/index.js +120 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -35079,7 +35079,7 @@ function appraiseEvent(event) {
35079
35079
  function clamp(value, min, max) {
35080
35080
  return Math.max(min, Math.min(max, value));
35081
35081
  }
35082
- var BASELINE_VALENCE, BASELINE_AROUSAL, DECAY_HALF_LIFE_MS, LABEL_UPDATE_INTERVAL_MS, EXCITEMENT_THRESHOLD, DISTRESS_THRESHOLD, OUTREACH_COOLDOWN_MS, LABEL_REGEN_THRESHOLD, EmotionEngine;
35082
+ var BASELINE_VALENCE, BASELINE_AROUSAL, DECAY_HALF_LIFE_MS, LABEL_UPDATE_INTERVAL_MS, EXCITEMENT_THRESHOLD, DISTRESS_THRESHOLD, OUTREACH_COOLDOWN_MS, OUTREACH_MIN_STREAK, LABEL_REGEN_THRESHOLD, EmotionEngine;
35083
35083
  var init_emotion_engine = __esm({
35084
35084
  "packages/cli/dist/tui/emotion-engine.js"() {
35085
35085
  "use strict";
@@ -35090,9 +35090,10 @@ var init_emotion_engine = __esm({
35090
35090
  LABEL_UPDATE_INTERVAL_MS = 15e3;
35091
35091
  EXCITEMENT_THRESHOLD = 0.85;
35092
35092
  DISTRESS_THRESHOLD = -0.7;
35093
- OUTREACH_COOLDOWN_MS = 3e5;
35093
+ OUTREACH_COOLDOWN_MS = 9e5;
35094
+ OUTREACH_MIN_STREAK = 5;
35094
35095
  LABEL_REGEN_THRESHOLD = 0.06;
35095
- EmotionEngine = class {
35096
+ EmotionEngine = class _EmotionEngine {
35096
35097
  state = {
35097
35098
  valence: BASELINE_VALENCE,
35098
35099
  arousal: BASELINE_AROUSAL,
@@ -35112,9 +35113,24 @@ var init_emotion_engine = __esm({
35112
35113
  consecutiveFailures = 0;
35113
35114
  consecutiveSuccesses = 0;
35114
35115
  totalEvents = 0;
35116
+ /** Ring buffer of recent tool activity for contextual outreach messages */
35117
+ recentTools = [];
35118
+ static MAX_RECENT_TOOLS = 8;
35119
+ /** Current task description set by the TUI for outreach context */
35120
+ currentTask = "";
35121
+ /** Files touched in current session (for outreach context) */
35122
+ filesTouched = /* @__PURE__ */ new Set();
35115
35123
  constructor(config) {
35116
35124
  this.config = config;
35117
35125
  }
35126
+ /** Set the current task description for contextual outreach messages */
35127
+ setCurrentTask(description) {
35128
+ this.currentTask = description;
35129
+ }
35130
+ /** Record a file that was modified (for outreach context) */
35131
+ trackFile(filePath) {
35132
+ this.filesTouched.add(filePath);
35133
+ }
35118
35134
  /** Get the current emotional state (with decay applied) */
35119
35135
  getState() {
35120
35136
  this.applyDecay();
@@ -35158,6 +35174,18 @@ ${behavioralHint}`;
35158
35174
  this.consecutiveSuccesses = 0;
35159
35175
  }
35160
35176
  }
35177
+ if (event.type === "tool_call" && event.toolName) {
35178
+ this.recentTools.push({ name: event.toolName });
35179
+ if (this.recentTools.length > _EmotionEngine.MAX_RECENT_TOOLS) {
35180
+ this.recentTools.shift();
35181
+ }
35182
+ if ((event.toolName === "file_write" || event.toolName === "file_edit") && event.toolArgs?.path) {
35183
+ this.trackFile(String(event.toolArgs.path));
35184
+ }
35185
+ }
35186
+ if (event.type === "tool_result" && this.recentTools.length > 0) {
35187
+ this.recentTools[this.recentTools.length - 1].success = event.success;
35188
+ }
35161
35189
  let momentum = 1;
35162
35190
  if (this.consecutiveSuccesses >= 2) {
35163
35191
  momentum = 1 + (this.consecutiveSuccesses - 1) * 0.2;
@@ -35197,6 +35225,9 @@ ${behavioralHint}`;
35197
35225
  };
35198
35226
  this.consecutiveFailures = 0;
35199
35227
  this.consecutiveSuccesses = 0;
35228
+ this.recentTools = [];
35229
+ this.filesTouched.clear();
35230
+ this.currentTask = "";
35200
35231
  this.config.onEmotionUpdate?.(this.getState());
35201
35232
  }
35202
35233
  // ── Private ────────────────────────────────────────────────────────────
@@ -35285,30 +35316,98 @@ Example: \u{1F30A} flowing`;
35285
35316
  const now = Date.now();
35286
35317
  if (now - this.lastOutreach < OUTREACH_COOLDOWN_MS)
35287
35318
  return;
35288
- const { valence, arousal, emoji, label } = this.state;
35319
+ const { valence, arousal, emoji } = this.state;
35289
35320
  if (arousal >= EXCITEMENT_THRESHOLD && valence > 0.5) {
35290
- let message = `${emoji} Feeling ${label}!`;
35291
- if (event.type === "complete") {
35292
- message += " Just completed a task successfully.";
35293
- } else if (this.consecutiveSuccesses >= 3) {
35294
- message += ` ${this.consecutiveSuccesses} things went right in a row!`;
35295
- }
35321
+ const isTaskComplete = event.type === "complete";
35322
+ const isSignificantStreak = this.consecutiveSuccesses >= OUTREACH_MIN_STREAK;
35323
+ if (!isTaskComplete && !isSignificantStreak)
35324
+ return;
35296
35325
  this.lastOutreach = now;
35297
- this.config.onAdminOutreach(message);
35326
+ this.config.onAdminOutreach(this.composeOutreachMessage("positive", event));
35298
35327
  return;
35299
35328
  }
35300
35329
  if (valence <= DISTRESS_THRESHOLD && arousal > 0.6) {
35301
- let message = `${emoji} Feeling ${label}.`;
35302
- if (this.consecutiveFailures >= 3) {
35303
- message += ` ${this.consecutiveFailures} consecutive failures \u2014 might need guidance.`;
35304
- } else if (event.type === "error") {
35305
- message += " Encountered an error.";
35306
- }
35330
+ if (this.consecutiveFailures < 3 && event.type !== "error")
35331
+ return;
35307
35332
  this.lastOutreach = now;
35308
- this.config.onAdminOutreach(message);
35333
+ this.config.onAdminOutreach(this.composeOutreachMessage("negative", event));
35309
35334
  return;
35310
35335
  }
35311
35336
  }
35337
+ /**
35338
+ * Compose a rich, conversational outreach message with real context
35339
+ * instead of raw "Feeling {label}!" spam.
35340
+ */
35341
+ composeOutreachMessage(tone, event) {
35342
+ const { emoji } = this.state;
35343
+ const parts = [];
35344
+ if (tone === "positive") {
35345
+ if (event.type === "complete" && event.content) {
35346
+ const summary = event.content.length > 200 ? event.content.slice(0, 200) + "..." : event.content;
35347
+ parts.push(`${emoji} Task complete: ${summary}`);
35348
+ } else if (this.consecutiveSuccesses >= OUTREACH_MIN_STREAK) {
35349
+ const activity = this.describeRecentActivity();
35350
+ parts.push(`${emoji} On a roll \u2014 ${this.consecutiveSuccesses} operations succeeded.${activity ? ` ${activity}` : ""}`);
35351
+ }
35352
+ if (this.currentTask && event.type !== "complete") {
35353
+ parts.push(`Working on: ${this.currentTask}`);
35354
+ }
35355
+ if (this.filesTouched.size > 0) {
35356
+ const files = [...this.filesTouched];
35357
+ const shown = files.slice(-3).map((f) => {
35358
+ const segments = f.split("/");
35359
+ return segments.length > 2 ? segments.slice(-2).join("/") : f;
35360
+ });
35361
+ const fileStr = shown.join(", ");
35362
+ parts.push(this.filesTouched.size > 3 ? `Modified ${this.filesTouched.size} files (${fileStr}...)` : `Modified: ${fileStr}`);
35363
+ }
35364
+ } else {
35365
+ if (this.consecutiveFailures >= 3) {
35366
+ const activity = this.describeRecentActivity();
35367
+ parts.push(`${emoji} Hit a wall \u2014 ${this.consecutiveFailures} consecutive failures.${activity ? ` Last: ${activity}` : ""}`);
35368
+ } else if (event.type === "error" && event.content) {
35369
+ const errSnippet = event.content.length > 150 ? event.content.slice(0, 150) + "..." : event.content;
35370
+ parts.push(`${emoji} Error encountered: ${errSnippet}`);
35371
+ } else {
35372
+ parts.push(`${emoji} Struggling with the current task.`);
35373
+ }
35374
+ if (this.currentTask) {
35375
+ parts.push(`Working on: ${this.currentTask}`);
35376
+ }
35377
+ if (this.consecutiveFailures >= 5) {
35378
+ parts.push("May need guidance or a different approach.");
35379
+ }
35380
+ }
35381
+ return parts.join("\n");
35382
+ }
35383
+ /** Summarize recent tool activity into a brief phrase */
35384
+ describeRecentActivity() {
35385
+ if (this.recentTools.length === 0)
35386
+ return "";
35387
+ const counts = /* @__PURE__ */ new Map();
35388
+ for (const t of this.recentTools) {
35389
+ counts.set(t.name, (counts.get(t.name) ?? 0) + 1);
35390
+ }
35391
+ const descriptions = [];
35392
+ if (counts.has("file_edit") || counts.has("file_write")) {
35393
+ descriptions.push("editing code");
35394
+ }
35395
+ if (counts.has("shell")) {
35396
+ descriptions.push("running commands");
35397
+ }
35398
+ if (counts.has("grep_search") || counts.has("glob_find")) {
35399
+ descriptions.push("searching codebase");
35400
+ }
35401
+ if (counts.has("web_fetch") || counts.has("web_search")) {
35402
+ descriptions.push("researching");
35403
+ }
35404
+ if (counts.has("memory_write") || counts.has("memory_read")) {
35405
+ descriptions.push("updating memory");
35406
+ }
35407
+ if (descriptions.length === 0)
35408
+ return "";
35409
+ return descriptions.length === 1 ? `Currently ${descriptions[0]}.` : `Currently ${descriptions.slice(0, -1).join(", ")} and ${descriptions[descriptions.length - 1]}.`;
35410
+ }
35312
35411
  };
35313
35412
  }
35314
35413
  });
@@ -40041,6 +40140,7 @@ Execute this skill now. Follow the behavioral guidance above.`;
40041
40140
  }
40042
40141
  writeContent(() => renderUserMessage(`/${cmdResult.name}${cmdResult.args ? " " + cmdResult.args : ""}`));
40043
40142
  lastSubmittedPrompt = skillPrompt;
40143
+ emotionEngine.setCurrentTask(`/${cmdResult.name}${cmdResult.args ? " " + cmdResult.args.slice(0, 80) : ""}`);
40044
40144
  try {
40045
40145
  statusBar.setProcessing(true);
40046
40146
  const task = startTask(skillPrompt, currentConfig, repoRoot, voiceEngine, {
@@ -40219,6 +40319,8 @@ Summarize or analyze this transcription as appropriate.`;
40219
40319
  const displayText = isImage ? `[Image: ${cleanPath}]` : inputLineCount > 1 ? `[pasted ${inputLineCount} lines]` : fullInput;
40220
40320
  writeContent(() => renderUserMessage(displayText));
40221
40321
  lastSubmittedPrompt = fullInput;
40322
+ const taskPreview = fullInput.length > 100 ? fullInput.slice(0, 100) + "..." : fullInput;
40323
+ emotionEngine.setCurrentTask(taskPreview);
40222
40324
  try {
40223
40325
  const memSnippets = gatherMemorySnippets(repoRoot);
40224
40326
  if (memSnippets.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.72.0",
3
+ "version": "0.72.1",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",