bopodev-db 0.1.8 → 0.1.10

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,5 +1,5 @@
1
1
 
2
2
  
3
- > bopodev-db@0.1.8 build /Users/danielkrusenstrahle/Documents/Projects/Monorepo/BopoHQ/packages/db
3
+ > bopodev-db@0.1.10 build /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/db
4
4
  > tsc -p tsconfig.json --emitDeclarationOnly
5
5
 
@@ -1,4 +1,4 @@
1
1
 
2
- > bopodev-db@0.1.7 typecheck /Users/danielkrusenstrahle/Documents/Projects/Monorepo/BopoHQ/packages/db
2
+ > bopodev-db@0.1.8 typecheck /Users/danielkrusenstrahle/Documents/Projects/Monorepo/bopohq/packages/db
3
3
  > tsc -p tsconfig.json --noEmit
4
4
 
@@ -0,0 +1,4 @@
1
+ export declare function resolveBopoHomeDir(): string;
2
+ export declare function resolveBopoInstanceId(): string;
3
+ export declare function resolveBopoInstanceRoot(): string;
4
+ export declare function resolveDefaultDbPath(): string;
@@ -175,6 +175,16 @@ export declare function listIssueComments(db: BopoDb, companyId: string, issueId
175
175
  body: string;
176
176
  createdAt: Date;
177
177
  }[]>;
