@modelprofile.com/flexharness 5.3.1 → 5.3.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelprofile.com/flexharness",
3
- "version": "5.3.1",
3
+ "version": "5.3.3",
4
4
  "private": false,
5
5
  "description": "Provider-neutral model-session runtime with durable history, permissions, typed events, and pluggable local or remote tool execution.",
6
6
  "main": "dist_ts/index.js",
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@modelprofile.com/flexharness',
6
- version: '5.3.1',
6
+ version: '5.3.3',
7
7
  description: 'Provider-neutral model-session runtime with durable history, permissions, typed events, and pluggable local or remote tool execution.'
8
8
  }
@@ -4807,52 +4807,107 @@ export class FlexHarness<TScope = unknown> {
4807
4807
  const content = plugins.z.string().min(1).max(FLEX_PROJECT_MANAGEMENT_LIMITS.maxTaskContentBytes);
4808
4808
  return plugins.tool({
4809
4809
  description: 'List, create, update, delete, or clear session-local project tasks.',
4810
- inputSchema: plugins.z.discriminatedUnion('action', [
4811
- plugins.z.object({ action: plugins.z.literal('list') }).strict(),
4812
- plugins.z.object({
4813
- action: plugins.z.literal('create'),
4814
- id: id.optional(),
4815
- content,
4816
- status: status.optional(),
4817
- priority: priority.optional(),
4818
- }).strict(),
4819
- plugins.z.object({
4820
- action: plugins.z.literal('update'),
4821
- id,
4822
- content: content.optional(),
4823
- status: status.optional(),
4824
- priority: priority.optional(),
4825
- }).strict().refine(
4826
- (input) => input.content !== undefined
4827
- || input.status !== undefined
4828
- || input.priority !== undefined,
4829
- { message: 'Task update requires content, status, or priority.' },
4830
- ),
4831
- plugins.z.object({ action: plugins.z.literal('delete'), id }).strict(),
4832
- plugins.z.object({ action: plugins.z.literal('clear') }).strict(),
4833
- ]),
4810
+ strict: false,
4811
+ inputSchema: plugins.z.object({
4812
+ action: plugins.z.enum(['list', 'create', 'update', 'delete', 'clear']),
4813
+ id: id.optional(),
4814
+ content: content.optional(),
4815
+ status: status.optional(),
4816
+ priority: priority.optional(),
4817
+ }).strict().superRefine((input, context) => {
4818
+ const rejectFields = (...fields: Array<keyof typeof input>): void => {
4819
+ for (const field of fields) {
4820
+ if (input[field] === undefined) continue;
4821
+ context.addIssue({
4822
+ code: 'custom',
4823
+ path: [field],
4824
+ message: `Task action "${input.action}" does not accept ${field}.`,
4825
+ });
4826
+ }
4827
+ };
4828
+ if (input.action === 'list' || input.action === 'clear') {
4829
+ rejectFields('id', 'content', 'status', 'priority');
4830
+ } else if (input.action === 'create') {
4831
+ if (input.content === undefined) {
4832
+ context.addIssue({
4833
+ code: 'custom',
4834
+ path: ['content'],
4835
+ message: 'Task creation requires content.',
4836
+ });
4837
+ }
4838
+ } else if (input.action === 'update') {
4839
+ if (input.id === undefined) {
4840
+ context.addIssue({
4841
+ code: 'custom',
4842
+ path: ['id'],
4843
+ message: 'Task update requires an id.',
4844
+ });
4845
+ }
4846
+ if (
4847
+ input.content === undefined
4848
+ && input.status === undefined
4849
+ && input.priority === undefined
4850
+ ) {
4851
+ context.addIssue({
4852
+ code: 'custom',
4853
+ message: 'Task update requires content, status, or priority.',
4854
+ });
4855
+ }
4856
+ } else {
4857
+ if (input.id === undefined) {
4858
+ context.addIssue({
4859
+ code: 'custom',
4860
+ path: ['id'],
4861
+ message: 'Task deletion requires an id.',
4862
+ });
4863
+ }
4864
+ rejectFields('content', 'status', 'priority');
4865
+ }
4866
+ }),
4834
4867
  execute: (
4835
- input: TProjectTaskToolInput,
4868
+ input,
4836
4869
  options?: { toolCallId?: string },
4837
- ) => this.executeProjectTaskTool(run, input, options?.toolCallId),
4870
+ ) => this.executeProjectTaskTool(
4871
+ run,
4872
+ input as TProjectTaskToolInput,
4873
+ options?.toolCallId,
4874
+ ),
4838
4875
  });
4839
4876
  }
4840
4877
 
