akm-opencode 0.4.1 → 0.4.3
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/index.ts +148 -59
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -92,6 +92,14 @@ type CliLogMeta = {
|
|
|
92
92
|
sessionID?: string
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
type SessionPromptBody = {
|
|
96
|
+
agent: string
|
|
97
|
+
parts: Array<{ type: "text"; text: string }>
|
|
98
|
+
system?: string
|
|
99
|
+
model?: { providerID: string; modelID: string }
|
|
100
|
+
tools?: Record<string, boolean>
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
function formatCliError(error: unknown): string {
|
|
96
104
|
if (error && typeof error === "object" && "code" in error && (error as { code?: unknown }).code === "ENOENT") {
|
|
97
105
|
return "The 'akm' CLI was not found on PATH. Install it first from https://github.com/itlackey/akm."
|
|
@@ -729,18 +737,111 @@ async function ensureTargetSessionID(input: {
|
|
|
729
737
|
context: { sessionID: string; directory: string }
|
|
730
738
|
title: string
|
|
731
739
|
client: PluginClient
|
|
740
|
+
logClient: LogCapableClient
|
|
741
|
+
toolName: string
|
|
732
742
|
}): Promise<{ ok: true; sessionID: string } | CliError> {
|
|
733
743
|
if (!input.useSubtask) return { ok: true, sessionID: input.context.sessionID }
|
|
734
744
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
745
|
+
try {
|
|
746
|
+
const created = await input.client.session.create({
|
|
747
|
+
body: { parentID: input.context.sessionID, title: input.title },
|
|
748
|
+
})
|
|
749
|
+
if (created.error || !created.data?.id) {
|
|
750
|
+
const reason = created.error ? JSON.stringify(created.error) : "missing child session id"
|
|
751
|
+
await writePluginLog(input.logClient, "error", "AKM dispatch child session failed", {
|
|
752
|
+
subsystem: "dispatch",
|
|
753
|
+
toolName: input.toolName,
|
|
754
|
+
sessionID: input.context.sessionID,
|
|
755
|
+
directory: input.context.directory,
|
|
756
|
+
title: input.title,
|
|
757
|
+
error: reason,
|
|
758
|
+
})
|
|
759
|
+
return { ok: false, error: `Failed to create child session: ${reason}` }
|
|
760
|
+
}
|
|
761
|
+
await writePluginLog(input.logClient, "info", "AKM dispatch child session created", {
|
|
762
|
+
subsystem: "dispatch",
|
|
763
|
+
toolName: input.toolName,
|
|
764
|
+
sessionID: input.context.sessionID,
|
|
765
|
+
directory: input.context.directory,
|
|
766
|
+
childSessionID: created.data.id,
|
|
767
|
+
title: input.title,
|
|
768
|
+
})
|
|
769
|
+
return { ok: true, sessionID: created.data.id }
|
|
770
|
+
} catch (error: unknown) {
|
|
771
|
+
const reason = error instanceof Error ? error.message : String(error)
|
|
772
|
+
await writePluginLog(input.logClient, "error", "AKM dispatch child session threw", {
|
|
773
|
+
subsystem: "dispatch",
|
|
774
|
+
toolName: input.toolName,
|
|
775
|
+
sessionID: input.context.sessionID,
|
|
776
|
+
directory: input.context.directory,
|
|
777
|
+
title: input.title,
|
|
778
|
+
error: reason,
|
|
779
|
+
})
|
|
741
780
|
return { ok: false, error: `Failed to create child session: ${reason}` }
|
|
742
781
|
}
|
|
743
|
-
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
async function promptTargetSession(input: {
|
|
785
|
+
client: PluginClient
|
|
786
|
+
logClient: LogCapableClient
|
|
787
|
+
toolName: string
|
|
788
|
+
context: { sessionID: string; directory: string }
|
|
789
|
+
targetSessionID: string
|
|
790
|
+
promptBody: SessionPromptBody
|
|
791
|
+
failureMessage: string
|
|
792
|
+
ref?: string
|
|
793
|
+
}): Promise<{ ok: true; data: { parts?: unknown } } | CliError> {
|
|
794
|
+
try {
|
|
795
|
+
const promptResponse = await input.client.session.prompt({
|
|
796
|
+
path: { id: input.targetSessionID },
|
|
797
|
+
body: input.promptBody,
|
|
798
|
+
})
|
|
799
|
+
|
|
800
|
+
if (promptResponse.error || !promptResponse.data) {
|
|
801
|
+
const reason = promptResponse.error ? JSON.stringify(promptResponse.error) : "empty response"
|
|
802
|
+
await writePluginLog(input.logClient, "error", "AKM dispatch prompt failed", {
|
|
803
|
+
subsystem: "dispatch",
|
|
804
|
+
toolName: input.toolName,
|
|
805
|
+
sessionID: input.context.sessionID,
|
|
806
|
+
directory: input.context.directory,
|
|
807
|
+
targetSessionID: input.targetSessionID,
|
|
808
|
+
dispatchAgent: input.promptBody.agent,
|
|
809
|
+
ref: input.ref,
|
|
810
|
+
error: reason,
|
|
811
|
+
})
|
|
812
|
+
return {
|
|
813
|
+
ok: false,
|
|
814
|
+
error: `${input.failureMessage}: ${reason}`,
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
await writePluginLog(input.logClient, "info", "AKM dispatch prompt completed", {
|
|
819
|
+
subsystem: "dispatch",
|
|
820
|
+
toolName: input.toolName,
|
|
821
|
+
sessionID: input.context.sessionID,
|
|
822
|
+
directory: input.context.directory,
|
|
823
|
+
targetSessionID: input.targetSessionID,
|
|
824
|
+
dispatchAgent: input.promptBody.agent,
|
|
825
|
+
ref: input.ref,
|
|
826
|
+
})
|
|
827
|
+
return { ok: true, data: promptResponse.data }
|
|
828
|
+
} catch (error: unknown) {
|
|
829
|
+
const reason = error instanceof Error ? error.message : String(error)
|
|
830
|
+
await writePluginLog(input.logClient, "error", "AKM dispatch prompt threw", {
|
|
831
|
+
subsystem: "dispatch",
|
|
832
|
+
toolName: input.toolName,
|
|
833
|
+
sessionID: input.context.sessionID,
|
|
834
|
+
directory: input.context.directory,
|
|
835
|
+
targetSessionID: input.targetSessionID,
|
|
836
|
+
dispatchAgent: input.promptBody.agent,
|
|
837
|
+
ref: input.ref,
|
|
838
|
+
error: reason,
|
|
839
|
+
})
|
|
840
|
+
return {
|
|
841
|
+
ok: false,
|
|
842
|
+
error: `${input.failureMessage}: ${reason}`,
|
|
843
|
+
}
|
|
844
|
+
}
|
|
744
845
|
}
|
|
745
846
|
|
|
746
847
|
function splitArguments(raw: string): string[] {
|
|
@@ -787,19 +888,11 @@ function createSearchArgs(input: {
|
|
|
787
888
|
type PluginClient = {
|
|
788
889
|
session: {
|
|
789
890
|
create: (input: {
|
|
790
|
-
query: { directory: string }
|
|
791
891
|
body: { parentID: string; title: string }
|
|
792
892
|
}) => Promise<{ data?: { id?: string }; error?: unknown }>
|
|
793
893
|
prompt: (input: {
|
|
794
|
-
query: { directory: string }
|
|
795
894
|
path: { id: string }
|
|
796
|
-
body:
|
|
797
|
-
agent: string
|
|
798
|
-
parts: Array<{ type: "text"; text: string }>
|
|
799
|
-
system?: string
|
|
800
|
-
model?: { providerID: string; modelID: string }
|
|
801
|
-
tools?: Record<string, boolean>
|
|
802
|
-
}
|
|
895
|
+
body: SessionPromptBody
|
|
803
896
|
}) => Promise<{ data?: { parts?: unknown }; error?: unknown }>
|
|
804
897
|
}
|
|
805
898
|
}
|
|
@@ -1203,6 +1296,8 @@ export const AkmPlugin: Plugin = async ({ client }) => {
|
|
|
1203
1296
|
context: { sessionID: context.sessionID, directory: context.directory },
|
|
1204
1297
|
title: "akm:curator",
|
|
1205
1298
|
client: client as unknown as PluginClient,
|
|
1299
|
+
logClient,
|
|
1300
|
+
toolName: "akm_evolve",
|
|
1206
1301
|
})
|
|
1207
1302
|
if (!targetSession.ok) return JSON.stringify(targetSession)
|
|
1208
1303
|
|
|
@@ -1210,23 +1305,20 @@ export const AkmPlugin: Plugin = async ({ client }) => {
|
|
|
1210
1305
|
? `Review recent AKM activity with an emphasis on: ${focus.trim()}. Produce the prioritized action list described in the system prompt.`
|
|
1211
1306
|
: "Review recent AKM activity and produce the prioritized action list described in the system prompt."
|
|
1212
1307
|
|
|
1213
|
-
const promptResponse = await
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1308
|
+
const promptResponse = await promptTargetSession({
|
|
1309
|
+
client: client as unknown as PluginClient,
|
|
1310
|
+
logClient,
|
|
1311
|
+
toolName: "akm_evolve",
|
|
1312
|
+
context: { sessionID: context.sessionID, directory: context.directory },
|
|
1313
|
+
targetSessionID: targetSession.sessionID,
|
|
1314
|
+
failureMessage: "Failed to dispatch curator",
|
|
1315
|
+
promptBody: {
|
|
1217
1316
|
agent: targetAgent,
|
|
1218
1317
|
system: CURATOR_AGENT_PROMPT,
|
|
1219
1318
|
parts: [{ type: "text", text: task }],
|
|
1220
1319
|
},
|
|
1221
1320
|
})
|
|
1222
|
-
|
|
1223
|
-
if (promptResponse.error || !promptResponse.data) {
|
|
1224
|
-
const reason = promptResponse.error ? JSON.stringify(promptResponse.error) : "empty response"
|
|
1225
|
-
return JSON.stringify({
|
|
1226
|
-
ok: false,
|
|
1227
|
-
error: `Failed to dispatch curator: ${reason}`,
|
|
1228
|
-
})
|
|
1229
|
-
}
|
|
1321
|
+
if (!promptResponse.ok) return JSON.stringify(promptResponse)
|
|
1230
1322
|
|
|
1231
1323
|
return JSON.stringify({
|
|
1232
1324
|
ok: true,
|
|
@@ -1286,16 +1378,12 @@ export const AkmPlugin: Plugin = async ({ client }) => {
|
|
|
1286
1378
|
context: { sessionID: context.sessionID, directory: context.directory },
|
|
1287
1379
|
title: `akm:${shown.name}`,
|
|
1288
1380
|
client: client as unknown as PluginClient,
|
|
1381
|
+
logClient,
|
|
1382
|
+
toolName: "akm_agent",
|
|
1289
1383
|
})
|
|
1290
1384
|
if (!targetSession.ok) return JSON.stringify(targetSession)
|
|
1291
1385
|
|
|
1292
|
-
const promptBody: {
|
|
1293
|
-
agent: string
|
|
1294
|
-
system: string
|
|
1295
|
-
parts: Array<{ type: "text"; text: string }>
|
|
1296
|
-
model?: { providerID: string; modelID: string }
|
|
1297
|
-
tools?: Record<string, boolean>
|
|
1298
|
-
} = {
|
|
1386
|
+
const promptBody: SessionPromptBody = {
|
|
1299
1387
|
agent: targetAgent,
|
|
1300
1388
|
system: shown.prompt,
|
|
1301
1389
|
parts: [{ type: "text", text: task_prompt }],
|
|
@@ -1303,19 +1391,17 @@ export const AkmPlugin: Plugin = async ({ client }) => {
|
|
|
1303
1391
|
if (model) promptBody.model = model
|
|
1304
1392
|
if (tools) promptBody.tools = tools
|
|
1305
1393
|
|
|
1306
|
-
const promptResponse = await
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1394
|
+
const promptResponse = await promptTargetSession({
|
|
1395
|
+
client: client as unknown as PluginClient,
|
|
1396
|
+
logClient,
|
|
1397
|
+
toolName: "akm_agent",
|
|
1398
|
+
context: { sessionID: context.sessionID, directory: context.directory },
|
|
1399
|
+
targetSessionID: targetSession.sessionID,
|
|
1400
|
+
promptBody,
|
|
1401
|
+
failureMessage: `Failed to dispatch prompt for ${resolved.ref}`,
|
|
1402
|
+
ref: resolved.ref,
|
|
1310
1403
|
})
|
|
1311
|
-
|
|
1312
|
-
if (promptResponse.error || !promptResponse.data) {
|
|
1313
|
-
const reason = promptResponse.error ? JSON.stringify(promptResponse.error) : "empty response"
|
|
1314
|
-
return JSON.stringify({
|
|
1315
|
-
ok: false,
|
|
1316
|
-
error: `Failed to dispatch prompt for ${resolved.ref}: ${reason}`,
|
|
1317
|
-
})
|
|
1318
|
-
}
|
|
1404
|
+
if (!promptResponse.ok) return JSON.stringify(promptResponse)
|
|
1319
1405
|
|
|
1320
1406
|
return JSON.stringify({
|
|
1321
1407
|
ok: true,
|
|
@@ -1370,25 +1456,25 @@ export const AkmPlugin: Plugin = async ({ client }) => {
|
|
|
1370
1456
|
context: { sessionID: context.sessionID, directory: context.directory },
|
|
1371
1457
|
title: `akm:cmd:${shown.name}`,
|
|
1372
1458
|
client: client as unknown as PluginClient,
|
|
1459
|
+
logClient,
|
|
1460
|
+
toolName: "akm_cmd",
|
|
1373
1461
|
})
|
|
1374
1462
|
if (!targetSession.ok) return JSON.stringify(targetSession)
|
|
1375
1463
|
|
|
1376
|
-
const promptResponse = await
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1464
|
+
const promptResponse = await promptTargetSession({
|
|
1465
|
+
client: client as unknown as PluginClient,
|
|
1466
|
+
logClient,
|
|
1467
|
+
toolName: "akm_cmd",
|
|
1468
|
+
context: { sessionID: context.sessionID, directory: context.directory },
|
|
1469
|
+
targetSessionID: targetSession.sessionID,
|
|
1470
|
+
failureMessage: `Failed to execute command ${resolved.ref}`,
|
|
1471
|
+
ref: resolved.ref,
|
|
1472
|
+
promptBody: {
|
|
1380
1473
|
agent: targetAgent,
|
|
1381
1474
|
parts: [{ type: "text", text: rendered }],
|
|
1382
1475
|
},
|
|
1383
1476
|
})
|
|
1384
|
-
|
|
1385
|
-
if (promptResponse.error || !promptResponse.data) {
|
|
1386
|
-
const reason = promptResponse.error ? JSON.stringify(promptResponse.error) : "empty response"
|
|
1387
|
-
return JSON.stringify({
|
|
1388
|
-
ok: false,
|
|
1389
|
-
error: `Failed to execute command ${resolved.ref}: ${reason}`,
|
|
1390
|
-
})
|
|
1391
|
-
}
|
|
1477
|
+
if (!promptResponse.ok) return JSON.stringify(promptResponse)
|
|
1392
1478
|
|
|
1393
1479
|
return JSON.stringify({
|
|
1394
1480
|
ok: true,
|
|
@@ -1497,3 +1583,6 @@ export const AkmPlugin: Plugin = async ({ client }) => {
|
|
|
1497
1583
|
},
|
|
1498
1584
|
}
|
|
1499
1585
|
}
|
|
1586
|
+
|
|
1587
|
+
export const server = AkmPlugin
|
|
1588
|
+
export default { server }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akm-opencode",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenCode plugin for AKM - search, show, and manage extension assets via the akm CLI, with agentic hooks that auto-load relevant stash assets, record feedback, and harvest session memories so the stash improves every session.",
|
|
6
6
|
"keywords": [
|