178
+ export declare function listIssueActivity(db: BopoDb, companyId: string, issueId: string, limit?: number): Promise<{
179
+ id: string;
180
+ companyId: string;
181
+ issueId: string | null;
182
+ actorType: string;
183
+ actorId: string | null;
184
+ eventType: string;
185
+ payloadJson: string;
186
+ createdAt: Date;
187
+ }[]>;
178
188
  export declare function updateIssueComment(db: BopoDb, input: {
179
189
  companyId: string;
180
190
  issueId: string;
@@ -249,8 +259,20 @@ export declare function createAgent(db: BopoDb, input: {
249
259
  heartbeatCron: string;
250
260
  monthlyBudgetUsd: string;
251
261
  canHireAgents?: boolean;
262
+ avatarSeed?: string;
263
+ runtimeCommand?: string | null;
264
+ runtimeArgsJson?: string;
265
+ runtimeCwd?: string | null;
266
+ runtimeEnvJson?: string;
267
+ runtimeModel?: string | null;
268
+ runtimeThinkingEffort?: "auto" | "low" | "medium" | "high";
269
+ bootstrapPrompt?: string | null;
270
+ runtimeTimeoutSec?: number;
271
+ interruptGraceSec?: number;
272
+ runPolicyJson?: string;
252
273
  initialState?: Record<string, unknown>;
253
274
  }): Promise<{
275
+ avatarSeed: string;
254
276
  companyId: string;
255
277
  managerAgentId?: string | null;
256
278
  role: string;
@@ -259,6 +281,16 @@ export declare function createAgent(db: BopoDb, input: {
259
281
  heartbeatCron: string;
260
282
  monthlyBudgetUsd: string;
261
283
  canHireAgents?: boolean;
284
+ runtimeCommand?: string | null;
285
+ runtimeArgsJson?: string;
286
+ runtimeCwd?: string | null;
287
+ runtimeEnvJson?: string;
288
+ runtimeModel?: string | null;
289
+ runtimeThinkingEffort?: "auto" | "low" | "medium" | "high";
290
+ bootstrapPrompt?: string | null;
291
+ runtimeTimeoutSec?: number;
292
+ interruptGraceSec?: number;
293
+ runPolicyJson?: string;
262
294
  initialState?: Record<string, unknown>;
263
295
  id: string;
264
296
  }>;
@@ -275,6 +307,17 @@ export declare function listAgents(db: BopoDb, companyId: string): Promise<{
275
307
  usedBudgetUsd: string;
276
308
  tokenUsage: number;
277
309
  canHireAgents: boolean;
310
+ avatarSeed: string;
311
+ runtimeCommand: string | null;
312
+ runtimeArgsJson: string;
313
+ runtimeCwd: string | null;
314
+ runtimeEnvJson: string;
315
+ runtimeModel: string | null;
316
+ runtimeThinkingEffort: string;
317
+ bootstrapPrompt: string | null;
318
+ runtimeTimeoutSec: number;
319
+ interruptGraceSec: number;
320
+ runPolicyJson: string;
278
321
  stateBlob: string;
279
322
  createdAt: Date;
280
323
  updatedAt: Date;
@@ -290,6 +333,16 @@ export declare function updateAgent(db: BopoDb, input: {
290
333
  heartbeatCron?: string;
291
334
  monthlyBudgetUsd?: string;
292
335
  canHireAgents?: boolean;
336
+ runtimeCommand?: string | null;
337
+ runtimeArgsJson?: string;
338
+ runtimeCwd?: string | null;
339
+ runtimeEnvJson?: string;
340
+ runtimeModel?: string | null;
341
+ runtimeThinkingEffort?: "auto" | "low" | "medium" | "high";
342
+ bootstrapPrompt?: string | null;
343
+ runtimeTimeoutSec?: number;
344
+ interruptGraceSec?: number;
345
+ runPolicyJson?: string;
293
346
  stateBlob?: Record<string, unknown>;
294
347
  }): Promise<{
295
348
  id: string;
@@ -304,6 +357,17 @@ export declare function updateAgent(db: BopoDb, input: {
304
357
  usedBudgetUsd: string;
305
358
  tokenUsage: number;
306
359
  canHireAgents: boolean;
360
+ avatarSeed: string;
361
+ runtimeCommand: string | null;
362
+ runtimeArgsJson: string;
363
+ runtimeCwd: string | null;
364
+ runtimeEnvJson: string;
365
+ runtimeModel: string | null;
366
+ runtimeThinkingEffort: string;
367
+ bootstrapPrompt: string | null;
368
+ runtimeTimeoutSec: number;
369
+ interruptGraceSec: number;
370
+ runPolicyJson: string;
307
371
  stateBlob: string;
308
372
  createdAt: Date;
309
373
  updatedAt: Date;
package/dist/schema.d.ts CHANGED
@@ -618,6 +618,193 @@ export declare const agents: import("drizzle-orm/pg-core").PgTableWithColumns<{
618
618
  identity: undefined;
619
619
  generated: undefined;
620
620
  }, {}, {}>;
621
+ avatarSeed: import("drizzle-orm/pg-core").PgColumn<{
622
+ name: "avatar_seed";
623
+ tableName: "agents";
624
+ dataType: "string";
625
+ columnType: "PgText";
626
+ data: string;
627
+ driverParam: string;
628
+ notNull: true;
629
+ hasDefault: true;
630
+ isPrimaryKey: false;
631
+ isAutoincrement: false;
632
+ hasRuntimeDefault: false;
633
+ enumValues: [string, ...string[]];
634
+ baseColumn: never;
635
+ identity: undefined;
636
+ generated: undefined;
637
+ }, {}, {}>;
638
+ runtimeCommand: import("drizzle-orm/pg-core").PgColumn<{
639
+ name: "runtime_command";
640
+ tableName: "agents";
641
+ dataType: "string";
642
+ columnType: "PgText";
643
+ data: string;
644
+ driverParam: string;
645
+ notNull: false;
646
+ hasDefault: false;
647
+ isPrimaryKey: false;
648
+ isAutoincrement: false;
649
+ hasRuntimeDefault: false;
650
+ enumValues: [string, ...string[]];
651
+ baseColumn: never;
652
+ identity: undefined;
653
+ generated: undefined;
654
+ }, {}, {}>;
655
+ runtimeArgsJson: import("drizzle-orm/pg-core").PgColumn<{
656
+ name: "runtime_args_json";
657
+ tableName: "agents";
658
+ dataType: "string";
659
+ columnType: "PgText";
660
+ data: string;
661
+ driverParam: string;
662
+ notNull: true;
663
+ hasDefault: true;
664
+ isPrimaryKey: false;
665
+ isAutoincrement: false;
666
+ hasRuntimeDefault: false;
667
+ enumValues: [string, ...string[]];
668
+ baseColumn: never;
669
+ identity: undefined;
670
+ generated: undefined;
671
+ }, {}, {}>;
672
+ runtimeCwd: import("drizzle-orm/pg-core").PgColumn<{
673
+ name: "runtime_cwd";
674
+ tableName: "agents";
675
+ dataType: "string";
676
+ columnType: "PgText";
677
+ data: string;
678
+ driverParam: string;
679
+ notNull: false;
680
+ hasDefault: false;
681
+ isPrimaryKey: false;
682
+ isAutoincrement: false;
683
+ hasRuntimeDefault: false;
684
+ enumValues: [string, ...string[]];
685
+ baseColumn: never;
686
+ identity: undefined;
687
+ generated: undefined;
688
+ }, {}, {}>;
689
+ runtimeEnvJson: import("drizzle-orm/pg-core").PgColumn<{
690
+ name: "runtime_env_json";
691
+ tableName: "agents";
692
+ dataType: "string";
693
+ columnType: "PgText";
694
+ data: string;
695
+ driverParam: string;
696
+ notNull: true;
697
+ hasDefault: true;
698
+ isPrimaryKey: false;
699
+ isAutoincrement: false;
700
+ hasRuntimeDefault: false;
701
+ enumValues: [string, ...string[]];
702
+ baseColumn: never;
703
+ identity: undefined;
704
+ generated: undefined;
705
+ }, {}, {}>;
706
+ runtimeModel: import("drizzle-orm/pg-core").PgColumn<{
707
+ name: "runtime_model";
708
+ tableName: "agents";
709
+ dataType: "string";
710
+ columnType: "PgText";
711
+ data: string;
712
+ driverParam: string;
713
+ notNull: false;
714
+ hasDefault: false;
715
+ isPrimaryKey: false;
716
+ isAutoincrement: false;
717
+ hasRuntimeDefault: false;
718
+ enumValues: [string, ...string[]];
719
+ baseColumn: never;
720
+ identity: undefined;
721
+ generated: undefined;
722
+ }, {}, {}>;
723
+ runtimeThinkingEffort: import("drizzle-orm/pg-core").PgColumn<{
724
+ name: "runtime_thinking_effort";
725
+ tableName: "agents";
726
+ dataType: "string";
727
+ columnType: "PgText";
728
+ data: string;
729
+ driverParam: string;
730
+ notNull: true;
731
+ hasDefault: true;
732
+ isPrimaryKey: false;
733
+ isAutoincrement: false;
734
+ hasRuntimeDefault: false;
735
+ enumValues: [string, ...string[]];
736
+ baseColumn: never;
737
+ identity: undefined;
738
+ generated: undefined;
739
+ }, {}, {}>;
740
+ bootstrapPrompt: import("drizzle-orm/pg-core").PgColumn<{
741
+ name: "bootstrap_prompt";
742
+ tableName: "agents";
743
+ dataType: "string";
744
+ columnType: "PgText";
745
+ data: string;
746
+ driverParam: string;
747
+ notNull: false;
748
+ hasDefault: false;
749
+ isPrimaryKey: false;
750
+ isAutoincrement: false;
751
+ hasRuntimeDefault: false;
752
+ enumValues: [string, ...string[]];
753
+ baseColumn: never;
754
+ identity: undefined;
755
+ generated: undefined;
756
+ }, {}, {}>;
757
+ runtimeTimeoutSec: import("drizzle-orm/pg-core").PgColumn<{
758
+ name: "runtime_timeout_sec";
759
+ tableName: "agents";
760
+ dataType: "number";
761
+ columnType: "PgInteger";
762
+ data: number;
763
+ driverParam: string | number;
764
+ notNull: true;
765
+ hasDefault: true;
766
+ isPrimaryKey: false;
767
+ isAutoincrement: false;
768
+ hasRuntimeDefault: false;
769
+ enumValues: undefined;
770
+ baseColumn: never;
771
+ identity: undefined;
772
+ generated: undefined;
773
+ }, {}, {}>;
774
+ interruptGraceSec: import("drizzle-orm/pg-core").PgColumn<{
775
+ name: "interrupt_grace_sec";
776
+ tableName: "agents";
777
+ dataType: "number";
778
+ columnType: "PgInteger";
779
+ data: number;
780
+ driverParam: string | number;
781
+ notNull: true;
782
+ hasDefault: true;
783
+ isPrimaryKey: false;
784
+ isAutoincrement: false;
785
+ hasRuntimeDefault: false;
786
+ enumValues: undefined;
787
+ baseColumn: never;
788
+ identity: undefined;
789
+ generated: undefined;
790
+ }, {}, {}>;
791
+ runPolicyJson: import("drizzle-orm/pg-core").PgColumn<{
792
+ name: "run_policy_json";
793
+ tableName: "agents";
794
+ dataType: "string";
795
+ columnType: "PgText";
796
+ data: string;
797
+ driverParam: string;
798
+ notNull: true;
799
+ hasDefault: true;
800
+ isPrimaryKey: false;
801
+ isAutoincrement: false;
802
+ hasRuntimeDefault: false;
803
+ enumValues: [string, ...string[]];
804
+ baseColumn: never;
805
+ identity: undefined;
806
+ generated: undefined;
807
+ }, {}, {}>;
621
808
  stateBlob: import("drizzle-orm/pg-core").PgColumn<{
622
809
  name: "state_blob";
623
810
  tableName: "agents";
@@ -2631,6 +2818,193 @@ export declare const schema: {
2631
2818
  identity: undefined;
2632
2819
  generated: undefined;
2633
2820
  }, {}, {}>;
2821
+ avatarSeed: import("drizzle-orm/pg-core").PgColumn<{
2822
+ name: "avatar_seed";
2823
+ tableName: "agents";
2824
+ dataType: "string";
2825
+ columnType: "PgText";
2826
+ data: string;
2827
+ driverParam: string;
2828
+ notNull: true;
2829
+ hasDefault: true;
2830
+ isPrimaryKey: false;
2831
+ isAutoincrement: false;
2832
+ hasRuntimeDefault: false;
2833
+ enumValues: [string, ...string[]];
2834
+ baseColumn: never;
2835
+ identity: undefined;
2836
+ generated: undefined;
2837
+ }, {}, {}>;
2838
+ runtimeCommand: import("drizzle-orm/pg-core").PgColumn<{
2839
+ name: "runtime_command";
2840
+ tableName: "agents";
2841
+ dataType: "string";
2842
+ columnType: "PgText";
2843
+ data: string;
2844
+ driverParam: string;
2845
+ notNull: false;
2846
+ hasDefault: false;
2847
+ isPrimaryKey: false;
2848
+ isAutoincrement: false;
2849
+ hasRuntimeDefault: false;
2850
+ enumValues: [string, ...string[]];
2851
+ baseColumn: never;
2852
+ identity: undefined;
2853
+ generated: undefined;
2854
+ }, {}, {}>;
2855
+ runtimeArgsJson: import("drizzle-orm/pg-core").PgColumn<{
2856
+ name: "runtime_args_json";
2857
+ tableName: "agents";
2858
+ dataType: "string";
2859
+ columnType: "PgText";
2860
+ data: string;
2861
+ driverParam: string;
2862
+ notNull: true;
2863
+ hasDefault: true;
2864
+ isPrimaryKey: false;
2865
+ isAutoincrement: false;
2866
+ hasRuntimeDefault: false;
2867
+ enumValues: [string, ...string[]];
2868
+ baseColumn: never;
2869
+ identity: undefined;
2870
+ generated: undefined;
2871
+ }, {}, {}>;
2872
+ runtimeCwd: import("drizzle-orm/pg-core").PgColumn<{
2873
+ name: "runtime_cwd";
2874
+ tableName: "agents";
2875
+ dataType: "string";
2876
+ columnType: "PgText";
2877
+ data: string;
2878
+ driverParam: string;
2879
+ notNull: false;
2880
+ hasDefault: false;
2881
+ isPrimaryKey: false;
2882
+ isAutoincrement: false;
2883
+ hasRuntimeDefault: false;
2884
+ enumValues: [string, ...string[]];
2885
+ baseColumn: never;
2886
+ identity: undefined;
2887
+ generated: undefined;
2888
+ }, {}, {}>;
2889
+ runtimeEnvJson: import("drizzle-orm/pg-core").PgColumn<{
2890
+ name: "runtime_env_json";
2891
+ tableName: "agents";
2892
+ dataType: "string";
2893
+ columnType: "PgText";
2894
+ data: string;
2895
+ driverParam: string;
2896
+ notNull: true;
2897
+ hasDefault: true;
2898
+ isPrimaryKey: false;
2899
+ isAutoincrement: false;
2900
+ hasRuntimeDefault: false;
2901
+ enumValues: [string, ...string[]];
2902
+ baseColumn: never;
2903
+ identity: undefined;
2904
+ generated: undefined;
2905
+ }, {}, {}>;
2906
+ runtimeModel: import("drizzle-orm/pg-core").PgColumn<{
2907
+ name: "runtime_model";
2908
+ tableName: "agents";
2909
+ dataType: "string";
2910
+ columnType: "PgText";
2911
+ data: string;
2912
+ driverParam: string;
2913
+ notNull: false;
2914
+ hasDefault: false;
2915
+ isPrimaryKey: false;
2916
+ isAutoincrement: false;
2917
+ hasRuntimeDefault: false;
2918
+ enumValues: [string, ...string[]];
2919
+ baseColumn: never;
2920
+ identity: undefined;
2921
+ generated: undefined;
2922
+ }, {}, {}>;
2923
+ runtimeThinkingEffort: import("drizzle-orm/pg-core").PgColumn<{
2924
+ name: "runtime_thinking_effort";
2925
+ tableName: "agents";
2926
+ dataType: "string";
2927
+ columnType: "PgText";
2928
+ data: string;
2929
+ driverParam: string;
2930
+ notNull: true;
2931
+ hasDefault: true;
2932
+ isPrimaryKey: false;
2933
+ isAutoincrement: false;
2934
+ hasRuntimeDefault: false;
2935
+ enumValues: [string, ...string[]];
2936
+ baseColumn: never;
2937
+ identity: undefined;
2938
+ generated: undefined;
2939
+ }, {}, {}>;
2940
+ bootstrapPrompt: import("drizzle-orm/pg-core").PgColumn<{
2941
+ name: "bootstrap_prompt";
2942
+ tableName: "agents";
2943
+ dataType: "string";
2944
+ columnType: "PgText";
2945
+ data: string;
2946
+ driverParam: string;
2947
+ notNull: false;
2948
+ hasDefault: false;
2949
+ isPrimaryKey: false;
2950
+ isAutoincrement: false;
2951
+ hasRuntimeDefault: false;
2952
+ enumValues: [string, ...string[]];
2953
+ baseColumn: never;
2954
+ identity: undefined;
2955
+ generated: undefined;
2956
+ }, {}, {}>;
2957
+ runtimeTimeoutSec: import("drizzle-orm/pg-core").PgColumn<{
2958
+ name: "runtime_timeout_sec";
2959
+ tableName: "agents";
2960
+ dataType: "number";
2961
+ columnType: "PgInteger";
2962
+ data: number;
2963
+ driverParam: string | number;
2964
+ notNull: true;
2965
+ hasDefault: true;
2966
+ isPrimaryKey: false;
2967
+ isAutoincrement: false;
2968
+ hasRuntimeDefault: false;
2969
+ enumValues: undefined;
2970
+ baseColumn: never;
2971
+ identity: undefined;
2972
+ generated: undefined;
2973
+ }, {}, {}>;
2974
+ interruptGraceSec: import("drizzle-orm/pg-core").PgColumn<{
2975
+ name: "interrupt_grace_sec";
2976
+ tableName: "agents";
2977
+ dataType: "number";
2978
+ columnType: "PgInteger";
2979
+ data: number;
2980
+ driverParam: string | number;
2981
+ notNull: true;
2982
+ hasDefault: true;
2983
+ isPrimaryKey: false;
2984
+ isAutoincrement: false;
2985
+ hasRuntimeDefault: false;
2986
+ enumValues: undefined;
2987
+ baseColumn: never;
2988
+ identity: undefined;
2989
+ generated: undefined;
2990
+ }, {}, {}>;
2991
+ runPolicyJson: import("drizzle-orm/pg-core").PgColumn<{
2992
+ name: "run_policy_json";
2993
+ tableName: "agents";
2994
+ dataType: "string";
2995
+ columnType: "PgText";
2996
+ data: string;
2997
+ driverParam: string;
2998
+ notNull: true;
2999
+ hasDefault: true;
3000
+ isPrimaryKey: false;
3001
+ isAutoincrement: false;
3002
+ hasRuntimeDefault: false;
3003
+ enumValues: [string, ...string[]];
3004
+ baseColumn: never;
3005
+ identity: undefined;
3006
+ generated: undefined;
3007
+ }, {}, {}>;
2634
3008
  stateBlob: import("drizzle-orm/pg-core").PgColumn<{
2635
3009
  name: "state_blob";
2636
3010
  tableName: "agents";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bopodev-db",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
package/src/bootstrap.ts CHANGED
@@ -69,11 +69,88 @@ export async function bootstrapDatabase(dbPath?: string) {
69
69
  used_budget_usd NUMERIC(12, 4) NOT NULL DEFAULT 0,
70
70
  token_usage INTEGER NOT NULL DEFAULT 0,
71
71
  can_hire_agents BOOLEAN NOT NULL DEFAULT false,
72
+ avatar_seed TEXT NOT NULL DEFAULT '',
73
+ runtime_command TEXT,
74
+ runtime_args_json TEXT NOT NULL DEFAULT '[]',
75
+ runtime_cwd TEXT,
76
+ runtime_env_json TEXT NOT NULL DEFAULT '{}',
77
+ runtime_model TEXT,
78
+ runtime_thinking_effort TEXT NOT NULL DEFAULT 'auto',
79
+ bootstrap_prompt TEXT,
80
+ runtime_timeout_sec INTEGER NOT NULL DEFAULT 0,
81
+ interrupt_grace_sec INTEGER NOT NULL DEFAULT 15,
82
+ run_policy_json TEXT NOT NULL DEFAULT '{}',
72
83
  state_blob TEXT NOT NULL DEFAULT '{}',
73
84
  created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
74
85
  updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
75
86
  );
76
87
  `);
88
+ await db.execute(sql`
89
+ ALTER TABLE agents
90
+ ADD COLUMN IF NOT EXISTS avatar_seed TEXT NOT NULL DEFAULT '';
91
+ `);
92
+ await db.execute(sql`
93
+ ALTER TABLE agents
94
+ ADD COLUMN IF NOT EXISTS runtime_command TEXT;
95
+ `);
96
+ await db.execute(sql`
97
+ ALTER TABLE agents
98
+ ADD COLUMN IF NOT EXISTS runtime_args_json TEXT NOT NULL DEFAULT '[]';
99
+ `);
100
+ await db.execute(sql`
101
+ ALTER TABLE agents
102
+ ADD COLUMN IF NOT EXISTS runtime_cwd TEXT;
103
+ `);
104
+ await db.execute(sql`
105
+ ALTER TABLE agents
106
+ ADD COLUMN IF NOT EXISTS runtime_env_json TEXT NOT NULL DEFAULT '{}';
107
+ `);
108
+ await db.execute(sql`
109
+ ALTER TABLE agents
110
+ ADD COLUMN IF NOT EXISTS runtime_model TEXT;
111
+ `);
112
+ await db.execute(sql`
113
+ ALTER TABLE agents
114
+ ADD COLUMN IF NOT EXISTS runtime_thinking_effort TEXT NOT NULL DEFAULT 'auto';
115
+ `);
116
+ await db.execute(sql`
117
+ ALTER TABLE agents
118
+ ADD COLUMN IF NOT EXISTS bootstrap_prompt TEXT;
119
+ `);
120
+ await db.execute(sql`
121
+ ALTER TABLE agents
122
+ ADD COLUMN IF NOT EXISTS runtime_timeout_sec INTEGER NOT NULL DEFAULT 0;
123
+ `);
124
+ await db.execute(sql`
125
+ ALTER TABLE agents
126
+ ADD COLUMN IF NOT EXISTS interrupt_grace_sec INTEGER NOT NULL DEFAULT 15;
127
+ `);
128
+ await db.execute(sql`
129
+ ALTER TABLE agents
130
+ ADD COLUMN IF NOT EXISTS run_policy_json TEXT NOT NULL DEFAULT '{}';
131
+ `);
132
+ await db.execute(sql`
133
+ UPDATE agents
134
+ SET
135
+ runtime_command = COALESCE(runtime_command, state_blob::jsonb->'runtime'->>'command'),
136
+ runtime_args_json = CASE
137
+ WHEN runtime_args_json IS NULL OR btrim(runtime_args_json) = '' OR runtime_args_json = '[]'
138
+ THEN COALESCE((state_blob::jsonb->'runtime'->'args')::text, '[]')
139
+ ELSE runtime_args_json
140
+ END,
141
+ runtime_cwd = COALESCE(runtime_cwd, state_blob::jsonb->'runtime'->>'cwd'),
142
+ runtime_env_json = CASE
143
+ WHEN runtime_env_json IS NULL OR btrim(runtime_env_json) = '' OR runtime_env_json = '{}'
144
+ THEN COALESCE((state_blob::jsonb->'runtime'->'env')::text, '{}')
145
+ ELSE runtime_env_json
146
+ END,
147
+ runtime_timeout_sec = CASE
148
+ WHEN runtime_timeout_sec IS NULL OR runtime_timeout_sec = 0
149
+ THEN COALESCE(((state_blob::jsonb->'runtime'->>'timeoutMs')::int / 1000), 0)
150
+ ELSE runtime_timeout_sec
151
+ END
152
+ WHERE state_blob IS NOT NULL AND btrim(state_blob) <> '';
153
+ `);
77
154
  await db.execute(sql`
78
155
  CREATE TABLE IF NOT EXISTS issues (
79
156
  id TEXT PRIMARY KEY,
package/src/client.ts CHANGED
@@ -1,12 +1,13 @@
1
1
  import { mkdir } from "node:fs/promises";
2
- import { dirname, resolve } from "node:path";
2
+ import { dirname } from "node:path";
3
3
  import { PGlite } from "@electric-sql/pglite";
4
4
  import { drizzle } from "drizzle-orm/pglite";
5
5
  import * as dbSchema from "./schema";
6
+ import { resolveDefaultDbPath } from "./default-paths";
6
7
 
7
8
  export type BopoDb = ReturnType<typeof drizzle<typeof dbSchema>>;
8
9
 
9
- const defaultDbPath = resolve(process.cwd(), "data", "bopohq.db");
10
+ const defaultDbPath = resolveDefaultDbPath();
10
11
 
11
12
  export async function createDb(dbPath = defaultDbPath) {
12
13
  await mkdir(dirname(dbPath), { recursive: true });
@@ -0,0 +1,47 @@
1
+ import { homedir } from "node:os";
2
+ import { join, resolve } from "node:path";
3
+
4
+ const DEFAULT_INSTANCE_ID = "default";
5
+ const SAFE_PATH_SEGMENT_RE = /^[a-zA-Z0-9_-]+$/;
6
+
7
+ function expandHomePrefix(value: string) {
8
+ if (value === "~") {
9
+ return homedir();
10
+ }
11
+ if (value.startsWith("~/")) {
12
+ return resolve(homedir(), value.slice(2));
13
+ }
14
+ return value;
15
+ }
16
+
17
+ function normalizePath(raw: string) {
18
+ return resolve(expandHomePrefix(raw.trim()));
19
+ }
20
+
21
+ export function resolveBopoHomeDir() {
22
+ const configured = process.env.BOPO_HOME?.trim();
23
+ if (configured) {
24
+ return normalizePath(configured);
25
+ }
26
+ return resolve(homedir(), ".bopodev");
27
+ }
28
+
29
+ export function resolveBopoInstanceId() {
30
+ const configured = process.env.BOPO_INSTANCE_ID?.trim() || DEFAULT_INSTANCE_ID;
31
+ if (!SAFE_PATH_SEGMENT_RE.test(configured)) {
32
+ throw new Error(`Invalid BOPO_INSTANCE_ID '${configured}'.`);
33
+ }
34
+ return configured;
35
+ }
36
+
37
+ export function resolveBopoInstanceRoot() {
38
+ const configuredRoot = process.env.BOPO_INSTANCE_ROOT?.trim();
39
+ if (configuredRoot) {
40
+ return normalizePath(configuredRoot);
41
+ }
42
+ return join(resolveBopoHomeDir(), "instances", resolveBopoInstanceId());
43
+ }
44
+
45
+ export function resolveDefaultDbPath() {
46
+ return join(resolveBopoInstanceRoot(), "db", "bopodev.db");
47
+ }
@@ -335,6 +335,15 @@ export async function listIssueComments(db: BopoDb, companyId: string, issueId:
335
335
  .orderBy(desc(issueComments.createdAt));
336
336
  }
337
337
 
338
+ export async function listIssueActivity(db: BopoDb, companyId: string, issueId: string, limit = 100) {
339
+ return db
340
+ .select()
341
+ .from(activityLogs)
342
+ .where(and(eq(activityLogs.companyId, companyId), eq(activityLogs.issueId, issueId)))
343
+ .orderBy(desc(activityLogs.createdAt))
344
+ .limit(limit);
345
+ }
346
+
338
347
  export async function updateIssueComment(
339
348
  db: BopoDb,
340
349
  input: {
@@ -456,6 +465,17 @@ export async function createAgent(
456
465
  heartbeatCron: string;
457
466
  monthlyBudgetUsd: string;
458
467
  canHireAgents?: boolean;
468
+ avatarSeed?: string;
469
+ runtimeCommand?: string | null;
470
+ runtimeArgsJson?: string;
471
+ runtimeCwd?: string | null;
472
+ runtimeEnvJson?: string;
473
+ runtimeModel?: string | null;
474
+ runtimeThinkingEffort?: "auto" | "low" | "medium" | "high";
475
+ bootstrapPrompt?: string | null;
476
+ runtimeTimeoutSec?: number;
477
+ interruptGraceSec?: number;
478
+ runPolicyJson?: string;
459
479
  initialState?: Record<string, unknown>;
460
480
  }
461
481
  ) {
@@ -463,6 +483,7 @@ export async function createAgent(
463
483
  await assertAgentBelongsToCompany(db, input.companyId, input.managerAgentId);
464
484
  }
465
485
  const id = nanoid(12);
486
+ const avatarSeed = input.avatarSeed ?? nanoid(10);
466
487
  await db.insert(agents).values({
467
488
  id,
468
489
  companyId: input.companyId,
@@ -473,10 +494,21 @@ export async function createAgent(
473
494
  heartbeatCron: input.heartbeatCron,
474
495
  monthlyBudgetUsd: input.monthlyBudgetUsd,
475
496
  canHireAgents: input.canHireAgents ?? false,
497
+ avatarSeed,
498
+ runtimeCommand: input.runtimeCommand ?? null,
499
+ runtimeArgsJson: input.runtimeArgsJson ?? "[]",
500
+ runtimeCwd: input.runtimeCwd ?? null,
501
+ runtimeEnvJson: input.runtimeEnvJson ?? "{}",
502
+ runtimeModel: input.runtimeModel ?? null,
503
+ runtimeThinkingEffort: input.runtimeThinkingEffort ?? "auto",
504
+ bootstrapPrompt: input.bootstrapPrompt ?? null,
505
+ runtimeTimeoutSec: input.runtimeTimeoutSec ?? 0,
506
+ interruptGraceSec: input.interruptGraceSec ?? 15,
507
+ runPolicyJson: input.runPolicyJson ?? "{}",
476
508
  stateBlob: JSON.stringify(input.initialState ?? {})
477
509
  });
478
510
 
479
- return { id, ...input };
511
+ return { id, ...input, avatarSeed };
480
512
  }
481
513
 
482
514
  export async function listAgents(db: BopoDb, companyId: string) {
@@ -496,6 +528,16 @@ export async function updateAgent(
496
528
  heartbeatCron?: string;
497
529
  monthlyBudgetUsd?: string;
498
530
  canHireAgents?: boolean;
531
+ runtimeCommand?: string | null;
532
+ runtimeArgsJson?: string;
533
+ runtimeCwd?: string | null;
534
+ runtimeEnvJson?: string;
535
+ runtimeModel?: string | null;
536
+ runtimeThinkingEffort?: "auto" | "low" | "medium" | "high";
537
+ bootstrapPrompt?: string | null;
538
+ runtimeTimeoutSec?: number;
539
+ interruptGraceSec?: number;
540
+ runPolicyJson?: string;
499
541
  stateBlob?: Record<string, unknown>;
500
542
  }
501
543
  ) {
@@ -514,6 +556,16 @@ export async function updateAgent(
514
556
  heartbeatCron: input.heartbeatCron,
515
557
  monthlyBudgetUsd: input.monthlyBudgetUsd,
516
558
  canHireAgents: input.canHireAgents,
559
+ runtimeCommand: input.runtimeCommand,
560
+ runtimeArgsJson: input.runtimeArgsJson,
561
+ runtimeCwd: input.runtimeCwd,
562
+ runtimeEnvJson: input.runtimeEnvJson,
563
+ runtimeModel: input.runtimeModel,
564
+ runtimeThinkingEffort: input.runtimeThinkingEffort,
565
+ bootstrapPrompt: input.bootstrapPrompt,
566
+ runtimeTimeoutSec: input.runtimeTimeoutSec,
567
+ interruptGraceSec: input.interruptGraceSec,
568
+ runPolicyJson: input.runPolicyJson,
517
569
  stateBlob: input.stateBlob ? JSON.stringify(input.stateBlob) : undefined,
518
570
  updatedAt: touchUpdatedAtSql
519
571
  })
package/src/schema.ts CHANGED
@@ -64,6 +64,17 @@ export const agents = pgTable("agents", {
64
64
  .default("0"),
65
65
  tokenUsage: integer("token_usage").notNull().default(0),
66
66
  canHireAgents: boolean("can_hire_agents").notNull().default(false),
67
+ avatarSeed: text("avatar_seed").notNull().default(""),
68
+ runtimeCommand: text("runtime_command"),
69
+ runtimeArgsJson: text("runtime_args_json").notNull().default("[]"),
70
+ runtimeCwd: text("runtime_cwd"),
71
+ runtimeEnvJson: text("runtime_env_json").notNull().default("{}"),
72
+ runtimeModel: text("runtime_model"),
73
+ runtimeThinkingEffort: text("runtime_thinking_effort").notNull().default("auto"),
74
+ bootstrapPrompt: text("bootstrap_prompt"),
75
+ runtimeTimeoutSec: integer("runtime_timeout_sec").notNull().default(0),
76
+ interruptGraceSec: integer("interrupt_grace_sec").notNull().default(15),
77
+ runPolicyJson: text("run_policy_json").notNull().default("{}"),
67
78
  stateBlob: text("state_blob").notNull().default("{}"),
68
79
  createdAt: timestamp("created_at", { mode: "date" }).defaultNow().notNull(),
69
80
  updatedAt: timestamp("updated_at", { mode: "date" }).defaultNow().notNull()
@@ -1,4 +0,0 @@
1
-
2
- > @bopo/db@0.1.0 lint /Users/danielkrusenstrahle/Documents/Projects/Monorepo/BopoHQ/packages/db
3
- > tsc -p tsconfig.json --noEmit
4
-