@myagentroam/node 0.1.4 → 0.1.6
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 +9 -1
- package/dist/capabilities.d.ts +2 -0
- package/dist/capabilities.js +15 -4
- package/dist/claude-agent-sdk.d.ts +3 -1
- package/dist/claude-agent-sdk.js +9 -2
- package/dist/claude-channel.js +0 -1
- package/dist/codex-app-server.d.ts +1 -0
- package/dist/codex-app-server.js +8 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +18 -2
- package/dist/connector/node-connector-options.d.ts +3 -0
- package/dist/connector/node-connector-options.js +0 -1
- package/dist/connector/node-operation-router.js +0 -1
- package/dist/connector.d.ts +3 -0
- package/dist/connector.js +109 -7
- package/dist/control-outbound-scheduler.js +0 -1
- package/dist/database.d.ts +4 -0
- package/dist/database.js +14 -9
- package/dist/event-buffer.js +0 -1
- package/dist/fake-runner.js +0 -1
- package/dist/health.js +0 -1
- package/dist/main.js +6 -1
- package/dist/migrations/v001.js +0 -1
- package/dist/migrations/v002.js +0 -1
- package/dist/migrations/v003.d.ts +4 -0
- package/dist/migrations/v003.js +44 -0
- package/dist/native-jsonl-reader.js +0 -1
- package/dist/native-session-history.d.ts +19 -1
- package/dist/native-session-history.js +65 -3
- package/dist/opencode-runtime.d.ts +33 -0
- package/dist/opencode-runtime.js +80 -0
- package/dist/opencode-server.d.ts +47 -0
- package/dist/opencode-server.js +250 -0
- package/dist/operational.js +10 -3
- package/dist/process-tree.js +0 -1
- package/dist/runner/abstract-runner.d.ts +7 -2
- package/dist/runner/abstract-runner.js +17 -2
- package/dist/runner/claude/managed-run-controller.js +20 -1
- package/dist/runner/claude-code-runner.d.ts +3 -1
- package/dist/runner/claude-code-runner.js +26 -8
- package/dist/runner/codex/conversation-parser.d.ts +1 -3
- package/dist/runner/codex/conversation-parser.js +174 -34
- package/dist/runner/codex/managed-run-controller.d.ts +2 -1
- package/dist/runner/codex/managed-run-controller.js +13 -4
- package/dist/runner/codex-runner.d.ts +4 -0
- package/dist/runner/codex-runner.js +27 -4
- package/dist/runner/fake-test-runner.js +0 -1
- package/dist/runner/opencode/conversation-parser.d.ts +27 -0
- package/dist/runner/opencode/conversation-parser.js +217 -0
- package/dist/runner/opencode/managed-run-controller.d.ts +76 -0
- package/dist/runner/opencode/managed-run-controller.js +451 -0
- package/dist/runner/opencode-runner.d.ts +60 -0
- package/dist/runner/opencode-runner.js +330 -0
- package/dist/runner/runner-registry.d.ts +3 -1
- package/dist/runner/runner-registry.js +12 -3
- package/dist/runner-command-engine.js +0 -1
- package/dist/runner-profiles.d.ts +4 -0
- package/dist/runner-profiles.js +76 -3
- package/dist/runner-usage.js +0 -1
- package/dist/runtime-state.js +20 -9
- package/dist/service/attachment-domain-state.js +0 -1
- package/dist/service/conversation-history-service.js +0 -1
- package/dist/service/external-session-resume-service.js +0 -1
- package/dist/service/fake-managed-run-service.js +0 -1
- package/dist/service/managed-runner-session-service.d.ts +3 -1
- package/dist/service/managed-runner-session-service.js +8 -4
- package/dist/service/native-session-projection-service.d.ts +2 -1
- package/dist/service/native-session-projection-service.js +8 -5
- package/dist/service/native-session-watch-service.js +0 -1
- package/dist/service/node-connection-lifecycle-service.js +3 -2
- package/dist/service/node-control-channel.d.ts +1 -1
- package/dist/service/node-control-channel.js +5 -4
- package/dist/service/node-control-message-service.js +0 -1
- package/dist/service/node-request-service.js +0 -1
- package/dist/service/node-run-event-bridge.d.ts +2 -0
- package/dist/service/node-run-event-bridge.js +4 -1
- package/dist/service/node-terminal-channel.js +16 -10
- package/dist/service/node-upgrade-coordinator.d.ts +29 -0
- package/dist/service/node-upgrade-coordinator.js +137 -0
- package/dist/service/node-workspace-coordinator.js +0 -1
- package/dist/service/run-attachment-service.js +0 -1
- package/dist/service/run-domain-state.js +0 -1
- package/dist/service/run-event-service.js +0 -1
- package/dist/service/run-workbench-service.js +0 -1
- package/dist/service/runner-channel-message-service.js +0 -1
- package/dist/service/runner-interaction-service.js +2 -1
- package/dist/service/runner-service.d.ts +5 -4
- package/dist/service/runner-service.js +19 -6
- package/dist/service/session-catalog-service.d.ts +16 -1
- package/dist/service/session-catalog-service.js +82 -3
- package/dist/service/session-command-service.js +0 -1
- package/dist/service/session-context-service.js +0 -1
- package/dist/service/session-domain-state.js +0 -1
- package/dist/service/session-identity-service.js +0 -1
- package/dist/service/session-lifecycle-service.js +13 -7
- package/dist/service/session-message-service.js +0 -1
- package/dist/service/session-presentation-service.js +0 -1
- package/dist/service/session-query-service.js +0 -1
- package/dist/service/terminal-relay-state.js +0 -1
- package/dist/service/terminal-service.js +0 -1
- package/dist/service/workbench-event-service.js +0 -1
- package/dist/service/workbench-manifest-service.d.ts +5 -4
- package/dist/service/workbench-manifest-service.js +3 -2
- package/dist/service/workspace-change-service.js +2 -2
- package/dist/service/workspace-content-search-service.d.ts +14 -0
- package/dist/service/workspace-content-search-service.js +477 -0
- package/dist/service/workspace-domain-state.js +0 -1
- package/dist/service/workspace-file-service.d.ts +3 -0
- package/dist/service/workspace-file-service.js +35 -3
- package/dist/service/workspace-queue-workbench-service.js +0 -1
- package/dist/service/workspace-service.js +23 -10
- package/dist/service/workspace-session-service.js +0 -1
- package/dist/service/workspace-upload-service.js +0 -1
- package/dist/service/workspace-watch-service.js +0 -1
- package/dist/service/workspace-workbench-service.d.ts +9 -0
- package/dist/service/workspace-workbench-service.js +69 -2
- package/dist/service.js +2 -3
- package/dist/storage.js +0 -1
- package/dist/supervisor.d.ts +1 -0
- package/dist/supervisor.js +154 -0
- package/dist/terminal.js +0 -1
- package/dist/util/node-operation-parsers.d.ts +1 -0
- package/dist/util/node-operation-parsers.js +3 -1
- package/dist/util/runner-native-session-parsers.js +117 -73
- package/dist/util/secret-environment.js +0 -1
- package/dist/workspace.d.ts +62 -2
- package/dist/workspace.js +539 -57
- package/package.json +3 -2
- package/dist/capabilities.js.map +0 -1
- package/dist/claude-agent-sdk.js.map +0 -1
- package/dist/claude-channel.js.map +0 -1
- package/dist/codex-app-server.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/connector/node-connector-options.js.map +0 -1
- package/dist/connector/node-operation-router.js.map +0 -1
- package/dist/connector.js.map +0 -1
- package/dist/control-outbound-scheduler.js.map +0 -1
- package/dist/database.js.map +0 -1
- package/dist/event-buffer.js.map +0 -1
- package/dist/fake-runner.js.map +0 -1
- package/dist/health.js.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/migrations/v001.js.map +0 -1
- package/dist/migrations/v002.js.map +0 -1
- package/dist/native-jsonl-reader.js.map +0 -1
- package/dist/native-session-history.js.map +0 -1
- package/dist/operational.js.map +0 -1
- package/dist/process-tree.js.map +0 -1
- package/dist/runner/abstract-runner.js.map +0 -1
- package/dist/runner/claude/managed-run-controller.js.map +0 -1
- package/dist/runner/claude-code-runner.js.map +0 -1
- package/dist/runner/codex/conversation-parser.js.map +0 -1
- package/dist/runner/codex/managed-run-controller.js.map +0 -1
- package/dist/runner/codex-runner.js.map +0 -1
- package/dist/runner/fake-test-runner.js.map +0 -1
- package/dist/runner/runner-registry.js.map +0 -1
- package/dist/runner-command-engine.js.map +0 -1
- package/dist/runner-profiles.js.map +0 -1
- package/dist/runner-usage.js.map +0 -1
- package/dist/runtime-state.js.map +0 -1
- package/dist/service/attachment-domain-state.js.map +0 -1
- package/dist/service/conversation-history-service.js.map +0 -1
- package/dist/service/external-session-resume-service.js.map +0 -1
- package/dist/service/fake-managed-run-service.js.map +0 -1
- package/dist/service/managed-runner-session-service.js.map +0 -1
- package/dist/service/native-session-projection-service.js.map +0 -1
- package/dist/service/native-session-watch-service.js.map +0 -1
- package/dist/service/node-connection-lifecycle-service.js.map +0 -1
- package/dist/service/node-control-channel.js.map +0 -1
- package/dist/service/node-control-message-service.js.map +0 -1
- package/dist/service/node-request-service.js.map +0 -1
- package/dist/service/node-run-event-bridge.js.map +0 -1
- package/dist/service/node-terminal-channel.js.map +0 -1
- package/dist/service/node-workspace-coordinator.js.map +0 -1
- package/dist/service/run-attachment-service.js.map +0 -1
- package/dist/service/run-domain-state.js.map +0 -1
- package/dist/service/run-event-service.js.map +0 -1
- package/dist/service/run-workbench-service.js.map +0 -1
- package/dist/service/runner-channel-message-service.js.map +0 -1
- package/dist/service/runner-interaction-service.js.map +0 -1
- package/dist/service/runner-service.js.map +0 -1
- package/dist/service/session-catalog-service.js.map +0 -1
- package/dist/service/session-command-service.js.map +0 -1
- package/dist/service/session-context-service.js.map +0 -1
- package/dist/service/session-domain-state.js.map +0 -1
- package/dist/service/session-identity-service.js.map +0 -1
- package/dist/service/session-lifecycle-service.js.map +0 -1
- package/dist/service/session-message-service.js.map +0 -1
- package/dist/service/session-presentation-service.js.map +0 -1
- package/dist/service/session-query-service.js.map +0 -1
- package/dist/service/terminal-relay-state.js.map +0 -1
- package/dist/service/terminal-service.js.map +0 -1
- package/dist/service/workbench-event-service.js.map +0 -1
- package/dist/service/workbench-manifest-service.js.map +0 -1
- package/dist/service/workspace-change-service.js.map +0 -1
- package/dist/service/workspace-domain-state.js.map +0 -1
- package/dist/service/workspace-file-service.js.map +0 -1
- package/dist/service/workspace-queue-workbench-service.js.map +0 -1
- package/dist/service/workspace-service.js.map +0 -1
- package/dist/service/workspace-session-service.js.map +0 -1
- package/dist/service/workspace-upload-service.js.map +0 -1
- package/dist/service/workspace-watch-service.js.map +0 -1
- package/dist/service/workspace-workbench-service.js.map +0 -1
- package/dist/service.js.map +0 -1
- package/dist/storage.js.map +0 -1
- package/dist/terminal.js.map +0 -1
- package/dist/util/node-operation-parsers.js.map +0 -1
- package/dist/util/runner-native-session-parsers.js.map +0 -1
- package/dist/util/secret-environment.js.map +0 -1
- package/dist/workspace.js.map +0 -1
package/dist/main.js
CHANGED
|
@@ -4,6 +4,7 @@ import { NodeConnector } from './connector.js';
|
|
|
4
4
|
import { loadNodeConfig, nodeConfigPath, nodeDatabasePath } from './config.js';
|
|
5
5
|
import { getNodeHealth } from './health.js';
|
|
6
6
|
import { removeServiceDefinition, writeServiceDefinition } from './service.js';
|
|
7
|
+
import { superviseNode } from './supervisor.js';
|
|
7
8
|
const [command = 'status', ...args] = process.argv.slice(2);
|
|
8
9
|
const config = readOption(args, '--config') ?? nodeConfigPath();
|
|
9
10
|
const output = readOption(args, '--output') ?? defaultServicePath();
|
|
@@ -14,6 +15,11 @@ if (command === 'run') {
|
|
|
14
15
|
process.once(signal, () => connector.stop());
|
|
15
16
|
}
|
|
16
17
|
}
|
|
18
|
+
else if (command === 'supervise') {
|
|
19
|
+
if (process.argv[1] === undefined)
|
|
20
|
+
throw new Error('NODE_ENTRYPOINT_UNAVAILABLE');
|
|
21
|
+
await superviseNode(config, process.argv[1]);
|
|
22
|
+
}
|
|
17
23
|
else if (command === 'install') {
|
|
18
24
|
await writeCurrentServiceDefinition(output, config);
|
|
19
25
|
process.stdout.write(`${output}\n`);
|
|
@@ -44,4 +50,3 @@ async function writeCurrentServiceDefinition(output, configPath) {
|
|
|
44
50
|
const nodeConfig = await loadNodeConfig(configPath);
|
|
45
51
|
await writeServiceDefinition(output, process.execPath, configPath, process.platform, process.argv[1], [dirname(nodeDatabasePath(nodeConfig, configPath)), ...nodeConfig.allowedRoots]);
|
|
46
52
|
}
|
|
47
|
-
//# sourceMappingURL=main.js.map
|
package/dist/migrations/v001.js
CHANGED
package/dist/migrations/v002.js
CHANGED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const NODE_SCHEMA_VERSION_V3 = 3;
|
|
2
|
+
export function migrateNodeSchemaV3(database) {
|
|
3
|
+
database.exec('PRAGMA foreign_keys = OFF');
|
|
4
|
+
database.exec('BEGIN IMMEDIATE');
|
|
5
|
+
try {
|
|
6
|
+
database.exec(`ALTER TABLE agent_sessions RENAME TO agent_sessions_v2;
|
|
7
|
+
CREATE TABLE agent_sessions (
|
|
8
|
+
id TEXT PRIMARY KEY,
|
|
9
|
+
workspace_id TEXT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
10
|
+
runner TEXT NOT NULL CHECK (runner IN ('codex', 'claude-code', 'opencode')),
|
|
11
|
+
pin_order INTEGER CHECK (pin_order IS NULL OR pin_order >= 0),
|
|
12
|
+
metadata TEXT NOT NULL CHECK (json_valid(metadata))
|
|
13
|
+
) STRICT;
|
|
14
|
+
INSERT INTO agent_sessions SELECT * FROM agent_sessions_v2;
|
|
15
|
+
DROP TABLE agent_sessions_v2;
|
|
16
|
+
ALTER TABLE runner_defaults RENAME TO runner_defaults_v2;
|
|
17
|
+
CREATE TABLE runner_defaults (
|
|
18
|
+
runner TEXT PRIMARY KEY CHECK (runner IN ('codex', 'claude-code', 'opencode')),
|
|
19
|
+
model TEXT NOT NULL, effort TEXT NOT NULL, access TEXT NOT NULL
|
|
20
|
+
) STRICT;
|
|
21
|
+
INSERT INTO runner_defaults SELECT * FROM runner_defaults_v2;
|
|
22
|
+
DROP TABLE runner_defaults_v2;`);
|
|
23
|
+
database
|
|
24
|
+
.prepare('INSERT INTO node_schema_migrations (version, applied_at) VALUES (?, ?)')
|
|
25
|
+
.run(NODE_SCHEMA_VERSION_V3, Date.now());
|
|
26
|
+
database.exec('COMMIT');
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
database.exec('ROLLBACK');
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
database.exec('PRAGMA foreign_keys = ON');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function assertNodeSchemaV3(database) {
|
|
37
|
+
for (const table of ['agent_sessions', 'runner_defaults']) {
|
|
38
|
+
const row = database
|
|
39
|
+
.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?")
|
|
40
|
+
.get(table);
|
|
41
|
+
if (typeof row?.sql !== 'string' || !row.sql.includes("'opencode'"))
|
|
42
|
+
throw new Error(`NODE_DATABASE_SCHEMA_INVALID:${table}:runner`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -4,6 +4,7 @@ export interface NativeTranscriptMessage {
|
|
|
4
4
|
readonly role: 'USER' | 'ASSISTANT';
|
|
5
5
|
readonly text: string;
|
|
6
6
|
readonly createdAt: number | null;
|
|
7
|
+
readonly nativeId?: string;
|
|
7
8
|
}
|
|
8
9
|
export interface NativeTranscriptToolCall {
|
|
9
10
|
readonly kind: 'tool_call';
|
|
@@ -18,6 +19,23 @@ export interface NativeTranscriptToolCall {
|
|
|
18
19
|
readonly imageAttachments?: readonly NativeTranscriptImageAttachment[];
|
|
19
20
|
readonly failed: boolean;
|
|
20
21
|
readonly createdAt: number | null;
|
|
22
|
+
readonly nativeId?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface NativeTranscriptUnknown {
|
|
25
|
+
readonly kind: 'unknown';
|
|
26
|
+
readonly sourceEventType: string;
|
|
27
|
+
readonly label: string;
|
|
28
|
+
readonly createdAt: number | null;
|
|
29
|
+
readonly nativeId?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface NativeTranscriptReasoningSummary {
|
|
32
|
+
readonly kind: 'reasoning_summary';
|
|
33
|
+
readonly sections: readonly {
|
|
34
|
+
readonly index: number;
|
|
35
|
+
readonly text: string;
|
|
36
|
+
}[];
|
|
37
|
+
readonly createdAt: number | null;
|
|
38
|
+
readonly nativeId?: string;
|
|
21
39
|
}
|
|
22
40
|
export interface NativeTranscriptImageAttachment {
|
|
23
41
|
readonly name: string;
|
|
@@ -25,7 +43,7 @@ export interface NativeTranscriptImageAttachment {
|
|
|
25
43
|
/** Codex-owned local artifact path; never sent to Web. */
|
|
26
44
|
readonly localPath?: string;
|
|
27
45
|
}
|
|
28
|
-
export type NativeTranscriptItem = NativeTranscriptMessage | NativeTranscriptToolCall;
|
|
46
|
+
export type NativeTranscriptItem = NativeTranscriptMessage | NativeTranscriptToolCall | NativeTranscriptReasoningSummary | NativeTranscriptUnknown;
|
|
29
47
|
export interface NativeSessionHistory {
|
|
30
48
|
readonly runner: RunnerName;
|
|
31
49
|
readonly externalSessionId: string;
|
|
@@ -261,7 +261,8 @@ async function readTranscript(path, runner, byteLimit) {
|
|
|
261
261
|
const generatedImage = codexGeneratedImageEvent(value);
|
|
262
262
|
if (generatedImage !== undefined)
|
|
263
263
|
items.push(generatedImage);
|
|
264
|
-
for (const
|
|
264
|
+
for (const parsedItem of transcriptItems(value)) {
|
|
265
|
+
const item = recordId === undefined ? parsedItem : { ...parsedItem, nativeId: recordId };
|
|
265
266
|
if (item.kind === 'tool_result') {
|
|
266
267
|
const toolIndex = toolIndexes.get(item.toolUseId);
|
|
267
268
|
if (toolIndex === undefined)
|
|
@@ -395,7 +396,10 @@ function transcriptItems(record) {
|
|
|
395
396
|
return results;
|
|
396
397
|
const values = [
|
|
397
398
|
...toolUsesOf(record, createdAt),
|
|
398
|
-
...codexToolUsesOf(record, createdAt)
|
|
399
|
+
...codexToolUsesOf(record, createdAt),
|
|
400
|
+
...codexReasoningSummariesOf(record, createdAt),
|
|
401
|
+
...unsupportedCodexResponseItems(record, createdAt),
|
|
402
|
+
...unsupportedTranscriptItems(record, createdAt)
|
|
399
403
|
];
|
|
400
404
|
const role = roleOf(record);
|
|
401
405
|
if (role === undefined)
|
|
@@ -411,6 +415,65 @@ function transcriptItems(record) {
|
|
|
411
415
|
values.unshift({ kind: 'message', role, text, createdAt });
|
|
412
416
|
return values;
|
|
413
417
|
}
|
|
418
|
+
function unsupportedCodexResponseItems(record, createdAt) {
|
|
419
|
+
const payload = codexToolPayload(record);
|
|
420
|
+
const type = typeof payload?.type === 'string' ? payload.type : undefined;
|
|
421
|
+
if (type === undefined ||
|
|
422
|
+
typeof payload?.role === 'string' ||
|
|
423
|
+
type === 'reasoning' ||
|
|
424
|
+
type === 'custom_tool_call' ||
|
|
425
|
+
type === 'custom_tool_call_output' ||
|
|
426
|
+
type === 'function_call' ||
|
|
427
|
+
type === 'function_call_output')
|
|
428
|
+
return [];
|
|
429
|
+
return [
|
|
430
|
+
{
|
|
431
|
+
kind: 'unknown',
|
|
432
|
+
sourceEventType: `codex:${type}`,
|
|
433
|
+
label: `Codex ${compact(type).slice(0, 128)}`,
|
|
434
|
+
createdAt
|
|
435
|
+
}
|
|
436
|
+
];
|
|
437
|
+
}
|
|
438
|
+
function codexReasoningSummariesOf(record, createdAt) {
|
|
439
|
+
const payload = codexToolPayload(record);
|
|
440
|
+
if (payload?.type !== 'reasoning')
|
|
441
|
+
return [];
|
|
442
|
+
const sections = Array.isArray(payload.summary)
|
|
443
|
+
? payload.summary.flatMap((value, index) => {
|
|
444
|
+
if (typeof value !== 'string')
|
|
445
|
+
return [];
|
|
446
|
+
const text = compact(value).slice(0, 10_000);
|
|
447
|
+
return text.length === 0 ? [] : [{ index, text }];
|
|
448
|
+
})
|
|
449
|
+
: [];
|
|
450
|
+
return [{ kind: 'reasoning_summary', sections, createdAt }];
|
|
451
|
+
}
|
|
452
|
+
function unsupportedTranscriptItems(record, createdAt) {
|
|
453
|
+
return contentBlocks(record).flatMap((block) => {
|
|
454
|
+
const type = typeof block.type === 'string' ? block.type : undefined;
|
|
455
|
+
if (type === undefined ||
|
|
456
|
+
type === 'text' ||
|
|
457
|
+
type === 'input_text' ||
|
|
458
|
+
type === 'output_text' ||
|
|
459
|
+
type === 'image' ||
|
|
460
|
+
type === 'input_image' ||
|
|
461
|
+
type === 'thinking' ||
|
|
462
|
+
type === 'redacted_thinking' ||
|
|
463
|
+
type === 'encrypted_thinking' ||
|
|
464
|
+
type === 'tool_use' ||
|
|
465
|
+
type === 'tool_result')
|
|
466
|
+
return [];
|
|
467
|
+
return [
|
|
468
|
+
{
|
|
469
|
+
kind: 'unknown',
|
|
470
|
+
sourceEventType: `transcript:${type}`,
|
|
471
|
+
label: `Agent ${compact(type).slice(0, 128)}`,
|
|
472
|
+
createdAt
|
|
473
|
+
}
|
|
474
|
+
];
|
|
475
|
+
});
|
|
476
|
+
}
|
|
414
477
|
function toolUsesOf(record, createdAt) {
|
|
415
478
|
return contentBlocks(record).flatMap((block) => {
|
|
416
479
|
if (block['type'] !== 'tool_use' ||
|
|
@@ -768,4 +831,3 @@ function indexKey(runner, cwd, externalSessionId) {
|
|
|
768
831
|
function isRecord(value) {
|
|
769
832
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
770
833
|
}
|
|
771
|
-
//# sourceMappingURL=native-session-history.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface OpenCodeProbe {
|
|
2
|
+
readonly available: boolean;
|
|
3
|
+
readonly compatible: boolean;
|
|
4
|
+
readonly version?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface OpenCodeProviderCatalog {
|
|
7
|
+
readonly connected?: readonly string[];
|
|
8
|
+
readonly default?: Readonly<Record<string, string>>;
|
|
9
|
+
readonly all?: readonly {
|
|
10
|
+
readonly id?: string;
|
|
11
|
+
readonly name?: string;
|
|
12
|
+
readonly source?: 'env' | 'config' | 'custom' | 'api';
|
|
13
|
+
readonly models?: Readonly<Record<string, {
|
|
14
|
+
readonly id?: string;
|
|
15
|
+
readonly name?: string;
|
|
16
|
+
readonly variants?: Readonly<Record<string, {
|
|
17
|
+
readonly disabled?: boolean;
|
|
18
|
+
}>>;
|
|
19
|
+
readonly limit?: {
|
|
20
|
+
readonly context?: number;
|
|
21
|
+
};
|
|
22
|
+
}>>;
|
|
23
|
+
}[];
|
|
24
|
+
}
|
|
25
|
+
export interface OpenCodeProfileModel {
|
|
26
|
+
readonly id: string;
|
|
27
|
+
readonly label: string;
|
|
28
|
+
readonly supportedEfforts: string[];
|
|
29
|
+
}
|
|
30
|
+
export declare function probeOpenCode(command?: string): OpenCodeProbe;
|
|
31
|
+
export declare function probeOpenCodeAsync(command?: string): Promise<OpenCodeProbe>;
|
|
32
|
+
export declare function openCodeProfileModels(catalog: OpenCodeProviderCatalog): OpenCodeProfileModel[];
|
|
33
|
+
export declare function openCodeContextLimits(catalog: OpenCodeProviderCatalog): ReadonlyMap<string, number>;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { minimalRunnerEnvironment, platformCliInvocation, runRunnerProbe } from './operational.js';
|
|
3
|
+
const PROBE_TIMEOUT_MS = 3_000;
|
|
4
|
+
export function probeOpenCode(command = 'opencode') {
|
|
5
|
+
const invocation = platformCliInvocation(command, ['--version']);
|
|
6
|
+
const result = spawnSync(invocation.command, invocation.args, {
|
|
7
|
+
windowsHide: true,
|
|
8
|
+
env: minimalRunnerEnvironment(),
|
|
9
|
+
timeout: PROBE_TIMEOUT_MS,
|
|
10
|
+
encoding: 'utf8'
|
|
11
|
+
});
|
|
12
|
+
if (result.status !== 0 || result.error !== undefined)
|
|
13
|
+
return { available: false, compatible: false };
|
|
14
|
+
return openCodeProbeResult(`${result.stdout}${result.stderr}`);
|
|
15
|
+
}
|
|
16
|
+
export async function probeOpenCodeAsync(command = 'opencode') {
|
|
17
|
+
const invocation = platformCliInvocation(command, ['--version']);
|
|
18
|
+
const result = await runRunnerProbe(invocation.command, invocation.args, {
|
|
19
|
+
env: minimalRunnerEnvironment(),
|
|
20
|
+
timeoutMs: PROBE_TIMEOUT_MS
|
|
21
|
+
});
|
|
22
|
+
return result.status === 0
|
|
23
|
+
? openCodeProbeResult(`${result.stdout}${result.stderr}`)
|
|
24
|
+
: { available: false, compatible: false };
|
|
25
|
+
}
|
|
26
|
+
function openCodeProbeResult(output) {
|
|
27
|
+
const version = output.trim().replace(/^v/i, '').slice(0, 128);
|
|
28
|
+
return {
|
|
29
|
+
available: version.length > 0,
|
|
30
|
+
compatible: /^1\.18\./.test(version),
|
|
31
|
+
...(version.length === 0 ? {} : { version })
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function openCodeProfileModels(catalog) {
|
|
35
|
+
const connected = new Set(catalog.connected ?? []);
|
|
36
|
+
return (catalog.all ?? [])
|
|
37
|
+
.filter((provider) => typeof provider.id === 'string' &&
|
|
38
|
+
connected.has(provider.id) &&
|
|
39
|
+
provider.source === 'config')
|
|
40
|
+
.flatMap((provider) => {
|
|
41
|
+
const providerId = provider.id;
|
|
42
|
+
return Object.entries(provider.models ?? {}).flatMap(([key, model]) => {
|
|
43
|
+
const modelId = boundedString(model.id) ?? boundedString(key);
|
|
44
|
+
if (modelId === undefined)
|
|
45
|
+
return [];
|
|
46
|
+
const variants = Object.entries(model.variants ?? {})
|
|
47
|
+
.filter(([, value]) => value.disabled !== true)
|
|
48
|
+
.map(([id]) => id)
|
|
49
|
+
.filter((id) => id.length > 0 && id.length <= 64)
|
|
50
|
+
.slice(0, 32);
|
|
51
|
+
return [
|
|
52
|
+
{
|
|
53
|
+
id: `${providerId}/${modelId}`.slice(0, 128),
|
|
54
|
+
label: (boundedString(model.name) ?? modelId).slice(0, 128),
|
|
55
|
+
supportedEfforts: variants
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
export function openCodeContextLimits(catalog) {
|
|
62
|
+
const connected = new Set(catalog.connected ?? []);
|
|
63
|
+
return new Map((catalog.all ?? [])
|
|
64
|
+
.filter((provider) => typeof provider.id === 'string' &&
|
|
65
|
+
connected.has(provider.id) &&
|
|
66
|
+
provider.source === 'config')
|
|
67
|
+
.flatMap((provider) => Object.entries(provider.models ?? {}).flatMap(([key, model]) => {
|
|
68
|
+
const modelId = boundedString(model.id) ?? boundedString(key);
|
|
69
|
+
const context = model.limit?.context;
|
|
70
|
+
return modelId !== undefined && Number.isSafeInteger(context) && (context ?? 0) > 0
|
|
71
|
+
? [[`${provider.id}/${modelId}`, context]]
|
|
72
|
+
: [];
|
|
73
|
+
})));
|
|
74
|
+
}
|
|
75
|
+
function boundedString(value) {
|
|
76
|
+
if (typeof value !== 'string')
|
|
77
|
+
return undefined;
|
|
78
|
+
const trimmed = value.trim();
|
|
79
|
+
return trimmed.length > 0 && trimmed.length <= 4096 ? trimmed : undefined;
|
|
80
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import type { OpenCodeProviderCatalog } from './opencode-runtime.js';
|
|
3
|
+
export interface OpenCodeServerOptions {
|
|
4
|
+
readonly command?: string;
|
|
5
|
+
readonly startTimeoutMs?: number;
|
|
6
|
+
readonly spawnProcess?: typeof spawn;
|
|
7
|
+
}
|
|
8
|
+
export declare class OpenCodeServerClient {
|
|
9
|
+
private readonly options;
|
|
10
|
+
private child;
|
|
11
|
+
private client;
|
|
12
|
+
private starting;
|
|
13
|
+
private environment;
|
|
14
|
+
constructor(options?: OpenCodeServerOptions);
|
|
15
|
+
configureEnvironment(environment: Readonly<Record<string, string>>): void;
|
|
16
|
+
start(): Promise<void>;
|
|
17
|
+
private startServer;
|
|
18
|
+
providers(directory: string): Promise<OpenCodeProviderCatalog>;
|
|
19
|
+
sessions(directory: string, limit?: number): Promise<readonly unknown[]>;
|
|
20
|
+
sessionStatus(directory: string): Promise<Readonly<Record<string, unknown>>>;
|
|
21
|
+
createSession(directory: string, title?: string): Promise<unknown>;
|
|
22
|
+
forkSession(directory: string, sessionID: string, messageID: string): Promise<unknown>;
|
|
23
|
+
messages(directory: string, sessionID: string, limit?: number): Promise<readonly unknown[]>;
|
|
24
|
+
updateSession(directory: string, sessionID: string, title: string): Promise<unknown>;
|
|
25
|
+
deleteSession(directory: string, sessionID: string): Promise<unknown>;
|
|
26
|
+
abort(directory: string, sessionID: string): Promise<unknown>;
|
|
27
|
+
summarize(directory: string, sessionID: string, model: string): Promise<unknown>;
|
|
28
|
+
replyPermission(directory: string, requestID: string, decision: 'APPROVED' | 'REJECTED'): Promise<unknown>;
|
|
29
|
+
replyQuestion(directory: string, requestID: string, answers: readonly (readonly string[])[]): Promise<unknown>;
|
|
30
|
+
rejectQuestion(directory: string, requestID: string): Promise<unknown>;
|
|
31
|
+
prompt(input: {
|
|
32
|
+
readonly directory: string;
|
|
33
|
+
readonly sessionID: string;
|
|
34
|
+
readonly text: string;
|
|
35
|
+
readonly model: string;
|
|
36
|
+
readonly variant?: string;
|
|
37
|
+
readonly agent?: 'plan' | 'build';
|
|
38
|
+
readonly attachments?: readonly {
|
|
39
|
+
readonly name: string;
|
|
40
|
+
readonly mime: 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp';
|
|
41
|
+
readonly dataBase64: string;
|
|
42
|
+
}[];
|
|
43
|
+
}): Promise<unknown>;
|
|
44
|
+
subscribe(directory: string, signal: AbortSignal, onEvent: (event: unknown) => void, onReady?: () => void): Promise<void>;
|
|
45
|
+
stop(): Promise<void>;
|
|
46
|
+
private requireClient;
|
|
47
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { randomBytes } from 'node:crypto';
|
|
3
|
+
import { createServer } from 'node:net';
|
|
4
|
+
import { createOpencodeClient } from '@opencode-ai/sdk/v2/client';
|
|
5
|
+
import { minimalRunnerEnvironment, platformCliInvocation } from './operational.js';
|
|
6
|
+
import { terminateProcessTree } from './process-tree.js';
|
|
7
|
+
const START_TIMEOUT_MS = 10_000;
|
|
8
|
+
export class OpenCodeServerClient {
|
|
9
|
+
options;
|
|
10
|
+
child;
|
|
11
|
+
client;
|
|
12
|
+
starting;
|
|
13
|
+
environment = {};
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.options = options;
|
|
16
|
+
}
|
|
17
|
+
configureEnvironment(environment) {
|
|
18
|
+
if (this.child !== undefined)
|
|
19
|
+
throw new Error('OPENCODE_SERVER_ALREADY_STARTED');
|
|
20
|
+
this.environment = { ...environment };
|
|
21
|
+
}
|
|
22
|
+
async start() {
|
|
23
|
+
if (this.client !== undefined)
|
|
24
|
+
return;
|
|
25
|
+
if (this.starting !== undefined)
|
|
26
|
+
return this.starting;
|
|
27
|
+
const starting = this.startServer();
|
|
28
|
+
this.starting = starting;
|
|
29
|
+
try {
|
|
30
|
+
await starting;
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
if (this.starting === starting)
|
|
34
|
+
this.starting = undefined;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async startServer() {
|
|
38
|
+
const port = await availablePort();
|
|
39
|
+
const password = randomBytes(24).toString('base64url');
|
|
40
|
+
const invocation = platformCliInvocation(this.options.command ?? 'opencode', [
|
|
41
|
+
'serve',
|
|
42
|
+
'--hostname',
|
|
43
|
+
'127.0.0.1',
|
|
44
|
+
'--port',
|
|
45
|
+
String(port)
|
|
46
|
+
]);
|
|
47
|
+
const spawnProcess = this.options.spawnProcess ?? spawn;
|
|
48
|
+
const child = spawnProcess(invocation.command, invocation.args, {
|
|
49
|
+
windowsHide: true,
|
|
50
|
+
detached: process.platform !== 'win32',
|
|
51
|
+
env: {
|
|
52
|
+
...minimalRunnerEnvironment(),
|
|
53
|
+
...this.environment,
|
|
54
|
+
OPENCODE_SERVER_USERNAME: 'opencode',
|
|
55
|
+
OPENCODE_SERVER_PASSWORD: password,
|
|
56
|
+
OPENCODE_DISABLE_AUTOUPDATE: 'true'
|
|
57
|
+
},
|
|
58
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
59
|
+
});
|
|
60
|
+
this.child = child;
|
|
61
|
+
const authorization = `Basic ${Buffer.from(`opencode:${password}`).toString('base64')}`;
|
|
62
|
+
const client = createOpencodeClient({
|
|
63
|
+
baseUrl: `http://127.0.0.1:${port}`,
|
|
64
|
+
headers: { authorization },
|
|
65
|
+
throwOnError: true
|
|
66
|
+
});
|
|
67
|
+
try {
|
|
68
|
+
await waitUntilHealthy(`http://127.0.0.1:${port}/global/health`, authorization, child, this.options.startTimeoutMs ?? START_TIMEOUT_MS);
|
|
69
|
+
this.client = client;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
await this.stop();
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async providers(directory) {
|
|
77
|
+
const client = await this.requireClient();
|
|
78
|
+
return unwrap(await client.provider.list({ directory }));
|
|
79
|
+
}
|
|
80
|
+
async sessions(directory, limit = 100) {
|
|
81
|
+
const client = await this.requireClient();
|
|
82
|
+
return unwrap(await client.session.list({ directory, limit }));
|
|
83
|
+
}
|
|
84
|
+
async sessionStatus(directory) {
|
|
85
|
+
const client = await this.requireClient();
|
|
86
|
+
return unwrap(await client.session.status({ directory }));
|
|
87
|
+
}
|
|
88
|
+
async createSession(directory, title) {
|
|
89
|
+
const client = await this.requireClient();
|
|
90
|
+
return unwrap(await client.session.create({ directory, ...(title === undefined ? {} : { title }) }));
|
|
91
|
+
}
|
|
92
|
+
async forkSession(directory, sessionID, messageID) {
|
|
93
|
+
const client = await this.requireClient();
|
|
94
|
+
return unwrap(await client.session.fork({ directory, sessionID, messageID }));
|
|
95
|
+
}
|
|
96
|
+
async messages(directory, sessionID, limit = 100) {
|
|
97
|
+
const client = await this.requireClient();
|
|
98
|
+
return unwrap(await client.session.messages({ directory, sessionID, limit }));
|
|
99
|
+
}
|
|
100
|
+
async updateSession(directory, sessionID, title) {
|
|
101
|
+
const client = await this.requireClient();
|
|
102
|
+
return unwrap(await client.session.update({ directory, sessionID, title }));
|
|
103
|
+
}
|
|
104
|
+
async deleteSession(directory, sessionID) {
|
|
105
|
+
const client = await this.requireClient();
|
|
106
|
+
return unwrap(await client.session.delete({ directory, sessionID }));
|
|
107
|
+
}
|
|
108
|
+
async abort(directory, sessionID) {
|
|
109
|
+
const client = await this.requireClient();
|
|
110
|
+
return unwrap(await client.session.abort({ directory, sessionID }));
|
|
111
|
+
}
|
|
112
|
+
async summarize(directory, sessionID, model) {
|
|
113
|
+
const client = await this.requireClient();
|
|
114
|
+
const separator = model.indexOf('/');
|
|
115
|
+
if (separator <= 0 || separator === model.length - 1)
|
|
116
|
+
throw new Error('OPENCODE_MODEL_INVALID');
|
|
117
|
+
return unwrap(await client.session.summarize({
|
|
118
|
+
directory,
|
|
119
|
+
sessionID,
|
|
120
|
+
providerID: model.slice(0, separator),
|
|
121
|
+
modelID: model.slice(separator + 1)
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
async replyPermission(directory, requestID, decision) {
|
|
125
|
+
const client = await this.requireClient();
|
|
126
|
+
return unwrap(await client.permission.reply({
|
|
127
|
+
directory,
|
|
128
|
+
requestID,
|
|
129
|
+
reply: decision === 'APPROVED' ? 'once' : 'reject'
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
async replyQuestion(directory, requestID, answers) {
|
|
133
|
+
const client = await this.requireClient();
|
|
134
|
+
return unwrap(await client.question.reply({
|
|
135
|
+
directory,
|
|
136
|
+
requestID,
|
|
137
|
+
answers: answers.map((answer) => [...answer])
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
async rejectQuestion(directory, requestID) {
|
|
141
|
+
const client = await this.requireClient();
|
|
142
|
+
return unwrap(await client.question.reject({ directory, requestID }));
|
|
143
|
+
}
|
|
144
|
+
async prompt(input) {
|
|
145
|
+
const client = await this.requireClient();
|
|
146
|
+
const separator = input.model.indexOf('/');
|
|
147
|
+
if (separator <= 0 || separator === input.model.length - 1)
|
|
148
|
+
throw new Error('OPENCODE_MODEL_INVALID');
|
|
149
|
+
return unwrap(await client.session.promptAsync({
|
|
150
|
+
directory: input.directory,
|
|
151
|
+
sessionID: input.sessionID,
|
|
152
|
+
model: {
|
|
153
|
+
providerID: input.model.slice(0, separator),
|
|
154
|
+
modelID: input.model.slice(separator + 1)
|
|
155
|
+
},
|
|
156
|
+
...(input.variant === undefined || input.variant.length === 0
|
|
157
|
+
? {}
|
|
158
|
+
: { variant: input.variant }),
|
|
159
|
+
...(input.agent === undefined ? {} : { agent: input.agent }),
|
|
160
|
+
parts: [
|
|
161
|
+
{ type: 'text', text: input.text },
|
|
162
|
+
...(input.attachments ?? []).map((attachment) => ({
|
|
163
|
+
type: 'file',
|
|
164
|
+
mime: attachment.mime,
|
|
165
|
+
filename: attachment.name,
|
|
166
|
+
url: `data:${attachment.mime};base64,${attachment.dataBase64}`
|
|
167
|
+
}))
|
|
168
|
+
]
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
async subscribe(directory, signal, onEvent, onReady) {
|
|
172
|
+
const client = await this.requireClient();
|
|
173
|
+
const stream = await client.event.subscribe({ directory }, { signal });
|
|
174
|
+
onReady?.();
|
|
175
|
+
for await (const event of stream.stream)
|
|
176
|
+
onEvent(event);
|
|
177
|
+
}
|
|
178
|
+
async stop() {
|
|
179
|
+
this.client = undefined;
|
|
180
|
+
const child = this.child;
|
|
181
|
+
this.child = undefined;
|
|
182
|
+
if (child === undefined)
|
|
183
|
+
return;
|
|
184
|
+
if (child.pid === undefined) {
|
|
185
|
+
child.kill('SIGTERM');
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
await terminateProcessTree({
|
|
190
|
+
pid: child.pid,
|
|
191
|
+
kill: (signal) => child.kill(signal)
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
child.kill('SIGTERM');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
async requireClient() {
|
|
199
|
+
await this.start();
|
|
200
|
+
return this.client;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async function availablePort() {
|
|
204
|
+
return new Promise((resolve, reject) => {
|
|
205
|
+
const server = createServer();
|
|
206
|
+
server.once('error', reject);
|
|
207
|
+
server.listen(0, '127.0.0.1', () => {
|
|
208
|
+
const address = server.address();
|
|
209
|
+
const port = typeof address === 'object' && address !== null ? address.port : undefined;
|
|
210
|
+
server.close((error) => {
|
|
211
|
+
if (error !== undefined)
|
|
212
|
+
reject(error);
|
|
213
|
+
else if (port === undefined)
|
|
214
|
+
reject(new Error('OPENCODE_PORT_UNAVAILABLE'));
|
|
215
|
+
else
|
|
216
|
+
resolve(port);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
async function waitUntilHealthy(url, authorization, child, timeoutMs) {
|
|
222
|
+
const deadline = Date.now() + timeoutMs;
|
|
223
|
+
while (Date.now() < deadline) {
|
|
224
|
+
if (child.exitCode !== null)
|
|
225
|
+
throw new Error('OPENCODE_SERVER_EXITED');
|
|
226
|
+
try {
|
|
227
|
+
const response = await fetch(url, {
|
|
228
|
+
headers: { authorization },
|
|
229
|
+
signal: AbortSignal.timeout(Math.min(1_000, Math.max(1, deadline - Date.now())))
|
|
230
|
+
});
|
|
231
|
+
if (response.ok)
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
// The child may still be binding its loopback socket.
|
|
236
|
+
}
|
|
237
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
238
|
+
}
|
|
239
|
+
throw new Error('OPENCODE_SERVER_START_TIMEOUT');
|
|
240
|
+
}
|
|
241
|
+
function unwrap(result) {
|
|
242
|
+
if (typeof result !== 'object' || result === null || !('data' in result))
|
|
243
|
+
return result;
|
|
244
|
+
const wrapped = result;
|
|
245
|
+
if (wrapped.error !== undefined)
|
|
246
|
+
throw new Error('OPENCODE_REQUEST_FAILED');
|
|
247
|
+
if (wrapped.data === undefined)
|
|
248
|
+
throw new Error('OPENCODE_RESPONSE_INVALID');
|
|
249
|
+
return wrapped.data;
|
|
250
|
+
}
|
package/dist/operational.js
CHANGED
|
@@ -101,12 +101,19 @@ export function platformCliInvocation(command, args, platform = process.platform
|
|
|
101
101
|
const cliCommand = platformCliCommand(command, platform);
|
|
102
102
|
if (platform !== 'win32' || !/\.(?:cmd|bat)$/i.test(cliCommand))
|
|
103
103
|
return { command: cliCommand, args };
|
|
104
|
-
if (![cliCommand, ...args].every((value) => /^[A-Za-z0-9_
|
|
104
|
+
if (![cliCommand, ...args].every((value) => /^[A-Za-z0-9_@./:\\ -]+$/.test(value)))
|
|
105
105
|
throw new Error('NODE_CLI_COMMAND_INVALID');
|
|
106
|
-
return {
|
|
106
|
+
return {
|
|
107
|
+
command: comspec,
|
|
108
|
+
args: [
|
|
109
|
+
'/d',
|
|
110
|
+
'/s',
|
|
111
|
+
'/c',
|
|
112
|
+
[cliCommand, ...args].map((value) => (value.includes(' ') ? `"${value}"` : value)).join(' ')
|
|
113
|
+
]
|
|
114
|
+
};
|
|
107
115
|
}
|
|
108
116
|
export function nodeLog(event, fields = {}) {
|
|
109
117
|
const safeFields = redactLogValue(fields);
|
|
110
118
|
process.stdout.write(`${JSON.stringify({ timestamp: new Date().toISOString(), level: 'info', component: 'mar-node', event, ...safeFields })}\n`);
|
|
111
119
|
}
|
|
112
|
-
//# sourceMappingURL=operational.js.map
|
package/dist/process-tree.js
CHANGED