@modelprofile.com/flexharness 10.17.0 → 10.18.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 (104) 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_tools/tool.filesystem.d.ts +2 -0
  56. package/dist_ts_tools/tool.filesystem.js +42 -1
  57. package/dist_ts_tools_node/classes.workspacereversion.d.ts +48 -0
  58. package/dist_ts_tools_node/classes.workspacereversion.js +202 -0
  59. package/dist_ts_tools_node/functions.fileimages.d.ts +22 -0
  60. package/dist_ts_tools_node/functions.fileimages.js +87 -0
  61. package/dist_ts_tools_node/index.d.ts +3 -1
  62. package/dist_ts_tools_node/index.js +2 -1
  63. package/dist_ts_tools_node/plugins.d.ts +1 -0
  64. package/dist_ts_tools_node/tool.context.d.ts +20 -0
  65. package/dist_ts_tools_node/tool.context.js +25 -4
  66. package/package.json +28 -4
  67. package/ts/00_commitinfo_data.ts +1 -1
  68. package/ts/errors.ts +10 -0
  69. package/ts/functions.toolpermissions.ts +60 -0
  70. package/ts/index.ts +6 -0
  71. package/ts/plugins.ts +1 -0
  72. package/ts_chat_harness/classes.chatclient.ts +343 -0
  73. package/ts_chat_harness/classes.chatrequesterror.ts +7 -0
  74. package/ts_chat_harness/classes.transcript.ts +1 -1
  75. package/ts_chat_harness/functions.intents.ts +2 -2
  76. package/ts_chat_harness/functions.mapping.ts +1 -1
  77. package/ts_chat_harness/index.ts +20 -0
  78. package/ts_chat_harness/interfaces.chat.ts +108 -0
  79. package/ts_chat_harness/readme.md +24 -0
  80. package/ts_chat_harness_server/classes.chathub.ts +400 -0
  81. package/ts_chat_harness_server/classes.chatsubscription.ts +257 -0
  82. package/ts_chat_harness_server/classes.sessionlists.ts +90 -0
  83. package/ts_chat_harness_server/classes.turngate.ts +247 -0
  84. package/ts_chat_harness_server/errors.ts +9 -0
  85. package/ts_chat_harness_server/functions.errorprojector.ts +40 -0
  86. package/ts_chat_harness_server/functions.validation.ts +104 -0
  87. package/ts_chat_harness_server/index.ts +19 -0
  88. package/ts_chat_harness_server/interfaces.ts +92 -0
  89. package/ts_chat_harness_server/plugins.ts +62 -0
  90. package/ts_chat_harness_server/readme.md +91 -0
  91. package/ts_chat_harness_typedsocket/classes.clienttransport.ts +87 -0
  92. package/ts_chat_harness_typedsocket/classes.serverbinding.ts +172 -0
  93. package/ts_chat_harness_typedsocket/index.ts +17 -0
  94. package/ts_chat_harness_typedsocket/interfaces.requests.ts +40 -0
  95. package/ts_chat_harness_typedsocket/plugins.ts +28 -0
  96. package/ts_chat_harness_typedsocket/readme.md +57 -0
  97. package/ts_tools/readme.md +10 -0
  98. package/ts_tools/tool.filesystem.ts +55 -0
  99. package/ts_tools_node/classes.workspacereversion.ts +255 -0
  100. package/ts_tools_node/functions.fileimages.ts +89 -0
  101. package/ts_tools_node/index.ts +7 -1
  102. package/ts_tools_node/plugins.ts +11 -0
  103. package/ts_tools_node/readme.md +27 -0
  104. package/ts_tools_node/tool.context.ts +49 -3
