@link-assistant/agent 0.0.8 → 0.0.11

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.
Files changed (104) hide show
  1. package/EXAMPLES.md +80 -1
  2. package/MODELS.md +72 -24
  3. package/README.md +95 -2
  4. package/TOOLS.md +20 -0
  5. package/package.json +36 -2
  6. package/src/agent/agent.ts +68 -54
  7. package/src/auth/claude-oauth.ts +426 -0
  8. package/src/auth/index.ts +28 -26
  9. package/src/auth/plugins.ts +876 -0
  10. package/src/bun/index.ts +53 -43
  11. package/src/bus/global.ts +5 -5
  12. package/src/bus/index.ts +59 -53
  13. package/src/cli/bootstrap.js +12 -12
  14. package/src/cli/bootstrap.ts +6 -6
  15. package/src/cli/cmd/agent.ts +97 -92
  16. package/src/cli/cmd/auth.ts +468 -0
  17. package/src/cli/cmd/cmd.ts +2 -2
  18. package/src/cli/cmd/export.ts +41 -41
  19. package/src/cli/cmd/mcp.ts +210 -53
  20. package/src/cli/cmd/models.ts +30 -29
  21. package/src/cli/cmd/run.ts +269 -213
  22. package/src/cli/cmd/stats.ts +185 -146
  23. package/src/cli/error.ts +17 -13
  24. package/src/cli/ui.ts +78 -0
  25. package/src/command/index.ts +26 -26
  26. package/src/config/config.ts +528 -288
  27. package/src/config/markdown.ts +15 -15
  28. package/src/file/ripgrep.ts +201 -169
  29. package/src/file/time.ts +21 -18
  30. package/src/file/watcher.ts +51 -42
  31. package/src/file.ts +1 -1
  32. package/src/flag/flag.ts +26 -11
  33. package/src/format/formatter.ts +206 -162
  34. package/src/format/index.ts +61 -61
  35. package/src/global/index.ts +21 -21
  36. package/src/id/id.ts +47 -33
  37. package/src/index.js +554 -332
  38. package/src/json-standard/index.ts +173 -0
  39. package/src/mcp/index.ts +135 -128
  40. package/src/patch/index.ts +336 -267
  41. package/src/project/bootstrap.ts +15 -15
  42. package/src/project/instance.ts +43 -36
  43. package/src/project/project.ts +47 -47
  44. package/src/project/state.ts +37 -33
  45. package/src/provider/models-macro.ts +5 -5
  46. package/src/provider/models.ts +32 -32
  47. package/src/provider/opencode.js +19 -19
  48. package/src/provider/provider.ts +518 -277
  49. package/src/provider/transform.ts +143 -102
  50. package/src/server/project.ts +21 -21
  51. package/src/server/server.ts +111 -105
  52. package/src/session/agent.js +66 -60
  53. package/src/session/compaction.ts +136 -111
  54. package/src/session/index.ts +189 -156
  55. package/src/session/message-v2.ts +312 -268
  56. package/src/session/message.ts +73 -57
  57. package/src/session/processor.ts +180 -166
  58. package/src/session/prompt.ts +678 -533
  59. package/src/session/retry.ts +26 -23
  60. package/src/session/revert.ts +76 -62
  61. package/src/session/status.ts +26 -26
  62. package/src/session/summary.ts +97 -76
  63. package/src/session/system.ts +77 -63
  64. package/src/session/todo.ts +22 -16
  65. package/src/snapshot/index.ts +92 -76
  66. package/src/storage/storage.ts +157 -120
  67. package/src/tool/bash.ts +116 -106
  68. package/src/tool/batch.ts +73 -59
  69. package/src/tool/codesearch.ts +60 -53
  70. package/src/tool/edit.ts +319 -263
  71. package/src/tool/glob.ts +32 -28
  72. package/src/tool/grep.ts +72 -53
  73. package/src/tool/invalid.ts +7 -7
  74. package/src/tool/ls.ts +77 -64
  75. package/src/tool/multiedit.ts +30 -21
  76. package/src/tool/patch.ts +121 -94
  77. package/src/tool/read.ts +140 -122
  78. package/src/tool/registry.ts +38 -38
  79. package/src/tool/task.ts +93 -60
  80. package/src/tool/todo.ts +16 -16
  81. package/src/tool/tool.ts +45 -36
  82. package/src/tool/webfetch.ts +97 -74
  83. package/src/tool/websearch.ts +78 -64
  84. package/src/tool/write.ts +21 -15
  85. package/src/util/binary.ts +27 -19
  86. package/src/util/context.ts +8 -8
  87. package/src/util/defer.ts +7 -5
  88. package/src/util/error.ts +24 -19
  89. package/src/util/eventloop.ts +16 -10
  90. package/src/util/filesystem.ts +37 -33
  91. package/src/util/fn.ts +11 -8
  92. package/src/util/iife.ts +1 -1
  93. package/src/util/keybind.ts +44 -44
  94. package/src/util/lazy.ts +7 -7
  95. package/src/util/locale.ts +20 -16
  96. package/src/util/lock.ts +43 -38
  97. package/src/util/log.ts +95 -85
  98. package/src/util/queue.ts +8 -8
  99. package/src/util/rpc.ts +35 -23
  100. package/src/util/scrap.ts +4 -4
  101. package/src/util/signal.ts +5 -5
  102. package/src/util/timeout.ts +6 -6
  103. package/src/util/token.ts +2 -2
  104. package/src/util/wildcard.ts +38 -27
