@code-yeongyu/senpi 2026.11.15-2 → 2026.11.15-3

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 (132) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/bundle/chunks/{chunk-Q4RJ4WLE.js → chunk-225TDKTA.js} +4 -4
  3. package/dist/bundle/chunks/{chunk-QSU2456D.js → chunk-3KR3CDGM.js} +1 -1
  4. package/dist/bundle/chunks/{chunk-AOTHPTMU.js → chunk-5GCZFK4X.js} +2 -2
  5. package/dist/bundle/chunks/{chunk-BMADOJHZ.js → chunk-5QIFH624.js} +1 -1
  6. package/dist/bundle/chunks/{chunk-THYIV26N.js → chunk-GQEXLLWJ.js} +1 -1
  7. package/dist/bundle/chunks/{chunk-3RILB2OD.js → chunk-OJOPOUAY.js} +9 -9
  8. package/dist/bundle/chunks/{chunk-64FJ4QQJ.js → chunk-PPCAJQDJ.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-74HCKLRH.js → chunk-TEXE4HT6.js} +1 -1
  10. package/dist/bundle/chunks/{chunk-RRFDLGX6.js → chunk-TNYFCGI7.js} +156 -156
  11. package/dist/bundle/chunks/{cli-main-GNQY2LTU.js → cli-main-CV3ODX4A.js} +1 -1
  12. package/dist/bundle/chunks/{hand-entry-D3DNH6XL.js → hand-entry-2NN7ZTY6.js} +1 -1
  13. package/dist/bundle/chunks/{interactive-mode-ATBPY4M5.js → interactive-mode-TGHZWM2T.js} +1 -1
  14. package/dist/bundle/chunks/{main-OMFVSMUR.js → main-B7WEY4JW.js} +1 -1
  15. package/dist/bundle/chunks/{multi-session-host-ACQ5N4UB.js → multi-session-host-53YLL2OD.js} +1 -1
  16. package/dist/bundle/chunks/{package-manager-cli-2VMRV4HL.js → package-manager-cli-2U54AVKW.js} +1 -1
  17. package/dist/bundle/chunks/{role-BTH5PVME.js → role-4IXZZAL4.js} +1 -1
  18. package/dist/bundle/chunks/{rpc-mode-XUK5SYKH.js → rpc-mode-RRYXENML.js} +1 -1
  19. package/dist/bundle/chunks/{runtime-session-VO3X4OE3.js → runtime-session-KKHEYZOH.js} +1 -1
  20. package/dist/bundle/chunks/{session-control-endpoint-Y5EIFFPY.js → session-control-endpoint-HVULSIUR.js} +1 -1
  21. package/dist/bundle/chunks/session-worker.js +331 -331
  22. package/dist/bundle/cli.js +2 -2
  23. package/dist/bundle/index.js +1 -1
  24. package/dist/bundle/rpc-entry.js +1 -1
  25. package/dist/bundle/runtime-manifest.json +1 -1
  26. package/dist/core/agent-session.d.ts +6 -0
  27. package/dist/core/agent-session.js +34 -3
  28. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.d.ts +2 -0
  29. package/dist/core/extensions/builtin/anthropic-subscription/auth-lane.js +1 -0
  30. package/dist/core/extensions/builtin/anthropic-subscription/failover.d.ts +2 -0
  31. package/dist/core/extensions/builtin/anthropic-subscription/failover.js +22 -4
  32. package/dist/core/extensions/builtin/anthropic-subscription/index.js +7 -2
  33. package/dist/core/extensions/builtin/anthropic-subscription/limit-recheck.d.ts +15 -0
  34. package/dist/core/extensions/builtin/anthropic-subscription/limit-recheck.js +55 -0
  35. package/dist/core/extensions/builtin/anthropic-subscription/session-stream.d.ts +1 -0
  36. package/dist/core/extensions/builtin/anthropic-subscription/session-stream.js +1 -0
  37. package/dist/core/extensions/builtin/anthropic-subscription/stream-guidance.js +8 -5
  38. package/dist/core/extensions/builtin/anthropic-subscription/stream.d.ts +1 -1
  39. package/dist/core/extensions/builtin/anthropic-subscription/stream.js +3 -1
  40. package/dist/core/extensions/builtin/terminal/extension-state.js +15 -0
  41. package/dist/core/extensions/builtin/terminal/notify.d.ts +2 -1
  42. package/dist/core/extensions/builtin/terminal/notify.js +15 -6
  43. package/dist/core/extensions/builtin/terminal/session-bundle.d.ts +5 -1
  44. package/dist/core/extensions/builtin/terminal/session-bundle.js +41 -1
  45. package/dist/core/extensions/builtin/terminal/tools/context.d.ts +4 -0
  46. package/dist/core/extensions/loader.js +5 -0
  47. package/dist/core/extensions/runner.d.ts +1 -0
  48. package/dist/core/extensions/runner.js +5 -0
  49. package/dist/core/extensions/types.d.ts +7 -0
  50. package/dist/core/run-background-jobs.d.ts +33 -0
  51. package/dist/core/run-background-jobs.js +47 -0
  52. package/dist/core/tools/bash-core.d.ts +50 -0
  53. package/dist/core/tools/bash-core.js +169 -0
  54. package/dist/core/tools/bash-schema.d.ts +48 -0
  55. package/dist/core/tools/bash-schema.js +34 -0
  56. package/dist/core/tools/bash.d.ts +4 -70
  57. package/dist/core/tools/bash.js +32 -409
  58. package/dist/core/tools/coding-tools-core.d.ts +24 -0
  59. package/dist/core/tools/coding-tools-core.js +14 -0
  60. package/dist/core/tools/edit-core.d.ts +56 -0
  61. package/dist/core/tools/edit-core.js +175 -0
  62. package/dist/core/tools/edit-diff.d.ts +0 -5
  63. package/dist/core/tools/edit-diff.js +0 -32
  64. package/dist/core/tools/edit-preview.d.ts +7 -0
  65. package/dist/core/tools/edit-preview.js +34 -0
  66. package/dist/core/tools/edit.d.ts +5 -43
  67. package/dist/core/tools/edit.js +10 -158
  68. package/dist/core/tools/encoding.d.ts +10 -0
  69. package/dist/core/tools/encoding.js +58 -0
  70. package/dist/core/tools/file-tool-host.d.ts +25 -0
  71. package/dist/core/tools/file-tool-host.js +109 -0
  72. package/dist/core/tools/fs-error-code.d.ts +2 -0
  73. package/dist/core/tools/fs-error-code.js +15 -0
  74. package/dist/core/tools/machine-output-spill.d.ts +11 -0
  75. package/dist/core/tools/machine-output-spill.js +65 -0
  76. package/dist/core/tools/machine.d.ts +4 -24
  77. package/dist/core/tools/machine.js +4 -44
  78. package/dist/core/tools/output-accumulator-core.d.ts +84 -0
  79. package/dist/core/tools/output-accumulator-core.js +200 -0
  80. package/dist/core/tools/output-accumulator.d.ts +9 -61
  81. package/dist/core/tools/output-accumulator.js +90 -265
  82. package/dist/core/tools/path-utils.js +3 -48
  83. package/dist/core/tools/posix-signals.d.ts +3 -0
  84. package/dist/core/tools/posix-signals.js +113 -0
  85. package/dist/core/tools/read-core.d.ts +64 -0
  86. package/dist/core/tools/read-core.js +180 -0
  87. package/dist/core/tools/read-text.d.ts +23 -0
  88. package/dist/core/tools/read-text.js +90 -0
  89. package/dist/core/tools/read.d.ts +6 -47
  90. package/dist/core/tools/read.js +13 -218
  91. package/dist/core/tools/renderers/bash.d.ts +0 -1
  92. package/dist/core/tools/renderers/bash.js +0 -1
  93. package/dist/core/tools/renderers/edit.d.ts +1 -1
  94. package/dist/core/tools/renderers/edit.js +1 -1
  95. package/dist/core/tools/secret-output-redactor.js +2 -1
  96. package/dist/core/tools/shell-operations.d.ts +53 -0
  97. package/dist/core/tools/shell-operations.js +115 -0
  98. package/dist/core/tools/shell-output.d.ts +20 -0
  99. package/dist/core/tools/shell-output.js +152 -0
  100. package/dist/core/tools/tail-window.js +5 -7
  101. package/dist/core/tools/tool-machine.d.ts +30 -0
  102. package/dist/core/tools/tool-machine.js +47 -0
  103. package/dist/core/tools/truncate.js +15 -14
  104. package/dist/core/tools/write-core.d.ts +47 -0
  105. package/dist/core/tools/write-core.js +108 -0
  106. package/dist/core/tools/write-result.d.ts +0 -1
  107. package/dist/core/tools/write-result.js +0 -13
  108. package/dist/core/tools/write.d.ts +6 -31
  109. package/dist/core/tools/write.js +25 -77
  110. package/dist/core/turn-origin.d.ts +4 -2
  111. package/dist/core/turn-origin.js +15 -8
  112. package/dist/modes/interactive/session-control-session-commands.js +1 -1
  113. package/dist/modes/rpc/connection-handler.js +2 -2
  114. package/dist/modes/rpc/effect-commands.d.ts +1 -4
  115. package/dist/modes/rpc/method-classes-schema-session.d.ts +1 -0
  116. package/dist/modes/rpc/method-classes-schema-session.js +5 -1
  117. package/dist/modes/rpc/method-classes-schema.d.ts +1 -0
  118. package/dist/modes/rpc/pause-command-validation.js +2 -0
  119. package/dist/modes/rpc/rpc-mutation-response-types.d.ts +2 -4
  120. package/dist/modes/rpc/rpc-session-command-types.d.ts +1 -0
  121. package/dist/modes/rpc/session-control-actions-data.d.ts +7 -3
  122. package/dist/modes/rpc/session-control-actions-data.js +12 -6
  123. package/dist/tools-core.d.ts +14 -0
  124. package/dist/tools-core.js +9 -0
  125. package/dist/utils/image-mime.d.ts +4 -0
  126. package/dist/utils/image-mime.js +99 -0
  127. package/dist/utils/mime.d.ts +1 -1
  128. package/dist/utils/mime.js +2 -97
  129. package/docs/extensions.md +7 -1
  130. package/docs/rpc.md +14 -0
  131. package/package.json +11 -7
  132. package/vendor/senpi-machine-ops/files/local-files.js +34 -5
