@ai-setting/roy-plugin-task-show 0.1.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.
- package/README.md +263 -0
- package/dist/collector.d.ts +104 -0
- package/dist/collector.d.ts.map +1 -0
- package/dist/collector.js +247 -0
- package/dist/collector.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +107 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +332 -0
- package/dist/plugin.js.map +1 -0
- package/dist/server.d.ts +79 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +570 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +96 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +20 -0
- package/dist/types.js.map +1 -0
- package/dist/url-injector.d.ts +53 -0
- package/dist/url-injector.d.ts.map +1 -0
- package/dist/url-injector.js +69 -0
- package/dist/url-injector.js.map +1 -0
- package/package.json +70 -0
- package/plugin.json +62 -0
- package/public/app.js +133 -0
- package/public/index.html +34 -0
- package/public/style.css +240 -0
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TaskShowPlugin — the roy-agent plugin entry point.
|
|
3
|
+
*
|
|
4
|
+
* Lifecycle (mirrors `ReminderPlugin` / `TaskTagPlugin`):
|
|
5
|
+
* 1. Constructor accepts a config (defaults merged in).
|
|
6
|
+
* 2. `init(env)` registers hooks on the global hook manager:
|
|
7
|
+
* - `tool:after.execute` → record each tool call
|
|
8
|
+
* - `task:after.update` → freeze session + emit URL
|
|
9
|
+
* 3. `dispose()` stops the HTTP service & releases listeners.
|
|
10
|
+
*
|
|
11
|
+
* The plugin is intentionally lean: all the heavy lifting lives in
|
|
12
|
+
* `collector.ts`, `server.ts`, and `url-injector.ts`. That keeps this file
|
|
13
|
+
* readable and makes the surface area easy to test.
|
|
14
|
+
*/
|
|
15
|
+
import type { PluginEnvLike, TaskShowConfig } from "./types.js";
|
|
16
|
+
import { ToolCallCollector } from "./collector.js";
|
|
17
|
+
/**
|
|
18
|
+
* Public, friendly type used in README + tests.
|
|
19
|
+
*
|
|
20
|
+
* It deliberately matches `BasePlugin` from `@ai-setting/roy-agent-core`
|
|
21
|
+
* (init/dispose/hooks-style), so this plugin can be loaded both by the
|
|
22
|
+
* official loader and by hand-rolled test harnesses.
|
|
23
|
+
*/
|
|
24
|
+
export interface TaskShowPluginInterface {
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly version: string;
|
|
27
|
+
readonly description: string;
|
|
28
|
+
init(env: PluginEnvLike): void | Promise<void>;
|
|
29
|
+
dispose(): void | Promise<void>;
|
|
30
|
+
/** accessor for tests / health checks */
|
|
31
|
+
getServerPort(): number | null;
|
|
32
|
+
/** accessor for tests / health checks */
|
|
33
|
+
getCollector(): ToolCallCollector;
|
|
34
|
+
/** accessor for tests that want to bypass the hook manager entirely */
|
|
35
|
+
getConfig(): TaskShowConfig;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Main plugin class. Decorated with the static `roy-agent` metadata block
|
|
39
|
+
* via a side-table so we don't have to import the host's BasePlugin.
|
|
40
|
+
*/
|
|
41
|
+
export declare class TaskShowPlugin implements TaskShowPluginInterface {
|
|
42
|
+
readonly name = "roy-plugin-task-show";
|
|
43
|
+
readonly version = "0.1.0";
|
|
44
|
+
readonly description = "Visually trace a task's tool-call chain on a local HTTP service and inject the URL into the last tool result.";
|
|
45
|
+
private readonly cfg;
|
|
46
|
+
private readonly collector;
|
|
47
|
+
private readonly server;
|
|
48
|
+
private env;
|
|
49
|
+
private disposed;
|
|
50
|
+
/** Last successful `tool:after.execute` result, used to inject the URL on task completion. */
|
|
51
|
+
private lastResultByTask;
|
|
52
|
+
/** cached list of hook points we registered, so dispose() can be defensive even if the env lacks unregister. */
|
|
53
|
+
private registered;
|
|
54
|
+
constructor(config?: Partial<TaskShowConfig>);
|
|
55
|
+
/**
|
|
56
|
+
* Called by the loader (or by tests) with the host's `PluginEnv`. We use
|
|
57
|
+
* the host's `registerHook` if available, otherwise fall back to the
|
|
58
|
+
* global hook manager from `@ai-setting/roy-agent-core`.
|
|
59
|
+
*/
|
|
60
|
+
init(env: PluginEnvLike): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Best-effort dispose. We tolerate the absence of `dispose` on the env.
|
|
63
|
+
*/
|
|
64
|
+
dispose(): Promise<void>;
|
|
65
|
+
getServerPort(): number | null;
|
|
66
|
+
getCollector(): ToolCallCollector;
|
|
67
|
+
getConfig(): TaskShowConfig;
|
|
68
|
+
/**
|
|
69
|
+
* Public function exposed so unit tests can simulate the
|
|
70
|
+
* `tool:after.execute` payload without going through the global hook
|
|
71
|
+
* manager.
|
|
72
|
+
*/
|
|
73
|
+
onToolAfterExecute(ctx: any, metadata?: Record<string, unknown>): Promise<void>;
|
|
74
|
+
/**
|
|
75
|
+
* Public function exposed for tests; mirrors the `task:after.update`
|
|
76
|
+
* payload.
|
|
77
|
+
*/
|
|
78
|
+
onTaskAfterUpdate(ctx: any): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Manual injection hook — useful when a custom caller has a known task
|
|
81
|
+
* id + ToolResult at hand (e.g. tests).
|
|
82
|
+
*/
|
|
83
|
+
injectFor(taskId: number, result: any): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Compute the URL the page would be served at. Helpful in tests where
|
|
86
|
+
* `init()` was skipped.
|
|
87
|
+
*/
|
|
88
|
+
getVisualizationUrl(taskId: number): string;
|
|
89
|
+
/**
|
|
90
|
+
* Subscribe to the hook points we care about. We try to use the env's
|
|
91
|
+
* `registerHook` first (the modern, type-safe plugin API), then fall back
|
|
92
|
+
* to the global hook manager if available.
|
|
93
|
+
*/
|
|
94
|
+
private registerHooks;
|
|
95
|
+
private registerViaGlobalManager;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Convenience factory — used when loaded as a bare ES module (the typical
|
|
99
|
+
* loader pattern in `coder-harness` / `task-tag`).
|
|
100
|
+
*/
|
|
101
|
+
export declare function createTaskShowPlugin(config?: Partial<TaskShowConfig>): TaskShowPlugin;
|
|
102
|
+
/**
|
|
103
|
+
* Default export. The loader imports `default` or `TaskShowPlugin` from this
|
|
104
|
+
* module — both routes are wired here.
|
|
105
|
+
*/
|
|
106
|
+
export default TaskShowPlugin;
|
|
107
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EAEf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAgCnD;;;;;;GAMG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,IAAI,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,yCAAyC;IACzC,aAAa,IAAI,MAAM,GAAG,IAAI,CAAC;IAC/B,yCAAyC;IACzC,YAAY,IAAI,iBAAiB,CAAC;IAClC,uEAAuE;IACvE,SAAS,IAAI,cAAc,CAAC;CAC7B;AAED;;;GAGG;AACH,qBAAa,cAAe,YAAW,uBAAuB;IAC5D,QAAQ,CAAC,IAAI,0BAA0B;IACvC,QAAQ,CAAC,OAAO,WAAW;IAC3B,QAAQ,CAAC,WAAW,mHAC8F;IAElH,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,GAAG,CAA8B;IACzC,OAAO,CAAC,QAAQ,CAAS;IACzB,8FAA8F;IAC9F,OAAO,CAAC,gBAAgB,CAA0B;IAClD,gHAAgH;IAChH,OAAO,CAAC,UAAU,CAAyC;gBAE/C,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAgB5C;;;;OAIG;IACG,IAAI,CAAC,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB7C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB9B,aAAa,IAAI,MAAM,GAAG,IAAI;IAK9B,YAAY,IAAI,iBAAiB;IAIjC,SAAS,IAAI,cAAc;IAQ3B;;;;OAIG;IACG,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCrF;;;OAGG;IACG,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA2ChD;;;OAGG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO;IAU/C;;;OAGG;IACH,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ3C;;;;OAIG;IACH,OAAO,CAAC,aAAa;YA2BP,wBAAwB;CA+BvC;AA+BD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,cAAc,CAErF;AAED;;;GAGG;AACH,eAAe,cAAc,CAAC"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview TaskShowPlugin — the roy-agent plugin entry point.
|
|
3
|
+
*
|
|
4
|
+
* Lifecycle (mirrors `ReminderPlugin` / `TaskTagPlugin`):
|
|
5
|
+
* 1. Constructor accepts a config (defaults merged in).
|
|
6
|
+
* 2. `init(env)` registers hooks on the global hook manager:
|
|
7
|
+
* - `tool:after.execute` → record each tool call
|
|
8
|
+
* - `task:after.update` → freeze session + emit URL
|
|
9
|
+
* 3. `dispose()` stops the HTTP service & releases listeners.
|
|
10
|
+
*
|
|
11
|
+
* The plugin is intentionally lean: all the heavy lifting lives in
|
|
12
|
+
* `collector.ts`, `server.ts`, and `url-injector.ts`. That keeps this file
|
|
13
|
+
* readable and makes the surface area easy to test.
|
|
14
|
+
*/
|
|
15
|
+
import { DEFAULT_CONFIG } from "./types.js";
|
|
16
|
+
import { ToolCallCollector } from "./collector.js";
|
|
17
|
+
import { TaskShowServer } from "./server.js";
|
|
18
|
+
import { buildVisualizationUrl, injectVisualizationUrl, } from "./url-injector.js";
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Logger
|
|
21
|
+
// ============================================================================
|
|
22
|
+
const TAG = "roy-plugin-task-show";
|
|
23
|
+
function info(msg) {
|
|
24
|
+
if (process.env?.TASK_SHOW_DEBUG) {
|
|
25
|
+
// eslint-disable-next-line no-console
|
|
26
|
+
console.log(`[${TAG}] ${msg}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function warn(msg) {
|
|
30
|
+
// eslint-disable-next-line no-console
|
|
31
|
+
console.warn(`[${TAG}] ${msg}`);
|
|
32
|
+
}
|
|
33
|
+
function error(msg) {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.error(`[${TAG}] ${msg}`);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Main plugin class. Decorated with the static `roy-agent` metadata block
|
|
39
|
+
* via a side-table so we don't have to import the host's BasePlugin.
|
|
40
|
+
*/
|
|
41
|
+
export class TaskShowPlugin {
|
|
42
|
+
name = "roy-plugin-task-show";
|
|
43
|
+
version = "0.1.0";
|
|
44
|
+
description = "Visually trace a task's tool-call chain on a local HTTP service and inject the URL into the last tool result.";
|
|
45
|
+
cfg;
|
|
46
|
+
collector;
|
|
47
|
+
server;
|
|
48
|
+
env = null;
|
|
49
|
+
disposed = false;
|
|
50
|
+
/** Last successful `tool:after.execute` result, used to inject the URL on task completion. */
|
|
51
|
+
lastResultByTask = new Map();
|
|
52
|
+
/** cached list of hook points we registered, so dispose() can be defensive even if the env lacks unregister. */
|
|
53
|
+
registered = [];
|
|
54
|
+
constructor(config) {
|
|
55
|
+
this.cfg = { ...DEFAULT_CONFIG, ...(config ?? {}) };
|
|
56
|
+
this.collector = new ToolCallCollector(this.cfg, {
|
|
57
|
+
onChange: () => info("collector snapshot changed"),
|
|
58
|
+
});
|
|
59
|
+
this.server = new TaskShowServer({
|
|
60
|
+
cfg: this.cfg,
|
|
61
|
+
collector: this.collector,
|
|
62
|
+
publicDir: this.cfg.publicDir,
|
|
63
|
+
// Pass metaUrl best-effort — we want to resolve `public/` relative to
|
|
64
|
+
// the dist directory in production.
|
|
65
|
+
metaUrl: typeof import.meta !== "undefined" ? import.meta.url : undefined,
|
|
66
|
+
logger: { info, warn, error },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Called by the loader (or by tests) with the host's `PluginEnv`. We use
|
|
71
|
+
* the host's `registerHook` if available, otherwise fall back to the
|
|
72
|
+
* global hook manager from `@ai-setting/roy-agent-core`.
|
|
73
|
+
*/
|
|
74
|
+
async init(env) {
|
|
75
|
+
if (this.disposed)
|
|
76
|
+
throw new Error(`${this.name} already disposed`);
|
|
77
|
+
if (this.env)
|
|
78
|
+
throw new Error(`${this.name} already initialized`);
|
|
79
|
+
this.env = env;
|
|
80
|
+
// Start the HTTP service first so we can compute per-task URLs as soon
|
|
81
|
+
// as hooks fire.
|
|
82
|
+
if (this.cfg.autoStart) {
|
|
83
|
+
try {
|
|
84
|
+
const serverInfo = await this.server.start();
|
|
85
|
+
info(`plugin ready at ${serverInfo.url}`);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
error(`failed to start HTTP server: ${err}`);
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
this.registerHooks(env);
|
|
93
|
+
info(`registered ${this.registered.length} hooks`);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Best-effort dispose. We tolerate the absence of `dispose` on the env.
|
|
97
|
+
*/
|
|
98
|
+
async dispose() {
|
|
99
|
+
if (this.disposed)
|
|
100
|
+
return;
|
|
101
|
+
this.disposed = true;
|
|
102
|
+
try {
|
|
103
|
+
await this.server.stop();
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
warn(`server.stop failed: ${err}`);
|
|
107
|
+
}
|
|
108
|
+
this.collector.clear();
|
|
109
|
+
this.lastResultByTask.clear();
|
|
110
|
+
this.env = null;
|
|
111
|
+
this.registered = [];
|
|
112
|
+
}
|
|
113
|
+
getServerPort() {
|
|
114
|
+
const info = this.server.getInfo();
|
|
115
|
+
return info?.port ?? null;
|
|
116
|
+
}
|
|
117
|
+
getCollector() {
|
|
118
|
+
return this.collector;
|
|
119
|
+
}
|
|
120
|
+
getConfig() {
|
|
121
|
+
return { ...this.cfg };
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------
|
|
124
|
+
// Hook handlers (exposed for tests)
|
|
125
|
+
// ---------------------------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Public function exposed so unit tests can simulate the
|
|
128
|
+
* `tool:after.execute` payload without going through the global hook
|
|
129
|
+
* manager.
|
|
130
|
+
*/
|
|
131
|
+
async onToolAfterExecute(ctx, metadata) {
|
|
132
|
+
if (this.disposed)
|
|
133
|
+
return;
|
|
134
|
+
if (!ctx)
|
|
135
|
+
return;
|
|
136
|
+
const tool = ctx.tool ?? ctx.toolDef ?? null;
|
|
137
|
+
const args = ctx.args ?? ctx.arguments ?? {};
|
|
138
|
+
const result = ctx.result ?? ctx.toolResult ?? null;
|
|
139
|
+
const toolName = tool?.name ?? ctx.toolName ?? "unknown";
|
|
140
|
+
const success = !result?.error && (result?.success ?? true);
|
|
141
|
+
const error = result?.error;
|
|
142
|
+
const startTs = metadata?.start_ts ?? ctx.start_ts ?? Date.now();
|
|
143
|
+
const durationMs = typeof ctx.durationMs === "number"
|
|
144
|
+
? ctx.durationMs
|
|
145
|
+
: Math.max(0, Date.now() - Number(startTs));
|
|
146
|
+
const outputPreview = previewOutput(result?.output ?? "");
|
|
147
|
+
const taskId = this.collector.recordToolCall({
|
|
148
|
+
toolName,
|
|
149
|
+
args,
|
|
150
|
+
success,
|
|
151
|
+
outputPreview,
|
|
152
|
+
error: typeof error === "string" ? error : undefined,
|
|
153
|
+
durationMs,
|
|
154
|
+
timestamp: Date.now(),
|
|
155
|
+
iteration: ctx.iteration,
|
|
156
|
+
metadata: result?.metadata,
|
|
157
|
+
ctx,
|
|
158
|
+
});
|
|
159
|
+
// Stash the result so we can inject the URL on completion.
|
|
160
|
+
if (result && typeof result === "object") {
|
|
161
|
+
this.lastResultByTask.set(taskId, result);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Public function exposed for tests; mirrors the `task:after.update`
|
|
166
|
+
* payload.
|
|
167
|
+
*/
|
|
168
|
+
async onTaskAfterUpdate(ctx) {
|
|
169
|
+
if (this.disposed)
|
|
170
|
+
return;
|
|
171
|
+
if (!ctx)
|
|
172
|
+
return;
|
|
173
|
+
// The hook payload may be either the host's `TaskUpdateContext` OR a
|
|
174
|
+
// duck-typed object. We try several shapes.
|
|
175
|
+
const data = (ctx.data ?? ctx);
|
|
176
|
+
const taskId = data?.task?.id ?? data?.taskId ?? data?.id;
|
|
177
|
+
const status = data?.task?.status ??
|
|
178
|
+
data?.status ??
|
|
179
|
+
"completed";
|
|
180
|
+
const title = data?.task?.title ?? data?.title;
|
|
181
|
+
if (typeof taskId !== "number")
|
|
182
|
+
return;
|
|
183
|
+
// Always finalize the session so the index page reflects the new state.
|
|
184
|
+
const finalized = this.collector.finalizeOnTaskUpdate({
|
|
185
|
+
taskId,
|
|
186
|
+
newStatus: status,
|
|
187
|
+
title,
|
|
188
|
+
timestamp: Date.now(),
|
|
189
|
+
});
|
|
190
|
+
if (!finalized)
|
|
191
|
+
return;
|
|
192
|
+
// Inject the URL ONLY when the task is terminal (not "running").
|
|
193
|
+
if (!isTerminalStatus(status))
|
|
194
|
+
return;
|
|
195
|
+
const lastResult = this.lastResultByTask.get(taskId);
|
|
196
|
+
if (!lastResult) {
|
|
197
|
+
// Some tasks may complete without any tool call (e.g. pure response).
|
|
198
|
+
info(`task ${taskId} completed without any recorded tool call — skipping URL injection`);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
const outcome = injectVisualizationUrl({
|
|
202
|
+
ctx: { result: lastResult },
|
|
203
|
+
cfg: this.cfg,
|
|
204
|
+
taskId,
|
|
205
|
+
});
|
|
206
|
+
if (outcome.mutated) {
|
|
207
|
+
info(`injected visualization URL ${outcome.url} into last tool result for task ${taskId}`);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Manual injection hook — useful when a custom caller has a known task
|
|
212
|
+
* id + ToolResult at hand (e.g. tests).
|
|
213
|
+
*/
|
|
214
|
+
injectFor(taskId, result) {
|
|
215
|
+
if (!result || typeof result.output !== "string")
|
|
216
|
+
return false;
|
|
217
|
+
const out = injectVisualizationUrl({
|
|
218
|
+
ctx: { result },
|
|
219
|
+
cfg: this.cfg,
|
|
220
|
+
taskId,
|
|
221
|
+
});
|
|
222
|
+
return out.mutated;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Compute the URL the page would be served at. Helpful in tests where
|
|
226
|
+
* `init()` was skipped.
|
|
227
|
+
*/
|
|
228
|
+
getVisualizationUrl(taskId) {
|
|
229
|
+
return buildVisualizationUrl(this.cfg, taskId);
|
|
230
|
+
}
|
|
231
|
+
// ---------------------------------------------------------------------
|
|
232
|
+
// Internals
|
|
233
|
+
// ---------------------------------------------------------------------
|
|
234
|
+
/**
|
|
235
|
+
* Subscribe to the hook points we care about. We try to use the env's
|
|
236
|
+
* `registerHook` first (the modern, type-safe plugin API), then fall back
|
|
237
|
+
* to the global hook manager if available.
|
|
238
|
+
*/
|
|
239
|
+
registerHooks(env) {
|
|
240
|
+
if (typeof env.registerHook === "function") {
|
|
241
|
+
env.registerHook({
|
|
242
|
+
point: "tool:after.execute",
|
|
243
|
+
priority: 50,
|
|
244
|
+
name: `${this.name}:tool-after`,
|
|
245
|
+
handler: async (ctx) => this.onToolAfterExecute(ctx),
|
|
246
|
+
});
|
|
247
|
+
this.registered.push({ point: "tool:after.execute", name: `${this.name}:tool-after` });
|
|
248
|
+
env.registerHook({
|
|
249
|
+
point: "task:after.update",
|
|
250
|
+
priority: 60,
|
|
251
|
+
name: `${this.name}:task-after`,
|
|
252
|
+
handler: async (ctx) => this.onTaskAfterUpdate(ctx),
|
|
253
|
+
});
|
|
254
|
+
this.registered.push({ point: "task:after.update", name: `${this.name}:task-after` });
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
// Fallback: directly import the global hook manager. We import dynamically
|
|
258
|
+
// so this code works even if `@ai-setting/roy-agent-core` is not yet linked.
|
|
259
|
+
void this.registerViaGlobalManager().catch((err) => {
|
|
260
|
+
warn(`global hook manager registration failed: ${err}`);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
async registerViaGlobalManager() {
|
|
264
|
+
let mgr;
|
|
265
|
+
try {
|
|
266
|
+
mgr = await import("@ai-setting/roy-agent-core");
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
// The plugin can still operate in pure-test mode where no global hook
|
|
270
|
+
// manager exists. We log and bail.
|
|
271
|
+
warn("@ai-setting/roy-agent-core not found — hook manager registration skipped");
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const globalHookManager = mgr.globalHookManager;
|
|
275
|
+
if (!globalHookManager) {
|
|
276
|
+
warn("@ai-setting/roy-agent-core does not export globalHookManager — skipping");
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
globalHookManager.register("tool:after.execute", {
|
|
280
|
+
name: `${this.name}:tool-after`,
|
|
281
|
+
priority: 50,
|
|
282
|
+
execute: async (ctx) => this.onToolAfterExecute(ctx),
|
|
283
|
+
});
|
|
284
|
+
this.registered.push({ point: "tool:after.execute", name: `${this.name}:tool-after` });
|
|
285
|
+
globalHookManager.register("task:after.update", {
|
|
286
|
+
name: `${this.name}:task-after`,
|
|
287
|
+
priority: 60,
|
|
288
|
+
execute: async (ctx) => this.onTaskAfterUpdate(ctx),
|
|
289
|
+
});
|
|
290
|
+
this.registered.push({ point: "task:after.update", name: `${this.name}:task-after` });
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
// ============================================================================
|
|
294
|
+
// Helpers
|
|
295
|
+
// ============================================================================
|
|
296
|
+
const TERMINAL_STATUSES = new Set([
|
|
297
|
+
"completed",
|
|
298
|
+
"failed",
|
|
299
|
+
"cancelled",
|
|
300
|
+
]);
|
|
301
|
+
function isTerminalStatus(status) {
|
|
302
|
+
return TERMINAL_STATUSES.has(status);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Truncate an output string to a useful preview length. We keep the tail
|
|
306
|
+
* because errors and "TRUNCATED ..." notes are more informative than the
|
|
307
|
+
* beginning of a huge blob.
|
|
308
|
+
*/
|
|
309
|
+
function previewOutput(output) {
|
|
310
|
+
if (typeof output !== "string")
|
|
311
|
+
return "";
|
|
312
|
+
const MAX = 512;
|
|
313
|
+
if (output.length <= MAX)
|
|
314
|
+
return output;
|
|
315
|
+
// Keep both ends for context.
|
|
316
|
+
const head = output.slice(0, MAX / 2);
|
|
317
|
+
const tail = output.slice(-MAX / 2);
|
|
318
|
+
return `${head}\n…[truncated ${output.length - MAX} chars]…\n${tail}`;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Convenience factory — used when loaded as a bare ES module (the typical
|
|
322
|
+
* loader pattern in `coder-harness` / `task-tag`).
|
|
323
|
+
*/
|
|
324
|
+
export function createTaskShowPlugin(config) {
|
|
325
|
+
return new TaskShowPlugin(config);
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Default export. The loader imports `default` or `TaskShowPlugin` from this
|
|
329
|
+
* module — both routes are wired here.
|
|
330
|
+
*/
|
|
331
|
+
export default TaskShowPlugin;
|
|
332
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Tiny standalone HTTP server for the visualization frontend.
|
|
3
|
+
*
|
|
4
|
+
* We deliberately avoid Express/Fastify to keep the dependency tree of this
|
|
5
|
+
* plugin at zero. Routes:
|
|
6
|
+
* GET / → index of recent task sessions
|
|
7
|
+
* GET /task/:taskId → detail page (mermaid flow + tables)
|
|
8
|
+
* GET /api/sessions → JSON list of sessions
|
|
9
|
+
* GET /api/sessions/:taskId → JSON detail of one session
|
|
10
|
+
* GET /static/* → static frontend assets (CSS/JS)
|
|
11
|
+
*
|
|
12
|
+
* The server is started/stopped via `TaskShowServer.start()` /
|
|
13
|
+
* `.stop()`. Multiple instances cooperate by random port fallback — if the
|
|
14
|
+
* configured port is busy we let the OS pick a free one and log the actual
|
|
15
|
+
* port.
|
|
16
|
+
*/
|
|
17
|
+
import * as http from "node:http";
|
|
18
|
+
import type { TaskShowConfig } from "./types.js";
|
|
19
|
+
import type { ToolCallCollector } from "./collector.js";
|
|
20
|
+
/** Public-facing server info (returned to whoever called `start`). */
|
|
21
|
+
export interface ServerInfo {
|
|
22
|
+
host: string;
|
|
23
|
+
port: number;
|
|
24
|
+
url: string;
|
|
25
|
+
server: http.Server;
|
|
26
|
+
/** True if the original port was busy and we had to pick a free one. */
|
|
27
|
+
portRewritten: boolean;
|
|
28
|
+
}
|
|
29
|
+
export declare class TaskShowServer {
|
|
30
|
+
private server;
|
|
31
|
+
private readonly cfg;
|
|
32
|
+
private readonly collector;
|
|
33
|
+
private readonly publicRoot;
|
|
34
|
+
private readonly logger;
|
|
35
|
+
constructor(opts: {
|
|
36
|
+
cfg: TaskShowConfig;
|
|
37
|
+
collector: ToolCallCollector;
|
|
38
|
+
/** Absolute or relative path to the directory with public/index.html. */
|
|
39
|
+
publicDir?: string;
|
|
40
|
+
logger?: {
|
|
41
|
+
info: (m: string) => void;
|
|
42
|
+
warn: (m: string) => void;
|
|
43
|
+
error: (m: string) => void;
|
|
44
|
+
};
|
|
45
|
+
metaUrl?: string;
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Start the listener. The promise resolves once the server is bound — but
|
|
49
|
+
* the caller can race against `getInfo()` immediately afterwards.
|
|
50
|
+
*/
|
|
51
|
+
start(): Promise<ServerInfo>;
|
|
52
|
+
/**
|
|
53
|
+
* Read-only accessor used by the plugin entry point to compute the per-task
|
|
54
|
+
* URL after the server has been bound.
|
|
55
|
+
*/
|
|
56
|
+
getInfo(): {
|
|
57
|
+
host: string;
|
|
58
|
+
port: number;
|
|
59
|
+
url: string;
|
|
60
|
+
} | null;
|
|
61
|
+
/**
|
|
62
|
+
* Stop the listener; safe to call multiple times.
|
|
63
|
+
*/
|
|
64
|
+
stop(): Promise<void>;
|
|
65
|
+
private handle;
|
|
66
|
+
/**
|
|
67
|
+
* Render the index page (lists known tasks).
|
|
68
|
+
*/
|
|
69
|
+
private sendIndex;
|
|
70
|
+
/**
|
|
71
|
+
* Send a 404 page that still includes nav + helpful hint.
|
|
72
|
+
*/
|
|
73
|
+
private sendNotFound;
|
|
74
|
+
private serveStatic;
|
|
75
|
+
private json;
|
|
76
|
+
private text;
|
|
77
|
+
private sendHtml;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,KAAK,EAEV,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAMxD,sEAAsE;AACtE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IACpB,wEAAwE;IACxE,aAAa,EAAE,OAAO,CAAC;CACxB;AAcD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;IACrC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoB;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuF;gBAElG,IAAI,EAAE;QAChB,GAAG,EAAE,cAAc,CAAC;QACpB,SAAS,EAAE,iBAAiB,CAAC;QAC7B,yEAAyE;QACzE,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,CAAC,EAAE;YAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;YAAC,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;YAAC,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;SAAE,CAAC;QAC9F,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;IAOD;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,UAAU,CAAC;IA0D5B;;;OAGG;IACH,OAAO,IAAI;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAW7D;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAyBP,MAAM;IAuEpB;;OAEG;IACH,OAAO,CAAC,SAAS;IAKjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,WAAW;IAuBnB,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,IAAI;IAMZ,OAAO,CAAC,QAAQ;CAMjB"}
|