oh-my-knowledge 0.52.3 → 0.54.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.
Files changed (106) hide show
  1. package/README.md +21 -1
  2. package/README.zh.md +21 -1
  3. package/dist/assets/agent-skills/omk/SKILL.md +6 -0
  4. package/dist/assets/agent-skills/omk/references/commands.md +1 -1
  5. package/dist/authoring/evolver.js +1 -1
  6. package/dist/authoring/generator.js +1 -1
  7. package/dist/cli/commands/eval/index.js +7 -6
  8. package/dist/cli/commands/install.js +5 -1
  9. package/dist/cli/lib/generation-failure-hint.js +6 -8
  10. package/dist/cli/lib/runtime-defaults.d.ts +2 -0
  11. package/dist/cli/lib/runtime-defaults.js +7 -4
  12. package/dist/dsh-plugin/cordis.patch.yml +3 -0
  13. package/dist/dsh-plugin/host-executor.d.ts +93 -0
  14. package/dist/dsh-plugin/host-executor.js +232 -0
  15. package/dist/dsh-plugin/index.d.ts +30 -0
  16. package/dist/dsh-plugin/index.js +275 -0
  17. package/dist/dsh-plugin/observe.d.ts +47 -0
  18. package/dist/dsh-plugin/observe.js +359 -0
  19. package/dist/dsh-plugin/protocol.d.ts +21 -0
  20. package/dist/dsh-plugin/protocol.js +229 -0
  21. package/dist/dsh-plugin/trace-adapter.d.ts +48 -0
  22. package/dist/dsh-plugin/trace-adapter.js +590 -0
  23. package/dist/eval-core/comparability.js +3 -0
  24. package/dist/eval-core/evaluation-execution.js +5 -13
  25. package/dist/eval-core/evaluation-reporting.d.ts +7 -4
  26. package/dist/eval-core/evaluation-reporting.js +39 -18
  27. package/dist/eval-core/judge-independence.d.ts +1 -1
  28. package/dist/eval-core/judge-independence.js +1 -1
  29. package/dist/eval-core/report-document.js +6 -0
  30. package/dist/eval-core/resume-compatibility.d.ts +1 -0
  31. package/dist/eval-core/resume-compatibility.js +5 -4
  32. package/dist/eval-workflows/batch-evaluation-workflow.js +1 -1
  33. package/dist/eval-workflows/evaluation-pipeline/preflight-warnings.js +4 -2
  34. package/dist/eval-workflows/evaluation-pipeline.d.ts +3 -1
  35. package/dist/eval-workflows/evaluation-pipeline.js +7 -3
  36. package/dist/eval-workflows/run-evaluation.d.ts +4 -2
  37. package/dist/eval-workflows/run-evaluation.js +7 -3
  38. package/dist/executors/{anthropic-api.d.ts → anthropic/api.d.ts} +1 -1
  39. package/dist/executors/{anthropic-api.js → anthropic/api.js} +4 -2
  40. package/dist/executors/{claude-cli.d.ts → anthropic/claude/cli.d.ts} +1 -1
  41. package/dist/executors/{claude-cli.js → anthropic/claude/cli.js} +5 -3
  42. package/dist/executors/anthropic/claude/protocol.d.ts +87 -0
  43. package/dist/executors/{claude-protocol.js → anthropic/claude/protocol.js} +6 -6
  44. package/dist/executors/{claude-sdk.d.ts → anthropic/claude/sdk.d.ts} +2 -2
  45. package/dist/executors/{claude-sdk.js → anthropic/claude/sdk.js} +8 -5
  46. package/dist/executors/anthropic/claude/trace.d.ts +9 -0
  47. package/dist/executors/{claude-sdk-trace.js → anthropic/claude/trace.js} +5 -5
  48. package/dist/executors/{capabilities.d.ts → core/capabilities.d.ts} +3 -5
  49. package/dist/executors/{capabilities.js → core/capabilities.js} +4 -11
  50. package/dist/executors/core/http.d.ts +6 -0
  51. package/dist/executors/core/http.js +19 -0
  52. package/dist/executors/core/limits.d.ts +2 -0
  53. package/dist/executors/core/limits.js +2 -0
  54. package/dist/executors/core/optional-dependencies.d.ts +7 -0
  55. package/dist/executors/core/optional-dependencies.js +35 -0
  56. package/dist/executors/core/registry.d.ts +145 -0
  57. package/dist/executors/core/registry.js +127 -0
  58. package/dist/executors/core/runtime-fingerprint.d.ts +13 -0
  59. package/dist/executors/{runtime-fingerprint.js → core/runtime-fingerprint.js} +119 -59
  60. package/dist/executors/core/runtime.d.ts +12 -0
  61. package/dist/executors/core/runtime.js +61 -0
  62. package/dist/executors/core/subprocess.d.ts +44 -0
  63. package/dist/executors/{shared.js → core/subprocess.js} +20 -156
  64. package/dist/executors/index.d.ts +4 -4
  65. package/dist/executors/index.js +26 -15
  66. package/dist/executors/{openai-api.d.ts → openai/api.d.ts} +1 -1
  67. package/dist/executors/{openai-api.js → openai/api.js} +4 -2
  68. package/dist/executors/{codex-cli.d.ts → openai/codex/cli.d.ts} +3 -3
  69. package/dist/executors/{codex-cli.js → openai/codex/cli.js} +5 -3
  70. package/dist/executors/openai/codex/protocol.d.ts +72 -0
  71. package/dist/executors/{codex-protocol.js → openai/codex/protocol.js} +33 -2
  72. package/dist/executors/{codex-sdk.d.ts → openai/codex/sdk.d.ts} +18 -4
  73. package/dist/executors/{codex-sdk.js → openai/codex/sdk.js} +7 -4
  74. package/dist/executors/{codex-cli-trace.d.ts → openai/codex/trace.d.ts} +2 -2
  75. package/dist/executors/{codex-cli-trace.js → openai/codex/trace.js} +4 -4
  76. package/dist/executors/{script.d.ts → script/index.d.ts} +1 -1
  77. package/dist/executors/{script.js → script/index.js} +6 -4
  78. package/dist/grading/judge.d.ts +1 -1
  79. package/dist/grading/judge.js +1 -1
  80. package/dist/observability/conversation-catalog.js +1 -1
  81. package/dist/observability/experience.js +4 -0
  82. package/dist/observability/inbox.d.ts +4 -1
  83. package/dist/observability/inbox.js +7 -2
  84. package/dist/observability/trace-ir.d.ts +6 -3
  85. package/dist/observability/turn-index.js +4 -0
  86. package/dist/renderer/conversation-renderer.js +20 -6
  87. package/dist/renderer/html-renderer.js +30 -11
  88. package/dist/renderer/knowledge-debugger-renderer.js +6 -1
  89. package/dist/renderer/observation-inbox-renderer.js +2 -2
  90. package/dist/renderer/trajectory-live.d.ts +1 -0
  91. package/dist/renderer/trajectory-live.js +5 -2
  92. package/dist/shared/trace-source-kind.js +1 -0
  93. package/dist/types/executor.d.ts +13 -2
  94. package/dist/types/judge.d.ts +2 -2
  95. package/dist/types/observability.d.ts +1 -1
  96. package/dist/types/trace.d.ts +1 -1
  97. package/package.json +25 -5
  98. package/dist/executors/claude-protocol.d.ts +0 -28
  99. package/dist/executors/claude-sdk-trace.d.ts +0 -9
  100. package/dist/executors/codex-protocol.d.ts +0 -24
  101. package/dist/executors/gemini.d.ts +0 -2
  102. package/dist/executors/gemini.js +0 -156
  103. package/dist/executors/runtime-fingerprint.d.ts +0 -6
  104. package/dist/executors/shared.d.ts +0 -226
  105. /package/dist/executors/{script-command.d.ts → script/command.d.ts} +0 -0
  106. /package/dist/executors/{script-command.js → script/command.js} +0 -0