@@ -0,0 +1,7 @@
1
+ import { FlexHarnessClosedError, FlexHarnessError, FlexHarnessNotFoundError, FlexHarnessSteerRejectedError, FlexHarnessValidationError, modelLimitErrorInfo } from '@modelprofile.com/flexharness';
2
+ import { FlexHarnessChatRequestError, FlexHarnessTranscript, flexHarnessSendIntent, flexSessionToHarnessMeta } from '@modelprofile.com/flexharness/chat/harness';
3
+ import { describeModelFailure } from '@modelprofile.com/flexharness-models';
4
+ export { FlexHarnessChatRequestError, FlexHarnessClosedError, FlexHarnessError, FlexHarnessNotFoundError, FlexHarnessSteerRejectedError, FlexHarnessTranscript, FlexHarnessValidationError, describeModelFailure, flexHarnessSendIntent, flexSessionToHarnessMeta, modelLimitErrorInfo, };
5
+ export type { FlexHarness, IFlexErrorInfo, IFlexExternalErrorContext, IFlexPromptQueueAdmission, IFlexSession, IFlexSessionCreatedEvent, IFlexSessionDeletedEvent, IFlexSessionUpdatedEvent, TFlexExternalErrorProjector, TFlexHarnessEvent, TJsonValue, } from '@modelprofile.com/flexharness';
6
+ export type { IFlexHarnessChatHistoryState, IFlexHarnessChatMethods, IFlexHarnessChatSessionsPush, IFlexHarnessChatSteerOutcome, IFlexHarnessChatToolRequest, IFlexHarnessChatUpdate, TFlexHarnessChatRequest, TFlexHarnessChatResponse, } from '@modelprofile.com/flexharness/chat/harness';
7
+ export type { IHarnessAttachment, IHarnessComposerSendDetail, IHarnessMessage, IHarnessSessionMeta, THarnessStreamDelta, } from '@design.estate/dees-catalog';
@@ -0,0 +1,6 @@
1
+ // @modelprofile.com scope
2
+ import { FlexHarnessClosedError, FlexHarnessError, FlexHarnessNotFoundError, FlexHarnessSteerRejectedError, FlexHarnessValidationError, modelLimitErrorInfo, } from '@modelprofile.com/flexharness';
3
+ import { FlexHarnessChatRequestError, FlexHarnessTranscript, flexHarnessSendIntent, flexSessionToHarnessMeta, } from '@modelprofile.com/flexharness/chat/harness';
4
+ import { describeModelFailure } from '@modelprofile.com/flexharness-models';
5
+ export { FlexHarnessChatRequestError, FlexHarnessClosedError, FlexHarnessError, FlexHarnessNotFoundError, FlexHarnessSteerRejectedError, FlexHarnessTranscript, FlexHarnessValidationError, describeModelFailure, flexHarnessSendIntent, flexSessionToHarnessMeta, modelLimitErrorInfo, };
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX2NoYXRfaGFybmVzc19zZXJ2ZXIvcGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwwQkFBMEI7QUFDMUIsT0FBTyxFQUNMLHNCQUFzQixFQUN0QixnQkFBZ0IsRUFDaEIsd0JBQXdCLEVBQ3hCLDZCQUE2QixFQUM3QiwwQkFBMEIsRUFDMUIsbUJBQW1CLEdBQ3BCLE1BQU0sK0JBQStCLENBQUM7QUFDdkMsT0FBTyxFQUNMLDJCQUEyQixFQUMzQixxQkFBcUIsRUFDckIscUJBQXFCLEVBQ3JCLHdCQUF3QixHQUN6QixNQUFNLDRDQUE0QyxDQUFDO0FBQ3BELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBRTVFLE9BQU8sRUFDTCwyQkFBMkIsRUFDM0Isc0JBQXNCLEVBQ3RCLGdCQUFnQixFQUNoQix3QkFBd0IsRUFDeEIsNkJBQTZCLEVBQzdCLHFCQUFxQixFQUNyQiwwQkFBMEIsRUFDMUIsb0JBQW9CLEVBQ3BCLHFCQUFxQixFQUNyQix3QkFBd0IsRUFDeEIsbUJBQW1CLEdBQ3BCLENBQUMifQ==
@@ -0,0 +1,22 @@
1
+ import * as plugins from './plugins.js';
2
+ export interface IFlexHarnessChatTypedSocketTransportOptions {
3
+ /** The tab's TypedSocket client. */
4
+ typedsocket: plugins.typedsocket.TypedSocket;
5
+ /** The router the client was created with; the transport adds its push handlers to it. */
6
+ typedrouter: plugins.typedrequest.TypedRouter;
7
+ /** The tab: 16 random bytes in hex. Defaults to a new random id for this transport's lifetime. */
8
+ tabId?: string;
9
+ /** The opaque credential the server's `resolve` reads, read for every request. */
10
+ callerToken?: () => string | undefined;
11
+ }
12
+ /** A `FlexHarnessChatClient` transport over the tab's TypedSocket client. */
13
+ export declare class FlexHarnessChatTypedSocketTransport implements plugins.IFlexHarnessChatClientTransport {
14
+ readonly tabId: string;
15
+ private readonly socket;
16
+ private readonly router;
17
+ private readonly callerToken;
18
+ constructor(optionsArg: IFlexHarnessChatTypedSocketTransportOptions);
19
+ request<TMethod extends plugins.TFlexHarnessChatMethod>(methodArg: TMethod, requestArg: plugins.TFlexHarnessChatRequest<TMethod>): Promise<plugins.TFlexHarnessChatResponse<TMethod>>;
20
+ listen(handlersArg: plugins.IFlexHarnessChatPushHandlers): () => void;
21
+ onReconnect(callbackArg: () => void): () => void;
22
+ }
@@ -0,0 +1,55 @@
1
+ import * as plugins from './plugins.js';
2
+ /** 128 random bits as hex; `getRandomValues` works on plain http too, unlike `randomUUID`. */
3
+ const randomTabId = () => Array.from(globalThis.crypto.getRandomValues(new Uint8Array(16)), (byte) => byte.toString(16).padStart(2, '0')).join('');
4
+ /** A `FlexHarnessChatClient` transport over the tab's TypedSocket client. */
5
+ export class FlexHarnessChatTypedSocketTransport {
6
+ tabId;
7
+ socket;
8
+ router;
9
+ callerToken;
10
+ constructor(optionsArg) {
11
+ this.socket = optionsArg.typedsocket;
12
+ this.router = optionsArg.typedrouter;
13
+ this.tabId = optionsArg.tabId ?? randomTabId();
14
+ this.callerToken = optionsArg.callerToken ?? (() => undefined);
15
+ }
16
+ async request(methodArg, requestArg) {
17
+ const token = this.callerToken();
18
+ return this.socket.createTypedRequest(methodArg).fire({
19
+ ...requestArg,
20
+ caller: { tabId: this.tabId, ...(token === undefined ? {} : { token }) },
21
+ });
22
+ }
23
+ listen(handlersArg) {
24
+ const pushes = new plugins.typedrequest.TypedRouter();
25
+ pushes.addTypedHandler(new plugins.typedrequest.TypedHandler('flexHarnessChatUpdate', async (pushArg) => {
26
+ handlersArg.update(pushArg);
27
+ return {};
28
+ }));
29
+ pushes.addTypedHandler(new plugins.typedrequest.TypedHandler('flexHarnessChatSessions', async (pushArg) => {
30
+ handlersArg.sessions(pushArg);
31
+ return {};
32
+ }));
33
+ pushes.addTypedHandler(new plugins.typedrequest.TypedHandler('flexHarnessChatTool', async (requestArg, toolsArg) => ({
34
+ // the server cancels the request when the turn stops or the call times out; the handler then
35
+ // settles at once, since TypedSocket fails a connection whose handlers outlive their requests
36
+ output: await handlersArg.tool(requestArg, toolsArg?.abortSignal),
37
+ })));
38
+ return this.router.addTypedRouter(pushes);
39
+ }
40
+ onReconnect(callbackArg) {
41
+ let wasConnected = true;
42
+ const subscription = this.socket.statusSubject.subscribe((statusArg) => {
43
+ if (statusArg !== 'connected') {
44
+ wasConnected = false;
45
+ return;
46
+ }
47
+ if (wasConnected)
48
+ return;
49
+ wasConnected = true;
50
+ callbackArg();
51
+ });
52
+ return () => subscription.unsubscribe();
53
+ }
54
+ }
55
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5jbGllbnR0cmFuc3BvcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19jaGF0X2hhcm5lc3NfdHlwZWRzb2NrZXQvY2xhc3Nlcy5jbGllbnR0cmFuc3BvcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFtQnhDLDhGQUE4RjtBQUM5RixNQUFNLFdBQVcsR0FBRyxHQUFXLEVBQUUsQ0FDL0IsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7QUFFM0gsNkVBQTZFO0FBQzdFLE1BQU0sT0FBTyxtQ0FBbUM7SUFDOUIsS0FBSyxDQUFTO0lBRWIsTUFBTSxDQUFrQztJQUN4QyxNQUFNLENBQW1DO0lBQ3pDLFdBQVcsQ0FBMkI7SUFFdkQsWUFBWSxVQUF1RDtRQUNqRSxJQUFJLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxXQUFXLENBQUM7UUFDckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsV0FBVyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDLEtBQUssSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUMvQyxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQyxXQUFXLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBRU0sS0FBSyxDQUFDLE9BQU8sQ0FDbEIsU0FBa0IsRUFDbEIsVUFBb0Q7UUFFcEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ2pDLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBZ0MsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ25GLEdBQUcsVUFBVTtZQUNiLE1BQU0sRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRTtTQUN6RSxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU0sTUFBTSxDQUFDLFdBQWlEO1FBQzdELE1BQU0sTUFBTSxHQUFHLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN0RCxNQUFNLENBQUMsZUFBZSxDQUNwQixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUE2Qix1QkFBdUIsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDM0csV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM1QixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQyxDQUNILENBQUM7UUFDRixNQUFNLENBQUMsZUFBZSxDQUNwQixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUErQix5QkFBeUIsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDL0csV0FBVyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM5QixPQUFPLEVBQUUsQ0FBQztRQUNaLENBQUMsQ0FBQyxDQUNILENBQUM7UUFDRixNQUFNLENBQUMsZUFBZSxDQUNwQixJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUEyQixxQkFBcUIsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN0SCw2RkFBNkY7WUFDN0YsOEZBQThGO1lBQzlGLE1BQU0sRUFBRSxNQUFNLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFFBQVEsRUFBRSxXQUFXLENBQUM7U0FDbEUsQ0FBQyxDQUFDLENBQ0osQ0FBQztRQUNGLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUVNLFdBQVcsQ0FBQyxXQUF1QjtRQUN4QyxJQUFJLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDeEIsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDckUsSUFBSSxTQUFTLEtBQUssV0FBVyxFQUFFLENBQUM7Z0JBQzlCLFlBQVksR0FBRyxLQUFLLENBQUM7Z0JBQ3JCLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxZQUFZO2dCQUFFLE9BQU87WUFDekIsWUFBWSxHQUFHLElBQUksQ0FBQztZQUNwQixXQUFXLEVBQUUsQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztRQUNILE9BQU8sR0FBRyxFQUFFLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzFDLENBQUM7Q0FDRiJ9
@@ -0,0 +1,46 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { IFlexHarnessChatCallerPayload } from './interfaces.requests.js';
3
+ /** The hub requests the binding routes; any `FlexHarnessChatHub` serves them. */
4
+ export type TFlexHarnessChatRequestHandler = Pick<plugins.FlexHarnessChatHub<unknown>, 'attach' | 'open' | 'close' | 'send' | 'abort' | 'respondToPermission' | 'moveHistory' | 'renameSession' | 'deleteSession'>;
5
+ /** The hub and scope a request reaches, as the host established them. */
6
+ export interface IFlexHarnessChatResolvedCaller {
7
+ hub: TFlexHarnessChatRequestHandler;
8
+ scopeId: string;
9
+ }
10
+ export interface IFlexHarnessChatTypedSocketBindingOptions {
11
+ /**
12
+ * Authenticates a request: from the caller payload and the request's TypedSocket context, the hub
13
+ * and the scope it reaches. Throw a `FlexHarnessChatRequestError` to refuse with a message.
14
+ */
15
+ resolve(caller: IFlexHarnessChatCallerPayload, context: plugins.typedsocket.ITypedSocketRequestContext | undefined): Promise<IFlexHarnessChatResolvedCaller>;
16
+ /** The server-owned connection tag that names a tab. Default: `flexHarnessChatTab`. */
17
+ tag?: string;
18
+ /** How long an update or a session-list push may wait for the tab. Default: 30 seconds. */
19
+ pushTimeoutMs?: number;
20
+ }
21
+ /**
22
+ * Serves a `FlexHarnessChatHub` over TypedSocket. Add `typedrouter` to the server's router, hand
23
+ * the server's TypedSocket to `setTypedSocket()` once it runs, and give the hub `peers`. A tab's
24
+ * connection carries the server-owned tag with its tab id; every request claims it again.
25
+ */
26
+ export declare class FlexHarnessChatTypedSocketBinding implements plugins.IFlexHarnessChatPeers {
27
+ readonly typedrouter: plugins.typedrequest.TypedRouter<plugins.typedrequestInterfaces.ITypedRequest>;
28
+ private readonly resolveCaller;
29
+ private readonly tag;
30
+ private readonly pushTimeoutMs;
31
+ private socket;
32
+ constructor(optionsArg: IFlexHarnessChatTypedSocketBindingOptions);
33
+ /** The server's TypedSocket; it exists once the server runs. */
34
+ setTypedSocket(socketArg: plugins.typedsocket.TypedSocket): void;
35
+ /** The tab's current connection in its scope, as the hub reaches it. */
36
+ find(tabArg: plugins.IFlexHarnessChatCaller): Promise<plugins.IFlexHarnessChatPeer | null>;
37
+ private route;
38
+ /** Authenticates a request, claims its connection for the tab and runs it on the resolved hub. */
39
+ private serve;
40
+ /**
41
+ * Marks the connection the request came in on as the tab's, and only that one. The tag names the
42
+ * tab in its resolved scope, so a caller of another scope that sends the same tab id names a tab
43
+ * of its own and never reaches this one's connection.
44
+ */
45
+ private claim;
46
+ }
@@ -0,0 +1,110 @@
1
+ import * as plugins from './plugins.js';
2
+ const TAB_ID_PATTERN = /^[0-9a-f]{32}$/;
3
+ const BAD_REQUEST_MESSAGE = 'The request is malformed. Reload the page and try again.';
4
+ const NOT_READY_MESSAGE = 'The server is not accepting connections yet.';
5
+ /** The tag payload that names a tab: its scope and its id, in a fixed key order. */
6
+ const tagPayload = (tabArg) => ({
7
+ scopeId: tabArg.scopeId,
8
+ tabId: tabArg.tabId,
9
+ });
10
+ class TypedSocketChatPeer {
11
+ socket;
12
+ connection;
13
+ pushTimeoutMs;
14
+ constructor(socket, connection, pushTimeoutMs) {
15
+ this.socket = socket;
16
+ this.connection = connection;
17
+ this.pushTimeoutMs = pushTimeoutMs;
18
+ }
19
+ async update(pushArg) {
20
+ await this.socket
21
+ .createTypedRequest('flexHarnessChatUpdate', this.connection, { timeoutMs: this.pushTimeoutMs })
22
+ .fire(pushArg);
23
+ }
24
+ async sessions(pushArg) {
25
+ await this.socket
26
+ .createTypedRequest('flexHarnessChatSessions', this.connection, { timeoutMs: this.pushTimeoutMs })
27
+ .fire(pushArg);
28
+ }
29
+ async runTool(requestArg, optionsArg) {
30
+ const answer = await this.socket
31
+ .createTypedRequest('flexHarnessChatTool', this.connection, optionsArg)
32
+ .fire(requestArg);
33
+ return answer.output;
34
+ }
35
+ }
36
+ /**
37
+ * Serves a `FlexHarnessChatHub` over TypedSocket. Add `typedrouter` to the server's router, hand
38
+ * the server's TypedSocket to `setTypedSocket()` once it runs, and give the hub `peers`. A tab's
39
+ * connection carries the server-owned tag with its tab id; every request claims it again.
40
+ */
41
+ export class FlexHarnessChatTypedSocketBinding {
42
+ typedrouter = new plugins.typedrequest.TypedRouter();
43
+ resolveCaller;
44
+ tag;
45
+ pushTimeoutMs;
46
+ socket = null;
47
+ constructor(optionsArg) {
48
+ this.resolveCaller = optionsArg.resolve;
49
+ this.tag = optionsArg.tag ?? 'flexHarnessChatTab';
50
+ this.pushTimeoutMs = optionsArg.pushTimeoutMs ?? 30 * 1000;
51
+ this.route('flexHarnessChatAttach', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.attach(caller)));
52
+ this.route('flexHarnessChatOpen', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.open(caller, request)));
53
+ this.route('flexHarnessChatClose', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.close(caller, request)));
54
+ this.route('flexHarnessChatSend', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.send(caller, request)));
55
+ this.route('flexHarnessChatAbort', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.abort(caller, request)));
56
+ this.route('flexHarnessChatPermission', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.respondToPermission(caller, request)));
57
+ this.route('flexHarnessChatHistory', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.moveHistory(caller, request)));
58
+ this.route('flexHarnessChatSessionUpdate', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.renameSession(caller, request)));
59
+ this.route('flexHarnessChatSessionDelete', (request, tools) => this.serve(request.caller, tools, (hub, caller) => hub.deleteSession(caller, request)));
60
+ }
61
+ /** The server's TypedSocket; it exists once the server runs. */
62
+ setTypedSocket(socketArg) {
63
+ this.socket = socketArg;
64
+ }
65
+ /** The tab's current connection in its scope, as the hub reaches it. */
66
+ async find(tabArg) {
67
+ if (!this.socket)
68
+ return null;
69
+ const connection = await this.socket.findTargetConnectionByTag(this.tag, tagPayload(tabArg));
70
+ return connection ? new TypedSocketChatPeer(this.socket, connection, this.pushTimeoutMs) : null;
71
+ }
72
+ route(methodArg, handlerArg) {
73
+ this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler(methodArg, handlerArg));
74
+ }
75
+ /** Authenticates a request, claims its connection for the tab and runs it on the resolved hub. */
76
+ async serve(payloadArg, contextArg, runArg) {
77
+ try {
78
+ if (!payloadArg || typeof payloadArg.tabId !== 'string' || !TAB_ID_PATTERN.test(payloadArg.tabId)) {
79
+ throw new plugins.FlexHarnessChatRequestError(BAD_REQUEST_MESSAGE);
80
+ }
81
+ const resolved = await this.resolveCaller(payloadArg, contextArg);
82
+ const caller = { tabId: payloadArg.tabId, scopeId: resolved.scopeId };
83
+ await this.claim(contextArg, caller);
84
+ return await runArg(resolved.hub, caller);
85
+ }
86
+ catch (error) {
87
+ if (error instanceof plugins.FlexHarnessChatRequestError) {
88
+ throw new plugins.typedrequest.TypedResponseError(error.message);
89
+ }
90
+ throw error;
91
+ }
92
+ }
93
+ /**
94
+ * Marks the connection the request came in on as the tab's, and only that one. The tag names the
95
+ * tab in its resolved scope, so a caller of another scope that sends the same tab id names a tab
96
+ * of its own and never reaches this one's connection.
97
+ */
98
+ async claim(contextArg, tabArg) {
99
+ if (!this.socket)
100
+ throw new plugins.FlexHarnessChatRequestError(NOT_READY_MESSAGE);
101
+ const connection = this.socket.getServerConnectionForRequest(contextArg);
102
+ const payload = tagPayload(tabArg);
103
+ for (const other of await this.socket.findAllTargetConnectionsByTag(this.tag, payload)) {
104
+ if (other.peer !== connection.peer)
105
+ this.socket.removeServerTag(other, this.tag);
106
+ }
107
+ this.socket.setServerTag(connection, this.tag, payload);
108
+ }
109
+ }
110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZXJ2ZXJiaW5kaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfY2hhdF9oYXJuZXNzX3R5cGVkc29ja2V0L2NsYXNzZXMuc2VydmVyYmluZGluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQW9DeEMsTUFBTSxjQUFjLEdBQUcsZ0JBQWdCLENBQUM7QUFDeEMsTUFBTSxtQkFBbUIsR0FBRywwREFBMEQsQ0FBQztBQUN2RixNQUFNLGlCQUFpQixHQUFHLDhDQUE4QyxDQUFDO0FBRXpFLG9GQUFvRjtBQUNwRixNQUFNLFVBQVUsR0FBRyxDQUFDLE1BQXNDLEVBQXNDLEVBQUUsQ0FBQyxDQUFDO0lBQ2xHLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztJQUN2QixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7Q0FDcEIsQ0FBQyxDQUFDO0FBRUgsTUFBTSxtQkFBbUI7SUFFSjtJQUNBO0lBQ0E7SUFIbkIsWUFDbUIsTUFBdUMsRUFDdkMsVUFBNEQsRUFDNUQsYUFBcUI7UUFGckIsV0FBTSxHQUFOLE1BQU0sQ0FBaUM7UUFDdkMsZUFBVSxHQUFWLFVBQVUsQ0FBa0Q7UUFDNUQsa0JBQWEsR0FBYixhQUFhLENBQVE7SUFDckMsQ0FBQztJQUVHLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBdUM7UUFDekQsTUFBTSxJQUFJLENBQUMsTUFBTTthQUNkLGtCQUFrQixDQUE2Qix1QkFBdUIsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQzthQUMzSCxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUVNLEtBQUssQ0FBQyxRQUFRLENBQUMsT0FBNkM7UUFDakUsTUFBTSxJQUFJLENBQUMsTUFBTTthQUNkLGtCQUFrQixDQUErQix5QkFBeUIsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFF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
@@ -0,0 +1,3 @@
1
+ export { FlexHarnessChatTypedSocketBinding, type IFlexHarnessChatResolvedCaller, type IFlexHarnessChatTypedSocketBindingOptions, type TFlexHarnessChatRequestHandler, } from './classes.serverbinding.js';
2
+ export { FlexHarnessChatTypedSocketTransport, type IFlexHarnessChatTypedSocketTransportOptions, } from './classes.clienttransport.js';
3
+ export type { IFlexHarnessChatCallerPayload, IReq_FlexHarnessChat, IReq_FlexHarnessChatSessions, IReq_FlexHarnessChatTool, IReq_FlexHarnessChatUpdate, } from './interfaces.requests.js';
@@ -0,0 +1,3 @@
1
+ export { FlexHarnessChatTypedSocketBinding, } from './classes.serverbinding.js';
2
+ export { FlexHarnessChatTypedSocketTransport, } from './classes.clienttransport.js';
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c19jaGF0X2hhcm5lc3NfdHlwZWRzb2NrZXQvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLGlDQUFpQyxHQUlsQyxNQUFNLDRCQUE0QixDQUFDO0FBQ3BDLE9BQU8sRUFDTCxtQ0FBbUMsR0FFcEMsTUFBTSw4QkFBOEIsQ0FBQyJ9
@@ -0,0 +1,38 @@
1
+ import type * as plugins from './plugins.js';
2
+ /** Who sends a request: the tab, and an opaque credential the host's `resolve` reads. */
3
+ export interface IFlexHarnessChatCallerPayload {
4
+ /**
5
+ * The tab: 16 random bytes in hex, kept for the tab's lifetime and never shared. Every request
6
+ * claims the connection it arrives on for the tab, so pushes and tool calls follow a reconnect.
7
+ */
8
+ tabId: string;
9
+ token?: string;
10
+ }
11
+ /** A tab's request to the hub over TypedSocket. */
12
+ export interface IReq_FlexHarnessChat<TMethod extends plugins.TFlexHarnessChatMethod> extends plugins.typedrequestInterfaces.ITypedRequest {
13
+ method: TMethod;
14
+ request: plugins.TFlexHarnessChatRequest<TMethod> & {
15
+ caller: IFlexHarnessChatCallerPayload;
16
+ };
17
+ response: plugins.TFlexHarnessChatResponse<TMethod>;
18
+ }
19
+ /** Push: what changed in the conversation a tab follows. */
20
+ export interface IReq_FlexHarnessChatUpdate extends plugins.typedrequestInterfaces.ITypedRequest {
21
+ method: 'flexHarnessChatUpdate';
22
+ request: plugins.IFlexHarnessChatUpdate;
23
+ response: Record<string, never>;
24
+ }
25
+ /** Push: changes of the tab's conversation list. */
26
+ export interface IReq_FlexHarnessChatSessions extends plugins.typedrequestInterfaces.ITypedRequest {
27
+ method: 'flexHarnessChatSessions';
28
+ request: plugins.IFlexHarnessChatSessionsPush;
29
+ response: Record<string, never>;
30
+ }
31
+ /** Push: run a tool of a turn in the tab; the answer is the tool's output. */
32
+ export interface IReq_FlexHarnessChatTool extends plugins.typedrequestInterfaces.ITypedRequest {
33
+ method: 'flexHarnessChatTool';
34
+ request: plugins.IFlexHarnessChatToolRequest;
35
+ response: {
36
+ output: plugins.TJsonValue;
37
+ };
38
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW50ZXJmYWNlcy5yZXF1ZXN0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX2NoYXRfaGFybmVzc190eXBlZHNvY2tldC9pbnRlcmZhY2VzLnJlcXVlc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -0,0 +1,9 @@
1
+ import * as typedrequest from '@api.global/typedrequest';
2
+ import * as typedsocket from '@api.global/typedsocket';
3
+ export { typedrequest, typedsocket };
4
+ export type * as typedrequestInterfaces from '@api.global/typedrequest-interfaces';
5
+ import { FlexHarnessChatRequestError } from '@modelprofile.com/flexharness/chat/harness';
6
+ export { FlexHarnessChatRequestError };
7
+ export type { TJsonValue } from '@modelprofile.com/flexharness';
8
+ export type { IFlexHarnessChatClientTransport, IFlexHarnessChatPushHandlers, IFlexHarnessChatSessionsPush, IFlexHarnessChatToolRequest, IFlexHarnessChatUpdate, TFlexHarnessChatMethod, TFlexHarnessChatRequest, TFlexHarnessChatResponse, } from '@modelprofile.com/flexharness/chat/harness';
9
+ export type { FlexHarnessChatHub, IFlexHarnessChatCaller, IFlexHarnessChatPeer, IFlexHarnessChatPeers, } from '@modelprofile.com/flexharness/chat/harness/server';
@@ -0,0 +1,8 @@
1
+ // @api.global scope
2
+ import * as typedrequest from '@api.global/typedrequest';
3
+ import * as typedsocket from '@api.global/typedsocket';
4
+ export { typedrequest, typedsocket };
5
+ // @modelprofile.com scope
6
+ import { FlexHarnessChatRequestError } from '@modelprofile.com/flexharness/chat/harness';
7
+ export { FlexHarnessChatRequestError };
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX2NoYXRfaGFybmVzc190eXBlZHNvY2tldC9wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLG9CQUFvQjtBQUNwQixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFFdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUdyQywwQkFBMEI7QUFDMUIsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFFekYsT0FBTyxFQUFFLDJCQUEyQixFQUFFLENBQUMifQ==
@@ -3,6 +3,8 @@ import { type IToolExecutionContext } from './tool.context.js';
3
3
  export interface ICreateFilesystemToolsOptions {
4
4
  /** Include delete_file. Default: true. */
5
5
  includeDelete?: boolean;
6
+ /** Include edit_file, which replaces an exact snippet of a file. Default: false. */
7
+ includeEdit?: boolean;
6
8
  /** Maximum output lines before truncating. */
7
9
  maxLines?: number;
8
10
  /** Maximum output bytes before truncating. */
@@ -75,6 +75,47 @@ export function createFilesystemTools(context, options = {}) {
75
75
  },
76
76
  }),
