@obrain/cli 0.1.11 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/index.js +239 -28
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -71573,6 +71573,7 @@ class OpenCodeA2AAgent {
71573
71573
  path;
71574
71574
  port;
71575
71575
  client;
71576
+ runningTasks = new Map;
71576
71577
  server = null;
71577
71578
  constructor(path, port) {
71578
71579
  this.path = path;
@@ -71645,7 +71646,7 @@ class OpenCodeA2AAgent {
71645
71646
  version: "0.1.0",
71646
71647
  url: `${agentUrl}/a2a/jsonrpc`,
71647
71648
  skills: userSkills,
71648
- capabilities: { pushNotifications: false },
71649
+ capabilities: { pushNotifications: false, streaming: true },
71649
71650
  defaultInputModes: ["text"],
71650
71651
  defaultOutputModes: ["text"],
71651
71652
  additionalInterfaces: [
@@ -71658,36 +71659,228 @@ class OpenCodeA2AAgent {
71658
71659
  }
71659
71660
  async execute(requestContext, eventBus) {
71660
71661
  const userMessage = requestContext.userMessage;
71661
- const session = await this.client.session.create();
71662
- const callerContext = this.getCallerContext(requestContext);
71663
- const executionContextText = this.buildExecutionContextText(requestContext);
71664
- const promptParts = userMessage.parts.filter((p) => p.kind === "text").map((part) => ({
71665
- type: "text",
71666
- text: part.text
71667
- }));
71668
- if (executionContextText) {
71669
- promptParts.unshift({
71670
- type: "text",
71671
- text: executionContextText
71672
- });
71662
+ const task = requestContext.task ?? {
71663
+ kind: "task",
71664
+ id: requestContext.taskId,
71665
+ contextId: requestContext.contextId,
71666
+ status: {
71667
+ state: "submitted",
71668
+ timestamp: new Date().toISOString()
71669
+ },
71670
+ history: [userMessage],
71671
+ metadata: userMessage.metadata
71672
+ };
71673
+ if (!requestContext.task) {
71674
+ eventBus.publish(task);
71673
71675
  }
71674
- const result = await this.client.session.prompt({
71675
- ...callerContext.isOwnerCall ? {} : { agent: "plan" },
71676
- sessionID: session.data?.id,
71677
- parts: promptParts
71676
+ this.runningTasks.set(requestContext.taskId, {
71677
+ contextId: requestContext.contextId,
71678
+ canceled: false,
71679
+ finalized: false
71678
71680
  });
71679
- for (const part of result.data?.parts || []) {
71680
- if (part.type === "text") {
71681
- eventBus.publish({
71681
+ this.runTask(requestContext, eventBus);
71682
+ }
71683
+ async runTask(requestContext, eventBus) {
71684
+ const userMessage = requestContext.userMessage;
71685
+ const publishStatus = (state, options) => eventBus.publish({
71686
+ kind: "status-update",
71687
+ taskId: requestContext.taskId,
71688
+ contextId: requestContext.contextId,
71689
+ status: {
71690
+ state,
71691
+ ...options?.message ? { message: options.message } : {},
71692
+ timestamp: new Date().toISOString()
71693
+ },
71694
+ final: options?.final ?? false
71695
+ });
71696
+ const publishWorkingTask = () => publishStatus("working");
71697
+ const runningTask = () => this.runningTasks.get(requestContext.taskId);
71698
+ const isCanceled = () => runningTask()?.canceled === true;
71699
+ const publishArtifact = (artifactId, name, text, options) => eventBus.publish({
71700
+ kind: "artifact-update",
71701
+ taskId: requestContext.taskId,
71702
+ contextId: requestContext.contextId,
71703
+ artifact: {
71704
+ artifactId,
71705
+ name,
71706
+ parts: [{ kind: "text", text }]
71707
+ },
71708
+ append: options?.append,
71709
+ lastChunk: options?.lastChunk
71710
+ });
71711
+ const stringifyEvent = (event) => {
71712
+ try {
71713
+ return JSON.stringify(event, (_key, value) => typeof value === "bigint" ? value.toString() : value);
71714
+ } catch (error51) {
71715
+ logger.warn({ error: error51 }, "Failed to serialize OpenCode event");
71716
+ return JSON.stringify({ type: "unserializable-event" });
71717
+ }
71718
+ };
71719
+ try {
71720
+ if (isCanceled()) {
71721
+ return;
71722
+ }
71723
+ publishWorkingTask();
71724
+ const session = await this.client.session.create();
71725
+ const taskState = runningTask();
71726
+ if (taskState) {
71727
+ taskState.sessionId = session.data?.id;
71728
+ }
71729
+ if (isCanceled()) {
71730
+ if (session.data?.id) {
71731
+ await this.client.session.abort({ sessionID: session.data.id });
71732
+ }
71733
+ return;
71734
+ }
71735
+ const callerContext = this.getCallerContext(requestContext);
71736
+ const executionContextText = this.buildExecutionContextText(requestContext);
71737
+ const promptParts = userMessage.parts.filter((p) => p.kind === "text").map((part) => ({
71738
+ type: "text",
71739
+ text: part.text
71740
+ }));
71741
+ if (executionContextText) {
71742
+ promptParts.unshift({
71743
+ type: "text",
71744
+ text: executionContextText
71745
+ });
71746
+ }
71747
+ const events = await this.client.event.subscribe();
71748
+ await this.client.session.promptAsync({
71749
+ ...callerContext.isOwnerCall ? {} : { agent: "plan" },
71750
+ sessionID: session.data?.id,
71751
+ parts: promptParts
71752
+ });
71753
+ let assistantMessageID;
71754
+ for await (const event of events.stream) {
71755
+ if (isCanceled()) {
71756
+ return;
71757
+ }
71758
+ if (event.type === "message.part.delta") {
71759
+ continue;
71760
+ }
71761
+ publishArtifact("opencode-events", "OpenCode events", `${stringifyEvent(event)}
71762
+ `, { append: true });
71763
+ publishWorkingTask();
71764
+ if (event.type === "message.updated" && event.properties.info.sessionID === session.data?.id && event.properties.info.role === "assistant") {
71765
+ assistantMessageID = event.properties.info.id;
71766
+ }
71767
+ if (event.type === "session.status" && event.properties.sessionID === session.data?.id && event.properties.status.type === "idle") {
71768
+ break;
71769
+ }
71770
+ }
71771
+ if (isCanceled()) {
71772
+ return;
71773
+ }
71774
+ let responseMessage = null;
71775
+ if (assistantMessageID) {
71776
+ const result = await this.client.session.message({
71777
+ sessionID: session.data?.id,
71778
+ messageID: assistantMessageID
71779
+ });
71780
+ responseMessage = {
71682
71781
  kind: "message",
71683
71782
  messageId: v4_default(),
71684
71783
  role: "agent",
71685
- parts: [{ kind: "text", text: part.text }]
71686
- });
71784
+ contextId: requestContext.contextId,
71785
+ taskId: requestContext.taskId,
71786
+ parts: result.data?.parts?.filter((part) => part.type === "text").map((part) => ({
71787
+ kind: part.type,
71788
+ text: part.text
71789
+ })) || []
71790
+ };
71791
+ } else {
71792
+ responseMessage = {
71793
+ kind: "message",
71794
+ messageId: v4_default(),
71795
+ role: "agent",
71796
+ contextId: requestContext.contextId,
71797
+ taskId: requestContext.taskId,
71798
+ parts: []
71799
+ };
71800
+ }
71801
+ if (responseMessage.parts.length > 0) {
71802
+ publishArtifact("opencode-response", "OpenCode response", responseMessage.parts.filter((part) => part.kind === "text").map((part) => part.text).join(`
71803
+ `), { lastChunk: true });
71804
+ }
71805
+ publishStatus("completed", {
71806
+ message: responseMessage,
71807
+ final: true
71808
+ });
71809
+ const completedTaskState = runningTask();
71810
+ if (completedTaskState) {
71811
+ completedTaskState.finalized = true;
71812
+ }
71813
+ eventBus.finished();
71814
+ } catch (error51) {
71815
+ if (isCanceled()) {
71816
+ return;
71817
+ }
71818
+ logger.error({ error: error51 }, "OpenCode task failed");
71819
+ publishStatus("failed", {
71820
+ message: {
71821
+ kind: "message",
71822
+ messageId: v4_default(),
71823
+ role: "agent",
71824
+ contextId: requestContext.contextId,
71825
+ taskId: requestContext.taskId,
71826
+ parts: [
71827
+ {
71828
+ kind: "text",
71829
+ text: "OpenCode task failed."
71830
+ }
71831
+ ]
71832
+ },
71833
+ final: true
71834
+ });
71835
+ const taskState = runningTask();
71836
+ if (taskState) {
71837
+ taskState.finalized = true;
71838
+ }
71839
+ eventBus.finished();
71840
+ } finally {
71841
+ const taskState = runningTask();
71842
+ if (taskState?.finalized || taskState?.canceled) {
71843
+ this.runningTasks.delete(requestContext.taskId);
71687
71844
  }
71688
71845
  }
71689
71846
  }
71690
- cancelTask = async () => {};
71847
+ cancelTask = async (taskId, eventBus) => {
71848
+ const taskState = this.runningTasks.get(taskId);
71849
+ if (taskState?.finalized) {
71850
+ return;
71851
+ }
71852
+ if (taskState) {
71853
+ taskState.canceled = true;
71854
+ taskState.finalized = true;
71855
+ }
71856
+ if (taskState?.sessionId) {
71857
+ try {
71858
+ await this.client.session.abort({ sessionID: taskState.sessionId });
71859
+ } catch (error51) {
71860
+ logger.warn({ error: error51, taskId }, "Failed to abort OpenCode session");
71861
+ }
71862
+ }
71863
+ const contextId = taskState?.contextId ?? taskId;
71864
+ eventBus.publish({
71865
+ kind: "status-update",
71866
+ taskId,
71867
+ contextId,
71868
+ status: {
71869
+ state: "canceled",
71870
+ message: {
71871
+ kind: "message",
71872
+ messageId: v4_default(),
71873
+ role: "agent",
71874
+ contextId,
71875
+ taskId,
71876
+ parts: [{ kind: "text", text: "Task canceled." }]
71877
+ },
71878
+ timestamp: new Date().toISOString()
71879
+ },
71880
+ final: true
71881
+ });
71882
+ eventBus.finished();
71883
+ };
71691
71884
  }
71692
71885
  // ../../packages/a2a/index.ts
71693
71886
  class A2AServerPortInUseError extends Error {
@@ -71952,8 +72145,8 @@ class AgentRuntimeManager {
71952
72145
  import { resolve as resolve5 } from "path";
71953
72146
  // version.json
71954
72147
  var version_default = {
71955
- version: "0.2.0",
71956
- gitCommitHash: "0856eb3ca1182a69ce7bee3041695344cc61e73f"
72148
+ version: "0.1.13",
72149
+ gitCommitHash: "9e43945"
71957
72150
  };
71958
72151
 
71959
72152
  // src/commands/login/device-auth.ts
@@ -77356,9 +77549,7 @@ var userSandbox = pgTable("user_sandbox", {
77356
77549
  sandboxId: text("sandbox_id").notNull(),
77357
77550
  createdAt: timestamp("created_at").notNull(),
77358
77551
  updatedAt: timestamp("updated_at").$onUpdate(() => new Date).notNull()
77359
- }, (table) => [
77360
- primaryKey({ columns: [table.userId, table.sandboxId] })
77361
- ]);
77552
+ }, (table) => [primaryKey({ columns: [table.userId, table.sandboxId] })]);
77362
77553
  var cliDevice = pgTable("cli_device", {
77363
77554
  id: text("id").primaryKey(),
77364
77555
  userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
@@ -77376,6 +77567,26 @@ var a2aAgent = pgTable("a2a_agent", {
77376
77567
  createdAt: timestamp("created_at").notNull(),
77377
77568
  updatedAt: timestamp("updated_at").$onUpdate(() => new Date).notNull()
77378
77569
  }, (table) => [index("a2a_agent_device_id_idx").on(table.deviceId)]);
77570
+ var a2aAgentTask = pgTable("a2a_agent_task", {
77571
+ id: text("id").primaryKey(),
77572
+ userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
77573
+ agentId: text("agent_id").notNull().references(() => a2aAgent.id, { onDelete: "cascade" }),
77574
+ remoteTaskId: text("remote_task_id").notNull(),
77575
+ contextId: text("context_id").notNull(),
77576
+ status: text("status").notNull(),
77577
+ prompt: text("prompt").notNull(),
77578
+ resultText: text("result_text"),
77579
+ artifacts: jsonb("artifacts"),
77580
+ events: jsonb("events"),
77581
+ metadata: jsonb("metadata"),
77582
+ createdAt: timestamp("created_at").notNull(),
77583
+ updatedAt: timestamp("updated_at").$onUpdate(() => new Date).notNull(),
77584
+ completedAt: timestamp("completed_at")
77585
+ }, (table) => [
77586
+ index("a2a_agent_task_user_id_idx").on(table.userId),
77587
+ index("a2a_agent_task_agent_id_idx").on(table.agentId),
77588
+ uniqueIndex("a2a_agent_task_agent_remote_task_idx").on(table.agentId, table.remoteTaskId)
77589
+ ]);
77379
77590
  var workerTask = pgTable("worker_task", {
77380
77591
  id: text("id").primaryKey(),
77381
77592
  taskType: text("task_type").notNull(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obrain/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -22,9 +22,9 @@
22
22
  "@types/node": "^20.14.15",
23
23
  "@types/yargs": "17.0.35",
24
24
  "bun-types": "^1.1.28",
25
- "@repo/trpc": "0.0.0",
26
25
  "@repo/a2a": "0.0.0",
27
- "@repo/better-auth": "0.0.0"
26
+ "@repo/better-auth": "0.0.0",
27
+ "@repo/trpc": "0.0.0"
28
28
  },
29
29
  "scripts": {
30
30
  "build": "bun build src/index.ts --outfile dist/index.js --target bun",