@migor/agentia 0.0.1 → 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 +61 -6
- package/dist/container/container.d.ts +1 -1
- package/dist/core/json.d.ts +2 -0
- package/dist/core/json.js +12 -0
- package/dist/core/json.js.map +1 -0
- package/dist/core/schema.d.ts +2 -1
- package/dist/core/schema.js +11 -9
- package/dist/core/schema.js.map +1 -1
- package/dist/core/tool.d.ts +21 -3
- package/dist/engine/context.d.ts +1 -1
- package/dist/engine/context.js +1 -1
- package/dist/engine/loop.d.ts +4 -2
- package/dist/engine/loop.js +64 -15
- package/dist/engine/loop.js.map +1 -1
- package/dist/engine/types.d.ts +19 -5
- package/dist/index.d.ts +13 -2
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/dist/run/async.d.ts +2 -1
- package/dist/run/async.js.map +1 -1
- package/dist/run/context.js +1 -2
- package/dist/run/context.js.map +1 -1
- package/dist/run/http.d.ts +47 -0
- package/dist/run/http.js +119 -0
- package/dist/run/http.js.map +1 -0
- package/dist/run/memory.d.ts +18 -0
- package/dist/run/memory.js +18 -0
- package/dist/run/memory.js.map +1 -0
- package/dist/run/openai.d.ts +24 -0
- package/dist/run/openai.js +181 -0
- package/dist/run/openai.js.map +1 -0
- package/dist/run/otlp.d.ts +26 -0
- package/dist/run/otlp.js +105 -0
- package/dist/run/otlp.js.map +1 -0
- package/dist/run/run.d.ts +10 -0
- package/dist/run/run.js +31 -0
- package/dist/run/run.js.map +1 -1
- package/dist/run/spec.d.ts +2 -1
- package/dist/run/spec.js.map +1 -1
- package/dist/run/sqliteStore.d.ts +24 -0
- package/dist/run/sqliteStore.js +60 -0
- package/dist/run/sqliteStore.js.map +1 -0
- package/dist/toolkit/collect.d.ts +23 -0
- package/dist/toolkit/collect.js +43 -0
- package/dist/toolkit/collect.js.map +1 -0
- package/dist/toolkit/discover.js +7 -1
- package/dist/toolkit/discover.js.map +1 -1
- package/dist/toolkit/middleware.d.ts +27 -0
- package/dist/toolkit/middleware.js +15 -0
- package/dist/toolkit/middleware.js.map +1 -0
- package/dist/toolkit/module.d.ts +18 -0
- package/dist/toolkit/module.js +34 -1
- package/dist/toolkit/module.js.map +1 -1
- package/dist/toolkit/prompt.js +6 -20
- package/dist/toolkit/prompt.js.map +1 -1
- package/dist/toolkit/skill.js +8 -29
- package/dist/toolkit/skill.js.map +1 -1
- package/dist/toolkit/subagent.js +7 -27
- package/dist/toolkit/subagent.js.map +1 -1
- package/dist/toolkit/tool.d.ts +1 -1
- package/dist/toolkit/tool.js +3 -25
- package/dist/toolkit/tool.js.map +1 -1
- package/dist/toolkit/zod.d.ts +26 -0
- package/dist/toolkit/zod.js +45 -0
- package/dist/toolkit/zod.js.map +1 -0
- package/package.json +28 -18
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAgBvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAgBvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,eAAe;AACf,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAUnD,gBAAgB;AAChB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAGxD,eAAe;AACf,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAKrD,kBAAkB;AAClB,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AASrD,uBAAuB;AACvB,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEnF,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAQvE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3C,oBAAoB;AACpB,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,mBAAmB;AACnB,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/run/async.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
import type { ModelClient } from '../core/tool.js';
|
|
2
3
|
import type { AgentRunResult } from '../engine/types.js';
|
|
3
4
|
import type { RunStatus } from './types.js';
|
|
4
5
|
import type { RunInvocationOptions } from './spec.js';
|
|
@@ -13,7 +14,7 @@ import type { TaskRecord, TaskStore } from './store.js';
|
|
|
13
14
|
* DB/队列宿主只需实现 TaskStore。
|
|
14
15
|
*/
|
|
15
16
|
export interface AsyncRunnerOptions {
|
|
16
|
-
client?:
|
|
17
|
+
client?: ModelClient;
|
|
17
18
|
store?: TaskStore;
|
|
18
19
|
/** 同时执行的任务上限;缺省不限。超出部分排队等槽位(状态保持 queued) */
|
|
19
20
|
concurrency?: number;
|
package/dist/run/async.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async.js","sourceRoot":"","sources":["../../src/run/async.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"async.js","sourceRoot":"","sources":["../../src/run/async.ts"],"names":[],"mappings":"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"}
|
package/dist/run/context.js
CHANGED
|
@@ -2,13 +2,12 @@ import { AsyncLocalStorage } from 'node:async_hooks';
|
|
|
2
2
|
/**
|
|
3
3
|
* Agentia —— run 作用域上下文(spec §2/§9:blackboard + 上下文传播载体)。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* 传播机制:executeRun 在建 Run 后、跑 engine 前,把本次
|
|
6
6
|
* RunContext 放进 AsyncLocalStorage;runAgent 内任何异步调用(含工具执行、
|
|
7
7
|
* 后续 subagent/skill 执行体)同处该 async 上下文,因此工具方法体内可直接
|
|
8
8
|
* `RunContext.current()` 拿到当前 run —— 无需把 ctx 作为参数层层下传。
|
|
9
9
|
*
|
|
10
10
|
* blackboard:单次 run 内累积的项目事实/产物,随 run 释放(spec §2)。
|
|
11
|
-
* 当前 span 句柄与单元 span 容器在后续 Turn(unit span + TraceInterceptor)接入。
|
|
12
11
|
*/
|
|
13
12
|
const store = new AsyncLocalStorage();
|
|
14
13
|
/** 在指定 ctx 下执行(executeRun 内部使用);当前上下文对外以 current() 读取 */
|
package/dist/run/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/run/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/run/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAGrD;;;;;;;;;GASG;AACH,MAAM,KAAK,GAAG,IAAI,iBAAiB,EAAc,CAAC;AAElD,yDAAyD;AACzD,MAAM,UAAU,cAAc,CAAI,GAAe,EAAE,EAAwB;IACzE,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAe,CAAC;AAC1C,CAAC;AAED,MAAM,OAAO,UAAU;IAGA,GAAG;IAFP,UAAU,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEzD,YAAqB,GAAQ;mBAAR,GAAG;IAAQ,CAAC;IAEjC,2CAA2C;IAC3C,MAAM,CAAC,OAAO;QACZ,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IAED,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;IACxB,CAAC;IAED,GAAG,CAAI,GAAW;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAkB,CAAC;IACnD,CAAC;IACD,GAAG,CAAC,GAAW,EAAE,KAAc;QAC7B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;CACF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { SpanError, Trace } from '../core/trace.js';
|
|
3
|
+
import type { AgentStopReason } from '../engine/types.js';
|
|
4
|
+
import { AsyncRunner } from './async.js';
|
|
5
|
+
import type { AppCallable } from './async.js';
|
|
6
|
+
import type { RunInvocationOptions } from './spec.js';
|
|
7
|
+
import type { RunStatus } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Agentia —— HTTP 宿主(spec §6.6:换宿主不换语义,roadmap R3)。
|
|
10
|
+
*
|
|
11
|
+
* 只产出一个 (req, res) handler,不做 listen —— 交给用户
|
|
12
|
+
* `http.createServer(createHttpHandler(app)).listen(...)`,可挂进任意 Node HTTP 框架。
|
|
13
|
+
*
|
|
14
|
+
* 端点契约(全部 JSON):
|
|
15
|
+
* - POST /run 同步 RPC。body = RunInput(string / messages / {prompt|text|messages}),
|
|
16
|
+
* 走 normalizeMessages 规整后同步执行;200 { runId, status, stopReason,
|
|
17
|
+
* finalText, typed?, trace, error? }。status=failed 也照返 200
|
|
18
|
+
* (rethrow:false 语义:硬失败以 error 字段返回,不用 HTTP 错误码表达);
|
|
19
|
+
* 输入无法规整为 messages → 400 { error }。
|
|
20
|
+
* - POST /tasks 异步任务。body { input, idempotencyKey?, options? } →
|
|
21
|
+
* AsyncRunner.submit → 202 TaskRecord(queued,幂等键去重照常生效)。
|
|
22
|
+
* - GET /tasks/<id> 轮询任务记录 → 200 TaskRecord;不存在 → 404。
|
|
23
|
+
*
|
|
24
|
+
* 方法不符 405;路径不符 404;body 非法 JSON 400。runner 缺省内部 new AsyncRunner(app)。
|
|
25
|
+
*/
|
|
26
|
+
/** POST /run 的响应形态 */
|
|
27
|
+
export interface RunHttpResponse {
|
|
28
|
+
runId: string;
|
|
29
|
+
status: RunStatus;
|
|
30
|
+
stopReason: AgentStopReason;
|
|
31
|
+
finalText: string;
|
|
32
|
+
/** 结构化结果(R2 起应用可携带;无则省略) */
|
|
33
|
+
typed?: unknown;
|
|
34
|
+
trace: Trace;
|
|
35
|
+
error?: SpanError;
|
|
36
|
+
}
|
|
37
|
+
/** POST /tasks 的请求体形态 */
|
|
38
|
+
export interface TaskSubmitBody {
|
|
39
|
+
input: unknown;
|
|
40
|
+
idempotencyKey?: string;
|
|
41
|
+
options?: RunInvocationOptions;
|
|
42
|
+
}
|
|
43
|
+
export interface HttpHandlerOptions {
|
|
44
|
+
/** 异步任务宿主;缺省 new AsyncRunner(app)(InMemoryTaskStore) */
|
|
45
|
+
runner?: AsyncRunner;
|
|
46
|
+
}
|
|
47
|
+
export declare function createHttpHandler(app: AppCallable, opts?: HttpHandlerOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
package/dist/run/http.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { AsyncRunner } from './async.js';
|
|
2
|
+
import { normalizeMessages } from './spec.js';
|
|
3
|
+
function sendJson(res, status, body) {
|
|
4
|
+
const payload = JSON.stringify(body);
|
|
5
|
+
res.writeHead(status, {
|
|
6
|
+
'content-type': 'application/json; charset=utf-8',
|
|
7
|
+
'content-length': Buffer.byteLength(payload),
|
|
8
|
+
});
|
|
9
|
+
res.end(payload);
|
|
10
|
+
}
|
|
11
|
+
function readBody(req) {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
const chunks = [];
|
|
14
|
+
req.on('data', (c) => chunks.push(c));
|
|
15
|
+
req.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
|
16
|
+
req.on('error', reject);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function errMessage(e) {
|
|
20
|
+
return e instanceof Error ? e.message : String(e);
|
|
21
|
+
}
|
|
22
|
+
export function createHttpHandler(app, opts = {}) {
|
|
23
|
+
const runner = opts.runner ?? new AsyncRunner(app);
|
|
24
|
+
return async (req, res) => {
|
|
25
|
+
const method = req.method ?? 'GET';
|
|
26
|
+
const pathname = (req.url ?? '/').split('?')[0];
|
|
27
|
+
try {
|
|
28
|
+
if (pathname === '/run') {
|
|
29
|
+
if (method !== 'POST') {
|
|
30
|
+
sendJson(res, 405, { error: `method ${method} not allowed, use POST` });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const input = await parseJsonBody(req, res);
|
|
34
|
+
if (input === PARSE_FAILED)
|
|
35
|
+
return;
|
|
36
|
+
let messages;
|
|
37
|
+
try {
|
|
38
|
+
messages = normalizeMessages(input);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
sendJson(res, 400, { error: errMessage(e) });
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
// rethrow:false —— 与 AsyncRunner 对齐:硬失败也以 status/error 字段返回 200
|
|
45
|
+
const out = await app.run(messages, { rethrow: false });
|
|
46
|
+
const body = {
|
|
47
|
+
runId: out.run.runId,
|
|
48
|
+
status: out.run.status,
|
|
49
|
+
stopReason: out.result.stopReason,
|
|
50
|
+
finalText: out.result.finalText,
|
|
51
|
+
typed: out.result.typed,
|
|
52
|
+
trace: out.result.trace,
|
|
53
|
+
error: out.result.error,
|
|
54
|
+
};
|
|
55
|
+
sendJson(res, 200, body);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (pathname === '/tasks') {
|
|
59
|
+
if (method !== 'POST') {
|
|
60
|
+
sendJson(res, 405, { error: `method ${method} not allowed, use POST` });
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const body = await parseJsonBody(req, res);
|
|
64
|
+
if (body === PARSE_FAILED)
|
|
65
|
+
return;
|
|
66
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) {
|
|
67
|
+
sendJson(res, 400, { error: 'body 需为 { input, idempotencyKey?, options? }' });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const submitBody = body;
|
|
71
|
+
let rec;
|
|
72
|
+
try {
|
|
73
|
+
rec = runner.submit(submitBody.input, {
|
|
74
|
+
idempotencyKey: submitBody.idempotencyKey,
|
|
75
|
+
options: submitBody.options,
|
|
76
|
+
source: 'http',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
sendJson(res, 400, { error: errMessage(e) });
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
sendJson(res, 202, rec);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
if (pathname.startsWith('/tasks/')) {
|
|
87
|
+
if (method !== 'GET') {
|
|
88
|
+
sendJson(res, 405, { error: `method ${method} not allowed, use GET` });
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const taskId = decodeURIComponent(pathname.slice('/tasks/'.length));
|
|
92
|
+
const rec = runner.poll(taskId);
|
|
93
|
+
if (!rec) {
|
|
94
|
+
sendJson(res, 404, { error: `task 不存在: ${taskId}` });
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
sendJson(res, 200, rec);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
sendJson(res, 404, { error: `路径不存在: ${pathname}` });
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
sendJson(res, 500, { error: errMessage(e) });
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const PARSE_FAILED = Symbol('parse-failed');
|
|
108
|
+
/** 读取并解析 JSON body;失败时直接回 400 并返回哨兵。 */
|
|
109
|
+
async function parseJsonBody(req, res) {
|
|
110
|
+
const raw = await readBody(req);
|
|
111
|
+
try {
|
|
112
|
+
return raw ? JSON.parse(raw) : undefined;
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
sendJson(res, 400, { error: '请求 body 不是合法 JSON' });
|
|
116
|
+
return PARSE_FAILED;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/run/http.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAgD9C,SAAS,QAAQ,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAa;IAClE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE;QACpB,cAAc,EAAE,iCAAiC;QACjD,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC;KAC7C,CAAC,CAAC;IACH,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,QAAQ,CAAC,GAAoB;IACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrE,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,UAAU,CAAC,CAAU;IAC5B,OAAO,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,GAAgB,EAChB,IAAI,GAAuB,EAAE;IAE7B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,CAAC;IAEnD,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE;QACxB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC;QACnC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhD,IAAI,CAAC;YACH,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;gBACxB,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;oBACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,MAAM,wBAAwB,EAAE,CAAC,CAAC;oBACxE,OAAO;gBACT,CAAC;gBACD,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC5C,IAAI,KAAK,KAAK,YAAY;oBAAE,OAAO;gBACnC,IAAI,QAAQ,CAAC;gBACb,IAAI,CAAC;oBACH,QAAQ,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC7C,OAAO;gBACT,CAAC;gBACD,gEAAgE;gBAChE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;gBACxD,MAAM,IAAI,GAAoB;oBAC5B,KAAK,EAAE,GAAG,CAAC,GAAG,CAAC,KAAK;oBACpB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,MAAM;oBACtB,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU;oBACjC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS;oBAC/B,KAAK,EAAG,GAAG,CAAC,MAA8B,CAAC,KAAK;oBAChD,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK;oBACvB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK;iBACxB,CAAC;gBACF,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,CAAC;gBACzB,OAAO;YACT,CAAC;YAED,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBAC1B,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;oBACtB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,MAAM,wBAAwB,EAAE,CAAC,CAAC;oBACxE,OAAO;gBACT,CAAC;gBACD,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;gBAC3C,IAAI,IAAI,KAAK,YAAY;oBAAE,OAAO;gBAClC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC7D,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,8CAA8C,EAAE,CAAC,CAAC;oBAC9E,OAAO;gBACT,CAAC;gBACD,MAAM,UAAU,GAAG,IAAsB,CAAC;gBAC1C,IAAI,GAAe,CAAC;gBACpB,IAAI,CAAC;oBACH,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE;wBACpC,cAAc,EAAE,UAAU,CAAC,cAAc;wBACzC,OAAO,EAAE,UAAU,CAAC,OAAO;wBAC3B,MAAM,EAAE,MAAM;qBACf,CAAC,CAAC;gBACL,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC7C,OAAO;gBACT,CAAC;gBACD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;gBACxB,OAAO;YACT,CAAC;YAED,IAAI,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACnC,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;oBACrB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,MAAM,uBAAuB,EAAE,CAAC,CAAC;oBACvE,OAAO;gBACT,CAAC;gBACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;gBACpE,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAChC,IAAI,CAAC,GAAG,EAAE,CAAC;oBACT,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,aAAa,MAAM,EAAE,EAAE,CAAC,CAAC;oBACrD,OAAO;gBACT,CAAC;gBACD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;gBACxB,OAAO;YACT,CAAC;YAED,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,QAAQ,EAAE,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AAE5C,wCAAwC;AACxC,KAAK,UAAU,aAAa,CAC1B,GAAoB,EACpB,GAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACnD,OAAO,YAAY,CAAC;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryStore —— 跨 run 记忆(R4)。
|
|
3
|
+
*
|
|
4
|
+
* blackboard(RunContext)随单次 run 释放;MemoryStore 在 run 边界做
|
|
5
|
+
* 水合/回写:run 开始时把 load(keys) 注入 blackboard,run 结束时把
|
|
6
|
+
* 这些 key 的当前值 save 回 store —— 同一份 store 跨多次 executeRun
|
|
7
|
+
* 复用即得跨 run 记忆。接线见 run/run.ts 的 ExecuteRunOptions.memory。
|
|
8
|
+
*/
|
|
9
|
+
export interface MemoryStore {
|
|
10
|
+
load(keys: string[]): Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
11
|
+
save(entries: Record<string, unknown>): void | Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
/** Map 实现:测试与缺省场景用(进程内,无持久化) */
|
|
14
|
+
export declare class InMemoryMemoryStore implements MemoryStore {
|
|
15
|
+
private readonly data;
|
|
16
|
+
load(keys: string[]): Record<string, unknown>;
|
|
17
|
+
save(entries: Record<string, unknown>): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Map 实现:测试与缺省场景用(进程内,无持久化) */
|
|
2
|
+
export class InMemoryMemoryStore {
|
|
3
|
+
data = new Map();
|
|
4
|
+
load(keys) {
|
|
5
|
+
const out = {};
|
|
6
|
+
for (const key of keys) {
|
|
7
|
+
if (this.data.has(key))
|
|
8
|
+
out[key] = this.data.get(key);
|
|
9
|
+
}
|
|
10
|
+
return out;
|
|
11
|
+
}
|
|
12
|
+
save(entries) {
|
|
13
|
+
for (const [key, value] of Object.entries(entries)) {
|
|
14
|
+
this.data.set(key, value);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/run/memory.ts"],"names":[],"mappings":"AAaA,gCAAgC;AAChC,MAAM,OAAO,mBAAmB;IACb,IAAI,GAAG,IAAI,GAAG,EAAmB,CAAC;IAEnD,IAAI,CAAC,IAAc;QACjB,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,CAAC,OAAgC;QACnC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ModelClient } from '../core/tool.js';
|
|
2
|
+
/**
|
|
3
|
+
* OpenAI 兼容端点适配器(R4 多模型)。
|
|
4
|
+
*
|
|
5
|
+
* 把 engine 的 Anthropic 形态请求翻译成 OpenAI chat.completions 请求,
|
|
6
|
+
* 响应再翻译回 Anthropic.Message —— 产出的 ModelClient 可直接喂给
|
|
7
|
+
* executeRun / runAgent 的 client 选项。兼容端点(DeepSeek 等)换 baseURL 即可。
|
|
8
|
+
*
|
|
9
|
+
* 边界(近似映射,头部声明):
|
|
10
|
+
* - 非流式模拟:底层一次性 POST(stream:false),on('text') 回调在
|
|
11
|
+
* finalMessage() 完成后收到一次完整文本,而非逐 token 增量;
|
|
12
|
+
* - cache token 恒 0:OpenAI 形态无 prompt cache 计量字段;
|
|
13
|
+
* - refusal 为近似:finish_reason=content_filter 映射为 'refusal',
|
|
14
|
+
* 语义上接近但不等同 Anthropic 的流式分类器干预。
|
|
15
|
+
*/
|
|
16
|
+
export interface OpenAIClientOptions {
|
|
17
|
+
/** 缺省读 env OPENAI_API_KEY */
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
/** 缺省 https://api.openai.com;兼容端点直接替换(如 https://api.deepseek.com) */
|
|
20
|
+
baseURL?: string;
|
|
21
|
+
/** 测试注入用 */
|
|
22
|
+
fetchImpl?: typeof fetch;
|
|
23
|
+
}
|
|
24
|
+
export declare function createOpenAIClient(opts?: OpenAIClientOptions): ModelClient;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
export function createOpenAIClient(opts = {}) {
|
|
2
|
+
const baseURL = (opts.baseURL ?? 'https://api.openai.com').replace(/\/+$/, '');
|
|
3
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
4
|
+
const apiKey = opts.apiKey ?? process.env.OPENAI_API_KEY;
|
|
5
|
+
return {
|
|
6
|
+
messages: {
|
|
7
|
+
stream(params) {
|
|
8
|
+
const textCallbacks = [];
|
|
9
|
+
return {
|
|
10
|
+
on(event, cb) {
|
|
11
|
+
if (event === 'text')
|
|
12
|
+
textCallbacks.push(cb);
|
|
13
|
+
},
|
|
14
|
+
async finalMessage() {
|
|
15
|
+
const res = await fetchImpl(`${baseURL}/v1/chat/completions`, {
|
|
16
|
+
method: 'POST',
|
|
17
|
+
headers: {
|
|
18
|
+
'content-type': 'application/json',
|
|
19
|
+
...(apiKey ? { authorization: `Bearer ${apiKey}` } : {}),
|
|
20
|
+
},
|
|
21
|
+
body: JSON.stringify(toOpenAIRequest(params)),
|
|
22
|
+
});
|
|
23
|
+
if (!res.ok) {
|
|
24
|
+
const body = await res.text();
|
|
25
|
+
throw new Error(`OpenAI 请求失败 ${res.status}: ${body.slice(0, 200)}`);
|
|
26
|
+
}
|
|
27
|
+
const data = (await res.json());
|
|
28
|
+
const message = toAnthropicMessage(data, params.model);
|
|
29
|
+
// 非流式模拟:完整文本一次性发给 text 回调
|
|
30
|
+
const fullText = message.content
|
|
31
|
+
.filter((b) => b.type === 'text')
|
|
32
|
+
.map((b) => b.text)
|
|
33
|
+
.join('');
|
|
34
|
+
if (fullText)
|
|
35
|
+
for (const cb of textCallbacks)
|
|
36
|
+
cb(fullText);
|
|
37
|
+
return message;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Anthropic 请求形态 → OpenAI chat.completions 请求 */
|
|
45
|
+
function toOpenAIRequest(params) {
|
|
46
|
+
const messages = [];
|
|
47
|
+
if (params.system) {
|
|
48
|
+
messages.push({
|
|
49
|
+
role: 'system',
|
|
50
|
+
content: typeof params.system === 'string'
|
|
51
|
+
? params.system
|
|
52
|
+
: params.system.map((b) => b.text).join('\n'),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
for (const m of params.messages) {
|
|
56
|
+
if (typeof m.content === 'string') {
|
|
57
|
+
messages.push({ role: m.role, content: m.content });
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (m.role === 'user') {
|
|
61
|
+
// tool_result blocks:每个 block 一条 role=tool 消息;其余合成一条 user
|
|
62
|
+
const blocks = m.content;
|
|
63
|
+
const toolResults = blocks.filter((b) => b.type === 'tool_result');
|
|
64
|
+
const rest = blocks.filter((b) => b.type !== 'tool_result');
|
|
65
|
+
for (const tr of toolResults) {
|
|
66
|
+
messages.push({
|
|
67
|
+
role: 'tool',
|
|
68
|
+
tool_call_id: tr.tool_use_id,
|
|
69
|
+
content: tr.content === undefined
|
|
70
|
+
? ''
|
|
71
|
+
: typeof tr.content === 'string'
|
|
72
|
+
? tr.content
|
|
73
|
+
: JSON.stringify(tr.content),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
if (rest.length > 0)
|
|
77
|
+
messages.push({ role: 'user', content: renderBlocks(rest) });
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// assistant:文本部分进 content(无则 null),tool_use → tool_calls
|
|
81
|
+
const blocks = m.content;
|
|
82
|
+
const text = blocks
|
|
83
|
+
.filter((b) => b.type === 'text')
|
|
84
|
+
.map((b) => b.text)
|
|
85
|
+
.join('\n');
|
|
86
|
+
const toolUses = blocks.filter((b) => b.type === 'tool_use');
|
|
87
|
+
messages.push({
|
|
88
|
+
role: 'assistant',
|
|
89
|
+
content: text || null,
|
|
90
|
+
...(toolUses.length > 0
|
|
91
|
+
? {
|
|
92
|
+
tool_calls: toolUses.map((tu) => ({
|
|
93
|
+
id: tu.id,
|
|
94
|
+
type: 'function',
|
|
95
|
+
function: { name: tu.name, arguments: JSON.stringify(tu.input) },
|
|
96
|
+
})),
|
|
97
|
+
}
|
|
98
|
+
: {}),
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
model: params.model,
|
|
104
|
+
max_tokens: params.max_tokens,
|
|
105
|
+
messages,
|
|
106
|
+
...(params.tools && params.tools.length > 0
|
|
107
|
+
? {
|
|
108
|
+
tools: params.tools.map((t) => ({
|
|
109
|
+
type: 'function',
|
|
110
|
+
function: {
|
|
111
|
+
name: t.name,
|
|
112
|
+
...(t.description ? { description: t.description } : {}),
|
|
113
|
+
parameters: t.input_schema,
|
|
114
|
+
},
|
|
115
|
+
})),
|
|
116
|
+
}
|
|
117
|
+
: {}),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** user 消息中非 tool_result 的 blocks 合成一段文本(text 取文本,其余 JSON 兜底) */
|
|
121
|
+
function renderBlocks(blocks) {
|
|
122
|
+
return blocks
|
|
123
|
+
.map((b) => (b.type === 'text' ? b.text : JSON.stringify(b)))
|
|
124
|
+
.join('\n');
|
|
125
|
+
}
|
|
126
|
+
/** OpenAI chat.completions 响应 → Anthropic.Message */
|
|
127
|
+
function toAnthropicMessage(data, model) {
|
|
128
|
+
const choice = data.choices?.[0];
|
|
129
|
+
const msg = choice?.message ?? {};
|
|
130
|
+
const content = [];
|
|
131
|
+
if (typeof msg.content === 'string' && msg.content) {
|
|
132
|
+
content.push({ type: 'text', text: msg.content });
|
|
133
|
+
}
|
|
134
|
+
for (const tc of msg.tool_calls ?? []) {
|
|
135
|
+
let input;
|
|
136
|
+
try {
|
|
137
|
+
input = JSON.parse(tc.function.arguments);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// arguments 非法 JSON:原样字符串兜底,交给下游 schema 校验报 is_error
|
|
141
|
+
input = tc.function.arguments;
|
|
142
|
+
}
|
|
143
|
+
content.push({
|
|
144
|
+
type: 'tool_use',
|
|
145
|
+
id: tc.id,
|
|
146
|
+
name: tc.function.name,
|
|
147
|
+
input,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
id: data.id ?? 'chatcmpl-unknown',
|
|
152
|
+
type: 'message',
|
|
153
|
+
role: 'assistant',
|
|
154
|
+
model: data.model ?? model,
|
|
155
|
+
content,
|
|
156
|
+
stop_reason: mapStopReason(choice?.finish_reason),
|
|
157
|
+
stop_sequence: null,
|
|
158
|
+
usage: {
|
|
159
|
+
input_tokens: data.usage?.prompt_tokens ?? 0,
|
|
160
|
+
output_tokens: data.usage?.completion_tokens ?? 0,
|
|
161
|
+
// OpenAI 形态无 cache 计量:恒 0
|
|
162
|
+
cache_creation_input_tokens: 0,
|
|
163
|
+
cache_read_input_tokens: 0,
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/** finish_reason → Anthropic stop_reason(content_filter→refusal 为近似映射) */
|
|
168
|
+
function mapStopReason(finish) {
|
|
169
|
+
switch (finish) {
|
|
170
|
+
case 'tool_calls':
|
|
171
|
+
return 'tool_use';
|
|
172
|
+
case 'length':
|
|
173
|
+
return 'max_tokens';
|
|
174
|
+
case 'content_filter':
|
|
175
|
+
return 'refusal';
|
|
176
|
+
case 'stop':
|
|
177
|
+
default:
|
|
178
|
+
return 'end_turn';
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/run/openai.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Trace } from '../core/trace.js';
|
|
2
|
+
/**
|
|
3
|
+
* Agentia —— OTLP trace 导出(spec §9.3 生产方向,roadmap R3)。
|
|
4
|
+
*
|
|
5
|
+
* 把一次 run 的 Trace 映射为 OTLP/JSON(resourceSpans → scopeSpans → spans),
|
|
6
|
+
* 用全局 fetch POST 到 `${endpoint}/v1/traces`,零外部依赖:
|
|
7
|
+
* - traceId/spanId/parentSpanId:内部用 UUID,OTLP 要求 hex —— 去掉 '-' 即 32 位 hex;
|
|
8
|
+
* - kind 固定 SPAN_KIND_INTERNAL(1);时间 ms × 1e6 转 string 纳秒;
|
|
9
|
+
* - status:ok → STATUS_CODE_OK,error → STATUS_CODE_ERROR(附 error.message);
|
|
10
|
+
* - attributes 展平 span.attributes + usage(usage.* 前缀);
|
|
11
|
+
* - events → OTLP events(body 的原始类型字段进 attributes,其余 JSON 化)。
|
|
12
|
+
*
|
|
13
|
+
* 非 2xx 抛错(含状态码与响应前 200 字符)。导出失败不影响 run 本身 —— 调用方自行取舍。
|
|
14
|
+
*/
|
|
15
|
+
export interface OtlpExporterOptions {
|
|
16
|
+
/** collector 基地址,例如 http://localhost:4318(尾部斜杠会被去掉) */
|
|
17
|
+
endpoint: string;
|
|
18
|
+
/** 额外请求头(鉴权等) */
|
|
19
|
+
headers?: Record<string, string>;
|
|
20
|
+
/** resource 的 service.name,缺省 'agentia' */
|
|
21
|
+
serviceName?: string;
|
|
22
|
+
}
|
|
23
|
+
export interface OtlpExporter {
|
|
24
|
+
export(trace: Trace): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export declare function createOtlpExporter(opts: OtlpExporterOptions): OtlpExporter;
|
package/dist/run/otlp.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
function toValue(v) {
|
|
2
|
+
if (typeof v === 'string')
|
|
3
|
+
return { stringValue: v };
|
|
4
|
+
if (typeof v === 'boolean')
|
|
5
|
+
return { boolValue: v };
|
|
6
|
+
// OTLP int64 走 string;小数用 double
|
|
7
|
+
return Number.isInteger(v) ? { intValue: String(v) } : { doubleValue: v };
|
|
8
|
+
}
|
|
9
|
+
/** 内部 UUID → OTLP hex(去掉 '-' 即 32 位小写 hex) */
|
|
10
|
+
function hexId(id) {
|
|
11
|
+
return id.replaceAll('-', '');
|
|
12
|
+
}
|
|
13
|
+
/** ms → string 纳秒 */
|
|
14
|
+
function nanos(ms) {
|
|
15
|
+
return String(Math.round(ms * 1e6));
|
|
16
|
+
}
|
|
17
|
+
function spanAttributes(span) {
|
|
18
|
+
const attrs = Object.entries(span.attributes).map(([key, v]) => ({
|
|
19
|
+
key,
|
|
20
|
+
value: toValue(v),
|
|
21
|
+
}));
|
|
22
|
+
if (span.usage) {
|
|
23
|
+
const u = span.usage;
|
|
24
|
+
attrs.push({ key: 'usage.inputTokens', value: toValue(u.inputTokens) }, { key: 'usage.outputTokens', value: toValue(u.outputTokens) }, { key: 'usage.cacheReadTokens', value: toValue(u.cacheReadTokens) }, { key: 'usage.cacheCreationTokens', value: toValue(u.cacheCreationTokens) });
|
|
25
|
+
if (u.costEstimate !== undefined) {
|
|
26
|
+
attrs.push({ key: 'usage.costEstimate', value: toValue(u.costEstimate) });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return attrs;
|
|
30
|
+
}
|
|
31
|
+
function eventAttributes(body) {
|
|
32
|
+
if (body === undefined)
|
|
33
|
+
return [];
|
|
34
|
+
if (body && typeof body === 'object' && !Array.isArray(body)) {
|
|
35
|
+
return Object.entries(body).map(([key, v]) => ({
|
|
36
|
+
key,
|
|
37
|
+
value: typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean'
|
|
38
|
+
? toValue(v)
|
|
39
|
+
: { stringValue: JSON.stringify(v) },
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
return [{ key: 'body', value: { stringValue: JSON.stringify(body) } }];
|
|
43
|
+
}
|
|
44
|
+
function mapEvent(e) {
|
|
45
|
+
return {
|
|
46
|
+
timeUnixNano: nanos(e.time),
|
|
47
|
+
name: e.name,
|
|
48
|
+
attributes: eventAttributes(e.body),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function mapSpan(span) {
|
|
52
|
+
return {
|
|
53
|
+
traceId: hexId(span.traceId),
|
|
54
|
+
spanId: hexId(span.spanId),
|
|
55
|
+
...(span.parentSpanId ? { parentSpanId: hexId(span.parentSpanId) } : {}),
|
|
56
|
+
name: span.name,
|
|
57
|
+
kind: 1, // SPAN_KIND_INTERNAL
|
|
58
|
+
startTimeUnixNano: nanos(span.startedAt),
|
|
59
|
+
...(span.endedAt !== undefined ? { endTimeUnixNano: nanos(span.endedAt) } : {}),
|
|
60
|
+
attributes: spanAttributes(span),
|
|
61
|
+
events: span.events.map(mapEvent),
|
|
62
|
+
status: span.status === 'error'
|
|
63
|
+
? {
|
|
64
|
+
code: 'STATUS_CODE_ERROR',
|
|
65
|
+
...(span.error ? { message: span.error.message } : {}),
|
|
66
|
+
}
|
|
67
|
+
: { code: 'STATUS_CODE_OK' },
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function createOtlpExporter(opts) {
|
|
71
|
+
const endpoint = opts.endpoint.replace(/\/+$/, '');
|
|
72
|
+
const serviceName = opts.serviceName ?? 'agentia';
|
|
73
|
+
return {
|
|
74
|
+
async export(trace) {
|
|
75
|
+
const payload = {
|
|
76
|
+
resourceSpans: [
|
|
77
|
+
{
|
|
78
|
+
resource: {
|
|
79
|
+
attributes: [{ key: 'service.name', value: { stringValue: serviceName } }],
|
|
80
|
+
},
|
|
81
|
+
scopeSpans: [
|
|
82
|
+
{
|
|
83
|
+
scope: { name: 'agentia' },
|
|
84
|
+
spans: trace.spans.map(mapSpan),
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
};
|
|
90
|
+
const res = await fetch(`${endpoint}/v1/traces`, {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: {
|
|
93
|
+
'content-type': 'application/json',
|
|
94
|
+
...opts.headers,
|
|
95
|
+
},
|
|
96
|
+
body: JSON.stringify(payload),
|
|
97
|
+
});
|
|
98
|
+
if (!res.ok) {
|
|
99
|
+
const text = (await res.text()).slice(0, 200);
|
|
100
|
+
throw new Error(`OTLP 导出失败: HTTP ${res.status} ${text}`);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=otlp.js.map
|