@link-assistant/agent 0.0.8

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 (133) hide show
  1. package/EXAMPLES.md +383 -0
  2. package/LICENSE +24 -0
  3. package/MODELS.md +95 -0
  4. package/README.md +388 -0
  5. package/TOOLS.md +134 -0
  6. package/package.json +89 -0
  7. package/src/agent/agent.ts +150 -0
  8. package/src/agent/generate.txt +75 -0
  9. package/src/auth/index.ts +64 -0
  10. package/src/bun/index.ts +96 -0
  11. package/src/bus/global.ts +10 -0
  12. package/src/bus/index.ts +119 -0
  13. package/src/cli/bootstrap.js +41 -0
  14. package/src/cli/bootstrap.ts +17 -0
  15. package/src/cli/cmd/agent.ts +165 -0
  16. package/src/cli/cmd/cmd.ts +5 -0
  17. package/src/cli/cmd/export.ts +88 -0
  18. package/src/cli/cmd/mcp.ts +80 -0
  19. package/src/cli/cmd/models.ts +58 -0
  20. package/src/cli/cmd/run.ts +359 -0
  21. package/src/cli/cmd/stats.ts +276 -0
  22. package/src/cli/error.ts +27 -0
  23. package/src/command/index.ts +73 -0
  24. package/src/command/template/initialize.txt +10 -0
  25. package/src/config/config.ts +705 -0
  26. package/src/config/markdown.ts +41 -0
  27. package/src/file/ripgrep.ts +391 -0
  28. package/src/file/time.ts +38 -0
  29. package/src/file/watcher.ts +75 -0
  30. package/src/file.ts +6 -0
  31. package/src/flag/flag.ts +19 -0
  32. package/src/format/formatter.ts +248 -0
  33. package/src/format/index.ts +137 -0
  34. package/src/global/index.ts +52 -0
  35. package/src/id/id.ts +72 -0
  36. package/src/index.js +371 -0
  37. package/src/mcp/index.ts +289 -0
  38. package/src/patch/index.ts +622 -0
  39. package/src/project/bootstrap.ts +22 -0
  40. package/src/project/instance.ts +67 -0
  41. package/src/project/project.ts +105 -0
  42. package/src/project/state.ts +65 -0
  43. package/src/provider/models-macro.ts +11 -0
  44. package/src/provider/models.ts +98 -0
  45. package/src/provider/opencode.js +47 -0
  46. package/src/provider/provider.ts +636 -0
  47. package/src/provider/transform.ts +241 -0
  48. package/src/server/project.ts +48 -0
  49. package/src/server/server.ts +249 -0
  50. package/src/session/agent.js +204 -0
  51. package/src/session/compaction.ts +249 -0
  52. package/src/session/index.ts +380 -0
  53. package/src/session/message-v2.ts +758 -0
  54. package/src/session/message.ts +189 -0
  55. package/src/session/processor.ts +356 -0
  56. package/src/session/prompt/anthropic-20250930.txt +166 -0
  57. package/src/session/prompt/anthropic.txt +105 -0
  58. package/src/session/prompt/anthropic_spoof.txt +1 -0
  59. package/src/session/prompt/beast.txt +147 -0
  60. package/src/session/prompt/build-switch.txt +5 -0
  61. package/src/session/prompt/codex.txt +318 -0
  62. package/src/session/prompt/copilot-gpt-5.txt +143 -0
  63. package/src/session/prompt/gemini.txt +155 -0
  64. package/src/session/prompt/grok-code.txt +1 -0
  65. package/src/session/prompt/plan.txt +8 -0
  66. package/src/session/prompt/polaris.txt +107 -0
  67. package/src/session/prompt/qwen.txt +109 -0
  68. package/src/session/prompt/summarize-turn.txt +5 -0
  69. package/src/session/prompt/summarize.txt +10 -0
  70. package/src/session/prompt/title.txt +25 -0
  71. package/src/session/prompt.ts +1390 -0
  72. package/src/session/retry.ts +53 -0
  73. package/src/session/revert.ts +108 -0
  74. package/src/session/status.ts +75 -0
  75. package/src/session/summary.ts +179 -0
  76. package/src/session/system.ts +138 -0
  77. package/src/session/todo.ts +36 -0
  78. package/src/snapshot/index.ts +197 -0
  79. package/src/storage/storage.ts +226 -0
  80. package/src/tool/bash.ts +193 -0
  81. package/src/tool/bash.txt +121 -0
  82. package/src/tool/batch.ts +173 -0
  83. package/src/tool/batch.txt +28 -0
  84. package/src/tool/codesearch.ts +123 -0
  85. package/src/tool/codesearch.txt +12 -0
  86. package/src/tool/edit.ts +604 -0
  87. package/src/tool/edit.txt +10 -0
  88. package/src/tool/glob.ts +65 -0
  89. package/src/tool/glob.txt +6 -0
  90. package/src/tool/grep.ts +116 -0
  91. package/src/tool/grep.txt +8 -0
  92. package/src/tool/invalid.ts +17 -0
  93. package/src/tool/ls.ts +110 -0
  94. package/src/tool/ls.txt +1 -0
  95. package/src/tool/multiedit.ts +46 -0
  96. package/src/tool/multiedit.txt +41 -0
  97. package/src/tool/patch.ts +188 -0
  98. package/src/tool/patch.txt +1 -0
  99. package/src/tool/read.ts +201 -0
  100. package/src/tool/read.txt +12 -0
  101. package/src/tool/registry.ts +87 -0
  102. package/src/tool/task.ts +126 -0
  103. package/src/tool/task.txt +60 -0
  104. package/src/tool/todo.ts +39 -0
  105. package/src/tool/todoread.txt +14 -0
  106. package/src/tool/todowrite.txt +167 -0
  107. package/src/tool/tool.ts +66 -0
  108. package/src/tool/webfetch.ts +171 -0
  109. package/src/tool/webfetch.txt +14 -0
  110. package/src/tool/websearch.ts +133 -0
  111. package/src/tool/websearch.txt +11 -0
  112. package/src/tool/write.ts +33 -0
  113. package/src/tool/write.txt +8 -0
  114. package/src/util/binary.ts +41 -0
  115. package/src/util/context.ts +25 -0
  116. package/src/util/defer.ts +12 -0
  117. package/src/util/error.ts +54 -0
  118. package/src/util/eventloop.ts +20 -0
  119. package/src/util/filesystem.ts +69 -0
  120. package/src/util/fn.ts +11 -0
  121. package/src/util/iife.ts +3 -0
  122. package/src/util/keybind.ts +79 -0
  123. package/src/util/lazy.ts +11 -0
  124. package/src/util/locale.ts +39 -0
  125. package/src/util/lock.ts +98 -0
  126. package/src/util/log.ts +177 -0
  127. package/src/util/queue.ts +19 -0
  128. package/src/util/rpc.ts +42 -0
  129. package/src/util/scrap.ts +10 -0
  130. package/src/util/signal.ts +12 -0
  131. package/src/util/timeout.ts +14 -0
  132. package/src/util/token.ts +7 -0
  133. package/src/util/wildcard.ts +54 -0