@@ -0,0 +1,108 @@
1
+ import { Type } from "typebox";
2
+ import { decodeUtf8, encodeUtf8 } from "./encoding.js";
3
+ import { fsErrorCode } from "./fs-error-code.js";
4
+ import { inProcessFileMutationQueue, lexicalCanonicalPath, posixDirname, resolvePosixToolPath, } from "./file-tool-host.js";
5
+ import { wrapToolDefinition } from "./tool-definition-wrapper.js";
6
+ import { createWriteDetails } from "./write-result.js";
7
+ export const writeSchema = Type.Object({
8
+ path: Type.String({ description: "Path to the file to write (relative or absolute)" }),
9
+ content: Type.String({ description: "Content to write to the file" }),
10
+ });
11
+ export const writeToolSystemPromptContribution = {
12
+ snippet: "Create or overwrite files",
13
+ guidelines: ["write only for new files or full rewrites."],
14
+ fullGuidelines: ["Use write only for new files or complete rewrites."],
15
+ };
16
+ /**
17
+ * The default write operations over the shared operation layer. `files.write` creates the parent directory in the
18
+ * same call (`createParentDirs`), so `mkdir` has nothing left to do; the tool already holds the file's mutation slot.
19
+ */
20
+ function machineWriteOperations(machine, signal) {
21
+ const ctx = machine.context(signal, "caller");
22
+ return {
23
+ writeFile: async (path, content) => {
24
+ await machine.ops.files.write({ path, bytes: encodeUtf8(content), createParentDirs: true }, ctx);
25
+ },
26
+ mkdir: async () => { },
27
+ };
28
+ }
29
+ /** The file's content before the write, read on the machine; it feeds the patch in the result details. */
30
+ function machineWriteBaseline(machine) {
31
+ return async (absolutePath) => {
32
+ try {
33
+ const { bytes } = await machine.ops.files.read({ path: absolutePath }, machine.context(undefined, "caller"));
34
+ return { kind: "present", content: decodeUtf8(bytes) };
35
+ }
36
+ catch (error) {
37
+ if (error instanceof Error && fsErrorCode(error) === "ENOENT")
38
+ return { kind: "missing" };
39
+ if (error instanceof Error)
40
+ return { kind: "unavailable" };
41
+ throw error;
42
+ }
43
+ };
44
+ }
45
+ export function createCoreWriteToolDefinition(cwd, options) {
46
+ const machine = options.machine;
47
+ const readBaseline = options.operations ? undefined : (options.readBaseline ?? machineWriteBaseline(machine));
48
+ const filesystemPolicy = options.filesystemPolicy;
49
+ const resolvePath = options.resolvePath ?? resolvePosixToolPath;
50
+ const dirname = options.dirname ?? posixDirname;
51
+ const withMutationQueue = options.withMutationQueue ?? inProcessFileMutationQueue;
52
+ const canonicalizePath = options.canonicalizePath ?? lexicalCanonicalPath;
53
+ return {
54
+ name: "write",
55
+ label: "write",
56
+ description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
57
+ promptSnippet: writeToolSystemPromptContribution.snippet,
58
+ promptGuidelines: [...writeToolSystemPromptContribution.guidelines],
59
+ fullPromptGuidelines: [...writeToolSystemPromptContribution.fullGuidelines],
60
+ parameters: writeSchema,
61
+ constrainedSampling: { type: "json_schema", strict: "prefer" },
62
+ async execute(_toolCallId, { path, content }, signal, _onUpdate, ctx) {
63
+ const admitted = machine.begin("files.write", { path, content }, signal);
64
+ if (admitted !== undefined)
65
+ await admitted;
66
+ const ops = options.operations ?? machineWriteOperations(machine, signal);
67
+ const absolutePath = resolvePath(path, ctx?.cwd || cwd);
68
+ const dir = dirname(absolutePath);
69
+ return withMutationQueue(absolutePath, async () => {
70
+ // Do not reject from an abort event listener here: that would release the
71
+ // mutation queue while an in-flight filesystem operation may still finish.
72
+ // Checking signal.aborted after each await observes the same aborts while
73
+ // keeping the queue locked until the current operation has settled.
74
+ const throwIfAborted = () => {
75
+ if (signal?.aborted)
76
+ throw new Error("Operation aborted");
77
+ };
78
+ throwIfAborted();
79
+ if (filesystemPolicy) {
80
+ const decision = await filesystemPolicy({
81
+ operation: "write",
82
+ canonicalPath: await canonicalizePath(absolutePath),
83
+ toolName: "write",
84
+ });
85
+ if (!decision.allow)
86
+ throw new Error(decision.reason);
87
+ throwIfAborted();
88
+ }
89
+ const baseline = readBaseline ? await readBaseline(absolutePath) : { kind: "unavailable" };
90
+ throwIfAborted();
91
+ // Create parent directories if needed.
92
+ await ops.mkdir(dir);
93
+ throwIfAborted();
94
+ // Write the file contents.
95
+ await ops.writeFile(absolutePath, content);
96
+ throwIfAborted();
97
+ return {
98
+ content: [{ type: "text", text: `Successfully wrote to ${path}` }],
99
+ details: createWriteDetails(path, content, baseline),
100
+ };
101
+ });
102
+ },
103
+ };
104
+ }
105
+ export function createCoreWriteTool(cwd, options) {
106
+ return wrapToolDefinition(createCoreWriteToolDefinition(cwd, options));
107
+ }
108
+ //# sourceMappingURL=write-core.js.map
@@ -11,7 +11,6 @@ export type WriteBaseline = {
11
11
  } | {
12
12
  readonly kind: "unavailable";
13
13
  };
