openbot 0.4.7 → 0.5.4
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.
- package/.claude/agents/runtime-security-reviewer.md +32 -0
- package/.claude/hooks/format.sh +18 -0
- package/.claude/hooks/protect-secrets.sh +23 -0
- package/.claude/settings.json +26 -0
- package/.claude/skills/deploy/SKILL.md +26 -0
- package/.claude/skills/new-plugin/SKILL.md +46 -0
- package/.dockerignore +9 -0
- package/.mcp.json +8 -0
- package/AGENTS.md +2 -2
- package/CLAUDE.md +50 -0
- package/Dockerfile +41 -0
- package/deploy/README.md +61 -0
- package/deploy/entrypoint.sh +6 -0
- package/deploy/fly.toml +36 -0
- package/dist/app/bootstrap.js +29 -0
- package/dist/app/cli.js +3 -1
- package/dist/app/cloud-mode.js +26 -0
- package/dist/app/config.js +61 -16
- package/dist/app/server.js +38 -6
- package/dist/plugins/approval/index.js +1 -1
- package/dist/plugins/bash/index.js +386 -164
- package/dist/plugins/memory/service.js +2 -5
- package/dist/plugins/openbot/context.js +17 -1
- package/dist/plugins/openbot/index.js +23 -8
- package/dist/plugins/openbot/model.js +59 -0
- package/dist/plugins/openbot/runtime.js +39 -56
- package/dist/plugins/openbot/system-prompt.js +43 -8
- package/dist/plugins/preview/index.js +267 -0
- package/dist/plugins/storage/index.js +3 -3
- package/dist/plugins/storage/service.js +58 -12
- package/dist/plugins/todo/index.js +131 -38
- package/dist/plugins/todo/service.js +93 -0
- package/dist/plugins/ui/index.js +8 -1
- package/dist/services/plugins/model-registry.js +101 -0
- package/dist/services/plugins/registry.js +6 -4
- package/dist/services/plugins/service.js +2 -6
- package/docs/agents.md +20 -2
- package/docs/architecture.md +1 -1
- package/docs/plugins.md +13 -3
- package/docs/templates/AGENT.example.md +1 -1
- package/package.json +5 -2
- package/pnpm-workspace.yaml +2 -0
- package/src/app/bootstrap.ts +43 -0
- package/src/app/cli.ts +3 -1
- package/src/app/cloud-mode.ts +41 -0
- package/src/app/config.ts +71 -19
- package/src/app/server.ts +45 -6
- package/src/app/types.ts +162 -31
- package/src/plugins/approval/index.ts +1 -1
- package/src/plugins/bash/index.ts +498 -185
- package/src/plugins/memory/service.ts +2 -5
- package/src/plugins/openbot/context.ts +17 -1
- package/src/plugins/openbot/index.ts +25 -10
- package/src/plugins/openbot/model.ts +76 -0
- package/src/plugins/openbot/runtime.ts +47 -69
- package/src/plugins/openbot/system-prompt.ts +43 -8
- package/src/plugins/preview/index.ts +323 -0
- package/src/plugins/storage/index.ts +5 -8
- package/src/plugins/storage/service.ts +79 -15
- package/src/plugins/todo/index.ts +166 -0
- package/src/plugins/todo/service.ts +123 -0
- package/src/plugins/ui/index.ts +8 -1
- package/src/services/plugins/domain.ts +2 -0
- package/src/services/plugins/model-registry.ts +146 -0
- package/src/services/plugins/registry.ts +6 -4
- package/src/services/plugins/service.ts +2 -6
- package/dist/agents/openbot/index.js +0 -76
- package/dist/agents/openbot/middleware/approval.js +0 -132
- package/dist/agents/openbot/runtime.js +0 -289
- package/dist/agents/openbot/system-prompt.js +0 -32
- package/dist/agents/openbot/tools/delegation.js +0 -78
- package/dist/agents/openbot/tools/mcp.js +0 -99
- package/dist/agents/openbot/tools/shell.js +0 -91
- package/dist/agents/openbot/tools/storage.js +0 -75
- package/dist/agents/openbot/tools/ui.js +0 -176
- package/dist/agents/system.js +0 -33
- package/dist/bus/agent-package.js +0 -1
- package/dist/bus/plugin.js +0 -1
- package/dist/bus/services.js +0 -754
- package/dist/bus/types.js +0 -1
- package/dist/harness/agent-harness.js +0 -45
- package/dist/harness/agent-invoke-run.js +0 -44
- package/dist/harness/agent-turn.js +0 -99
- package/dist/harness/channel-participants.js +0 -40
- package/dist/harness/constants.js +0 -2
- package/dist/harness/context-meter.js +0 -97
- package/dist/harness/context.js +0 -363
- package/dist/harness/dispatch.js +0 -144
- package/dist/harness/dispatcher.js +0 -156
- package/dist/harness/event-normalizer.js +0 -59
- package/dist/harness/history.js +0 -177
- package/dist/harness/mcp.js +0 -61
- package/dist/harness/orchestration.js +0 -88
- package/dist/harness/orchestrator.js +0 -149
- package/dist/harness/participants.js +0 -22
- package/dist/harness/process.js +0 -29
- package/dist/harness/queue-processor.js +0 -187
- package/dist/harness/run-harness.js +0 -154
- package/dist/harness/run.js +0 -98
- package/dist/harness/runtime-factory.js +0 -73
- package/dist/harness/runtime.js +0 -57
- package/dist/harness/todo-advance.js +0 -93
- package/dist/harness/todo-dispatch.js +0 -51
- package/dist/harness/todos.js +0 -5
- package/dist/harness/turn.js +0 -79
- package/dist/harness/types.js +0 -1
- package/dist/plugins/ai-sdk/index.js +0 -34
- package/dist/plugins/ai-sdk/runtime.js +0 -395
- package/dist/plugins/ai-sdk/system-prompt.js +0 -18
- package/dist/plugins/ai-sdk.js +0 -331
- package/dist/plugins/approval.js +0 -163
- package/dist/plugins/delegation.js +0 -108
- package/dist/plugins/mcp/index.js +0 -108
- package/dist/plugins/mcp.js +0 -140
- package/dist/plugins/shell/index.js +0 -100
- package/dist/plugins/shell.js +0 -123
- package/dist/plugins/storage-tools/index.js +0 -76
- package/dist/plugins/storage.js +0 -737
- package/dist/plugins/thread-namer/index.js +0 -72
- package/dist/plugins/threads/index.js +0 -114
- package/dist/plugins/ui.js +0 -211
- package/dist/plugins/workflow/index.js +0 -65
- package/dist/registry/agents.js +0 -138
- package/dist/registry/plugins.js +0 -110
- package/dist/services/agent-packages.js +0 -103
- package/dist/services/memory.js +0 -152
- package/dist/services/plugins.js +0 -98
- package/dist/services/storage.js +0 -1028
- package/dist/workflow/service.js +0 -106
- package/dist/workflow/types.js +0 -3
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { melony } from 'melony';
|
|
2
|
-
import { resolvePlugin } from '../registry/plugins.js';
|
|
3
|
-
import { storageService } from '../services/storage.js';
|
|
4
|
-
import { busServicesPlugin } from '../bus/services.js';
|
|
5
|
-
const composeMelonyPlugin = (...plugins) => {
|
|
6
|
-
return (builder) => {
|
|
7
|
-
for (const plugin of plugins) {
|
|
8
|
-
plugin(builder);
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
-
/**
|
|
13
|
-
* Build the Melony runtime that drives a single agent run on the OpenBot bus.
|
|
14
|
-
*
|
|
15
|
-
* The runtime always wires:
|
|
16
|
-
* 1. `busServicesPlugin` — bus-level services (storage, channels, threads,
|
|
17
|
-
* plugin install/marketplace) shared by every agent.
|
|
18
|
-
* 2. Every Plugin referenced by the agent's `plugins[]` frontmatter, in
|
|
19
|
-
* order. Tool definitions from each plugin are merged into a single map
|
|
20
|
-
* and passed to every plugin via `PluginContext.tools`. Runtime plugins
|
|
21
|
-
* (those that handle `agent:invoke`) consume the merged map; tool plugins
|
|
22
|
-
* ignore it.
|
|
23
|
-
*
|
|
24
|
-
* Tool name collisions across plugins log a warning; the first plugin wins.
|
|
25
|
-
*/
|
|
26
|
-
export async function createAgentRuntime(state) {
|
|
27
|
-
const runtime = melony({
|
|
28
|
-
initialState: state,
|
|
29
|
-
});
|
|
30
|
-
runtime.use(busServicesPlugin({ storage: storageService }));
|
|
31
|
-
const refs = state.agentDetails?.pluginRefs || [];
|
|
32
|
-
if (refs.length === 0) {
|
|
33
|
-
console.warn(`[agent] Agent "${state.agentId}" has no plugins; only bus services will be active.`);
|
|
34
|
-
return runtime.build();
|
|
35
|
-
}
|
|
36
|
-
// Resolve all plugins first so we can merge tool definitions before factory calls.
|
|
37
|
-
const resolved = [];
|
|
38
|
-
for (const ref of refs) {
|
|
39
|
-
const plugin = await resolvePlugin(ref.id);
|
|
40
|
-
if (!plugin) {
|
|
41
|
-
console.warn(`[agent] Plugin "${ref.id}" for agent "${state.agentId}" could not be resolved.`);
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
resolved.push({ ref, plugin });
|
|
45
|
-
}
|
|
46
|
-
// Merge tool definitions; first plugin wins on collision.
|
|
47
|
-
const tools = {};
|
|
48
|
-
for (const { plugin } of resolved) {
|
|
49
|
-
if (!plugin.toolDefinitions)
|
|
50
|
-
continue;
|
|
51
|
-
for (const [name, def] of Object.entries(plugin.toolDefinitions)) {
|
|
52
|
-
if (tools[name]) {
|
|
53
|
-
console.warn(`[agent] Tool name collision for "${name}" while loading plugin "${plugin.id}"; keeping first registration.`);
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
tools[name] = def;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// Compose all plugin factories with the shared context.
|
|
60
|
-
const pluginPlugins = [];
|
|
61
|
-
for (const { ref, plugin } of resolved) {
|
|
62
|
-
const context = {
|
|
63
|
-
agentId: state.agentId,
|
|
64
|
-
agentDetails: state.agentDetails,
|
|
65
|
-
config: ref.config || {},
|
|
66
|
-
storage: storageService,
|
|
67
|
-
tools,
|
|
68
|
-
};
|
|
69
|
-
pluginPlugins.push(plugin.factory(context));
|
|
70
|
-
}
|
|
71
|
-
runtime.use(composeMelonyPlugin(...pluginPlugins));
|
|
72
|
-
return runtime.build();
|
|
73
|
-
}
|
package/dist/harness/runtime.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { melony } from 'melony';
|
|
2
|
-
import { resolvePlugin } from '../registry/plugins.js';
|
|
3
|
-
import { storageService } from '../services/storage.js';
|
|
4
|
-
import { busServicesPlugin } from '../bus/services.js';
|
|
5
|
-
const composeMelonyPlugin = (...plugins) => {
|
|
6
|
-
return (builder) => {
|
|
7
|
-
for (const plugin of plugins) {
|
|
8
|
-
plugin(builder);
|
|
9
|
-
}
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
-
/** Build the Melony runtime for a single agent turn. */
|
|
13
|
-
export async function createAgentRuntime(state) {
|
|
14
|
-
const runtime = melony({
|
|
15
|
-
initialState: state,
|
|
16
|
-
});
|
|
17
|
-
runtime.use(busServicesPlugin({ storage: storageService }));
|
|
18
|
-
const refs = state.agentDetails?.pluginRefs || [];
|
|
19
|
-
if (refs.length === 0) {
|
|
20
|
-
console.warn(`[harness] Agent "${state.agentId}" has no plugins; only bus services will be active.`);
|
|
21
|
-
return runtime.build();
|
|
22
|
-
}
|
|
23
|
-
const resolved = [];
|
|
24
|
-
for (const ref of refs) {
|
|
25
|
-
const plugin = await resolvePlugin(ref.id);
|
|
26
|
-
if (!plugin) {
|
|
27
|
-
console.warn(`[harness] Plugin "${ref.id}" for agent "${state.agentId}" could not be resolved.`);
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
resolved.push({ ref, plugin });
|
|
31
|
-
}
|
|
32
|
-
const tools = {};
|
|
33
|
-
for (const { plugin } of resolved) {
|
|
34
|
-
if (!plugin.toolDefinitions)
|
|
35
|
-
continue;
|
|
36
|
-
for (const [name, def] of Object.entries(plugin.toolDefinitions)) {
|
|
37
|
-
if (tools[name]) {
|
|
38
|
-
console.warn(`[harness] Tool name collision for "${name}" while loading plugin "${plugin.id}"; keeping first registration.`);
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
tools[name] = def;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
const pluginPlugins = [];
|
|
45
|
-
for (const { ref, plugin } of resolved) {
|
|
46
|
-
const context = {
|
|
47
|
-
agentId: state.agentId,
|
|
48
|
-
agentDetails: state.agentDetails,
|
|
49
|
-
config: ref.config || {},
|
|
50
|
-
storage: storageService,
|
|
51
|
-
tools,
|
|
52
|
-
};
|
|
53
|
-
pluginPlugins.push(plugin.factory(context));
|
|
54
|
-
}
|
|
55
|
-
runtime.use(composeMelonyPlugin(...pluginPlugins));
|
|
56
|
-
return runtime.build();
|
|
57
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/** Stored on each todo and inlined into the next assignee's invoke payload. */
|
|
2
|
-
const RESULT_MAX_CHARS = 12000;
|
|
3
|
-
/**
|
|
4
|
-
* Shared helpers that drive the autonomous todo loop. The queue processor
|
|
5
|
-
* calls `advanceAfterRun` once per `agent:run:end`; that is the only place
|
|
6
|
-
* todos are completed and dispatched, which keeps the autonomous flow
|
|
7
|
-
* single-threaded and easy to reason about.
|
|
8
|
-
*/
|
|
9
|
-
export const readTodosFromState = (state) => {
|
|
10
|
-
const raw = state?.todos;
|
|
11
|
-
return Array.isArray(raw) ? raw : [];
|
|
12
|
-
};
|
|
13
|
-
export function truncateTodoResult(text, maxChars = RESULT_MAX_CHARS) {
|
|
14
|
-
const trimmed = text.trim();
|
|
15
|
-
if (!trimmed)
|
|
16
|
-
return undefined;
|
|
17
|
-
if (trimmed.length <= maxChars)
|
|
18
|
-
return trimmed;
|
|
19
|
-
return `${trimmed.slice(0, maxChars)}\n…[truncated]`;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Apply a single advance step:
|
|
23
|
-
* 1. If a todo is `in_progress` and `assignee` matches the agent whose run
|
|
24
|
-
* just ended, mark it `done` and attach `result` from `lastOutput` when present.
|
|
25
|
-
* 2. Pick the next `pending` todo with an `assignee` and flip it to
|
|
26
|
-
* `in_progress`. That assignee gets handed off to; `invoke content` includes
|
|
27
|
-
* the previous step output when available so agents without short-term
|
|
28
|
-
* history still see prior work.
|
|
29
|
-
*
|
|
30
|
-
* If a todo is already `in_progress` and the just-ended agent wasn't its
|
|
31
|
-
* assignee, leave it alone — someone else is working.
|
|
32
|
-
*/
|
|
33
|
-
export function advanceTodos(todos, endedAgentId, lastOutput) {
|
|
34
|
-
const now = Date.now();
|
|
35
|
-
const truncated = truncateTodoResult(lastOutput ?? '');
|
|
36
|
-
let completedOutput;
|
|
37
|
-
let working = todos.map((t) => {
|
|
38
|
-
if (t.status === 'in_progress' && t.assignee === endedAgentId) {
|
|
39
|
-
completedOutput = truncated;
|
|
40
|
-
return {
|
|
41
|
-
...t,
|
|
42
|
-
status: 'done',
|
|
43
|
-
updatedAt: now,
|
|
44
|
-
...(truncated !== undefined ? { result: truncated } : {}),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
return t;
|
|
48
|
-
});
|
|
49
|
-
if (working.some((t) => t.status === 'in_progress')) {
|
|
50
|
-
return { todos: working, handoff: null };
|
|
51
|
-
}
|
|
52
|
-
const idx = working.findIndex((t) => t.status === 'pending' && t.assignee);
|
|
53
|
-
if (idx === -1)
|
|
54
|
-
return { todos: working, handoff: null };
|
|
55
|
-
const picked = working[idx];
|
|
56
|
-
working = working.map((t, i) => i === idx ? { ...t, status: 'in_progress', updatedAt: now } : t);
|
|
57
|
-
const invokeContent = completedOutput !== undefined && completedOutput !== ''
|
|
58
|
-
? `${picked.content}\n\n--- Output from previous step ---\n${completedOutput}`
|
|
59
|
-
: picked.content;
|
|
60
|
-
return {
|
|
61
|
-
todos: working,
|
|
62
|
-
handoff: {
|
|
63
|
-
agentId: picked.assignee,
|
|
64
|
-
content: invokeContent,
|
|
65
|
-
todoId: picked.id,
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
export async function advanceAfterRun(options) {
|
|
70
|
-
const { storage, channelId, threadId, endedAgentId, lastAgentOutput } = options;
|
|
71
|
-
if (!threadId)
|
|
72
|
-
return null;
|
|
73
|
-
const details = await storage.getThreadDetails({ channelId, threadId });
|
|
74
|
-
const todos = readTodosFromState(details?.state);
|
|
75
|
-
if (todos.length === 0)
|
|
76
|
-
return null;
|
|
77
|
-
const { todos: nextList, handoff } = advanceTodos(todos, endedAgentId, lastAgentOutput);
|
|
78
|
-
const changed = nextList.length !== todos.length ||
|
|
79
|
-
nextList.some((t, i) => {
|
|
80
|
-
const u = todos[i];
|
|
81
|
-
if (!u)
|
|
82
|
-
return true;
|
|
83
|
-
return (t.status !== u.status ||
|
|
84
|
-
t.updatedAt !== u.updatedAt ||
|
|
85
|
-
t.result !== u.result ||
|
|
86
|
-
t.assignee !== u.assignee ||
|
|
87
|
-
t.content !== u.content);
|
|
88
|
-
});
|
|
89
|
-
if (changed) {
|
|
90
|
-
await storage.patchThreadState({ channelId, threadId, state: { todos: nextList } });
|
|
91
|
-
}
|
|
92
|
-
return handoff;
|
|
93
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { ORCHESTRATOR_AGENT_ID } from './context.js';
|
|
2
|
-
import { hasOpenTodos, readTodosFromState } from './todos.js';
|
|
3
|
-
export const ORCHESTRATOR_REVIEW_PREFIX = '[Orchestrator review]';
|
|
4
|
-
export const ORCHESTRATOR_KICKOFF_PREFIX = '[Orchestrator kickoff]';
|
|
5
|
-
/** After a specialist finishes — decide what's next. */
|
|
6
|
-
export const ORCHESTRATOR_REVIEW_PROMPT = [
|
|
7
|
-
ORCHESTRATOR_REVIEW_PREFIX,
|
|
8
|
-
'A specialist agent just finished a step in this thread.',
|
|
9
|
-
'Review the shared todo list in your context.',
|
|
10
|
-
'Use `todo_write` to update statuses or capture results.',
|
|
11
|
-
'If more work remains, call `delegate` with a clear briefing for the right participant.',
|
|
12
|
-
'If the plan is complete, summarize outcomes for the user.',
|
|
13
|
-
].join(' ');
|
|
14
|
-
/** After the orchestrator wrote a plan but did not delegate — start execution. */
|
|
15
|
-
export const ORCHESTRATOR_KICKOFF_PROMPT = [
|
|
16
|
-
ORCHESTRATOR_KICKOFF_PREFIX,
|
|
17
|
-
'The thread has open todos but no specialist is running yet.',
|
|
18
|
-
'Pick the next actionable item, mark it `in_progress` with `todo_write`,',
|
|
19
|
-
'and call `delegate` to the assignee (or best participant) with a concrete briefing.',
|
|
20
|
-
'Use reasonable defaults when the user did not specify a preference — do not stop at planning.',
|
|
21
|
-
].join(' ');
|
|
22
|
-
export function isInternalOrchestratorInvoke(content) {
|
|
23
|
-
const text = content?.trim() ?? '';
|
|
24
|
-
return (text.startsWith(ORCHESTRATOR_REVIEW_PREFIX) ||
|
|
25
|
-
text.startsWith(ORCHESTRATOR_KICKOFF_PREFIX));
|
|
26
|
-
}
|
|
27
|
-
export async function planOrchestratorReview(options) {
|
|
28
|
-
const { storage, channelId, threadId, endedAgentId, invokeContent, hasQueuedFollowUps, orchestratorKickoffUsed, } = options;
|
|
29
|
-
if (!threadId || hasQueuedFollowUps)
|
|
30
|
-
return { review: false };
|
|
31
|
-
if (isInternalOrchestratorInvoke(invokeContent))
|
|
32
|
-
return { review: false };
|
|
33
|
-
const details = await storage.getThreadDetails({ channelId, threadId });
|
|
34
|
-
const todos = readTodosFromState(details?.state);
|
|
35
|
-
if (!hasOpenTodos(todos))
|
|
36
|
-
return { review: false };
|
|
37
|
-
if (endedAgentId === ORCHESTRATOR_AGENT_ID) {
|
|
38
|
-
if (orchestratorKickoffUsed)
|
|
39
|
-
return { review: false };
|
|
40
|
-
return {
|
|
41
|
-
review: true,
|
|
42
|
-
reason: 'plan_not_started',
|
|
43
|
-
prompt: ORCHESTRATOR_KICKOFF_PROMPT,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
review: true,
|
|
48
|
-
reason: 'specialist_finished',
|
|
49
|
-
prompt: ORCHESTRATOR_REVIEW_PROMPT,
|
|
50
|
-
};
|
|
51
|
-
}
|
package/dist/harness/todos.js
DELETED
package/dist/harness/turn.js
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { ensureEventId } from '../app/utils.js';
|
|
2
|
-
import { storageService } from '../services/storage.js';
|
|
3
|
-
import { createAgentRuntime } from './runtime-factory.js';
|
|
4
|
-
export function makeInternalInvoke(content, threadId) {
|
|
5
|
-
return ensureEventId({
|
|
6
|
-
type: 'agent:invoke',
|
|
7
|
-
data: { role: 'user', content },
|
|
8
|
-
meta: { threadId, internal: true },
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Run one agent turn. Yields all runtime events for persistence/streaming;
|
|
13
|
-
* returns the last non-empty `agent:output` text from the target agent.
|
|
14
|
-
*/
|
|
15
|
-
export async function* runTurn(options) {
|
|
16
|
-
const { runId, channelId, threadId, agentId, event, lifecycle = true, stream = true, shouldStop, onThreadId, } = options;
|
|
17
|
-
const target = { runId, agentId, channelId, threadId };
|
|
18
|
-
let state;
|
|
19
|
-
try {
|
|
20
|
-
state = await storageService.getOpenBotState({ ...target, event });
|
|
21
|
-
}
|
|
22
|
-
catch (error) {
|
|
23
|
-
if (error.code === 'AGENT_NOT_FOUND') {
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
throw error;
|
|
27
|
-
}
|
|
28
|
-
if (lifecycle && stream) {
|
|
29
|
-
yield {
|
|
30
|
-
type: 'agent:run:start',
|
|
31
|
-
data: { ...target },
|
|
32
|
-
meta: { agentId, threadId },
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
let lastAgentOutput;
|
|
36
|
-
try {
|
|
37
|
-
const runtime = await createAgentRuntime(state);
|
|
38
|
-
for await (const chunk of runtime.run(event, { state, runId })) {
|
|
39
|
-
const stop = shouldStop?.();
|
|
40
|
-
if (stop) {
|
|
41
|
-
yield {
|
|
42
|
-
type: 'agent:run:stopped',
|
|
43
|
-
data: { ...target, reason: stop.reason },
|
|
44
|
-
};
|
|
45
|
-
break;
|
|
46
|
-
}
|
|
47
|
-
if (chunk.id === event.id && chunk.type === event.type)
|
|
48
|
-
continue;
|
|
49
|
-
if (chunk.type === 'action:create_thread:result' && chunk.data.success) {
|
|
50
|
-
const newThreadId = chunk.data.threadId;
|
|
51
|
-
if (newThreadId)
|
|
52
|
-
onThreadId?.(newThreadId);
|
|
53
|
-
}
|
|
54
|
-
if (chunk.type === 'agent:output') {
|
|
55
|
-
const content = chunk.data?.content;
|
|
56
|
-
if (typeof content === 'string' && content.trim()) {
|
|
57
|
-
lastAgentOutput = content.trim();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (stream) {
|
|
61
|
-
chunk.meta = { ...chunk.meta, agentId: chunk.meta?.agentId ?? agentId };
|
|
62
|
-
yield chunk;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
catch (error) {
|
|
67
|
-
console.error(`[turn] Agent run failed: ${agentId}`, error);
|
|
68
|
-
}
|
|
69
|
-
finally {
|
|
70
|
-
if (lifecycle && stream) {
|
|
71
|
-
yield {
|
|
72
|
-
type: 'agent:run:end',
|
|
73
|
-
data: { ...target },
|
|
74
|
-
meta: { agentId, threadId },
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
return lastAgentOutput;
|
|
79
|
-
}
|
package/dist/harness/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { aiSdkRuntime } from './runtime.js';
|
|
2
|
-
/**
|
|
3
|
-
* `ai-sdk` — generic LLM runtime plugin built on the Vercel AI SDK.
|
|
4
|
-
*
|
|
5
|
-
* Owns `agent:invoke` and consumes the merged `tools` map provided by the
|
|
6
|
-
* agent loader (collected from every tool plugin attached to the same agent).
|
|
7
|
-
* Pair with tool plugins like `shell`, `mcp`, `delegation`, etc.
|
|
8
|
-
*/
|
|
9
|
-
export const aiSdkPlugin = {
|
|
10
|
-
id: 'ai-sdk',
|
|
11
|
-
name: 'AI SDK Runtime',
|
|
12
|
-
description: 'Generic LLM runtime built on the Vercel AI SDK. Consumes tools contributed by other plugins.',
|
|
13
|
-
configSchema: {
|
|
14
|
-
type: 'object',
|
|
15
|
-
properties: {
|
|
16
|
-
model: {
|
|
17
|
-
type: 'string',
|
|
18
|
-
description: 'Provider model string, e.g. openai/gpt-4o-mini, anthropic/claude-3-5-sonnet-20240620',
|
|
19
|
-
default: 'openai/gpt-4o-mini',
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
factory: ({ agentDetails, config, storage, tools }) => {
|
|
24
|
-
const model = typeof config.model === 'string' && config.model
|
|
25
|
-
? config.model
|
|
26
|
-
: 'openai/gpt-4o-mini';
|
|
27
|
-
return aiSdkRuntime({
|
|
28
|
-
model,
|
|
29
|
-
storage,
|
|
30
|
-
toolDefinitions: tools,
|
|
31
|
-
});
|
|
32
|
-
},
|
|
33
|
-
};
|
|
34
|
-
export default aiSdkPlugin;
|