@ottocode/sdk 0.1.237 → 0.1.242
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 +1 -1
- package/src/config/src/index.ts +1 -0
- package/src/config/src/manager.ts +2 -1
- package/src/prompts/src/agents/init.txt +24 -0
- package/src/providers/src/catalog.ts +977 -1225
- package/src/providers/src/oauth-models.ts +2 -0
- package/src/providers/src/utils.ts +1 -1
- package/src/skills/loader.ts +1 -1
- package/src/skills/parser.ts +209 -24
- package/src/types/src/config.ts +2 -1
|
@@ -5,6 +5,7 @@ const OAUTH_MODEL_PREFIXES: Partial<Record<ProviderId, string[]>> = {
|
|
|
5
5
|
'claude-haiku-4-5',
|
|
6
6
|
'claude-opus-4-5',
|
|
7
7
|
'claude-opus-4-6',
|
|
8
|
+
'claude-opus-4-7',
|
|
8
9
|
'claude-sonnet-4-5',
|
|
9
10
|
'claude-sonnet-4-6',
|
|
10
11
|
],
|
|
@@ -19,6 +20,7 @@ const OAUTH_MODEL_IDS: Partial<Record<ProviderId, string[]>> = {
|
|
|
19
20
|
'gpt-5.2-codex',
|
|
20
21
|
'gpt-5.3-codex',
|
|
21
22
|
'gpt-5.4',
|
|
23
|
+
'gpt-5.4-mini',
|
|
22
24
|
],
|
|
23
25
|
};
|
|
24
26
|
|
|
@@ -40,7 +40,7 @@ const PREFERRED_FAST_MODELS: Partial<Record<ProviderId, string[]>> = {
|
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
const PREFERRED_FAST_MODELS_OAUTH: Partial<Record<ProviderId, string[]>> = {
|
|
43
|
-
openai: ['gpt-5.
|
|
43
|
+
openai: ['gpt-5.4-mini'],
|
|
44
44
|
anthropic: ['claude-haiku-4-5'],
|
|
45
45
|
};
|
|
46
46
|
|
package/src/skills/loader.ts
CHANGED
|
@@ -74,6 +74,7 @@ export async function discoverSkills(
|
|
|
74
74
|
let current = cwd;
|
|
75
75
|
const visited = new Set<string>();
|
|
76
76
|
while (current && !visited.has(current)) {
|
|
77
|
+
if (repoRoot && !current.startsWith(repoRoot)) break;
|
|
77
78
|
visited.add(current);
|
|
78
79
|
const scope: SkillScope =
|
|
79
80
|
current === cwd ? 'cwd' : current === repoRoot ? 'repo' : 'parent';
|
|
@@ -82,7 +83,6 @@ export async function discoverSkills(
|
|
|
82
83
|
}
|
|
83
84
|
const parent = dirname(current);
|
|
84
85
|
if (parent === current) break;
|
|
85
|
-
if (repoRoot && !current.startsWith(repoRoot)) break;
|
|
86
86
|
current = parent;
|
|
87
87
|
}
|
|
88
88
|
|
package/src/skills/parser.ts
CHANGED
|
@@ -35,50 +35,219 @@ function parseYamlFrontmatter(
|
|
|
35
35
|
): Record<string, unknown> {
|
|
36
36
|
const result: Record<string, unknown> = {};
|
|
37
37
|
const lines = yaml.split('\n');
|
|
38
|
-
let
|
|
39
|
-
let currentIndent = 0;
|
|
40
|
-
let nestedObject: Record<string, string> | null = null;
|
|
38
|
+
let index = 0;
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
while (index < lines.length) {
|
|
41
|
+
const line = lines[index];
|
|
42
|
+
if (!line || !line.trim()) {
|
|
43
|
+
index += 1;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
44
46
|
|
|
45
47
|
const indent = line.search(/\S/);
|
|
48
|
+
if (indent > 0) {
|
|
49
|
+
index += 1;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
46
53
|
const trimmed = line.trim();
|
|
54
|
+
const colonIdx = trimmed.indexOf(':');
|
|
55
|
+
if (colonIdx === -1) {
|
|
56
|
+
index += 1;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
47
59
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
const key = normalizeKey(trimmed.slice(0, colonIdx).trim());
|
|
61
|
+
const value = trimmed.slice(colonIdx + 1).trim();
|
|
62
|
+
|
|
63
|
+
if (value === '|' || value === '>') {
|
|
64
|
+
const { content, nextIndex } = readBlockScalar(
|
|
65
|
+
lines,
|
|
66
|
+
index + 1,
|
|
67
|
+
indent,
|
|
68
|
+
value,
|
|
69
|
+
);
|
|
70
|
+
result[key] = content;
|
|
71
|
+
index = nextIndex;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!value) {
|
|
76
|
+
const { content, nextIndex } = readIndentedValue(
|
|
77
|
+
lines,
|
|
78
|
+
index + 1,
|
|
79
|
+
indent,
|
|
80
|
+
);
|
|
81
|
+
result[key] = content;
|
|
82
|
+
index = nextIndex;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
result[key] = parseYamlValue(value);
|
|
87
|
+
index += 1;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function readIndentedValue(
|
|
94
|
+
lines: string[],
|
|
95
|
+
startIndex: number,
|
|
96
|
+
parentIndent: number,
|
|
97
|
+
): { content: Record<string, string> | string; nextIndex: number } {
|
|
98
|
+
for (let index = startIndex; index < lines.length; index += 1) {
|
|
99
|
+
const line = lines[index];
|
|
100
|
+
if (!line || !line.trim()) continue;
|
|
101
|
+
|
|
102
|
+
const indent = line.search(/\S/);
|
|
103
|
+
if (indent <= parentIndent) {
|
|
104
|
+
return { content: '', nextIndex: index };
|
|
54
105
|
}
|
|
55
106
|
|
|
107
|
+
if (isNestedObjectLine(line.trim())) {
|
|
108
|
+
return readNestedObject(lines, startIndex, parentIndent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return readIndentedScalar(lines, startIndex, parentIndent);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return { content: '', nextIndex: lines.length };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function readNestedObject(
|
|
118
|
+
lines: string[],
|
|
119
|
+
startIndex: number,
|
|
120
|
+
parentIndent: number,
|
|
121
|
+
): { content: Record<string, string>; nextIndex: number } {
|
|
122
|
+
const result: Record<string, string> = {};
|
|
123
|
+
let index = startIndex;
|
|
124
|
+
|
|
125
|
+
while (index < lines.length) {
|
|
126
|
+
const line = lines[index];
|
|
127
|
+
if (!line || !line.trim()) {
|
|
128
|
+
index += 1;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const indent = line.search(/\S/);
|
|
133
|
+
if (indent <= parentIndent) break;
|
|
134
|
+
|
|
135
|
+
const trimmed = line.trim();
|
|
56
136
|
const colonIdx = trimmed.indexOf(':');
|
|
57
|
-
if (colonIdx === -1)
|
|
137
|
+
if (colonIdx === -1) {
|
|
138
|
+
index += 1;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
58
141
|
|
|
59
|
-
const key = trimmed.slice(0, colonIdx).trim();
|
|
142
|
+
const key = normalizeKey(trimmed.slice(0, colonIdx).trim());
|
|
60
143
|
const value = trimmed.slice(colonIdx + 1).trim();
|
|
61
144
|
|
|
62
|
-
if (
|
|
63
|
-
|
|
145
|
+
if (value === '|' || value === '>') {
|
|
146
|
+
const block = readBlockScalar(lines, index + 1, indent, value);
|
|
147
|
+
result[key] = block.content;
|
|
148
|
+
index = block.nextIndex;
|
|
64
149
|
continue;
|
|
65
150
|
}
|
|
66
151
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
152
|
+
result[key] = String(parseYamlValue(value));
|
|
153
|
+
index += 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return { content: result, nextIndex: index };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function readIndentedScalar(
|
|
160
|
+
lines: string[],
|
|
161
|
+
startIndex: number,
|
|
162
|
+
parentIndent: number,
|
|
163
|
+
): { content: string; nextIndex: number } {
|
|
164
|
+
const scalarLines: string[] = [];
|
|
165
|
+
let index = startIndex;
|
|
166
|
+
let contentIndent: number | null = null;
|
|
167
|
+
|
|
168
|
+
while (index < lines.length) {
|
|
169
|
+
const line = lines[index];
|
|
170
|
+
if (!line) {
|
|
171
|
+
scalarLines.push('');
|
|
172
|
+
index += 1;
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (!line.trim()) {
|
|
177
|
+
scalarLines.push('');
|
|
178
|
+
index += 1;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const indent = line.search(/\S/);
|
|
183
|
+
if (indent <= parentIndent) break;
|
|
184
|
+
|
|
185
|
+
contentIndent ??= indent;
|
|
186
|
+
scalarLines.push(line.slice(contentIndent));
|
|
187
|
+
index += 1;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return { content: foldBlockScalar(scalarLines), nextIndex: index };
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function readBlockScalar(
|
|
194
|
+
lines: string[],
|
|
195
|
+
startIndex: number,
|
|
196
|
+
parentIndent: number,
|
|
197
|
+
style: '|' | '>',
|
|
198
|
+
): { content: string; nextIndex: number } {
|
|
199
|
+
const blockLines: string[] = [];
|
|
200
|
+
let index = startIndex;
|
|
201
|
+
let contentIndent: number | null = null;
|
|
202
|
+
|
|
203
|
+
while (index < lines.length) {
|
|
204
|
+
const line = lines[index];
|
|
205
|
+
if (!line) {
|
|
206
|
+
blockLines.push('');
|
|
207
|
+
index += 1;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (!line.trim()) {
|
|
212
|
+
blockLines.push('');
|
|
213
|
+
index += 1;
|
|
71
214
|
continue;
|
|
72
215
|
}
|
|
73
216
|
|
|
74
|
-
|
|
217
|
+
const indent = line.search(/\S/);
|
|
218
|
+
if (indent <= parentIndent) break;
|
|
219
|
+
|
|
220
|
+
contentIndent ??= indent;
|
|
221
|
+
blockLines.push(line.slice(contentIndent));
|
|
222
|
+
index += 1;
|
|
75
223
|
}
|
|
76
224
|
|
|
77
|
-
|
|
78
|
-
|
|
225
|
+
const content =
|
|
226
|
+
style === '>' ? foldBlockScalar(blockLines) : blockLines.join('\n').trim();
|
|
227
|
+
return { content, nextIndex: index };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function foldBlockScalar(lines: string[]): string {
|
|
231
|
+
const segments: string[] = [];
|
|
232
|
+
let current = '';
|
|
233
|
+
|
|
234
|
+
for (const line of lines) {
|
|
235
|
+
if (!line.trim()) {
|
|
236
|
+
if (current) {
|
|
237
|
+
segments.push(current.trim());
|
|
238
|
+
current = '';
|
|
239
|
+
}
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
current = current ? `${current} ${line.trim()}` : line.trim();
|
|
79
244
|
}
|
|
80
245
|
|
|
81
|
-
|
|
246
|
+
if (current) {
|
|
247
|
+
segments.push(current.trim());
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return segments.join('\n');
|
|
82
251
|
}
|
|
83
252
|
|
|
84
253
|
function normalizeKey(key: string): string {
|
|
@@ -86,13 +255,29 @@ function normalizeKey(key: string): string {
|
|
|
86
255
|
return key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
|
|
87
256
|
}
|
|
88
257
|
|
|
89
|
-
function
|
|
258
|
+
function isNestedObjectLine(line: string): boolean {
|
|
259
|
+
return /^[A-Za-z0-9_-]+\s*:/.test(line);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function parseYamlValue(value: string): unknown {
|
|
90
263
|
if (
|
|
91
264
|
(value.startsWith('"') && value.endsWith('"')) ||
|
|
92
265
|
(value.startsWith("'") && value.endsWith("'"))
|
|
93
266
|
) {
|
|
94
267
|
return value.slice(1, -1);
|
|
95
268
|
}
|
|
269
|
+
|
|
270
|
+
if (
|
|
271
|
+
(value.startsWith('{') && value.endsWith('}')) ||
|
|
272
|
+
(value.startsWith('[') && value.endsWith(']'))
|
|
273
|
+
) {
|
|
274
|
+
try {
|
|
275
|
+
return JSON.parse(value) as unknown;
|
|
276
|
+
} catch {
|
|
277
|
+
return value;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
96
281
|
return value;
|
|
97
282
|
}
|
|
98
283
|
|
package/src/types/src/config.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type Scope = 'global' | 'local';
|
|
|
8
8
|
/**
|
|
9
9
|
* Default settings for the CLI
|
|
10
10
|
*/
|
|
11
|
-
export type ToolApprovalMode = 'auto' | 'dangerous' | 'all';
|
|
11
|
+
export type ToolApprovalMode = 'auto' | 'dangerous' | 'all' | 'yolo';
|
|
12
12
|
export type ReasoningLevel =
|
|
13
13
|
| 'minimal'
|
|
14
14
|
| 'low'
|
|
@@ -27,6 +27,7 @@ export type DefaultConfig = {
|
|
|
27
27
|
reasoningLevel?: ReasoningLevel;
|
|
28
28
|
theme?: string;
|
|
29
29
|
fullWidthContent?: boolean;
|
|
30
|
+
autoCompactThresholdTokens?: number | null;
|
|
30
31
|
};
|
|
31
32
|
|
|
32
33
|
export type ProviderSettings = Record<
|