@@ -1,248 +1,292 @@
1
- import { readableStreamToText } from "bun"
2
- import { BunProc } from "../bun"
3
- import { Instance } from "../project/instance"
4
- import { Filesystem } from "../util/filesystem"
1
+ import { readableStreamToText } from 'bun';
2
+ import { BunProc } from '../bun';
3
+ import { Instance } from '../project/instance';
4
+ import { Filesystem } from '../util/filesystem';
5
5
 
6
6
  export interface Info {
7
- name: string
8
- command: string[]
9
- environment?: Record<string, string>
10
- extensions: string[]
11
- enabled(): Promise<boolean>
7
+ name: string;
8
+ command: string[];
9
+ environment?: Record<string, string>;
10
+ extensions: string[];
11
+ enabled(): Promise<boolean>;
12
12
  }
13
13
 
14
14
  export const gofmt: Info = {
15
- name: "gofmt",
16
- command: ["gofmt", "-w", "$FILE"],
17
- extensions: [".go"],
15
+ name: 'gofmt',
16
+ command: ['gofmt', '-w', '$FILE'],
17
+ extensions: ['.go'],
18
18
  async enabled() {
19
- return Bun.which("gofmt") !== null
19
+ return Bun.which('gofmt') !== null;
20
20
  },
21
- }
21
+ };
22
22
 
23
23
  export const mix: Info = {
24
- name: "mix",
25
- command: ["mix", "format", "$FILE"],
26
- extensions: [".ex", ".exs", ".eex", ".heex", ".leex", ".neex", ".sface"],
24
+ name: 'mix',
25
+ command: ['mix', 'format', '$FILE'],
26
+ extensions: ['.ex', '.exs', '.eex', '.heex', '.leex', '.neex', '.sface'],
27
27
  async enabled() {
28
- return Bun.which("mix") !== null
28
+ return Bun.which('mix') !== null;
29
29
  },
30
- }
30
+ };
31
31
 
