openfork 1.17.16 → 1.17.18
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/script/trace-imports.ts +1 -1
- package/specs/v2/api.ts +2 -2
- package/src/acp/service.ts +7 -7
- package/src/acp/usage.ts +4 -4
- package/src/cli/cmd/account.ts +1 -1
- package/src/cli/cmd/github.handler.ts +5 -5
- package/src/cli/cmd/pr.ts +2 -2
- package/src/cli/cmd/providers.ts +2 -2
- package/src/cli/cmd/run/footer.permission.tsx +2 -2
- package/src/cli/cmd/run/footer.prompt.tsx +1 -1
- package/src/cli/cmd/run/permission.shared.ts +2 -2
- package/src/cli/cmd/run/splash.ts +1 -1
- package/src/cli/cmd/uninstall.ts +2 -2
- package/src/config/config.ts +5 -5
- package/src/config/managed.ts +1 -1
- package/src/config/tui-migrate.ts +3 -3
- package/src/installation/index.ts +3 -3
- package/src/mcp/index.ts +4 -4
- package/src/mcp/oauth-provider.ts +1 -1
- package/src/plugin/digitalocean.ts +1 -1
- package/src/plugin/github-copilot/models.ts +1 -1
- package/src/plugin/shared.ts +4 -4
- package/src/plugin/snowflake-cortex.ts +1 -1
- package/src/provider/provider.ts +7 -7
- package/src/provider/transform.ts +1 -1
- package/src/server/routes/instance/httpapi/api.ts +1 -1
- package/src/server/routes/instance/httpapi/groups/config.ts +2 -2
- package/src/server/routes/instance/httpapi/groups/experimental.ts +3 -3
- package/src/server/routes/instance/httpapi/groups/global.ts +5 -5
- package/src/server/routes/instance/httpapi/groups/instance.ts +5 -5
- package/src/server/routes/instance/httpapi/groups/project.ts +2 -2
- package/src/server/routes/instance/httpapi/groups/pty.ts +1 -1
- package/src/server/routes/instance/httpapi/groups/session.ts +3 -3
- package/src/server/routes/instance/httpapi/public.ts +3 -3
- package/src/session/llm/request.ts +2 -2
- package/src/session/prompt/composio.txt +15 -0
- package/src/session/prompt/mem0.txt +32 -0
- package/src/session/prompt/opensearch.txt +30 -0
- package/src/session/prompt/remote_tools.txt +39 -0
- package/src/session/prompt/supermemory.txt +13 -0
- package/src/session/retry.ts +3 -3
- package/src/session/system.ts +12 -0
package/package.json
CHANGED
package/script/trace-imports.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as path from "path"
|
|
3
3
|
import * as ts from "typescript"
|
|
4
4
|
|
|
5
|
-
const BASE_DIR = "/home/thdxr/dev/projects/anomalyco/
|
|
5
|
+
const BASE_DIR = "/home/thdxr/dev/projects/anomalyco/openfork/packages/openfork"
|
|
6
6
|
|
|
7
7
|
// Get entry file from command line arg or use default
|
|
8
8
|
const ENTRY_FILE = process.argv[2] || "src/plugin/tui/runtime.ts"
|
package/specs/v2/api.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// @ts-nocheck
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { OpenFork } from "@openfork-ai/core"
|
|
4
4
|
import { ReadTool } from "@openfork-ai/core/tools"
|
|
5
5
|
|
|
6
|
-
const openfork =
|
|
6
|
+
const openfork = OpenFork.make({})
|
|
7
7
|
|
|
8
8
|
openfork.tool.add(ReadTool)
|
|
9
9
|
|
package/src/acp/service.ts
CHANGED
|
@@ -102,7 +102,7 @@ export function make(input: {
|
|
|
102
102
|
"terminal-auth": {
|
|
103
103
|
command: "openfork",
|
|
104
104
|
args: ["auth", "login"],
|
|
105
|
-
label: "
|
|
105
|
+
label: "OpenFork Login",
|
|
106
106
|
},
|
|
107
107
|
}
|
|
108
108
|
}
|
|
@@ -128,7 +128,7 @@ export function make(input: {
|
|
|
128
128
|
},
|
|
129
129
|
authMethods: [authMethod],
|
|
130
130
|
agentInfo: {
|
|
131
|
-
name: "
|
|
131
|
+
name: "OpenFork",
|
|
132
132
|
version: InstallationVersion,
|
|
133
133
|
},
|
|
134
134
|
}
|
|
@@ -784,9 +784,9 @@ function defaultModelFromConfig(
|
|
|
784
784
|
// First-session ACP startup must not scan historical sessions just to infer
|
|
785
785
|
// a default. Configured model, openfork provider, then sorted best model keep
|
|
786
786
|
// the protocol response deterministic without extra session/message reads.
|
|
787
|
-
const
|
|
788
|
-
const
|
|
789
|
-
if (
|
|
787
|
+
const openforkProvider = providers[ProviderV2.ID.make("openfork")]
|
|
788
|
+
const openforkModel = openforkProvider ? Provider.sort(Object.values(openforkProvider.models))[0] : undefined
|
|
789
|
+
if (openforkProvider && openforkModel) return { providerID: openforkProvider.id, modelID: openforkModel.id }
|
|
790
790
|
|
|
791
791
|
const best = Provider.sort(Object.values(providers).flatMap((provider) => Object.values(provider.models)))[0]
|
|
792
792
|
if (best) return { providerID: best.providerID, modelID: best.id }
|
|
@@ -866,7 +866,7 @@ const promptResponse = Effect.fn("ACP.promptResponse")(function* (
|
|
|
866
866
|
|
|
867
867
|
function promptErrorMessage(error: AssistantError) {
|
|
868
868
|
if ("message" in error.data && typeof error.data.message === "string") return error.data.message
|
|
869
|
-
return "
|
|
869
|
+
return "OpenFork prompt failed"
|
|
870
870
|
}
|
|
871
871
|
|
|
872
872
|
function sendUsageUpdate(
|
|
@@ -1059,7 +1059,7 @@ function fromUnknownError(error: unknown, service?: string): Error {
|
|
|
1059
1059
|
if (isAuthRequired(error)) {
|
|
1060
1060
|
return new ACPError.AuthRequiredError({ providerId: findProviderID(error) })
|
|
1061
1061
|
}
|
|
1062
|
-
return new ACPError.ServiceFailureError({ safeMessage: "
|
|
1062
|
+
return new ACPError.ServiceFailureError({ safeMessage: "OpenFork service failure", service })
|
|
1063
1063
|
}
|
|
1064
1064
|
|
|
1065
1065
|
function isACPError(error: unknown): error is Error {
|
package/src/acp/usage.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentSideConnection, Usage } from "@agentclientprotocol/sdk"
|
|
2
|
-
import type { AssistantMessage as
|
|
2
|
+
import type { AssistantMessage as OpenForkAssistantMessage, Message } from "@openfork-ai/sdk/v2"
|
|
3
3
|
import { InstanceRef } from "@/effect/instance-ref"
|
|
4
4
|
import { InstanceBootstrap } from "@/project/bootstrap"
|
|
5
5
|
import { InstanceStore } from "@/project/instance-store"
|
|
@@ -10,11 +10,11 @@ import { ModelV2 } from "@openfork-ai/core/model"
|
|
|
10
10
|
import { Provider } from "@/provider/provider"
|
|
11
11
|
import { Context, Effect, Layer, SynchronizedRef } from "effect"
|
|
12
12
|
|
|
13
|
-
export type AssistantTokenCost = Pick<
|
|
13
|
+
export type AssistantTokenCost = Pick<OpenForkAssistantMessage, "cost" | "tokens">
|
|
14
14
|
|
|
15
15
|
export type AssistantMessage = AssistantTokenCost &
|
|
16
|
-
Pick<
|
|
17
|
-
Partial<Pick<
|
|
16
|
+
Pick<OpenForkAssistantMessage, "role"> &
|
|
17
|
+
Partial<Pick<OpenForkAssistantMessage, "providerID" | "modelID">>
|
|
18
18
|
|
|
19
19
|
export type SessionMessage = {
|
|
20
20
|
readonly info: { readonly role: Message["role"] } | AssistantMessage
|
package/src/cli/cmd/account.ts
CHANGED
|
@@ -15,7 +15,7 @@ const dim = (value: string) => UI.Style.TEXT_DIM + value + UI.Style.TEXT_NORMAL
|
|
|
15
15
|
|
|
16
16
|
const activeSuffix = (isActive: boolean) => (isActive ? dim(" (active)") : "")
|
|
17
17
|
|
|
18
|
-
export const defaultConsoleUrl = "https://console.
|
|
18
|
+
export const defaultConsoleUrl = "https://console.openfork.dev"
|
|
19
19
|
|
|
20
20
|
export const formatAccountLabel = (account: { email: string; url: string }, isActive: boolean) =>
|
|
21
21
|
`${account.email} ${dim(account.url)}${activeSuffix(isActive)}`
|
|
@@ -200,7 +200,7 @@ export const githubInstall = Effect.fn("Cli.github.install")(function* () {
|
|
|
200
200
|
"",
|
|
201
201
|
" 3. Go to a GitHub issue and comment `/oc summarize` to see the agent in action",
|
|
202
202
|
"",
|
|
203
|
-
" Learn more about the GitHub agent - https://
|
|
203
|
+
" Learn more about the GitHub agent - https://openfork.dev/docs/github/#usage-examples",
|
|
204
204
|
].join("\n"),
|
|
205
205
|
)
|
|
206
206
|
}
|
|
@@ -320,7 +320,7 @@ export const githubInstall = Effect.fn("Cli.github.install")(function* () {
|
|
|
320
320
|
s.stop("Installed GitHub app")
|
|
321
321
|
|
|
322
322
|
async function getInstallation() {
|
|
323
|
-
return await fetch(`https://api.
|
|
323
|
+
return await fetch(`https://api.openfork.dev/get_github_app_installation?owner=${app.owner}&repo=${app.repo}`)
|
|
324
324
|
.then((res) => res.json())
|
|
325
325
|
.then((data) => data.installation)
|
|
326
326
|
}
|
|
@@ -362,7 +362,7 @@ jobs:
|
|
|
362
362
|
persist-credentials: false
|
|
363
363
|
|
|
364
364
|
- name: Run openfork
|
|
365
|
-
uses: anomalyco/
|
|
365
|
+
uses: anomalyco/openfork/github@latest${envStr}
|
|
366
366
|
with:
|
|
367
367
|
model: ${provider}/${model}`,
|
|
368
368
|
)
|
|
@@ -426,7 +426,7 @@ export const githubRun = Effect.fn("Cli.github.run")(function* (args: { event?:
|
|
|
426
426
|
? (payload as IssueCommentEvent | IssuesEvent).issue.number
|
|
427
427
|
: (payload as PullRequestEvent | PullRequestReviewCommentEvent).pull_request.number
|
|
428
428
|
const runUrl = `/${owner}/${repo}/actions/runs/${runId}`
|
|
429
|
-
const shareBaseUrl = isMock ? "https://dev.
|
|
429
|
+
const shareBaseUrl = isMock ? "https://dev.openfork.dev" : "https://openfork.ai"
|
|
430
430
|
|
|
431
431
|
let appToken: string
|
|
432
432
|
let octoRest: Octokit
|
|
@@ -687,7 +687,7 @@ export const githubRun = Effect.fn("Cli.github.run")(function* (args: { event?:
|
|
|
687
687
|
|
|
688
688
|
function normalizeOidcBaseUrl(): string {
|
|
689
689
|
const value = process.env["OIDC_BASE_URL"]
|
|
690
|
-
if (!value) return "https://api.
|
|
690
|
+
if (!value) return "https://api.openfork.dev"
|
|
691
691
|
return value.replace(/\/+$/, "")
|
|
692
692
|
}
|
|
693
693
|
|
package/src/cli/cmd/pr.ts
CHANGED
|
@@ -98,10 +98,10 @@ export const PrCommand = effectCmd({
|
|
|
98
98
|
UI.println("Starting openfork...")
|
|
99
99
|
UI.println()
|
|
100
100
|
|
|
101
|
-
const
|
|
101
|
+
const openforkArgs = sessionId ? ["-s", sessionId] : []
|
|
102
102
|
const code = yield* Effect.promise(
|
|
103
103
|
() =>
|
|
104
|
-
Process.spawn(["openfork", ...
|
|
104
|
+
Process.spawn(["openfork", ...openforkArgs], {
|
|
105
105
|
stdin: "inherit",
|
|
106
106
|
stdout: "inherit",
|
|
107
107
|
stderr: "inherit",
|
package/src/cli/cmd/providers.ts
CHANGED
|
@@ -464,7 +464,7 @@ export const ProvidersLoginCommand = effectCmd({
|
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
if (provider === "openfork") {
|
|
467
|
-
yield* Prompt.log.info("Create an api key at https://
|
|
467
|
+
yield* Prompt.log.info("Create an api key at https://openfork.dev/auth")
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
if (provider === "vercel") {
|
|
@@ -473,7 +473,7 @@ export const ProvidersLoginCommand = effectCmd({
|
|
|
473
473
|
|
|
474
474
|
if (["cloudflare", "cloudflare-ai-gateway"].includes(provider)) {
|
|
475
475
|
yield* Prompt.log.info(
|
|
476
|
-
"Cloudflare AI Gateway can be configured with CLOUDFLARE_GATEWAY_ID, CLOUDFLARE_ACCOUNT_ID, and CLOUDFLARE_API_TOKEN environment variables. Read more: https://
|
|
476
|
+
"Cloudflare AI Gateway can be configured with CLOUDFLARE_GATEWAY_ID, CLOUDFLARE_ACCOUNT_ID, and CLOUDFLARE_API_TOKEN environment variables. Read more: https://openfork.dev/docs/providers/#cloudflare-ai-gateway",
|
|
477
477
|
)
|
|
478
478
|
}
|
|
479
479
|
|
|
@@ -100,7 +100,7 @@ export function RejectField(props: {
|
|
|
100
100
|
minHeight={1}
|
|
101
101
|
maxHeight={3}
|
|
102
102
|
wrapMode="word"
|
|
103
|
-
placeholder="Tell
|
|
103
|
+
placeholder="Tell OpenFork what to do differently"
|
|
104
104
|
placeholderColor={props.theme.muted}
|
|
105
105
|
textColor={props.theme.text}
|
|
106
106
|
focusedTextColor={props.theme.text}
|
|
@@ -284,7 +284,7 @@ export function RunPermissionBody(props: {
|
|
|
284
284
|
</Match>
|
|
285
285
|
<Match when={state().stage === "reject"}>
|
|
286
286
|
<box paddingLeft={1}>
|
|
287
|
-
<text fg={props.theme.muted}>Tell
|
|
287
|
+
<text fg={props.theme.muted}>Tell OpenFork what to do differently</text>
|
|
288
288
|
</box>
|
|
289
289
|
</Match>
|
|
290
290
|
</Switch>
|
|
@@ -417,7 +417,7 @@ export function createPromptState(input: PromptInput): PromptState {
|
|
|
417
417
|
description: "compose in your external editor",
|
|
418
418
|
} satisfies SlashOption,
|
|
419
419
|
{ kind: "slash", name: "new", display: "/new", description: "start a new session" } satisfies SlashOption,
|
|
420
|
-
{ kind: "slash", name: "exit", display: "/exit", description: "close
|
|
420
|
+
{ kind: "slash", name: "exit", display: "/exit", description: "close OpenFork" } satisfies SlashOption,
|
|
421
421
|
]
|
|
422
422
|
const hidden = new Set(builtins.map((item) => item.name))
|
|
423
423
|
const showSkillMenu = !shell() && skillCommands().length > 0 && !hasSkillsCommand()
|
|
@@ -125,11 +125,11 @@ export function permissionInfo(request: PermissionRequest): PermissionInfo {
|
|
|
125
125
|
|
|
126
126
|
export function permissionAlwaysLines(request: PermissionRequest): string[] {
|
|
127
127
|
if (request.always.length === 1 && request.always[0] === "*") {
|
|
128
|
-
return [`This will allow ${request.permission} until
|
|
128
|
+
return [`This will allow ${request.permission} until OpenFork is restarted.`]
|
|
129
129
|
}
|
|
130
130
|
|
|
131
131
|
return [
|
|
132
|
-
"This will allow the following patterns until
|
|
132
|
+
"This will allow the following patterns until OpenFork is restarted.",
|
|
133
133
|
...request.always.map((item) => `- ${item}`),
|
|
134
134
|
]
|
|
135
135
|
}
|
|
@@ -194,7 +194,7 @@ function build(input: SplashWriterInput, kind: "entry" | "exit", ctx: Scrollback
|
|
|
194
194
|
})
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
push(lines, body_left, top, "
|
|
197
|
+
push(lines, body_left, top, "OpenFork", right, undefined, TextAttributes.BOLD)
|
|
198
198
|
if (input.detail) {
|
|
199
199
|
push(
|
|
200
200
|
lines,
|
package/src/cli/cmd/uninstall.ts
CHANGED
|
@@ -55,7 +55,7 @@ export const UninstallCommand = {
|
|
|
55
55
|
UI.empty()
|
|
56
56
|
UI.println(UI.logo(" "))
|
|
57
57
|
UI.empty()
|
|
58
|
-
prompts.intro("Uninstall
|
|
58
|
+
prompts.intro("Uninstall OpenFork")
|
|
59
59
|
|
|
60
60
|
const method = await Installation.method()
|
|
61
61
|
prompts.log.info(`Installation method: ${method}`)
|
|
@@ -229,7 +229,7 @@ async function executeUninstall(method: Installation.Method, targets: RemovalTar
|
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
UI.empty()
|
|
232
|
-
prompts.log.success("Thank you for using
|
|
232
|
+
prompts.log.success("Thank you for using OpenFork!")
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
async function getShellConfigFile(): Promise<string | null> {
|
package/src/config/config.ts
CHANGED
|
@@ -229,8 +229,8 @@ const layer = Layer.effect(
|
|
|
229
229
|
|
|
230
230
|
yield* Effect.promise(() => resolveLoadedPlugins(data, options.path))
|
|
231
231
|
if (!data.$schema) {
|
|
232
|
-
data.$schema = "https://
|
|
233
|
-
const updated = text.replace(/^\s*\{/, '{\n "$schema": "https://
|
|
232
|
+
data.$schema = "https://openfork.dev/config.json"
|
|
233
|
+
const updated = text.replace(/^\s*\{/, '{\n "$schema": "https://openfork.dev/config.json",')
|
|
234
234
|
yield* fs.writeFileString(options.path, updated).pipe(Effect.catch(() => Effect.void))
|
|
235
235
|
}
|
|
236
236
|
return data
|
|
@@ -251,7 +251,7 @@ const layer = Layer.effect(
|
|
|
251
251
|
const file = globalConfigFile()
|
|
252
252
|
if (!existsSync(file)) {
|
|
253
253
|
yield* fs
|
|
254
|
-
.writeWithDirs(file, JSON.stringify({ $schema: "https://
|
|
254
|
+
.writeWithDirs(file, JSON.stringify({ $schema: "https://openfork.dev/config.json" }, null, 2))
|
|
255
255
|
.pipe(Effect.catch(() => Effect.void))
|
|
256
256
|
}
|
|
257
257
|
}
|
|
@@ -266,7 +266,7 @@ const layer = Layer.effect(
|
|
|
266
266
|
.then(async (mod) => {
|
|
267
267
|
const { provider, model, ...rest } = mod.default
|
|
268
268
|
if (provider && model) result.model = `${provider}/${model}`
|
|
269
|
-
result["$schema"] = "https://
|
|
269
|
+
result["$schema"] = "https://openfork.dev/config.json"
|
|
270
270
|
result = mergeConfig(result, rest)
|
|
271
271
|
await fsNode.writeFile(path.join(Global.Path.config, "config.json"), JSON.stringify(result, null, 2))
|
|
272
272
|
await fsNode.unlink(legacy)
|
|
@@ -379,7 +379,7 @@ const layer = Layer.effect(
|
|
|
379
379
|
})
|
|
380
380
|
: {}
|
|
381
381
|
const remoteConfig = mergeConfig(isRecord(wellknown.config) ? wellknown.config : {}, fetchedConfig)
|
|
382
|
-
if (!remoteConfig.$schema) remoteConfig.$schema = "https://
|
|
382
|
+
if (!remoteConfig.$schema) remoteConfig.$schema = "https://openfork.dev/config.json"
|
|
383
383
|
const source = wellknownURL
|
|
384
384
|
const next = yield* loadConfig(
|
|
385
385
|
JSON.stringify(remoteConfig),
|
package/src/config/managed.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { Process } from "@/util/process"
|
|
|
7
7
|
|
|
8
8
|
const MANAGED_PLIST_DOMAIN = "ai.openfork.managed"
|
|
9
9
|
|
|
10
|
-
// Keys injected by macOS/MDM into the managed plist that are not
|
|
10
|
+
// Keys injected by macOS/MDM into the managed plist that are not OpenFork config
|
|
11
11
|
const PLIST_META = new Set([
|
|
12
12
|
"PayloadDisplayName",
|
|
13
13
|
"PayloadIdentifier",
|
|
@@ -8,7 +8,7 @@ import { Global } from "@openfork-ai/core/global"
|
|
|
8
8
|
import { Filesystem } from "@/util/filesystem"
|
|
9
9
|
import * as ConfigPaths from "@/config/paths"
|
|
10
10
|
|
|
11
|
-
const TUI_SCHEMA_URL = "https://
|
|
11
|
+
const TUI_SCHEMA_URL = "https://openfork.dev/tui.json"
|
|
12
12
|
|
|
13
13
|
const decodeTheme = Schema.decodeUnknownOption(Schema.String)
|
|
14
14
|
const decodeRecord = Schema.decodeUnknownOption(Schema.Record(Schema.String, Schema.Unknown))
|
|
@@ -27,7 +27,7 @@ interface MigrateInput {
|
|
|
27
27
|
* skips only locations where a tui.json already exists.
|
|
28
28
|
*/
|
|
29
29
|
export async function migrateTuiConfig(input: MigrateInput) {
|
|
30
|
-
const openfork = await
|
|
30
|
+
const openfork = await openforkFiles(input)
|
|
31
31
|
for (const file of openfork) {
|
|
32
32
|
const source = await Filesystem.readText(file).catch(() => undefined)
|
|
33
33
|
if (!source) continue
|
|
@@ -112,7 +112,7 @@ async function backupAndStripLegacy(file: string, source: string) {
|
|
|
112
112
|
.catch(() => false)
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
async function
|
|
115
|
+
async function openforkFiles(input: { directories: string[]; cwd: string }) {
|
|
116
116
|
const files = [
|
|
117
117
|
...ConfigPaths.fileInDirectory(Global.Path.config, "openfork"),
|
|
118
118
|
...(await Filesystem.findUp(["openfork.json", "openfork.jsonc"], input.cwd, undefined, { rootFirst: true })),
|
|
@@ -144,7 +144,7 @@ const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProcess.Serv
|
|
|
144
144
|
|
|
145
145
|
const upgradeCurl = Effect.fnUntraced(
|
|
146
146
|
function* (target: string) {
|
|
147
|
-
const response = yield* httpOk.execute(HttpClientRequest.get("https://
|
|
147
|
+
const response = yield* httpOk.execute(HttpClientRequest.get("https://openfork.dev/install"))
|
|
148
148
|
const body = yield* response.text
|
|
149
149
|
const bodyBytes = new TextEncoder().encode(body)
|
|
150
150
|
const shell = yield* upgradeScriptShell()
|
|
@@ -237,7 +237,7 @@ const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProcess.Serv
|
|
|
237
237
|
if (detectedMethod === "choco") {
|
|
238
238
|
const response = yield* httpOk.execute(
|
|
239
239
|
HttpClientRequest.get(
|
|
240
|
-
"https://community.chocolatey.org/api/v2/Packages?$filter=Id%20eq%20%
|
|
240
|
+
"https://community.chocolatey.org/api/v2/Packages?$filter=Id%20eq%20%27openfork%27%20and%20IsLatestVersion&$select=Version",
|
|
241
241
|
).pipe(HttpClientRequest.setHeaders({ Accept: "application/json;odata=verbose" })),
|
|
242
242
|
)
|
|
243
243
|
const data = yield* HttpClientResponse.schemaBodyJson(ChocoPackage)(response)
|
|
@@ -255,7 +255,7 @@ const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProcess.Serv
|
|
|
255
255
|
}
|
|
256
256
|
|
|
257
257
|
const response = yield* httpOk.execute(
|
|
258
|
-
HttpClientRequest.get("https://api.github.com/repos/anomalyco/
|
|
258
|
+
HttpClientRequest.get("https://api.github.com/repos/anomalyco/openfork/releases/latest").pipe(
|
|
259
259
|
HttpClientRequest.acceptJson,
|
|
260
260
|
),
|
|
261
261
|
)
|
package/src/mcp/index.ts
CHANGED
|
@@ -38,13 +38,13 @@ import { McpEvent } from "@openfork-ai/schema/mcp-event"
|
|
|
38
38
|
const DEFAULT_TIMEOUT = 30_000
|
|
39
39
|
const CLIENT_OPTIONS = {
|
|
40
40
|
capabilities: {
|
|
41
|
-
// https://github.com/anomalyco/
|
|
41
|
+
// https://github.com/anomalyco/openfork/issues/11948
|
|
42
42
|
// sampling: {},
|
|
43
|
-
// https://github.com/anomalyco/
|
|
43
|
+
// https://github.com/anomalyco/openfork/issues/23066
|
|
44
44
|
// elicitation: {},
|
|
45
|
-
// https://github.com/anomalyco/
|
|
45
|
+
// https://github.com/anomalyco/openfork/issues/2308
|
|
46
46
|
roots: {},
|
|
47
|
-
// https://github.com/anomalyco/
|
|
47
|
+
// https://github.com/anomalyco/openfork/issues/28567
|
|
48
48
|
// tasks: {},
|
|
49
49
|
},
|
|
50
50
|
} satisfies ClientOptions
|
|
@@ -43,7 +43,7 @@ export class McpOAuthProvider implements OAuthClientProvider {
|
|
|
43
43
|
get clientMetadata(): OAuthClientMetadata {
|
|
44
44
|
return {
|
|
45
45
|
redirect_uris: [this.redirectUrl],
|
|
46
|
-
client_name: "
|
|
46
|
+
client_name: "OpenFork",
|
|
47
47
|
client_uri: "https://openfork.ai",
|
|
48
48
|
grant_types: ["authorization_code", "refresh_token"],
|
|
49
49
|
response_types: ["code"],
|
|
@@ -283,7 +283,7 @@ export async function DigitalOceanAuthPlugin(input: PluginInput): Promise<Hooks>
|
|
|
283
283
|
return {
|
|
284
284
|
url,
|
|
285
285
|
instructions:
|
|
286
|
-
"Sign in to DigitalOcean in your browser.
|
|
286
|
+
"Sign in to DigitalOcean in your browser. OpenFork will use your DigitalOcean API token directly for inference and load your Inference Routers. Re-run /connect to refresh routers later.",
|
|
287
287
|
method: "auto" as const,
|
|
288
288
|
async callback() {
|
|
289
289
|
try {
|
|
@@ -98,7 +98,7 @@ function build(key: string, remote: SelectableItem, url: string, prev?: Model):
|
|
|
98
98
|
? "chat"
|
|
99
99
|
: undefined
|
|
100
100
|
const prices = remote.billing?.token_prices
|
|
101
|
-
// Copilot prices are AIC per billing batch;
|
|
101
|
+
// Copilot prices are AIC per billing batch; OpenFork stores USD per million tokens.
|
|
102
102
|
const usdPerMillion = prices ? 10_000 / prices.batch_size : 0
|
|
103
103
|
|
|
104
104
|
const model: CopilotModel = {
|
package/src/plugin/shared.ts
CHANGED
|
@@ -191,16 +191,16 @@ export async function resolvePathPluginTarget(spec: string) {
|
|
|
191
191
|
throw new Error(`Plugin directory ${file} is missing package.json or index file`)
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
export async function checkPluginCompatibility(target: string,
|
|
195
|
-
if (!semver.valid(
|
|
194
|
+
export async function checkPluginCompatibility(target: string, openforkVersion: string, pkg?: PluginPackage) {
|
|
195
|
+
if (!semver.valid(openforkVersion) || semver.major(openforkVersion) === 0) return
|
|
196
196
|
const hit = pkg ?? (await readPluginPackage(target).catch(() => undefined))
|
|
197
197
|
if (!hit) return
|
|
198
198
|
const engines = hit.json.engines
|
|
199
199
|
if (!isRecord(engines)) return
|
|
200
200
|
const range = engines.openfork
|
|
201
201
|
if (typeof range !== "string") return
|
|
202
|
-
if (!semver.satisfies(
|
|
203
|
-
throw new Error(`Plugin requires openfork ${range} but running ${
|
|
202
|
+
if (!semver.satisfies(openforkVersion, range)) {
|
|
203
|
+
throw new Error(`Plugin requires openfork ${range} but running ${openforkVersion}`)
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
@@ -475,7 +475,7 @@ export async function SnowflakeCortexAuthPlugin(_input: PluginInput): Promise<Ho
|
|
|
475
475
|
return {
|
|
476
476
|
url,
|
|
477
477
|
instructions:
|
|
478
|
-
"Complete Snowflake sign-in in your browser.
|
|
478
|
+
"Complete Snowflake sign-in in your browser. OpenFork will capture the OAuth callback and store the bearer token automatically.",
|
|
479
479
|
method: "auto" as const,
|
|
480
480
|
async callback() {
|
|
481
481
|
try {
|
package/src/provider/provider.ts
CHANGED
|
@@ -449,7 +449,7 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|
|
449
449
|
autoload: false,
|
|
450
450
|
options: {
|
|
451
451
|
headers: {
|
|
452
|
-
"HTTP-Referer": "https://
|
|
452
|
+
"HTTP-Referer": "https://openfork.dev/",
|
|
453
453
|
"X-Title": "openfork",
|
|
454
454
|
"X-Source": "openfork",
|
|
455
455
|
},
|
|
@@ -460,7 +460,7 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|
|
460
460
|
autoload: false,
|
|
461
461
|
options: {
|
|
462
462
|
headers: {
|
|
463
|
-
"HTTP-Referer": "https://
|
|
463
|
+
"HTTP-Referer": "https://openfork.dev/",
|
|
464
464
|
"X-Title": "openfork",
|
|
465
465
|
},
|
|
466
466
|
},
|
|
@@ -470,9 +470,9 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|
|
470
470
|
autoload: provider.source === "config",
|
|
471
471
|
options: {
|
|
472
472
|
headers: {
|
|
473
|
-
"HTTP-Referer": "https://
|
|
473
|
+
"HTTP-Referer": "https://openfork.dev/",
|
|
474
474
|
"X-Title": "openfork",
|
|
475
|
-
"X-BILLING-INVOKE-ORIGIN": "
|
|
475
|
+
"X-BILLING-INVOKE-ORIGIN": "OpenFork",
|
|
476
476
|
},
|
|
477
477
|
},
|
|
478
478
|
}),
|
|
@@ -481,7 +481,7 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|
|
481
481
|
autoload: false,
|
|
482
482
|
options: {
|
|
483
483
|
headers: {
|
|
484
|
-
"http-referer": "https://
|
|
484
|
+
"http-referer": "https://openfork.dev/",
|
|
485
485
|
"x-title": "openfork",
|
|
486
486
|
},
|
|
487
487
|
},
|
|
@@ -587,7 +587,7 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|
|
587
587
|
autoload: false,
|
|
588
588
|
options: {
|
|
589
589
|
headers: {
|
|
590
|
-
"HTTP-Referer": "https://
|
|
590
|
+
"HTTP-Referer": "https://openfork.dev/",
|
|
591
591
|
"X-Title": "openfork",
|
|
592
592
|
},
|
|
593
593
|
},
|
|
@@ -845,7 +845,7 @@ function custom(dep: CustomDep): Record<string, CustomLoader> {
|
|
|
845
845
|
autoload: false,
|
|
846
846
|
options: {
|
|
847
847
|
headers: {
|
|
848
|
-
"HTTP-Referer": "https://
|
|
848
|
+
"HTTP-Referer": "https://openfork.dev/",
|
|
849
849
|
"X-Title": "openfork",
|
|
850
850
|
},
|
|
851
851
|
},
|
|
@@ -1437,7 +1437,7 @@ export function schema(model: Provider.Model, schema: JSONSchema7): JSONSchema7
|
|
|
1437
1437
|
|
|
1438
1438
|
if (model.api.npm === "@ai-sdk/openai" || model.api.npm === "@ai-sdk/azure") {
|
|
1439
1439
|
schema = sanitizeOpenAISchema(schema) as JSONSchema7
|
|
1440
|
-
// Codex also applies lossy compaction above 4 KB; defer that until
|
|
1440
|
+
// Codex also applies lossy compaction above 4 KB; defer that until OpenFork needs the same schema budget.
|
|
1441
1441
|
}
|
|
1442
1442
|
|
|
1443
1443
|
if (model.providerID === "moonshotai" || model.api.id.toLowerCase().includes("kimi")) {
|
|
@@ -76,7 +76,7 @@ export const InstanceHttpApi = HttpApi.make("openfork-instance")
|
|
|
76
76
|
.addHttpApi(WorkspaceApi)
|
|
77
77
|
.middleware(SchemaErrorMiddleware)
|
|
78
78
|
|
|
79
|
-
export const
|
|
79
|
+
export const OpenForkHttpApi = HttpApi.make("openfork")
|
|
80
80
|
.addHttpApi(RootHttpApi)
|
|
81
81
|
.addHttpApi(EventApi)
|
|
82
82
|
.addHttpApi(InstanceHttpApi)
|
|
@@ -20,7 +20,7 @@ export const ConfigApi = HttpApi.make("config")
|
|
|
20
20
|
OpenApi.annotations({
|
|
21
21
|
identifier: "config.get",
|
|
22
22
|
summary: "Get configuration",
|
|
23
|
-
description: "Retrieve the current
|
|
23
|
+
description: "Retrieve the current OpenFork configuration settings and preferences.",
|
|
24
24
|
}),
|
|
25
25
|
),
|
|
26
26
|
HttpApiEndpoint.patch("update", root, {
|
|
@@ -32,7 +32,7 @@ export const ConfigApi = HttpApi.make("config")
|
|
|
32
32
|
OpenApi.annotations({
|
|
33
33
|
identifier: "config.update",
|
|
34
34
|
summary: "Update configuration",
|
|
35
|
-
description: "Update
|
|
35
|
+
description: "Update OpenFork configuration settings and preferences.",
|
|
36
36
|
}),
|
|
37
37
|
),
|
|
38
38
|
HttpApiEndpoint.get("providers", `${root}/providers`, {
|
|
@@ -112,7 +112,7 @@ export const ExperimentalApi = HttpApi.make("experimental")
|
|
|
112
112
|
OpenApi.annotations({
|
|
113
113
|
identifier: "experimental.capabilities.get",
|
|
114
114
|
summary: "Get experimental capabilities",
|
|
115
|
-
description: "Get experimental features enabled on the
|
|
115
|
+
description: "Get experimental features enabled on the OpenFork server.",
|
|
116
116
|
}),
|
|
117
117
|
),
|
|
118
118
|
HttpApiEndpoint.get("console", ExperimentalPaths.console, {
|
|
@@ -146,7 +146,7 @@ export const ExperimentalApi = HttpApi.make("experimental")
|
|
|
146
146
|
OpenApi.annotations({
|
|
147
147
|
identifier: "experimental.console.switchOrg",
|
|
148
148
|
summary: "Switch active Console org",
|
|
149
|
-
description: "Persist a new active Console account/org selection for the current local
|
|
149
|
+
description: "Persist a new active Console account/org selection for the current local OpenFork state.",
|
|
150
150
|
}),
|
|
151
151
|
),
|
|
152
152
|
HttpApiEndpoint.get("tool", ExperimentalPaths.tool, {
|
|
@@ -229,7 +229,7 @@ export const ExperimentalApi = HttpApi.make("experimental")
|
|
|
229
229
|
identifier: "experimental.session.list",
|
|
230
230
|
summary: "List sessions",
|
|
231
231
|
description:
|
|
232
|
-
"Get a list of all
|
|
232
|
+
"Get a list of all OpenFork sessions across projects, sorted by most recently updated. Archived sessions are excluded by default.",
|
|
233
233
|
}),
|
|
234
234
|
),
|
|
235
235
|
HttpApiEndpoint.post("sessionBackground", ExperimentalPaths.sessionBackground, {
|
|
@@ -79,7 +79,7 @@ export const GlobalApi = HttpApi.make("global").add(
|
|
|
79
79
|
OpenApi.annotations({
|
|
80
80
|
identifier: "global.health",
|
|
81
81
|
summary: "Get health",
|
|
82
|
-
description: "Get health information about the
|
|
82
|
+
description: "Get health information about the OpenFork server.",
|
|
83
83
|
}),
|
|
84
84
|
),
|
|
85
85
|
HttpApiEndpoint.get("event", GlobalPaths.event, {
|
|
@@ -88,7 +88,7 @@ export const GlobalApi = HttpApi.make("global").add(
|
|
|
88
88
|
OpenApi.annotations({
|
|
89
89
|
identifier: "global.event",
|
|
90
90
|
summary: "Get global events",
|
|
91
|
-
description: "Subscribe to global events from the
|
|
91
|
+
description: "Subscribe to global events from the OpenFork system using server-sent events.",
|
|
92
92
|
}),
|
|
93
93
|
),
|
|
94
94
|
HttpApiEndpoint.get("configGet", GlobalPaths.config, {
|
|
@@ -97,7 +97,7 @@ export const GlobalApi = HttpApi.make("global").add(
|
|
|
97
97
|
OpenApi.annotations({
|
|
98
98
|
identifier: "global.config.get",
|
|
99
99
|
summary: "Get global configuration",
|
|
100
|
-
description: "Retrieve the current global
|
|
100
|
+
description: "Retrieve the current global OpenFork configuration settings and preferences.",
|
|
101
101
|
}),
|
|
102
102
|
),
|
|
103
103
|
HttpApiEndpoint.patch("configUpdate", GlobalPaths.config, {
|
|
@@ -108,7 +108,7 @@ export const GlobalApi = HttpApi.make("global").add(
|
|
|
108
108
|
OpenApi.annotations({
|
|
109
109
|
identifier: "global.config.update",
|
|
110
110
|
summary: "Update global configuration",
|
|
111
|
-
description: "Update global
|
|
111
|
+
description: "Update global OpenFork configuration settings and preferences.",
|
|
112
112
|
}),
|
|
113
113
|
),
|
|
114
114
|
HttpApiEndpoint.post("dispose", GlobalPaths.dispose, {
|
|
@@ -117,7 +117,7 @@ export const GlobalApi = HttpApi.make("global").add(
|
|
|
117
117
|
OpenApi.annotations({
|
|
118
118
|
identifier: "global.dispose",
|
|
119
119
|
summary: "Dispose instance",
|
|
120
|
-
description: "Clean up and dispose all
|
|
120
|
+
description: "Clean up and dispose all OpenFork instances, releasing all resources.",
|
|
121
121
|
}),
|
|
122
122
|
),
|
|
123
123
|
HttpApiEndpoint.post("upgrade", GlobalPaths.upgrade, {
|
|
@@ -66,7 +66,7 @@ export const InstanceApi = HttpApi.make("instance")
|
|
|
66
66
|
OpenApi.annotations({
|
|
67
67
|
identifier: "instance.dispose",
|
|
68
68
|
summary: "Dispose instance",
|
|
69
|
-
description: "Clean up and dispose the current
|
|
69
|
+
description: "Clean up and dispose the current OpenFork instance, releasing all resources.",
|
|
70
70
|
}),
|
|
71
71
|
),
|
|
72
72
|
HttpApiEndpoint.get("path", InstancePaths.path, {
|
|
@@ -77,7 +77,7 @@ export const InstanceApi = HttpApi.make("instance")
|
|
|
77
77
|
identifier: "path.get",
|
|
78
78
|
summary: "Get paths",
|
|
79
79
|
description:
|
|
80
|
-
"Retrieve the current working directory and related path information for the
|
|
80
|
+
"Retrieve the current working directory and related path information for the OpenFork instance.",
|
|
81
81
|
}),
|
|
82
82
|
),
|
|
83
83
|
HttpApiEndpoint.get("vcs", InstancePaths.vcs, {
|
|
@@ -143,7 +143,7 @@ export const InstanceApi = HttpApi.make("instance")
|
|
|
143
143
|
OpenApi.annotations({
|
|
144
144
|
identifier: "command.list",
|
|
145
145
|
summary: "List commands",
|
|
146
|
-
description: "Get a list of all available commands in the
|
|
146
|
+
description: "Get a list of all available commands in the OpenFork system.",
|
|
147
147
|
}),
|
|
148
148
|
),
|
|
149
149
|
HttpApiEndpoint.get("agent", InstancePaths.agent, {
|
|
@@ -153,7 +153,7 @@ export const InstanceApi = HttpApi.make("instance")
|
|
|
153
153
|
OpenApi.annotations({
|
|
154
154
|
identifier: "app.agents",
|
|
155
155
|
summary: "List agents",
|
|
156
|
-
description: "Get a list of all available AI agents in the
|
|
156
|
+
description: "Get a list of all available AI agents in the OpenFork system.",
|
|
157
157
|
}),
|
|
158
158
|
),
|
|
159
159
|
HttpApiEndpoint.get("skill", InstancePaths.skill, {
|
|
@@ -163,7 +163,7 @@ export const InstanceApi = HttpApi.make("instance")
|
|
|
163
163
|
OpenApi.annotations({
|
|
164
164
|
identifier: "app.skills",
|
|
165
165
|
summary: "List skills",
|
|
166
|
-
description: "Get a list of all available skills in the
|
|
166
|
+
description: "Get a list of all available skills in the OpenFork system.",
|
|
167
167
|
}),
|
|
168
168
|
),
|
|
169
169
|
HttpApiEndpoint.get("lsp", InstancePaths.lsp, {
|
|
@@ -26,7 +26,7 @@ export const ProjectApi = HttpApi.make("project")
|
|
|
26
26
|
OpenApi.annotations({
|
|
27
27
|
identifier: "project.list",
|
|
28
28
|
summary: "List all projects",
|
|
29
|
-
description: "Get a list of projects that have been opened with
|
|
29
|
+
description: "Get a list of projects that have been opened with OpenFork.",
|
|
30
30
|
}),
|
|
31
31
|
),
|
|
32
32
|
HttpApiEndpoint.get("current", `${root}/current`, {
|
|
@@ -36,7 +36,7 @@ export const ProjectApi = HttpApi.make("project")
|
|
|
36
36
|
OpenApi.annotations({
|
|
37
37
|
identifier: "project.current",
|
|
38
38
|
summary: "Get current project",
|
|
39
|
-
description: "Retrieve the currently active project that
|
|
39
|
+
description: "Retrieve the currently active project that OpenFork is working with.",
|
|
40
40
|
}),
|
|
41
41
|
),
|
|
42
42
|
HttpApiEndpoint.post("initGit", `${root}/git/init`, {
|
|
@@ -58,7 +58,7 @@ export const PtyApi = HttpApi.make("pty")
|
|
|
58
58
|
OpenApi.annotations({
|
|
59
59
|
identifier: "pty.list",
|
|
60
60
|
summary: "List PTY sessions",
|
|
61
|
-
description: "Get a list of all active pseudo-terminal (PTY) sessions managed by
|
|
61
|
+
description: "Get a list of all active pseudo-terminal (PTY) sessions managed by OpenFork.",
|
|
62
62
|
}),
|
|
63
63
|
),
|
|
64
64
|
HttpApiEndpoint.post("create", PtyPaths.create, {
|
|
@@ -115,7 +115,7 @@ export const SessionApi = HttpApi.make("session")
|
|
|
115
115
|
OpenApi.annotations({
|
|
116
116
|
identifier: "session.list",
|
|
117
117
|
summary: "List sessions",
|
|
118
|
-
description: "Get a list of all
|
|
118
|
+
description: "Get a list of all OpenFork sessions, sorted by most recently updated.",
|
|
119
119
|
}),
|
|
120
120
|
),
|
|
121
121
|
HttpApiEndpoint.get("status", SessionPaths.status, {
|
|
@@ -138,7 +138,7 @@ export const SessionApi = HttpApi.make("session")
|
|
|
138
138
|
OpenApi.annotations({
|
|
139
139
|
identifier: "session.get",
|
|
140
140
|
summary: "Get session",
|
|
141
|
-
description: "Retrieve detailed information about a specific
|
|
141
|
+
description: "Retrieve detailed information about a specific OpenFork session.",
|
|
142
142
|
}),
|
|
143
143
|
),
|
|
144
144
|
HttpApiEndpoint.get("children", SessionPaths.children, {
|
|
@@ -209,7 +209,7 @@ export const SessionApi = HttpApi.make("session")
|
|
|
209
209
|
OpenApi.annotations({
|
|
210
210
|
identifier: "session.create",
|
|
211
211
|
summary: "Create session",
|
|
212
|
-
description: "Create a new
|
|
212
|
+
description: "Create a new OpenFork session for interacting with AI assistants and managing conversations.",
|
|
213
213
|
}),
|
|
214
214
|
),
|
|
215
215
|
HttpApiEndpoint.delete("remove", SessionPaths.remove, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { OpenApi } from "effect/unstable/httpapi"
|
|
2
|
-
import {
|
|
2
|
+
import { OpenForkHttpApi } from "./api"
|
|
3
3
|
import { QueryBooleanOpenApi } from "./groups/query"
|
|
4
4
|
|
|
5
5
|
type OpenApiParameter = {
|
|
@@ -449,7 +449,7 @@ function fixSelfReferencingComponents(spec: OpenApiSpec) {
|
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
// Simplest fix: generate the raw spec (without transform) to get correct schemas
|
|
452
|
-
const raw: OpenApiSpec = OpenApi.fromApi(
|
|
452
|
+
const raw: OpenApiSpec = OpenApi.fromApi(OpenForkHttpApi)
|
|
453
453
|
const rawSchemas = raw.components?.schemas
|
|
454
454
|
if (!rawSchemas) return
|
|
455
455
|
for (const name of selfRefs) {
|
|
@@ -527,7 +527,7 @@ function normalizeParameter(param: OpenApiParameter, route: string) {
|
|
|
527
527
|
param.schema = stripOptionalNull(param.schema)
|
|
528
528
|
}
|
|
529
529
|
|
|
530
|
-
export const PublicApi =
|
|
530
|
+
export const PublicApi = OpenForkHttpApi.annotateMerge(
|
|
531
531
|
OpenApi.annotations({
|
|
532
532
|
title: "openfork",
|
|
533
533
|
version: "1.0.0",
|
|
@@ -174,7 +174,7 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre
|
|
|
174
174
|
})
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
const
|
|
177
|
+
const openforkProjectID = input.model.providerID.startsWith("openfork")
|
|
178
178
|
? (yield* InstanceState.context).project.id
|
|
179
179
|
: undefined
|
|
180
180
|
|
|
@@ -187,7 +187,7 @@ export const prepare = Effect.fn("LLMRequestPrep.prepare")(function* (input: Pre
|
|
|
187
187
|
headers: {
|
|
188
188
|
...(input.model.providerID.startsWith("openfork")
|
|
189
189
|
? {
|
|
190
|
-
...(
|
|
190
|
+
...(openforkProjectID ? { "x-openfork-project": openforkProjectID } : {}),
|
|
191
191
|
"x-openfork-session": input.sessionID,
|
|
192
192
|
"x-openfork-request": input.user.id,
|
|
193
193
|
"x-openfork-client": input.flags.client,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
You are connected to Composio.
|
|
2
|
+
|
|
3
|
+
Use the Composio tools when the user wants to manage external app integrations, list available toolkits, inspect connections, search tools, or execute a connected tool.
|
|
4
|
+
|
|
5
|
+
Be direct about setup:
|
|
6
|
+
- Check whether Composio is installed and configured.
|
|
7
|
+
- Help the user connect the requested toolkit if needed.
|
|
8
|
+
- Use the tool schema and connection state before attempting execution.
|
|
9
|
+
|
|
10
|
+
When useful, summarize:
|
|
11
|
+
- available toolkits
|
|
12
|
+
- active connections
|
|
13
|
+
- any missing authorization or install step
|
|
14
|
+
|
|
15
|
+
Prefer tool-driven actions over manual instructions.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
You are running Mem0, a memory management system that stores and retrieves contextual information for AI agents.
|
|
2
|
+
|
|
3
|
+
Key capabilities:
|
|
4
|
+
- Store conversation history and context
|
|
5
|
+
- Retrieve relevant information across sessions
|
|
6
|
+
- Manage memory clusters and threads
|
|
7
|
+
- Handle short-term and long-term memory
|
|
8
|
+
- Integrate with existing agent workflows
|
|
9
|
+
|
|
10
|
+
You should provide structured help for Mem0 operations:
|
|
11
|
+
- Memory storage and retrieval
|
|
12
|
+
- Memory session management
|
|
13
|
+
- Memory graph operations
|
|
14
|
+
- Memory lifecycle management
|
|
15
|
+
- Memory sharing and collaboration
|
|
16
|
+
|
|
17
|
+
For Mem0 operations, ask clarifying questions:
|
|
18
|
+
- What memories should be stored?
|
|
19
|
+
- How should memories be retrieved? (by session, thread, graph)
|
|
20
|
+
- Are there specific memory types or categories?
|
|
21
|
+
- What are the retention and expiration requirements?
|
|
22
|
+
|
|
23
|
+
Remember to handle memory operations and provide context from previous conversations through Mem0.
|
|
24
|
+
|
|
25
|
+
### Mem0 Integration Commands
|
|
26
|
+
You can use the following commands:
|
|
27
|
+
- `/mem0` - Access Mem0 operations
|
|
28
|
+
- `/memories` - Alias for Mem0 memory operations
|
|
29
|
+
- `/context` - Access contextual memories
|
|
30
|
+
|
|
31
|
+
### Quick Start
|
|
32
|
+
To access Mem0, use `/mem0 retrieve --query "your query" --session-id <session_id>` for easy setup.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
You are running OpenSearch, a powerful search engine that provides distributed search and analytics capabilities.
|
|
2
|
+
|
|
3
|
+
Key capabilities:
|
|
4
|
+
- Full-text search with advanced query syntax
|
|
5
|
+
- Multi-field search with boosting
|
|
6
|
+
- Faceted navigation and aggregations
|
|
7
|
+
- High performance and scalability
|
|
8
|
+
- REST API for easy integration
|
|
9
|
+
|
|
10
|
+
You should provide structured help for search operations:
|
|
11
|
+
- Query syntax and operators
|
|
12
|
+
- Search strategies and optimization tips
|
|
13
|
+
- Indexing best practices
|
|
14
|
+
- API usage examples
|
|
15
|
+
|
|
16
|
+
For search operations, ask clarifying questions:
|
|
17
|
+
- What are the target documents or data?
|
|
18
|
+
- What fields need to be searched?
|
|
19
|
+
- What search operators or special syntax are needed?
|
|
20
|
+
- Are there performance constraints or optimization requirements?
|
|
21
|
+
|
|
22
|
+
Remember to handle search result analysis and provide insights based on the query results.
|
|
23
|
+
|
|
24
|
+
### OpenSearch Integration Commands
|
|
25
|
+
You can use the following commands:
|
|
26
|
+
- `/search` - Perform structured searches
|
|
27
|
+
- `/opensearch` - Access OpenSearch operations
|
|
28
|
+
|
|
29
|
+
### Quick Start
|
|
30
|
+
To connect to OpenSearch, use `/integration opensearch --connect` for easy setup.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
You are running Remote Tools, a system for executing commands and tools remotely from your AI agent.
|
|
2
|
+
|
|
3
|
+
Key capabilities:
|
|
4
|
+
- Execute shell commands and scripts
|
|
5
|
+
- Run Git operations (commit, push, merge)
|
|
6
|
+
- Manage file operations (read, write, edit, create)
|
|
7
|
+
- Access remote Git repositories
|
|
8
|
+
- Coordinate deployment operations
|
|
9
|
+
- Handle CI/CD pipeline operations
|
|
10
|
+
- Manage environment configuration
|
|
11
|
+
|
|
12
|
+
You should provide structured help for Remote Tools operations:
|
|
13
|
+
- Shell command execution with proper permissions
|
|
14
|
+
- Git workflow management
|
|
15
|
+
- File system operations
|
|
16
|
+
- Repository management
|
|
17
|
+
- Deployment and release operations
|
|
18
|
+
- Configuration management
|
|
19
|
+
- Error handling and recovery
|
|
20
|
+
|
|
21
|
+
For Remote Tools operations, ask clarifying questions:
|
|
22
|
+
- What shell commands should be executed?
|
|
23
|
+
- Which Git repositories need to be accessed?
|
|
24
|
+
- Are there specific file operations required?
|
|
25
|
+
- What are the permission and access requirements?
|
|
26
|
+
|
|
27
|
+
Remember to handle command execution errors and provide recovery options.
|
|
28
|
+
|
|
29
|
+
### Remote Tools Integration Commands
|
|
30
|
+
You can use the following commands:
|
|
31
|
+
- `/remote` - Access remote operations
|
|
32
|
+
- `/shell` - Execute shell commands
|
|
33
|
+
- `/git` - Manage Git operations
|
|
34
|
+
- `/file` - Perform file operations
|
|
35
|
+
|
|
36
|
+
### Quick Start
|
|
37
|
+
To execute shell commands, use `/shell --command "your command"`.
|
|
38
|
+
To access Git operations, use `/git --branch <branch> --command "git operation"`.
|
|
39
|
+
To manage files, use `/file --command "read" --path "path/to/file"`.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
You are connected to SuperMemory.
|
|
2
|
+
|
|
3
|
+
Use the SuperMemory tools when the user wants to configure local memory, connect to the hosted memory service, inspect status, or work with their memory layer.
|
|
4
|
+
|
|
5
|
+
Be direct about setup:
|
|
6
|
+
- Check whether the local service or remote connection is available.
|
|
7
|
+
- Tell the user the exact install or login step if something is missing.
|
|
8
|
+
- Prefer the memory tool or configured endpoint over manual workarounds.
|
|
9
|
+
|
|
10
|
+
When useful, summarize:
|
|
11
|
+
- the current connection mode
|
|
12
|
+
- the API key or local server requirement
|
|
13
|
+
- any next step needed to make memory available
|
package/src/session/retry.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { isRecord } from "@/util/record"
|
|
|
8
8
|
export type Err = ReturnType<NamedError["toObject"]>
|
|
9
9
|
|
|
10
10
|
export const GO_UPSELL_MESSAGE = "Free usage exceeded, subscribe to Go"
|
|
11
|
-
export const GO_UPSELL_URL = "https://
|
|
11
|
+
export const GO_UPSELL_URL = "https://openfork.dev/go"
|
|
12
12
|
export type RetryReason = "free_tier_limit" | "account_rate_limit" | (string & {})
|
|
13
13
|
|
|
14
14
|
export type Retryable = {
|
|
@@ -80,7 +80,7 @@ export function retryable(error: Err, provider: string) {
|
|
|
80
80
|
reason: "free_tier_limit",
|
|
81
81
|
provider,
|
|
82
82
|
title: "Free limit reached",
|
|
83
|
-
message: "Subscribe to
|
|
83
|
+
message: "Subscribe to OpenFork Go for reliable access to the best open-source models, starting at $5/month.",
|
|
84
84
|
label: "subscribe",
|
|
85
85
|
link: GO_UPSELL_URL,
|
|
86
86
|
},
|
|
@@ -106,7 +106,7 @@ export function retryable(error: Err, provider: string) {
|
|
|
106
106
|
|
|
107
107
|
const message = `${limitName ? `${limitName} usage limit` : "Usage limit"} reached. It will reset in ${resetIn}. To continue using this model now, enable usage from your available balance`
|
|
108
108
|
|
|
109
|
-
const link = `https://
|
|
109
|
+
const link = `https://openfork.dev/workspace/${workspace}/go`
|
|
110
110
|
return {
|
|
111
111
|
message: `${message} - ${link}`,
|
|
112
112
|
action: {
|
package/src/session/system.ts
CHANGED
|
@@ -12,6 +12,11 @@ import PROMPT_KIMI from "./prompt/kimi.txt"
|
|
|
12
12
|
|
|
13
13
|
import PROMPT_CODEX from "./prompt/codex.txt"
|
|
14
14
|
import PROMPT_TRINITY from "./prompt/trinity.txt"
|
|
15
|
+
import PROMPT_OPENSEARCH from "./prompt/opensearch.txt"
|
|
16
|
+
import PROMPT_COMPOSIO from "./prompt/composio.txt"
|
|
17
|
+
import PROMPT_SUPERMEMORY from "./prompt/supermemory.txt"
|
|
18
|
+
import PROMPT_MEM0 from "./prompt/mem0.txt"
|
|
19
|
+
import PROMPT_REMOTE_TOOLS from "./prompt/remote_tools.txt"
|
|
15
20
|
import type { Provider } from "@/provider/provider"
|
|
16
21
|
import type { Agent } from "@/agent/agent"
|
|
17
22
|
import { Permission } from "@/permission"
|
|
@@ -36,6 +41,13 @@ export function provider(model: Provider.Model) {
|
|
|
36
41
|
if (model.api.id.includes("claude")) return [PROMPT_ANTHROPIC]
|
|
37
42
|
if (model.api.id.toLowerCase().includes("trinity")) return [PROMPT_TRINITY]
|
|
38
43
|
if (model.api.id.toLowerCase().includes("kimi")) return [PROMPT_KIMI]
|
|
44
|
+
|
|
45
|
+
if (model.api.id.toLowerCase().includes("search") || model.providerID.toLowerCase().includes("opensearch")) return [PROMPT_OPENSEARCH]
|
|
46
|
+
if (model.api.id.toLowerCase().includes("composio")) return [PROMPT_COMPOSIO]
|
|
47
|
+
if (model.api.id.toLowerCase().includes("supermemory") || model.api.id.toLowerCase().includes("super memory")) return [PROMPT_SUPERMEMORY]
|
|
48
|
+
if (model.api.id.toLowerCase().includes("mem0") || model.api.id.toLowerCase().includes("memory")) return [PROMPT_MEM0]
|
|
49
|
+
if (model.api.id.toLowerCase().includes("remote") || model.api.id.toLowerCase().includes("tool")) return [PROMPT_REMOTE_TOOLS]
|
|
50
|
+
|
|
39
51
|
return [PROMPT_DEFAULT]
|
|
40
52
|
}
|
|
41
53
|
|