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 +1 -1
- package/src/agent/agent.ts +26 -14
- package/src/cli/cmd/run/footer.ts +2 -2
- package/src/cli/cmd/run/runtime.lifecycle.ts +6 -2
- package/src/cli/cmd/run/theme.ts +2 -2
- package/src/cli/cmd/tui.ts +1 -1
- package/src/memory/memory.ts +25 -6
- package/src/tool/computer.ts +17 -17
- package/src/tool/memory.txt +1 -1
- package/tsconfig.json +2 -1
package/package.json
CHANGED
package/src/agent/agent.ts
CHANGED
|
@@ -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
|
-
|
|
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 (
|
|
790
|
-
item.variant =
|
|
791
|
-
item.prompt =
|
|
792
|
-
item.description =
|
|
793
|
-
item.
|
|
794
|
-
item.
|
|
795
|
-
item.
|
|
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 =
|
|
800
|
-
|
|
801
|
-
|
|
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(
|
|
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 {
|
package/src/cli/cmd/run/theme.ts
CHANGED
|
@@ -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
|
package/src/cli/cmd/tui.ts
CHANGED
|
@@ -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
|
-
|
|
19
|
+
var ANYMOUS_WORKER_PATH: string
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
type RpcClient = ReturnType<typeof Rpc.client<typeof rpc>>
|
package/src/memory/memory.ts
CHANGED
|
@@ -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 = {
|
|
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
|
|
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
|
-
|
|
100
|
-
|
|
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
|
|
package/src/tool/computer.ts
CHANGED
|
@@ -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.
|
|
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] =
|
|
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.
|
|
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.
|
|
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, {},
|
|
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}`,
|
package/src/tool/memory.txt
CHANGED
|
@@ -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
|