32
32
  export const prettier: Info = {
33
- name: "prettier",
34
- command: [BunProc.which(), "x", "prettier", "--write", "$FILE"],
33
+ name: 'prettier',
34
+ command: [BunProc.which(), 'x', 'prettier', '--write', '$FILE'],
35
35
  environment: {
36
- BUN_BE_BUN: "1",
36
+ BUN_BE_BUN: '1',
37
37
  },
38
38
  extensions: [
39
- ".js",
40
- ".jsx",
41
- ".mjs",
42
- ".cjs",
43
- ".ts",
44
- ".tsx",
45
- ".mts",
46
- ".cts",
47
- ".html",
48
- ".htm",
49
- ".css",
50
- ".scss",
51
- ".sass",
52
- ".less",
53
- ".vue",
54
- ".svelte",
55
- ".json",
56
- ".jsonc",
57
- ".yaml",
58
- ".yml",
59
- ".toml",
60
- ".xml",
61
- ".md",
62
- ".mdx",
63
- ".graphql",
64
- ".gql",
39
+ '.js',
40
+ '.jsx',
41
+ '.mjs',
42
+ '.cjs',
43
+ '.ts',
44
+ '.tsx',
45
+ '.mts',
46
+ '.cts',
47
+ '.html',
48
+ '.htm',
49
+ '.css',
50
+ '.scss',
51
+ '.sass',
52
+ '.less',
53
+ '.vue',
54
+ '.svelte',
55
+ '.json',
56
+ '.jsonc',
57
+ '.yaml',
58
+ '.yml',
59
+ '.toml',
60
+ '.xml',
61
+ '.md',
62
+ '.mdx',
63
+ '.graphql',
64
+ '.gql',
65
65
  ],
66
66
  async enabled() {
67
- const items = await Filesystem.findUp("package.json", Instance.directory, Instance.worktree)
67
+ const items = await Filesystem.findUp(
68
+ 'package.json',
69
+ Instance.directory,
70
+ Instance.worktree
71
+ );
68
72
  for (const item of items) {
69
- const json = await Bun.file(item).json()
70
- if (json.dependencies?.prettier) return true
71
- if (json.devDependencies?.prettier) return true
73
+ const json = await Bun.file(item).json();
74
+ if (json.dependencies?.prettier) return true;
75
+ if (json.devDependencies?.prettier) return true;
72
76
  }
73
- return false
77
+ return false;
74
78
  },
75
- }
79
+ };
76
80
 
77
81
  export const biome: Info = {
78
- name: "biome",
79
- command: [BunProc.which(), "x", "@biomejs/biome", "format", "--write", "$FILE"],
82
+ name: 'biome',
83
+ command: [
84
+ BunProc.which(),
85
+ 'x',
86
+ '@biomejs/biome',
87
+ 'format',
88
+ '--write',
89
+ '$FILE',
90
+ ],
80
91
  environment: {
81
- BUN_BE_BUN: "1",
92
+ BUN_BE_BUN: '1',
82
93
  },
83
94
  extensions: [
84
- ".js",
85
- ".jsx",
86
- ".mjs",
87
- ".cjs",
88
- ".ts",
89
- ".tsx",
90
- ".mts",
91
- ".cts",
92
- ".html",
93
- ".htm",
94
- ".css",
95
- ".scss",
96
- ".sass",
97
- ".less",
98
- ".vue",
99
- ".svelte",
100
- ".json",
101
- ".jsonc",
102
- ".yaml",
103
- ".yml",
104
- ".toml",
105
- ".xml",
106
- ".md",
107
- ".mdx",
108
- ".graphql",
109
- ".gql",
95
+ '.js',
96
+ '.jsx',
97
+ '.mjs',
98
+ '.cjs',
99
+ '.ts',
100
+ '.tsx',
101
+ '.mts',
102
+ '.cts',
103
+ '.html',
104
+ '.htm',
105
+ '.css',
106
+ '.scss',
107
+ '.sass',
108
+ '.less',
109
+ '.vue',
110
+ '.svelte',
111
+ '.json',
112
+ '.jsonc',
113
+ '.yaml',
114
+ '.yml',
115
+ '.toml',
116
+ '.xml',
117
+ '.md',
118
+ '.mdx',
119
+ '.graphql',
120
+ '.gql',
110
121
  ],
111
122
  async enabled() {
112
- const configs = ["biome.json", "biome.jsonc"]
123
+ const configs = ['biome.json', 'biome.jsonc'];
113
124
  for (const config of configs) {
114
- const found = await Filesystem.findUp(config, Instance.directory, Instance.worktree)
125
+ const found = await Filesystem.findUp(
126
+ config,
127
+ Instance.directory,
128
+ Instance.worktree
129
+ );
115
130
  if (found.length > 0) {
116
- return true
131
+ return true;
117
132
  }
118
133
  }
119
- return false
134
+ return false;
120
135
  },
121
- }
136
+ };
122
137
 
123
138
  export const zig: Info = {
124
- name: "zig",
125
- command: ["zig", "fmt", "$FILE"],
126
- extensions: [".zig", ".zon"],
139
+ name: 'zig',
140
+ command: ['zig', 'fmt', '$FILE'],
141
+ extensions: ['.zig', '.zon'],
127
142
  async enabled() {
128
- return Bun.which("zig") !== null
143
+ return Bun.which('zig') !== null;
129
144
  },
130
- }
145
+ };
131
146
 
132
147
  export const clang: Info = {
133
- name: "clang-format",
134
- command: ["clang-format", "-i", "$FILE"],
135
- extensions: [".c", ".cc", ".cpp", ".cxx", ".c++", ".h", ".hh", ".hpp", ".hxx", ".h++", ".ino", ".C", ".H"],
148
+ name: 'clang-format',
149
+ command: ['clang-format', '-i', '$FILE'],
150
+ extensions: [
151
+ '.c',
152
+ '.cc',
153
+ '.cpp',
154
+ '.cxx',
155
+ '.c++',
156
+ '.h',
157
+ '.hh',
158
+ '.hpp',
159
+ '.hxx',
160
+ '.h++',
161
+ '.ino',
162
+ '.C',
163
+ '.H',
164
+ ],
136
165
  async enabled() {
137
- const items = await Filesystem.findUp(".clang-format", Instance.directory, Instance.worktree)
138
- return items.length > 0
166
+ const items = await Filesystem.findUp(
167
+ '.clang-format',
168
+ Instance.directory,
169
+ Instance.worktree
170
+ );
171
+ return items.length > 0;
139
172
  },
140
- }
173
+ };
141
174
 
142
175
  export const ktlint: Info = {
143
- name: "ktlint",
144
- command: ["ktlint", "-F", "$FILE"],
145
- extensions: [".kt", ".kts"],
176
+ name: 'ktlint',
177
+ command: ['ktlint', '-F', '$FILE'],
178
+ extensions: ['.kt', '.kts'],
146
179
  async enabled() {
147
- return Bun.which("ktlint") !== null
180
+ return Bun.which('ktlint') !== null;
148
181
  },
149
- }
182
+ };
150
183
 
151
184
  export const ruff: Info = {
152
- name: "ruff",
153
- command: ["ruff", "format", "$FILE"],
154
- extensions: [".py", ".pyi"],
185
+ name: 'ruff',
186
+ command: ['ruff', 'format', '$FILE'],
187
+ extensions: ['.py', '.pyi'],
155
188
  async enabled() {
156
- if (!Bun.which("ruff")) return false
157
- const configs = ["pyproject.toml", "ruff.toml", ".ruff.toml"]
189
+ if (!Bun.which('ruff')) return false;
190
+ const configs = ['pyproject.toml', 'ruff.toml', '.ruff.toml'];
158
191
  for (const config of configs) {
159
- const found = await Filesystem.findUp(config, Instance.directory, Instance.worktree)
192
+ const found = await Filesystem.findUp(
193
+ config,
194
+ Instance.directory,
195
+ Instance.worktree
196
+ );
160
197
  if (found.length > 0) {
161
- if (config === "pyproject.toml") {
162
- const content = await Bun.file(found[0]).text()
163
- if (content.includes("[tool.ruff]")) return true
198
+ if (config === 'pyproject.toml') {
199
+ const content = await Bun.file(found[0]).text();
200
+ if (content.includes('[tool.ruff]')) return true;
164
201
  } else {
165
- return true
202
+ return true;
166
203
  }
167
204
  }
168
205
  }
169
- const deps = ["requirements.txt", "pyproject.toml", "Pipfile"]
206
+ const deps = ['requirements.txt', 'pyproject.toml', 'Pipfile'];
170
207
  for (const dep of deps) {
171
- const found = await Filesystem.findUp(dep, Instance.directory, Instance.worktree)
208
+ const found = await Filesystem.findUp(
209
+ dep,
210
+ Instance.directory,
211
+ Instance.worktree
212
+ );
172
213
  if (found.length > 0) {
173
- const content = await Bun.file(found[0]).text()
174
- if (content.includes("ruff")) return true
214
+ const content = await Bun.file(found[0]).text();
215
+ if (content.includes('ruff')) return true;
175
216
  }
176
217
  }
177
- return false
218
+ return false;
178
219
  },
179
- }
220
+ };
180
221
 
181
222
  export const rlang: Info = {
182
- name: "air",
183
- command: ["air", "format", "$FILE"],
184
- extensions: [".R"],
223
+ name: 'air',
224
+ command: ['air', 'format', '$FILE'],
225
+ extensions: ['.R'],
185
226
  async enabled() {
186
- const airPath = Bun.which("air")
187
- if (airPath == null) return false
227
+ const airPath = Bun.which('air');
228
+ if (airPath == null) return false;
188
229
 
189
230
  try {
190
- const proc = Bun.spawn(["air", "--help"], {
191
- stdout: "pipe",
192
- stderr: "pipe",
193
- })
194
- await proc.exited
195
- const output = await readableStreamToText(proc.stdout)
231
+ const proc = Bun.spawn(['air', '--help'], {
232
+ stdout: 'pipe',
233
+ stderr: 'pipe',
234
+ });
235
+ await proc.exited;
236
+ const output = await readableStreamToText(proc.stdout);
196
237
 
197
238
  // Check for "Air: An R language server and formatter"
198
- const firstLine = output.split("\n")[0]
199
- const hasR = firstLine.includes("R language")
200
- const hasFormatter = firstLine.includes("formatter")
201
- return hasR && hasFormatter
239
+ const firstLine = output.split('\n')[0];
240
+ const hasR = firstLine.includes('R language');
241
+ const hasFormatter = firstLine.includes('formatter');
242
+ return hasR && hasFormatter;
202
243
  } catch (error) {
203
- return false
244
+ return false;
204
245
  }
205
246
  },
206
- }
247
+ };
207
248
 
208
249
  export const uvformat: Info = {
209
- name: "uv format",
210
- command: ["uv", "format", "--", "$FILE"],
211
- extensions: [".py", ".pyi"],
250
+ name: 'uv format',
251
+ command: ['uv', 'format', '--', '$FILE'],
252
+ extensions: ['.py', '.pyi'],
212
253
  async enabled() {
213
- if (await ruff.enabled()) return false
214
- if (Bun.which("uv") !== null) {
215
- const proc = Bun.spawn(["uv", "format", "--help"], { stderr: "pipe", stdout: "pipe" })
216
- const code = await proc.exited
217
- return code === 0
254
+ if (await ruff.enabled()) return false;
255
+ if (Bun.which('uv') !== null) {
256
+ const proc = Bun.spawn(['uv', 'format', '--help'], {
257
+ stderr: 'pipe',
258
+ stdout: 'pipe',
259
+ });
260
+ const code = await proc.exited;
261
+ return code === 0;
218
262
  }
219
- return false
263
+ return false;
220
264
  },
221
- }
265
+ };
222
266
 
223
267
  export const rubocop: Info = {
224
- name: "rubocop",
225
- command: ["rubocop", "--autocorrect", "$FILE"],
226
- extensions: [".rb", ".rake", ".gemspec", ".ru"],
268
+ name: 'rubocop',
269
+ command: ['rubocop', '--autocorrect', '$FILE'],
270
+ extensions: ['.rb', '.rake', '.gemspec', '.ru'],
227
271
  async enabled() {
228
- return Bun.which("rubocop") !== null
272
+ return Bun.which('rubocop') !== null;
229
273
  },
230
- }
274
+ };
231
275
 
