clawcompany 0.3.0 → 0.4.0

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 +275 -85
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -9,89 +9,6 @@ var __export = (target, all) => {
9
9
  __defProp(target, name, { get: all[name], enumerable: true });
10
10
  };
11
11
 
12
- // src/utils.ts
13
- import { join } from "path";
14
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
15
- function banner() {
16
- console.log("");
17
- console.log(" \u{1F99E} ClawCompany v0.3.0");
18
- console.log(" Build for OPC. Every human being is a chairman.");
19
- console.log("");
20
- }
21
- function getConfigDir() {
22
- const dir = join(process.env.HOME ?? "~", ".clawcompany");
23
- if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
24
- return dir;
25
- }
26
- function getConfigPath() {
27
- return join(getConfigDir(), "config.json");
28
- }
29
- function configExists() {
30
- return existsSync(getConfigPath());
31
- }
32
- function readConfig() {
33
- if (!configExists()) return null;
34
- try {
35
- return JSON.parse(readFileSync(getConfigPath(), "utf-8"));
36
- } catch {
37
- return null;
38
- }
39
- }
40
- function writeConfig(config) {
41
- writeFileSync(getConfigPath(), JSON.stringify(config, null, 2));
42
- }
43
- async function apiGet(path, port = 3200) {
44
- const res = await fetch(`http://localhost:${port}${path}`);
45
- if (!res.ok) throw new Error(`API error: ${res.status}`);
46
- return res.json();
47
- }
48
- async function apiPost(path, body, port = 3200) {
49
- const res = await fetch(`http://localhost:${port}${path}`, {
50
- method: "POST",
51
- headers: { "Content-Type": "application/json" },
52
- body: JSON.stringify(body)
53
- });
54
- if (!res.ok) {
55
- const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
56
- throw new Error(err.error ?? `API error: ${res.status}`);
57
- }
58
- return res.json();
59
- }
60
- async function validateClawApiKey(key) {
61
- try {
62
- const res = await fetch("https://clawapi.org/api/v1/chat/completions", {
63
- method: "POST",
64
- headers: {
65
- "Authorization": `Bearer ${key}`,
66
- "Content-Type": "application/json"
67
- },
68
- body: JSON.stringify({
69
- model: "gpt-oss-20b",
70
- messages: [{ role: "user", content: "hi" }],
71
- max_tokens: 5
72
- })
73
- });
74
- if (res.status === 401) return { valid: false, error: "Invalid key. Check your key at clawapi.org" };
75
- if (!res.ok) return { valid: false, error: `ClawAPI returned ${res.status}. Try again later.` };
76
- return { valid: true };
77
- } catch (err) {
78
- return { valid: false, error: `Cannot reach ClawAPI: ${err.message}. Check your internet connection.` };
79
- }
80
- }
81
- async function isServerRunning(port = 3200) {
82
- try {
83
- const res = await fetch(`http://localhost:${port}/api/health`);
84
- return res.ok;
85
- } catch {
86
- return false;
87
- }
88
- }
89
- var init_utils = __esm({
90
- "src/utils.ts"() {
91
- "use strict";
92
- }
93
- });
94
-
95
12
  // ../packages/shared/src/types.ts
