anymous 1.2.4 → 1.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "anymous",
3
- "version": "1.2.4",
3
+ "version": "1.2.6",
4
4
  "description": "AI-powered reverse engineering platform",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -3,12 +3,12 @@ import { PermissionV1 } from "@anymous-ai/core/v1/permission"
3
3
  import { Config } from "@/config/config"
4
4
  import { serviceUse } from "@anymous-ai/core/effect/service-use"
5
5
  import { Provider } from "@/provider/provider"
6
+ import { ConfigMigrateV1 } from "@anymous-ai/core/v1/config/migrate"
6
7
 
7
8
  import { generateObject, streamObject, type ModelMessage } from "ai"
8
9
  import { Truncate } from "@/tool/truncate"
9
10
  import { Auth } from "../auth"
10
11
  import { ProviderTransform } from "@/provider/transform"
11
-
12
12
  import PROMPT_GENERATE from "./generate.txt"
13
13
  import PROMPT_BUILD from "./prompt/build.txt"
14
14
  import PROMPT_PLAN from "./prompt/plan.txt"
@@ -773,7 +773,8 @@ const layer = Layer.effect(
773
773
  }
774
774
 
775
775
  for (const [key, value] of Object.entries(cfg.agent ?? {})) {
776
- if (value.disable) {
776
+ const migrated = ConfigMigrateV1.migrateAgent(value)
777
+ if (migrated.disabled) {
777
778
  delete agents[key]
778
779
  continue
779
780
  }
@@ -786,19 +787,30 @@ const layer = Layer.effect(
786
787
  options: {},
787
788
  native: false,
788
789
  }
789
- if (value.model) item.model = Provider.parseModel(value.model)
790
- item.variant = value.variant ?? item.variant
791
- item.prompt = value.prompt ?? item.prompt
792
- item.description = value.description ?? item.description
793
- item.temperature = value.temperature ?? item.temperature
794
- item.topP = value.top_p ?? item.topP
795
- item.mode = value.mode ?? item.mode
796
- item.color = value.color ?? item.color
797
- item.hidden = value.hidden ?? item.hidden
790
+ if (migrated.model) item.model = Provider.parseModel(migrated.model)
791
+ item.variant = migrated.variant ?? item.variant
792
+ item.prompt = migrated.system ?? item.prompt
793
+ item.description = migrated.description ?? item.description
794
+ item.mode = migrated.mode ?? item.mode
795
+ item.color = migrated.color ?? item.color
796
+ item.hidden = migrated.hidden ?? item.hidden
798
797
  item.name = value.name ?? item.name
799
- item.steps = value.steps ?? item.steps
800
- item.options = mergeDeep(item.options, value.options ?? {})
801
- item.permission = Permission.merge(item.permission, Permission.fromConfig(value.permission ?? {}))
798
+ item.steps = migrated.steps ?? item.steps
799
+ const body = migrated.request?.body ?? {}
800
+ const { temperature, top_p, ...options } = body
801
+ item.temperature = temperature ?? item.temperature
802
+ item.topP = top_p ?? item.topP
803
+ item.options = mergeDeep(item.options, options)
804
+ if (migrated.permissions) {
805
+ item.permission = Permission.merge(
806
+ item.permission,
807
+ migrated.permissions.map((rule) => ({
808
+ permission: rule.action,
809
+ pattern: rule.resource,
810
+ action: rule.effect,
811
+ })),
812
+ )
813
+ }
802
814
  }
803
815
 
804
816
  // Ensure Truncate.GLOB is allowed unless explicitly configured
@@ -29,7 +29,7 @@ import type { Keymap } from "@opentui/keymap"
29
29
  import { render } from "@opentui/solid"
30
30
  import { createComponent, createSignal, type Accessor, type Setter } from "solid-js"
31
31
  import { createStore, reconcile } from "solid-js/store"
32
- import { anymousKeymapProvider } from "@anymous-ai/tui/keymap"
32
+ import { anymousKeymapProvider, type OpenTuiKeymap } from "@anymous-ai/tui/keymap"
33
33
  import { RUN_COMMAND_PANEL_ROWS, RUN_SUBAGENT_PANEL_ROWS } from "./footer.command"
34
34
  import { SUBAGENT_INSPECTOR_ROWS } from "./footer.subagent"
35
35
  import { PROMPT_MAX_ROWS, TEXTAREA_MIN_ROWS } from "./footer.prompt"
@@ -301,7 +301,7 @@ export class RunFooter implements FooterApi {
301
301
  void render(
302
302
  () =>
303
303
  createComponent(anymousKeymapProvider, {
304
- keymap: options.keymap,
304
+ keymap: options.keymap as unknown as OpenTuiKeymap,
305
305
  get children() {
306
306
  return createComponent(RunFooterView, {
307
307
  directory: options.directory,
@@ -196,7 +196,11 @@ export async function createRuntimeLifecycle(input: LifecycleInput): Promise<Lif
196
196
  const theme = await resolveRunTheme(renderer)
197
197
  renderer.setBackgroundColor(theme.background)
198
198
  const keymap = createDefaultOpenTuiKeymap(renderer)
199
- unregisterKeymap = registeranymousKeymap(keymap, renderer, input.tuiConfig)
199
+ unregisterKeymap = registeranymousKeymap(
200
+ keymap as Parameters<typeof registeranymousKeymap>[0],
201
+ renderer,
202
+ input.tuiConfig,
203
+ )
200
204
  const state: SplashState = {
201
205
  entry: false,
202
206
  exit: false,
@@ -267,7 +271,7 @@ export async function createRuntimeLifecycle(input: LifecycleInput): Promise<Lif
267
271
  return await openEditor({
268
272
  value,
269
273
  cwd: input.directory,
270
- renderer,
274
+ renderer: renderer as Parameters<typeof openEditor>[0]["renderer"],
271
275
  stdin: source.stdin,
272
276
  })
273
277
  } finally {
@@ -681,8 +681,8 @@ export async function resolveRunTheme(renderer: CliRenderer): Promise<RunTheme>
681
681
  footerTheme,
682
682
  scrollbackTheme,
683
683
  splashTheme(scrollbackTheme, indexed),
684
- syntax,
685
- shared.generateSubtleSyntax(syntaxTheme),
684
+ syntax as unknown as SyntaxStyle,
685
+ shared.generateSubtleSyntax(syntaxTheme) as unknown as SyntaxStyle,
686
686
  )
687
687
  } catch {
688
688
  return RUN_THEME_FALLBACK
@@ -16,7 +16,7 @@ import { validateSession } from "../tui/validate-session"
16
16
  import { win32InstallCtrlCGuard } from "@anymous-ai/tui/terminal-win32"
17
17
 
18
18
  declare global {
19
- const ANYMOUS_WORKER_PATH: string
19
+ var ANYMOUS_WORKER_PATH: string
20
20
  }
21
21
 
22
22
  type RpcClient = ReturnType<typeof Rpc.client<typeof rpc>>
@@ -2,6 +2,7 @@ import { LayerNode } from "@anymous-ai/core/effect/layer-node"
2
2
  import { Effect, Layer, Context, Schema } from "effect"
3
3
  import { FSUtil } from "@anymous-ai/core/fs-util"
4
4
  import { Global } from "@anymous-ai/core/global"
5
+ import { InstanceState } from "@/effect/instance-state"
5
6
  import path from "path"
6
7
 
7
8
  const MemoryEntry = Schema.Struct({
@@ -9,6 +10,7 @@ const MemoryEntry = Schema.Struct({
9
10
  value: Schema.String,
10
11
  timestamp: Schema.Number,
11
12
  sessionID: Schema.optional(Schema.String),
13
+ scope: Schema.optional(Schema.String),
12
14
  })
13
15
 
14
16
  const MemoryStore = Schema.Struct({
@@ -50,6 +52,10 @@ const saveStore = (fs: FSUtil.Interface, filePath: string, store: MemoryStoreTyp
50
52
  yield* fs.writeFileString(filePath, JSON.stringify(store, null, 2))
51
53
  })
52
54
 
55
+ // Resolve the current workspace scope. Falls back to the process-wide default workspace
56
+ // when the effect is run outside a project instance (e.g. CLI/global context).
57
+ const currentScope = Effect.map(InstanceState.workspaceID, (id) => id ?? undefined)
58
+
53
59
  const layer = Layer.effect(
54
60
  Service,
55
61
  Effect.gen(function* () {
@@ -67,10 +73,17 @@ const layer = Layer.effect(
67
73
  value: string,
68
74
  sessionID?: string,
69
75
  ) {
76
+ const scope = yield* currentScope
70
77
  const store = yield* loadStore(fs, filePath).pipe(Effect.orDie)
71
78
  const memories = [...store.memories]
72
- const existing = memories.findIndex((m) => m.key === key)
73
- const entry: MemoryEntryType = { key, value, timestamp: Date.now(), ...(sessionID ? { sessionID } : {}) }
79
+ const existing = memories.findIndex((m) => m.key === key && m.scope === scope)
80
+ const entry: MemoryEntryType = {
81
+ key,
82
+ value,
83
+ timestamp: Date.now(),
84
+ ...(sessionID ? { sessionID } : {}),
85
+ ...(scope ? { scope } : {}),
86
+ }
74
87
  if (existing >= 0) {
75
88
  memories[existing] = entry
76
89
  } else {
@@ -80,14 +93,16 @@ const layer = Layer.effect(
80
93
  })
81
94
 
82
95
  const list: Interface["list"] = Effect.fn("Memory.list")(function* () {
96
+ const scope = yield* currentScope
83
97
  const store = yield* loadStore(fs, filePath).pipe(Effect.orDie)
84
- return [...store.memories]
98
+ return store.memories.filter((m) => m.scope === scope)
85
99
  })
86
100
 
87
101
  const remove: Interface["delete"] = Effect.fn("Memory.delete")(function* (key: string) {
102
+ const scope = yield* currentScope
88
103
  const store = yield* loadStore(fs, filePath).pipe(Effect.orDie)
89
104
  const memories = [...store.memories]
90
- const idx = memories.findIndex((m) => m.key === key)
105
+ const idx = memories.findIndex((m) => m.key === key && m.scope === scope)
91
106
  if (idx < 0) return false
92
107
  memories.splice(idx, 1)
93
108
  yield* saveStore(fs, filePath, { ...store, memories }).pipe(Effect.orDie)
@@ -95,9 +110,13 @@ const layer = Layer.effect(
95
110
  })
96
111
 
97
112
  const allText: Interface["allText"] = Effect.fn("Memory.allText")(function* () {
113
+ const scope = yield* currentScope
98
114
  const store = yield* loadStore(fs, filePath).pipe(Effect.orDie)
99
- if (store.memories.length === 0) return undefined
100
- const lines = store.memories.map((m) => `- ${m.key}: ${m.value}`)
115
+ // Project-scoped memories are visible only within their own project; unscoped
116
+ // entries remain global (shared context for every workspace).
117
+ const entries = store.memories.filter((m) => m.scope === undefined || m.scope === scope)
118
+ if (entries.length === 0) return undefined
119
+ const lines = entries.map((m) => `- ${m.key}: ${m.value}`)
101
120
  return `## Shared Context / Memory\n\n${lines.join("\n")}`
102
121
  })
103
122
 
@@ -216,12 +216,12 @@ const typeText = Effect.fn("Computer.typeText")(function* (text: string, delayMs
216
216
  } else {
217
217
  for (const char of text) {
218
218
  yield* typeChar(char)
219
- if (delayMs > 0) yield* Effect.promise<void>((resolve) => setTimeout(resolve, delayMs))
219
+ if (delayMs > 0) yield* Effect.sleep(delayMs)
220
220
  }
221
221
  }
222
222
  })
223
223
 
224
- const keyPress = Effect.fn("Computer.keyPress")(function* (keys: string[]) {
224
+ const keyPress = Effect.fn("Computer.keyPress")(function* (keys: readonly string[]) {
225
225
  const combo = keys.join("+")
226
226
  if (platform === "win32") {
227
227
  const mapping: Record<string, string> = {
@@ -324,7 +324,7 @@ Write-Output "$($s.Width) $($s.Height)"
324
324
  proc.on("error", reject)
325
325
  }),
326
326
  )
327
- const [_, __, w, h] = d.split(", ").map(Number)
327
+ const [_, __, w, h] = raw.split(", ").map(Number)
328
328
  return { width: w, height: h }
329
329
  }
330
330
  if (platform === "linux") {
@@ -345,17 +345,17 @@ Write-Output "$($s.Width) $($s.Height)"
345
345
  })
346
346
 
347
347
  export const Action = Schema.Struct({
348
- action: Schema.Literal("screenshot", "click", "doubleclick", "rightclick", "move", "type", "keypress", "scroll", "screensize"),
348
+ action: Schema.Literals(["screenshot", "click", "doubleclick", "rightclick", "move", "type", "keypress", "scroll", "screensize"]),
349
349
  x: Schema.optional(Schema.Number).annotate({ description: "X coordinate for click/move actions" }),
350
350
  y: Schema.optional(Schema.Number).annotate({ description: "Y coordinate for click/move actions" }),
351
351
  text: Schema.optional(Schema.String).annotate({ description: "Text to type (for type action)" }),
352
352
  delayMs: Schema.optional(Schema.Number).annotate({ description: "Delay in ms between keystrokes (for type action, default: 0)" }),
353
353
  keys: Schema.optional(Schema.Array(Schema.String)).annotate({ description: "Keys to press (for keypress action), e.g. ['ctrl', 'c']" }),
354
- button: Schema.optional(Schema.Literal("left", "right", "middle")).annotate({ description: "Mouse button (default: left)" }),
354
+ button: Schema.optional(Schema.Literals(["left", "right", "middle"])).annotate({ description: "Mouse button (default: left)" }),
355
355
  clicks: Schema.optional(Schema.Number).annotate({ description: "Scroll clicks (positive=up, negative=down)" }),
356
356
  })
357
357
 
358
- export const ComputerTool = Tool.define<typeof Action, {}, Question.Service>(
358
+ export const ComputerTool = Tool.define<typeof Action, {}, never>(
359
359
  "computer",
360
360
  Effect.gen(function* () {
361
361
  return {
@@ -366,12 +366,12 @@ export const ComputerTool = Tool.define<typeof Action, {}, Question.Service>(
366
366
  const { action } = params
367
367
 
368
368
  if (action === "screenshot") {
369
- const dataUrl = yield* captureScreenshot
369
+ const dataUrl = yield* captureScreenshot()
370
370
  return {
371
371
  title: "Captured screenshot",
372
372
  output: "Screenshot captured. Use the image to decide the next action.",
373
373
  attachments: [{
374
- type: "file",
374
+ type: "file" as const,
375
375
  mime: "image/png",
376
376
  filename: "screenshot.png",
377
377
  url: dataUrl,
@@ -394,12 +394,12 @@ export const ComputerTool = Tool.define<typeof Action, {}, Question.Service>(
394
394
  if (action === "doubleclick") {
395
395
  yield* clickMouse(btn as "left" | "right" | "middle")
396
396
  }
397
- const dataUrl = yield* captureScreenshot
397
+ const dataUrl = yield* captureScreenshot()
398
398
  return {
399
399
  title: `${action} at (${params.x ?? "current"}, ${params.y ?? "current"})`,
400
400
  output: `Performed ${action}. Screenshot shows the result.`,
401
401
  attachments: [{
402
- type: "file",
402
+ type: "file" as const,
403
403
  mime: "image/png",
404
404
  filename: "screenshot.png",
405
405
  url: dataUrl,
@@ -410,12 +410,12 @@ export const ComputerTool = Tool.define<typeof Action, {}, Question.Service>(
410
410
 
411
411
  if (action === "type") {
412
412
  yield* typeText(params.text!, params.delayMs ?? 0)
413
- const dataUrl = yield* captureScreenshot
413
+ const dataUrl = yield* captureScreenshot()
414
414
  return {
415
415
  title: `Typed text`,
416
416
  output: `Typed "${params.text!.length > 50 ? params.text!.slice(0, 50) + "..." : params.text!}". Screenshot shows the result.`,
417
417
  attachments: [{
418
- type: "file",
418
+ type: "file" as const,
419
419
  mime: "image/png",
420
420
  filename: "screenshot.png",
421
421
  url: dataUrl,
@@ -426,12 +426,12 @@ export const ComputerTool = Tool.define<typeof Action, {}, Question.Service>(
426
426
 
427
427
  if (action === "keypress") {
428
428
  yield* keyPress(params.keys!)
429
- const dataUrl = yield* captureScreenshot
429
+ const dataUrl = yield* captureScreenshot()
430
430
  return {
431
431
  title: `Key press: ${params.keys!.join("+")}`,
432
432
  output: `Pressed ${params.keys!.join("+")}. Screenshot shows the result.`,
433
433
  attachments: [{
434
- type: "file",
434
+ type: "file" as const,
435
435
  mime: "image/png",
436
436
  filename: "screenshot.png",
437
437
  url: dataUrl,
@@ -442,12 +442,12 @@ export const ComputerTool = Tool.define<typeof Action, {}, Question.Service>(
442
442
 
443
443
  if (action === "scroll") {
444
444
  yield* scrollMouse(params.clicks ?? 3)
445
- const dataUrl = yield* captureScreenshot
445
+ const dataUrl = yield* captureScreenshot()
446
446
  return {
447
447
  title: `Scrolled ${params.clicks ?? 3} clicks`,
448
448
  output: `Scrolled. Screenshot shows the result.`,
449
449
  attachments: [{
450
- type: "file",
450
+ type: "file" as const,
451
451
  mime: "image/png",
452
452
  filename: "screenshot.png",
453
453
  url: dataUrl,
@@ -457,7 +457,7 @@ export const ComputerTool = Tool.define<typeof Action, {}, Question.Service>(
457
457
  }
458
458
 
459
459
  if (action === "screensize") {
460
- const size = yield* getScreenSize
460
+ const size = yield* getScreenSize()
461
461
  return {
462
462
  title: "Screen size",
463
463
  output: `Screen resolution: ${size.width}x${size.height}`,
@@ -6,7 +6,7 @@ Actions:
6
6
  - delete (key): Remove a memory
7
7
  - list: List all memories
8
8
 
9
- Memories are automatically injected into the system prompt at the start of every session as shared context. Use this for:
9
+ Memories are scoped to the current project (workspace). Memories you write are only visible when working inside this same project. They are automatically injected into the system prompt at the start of every session as shared context. Use this for:
10
10
  - Project architecture decisions
11
11
  - Coding conventions and preferences
12
12
  - Authentication tokens or API keys
package/tsconfig.json CHANGED
@@ -12,5 +12,6 @@
12
12
  "@/*": ["./src/*"],
13
13
  "@test/*": ["./test/*"]
14
14
  }
15
- }
15
+ },
16
+ "exclude": ["dist-npm", "node_modules"]
16
17
  }