orynacode-ai 1.16.8 → 1.16.10

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
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "1.16.8",
3
+ "version": "1.16.10",
4
4
  "name": "orynacode-ai",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -6,6 +6,7 @@ import { InstallationVersion } from "@opencode-ai/core/installation/version"
6
6
  import { GlobalBus } from "@/bus/global"
7
7
 
8
8
  export async function upgrade() {
9
+ if (InstallationVersion.startsWith("0.0.0-")) return
9
10
  const config = await AppRuntime.runPromise(Config.Service.use((cfg) => cfg.getGlobal()))
10
11
  if (config.autoupdate === false || Flag.OPENCODE_DISABLE_AUTOUPDATE) return
11
12
  const method = await Installation.method()
@@ -136,11 +136,9 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProce
136
136
  )
137
137
 
138
138
  const getBrewFormula = Effect.fnUntraced(function* () {
139
- const tapFormula = yield* text(["brew", "list", "--formula", "anomalyco/tap/opencode"])
140
- if (tapFormula.includes("opencode")) return "anomalyco/tap/opencode"
141
- const coreFormula = yield* text(["brew", "list", "--formula", "opencode"])
142
- if (coreFormula.includes("opencode")) return "opencode"
143
- return "opencode"
139
+ const tapFormula = yield* text(["brew", "list", "--formula", "oryna-ai/tap/orynacode"])
140
+ if (tapFormula.includes("orynacode")) return "oryna-ai/tap/orynacode"
141
+ return "oryna-ai/tap/orynacode"
144
142
  })
145
143
 
146
144
  const upgradeFailure = (method: Method, result?: { code: number; stdout: string; stderr: string }) => {
@@ -194,9 +192,7 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProce
194
192
  { name: "yarn", command: () => text(["yarn", "global", "list"]) },
195
193
  { name: "pnpm", command: () => text(["pnpm", "list", "-g", "--depth=0"]) },
196
194
  { name: "bun", command: () => text(["bun", "pm", "ls", "-g"]) },
197
- { name: "brew", command: () => text(["brew", "list", "--formula", "opencode"]) },
198
- { name: "scoop", command: () => text(["scoop", "list", "opencode"]) },
199
- { name: "choco", command: () => text(["choco", "list", "--limit-output", "opencode"]) },
195
+ { name: "brew", command: () => text(["brew", "list", "--formula", "orynacode"]) },
200
196
  ]
201
197
 
202
198
  checks.sort((a, b) => {
@@ -209,8 +205,7 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProce
209
205
 
210
206
  for (const check of checks) {
211
207
  const output = yield* check.command()
212
- const installedName =
213
- check.name === "brew" || check.name === "choco" || check.name === "scoop" ? "opencode" : "opencode-ai"
208
+ const installedName = check.name === "brew" ? "orynacode" : "orynacode-ai"
214
209
  if (output.includes(installedName)) {
215
210
  return check.name
216
211
  }
@@ -228,45 +223,18 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProce
228
223
  const info = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(BrewInfoV2))(infoJson)
229
224
  return info.formulae[0].versions.stable
230
225
  }
231
- const response = yield* httpOk.execute(
232
- HttpClientRequest.get("https://formulae.brew.sh/api/formula/opencode.json").pipe(
233
- HttpClientRequest.acceptJson,
234
- ),
235
- )
236
- const data = yield* HttpClientResponse.schemaBodyJson(BrewFormula)(response)
237
- return data.versions.stable
238
226
  }
239
227
 
240
228
  if (detectedMethod === "npm" || detectedMethod === "bun" || detectedMethod === "pnpm") {
241
229
  const response = yield* httpOk.execute(
242
230
  HttpClientRequest.get(
243
- `${yield* NpmConfig.registry(process.cwd())}/opencode-ai/${InstallationChannel}`,
231
+ `${yield* NpmConfig.registry(process.cwd())}/orynacode-ai/${InstallationChannel}`,
244
232
  ).pipe(HttpClientRequest.acceptJson),
245
233
  )
246
234
  const data = yield* HttpClientResponse.schemaBodyJson(NpmPackage)(response)
247
235
  return data.version
248
236
  }
249
237
 