96
13
  var init_types = __esm({
97
14
  "../packages/shared/src/types.ts"() {
@@ -856,6 +773,153 @@ var init_market = __esm({
856
773
  }
857
774
  });
858
775
 
776
+ // ../packages/shared/src/memory.ts
777
+ function createEmptyMemory() {
778
+ return {
779
+ version: 1,
780
+ chairman: {
781
+ domains: [],
782
+ commonMissions: [],
783
+ preferences: []
784
+ },
785
+ company: {
786
+ missionCount: 0,
787
+ learnings: [],
788
+ domainKnowledge: [],
789
+ goodPatterns: [],
790
+ recentMissions: []
791
+ },
792
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
793
+ };
794
+ }
795
+ function buildMemoryContext(memory) {
796
+ const parts = [];
797
+ const ch = memory.chairman;
798
+ if (ch.language) parts.push(`Chairman language: ${ch.language}`);
799
+ if (ch.outputStyle) parts.push(`Output style: ${ch.outputStyle}`);
800
+ if (ch.domains.length > 0) parts.push(`Focus areas: ${ch.domains.slice(0, 5).join(", ")}`);
801
+ if (ch.preferences.length > 0) parts.push(`Preferences: ${ch.preferences.slice(0, 5).join("; ")}`);
802
+ const co = memory.company;
803
+ if (co.missionCount > 0) parts.push(`Missions completed: ${co.missionCount}`);
804
+ if (co.learnings.length > 0) parts.push(`Key learnings: ${co.learnings.slice(-5).join("; ")}`);
805
+ if (co.domainKnowledge.length > 0) parts.push(`Domain knowledge: ${co.domainKnowledge.slice(-5).join("; ")}`);
806
+ if (co.recentMissions.length > 0) {
807
+ const recent = co.recentMissions.slice(-3).map((m) => m.goal).join("; ");
808
+ parts.push(`Recent missions: ${recent}`);
809
+ }
810
+ if (parts.length === 0) return "";
811
+ return `
812
+
813
+ ## Company Memory
814
+ ${parts.join("\n")}`;
815
+ }
816
+ function updateMemoryFromMission(memory, mission, chairmanMessage) {
817
+ const updated = structuredClone(memory);
818
+ const now = (/* @__PURE__ */ new Date()).toISOString();
819
+ updated.updatedAt = now;
820
+ if (chairmanMessage || mission.goal) {
821
+ const text = chairmanMessage ?? mission.goal;
822
+ const hasChinese = /[\u4e00-\u9fff]/.test(text);
823
+ const hasJapanese = /[\u3040-\u309f\u30a0-\u30ff]/.test(text);
824
+ if (hasChinese) updated.chairman.language = "zh";
825
+ else if (hasJapanese) updated.chairman.language = "ja";
826
+ else if (!updated.chairman.language) updated.chairman.language = "en";
827
+ }
828
+ const domainKeywords = extractDomains(mission.goal);
829
+ for (const d of domainKeywords) {
830
+ if (!updated.chairman.domains.includes(d)) {
831
+ updated.chairman.domains.push(d);
832
+ }
833
+ }
834
+ if (updated.chairman.domains.length > 10) {
835
+ updated.chairman.domains = updated.chairman.domains.slice(-10);
836
+ }
837
+ const missionType = classifyMission(mission.goal);
838
+ if (missionType && !updated.chairman.commonMissions.includes(missionType)) {
839
+ updated.chairman.commonMissions.push(missionType);
840
+ }
841
+ if (updated.chairman.commonMissions.length > 8) {
842
+ updated.chairman.commonMissions = updated.chairman.commonMissions.slice(-8);
843
+ }
844
+ updated.company.missionCount++;
845
+ const rolesUsed = [...new Set(mission.workStreams.map((ws) => ws.assignedTo))];
846
+ updated.company.recentMissions.push({
847
+ goal: mission.goal.slice(0, 100),
848
+ date: now.split("T")[0],
849
+ cost: mission.cost,
850
+ duration: mission.duration,
851
+ workStreamCount: mission.workStreams.length,
852
+ rolesUsed,
853
+ success: mission.workStreams.every((ws) => ws.status === "completed")
854
+ });
855
+ if (updated.company.recentMissions.length > 10) {
856
+ updated.company.recentMissions = updated.company.recentMissions.slice(-10);
857
+ }
858
+ return updated;
859
+ }
860
+ function extractDomains(text) {
861
+ const domains = [];
862
+ const lower = text.toLowerCase();
863
+ const domainMap = {
864
+ bitcoin: "crypto",
865
+ btc: "crypto",
866
+ ethereum: "crypto",
867
+ eth: "crypto",
868
+ "\u6BD4\u7279\u5E01": "crypto",
869
+ "\u4EE5\u592A\u574A": "crypto",
870
+ "\u52A0\u5BC6": "crypto",
871
+ defi: "crypto",
872
+ crypto: "crypto",
873
+ trading: "finance",
874
+ investment: "finance",
875
+ revenue: "finance",
876
+ stock: "finance",
877
+ market: "finance",
878
+ ai: "ai/ml",
879
+ "machine learning": "ai/ml",
880
+ llm: "ai/ml",
881
+ agent: "ai/ml",
882
+ "\u4EBA\u5DE5\u667A\u80FD": "ai/ml",
883
+ marketing: "marketing",
884
+ seo: "marketing",
885
+ content: "marketing",
886
+ brand: "marketing",
887
+ "\u8425\u9500": "marketing",
888
+ code: "engineering",
889
+ api: "engineering",
890
+ software: "engineering",
891
+ deploy: "engineering",
892
+ legal: "legal",
893
+ contract: "legal",
894
+ compliance: "legal",
895
+ ecommerce: "ecommerce",
896
+ product: "ecommerce",
897
+ shopify: "ecommerce"
898
+ };
899
+ for (const [keyword, domain] of Object.entries(domainMap)) {
900
+ if (lower.includes(keyword) && !domains.includes(domain)) {
901
+ domains.push(domain);
902
+ }
903
+ }
904
+ return domains;
905
+ }
906
+ function classifyMission(goal) {
907
+ const lower = goal.toLowerCase();
908
+ if (lower.includes("analyz") || lower.includes("\u5206\u6790")) return "analysis";
909
+ if (lower.includes("research") || lower.includes("\u7814\u7A76") || lower.includes("\u8C03\u7814")) return "research";
910
+ if (lower.includes("write") || lower.includes("draft") || lower.includes("\u5199")) return "writing";
911
+ if (lower.includes("compare") || lower.includes("\u5BF9\u6BD4") || lower.includes("\u6BD4\u8F83")) return "comparison";
912
+ if (lower.includes("build") || lower.includes("create") || lower.includes("\u5F00\u53D1")) return "building";
913
+ if (lower.includes("plan") || lower.includes("strategy") || lower.includes("\u7B56\u7565")) return "strategy";
914
+ if (lower.includes("price") || lower.includes("cost") || lower.includes("\u4EF7\u683C")) return "pricing";
915
+ return null;
916
+ }
917
+ var init_memory = __esm({
918
+ "../packages/shared/src/memory.ts"() {
919
+ "use strict";
920
+ }
921
+ });
922
+
859
923
  // ../packages/shared/src/index.ts
860
924
  var init_src = __esm({
861
925
  "../packages/shared/src/index.ts"() {
@@ -864,6 +928,106 @@ var init_src = __esm({
864
928
  init_defaults();
865
929
  init_api_paths();
866
930
  init_market();
931
+ init_memory();
932
+ }
933
+ });
934
+
935
+ // src/utils.ts
936
+ import { join } from "path";
937
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
938
+ function banner() {
939
+ console.log("");
940
+ console.log(" \u{1F99E} ClawCompany v0.1.0");
941
+ console.log(" Build for OPC. Every human being is a chairman.");
942
+ console.log("");
943
+ }
944
+ function getConfigDir() {
945
+ const dir = join(process.env.HOME ?? "~", ".clawcompany");
946
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
947
+ return dir;
948
+ }
949
+ function getConfigPath() {
950
+ return join(getConfigDir(), "config.json");
951
+ }
952
+ function configExists() {
953
+ return existsSync(getConfigPath());
954
+ }
955
+ function readConfig() {
956
+ if (!configExists()) return null;
957
+ try {
958
+ return JSON.parse(readFileSync(getConfigPath(), "utf-8"));
959
+ } catch {
960
+ return null;
961
+ }
962
+ }
963
+ function writeConfig(config) {
964
+ writeFileSync(getConfigPath(), JSON.stringify(config, null, 2));
965
+ }
966
+ function getMemoryPath() {
967
+ return join(getConfigDir(), "memory.json");
968
+ }
969
+ function readMemory() {
970
+ try {
971
+ if (existsSync(getMemoryPath())) {
972
+ return JSON.parse(readFileSync(getMemoryPath(), "utf-8"));
973
+ }
974
+ } catch {
975
+ }
976
+ return createEmptyMemory();
977
+ }
978
+ function writeMemory(memory) {
979
+ writeFileSync(getMemoryPath(), JSON.stringify(memory, null, 2));
980
+ }
981
+ async function apiGet(path, port = 3200) {
982
+ const res = await fetch(`http://localhost:${port}${path}`);
983
+ if (!res.ok) throw new Error(`API error: ${res.status}`);
984
+ return res.json();
985
+ }
986
+ async function apiPost(path, body, port = 3200) {
987
+ const res = await fetch(`http://localhost:${port}${path}`, {
988
+ method: "POST",
989
+ headers: { "Content-Type": "application/json" },
990
+ body: JSON.stringify(body)
991
+ });
992
+ if (!res.ok) {
993
+ const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
994
+ throw new Error(err.error ?? `API error: ${res.status}`);
995
+ }
996
+ return res.json();
997
+ }
998
+ async function validateClawApiKey(key) {
999
+ try {
1000
+ const res = await fetch("https://clawapi.org/api/v1/chat/completions", {
1001
+ method: "POST",
1002
+ headers: {
1003
+ "Authorization": `Bearer ${key}`,
1004
+ "Content-Type": "application/json"
1005
+ },
1006
+ body: JSON.stringify({
1007
+ model: "gpt-oss-20b",
1008
+ messages: [{ role: "user", content: "hi" }],
1009
+ max_tokens: 5
1010
+ })
1011
+ });
1012
+ if (res.status === 401) return { valid: false, error: "Invalid key. Check your key at clawapi.org" };
1013
+ if (!res.ok) return { valid: false, error: `ClawAPI returned ${res.status}. Try again later.` };
1014
+ return { valid: true };
1015
+ } catch (err) {
1016
+ return { valid: false, error: `Cannot reach ClawAPI: ${err.message}. Check your internet connection.` };
1017
+ }
1018
+ }
1019
+ async function isServerRunning(port = 3200) {
1020
+ try {
1021
+ const res = await fetch(`http://localhost:${port}/api/health`);
1022
+ return res.ok;
1023
+ } catch {
1024
+ return false;
1025
+ }
1026
+ }
1027
+ var init_utils = __esm({
1028
+ "src/utils.ts"() {
1029
+ "use strict";
1030
+ init_src();
867
1031
  }
868
1032
  });
869
1033
 
@@ -1995,6 +2159,11 @@ var TaskOrchestrator = class {
1995
2159
  this.executor = new AgentExecutor(router, new ToolExecutor());
1996
2160
  }
1997
2161
  executor;
2162
+ memoryContext = "";
2163
+ /** Set company memory context to inject into all agent prompts */
2164
+ setMemoryContext(ctx) {
2165
+ this.memoryContext = ctx;
2166
+ }
1998
2167
  /**
1999
2168
  * Phase 2: CEO decomposes mission into work streams.
2000
2169
  * Human (Chairman) gives the mission → CEO breaks it down.
@@ -2013,7 +2182,8 @@ var TaskOrchestrator = class {
2013
2182
  Priority: ${mission.priority}
2014
2183
  ${mission.deadline ? `Deadline: ${mission.deadline}` : ""}
2015
2184
  ${mission.budgetLimit ? `Budget limit: $${mission.budgetLimit}` : ""}
2016
-
2185
+ ${this.memoryContext ? `${this.memoryContext}
2186
+ ` : ""}
2017
2187
  Your team:
2018
2188
  ${roleList}
2019
2189
 
@@ -2142,7 +2312,8 @@ ${truncated}
2142
2312
  title: ws.title,
2143
2313
  description: `${ws.description}
2144
2314
 
2145
- Complexity: ${ws.estimatedComplexity}${context}
2315
+ Complexity: ${ws.estimatedComplexity}${context}${this.memoryContext ? `
2316
+ ${this.memoryContext}` : ""}
2146
2317
 
2147
2318
  Today's date is ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.`,
2148
2319
  assignedTo: ws.assignTo,
@@ -2230,6 +2401,12 @@ async function runInProcess(goal, userConfig) {
2230
2401
  await registry.loadFromConfig(clawConfig.providers);
2231
2402
  const router = new ModelRouter(registry, clawConfig);
2232
2403
  const orchestrator = new TaskOrchestrator(router);
2404
+ const memory = readMemory();
2405
+ const memoryCtx = buildMemoryContext(memory);
2406
+ if (memoryCtx) {
2407
+ orchestrator.setMemoryContext(memoryCtx);
2408
+ console.log(" \u{1F9E0} Company memory loaded\n");
2409
+ }
2233
2410
  console.log(" Phase 2: CEO decomposing...");
2234
2411
  const mission = {
2235
2412
  id: `mission-${Date.now()}`,
@@ -2247,6 +2424,19 @@ async function runInProcess(goal, userConfig) {
2247
2424
  console.log(" Phase 3-5: Executing...");
2248
2425
  const report = await orchestrator.executeMission(mission, workStreams);
2249
2426
  console.log(" Phase 6: Delivering to Chairman\n");
2427
+ const updatedMemory = updateMemoryFromMission(memory, {
2428
+ goal,
2429
+ cost: report.totalCost,
2430
+ duration: report.totalTimeSeconds,
2431
+ workStreams: report.workStreams.map((ws) => ({
2432
+ title: ws.title,
2433
+ assignedTo: ws.assignedTo,
2434
+ status: ws.status,
2435
+ output: ws.output
2436
+ }))
2437
+ }, goal);
2438
+ writeMemory(updatedMemory);
2439
+ console.log(" \u{1F9E0} Memory updated\n");
2250
2440
  const result = {
2251
2441
  status: "completed",
2252
2442
  mission: report.mission,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawcompany",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Build for OPC. Every human being is a chairman. AI company infrastructure — one key, 9 roles, 4 models.",
5
5
  "type": "module",
6
6
  "bin": { "clawcompany": "dist/index.js" },