232
276
  export const standardrb: Info = {
233
- name: "standardrb",
234
- command: ["standardrb", "--fix", "$FILE"],
235
- extensions: [".rb", ".rake", ".gemspec", ".ru"],
277
+ name: 'standardrb',
278
+ command: ['standardrb', '--fix', '$FILE'],
279
+ extensions: ['.rb', '.rake', '.gemspec', '.ru'],
236
280
  async enabled() {
237
- return Bun.which("standardrb") !== null
281
+ return Bun.which('standardrb') !== null;
238
282
  },
239
- }
283
+ };
240
284
 
241
285
  export const htmlbeautifier: Info = {
242
- name: "htmlbeautifier",
243
- command: ["htmlbeautifier", "$FILE"],
244
- extensions: [".erb", ".html.erb"],
286
+ name: 'htmlbeautifier',
287
+ command: ['htmlbeautifier', '$FILE'],
288
+ extensions: ['.erb', '.html.erb'],
245
289
  async enabled() {
246
- return Bun.which("htmlbeautifier") !== null
290
+ return Bun.which('htmlbeautifier') !== null;
247
291
  },
248
- }
292
+ };
@@ -1,16 +1,16 @@
1
- import { Bus } from "../bus"
2
- import { File } from "../file"
3
- import { Log } from "../util/log"
4
- import path from "path"
5
- import z from "zod"
1
+ import { Bus } from '../bus';
2
+ import { File } from '../file';
3
+ import { Log } from '../util/log';
4
+ import path from 'path';
5
+ import z from 'zod';
6
6
 
7
- import * as Formatter from "./formatter"
8
- import { Config } from "../config/config"
9
- import { mergeDeep } from "remeda"
10
- import { Instance } from "../project/instance"
7
+ import * as Formatter from './formatter';
8
+ import { Config } from '../config/config';
9
+ import { mergeDeep } from 'remeda';
10
+ import { Instance } from '../project/instance';
11
11
 
12
12
  export namespace Format {
13
- const log = Log.create({ service: "format" })
13
+ const log = Log.create({ service: 'format' });
14
14
 
15
15
  export const Status = z
16
16
  .object({
@@ -19,119 +19,119 @@ export namespace Format {
19
19
  enabled: z.boolean(),
20
20
  })
21
21
  .meta({
22
- ref: "FormatterStatus",
23
- })
24
- export type Status = z.infer<typeof Status>
22
+ ref: 'FormatterStatus',
23
+ });
24
+ export type Status = z.infer<typeof Status>;
25
25
 
26
26
  const state = Instance.state(async () => {
27
- const enabled: Record<string, boolean> = {}
28
- const cfg = await Config.get()
27
+ const enabled: Record<string, boolean> = {};
28
+ const cfg = await Config.get();
29
29
 
30
- const formatters: Record<string, Formatter.Info> = {}
30
+ const formatters: Record<string, Formatter.Info> = {};
31
31
  if (cfg.formatter === false) {
32
- log.info("all formatters are disabled")
32
+ log.info('all formatters are disabled');
33
33
  return {
34
34
  enabled,
35
35
  formatters,
36
- }
36
+ };
37
37
  }
38
38
 
39
39
  for (const item of Object.values(Formatter)) {
40
- formatters[item.name] = item
40
+ formatters[item.name] = item;
41
41
  }
42
42
  for (const [name, item] of Object.entries(cfg.formatter ?? {})) {
43
43
  if (item.disabled) {
44
- delete formatters[name]
45
- continue
44
+ delete formatters[name];
45
+ continue;
46
46
  }
47
47
  const result: Formatter.Info = mergeDeep(formatters[name] ?? {}, {
48
48
  command: [],
49
49
  extensions: [],
50
50
  ...item,
51
- })
51
+ });
52
52
 