250
- if (detectedMethod === "choco") {
251
- const response = yield* httpOk.execute(
252
- HttpClientRequest.get(
253
- "https://community.chocolatey.org/api/v2/Packages?$filter=Id%20eq%20%27opencode%27%20and%20IsLatestVersion&$select=Version",
254
- ).pipe(HttpClientRequest.setHeaders({ Accept: "application/json;odata=verbose" })),
255
- )
256
- const data = yield* HttpClientResponse.schemaBodyJson(ChocoPackage)(response)
257
- return data.d.results[0].Version
258
- }
259
-
260
- if (detectedMethod === "scoop") {
261
- const response = yield* httpOk.execute(
262
- HttpClientRequest.get(
263
- "https://raw.githubusercontent.com/ScoopInstaller/Main/master/bucket/opencode.json",
264
- ).pipe(HttpClientRequest.setHeaders({ Accept: "application/json" })),
265
- )
266
- const data = yield* HttpClientResponse.schemaBodyJson(ScoopManifest)(response)
267
- return data.version
268
- }
269
-
270
238
  const response = yield* httpOk.execute(
271
239
  HttpClientRequest.get("https://api.github.com/repos/oryna-ai/orynacode/releases/latest").pipe(
272
240
  HttpClientRequest.acceptJson,
@@ -282,24 +250,24 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProce
282
250
  upgradeResult = yield* upgradeCurl(target)
283
251
  break
284
252
  case "npm":
285
- upgradeResult = yield* run(["npm", "install", "-g", `opencode-ai@${target}`])
253
+ upgradeResult = yield* run(["npm", "install", "-g", `orynacode-ai@${target}`])
286
254
  break
287
255
  case "pnpm":
288
- upgradeResult = yield* run(["pnpm", "install", "-g", `opencode-ai@${target}`])
256
+ upgradeResult = yield* run(["pnpm", "install", "-g", `orynacode-ai@${target}`])
289
257
  break
290
258
  case "bun":
291
- upgradeResult = yield* run(["bun", "install", "-g", `opencode-ai@${target}`])
259
+ upgradeResult = yield* run(["bun", "install", "-g", `orynacode-ai@${target}`])
292
260
  break
293
261
  case "brew": {
294
262
  const formula = yield* getBrewFormula()
295
263
  const env = { HOMEBREW_NO_AUTO_UPDATE: "1" }
296
264
  if (formula.includes("/")) {
297
- const tap = yield* run(["brew", "tap", "anomalyco/tap"], { env })
265
+ const tap = yield* run(["brew", "tap", "oryna-ai/tap"], { env })
298
266
  if (tap.code !== 0) {
299
267
  upgradeResult = tap
300
268
  break
301
269
  }
302
- const repo = yield* text(["brew", "--repo", "anomalyco/tap"])
270
+ const repo = yield* text(["brew", "--repo", "oryna-ai/tap"])
303
271
  const dir = repo.trim()
304
272
  if (dir) {
305
273
  const pull = yield* run(["git", "pull", "--ff-only"], { cwd: dir, env })
@@ -312,12 +280,6 @@ export const layer: Layer.Layer<Service, never, HttpClient.HttpClient | AppProce
312
280
  upgradeResult = yield* run(["brew", "upgrade", formula], { env })
313
281
  break
314
282
  }
315
- case "choco":
316
- upgradeResult = yield* run(["choco", "upgrade", "opencode", `--version=${target}`, "-y"])
317
- break
318
- case "scoop":
319
- upgradeResult = yield* run(["scoop", "install", `opencode@${target}`])
320
- break
321
283
  default:
322
284
  return yield* new UpgradeFailedError({ stderr: `Unknown installation method: ${m}` })
323
285
  }
@@ -224,6 +224,22 @@ function mapOrynaModels(data: Record<string, any>): Record<string, any> {
224
224
  return result
225
225
  }
226
226
 
227
+ export async function reAuthOryna(): Promise<string> {
228
+ const port = await startOAuthServer()
229
+ const state = randomState()
230
+ const redirectUri = `http://127.0.0.1:${port}/callback`
231
+ const loginUrl = `${ORYNA_LOGIN_URL}?redirect_uri=${encodeURIComponent(redirectUri)}&state=${state}`
232
+
233
+ const tokenPromise = waitForToken(state)
234
+ await open(loginUrl)
235
+
236
+ try {
237
+ return await tokenPromise
238
+ } finally {
239
+ stopOAuthServer()
240
+ }
241
+ }
242
+
227
243
  export async function OrynaAuthPlugin(input: PluginInput): Promise<Hooks> {
228
244
  return {
229
245
  provider: {
@@ -251,15 +267,18 @@ export async function OrynaAuthPlugin(input: PluginInput): Promise<Hooks> {
251
267
 
252
268
  if (jwtExpired(jwt)) {
253
269
  if (!_refreshPromise) {
254
- _refreshPromise = refreshJwt(jwt).catch(() => {
270
+ _refreshPromise = refreshJwt(jwt).catch(async () => {
255
271
  _refreshPromise = undefined
256
- return jwt
272
+ log.info("oryna token refresh failed, removing stale auth")
273
+ await (input.client as any)._client.delete({ url: "/auth/{id}", path: { id: "oryna" } }).catch(() => {})
274
+ log.info("oryna stale auth removed")
275
+ return ""
257
276
  })
258
277
  }
259
278
  jwt = await _refreshPromise
260
279
  _refreshPromise = undefined
261
280
 
262
- if (jwt !== auth.key) {
281
+ if (jwt && jwt !== auth.key) {
263
282
  await input.client.auth
264
283
  .set({
265
284
  path: { id: "oryna" },
@@ -269,7 +288,7 @@ export async function OrynaAuthPlugin(input: PluginInput): Promise<Hooks> {
269
288
  }
270
289
  }
271
290
 
272
- return { apiKey: jwt }
291
+ return jwt ? { apiKey: jwt } : {}
273
292
  },
274
293
  methods: [
275
294
  {
@@ -277,36 +296,20 @@ export async function OrynaAuthPlugin(input: PluginInput): Promise<Hooks> {
277
296
  label: "Login with Oryna AI (Browser)",
278
297
  authorize: async () => {
279
298
  try {
280
- const port = await startOAuthServer()
281
- const state = randomState()
282
- const redirectUri = `http://127.0.0.1:${port}/callback`
283
- const loginUrl = `${ORYNA_LOGIN_URL}?redirect_uri=${encodeURIComponent(redirectUri)}&state=${state}`
284
-
285
- const tokenPromise = waitForToken(state)
286
-
287
- await open(loginUrl)
288
-
299
+ const tokenPromise = reAuthOryna()
289
300
  return {
290
- url: loginUrl,
301
+ url: ORYNA_LOGIN_URL,
291
302
  instructions: "Complete login in your browser. This window will close automatically when done.",
292
303
  method: "auto" as const,
293
304
  callback: async () => {
294
305
  try {
295
- const token = await tokenPromise
296
- return {
297
- type: "success" as const,
298
- key: token,
299
- }
300
- } catch (err) {
301
- log.error("oryna login callback failed", { error: err })
306
+ return { type: "success" as const, key: await tokenPromise }
307
+ } catch {
302
308
  return { type: "failed" as const }
303
- } finally {
304
- stopOAuthServer()
305
309
  }
306
310
  },
307
311
  }
308
- } catch (err) {
309
- log.error("oryna login authorize failed", { error: err })
312
+ } catch {
310
313
  return {
311
314
  url: ORYNA_LOGIN_URL,
312
315
  instructions: "Failed to start login server. Please use API key instead.",
@@ -952,7 +952,14 @@ export const layer = Layer.effect(
952
952
  sessionID: ctx.assistantMessage.sessionID,
953
953
  error: ctx.assistantMessage.error,
954
954
  })
955
- yield* status.set(ctx.sessionID, { type: "idle" })
955
+ if (
956
+ error.name === "ProviderAuthError" ||
957
+ (error.data as any)?.statusCode === 401
958
+ ) {
959
+ yield* status.set(ctx.sessionID, { type: "needs_auth", providerID: String(input.model.providerID) })
960
+ } else {
961
+ yield* status.set(ctx.sessionID, { type: "idle" })
962
+ }
956
963
  })
957
964
 
958
965
  const process = Effect.fn("SessionProcessor.process")(function* (streamInput: LLM.StreamInput) {
@@ -28,6 +28,10 @@ export const Info = Schema.Union([
28
28
  Schema.Struct({
29
29
  type: Schema.Literal("busy"),
30
30
  }),
31
+ Schema.Struct({
32
+ type: Schema.Literal("needs_auth"),
33
+ providerID: Schema.String,
34
+ }),
31
35
  ]).annotate({ identifier: "SessionStatus" })
32
36
  export type Info = Schema.Schema.Type<typeof Info>
33
37
 
@@ -76,6 +80,7 @@ export const layer = Layer.effect(
76
80
 
77
81
  const set = Effect.fn("SessionStatus.set")(function* (sessionID: SessionID, status: Info) {
78
82
  const data = yield* InstanceState.get(state)
83
+ if (status.type === "idle" && data.get(sessionID)?.type === "needs_auth") return
79
84
  yield* events.publish(Event.Status, { sessionID, status })
80
85
  if (status.type === "idle") {
81
86
  yield* events.publish(Event.Idle, { sessionID })
@@ -240,7 +240,7 @@ export const layer: Layer.Layer<
240
240
  question: Tool.init(question),
241
241
  lsp: Tool.init(lsptool),
242
242
  plan: Tool.init(plan),
243
- reply: Tool.init(replytool),
243
+ collab_reply: Tool.init(replytool),
244
244
  })
245
245
 
246
246
  return {
@@ -260,7 +260,7 @@ export const layer: Layer.Layer<
260
260
  tool.search,
261
261
  tool.skill,
262
262
  tool.patch,
263
- tool.reply,
263
+ tool.collab_reply,
264
264
  ...(flags.experimentalLspTool ? [tool.lsp] : []),
265
265
  ...(flags.experimentalPlanMode && flags.client === "cli" ? [tool.plan] : []),
266
266
  ],
package/src/tool/reply.ts CHANGED
@@ -12,7 +12,7 @@ export const Parameters = Schema.Struct({
12
12
  })
13
13
 
14
14
  export const ReplyTool = Tool.define(
15
- "reply",
15
+ "collab_reply",
16
16
  Effect.gen(function* () {
17
17
  return {
18
18
  description: