@ai-sdk/harness-opencode 1.0.10 → 1.0.12

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.
@@ -9,6 +9,7 @@ import {
9
9
  type HarnessV1,
10
10
  type HarnessV1Bootstrap,
11
11
  type HarnessV1BuiltinTool,
12
+ type HarnessV1BuiltinToolFiltering,
12
13
  type HarnessV1ContinueTurnState,
13
14
  type HarnessV1DebugConfig,
14
15
  type HarnessV1NetworkSandboxSession,
@@ -23,8 +24,11 @@ import {
23
24
  import {
24
25
  classifyDiskLog,
25
26
  markBridgeStarting,
27
+ resolveSandboxHomeDir,
26
28
  SandboxChannel,
29
+ shellQuote,
27
30
  waitForBridgeReady,
31
+ writeSkills as writeHarnessSkills,
28
32
  } from '@ai-sdk/harness/utils';
29
33
  import {
30
34
  tool,
@@ -295,6 +299,7 @@ export function createOpenCode(
295
299
  sandboxId,
296
300
  debug: startOpts.observability?.debug,
297
301
  permissionMode: startOpts.permissionMode,
302
+ builtinToolFiltering: startOpts.builtinToolFiltering,
298
303
  });
299
304
  } catch {}
300
305
  }
@@ -326,7 +331,7 @@ export function createOpenCode(
326
331
  const xdgStateHome = `${sandboxHomeDir}/.local/state`;
327
332
  const skillSetup =
328
333
  startOpts.skills && startOpts.skills.length > 0
329
- ? await writeSkills({
334
+ ? await writeOpenCodeSkills({
330
335
  sandbox: session,
331
336
  skills: startOpts.skills,
332
337
  homeDir: sandboxHomeDir,
@@ -421,6 +426,7 @@ export function createOpenCode(
421
426
  sandboxId,
422
427
  debug: startOpts.observability?.debug,
423
428
  permissionMode: startOpts.permissionMode,
429
+ builtinToolFiltering: startOpts.builtinToolFiltering,
424
430
  });
425
431
  },
426
432
  };
@@ -458,7 +464,7 @@ async function readBridgeAsset(name: string): Promise<string> {
458
464
  throw lastErr ?? new Error(`bridge asset not found: ${name}`);
459
465
  }
460
466
 
461
- async function writeSkills({
467
+ async function writeOpenCodeSkills({
462
468
  sandbox,
463
469
  skills,
464
470
  homeDir,
@@ -469,96 +475,21 @@ async function writeSkills({
469
475
  homeDir: string;
470
476
  abortSignal?: AbortSignal;
471
477
  }): Promise<WriteSkillsResult> {
472
- for (const skill of skills) {
473
- safeOpenCodeSkillName(skill.name);
474
- for (const file of skill.files ?? []) {
475
- safeOpenCodeSkillFilePath({ skillName: skill.name, filePath: file.path });
476
- }
477
- }
478
-
479
478
  const skillsDir = path.posix.join(homeDir, '.agents', 'skills');
480
- await sandbox.run({
481
- command: `mkdir -p ${shellQuote(skillsDir)}`,
479
+ await writeHarnessSkills({
480
+ sandbox,
481
+ rootDir: skillsDir,
482
+ skills,
482
483
  abortSignal,
484
+ invalidSkillNameMessage: ({ name }) =>
485
+ `Invalid OpenCode skill name: ${name}`,
486
+ invalidSkillFilePathMessage: ({ skillName, filePath }) =>
487
+ `Invalid OpenCode skill file path for ${skillName}: ${filePath}`,
483
488
  });
484
489
 
485
- for (const skill of skills) {
486
- const name = safeOpenCodeSkillName(skill.name);
487
- const skillDir = path.posix.join(skillsDir, name);
488
- const content = `---\nname: ${skill.name}\ndescription: ${skill.description}\n---\n\n${skill.content}`;
489
- await sandbox.writeTextFile({
490
- path: path.posix.join(skillDir, 'SKILL.md'),
491
- content,
492
- abortSignal,
493
- });
494
-
495
- for (const file of skill.files ?? []) {
496
- const filePath = safeOpenCodeSkillFilePath({
497
- skillName: skill.name,
498
- filePath: file.path,
499
- });
500
- await sandbox.writeTextFile({
501
- path: path.posix.join(skillDir, filePath),
502
- content: file.content,
503
- abortSignal,
504
- });
505
- }
506
- }
507
-
508
490
  return { skillsDir };
509
491
  }
510
492
 
511
- async function resolveSandboxHomeDir({
512
- sandbox,
513
- abortSignal,
514
- }: {
515
- sandbox: Experimental_SandboxSession;
516
- abortSignal?: AbortSignal;
517
- }): Promise<string> {
518
- const result = await sandbox.run({
519
- command: 'printf "%s" "$HOME"',
520
- abortSignal,
521
- });
522
- const homeDir = result.stdout.trim();
523
- if (result.exitCode !== 0 || !homeDir || !path.posix.isAbsolute(homeDir)) {
524
- throw new Error(
525
- `Unable to resolve sandbox HOME directory: ${result.stderr || result.stdout}`,
526
- );
527
- }
528
- return homeDir;
529
- }
530
-
531
- function safeOpenCodeSkillName(name: string): string {
532
- if (!/^[A-Za-z0-9._-]+$/.test(name) || name === '.' || name === '..') {
533
- throw new Error(`Invalid OpenCode skill name: ${name}`);
534
- }
535
- return name;
536
- }
537
-
538
- function safeOpenCodeSkillFilePath({
539
- skillName,
540
- filePath,
541
- }: {
542
- skillName: string;
543
- filePath: string;
544
- }): string {
545
- const normalized = path.posix.normalize(filePath);
546
- if (
547
- normalized === '.' ||
548
- normalized.startsWith('../') ||
549
- path.posix.isAbsolute(normalized)
550
- ) {
551
- throw new Error(
552
- `Invalid OpenCode skill file path for ${skillName}: ${filePath}`,
553
- );
554
- }
555
- return normalized;
556
- }
557
-
558
- function shellQuote(value: string): string {
559
- return `'${value.replace(/'/g, `'\\''`)}'`;
560
- }
561
-
562
493
  async function forwardBridgeStderr(
563
494
  stream: ReadableStream<Uint8Array>,
564
495
  ): Promise<void> {
@@ -619,6 +550,7 @@ function createSession({
619
550
  sandboxId,
620
551
  debug,
621
552
  permissionMode,
553
+ builtinToolFiltering,
622
554
  }: {
623
555
  sessionId: string;
624
556
  channel: OpenCodeChannel;
@@ -635,6 +567,7 @@ function createSession({
635
567
  sandboxId: string;
636
568
  debug: HarnessV1DebugConfig | undefined;
637
569
  permissionMode: HarnessV1PermissionMode | undefined;
570
+ builtinToolFiltering: HarnessV1BuiltinToolFiltering | undefined;
638
571
  }): HarnessV1Session {
639
572
  let stopped = false;
640
573
  let stopPromise: Promise<void> | undefined;
@@ -786,6 +719,7 @@ function createSession({
786
719
  provider,
787
720
  ...(reasoningVariant ? { variant: reasoningVariant } : {}),
788
721
  ...(permissionMode ? { permissionMode } : {}),
722
+ ...(builtinToolFiltering ? { builtinToolFiltering } : {}),
789
723
  ...(pendingResumeSessionId
790
724
  ? { resumeSessionId: pendingResumeSessionId }
791
725
  : latestOpenCodeSessionId