@@ -0,0 +1,19 @@
1
+ export async function readJsonResponse(response) {
2
+ const rawBody = await response.text();
3
+ if (!rawBody.trim())
4
+ return { data: null, rawBody };
5
+ try {
6
+ return { data: JSON.parse(rawBody), rawBody };
7
+ }
8
+ catch {
9
+ return { data: null, rawBody };
10
+ }
11
+ }
12
+ export function responseBodyPreview(rawBody, maxLength = 500) {
13
+ const normalized = rawBody.replace(/\s+/g, ' ').trim();
14
+ if (!normalized)
15
+ return '';
16
+ return normalized.length > maxLength
17
+ ? `${normalized.slice(0, maxLength)}...`
18
+ : normalized;
19
+ }
@@ -0,0 +1,2 @@
1
+ export declare const DEFAULT_TIMEOUT_MS = 600000;
2
+ export declare const MAX_BUFFER: number;
@@ -0,0 +1,2 @@
1
+ export const DEFAULT_TIMEOUT_MS = 600_000;
2
+ export const MAX_BUFFER = 10 * 1024 * 1024;
@@ -0,0 +1,7 @@
1
+ import type { ExecutableExecutorName } from './registry.js';
2
+ export interface OptionalExecutorDependency {
3
+ readonly packageName: string;
4
+ readonly installSpec: string;
5
+ }
6
+ export declare function getOptionalExecutorDependency(executorName: ExecutableExecutorName): OptionalExecutorDependency | undefined;
7
+ export declare function assertOptionalExecutorDependency(executorName: ExecutableExecutorName, available?: (packageName: string) => boolean): void;
@@ -0,0 +1,35 @@
1
+ const OPTIONAL_EXECUTOR_DEPENDENCIES = {
2
+ 'claude-sdk': {
3
+ packageName: '@anthropic-ai/claude-agent-sdk',
4
+ installSpec: '@anthropic-ai/claude-agent-sdk@^0.3.143',
5
+ },
6
+ 'codex-sdk': {
7
+ packageName: '@openai/codex-sdk',
8
+ installSpec: '@openai/codex-sdk@^0.149.0',
9
+ },
10
+ };
11
+ export function getOptionalExecutorDependency(executorName) {
12
+ return OPTIONAL_EXECUTOR_DEPENDENCIES[executorName];
13
+ }
14
+ function packageAvailable(packageName) {
15
+ try {
16
+ // Use ESM resolution because @openai/codex-sdk only exposes an `import`
17
+ // condition; createRequire().resolve() reports ERR_PACKAGE_PATH_NOT_EXPORTED
18
+ // even when that optional peer is correctly installed.
19
+ import.meta.resolve(packageName);
20
+ return true;
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ export function assertOptionalExecutorDependency(executorName, available = packageAvailable) {
27
+ const dependency = getOptionalExecutorDependency(executorName);
28
+ if (!dependency || available(dependency.packageName))
29
+ return;
30
+ throw new Error([
31
+ `执行器「${executorName}」需要可选依赖「${dependency.packageName}」,但当前 OMK 安装作用域中未找到。`,
32
+ `本地安装:npm install ${dependency.installSpec}`,
33
+ `全局安装:npm install -g ${dependency.installSpec}`,
34
+ ].join('\n'));
35
+ }
@@ -0,0 +1,145 @@
1
+ export type ExecutorVendor = 'anthropic' | 'openai' | 'unknown';
2
+ export type ExecutorFamily = 'claude' | 'codex' | 'dsh' | 'anthropic-api' | 'openai-api';
3
+ export type SampleMockSupport = 'native-hooks' | 'delegated-script' | 'unsupported';
4
+ export interface ExecutorCapabilities {
5
+ sampleMocks: SampleMockSupport;
6
+ }
7
+ export type ExecutorFingerprintSpec = {
8
+ readonly strategy: 'path-cli';
9
+ readonly command: 'claude' | 'codex';
10
+ } | {
11
+ readonly strategy: 'claude-sdk';
12
+ } | {
13
+ readonly strategy: 'codex-sdk';
14
+ } | {
15
+ readonly strategy: 'api';
16
+ } | {
17
+ readonly strategy: 'dsh-host';
18
+ };
19
+ declare const EXECUTOR_DESCRIPTORS: readonly [{
20
+ readonly name: "claude";
21
+ readonly execution: "builtin";
22
+ readonly family: "claude";
23
+ readonly vendor: "anthropic";
24
+ readonly sampleMocks: "native-hooks";
25
+ readonly runtimeKind: "agent-cli";
26
+ readonly runtimeCapabilities: {
27
+ readonly systemPrompt: "native";
28
+ readonly costUSD: "reported";
29
+ readonly trace: "native";
30
+ readonly skillIsolation: "full-no-partial";
31
+ };
32
+ readonly fingerprint: {
33
+ readonly strategy: "path-cli";
34
+ readonly command: "claude";
35
+ };
36
+ }, {
37
+ readonly name: "claude-sdk";
38
+ readonly execution: "builtin";
39
+ readonly family: "claude";
40
+ readonly vendor: "anthropic";
41
+ readonly sampleMocks: "native-hooks";
42
+ readonly runtimeKind: "agent-sdk";
43
+ readonly runtimeCapabilities: {
44
+ readonly systemPrompt: "native";
45
+ readonly costUSD: "reported";
46
+ readonly trace: "native";
47
+ readonly skillIsolation: "full";
48
+ };
49
+ readonly fingerprint: {
50
+ readonly strategy: "claude-sdk";
51
+ };
52
+ }, {
53
+ readonly name: "codex";
54
+ readonly execution: "builtin";
55
+ readonly family: "codex";
56
+ readonly vendor: "openai";
57
+ readonly sampleMocks: "unsupported";
58
+ readonly runtimeKind: "agent-cli";
59
+ readonly runtimeCapabilities: {
60
+ readonly systemPrompt: "prepended";
61
+ readonly costUSD: "not-reported";
62
+ readonly trace: "best-effort";
63
+ readonly skillIsolation: "cwd-only";
64
+ };
65
+ readonly fingerprint: {
66
+ readonly strategy: "path-cli";
67
+ readonly command: "codex";
68
+ };
69
+ }, {
70
+ readonly name: "codex-sdk";
71
+ readonly execution: "builtin";
72
+ readonly family: "codex";
73
+ readonly vendor: "openai";
74
+ readonly sampleMocks: "unsupported";
75
+ readonly runtimeKind: "agent-sdk";
76
+ readonly runtimeCapabilities: {
77
+ readonly systemPrompt: "prepended";
78
+ readonly costUSD: "not-reported";
79
+ readonly trace: "best-effort";
80
+ readonly skillIsolation: "cwd-only";
81
+ };
82
+ readonly fingerprint: {
83
+ readonly strategy: "codex-sdk";
84
+ };
85
+ }, {
86
+ readonly name: "dsh-host";
87
+ readonly execution: "host-only";
88
+ readonly family: "dsh";
89
+ readonly vendor: "unknown";
90
+ readonly sampleMocks: "unsupported";
91
+ readonly runtimeKind: "agent-sdk";
92
+ readonly runtimeCapabilities: {
93
+ readonly systemPrompt: "native";
94
+ readonly costUSD: "not-reported";
95
+ readonly trace: "native";
96
+ readonly skillIsolation: "full-no-partial";
97
+ };
98
+ readonly fingerprint: {
99
+ readonly strategy: "dsh-host";
100
+ };
101
+ }, {
102
+ readonly name: "anthropic-api";
103
+ readonly execution: "builtin";
104
+ readonly family: "anthropic-api";
105
+ readonly vendor: "anthropic";
106
+ readonly sampleMocks: "unsupported";
107
+ readonly runtimeKind: "api";
108
+ readonly runtimeCapabilities: {
109
+ readonly systemPrompt: "native";
110
+ readonly costUSD: "not-reported";
111
+ readonly trace: "none";
112
+ readonly skillIsolation: "none";
113
+ };
114
+ readonly fingerprint: {
115
+ readonly strategy: "api";
116
+ };
117
+ }, {
118
+ readonly name: "openai-api";
119
+ readonly execution: "builtin";
120
+ readonly family: "openai-api";
121
+ readonly vendor: "openai";
122
+ readonly sampleMocks: "unsupported";
123
+ readonly runtimeKind: "api";
124
+ readonly runtimeCapabilities: {
125
+ readonly systemPrompt: "native";
126
+ readonly costUSD: "not-reported";
127
+ readonly trace: "none";
128
+ readonly skillIsolation: "none";
129
+ };
130
+ readonly fingerprint: {
131
+ readonly strategy: "api";
132
+ };
133
+ }];
134
+ export type RegisteredExecutorDescriptor = (typeof EXECUTOR_DESCRIPTORS)[number];
135
+ export type RegisteredExecutorName = RegisteredExecutorDescriptor['name'];
136
+ export type ExecutableExecutorName = Extract<RegisteredExecutorDescriptor, {
137
+ execution: 'builtin';
138
+ }>['name'];
139
+ export declare function executorDescriptors(): readonly RegisteredExecutorDescriptor[];
140
+ export declare function getExecutorDescriptor(name: string): RegisteredExecutorDescriptor | undefined;
141
+ export declare function isRegisteredExecutorName(name: string): name is RegisteredExecutorName;
142
+ export declare function executorVendor(executor: string): ExecutorVendor;
143
+ export declare function executorFamily(executor: string): ExecutorFamily | 'custom';
144
+ export declare function executorNamesForFamily(family: ExecutorFamily): ReadonlySet<string>;
145
+ export {};
@@ -0,0 +1,127 @@
1
+ const EXECUTOR_DESCRIPTORS = [
2
+ {
3
+ name: 'claude',
4
+ execution: 'builtin',
5
+ family: 'claude',
6
+ vendor: 'anthropic',
7
+ sampleMocks: 'native-hooks',
8
+ runtimeKind: 'agent-cli',
9
+ runtimeCapabilities: {
10
+ systemPrompt: 'native',
11
+ costUSD: 'reported',
12
+ trace: 'native',
13
+ skillIsolation: 'full-no-partial',
14
+ },
15
+ fingerprint: { strategy: 'path-cli', command: 'claude' },
16
+ },
17
+ {
18
+ name: 'claude-sdk',
19
+ execution: 'builtin',
20
+ family: 'claude',
21
+ vendor: 'anthropic',
22
+ sampleMocks: 'native-hooks',
23
+ runtimeKind: 'agent-sdk',
24
+ runtimeCapabilities: {
25
+ systemPrompt: 'native',
26
+ costUSD: 'reported',
27
+ trace: 'native',
28
+ skillIsolation: 'full',
29
+ },
30
+ fingerprint: { strategy: 'claude-sdk' },
31
+ },
32
+ {
33
+ name: 'codex',
34
+ execution: 'builtin',
35
+ family: 'codex',
36
+ vendor: 'openai',
37
+ sampleMocks: 'unsupported',
38
+ runtimeKind: 'agent-cli',
39
+ runtimeCapabilities: {
40
+ systemPrompt: 'prepended',
41
+ costUSD: 'not-reported',
42
+ trace: 'best-effort',
43
+ skillIsolation: 'cwd-only',
44
+ },
45
+ fingerprint: { strategy: 'path-cli', command: 'codex' },
46
+ },
47
+ {
48
+ name: 'codex-sdk',
49
+ execution: 'builtin',
50
+ family: 'codex',
51
+ vendor: 'openai',
52
+ sampleMocks: 'unsupported',
53
+ runtimeKind: 'agent-sdk',
54
+ runtimeCapabilities: {
55
+ systemPrompt: 'prepended',
56
+ costUSD: 'not-reported',
57
+ trace: 'best-effort',
58
+ skillIsolation: 'cwd-only',
59
+ },
60
+ fingerprint: { strategy: 'codex-sdk' },
61
+ },
62
+ {
63
+ name: 'dsh-host',
64
+ execution: 'host-only',
65
+ family: 'dsh',
66
+ vendor: 'unknown',
67
+ sampleMocks: 'unsupported',
68
+ runtimeKind: 'agent-sdk',
69
+ runtimeCapabilities: {
70
+ systemPrompt: 'native',
71
+ costUSD: 'not-reported',
72
+ trace: 'native',
73
+ skillIsolation: 'full-no-partial',
74
+ },
75
+ fingerprint: { strategy: 'dsh-host' },
76
+ },
77
+ {
78
+ name: 'anthropic-api',
79
+ execution: 'builtin',
80
+ family: 'anthropic-api',
81
+ vendor: 'anthropic',
82
+ sampleMocks: 'unsupported',
83
+ runtimeKind: 'api',
84
+ runtimeCapabilities: {
85
+ systemPrompt: 'native',
86
+ costUSD: 'not-reported',
87
+ trace: 'none',
88
+ skillIsolation: 'none',
89
+ },
90
+ fingerprint: { strategy: 'api' },
91
+ },
92
+ {
93
+ name: 'openai-api',
94
+ execution: 'builtin',
95
+ family: 'openai-api',
96
+ vendor: 'openai',
97
+ sampleMocks: 'unsupported',
98
+ runtimeKind: 'api',
99
+ runtimeCapabilities: {
100
+ systemPrompt: 'native',
101
+ costUSD: 'not-reported',
102
+ trace: 'none',
103
+ skillIsolation: 'none',
104
+ },
105
+ fingerprint: { strategy: 'api' },
106
+ },
107
+ ];
108
+ export function executorDescriptors() {
109
+ return EXECUTOR_DESCRIPTORS;
110
+ }
111
+ export function getExecutorDescriptor(name) {
112
+ return EXECUTOR_DESCRIPTORS.find((descriptor) => descriptor.name === name);
113
+ }
114
+ export function isRegisteredExecutorName(name) {
115
+ return getExecutorDescriptor(name) !== undefined;
116
+ }
117
+ export function executorVendor(executor) {
118
+ return getExecutorDescriptor(executor)?.vendor ?? 'unknown';
119
+ }
120
+ export function executorFamily(executor) {
121
+ return getExecutorDescriptor(executor)?.family ?? 'custom';
122
+ }
123
+ export function executorNamesForFamily(family) {
124
+ return new Set(EXECUTOR_DESCRIPTORS
125
+ .filter((descriptor) => descriptor.family === family)
126
+ .map((descriptor) => descriptor.name));
127
+ }
@@ -0,0 +1,13 @@
1
+ import type { ExecutorFn, ExecutorRuntimeFingerprint } from '../../types/index.js';
2
+ export interface DshHostRuntimeIdentity {
3
+ provider?: string;
4
+ agentPreset?: string;
5
+ toolSchemas?: readonly unknown[];
6
+ }
7
+ export interface ExecutorRuntimeFingerprintOptions {
8
+ skillDir?: string | null;
9
+ env?: NodeJS.ProcessEnv;
10
+ }
11
+ export declare function createDshHostRuntimeFingerprint(model: string, identity?: DshHostRuntimeIdentity): ExecutorRuntimeFingerprint;
12
+ export declare function resolveExecutorRuntimeFingerprint(executorName: string, model: string, options?: ExecutorRuntimeFingerprintOptions, executor?: ExecutorFn): ExecutorRuntimeFingerprint;
13
+ export declare function getExecutorRuntimeFingerprint(executorName: string, model: string, options?: ExecutorRuntimeFingerprintOptions): ExecutorRuntimeFingerprint;
@@ -1,11 +1,12 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import { createHash } from 'node:crypto';
3
- import { existsSync, readFileSync, statSync } from 'node:fs';
3
+ import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
4
4
  import { createRequire } from 'node:module';
5
5
  import { delimiter, dirname, isAbsolute, join } from 'node:path';
6
6
  import { fileURLToPath } from 'node:url';
7
- import { buildExecEnv } from './shared.js';
8
- import { isScriptFileInterpreter, resolveScriptCommand, } from './script-command.js';
7
+ import { buildExecEnv } from './runtime.js';
8
+ import { isScriptFileInterpreter, resolveScriptCommand, } from '../script/command.js';
9
+ import { getExecutorDescriptor } from './registry.js';
9
10
  const __dirname = dirname(fileURLToPath(import.meta.url));
10
11
  const requireFromHere = createRequire(import.meta.url);
11
12
  const RUNTIME_CACHE = new Map();
@@ -56,6 +57,50 @@ function findNearestPackageJson(fromPath) {
56
57
  }
57
58
  return null;
58
59
  }
60
+ function readInvokingDshPackage() {
61
+ const invokedEntrypoint = process.argv[1];
62
+ if (!invokedEntrypoint || !isAbsolute(invokedEntrypoint)) {
63
+ return {
64
+ package: { name: '@deepseek-ai/dsh', error: 'DSH host entrypoint not found' },
65
+ };
66
+ }
67
+ let entrypoint = invokedEntrypoint;
68
+ try {
69
+ entrypoint = realpathSync(invokedEntrypoint);
70
+ }
71
+ catch {
72
+ // Keep the invoked path so the audit record still explains the lookup failure.
73
+ }
74
+ let dir = dirname(entrypoint);
75
+ for (let i = 0; i < 10; i++) {
76
+ const candidate = join(dir, 'package.json');
77
+ if (existsSync(candidate)) {
78
+ try {
79
+ const pkg = JSON.parse(readFileSync(candidate, 'utf-8'));
80
+ if (pkg.name === '@deepseek-ai/dsh') {
81
+ return {
82
+ entrypoint,
83
+ package: {
84
+ name: pkg.name,
85
+ ...(pkg.version ? { version: pkg.version } : {}),
86
+ },
87
+ };
88
+ }
89
+ }
90
+ catch {
91
+ // Keep walking: a parent package may still be the DSH CLI package.
92
+ }
93
+ }
94
+ const parent = dirname(dir);
95
+ if (parent === dir)
96
+ break;
97
+ dir = parent;
98
+ }
99
+ return {
100
+ entrypoint,
101
+ package: { name: '@deepseek-ai/dsh', error: 'invoking @deepseek-ai/dsh package.json not found' },
102
+ };
103
+ }
59
104
  function resolvePackageJson(packageName, from) {
60
105
  const req = from ? createRequire(from) : requireFromHere;
61
106
  try {
@@ -165,6 +210,7 @@ function withFingerprint(input) {
165
210
  status: input.sdk.version ? 'ok' : input.sdk.error ? 'error' : 'missing',
166
211
  }
167
212
  : undefined,
213
+ ...(input.auditability ? { auditability: input.auditability } : {}),
168
214
  capabilities: input.capabilities,
169
215
  };
170
216
  return { ...input, fingerprint: hashString(canonicalStringify(stablePayload)) };
@@ -178,6 +224,32 @@ function runtime(executor, model, kind, capabilities, extra = {}) {
178
224
  ...extra,
179
225
  });
180
226
  }