@@ -0,0 +1,105 @@
1
+ import z from "zod"
2
+ import { Filesystem } from "../util/filesystem"
3
+ import path from "path"
4
+ import { $ } from "bun"
5
+ import { Storage } from "../storage/storage"
6
+ import { Log } from "../util/log"
7
+ import { Flag } from "../flag/flag"
8
+
9
+ export namespace Project {
10
+ const log = Log.create({ service: "project" })
11
+ export const Info = z
12
+ .object({
13
+ id: z.string(),
14
+ worktree: z.string(),
15
+ vcs: z.literal("git").optional(),
16
+ time: z.object({
17
+ created: z.number(),
18
+ initialized: z.number().optional(),
19
+ }),
20
+ })
21
+ .meta({
22
+ ref: "Project",
23
+ })
24
+ export type Info = z.infer<typeof Info>
25
+
26
+ export async function fromDirectory(directory: string) {
27
+ log.info("fromDirectory", { directory })
28
+ const matches = Filesystem.up({ targets: [".git"], start: directory })
29
+ const git = await matches.next().then((x) => x.value)
30
+ await matches.return()
31
+ if (!git) {
32
+ const project: Info = {
33
+ id: "global",
34
+ worktree: "/",
35
+ vcs: "none", // No VCS
36
+ time: {
37
+ created: Date.now(),
38
+ },
39
+ }
40
+ await Storage.write<Info>(["project", "global"], project)
41
+ return project
42
+ }
43
+ let worktree = path.dirname(git)
44
+ const timer = log.time("git.rev-parse")
45
+ let id = await Bun.file(path.join(git, "opencode"))
46
+ .text()
47
+ .then((x) => x.trim())
48
+ .catch(() => {})
49
+ if (!id) {
50
+ const roots = await $`git rev-list --max-parents=0 --all`
51
+ .quiet()
52
+ .nothrow()
53
+ .cwd(worktree)
54
+ .text()
55
+ .then((x) =>
56
+ x
57
+ .split("\n")
58
+ .filter(Boolean)
59
+ .map((x) => x.trim())
60
+ .toSorted(),
61
+ )
62
+ id = roots[0]
63
+ if (id) Bun.file(path.join(git, "opencode")).write(id)
64
+ }
65
+ timer.stop()
66
+ if (!id) {
67
+ const project: Info = {
68
+ id: "global",
69
+ worktree: "/",
70
+ time: {
71
+ created: Date.now(),
72
+ },
73
+ }
74
+ await Storage.write<Info>(["project", "global"], project)
75
+ return project
76
+ }
77
+ worktree = await $`git rev-parse --path-format=absolute --show-toplevel`
78
+ .quiet()
79
+ .nothrow()
80
+ .cwd(worktree)
81
+ .text()
82
+ .then((x) => x.trim())
83
+ const project: Info = {
84
+ id,
85
+ worktree,
86
+ vcs: "git",
87
+ time: {
88
+ created: Date.now(),
89
+ },
90
+ }
91
+ await Storage.write<Info>(["project", id], project)
92
+ return project
93
+ }
94
+
95
+ export async function setInitialized(projectID: string) {
96
+ await Storage.update<Info>(["project", projectID], (draft) => {
97
+ draft.time.initialized = Date.now()
98
+ })
99
+ }
100
+
101
+ export async function list() {
102
+ const keys = await Storage.list(["project"])
103
+ return await Promise.all(keys.map((x) => Storage.read<Info>(x)))
104
+ }
105
+ }
@@ -0,0 +1,65 @@
1
+ import { Log } from "../util/log"
2
+
3
+ export namespace State {
4
+ interface Entry {
5
+ state: any
6
+ dispose?: (state: any) => Promise<void>
7
+ }
8
+
9
+ const log = Log.create({ service: "state" })
10
+ const recordsByKey = new Map<string, Map<any, Entry>>()
11
+
12
+ export function create<S>(root: () => string, init: () => S, dispose?: (state: Awaited<S>) => Promise<void>) {
13
+ return () => {
14
+ const key = root()
15
+ let entries = recordsByKey.get(key)
16
+ if (!entries) {
17
+ entries = new Map<string, Entry>()
18
+ recordsByKey.set(key, entries)
19
+ }
20
+ const exists = entries.get(init)
21
+ if (exists) return exists.state as S
22
+ const state = init()
23
+ entries.set(init, {
24
+ state,
25
+ dispose,
26
+ })
27
+ return state
28
+ }
29
+ }
30
+
31
+ export async function dispose(key: string) {
32
+ const entries = recordsByKey.get(key)
33
+ if (!entries) return
34
+
35
+ log.info("waiting for state disposal to complete", { key })
36
+
37
+ let disposalFinished = false
38
+
39
+ setTimeout(() => {
40
+ if (!disposalFinished) {
41
+ log.warn(
42
+ "state disposal is taking an unusually long time - if it does not complete in a reasonable time, please report this as a bug",
43
+ { key },
44
+ )
45
+ }
46
+ }, 10000).unref()
47
+
48
+ const tasks: Promise<void>[] = []
49
+ for (const entry of entries.values()) {
50
+ if (!entry.dispose) continue
51
+
52
+ const task = Promise.resolve(entry.state)
53
+ .then((state) => entry.dispose!(state))
54
+ .catch((error) => {
55
+ log.error("Error while disposing state:", { error, key })
56
+ })
57
+
58
+ tasks.push(task)
59
+ }
60
+ await Promise.all(tasks)
61
+ recordsByKey.delete(key)
62
+ disposalFinished = true
63
+ log.info("state disposal completed", { key })
64
+ }
65
+ }
@@ -0,0 +1,11 @@
1
+ export async function data() {
2
+ const path = Bun.env.MODELS_DEV_API_JSON
3
+ if (path) {
4
+ const file = Bun.file(path)
5
+ if (await file.exists()) {
6
+ return await file.text()
7
+ }
8
+ }
9
+ const json = await fetch("https://models.dev/api.json").then((x) => x.text())
10
+ return json
11
+ }
@@ -0,0 +1,98 @@
1
+ import { Global } from "../global"
2
+ import { Log } from "../util/log"
3
+ import path from "path"
4
+ import z from "zod"
5
+ import { data } from "./models-macro"
6
+
7
+ export namespace ModelsDev {
8
+ const log = Log.create({ service: "models.dev" })
9
+ const filepath = path.join(Global.Path.cache, "models.json")
10
+
11
+ export const Model = z
12
+ .object({
13
+ id: z.string(),
14
+ name: z.string(),
15
+ release_date: z.string(),
16
+ attachment: z.boolean(),
17
+ reasoning: z.boolean(),
18
+ temperature: z.boolean(),
19
+ tool_call: z.boolean(),
20
+ cost: z.object({
21
+ input: z.number(),
22
+ output: z.number(),
23
+ cache_read: z.number().optional(),
24
+ cache_write: z.number().optional(),
25
+ context_over_200k: z
26
+ .object({
27
+ input: z.number(),
28
+ output: z.number(),
29
+ cache_read: z.number().optional(),
30
+ cache_write: z.number().optional(),
31
+ })
32
+ .optional(),
33
+ }),
34
+ limit: z.object({
35
+ context: z.number(),
36
+ output: z.number(),
37
+ }),
38
+ modalities: z
39
+ .object({
40
+ input: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
41
+ output: z.array(z.enum(["text", "audio", "image", "video", "pdf"])),
42
+ })
43
+ .optional(),
44
+ experimental: z.boolean().optional(),
45
+ status: z.enum(["alpha", "beta", "deprecated"]).optional(),
46
+ options: z.record(z.string(), z.any()),
47
+ headers: z.record(z.string(), z.string()).optional(),
48
+ provider: z.object({ npm: z.string() }).optional(),
49
+ })
50
+ .meta({
51
+ ref: "Model",
52
+ })
53
+ export type Model = z.infer<typeof Model>
54
+
55
+ export const Provider = z
56
+ .object({
57
+ api: z.string().optional(),
58
+ name: z.string(),
59
+ env: z.array(z.string()),
60
+ id: z.string(),
61
+ npm: z.string().optional(),
62
+ models: z.record(z.string(), Model),
63
+ })
64
+ .meta({
65
+ ref: "Provider",
66
+ })
67
+
68
+ export type Provider = z.infer<typeof Provider>
69
+
70
+ export async function get() {
71
+ refresh()
72
+ const file = Bun.file(filepath)
73
+ const result = await file.json().catch(() => {})
74
+ if (result) return result as Record<string, Provider>
75
+ const json = await data()
76
+ return JSON.parse(json) as Record<string, Provider>
77
+ }
78
+
79
+ export async function refresh() {
80
+ const file = Bun.file(filepath)
81
+ log.info("refreshing", {
82
+ file,
83
+ })
84
+ const result = await fetch("https://models.dev/api.json", {
85
+ headers: {
86
+ "User-Agent": "agent-cli/1.0.0",
87
+ },
88
+ signal: AbortSignal.timeout(10 * 1000),
89
+ }).catch((e) => {
90
+ log.error("Failed to fetch models.dev", {
91
+ error: e,
92
+ })
93
+ })
94
+ if (result && result.ok) await Bun.write(file, await result.text())
95
+ }
96
+ }
97
+
98
+ setInterval(() => ModelsDev.refresh(), 60 * 1000 * 60).unref()
@@ -0,0 +1,47 @@
1
+ // Permalink: https://github.com/sst/opencode/blob/main/packages/opencode/src/provider/provider.ts
2
+
3
+ import { createOpenCode } from '@opencode-ai/sdk'
4
+
5
+ class OpenCodeProvider {
6
+ constructor() {
7
+ this.name = 'opencode'
8
+ }
9
+
10
+ async getModel(modelId) {
11
+ // For grok-code, return a model that uses the opencode API
12
+ if (modelId === 'grok-code') {
13
+ return {
14
+ id: 'grok-code',
15
+ provider: this,
16
+ generateText: async (options) => {
17
+ // Use opencode API
18
+ const opencode = await createOpenCode()
19
+ const { client } = opencode
20
+
21
+ const sessionResult = await client.session.create()
22
+ const sessionId = sessionResult.data?.id
23
+
24
+ await client.session.prompt({
25
+ path: { id: sessionId },
26
+ body: {
27
+ agent: "build",
28
+ model: { providerID: "opencode", modelID: "grok-code" },
29
+ parts: [{ type: "text", text: options.prompt }]
30
+ }
31
+ })
32
+
33
+ // For simplicity, return a mock response
34
+ return {
35
+ text: 'Hello from Grok Code!',
36
+ usage: { promptTokens: 10, completionTokens: 5 }
37
+ }
38
+ }
39
+ }
40
+ }
41
+ throw new Error(`Model ${modelId} not found`)
42
+ }
43
+ }
44
+
45
+ const opencodeProvider = new OpenCodeProvider()
46
+
47
+ export { opencodeProvider }