neoctl 0.1.17 → 0.1.19

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 (121) hide show
  1. package/dist/agents/local-agent-task.js +1 -2
  2. package/dist/agents/local-agent-task.js.map +1 -1
  3. package/dist/agents/smoke-agents.js +4 -21
  4. package/dist/agents/smoke-agents.js.map +1 -1
  5. package/dist/context/prompts.js +0 -4
  6. package/dist/context/prompts.js.map +1 -1
  7. package/dist/core/query-engine.d.ts +1 -22
  8. package/dist/core/query-engine.js +12 -106
  9. package/dist/core/query-engine.js.map +1 -1
  10. package/dist/core/query.d.ts +1 -2
  11. package/dist/core/query.js +5 -59
  12. package/dist/core/query.js.map +1 -1
  13. package/dist/core/smoke-core-loop.js +6 -95
  14. package/dist/core/smoke-core-loop.js.map +1 -1
  15. package/dist/index.d.ts +1 -25
  16. package/dist/index.js +1 -25
  17. package/dist/index.js.map +1 -1
  18. package/dist/model/communication-logger.d.ts +1 -2
  19. package/dist/model/communication-logger.js +0 -3
  20. package/dist/model/communication-logger.js.map +1 -1
  21. package/dist/model/config.d.ts +4 -10
  22. package/dist/model/config.js +12 -61
  23. package/dist/model/config.js.map +1 -1
  24. package/dist/model/context-window.js +0 -1
  25. package/dist/model/context-window.js.map +1 -1
  26. package/dist/model/env.js +19 -35
  27. package/dist/model/env.js.map +1 -1
  28. package/dist/model/model-metadata.json +677 -726
  29. package/dist/model/openai-adapter.d.ts +1 -1
  30. package/dist/model/openai-chat-mapper.d.ts +1 -4
  31. package/dist/model/openai-chat-mapper.js +8 -30
  32. package/dist/model/openai-chat-mapper.js.map +1 -1
  33. package/dist/model/openai-mappers.d.ts +2 -5
  34. package/dist/model/openai-mappers.js +4 -17
  35. package/dist/model/openai-mappers.js.map +1 -1
  36. package/dist/model/openai-responses-mapper.d.ts +1 -1
  37. package/dist/model/openai-responses-mapper.js +1 -2
  38. package/dist/model/openai-responses-mapper.js.map +1 -1
  39. package/dist/model/provider-factory.js +0 -32
  40. package/dist/model/provider-factory.js.map +1 -1
  41. package/dist/model/smoke-openai.js +1 -1
  42. package/dist/model/smoke-openai.js.map +1 -1
  43. package/dist/model/smoke-responses-mapper.js +6 -6
  44. package/dist/model/smoke-responses-mapper.js.map +1 -1
  45. package/dist/repl/commands.d.ts +0 -15
  46. package/dist/repl/commands.js +0 -58
  47. package/dist/repl/commands.js.map +1 -1
  48. package/dist/repl/index.js +144 -970
  49. package/dist/repl/index.js.map +1 -1
  50. package/dist/repl/render.js +2 -0
  51. package/dist/repl/render.js.map +1 -1
  52. package/dist/repl/status-line.d.ts +1 -0
  53. package/dist/repl/status-line.js +34 -27
  54. package/dist/repl/status-line.js.map +1 -1
  55. package/dist/session/session-store.js +2 -2
  56. package/dist/session/session-store.js.map +1 -1
  57. package/dist/session/smoke-session.js +1 -22
  58. package/dist/session/smoke-session.js.map +1 -1
  59. package/dist/skills/skill-tool.d.ts +5 -85
  60. package/dist/skills/skill-tool.js +14 -173
  61. package/dist/skills/skill-tool.js.map +1 -1
  62. package/dist/skills/smoke-skills.js +5 -54
  63. package/dist/skills/smoke-skills.js.map +1 -1
  64. package/dist/tools/builtins/search-providers.d.ts +1 -15
  65. package/dist/tools/builtins/search-providers.js +1 -195
  66. package/dist/tools/builtins/search-providers.js.map +1 -1
  67. package/dist/tools/builtins/search-tool.js +2 -2
  68. package/dist/tools/builtins/search-tool.js.map +1 -1
  69. package/dist/tools/registry.d.ts +0 -1
  70. package/dist/tools/registry.js +0 -11
  71. package/dist/tools/registry.js.map +1 -1
  72. package/dist/tools/run-tool-use.js +1 -1
  73. package/dist/tools/run-tool-use.js.map +1 -1
  74. package/dist/tools/smoke-tool-system.js +9 -43
  75. package/dist/tools/smoke-tool-system.js.map +1 -1
  76. package/dist/tools/tool.d.ts +1 -9
  77. package/dist/tools/tool.js.map +1 -1
  78. package/package.json +1 -1
  79. package/scripts/build-standalone.mjs +139 -139
  80. package/dist/model/deepseek-adapter.d.ts +0 -29
  81. package/dist/model/deepseek-adapter.js +0 -108
  82. package/dist/model/deepseek-adapter.js.map +0 -1
  83. package/dist/model/kimi-adapter.d.ts +0 -29
  84. package/dist/model/kimi-adapter.js +0 -108
  85. package/dist/model/kimi-adapter.js.map +0 -1
  86. package/dist/model/smoke-deepseek-mapper.d.ts +0 -1
  87. package/dist/model/smoke-deepseek-mapper.js +0 -65
  88. package/dist/model/smoke-deepseek-mapper.js.map +0 -1
  89. package/dist/open-directory.d.ts +0 -1
  90. package/dist/open-directory.js +0 -26
  91. package/dist/open-directory.js.map +0 -1
  92. package/dist/paths.d.ts +0 -7
  93. package/dist/paths.js +0 -12
  94. package/dist/paths.js.map +0 -1
  95. package/dist/session/session-export.d.ts +0 -33
  96. package/dist/session/session-export.js +0 -351
  97. package/dist/session/session-export.js.map +0 -1
  98. package/dist/session/simple-session-runtime.d.ts +0 -74
  99. package/dist/session/simple-session-runtime.js +0 -171
  100. package/dist/session/simple-session-runtime.js.map +0 -1
  101. package/dist/skills/skill-filesystem.d.ts +0 -32
  102. package/dist/skills/skill-filesystem.js +0 -371
  103. package/dist/skills/skill-filesystem.js.map +0 -1
  104. package/dist/skills/skill-management-tools.d.ts +0 -36
  105. package/dist/skills/skill-management-tools.js +0 -188
  106. package/dist/skills/skill-management-tools.js.map +0 -1
  107. package/dist/tips.d.ts +0 -10
  108. package/dist/tips.js +0 -168
  109. package/dist/tips.js.map +0 -1
  110. package/dist/tools/builtins/image-generation-tool.d.ts +0 -68
  111. package/dist/tools/builtins/image-generation-tool.js +0 -315
  112. package/dist/tools/builtins/image-generation-tool.js.map +0 -1
  113. package/dist/ui/display-message.d.ts +0 -101
  114. package/dist/ui/display-message.js +0 -113
  115. package/dist/ui/display-message.js.map +0 -1
  116. package/dist/web/html.d.ts +0 -1
  117. package/dist/web/html.js +0 -858
  118. package/dist/web/html.js.map +0 -1
  119. package/dist/web/index.d.ts +0 -2
  120. package/dist/web/index.js +0 -1810
  121. package/dist/web/index.js.map +0 -1
