@modelprofile.com/flexharness 10.17.1 → 10.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/errors.d.ts +4 -0
  3. package/dist_ts/errors.js +9 -1
  4. package/dist_ts/functions.toolpermissions.d.ts +24 -0
  5. package/dist_ts/functions.toolpermissions.js +38 -0
  6. package/dist_ts/index.d.ts +1 -0
  7. package/dist_ts/index.js +2 -1
  8. package/dist_ts/plugins.d.ts +1 -1
  9. package/dist_ts/plugins.js +1 -1
  10. package/dist_ts_chat_harness/classes.chatclient.d.ts +95 -0
  11. package/dist_ts_chat_harness/classes.chatclient.js +263 -0
  12. package/dist_ts_chat_harness/classes.chatrequesterror.d.ts +4 -0
  13. package/dist_ts_chat_harness/classes.chatrequesterror.js +8 -0
  14. package/dist_ts_chat_harness/classes.transcript.d.ts +1 -1
  15. package/dist_ts_chat_harness/classes.transcript.js +1 -1
  16. package/dist_ts_chat_harness/functions.intents.d.ts +1 -2
  17. package/dist_ts_chat_harness/functions.intents.js +1 -1
  18. package/dist_ts_chat_harness/functions.mapping.d.ts +1 -1
  19. package/dist_ts_chat_harness/functions.mapping.js +1 -1
  20. package/dist_ts_chat_harness/index.d.ts +3 -0
  21. package/dist_ts_chat_harness/index.js +3 -1
  22. package/dist_ts_chat_harness/interfaces.chat.d.ts +136 -0
  23. package/dist_ts_chat_harness/interfaces.chat.js +2 -0
  24. package/dist_ts_chat_harness/plugins.js +1 -1
  25. package/dist_ts_chat_harness_server/classes.chathub.d.ts +78 -0
  26. package/dist_ts_chat_harness_server/classes.chathub.js +332 -0
  27. package/dist_ts_chat_harness_server/classes.chatsubscription.d.ts +55 -0
  28. package/dist_ts_chat_harness_server/classes.chatsubscription.js +236 -0
  29. package/dist_ts_chat_harness_server/classes.sessionlists.d.ts +21 -0
  30. package/dist_ts_chat_harness_server/classes.sessionlists.js +70 -0
  31. package/dist_ts_chat_harness_server/classes.turngate.d.ts +38 -0
  32. package/dist_ts_chat_harness_server/classes.turngate.js +207 -0
  33. package/dist_ts_chat_harness_server/errors.d.ts +5 -0
  34. package/dist_ts_chat_harness_server/errors.js +9 -0
  35. package/dist_ts_chat_harness_server/functions.errorprojector.d.ts +11 -0
  36. package/dist_ts_chat_harness_server/functions.errorprojector.js +32 -0
  37. package/dist_ts_chat_harness_server/functions.validation.d.ts +18 -0
  38. package/dist_ts_chat_harness_server/functions.validation.js +88 -0
  39. package/dist_ts_chat_harness_server/index.d.ts +4 -0
  40. package/dist_ts_chat_harness_server/index.js +4 -0
  41. package/dist_ts_chat_harness_server/interfaces.d.ts +67 -0
  42. package/dist_ts_chat_harness_server/interfaces.js +2 -0
  43. package/dist_ts_chat_harness_server/plugins.d.ts +7 -0
  44. package/dist_ts_chat_harness_server/plugins.js +6 -0
  45. package/dist_ts_chat_harness_typedsocket/classes.clienttransport.d.ts +22 -0
  46. package/dist_ts_chat_harness_typedsocket/classes.clienttransport.js +55 -0
  47. package/dist_ts_chat_harness_typedsocket/classes.serverbinding.d.ts +46 -0
  48. package/dist_ts_chat_harness_typedsocket/classes.serverbinding.js +110 -0
  49. package/dist_ts_chat_harness_typedsocket/index.d.ts +3 -0
  50. package/dist_ts_chat_harness_typedsocket/index.js +3 -0
  51. package/dist_ts_chat_harness_typedsocket/interfaces.requests.d.ts +38 -0
  52. package/dist_ts_chat_harness_typedsocket/interfaces.requests.js +2 -0
  53. package/dist_ts_chat_harness_typedsocket/plugins.d.ts +9 -0
  54. package/dist_ts_chat_harness_typedsocket/plugins.js +8 -0
  55. package/dist_ts_ocr/ocr.mistral.d.ts +20 -1
  56. package/dist_ts_ocr/ocr.mistral.js +66 -43
  57. package/dist_ts_tools/tool.filesystem.d.ts +2 -0
  58. package/dist_ts_tools/tool.filesystem.js +42 -1
  59. package/dist_ts_tools_node/classes.workspacereversion.d.ts +48 -0
  60. package/dist_ts_tools_node/classes.workspacereversion.js +202 -0
  61. package/dist_ts_tools_node/functions.fileimages.d.ts +22 -0
  62. package/dist_ts_tools_node/functions.fileimages.js +87 -0
  63. package/dist_ts_tools_node/index.d.ts +3 -1
  64. package/dist_ts_tools_node/index.js +2 -1
  65. package/dist_ts_tools_node/plugins.d.ts +1 -0
  66. package/dist_ts_tools_node/tool.context.d.ts +20 -0
  67. package/dist_ts_tools_node/tool.context.js +25 -4
  68. package/package.json +28 -4
  69. package/ts/00_commitinfo_data.ts +1 -1
  70. package/ts/errors.ts +10 -0
  71. package/ts/functions.toolpermissions.ts +60 -0
  72. package/ts/index.ts +6 -0
  73. package/ts/plugins.ts +1 -0
  74. package/ts_chat_harness/classes.chatclient.ts +343 -0
  75. package/ts_chat_harness/classes.chatrequesterror.ts +7 -0
  76. package/ts_chat_harness/classes.transcript.ts +1 -1
  77. package/ts_chat_harness/functions.intents.ts +2 -2
  78. package/ts_chat_harness/functions.mapping.ts +1 -1
  79. package/ts_chat_harness/index.ts +20 -0
  80. package/ts_chat_harness/interfaces.chat.ts +108 -0
  81. package/ts_chat_harness/readme.md +24 -0
  82. package/ts_chat_harness_server/classes.chathub.ts +400 -0
  83. package/ts_chat_harness_server/classes.chatsubscription.ts +257 -0
  84. package/ts_chat_harness_server/classes.sessionlists.ts +90 -0
  85. package/ts_chat_harness_server/classes.turngate.ts +247 -0
  86. package/ts_chat_harness_server/errors.ts +9 -0
  87. package/ts_chat_harness_server/functions.errorprojector.ts +40 -0
  88. package/ts_chat_harness_server/functions.validation.ts +104 -0
  89. package/ts_chat_harness_server/index.ts +19 -0
  90. package/ts_chat_harness_server/interfaces.ts +92 -0
  91. package/ts_chat_harness_server/plugins.ts +62 -0
  92. package/ts_chat_harness_server/readme.md +91 -0
  93. package/ts_chat_harness_typedsocket/classes.clienttransport.ts +87 -0
  94. package/ts_chat_harness_typedsocket/classes.serverbinding.ts +172 -0
  95. package/ts_chat_harness_typedsocket/index.ts +17 -0
  96. package/ts_chat_harness_typedsocket/interfaces.requests.ts +40 -0
  97. package/ts_chat_harness_typedsocket/plugins.ts +28 -0
  98. package/ts_chat_harness_typedsocket/readme.md +57 -0
  99. package/ts_ocr/ocr.mistral.ts +102 -49
  100. package/ts_ocr/readme.md +12 -1
  101. package/ts_tools/readme.md +10 -0
  102. package/ts_tools/tool.filesystem.ts +55 -0
  103. package/ts_tools_node/classes.workspacereversion.ts +255 -0
  104. package/ts_tools_node/functions.fileimages.ts +89 -0
  105. package/ts_tools_node/index.ts +7 -1
  106. package/ts_tools_node/plugins.ts +11 -0
  107. package/ts_tools_node/readme.md +27 -0
  108. package/ts_tools_node/tool.context.ts +49 -3
