@kisev/agentomatic 11.0.2-dev.93.g810c3f0460fa → 11.0.2

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.
@@ -1,16 +1,13 @@
1
- import type { Plugin } from "@opencode/plugin";
2
1
  export type ZedBellOptions = {
3
2
  enabled?: boolean;
4
3
  };
5
4
  export declare function zedBell(options?: ZedBellOptions): Promise<{
6
5
  event?: undefined;
7
6
  } | {
8
- event: (event: {
9
- type: string;
7
+ event: ({ event }: {
8
+ event: {
9
+ type?: string;
10
+ };
10
11
  }) => Promise<void>;
11
12
  }>;
12
- declare const _default: {
13
- id: string;
14
- setup(ctx: Plugin.Context): Promise<(() => Promise<void>) | undefined>;
15
- };
16
- export default _default;
13
+ export default zedBell;
@@ -1,9 +1,8 @@
1
- import { subscribeEvents } from "./events.js";
2
1
  export async function zedBell(options = {}) {
3
2
  if (!options.enabled)
4
3
  return {};
5
4
  return {
6
- event: async (event) => {
5
+ event: async ({ event }) => {
7
6
  if (event.type !== "session.idle" && event.type !== "permission.asked")
8
7
  return;
9
8
  const acp = process.env.OPENCODE_CLIENT === "acp" || process.argv.includes("acp");
@@ -12,11 +11,4 @@ export async function zedBell(options = {}) {
12
11
  },
13
12
  };
14
13
  }
15
- export default {
16
- id: "agentomatic.zed-bell",
17
- async setup(ctx) {
18
- const hooks = await zedBell(ctx.options);
19
- if (hooks.event)
20
- return subscribeEvents(ctx, hooks.event);
21
- },
22
- };
14
+ export default zedBell;
package/dist/registry.js CHANGED
@@ -57,7 +57,7 @@ const COMMANDS = [
57
57
  "Show the RTK output-compression observability summary for this host.",
58
58
  `Run \`npx --yes @kisev/agentomatic@${requirePackageVersion()} doctor --json\` and render the \`rtk.observability\` check as a short human summary: wrapper status, rtk binary availability, event counters, characters saved, and the token estimate.`,
59
59
  "When the doctor command is unavailable, read the stats file directly: `$XDG_STATE_HOME/opencode/skills/rtk/stats.json`, or `~/.local/state/opencode/skills/rtk/stats.json` when that variable is unset.",
60
- "Zero counters with an active wrapper mean no verbose shell output has been compressed yet.",
60
+ "Zero counters with an active wrapper mean no verbose bash output has been compressed yet.",
61
61
  "The `/rtk` command still loads the portable rtk skill and is unaffected by this summary.",
62
62
  ],
63
63
  },
package/dist/routing.js CHANGED
@@ -21,7 +21,7 @@ const MATRIX = {
21
21
  implementation: {
22
22
  profiles: ["worker"],
23
23
  capabilities: ["read", "write", "verify"],
24
- tools: ["read", "edit", "shell"],
24
+ tools: ["read", "edit", "bash"],
25
25
  cost: "medium",
26
26
  latency: "standard",
27
27
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kisev/agentomatic",
3
- "version": "11.0.2-dev.93.g810c3f0460fa",
3
+ "version": "11.0.2",
4
4
  "description": "OpenCode integration and opt-in installer for portable Agent Skills.",
5
5
  "homepage": "https://github.com/kisev/skills#readme",
6
6
  "bugs": {
@@ -40,26 +40,25 @@
40
40
  },
41
41
  "scripts": {
42
42
  "build": "node scripts/clean-dist.mjs && tsc --project tsconfig.json && node dist/generate-assets.js",
43
- "test": "node --test test/agent-profiles.test.mjs test/config-setup.test.mjs test/legacy-migration.test.mjs test/doctor.test.mjs test/package.test.mjs test/rtk.test.mjs test/self-install.test.mjs test/stage19.test.mjs test/surface-coverage.test.mjs test/opencode-compatibility.test.mjs",
43
+ "test": "node --test test/agent-profiles.test.mjs test/config-setup.test.mjs test/legacy-migration.test.mjs test/doctor.test.mjs test/package.test.mjs test/rtk.test.mjs test/self-install.test.mjs test/stage19.test.mjs test/surface-coverage.test.mjs",
44
44
  "smoke": "node test/smoke.mjs",
45
45
  "pack:check": "node test/pack-allowlist.mjs"
46
46
  },
47
47
  "dependencies": {
48
48
  "@clack/prompts": "^1.8.1",
49
- "@kisev/safe-fs": "1.0.0-dev.93.g810c3f0460fa",
50
- "commander": "15.0.0",
51
- "zod": "4.1.8"
49
+ "@kisev/safe-fs": "^1.0.0",
50
+ "commander": "15.0.0"
52
51
  },
53
52
  "devDependencies": {
54
- "@opencode/plugin": "2.0.19",
53
+ "@opencode-ai/plugin": "1.18.29",
55
54
  "@types/node": "22.15.30",
56
55
  "typescript": "7.0.2"
57
56
  },
58
57
  "peerDependencies": {
59
- "@opencode/plugin": ">=2.0.0 <2.1.0"
58
+ "@opencode-ai/plugin": ">=1.18.29 <1.19.0"
60
59
  },
61
60
  "peerDependenciesMeta": {
62
- "@opencode/plugin": {
61
+ "@opencode-ai/plugin": {
63
62
  "optional": true
64
63
  }
65
64
  },
@@ -1,9 +0,0 @@
1
- import { type JsoncEdit } from "./jsonc.js";
2
- export type PermissionRule = {
3
- action: string;
4
- resource: string;
5
- effect: "allow" | "ask" | "deny";
6
- };
7
- export declare function permissionEdits(config: Record<string, unknown>, additions: PermissionRule[]): JsoncEdit[];
8
- export declare function matchesWildcard(pattern: string, value: string): boolean;
9
- export declare function corePluginEdits(config: Record<string, unknown>): JsoncEdit[];
@@ -1,158 +0,0 @@
1
- import { JsoncError } from "./jsonc.js";
2
- import { requirePackageVersion } from "./package-metadata.js";
3
- const effects = new Set(["allow", "ask", "deny"]);
4
- const aliases = {
5
- bash: "shell",
6
- task: "subagent",
7
- write: "edit",
8
- patch: "edit",
9
- };
10
- function object(value) {
11
- return Boolean(value && typeof value === "object" && !Array.isArray(value));
12
- }
13
- function legacyPermissions(value) {
14
- if (typeof value === "string" && effects.has(value))
15
- return [{ action: "*", resource: "*", effect: value }];
16
- if (!object(value))
17
- throw new JsoncError("conflict", "Legacy permission must be an effect or a tool map");
18
- return Object.entries(value).flatMap(([name, entry]) => {
19
- if (name === "lsp" || name === "doom_loop")
20
- throw new JsoncError("conflict", `Permission action has no V2 equivalent: ${name}`);
21
- const action = aliases[name] ?? name;
22
- const resources = typeof entry === "string" ? { "*": entry } : entry;
23
- if (!object(resources))
24
- throw new JsoncError("conflict", `Invalid permission map: ${name}`);
25
- return Object.entries(resources).map(([resource, effect]) => {
26
- if (typeof effect !== "string" || !effects.has(effect))
27
- throw new JsoncError("conflict", `Invalid permission effect: ${name}`);
28
- return { action, resource, effect: effect };
29
- });
30
- });
31
- }
32
- export function permissionEdits(config, additions) {
33
- const edits = [];
34
- let rules = [];
35
- if ("permissions" in config) {
36
- if (!Array.isArray(config.permissions) ||
37
- !config.permissions.every((rule) => object(rule) &&
38
- typeof rule.action === "string" &&
39
- typeof rule.resource === "string" &&
40
- typeof rule.effect === "string" &&
41
- effects.has(rule.effect)))
42
- throw new JsoncError("conflict", "V2 permissions must be an ordered array of action/resource/effect rules");
43
- rules = config.permissions;
44
- }
45
- let tools = [];
46
- if ("tools" in config) {
47
- if (!object(config.tools) ||
48
- !Object.values(config.tools).every((value) => typeof value === "boolean"))
49
- throw new JsoncError("conflict", "Legacy tools must be a boolean map");
50
- tools = Object.entries(config.tools).map(([name, enabled]) => ({
51
- action: aliases[name] ?? name,
52
- resource: "*",
53
- effect: enabled ? "allow" : "deny",
54
- }));
55
- }
56
- const legacyKeys = ["tools", "permission"].filter((key) => key in config);
57
- if (legacyKeys.length) {
58
- // V2 normalizes tools first, legacy permission next, and native rules last.
59
- rules = [
60
- ...tools,
61
- ...("permission" in config ? legacyPermissions(config.permission) : []),
62
- ...rules,
63
- ];
64
- const renamed = "permissions" in config ? undefined : legacyKeys[0];
65
- for (const key of legacyKeys)
66
- edits.push(key === renamed
67
- ? { kind: "rename-key", path: [key], to: "permissions" }
68
- : { kind: "remove-key", path: [key] });
69
- edits.push({ kind: "set-value", path: ["permissions"], value: rules });
70
- }
71
- else if (!("permissions" in config))
72
- edits.push({ kind: "set-if-absent", path: ["permissions"], value: [] });
73
- for (const rule of additions) {
74
- const exact = rules.reduce((last, existing, index) => existing.action === rule.action && existing.resource === rule.resource ? index : last, -1);
75
- if (exact >= 0) {
76
- if (rules[exact].effect !== rule.effect ||
77
- rules
78
- .slice(exact + 1)
79
- .some((later) => matchesWildcard(later.action, rule.action) &&
80
- matchesWildcard(later.resource, rule.resource) &&
81
- later.effect !== rule.effect))
82
- throw new JsoncError("conflict", `Existing permission conflicts with preset: ${rule.action} ${rule.resource}`);
83
- continue;
84
- }
85
- edits.push({ kind: "append-unique", path: ["permissions"], value: rule });
86
- rules = [...rules, rule];
87
- }
88
- return edits;
89
- }
90
- export function matchesWildcard(pattern, value) {
91
- return new RegExp(`^${pattern
92
- .replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
93
- .replace(/\\\*/g, ".*")
94
- .replace(/\\\?/g, ".")}$`).test(value);
95
- }
96
- function plugins(value, legacy) {
97
- if (!Array.isArray(value))
98
- throw new JsoncError("conflict", "Plugin configuration must be an array");
99
- return value.map((entry) => {
100
- if (typeof entry === "string")
101
- return entry === "@kisev/skills-opencode" ? "@kisev/agentomatic" : entry;
102
- if (legacy &&
103
- Array.isArray(entry) &&
104
- entry.length === 2 &&
105
- typeof entry[0] === "string" &&
106
- object(entry[1]))
107
- return {
108
- package: entry[0] === "@kisev/skills-opencode" ? "@kisev/agentomatic" : entry[0],
109
- options: entry[1],
110
- };
111
- if (object(entry) && typeof entry.package === "string")
112
- return {
113
- ...entry,
114
- package: entry.package === "@kisev/skills-opencode" ? "@kisev/agentomatic" : entry.package,
115
- };
116
- throw new JsoncError("conflict", "Invalid plugin entry; use a package string or V2 package/options object");
117
- });
118
- }
119
- const OUR_PACKAGE = /^@kisev\/(?:agentomatic|skills-opencode)(?:@|$)/;
120
- function ourEntry(entry) {
121
- if (typeof entry === "string")
122
- return OUR_PACKAGE.test(entry);
123
- return object(entry) && typeof entry.package === "string" && OUR_PACKAGE.test(entry.package);
124
- }
125
- export function corePluginEdits(config) {
126
- const edits = [
127
- { kind: "set-if-absent", path: ["$schema"], value: "https://opencode.ai/config.json" },
128
- ];
129
- // V2 resolves a bare package name through the registry "latest" dist-tag, which
130
- // can differ from the installed build; pin the exact running version instead.
131
- const pinned = `@kisev/agentomatic@${requirePackageVersion()}`;
132
- const native = "plugins" in config ? plugins(config.plugins, false) : undefined;
133
- const legacy = "plugin" in config ? plugins(config.plugin, true) : undefined;
134
- if (native && legacy) {
135
- if (JSON.stringify(native) !== JSON.stringify(legacy))
136
- throw new JsoncError("conflict", "Conflicting plugin and plugins sections; migrate explicitly before config setup");
137
- edits.push({ kind: "remove-key", path: ["plugin"] });
138
- }
139
- else if (legacy)
140
- edits.push({ kind: "rename-key", path: ["plugin"], to: "plugins" });
141
- const normalized = [];
142
- let pinnedPresent = false;
143
- for (const entry of native ?? legacy ?? []) {
144
- if (!ourEntry(entry)) {
145
- normalized.push(entry);
146
- continue;
147
- }
148
- if (pinnedPresent)
149
- continue;
150
- normalized.push(object(entry) ? { ...entry, package: pinned } : pinned);
151
- pinnedPresent = true;
152
- }
153
- const entries = normalized;
154
- if (!pinnedPresent)
155
- entries.push(pinned);
156
- edits.push({ kind: "set-value", path: ["plugins"], value: entries });
157
- return edits;
158
- }
@@ -1,20 +0,0 @@
1
- import type { Plugin } from "@opencode/plugin";
2
- import type { Result } from "@opencode/plugin/promise/tool";
3
- export type ToolAfter = {
4
- tool: string;
5
- sessionID: string;
6
- input: unknown;
7
- } & ({
8
- status: "completed";
9
- result: Result;
10
- } | {
11
- status: "error";
12
- error: unknown;
13
- });
14
- export declare function toolInput(value: unknown): Record<string, unknown>;
15
- export declare function resultText(result: Result): string | undefined;
16
- export declare function replaceResultText(result: Result, text: string): Result;
17
- export declare function subscribeEvents(ctx: Plugin.Context, receive: (event: {
18
- type: string;
19
- data?: unknown;
20
- }) => Promise<void>): () => Promise<void>;
@@ -1,48 +0,0 @@
1
- export function toolInput(value) {
2
- return value && typeof value === "object" && !Array.isArray(value)
3
- ? value
4
- : {};
5
- }
6
- export function resultText(result) {
7
- if (typeof result.content === "string")
8
- return result.content;
9
- if (Array.isArray(result.content))
10
- return result.content
11
- .filter((part) => part.type === "text")
12
- .map((part) => part.text)
13
- .join("\n");
14
- return undefined;
15
- }
16
- export function replaceResultText(result, text) {
17
- if (!Array.isArray(result.content))
18
- return { ...result, content: text };
19
- let replaced = false;
20
- return {
21
- ...result,
22
- content: result.content.flatMap((part) => {
23
- if (part.type !== "text")
24
- return [part];
25
- if (replaced)
26
- return [];
27
- replaced = true;
28
- return [{ type: "text", text }];
29
- }),
30
- };
31
- }
32
- export function subscribeEvents(ctx, receive) {
33
- const controller = new AbortController();
34
- const subscription = (async () => {
35
- try {
36
- for await (const event of ctx.event.subscribe({ signal: controller.signal }))
37
- await receive(event);
38
- }
39
- catch (error) {
40
- if (!controller.signal.aborted)
41
- console.error("agentomatic event subscription failed", error);
42
- }
43
- })();
44
- return async () => {
45
- controller.abort();
46
- await subscription;
47
- };
48
- }