53
- if (result.command.length === 0) continue
53
+ if (result.command.length === 0) continue;
54
54
 
55
- result.enabled = async () => true
56
- result.name = name
57
- formatters[name] = result
55
+ result.enabled = async () => true;
56
+ result.name = name;
57
+ formatters[name] = result;
58
58
  }
59
59
 
60
60
  return {
61
61
  enabled,
62
62
  formatters,
63
- }
64
- })
63
+ };
64
+ });
65
65
 
66
66
  async function isEnabled(item: Formatter.Info) {
67
- const s = await state()
68
- let status = s.enabled[item.name]
67
+ const s = await state();
68
+ let status = s.enabled[item.name];
69
69
  if (status === undefined) {
70
- status = await item.enabled()
71
- s.enabled[item.name] = status
70
+ status = await item.enabled();
71
+ s.enabled[item.name] = status;
72
72
  }
73
- return status
73
+ return status;
74
74
  }
75
75
 
76
76
  async function getFormatter(ext: string) {
77
- const formatters = await state().then((x) => x.formatters)
78
- const result = []
77
+ const formatters = await state().then((x) => x.formatters);
78
+ const result = [];
79
79
  for (const item of Object.values(formatters)) {
80
- log.info("checking", { name: item.name, ext })
81
- if (!item.extensions.includes(ext)) continue
82
- if (!(await isEnabled(item))) continue
83
- log.info("enabled", { name: item.name, ext })
84
- result.push(item)
80
+ log.info('checking', { name: item.name, ext });
81
+ if (!item.extensions.includes(ext)) continue;
82
+ if (!(await isEnabled(item))) continue;
83
+ log.info('enabled', { name: item.name, ext });
84
+ result.push(item);
85
85
  }
86
- return result
86
+ return result;
87
87
  }
88
88
 
89
89
  export async function status() {
90
- const s = await state()
91
- const result: Status[] = []
90
+ const s = await state();
91
+ const result: Status[] = [];
92
92
  for (const formatter of Object.values(s.formatters)) {
93
- const enabled = await isEnabled(formatter)
93
+ const enabled = await isEnabled(formatter);
94
94
  result.push({
95
95
  name: formatter.name,
96
96
  extensions: formatter.extensions,
97
97
  enabled,
98
- })
98
+ });
99
99
  }
100
- return result
100
+ return result;
101
101
  }
102
102
 
103
103
  export function init() {
104
- log.info("init")
104
+ log.info('init');
105
105
  Bus.subscribe(File.Event.Edited, async (payload) => {
106
- const file = payload.properties.file
107
- log.info("formatting", { file })
108
- const ext = path.extname(file)
106
+ const file = payload.properties.file;
107
+ log.info('formatting', { file });
108
+ const ext = path.extname(file);
109
109
 
110
110
  for (const item of await getFormatter(ext)) {
111
- log.info("running", { command: item.command })
111
+ log.info('running', { command: item.command });
112
112
  try {
113
113
  const proc = Bun.spawn({
114
- cmd: item.command.map((x) => x.replace("$FILE", file)),
114
+ cmd: item.command.map((x) => x.replace('$FILE', file)),
115
115
  cwd: Instance.directory,
116
116
  env: { ...process.env, ...item.environment },
117
- stdout: "ignore",
118
- stderr: "ignore",
119
- })
120
- const exit = await proc.exited
117
+ stdout: 'ignore',
118
+ stderr: 'ignore',
119
+ });
120
+ const exit = await proc.exited;
121
121
  if (exit !== 0)
122
- log.error("failed", {
122
+ log.error('failed', {
123
123
  command: item.command,
124
124
  ...item.environment,
125
- })
125
+ });
126
126
  } catch (error) {
127
- log.error("failed to format file", {
127
+ log.error('failed to format file', {
128
128
  error,
129
129
  command: item.command,
130
130
  ...item.environment,
131
131
  file,
132
- })
132
+ });
133
133
  }
134
134
  }
135
- })
135
+ });
136
136
  }
137
137
  }