77
77
  };
78
+ if (options.includeEdit === true) {
79
+ tools.edit_file = plugins.tool({
80
+ description: 'Replace an exact snippet of a UTF-8 file in the active workspace. `find` must occur exactly once unless `replaceAll` is set; include enough surrounding text to make it unique. Requires host permission when configured.',
81
+ inputSchema: plugins.z.object({
82
+ path: plugins.z.string().describe('File path'),
83
+ find: plugins.z.string().min(1).describe('Exact text to replace, copied from the current file'),
84
+ replace: plugins.z.string().describe('The text to put in its place'),
85
+ replaceAll: plugins.z
86
+ .boolean()
87
+ .optional()
88
+ .describe('Replace every occurrence instead of exactly one. Default: false'),
89
+ }),
90
+ execute: async ({ path: filePath, find, replace, replaceAll, }, invocationOptions) => {
91
+ if (!context.fs) {
92
+ throw new Error('Filesystem tools are not available in this execution context.');
93
+ }
94
+ const abortSignal = invocationOptions?.abortSignal ?? context.abortSignal;
95
+ const invocation = { toolCallId: invocationOptions?.toolCallId, abortSignal };
96
+ // asked before the file is read: an edit made while the request waits is kept, not overwritten
97
+ await context.requestPermission?.({
98
+ type: 'write',
99
+ title: 'Edit file',
100
+ metadata: { path: filePath },
101
+ toolCallId: invocationOptions?.toolCallId,
102
+ abortSignal,
103
+ });
104
+ const content = await context.fs.readFile(filePath, undefined, invocation);
105
+ const occurrences = content.split(find).length - 1;
106
+ if (occurrences === 0) {
107
+ throw new Error(`The text to replace does not occur in ${filePath}.`);
108
+ }
109
+ if (occurrences > 1 && replaceAll !== true) {
110
+ throw new Error(`The text to replace occurs ${occurrences} times in ${filePath}; include more surrounding text or set replaceAll.`);
111
+ }
112
+ const updated = replaceAll === true ? content.split(find).join(replace) : content.replace(find, () => replace);
113
+ await context.fs.writeFile(filePath, updated, invocation);
114
+ const replaced = replaceAll === true ? occurrences : 1;
115
+ return truncate(`Replaced ${replaced} occurrence${replaced === 1 ? '' : 's'} in ${filePath}`);
116
+ },
117
+ });
118
+ }
78
119
  if (options.includeDelete !== false) {
79
120
  tools.delete_file = plugins.tool({
80
121
  description: 'Delete a file or empty directory in the active workspace. Requires host permission when configured.',
@@ -103,4 +144,4 @@ export function createFilesystemTools(context, options = {}) {
103
144
  }
104
145
  return tools;
105
146
  }
106
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbC5maWxlc3lzdGVtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfdG9vbHMvdG9vbC5maWxlc3lzdGVtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFDTCxnQkFBZ0IsR0FFakIsTUFBTSxtQkFBbUIsQ0FBQztBQVczQixNQUFNLFVBQVUscUJBQXFCLENBQUMsT0FBOEIsRUFBRSxVQUF5QyxFQUFFO0lBQy9HLE1BQU0sUUFBUSxHQUFHLENBQUMsTUFBZSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxFQUFFO1FBQ3JGLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtRQUMxQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7S0FDM0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUNYLE1BQU0sS0FBSyxHQUFvQjtRQUM3QixTQUFTLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQztZQUN0QixXQUFXLEVBQ1QscUdBQXFHO1lBQ3ZHLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDNUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQztnQkFDOUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO3FCQUNqQixNQUFNLEVBQUU7cUJBQ1IsUUFBUSxFQUFFO3FCQUNWLFFBQVEsQ0FBQyxtQ0FBbUMsQ0FBQztnQkFDaEQsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO3FCQUNmLE1BQU0sRUFBRTtxQkFDUixRQUFRLEVBQUU7cUJBQ1YsUUFBUSxDQUFDLGtDQUFrQyxDQUFDO2FBQ2hELENBQUM7WUFDRixPQUFPLEVBQUUsS0FBSyxFQUNaLEVBQ0UsSUFBSSxFQUFFLFFBQVEsRUFDZCxTQUFTLEVBQ1QsT0FBTyxHQUtS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
147
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9vbC5maWxlc3lzdGVtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHNfdG9vbHMvdG9vbC5maWxlc3lzdGVtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFDTCxnQkFBZ0IsR0FFakIsTUFBTSxtQkFBbUIsQ0FBQztBQWEzQixNQUFNLFVBQVUscUJBQXFCLENBQUMsT0FBOEIsRUFBRSxVQUF5QyxFQUFFO0lBQy9HLE1BQU0sUUFBUSxHQUFHLENBQUMsTUFBZSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxFQUFFO1FBQ3JGLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtRQUMxQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7S0FDM0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUNYLE1BQU0sS0FBSyxHQUFvQjtRQUM3QixTQUFTLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQztZQUN0QixXQUFXLEVBQ1QscUdBQXFHO1lBQ3ZHLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztnQkFDNUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQztnQkFDOUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDO3FCQUNqQixNQUFNLEVBQUU7cUJBQ1IsUUFBUSxFQUFFO3FCQUNWLFFBQVEsQ0FBQyxtQ0FBbUMsQ0FBQztnQkFDaEQsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO3FCQUNmLE1BQU0sRUFBRTtxQkFDUixRQUFRLEVBQUU7cUJBQ1YsUUFBUSxDQUFDLGtDQUFrQyxDQUFDO2FBQ2hELENBQUM7WUFDRixPQUFPLEVBQUUsS0FBSyxFQUNaLEVBQ0UsSUFBSSxFQUFFLFFBQVEsRUFDZCxTQUFTLEVBQ1QsT0FBTyxHQUtS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
@@ -0,0 +1,48 @@
1
+ import * as plugins from './plugins.js';
2
+ import type { IToolFileChangeObserver } from './tool.context.js';
3
+ export interface IInMemoryWorkspaceReversionOptions {
4
+ /** The workspace a revertible turn names in the session's reversion info. */
5
+ workspace: plugins.IFlexAffectedWorkspace;
6
+ /**
7
+ * The bytes of file images one turn may hold. A turn that changes more is recorded as
8
+ * nonrevertible (`capture-too-large`) and its images are dropped. Default: 64 MiB.
9
+ */
10
+ maxCaptureBytes?: number;
11
+ }
12
+ /**
13
+ * Turn reversion for the local filesystem tools, held in memory: FlexHarness `/undo` and `/redo`
14
+ * move a turn's file changes together with its transcript.
15
+ *
16
+ * Give each run's `createLocalToolExecutionContext` the observer `observerFor(context.runId)`. The
17
+ * first change of a file in a turn records what the file held before; `finalize` records what it
18
+ * holds after. Undo puts the before images back and redo the after images, each only while every
19
+ * file still holds what the other direction left, so a later edit of the user is never overwritten.
20
+ * A turn that ran a shell command is nonrevertible, since the command may have changed files no
21
+ * observer saw.
22
+ *
23
+ * Captures live as long as the process. A capture FlexHarness asks about after a restart is
24
+ * `missing`, and undoing past it fails without changing anything. Only root-session runs are
25
+ * captured; a change of a run without a prepared capture is refused.
26
+ */
27
+ export declare class InMemoryWorkspaceReversion<TScope = unknown> implements plugins.IFlexTurnReversionProviderV2<TScope> {
28
+ readonly protocolVersion = 2;
29
+ private readonly workspace;
30
+ private readonly maxCaptureBytes;
31
+ private readonly captures;
32
+ private readonly captureIdsByRun;
33
+ constructor(optionsArg: IInMemoryWorkspaceReversionOptions);
34
+ /** The observer of one run's file changes and shell commands. */
35
+ observerFor(runIdArg: string): IToolFileChangeObserver;
36
+ prepare(contextArg: plugins.IFlexTurnReversionBaseContext<TScope>): void;
37
+ inspectCapture(contextArg: plugins.IFlexTurnReversionBaseContext<TScope>): plugins.TFlexTurnReversionCaptureInspectionV2;
38
+ finalize(contextArg: plugins.IFlexTurnReversionBaseContext<TScope>): Promise<plugins.TFlexTurnReversionFinalizedOutcome>;
39
+ apply(contextArg: plugins.IFlexTurnReversionApplyContext<TScope>): Promise<void>;
40
+ inspectApply(contextArg: plugins.IFlexTurnReversionApplyContext<TScope>): plugins.IFlexTurnReversionApplyInspection;
41
+ release(contextArg: plugins.IFlexTurnReversionReleaseContext<TScope>): void;
42
+ private recordChange;
43
+ private markNonrevertible;
44
+ private rollBack;
45
+ private requirePreparedCapture;
46
+ private requireCapture;
47
+ private captureOf;
48
+ }