@ai-sdk/harness-opencode 1.0.102 → 1.0.103

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.
@@ -0,0 +1,90 @@
1
+ import type {
2
+ HarnessV1QuestionsToolInput,
3
+ HarnessV1QuestionsToolOutput,
4
+ } from '@ai-sdk/harness';
5
+ import type { QuestionInfo } from '@opencode-ai/sdk/v2';
6
+
7
+ export type OpenCodeQuestionRequest = {
8
+ id: string;
9
+ sessionID: string;
10
+ questions: QuestionInfo[];
11
+ tool?: { messageID: string; callID: string };
12
+ };
13
+
14
+ export function openCodeQuestionKey(
15
+ nativeRequest: OpenCodeQuestionRequest,
16
+ ): string {
17
+ return JSON.stringify(nativeRequest.questions);
18
+ }
19
+
20
+ export function toHarnessQuestionsInput(
21
+ nativeRequest: OpenCodeQuestionRequest,
22
+ ): HarnessV1QuestionsToolInput {
23
+ return {
24
+ allowPartialAnswers: true,
25
+ questions: nativeRequest.questions.map((question, questionIndex) => ({
26
+ id: `question-${questionIndex + 1}`,
27
+ question: question.question,
28
+ header: question.header,
29
+ options: question.options.map((option, optionIndex) => ({
30
+ id: `option-${optionIndex + 1}`,
31
+ label: option.label,
32
+ description: option.description,
33
+ })),
34
+ ...(question.multiple !== undefined
35
+ ? { allowMultiple: question.multiple }
36
+ : {}),
37
+ ...(question.custom !== undefined
38
+ ? { allowFreeForm: question.custom }
39
+ : {}),
40
+ })),
41
+ };
42
+ }
43
+
44
+ export function toOpenCodeQuestionResponse(input: {
45
+ nativeRequest: OpenCodeQuestionRequest;
46
+ output: HarnessV1QuestionsToolOutput;
47
+ }): { action: 'reply'; answers: string[][] } | { action: 'reject' } {
48
+ if (
49
+ input.output.action === 'declined' ||
50
+ input.output.action === 'cancelled'
51
+ ) {
52
+ return { action: 'reject' };
53
+ }
54
+
55
+ const answers = input.nativeRequest.questions.map(
56
+ (nativeQuestion, questionIndex) => {
57
+ const answer =
58
+ input.output.action === 'answered' ||
59
+ input.output.action === 'partially-answered'
60
+ ? input.output.answers[`question-${questionIndex + 1}`]
61
+ : undefined;
62
+ if (answer == null) return [];
63
+ const selectedLabels = answer.optionIds.flatMap(optionId => {
64
+ const index = positionalIdIndex({
65
+ id: optionId,
66
+ prefix: 'option-',
67
+ });
68
+ const option =
69
+ index == null ? undefined : nativeQuestion.options[index];
70
+ return option == null ? [] : [option.label];
71
+ });
72
+ return answer.freeform === undefined
73
+ ? selectedLabels
74
+ : [...selectedLabels, answer.freeform];
75
+ },
76
+ );
77
+
78
+ return { action: 'reply', answers };
79
+ }
80
+
81
+ function positionalIdIndex(input: {
82
+ id: string;
83
+ prefix: string;
84
+ }): number | undefined {
85
+ if (!input.id.startsWith(input.prefix)) return undefined;
86
+ const oneBasedIndex = Number(input.id.slice(input.prefix.length));
87
+ return Number.isInteger(oneBasedIndex) && oneBasedIndex > 0
88
+ ? oneBasedIndex - 1
89
+ : undefined;
90
+ }
@@ -1,6 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import {
3
3
  commonTool,
4
+ HARNESS_V1_BUILTIN_TOOLS,
4
5
  HarnessCapabilityUnsupportedError,
5
6
  harnessV1DiagnosticFromBridgeFrame,
6
7
  type HarnessV1,
@@ -123,6 +124,11 @@ export type OpenCodeHarnessSettings = {
123
124
  const optionalStringRecord = z.record(z.string(), z.unknown()).optional();
124
125
 
125
126
  const OPENCODE_BUILTIN_TOOLS = {
127
+ askUserQuestions: {
128
+ ...HARNESS_V1_BUILTIN_TOOLS.askUserQuestions,
129
+ nativeName: 'question',
130
+ toolUseKind: 'readonly',
131
+ },
126
132
  read: commonTool('read', {
127
133
  nativeName: 'view',
128
134
  toolUseKind: 'readonly',
@@ -954,6 +960,9 @@ function createSession({
954
960
  toolCallId: input.toolCallId,
955
961
  output: input.output,
956
962
  isError: input.isError,
963
+ ...(input.toolResult !== undefined
964
+ ? { toolResult: input.toolResult }
965
+ : {}),
957
966
  });
958
967
  },
959
968
  submitToolApproval: async input => {