@@ -41,3 +41,14 @@ export type {
41
41
  TToolJobEvent,
42
42
  TToolJobEventListener,
43
43
  } from '@modelprofile.com/flexharness-agent';
44
+ export type {
45
+ IFlexAffectedWorkspace,
46
+ IFlexTurnReversionApplyContext,
47
+ IFlexTurnReversionApplyInspection,
48
+ IFlexTurnReversionBaseContext,
49
+ IFlexTurnReversionProviderV2,
50
+ IFlexTurnReversionReleaseContext,
51
+ TFlexTurnReversionCaptureInspectionV2,
52
+ TFlexTurnReversionFinalizedOutcome,
53
+ TJsonValue,
54
+ } from '@modelprofile.com/flexharness';
@@ -11,6 +11,33 @@ pnpm add @modelprofile.com/flexharness
11
11
  See the [toolbox usage and migration guide](https://code.foss.global/modelprofile.com/flexharness#readme)
12
12
  for composition examples and the SmartAI/SmartAgent migration map.
13
13
 
14
+ ## Turn reversion for local files
15
+
16
+ `InMemoryWorkspaceReversion` is a FlexHarness `turnReversionProvider` that undoes and redoes a turn's changes of the local filesystem tools together with its transcript, held in memory for the process's lifetime.
17
+
18
+ ```typescript
19
+ const reversion = new InMemoryWorkspaceReversion({ workspace: { id: rootDir, label: 'project' } });
20
+ const harness = new FlexHarness({
21
+ scopeResolver,
22
+ modelResolver,
23
+ turnReversionProvider: reversion,
24
+ reversionPolicy: 'workspace-required',
25
+ toolProvider: {
26
+ provideTools: (context) => {
27
+ const execution = createLocalToolExecutionContext({
28
+ rootDir,
29
+ cwd: rootDir,
30
+ fileChangeObserver: reversion.observerFor(context.runId),
31
+ requestPermission: createFlexToolPermissionRequester(context, { policy: { write: 'allow' } }),
32
+ });
33
+ return { tools: { ...createFilesystemTools(execution, { includeEdit: true }), ...createShellTools(execution) } };
34
+ },
35
+ },
36
+ });
37
+ ```
38
+
39
+ The `fileChangeObserver` of `createLocalToolExecutionContext` sees every write and delete by its canonical path (a write follows a symbolic link to its target, a delete removes the link itself) after the root checks and before the change, and every shell command before it starts; a rejection refuses the operation. The first change of a file in a turn records its bytes, mode or link target, and the directories a new file's write creates. Undo puts the before images back and removes those directories while empty; redo puts the after images back. Either direction applies only while every file still holds what the other direction left, so a later edit is never overwritten: the undo fails without a change and can be retried. A turn that ran a shell command is nonrevertible (`shell-command`), as is one whose images exceed `maxCaptureBytes` (64 MiB by default; `capture-too-large`). Only root-session runs are captured: a change of a run without a capture is refused. Captures do not survive a restart; FlexHarness then finds them `missing`.
40
+
14
41
  ## Issue Reporting and Security
15
42
 
16
43
  Report issues and security concerns through [community.foss.global](https://community.foss.global).
@@ -1,6 +1,26 @@
1
1
  import * as plugins from './plugins.js';
2
2
  import type { IToolJobStore, IToolPermissionRequest, IToolInvocationOptions, IToolRunOptions, IToolShellResult, IShellCommand, IToolShellContext, IToolJobRequest, IShellStartedResult, IShellFinishedResult, IToolJobState, IToolJobHandle, IToolJobEvent, IToolJobOutputEvent, TToolJobEvent, TToolJobEventListener, IToolJobContext, IToolFilesystemReadOptions, IToolFilesystemListOptions, IToolFilesystemContext, IToolBrowserRunOptions, TBrowserToolAction, IBrowserToolInput, IToolBrowserContext, IToolExecutionContext } from './plugins.js';
3
3
 
4
+ /** A file a tool is about to change, named by its canonical path. */
5
+ export interface IToolFileChange {
6
+ kind: 'write' | 'delete';
7
+ /**
8
+ * The canonical absolute path the operation changes. A write follows a symlink to its target; a
9
+ * delete removes the link itself, so its path is the link's.
10
+ */
11
+ path: string;
12
+ }
13
+
14
+ /**
15
+ * Sees every change the local filesystem tools make, after the path checks and before the change,
16
+ * and every shell command before it starts. A rejection refuses the operation.
17
+ */
18
+ export interface IToolFileChangeObserver {
19
+ beforeFileChange(change: IToolFileChange): Promise<void> | void;
20
+ /** A shell command or background job may change files the observer does not see. */
21
+ beforeShellCommand(): Promise<void> | void;
22
+ }
23
+
4
24
  export interface ILocalToolExecutionContextOptions {
5
25
  cwd?: string;
6
26
  rootDir?: string;
@@ -9,6 +29,8 @@ export interface ILocalToolExecutionContextOptions {
9
29
  abortSignal?: AbortSignal;
10
30
  /** Guards each local filesystem operation or shell side effect. */
11
31
  beforeOperation?: () => Promise<void> | void;
32
+ /** Observes every file change and shell command, for example to capture a turn for undo. */
33
+ fileChangeObserver?: IToolFileChangeObserver;
12
34
  /** Hard combined stdout/stderr capture limit for each local shell command. Default: 1 MiB. */
13
35
  maxShellOutputBytes?: number;
14
36
  /** Number of terminal background job snapshots retained for get/list. Default: 100. */
@@ -58,6 +80,13 @@ export const createLocalToolExecutionContext = (options: ILocalToolExecutionCont
58
80
  if (!Number.isSafeInteger(jobStoreOperationTimeoutMs) || jobStoreOperationTimeoutMs <= 0) {
59
81
  throw new Error('jobStoreOperationTimeoutMs must be a positive integer.');
60
82
  }
83
+ const fileChangeObserver = options.fileChangeObserver;
84
+ const beforeShellOperation: ILocalToolExecutionContextOptions['beforeOperation'] = fileChangeObserver
85
+ ? async () => {
86
+ await options.beforeOperation?.();
87
+ await fileChangeObserver.beforeShellCommand();
88
+ }
89
+ : options.beforeOperation;
61
90
  const jobs = createLocalToolJobContext({
62
91
  cwd,
63
92
  rootDir,
@@ -67,7 +96,7 @@ export const createLocalToolExecutionContext = (options: ILocalToolExecutionCont
67
96
  outputListenerTimeoutMs,
68
97
  jobStoreOperationTimeoutMs,
69
98
  settleOrphanedJob: options.settleOrphanedJob,
70
- beforeOperation: options.beforeOperation,
99
+ beforeOperation: beforeShellOperation,
71
100
  abortSignal: options.abortSignal,
72
101
  });
73
102
  return {
@@ -84,7 +113,7 @@ export const createLocalToolExecutionContext = (options: ILocalToolExecutionCont
84
113
  onOutput: runOptions?.onOutput,
85
114
  outputListenerTimeoutMs,
86
115
  maxOutputBytes: maxShellOutputBytes,
87
- beforeOperation: options.beforeOperation,
116
+ beforeOperation: beforeShellOperation,
88
117
  }),
89
118
  runStructured: (command, runOptions) => runLocalStructuredCommand(command, {
90
119
  cwd: resolveLocalPath(runOptions?.cwd ?? cwd, rootDir),
@@ -93,7 +122,7 @@ export const createLocalToolExecutionContext = (options: ILocalToolExecutionCont
93
122
  onOutput: runOptions?.onOutput,
94
123
  outputListenerTimeoutMs,
95
124
  maxOutputBytes: maxShellOutputBytes,
96
- beforeOperation: options.beforeOperation,
125
+ beforeOperation: beforeShellOperation,
97
126
  }),
98
127
  },
99
128
  jobs,
@@ -147,6 +176,13 @@ export const createLocalToolExecutionContext = (options: ILocalToolExecutionCont
147
176
  canonicalBoundary.rootDir,
148
177
  );
149
178
  }
179
+ if (fileChangeObserver) {
180
+ await fileChangeObserver.beforeFileChange({
181
+ kind: 'write',
182
+ path: await resolveCanonicalProspectivePath(resolved),
183
+ });
184
+ throwIfAborted(abortSignal);
185
+ }
150
186
  await runBeforeLocalOperation(options.beforeOperation, abortSignal);
151
187
  await plugins.fs.promises.mkdir(parentPath, { recursive: true });
152
188
  throwIfAborted(abortSignal);
@@ -193,6 +229,16 @@ export const createLocalToolExecutionContext = (options: ILocalToolExecutionCont
193
229
  if (rootDir) {
194
230
  await resolveCanonicalExistingLocalPath(resolved, targetPath, rootDir);
195
231
  }
232
+ if (fileChangeObserver) {
233
+ await fileChangeObserver.beforeFileChange({
234
+ kind: 'delete',
235
+ path: plugins.path.join(
236
+ await resolveCanonicalProspectivePath(plugins.path.dirname(resolved)),
237
+ plugins.path.basename(resolved),
238
+ ),
239
+ });
240
+ throwIfAborted(abortSignal);
241
+ }
196
242
  await runBeforeLocalOperation(options.beforeOperation, abortSignal);
197
243
  await plugins.fs.promises.rm(resolved, { recursive: false, force: false });
198
244
  throwIfAborted(abortSignal);