@@ -1,108 +0,0 @@
1
- import { EnvCredentialProvider, StaticCredentialProvider } from "./credentials.js";
2
- import { ModelAPIError } from "./errors.js";
3
- import { HttpTransport } from "./http-transport.js";
4
- import { supportsImageInput } from "./context-window.js";
5
- import { streamWithRetry } from "./retry-runner.js";
6
- import { buildChatRequest, normalizeChatObject, normalizeChatStream } from "./openai-chat-mapper.js";
7
- export class KimiAdapter {
8
- options;
9
- name = "kimi";
10
- capabilities = {
11
- streaming: true,
12
- functionTools: true,
13
- parallelToolCalls: false,
14
- structuredOutput: false,
15
- previousResponseId: false,
16
- imageInput: true,
17
- fileInput: false,
18
- reasoningConfig: true,
19
- builtInTools: false,
20
- };
21
- credentialProvider;
22
- transport = new HttpTransport(this.name);
23
- baseUrl;
24
- constructor(options) {
25
- this.options = options;
26
- this.credentialProvider =
27
- options.credentialProvider ??
28
- (options.apiKey ? new StaticCredentialProvider(options.apiKey) : new EnvCredentialProvider(options.apiKeyEnvName ?? "KIMI_API_KEY"));
29
- this.baseUrl = stripTrailingSlash(options.baseUrl ?? "https://api.moonshot.cn/v1");
30
- }
31
- async *stream(request) {
32
- this.assertRequestCapabilities(request);
33
- yield* streamWithRetry((attempt) => this.streamChat(request, attempt), {
34
- provider: this.name,
35
- maxRetries: this.options.maxRetries ?? 2,
36
- delayMs: 3000,
37
- });
38
- }
39
- async *streamChat(request, attempt) {
40
- const body = buildChatRequest(request, {
41
- ...this.options,
42
- includeMetadata: false,
43
- includeReasoningContent: true,
44
- });
45
- const headers = await this.authHeaders();
46
- const timeoutMs = request.timeoutMs ?? this.options.timeoutMs ?? 120000;
47
- if (attempt > 0)
48
- yield { type: "provider_event", event: { type: "kimi_retry_attempt", attempt } };
49
- if (request.stream !== false) {
50
- const streamOptions = body.stream_options && typeof body.stream_options === "object"
51
- ? body.stream_options
52
- : {};
53
- const response = await this.transport.sendStream({
54
- method: "POST",
55
- url: `${this.baseUrl}/chat/completions`,
56
- headers,
57
- body: { ...body, stream: true, stream_options: { include_usage: true, ...streamOptions } },
58
- timeoutMs,
59
- signal: request.cancellation,
60
- });
61
- yield* normalizeChatStream(response.body, { ...this.options, includeReasoningContent: true, providerName: this.name });
62
- return;
63
- }
64
- const response = await this.transport.sendJson({
65
- method: "POST",
66
- url: `${this.baseUrl}/chat/completions`,
67
- headers,
68
- body: { ...body, stream: false },
69
- timeoutMs,
70
- signal: request.cancellation,
71
- });
72
- yield* normalizeChatObject(response);
73
- }
74
- assertRequestCapabilities(request) {
75
- const model = request.model ?? this.options.model;
76
- const supported = supportsImageInput(model);
77
- if (supported === false && hasImageInput(request)) {
78
- throw new ModelAPIError({
79
- category: "unsupported_image_input",
80
- provider: this.name,
81
- message: `Model ${model} does not support image input according to static model metadata`,
82
- retryable: false,
83
- });
84
- }
85
- }
86
- async authHeaders() {
87
- const credential = await this.credentialProvider.getCredential();
88
- if (!credential) {
89
- throw new ModelAPIError({
90
- category: "auth_unavailable",
91
- provider: this.name,
92
- message: "Kimi API key is not configured",
93
- retryable: false,
94
- });
95
- }
96
- return { Authorization: `Bearer ${credential}` };
97
- }
98
- }
99
- function hasImageInput(request) {
100
- return request.messages.some((message) => message.blocks.some((block) => {
101
- const type = block.type;
102
- return type === "image" || type === "input_image" || (block.type === "text" && /!\[[^\]]*\]\([^\)]+\)/.test(block.text));
103
- }));
104
- }
105
- function stripTrailingSlash(value) {
106
- return value.replace(/\/+$/, "");
107
- }
108
- //# sourceMappingURL=kimi-adapter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kimi-adapter.js","sourceRoot":"","sources":["../../src/model/kimi-adapter.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export {};
@@ -1,65 +0,0 @@
1
- import { createTextMessage } from "../types/messages.js";
2
- import { buildChatRequest, normalizeChatStream } from "./openai-chat-mapper.js";
3
- async function main() {
4
- const request = buildChatRequest({
5
- model: "deepseek-reasoner",
6
- instructions: "Be brief.",
7
- messages: [createTextMessage("user", "Say pong")],
8
- tools: [],
9
- stream: true,
10
- reasoning: { effort: "high" },
11
- maxOutputTokens: 16,
12
- }, {
13
- model: "deepseek-chat",
14
- defaultMaxOutputTokens: 800,
15
- includeMetadata: false,
16
- includeReasoningContent: true,
17
- });
18
- assertEqual(request.model, "deepseek-reasoner", "model override");
19
- assertDeepEqual(request.thinking, { type: "enabled" }, "deepseek thinking option");
20
- assertEqual(request.reasoning_effort, "high", "reasoning effort");
21
- assertEqual("metadata" in request, false, "metadata omitted for deepseek");
22
- const stream = sseStream([
23
- { id: "chatcmpl_1", choices: [{ delta: { reasoning_content: "think" } }] },
24
- { id: "chatcmpl_1", choices: [{ delta: { content: "pong" } }] },
25
- { id: "chatcmpl_1", choices: [{ finish_reason: "stop", delta: {} }], usage: { prompt_tokens: 2, completion_tokens: 3, total_tokens: 5 } },
26
- ]);
27
- const events = [];
28
- events.push(...await collect(normalizeChatStream(stream, { model: "deepseek-reasoner", includeReasoningContent: true })));
29
- assertEqual(events.some((event) => event.type === "thinking_delta" && event.text === "think"), true, "thinking delta emitted");
30
- assertEqual(events.some((event) => event.type === "assistant_delta" && event.text === "pong"), true, "assistant delta emitted");
31
- assertEqual(events.some((event) => event.type === "assistant_message" && event.message.blocks.some((block) => block.type === "thinking" && block.text === "think")), true, "thinking message emitted");
32
- assertEqual(events.some((event) => event.type === "response_completed" && event.usage?.totalTokens === 5), true, "usage normalized");
33
- console.log(JSON.stringify({ ok: true, events: events.map((event) => event.type) }, null, 2));
34
- }
35
- async function collect(iterable) {
36
- const items = [];
37
- for await (const item of iterable)
38
- items.push(item);
39
- return items;
40
- }
41
- function sseStream(events) {
42
- const encoder = new TextEncoder();
43
- const chunks = events.map((event) => `data: ${JSON.stringify(event)}\n\n`).join("") + "data: [DONE]\n\n";
44
- return new ReadableStream({
45
- start(controller) {
46
- controller.enqueue(encoder.encode(chunks));
47
- controller.close();
48
- },
49
- });
50
- }
51
- function assertEqual(actual, expected, label) {
52
- if (actual !== expected)
53
- throw new Error(`${label}: expected ${String(expected)}, got ${String(actual)}`);
54
- }
55
- function assertDeepEqual(actual, expected, label) {
56
- const actualJson = JSON.stringify(actual);
57
- const expectedJson = JSON.stringify(expected);
58
- if (actualJson !== expectedJson)
59
- throw new Error(`${label}: expected ${expectedJson}, got ${actualJson}`);
60
- }
61
- main().catch((error) => {
62
- console.error(error instanceof Error ? error.stack ?? error.message : String(error));
63
- process.exitCode = 1;
64
- });
65
- //# sourceMappingURL=smoke-deepseek-mapper.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"smoke-deepseek-mapper.js","sourceRoot":"","sources":["../../src/model/smoke-deepseek-mapper.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- export declare function openDirectory(directory: string): Promise<void>;
@@ -1,26 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- export async function openDirectory(directory) {
3
- const opener = directoryOpener(directory);
4
- await new Promise((resolve, reject) => {
5
- const child = spawn(opener.command, opener.args, {
6
- stdio: "ignore",
7
- windowsHide: true,
8
- });
9
- child.once("error", reject);
10
- child.once("close", (code) => {
11
- if (code === 0) {
12
- resolve();
13
- return;
14
- }
15
- reject(new Error(`${opener.command} exited with code ${code ?? "unknown"}`));
16
- });
17
- });
18
- }
19
- function directoryOpener(directory) {
20
- if (process.platform === "win32")
21
- return { command: "cmd", args: ["/d", "/c", "start", "", directory] };
22
- if (process.platform === "darwin")
23
- return { command: "open", args: [directory] };
24
- return { command: "xdg-open", args: [directory] };
25
- }
26
- //# sourceMappingURL=open-directory.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"open-directory.js","sourceRoot":"","sources":["../src/open-directory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,SAAiB;IACnD,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE;YAC/C,KAAK,EAAE,QAAQ;YACf,WAAW,EAAE,IAAI;SAClB,CAAC,CAAC;QAEH,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YAC3B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO;YACT,CAAC;YACD,MAAM,CAAC,IAAI,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,qBAAqB,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC;QAC/E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,SAAiB;IACxC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC;IACxG,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;IACjF,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;AACpD,CAAC"}
package/dist/paths.d.ts DELETED
@@ -1,7 +0,0 @@
1
- /**
2
- * Returns the neoctl user home directory.
3
- *
4
- * - Windows: `%USERPROFILE%\.neoctl` (e.g. `C:\Users\<user>\.neoctl`)
5
- * - Linux / macOS: `~/.neoctl`
6
- */
7
- export declare function getNeoctlHome(): string;
package/dist/paths.js DELETED
@@ -1,12 +0,0 @@
1
- import { homedir } from "node:os";
2
- import { resolve } from "node:path";
3
- /**
4
- * Returns the neoctl user home directory.
5
- *
6
- * - Windows: `%USERPROFILE%\.neoctl` (e.g. `C:\Users\<user>\.neoctl`)
7
- * - Linux / macOS: `~/.neoctl`
8
- */
9
- export function getNeoctlHome() {
10
- return resolve(homedir(), ".neoctl");
11
- }
12
- //# sourceMappingURL=paths.js.map
package/dist/paths.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AACvC,CAAC"}
@@ -1,33 +0,0 @@
1
- import type { SessionStoreSnapshot } from "./session-store.js";
2
- export interface SessionPromptExportSnapshot {
3
- model?: string;
4
- fallbackModel?: string;
5
- reasoning?: unknown;
6
- systemPrompt?: string;
7
- baseSystemPrompt?: string;
8
- promptSections?: unknown;
9
- userContext?: unknown;
10
- systemContext?: unknown;
11
- userContextPrompt?: string;
12
- toolDefinitions?: unknown;
13
- commands?: readonly string[];
14
- agents?: readonly string[];
15
- skills?: readonly string[];
16
- plugins?: readonly string[];
17
- }
18
- export interface SessionMarkdownExportOptions {
19
- outputPath: string;
20
- session: SessionStoreSnapshot;
21
- agentId?: string;
22
- promptSnapshot?: SessionPromptExportSnapshot;
23
- engineSnapshot?: unknown;
24
- exportedAt?: string;
25
- maxToolResultLines?: number;
26
- }
27
- export interface SessionMarkdownExportResult {
28
- outputPath: string;
29
- bytes: number;
30
- entries: number;
31
- messages: number;
32
- }
33
- export declare function writeSessionMarkdownExport(options: SessionMarkdownExportOptions): Promise<SessionMarkdownExportResult>;
@@ -1,351 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
- import { PERSISTED_OUTPUT_TAG } from "./tool-result-memory.js";
4
- const DEFAULT_MAX_TOOL_RESULT_LINES = 500;
5
- export async function writeSessionMarkdownExport(options) {
6
- const outputPath = normalizeOutputPath(options.outputPath);
7
- const entries = await readTranscriptEntries(options.session.transcriptPath);
8
- const markdown = await renderSessionMarkdown({
9
- ...options,
10
- outputPath,
11
- entries,
12
- exportedAt: options.exportedAt ?? new Date().toISOString(),
13
- maxToolResultLines: options.maxToolResultLines ?? DEFAULT_MAX_TOOL_RESULT_LINES,
14
- });
15
- await ensureOutputParentDirectory(outputPath);
16
- await fs.writeFile(outputPath, markdown, "utf8");
17
- const stat = await fs.stat(outputPath);
18
- return {
19
- outputPath,
20
- bytes: stat.size,
21
- entries: entries.length,
22
- messages: entries.filter((line) => line.ok && line.entry.type === "message").length,
23
- };
24
- }
25
- function normalizeOutputPath(rawPath) {
26
- const unquoted = stripSurroundingQuotes(rawPath.trim());
27
- if (!unquoted)
28
- throw new Error("/export requires an absolute markdown file path");
29
- if (!path.isAbsolute(unquoted))
30
- throw new Error(`/export requires an absolute path: ${rawPath}`);
31
- return path.resolve(unquoted);
32
- }
33
- function stripSurroundingQuotes(value) {
34
- if (value.length >= 2) {
35
- const first = value[0];
36
- const last = value[value.length - 1];
37
- if ((first === '"' && last === '"') || (first === "'" && last === "'"))
38
- return value.slice(1, -1);
39
- }
40
- return value;
41
- }
42
- async function ensureOutputParentDirectory(outputPath) {
43
- const directory = path.dirname(outputPath);
44
- const parsed = path.parse(outputPath);
45
- if (directory === parsed.root)
46
- return;
47
- await fs.mkdir(directory, { recursive: true });
48
- }
49
- async function readTranscriptEntries(transcriptPath) {
50
- const text = await fs.readFile(transcriptPath, "utf8");
51
- const entries = [];
52
- const lines = text.split(/\r?\n/);
53
- for (let index = 0; index < lines.length; index += 1) {
54
- const raw = lines[index];
55
- if (!raw.trim())
56
- continue;
57
- try {
58
- entries.push({ lineNumber: index + 1, ok: true, entry: JSON.parse(raw) });
59
- }
60
- catch (error) {
61
- entries.push({
62
- lineNumber: index + 1,
63
- ok: false,
64
- raw,
65
- error: error instanceof Error ? error.message : String(error),
66
- });
67
- }
68
- }
69
- return entries;
70
- }
71
- async function renderSessionMarkdown(input) {
72
- const lines = [];
73
- const title = input.session.title ? ` — ${input.session.title}` : "";
74
- lines.push(`# Neo Session Export${title}`);
75
- lines.push("");
76
- lines.push("## Export Metadata");
77
- lines.push(`- Exported at: ${input.exportedAt}`);
78
- lines.push(`- Agent: ${input.agentId ?? "<unknown>"}`);
79
- lines.push(`- Session ID: ${input.session.sessionId}`);
80
- if (input.session.title)
81
- lines.push(`- Session title: ${input.session.title}`);
82
- if (input.session.titleKind)
83
- lines.push(`- Session title kind: ${input.session.titleKind}`);
84
- lines.push(`- Session directory: ${inlineCode(input.session.sessionDir)}`);
85
- lines.push(`- Transcript: ${inlineCode(input.session.transcriptPath)}`);
86
- lines.push(`- Export file: ${inlineCode(input.outputPath)}`);
87
- lines.push(`- Transcript entries: ${input.entries.length}`);
88
- lines.push(`- Messages: ${input.entries.filter((line) => line.ok && line.entry.type === "message").length}`);
89
- lines.push(`- Tool result display cap: ${input.maxToolResultLines} lines per tool result`);
90
- lines.push("");
91
- renderPromptSnapshot(lines, input.promptSnapshot);
92
- renderJsonSection(lines, "Engine Snapshot", input.engineSnapshot);
93
- lines.push("---");
94
- lines.push("");
95
- lines.push("## Transcript");
96
- lines.push("");
97
- for (let index = 0; index < input.entries.length; index += 1) {
98
- const line = input.entries[index];
99
- lines.push("---");
100
- lines.push("");
101
- lines.push(`## Entry ${index + 1} (transcript line ${line.lineNumber})`);
102
- lines.push("");
103
- if (!line.ok) {
104
- lines.push("- Type: malformed JSONL entry");
105
- lines.push(`- Error: ${line.error}`);
106
- lines.push("");
107
- lines.push(fenced(line.raw, "json"));
108
- lines.push("");
109
- continue;
110
- }
111
- await renderTranscriptEntry(lines, line.entry, input.session.sessionDir, input.maxToolResultLines);
112
- }
113
- return `${lines.join("\n").replace(/[ \t]+$/gm, "")}\n`;
114
- }
115
- function renderPromptSnapshot(lines, snapshot) {
116
- lines.push("## Prompt Context Snapshot");
117
- lines.push("");
118
- if (!snapshot) {
119
- lines.push("No prompt context snapshot was available at export time.");
120
- lines.push("");
121
- return;
122
- }
123
- lines.push("### Model Settings");
124
- lines.push(`- Model: ${snapshot.model ?? "<default>"}`);
125
- lines.push(`- Fallback model: ${snapshot.fallbackModel ?? "<none>"}`);
126
- lines.push(`- Reasoning: ${formatInlineValue(snapshot.reasoning ?? "<default>")}`);
127
- lines.push("");
128
- if (snapshot.systemPrompt !== undefined) {
129
- lines.push("### Effective System Prompt");
130
- lines.push("");
131
- lines.push(fenced(snapshot.systemPrompt, "text"));
132
- lines.push("");
133
- }
134
- if (snapshot.baseSystemPrompt !== undefined && snapshot.baseSystemPrompt !== snapshot.systemPrompt) {
135
- lines.push("### Base System Prompt (before runtime system context)");
136
- lines.push("");
137
- lines.push(fenced(snapshot.baseSystemPrompt, "text"));
138
- lines.push("");
139
- }
140
- if (snapshot.userContextPrompt !== undefined) {
141
- lines.push("### Injected User Context Prompt");
142
- lines.push("");
143
- lines.push(fenced(snapshot.userContextPrompt, "text"));
144
- lines.push("");
145
- }
146
- renderJsonSection(lines, "Prompt Sections", snapshot.promptSections);
147
- renderJsonSection(lines, "System Context", snapshot.systemContext);
148
- renderJsonSection(lines, "User Context", snapshot.userContext);
149
- renderJsonSection(lines, "Tool Definitions", snapshot.toolDefinitions);
150
- renderJsonSection(lines, "REPL Commands", snapshot.commands);
151
- renderJsonSection(lines, "Agents", snapshot.agents);
152
- renderJsonSection(lines, "Skills", snapshot.skills);
153
- renderJsonSection(lines, "Plugins", snapshot.plugins);
154
- }
155
- function renderJsonSection(lines, title, value) {
156
- if (value === undefined)
157
- return;
158
- lines.push(`### ${title}`);
159
- lines.push("");
160
- lines.push(fenced(stableStringify(value), "json"));
161
- lines.push("");
162
- }
163
- async function renderTranscriptEntry(lines, entry, sessionDir, maxToolResultLines) {
164
- lines.push(`- Type: ${entry.type}`);
165
- lines.push(`- Agent: ${"agentId" in entry ? entry.agentId : "<unknown>"}`);
166
- lines.push(`- Session: ${"sessionId" in entry ? entry.sessionId : "<unknown>"}`);
167
- if (entry.type === "message") {
168
- renderMessageHeader(lines, entry.message);
169
- for (let index = 0; index < entry.message.blocks.length; index += 1) {
170
- await renderMessageBlock(lines, entry.message.blocks[index], index + 1, sessionDir, maxToolResultLines);
171
- }
172
- return;
173
- }
174
- if (entry.type === "content-replacement") {
175
- lines.push("");
176
- lines.push("### Content Replacements");
177
- lines.push("");
178
- lines.push(fenced(stableStringify(entry.replacements), "json"));
179
- lines.push("");
180
- return;
181
- }
182
- if (entry.type === "title") {
183
- lines.push(`- Created at: ${entry.createdAt}`);
184
- lines.push(`- Kind: ${entry.kind ?? "initial"}`);
185
- lines.push(`- Title: ${entry.title}`);
186
- lines.push("");
187
- return;
188
- }
189
- if (entry.type === "compact" || entry.type === "reset") {
190
- lines.push(`- Created at: ${entry.createdAt}`);
191
- lines.push("");
192
- }
193
- }
194
- function renderMessageHeader(lines, message) {
195
- lines.push(`- Message role: ${message.role}`);
196
- lines.push(`- Message ID: ${message.id}`);
197
- lines.push(`- Created at: ${message.createdAt}`);
198
- if (message.providerMessageId)
199
- lines.push(`- Provider message ID: ${message.providerMessageId}`);
200
- if (message.requestId)
201
- lines.push(`- Request ID: ${message.requestId}`);
202
- if (message.isMeta !== undefined)
203
- lines.push(`- Meta message: ${message.isMeta}`);
204
- if (message.isApiErrorMessage !== undefined)
205
- lines.push(`- API error message: ${message.isApiErrorMessage}`);
206
- if (message.usage !== undefined) {
207
- lines.push("- Usage:");
208
- lines.push(indentBlock(stableStringify(message.usage), " "));
209
- }
210
- if (message.metadata !== undefined) {
211
- lines.push("- Metadata:");
212
- lines.push(indentBlock(stableStringify(message.metadata), " "));
213
- }
214
- lines.push("");
215
- }
216
- async function renderMessageBlock(lines, block, index, sessionDir, maxToolResultLines) {
217
- lines.push(`### Block ${index}: ${block.type}`);
218
- lines.push("");
219
- if (block.type === "text") {
220
- lines.push(fenced(block.text, "text"));
221
- lines.push("");
222
- return;
223
- }
224
- if (block.type === "thinking") {
225
- lines.push("Stored model thinking/reasoning block:");
226
- if (block.signature)
227
- lines.push(`- Signature: ${block.signature}`);
228
- lines.push("");
229
- lines.push(fenced(block.text, "text"));
230
- lines.push("");
231
- return;
232
- }
233
- if (block.type === "tool_use") {
234
- lines.push(`- Tool: ${block.name}`);
235
- lines.push(`- Tool use ID: ${block.id}`);
236
- lines.push("");
237
- lines.push("Input:");
238
- lines.push(fenced(stableStringify(block.input), "json"));
239
- lines.push("");
240
- return;
241
- }
242
- if (block.type === "tool_result") {
243
- lines.push(`- Tool: ${block.name}`);
244
- lines.push(`- Tool use ID: ${block.toolUseId}`);
245
- lines.push(`- OK: ${block.ok}`);
246
- lines.push("");
247
- const output = await renderToolResultOutput(block.output, sessionDir, maxToolResultLines);
248
- if (output.sourcePath)
249
- lines.push(`- Persisted full output source: ${inlineCode(output.sourcePath)}`);
250
- if (output.truncated)
251
- lines.push(`- Truncated: showing first ${output.shownLines} of ${output.totalLines} lines`);
252
- lines.push("Output:");
253
- lines.push(fenced(output.text, output.language));
254
- lines.push("");
255
- return;
256
- }
257
- if (block.type === "image") {
258
- lines.push(`- MIME type: ${block.mimeType}`);
259
- if (block.label)
260
- lines.push(`- Label: ${block.label}`);
261
- lines.push(`- Data bytes (base64 chars): ${block.data.length}`);
262
- lines.push("- Data omitted from markdown body for readability.");
263
- lines.push("");
264
- }
265
- }
266
- async function renderToolResultOutput(output, sessionDir, maxLines) {
267
- const persistedPath = typeof output === "string" ? extractPersistedOutputPath(output) : undefined;
268
- if (persistedPath) {
269
- const sourcePath = path.isAbsolute(persistedPath) ? persistedPath : path.resolve(sessionDir, persistedPath);
270
- const persisted = await fs.readFile(sourcePath, "utf8").catch(() => undefined);
271
- if (persisted !== undefined) {
272
- const text = maybePrettyJson(persisted);
273
- const limited = limitLines(text, maxLines);
274
- return { ...limited, language: looksLikeJson(text) ? "json" : "text", sourcePath };
275
- }
276
- }
277
- const text = typeof output === "string" ? output : stableStringify(output);
278
- const limited = limitLines(text, maxLines);
279
- return { ...limited, language: typeof output === "string" && !looksLikeJson(text) ? "text" : "json", sourcePath: persistedPath };
280
- }
281
- function extractPersistedOutputPath(output) {
282
- if (!output.startsWith(PERSISTED_OUTPUT_TAG))
283
- return undefined;
284
- const match = /^Output too large \([^\n]+\)\. Full output saved to:\s*(.+)$/m.exec(output);
285
- return match?.[1]?.trim();
286
- }
287
- function maybePrettyJson(text) {
288
- if (!looksLikeJson(text))
289
- return text;
290
- try {
291
- return stableStringify(JSON.parse(text));
292
- }
293
- catch {
294
- return text;
295
- }
296
- }
297
- function looksLikeJson(text) {
298
- const trimmed = text.trimStart();
299
- return trimmed.startsWith("{") || trimmed.startsWith("[");
300
- }
301
- function limitLines(text, maxLines) {
302
- const lines = text.split(/\r?\n/);
303
- if (lines.length <= maxLines)
304
- return { text, truncated: false, shownLines: lines.length, totalLines: lines.length };
305
- return {
306
- text: lines.slice(0, maxLines).join("\n"),
307
- truncated: true,
308
- shownLines: maxLines,
309
- totalLines: lines.length,
310
- };
311
- }
312
- function fenced(content, language) {
313
- const fence = chooseFence(content);
314
- return `${fence}${language}\n${content}\n${fence}`;
315
- }
316
- function chooseFence(content) {
317
- const matches = content.match(/`{3,}/g) ?? [];
318
- const max = matches.reduce((value, match) => Math.max(value, match.length), 2);
319
- return "`".repeat(max + 1);
320
- }
321
- function inlineCode(value) {
322
- return `\`${value.replace(/`/g, "\\`")}\``;
323
- }
324
- function indentBlock(value, prefix) {
325
- return value.split(/\r?\n/).map((line) => `${prefix}${line}`).join("\n");
326
- }
327
- function formatInlineValue(value) {
328
- if (typeof value === "string")
329
- return value;
330
- return inlineCode(stableStringify(value));
331
- }
332
- function stableStringify(value) {
333
- const seen = new WeakSet();
334
- return JSON.stringify(value, (_key, nested) => {
335
- if (typeof nested === "bigint")
336
- return nested.toString();
337
- if (typeof nested === "function")
338
- return `[Function ${nested.name || "anonymous"}]`;
339
- if (nested instanceof Set)
340
- return [...nested];
341
- if (nested instanceof Map)
342
- return Object.fromEntries(nested.entries());
343
- if (nested && typeof nested === "object") {
344
- if (seen.has(nested))
345
- return "[Circular]";
346
- seen.add(nested);
347
- }
348
- return nested;
349
- }, 2);
350
- }
351
- //# sourceMappingURL=session-export.js.map