@link-assistant/agent 0.2.0 → 0.2.1

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": "@link-assistant/agent",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A minimal, public domain AI CLI agent compatible with OpenCode's JSON interface. Bun-only runtime.",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
package/src/bun/index.ts CHANGED
@@ -4,6 +4,7 @@ import { Log } from '../util/log';
4
4
  import path from 'path';
5
5
  import { NamedError } from '../util/error';
6
6
  import { readableStreamToText } from 'bun';
7
+ import { Flag } from '../flag/flag';
7
8
 
8
9
  export namespace BunProc {
9
10
  const log = Log.create({ service: 'bun' });
@@ -43,7 +44,10 @@ export namespace BunProc {
43
44
  stderr,
44
45
  });
45
46
  if (code !== 0) {
46
- throw new Error(`Command failed with exit code ${result.exitCode}`);
47
+ const parts = [`Command failed with exit code ${result.exitCode}`];
48
+ if (stderr) parts.push(`stderr: ${stderr}`);
49
+ if (stdout) parts.push(`stdout: ${stdout}`);
50
+ throw new Error(parts.join('\n'));
47
51
  }
48
52
  return result;
49
53
  }
@@ -57,6 +61,7 @@ export namespace BunProc {
57
61
  z.object({
58
62
  pkg: z.string(),
59
63
  version: z.string(),
64
+ details: z.string().optional(),
60
65
  })
61
66
  );
62
67
 
@@ -70,6 +75,20 @@ export namespace BunProc {
70
75
  });
71
76
  if (parsed.dependencies[pkg] === version) return mod;
72
77
 
78
+ // Check for dry-run mode
79
+ if (Flag.OPENCODE_DRY_RUN) {
80
+ log.info(
81
+ '[DRY RUN] Would install package (skipping actual installation)',
82
+ {
83
+ pkg,
84
+ version,
85
+ targetPath: mod,
86
+ }
87
+ );
88
+ // In dry-run mode, pretend the package is installed
89
+ return mod;
90
+ }
91
+
73
92
  // Build command arguments
74
93
  const args = [
75
94
  'add',
@@ -92,13 +111,20 @@ export namespace BunProc {
92
111
  await BunProc.run(args, {
93
112
  cwd: Global.Path.cache,
94
113
  }).catch((e) => {
114
+ log.error('package installation failed', {
115
+ pkg,
116
+ version,
117
+ error: e instanceof Error ? e.message : String(e),
118
+ stack: e instanceof Error ? e.stack : undefined,
119
+ });
95
120
  throw new InstallFailedError(
96
- { pkg, version },
121
+ { pkg, version, details: e instanceof Error ? e.message : String(e) },
97
122
  {
98
123
  cause: e,
99
124
  }
100
125
  );
101
126
  });
127
+ log.info('package installed successfully', { pkg, version });
102
128
  parsed.dependencies[pkg] = version;
103
129
  await Bun.write(pkgjson.name!, JSON.stringify(parsed, null, 2));
104
130
  return mod;
package/src/flag/flag.ts CHANGED
@@ -22,11 +22,19 @@ export namespace Flag {
22
22
  // Verbose mode - enables detailed logging of API requests
23
23
  export let OPENCODE_VERBOSE = truthy('OPENCODE_VERBOSE');
24
24
 
25
+ // Dry run mode - simulate operations without making actual API calls or changes
26
+ export let OPENCODE_DRY_RUN = truthy('OPENCODE_DRY_RUN');
27
+
25
28
  // Allow setting verbose mode programmatically (e.g., from CLI --verbose flag)
26
29
  export function setVerbose(value: boolean) {
27
30
  OPENCODE_VERBOSE = value;
28
31
  }
29
32
 
33
+ // Allow setting dry run mode programmatically (e.g., from CLI --dry-run flag)
34
+ export function setDryRun(value: boolean) {
35
+ OPENCODE_DRY_RUN = value;
36
+ }
37
+
30
38
  function truthy(key: string) {
31
39
  const value = process.env[key]?.toLowerCase();
32
40
  return value === 'true' || value === '1';
@@ -24,6 +24,7 @@ export namespace Global {
24
24
 
25
25
  await Promise.all([
26
26
  fs.mkdir(Global.Path.data, { recursive: true }),
27
+ fs.mkdir(Global.Path.cache, { recursive: true }),
27
28
  fs.mkdir(Global.Path.config, { recursive: true }),
28
29
  fs.mkdir(Global.Path.state, { recursive: true }),
29
30
  fs.mkdir(Global.Path.log, { recursive: true }),
package/src/index.js CHANGED
@@ -110,6 +110,13 @@ async function runAgentMode(argv) {
110
110
  console.error(`Script path: ${import.meta.path}`);
111
111
  }
112
112
 
113
+ // Log dry-run mode if enabled
114
+ if (Flag.OPENCODE_DRY_RUN) {
115
+ console.error(
116
+ `[DRY RUN MODE] No actual API calls or package installations will be made`
117
+ );
118
+ }
119
+
113
120
  // Parse model argument (handle model IDs with slashes like groq/qwen/qwen3-32b)
114
121
  const modelParts = argv.model.split('/');
115
122
  let providerID = modelParts[0] || 'opencode';
@@ -574,6 +581,12 @@ async function main() {
574
581
  'Enable verbose mode to debug API requests (shows system prompt, token counts, etc.)',
575
582
  default: false,
576
583
  })
584
+ .option('dry-run', {
585
+ type: 'boolean',
586
+ description:
587
+ 'Simulate operations without making actual API calls or package installations (useful for testing)',
588
+ default: false,
589
+ })
577
590
  .option('use-existing-claude-oauth', {
578
591
  type: 'boolean',
579
592
  description:
@@ -588,6 +601,11 @@ async function main() {
588
601
  Flag.setVerbose(true);
589
602
  }
590
603
 
604
+ // Set dry-run flag if requested
605
+ if (argv['dry-run']) {
606
+ Flag.setDryRun(true);
607
+ }
608
+
591
609
  // Initialize logging system
592
610
  // - If verbose: print logs to stderr for debugging
593
611
  // - Otherwise: write logs to file to keep CLI output clean
@@ -721,7 +721,17 @@ export namespace Provider {
721
721
 
722
722
  let installedPath: string;
723
723
  if (!pkg.startsWith('file://')) {
724
+ log.info('installing provider package', {
725
+ providerID: provider.id,
726
+ pkg,
727
+ version: 'latest',
728
+ });
724
729
  installedPath = await BunProc.install(pkg, 'latest');
730
+ log.info('provider package installed successfully', {
731
+ providerID: provider.id,
732
+ pkg,
733
+ installedPath,
734
+ });
725
735
  } else {
726
736
  log.info('loading local provider', { pkg });
727
737
  installedPath = pkg;
@@ -769,6 +779,13 @@ export namespace Provider {
769
779
  s.sdk.set(key, loaded);
770
780
  return loaded as SDK;
771
781
  })().catch((e) => {
782
+ log.error('provider initialization failed', {
783
+ providerID: provider.id,
784
+ pkg: model.provider?.npm ?? provider.npm ?? provider.id,
785
+ error: e instanceof Error ? e.message : String(e),
786
+ stack: e instanceof Error ? e.stack : undefined,
787
+ cause: e instanceof Error && e.cause ? String(e.cause) : undefined,
788
+ });
772
789
  throw new InitError({ providerID: provider.id }, { cause: e });
773
790
  });
774
791
  }