4841
4878
  private createProjectGoalTool(run: IActiveRun): unknown {
4842
4879
  return plugins.tool({
4843
4880
  description: 'Get, set, or clear the session-local project goal.',
4844
- inputSchema: plugins.z.discriminatedUnion('action', [
4845
- plugins.z.object({ action: plugins.z.literal('get') }).strict(),
4846
- plugins.z.object({
4847
- action: plugins.z.literal('set'),
4848
- goal: plugins.z.string().min(1).max(FLEX_PROJECT_MANAGEMENT_LIMITS.maxGoalBytes),
4849
- }).strict(),
4850
- plugins.z.object({ action: plugins.z.literal('clear') }).strict(),
4851
- ]),
4881
+ strict: false,
4882
+ inputSchema: plugins.z.object({
4883
+ action: plugins.z.enum(['get', 'set', 'clear']),
4884
+ goal: plugins.z.string()
4885
+ .min(1)
4886
+ .max(FLEX_PROJECT_MANAGEMENT_LIMITS.maxGoalBytes)
4887
+ .optional(),
4888
+ }).strict().superRefine((input, context) => {
4889
+ if (input.action === 'set' && input.goal === undefined) {
4890
+ context.addIssue({
4891
+ code: 'custom',
4892
+ path: ['goal'],
4893
+ message: 'Goal set requires a goal.',
4894
+ });
4895
+ } else if (input.action !== 'set' && input.goal !== undefined) {
4896
+ context.addIssue({
4897
+ code: 'custom',
4898
+ path: ['goal'],
4899
+ message: `Goal action "${input.action}" does not accept goal.`,
4900
+ });
4901
+ }
4902
+ }),
4852
4903
  execute: (
4853
- input: TProjectGoalToolInput,
4904
+ input,
4854
4905
  options?: { toolCallId?: string },
4855
- ) => this.executeProjectGoalTool(run, input, options?.toolCallId),
4906
+ ) => this.executeProjectGoalTool(
4907
+ run,
4908
+ input as TProjectGoalToolInput,
4909
+ options?.toolCallId,
4910
+ ),
4856
4911
  });
4857
4912
  }
4858
4913
 
@@ -4860,16 +4915,39 @@ export class FlexHarness<TScope = unknown> {
4860
4915
  const content = plugins.z.string().max(FLEX_PROJECT_MANAGEMENT_LIMITS.maxScratchpadBytes);
4861
4916
  return plugins.tool({
4862
4917
  description: 'Get, set, append to, or clear the session-local project scratchpad.',
4863
- inputSchema: plugins.z.discriminatedUnion('action', [
4864
- plugins.z.object({ action: plugins.z.literal('get') }).strict(),
4865
- plugins.z.object({ action: plugins.z.literal('set'), content }).strict(),
4866
- plugins.z.object({ action: plugins.z.literal('append'), content }).strict(),
4867
- plugins.z.object({ action: plugins.z.literal('clear') }).strict(),
4868
- ]),
4918
+ strict: false,
4919
+ inputSchema: plugins.z.object({
4920
+ action: plugins.z.enum(['get', 'set', 'append', 'clear']),
4921
+ content: content.optional(),
4922
+ }).strict().superRefine((input, context) => {
4923
+ if (
4924
+ (input.action === 'set' || input.action === 'append')
4925
+ && input.content === undefined
4926
+ ) {
4927
+ context.addIssue({
4928
+ code: 'custom',
4929
+ path: ['content'],
4930
+ message: `Scratchpad ${input.action} requires content.`,
4931
+ });
4932
+ } else if (
4933
+ (input.action === 'get' || input.action === 'clear')
4934
+ && input.content !== undefined
4935
+ ) {
4936
+ context.addIssue({
4937
+ code: 'custom',
4938
+ path: ['content'],
4939
+ message: `Scratchpad action "${input.action}" does not accept content.`,
4940
+ });
4941
+ }
4942
+ }),
4869
4943
  execute: (
4870
- input: TProjectScratchpadToolInput,
4944
+ input,
4871
4945
  options?: { toolCallId?: string },
4872
- ) => this.executeProjectScratchpadTool(run, input, options?.toolCallId),
4946
+ ) => this.executeProjectScratchpadTool(
4947
+ run,
4948
+ input as TProjectScratchpadToolInput,
4949
+ options?.toolCallId,
4950
+ ),
4873
4951
  });
4874
4952
  }
4875
4953
 
@@ -5016,6 +5094,7 @@ export class FlexHarness<TScope = unknown> {
5016
5094
  .join('\n');
5017
5095
  return plugins.tool({
5018
5096
  description: `Run one configured FlexHarness subagent in the foreground and return its final text. Omit taskId to create a new child. Supply taskId only to resume the exact child ID returned by an earlier completed delegate call in a later parent run.\nAvailable subagents:\n${available}`,
5097
+ strict: false,
5019
5098
  inputSchema: plugins.z.object({
5020
5099
  description: plugins.z.string(),
5021
5100
  prompt: plugins.z.string(),