@markjaquith/agency 2.47.0 → 2.47.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.
package/README.md CHANGED
@@ -54,7 +54,7 @@ workbase/
54
54
  opencode.jsonc # managed @agency subagent, instructions, and reference
55
55
  tui.jsonc # managed TUI plugin registration
56
56
  command/agency.md # managed /agency workflow command
57
- plugin/agency-repository-skills.ts # managed checkout skill discovery
57
+ plugin/agency-repository-skills.ts # managed workbase access and checkout skills
58
58
  tui/agency-debug.ts # managed /agency-debug TUI diagnostic
59
59
  agency.json # tracked config and portable repository declarations
60
60
  repos/ # ignored local materializations
@@ -111,9 +111,10 @@ whether the server plugin registered writable-checkout skills. It uses a native
111
111
  toast and does not submit a prompt to an LLM. When no writable checkout skill
112
112
  directory is available, server initialization is reported as indeterminate
113
113
  rather than inferred from plugin discovery.
114
- OpenCode discovers the config from task and epic launch directories. Agents
115
- receive whole-workbase visibility from that reference. Bash and Agency operations
116
- must still follow the write authority reported by `agency context`.
114
+ OpenCode discovers the config and plugin from task and epic launch directories.
115
+ The plugin grants whole-workbase access dynamically, while the portable
116
+ reference advertises that context to agents. Bash and Agency operations must
117
+ still follow the write authority reported by `agency context`.
117
118
 
118
119
  OpenCode also discovers a managed `/agency` command. Use `/agency status` for a
119
120
  read-only current-work summary, `/agency start [target]` to begin or resume work
@@ -252,8 +253,9 @@ authoritative writable checkout path.
252
253
  `AGENCY_PROMPT` is empty unless `--auto` is set.
253
254
  The `opencode` runner remains rooted in its task or epic working directory so
254
255
  the workbase `AGENTS.md` and managed OpenCode config are discovered normally.
255
- Agency's managed OpenCode plugin adds existing checkout-local `.claude/skills`,
256
- `.agents/skills`, and `.opencode/{skill,skills}` directories to `skills.paths`.
256
+ Agency's managed OpenCode plugin grants the active workbase external-directory
257
+ access and adds existing checkout-local `.claude/skills`, `.agents/skills`, and
258
+ `.opencode/{skill,skills}` directories to `skills.paths`.
257
259
  `agency work` supplies the checkout directly; plain OpenCode launches resolve a
258
260
  materialized execution-unit checkout through `agency context`. A multi-phase
259
261
  task root has no single checkout, so launch from its phase directory when using
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "2.47.0",
3
+ "version": "2.47.2",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -92,9 +92,8 @@ checks readiness, materializes worktrees, marks this execution unit working
92
92
  without a claim, and launches the runner. Run it again to relaunch unclaimed
93
93
  working work. The runner opens without a prompt by default; add `--auto` only
94
94
  when the generated context prompt should start autonomous execution.
95
- OpenCode receives whole-workbase read visibility through runtime-only config and
96
- permission values; this does not expand the writable checkout reported by
97
- `agency context`.
95
+ OpenCode receives whole-workbase visibility through the managed project plugin;
96
+ this does not expand the writable checkout reported by `agency context`.
98
97
 
99
98
  ## Active Agent: Execute Assigned Work
100
99
 
package/src/cli.test.ts CHANGED
@@ -1059,13 +1059,7 @@ status: open
1059
1059
  expect(contract.environment.AGENCY_WRITABLE_CHECKOUT).toBe(
1060
1060
  launch.checkoutPath,
1061
1061
  )
1062
- expect(
1063
- JSON.parse(contract.environment.OPENCODE_CONFIG_CONTENT),
1064
- ).toEqual({
1065
- permission: {
1066
- external_directory: { [join(workbaseRoot, "*")]: "allow" },
1067
- },
1068
- })
1062
+ expect(contract.environment.OPENCODE_CONFIG_CONTENT).toBeUndefined()
1069
1063
  const environment = {
1070
1064
  ...process.env,
1071
1065
  ...contract.environment,
@@ -1093,6 +1087,9 @@ status: open
1093
1087
  })
1094
1088
  expect(configProbe.exitCode).toBe(0)
1095
1089
  const effectiveConfig = JSON.parse(configProbe.stdout.toString())
