@router-agent/runtime 0.0.0-stage → 0.3.32
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/dist/agents/claude.d.ts +51 -0
- package/dist/agents/claude.js +270 -0
- package/dist/agents/claude.js.map +1 -0
- package/dist/agents/codex.d.ts +36 -0
- package/dist/agents/codex.js +292 -0
- package/dist/agents/codex.js.map +1 -0
- package/dist/agents/profile.d.ts +39 -0
- package/dist/agents/profile.js +2 -0
- package/dist/agents/profile.js.map +1 -0
- package/dist/agents/registry.d.ts +21 -0
- package/dist/agents/registry.js +78 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +9 -0
- package/dist/errors.js.map +1 -0
- package/dist/evidence-gate.d.ts +78 -0
- package/dist/evidence-gate.js +196 -0
- package/dist/evidence-gate.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/naming.d.ts +23 -0
- package/dist/naming.js +40 -0
- package/dist/naming.js.map +1 -0
- package/dist/permissions/acp.d.ts +21 -0
- package/dist/permissions/acp.js +73 -0
- package/dist/permissions/acp.js.map +1 -0
- package/dist/permissions.d.ts +1 -0
- package/dist/permissions.js +2 -0
- package/dist/permissions.js.map +1 -0
- package/dist/plugins/loader.d.ts +46 -0
- package/dist/plugins/loader.js +117 -0
- package/dist/plugins/loader.js.map +1 -0
- package/dist/plugins/types.d.ts +52 -0
- package/dist/plugins/types.js +2 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/port.d.ts +295 -0
- package/dist/port.js +17 -0
- package/dist/port.js.map +1 -0
- package/dist/registry.d.ts +13 -0
- package/dist/registry.js +35 -0
- package/dist/registry.js.map +1 -0
- package/dist/report-poller.d.ts +58 -0
- package/dist/report-poller.js +130 -0
- package/dist/report-poller.js.map +1 -0
- package/dist/resume.d.ts +52 -0
- package/dist/resume.js +109 -0
- package/dist/resume.js.map +1 -0
- package/dist/runtimes/acp-agents.d.ts +85 -0
- package/dist/runtimes/acp-agents.js +167 -0
- package/dist/runtimes/acp-agents.js.map +1 -0
- package/dist/runtimes/acp-detect-utils.d.ts +4 -0
- package/dist/runtimes/acp-detect-utils.js +35 -0
- package/dist/runtimes/acp-detect-utils.js.map +1 -0
- package/dist/runtimes/builtin-options.d.ts +3 -0
- package/dist/runtimes/builtin-options.js +44 -0
- package/dist/runtimes/builtin-options.js.map +1 -0
- package/dist/runtimes/catalog.d.ts +31 -0
- package/dist/runtimes/catalog.js +75 -0
- package/dist/runtimes/catalog.js.map +1 -0
- package/dist/runtimes/options.d.ts +60 -0
- package/dist/runtimes/options.js +89 -0
- package/dist/runtimes/options.js.map +1 -0
- package/dist/spec/contract.md +120 -0
- package/dist/spec/index.d.ts +35 -0
- package/dist/spec/index.js +59 -0
- package/dist/spec/index.js.map +1 -0
- package/dist/spec/prompt-mode.md +176 -0
- package/dist/spec/reader.d.ts +5 -0
- package/dist/spec/reader.js +32 -0
- package/dist/spec/reader.js.map +1 -0
- package/dist/status.d.ts +8 -0
- package/dist/status.js +22 -0
- package/dist/status.js.map +1 -0
- package/dist/workspaces/git-worktree.d.ts +44 -0
- package/dist/workspaces/git-worktree.js +183 -0
- package/dist/workspaces/git-worktree.js.map +1 -0
- package/dist/workspaces/overview.d.ts +66 -0
- package/dist/workspaces/overview.js +12 -0
- package/dist/workspaces/overview.js.map +1 -0
- package/package.json +36 -4
- package/README.md +0 -3
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export function decidePermission(tools, toolCall, options) {
|
|
2
|
+
const kind = normalizeKind(toolCall.kind);
|
|
3
|
+
const allowed = isAllowed(tools, kind, toolCall);
|
|
4
|
+
const desired = allowed ? 'allow' : 'reject';
|
|
5
|
+
return options.find(option => option.kind.startsWith(desired)) ?? null;
|
|
6
|
+
}
|
|
7
|
+
export function isAllowed(tools, kind, toolCall) {
|
|
8
|
+
switch (kind) {
|
|
9
|
+
case 'read':
|
|
10
|
+
case 'search':
|
|
11
|
+
case 'think':
|
|
12
|
+
return true;
|
|
13
|
+
case 'fetch':
|
|
14
|
+
return tools.allowNetwork;
|
|
15
|
+
case 'edit':
|
|
16
|
+
case 'move':
|
|
17
|
+
case 'delete':
|
|
18
|
+
return tools.fileAccess === 'read-write';
|
|
19
|
+
case 'execute':
|
|
20
|
+
return shellAllowed(tools, commandOf(toolCall));
|
|
21
|
+
case 'other':
|
|
22
|
+
default:
|
|
23
|
+
return tools.fileAccess === 'read-write';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function shellAllowed(tools, command) {
|
|
27
|
+
if (tools.shell === 'deny')
|
|
28
|
+
return false;
|
|
29
|
+
if (tools.shell === 'allow')
|
|
30
|
+
return true;
|
|
31
|
+
if (!command)
|
|
32
|
+
return false;
|
|
33
|
+
return (tools.shellAllow ?? []).some(prefix => {
|
|
34
|
+
const value = prefix.trim();
|
|
35
|
+
if (!value)
|
|
36
|
+
return false;
|
|
37
|
+
return command === value || command.startsWith(`${value} `);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
export function commandOf(toolCall) {
|
|
41
|
+
const raw = toolCall.rawInput;
|
|
42
|
+
if (raw && typeof raw === 'object') {
|
|
43
|
+
const record = raw;
|
|
44
|
+
if (typeof record.command === 'string')
|
|
45
|
+
return record.command.trim() || null;
|
|
46
|
+
if (Array.isArray(record.command) && record.command.every(item => typeof item === 'string')) {
|
|
47
|
+
return record.command.join(' ').trim() || null;
|
|
48
|
+
}
|
|
49
|
+
const argv = record.argv ?? record.args;
|
|
50
|
+
if (Array.isArray(argv) && argv.every(item => typeof item === 'string')) {
|
|
51
|
+
return argv.join(' ').trim() || null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (typeof toolCall.title === 'string')
|
|
55
|
+
return toolCall.title.trim() || null;
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function normalizeKind(kind) {
|
|
59
|
+
switch (kind) {
|
|
60
|
+
case 'read':
|
|
61
|
+
case 'edit':
|
|
62
|
+
case 'delete':
|
|
63
|
+
case 'move':
|
|
64
|
+
case 'search':
|
|
65
|
+
case 'execute':
|
|
66
|
+
case 'think':
|
|
67
|
+
case 'fetch':
|
|
68
|
+
return kind;
|
|
69
|
+
default:
|
|
70
|
+
return 'other';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=acp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/permissions/acp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './permissions/acp.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../../../packages/runtime/src/permissions.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { RuntimeConfigView } from '@router-agent/core/config.js';
|
|
2
|
+
import { type Logger } from '@router-agent/infra/logger.js';
|
|
3
|
+
import type { CommandRunner } from '@router-agent/infra/process.js';
|
|
4
|
+
import { type PluginFailure } from '@router-agent/infra/plugin-loader.js';
|
|
5
|
+
import { RuntimeRegistry } from '../registry.js';
|
|
6
|
+
import type { RuntimeOptionSpec } from '../runtimes/options.js';
|
|
7
|
+
import type { PluginEntry, PluginModuleLoader } from '../plugins/types.js';
|
|
8
|
+
import type { RuntimePluginMeta } from './types.js';
|
|
9
|
+
export declare const DEFAULT_RUNTIME_PLUGINS: Readonly<Record<string, string>>;
|
|
10
|
+
export interface RuntimePluginConfigView extends RuntimeConfigView {
|
|
11
|
+
runtime: RuntimeConfigView['runtime'] & {
|
|
12
|
+
plugins?: Record<string, PluginEntry>;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export declare function pluginEntryOf(config: RuntimePluginConfigView, kind: 'runtime', id: string): string;
|
|
16
|
+
export declare function describePluginLoadError(kind: 'runtime' | 'channel', id: string, error: unknown): string;
|
|
17
|
+
export interface RuntimePluginDeps {
|
|
18
|
+
home: string;
|
|
19
|
+
workersDir: string;
|
|
20
|
+
logger?: Logger;
|
|
21
|
+
env?: NodeJS.ProcessEnv;
|
|
22
|
+
runners?: {
|
|
23
|
+
orca?: CommandRunner;
|
|
24
|
+
claude?: CommandRunner;
|
|
25
|
+
git?: CommandRunner;
|
|
26
|
+
herdr?: CommandRunner;
|
|
27
|
+
};
|
|
28
|
+
claudeBin?: string;
|
|
29
|
+
claudeProjectsDir?: string;
|
|
30
|
+
loader?: PluginModuleLoader;
|
|
31
|
+
/** 测试注入:跳过内置包加载。 */
|
|
32
|
+
builtins?: readonly string[];
|
|
33
|
+
}
|
|
34
|
+
export interface LoadedRuntimePlugins {
|
|
35
|
+
registry: RuntimeRegistry;
|
|
36
|
+
metas: RuntimePluginMeta[];
|
|
37
|
+
specs: RuntimeOptionSpec[];
|
|
38
|
+
/** 已加载的运行时 id;未知 id 用于配置校验。 */
|
|
39
|
+
ids: string[];
|
|
40
|
+
/** 插件元数据 id → createAll() 实际注册的运行时 id;自定义多实例运行时用。 */
|
|
41
|
+
loadedIds: Record<string, string[]>;
|
|
42
|
+
/** 加载失败的插件;启动不阻塞,但面板与 doctor 要能看到。 */
|
|
43
|
+
failures: PluginFailure[];
|
|
44
|
+
}
|
|
45
|
+
/** 加载 runtime 插件并创建 adapter;单个插件失败只记录,不阻塞其它运行时。 */
|
|
46
|
+
export declare function loadRuntimePlugins(config: RuntimePluginConfigView, deps: RuntimePluginDeps): Promise<LoadedRuntimePlugins>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { errorMessage, noopLogger } from '@router-agent/infra/logger.js';
|
|
2
|
+
import { loadPluginModules, pluginEntryTarget, pluginSpecifier, } from '@router-agent/infra/plugin-loader.js';
|
|
3
|
+
import { RuntimeRegistry } from '../registry.js';
|
|
4
|
+
import { RuntimePluginError } from '../errors.js';
|
|
5
|
+
export const DEFAULT_RUNTIME_PLUGINS = {
|
|
6
|
+
orca: '@router-agent/runtime-orca',
|
|
7
|
+
'claude-code': '@router-agent/runtime-claude-code',
|
|
8
|
+
'codex-app': '@router-agent/runtime-codex',
|
|
9
|
+
acp: '@router-agent/runtime-acp',
|
|
10
|
+
herdr: '@router-agent/runtime-herdr',
|
|
11
|
+
};
|
|
12
|
+
export function pluginEntryOf(config, kind, id) {
|
|
13
|
+
const entry = config.runtime.plugins?.[id];
|
|
14
|
+
return pluginSpecifier(entry) ?? DEFAULT_RUNTIME_PLUGINS[id] ?? id;
|
|
15
|
+
}
|
|
16
|
+
export function describePluginLoadError(kind, id, error) {
|
|
17
|
+
return `${kind} 插件 ${id} 加载失败:${errorMessage(error)}`;
|
|
18
|
+
}
|
|
19
|
+
/** 加载 runtime 插件并创建 adapter;单个插件失败只记录,不阻塞其它运行时。 */
|
|
20
|
+
export async function loadRuntimePlugins(config, deps) {
|
|
21
|
+
const logger = deps.logger ?? noopLogger;
|
|
22
|
+
const loader = deps.loader;
|
|
23
|
+
const entries = config.runtime.plugins;
|
|
24
|
+
const builtins = deps.builtins ?? Object.keys(DEFAULT_RUNTIME_PLUGINS);
|
|
25
|
+
const ids = [...new Set([...builtins, ...Object.keys(entries ?? {})])];
|
|
26
|
+
const loaded = await loadPluginModules({
|
|
27
|
+
kind: 'runtime',
|
|
28
|
+
home: deps.home,
|
|
29
|
+
ids,
|
|
30
|
+
...(loader ? { loader } : {}),
|
|
31
|
+
logger,
|
|
32
|
+
specifierOf: id => specifierOf(entries, id),
|
|
33
|
+
entryOf: id => pluginEntryTarget(entries?.[id]),
|
|
34
|
+
});
|
|
35
|
+
const plugins = loaded.plugins;
|
|
36
|
+
const ctx = {
|
|
37
|
+
home: deps.home,
|
|
38
|
+
workersDir: deps.workersDir,
|
|
39
|
+
config,
|
|
40
|
+
env: deps.env ?? process.env,
|
|
41
|
+
logger,
|
|
42
|
+
runners: {
|
|
43
|
+
orca: deps.runners?.orca ?? missingRunner('orca'),
|
|
44
|
+
claude: deps.runners?.claude ?? missingRunner('claude'),
|
|
45
|
+
git: deps.runners?.git ?? missingRunner('git'),
|
|
46
|
+
herdr: deps.runners?.herdr ?? missingRunner('herdr'),
|
|
47
|
+
},
|
|
48
|
+
...(deps.claudeBin ? { claudeBin: deps.claudeBin } : {}),
|
|
49
|
+
...(deps.claudeProjectsDir ? { claudeProjectsDir: deps.claudeProjectsDir } : {}),
|
|
50
|
+
};
|
|
51
|
+
const runtimes = new Map();
|
|
52
|
+
const metas = [];
|
|
53
|
+
const specs = [];
|
|
54
|
+
const loadedIds = {};
|
|
55
|
+
for (const { id, plugin } of loaded.entries) {
|
|
56
|
+
try {
|
|
57
|
+
const instances = plugin.createAll ? await plugin.createAll(ctx) : [await plugin.create(ctx)];
|
|
58
|
+
const ids = [];
|
|
59
|
+
for (const runtime of instances) {
|
|
60
|
+
if (!runtime)
|
|
61
|
+
continue;
|
|
62
|
+
runtimes.set(runtime.id, runtime);
|
|
63
|
+
ids.push(runtime.id);
|
|
64
|
+
logger.info('plugin:loaded', { kind: 'runtime', id: runtime.id });
|
|
65
|
+
}
|
|
66
|
+
if (plugin.meta) {
|
|
67
|
+
if (plugin.meta.id !== id) {
|
|
68
|
+
logger.warn('plugin:id-mismatch', {
|
|
69
|
+
kind: 'runtime',
|
|
70
|
+
id,
|
|
71
|
+
declared: plugin.meta.id,
|
|
72
|
+
detail: '配置里的插件 id 与插件声明的 meta.id 不一致,请改成一致以便面板回链',
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
// 以配置 id 作为面板身份,声明 id 只用于说明;实例 id 另存。
|
|
76
|
+
metas.push({ ...plugin.meta, id });
|
|
77
|
+
loadedIds[id] = ids;
|
|
78
|
+
}
|
|
79
|
+
if (plugin.options)
|
|
80
|
+
specs.push(plugin.options);
|
|
81
|
+
// createAll 没声明 meta 时也要把实例 id 记下来,否则无法按插件回推。
|
|
82
|
+
if (!plugin.meta && ids.length > 0)
|
|
83
|
+
loadedIds[id] = ids;
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
const failureId = id || plugin.meta?.id || 'unknown';
|
|
87
|
+
logger.error('plugin:create-failed', { kind: 'runtime', id: failureId, detail: errorMessage(error) });
|
|
88
|
+
loaded.failures.push({ kind: 'runtime', id: failureId, specifier: pluginEntryOf(config, 'runtime', failureId), message: errorMessage(error) });
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const defaultId = config.runtime.default;
|
|
92
|
+
if (runtimes.size === 0) {
|
|
93
|
+
throw new RuntimePluginError('plugin:not-found', `没有可用的 runtime 插件,无法启动 ${defaultId}`);
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
registry: new RuntimeRegistry(runtimes, defaultId),
|
|
97
|
+
metas,
|
|
98
|
+
specs,
|
|
99
|
+
ids: [...runtimes.keys()],
|
|
100
|
+
loadedIds,
|
|
101
|
+
failures: loaded.failures,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function specifierOf(entries, id) {
|
|
105
|
+
const entry = entries?.[id];
|
|
106
|
+
if (entry !== undefined)
|
|
107
|
+
return pluginSpecifier(entry);
|
|
108
|
+
return DEFAULT_RUNTIME_PLUGINS[id] ?? id;
|
|
109
|
+
}
|
|
110
|
+
function missingRunner(bin) {
|
|
111
|
+
return {
|
|
112
|
+
async run() {
|
|
113
|
+
throw new Error(`runtime 插件未注入 ${bin} 运行器`);
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/plugins/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { RuntimeConfigView } from '@router-agent/core/config.js';
|
|
2
|
+
import type { CommandRunner } from '@router-agent/infra/process.js';
|
|
3
|
+
import type { Logger } from '@router-agent/infra/logger.js';
|
|
4
|
+
import type { PluginEntry, PluginModuleLoader } from '@router-agent/infra/plugin-loader.js';
|
|
5
|
+
import type { WorkerRuntime } from '../port.js';
|
|
6
|
+
import type { RuntimeOptionSpec } from '../runtimes/options.js';
|
|
7
|
+
export type { PluginEntry, PluginModuleLoader };
|
|
8
|
+
/** 运行时插件元数据;Web 面板与配置校验共用。 */
|
|
9
|
+
export interface RuntimePluginMeta {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
label: string;
|
|
13
|
+
hint: string;
|
|
14
|
+
installHint?: string;
|
|
15
|
+
installUrl?: string;
|
|
16
|
+
/** 是否可由 ra 自动安装(ACP 扩展)。 */
|
|
17
|
+
installable?: boolean;
|
|
18
|
+
packageName?: string;
|
|
19
|
+
/** 已有原生运行时替代品:面板不再作为可选项展示。 */
|
|
20
|
+
deprecated?: boolean;
|
|
21
|
+
/** 是否接受非本地仓库选择器(Orca 的 name: / id:)。 */
|
|
22
|
+
repoSelector?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/** 运行时 adapter 创建上下文;宿主只注入中立依赖。 */
|
|
25
|
+
export interface RuntimePluginContext {
|
|
26
|
+
home: string;
|
|
27
|
+
workersDir: string;
|
|
28
|
+
config: RuntimeConfigView;
|
|
29
|
+
env: NodeJS.ProcessEnv;
|
|
30
|
+
logger: Logger;
|
|
31
|
+
/** 运行时可能需要的工作目录运行器;插件自行选择使用哪一个。 */
|
|
32
|
+
runners: {
|
|
33
|
+
orca: CommandRunner;
|
|
34
|
+
claude: CommandRunner;
|
|
35
|
+
git: CommandRunner;
|
|
36
|
+
herdr: CommandRunner;
|
|
37
|
+
};
|
|
38
|
+
claudeBin?: string;
|
|
39
|
+
claudeProjectsDir?: string;
|
|
40
|
+
}
|
|
41
|
+
/** 运行时插件:一个包可以导出多个运行时实例。 */
|
|
42
|
+
export interface RuntimePlugin {
|
|
43
|
+
kind: 'runtime';
|
|
44
|
+
meta?: RuntimePluginMeta;
|
|
45
|
+
/** 声明面板可配置项;配置落点统一为 runtime.options.<id>.<key>。 */
|
|
46
|
+
options?: RuntimeOptionSpec;
|
|
47
|
+
/** 创建 adapter;返回 null 表示当前配置下不启用(例如未配置 command)。 */
|
|
48
|
+
create(ctx: RuntimePluginContext): WorkerRuntime | null | Promise<WorkerRuntime | null>;
|
|
49
|
+
/** 附加运行时;ACP 这类目录型插件用它一次注册多个 id。 */
|
|
50
|
+
createAll?(ctx: RuntimePluginContext): Array<WorkerRuntime | null> | Promise<Array<WorkerRuntime | null>>;
|
|
51
|
+
}
|
|
52
|
+
export type Plugin = RuntimePlugin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../packages/runtime/src/plugins/types.ts"],"names":[],"mappings":""}
|
package/dist/port.d.ts
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import type { Assignment, InputKind, Ticket } from '@router-agent/core/model.js';
|
|
2
|
+
/** 工单执行上下文:Router 负责拼装,运行时只消费。 */
|
|
3
|
+
export interface WorkerContext {
|
|
4
|
+
ticket: Ticket;
|
|
5
|
+
assignment: Assignment;
|
|
6
|
+
/** 预分配目录;为空表示由运行时决定。 */
|
|
7
|
+
workdir: string;
|
|
8
|
+
/** 运行时中立的工单契约;Router 正常都会提供,缺省时 adapter 可自行渲染。 */
|
|
9
|
+
brief?: WorkerBrief;
|
|
10
|
+
/** 报告文件路径;缺省时由 adapter 按 workersDir 推导。 */
|
|
11
|
+
report?: ReportPaths;
|
|
12
|
+
/** 工具策略;缺省时使用内置默认值。 */
|
|
13
|
+
tools?: ToolPolicy;
|
|
14
|
+
}
|
|
15
|
+
/** 运行时中立的任务契约:只讲“做什么/怎么上报”,不讲某个 CLI 的参数。 */
|
|
16
|
+
export interface WorkerBrief {
|
|
17
|
+
ticketId: string;
|
|
18
|
+
title: string;
|
|
19
|
+
scope: string;
|
|
20
|
+
workBranch: string;
|
|
21
|
+
/** 已渲染的正文(工单、授权范围、交付规则、上报命令)。 */
|
|
22
|
+
contract: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ReportPaths {
|
|
25
|
+
statePath: string;
|
|
26
|
+
eventsPath: string;
|
|
27
|
+
}
|
|
28
|
+
/** 中立工具策略;adapter 负责映射到各 CLI 的开关。 */
|
|
29
|
+
export interface ToolPolicy {
|
|
30
|
+
fileAccess: 'read-only' | 'read-write';
|
|
31
|
+
/** deny=不给 shell;allowlist=只放行 shellAllow 中的命令前缀;allow=任意 shell。 */
|
|
32
|
+
shell: 'deny' | 'allowlist' | 'allow';
|
|
33
|
+
/** shell=allowlist 时生效,按命令前缀匹配,例如 ['ra report','ra doc','git','gh']。 */
|
|
34
|
+
shellAllow?: string[];
|
|
35
|
+
allowNetwork: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface InboundMessage {
|
|
38
|
+
/** 输入 id(in_xxx);投递时原样展示给 worker,用于写进 acked_inputs。 */
|
|
39
|
+
id: string;
|
|
40
|
+
kind: InputKind;
|
|
41
|
+
text: string;
|
|
42
|
+
}
|
|
43
|
+
export type ContextItem = {
|
|
44
|
+
kind: 'system-prompt';
|
|
45
|
+
text: string;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'file';
|
|
48
|
+
path: string;
|
|
49
|
+
content: string;
|
|
50
|
+
} | {
|
|
51
|
+
kind: 'env';
|
|
52
|
+
key: string;
|
|
53
|
+
value: string;
|
|
54
|
+
} | {
|
|
55
|
+
kind: 'dir';
|
|
56
|
+
path: string;
|
|
57
|
+
};
|
|
58
|
+
/** Router 传给运行时的引用:handle 不透明,其余字段让运行时能定位自己的 meta/会话。 */
|
|
59
|
+
export interface WorkspaceRequest {
|
|
60
|
+
ticketId: string;
|
|
61
|
+
repo: string;
|
|
62
|
+
baseBranch: string;
|
|
63
|
+
workBranch: string;
|
|
64
|
+
name: string;
|
|
65
|
+
workdir?: string;
|
|
66
|
+
}
|
|
67
|
+
export interface Workspace {
|
|
68
|
+
workspaceRef: string;
|
|
69
|
+
workdir: string;
|
|
70
|
+
branch: string;
|
|
71
|
+
meta?: Record<string, unknown>;
|
|
72
|
+
}
|
|
73
|
+
/** 内部构件:工作区生命周期。Orca 等运行时可以不严格实现。 */
|
|
74
|
+
export interface WorkspaceProvider {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
create(req: WorkspaceRequest): Promise<Workspace>;
|
|
77
|
+
inspect(ref: string): Promise<WorkspaceInfo | null>;
|
|
78
|
+
/**
|
|
79
|
+
* 回收检出。`repo` 是源仓库绝对路径:git worktree remove 必须在 git 上下文里跑,
|
|
80
|
+
* 否则会报 `fatal: not a git repository`。
|
|
81
|
+
*/
|
|
82
|
+
remove(ref: string, opts?: {
|
|
83
|
+
force?: boolean;
|
|
84
|
+
repo?: string;
|
|
85
|
+
}): Promise<void>;
|
|
86
|
+
listRepos?(): Promise<RepoDescriptor[]>;
|
|
87
|
+
}
|
|
88
|
+
export interface WorkerRef {
|
|
89
|
+
handle: string;
|
|
90
|
+
ticketId: string;
|
|
91
|
+
workdir?: string;
|
|
92
|
+
/** 运行时自己的会话 ID(Claude/Codex 用;Orca 可空)。 */
|
|
93
|
+
sessionId?: string;
|
|
94
|
+
}
|
|
95
|
+
/** 工作区引用:回收/查询时使用,不依赖 provider 私有选择器语法。 */
|
|
96
|
+
export interface WorkspaceRef {
|
|
97
|
+
ticketId: string;
|
|
98
|
+
workdir: string;
|
|
99
|
+
/** provider 自己的稳定标识;为空时由 workdir 推导。 */
|
|
100
|
+
workspaceRef?: string;
|
|
101
|
+
/** 源仓库绝对路径;回收检出时用它当 git 上下文。 */
|
|
102
|
+
repo?: string;
|
|
103
|
+
}
|
|
104
|
+
export interface StartResult {
|
|
105
|
+
handle: string;
|
|
106
|
+
workdir: string;
|
|
107
|
+
/** 实际工作分支(可能被 provider 加后缀);供 PR 兜底查询。 */
|
|
108
|
+
branch?: string;
|
|
109
|
+
/** 会话 ID;写入 runtime 的 meta.json,供 resume/活动定位。 */
|
|
110
|
+
sessionId?: string;
|
|
111
|
+
workspaceRef?: string;
|
|
112
|
+
}
|
|
113
|
+
export interface ActivityQuery {
|
|
114
|
+
ref: WorkerRef;
|
|
115
|
+
opts?: {
|
|
116
|
+
maxBytes?: number;
|
|
117
|
+
maxEvents?: number;
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** 投递回执:Router 据此决定是否重投;accepted 不等于 ack。 */
|
|
121
|
+
export type DeliveryReceipt = {
|
|
122
|
+
status: 'accepted';
|
|
123
|
+
inputIds: string[];
|
|
124
|
+
/**
|
|
125
|
+
* 运行时在投递过程中切换了会话(例如 Claude 的 resume 产生副本)。
|
|
126
|
+
* Router 必须把 Assignment 的 handle 换成新值,后续 status/stop 才能命中同一会话。
|
|
127
|
+
*/
|
|
128
|
+
handle?: string;
|
|
129
|
+
sessionId?: string;
|
|
130
|
+
} | {
|
|
131
|
+
status: 'queued';
|
|
132
|
+
inputIds: string[];
|
|
133
|
+
reason?: string;
|
|
134
|
+
} | {
|
|
135
|
+
status: 'rejected';
|
|
136
|
+
inputIds: string[];
|
|
137
|
+
reason: string;
|
|
138
|
+
retryable?: boolean;
|
|
139
|
+
retryAfterMs?: number;
|
|
140
|
+
};
|
|
141
|
+
export interface DeliverOptions {
|
|
142
|
+
/** 第几次投递(从 1 开始);同一 attempt 的并发调用必须幂等。 */
|
|
143
|
+
attempt?: number;
|
|
144
|
+
/** Router 显式重投:adapter 必须允许同一 input.id 再次进入。 */
|
|
145
|
+
redeliver?: boolean;
|
|
146
|
+
}
|
|
147
|
+
export type AgentPhase = 'starting' | 'running' | 'blocked' | 'exited' | 'lost' | 'unknown';
|
|
148
|
+
export interface AgentStatus {
|
|
149
|
+
alive: boolean;
|
|
150
|
+
phase: AgentPhase;
|
|
151
|
+
acceptingInput: boolean;
|
|
152
|
+
/** 最后一次可观测活动时间(ISO);用于 idle / zombie 判定。 */
|
|
153
|
+
lastActivityAt?: string;
|
|
154
|
+
exitCode?: number;
|
|
155
|
+
exitSignal?: string;
|
|
156
|
+
/** provider 细节;只进日志,不进判断。 */
|
|
157
|
+
detail?: Record<string, unknown>;
|
|
158
|
+
}
|
|
159
|
+
export interface AgentOutput {
|
|
160
|
+
status: 'running' | 'exited' | 'unknown';
|
|
161
|
+
lines: string[];
|
|
162
|
+
source?: string;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* 被中断的一轮执行。
|
|
166
|
+
*
|
|
167
|
+
* 运行时重启后用来回答「上一轮做到哪、是不是被中途打断的」。
|
|
168
|
+
* 只有进程会随 Router 一起死的运行时(capabilities.agent.processExit=true)
|
|
169
|
+
* 才有这个概念;常驻 worker 不会因为 Router 重启而中断,不需要实现。
|
|
170
|
+
*/
|
|
171
|
+
export interface InterruptedTurn {
|
|
172
|
+
/** 运行时自己的轮次 id;用于去重,保证同一轮只提醒一次。 */
|
|
173
|
+
turnId: string;
|
|
174
|
+
/** 已执行到哪一步的简要描述;用来生成有意义的恢复提示。 */
|
|
175
|
+
summary?: string;
|
|
176
|
+
/** 中断发生时间(ISO),尽力而为。 */
|
|
177
|
+
at?: string;
|
|
178
|
+
}
|
|
179
|
+
/** 兼容旧命名。 */
|
|
180
|
+
export type TerminalOutput = AgentOutput;
|
|
181
|
+
/** Agent 会话记录里的一条活动(assistant 文本或工具调用)。 */
|
|
182
|
+
export interface SessionEvent {
|
|
183
|
+
at: string;
|
|
184
|
+
kind: 'text' | 'tool';
|
|
185
|
+
text: string;
|
|
186
|
+
tool?: {
|
|
187
|
+
name: string;
|
|
188
|
+
target?: string;
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/** 从 Agent 自己的会话记录里读出的最近活动。 */
|
|
192
|
+
export interface SessionSnapshot {
|
|
193
|
+
at: string;
|
|
194
|
+
events: SessionEvent[];
|
|
195
|
+
sessionId?: string;
|
|
196
|
+
filePath?: string;
|
|
197
|
+
}
|
|
198
|
+
/** 人工接管会话时可直接粘贴到终端的恢复提示。 */
|
|
199
|
+
export interface ResumeHint {
|
|
200
|
+
/** 完整 shell 命令,已包含 cd 到工作目录。 */
|
|
201
|
+
command: string;
|
|
202
|
+
/** 运行时自己的会话 ID;用于展示与排障。 */
|
|
203
|
+
sessionId?: string;
|
|
204
|
+
/** 不阻断复制,但需要提示用户的注意事项。 */
|
|
205
|
+
note?: string;
|
|
206
|
+
}
|
|
207
|
+
export interface RuntimeCapabilities {
|
|
208
|
+
agent: {
|
|
209
|
+
liveStatus: boolean;
|
|
210
|
+
processExit: boolean;
|
|
211
|
+
output: boolean;
|
|
212
|
+
activity: boolean;
|
|
213
|
+
structuredInput: boolean;
|
|
214
|
+
nudge: boolean;
|
|
215
|
+
};
|
|
216
|
+
workspace: {
|
|
217
|
+
cleanup: boolean;
|
|
218
|
+
prLink: boolean;
|
|
219
|
+
discovery: boolean;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
export interface RepoDescriptor {
|
|
223
|
+
name: string;
|
|
224
|
+
path: string;
|
|
225
|
+
kind?: string;
|
|
226
|
+
}
|
|
227
|
+
export interface WorkspaceInfo {
|
|
228
|
+
workdir: string;
|
|
229
|
+
branch: string;
|
|
230
|
+
dirty?: boolean;
|
|
231
|
+
linkedPr?: {
|
|
232
|
+
number: number;
|
|
233
|
+
url: string;
|
|
234
|
+
state?: 'open' | 'merged' | 'closed';
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
export interface DiagnosticCheck {
|
|
238
|
+
name: string;
|
|
239
|
+
status: 'ok' | 'warn' | 'fail';
|
|
240
|
+
detail: string;
|
|
241
|
+
hint?: string;
|
|
242
|
+
}
|
|
243
|
+
/** 运行时错误码;所有 adapter 必须抛 WorkerRuntimeError。 */
|
|
244
|
+
export type WorkerErrorCode = 'workspace:create-failed' | 'workspace:missing-repo' | 'workspace:missing-branch' | 'workspace:remove-failed' | 'agent:launch-failed' | 'agent:not-accepting-input' | 'agent:gone' | 'agent:timeout' | 'runtime:unavailable' | 'runtime:unknown';
|
|
245
|
+
export declare class WorkerRuntimeError extends Error {
|
|
246
|
+
readonly code: WorkerErrorCode;
|
|
247
|
+
readonly retryable: boolean;
|
|
248
|
+
readonly reason: string;
|
|
249
|
+
readonly cause?: string;
|
|
250
|
+
readonly detail?: Record<string, unknown>;
|
|
251
|
+
constructor(code: WorkerErrorCode, reason: string, opts?: {
|
|
252
|
+
retryable?: boolean;
|
|
253
|
+
cause?: string;
|
|
254
|
+
detail?: Record<string, unknown>;
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
/** Worker 运行时端口:换运行时只加一个 adapter,内核与 Router 不改。 */
|
|
258
|
+
export interface WorkerRuntime {
|
|
259
|
+
readonly id: string;
|
|
260
|
+
readonly capabilities: RuntimeCapabilities;
|
|
261
|
+
start(ctx: WorkerContext): Promise<StartResult>;
|
|
262
|
+
deliver(ref: WorkerRef, inputs: InboundMessage[], opts?: DeliverOptions): Promise<DeliveryReceipt>;
|
|
263
|
+
stop(ref: WorkerRef, reason: string): Promise<void>;
|
|
264
|
+
/** 可选:显式唤醒/探活;只有 capabilities.agent.nudge=true 时才实现。 */
|
|
265
|
+
nudge?(ref: WorkerRef): Promise<void>;
|
|
266
|
+
/** 可选:进程重启后把仍可恢复的会话接回来;接不回返回 false,不算丢失。 */
|
|
267
|
+
reattach?(ref: WorkerRef): Promise<boolean>;
|
|
268
|
+
/**
|
|
269
|
+
* 可选:查询上一轮是否被中途打断。
|
|
270
|
+
*
|
|
271
|
+
* 只有 worker 进程会随 Router 一起死的运行时(capabilities.agent.processExit=true)
|
|
272
|
+
* 才需要实现:这类运行时重启后「上一轮」确实可能停在半路。
|
|
273
|
+
* 返回 null 表示「没有被打断的轮次」或「判断不了」,不触发任何恢复动作。
|
|
274
|
+
*/
|
|
275
|
+
interruptedTurn?(ref: WorkerRef): Promise<InterruptedTurn | null>;
|
|
276
|
+
/** 可选:结构化活性;返回 null 表示「无法判断」,不是「已丢失」。 */
|
|
277
|
+
status?(ref: WorkerRef): Promise<AgentStatus | null>;
|
|
278
|
+
/** 可选:输出尾部;没有则巡检跳过这一路。 */
|
|
279
|
+
output?(ref: WorkerRef, opts?: {
|
|
280
|
+
limit?: number;
|
|
281
|
+
}): Promise<AgentOutput | null>;
|
|
282
|
+
/** 可选:结构化活动;优先于 output。 */
|
|
283
|
+
activity?(query: ActivityQuery): Promise<SessionSnapshot | null>;
|
|
284
|
+
/** 可选:工作区查询/回收;不再使用运行时私有选择器。 */
|
|
285
|
+
inspectWorkspace?(ref: WorkspaceRef): Promise<WorkspaceInfo | null>;
|
|
286
|
+
removeWorkspace?(ref: WorkspaceRef): Promise<void>;
|
|
287
|
+
/** 可选:仓库发现(doctor / init)。 */
|
|
288
|
+
listRepos?(): Promise<RepoDescriptor[]>;
|
|
289
|
+
/** 可选:把本地仓库路径解析成 GitHub owner/repo,供 PR 跟踪。 */
|
|
290
|
+
repoSlug?(ref: WorkerRef): Promise<string | null>;
|
|
291
|
+
/** 可选:启动前自检。 */
|
|
292
|
+
doctor?(): Promise<DiagnosticCheck[]>;
|
|
293
|
+
/** 兼容保留:当前 Router 未调用。 */
|
|
294
|
+
registerContext?(ref: WorkerRef, items: ContextItem[]): Promise<void>;
|
|
295
|
+
}
|
package/dist/port.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class WorkerRuntimeError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
retryable;
|
|
4
|
+
reason;
|
|
5
|
+
cause;
|
|
6
|
+
detail;
|
|
7
|
+
constructor(code, reason, opts = {}) {
|
|
8
|
+
super(reason);
|
|
9
|
+
this.name = 'WorkerRuntimeError';
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.reason = reason;
|
|
12
|
+
this.retryable = opts.retryable ?? false;
|
|
13
|
+
this.cause = opts.cause;
|
|
14
|
+
this.detail = opts.detail;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=port.js.map
|
package/dist/port.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port.js","sourceRoot":"","sources":["../../../../packages/runtime/src/port.ts"],"names":[],"mappings":"AA6PA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAiB;IACrB,SAAS,CAAS;IAClB,MAAM,CAAQ;IACL,KAAK,CAAS;IACvB,MAAM,CAA0B;IAEzC,YACE,IAAqB,EACrB,MAAc,EACd,OAAkF,EAAE;QAEpF,KAAK,CAAC,MAAM,CAAC,CAAA;QACb,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAA;QACxC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type WorkerRuntime } from './port.js';
|
|
2
|
+
/** 按 id 持有运行时;内核只通过它取运行时,不直接 new OrcaRuntime。 */
|
|
3
|
+
export declare class RuntimeRegistry {
|
|
4
|
+
private readonly runtimes;
|
|
5
|
+
private readonly defaultId;
|
|
6
|
+
constructor(runtimes: Map<string, WorkerRuntime>, defaultId: string);
|
|
7
|
+
get(id: string): WorkerRuntime;
|
|
8
|
+
has(id: string): boolean;
|
|
9
|
+
ids(): string[];
|
|
10
|
+
default(): WorkerRuntime;
|
|
11
|
+
}
|
|
12
|
+
/** 用插件创建好的 adapter 组装注册表;插件发现与加载由 plugins/loader 负责。 */
|
|
13
|
+
export declare function createRuntimes(runtimes: Iterable<WorkerRuntime>, defaultId: string): RuntimeRegistry;
|