14
- export declare function readLocalWriteBaseline(absolutePath: string): Promise<WriteBaseline>;
15
14
  export declare function createWriteDetails(path: string, content: string, baseline: WriteBaseline): WriteToolDetails | undefined;
16
15
  export declare function formatWriteResult(result: {
17
16
  readonly content: readonly {
@@ -1,17 +1,4 @@
1
- import { readFile } from "fs/promises";
2
1
  import { createUnifiedPatch } from "./unified-diff.js";
3
- export async function readLocalWriteBaseline(absolutePath) {
4
- try {
5
- return { kind: "present", content: await readFile(absolutePath, "utf-8") };
6
- }
7
- catch (error) {
8
- if (error instanceof Error && "code" in error && error.code === "ENOENT")
9
- return { kind: "missing" };
10
- if (error instanceof Error)
11
- return { kind: "unavailable" };
12
- throw error;
13
- }
14
- }
15
2
  export function createWriteDetails(path, content, baseline) {
16
3
  switch (baseline.kind) {
17
4
  case "missing":
@@ -1,37 +1,12 @@
1
1
  import type { AgentTool } from "@earendil-works/pi-agent-core";
2
- import { type Static, Type } from "typebox";
3
- import type { FilesystemPolicyChecker, ToolDefinition } from "../extensions/types.ts";
4
- import { type ToolMachine } from "./machine.ts";
5
- import { type WriteToolDetails } from "./write-result.ts";
6
- declare const writeSchema: Type.TObject<{
7
- path: Type.TString;
8
- content: Type.TString;
9
- }>;
10
- export declare const writeToolSystemPromptContribution: {
11
- readonly snippet: "Create or overwrite files";
12
- readonly guidelines: readonly ["write only for new files or full rewrites."];
13
- readonly fullGuidelines: readonly ["Use write only for new files or complete rewrites."];
14
- };
15
- export type WriteToolInput = Static<typeof writeSchema>;
16
- /**
17
- * Pluggable operations for the write tool.
18
- * Override these to delegate file writing to remote systems (for example SSH).
19
- */
20
- export interface WriteOperations {
21
- /** Write content to a file */
22
- writeFile: (absolutePath: string, content: string) => Promise<void>;
23
- /** Create directory recursively */
24
- mkdir: (dir: string) => Promise<void>;
25
- }
26
- export interface WriteToolOptions {
27
- /** Custom operations for file writing. Default: local filesystem */
28
- operations?: WriteOperations;
29
- /** Extension-registered filesystem policy checker. */
30
- filesystemPolicy?: FilesystemPolicyChecker;
2
+ import type { ToolDefinition } from "../extensions/types.ts";
3
+ import { type CoreWriteToolOptions, type writeSchema } from "./write-core.ts";
4
+ import type { WriteToolDetails } from "./write-result.ts";
5
+ export { type WriteOperations, type WriteToolInput, writeToolSystemPromptContribution } from "./write-core.ts";
6
+ export interface WriteToolOptions extends Pick<CoreWriteToolOptions, "operations" | "filesystemPolicy"> {
31
7
  /** Operation layer and policy gate. Default: the process-wide local machine. */
32
- machine?: ToolMachine;
8
+ machine?: CoreWriteToolOptions["machine"];
33
9
  }
34
10
  export declare function createWriteToolDefinition(cwd: string, options?: WriteToolOptions): ToolDefinition<typeof writeSchema, WriteToolDetails | undefined>;
35
11
  export declare function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema>;
36
- export {};
37
12
  //# sourceMappingURL=write.d.ts.map
@@ -1,89 +1,37 @@
1
- import { dirname } from "path";
2
- import { Type } from "typebox";
1
+ import { readFile } from "node:fs/promises";
2
+ import { dirname } from "node:path";
3
3
  import { withFileMutationQueue } from "./file-mutation-queue.js";
4
4
  import { canonicalizeFilesystemPath } from "./filesystem-policy.js";
5
5
  import { defaultToolMachine } from "./machine.js";
6
6
  import { resolveToCwd } from "./path-utils.js";
7
7
  import { writeRenderers } from "./renderers/write.js";
8
8
  import { wrapToolDefinition } from "./tool-definition-wrapper.js";
9
- import { createWriteDetails, readLocalWriteBaseline } from "./write-result.js";
10
- const writeSchema = Type.Object({
11
- path: Type.String({ description: "Path to the file to write (relative or absolute)" }),
12
- content: Type.String({ description: "Content to write to the file" }),
13
- });
14
- export const writeToolSystemPromptContribution = {
15
- snippet: "Create or overwrite files",
16
- guidelines: ["write only for new files or full rewrites."],
17
- fullGuidelines: ["Use write only for new files or complete rewrites."],
18
- };
19
- /**
20
- * The default write operations over the shared operation layer. `files.write` creates the parent directory in the
21
- * same call (`createParentDirs`), so `mkdir` has nothing left to do; the tool already holds the file's mutation slot.
22
- */
23
- function machineWriteOperations(machine, signal) {
24
- const ctx = machine.context(signal, "caller");
25
- return {
26
- writeFile: async (path, content) => {
27
- await machine.ops.files.write({ path, bytes: Buffer.from(content, "utf-8"), createParentDirs: true }, ctx);
28
- },
29
- mkdir: async () => { },
30
- };
9
+ import { createCoreWriteToolDefinition } from "./write-core.js";
10
+ export { writeToolSystemPromptContribution } from "./write-core.js";
11
+ async function readLocalWriteBaseline(absolutePath) {
12
+ try {
13
+ return { kind: "present", content: await readFile(absolutePath, "utf-8") };
14
+ }
15
+ catch (error) {
16
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
17
+ return { kind: "missing" };
18
+ if (error instanceof Error)
19
+ return { kind: "unavailable" };
20
+ throw error;
21
+ }
31
22
  }
32
23
  export function createWriteToolDefinition(cwd, options) {
33
- const machine = options?.machine ?? defaultToolMachine();
34
- const readBaseline = options?.operations ? undefined : readLocalWriteBaseline;
35
- const filesystemPolicy = options?.filesystemPolicy;
36
24
  return {
37
- ...(options?.operations !== undefined || filesystemPolicy !== undefined ? { serverPinned: true } : {}),
38
- name: "write",
39
- label: "write",
40
- description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
41
- promptSnippet: writeToolSystemPromptContribution.snippet,
42
- promptGuidelines: [...writeToolSystemPromptContribution.guidelines],
43
- fullPromptGuidelines: [...writeToolSystemPromptContribution.fullGuidelines],
44
- parameters: writeSchema,
45
- constrainedSampling: { type: "json_schema", strict: "prefer" },
46
- async execute(_toolCallId, { path, content }, signal, _onUpdate, ctx) {
47
- const admitted = machine.begin("files.write", { path, content }, signal);
48
- if (admitted !== undefined)
49
- await admitted;
50
- const ops = options?.operations ?? machineWriteOperations(machine, signal);
51
- const absolutePath = resolveToCwd(path, ctx?.cwd || cwd);
52
- const dir = dirname(absolutePath);
53
- return withFileMutationQueue(absolutePath, async () => {
54
- // Do not reject from an abort event listener here: that would release the
55
- // mutation queue while an in-flight filesystem operation may still finish.
56
- // Checking signal.aborted after each await observes the same aborts while
57
- // keeping the queue locked until the current operation has settled.
58
- const throwIfAborted = () => {
59
- if (signal?.aborted)
60
- throw new Error("Operation aborted");
61
- };
62
- throwIfAborted();
63
- if (filesystemPolicy) {
64
- const decision = await filesystemPolicy({
65
- operation: "write",
66
- canonicalPath: await canonicalizeFilesystemPath(absolutePath),
67
- toolName: "write",
68
- });
69
- if (!decision.allow)
70
- throw new Error(decision.reason);
71
- throwIfAborted();
72
- }
73
- const baseline = readBaseline ? await readBaseline(absolutePath) : { kind: "unavailable" };
74
- throwIfAborted();
75
- // Create parent directories if needed.
76
- await ops.mkdir(dir);
77
- throwIfAborted();
78
- // Write the file contents.
79
- await ops.writeFile(absolutePath, content);
80
- throwIfAborted();
81
- return {
82
- content: [{ type: "text", text: `Successfully wrote to ${path}` }],
83
- details: createWriteDetails(path, content, baseline),
84
- };
85
- });
86
- },
25
+ ...(options?.operations !== undefined || options?.filesystemPolicy !== undefined ? { serverPinned: true } : {}),
26
+ ...createCoreWriteToolDefinition(cwd, {
27
+ ...options,
28
+ machine: options?.machine ?? defaultToolMachine(),
29
+ resolvePath: resolveToCwd,
30
+ dirname,
31
+ withMutationQueue: withFileMutationQueue,
32
+ canonicalizePath: canonicalizeFilesystemPath,
33
+ readBaseline: readLocalWriteBaseline,
34
+ }),
87
35
  ...writeRenderers,
88
36
  };
89
37
  }
@@ -16,7 +16,7 @@ export declare function inputTurnMark(input: {
16
16
  readonly connectionOrigin?: ConnectionOrigin;
17
17
  readonly source?: string;
18
18
  }): InputTurnMark;
19
- export declare function markInputTurnOrigin(message: object, mark: InputTurnMark): void;
19
+ export declare function markInputTurnOrigin(message: object, mark: InputTurnMark, personStarted?: boolean): void;
20
20
  /** Carries `from`'s origin mark onto `to`, a copy of the same input: a copy without it would open or join a turn unmarked. */
21
21
  export declare function copyInputTurnMark(from: object, to: object): void;
22
22
  /** Whether a message carries an origin mark: a user message always opens a turn's origin, any other only when marked. */
@@ -30,10 +30,12 @@ export declare function recordIsDelegated(): boolean;
30
30
  * the turn it continues. The user message that opens a turn sets its origin, a steer keeps it.
31
31
  */
32
32
  export declare function noteRunStart(sessionManager: object): void;
33
- /** A retry or recovery run repeats the turn it continues, so it keeps that turn's origin until the continuation ends. */
33
+ /** The next retry or recovery run repeats this turn; its start consumes the continuation mark. */
34
34
  export declare function noteTurnContinuation(sessionManager: object): void;
35
35
  export declare function endTurnContinuation(sessionManager: object): void;
36
36
  export declare function noteUserMessageStart(sessionManager: object, message: object): void;
37
+ /** A person's admitted message owns this identity; only an explicit continuation preserves it across run starts. */
38
+ export declare function currentPersonTurn(sessionManager: object): object | undefined;
37
39
  /** Whether the deciding turn counts as delegated-origin: a cross-account device started this turn or this run. */
38
40
  export declare function decidingTurnIsDelegated(sessionManager: object): boolean;
39
41
  //# sourceMappingURL=turn-origin.d.ts.map
@@ -32,8 +32,8 @@ export function inputTurnMark(input) {
32
32
  return "delegated";
33
33
  return input.source === undefined || input.source === "interactive" ? "local" : "engine";
34
34
  }
35
- export function markInputTurnOrigin(message, mark) {
36
- inputMarks.set(message, mark);
35
+ export function markInputTurnOrigin(message, mark, personStarted = false) {
36
+ inputMarks.set(message, { origin: mark, personStarted });
37
37
  }
38
38
  /** Carries `from`'s origin mark onto `to`, a copy of the same input: a copy without it would open or join a turn unmarked. */
39
39
  export function copyInputTurnMark(from, to) {
@@ -58,11 +58,11 @@ export function recordIsDelegated() {
58
58
  * the turn it continues. The user message that opens a turn sets its origin, a steer keeps it.
59
59
  */
60
60
  export function noteRunStart(sessionManager) {
61
- if (continuingTurns.has(sessionManager))
61
+ if (continuingTurns.delete(sessionManager))
62
62
  return;
63
- currentOrigins.set(sessionManager, recordScope.closeAtRunStart() === true ? "delegated" : "engine");
63
+ currentOrigins.set(sessionManager, { origin: recordScope.closeAtRunStart() === true ? "delegated" : "engine" });
64
64
  }
65
- /** A retry or recovery run repeats the turn it continues, so it keeps that turn's origin until the continuation ends. */
65
+ /** The next retry or recovery run repeats this turn; its start consumes the continuation mark. */
66
66
  export function noteTurnContinuation(sessionManager) {
67
67
  continuingTurns.add(sessionManager);
68
68
  }
@@ -71,12 +71,19 @@ export function endTurnContinuation(sessionManager) {
71
71
  }
72
72
  export function noteUserMessageStart(sessionManager, message) {
73
73
  const mark = inputMarks.get(message);
74
- if (mark === "join")
74
+ if (mark?.origin === "join")
75
75
  return;
76
- currentOrigins.set(sessionManager, mark ?? "engine");
76
+ currentOrigins.set(sessionManager, {
77
+ origin: mark?.origin ?? "engine",
78
+ personTurn: mark?.personStarted ? {} : undefined,
79
+ });
80
+ }
81
+ /** A person's admitted message owns this identity; only an explicit continuation preserves it across run starts. */
82
+ export function currentPersonTurn(sessionManager) {
83
+ return currentOrigins.get(sessionManager)?.personTurn;
77
84
  }
78
85
  /** Whether the deciding turn counts as delegated-origin: a cross-account device started this turn or this run. */
79
86
  export function decidingTurnIsDelegated(sessionManager) {
80
- return currentOrigins.get(sessionManager) === "delegated";
87
+ return currentOrigins.get(sessionManager)?.origin === "delegated";
81
88
  }
82
89
  //# sourceMappingURL=turn-origin.js.map
@@ -24,7 +24,7 @@ export async function runSessionControlCommand(session, controls, command) {
24
24
  return success(id, type);
25
25
  }
26
26
  case "interrupt":
27
- return success(id, type, await interruptRunningTurn(session, command.turnId, () => controls.interruptTurn()));
27
+ return success(id, type, await interruptRunningTurn(session, command.turnId, () => controls.interruptTurn(), command.background));
28
28
  default:
29
29
  return undefined;
30
30
  }
@@ -1166,7 +1166,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1166
1166
  const stopped = await interruptRunningTurn(session, undefined, () => {
1167
1167
  ClientAdmissions.forSession(session).noteAbort(effectContext().by);
1168
1168
  return session.stop();
1169
- });
1169
+ }, command.background);
1170
1170
  if (!stopped.interrupted)
1171
1171
  await session.stop();
1172
1172
  return success(id, "interrupt", stopped);
@@ -1174,7 +1174,7 @@ export function createRpcConnectionHandler(runtimeHost, sink, options = {}) {
1174
1174
  return success(id, "interrupt", await interruptRunningTurn(session, command.turnId, () => {
1175
1175
  ClientAdmissions.forSession(session).noteAbort(effectContext().by);
1176
1176
  return session.abort();
1177
- }));
1177
+ }, command.background));
1178
1178
  case "hold_input": {
1179
1179
  const answer = runHoldInput(session, command, {
1180
1180
  interactiveUser: hasRole(INTERACTIVE_USER_CAPABILITY),
@@ -315,10 +315,7 @@ export declare function runSetThinkingLevel(ctx: EffectCommandContext, command:
315
315
  type: "response";
316
316
  command: "interrupt";
317
317
  success: true;
318
- data: {
319
- interrupted: boolean;
320
- turnId?: string;
321
- };
318
+ data: import("./session-control-actions-data.ts").InterruptOutcome;
322
319
  } | {
323
320
  id?: string;
324
321
  type: "response";
@@ -177,6 +177,7 @@ export declare const SESSION_RECORD_SCHEMAS: {
177
177
  } & {
178
178
  readonly turnId: Type.TOptional<Type.TString>;
179
179
  readonly intent: Type.TOptional<Type.TUnion<[Type.TLiteral<string>, ...Type.TLiteral<string>[]]>>;
180
+ readonly background: Type.TOptional<Type.TUnion<[Type.TLiteral<string>, ...Type.TLiteral<string>[]]>>;
180
181
  }>;
181
182
  hold_input: Type.TObject<{
182
183
  id: Type.TOptional<Type.TString>;
@@ -65,7 +65,11 @@ const PROMPTING_SCHEMAS = {
65
65
  graceMs: OptNum,
66
66
  intent: Opt(literals("stop", "abort")),
67
67
  }),
68
- interrupt: session("interrupt", { turnId: OptId, intent: Opt(literals("stop", "abort")) }),
68
+ interrupt: session("interrupt", {
69
+ turnId: OptId,
70
+ intent: Opt(literals("stop", "abort")),
71
+ background: Opt(literals("stop")),
72
+ }),
69
73
  hold_input: session("hold_input", {
70
74
  inputId: Id,
71
75
  revision: Num,
@@ -650,6 +650,7 @@ export declare const RPC_INBOUND_SCHEMAS: {
650
650
  } & {
651
651
  readonly turnId: import("typebox").TOptional<import("typebox").TString>;
652
652
  readonly intent: import("typebox").TOptional<import("typebox").TUnion<[import("typebox").TLiteral<string>, ...import("typebox").TLiteral<string>[]]>>;
653
+ readonly background: import("typebox").TOptional<import("typebox").TUnion<[import("typebox").TLiteral<string>, ...import("typebox").TLiteral<string>[]]>>;
653
654
  }>;
654
655
  readonly hold_input: import("typebox").TObject<{
655
656
  id: import("typebox").TOptional<import("typebox").TString>;
@@ -12,6 +12,8 @@ export function validatePauseCommand(value) {
12
12
  if (value.intent !== "stop" && value.intent !== "abort")
13
13
  return 'intent must be "stop" or "abort".';
14
14
  }
15
+ if (value.type === "interrupt" && value.background !== undefined && value.background !== "stop")
16
+ return 'background must be "stop".';
15
17
  if (value.type === "resume_session") {
16
18
  if (value.expectedSeq !== undefined && !seq(value.expectedSeq))
17
19
  return "expectedSeq must be a non-negative integer.";
@@ -8,6 +8,7 @@ import type { ServiceTier } from "../../core/extensions/builtin/service-tier.ts"
8
8
  import type { SessionControlAdmission } from "../../core/extensions/types.ts";
9
9
  import type { PermissionModeReply } from "../../core/permission-mode.ts";
10
10
  import type { ApiKeyVerification } from "../../core/verify-api-key.ts";
11
+ import type { InterruptOutcome } from "./session-control-actions-data.ts";
11
12
  import type { ClientMessageAdmission } from "./client-admission-record.ts";
12
13
  import type { RpcProjectFile } from "./project-file-commands.ts";
13
14
  import type { RpcProjectSettings, RpcProjectTrust } from "./project-workspace-commands.ts";
@@ -99,10 +100,7 @@ export type RpcMutationResponse = {
99
100
  type: "response";
100
101
  command: "interrupt";
101
102
  success: true;
102
- data: {
103
- interrupted: boolean;
104
- turnId?: string;
105
- };
103
+ data: InterruptOutcome;
106
104
  } | {
107
105
  id?: string;
108
106
  type: "response";
@@ -111,6 +111,7 @@ export type RpcSessionCommand = {
111
111
  type: "interrupt";
112
112
  turnId?: string;
113
113
  intent?: "stop" | "abort";
114
+ background?: "stop";
114
115
  }
115
116
  /** Human input held for a paused session, delivered when it resumes; idempotent by inputId (senpi#3811). */
116
117
  | {
@@ -1,4 +1,5 @@
1
1
  import type { AgentSession } from "../../core/agent-session.ts";
2
+ import type { RunBackgroundStopOutcome } from "../../core/run-background-jobs.ts";
2
3
  export declare function availableModelsData(session: AgentSession): Promise<{
3
4
  models: readonly object[];
4
5
  }>;
@@ -7,11 +8,14 @@ export declare function unsupportedThinkingLevel(level: unknown): string;
7
8
  export interface InterruptOutcome {
8
9
  readonly interrupted: boolean;
9
10
  readonly turnId?: string;
11
+ /** Present when the caller asked `background: "stop"`: the interrupted turn's background jobs it stopped. */
12
+ readonly background?: RunBackgroundStopOutcome;
10
13
  }
11
14
  /**
12
- * `interrupt { turnId? }`: stops the running turn and only that. An idle session answers
15
+ * `interrupt { turnId?, background? }`: stops the running turn and only that. An idle session answers
13
16
  * `interrupted: false`; so does a `turnId` naming a turn that is no longer the running one, which
14
- * then answers the running turn's id. `stop` resolves once the turn has stopped.
17
+ * then answers the running turn's id. `stop` resolves once the turn has stopped; with `background:
18
+ * "stop"` the background jobs that turn started are stopped after it, and the answer names them.
15
19
  */
16
- export declare function interruptRunningTurn(session: AgentSession, requestedTurnId: unknown, stop: () => Promise<void>): Promise<InterruptOutcome>;
20
+ export declare function interruptRunningTurn(session: AgentSession, requestedTurnId: unknown, stop: () => Promise<void>, background?: unknown): Promise<InterruptOutcome>;
17
21
  //# sourceMappingURL=session-control-actions-data.d.ts.map
@@ -30,18 +30,24 @@ export async function availableModelsData(session) {
30
30
  export function unsupportedThinkingLevel(level) {
31
31
  return `Thinking level ${String(level)} is not supported by the active model.`;
32
32
  }
33
+ const NOTHING_STOPPED = { stopped: [], failed: [] };
33
34
  /**
34
- * `interrupt { turnId? }`: stops the running turn and only that. An idle session answers
35
+ * `interrupt { turnId?, background? }`: stops the running turn and only that. An idle session answers
35
36
  * `interrupted: false`; so does a `turnId` naming a turn that is no longer the running one, which
36
- * then answers the running turn's id. `stop` resolves once the turn has stopped.
37
+ * then answers the running turn's id. `stop` resolves once the turn has stopped; with `background:
38
+ * "stop"` the background jobs that turn started are stopped after it, and the answer names them.
37
39
  */
38
- export async function interruptRunningTurn(session, requestedTurnId, stop) {
40
+ export async function interruptRunningTurn(session, requestedTurnId, stop, background) {
41
+ const stopsBackground = background === "stop";
42
+ const nothing = stopsBackground ? { background: NOTHING_STOPPED } : {};
39
43
  if (!session.isStreaming && session.retryAttempt === 0)
40
- return { interrupted: false };
44
+ return { interrupted: false, ...nothing };
41
45
  const turnId = String(session.externalAdmission.turnEpoch);
42
46
  if (typeof requestedTurnId === "string" && requestedTurnId !== turnId)
43
- return { interrupted: false, turnId };
47
+ return { interrupted: false, turnId, ...nothing };
44
48
  await stop();
45
- return { interrupted: true, turnId };
49
+ if (!stopsBackground)
50
+ return { interrupted: true, turnId };
51
+ return { interrupted: true, turnId, background: await session.stopRunBackgroundJobs(turnId) };
46
52
  }
47
53
  //# sourceMappingURL=session-control-actions-data.js.map
@@ -0,0 +1,14 @@
1
+ export type { ExecRequest as MachineExecRequest, ExecResult as MachineExecResult, ExecShell as MachineExecShell, MachineOps, OpContext, } from "../vendor/senpi-machine-ops/index.js";
2
+ export { type CoreBashToolOptions, createCoreBashTool, createCoreBashToolDefinition } from "./core/tools/bash-core.ts";
3
+ export type { BashToolDetails, BashToolInput, BashToolOutput } from "./core/tools/bash-schema.ts";
4
+ export { type CoreCodingToolsOptions, createCoreCodingTools } from "./core/tools/coding-tools-core.ts";
5
+ export { type CoreEditToolOptions, createCoreEditTool, createCoreEditToolDefinition, type EditOperations, type EditToolDetails, type EditToolInput, } from "./core/tools/edit-core.ts";
6
+ export type { FileMutationQueue, ToolPathCanonicalizer, ToolPathResolver } from "./core/tools/file-tool-host.ts";
7
+ export { createMachineOutputSpill } from "./core/tools/machine-output-spill.ts";
8
+ export type { FullOutput, OutputSpill, OutputSpillFactory } from "./core/tools/output-accumulator-core.ts";
9
+ export { type CoreReadToolOptions, createCoreReadTool, createCoreReadToolDefinition, type ReadImageProcessor, type ReadOperations, type ReadToolDetails, type ReadToolInput, } from "./core/tools/read-core.ts";
10
+ export { type BashOperations, createShellOperations, machineShellExecHost, type ShellExecHost, } from "./core/tools/shell-operations.ts";
11
+ export { createToolMachine, type ToolMachine, type ToolPathPolicy } from "./core/tools/tool-machine.ts";
12
+ export { type CoreWriteToolOptions, createCoreWriteTool, createCoreWriteToolDefinition, type WriteOperations, type WriteToolInput, } from "./core/tools/write-core.ts";
13
+ export type { WriteToolDetails } from "./core/tools/write-result.ts";
14
+ //# sourceMappingURL=tools-core.d.ts.map
@@ -0,0 +1,9 @@
1
+ export { createCoreBashTool, createCoreBashToolDefinition } from "./core/tools/bash-core.js";
2
+ export { createCoreCodingTools } from "./core/tools/coding-tools-core.js";
3
+ export { createCoreEditTool, createCoreEditToolDefinition, } from "./core/tools/edit-core.js";
4
+ export { createMachineOutputSpill } from "./core/tools/machine-output-spill.js";
5
+ export { createCoreReadTool, createCoreReadToolDefinition, } from "./core/tools/read-core.js";
6
+ export { createShellOperations, machineShellExecHost, } from "./core/tools/shell-operations.js";
7
+ export { createToolMachine } from "./core/tools/tool-machine.js";
8
+ export { createCoreWriteTool, createCoreWriteToolDefinition, } from "./core/tools/write-core.js";
9
+ //# sourceMappingURL=tools-core.js.map
@@ -0,0 +1,4 @@
1
+ /** Bytes from the start of a file that decide its image type. */
2
+ export declare const IMAGE_TYPE_SNIFF_BYTES = 4100;
3
+ export declare function detectSupportedImageMimeType(buffer: Uint8Array): string | null;
4
+ //# sourceMappingURL=image-mime.d.ts.map