227
+ function ownPackage() {
228
+ const packageJson = findNearestPackageJson(fileURLToPath(import.meta.url));
229
+ if (!packageJson)
230
+ return { name: 'oh-my-knowledge', error: 'package.json not found' };
231
+ try {
232
+ const pkg = JSON.parse(readFileSync(packageJson, 'utf-8'));
233
+ return {
234
+ name: pkg.name ?? 'oh-my-knowledge',
235
+ ...(pkg.version ? { version: pkg.version } : {}),
236
+ };
237
+ }
238
+ catch (error) {
239
+ return {
240
+ name: 'oh-my-knowledge',
241
+ error: error instanceof Error ? error.message : String(error),
242
+ };
243
+ }
244
+ }
245
+ function dshCompositionHash(identity) {
246
+ return createHash('sha256').update(canonicalStringify({
247
+ adapter: 'omk-dsh-host-v1',
248
+ provider: identity.provider ?? null,
249
+ agentPreset: identity.agentPreset ?? null,
250
+ toolSchemas: identity.toolSchemas ?? null,
251
+ })).digest('hex');
252
+ }
181
253
  function runtimeEnv(options) {
182
254
  return options?.env ?? buildExecEnv(options?.skillDir);
183
255
  }
@@ -245,48 +317,63 @@ function scriptRuntime(executorName, model, env) {
245
317
  },