1090
+ expect(effectiveConfig.permission.external_directory).toMatchObject({
1091
+ [join(workbaseRoot, "*")]: "allow",
1092
+ })
1096
1093
  expect(effectiveConfig.plugin_origins).toEqual(
1097
1094
  expect.arrayContaining([
1098
1095
  expect.objectContaining({
@@ -1218,9 +1215,11 @@ status: open
1218
1215
  env: directEnvironment,
1219
1216
  })
1220
1217
  expect(configProbe.exitCode).toBe(0)
1221
- expect(
1222
- JSON.parse(configProbe.stdout.toString()).plugin_origins,
1223
- ).toEqual(
1218
+ const effectiveConfig = JSON.parse(configProbe.stdout.toString())
1219
+ expect(effectiveConfig.permission.external_directory).toMatchObject({
1220
+ [join(workbaseRoot, "*")]: "allow",
1221
+ })
1222
+ expect(effectiveConfig.plugin_origins).toEqual(
1224
1223
  expect.arrayContaining([
1225
1224
  expect.objectContaining({
1226
1225
  spec: expect.stringContaining("agency-repository-skills.ts"),
@@ -1247,6 +1246,31 @@ status: open
1247
1246
  )
1248
1247
  }
1249
1248
  }
1249
+ const denied = Bun.spawnSync(["opencode", "debug", "agent", "build"], {
1250
+ cwd: directDirectories[0],
1251
+ env: {
1252
+ ...directEnvironment,
1253
+ OPENCODE_CONFIG_CONTENT: JSON.stringify({
1254
+ permission: { external_directory: { "*": "deny" } },
1255
+ }),
1256
+ },
1257
+ })
1258
+ expect(denied.exitCode).toBe(0)
1259
+ const deniedRules = JSON.parse(denied.stdout.toString()).permission
1260
+ const managedRule = deniedRules.findIndex(
1261
+ (rule: any) =>
1262
+ rule.permission === "external_directory" &&
1263
+ rule.pattern === join(workbaseRoot, "*") &&
1264
+ rule.action === "allow",
1265
+ )
1266
+ const userRule = deniedRules.findLastIndex(
1267
+ (rule: any) =>
1268
+ rule.permission === "external_directory" &&
1269
+ rule.pattern === "*" &&
1270
+ rule.action === "deny",
1271
+ )
1272
+ expect(managedRule).toBeGreaterThanOrEqual(0)
1273
+ expect(userRule).toBeGreaterThan(managedRule)
1250
1274
  for (const cwd of [
1251
1275
  join(workbaseRoot, "tasks/example"),
1252
1276
  join(workbaseRoot, "tasks/pipeline/phases/build"),
@@ -1325,7 +1349,7 @@ status: open
1325
1349
  graph.nodes.find((node: any) => node.id === "task:pipeline").status,
1326
1350
  ).toBe("working")
1327
1351
  },
1328
- 90_000,
1352
+ 180_000,
1329
1353
  )
1330
1354
 
1331
1355
  test("envelopes help and version output in machine mode", async () => {
@@ -96,10 +96,10 @@ OpenCode /agency command: missing
96
96
  The managed OpenCode /agency command needs synchronization.
97
97
  Action: Run 'agency integration sync' to install the managed /agency command.
98
98
 
99
- OpenCode checkout skills: missing
99
+ OpenCode workbase plugin: missing
100
100
  Path: .opencode/plugin/agency-repository-skills.ts
101
- The managed OpenCode checkout-skill plugin needs synchronization.
102
- Action: Run 'agency integration sync' to expose writable-checkout skills in OpenCode.
101
+ The managed OpenCode workbase plugin needs synchronization.
102
+ Action: Run 'agency integration sync' to provide workbase access and expose writable-checkout skills in OpenCode.
103
103
 
104
104
  OpenCode TUI config: missing
105
105
  Path: .opencode/tui.jsonc
@@ -165,9 +165,9 @@ OpenCode /agency command: synced
165
165
  Path: .opencode/command/agency.md
166
166
  Agency's managed OpenCode /agency command is current.
167
167
 
168
- OpenCode checkout skills: synced
168
+ OpenCode workbase plugin: synced
169
169
  Path: .opencode/plugin/agency-repository-skills.ts
170
- Agency's managed OpenCode plugin exposes writable-checkout skills to work-item sessions.
170
+ Agency's managed OpenCode plugin provides whole-workbase access and exposes writable-checkout skills.
171
171
 
172
172
  OpenCode TUI config: synced
173
173
  Path: .opencode/tui.jsonc
@@ -31,7 +31,7 @@ const integrationNames = {
31
31
  agents: "Agent instructions",
32
32
  opencode: "OpenCode config",
33
33
  "opencode-command": "OpenCode /agency command",
34
- "opencode-plugin": "OpenCode checkout skills",
34
+ "opencode-plugin": "OpenCode workbase plugin",
35
35
  "opencode-tui": "OpenCode TUI config",
36
36
  "opencode-tui-plugin": "OpenCode /agency-debug",
37
37
  } as const
@@ -91,9 +91,10 @@ export const help = `
91
91
  Usage: agency integration <subcommand>
92
92
 
93
93
  Inspect or explicitly synchronize managed agent integration files. OpenCode
94
- launches load the managed instructions and project config at runtime, and expose
95
- the managed /agency command, writable-checkout skills, and /agency-debug TUI
96
- diagnostic, without changing Agency write authority.
94
+ launches load the managed instructions and project config at runtime. The
95
+ managed plugin provides whole-workbase access and writable-checkout skills, and
96
+ the /agency-debug TUI diagnostic reports integration state without changing
97
+ Agency write authority.
97
98
 
98
99
  Subcommands:
99
100
  status Report file state, access diagnostics, and safe remediation
@@ -45,10 +45,6 @@ const multiPhaseWorkspace: ExecutionWorkspace = {
45
45
  }
46
46
 
47
47
  const taskDirectory = "/workbase/tasks/example"
48
- const workbasePermission = JSON.stringify({
49
- permission: { external_directory: { "/workbase/*": "allow" } },
50
- })
51
-
52
48
  interface HarnessOptions {
53
49
  readonly workspace?: ExecutionWorkspace
54
50
  readonly materializeError?: Error
@@ -74,7 +70,6 @@ interface HarnessOptions {
74
70
  readonly guardError?: Error
75
71
  readonly launchError?: Error
76
72
  readonly workTargetIds?: readonly string[]
77
- readonly opencodeIntegrationState?: "managed" | "customized"
78
73
  readonly taskStatus?: "open" | "working" | "delegated" | "done" | "dropped"
79
74
  readonly phaseStatus?: "open" | "working" | "delegated" | "done" | "dropped"
80
75
  readonly taskStatuses?: Readonly<
@@ -237,7 +232,7 @@ const createHarness = (options: HarnessOptions = {}) => {
237
232
  files: [
238
233
  {
239
234
  name: "opencode",
240
- state: options.opencodeIntegrationState ?? "managed",
235
+ state: "managed",
241
236
  },
242
237
  ],
243
238
  })
@@ -490,9 +485,9 @@ describe("work command", () => {
490
485
  cwd: "/workbase/epics/delivery",
491
486
  })
492
487
  expect(harness.launchEnvironments[0]?.OPENCODE_CONFIG).toBeUndefined()
493
- expect(harness.launchEnvironments[0]?.OPENCODE_CONFIG_CONTENT).toBe(
494
- workbasePermission,
495
- )
488
+ expect(
489
+ harness.launchEnvironments[0]?.OPENCODE_CONFIG_CONTENT,
490
+ ).toBeUndefined()
496
491
  })
497
492
 
498
493
  test("resolves an existing positional path before treating it as a task ID", async () => {
@@ -918,7 +913,7 @@ describe("work command", () => {
918
913
  expect(harness.taskStatuses.example).toBe("done")
919
914
  })
920
915
 
921
- test("grants managed OpenCode launches absolute workbase access", async () => {
916
+ test("leaves managed OpenCode access to the project plugin", async () => {
922
917
  const harness = createHarness()
923
918
  const output = await captureLogs(() =>
924
919
  harness.run({ taskId: "example", opencode: true, printCommand: true }),
@@ -926,7 +921,7 @@ describe("work command", () => {
926
921
  const printed = JSON.parse(output.join("\n"))
927
922
 
928
923
  expect(printed.environment.OPENCODE_CONFIG).toBeUndefined()
929
- expect(printed.environment.OPENCODE_CONFIG_CONTENT).toBe(workbasePermission)
924
+ expect(printed.environment.OPENCODE_CONFIG_CONTENT).toBeUndefined()
930
925
  })
931
926
 
932
927
  test("provides the writable checkout to plugins without changing the project", async () => {
@@ -941,16 +936,6 @@ describe("work command", () => {
941
936
  expect(harness.launchEnvironments[0]?.AGENCY_WRITABLE_CHECKOUT).toBe(
942
937
  "/workbase/tasks/example/code/agency",
943
938
  )
944
- expect(harness.launchEnvironments[0]?.OPENCODE_CONFIG_CONTENT).toBe(
945
- workbasePermission,
946
- )
947
- })
948
-
949
- test("does not override customized OpenCode access policy", async () => {
950
- const harness = createHarness({ opencodeIntegrationState: "customized" })
951
- await harness.run({ taskId: "example", opencode: true })
952
-
953
- expect(harness.launchEnvironments[0]?.OPENCODE_CONFIG).toBeUndefined()
954
939
  expect(
955
940
  harness.launchEnvironments[0]?.OPENCODE_CONFIG_CONTENT,
956
941
  ).toBeUndefined()
@@ -1,5 +1,5 @@
1
1
  import { Effect } from "effect"
2
- import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path"
2
+ import { dirname, isAbsolute, relative, resolve, sep } from "node:path"
3
3
  import type { BaseCommandOptions } from "../utils/command"
4
4
  import { WorktreeService } from "../services/WorktreeService"
5
5
  import { FileSystemService } from "../services/FileSystemService"
@@ -122,10 +122,7 @@ export const work = (
122
122
  const inputAllowed = options.inputAllowed ?? true
123
123
  const root = yield* resolveWorkbase(startPath, pickBase, inputAllowed)
124
124
  if (!root) return
125
- const integration = yield* integrations.sync(root)
126
- const managedOpencode = integration.files.some(
127
- (file) => file.name === "opencode" && file.state === "managed",
128
- )
125
+ yield* integrations.sync(root)
129
126
  const { config } = yield* workbase.loadConfig(root)
130
127
 
131
128
  let target: WorkTarget | null = null
@@ -337,13 +334,6 @@ export const work = (
337
334
  ...runnerEnvironment(runner, variables),
338
335
  }
339
336
  if (writablePath) environment.AGENCY_WRITABLE_CHECKOUT = writablePath
340
- if (runner === "opencode" && managedOpencode) {
341
- environment.OPENCODE_CONFIG_CONTENT = JSON.stringify({
342
- permission: {
343
- external_directory: { [join(root, "*")]: "allow" },
344
- },
345
- })
346
- }
347
337
  if (options.printCommand) {
348
338
  log(
349
339
  JSON.stringify(
@@ -490,8 +480,8 @@ Usage: agency work [<directory-or-task-id> | --epic <epic-id>] [--runner <name>]
490
480
  Launch an agent for an epic, task, or phase. With no directory, select one
491
481
  interactively. A positional argument resolves as a directory first, then as a task
492
482
  ID. Use '.' for the current directory. Outside a workbase, select a registered
493
- workbase first. OpenCode launches receive whole-workbase read access through the
494
- runtime environment; Agency context remains authoritative for writes.
483
+ workbase first. Managed OpenCode launches receive whole-workbase access through
484
+ Agency's project plugin; Agency context remains authoritative for writes.
495
485
 
496
486
  The prepare subcommand resolves and materializes an execution workspace without
497
487
  launching an agent or changing lifecycle status. --dry-run reports planned Git
@@ -113,7 +113,7 @@ describe("IntegrationService", () => {
113
113
  ])
114
114
  })
115
115
 
116
- test("generates a dynamic repository skill plugin", () => {
116
+ test("generates a dynamic workbase plugin", () => {
117
117
  expect(managedWorkbaseOpencodePlugin).toContain(
118
118
  "process.env.AGENCY_WRITABLE_CHECKOUT",
119
119
  )
@@ -129,6 +129,9 @@ describe("IntegrationService", () => {
129
129
  expect(managedWorkbaseOpencodePlugin).toContain(
130
130
  'join(checkout, ".opencode", "skills")',
131
131
  )
132
+ expect(managedWorkbaseOpencodePlugin).toContain(
133
+ 'config.permission.external_directory = { [join(root, "*")]: "allow" }',
134
+ )
132
135
  expect(managedWorkbaseOpencodePlugin).toContain(
133
136
  "config.skills.paths = [...new Set",
134
137
  )
@@ -161,7 +164,14 @@ describe("IntegrationService", () => {
161
164
  const module = await import(pathToFileURL(path).href)
162
165
  let clientReads = 0
163
166
 
164
- const runDiagnostic = async (paths: string[], ready = true) => {
167
+ const runDiagnostic = async (
168
+ paths: string[],
169
+ options: {
170
+ ready?: boolean
171
+ managedReference?: boolean
172
+ externalDirectory?: Record<string, string>
173
+ } = {},
174
+ ) => {
165
175
  let command:
166
176
  | {
167
177
  slashName?: string
@@ -175,7 +185,25 @@ describe("IntegrationService", () => {
175
185
  clientReads += 1
176
186
  throw new Error("diagnostic must not access the server client")
177
187
  },
178
- state: { ready, config: { skills: { paths } } },
188
+ state: {
189
+ ready: options.ready ?? true,
190
+ config: {
191
+ skills: { paths },
192
+ references: options.managedReference
193
+ ? {
194
+ workbase: {
195
+ path: "..",
196
+ description:
197
+ "Complete Agency workbase context; write authority still comes only from agency context",
198
+ },
199
+ }
200
+ : undefined,
201
+ permission: options.externalDirectory
202
+ ? { external_directory: options.externalDirectory }
203
+ : undefined,
204
+ },
205
+ path: { directory: join(root, "tasks", "example") },
206
+ },
179
207
  keymap: {
180
208
  registerLayer: (layer: { commands: (typeof command)[] }) => {
181
209
  command = layer.commands[0]
@@ -199,6 +227,23 @@ describe("IntegrationService", () => {
199
227
  variant: "success",
200
228
  message: expect.stringContaining("Server plugin: initialized"),
201
229
  })
230
+ expect(
231
+ await runDiagnostic([], {
232
+ managedReference: true,
233
+ externalDirectory: { [join(root, "*")]: "allow" },
234
+ }),
235
+ ).toMatchObject({
236
+ variant: "success",
237
+ message: expect.stringContaining("workbase access registered"),
238
+ })
239
+ expect(
240
+ await runDiagnostic([], {
241
+ externalDirectory: { [join(root, "*")]: "allow" },
242
+ }),
243
+ ).toMatchObject({
244
+ variant: "warning",
245
+ message: expect.stringContaining("Server plugin: indeterminate"),
246
+ })
202
247
  expect(await runDiagnostic([])).toMatchObject({
203
248
  variant: "warning",
204
249
  message: expect.stringContaining("Server plugin: indeterminate"),
@@ -97,7 +97,7 @@ const describe = (
97
97
  return state === "managed"
98
98
  ? {
99
99
  diagnostic:
100
- "Agency's managed OpenCode plugin exposes writable-checkout skills to work-item sessions.",
100
+ "Agency's managed OpenCode plugin provides whole-workbase access and exposes writable-checkout skills.",
101
101
  remediation: null,
102
102
  }
103
103
  : state === "customized"
@@ -108,9 +108,9 @@ const describe = (
108
108
  }
109
109
  : {
110
110
  diagnostic:
111
- "The managed OpenCode checkout-skill plugin needs synchronization.",
111
+ "The managed OpenCode workbase plugin needs synchronization.",
112
112
  remediation:
113
- "Run 'agency integration sync' to expose writable-checkout skills in OpenCode.",
113
+ "Run 'agency integration sync' to provide workbase access and expose writable-checkout skills in OpenCode.",
114
114
  }
115
115
  }
116
116
  if (name === "opencode-tui") {
@@ -10,7 +10,7 @@ const body = `import { existsSync } from "node:fs"
10
10
  import { join, sep } from "node:path"
11
11
  import type { Plugin } from "@opencode-ai/plugin"
12
12
 
13
- const contextCheckout = async (directory: string) => {
13
+ const agencyContext = async (directory: string) => {
14
14
  const task = process.env.AGENCY_TASK_ID
15
15
  const phase = process.env.AGENCY_PHASE_ID
16
16
  const args = task
@@ -21,14 +21,39 @@ const contextCheckout = async (directory: string) => {
21
21
  if ((await child.exited) !== 0) return
22
22
  const envelope = JSON.parse(output)
23
23
  if (envelope.ok !== true) return
24
- return envelope.result?.authority?.writable?.checkoutPath as string | undefined
24
+ return {
25
+ root: envelope.result?.workbase?.root as string | undefined,
26
+ checkout: envelope.result?.authority?.writable?.checkoutPath as string | undefined,
27
+ }
25
28
  }
26
29
 
27
30
  const plugin: Plugin = async ({ directory }) => ({
28
31
  config: async (config) => {
29
- const checkout =
30
- process.env.AGENCY_WRITABLE_CHECKOUT ??
31
- (await contextCheckout(directory).catch(() => undefined))
32
+ const context = await agencyContext(directory).catch(() => undefined)
33
+ const root = process.env.AGENCY_WORKBASE ?? context?.root
34
+ const checkout = process.env.AGENCY_WRITABLE_CHECKOUT ?? context?.checkout
35
+
36
+ const reference = config.references?.workbase
37
+ if (
38
+ root &&
39
+ typeof reference === "object" &&
40
+ reference.path === ".." &&
41
+ reference.description ===
42
+ "Complete Agency workbase context; write authority still comes only from agency context" &&
43
+ typeof config.permission !== "string"
44
+ ) {
45
+ config.permission ??= {}
46
+ const external = config.permission.external_directory
47
+ if (external === undefined) {
48
+ config.permission.external_directory = { [join(root, "*")]: "allow" }
49
+ } else if (typeof external === "object") {
50
+ config.permission.external_directory = {
51
+ [join(root, "*")]: "allow",
52
+ ...external,
53
+ }
54
+ }
55
+ }
56
+
32
57
  if (!checkout) return
33
58
 
34
59
  const paths = [
@@ -6,10 +6,22 @@ const managedHeaderPattern =
6
6
  const checksum = (content: string) =>
7
7
  createHash("sha256").update(content).digest("hex")
8
8
 
9
- const body = `import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui"
9
+ const body = `import { existsSync } from "node:fs"
10
+ import { dirname, join } from "node:path"
11
+ import type { TuiPlugin, TuiPluginModule } from "@opencode-ai/plugin/tui"
10
12
 
11
13
  const serverMarker = /[\\\\/]\\.$/
12
14
 
15
+ const findWorkbase = (start: string) => {
16
+ let directory = start
17
+ while (true) {
18
+ if (existsSync(join(directory, "agency.json"))) return directory
19
+ const parent = dirname(directory)
20
+ if (parent === directory) return
21
+ directory = parent
22
+ }
23
+ }
24
+
13
25
  const tui: TuiPlugin = async (api) => {
14
26
  api.keymap.registerLayer({
15
27
  commands: [
@@ -21,14 +33,35 @@ const tui: TuiPlugin = async (api) => {
21
33
  namespace: "palette",
22
34
  slashName: "agency-debug",
23
35
  run() {
24
- const paths = api.state.config.skills?.paths
25
- const serverInitialized = paths?.some(
36
+ const config = api.state.config
37
+ const checkoutSkillsRegistered = config.skills?.paths?.some(
26
38
  (path) => typeof path === "string" && serverMarker.test(path),
27
39
  )
40
+ const reference = config.references?.workbase
41
+ const managedReference =
42
+ typeof reference === "object" &&
43
+ reference.path === ".." &&
44
+ reference.description ===
45
+ "Complete Agency workbase context; write authority still comes only from agency context"
46
+ const workbase = managedReference
47
+ ? findWorkbase(api.state.path.directory)
48
+ : undefined
49
+ const external =
50
+ typeof config.permission === "object"
51
+ ? config.permission.external_directory
52
+ : undefined
53
+ const workbaseAccessRegistered =
54
+ workbase !== undefined &&
55
+ typeof external === "object" &&
56
+ external[join(workbase, "*")] === "allow"
57
+ const serverInitialized =
58
+ checkoutSkillsRegistered || workbaseAccessRegistered
28
59
  const message = serverInitialized
29
- ? "TUI companion: initialized. Server plugin: initialized; checkout skills registered."
60
+ ? checkoutSkillsRegistered
61
+ ? "TUI companion: initialized. Server plugin: initialized; checkout skills registered."
62
+ : "TUI companion: initialized. Server plugin: initialized; workbase access registered."
30
63
  : api.state.ready
31
- ? "TUI companion: initialized. Server plugin: indeterminate; no checkout skill marker is present."
64
+ ? "TUI companion: initialized. Server plugin: indeterminate; no Agency config marker is present."
32
65
  : "TUI companion: initialized. Server plugin: indeterminate; server state is not ready."
33
66
 
34
67
  api.ui.toast({