246
318
  });
247
319
  }
320
+ export function createDshHostRuntimeFingerprint(model, identity = {}) {
321
+ const descriptor = getExecutorDescriptor('dsh-host');
322
+ if (!descriptor || descriptor.name !== 'dsh-host') {
323
+ throw new Error('dsh-host executor descriptor is missing');
324
+ }
325
+ const host = readInvokingDshPackage();
326
+ return runtime(descriptor.name, model, descriptor.runtimeKind, descriptor.runtimeCapabilities, {
327
+ binary: {
328
+ name: '@deepseek-ai/dsh',
329
+ source: host.package.version ? 'path' : 'unknown',
330
+ ...(host.package.version ? { version: host.package.version } : {}),
331
+ ...(host.entrypoint ? { path: host.entrypoint } : {}),
332
+ contentHash: dshCompositionHash(identity),
333
+ package: host.package,
334
+ ...(host.package.error ? { error: host.package.error } : {}),
335
+ },
336
+ sdk: ownPackage(),
337
+ auditability: {
338
+ status: 'partial',
339
+ reasons: [
340
+ 'DSH does not expose a canonical digest for every active plugin and policy; the fingerprint covers provider, agent preset, and effective tool schemas',
341
+ ],
342
+ },
343
+ });
344
+ }
345
+ export function resolveExecutorRuntimeFingerprint(executorName, model, options = {}, executor) {
346
+ return executor?.runtimeFingerprint?.(model, options)
347
+ ?? getExecutorRuntimeFingerprint(executorName, model, options);
348
+ }
248
349
  export function getExecutorRuntimeFingerprint(executorName, model, options = {}) {
249
350
  const env = runtimeEnv(options);
250
- if (![
251
- 'claude',
252
- 'claude-sdk',
253
- 'codex',
254
- 'codex-sdk',
255
- 'gemini',
256
- 'anthropic-api',
257
- 'openai-api',
258
- ].includes(executorName)) {
351
+ const descriptor = getExecutorDescriptor(executorName);
352
+ if (!descriptor) {
259
353
  // Custom executors are local code. Re-read their referenced files so a
260
354
  // long-running Studio process cannot reuse stale outputs after the script
261
355
  // changes while the command line remains identical.
262
356
  return scriptRuntime(executorName, model, env);
263
357
  }
358
+ if (descriptor.fingerprint.strategy === 'dsh-host') {
359
+ return createDshHostRuntimeFingerprint(model);
360
+ }
264
361
  const pathHash = hashString(env.PATH || '');
265
362
  const cacheKey = `${executorName}\0${model}\0${pathHash}`;
266
363
  const cached = RUNTIME_CACHE.get(cacheKey);
267
364
  if (cached)
268
365
  return structuredClone(cached);
269
366
  let fp;
270
- switch (executorName) {
271
- case 'claude': {
272
- fp = runtime(executorName, model, 'agent-cli', {
273
- systemPrompt: 'native',
274
- costUSD: 'reported',
275
- trace: 'native',
276
- skillIsolation: 'full-no-partial',
277
- }, { binary: readPathBinary('claude', env) });
367
+ switch (descriptor.fingerprint.strategy) {
368
+ case 'path-cli': {
369
+ fp = runtime(descriptor.name, model, descriptor.runtimeKind, descriptor.runtimeCapabilities, { binary: readPathBinary(descriptor.fingerprint.command, env) });
278
370
  break;
279
371
  }
280
372
  case 'claude-sdk': {
281
373
  const sdkPackageJson = resolvePackageJson('@anthropic-ai/claude-agent-sdk');
282
374
  const sdk = readPackage('@anthropic-ai/claude-agent-sdk', sdkPackageJson ?? undefined);
283
375
  const claudeCodeVersion = readPackageField('@anthropic-ai/claude-agent-sdk', 'claudeCodeVersion', sdkPackageJson ?? undefined);
284
- fp = runtime(executorName, model, 'agent-sdk', {
285
- systemPrompt: 'native',
286
- costUSD: 'reported',
287
- trace: 'native',
288
- skillIsolation: 'full',
289
- }, {
376
+ fp = runtime(descriptor.name, model, descriptor.runtimeKind, descriptor.runtimeCapabilities, {
290
377
  sdk,
291
378
  binary: {
292
379
  name: 'claude-code',
@@ -297,25 +384,11 @@ export function getExecutorRuntimeFingerprint(executorName, model, options = {})
297
384
  });
298
385
  break;
299
386
  }
300
- case 'codex': {
301
- fp = runtime(executorName, model, 'agent-cli', {
302
- systemPrompt: 'prepended',
303
- costUSD: 'not-reported',
304
- trace: 'best-effort',
305
- skillIsolation: 'cwd-only',
306
- }, { binary: readPathBinary('codex', env) });
307
- break;
308
- }
309
387
  case 'codex-sdk': {
310
388
  const sdkPackageJson = resolvePackageJson('@openai/codex-sdk');
311
389
  const sdk = readPackage('@openai/codex-sdk', sdkPackageJson ?? undefined);
312
390
  const bundledCodex = readPackage('@openai/codex', sdkPackageJson ?? undefined);
313
- fp = runtime(executorName, model, 'agent-sdk', {
314
- systemPrompt: 'prepended',
315
- costUSD: 'not-reported',
316
- trace: 'best-effort',
317
- skillIsolation: 'cwd-only',
318
- }, {
391
+ fp = runtime(descriptor.name, model, descriptor.runtimeKind, descriptor.runtimeCapabilities, {
319
392
  sdk,
320
393
  binary: {
321
394
  name: 'codex',
@@ -326,27 +399,14 @@ export function getExecutorRuntimeFingerprint(executorName, model, options = {})
326
399
  });
327
400
  break;
328
401
  }
329
- case 'gemini': {
330
- fp = runtime(executorName, model, 'agent-cli', {
331
- systemPrompt: 'prepended',
332
- costUSD: 'not-reported',
333
- trace: 'none',
334
- skillIsolation: 'none',
335
- }, { binary: readPathBinary('gemini', env) });
402
+ case 'api': {
403
+ fp = runtime(descriptor.name, model, descriptor.runtimeKind, descriptor.runtimeCapabilities, { binary: { name: descriptor.name, source: 'none' } });
336
404
  break;
337
405
  }
338
- case 'anthropic-api':
339
- case 'openai-api': {
340
- fp = runtime(executorName, model, 'api', {
341
- systemPrompt: 'native',
342
- costUSD: 'not-reported',
343
- trace: 'none',
344
- skillIsolation: 'none',
345
- }, { binary: { name: executorName, source: 'none' } });
346
- break;
406
+ default: {
407
+ const unreachable = descriptor.fingerprint;
408
+ throw new Error(`unreachable executor fingerprint strategy: ${JSON.stringify(unreachable)}`);
347
409
  }
348
- default:
349
- throw new Error(`unreachable executor runtime: ${executorName}`);
350
410
  }
351
411
  RUNTIME_CACHE.set(cacheKey, structuredClone(fp));
352
412
  return structuredClone(fp);
@@ -0,0 +1,12 @@
1
+ import type { ExecResult } from '../../types/index.js';
2
+ export interface ExecutorErrorLike {
3
+ message?: string;
4
+ name?: string;
5
+ killed?: boolean;
6
+ stdout?: string;
7
+ }
8
+ export declare function asErrorLike(err: unknown): ExecutorErrorLike;
9
+ export declare function errorMessage(err: unknown, fallback?: string): string;
10
+ export declare function buildExecEnv(skillDir?: string | null): NodeJS.ProcessEnv;
11
+ export declare function timeoutExecResult(timeoutMs: number, durationMs: number): ExecResult;
12
+ export declare function interruptedExecResult(durationMs: number): ExecResult;